@igniter-js/agents 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/dist/index.mjs ADDED
@@ -0,0 +1,4011 @@
1
+ import { IgniterError } from '@igniter-js/core';
2
+ import { experimental_createMCPClient } from '@ai-sdk/mcp';
3
+ import { StdioClientTransport } from '@modelcontextprotocol/sdk/client/stdio.js';
4
+ import { StreamableHTTPClientTransport } from '@modelcontextprotocol/sdk/client/streamableHttp.js';
5
+ import { ToolLoopAgent, tool } from 'ai';
6
+ import { IgniterTelemetryEvents } from '@igniter-js/telemetry';
7
+ import { z } from 'zod';
8
+ import { readFile, writeFile, mkdir } from 'fs/promises';
9
+ import { join } from 'path';
10
+
11
+ // src/errors/agent.error.ts
12
+ var IgniterAgentErrorCode = /* @__PURE__ */ ((IgniterAgentErrorCode3) => {
13
+ IgniterAgentErrorCode3["UNKNOWN"] = "IGNITER_AGENT_UNKNOWN_ERROR";
14
+ IgniterAgentErrorCode3["INVALID_CONFIG"] = "IGNITER_AGENT_INVALID_CONFIG";
15
+ IgniterAgentErrorCode3["MISSING_REQUIRED"] = "IGNITER_AGENT_MISSING_REQUIRED";
16
+ IgniterAgentErrorCode3["AGENT_NOT_INITIALIZED"] = "IGNITER_AGENT_NOT_INITIALIZED";
17
+ IgniterAgentErrorCode3["AGENT_MODEL_MISSING"] = "IGNITER_AGENT_MODEL_MISSING";
18
+ IgniterAgentErrorCode3["AGENT_BUILD_FAILED"] = "IGNITER_AGENT_BUILD_FAILED";
19
+ IgniterAgentErrorCode3["MCP_CONNECTION_FAILED"] = "IGNITER_AGENT_MCP_CONNECTION_FAILED";
20
+ IgniterAgentErrorCode3["MCP_CLIENT_NOT_FOUND"] = "IGNITER_AGENT_MCP_CLIENT_NOT_FOUND";
21
+ IgniterAgentErrorCode3["MCP_TOOL_ERROR"] = "IGNITER_AGENT_MCP_TOOL_ERROR";
22
+ IgniterAgentErrorCode3["MCP_INVALID_CONFIG"] = "IGNITER_AGENT_MCP_INVALID_CONFIG";
23
+ IgniterAgentErrorCode3["TOOL_EXECUTION_FAILED"] = "IGNITER_AGENT_TOOL_EXECUTION_FAILED";
24
+ IgniterAgentErrorCode3["TOOL_NOT_FOUND"] = "IGNITER_AGENT_TOOL_NOT_FOUND";
25
+ IgniterAgentErrorCode3["TOOL_VALIDATION_FAILED"] = "IGNITER_AGENT_TOOL_VALIDATION_FAILED";
26
+ IgniterAgentErrorCode3["AGENT_CONTEXT_SCHEMA_INVALID"] = "IGNITER_AGENT_CONTEXT_SCHEMA_INVALID";
27
+ IgniterAgentErrorCode3["MEMORY_PROVIDER_ERROR"] = "IGNITER_AGENT_MEMORY_PROVIDER_ERROR";
28
+ IgniterAgentErrorCode3["MEMORY_NOT_FOUND"] = "IGNITER_AGENT_MEMORY_NOT_FOUND";
29
+ IgniterAgentErrorCode3["MEMORY_UPDATE_FAILED"] = "IGNITER_AGENT_MEMORY_UPDATE_FAILED";
30
+ IgniterAgentErrorCode3["ADAPTER_CONNECTION_FAILED"] = "IGNITER_AGENT_ADAPTER_CONNECTION_FAILED";
31
+ IgniterAgentErrorCode3["ADAPTER_OPERATION_FAILED"] = "IGNITER_AGENT_ADAPTER_OPERATION_FAILED";
32
+ IgniterAgentErrorCode3["ADAPTER_NOT_INITIALIZED"] = "IGNITER_AGENT_ADAPTER_NOT_INITIALIZED";
33
+ return IgniterAgentErrorCode3;
34
+ })(IgniterAgentErrorCode || {});
35
+ var IgniterAgentError = class extends IgniterError {
36
+ /**
37
+ * Creates a new IgniterAgentError.
38
+ *
39
+ * @param options - Error configuration options
40
+ */
41
+ constructor(options) {
42
+ super({
43
+ message: options.message,
44
+ code: options.code,
45
+ statusCode: options.statusCode ?? 500,
46
+ causer: options.causer,
47
+ details: options.details,
48
+ metadata: options.metadata,
49
+ logger: options.logger,
50
+ cause: options.cause
51
+ });
52
+ this.name = "IgniterAgentError";
53
+ }
54
+ };
55
+ var IgniterAgentConfigError = class extends IgniterAgentError {
56
+ constructor(options) {
57
+ super({
58
+ ...options,
59
+ code: "IGNITER_AGENT_INVALID_CONFIG" /* INVALID_CONFIG */,
60
+ metadata: { ...options.metadata, field: options.field }
61
+ });
62
+ this.name = "IgniterAgentConfigError";
63
+ this.field = options.field;
64
+ }
65
+ };
66
+ var IgniterAgentMCPError = class extends IgniterAgentError {
67
+ constructor(options) {
68
+ super({
69
+ ...options,
70
+ metadata: { ...options.metadata, mcpName: options.mcpName }
71
+ });
72
+ this.name = "IgniterAgentMCPError";
73
+ this.mcpName = options.mcpName;
74
+ }
75
+ };
76
+ var IgniterAgentToolError = class extends IgniterAgentError {
77
+ constructor(options) {
78
+ super({
79
+ ...options,
80
+ code: "IGNITER_AGENT_TOOL_EXECUTION_FAILED" /* TOOL_EXECUTION_FAILED */,
81
+ metadata: { ...options.metadata, toolName: options.toolName }
82
+ });
83
+ this.name = "IgniterAgentToolError";
84
+ this.toolName = options.toolName;
85
+ }
86
+ };
87
+ var IgniterAgentMemoryError = class extends IgniterAgentError {
88
+ constructor(options) {
89
+ super(options);
90
+ this.name = "IgniterAgentMemoryError";
91
+ }
92
+ };
93
+ var IgniterAgentAdapterError = class extends IgniterAgentError {
94
+ constructor(options) {
95
+ super({
96
+ ...options,
97
+ metadata: { ...options.metadata, adapterName: options.adapterName }
98
+ });
99
+ this.name = "IgniterAgentAdapterError";
100
+ this.adapterName = options.adapterName;
101
+ }
102
+ };
103
+ function isIgniterAgentError(error) {
104
+ return error instanceof IgniterAgentError;
105
+ }
106
+ function isIgniterAgentMCPError(error) {
107
+ return error instanceof IgniterAgentMCPError;
108
+ }
109
+ function isIgniterAgentToolError(error) {
110
+ return error instanceof IgniterAgentToolError;
111
+ }
112
+ function wrapError(error, options = {}) {
113
+ if (isIgniterAgentError(error)) {
114
+ return error;
115
+ }
116
+ const message = error instanceof Error ? error.message : String(error);
117
+ const cause = error instanceof Error ? error : void 0;
118
+ return new IgniterAgentError({
119
+ message,
120
+ code: "IGNITER_AGENT_UNKNOWN_ERROR" /* UNKNOWN */,
121
+ ...options,
122
+ cause
123
+ });
124
+ }
125
+
126
+ // src/core/manager.ts
127
+ var IgniterAgentManagerCore = class _IgniterAgentManagerCore {
128
+ /**
129
+ * Creates a new IgniterAgentManager.
130
+ *
131
+ * @param options - Manager configuration options
132
+ *
133
+ * @example
134
+ * ```typescript
135
+ * const manager = new IgniterAgentManager({
136
+ * autoStart: false,
137
+ * continueOnError: true
138
+ * });
139
+ * ```
140
+ */
141
+ constructor(options) {
142
+ /**
143
+ * Agent statuses.
144
+ * @internal
145
+ */
146
+ this._statuses = /* @__PURE__ */ new Map();
147
+ this._options = {
148
+ logger: options.logger,
149
+ telemetry: options.telemetry,
150
+ agents: options.agents ?? {},
151
+ autoStart: options.autoStart ?? false,
152
+ continueOnError: options.continueOnError ?? true,
153
+ onAgentStart: options.onAgentStart ?? (() => {
154
+ }),
155
+ onAgentError: options.onAgentError ?? (() => {
156
+ }),
157
+ onToolCallStart: options.onToolCallStart ?? (() => {
158
+ }),
159
+ onToolCallEnd: options.onToolCallEnd ?? (() => {
160
+ }),
161
+ onToolCallError: options.onToolCallError ?? (() => {
162
+ }),
163
+ onMCPStart: options.onMCPStart ?? (() => {
164
+ }),
165
+ onMCPError: options.onMCPError ?? (() => {
166
+ })
167
+ };
168
+ for (const [name, agent] of Object.entries(this._options.agents)) {
169
+ this.applyManagerContext(name, agent);
170
+ this._statuses.set(name, {
171
+ name,
172
+ status: "idle",
173
+ registeredAt: /* @__PURE__ */ new Date(),
174
+ toolsetCount: Object.keys(agent.getToolsets()).length
175
+ });
176
+ }
177
+ }
178
+ applyManagerContext(name, agent) {
179
+ const logger = this._options.logger;
180
+ const telemetry = this._options.telemetry;
181
+ if (logger) {
182
+ const scopedLogger = logger.child?.("IgniterAgent", { agent: name }) ?? logger;
183
+ agent.attachLogger?.(scopedLogger);
184
+ }
185
+ if (telemetry) {
186
+ agent.attachTelemetry?.(telemetry);
187
+ }
188
+ agent.attachHooks?.({
189
+ onToolCallStart: this._options.onToolCallStart,
190
+ onToolCallEnd: this._options.onToolCallEnd,
191
+ onToolCallError: this._options.onToolCallError,
192
+ onMCPStart: this._options.onMCPStart,
193
+ onMCPError: this._options.onMCPError
194
+ });
195
+ }
196
+ /**
197
+ * Creates a new IgniterAgentManager with default options.
198
+ * @param options - Manager configuration options
199
+ * @returns A new IgniterAgentManager instance
200
+ * @example
201
+ * ```typescript
202
+ * const manager = IgniterAgentManager.create({
203
+ * autoStart: true
204
+ * });
205
+ * ```
206
+ */
207
+ static create() {
208
+ return new _IgniterAgentManagerCore({
209
+ agents: {}
210
+ });
211
+ }
212
+ /* ---------------------------------------------------------------------------
213
+ * REGISTRATION
214
+ * --------------------------------------------------------------------------- */
215
+ /**
216
+ * Registers an agent with the manager.
217
+ *
218
+ * @description
219
+ * Adds an agent to the manager's registry. If `autoStart` is enabled,
220
+ * the agent will be started immediately after registration.
221
+ *
222
+ * @param name - Unique name for the agent
223
+ * @param agent - The built agent instance
224
+ * @returns This manager for chaining
225
+ * @throws {IgniterAgentError} If an agent with the name already exists
226
+ *
227
+ * @example
228
+ * ```typescript
229
+ * manager
230
+ * .register('support', supportAgent)
231
+ * .register('sales', salesAgent);
232
+ * ```
233
+ */
234
+ register(name, agent) {
235
+ if (this._options.agents[name]) {
236
+ throw new IgniterAgentError({
237
+ message: `Agent '${name}' is already registered`,
238
+ code: "IGNITER_AGENT_INVALID_CONFIG" /* INVALID_CONFIG */,
239
+ causer: "IgniterAgentManager",
240
+ metadata: { operation: "register" }
241
+ });
242
+ }
243
+ this._options.agents[name] = agent;
244
+ this.applyManagerContext(name, agent);
245
+ this._statuses.set(name, {
246
+ name,
247
+ status: "idle",
248
+ registeredAt: /* @__PURE__ */ new Date(),
249
+ toolsetCount: Object.keys(agent.getToolsets()).length
250
+ });
251
+ if (this._options.autoStart) {
252
+ this.start(name).catch((err) => {
253
+ this._options.onAgentError(name, err);
254
+ });
255
+ }
256
+ return this;
257
+ }
258
+ /**
259
+ * Unregisters an agent from the manager.
260
+ *
261
+ * @param name - The agent name to unregister
262
+ * @returns True if the agent was unregistered
263
+ *
264
+ * @example
265
+ * ```typescript
266
+ * manager.unregister('old-agent');
267
+ * ```
268
+ */
269
+ unregister(name) {
270
+ const removed = delete this._options.agents[name];
271
+ this._statuses.delete(name);
272
+ return removed;
273
+ }
274
+ /**
275
+ * Checks if an agent is registered.
276
+ *
277
+ * @param name - The agent name to check
278
+ * @returns True if the agent is registered
279
+ */
280
+ has(name) {
281
+ return Boolean(this._options.agents[name]);
282
+ }
283
+ /* ---------------------------------------------------------------------------
284
+ * LIFECYCLE
285
+ * --------------------------------------------------------------------------- */
286
+ /**
287
+ * Starts a specific agent.
288
+ *
289
+ * @description
290
+ * Initializes the agent's MCP connections and prepares it for use.
291
+ *
292
+ * @param name - The agent name to start
293
+ * @returns The agent's toolsets after initialization
294
+ * @throws {IgniterAgentError} If the agent is not found
295
+ *
296
+ * @example
297
+ * ```typescript
298
+ * const toolsets = await manager.start('support');
299
+ * console.log('Connected toolsets:', Object.keys(toolsets));
300
+ * ```
301
+ */
302
+ async start(name) {
303
+ const agent = this._options.agents[name];
304
+ const info = this._statuses.get(name);
305
+ if (!agent || !info) {
306
+ throw new IgniterAgentError({
307
+ message: `Agent '${name}' is not registered`,
308
+ code: "IGNITER_AGENT_NOT_INITIALIZED" /* AGENT_NOT_INITIALIZED */,
309
+ causer: "IgniterAgentManager",
310
+ metadata: { operation: "start" }
311
+ });
312
+ }
313
+ try {
314
+ info.status = "starting";
315
+ this._options.logger?.debug("IgniterAgentManager.start started", {
316
+ agent: name
317
+ });
318
+ await agent.start();
319
+ info.status = "running";
320
+ info.startedAt = /* @__PURE__ */ new Date();
321
+ info.toolsetCount = Object.keys(agent.getToolsets()).length;
322
+ this._options.onAgentStart?.(name);
323
+ this._options.logger?.success?.("IgniterAgentManager.start success", {
324
+ agent: name
325
+ });
326
+ return agent;
327
+ } catch (error) {
328
+ info.status = "error";
329
+ info.error = error instanceof Error ? error : new Error(String(error));
330
+ this._options.onAgentError?.(name, info.error);
331
+ this._options.logger?.error("IgniterAgentManager.start failed", info.error);
332
+ throw error;
333
+ }
334
+ }
335
+ /**
336
+ * Starts all registered agents.
337
+ *
338
+ * @description
339
+ * Initializes all agents in parallel. If `continueOnError` is true,
340
+ * failed agents won't prevent others from starting.
341
+ *
342
+ * @returns Map of agent names to their results (toolsets or errors)
343
+ *
344
+ * @example
345
+ * ```typescript
346
+ * const results = await manager.startAll();
347
+ *
348
+ * for (const [name, result] of results) {
349
+ * if (result instanceof Error) {
350
+ * console.error(`${name} failed:`, result.message);
351
+ * } else {
352
+ * console.log(`${name} started with ${Object.keys(result).length} toolsets`);
353
+ * }
354
+ * }
355
+ * ```
356
+ */
357
+ async startAll() {
358
+ const results = /* @__PURE__ */ new Map();
359
+ const promises = Object.keys(this._options.agents).map(async (name) => {
360
+ try {
361
+ const builtAgent = await this.start(name);
362
+ results.set(name, builtAgent.getToolsets());
363
+ } catch (error) {
364
+ const err = error instanceof Error ? error : new Error(String(error));
365
+ results.set(name, err);
366
+ if (!this._options.continueOnError) {
367
+ throw error;
368
+ }
369
+ }
370
+ });
371
+ await Promise.all(promises);
372
+ this._options.logger?.info("IgniterAgentManager.startAll completed", {
373
+ agents: this.getNames().length,
374
+ failed: this.getFailedAgents().length
375
+ });
376
+ return results;
377
+ }
378
+ /* ---------------------------------------------------------------------------
379
+ * ACCESS
380
+ * --------------------------------------------------------------------------- */
381
+ /**
382
+ * Gets a registered agent by name.
383
+ *
384
+ * @param name - The agent name
385
+ * @returns The agent instance
386
+ * @throws {IgniterAgentError} If the agent is not found
387
+ *
388
+ * @example
389
+ * ```typescript
390
+ * const agent = manager.get('support');
391
+ * const response = await agent.generate({ messages: [...] });
392
+ * ```
393
+ */
394
+ get(name) {
395
+ const agent = this._options.agents[name];
396
+ if (!agent) {
397
+ throw new IgniterAgentError({
398
+ message: `Agent '${name}' is not registered`,
399
+ code: "IGNITER_AGENT_NOT_INITIALIZED" /* AGENT_NOT_INITIALIZED */,
400
+ causer: "IgniterAgentManager",
401
+ metadata: { operation: "get" }
402
+ });
403
+ }
404
+ return agent;
405
+ }
406
+ /**
407
+ * Gets an agent if it exists, undefined otherwise.
408
+ *
409
+ * @param name - The agent name
410
+ * @returns The agent instance or undefined
411
+ */
412
+ tryGet(name) {
413
+ return this._options.agents[name];
414
+ }
415
+ /**
416
+ * Gets all registered agent names.
417
+ *
418
+ * @returns Array of agent names
419
+ */
420
+ getNames() {
421
+ return Object.keys(this._options.agents);
422
+ }
423
+ /**
424
+ * Gets the number of registered agents.
425
+ *
426
+ * @returns Agent count
427
+ */
428
+ get size() {
429
+ return Object.keys(this._options.agents).length;
430
+ }
431
+ /* ---------------------------------------------------------------------------
432
+ * STATUS
433
+ * --------------------------------------------------------------------------- */
434
+ /**
435
+ * Gets information about a specific agent.
436
+ *
437
+ * @param name - The agent name
438
+ * @returns Agent information or undefined
439
+ */
440
+ getInfo(name) {
441
+ return this._statuses.get(name);
442
+ }
443
+ /**
444
+ * Gets status information for all agents.
445
+ *
446
+ * @returns Array of agent information objects
447
+ *
448
+ * @example
449
+ * ```typescript
450
+ * const status = manager.getStatus();
451
+ *
452
+ * for (const info of status) {
453
+ * console.log(`${info.name}: ${info.status}`);
454
+ * }
455
+ * ```
456
+ */
457
+ getStatus() {
458
+ return Array.from(this._statuses.values());
459
+ }
460
+ /**
461
+ * Checks if all agents are running.
462
+ *
463
+ * @returns True if all agents are in 'running' status
464
+ */
465
+ isAllRunning() {
466
+ for (const info of this._statuses.values()) {
467
+ if (info.status !== "running") {
468
+ return false;
469
+ }
470
+ }
471
+ return Object.keys(this._options.agents).length > 0;
472
+ }
473
+ /**
474
+ * Gets agents that are in error state.
475
+ *
476
+ * @returns Array of agent info for failed agents
477
+ */
478
+ getFailedAgents() {
479
+ return Array.from(this._statuses.values()).filter(
480
+ (info) => info.status === "error"
481
+ );
482
+ }
483
+ };
484
+ var BaseAgentAttributesSchema = z.object({
485
+ /**
486
+ * The agent name.
487
+ */
488
+ "ctx.agent.name": z.string(),
489
+ /**
490
+ * The current scope (if scoped).
491
+ */
492
+ "ctx.agent.scope": z.string().optional(),
493
+ /**
494
+ * The scope identifier value.
495
+ */
496
+ "ctx.agent.scopeId": z.string().optional()
497
+ });
498
+ var LifecycleAttributesSchema = BaseAgentAttributesSchema.extend({
499
+ /**
500
+ * Number of toolsets registered.
501
+ */
502
+ "ctx.lifecycle.toolsetCount": z.number().optional(),
503
+ /**
504
+ * Number of MCP connections configured.
505
+ */
506
+ "ctx.lifecycle.mcpCount": z.number().optional(),
507
+ /**
508
+ * Whether memory adapter is configured.
509
+ */
510
+ "ctx.lifecycle.hasMemory": z.boolean().optional()
511
+ });
512
+ var GenerationAttributesSchema = BaseAgentAttributesSchema.extend({
513
+ /**
514
+ * The model used for generation.
515
+ */
516
+ "ctx.generation.model": z.string().optional(),
517
+ /**
518
+ * Number of input messages.
519
+ */
520
+ "ctx.generation.inputMessages": z.number().optional(),
521
+ /**
522
+ * Number of input tokens (if available).
523
+ */
524
+ "ctx.generation.inputTokens": z.number().optional(),
525
+ /**
526
+ * Number of output tokens (if available).
527
+ */
528
+ "ctx.generation.outputTokens": z.number().optional(),
529
+ /**
530
+ * Total tokens used (if available).
531
+ */
532
+ "ctx.generation.totalTokens": z.number().optional(),
533
+ /**
534
+ * Generation duration in milliseconds.
535
+ */
536
+ "ctx.generation.durationMs": z.number().optional(),
537
+ /**
538
+ * Number of tool calls made during generation.
539
+ */
540
+ "ctx.generation.toolCalls": z.number().optional(),
541
+ /**
542
+ * Whether the response was streamed.
543
+ */
544
+ "ctx.generation.streamed": z.boolean().optional()
545
+ });
546
+ var ToolAttributesSchema = BaseAgentAttributesSchema.extend({
547
+ /**
548
+ * The toolset name.
549
+ */
550
+ "ctx.tool.toolset": z.string(),
551
+ /**
552
+ * The tool name (within the toolset).
553
+ */
554
+ "ctx.tool.name": z.string(),
555
+ /**
556
+ * The full tool identifier (toolset_name).
557
+ */
558
+ "ctx.tool.fullName": z.string(),
559
+ /**
560
+ * Tool execution duration in milliseconds.
561
+ */
562
+ "ctx.tool.durationMs": z.number().optional()
563
+ });
564
+ var MCPAttributesSchema = BaseAgentAttributesSchema.extend({
565
+ /**
566
+ * The MCP configuration name.
567
+ */
568
+ "ctx.mcp.name": z.string(),
569
+ /**
570
+ * The MCP transport type (stdio, http).
571
+ */
572
+ "ctx.mcp.type": z.enum(["stdio", "http"]),
573
+ /**
574
+ * Number of tools provided by this MCP.
575
+ */
576
+ "ctx.mcp.toolCount": z.number().optional(),
577
+ /**
578
+ * Connection duration in milliseconds.
579
+ */
580
+ "ctx.mcp.durationMs": z.number().optional()
581
+ });
582
+ var MemoryAttributesSchema = BaseAgentAttributesSchema.extend({
583
+ /**
584
+ * The memory operation type.
585
+ */
586
+ "ctx.memory.operation": z.enum([
587
+ "getWorkingMemory",
588
+ "updateWorkingMemory",
589
+ "getMessages",
590
+ "saveMessage",
591
+ "getChats",
592
+ "saveChat",
593
+ "getChat",
594
+ "updateChatTitle",
595
+ "deleteChat"
596
+ ]),
597
+ /**
598
+ * The memory scope (user, chat, global).
599
+ */
600
+ "ctx.memory.scope": z.string().optional(),
601
+ /**
602
+ * Number of items affected.
603
+ */
604
+ "ctx.memory.count": z.number().optional(),
605
+ /**
606
+ * Operation duration in milliseconds.
607
+ */
608
+ "ctx.memory.durationMs": z.number().optional()
609
+ });
610
+ var ErrorAttributesSchema = BaseAgentAttributesSchema.extend({
611
+ /**
612
+ * The error code.
613
+ */
614
+ "ctx.error.code": z.string(),
615
+ /**
616
+ * The sanitized error message (no sensitive data).
617
+ */
618
+ "ctx.error.message": z.string().optional(),
619
+ /**
620
+ * The operation that failed.
621
+ */
622
+ "ctx.error.operation": z.string().optional(),
623
+ /**
624
+ * The component that threw the error.
625
+ */
626
+ "ctx.error.component": z.string().optional()
627
+ });
628
+ var IgniterAgentTelemetryEvents = IgniterTelemetryEvents.namespace(
629
+ "igniter.agent"
630
+ ).event("lifecycle.start.started", LifecycleAttributesSchema).event("lifecycle.start.success", LifecycleAttributesSchema).event("lifecycle.start.error", ErrorAttributesSchema).event("lifecycle.stop.started", LifecycleAttributesSchema).event("lifecycle.stop.success", LifecycleAttributesSchema).event("lifecycle.stop.error", ErrorAttributesSchema).event("generation.generate.started", GenerationAttributesSchema).event("generation.generate.success", GenerationAttributesSchema).event("generation.generate.error", ErrorAttributesSchema).event("generation.stream.started", GenerationAttributesSchema).event("generation.stream.chunk", GenerationAttributesSchema).event("generation.stream.success", GenerationAttributesSchema).event("generation.stream.error", ErrorAttributesSchema).event("tool.execute.started", ToolAttributesSchema).event("tool.execute.success", ToolAttributesSchema).event("tool.execute.error", ErrorAttributesSchema).event("mcp.connect.started", MCPAttributesSchema).event("mcp.connect.success", MCPAttributesSchema).event("mcp.connect.error", ErrorAttributesSchema).event("mcp.disconnect.started", MCPAttributesSchema).event("mcp.disconnect.success", MCPAttributesSchema).event("mcp.disconnect.error", ErrorAttributesSchema).event("memory.operation.started", MemoryAttributesSchema).event("memory.operation.success", MemoryAttributesSchema).event("memory.operation.error", ErrorAttributesSchema).build();
631
+
632
+ // src/core/memory.ts
633
+ var MEMORY_ERROR_CODE = "IGNITER_AGENT_MEMORY_PROVIDER_ERROR" /* MEMORY_PROVIDER_ERROR */;
634
+ var IgniterAgentMemoryCore = class {
635
+ constructor(config, agentName, logger, telemetry) {
636
+ this.provider = config.provider;
637
+ this.agentName = agentName;
638
+ this.logger = logger;
639
+ this.telemetry = telemetry;
640
+ }
641
+ getBaseAttributes(operation, scope) {
642
+ const attributes = {
643
+ "ctx.agent.name": this.agentName,
644
+ "ctx.memory.operation": operation
645
+ };
646
+ if (scope) {
647
+ attributes["ctx.memory.scope"] = scope;
648
+ }
649
+ return attributes;
650
+ }
651
+ emitStart(operation, scope) {
652
+ this.telemetry?.emit(IgniterAgentTelemetryEvents.get.key("memory.operation.started"), {
653
+ level: "debug",
654
+ attributes: this.getBaseAttributes(operation, scope)
655
+ });
656
+ }
657
+ emitSuccess(operation, durationMs, scope, count) {
658
+ const attributes = {
659
+ ...this.getBaseAttributes(operation, scope),
660
+ "ctx.memory.durationMs": durationMs
661
+ };
662
+ if (count !== void 0) {
663
+ attributes["ctx.memory.count"] = count;
664
+ }
665
+ this.telemetry?.emit(IgniterAgentTelemetryEvents.get.key("memory.operation.success"), {
666
+ level: "debug",
667
+ attributes
668
+ });
669
+ }
670
+ emitError(operation, error, scope) {
671
+ const attributes = {
672
+ ...this.getBaseAttributes(operation, scope),
673
+ "ctx.error.code": MEMORY_ERROR_CODE,
674
+ "ctx.error.message": error.message,
675
+ "ctx.error.operation": operation,
676
+ "ctx.error.component": "memory"
677
+ };
678
+ this.telemetry?.emit(IgniterAgentTelemetryEvents.get.key("memory.operation.error"), {
679
+ level: "error",
680
+ attributes
681
+ });
682
+ }
683
+ async runOperation(operation, scope, handler, count) {
684
+ const start = Date.now();
685
+ this.emitStart(operation, scope);
686
+ this.logger?.debug(`IgniterAgent.memory.${operation} started`, {
687
+ agent: this.agentName,
688
+ scope
689
+ });
690
+ try {
691
+ const result = await handler();
692
+ const durationMs = Date.now() - start;
693
+ this.emitSuccess(operation, durationMs, scope, count?.(result));
694
+ this.logger?.success?.(
695
+ `IgniterAgent.memory.${operation} success`,
696
+ { agent: this.agentName, scope, durationMs }
697
+ );
698
+ return result;
699
+ } catch (err) {
700
+ const error = err instanceof Error ? err : new Error(String(err));
701
+ this.emitError(operation, error, scope);
702
+ this.logger?.error(`IgniterAgent.memory.${operation} failed`, error);
703
+ throw new IgniterAgentMemoryError({
704
+ message: error.message,
705
+ code: MEMORY_ERROR_CODE,
706
+ cause: error,
707
+ metadata: { operation }
708
+ });
709
+ }
710
+ }
711
+ async getWorkingMemory(params) {
712
+ return this.runOperation(
713
+ "getWorkingMemory",
714
+ params.scope,
715
+ () => this.provider.getWorkingMemory(params)
716
+ );
717
+ }
718
+ async updateWorkingMemory(params) {
719
+ await this.runOperation(
720
+ "updateWorkingMemory",
721
+ params.scope,
722
+ () => this.provider.updateWorkingMemory(params)
723
+ );
724
+ }
725
+ async saveMessage(message) {
726
+ await this.runOperation(
727
+ "saveMessage",
728
+ void 0,
729
+ async () => {
730
+ if (!this.provider.saveMessage) {
731
+ throw new Error("saveMessage is not supported by the provider");
732
+ }
733
+ await this.provider.saveMessage(message);
734
+ }
735
+ );
736
+ }
737
+ async getMessages(params) {
738
+ return this.runOperation(
739
+ "getMessages",
740
+ void 0,
741
+ async () => {
742
+ if (!this.provider.getMessages) {
743
+ throw new Error("getMessages is not supported by the provider");
744
+ }
745
+ return this.provider.getMessages(params);
746
+ },
747
+ (result) => result.length
748
+ );
749
+ }
750
+ async saveChat(chat) {
751
+ await this.runOperation(
752
+ "saveChat",
753
+ void 0,
754
+ async () => {
755
+ if (!this.provider.saveChat) {
756
+ throw new Error("saveChat is not supported by the provider");
757
+ }
758
+ await this.provider.saveChat(chat);
759
+ }
760
+ );
761
+ }
762
+ async getChats(params) {
763
+ return this.runOperation(
764
+ "getChats",
765
+ void 0,
766
+ async () => {
767
+ if (!this.provider.getChats) {
768
+ throw new Error("getChats is not supported by the provider");
769
+ }
770
+ return this.provider.getChats(params);
771
+ },
772
+ (result) => result.length
773
+ );
774
+ }
775
+ async getChat(chatId) {
776
+ return this.runOperation(
777
+ "getChat",
778
+ void 0,
779
+ async () => {
780
+ if (!this.provider.getChat) {
781
+ throw new Error("getChat is not supported by the provider");
782
+ }
783
+ return this.provider.getChat(chatId);
784
+ }
785
+ );
786
+ }
787
+ async updateChatTitle(chatId, title) {
788
+ await this.runOperation(
789
+ "updateChatTitle",
790
+ void 0,
791
+ async () => {
792
+ if (!this.provider.updateChatTitle) {
793
+ throw new Error("updateChatTitle is not supported by the provider");
794
+ }
795
+ await this.provider.updateChatTitle(chatId, title);
796
+ }
797
+ );
798
+ }
799
+ async deleteChat(chatId) {
800
+ await this.runOperation(
801
+ "deleteChat",
802
+ void 0,
803
+ async () => {
804
+ if (!this.provider.deleteChat) {
805
+ throw new Error("deleteChat is not supported by the provider");
806
+ }
807
+ await this.provider.deleteChat(chatId);
808
+ }
809
+ );
810
+ }
811
+ };
812
+
813
+ // src/core/agent.ts
814
+ var IgniterAgentCore = class {
815
+ constructor(agent) {
816
+ this._agent = agent;
817
+ this.logger = agent.logger;
818
+ this.telemetry = agent.telemetry;
819
+ this.hooks = agent.hooks ?? {};
820
+ if (agent.memory) {
821
+ this.memory = new IgniterAgentMemoryCore(agent.memory, String(agent.name), this.logger, this.telemetry);
822
+ }
823
+ }
824
+ /**
825
+ * Attaches a logger instance to the agent.
826
+ */
827
+ attachLogger(logger) {
828
+ if (!logger) return;
829
+ if (!this.logger) {
830
+ this.logger = logger;
831
+ if (this._agent.memory) {
832
+ this.memory = new IgniterAgentMemoryCore(
833
+ this._agent.memory,
834
+ this.getName(),
835
+ this.logger,
836
+ this.telemetry
837
+ );
838
+ }
839
+ }
840
+ }
841
+ /**
842
+ * Attaches a telemetry manager to the agent.
843
+ */
844
+ attachTelemetry(telemetry) {
845
+ if (!telemetry) return;
846
+ if (!this.telemetry) {
847
+ this.telemetry = telemetry;
848
+ if (this._agent.memory) {
849
+ this.memory = new IgniterAgentMemoryCore(
850
+ this._agent.memory,
851
+ this.getName(),
852
+ this.logger,
853
+ this.telemetry
854
+ );
855
+ }
856
+ }
857
+ }
858
+ /**
859
+ * Attaches hook callbacks to the agent.
860
+ */
861
+ attachHooks(hooks) {
862
+ if (!hooks) return;
863
+ const merge = (current, incoming) => {
864
+ if (!current) return incoming;
865
+ if (!incoming) return current;
866
+ return ((...args) => {
867
+ current(...args);
868
+ incoming(...args);
869
+ });
870
+ };
871
+ this.hooks = {
872
+ onAgentStart: merge(this.hooks.onAgentStart, hooks.onAgentStart),
873
+ onAgentError: merge(this.hooks.onAgentError, hooks.onAgentError),
874
+ onToolCallStart: merge(this.hooks.onToolCallStart, hooks.onToolCallStart),
875
+ onToolCallEnd: merge(this.hooks.onToolCallEnd, hooks.onToolCallEnd),
876
+ onToolCallError: merge(this.hooks.onToolCallError, hooks.onToolCallError),
877
+ onMCPStart: merge(this.hooks.onMCPStart, hooks.onMCPStart),
878
+ onMCPError: merge(this.hooks.onMCPError, hooks.onMCPError)
879
+ };
880
+ }
881
+ /**
882
+ * Returns the agent name.
883
+ */
884
+ getName() {
885
+ return String(this._agent.name);
886
+ }
887
+ /**
888
+ * Starts the agent by initializing all MCP connections.
889
+ */
890
+ async start() {
891
+ const startTime = Date.now();
892
+ const toolsets = this._agent.toolsets;
893
+ const mcpConfigs = Object.values(this._agent.configs || {});
894
+ const lifecycleAttributes = {
895
+ "ctx.agent.name": this.getName(),
896
+ "ctx.lifecycle.toolsetCount": Object.keys(toolsets || {}).length,
897
+ "ctx.lifecycle.mcpCount": mcpConfigs.length,
898
+ "ctx.lifecycle.hasMemory": Boolean(this.memory)
899
+ };
900
+ this.logger?.debug("IgniterAgent.start started", lifecycleAttributes);
901
+ this.telemetry?.emit(IgniterAgentTelemetryEvents.get.key("lifecycle.start.started"), {
902
+ level: "debug",
903
+ attributes: lifecycleAttributes
904
+ });
905
+ try {
906
+ for (const mcpConfig of mcpConfigs) {
907
+ const mcpStart = Date.now();
908
+ this.hooks.onMCPStart?.(this.getName(), mcpConfig.name);
909
+ this.telemetry?.emit(IgniterAgentTelemetryEvents.get.key("mcp.connect.started"), {
910
+ level: "debug",
911
+ attributes: {
912
+ "ctx.agent.name": this.getName(),
913
+ "ctx.mcp.name": mcpConfig.name,
914
+ "ctx.mcp.type": mcpConfig.type
915
+ }
916
+ });
917
+ try {
918
+ const mcpToolset = await this.initializeMCPClient(mcpConfig);
919
+ toolsets[mcpConfig.name] = mcpToolset;
920
+ this.telemetry?.emit(IgniterAgentTelemetryEvents.get.key("mcp.connect.success"), {
921
+ level: "debug",
922
+ attributes: {
923
+ "ctx.agent.name": this.getName(),
924
+ "ctx.mcp.name": mcpConfig.name,
925
+ "ctx.mcp.type": mcpConfig.type,
926
+ "ctx.mcp.toolCount": Object.keys(mcpToolset.tools || {}).length,
927
+ "ctx.mcp.durationMs": Date.now() - mcpStart
928
+ }
929
+ });
930
+ } catch (error) {
931
+ const err = error instanceof Error ? error : new Error(String(error));
932
+ this.telemetry?.emit(IgniterAgentTelemetryEvents.get.key("mcp.connect.error"), {
933
+ level: "error",
934
+ attributes: {
935
+ "ctx.agent.name": this.getName(),
936
+ "ctx.mcp.name": mcpConfig.name,
937
+ "ctx.mcp.type": mcpConfig.type,
938
+ "ctx.mcp.durationMs": Date.now() - mcpStart,
939
+ ...this.getErrorAttributes(err, "mcp.connect")
940
+ }
941
+ });
942
+ this.logger?.error("IgniterAgent.mcp.connect failed", err);
943
+ throw err;
944
+ }
945
+ }
946
+ const durationMs = Date.now() - startTime;
947
+ this.telemetry?.emit(IgniterAgentTelemetryEvents.get.key("lifecycle.start.success"), {
948
+ level: "debug",
949
+ attributes: {
950
+ ...lifecycleAttributes,
951
+ "ctx.lifecycle.toolsetCount": Object.keys(this._agent.toolsets || {}).length,
952
+ "ctx.lifecycle.mcpCount": mcpConfigs.length
953
+ }
954
+ });
955
+ this.logger?.success?.("IgniterAgent.start success", {
956
+ ...lifecycleAttributes,
957
+ durationMs
958
+ });
959
+ this.hooks.onAgentStart?.(this.getName());
960
+ } catch (error) {
961
+ const err = error instanceof Error ? error : new Error(String(error));
962
+ this.telemetry?.emit(IgniterAgentTelemetryEvents.get.key("lifecycle.start.error"), {
963
+ level: "error",
964
+ attributes: {
965
+ ...lifecycleAttributes,
966
+ ...this.getErrorAttributes(err, "lifecycle.start")
967
+ }
968
+ });
969
+ this.logger?.error("IgniterAgent.start failed", err);
970
+ this.hooks.onAgentError?.(this.getName(), err);
971
+ throw err;
972
+ }
973
+ }
974
+ /**
975
+ * Stops the agent by disconnecting MCP toolsets.
976
+ */
977
+ async stop() {
978
+ const startTime = Date.now();
979
+ const mcpConfigs = Object.values(this._agent.configs || {});
980
+ const lifecycleAttributes = {
981
+ "ctx.agent.name": this.getName(),
982
+ "ctx.lifecycle.toolsetCount": Object.keys(this._agent.toolsets || {}).length,
983
+ "ctx.lifecycle.mcpCount": mcpConfigs.length,
984
+ "ctx.lifecycle.hasMemory": Boolean(this.memory)
985
+ };
986
+ this.logger?.debug("IgniterAgent.stop started", lifecycleAttributes);
987
+ this.telemetry?.emit(IgniterAgentTelemetryEvents.get.key("lifecycle.stop.started"), {
988
+ level: "debug",
989
+ attributes: lifecycleAttributes
990
+ });
991
+ try {
992
+ for (const mcpConfig of mcpConfigs) {
993
+ const mcpStart = Date.now();
994
+ this.telemetry?.emit(IgniterAgentTelemetryEvents.get.key("mcp.disconnect.started"), {
995
+ level: "debug",
996
+ attributes: {
997
+ "ctx.agent.name": this.getName(),
998
+ "ctx.mcp.name": mcpConfig.name,
999
+ "ctx.mcp.type": mcpConfig.type
1000
+ }
1001
+ });
1002
+ try {
1003
+ const existing = this._agent.toolsets[mcpConfig.name];
1004
+ if (existing?.disconnect) {
1005
+ await existing.disconnect();
1006
+ }
1007
+ if (existing) {
1008
+ this._agent.toolsets[mcpConfig.name] = {
1009
+ ...existing,
1010
+ status: "disconnected",
1011
+ tools: {}
1012
+ };
1013
+ }
1014
+ this.telemetry?.emit(IgniterAgentTelemetryEvents.get.key("mcp.disconnect.success"), {
1015
+ level: "debug",
1016
+ attributes: {
1017
+ "ctx.agent.name": this.getName(),
1018
+ "ctx.mcp.name": mcpConfig.name,
1019
+ "ctx.mcp.type": mcpConfig.type,
1020
+ "ctx.mcp.durationMs": Date.now() - mcpStart
1021
+ }
1022
+ });
1023
+ } catch (error) {
1024
+ const err = error instanceof Error ? error : new Error(String(error));
1025
+ this.telemetry?.emit(IgniterAgentTelemetryEvents.get.key("mcp.disconnect.error"), {
1026
+ level: "error",
1027
+ attributes: {
1028
+ "ctx.agent.name": this.getName(),
1029
+ "ctx.mcp.name": mcpConfig.name,
1030
+ "ctx.mcp.type": mcpConfig.type,
1031
+ "ctx.mcp.durationMs": Date.now() - mcpStart,
1032
+ ...this.getErrorAttributes(err, "mcp.disconnect")
1033
+ }
1034
+ });
1035
+ this.logger?.error("IgniterAgent.mcp.disconnect failed", err);
1036
+ throw err;
1037
+ }
1038
+ }
1039
+ const durationMs = Date.now() - startTime;
1040
+ this.telemetry?.emit(IgniterAgentTelemetryEvents.get.key("lifecycle.stop.success"), {
1041
+ level: "debug",
1042
+ attributes: {
1043
+ ...lifecycleAttributes,
1044
+ "ctx.lifecycle.toolsetCount": Object.keys(this._agent.toolsets || {}).length,
1045
+ "ctx.lifecycle.mcpCount": mcpConfigs.length
1046
+ }
1047
+ });
1048
+ this.logger?.success?.("IgniterAgent.stop success", {
1049
+ ...lifecycleAttributes,
1050
+ durationMs
1051
+ });
1052
+ } catch (error) {
1053
+ const err = error instanceof Error ? error : new Error(String(error));
1054
+ this.telemetry?.emit(IgniterAgentTelemetryEvents.get.key("lifecycle.stop.error"), {
1055
+ level: "error",
1056
+ attributes: {
1057
+ ...lifecycleAttributes,
1058
+ ...this.getErrorAttributes(err, "lifecycle.stop")
1059
+ }
1060
+ });
1061
+ this.logger?.error("IgniterAgent.stop failed", err);
1062
+ throw err;
1063
+ }
1064
+ }
1065
+ /**
1066
+ * Generates a response from the agent.
1067
+ */
1068
+ async generate(input) {
1069
+ const startTime = Date.now();
1070
+ const attributes = {
1071
+ "ctx.agent.name": this.getName(),
1072
+ "ctx.generation.inputMessages": Array.isArray(input.messages) ? input.messages.length : void 0,
1073
+ "ctx.generation.streamed": false
1074
+ };
1075
+ this.logger?.debug("IgniterAgent.generate started", attributes);
1076
+ this.telemetry?.emit(IgniterAgentTelemetryEvents.get.key("generation.generate.started"), {
1077
+ level: "debug",
1078
+ attributes
1079
+ });
1080
+ try {
1081
+ const agent = this.getAgentInstanceWithContext(
1082
+ input.options
1083
+ );
1084
+ const result = await agent.generate(input);
1085
+ const durationMs = Date.now() - startTime;
1086
+ this.telemetry?.emit(IgniterAgentTelemetryEvents.get.key("generation.generate.success"), {
1087
+ level: "debug",
1088
+ attributes: {
1089
+ ...attributes,
1090
+ "ctx.generation.durationMs": durationMs
1091
+ }
1092
+ });
1093
+ this.logger?.success?.("IgniterAgent.generate success", {
1094
+ ...attributes,
1095
+ durationMs
1096
+ });
1097
+ return result;
1098
+ } catch (error) {
1099
+ const err = error instanceof Error ? error : new Error(String(error));
1100
+ this.telemetry?.emit(IgniterAgentTelemetryEvents.get.key("generation.generate.error"), {
1101
+ level: "error",
1102
+ attributes: {
1103
+ ...attributes,
1104
+ ...this.getErrorAttributes(err, "generation.generate")
1105
+ }
1106
+ });
1107
+ this.logger?.error("IgniterAgent.generate failed", err);
1108
+ throw err;
1109
+ }
1110
+ }
1111
+ /**
1112
+ * Streams a response from the agent.
1113
+ */
1114
+ async stream(input) {
1115
+ const startTime = Date.now();
1116
+ const attributes = {
1117
+ "ctx.agent.name": this.getName(),
1118
+ "ctx.generation.inputMessages": Array.isArray(input.messages) ? input.messages.length : void 0,
1119
+ "ctx.generation.streamed": true
1120
+ };
1121
+ this.logger?.debug("IgniterAgent.stream started", attributes);
1122
+ this.telemetry?.emit(IgniterAgentTelemetryEvents.get.key("generation.stream.started"), {
1123
+ level: "debug",
1124
+ attributes
1125
+ });
1126
+ try {
1127
+ const agent = this.getAgentInstanceWithContext(
1128
+ input.options
1129
+ );
1130
+ const result = await agent.stream(input);
1131
+ const durationMs = Date.now() - startTime;
1132
+ const emitChunk = () => {
1133
+ this.telemetry?.emit(IgniterAgentTelemetryEvents.get.key("generation.stream.chunk"), {
1134
+ level: "debug",
1135
+ attributes
1136
+ });
1137
+ };
1138
+ const wrapped = this.wrapStreamResult(result, emitChunk);
1139
+ this.telemetry?.emit(IgniterAgentTelemetryEvents.get.key("generation.stream.success"), {
1140
+ level: "debug",
1141
+ attributes: {
1142
+ ...attributes,
1143
+ "ctx.generation.durationMs": durationMs
1144
+ }
1145
+ });
1146
+ this.logger?.success?.("IgniterAgent.stream success", {
1147
+ ...attributes,
1148
+ durationMs
1149
+ });
1150
+ return wrapped;
1151
+ } catch (error) {
1152
+ const err = error instanceof Error ? error : new Error(String(error));
1153
+ this.telemetry?.emit(IgniterAgentTelemetryEvents.get.key("generation.stream.error"), {
1154
+ level: "error",
1155
+ attributes: {
1156
+ ...attributes,
1157
+ ...this.getErrorAttributes(err, "generation.stream")
1158
+ }
1159
+ });
1160
+ this.logger?.error("IgniterAgent.stream failed", err);
1161
+ throw err;
1162
+ }
1163
+ }
1164
+ /**
1165
+ * Gets all registered toolsets.
1166
+ */
1167
+ getToolsets() {
1168
+ return this._agent.toolsets;
1169
+ }
1170
+ /**
1171
+ * Gets the configured model.
1172
+ */
1173
+ getModel() {
1174
+ return this._agent.model;
1175
+ }
1176
+ /**
1177
+ * Gets the configured instructions.
1178
+ */
1179
+ getInstructions() {
1180
+ return this._agent.instructions;
1181
+ }
1182
+ /**
1183
+ * Gets the context schema.
1184
+ */
1185
+ getContextSchema() {
1186
+ return this._agent.schema;
1187
+ }
1188
+ /**
1189
+ * Gets all registered tools from all toolsets.
1190
+ */
1191
+ getTools() {
1192
+ const toolsets = this.getToolsets();
1193
+ const allTools = {};
1194
+ for (const toolset of Object.values(toolsets)) {
1195
+ for (const [toolName, tool2] of Object.entries(toolset.tools)) {
1196
+ const wrapped = this.wrapToolExecution(toolset.name, toolName, tool2);
1197
+ allTools[toolName] = wrapped;
1198
+ }
1199
+ }
1200
+ return allTools;
1201
+ }
1202
+ wrapToolExecution(toolsetName, toolName, tool2) {
1203
+ if (!tool2 || !tool2.execute || typeof tool2.execute !== "function") {
1204
+ return tool2;
1205
+ }
1206
+ const execute = tool2.execute;
1207
+ const fullName = `${toolsetName}.${toolName}`;
1208
+ const agentName = this.getName();
1209
+ return {
1210
+ ...tool2,
1211
+ execute: async (input, options) => {
1212
+ const startTime = Date.now();
1213
+ this.hooks.onToolCallStart?.(agentName, fullName, input);
1214
+ this.telemetry?.emit(IgniterAgentTelemetryEvents.get.key("tool.execute.started"), {
1215
+ level: "debug",
1216
+ attributes: {
1217
+ "ctx.agent.name": agentName,
1218
+ "ctx.tool.toolset": toolsetName,
1219
+ "ctx.tool.name": toolName,
1220
+ "ctx.tool.fullName": fullName
1221
+ }
1222
+ });
1223
+ this.logger?.debug("IgniterAgent.tool.execute started", {
1224
+ agent: agentName,
1225
+ tool: fullName
1226
+ });
1227
+ try {
1228
+ const result = await execute(input, options);
1229
+ const durationMs = Date.now() - startTime;
1230
+ this.hooks.onToolCallEnd?.(agentName, fullName, result);
1231
+ this.telemetry?.emit(IgniterAgentTelemetryEvents.get.key("tool.execute.success"), {
1232
+ level: "debug",
1233
+ attributes: {
1234
+ "ctx.agent.name": agentName,
1235
+ "ctx.tool.toolset": toolsetName,
1236
+ "ctx.tool.name": toolName,
1237
+ "ctx.tool.fullName": fullName,
1238
+ "ctx.tool.durationMs": durationMs
1239
+ }
1240
+ });
1241
+ this.logger?.success?.("IgniterAgent.tool.execute success", {
1242
+ agent: agentName,
1243
+ tool: fullName,
1244
+ durationMs
1245
+ });
1246
+ return result;
1247
+ } catch (error) {
1248
+ const err = error instanceof Error ? error : new Error(String(error));
1249
+ this.hooks.onToolCallError?.(agentName, fullName, err);
1250
+ this.telemetry?.emit(IgniterAgentTelemetryEvents.get.key("tool.execute.error"), {
1251
+ level: "error",
1252
+ attributes: {
1253
+ "ctx.agent.name": agentName,
1254
+ "ctx.tool.toolset": toolsetName,
1255
+ "ctx.tool.name": toolName,
1256
+ "ctx.tool.fullName": fullName,
1257
+ ...this.getErrorAttributes(err, "tool.execute")
1258
+ }
1259
+ });
1260
+ this.logger?.error("IgniterAgent.tool.execute failed", err);
1261
+ throw err;
1262
+ }
1263
+ }
1264
+ };
1265
+ }
1266
+ wrapStreamResult(result, onChunk) {
1267
+ if (!result) {
1268
+ return result;
1269
+ }
1270
+ if (typeof result[Symbol.asyncIterator] === "function") {
1271
+ const iterable = result;
1272
+ return {
1273
+ [Symbol.asyncIterator]: async function* () {
1274
+ for await (const chunk of iterable) {
1275
+ onChunk();
1276
+ yield chunk;
1277
+ }
1278
+ }
1279
+ };
1280
+ }
1281
+ const maybeTextStream = result.textStream;
1282
+ if (maybeTextStream && typeof maybeTextStream[Symbol.asyncIterator] === "function") {
1283
+ return {
1284
+ ...result,
1285
+ textStream: (async function* () {
1286
+ for await (const chunk of maybeTextStream) {
1287
+ onChunk();
1288
+ yield chunk;
1289
+ }
1290
+ })()
1291
+ };
1292
+ }
1293
+ return result;
1294
+ }
1295
+ getErrorAttributes(error, operation) {
1296
+ return {
1297
+ "ctx.error.code": error.code ?? error.name ?? "IGNITER_AGENT_UNKNOWN_ERROR" /* UNKNOWN */,
1298
+ "ctx.error.message": error.message,
1299
+ "ctx.error.operation": operation,
1300
+ "ctx.error.component": "agent"
1301
+ };
1302
+ }
1303
+ getAgentInstanceWithContext(context) {
1304
+ const tools = this.getTools();
1305
+ if (!this._agent.model) {
1306
+ throw new IgniterAgentConfigError({
1307
+ message: "Model is required. Call withModel() before build()",
1308
+ field: "model"
1309
+ });
1310
+ }
1311
+ if (this._agent.schema !== void 0) {
1312
+ const parseResult = this._agent.schema.safeParse(context);
1313
+ if (parseResult.success) {
1314
+ context = parseResult.data;
1315
+ } else {
1316
+ throw new IgniterAgentError({
1317
+ message: "Invalid context schema",
1318
+ code: "IGNITER_AGENT_CONTEXT_SCHEMA_INVALID" /* AGENT_CONTEXT_SCHEMA_INVALID */
1319
+ });
1320
+ }
1321
+ }
1322
+ return new ToolLoopAgent({
1323
+ model: this._agent.model,
1324
+ instructions: this._agent.instructions ? this._agent.instructions.build(context) : "",
1325
+ tools,
1326
+ callOptionsSchema: this._agent.schema
1327
+ });
1328
+ }
1329
+ async initializeMCPClient(mcpConfig) {
1330
+ if (this._agent.toolsets[mcpConfig.name]) {
1331
+ return this._agent.toolsets[mcpConfig.name];
1332
+ }
1333
+ let client = null;
1334
+ try {
1335
+ if (mcpConfig.type === "stdio") {
1336
+ const stdioConfig = mcpConfig;
1337
+ this.logger?.debug("IgniterAgent.mcp.connect stdio", {
1338
+ command: stdioConfig.command,
1339
+ args: stdioConfig.args
1340
+ });
1341
+ client = await experimental_createMCPClient({
1342
+ transport: new StdioClientTransport({
1343
+ command: stdioConfig.command,
1344
+ args: stdioConfig.args,
1345
+ env: stdioConfig.env
1346
+ })
1347
+ });
1348
+ }
1349
+ if (mcpConfig.type === "http") {
1350
+ const httpConfig = mcpConfig;
1351
+ this.logger?.debug("IgniterAgent.mcp.connect http", {
1352
+ url: httpConfig.url
1353
+ });
1354
+ const url = new URL(httpConfig.url);
1355
+ client = await experimental_createMCPClient({
1356
+ transport: new StreamableHTTPClientTransport(url, {
1357
+ requestInit: {
1358
+ headers: httpConfig.headers
1359
+ }
1360
+ })
1361
+ });
1362
+ }
1363
+ if (!client) {
1364
+ throw new IgniterAgentMCPError({
1365
+ message: `Failed to create MCP client for '${mcpConfig.name}'`,
1366
+ code: "IGNITER_AGENT_MCP_CONNECTION_FAILED" /* MCP_CONNECTION_FAILED */,
1367
+ mcpName: mcpConfig.name
1368
+ });
1369
+ }
1370
+ const tools = await client.tools();
1371
+ return {
1372
+ type: mcpConfig.type,
1373
+ status: "connected",
1374
+ name: mcpConfig.name,
1375
+ tools
1376
+ };
1377
+ } catch (error) {
1378
+ const err = error instanceof Error ? error : new Error(String(error));
1379
+ this.hooks.onMCPError?.(this.getName(), mcpConfig.name, err);
1380
+ throw err;
1381
+ }
1382
+ }
1383
+ };
1384
+
1385
+ // src/builders/main.builder.ts
1386
+ var IgniterAgentManagerBuilder = class _IgniterAgentManagerBuilder {
1387
+ constructor(manager) {
1388
+ this._manager = manager;
1389
+ }
1390
+ addAgent(name, agent) {
1391
+ return new _IgniterAgentManagerBuilder({
1392
+ logger: this._manager.logger,
1393
+ telemetry: this._manager.telemetry,
1394
+ autoStart: this._manager.autoStart,
1395
+ continueOnError: this._manager.continueOnError,
1396
+ onAgentStart: this._manager.onAgentStart,
1397
+ onAgentError: this._manager.onAgentError,
1398
+ onToolCallStart: this._manager.onToolCallStart,
1399
+ onToolCallEnd: this._manager.onToolCallEnd,
1400
+ onToolCallError: this._manager.onToolCallError,
1401
+ onMCPStart: this._manager.onMCPStart,
1402
+ onMCPError: this._manager.onMCPError,
1403
+ agents: {
1404
+ ...this._manager.agents,
1405
+ [name]: agent
1406
+ }
1407
+ });
1408
+ }
1409
+ withLogger(logger) {
1410
+ return new _IgniterAgentManagerBuilder({
1411
+ ...this._manager,
1412
+ logger
1413
+ });
1414
+ }
1415
+ withTelemetry(telemetry) {
1416
+ return new _IgniterAgentManagerBuilder({
1417
+ ...this._manager,
1418
+ telemetry
1419
+ });
1420
+ }
1421
+ withAutoStart(autoStart) {
1422
+ return new _IgniterAgentManagerBuilder({
1423
+ ...this._manager,
1424
+ autoStart
1425
+ });
1426
+ }
1427
+ withContinueOnError(continueOnError) {
1428
+ return new _IgniterAgentManagerBuilder({
1429
+ ...this._manager,
1430
+ continueOnError
1431
+ });
1432
+ }
1433
+ onAgentStart(callback) {
1434
+ return new _IgniterAgentManagerBuilder({
1435
+ ...this._manager,
1436
+ onAgentStart: callback
1437
+ });
1438
+ }
1439
+ onAgentError(callback) {
1440
+ return new _IgniterAgentManagerBuilder({
1441
+ ...this._manager,
1442
+ onAgentError: callback
1443
+ });
1444
+ }
1445
+ onToolCallStart(callback) {
1446
+ const manager = new _IgniterAgentManagerBuilder({
1447
+ ...this._manager,
1448
+ onToolCallStart: callback
1449
+ });
1450
+ return manager;
1451
+ }
1452
+ onToolCallEnd(callback) {
1453
+ const manager = new _IgniterAgentManagerBuilder({
1454
+ ...this._manager,
1455
+ onToolCallEnd: callback
1456
+ });
1457
+ return manager;
1458
+ }
1459
+ onToolCallError(callback) {
1460
+ const manager = new _IgniterAgentManagerBuilder({
1461
+ ...this._manager,
1462
+ onToolCallError: callback
1463
+ });
1464
+ return manager;
1465
+ }
1466
+ onMCPStart(callback) {
1467
+ const manager = new _IgniterAgentManagerBuilder({
1468
+ ...this._manager,
1469
+ onMCPStart: callback
1470
+ });
1471
+ return manager;
1472
+ }
1473
+ onMCPError(callback) {
1474
+ const manager = new _IgniterAgentManagerBuilder({
1475
+ ...this._manager,
1476
+ onMCPError: callback
1477
+ });
1478
+ return manager;
1479
+ }
1480
+ static create() {
1481
+ return new _IgniterAgentManagerBuilder({
1482
+ agents: {},
1483
+ autoStart: false,
1484
+ continueOnError: true
1485
+ });
1486
+ }
1487
+ build() {
1488
+ return new IgniterAgentManagerCore(this._manager);
1489
+ }
1490
+ };
1491
+ var IgniterAgentManager = {
1492
+ create: IgniterAgentManagerBuilder.create
1493
+ };
1494
+
1495
+ // src/builders/prompt.builder.ts
1496
+ var TEMPLATE_PATTERN = /\{\{\s*([^}]+?)\s*\}\}/g;
1497
+ var resolvePath = (value, path) => {
1498
+ if (!path) return void 0;
1499
+ return path.split(".").reduce((acc, key) => {
1500
+ if (acc && typeof acc === "object" && key in acc) {
1501
+ return acc[key];
1502
+ }
1503
+ return void 0;
1504
+ }, value);
1505
+ };
1506
+ var IgniterAgentPromptBuilder = class _IgniterAgentPromptBuilder {
1507
+ constructor(template) {
1508
+ this.template = template;
1509
+ }
1510
+ /**
1511
+ * Creates a new prompt builder.
1512
+ *
1513
+ * @param template - Prompt template string with {{placeholders}}
1514
+ * @returns A new prompt builder instance
1515
+ */
1516
+ static create(template) {
1517
+ return new _IgniterAgentPromptBuilder(
1518
+ template
1519
+ );
1520
+ }
1521
+ /**
1522
+ * Builds the prompt string with the provided context.
1523
+ *
1524
+ * @param context - Context data used for interpolation
1525
+ * @returns The resolved prompt string
1526
+ */
1527
+ build(context) {
1528
+ return this.template.replace(TEMPLATE_PATTERN, (_match, path) => {
1529
+ const value = resolvePath(context, String(path));
1530
+ return value === void 0 || value === null ? "" : String(value);
1531
+ });
1532
+ }
1533
+ /**
1534
+ * Returns the raw prompt template string.
1535
+ */
1536
+ getTemplate() {
1537
+ return this.template;
1538
+ }
1539
+ };
1540
+ var IgniterAgentPrompt = IgniterAgentPromptBuilder;
1541
+
1542
+ // src/builders/agent.builder.ts
1543
+ var IgniterAgentBuilder = class _IgniterAgentBuilder {
1544
+ /**
1545
+ * Creates a new IgniterAgentBuilder instance.
1546
+ *
1547
+ * @param config - Initial configuration
1548
+ * @internal
1549
+ */
1550
+ constructor(config = {}) {
1551
+ this._config = {
1552
+ name: "agent",
1553
+ toolsets: {},
1554
+ configs: {},
1555
+ instructions: IgniterAgentPromptBuilder.create(""),
1556
+ ...config
1557
+ };
1558
+ }
1559
+ /* ---------------------------------------------------------------------------
1560
+ * STATIC FACTORY METHODS
1561
+ * --------------------------------------------------------------------------- */
1562
+ /**
1563
+ * Creates a new agent builder.
1564
+ *
1565
+ * @description
1566
+ * Primary entry point for creating an agent. Returns a new builder
1567
+ * instance that can be configured using fluent methods.
1568
+ *
1569
+ * @returns A new IgniterAgentBuilder instance
1570
+ *
1571
+ * @example
1572
+ * ```typescript
1573
+ * const agent = IgniterAgent.create('my-agent')
1574
+ * .withModel(openai('gpt-4'))
1575
+ * .build();
1576
+ * ```
1577
+ *
1578
+ * @public
1579
+ */
1580
+ static create(name = "agent") {
1581
+ return new _IgniterAgentBuilder({
1582
+ name
1583
+ });
1584
+ }
1585
+ /* ---------------------------------------------------------------------------
1586
+ * BUILDER METHODS
1587
+ * --------------------------------------------------------------------------- */
1588
+ /**
1589
+ * Sets the language model.
1590
+ *
1591
+ * @description
1592
+ * Configures the AI model that powers the agent. Supports any model
1593
+ * provider compatible with the Vercel AI SDK.
1594
+ *
1595
+ * @typeParam TNewModel - The new model type
1596
+ * @param model - The language model instance
1597
+ * @returns A new builder with the model set
1598
+ *
1599
+ * @example
1600
+ * ```typescript
1601
+ * import { openai } from '@ai-sdk/openai';
1602
+ * import { anthropic } from '@ai-sdk/anthropic';
1603
+ * import { google } from '@ai-sdk/google';
1604
+ *
1605
+ * // Using OpenAI
1606
+ * const agent1 = IgniterAgent.create()
1607
+ * .withModel(openai('gpt-4-turbo'))
1608
+ * .build();
1609
+ *
1610
+ * // Using Anthropic
1611
+ * const agent2 = IgniterAgent.create()
1612
+ * .withModel(anthropic('claude-3-opus'))
1613
+ * .build();
1614
+ *
1615
+ * // Using Google
1616
+ * const agent3 = IgniterAgent.create()
1617
+ * .withModel(google('gemini-pro'))
1618
+ * .build();
1619
+ * ```
1620
+ *
1621
+ * @public
1622
+ */
1623
+ withModel(model) {
1624
+ return new _IgniterAgentBuilder({
1625
+ ...this._config,
1626
+ model
1627
+ });
1628
+ }
1629
+ /**
1630
+ * Sets the prompt instructions.
1631
+ *
1632
+ * @description
1633
+ * Configures the agent's system prompt using an IgniterAgentPrompt template.
1634
+ * The prompt defines the agent's behavior, personality, and capabilities.
1635
+ *
1636
+ * @typeParam TNewInstructions - The new instructions type
1637
+ * @param instructions - The prompt template instance
1638
+ * @returns A new builder with the instructions set
1639
+ *
1640
+ * @example
1641
+ * ```typescript
1642
+ * const agent = IgniterAgent.create()
1643
+ * .withPrompt(
1644
+ * IgniterAgentPrompt.create(`
1645
+ * You are a helpful coding assistant specialized in TypeScript.
1646
+ *
1647
+ * Guidelines:
1648
+ * - Always provide type-safe code
1649
+ * - Include JSDoc comments
1650
+ * - Follow best practices
1651
+ * `)
1652
+ * )
1653
+ * .build();
1654
+ * ```
1655
+ *
1656
+ * @public
1657
+ */
1658
+ withPrompt(instructions) {
1659
+ return new _IgniterAgentBuilder({
1660
+ ...this._config,
1661
+ instructions
1662
+ });
1663
+ }
1664
+ /**
1665
+ * Attaches a logger instance for operational logs.
1666
+ */
1667
+ withLogger(logger) {
1668
+ return new _IgniterAgentBuilder({
1669
+ ...this._config,
1670
+ logger
1671
+ });
1672
+ }
1673
+ /**
1674
+ * Attaches a telemetry manager for observability.
1675
+ */
1676
+ withTelemetry(telemetry) {
1677
+ return new _IgniterAgentBuilder({
1678
+ ...this._config,
1679
+ telemetry
1680
+ });
1681
+ }
1682
+ /**
1683
+ * Configures persistent memory for the agent.
1684
+ */
1685
+ withMemory(memory) {
1686
+ return new _IgniterAgentBuilder({
1687
+ ...this._config,
1688
+ memory
1689
+ });
1690
+ }
1691
+ /**
1692
+ * Callback when the agent starts.
1693
+ */
1694
+ onAgentStart(callback) {
1695
+ return new _IgniterAgentBuilder({
1696
+ ...this._config,
1697
+ hooks: {
1698
+ ...this._config.hooks,
1699
+ onAgentStart: callback
1700
+ }
1701
+ });
1702
+ }
1703
+ /**
1704
+ * Callback when the agent errors.
1705
+ */
1706
+ onAgentError(callback) {
1707
+ return new _IgniterAgentBuilder({
1708
+ ...this._config,
1709
+ hooks: {
1710
+ ...this._config.hooks,
1711
+ onAgentError: callback
1712
+ }
1713
+ });
1714
+ }
1715
+ /**
1716
+ * Callback when a tool call starts.
1717
+ */
1718
+ onToolCallStart(callback) {
1719
+ return new _IgniterAgentBuilder({
1720
+ ...this._config,
1721
+ hooks: {
1722
+ ...this._config.hooks,
1723
+ onToolCallStart: callback
1724
+ }
1725
+ });
1726
+ }
1727
+ /**
1728
+ * Callback when a tool call completes.
1729
+ */
1730
+ onToolCallEnd(callback) {
1731
+ return new _IgniterAgentBuilder({
1732
+ ...this._config,
1733
+ hooks: {
1734
+ ...this._config.hooks,
1735
+ onToolCallEnd: callback
1736
+ }
1737
+ });
1738
+ }
1739
+ /**
1740
+ * Callback when a tool call fails.
1741
+ */
1742
+ onToolCallError(callback) {
1743
+ return new _IgniterAgentBuilder({
1744
+ ...this._config,
1745
+ hooks: {
1746
+ ...this._config.hooks,
1747
+ onToolCallError: callback
1748
+ }
1749
+ });
1750
+ }
1751
+ /**
1752
+ * Callback when an MCP connection starts.
1753
+ */
1754
+ onMCPStart(callback) {
1755
+ return new _IgniterAgentBuilder({
1756
+ ...this._config,
1757
+ hooks: {
1758
+ ...this._config.hooks,
1759
+ onMCPStart: callback
1760
+ }
1761
+ });
1762
+ }
1763
+ /**
1764
+ * Callback when an MCP connection fails.
1765
+ */
1766
+ onMCPError(callback) {
1767
+ return new _IgniterAgentBuilder({
1768
+ ...this._config,
1769
+ hooks: {
1770
+ ...this._config.hooks,
1771
+ onMCPError: callback
1772
+ }
1773
+ });
1774
+ }
1775
+ /**
1776
+ * Sets the context schema.
1777
+ *
1778
+ * @description
1779
+ * Configures a Zod schema for validating context passed to the agent.
1780
+ * The context is available in prompt templates and can be used to
1781
+ * customize agent behavior per-request.
1782
+ *
1783
+ * @typeParam TNewSchema - The new schema type
1784
+ * @param schema - The Zod schema for context validation
1785
+ * @returns A new builder with the schema set
1786
+ *
1787
+ * @example
1788
+ * ```typescript
1789
+ * import { z } from 'zod';
1790
+ *
1791
+ * const contextSchema = z.object({
1792
+ * userId: z.string(),
1793
+ * chatId: z.string(),
1794
+ * userRole: z.enum(['admin', 'user', 'guest']),
1795
+ * preferences: z.object({
1796
+ * language: z.string().default('en'),
1797
+ * theme: z.string().optional()
1798
+ * })
1799
+ * });
1800
+ *
1801
+ * const agent = IgniterAgent.create()
1802
+ * .withContextSchema(contextSchema)
1803
+ * .build();
1804
+ *
1805
+ * // Context is type-safe when calling generate
1806
+ * await agent.generate({
1807
+ * messages: [...],
1808
+ * options: {
1809
+ * userId: 'user_123',
1810
+ * chatId: 'chat_456',
1811
+ * userRole: 'admin',
1812
+ * preferences: { language: 'pt' }
1813
+ * }
1814
+ * });
1815
+ * ```
1816
+ *
1817
+ * @public
1818
+ */
1819
+ withContextSchema(schema) {
1820
+ return new _IgniterAgentBuilder({
1821
+ ...this._config,
1822
+ schema
1823
+ });
1824
+ }
1825
+ /**
1826
+ * Adds a toolset to the agent.
1827
+ *
1828
+ * @description
1829
+ * Registers a toolset with the agent. The toolset's tools become available
1830
+ * for the AI to invoke. Multiple toolsets can be added to a single agent.
1831
+ *
1832
+ * Tool names are prefixed with the toolset name to avoid collisions:
1833
+ * `{toolsetName}_{toolName}`
1834
+ *
1835
+ * @typeParam TNewToolset - The toolset type
1836
+ * @param toolset - The toolset to register
1837
+ * @returns A new builder with the toolset added
1838
+ *
1839
+ * @example
1840
+ * ```typescript
1841
+ * const githubToolset = IgniterAgentToolset.create('github')
1842
+ * .addTool(createIssueTool)
1843
+ * .addTool(listReposTool)
1844
+ * .build();
1845
+ *
1846
+ * const dockerToolset = IgniterAgentToolset.create('docker')
1847
+ * .addTool(buildImageTool)
1848
+ * .addTool(runContainerTool)
1849
+ * .build();
1850
+ *
1851
+ * const agent = IgniterAgent.create()
1852
+ * .addToolset(githubToolset) // Adds github_createIssue, github_listRepos
1853
+ * .addToolset(dockerToolset) // Adds docker_build, docker_run
1854
+ * .build();
1855
+ * ```
1856
+ *
1857
+ * @public
1858
+ */
1859
+ addToolset(toolset) {
1860
+ return new _IgniterAgentBuilder({
1861
+ ...this._config,
1862
+ toolsets: {
1863
+ ...this._config.toolsets,
1864
+ [toolset.name]: toolset
1865
+ }
1866
+ });
1867
+ }
1868
+ /**
1869
+ * Adds an MCP configuration to the agent.
1870
+ *
1871
+ * @description
1872
+ * Registers an MCP server configuration with the agent. The MCP server
1873
+ * will be connected when `agent.start()` is called, and its tools will
1874
+ * become available for the AI to invoke.
1875
+ *
1876
+ * @typeParam TMCPType - The MCP transport type
1877
+ * @typeParam TMCPName - The MCP configuration name
1878
+ * @param config - The MCP configuration
1879
+ * @returns A new builder with the MCP config added
1880
+ *
1881
+ * @example
1882
+ * ```typescript
1883
+ * const filesystemMCP = IgniterAgentMCPClient.create('filesystem')
1884
+ * .withType('stdio')
1885
+ * .withCommand('npx')
1886
+ * .withArgs(['-y', '@modelcontextprotocol/server-filesystem', '/tmp'])
1887
+ * .build();
1888
+ *
1889
+ * const remoteMCP = IgniterAgentMCPClient.create('remote-api')
1890
+ * .withType('http')
1891
+ * .withURL('https://api.example.com/mcp')
1892
+ * .withHeaders({ 'Authorization': 'Bearer xxx' })
1893
+ * .build();
1894
+ *
1895
+ * const agent = IgniterAgent.create()
1896
+ * .addMCP(filesystemMCP)
1897
+ * .addMCP(remoteMCP)
1898
+ * .build();
1899
+ *
1900
+ * // MCP connections are established here
1901
+ * await agent.start();
1902
+ * ```
1903
+ *
1904
+ * @public
1905
+ */
1906
+ addMCP(config) {
1907
+ return new _IgniterAgentBuilder({
1908
+ ...this._config,
1909
+ configs: {
1910
+ ...this._config.configs,
1911
+ [config.name]: config
1912
+ }
1913
+ });
1914
+ }
1915
+ /* ---------------------------------------------------------------------------
1916
+ * BUILD METHOD
1917
+ * --------------------------------------------------------------------------- */
1918
+ /**
1919
+ * Builds and returns the completed agent.
1920
+ *
1921
+ * @description
1922
+ * Finalizes the agent configuration and returns a runtime agent object.
1923
+ * The agent provides methods for:
1924
+ * - `start()`: Initialize MCP connections
1925
+ * - `generate()`: Generate a single response
1926
+ * - `stream()`: Stream a response
1927
+ * - Accessors for configuration
1928
+ *
1929
+ * @returns The built agent runtime object
1930
+ *
1931
+ * @example
1932
+ * ```typescript
1933
+ * const agent = IgniterAgent.create('assistant')
1934
+ * .withModel(openai('gpt-4'))
1935
+ * .addToolset(myToolset)
1936
+ * .build();
1937
+ *
1938
+ * // Start the agent
1939
+ * await agent.start();
1940
+ *
1941
+ * // Generate a response
1942
+ * const result = await agent.generate({
1943
+ * messages: [{ role: 'user', content: 'Hello!' }]
1944
+ * });
1945
+ *
1946
+ * // Access configuration
1947
+ * console.log('Model:', agent.getModel());
1948
+ * console.log('Toolsets:', agent.getToolsets());
1949
+ * ```
1950
+ *
1951
+ * @public
1952
+ */
1953
+ build() {
1954
+ return new IgniterAgentCore(this._config);
1955
+ }
1956
+ /* ---------------------------------------------------------------------------
1957
+ * ACCESSORS
1958
+ * --------------------------------------------------------------------------- */
1959
+ /**
1960
+ * Gets the current configuration (partial).
1961
+ *
1962
+ * @returns The current configuration state
1963
+ * @public
1964
+ */
1965
+ getConfig() {
1966
+ return { ...this._config };
1967
+ }
1968
+ /**
1969
+ * Gets the agent name.
1970
+ *
1971
+ * @returns The agent's name
1972
+ * @public
1973
+ */
1974
+ getName() {
1975
+ return this._config.name;
1976
+ }
1977
+ };
1978
+ var IgniterAgent = {
1979
+ create: IgniterAgentBuilder.create
1980
+ };
1981
+ var IgniterAgentToolsetBuilder = class _IgniterAgentToolsetBuilder {
1982
+ /**
1983
+ * Creates a new IgniterAgentToolsetBuilder instance.
1984
+ *
1985
+ * @param params - The toolset name and initial tools
1986
+ * @internal
1987
+ */
1988
+ constructor(params) {
1989
+ this._name = params.name;
1990
+ this._tools = params.tools;
1991
+ }
1992
+ /* ---------------------------------------------------------------------------
1993
+ * STATIC FACTORY METHODS
1994
+ * --------------------------------------------------------------------------- */
1995
+ /**
1996
+ * Creates a new toolset builder with the given name.
1997
+ *
1998
+ * @description
1999
+ * This is the primary entry point for creating a new toolset.
2000
+ * The name must be unique within an agent and is used as a prefix
2001
+ * for tool names when the toolset is registered.
2002
+ *
2003
+ * @typeParam TName - The toolset name type
2004
+ * @param name - Unique name for the toolset
2005
+ * @returns A new IgniterAgentToolsetBuilder instance
2006
+ *
2007
+ * @example
2008
+ * ```typescript
2009
+ * const tool = IgniterAgentTool
2010
+ * .create('doSomething')
2011
+ * .withDescription('Does something')
2012
+ * .withInputect({}))
2013
+ * .withExecute(async () => ({ ok: true }))
2014
+ * .build();
2015
+ *
2016
+ * const toolset = IgniterAgentToolset
2017
+ * .create('myTools')
2018
+ * .addTool(tool)
2019
+ * .build();
2020
+ * ```
2021
+ *
2022
+ * @public
2023
+ */
2024
+ static create(name) {
2025
+ if (!name || typeof name !== "string") {
2026
+ throw new IgniterAgentConfigError({
2027
+ message: "Toolset name is required and must be a non-empty string",
2028
+ field: "name"
2029
+ });
2030
+ }
2031
+ return new _IgniterAgentToolsetBuilder({
2032
+ name,
2033
+ tools: {}
2034
+ });
2035
+ }
2036
+ /* ---------------------------------------------------------------------------
2037
+ * BUILDER METHODS
2038
+ * --------------------------------------------------------------------------- */
2039
+ /**
2040
+ * Changes the toolset name.
2041
+ *
2042
+ * @description
2043
+ * Allows renaming the toolset during the building process.
2044
+ * This creates a new builder instance with the new name.
2045
+ *
2046
+ * @typeParam TNewName - The new name type
2047
+ * @param name - The new name for the toolset
2048
+ * @returns A new builder with the updated name
2049
+ *
2050
+ * @example
2051
+ * ```typescript
2052
+ * const toolset = IgniterAgentToolset
2053
+ * .create('temp')
2054
+ * .withName('production') // Rename to 'production'
2055
+ * .addTool(myTool)
2056
+ * .build();
2057
+ * ```
2058
+ *
2059
+ * @public
2060
+ */
2061
+ withName(name) {
2062
+ return new _IgniterAgentToolsetBuilder({
2063
+ name,
2064
+ tools: this._tools
2065
+ });
2066
+ }
2067
+ /**
2068
+ * Adds a tool to the toolset.
2069
+ *
2070
+ * @description
2071
+ * Adds a built tool definition to the toolset. The tool is automatically
2072
+ * wrapped with error handling that returns a consistent result format
2073
+ * (`{ success: true, data: ... }` or `{ success: false, error: ... }`).
2074
+ *
2075
+ * @typeParam TToolName - The tool name type
2076
+ * @param dto - The built tool definition
2077
+ * @returns A new builder with the tool added
2078
+ *
2079
+ * @example
2080
+ * ```typescript
2081
+ * const greetTool = IgniterAgentTool.create('greet')
2082
+ * .withDescription('Greets a user')
2083
+ * .withInputect({ name: z.string() }))
2084
+ * .withExecute(async ({ name }) => `Hello, ${name}!`)
2085
+ * .build();
2086
+ *
2087
+ * const toolset = IgniterAgentToolset.create('utils')
2088
+ * .addTool(greetTool)
2089
+ * .build();
2090
+ * ```
2091
+ *
2092
+ * @public
2093
+ */
2094
+ addTool(dto) {
2095
+ if (!dto.name || typeof dto.name !== "string") {
2096
+ throw new IgniterAgentConfigError({
2097
+ message: "Tool name is required and must be a non-empty string",
2098
+ field: "name",
2099
+ metadata: { toolset: this._name }
2100
+ });
2101
+ }
2102
+ const wrappedTool = tool({
2103
+ description: dto.description,
2104
+ inputSchema: dto.inputSchema,
2105
+ outputSchema: dto.outputSchema,
2106
+ execute: async (params, options) => {
2107
+ if (!dto.execute) {
2108
+ const result = {
2109
+ success: false,
2110
+ error: `Tool '${dto.name}' has no execute method`
2111
+ };
2112
+ return result;
2113
+ }
2114
+ try {
2115
+ const response = await dto.execute(params, options);
2116
+ const result = {
2117
+ success: true,
2118
+ data: response
2119
+ };
2120
+ return result;
2121
+ } catch (error) {
2122
+ console.error(
2123
+ `[IgniterAgent] Error executing tool '${dto.name}':`,
2124
+ error
2125
+ );
2126
+ const errorMessage = error instanceof Error ? error.message : String(error);
2127
+ const result = {
2128
+ success: false,
2129
+ error: errorMessage
2130
+ };
2131
+ return result;
2132
+ }
2133
+ }
2134
+ });
2135
+ return new _IgniterAgentToolsetBuilder({
2136
+ name: this._name,
2137
+ tools: {
2138
+ ...this._tools,
2139
+ [dto.name]: wrappedTool
2140
+ }
2141
+ });
2142
+ }
2143
+ /* ---------------------------------------------------------------------------
2144
+ * BUILD METHOD
2145
+ * --------------------------------------------------------------------------- */
2146
+ /**
2147
+ * Builds and returns the completed toolset.
2148
+ *
2149
+ * @description
2150
+ * Finalizes the toolset configuration and returns an object that can
2151
+ * be registered with an agent using `addToolset()`.
2152
+ *
2153
+ * The returned object includes:
2154
+ * - `name`: The toolset's unique identifier
2155
+ * - `type`: Always `'custom'` for user-defined toolsets
2156
+ * - `status`: Always `'connected'` for custom toolsets
2157
+ * - `tools`: The tools collection
2158
+ * - `toolset`: Reference to the raw tools object
2159
+ *
2160
+ * @returns The completed toolset configuration
2161
+ *
2162
+ * @example
2163
+ * ```typescript
2164
+ * const toolset = IgniterAgentToolset
2165
+ * .create('utils')
2166
+ * .addTool(formatDateTool)
2167
+ * .addTool(parseJsonTool)
2168
+ * .build();
2169
+ *
2170
+ * console.log(toolset.name); // 'utils'
2171
+ * console.log(toolset.type); // 'custom'
2172
+ * console.log(toolset.status); // 'connected'
2173
+ * console.log(Object.keys(toolset.tools)); // ['formatDate', 'parseJSON']
2174
+ * ```
2175
+ *
2176
+ * @public
2177
+ */
2178
+ build() {
2179
+ return {
2180
+ type: "custom",
2181
+ name: this._name,
2182
+ toolset: this._tools,
2183
+ status: "connected",
2184
+ tools: this._tools,
2185
+ $Infer: {}
2186
+ };
2187
+ }
2188
+ /* ---------------------------------------------------------------------------
2189
+ * ACCESSORS
2190
+ * --------------------------------------------------------------------------- */
2191
+ /**
2192
+ * Gets the current toolset name.
2193
+ *
2194
+ * @returns The toolset's name
2195
+ * @public
2196
+ */
2197
+ getName() {
2198
+ return this._name;
2199
+ }
2200
+ /**
2201
+ * Gets the current tools collection.
2202
+ *
2203
+ * @returns The tools object
2204
+ * @public
2205
+ */
2206
+ getTools() {
2207
+ return this._tools;
2208
+ }
2209
+ /**
2210
+ * Gets the number of tools in the toolset.
2211
+ *
2212
+ * @returns The tool count
2213
+ * @public
2214
+ */
2215
+ getToolCount() {
2216
+ return Object.keys(this._tools).length;
2217
+ }
2218
+ };
2219
+ var IgniterAgentToolset = {
2220
+ create: IgniterAgentToolsetBuilder.create
2221
+ };
2222
+
2223
+ // src/builders/tool.builder.ts
2224
+ var IgniterAgentToolBuilder = class _IgniterAgentToolBuilder {
2225
+ /**
2226
+ * Creates a new IgniterAgentToolBuilder instance.
2227
+ *
2228
+ * @param name - The tool name
2229
+ * @param definition - Partial tool definition
2230
+ * @internal
2231
+ */
2232
+ constructor(definition = {}) {
2233
+ this._definition = definition;
2234
+ }
2235
+ /* ---------------------------------------------------------------------------
2236
+ * STATIC FACTORY METHODS
2237
+ * --------------------------------------------------------------------------- */
2238
+ /**
2239
+ * Creates a new tool builder with the given name.
2240
+ *
2241
+ * @description
2242
+ * The name must be unique within a toolset.
2243
+ *
2244
+ * @typeParam TNewName - The tool name type
2245
+ * @param name - Unique name for the tool
2246
+ * @returns A new IgniterAgentToolBuilder instance
2247
+ *
2248
+ * @public
2249
+ */
2250
+ static create(name) {
2251
+ if (!name || typeof name !== "string") {
2252
+ throw new IgniterAgentConfigError({
2253
+ message: "Tool name is required and must be a non-empty string",
2254
+ field: "name"
2255
+ });
2256
+ }
2257
+ return new _IgniterAgentToolBuilder({
2258
+ name
2259
+ });
2260
+ }
2261
+ /* ---------------------------------------------------------------------------
2262
+ * BUILDER METHODS
2263
+ * --------------------------------------------------------------------------- */
2264
+ /**
2265
+ * Sets the tool description.
2266
+ *
2267
+ * @param description - Human-readable description shown to the AI
2268
+ * @returns A new builder with the description set
2269
+ *
2270
+ * @public
2271
+ */
2272
+ withDescription(description) {
2273
+ if (!description || typeof description !== "string") {
2274
+ throw new IgniterAgentConfigError({
2275
+ message: "Tool description is required and must be a non-empty string",
2276
+ field: "description",
2277
+ metadata: { tool: this._definition.name }
2278
+ });
2279
+ }
2280
+ return new _IgniterAgentToolBuilder({
2281
+ ...this._definition,
2282
+ description
2283
+ });
2284
+ }
2285
+ /**
2286
+ * Sets the tool parameters schema.
2287
+ *
2288
+ * @typeParam TNewParams - The new parameters type
2289
+ * @param parameters - Zod schema defining input parameters
2290
+ * @returns A new builder with the parameters set
2291
+ *
2292
+ * @public
2293
+ */
2294
+ withInput(inputSchema) {
2295
+ if (!inputSchema) {
2296
+ throw new IgniterAgentConfigError({
2297
+ message: "Tool parameters schema is required",
2298
+ field: "parameters",
2299
+ metadata: { tool: this._definition.name }
2300
+ });
2301
+ }
2302
+ return new _IgniterAgentToolBuilder({
2303
+ ...this._definition,
2304
+ inputSchema
2305
+ });
2306
+ }
2307
+ /**
2308
+ * Sets the tool output schema.
2309
+ *
2310
+ * @typeParam TNewResult - The new result type
2311
+ * @param outputSchema - Zod schema defining the tool's output
2312
+ * @returns A new builder with the output schema set
2313
+ *
2314
+ * @public
2315
+ */
2316
+ withOutput(outputSchema) {
2317
+ if (!outputSchema) {
2318
+ throw new IgniterAgentConfigError({
2319
+ message: "Tool output schema is required",
2320
+ field: "outputSchema",
2321
+ metadata: { tool: this._definition.name }
2322
+ });
2323
+ }
2324
+ return new _IgniterAgentToolBuilder({
2325
+ ...this._definition,
2326
+ outputSchema
2327
+ });
2328
+ }
2329
+ /**
2330
+ * Sets the tool execution handler.
2331
+ *
2332
+ * @typeParam TNewResult - The new result type
2333
+ * @param execute - Function that performs the tool's logic
2334
+ * @returns A new builder with the execute handler set
2335
+ *
2336
+ * @public
2337
+ */
2338
+ withExecute(execute) {
2339
+ if (typeof execute !== "function") {
2340
+ throw new IgniterAgentConfigError({
2341
+ message: "Tool execute handler must be a function",
2342
+ field: "execute",
2343
+ metadata: { tool: this._definition.name }
2344
+ });
2345
+ }
2346
+ return new _IgniterAgentToolBuilder({
2347
+ ...this._definition,
2348
+ execute
2349
+ });
2350
+ }
2351
+ /* ---------------------------------------------------------------------------
2352
+ * BUILD METHOD
2353
+ * --------------------------------------------------------------------------- */
2354
+ /**
2355
+ * Builds and returns the completed tool definition.
2356
+ *
2357
+ * @returns The completed tool definition with its name
2358
+ *
2359
+ * @public
2360
+ */
2361
+ build() {
2362
+ const { name, description, inputSchema, outputSchema, execute } = this._definition;
2363
+ if (!name) {
2364
+ throw new IgniterAgentConfigError({
2365
+ message: "Tool name is required before building",
2366
+ field: "name"
2367
+ });
2368
+ }
2369
+ if (!description) {
2370
+ throw new IgniterAgentConfigError({
2371
+ message: "Tool description is required before building",
2372
+ field: "description",
2373
+ metadata: { tool: this._definition.name }
2374
+ });
2375
+ }
2376
+ if (!inputSchema) {
2377
+ throw new IgniterAgentConfigError({
2378
+ message: "Tool parameters schema is required before building",
2379
+ field: "parameters",
2380
+ metadata: { tool: this._definition.name }
2381
+ });
2382
+ }
2383
+ if (!execute) {
2384
+ throw new IgniterAgentConfigError({
2385
+ message: "Tool execute handler is required before building",
2386
+ field: "execute",
2387
+ metadata: { tool: this._definition.name }
2388
+ });
2389
+ }
2390
+ return {
2391
+ name,
2392
+ description,
2393
+ inputSchema,
2394
+ outputSchema,
2395
+ execute,
2396
+ $Infer: {}
2397
+ };
2398
+ }
2399
+ };
2400
+ var IgniterAgentTool = {
2401
+ create: IgniterAgentToolBuilder.create
2402
+ };
2403
+
2404
+ // src/builders/mcp.builder.ts
2405
+ var IgniterAgentMCPBuilder = class _IgniterAgentMCPBuilder {
2406
+ /**
2407
+ * Creates a new IgniterAgentMCPBuilder instance.
2408
+ *
2409
+ * @param config - Initial configuration
2410
+ * @internal
2411
+ */
2412
+ constructor(config = {}) {
2413
+ this._config = config;
2414
+ }
2415
+ /* ---------------------------------------------------------------------------
2416
+ * STATIC FACTORY METHODS
2417
+ * --------------------------------------------------------------------------- */
2418
+ /**
2419
+ * Creates a new MCP builder with the given name.
2420
+ *
2421
+ * @description
2422
+ * This is the primary entry point for creating an MCP configuration.
2423
+ * The name must be unique within an agent and is used to identify
2424
+ * the MCP server and its tools.
2425
+ *
2426
+ * After calling `create()`, you must call `withType()` to specify
2427
+ * the transport type before configuring transport-specific options.
2428
+ *
2429
+ * @typeParam TNewName - The configuration name type
2430
+ * @param name - Unique name for the MCP configuration
2431
+ * @returns A new IgniterAgentMCPBuilder instance
2432
+ *
2433
+ * @example
2434
+ * ```typescript
2435
+ * const mcpConfig = IgniterAgentMCPBuilder
2436
+ * .create('my-mcp')
2437
+ * .withType('stdio') // or 'http'
2438
+ * .withCommand('...') // available after withType('stdio')
2439
+ * .build();
2440
+ * ```
2441
+ *
2442
+ * @public
2443
+ */
2444
+ static create(name) {
2445
+ if (!name || typeof name !== "string") {
2446
+ throw new IgniterAgentConfigError({
2447
+ message: "MCP configuration name is required and must be a non-empty string",
2448
+ field: "name"
2449
+ });
2450
+ }
2451
+ return new _IgniterAgentMCPBuilder({
2452
+ name
2453
+ });
2454
+ }
2455
+ /* ---------------------------------------------------------------------------
2456
+ * COMMON BUILDER METHODS
2457
+ * --------------------------------------------------------------------------- */
2458
+ /**
2459
+ * Sets the configuration name.
2460
+ *
2461
+ * @description
2462
+ * Allows changing the configuration name during the building process.
2463
+ *
2464
+ * @typeParam TNewName - The new name type
2465
+ * @param name - The new name for the configuration
2466
+ * @returns A new builder with the updated name
2467
+ *
2468
+ * @public
2469
+ */
2470
+ withName(name) {
2471
+ return new _IgniterAgentMCPBuilder({
2472
+ ...this._config,
2473
+ name
2474
+ });
2475
+ }
2476
+ /**
2477
+ * Sets the transport type for the MCP connection.
2478
+ *
2479
+ * @description
2480
+ * Specifies how the agent will communicate with the MCP server:
2481
+ * - `stdio`: Spawns a local process and communicates via stdin/stdout
2482
+ * - `http`: Connects to a remote server via HTTP/HTTPS
2483
+ *
2484
+ * After calling this method, transport-specific methods become available:
2485
+ * - For `stdio`: `withCommand()`, `withArgs()`, `withEnv()`
2486
+ * - For `http`: `withURL()`, `withHeaders()`
2487
+ *
2488
+ * @typeParam TNewType - The transport type
2489
+ * @param type - The transport type to use
2490
+ * @returns A new builder configured for the specified transport
2491
+ *
2492
+ * @example
2493
+ * ```typescript
2494
+ * // Stdio transport
2495
+ * const stdioConfig = IgniterAgentMCPBuilder
2496
+ * .create('local')
2497
+ * .withType('stdio')
2498
+ * .withCommand('python')
2499
+ * .withArgs(['mcp_server.py'])
2500
+ * .build();
2501
+ *
2502
+ * // HTTP transport
2503
+ * const httpConfig = IgniterAgentMCPBuilder
2504
+ * .create('remote')
2505
+ * .withType('http')
2506
+ * .withURL('https://api.example.com/mcp')
2507
+ * .build();
2508
+ * ```
2509
+ *
2510
+ * @public
2511
+ */
2512
+ withType(type) {
2513
+ if (type !== "stdio" && type !== "http") {
2514
+ throw new IgniterAgentConfigError({
2515
+ message: `Invalid MCP transport type: '${type}'. Must be 'stdio' or 'http'`,
2516
+ field: "type",
2517
+ metadata: { validTypes: ["stdio", "http"] }
2518
+ });
2519
+ }
2520
+ return new _IgniterAgentMCPBuilder({
2521
+ ...this._config,
2522
+ type
2523
+ });
2524
+ }
2525
+ /* ---------------------------------------------------------------------------
2526
+ * STDIO-SPECIFIC BUILDER METHODS
2527
+ * --------------------------------------------------------------------------- */
2528
+ /**
2529
+ * Sets the command to execute for stdio transport.
2530
+ *
2531
+ * @description
2532
+ * Specifies the executable to run when starting the MCP server process.
2533
+ * Common values include `npx`, `node`, `python`, `deno`, etc.
2534
+ *
2535
+ * @param command - The command to execute
2536
+ * @returns A new builder with the command set
2537
+ * @throws {IgniterAgentConfigError} If transport type is not 'stdio'
2538
+ *
2539
+ * @example
2540
+ * ```typescript
2541
+ * const config = IgniterAgentMCPBuilder
2542
+ * .create('filesystem')
2543
+ * .withType('stdio')
2544
+ * .withCommand('npx')
2545
+ * .withArgs(['-y', '@modelcontextprotocol/server-filesystem'])
2546
+ * .build();
2547
+ * ```
2548
+ *
2549
+ * @public
2550
+ */
2551
+ withCommand(command) {
2552
+ this._assertStdioType("withCommand");
2553
+ if (!command || typeof command !== "string") {
2554
+ throw new IgniterAgentConfigError({
2555
+ message: "Command is required and must be a non-empty string",
2556
+ field: "command",
2557
+ metadata: { mcpName: this._config.name }
2558
+ });
2559
+ }
2560
+ return new _IgniterAgentMCPBuilder({
2561
+ ...this._config,
2562
+ command
2563
+ });
2564
+ }
2565
+ /**
2566
+ * Sets the arguments to pass to the command.
2567
+ *
2568
+ * @description
2569
+ * Specifies command-line arguments for the MCP server process.
2570
+ *
2571
+ * @param args - Array of command arguments
2572
+ * @returns A new builder with the arguments set
2573
+ * @throws {IgniterAgentConfigError} If transport type is not 'stdio'
2574
+ *
2575
+ * @example
2576
+ * ```typescript
2577
+ * const config = IgniterAgentMCPBuilder
2578
+ * .create('filesystem')
2579
+ * .withType('stdio')
2580
+ * .withCommand('npx')
2581
+ * .withArgs([
2582
+ * '-y',
2583
+ * '@modelcontextprotocol/server-filesystem',
2584
+ * '/home/user/documents',
2585
+ * '--read-only'
2586
+ * ])
2587
+ * .build();
2588
+ * ```
2589
+ *
2590
+ * @public
2591
+ */
2592
+ withArgs(args) {
2593
+ this._assertStdioType("withArgs");
2594
+ if (!Array.isArray(args)) {
2595
+ throw new IgniterAgentConfigError({
2596
+ message: "Args must be an array of strings",
2597
+ field: "args",
2598
+ metadata: { mcpName: this._config.name }
2599
+ });
2600
+ }
2601
+ return new _IgniterAgentMCPBuilder({
2602
+ ...this._config,
2603
+ args
2604
+ });
2605
+ }
2606
+ /**
2607
+ * Sets environment variables for the command process.
2608
+ *
2609
+ * @description
2610
+ * Specifies environment variables to pass to the MCP server process.
2611
+ * Useful for passing API keys, configuration, or feature flags.
2612
+ *
2613
+ * @param env - Record of environment variable names to values
2614
+ * @returns A new builder with the environment variables set
2615
+ * @throws {IgniterAgentConfigError} If transport type is not 'stdio'
2616
+ *
2617
+ * @example
2618
+ * ```typescript
2619
+ * const config = IgniterAgentMCPBuilder
2620
+ * .create('github')
2621
+ * .withType('stdio')
2622
+ * .withCommand('npx')
2623
+ * .withArgs(['-y', '@modelcontextprotocol/server-github'])
2624
+ * .withEnv({
2625
+ * GITHUB_TOKEN: process.env.GITHUB_TOKEN!,
2626
+ * GITHUB_ORG: 'my-organization',
2627
+ * DEBUG: 'mcp:*'
2628
+ * })
2629
+ * .build();
2630
+ * ```
2631
+ *
2632
+ * @public
2633
+ */
2634
+ withEnv(env) {
2635
+ this._assertStdioType("withEnv");
2636
+ if (!env || typeof env !== "object") {
2637
+ throw new IgniterAgentConfigError({
2638
+ message: "Env must be an object mapping variable names to values",
2639
+ field: "env",
2640
+ metadata: { mcpName: this._config.name }
2641
+ });
2642
+ }
2643
+ return new _IgniterAgentMCPBuilder({
2644
+ ...this._config,
2645
+ env
2646
+ });
2647
+ }
2648
+ /* ---------------------------------------------------------------------------
2649
+ * HTTP-SPECIFIC BUILDER METHODS
2650
+ * --------------------------------------------------------------------------- */
2651
+ /**
2652
+ * Sets the URL for HTTP transport.
2653
+ *
2654
+ * @description
2655
+ * Specifies the endpoint URL for the remote MCP server.
2656
+ * Must be a valid HTTP or HTTPS URL.
2657
+ *
2658
+ * @param url - The MCP server URL
2659
+ * @returns A new builder with the URL set
2660
+ * @throws {IgniterAgentConfigError} If transport type is not 'http' or URL is invalid
2661
+ *
2662
+ * @example
2663
+ * ```typescript
2664
+ * const config = IgniterAgentMCPBuilder
2665
+ * .create('opencode')
2666
+ * .withType('http')
2667
+ * .withURL('https://sandbox.example.com/mcp/v1')
2668
+ * .build();
2669
+ * ```
2670
+ *
2671
+ * @public
2672
+ */
2673
+ withURL(url) {
2674
+ this._assertHttpType("withURL");
2675
+ if (!url || typeof url !== "string") {
2676
+ throw new IgniterAgentConfigError({
2677
+ message: "URL is required and must be a non-empty string",
2678
+ field: "url",
2679
+ metadata: { mcpName: this._config.name }
2680
+ });
2681
+ }
2682
+ try {
2683
+ new URL(url);
2684
+ } catch {
2685
+ throw new IgniterAgentConfigError({
2686
+ message: `Invalid URL format: '${url}'`,
2687
+ field: "url",
2688
+ metadata: { mcpName: this._config.name }
2689
+ });
2690
+ }
2691
+ return new _IgniterAgentMCPBuilder({
2692
+ ...this._config,
2693
+ url
2694
+ });
2695
+ }
2696
+ /**
2697
+ * Sets HTTP headers for requests to the MCP server.
2698
+ *
2699
+ * @description
2700
+ * Specifies headers to include in all HTTP requests to the MCP server.
2701
+ * Commonly used for authentication, API keys, or content type.
2702
+ *
2703
+ * @param headers - Record of header names to values
2704
+ * @returns A new builder with the headers set
2705
+ * @throws {IgniterAgentConfigError} If transport type is not 'http'
2706
+ *
2707
+ * @example
2708
+ * ```typescript
2709
+ * const config = IgniterAgentMCPBuilder
2710
+ * .create('authenticated-mcp')
2711
+ * .withType('http')
2712
+ * .withURL('https://api.example.com/mcp')
2713
+ * .withHeaders({
2714
+ * 'Authorization': `Bearer ${process.env.API_TOKEN}`,
2715
+ * 'X-Client-ID': 'my-app',
2716
+ * 'Content-Type': 'application/json'
2717
+ * })
2718
+ * .build();
2719
+ * ```
2720
+ *
2721
+ * @public
2722
+ */
2723
+ withHeaders(headers) {
2724
+ this._assertHttpType("withHeaders");
2725
+ if (!headers || typeof headers !== "object") {
2726
+ throw new IgniterAgentConfigError({
2727
+ message: "Headers must be an object mapping header names to values",
2728
+ field: "headers",
2729
+ metadata: { mcpName: this._config.name }
2730
+ });
2731
+ }
2732
+ return new _IgniterAgentMCPBuilder({
2733
+ ...this._config,
2734
+ headers
2735
+ });
2736
+ }
2737
+ /* ---------------------------------------------------------------------------
2738
+ * BUILD METHOD
2739
+ * --------------------------------------------------------------------------- */
2740
+ /**
2741
+ * Builds and returns the completed MCP configuration.
2742
+ *
2743
+ * @description
2744
+ * Validates the configuration and returns a typed configuration object
2745
+ * that can be registered with an agent using `addMCP()`.
2746
+ *
2747
+ * @returns The completed MCP configuration
2748
+ * @throws {IgniterAgentConfigError} If required fields are missing
2749
+ *
2750
+ * @example
2751
+ * ```typescript
2752
+ * const mcpConfig = IgniterAgentMCPBuilder
2753
+ * .create('filesystem')
2754
+ * .withType('stdio')
2755
+ * .withCommand('npx')
2756
+ * .withArgs(['-y', '@modelcontextprotocol/server-filesystem', '/tmp'])
2757
+ * .build();
2758
+ *
2759
+ * // Use with an agent
2760
+ * const agent = IgniterAgent.create()
2761
+ * .addMCP(mcpConfig)
2762
+ * .build();
2763
+ * ```
2764
+ *
2765
+ * @public
2766
+ */
2767
+ build() {
2768
+ if (!this._config.name) {
2769
+ throw new IgniterAgentConfigError({
2770
+ message: "MCP configuration name is required",
2771
+ field: "name"
2772
+ });
2773
+ }
2774
+ if (!this._config.type) {
2775
+ throw new IgniterAgentConfigError({
2776
+ message: 'MCP transport type is required. Call withType("stdio") or withType("http")',
2777
+ field: "type",
2778
+ metadata: { mcpName: this._config.name }
2779
+ });
2780
+ }
2781
+ if (this._config.type === "stdio") {
2782
+ const config = this._config;
2783
+ if (!config.command) {
2784
+ throw new IgniterAgentConfigError({
2785
+ message: "Command is required for stdio transport",
2786
+ field: "command",
2787
+ metadata: { mcpName: this._config.name }
2788
+ });
2789
+ }
2790
+ if (!config.args) {
2791
+ throw new IgniterAgentConfigError({
2792
+ message: "Args are required for stdio transport",
2793
+ field: "args",
2794
+ metadata: { mcpName: this._config.name }
2795
+ });
2796
+ }
2797
+ return {
2798
+ type: "stdio",
2799
+ name: config.name,
2800
+ command: config.command,
2801
+ args: config.args,
2802
+ env: config.env
2803
+ };
2804
+ }
2805
+ if (this._config.type === "http") {
2806
+ const config = this._config;
2807
+ if (!config.url) {
2808
+ throw new IgniterAgentConfigError({
2809
+ message: "URL is required for http transport",
2810
+ field: "url",
2811
+ metadata: { mcpName: this._config.name }
2812
+ });
2813
+ }
2814
+ return {
2815
+ type: "http",
2816
+ name: config.name,
2817
+ url: config.url,
2818
+ headers: config.headers
2819
+ };
2820
+ }
2821
+ throw new IgniterAgentConfigError({
2822
+ message: `Invalid transport type: '${this._config.type}'`,
2823
+ field: "type",
2824
+ metadata: { mcpName: this._config.name }
2825
+ });
2826
+ }
2827
+ /* ---------------------------------------------------------------------------
2828
+ * PRIVATE HELPER METHODS
2829
+ * --------------------------------------------------------------------------- */
2830
+ /**
2831
+ * Asserts that the current transport type is 'stdio'.
2832
+ * @internal
2833
+ */
2834
+ _assertStdioType(methodName) {
2835
+ if (this._config.type !== "stdio") {
2836
+ throw new IgniterAgentConfigError({
2837
+ message: `${methodName}() is only available for stdio transport. Current type: '${this._config.type || "not set"}'. Call withType('stdio') first.`,
2838
+ field: "type",
2839
+ metadata: { mcpName: this._config.name, operation: methodName }
2840
+ });
2841
+ }
2842
+ }
2843
+ /**
2844
+ * Asserts that the current transport type is 'http'.
2845
+ * @internal
2846
+ */
2847
+ _assertHttpType(methodName) {
2848
+ if (this._config.type !== "http") {
2849
+ throw new IgniterAgentConfigError({
2850
+ message: `${methodName}() is only available for http transport. Current type: '${this._config.type || "not set"}'. Call withType('http') first.`,
2851
+ field: "type",
2852
+ metadata: { mcpName: this._config.name, operation: methodName }
2853
+ });
2854
+ }
2855
+ }
2856
+ };
2857
+ var IgniterAgentMCPClient = {
2858
+ create: IgniterAgentMCPBuilder.create
2859
+ };
2860
+
2861
+ // src/adapters/memory.adapter.ts
2862
+ var IgniterAgentInMemoryAdapter = class _IgniterAgentInMemoryAdapter {
2863
+ /**
2864
+ * Creates a new IgniterAgentInMemoryAdapter.
2865
+ *
2866
+ * @param options - Adapter configuration
2867
+ *
2868
+ * @example
2869
+ * ```typescript
2870
+ * const adapter = new IgniterAgentInMemoryAdapter({
2871
+ * namespace: 'myapp',
2872
+ * maxMessages: 1000,
2873
+ * maxChats: 100
2874
+ * });
2875
+ * ```
2876
+ */
2877
+ constructor(options = {}) {
2878
+ /**
2879
+ * Storage for working memory.
2880
+ * Key format: `{namespace}:{scope}:{identifier}`
2881
+ * @internal
2882
+ */
2883
+ this._workingMemory = /* @__PURE__ */ new Map();
2884
+ /**
2885
+ * Storage for conversation messages.
2886
+ * Key format: `{namespace}:{chatId}`
2887
+ * @internal
2888
+ */
2889
+ this._messages = /* @__PURE__ */ new Map();
2890
+ /**
2891
+ * Storage for chat sessions.
2892
+ * Key format: `{namespace}:{chatId}`
2893
+ * @internal
2894
+ */
2895
+ this._chats = /* @__PURE__ */ new Map();
2896
+ this.options = {
2897
+ namespace: options.namespace ?? "igniter",
2898
+ maxMessages: options.maxMessages ?? 1e3,
2899
+ maxChats: options.maxChats ?? 100
2900
+ };
2901
+ }
2902
+ /**
2903
+ * Factory method to create a new adapter instance.
2904
+ * @param options - Adapter configuration
2905
+ * @returns A new IgniterAgentInMemoryAdapter instance
2906
+ *
2907
+ * @example
2908
+ * ```typescript
2909
+ * const adapter = IgniterAgentInMemoryAdapter.create({
2910
+ * namespace: 'test',
2911
+ * });
2912
+ * ```
2913
+ */
2914
+ static create(options) {
2915
+ return new _IgniterAgentInMemoryAdapter(options);
2916
+ }
2917
+ /* ---------------------------------------------------------------------------
2918
+ * HELPER METHODS
2919
+ * --------------------------------------------------------------------------- */
2920
+ /**
2921
+ * Generates a storage key with namespace prefix.
2922
+ * @internal
2923
+ */
2924
+ _key(...parts) {
2925
+ return [this.options.namespace, ...parts].join(":");
2926
+ }
2927
+ /* ---------------------------------------------------------------------------
2928
+ * LIFECYCLE METHODS
2929
+ * --------------------------------------------------------------------------- */
2930
+ /**
2931
+ * Connects to the storage backend (no-op for in-memory).
2932
+ *
2933
+ * @description
2934
+ * In-memory adapter doesn't require connection setup.
2935
+ * This method exists for interface compatibility.
2936
+ */
2937
+ async connect() {
2938
+ }
2939
+ /**
2940
+ * Disconnects from the storage backend (no-op for in-memory).
2941
+ *
2942
+ * @description
2943
+ * In-memory adapter doesn't require disconnection.
2944
+ * This method exists for interface compatibility.
2945
+ */
2946
+ async disconnect() {
2947
+ }
2948
+ /**
2949
+ * Checks if the adapter is connected.
2950
+ *
2951
+ * @returns Always true for in-memory adapter
2952
+ */
2953
+ isConnected() {
2954
+ return true;
2955
+ }
2956
+ /**
2957
+ * Clears all stored data.
2958
+ *
2959
+ * @description
2960
+ * Removes all working memory, messages, and chat sessions.
2961
+ * Use with caution.
2962
+ *
2963
+ * @example
2964
+ * ```typescript
2965
+ * // Clear all data (useful for testing)
2966
+ * await adapter.clear();
2967
+ * ```
2968
+ */
2969
+ async clear() {
2970
+ this._workingMemory.clear();
2971
+ this._messages.clear();
2972
+ this._chats.clear();
2973
+ }
2974
+ /* ---------------------------------------------------------------------------
2975
+ * WORKING MEMORY METHODS
2976
+ * --------------------------------------------------------------------------- */
2977
+ /**
2978
+ * Gets working memory for a scope and identifier.
2979
+ *
2980
+ * @param params - The scope and identifier
2981
+ * @returns The working memory or null if not found
2982
+ *
2983
+ * @example
2984
+ * ```typescript
2985
+ * const memory = await adapter.getWorkingMemory({
2986
+ * scope: 'chat',
2987
+ * identifier: 'chat_123'
2988
+ * });
2989
+ *
2990
+ * if (memory) {
2991
+ * console.log('Content:', memory.content);
2992
+ * console.log('Updated:', memory.updatedAt);
2993
+ * }
2994
+ * ```
2995
+ */
2996
+ async getWorkingMemory(params) {
2997
+ const key = this._key("memory", params.scope, params.identifier);
2998
+ return this._workingMemory.get(key) ?? null;
2999
+ }
3000
+ /**
3001
+ * Updates working memory for a scope and identifier.
3002
+ *
3003
+ * @param params - The scope, identifier, and new content
3004
+ *
3005
+ * @example
3006
+ * ```typescript
3007
+ * await adapter.updateWorkingMemory({
3008
+ * scope: 'chat',
3009
+ * identifier: 'chat_123',
3010
+ * content: `
3011
+ * ## User Preferences
3012
+ * - Prefers TypeScript
3013
+ * - Uses VS Code
3014
+ * `
3015
+ * });
3016
+ * ```
3017
+ */
3018
+ async updateWorkingMemory(params) {
3019
+ const key = this._key("memory", params.scope, params.identifier);
3020
+ this._workingMemory.set(key, {
3021
+ content: params.content,
3022
+ updatedAt: /* @__PURE__ */ new Date()
3023
+ });
3024
+ }
3025
+ /* ---------------------------------------------------------------------------
3026
+ * MESSAGE METHODS
3027
+ * --------------------------------------------------------------------------- */
3028
+ /**
3029
+ * Saves a message to the conversation history.
3030
+ *
3031
+ * @param message - The message to save
3032
+ *
3033
+ * @example
3034
+ * ```typescript
3035
+ * await adapter.saveMessage({
3036
+ * chatId: 'chat_123',
3037
+ * userId: 'user_456',
3038
+ * role: 'user',
3039
+ * content: 'How do I use TypeScript?',
3040
+ * timestamp: new Date()
3041
+ * });
3042
+ * ```
3043
+ */
3044
+ async saveMessage(message) {
3045
+ const key = this._key("messages", message.chatId);
3046
+ let messages = this._messages.get(key);
3047
+ if (!messages) {
3048
+ messages = [];
3049
+ this._messages.set(key, messages);
3050
+ }
3051
+ messages.push(message);
3052
+ if (messages.length > this.options.maxMessages) {
3053
+ messages.splice(0, messages.length - this.options.maxMessages);
3054
+ }
3055
+ }
3056
+ /**
3057
+ * Gets messages from the conversation history.
3058
+ *
3059
+ * @typeParam T - The message type to return
3060
+ * @param params - Query parameters
3061
+ * @returns Array of messages
3062
+ *
3063
+ * @example
3064
+ * ```typescript
3065
+ * const messages = await adapter.getMessages({
3066
+ * chatId: 'chat_123',
3067
+ * limit: 50
3068
+ * });
3069
+ *
3070
+ * for (const msg of messages) {
3071
+ * console.log(`[${msg.role}]: ${msg.content}`);
3072
+ * }
3073
+ * ```
3074
+ */
3075
+ async getMessages(params) {
3076
+ const key = this._key("messages", params.chatId);
3077
+ let messages = this._messages.get(key) ?? [];
3078
+ if (params.userId) {
3079
+ messages = messages.filter((m) => m.userId === params.userId);
3080
+ }
3081
+ if (params.limit && params.limit > 0) {
3082
+ messages = messages.slice(-params.limit);
3083
+ }
3084
+ return messages.map((m) => ({
3085
+ id: `${m.chatId}-${m.timestamp.getTime()}`,
3086
+ role: m.role,
3087
+ content: m.content,
3088
+ createdAt: m.timestamp
3089
+ }));
3090
+ }
3091
+ /* ---------------------------------------------------------------------------
3092
+ * CHAT SESSION METHODS
3093
+ * --------------------------------------------------------------------------- */
3094
+ /**
3095
+ * Saves or updates a chat session.
3096
+ *
3097
+ * @param chat - The chat session to save
3098
+ *
3099
+ * @example
3100
+ * ```typescript
3101
+ * await adapter.saveChat({
3102
+ * chatId: 'chat_123',
3103
+ * userId: 'user_456',
3104
+ * title: 'TypeScript Help',
3105
+ * createdAt: new Date(),
3106
+ * updatedAt: new Date(),
3107
+ * messageCount: 0
3108
+ * });
3109
+ * ```
3110
+ */
3111
+ async saveChat(chat) {
3112
+ const key = this._key("chats", chat.chatId);
3113
+ this._chats.set(key, chat);
3114
+ if (this._chats.size > this.options.maxChats) {
3115
+ const entries = Array.from(this._chats.entries()).sort((a, b) => a[1].updatedAt.getTime() - b[1].updatedAt.getTime());
3116
+ const toRemove = entries.slice(0, this._chats.size - this.options.maxChats);
3117
+ for (const [k] of toRemove) {
3118
+ this._chats.delete(k);
3119
+ }
3120
+ }
3121
+ }
3122
+ /**
3123
+ * Gets chat sessions matching the query parameters.
3124
+ *
3125
+ * @param params - Query parameters
3126
+ * @returns Array of chat sessions
3127
+ *
3128
+ * @example
3129
+ * ```typescript
3130
+ * const chats = await adapter.getChats({
3131
+ * userId: 'user_456',
3132
+ * search: 'typescript',
3133
+ * limit: 10
3134
+ * });
3135
+ *
3136
+ * for (const chat of chats) {
3137
+ * console.log(`${chat.title} (${chat.messageCount} messages)`);
3138
+ * }
3139
+ * ```
3140
+ */
3141
+ async getChats(params) {
3142
+ let chats = Array.from(this._chats.values());
3143
+ if (params.userId) {
3144
+ chats = chats.filter((c) => c.userId === params.userId);
3145
+ }
3146
+ if (params.search) {
3147
+ const searchLower = params.search.toLowerCase();
3148
+ chats = chats.filter(
3149
+ (c) => c.title?.toLowerCase().includes(searchLower)
3150
+ );
3151
+ }
3152
+ chats.sort((a, b) => b.updatedAt.getTime() - a.updatedAt.getTime());
3153
+ if (params.limit && params.limit > 0) {
3154
+ chats = chats.slice(0, params.limit);
3155
+ }
3156
+ return chats;
3157
+ }
3158
+ /**
3159
+ * Gets a specific chat session by ID.
3160
+ *
3161
+ * @param chatId - The chat ID
3162
+ * @returns The chat session or null if not found
3163
+ *
3164
+ * @example
3165
+ * ```typescript
3166
+ * const chat = await adapter.getChat('chat_123');
3167
+ *
3168
+ * if (chat) {
3169
+ * console.log('Title:', chat.title);
3170
+ * console.log('Messages:', chat.messageCount);
3171
+ * }
3172
+ * ```
3173
+ */
3174
+ async getChat(chatId) {
3175
+ const key = this._key("chats", chatId);
3176
+ return this._chats.get(key) ?? null;
3177
+ }
3178
+ /**
3179
+ * Updates the title of a chat session.
3180
+ *
3181
+ * @param chatId - The chat ID
3182
+ * @param title - The new title
3183
+ *
3184
+ * @example
3185
+ * ```typescript
3186
+ * await adapter.updateChatTitle('chat_123', 'New Title');
3187
+ * ```
3188
+ */
3189
+ async updateChatTitle(chatId, title) {
3190
+ const key = this._key("chats", chatId);
3191
+ const chat = this._chats.get(key);
3192
+ if (chat) {
3193
+ chat.title = title;
3194
+ chat.updatedAt = /* @__PURE__ */ new Date();
3195
+ }
3196
+ }
3197
+ /**
3198
+ * Deletes a chat session and its messages.
3199
+ *
3200
+ * @param chatId - The chat ID to delete
3201
+ *
3202
+ * @example
3203
+ * ```typescript
3204
+ * await adapter.deleteChat('chat_123');
3205
+ * ```
3206
+ */
3207
+ async deleteChat(chatId) {
3208
+ const chatKey = this._key("chats", chatId);
3209
+ const messagesKey = this._key("messages", chatId);
3210
+ this._chats.delete(chatKey);
3211
+ this._messages.delete(messagesKey);
3212
+ }
3213
+ /* ---------------------------------------------------------------------------
3214
+ * STATS METHODS
3215
+ * --------------------------------------------------------------------------- */
3216
+ /**
3217
+ * Gets storage statistics.
3218
+ *
3219
+ * @returns Current storage stats
3220
+ *
3221
+ * @example
3222
+ * ```typescript
3223
+ * const stats = await adapter.getStats();
3224
+ * console.log(`Storing ${stats.messageCount} messages`);
3225
+ * console.log(`Across ${stats.chatCount} chats`);
3226
+ * ```
3227
+ */
3228
+ async getStats() {
3229
+ let messageCount = 0;
3230
+ for (const messages of this._messages.values()) {
3231
+ messageCount += messages.length;
3232
+ }
3233
+ return {
3234
+ workingMemoryCount: this._workingMemory.size,
3235
+ messageCount,
3236
+ chatCount: this._chats.size,
3237
+ timestamp: /* @__PURE__ */ new Date()
3238
+ };
3239
+ }
3240
+ };
3241
+ var IgniterAgentJSONFileAdapter = class _IgniterAgentJSONFileAdapter {
3242
+ /**
3243
+ * Creates a new IgniterAgentJSONFileAdapter.
3244
+ *
3245
+ * @param options - Adapter configuration
3246
+ *
3247
+ * @example
3248
+ * ```typescript
3249
+ * const adapter = new IgniterAgentJSONFileAdapter({
3250
+ * dataDir: './memory',
3251
+ * namespace: 'myapp'
3252
+ * });
3253
+ * ```
3254
+ */
3255
+ constructor(options = {}) {
3256
+ /**
3257
+ * Whether the adapter is currently connected and ready to use.
3258
+ * @internal
3259
+ */
3260
+ this._connected = false;
3261
+ /**
3262
+ * In-memory cache of working memory entries.
3263
+ * @internal
3264
+ */
3265
+ this._workingMemoryCache = /* @__PURE__ */ new Map();
3266
+ /**
3267
+ * In-memory cache of messages.
3268
+ * @internal
3269
+ */
3270
+ this._messagesCache = /* @__PURE__ */ new Map();
3271
+ /**
3272
+ * In-memory cache of chat sessions.
3273
+ * @internal
3274
+ */
3275
+ this._chatsCache = /* @__PURE__ */ new Map();
3276
+ this.options = {
3277
+ dataDir: options.dataDir ?? "./igniter-agent-memory",
3278
+ namespace: options.namespace ?? "igniter",
3279
+ autoSync: options.autoSync ?? true,
3280
+ debug: options.debug ?? false,
3281
+ maxMessages: options.maxMessages ?? 1e3,
3282
+ maxChats: options.maxChats ?? 100
3283
+ };
3284
+ }
3285
+ /**
3286
+ * Factory method to create a new adapter instance.
3287
+ * @param options - Adapter configuration
3288
+ * @returns A new IgniterAgentJSONFileAdapter instance
3289
+ *
3290
+ * @example
3291
+ * ```typescript
3292
+ * const adapter = IgniterAgentJSONFileAdapter.create({
3293
+ * dataDir: './data',
3294
+ * });
3295
+ * ```
3296
+ */
3297
+ static create(options) {
3298
+ return new _IgniterAgentJSONFileAdapter(options);
3299
+ }
3300
+ /* ---------------------------------------------------------------------------
3301
+ * PRIVATE HELPER METHODS
3302
+ * --------------------------------------------------------------------------- */
3303
+ /**
3304
+ * Logs debug messages if debug mode is enabled.
3305
+ * @internal
3306
+ */
3307
+ _log(message, data) {
3308
+ if (this.options.debug) {
3309
+ console.log(`[IgniterAgentJSONFileAdapter] ${message}`, data ?? "");
3310
+ }
3311
+ }
3312
+ /**
3313
+ * Gets the path for the working memory JSON file.
3314
+ * @internal
3315
+ */
3316
+ _getWorkingMemoryPath() {
3317
+ return join(this.options.dataDir, "working-memory.json");
3318
+ }
3319
+ /**
3320
+ * Gets the path for the chats JSON file.
3321
+ * @internal
3322
+ */
3323
+ _getChatsPath() {
3324
+ return join(this.options.dataDir, "chats.json");
3325
+ }
3326
+ /**
3327
+ * Gets the directory for message files.
3328
+ * @internal
3329
+ */
3330
+ _getMessagesDir() {
3331
+ return join(this.options.dataDir, "messages");
3332
+ }
3333
+ /**
3334
+ * Gets the path for a specific chat's messages JSON file.
3335
+ * @internal
3336
+ */
3337
+ _getMessagesPath(chatId) {
3338
+ return join(this._getMessagesDir(), `${chatId}.json`);
3339
+ }
3340
+ /**
3341
+ * Generates a cache key with namespace prefix.
3342
+ * @internal
3343
+ */
3344
+ _key(...parts) {
3345
+ return [this.options.namespace, ...parts].join(":");
3346
+ }
3347
+ /**
3348
+ * Loads working memory from disk.
3349
+ * @internal
3350
+ */
3351
+ async _loadWorkingMemory() {
3352
+ try {
3353
+ const path = this._getWorkingMemoryPath();
3354
+ const content = await readFile(path, "utf-8");
3355
+ const data = JSON.parse(content);
3356
+ this._workingMemoryCache.clear();
3357
+ for (const [key, value] of Object.entries(data)) {
3358
+ this._workingMemoryCache.set(key, {
3359
+ content: value.content,
3360
+ updatedAt: new Date(value.updatedAt)
3361
+ });
3362
+ }
3363
+ this._log("Loaded working memory", {
3364
+ entries: this._workingMemoryCache.size
3365
+ });
3366
+ } catch (err) {
3367
+ this._log("Working memory file not found, starting fresh");
3368
+ }
3369
+ }
3370
+ /**
3371
+ * Loads chats from disk.
3372
+ * @internal
3373
+ */
3374
+ async _loadChats() {
3375
+ try {
3376
+ const path = this._getChatsPath();
3377
+ const content = await readFile(path, "utf-8");
3378
+ const data = JSON.parse(content);
3379
+ this._chatsCache.clear();
3380
+ for (const [key, value] of Object.entries(data)) {
3381
+ const chat = value;
3382
+ this._chatsCache.set(key, {
3383
+ chatId: chat.chatId,
3384
+ userId: chat.userId,
3385
+ title: chat.title,
3386
+ createdAt: new Date(chat.createdAt),
3387
+ updatedAt: new Date(chat.updatedAt),
3388
+ messageCount: chat.messageCount
3389
+ });
3390
+ }
3391
+ this._log("Loaded chats", { entries: this._chatsCache.size });
3392
+ } catch (err) {
3393
+ this._log("Chats file not found, starting fresh");
3394
+ }
3395
+ }
3396
+ /**
3397
+ * Loads a specific chat's messages from disk.
3398
+ * @internal
3399
+ */
3400
+ async _loadMessages(chatId) {
3401
+ try {
3402
+ const path = this._getMessagesPath(chatId);
3403
+ const content = await readFile(path, "utf-8");
3404
+ const data = JSON.parse(content);
3405
+ const key = this._key("messages", chatId);
3406
+ const messages = data.map(
3407
+ (msg) => ({
3408
+ chatId: msg.chatId,
3409
+ userId: msg.userId,
3410
+ role: msg.role,
3411
+ content: msg.content,
3412
+ timestamp: new Date(msg.timestamp)
3413
+ })
3414
+ );
3415
+ this._messagesCache.set(key, messages);
3416
+ this._log("Loaded messages", { chatId, count: messages.length });
3417
+ } catch (err) {
3418
+ this._log("Messages file not found for chat", { chatId });
3419
+ }
3420
+ }
3421
+ /**
3422
+ * Saves working memory to disk.
3423
+ * @internal
3424
+ */
3425
+ async _saveWorkingMemory() {
3426
+ const path = this._getWorkingMemoryPath();
3427
+ const data = {};
3428
+ for (const [key, value] of this._workingMemoryCache.entries()) {
3429
+ data[key] = {
3430
+ content: value.content,
3431
+ updatedAt: value.updatedAt.toISOString()
3432
+ };
3433
+ }
3434
+ await writeFile(path, JSON.stringify(data, null, 2));
3435
+ this._log("Saved working memory");
3436
+ }
3437
+ /**
3438
+ * Saves chats to disk.
3439
+ * @internal
3440
+ */
3441
+ async _saveChats() {
3442
+ const path = this._getChatsPath();
3443
+ const data = {};
3444
+ for (const [key, value] of this._chatsCache.entries()) {
3445
+ data[key] = {
3446
+ chatId: value.chatId,
3447
+ userId: value.userId,
3448
+ title: value.title,
3449
+ createdAt: value.createdAt.toISOString(),
3450
+ updatedAt: value.updatedAt.toISOString(),
3451
+ messageCount: value.messageCount
3452
+ };
3453
+ }
3454
+ await writeFile(path, JSON.stringify(data, null, 2));
3455
+ this._log("Saved chats");
3456
+ }
3457
+ /**
3458
+ * Saves messages for a specific chat to disk.
3459
+ * @internal
3460
+ */
3461
+ async _saveMessages(chatId) {
3462
+ const key = this._key("messages", chatId);
3463
+ const messages = this._messagesCache.get(key) ?? [];
3464
+ const path = this._getMessagesPath(chatId);
3465
+ const data = messages.map((msg) => ({
3466
+ chatId: msg.chatId,
3467
+ userId: msg.userId,
3468
+ role: msg.role,
3469
+ content: msg.content,
3470
+ timestamp: msg.timestamp.toISOString()
3471
+ }));
3472
+ await writeFile(path, JSON.stringify(data, null, 2));
3473
+ this._log("Saved messages", { chatId, count: messages.length });
3474
+ }
3475
+ /* ---------------------------------------------------------------------------
3476
+ * LIFECYCLE METHODS
3477
+ * --------------------------------------------------------------------------- */
3478
+ /**
3479
+ * Connects to the storage backend and loads data from disk.
3480
+ *
3481
+ * @description
3482
+ * Creates necessary directories and loads all data into memory cache.
3483
+ * Must be called before using the adapter.
3484
+ *
3485
+ * @throws {Error} If directory creation fails
3486
+ *
3487
+ * @example
3488
+ * ```typescript
3489
+ * const adapter = new IgniterAgentJSONFileAdapter();
3490
+ * await adapter.connect();
3491
+ * ```
3492
+ */
3493
+ async connect() {
3494
+ try {
3495
+ await mkdir(this.options.dataDir, { recursive: true });
3496
+ await mkdir(this._getMessagesDir(), { recursive: true });
3497
+ await this._loadWorkingMemory();
3498
+ await this._loadChats();
3499
+ this._connected = true;
3500
+ this._log("Connected successfully", {
3501
+ dataDir: this.options.dataDir
3502
+ });
3503
+ } catch (err) {
3504
+ this._log("Connection failed", err);
3505
+ throw err;
3506
+ }
3507
+ }
3508
+ /**
3509
+ * Disconnects from the storage backend.
3510
+ *
3511
+ * @description
3512
+ * Syncs any pending changes to disk before disconnecting.
3513
+ *
3514
+ * @example
3515
+ * ```typescript
3516
+ * await adapter.disconnect();
3517
+ * ```
3518
+ */
3519
+ async disconnect() {
3520
+ if (this._connected) {
3521
+ await this.sync();
3522
+ this._connected = false;
3523
+ this._log("Disconnected");
3524
+ }
3525
+ }
3526
+ /**
3527
+ * Checks if the adapter is connected and ready to use.
3528
+ *
3529
+ * @returns True if connected, false otherwise
3530
+ */
3531
+ isConnected() {
3532
+ return this._connected;
3533
+ }
3534
+ /**
3535
+ * Manually syncs all in-memory data to disk.
3536
+ *
3537
+ * @description
3538
+ * Called automatically if autoSync is enabled. Can be called manually
3539
+ * to ensure data is persisted to disk.
3540
+ *
3541
+ * @example
3542
+ * ```typescript
3543
+ * await adapter.updateWorkingMemory({ ... });
3544
+ * await adapter.sync(); // Ensure written to disk
3545
+ * ```
3546
+ */
3547
+ async sync() {
3548
+ try {
3549
+ await this._saveWorkingMemory();
3550
+ await this._saveChats();
3551
+ for (const chatId of this._messagesCache.keys()) {
3552
+ const idParts = chatId.split(":");
3553
+ if (idParts.length > 0) {
3554
+ const actualChatId = idParts[idParts.length - 1];
3555
+ await this._saveMessages(actualChatId);
3556
+ }
3557
+ }
3558
+ this._log("Synced all data to disk");
3559
+ } catch (err) {
3560
+ this._log("Sync failed", err);
3561
+ throw err;
3562
+ }
3563
+ }
3564
+ /**
3565
+ * Clears all stored data from disk and memory.
3566
+ *
3567
+ * @description
3568
+ * Removes all working memory, messages, and chat sessions.
3569
+ * Use with caution.
3570
+ *
3571
+ * @example
3572
+ * ```typescript
3573
+ * await adapter.clear();
3574
+ * ```
3575
+ */
3576
+ async clear() {
3577
+ this._workingMemoryCache.clear();
3578
+ this._messagesCache.clear();
3579
+ this._chatsCache.clear();
3580
+ if (this.options.autoSync) {
3581
+ await this.sync();
3582
+ }
3583
+ this._log("Cleared all data");
3584
+ }
3585
+ /* ---------------------------------------------------------------------------
3586
+ * WORKING MEMORY METHODS
3587
+ * --------------------------------------------------------------------------- */
3588
+ /**
3589
+ * Gets working memory for a scope and identifier.
3590
+ *
3591
+ * @param params - The scope and identifier
3592
+ * @returns The working memory or null if not found
3593
+ *
3594
+ * @example
3595
+ * ```typescript
3596
+ * const memory = await adapter.getWorkingMemory({
3597
+ * scope: 'chat',
3598
+ * identifier: 'chat_123'
3599
+ * });
3600
+ *
3601
+ * if (memory) {
3602
+ * console.log('Content:', memory.content);
3603
+ * }
3604
+ * ```
3605
+ */
3606
+ async getWorkingMemory(params) {
3607
+ const key = this._key("memory", params.scope, params.identifier);
3608
+ return this._workingMemoryCache.get(key) ?? null;
3609
+ }
3610
+ /**
3611
+ * Updates working memory for a scope and identifier.
3612
+ *
3613
+ * @param params - The scope, identifier, and new content
3614
+ *
3615
+ * @example
3616
+ * ```typescript
3617
+ * await adapter.updateWorkingMemory({
3618
+ * scope: 'chat',
3619
+ * identifier: 'chat_123',
3620
+ * content: 'User prefers TypeScript'
3621
+ * });
3622
+ * ```
3623
+ */
3624
+ async updateWorkingMemory(params) {
3625
+ const key = this._key("memory", params.scope, params.identifier);
3626
+ this._workingMemoryCache.set(key, {
3627
+ content: params.content,
3628
+ updatedAt: /* @__PURE__ */ new Date()
3629
+ });
3630
+ if (this.options.autoSync) {
3631
+ await this._saveWorkingMemory();
3632
+ }
3633
+ }
3634
+ /* ---------------------------------------------------------------------------
3635
+ * MESSAGE METHODS
3636
+ * --------------------------------------------------------------------------- */
3637
+ /**
3638
+ * Saves a message to the conversation history.
3639
+ *
3640
+ * @param message - The message to save
3641
+ *
3642
+ * @example
3643
+ * ```typescript
3644
+ * await adapter.saveMessage({
3645
+ * chatId: 'chat_123',
3646
+ * userId: 'user_456',
3647
+ * role: 'user',
3648
+ * content: 'How do I use TypeScript?',
3649
+ * timestamp: new Date()
3650
+ * });
3651
+ * ```
3652
+ */
3653
+ async saveMessage(message) {
3654
+ const key = this._key("messages", message.chatId);
3655
+ let messages = this._messagesCache.get(key);
3656
+ if (!messages) {
3657
+ messages = [];
3658
+ this._messagesCache.set(key, messages);
3659
+ }
3660
+ messages.push(message);
3661
+ if (messages.length > this.options.maxMessages) {
3662
+ messages.splice(0, messages.length - this.options.maxMessages);
3663
+ }
3664
+ if (this.options.autoSync) {
3665
+ await this._saveMessages(message.chatId);
3666
+ }
3667
+ }
3668
+ /**
3669
+ * Gets messages from the conversation history.
3670
+ *
3671
+ * @typeParam T - The message type to return
3672
+ * @param params - Query parameters
3673
+ * @returns Array of messages
3674
+ *
3675
+ * @example
3676
+ * ```typescript
3677
+ * const messages = await adapter.getMessages({
3678
+ * chatId: 'chat_123',
3679
+ * limit: 50
3680
+ * });
3681
+ *
3682
+ * for (const msg of messages) {
3683
+ * console.log(`[${msg.role}]: ${msg.content}`);
3684
+ * }
3685
+ * ```
3686
+ */
3687
+ async getMessages(params) {
3688
+ const key = this._key("messages", params.chatId);
3689
+ if (!this._messagesCache.has(key)) {
3690
+ await this._loadMessages(params.chatId);
3691
+ }
3692
+ let messages = this._messagesCache.get(key) ?? [];
3693
+ if (params.userId) {
3694
+ messages = messages.filter((m) => m.userId === params.userId);
3695
+ }
3696
+ if (params.limit && params.limit > 0) {
3697
+ messages = messages.slice(-params.limit);
3698
+ }
3699
+ return messages.map((m) => ({
3700
+ id: `${m.chatId}-${m.timestamp.getTime()}`,
3701
+ role: m.role,
3702
+ content: m.content,
3703
+ createdAt: m.timestamp
3704
+ }));
3705
+ }
3706
+ /* ---------------------------------------------------------------------------
3707
+ * CHAT SESSION METHODS
3708
+ * --------------------------------------------------------------------------- */
3709
+ /**
3710
+ * Saves or updates a chat session.
3711
+ *
3712
+ * @param chat - The chat session to save
3713
+ *
3714
+ * @example
3715
+ * ```typescript
3716
+ * await adapter.saveChat({
3717
+ * chatId: 'chat_123',
3718
+ * userId: 'user_456',
3719
+ * title: 'TypeScript Help',
3720
+ * createdAt: new Date(),
3721
+ * updatedAt: new Date(),
3722
+ * messageCount: 0
3723
+ * });
3724
+ * ```
3725
+ */
3726
+ async saveChat(chat) {
3727
+ const key = this._key("chats", chat.chatId);
3728
+ this._chatsCache.set(key, chat);
3729
+ if (this._chatsCache.size > this.options.maxChats) {
3730
+ const entries = Array.from(this._chatsCache.entries()).sort(
3731
+ (a, b) => a[1].updatedAt.getTime() - b[1].updatedAt.getTime()
3732
+ );
3733
+ const toRemove = entries.slice(
3734
+ 0,
3735
+ this._chatsCache.size - this.options.maxChats
3736
+ );
3737
+ for (const [k] of toRemove) {
3738
+ this._chatsCache.delete(k);
3739
+ }
3740
+ }
3741
+ if (this.options.autoSync) {
3742
+ await this._saveChats();
3743
+ }
3744
+ }
3745
+ /**
3746
+ * Gets chat sessions matching the query parameters.
3747
+ *
3748
+ * @param params - Query parameters
3749
+ * @returns Array of chat sessions
3750
+ *
3751
+ * @example
3752
+ * ```typescript
3753
+ * const chats = await adapter.getChats({
3754
+ * userId: 'user_456',
3755
+ * search: 'typescript',
3756
+ * limit: 10
3757
+ * });
3758
+ *
3759
+ * for (const chat of chats) {
3760
+ * console.log(`${chat.title} (${chat.messageCount} messages)`);
3761
+ * }
3762
+ * ```
3763
+ */
3764
+ async getChats(params) {
3765
+ let chats = Array.from(this._chatsCache.values());
3766
+ if (params.userId) {
3767
+ chats = chats.filter((c) => c.userId === params.userId);
3768
+ }
3769
+ if (params.search) {
3770
+ const searchLower = params.search.toLowerCase();
3771
+ chats = chats.filter(
3772
+ (c) => c.title?.toLowerCase().includes(searchLower)
3773
+ );
3774
+ }
3775
+ chats.sort((a, b) => b.updatedAt.getTime() - a.updatedAt.getTime());
3776
+ if (params.limit && params.limit > 0) {
3777
+ chats = chats.slice(0, params.limit);
3778
+ }
3779
+ return chats;
3780
+ }
3781
+ /**
3782
+ * Gets a specific chat session by ID.
3783
+ *
3784
+ * @param chatId - The chat ID
3785
+ * @returns The chat session or null if not found
3786
+ *
3787
+ * @example
3788
+ * ```typescript
3789
+ * const chat = await adapter.getChat('chat_123');
3790
+ *
3791
+ * if (chat) {
3792
+ * console.log('Title:', chat.title);
3793
+ * }
3794
+ * ```
3795
+ */
3796
+ async getChat(chatId) {
3797
+ const key = this._key("chats", chatId);
3798
+ return this._chatsCache.get(key) ?? null;
3799
+ }
3800
+ /**
3801
+ * Updates the title of a chat session.
3802
+ *
3803
+ * @param chatId - The chat ID
3804
+ * @param title - The new title
3805
+ *
3806
+ * @example
3807
+ * ```typescript
3808
+ * await adapter.updateChatTitle('chat_123', 'New Title');
3809
+ * ```
3810
+ */
3811
+ async updateChatTitle(chatId, title) {
3812
+ const key = this._key("chats", chatId);
3813
+ const chat = this._chatsCache.get(key);
3814
+ if (chat) {
3815
+ chat.title = title;
3816
+ chat.updatedAt = /* @__PURE__ */ new Date();
3817
+ if (this.options.autoSync) {
3818
+ await this._saveChats();
3819
+ }
3820
+ }
3821
+ }
3822
+ /**
3823
+ * Deletes a chat session and its messages.
3824
+ *
3825
+ * @param chatId - The chat ID to delete
3826
+ *
3827
+ * @example
3828
+ * ```typescript
3829
+ * await adapter.deleteChat('chat_123');
3830
+ * ```
3831
+ */
3832
+ async deleteChat(chatId) {
3833
+ const chatKey = this._key("chats", chatId);
3834
+ const messagesKey = this._key("messages", chatId);
3835
+ this._chatsCache.delete(chatKey);
3836
+ this._messagesCache.delete(messagesKey);
3837
+ if (this.options.autoSync) {
3838
+ await this._saveChats();
3839
+ try {
3840
+ const path = this._getMessagesPath(chatId);
3841
+ await readFile(path);
3842
+ this._log("Messages file for deleted chat still exists");
3843
+ } catch {
3844
+ }
3845
+ }
3846
+ }
3847
+ /* ---------------------------------------------------------------------------
3848
+ * STATS METHODS
3849
+ * --------------------------------------------------------------------------- */
3850
+ /**
3851
+ * Gets storage statistics.
3852
+ *
3853
+ * @returns Current storage stats
3854
+ *
3855
+ * @example
3856
+ * ```typescript
3857
+ * const stats = await adapter.getStats();
3858
+ * console.log(`Storing ${stats.messageCount} messages`);
3859
+ * console.log(`Across ${stats.chatCount} chats`);
3860
+ * ```
3861
+ */
3862
+ async getStats() {
3863
+ let messageCount = 0;
3864
+ for (const messages of this._messagesCache.values()) {
3865
+ messageCount += messages.length;
3866
+ }
3867
+ return {
3868
+ workingMemoryCount: this._workingMemoryCache.size,
3869
+ messageCount,
3870
+ chatCount: this._chatsCache.size,
3871
+ timestamp: /* @__PURE__ */ new Date()
3872
+ };
3873
+ }
3874
+ };
3875
+
3876
+ // src/utils/strings.ts
3877
+ var IgniterAgentStringUtils = class {
3878
+ /**
3879
+ * Generates a unique identifier.
3880
+ */
3881
+ static generateId(prefix) {
3882
+ const random = Math.random().toString(36).substring(2, 12);
3883
+ return prefix ? `${prefix}_${random}` : random;
3884
+ }
3885
+ /**
3886
+ * Truncates a string to a maximum length.
3887
+ */
3888
+ static truncate(str, maxLength, suffix = "...") {
3889
+ if (str.length <= maxLength) return str;
3890
+ return str.slice(0, maxLength - suffix.length) + suffix;
3891
+ }
3892
+ /**
3893
+ * Converts a string to snake_case.
3894
+ */
3895
+ static toSnakeCase(str) {
3896
+ return str.replace(/([A-Z])/g, "_$1").toLowerCase().replace(/^_/, "");
3897
+ }
3898
+ /**
3899
+ * Converts a string to camelCase.
3900
+ */
3901
+ static toCamelCase(str) {
3902
+ return str.replace(/[-_](.)/g, (_, char) => char.toUpperCase()).replace(/^(.)/, (char) => char.toLowerCase());
3903
+ }
3904
+ };
3905
+
3906
+ // src/utils/objects.ts
3907
+ var IgniterAgentObjectUtils = class _IgniterAgentObjectUtils {
3908
+ /**
3909
+ * Deep merges two objects.
3910
+ */
3911
+ static deepMerge(target, source) {
3912
+ const result = { ...target };
3913
+ for (const key in source) {
3914
+ const sourceValue = source[key];
3915
+ const targetValue = target[key];
3916
+ if (sourceValue !== null && typeof sourceValue === "object" && !Array.isArray(sourceValue) && targetValue !== null && typeof targetValue === "object" && !Array.isArray(targetValue)) {
3917
+ result[key] = _IgniterAgentObjectUtils.deepMerge(
3918
+ targetValue,
3919
+ sourceValue
3920
+ );
3921
+ } else {
3922
+ result[key] = sourceValue;
3923
+ }
3924
+ }
3925
+ return result;
3926
+ }
3927
+ /**
3928
+ * Picks specified keys from an object.
3929
+ */
3930
+ static pick(obj, keys) {
3931
+ const result = {};
3932
+ for (const key of keys) {
3933
+ if (key in obj) {
3934
+ result[key] = obj[key];
3935
+ }
3936
+ }
3937
+ return result;
3938
+ }
3939
+ /**
3940
+ * Omits specified keys from an object.
3941
+ */
3942
+ static omit(obj, keys) {
3943
+ const result = { ...obj };
3944
+ for (const key of keys) {
3945
+ delete result[key];
3946
+ }
3947
+ return result;
3948
+ }
3949
+ };
3950
+
3951
+ // src/utils/async.ts
3952
+ var IgniterAgentAsyncUtils = class _IgniterAgentAsyncUtils {
3953
+ /**
3954
+ * Delays execution for a specified duration.
3955
+ */
3956
+ static delay(ms) {
3957
+ return new Promise((resolve) => setTimeout(resolve, ms));
3958
+ }
3959
+ /**
3960
+ * Retries an async function with exponential backoff.
3961
+ */
3962
+ static async retry(fn, options = {}) {
3963
+ const {
3964
+ maxAttempts = 3,
3965
+ baseDelay = 1e3,
3966
+ maxDelay = 3e4,
3967
+ onRetry
3968
+ } = options;
3969
+ let lastError;
3970
+ for (let attempt = 1; attempt <= maxAttempts; attempt++) {
3971
+ try {
3972
+ return await fn();
3973
+ } catch (error) {
3974
+ lastError = error instanceof Error ? error : new Error(String(error));
3975
+ if (attempt === maxAttempts) {
3976
+ throw lastError;
3977
+ }
3978
+ onRetry?.(attempt, lastError);
3979
+ const delayMs = Math.min(baseDelay * Math.pow(2, attempt - 1), maxDelay);
3980
+ await _IgniterAgentAsyncUtils.delay(delayMs);
3981
+ }
3982
+ }
3983
+ throw lastError;
3984
+ }
3985
+ };
3986
+
3987
+ // src/utils/validation.ts
3988
+ var IgniterAgentValidationUtils = class {
3989
+ /**
3990
+ * Checks if a value is defined (not null or undefined).
3991
+ */
3992
+ static isDefined(value) {
3993
+ return value !== null && value !== void 0;
3994
+ }
3995
+ /**
3996
+ * Checks if a value is a non-empty string.
3997
+ */
3998
+ static isNonEmptyString(value) {
3999
+ return typeof value === "string" && value.length > 0;
4000
+ }
4001
+ /**
4002
+ * Checks if a value is a plain object.
4003
+ */
4004
+ static isPlainObject(value) {
4005
+ return typeof value === "object" && value !== null && !Array.isArray(value) && Object.getPrototypeOf(value) === Object.prototype;
4006
+ }
4007
+ };
4008
+
4009
+ export { IgniterAgent, IgniterAgentAdapterError, IgniterAgentAsyncUtils, IgniterAgentBuilder, IgniterAgentConfigError, IgniterAgentCore, IgniterAgentError, IgniterAgentErrorCode, IgniterAgentInMemoryAdapter, IgniterAgentJSONFileAdapter, IgniterAgentMCPBuilder, IgniterAgentMCPClient, IgniterAgentMCPError, IgniterAgentManager, IgniterAgentManagerBuilder, IgniterAgentManagerCore, IgniterAgentMemoryCore, IgniterAgentMemoryError, IgniterAgentObjectUtils, IgniterAgentPrompt, IgniterAgentPromptBuilder, IgniterAgentStringUtils, IgniterAgentTelemetryEvents, IgniterAgentTool, IgniterAgentToolBuilder, IgniterAgentToolError, IgniterAgentToolset, IgniterAgentToolsetBuilder, IgniterAgentValidationUtils, isIgniterAgentError, isIgniterAgentMCPError, isIgniterAgentToolError, wrapError };
4010
+ //# sourceMappingURL=index.mjs.map
4011
+ //# sourceMappingURL=index.mjs.map