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