@igniter-js/agents 0.1.12 → 0.1.14
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/AGENTS.md +115 -54
- package/README.md +72 -42
- package/dist/adapters/index.d.mts +1 -1
- package/dist/adapters/index.d.ts +1 -1
- package/dist/{index-CX4IgrRt.d.mts → index-CqUbHeyY.d.mts} +78 -2
- package/dist/{index-CX4IgrRt.d.ts → index-CqUbHeyY.d.ts} +78 -2
- package/dist/index.d.mts +446 -53
- package/dist/index.d.ts +446 -53
- package/dist/index.js +718 -331
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +718 -332
- package/dist/index.mjs.map +1 -1
- package/dist/telemetry/index.d.mts +4 -4
- package/dist/telemetry/index.d.ts +4 -4
- package/package.json +5 -4
package/dist/index.mjs
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
import { IgniterError } from '@igniter-js/
|
|
1
|
+
import { IgniterError } from '@igniter-js/common';
|
|
2
2
|
import { experimental_createMCPClient } from '@ai-sdk/mcp';
|
|
3
3
|
import { StdioClientTransport } from '@modelcontextprotocol/sdk/client/stdio.js';
|
|
4
4
|
import { StreamableHTTPClientTransport } from '@modelcontextprotocol/sdk/client/streamableHttp.js';
|
|
5
|
-
import { ToolLoopAgent, tool } from 'ai';
|
|
5
|
+
import { ToolLoopAgent, generateText, Output, tool } from 'ai';
|
|
6
|
+
import { z } from 'zod';
|
|
6
7
|
import { readFile, writeFile, mkdir } from 'fs/promises';
|
|
7
8
|
import { join } from 'path';
|
|
8
9
|
|
|
@@ -386,7 +387,12 @@ var IgniterAgentManagerCore = class _IgniterAgentManagerCore {
|
|
|
386
387
|
* @example
|
|
387
388
|
* ```typescript
|
|
388
389
|
* const agent = manager.get('support');
|
|
389
|
-
* const response = await agent.generate({
|
|
390
|
+
* const response = await agent.generate({
|
|
391
|
+
* chatId: 'chat_123',
|
|
392
|
+
* userId: 'user_123',
|
|
393
|
+
* context: {},
|
|
394
|
+
* message: { role: 'user', content: 'Hello!' }
|
|
395
|
+
* });
|
|
390
396
|
* ```
|
|
391
397
|
*/
|
|
392
398
|
get(name) {
|
|
@@ -661,6 +667,244 @@ var IgniterAgentMemoryCore = class {
|
|
|
661
667
|
}
|
|
662
668
|
};
|
|
663
669
|
|
|
670
|
+
// src/utils/strings.ts
|
|
671
|
+
var IgniterAgentStringUtils = class {
|
|
672
|
+
/**
|
|
673
|
+
* Generates a unique identifier.
|
|
674
|
+
*/
|
|
675
|
+
static generateId(prefix) {
|
|
676
|
+
const random = Math.random().toString(36).substring(2, 12);
|
|
677
|
+
return prefix ? `${prefix}_${random}` : random;
|
|
678
|
+
}
|
|
679
|
+
/**
|
|
680
|
+
* Truncates a string to a maximum length.
|
|
681
|
+
*/
|
|
682
|
+
static truncate(str, maxLength, suffix = "...") {
|
|
683
|
+
if (str.length <= maxLength) return str;
|
|
684
|
+
return str.slice(0, maxLength - suffix.length) + suffix;
|
|
685
|
+
}
|
|
686
|
+
/**
|
|
687
|
+
* Converts a string to snake_case.
|
|
688
|
+
*/
|
|
689
|
+
static toSnakeCase(str) {
|
|
690
|
+
return str.replace(/([A-Z])/g, "_$1").toLowerCase().replace(/^_/, "");
|
|
691
|
+
}
|
|
692
|
+
/**
|
|
693
|
+
* Converts a string to camelCase.
|
|
694
|
+
*/
|
|
695
|
+
static toCamelCase(str) {
|
|
696
|
+
return str.replace(/[-_](.)/g, (_, char) => char.toUpperCase()).replace(/^(.)/, (char) => char.toLowerCase());
|
|
697
|
+
}
|
|
698
|
+
};
|
|
699
|
+
|
|
700
|
+
// src/utils/objects.ts
|
|
701
|
+
var IgniterAgentObjectUtils = class _IgniterAgentObjectUtils {
|
|
702
|
+
/**
|
|
703
|
+
* Deep merges two objects.
|
|
704
|
+
*/
|
|
705
|
+
static deepMerge(target, source) {
|
|
706
|
+
const result = { ...target };
|
|
707
|
+
for (const key in source) {
|
|
708
|
+
const sourceValue = source[key];
|
|
709
|
+
const targetValue = target[key];
|
|
710
|
+
if (sourceValue !== null && typeof sourceValue === "object" && !Array.isArray(sourceValue) && targetValue !== null && typeof targetValue === "object" && !Array.isArray(targetValue)) {
|
|
711
|
+
result[key] = _IgniterAgentObjectUtils.deepMerge(
|
|
712
|
+
targetValue,
|
|
713
|
+
sourceValue
|
|
714
|
+
);
|
|
715
|
+
} else {
|
|
716
|
+
result[key] = sourceValue;
|
|
717
|
+
}
|
|
718
|
+
}
|
|
719
|
+
return result;
|
|
720
|
+
}
|
|
721
|
+
/**
|
|
722
|
+
* Picks specified keys from an object.
|
|
723
|
+
*/
|
|
724
|
+
static pick(obj, keys) {
|
|
725
|
+
const result = {};
|
|
726
|
+
for (const key of keys) {
|
|
727
|
+
if (key in obj) {
|
|
728
|
+
result[key] = obj[key];
|
|
729
|
+
}
|
|
730
|
+
}
|
|
731
|
+
return result;
|
|
732
|
+
}
|
|
733
|
+
/**
|
|
734
|
+
* Omits specified keys from an object.
|
|
735
|
+
*/
|
|
736
|
+
static omit(obj, keys) {
|
|
737
|
+
const result = { ...obj };
|
|
738
|
+
for (const key of keys) {
|
|
739
|
+
delete result[key];
|
|
740
|
+
}
|
|
741
|
+
return result;
|
|
742
|
+
}
|
|
743
|
+
};
|
|
744
|
+
|
|
745
|
+
// src/utils/async.ts
|
|
746
|
+
var IgniterAgentAsyncUtils = class _IgniterAgentAsyncUtils {
|
|
747
|
+
/**
|
|
748
|
+
* Delays execution for a specified duration.
|
|
749
|
+
*/
|
|
750
|
+
static delay(ms) {
|
|
751
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
752
|
+
}
|
|
753
|
+
/**
|
|
754
|
+
* Retries an async function with exponential backoff.
|
|
755
|
+
*/
|
|
756
|
+
static async retry(fn, options = {}) {
|
|
757
|
+
const {
|
|
758
|
+
maxAttempts = 3,
|
|
759
|
+
baseDelay = 1e3,
|
|
760
|
+
maxDelay = 3e4,
|
|
761
|
+
onRetry
|
|
762
|
+
} = options;
|
|
763
|
+
let lastError;
|
|
764
|
+
for (let attempt = 1; attempt <= maxAttempts; attempt++) {
|
|
765
|
+
try {
|
|
766
|
+
return await fn();
|
|
767
|
+
} catch (error) {
|
|
768
|
+
lastError = error instanceof Error ? error : new Error(String(error));
|
|
769
|
+
if (attempt === maxAttempts) {
|
|
770
|
+
throw lastError;
|
|
771
|
+
}
|
|
772
|
+
onRetry?.(attempt, lastError);
|
|
773
|
+
const delayMs = Math.min(baseDelay * Math.pow(2, attempt - 1), maxDelay);
|
|
774
|
+
await _IgniterAgentAsyncUtils.delay(delayMs);
|
|
775
|
+
}
|
|
776
|
+
}
|
|
777
|
+
throw lastError;
|
|
778
|
+
}
|
|
779
|
+
};
|
|
780
|
+
|
|
781
|
+
// src/utils/validation.ts
|
|
782
|
+
var IgniterAgentValidationUtils = class {
|
|
783
|
+
/**
|
|
784
|
+
* Checks if a value is defined (not null or undefined).
|
|
785
|
+
*/
|
|
786
|
+
static isDefined(value) {
|
|
787
|
+
return value !== null && value !== void 0;
|
|
788
|
+
}
|
|
789
|
+
/**
|
|
790
|
+
* Checks if a value is a non-empty string.
|
|
791
|
+
*/
|
|
792
|
+
static isNonEmptyString(value) {
|
|
793
|
+
return typeof value === "string" && value.length > 0;
|
|
794
|
+
}
|
|
795
|
+
/**
|
|
796
|
+
* Checks if a value is a plain object.
|
|
797
|
+
*/
|
|
798
|
+
static isPlainObject(value) {
|
|
799
|
+
return typeof value === "object" && value !== null && !Array.isArray(value) && Object.getPrototypeOf(value) === Object.prototype;
|
|
800
|
+
}
|
|
801
|
+
};
|
|
802
|
+
|
|
803
|
+
// src/utils/context.ts
|
|
804
|
+
var IgniterAgentContext = class {
|
|
805
|
+
/**
|
|
806
|
+
* Private constructor to prevent instantiation.
|
|
807
|
+
* This is a static-only utility class.
|
|
808
|
+
*/
|
|
809
|
+
constructor() {
|
|
810
|
+
}
|
|
811
|
+
/**
|
|
812
|
+
* Creates an execution context to pass to AI SDK's experimental_context.
|
|
813
|
+
*
|
|
814
|
+
* Your context object is spread at the top level, merged with writer and metadata.
|
|
815
|
+
* This means you can access your fields directly without a wrapper.
|
|
816
|
+
*
|
|
817
|
+
* @template TContext - Your custom context type (must be an object)
|
|
818
|
+
* @param options - The context creation options
|
|
819
|
+
* @returns The merged execution context ready for AI SDK
|
|
820
|
+
*
|
|
821
|
+
* @example Basic usage
|
|
822
|
+
* ```typescript
|
|
823
|
+
* const context = IgniterAgentContext.create({
|
|
824
|
+
* context: { userId: '123', db: database, permissions: ['read', 'write'] },
|
|
825
|
+
* writer: streamWriter
|
|
826
|
+
* });
|
|
827
|
+
* // Access in tools: executionOptions.experimental_context.userId
|
|
828
|
+
* ```
|
|
829
|
+
*
|
|
830
|
+
* @example With typed context
|
|
831
|
+
* ```typescript
|
|
832
|
+
* interface MyAppContext {
|
|
833
|
+
* tenant: string;
|
|
834
|
+
* workspace: string;
|
|
835
|
+
* features: string[];
|
|
836
|
+
* }
|
|
837
|
+
*
|
|
838
|
+
* const context = IgniterAgentContext.create<MyAppContext>({
|
|
839
|
+
* context: { tenant: 'acme', workspace: 'main', features: ['analytics'] },
|
|
840
|
+
* writer: streamWriter
|
|
841
|
+
* });
|
|
842
|
+
* // Access in tools: executionOptions.experimental_context.tenant
|
|
843
|
+
* ```
|
|
844
|
+
*
|
|
845
|
+
* @example With metadata for tracing
|
|
846
|
+
* ```typescript
|
|
847
|
+
* const context = IgniterAgentContext.create({
|
|
848
|
+
* context: { userId: '123', tenantId: 'acme' },
|
|
849
|
+
* writer: streamWriter,
|
|
850
|
+
* metadata: { agent: 'reports', requestId: 'req_123' }
|
|
851
|
+
* });
|
|
852
|
+
* ```
|
|
853
|
+
*/
|
|
854
|
+
static create(options) {
|
|
855
|
+
return {
|
|
856
|
+
...options.context,
|
|
857
|
+
writer: options.writer,
|
|
858
|
+
metadata: {
|
|
859
|
+
startTime: /* @__PURE__ */ new Date(),
|
|
860
|
+
...options.metadata
|
|
861
|
+
}
|
|
862
|
+
};
|
|
863
|
+
}
|
|
864
|
+
/**
|
|
865
|
+
* Gets your custom context from execution options.
|
|
866
|
+
*
|
|
867
|
+
* Your context fields are available directly in experimental_context (no wrapper).
|
|
868
|
+
* This helper provides type-safe access.
|
|
869
|
+
*
|
|
870
|
+
* @template T - Your custom context type (object)
|
|
871
|
+
* @param executionOptions - Tool execution options from AI SDK
|
|
872
|
+
* @returns Your custom context or undefined if not available
|
|
873
|
+
*
|
|
874
|
+
* @example Direct access (no helper needed)
|
|
875
|
+
* ```typescript
|
|
876
|
+
* export const myTool = tool({
|
|
877
|
+
* execute: async (params, executionOptions) => {
|
|
878
|
+
* // Access fields directly
|
|
879
|
+
* const userId = executionOptions.experimental_context.userId;
|
|
880
|
+
* const db = executionOptions.experimental_context.db;
|
|
881
|
+
* }
|
|
882
|
+
* });
|
|
883
|
+
* ```
|
|
884
|
+
*
|
|
885
|
+
* @example With typed helper
|
|
886
|
+
* ```typescript
|
|
887
|
+
* interface AppContext {
|
|
888
|
+
* userId: string;
|
|
889
|
+
* tenantId: string;
|
|
890
|
+
* db: Database;
|
|
891
|
+
* }
|
|
892
|
+
*
|
|
893
|
+
* export const myTool = tool({
|
|
894
|
+
* execute: async (params, executionOptions) => {
|
|
895
|
+
* const ctx = IgniterAgentContext.get<AppContext>(executionOptions);
|
|
896
|
+
* if (ctx) {
|
|
897
|
+
* const user = await ctx.db.users.findOne(ctx.userId);
|
|
898
|
+
* }
|
|
899
|
+
* }
|
|
900
|
+
* });
|
|
901
|
+
* ```
|
|
902
|
+
*/
|
|
903
|
+
static get(executionOptions) {
|
|
904
|
+
return executionOptions?.experimental_context;
|
|
905
|
+
}
|
|
906
|
+
};
|
|
907
|
+
|
|
664
908
|
// src/core/agent.ts
|
|
665
909
|
var IgniterAgentCore = class {
|
|
666
910
|
constructor(agent) {
|
|
@@ -914,101 +1158,107 @@ var IgniterAgentCore = class {
|
|
|
914
1158
|
}
|
|
915
1159
|
}
|
|
916
1160
|
/**
|
|
917
|
-
* Generates a response
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
this.
|
|
928
|
-
|
|
929
|
-
|
|
1161
|
+
* Generates a response for the given message or messages.
|
|
1162
|
+
*
|
|
1163
|
+
* @description
|
|
1164
|
+
* Accepts either a single `message` or an array of `messages`.
|
|
1165
|
+
* When both are provided, `message` takes precedence.
|
|
1166
|
+
*
|
|
1167
|
+
* @param params - The parameters for the generate call.
|
|
1168
|
+
* @returns The generated response.
|
|
1169
|
+
*/
|
|
1170
|
+
async generate(params) {
|
|
1171
|
+
const { message, messages } = this.resolveMessageInput(params);
|
|
1172
|
+
const requestId = `req_${Date.now()}_${Math.random().toString(36).substring(7)}`;
|
|
1173
|
+
const historyMessages = await this.initializeChatMemory({
|
|
1174
|
+
chatId: params.chatId,
|
|
1175
|
+
userId: params.userId,
|
|
1176
|
+
agentId: this.getName(),
|
|
1177
|
+
message
|
|
930
1178
|
});
|
|
1179
|
+
const agent = this.prepare({
|
|
1180
|
+
chatId: params.chatId,
|
|
1181
|
+
userId: params.userId,
|
|
1182
|
+
agentId: this.getName(),
|
|
1183
|
+
message,
|
|
1184
|
+
requestId,
|
|
1185
|
+
context: params.context,
|
|
1186
|
+
streamed: false
|
|
1187
|
+
});
|
|
1188
|
+
const inputMessages = params.message ? [message] : messages;
|
|
1189
|
+
const resolvedMessages = historyMessages ? [...historyMessages, ...inputMessages] : inputMessages;
|
|
931
1190
|
try {
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
this.telemetry?.emit("igniter.agent.generation.generate.success", {
|
|
938
|
-
level: "debug",
|
|
939
|
-
attributes: {
|
|
940
|
-
...attributes,
|
|
941
|
-
"ctx.generation.durationMs": durationMs
|
|
942
|
-
}
|
|
1191
|
+
return await agent.generate({
|
|
1192
|
+
abortSignal: params.abortSignal,
|
|
1193
|
+
options: params.options,
|
|
1194
|
+
messages: resolvedMessages,
|
|
1195
|
+
prompt: params.prompt
|
|
943
1196
|
});
|
|
944
|
-
this.logger?.success?.("IgniterAgent.generate success", {
|
|
945
|
-
...attributes,
|
|
946
|
-
durationMs
|
|
947
|
-
});
|
|
948
|
-
return result;
|
|
949
1197
|
} catch (error) {
|
|
950
1198
|
const err = error instanceof Error ? error : new Error(String(error));
|
|
951
1199
|
this.telemetry?.emit("igniter.agent.generation.generate.error", {
|
|
952
1200
|
level: "error",
|
|
953
1201
|
attributes: {
|
|
954
|
-
|
|
1202
|
+
"ctx.agent.name": this.getName(),
|
|
1203
|
+
"ctx.agent.chatId": params.chatId,
|
|
1204
|
+
"ctx.agent.userId": params.userId,
|
|
1205
|
+
"ctx.generation.streamed": false,
|
|
955
1206
|
...this.getErrorAttributes(err, "generation.generate")
|
|
956
1207
|
}
|
|
957
1208
|
});
|
|
958
|
-
this.logger?.error("IgniterAgent.generate failed", err);
|
|
959
1209
|
throw err;
|
|
960
1210
|
}
|
|
961
1211
|
}
|
|
962
1212
|
/**
|
|
963
|
-
* Streams a response
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
this.
|
|
974
|
-
|
|
975
|
-
|
|
1213
|
+
* Streams a response for the given message or messages.
|
|
1214
|
+
*
|
|
1215
|
+
* @description
|
|
1216
|
+
* Accepts either a single `message` or an array of `messages`.
|
|
1217
|
+
* When both are provided, `message` takes precedence.
|
|
1218
|
+
*
|
|
1219
|
+
* @param params - The parameters for the stream call.
|
|
1220
|
+
* @returns The streaming response.
|
|
1221
|
+
*/
|
|
1222
|
+
async stream(params) {
|
|
1223
|
+
const { message, messages } = this.resolveMessageInput(params);
|
|
1224
|
+
const requestId = `req_${Date.now()}_${Math.random().toString(36).substring(7)}`;
|
|
1225
|
+
const historyMessages = await this.initializeChatMemory({
|
|
1226
|
+
chatId: params.chatId,
|
|
1227
|
+
userId: params.userId,
|
|
1228
|
+
agentId: this.getName(),
|
|
1229
|
+
message
|
|
976
1230
|
});
|
|
1231
|
+
const agent = this.prepare({
|
|
1232
|
+
chatId: params.chatId,
|
|
1233
|
+
userId: params.userId,
|
|
1234
|
+
agentId: this.getName(),
|
|
1235
|
+
message,
|
|
1236
|
+
requestId,
|
|
1237
|
+
context: params.context,
|
|
1238
|
+
streamed: true
|
|
1239
|
+
});
|
|
1240
|
+
const inputMessages = params.message ? [message] : messages;
|
|
1241
|
+
const resolvedMessages = historyMessages ? [...historyMessages, ...inputMessages] : inputMessages;
|
|
977
1242
|
try {
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
this.telemetry?.emit("igniter.agent.generation.stream.chunk", {
|
|
985
|
-
level: "debug",
|
|
986
|
-
attributes
|
|
987
|
-
});
|
|
988
|
-
};
|
|
989
|
-
const wrapped = this.wrapStreamResult(result, emitChunk);
|
|
990
|
-
this.telemetry?.emit("igniter.agent.generation.stream.success", {
|
|
991
|
-
level: "debug",
|
|
992
|
-
attributes: {
|
|
993
|
-
...attributes,
|
|
994
|
-
"ctx.generation.durationMs": durationMs
|
|
995
|
-
}
|
|
996
|
-
});
|
|
997
|
-
this.logger?.success?.("IgniterAgent.stream success", {
|
|
998
|
-
...attributes,
|
|
999
|
-
durationMs
|
|
1243
|
+
return await agent.stream({
|
|
1244
|
+
abortSignal: params.abortSignal,
|
|
1245
|
+
experimental_transform: params.experimental_transform,
|
|
1246
|
+
options: params.options,
|
|
1247
|
+
messages: resolvedMessages,
|
|
1248
|
+
prompt: params.prompt
|
|
1000
1249
|
});
|
|
1001
|
-
return wrapped;
|
|
1002
1250
|
} catch (error) {
|
|
1003
1251
|
const err = error instanceof Error ? error : new Error(String(error));
|
|
1004
1252
|
this.telemetry?.emit("igniter.agent.generation.stream.error", {
|
|
1005
1253
|
level: "error",
|
|
1006
1254
|
attributes: {
|
|
1007
|
-
|
|
1255
|
+
"ctx.agent.name": this.getName(),
|
|
1256
|
+
"ctx.agent.chatId": params.chatId,
|
|
1257
|
+
"ctx.agent.userId": params.userId,
|
|
1258
|
+
"ctx.generation.streamed": true,
|
|
1008
1259
|
...this.getErrorAttributes(err, "generation.stream")
|
|
1009
1260
|
}
|
|
1010
1261
|
});
|
|
1011
|
-
this.logger?.error("IgniterAgent.stream failed", err);
|
|
1012
1262
|
throw err;
|
|
1013
1263
|
}
|
|
1014
1264
|
}
|
|
@@ -1040,109 +1290,16 @@ var IgniterAgentCore = class {
|
|
|
1040
1290
|
* Gets all registered tools from all toolsets.
|
|
1041
1291
|
*/
|
|
1042
1292
|
getTools() {
|
|
1043
|
-
const
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
allTools[toolName] = wrapped;
|
|
1049
|
-
}
|
|
1050
|
-
}
|
|
1293
|
+
const allTools = this.initializeTools({
|
|
1294
|
+
chatId: "",
|
|
1295
|
+
userId: "",
|
|
1296
|
+
agentId: this.getName()
|
|
1297
|
+
});
|
|
1051
1298
|
return allTools;
|
|
1052
1299
|
}
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
}
|
|
1057
|
-
const execute = tool2.execute;
|
|
1058
|
-
const fullName = `${toolsetName}.${toolName}`;
|
|
1059
|
-
const agentName = this.getName();
|
|
1060
|
-
return {
|
|
1061
|
-
...tool2,
|
|
1062
|
-
execute: async (input, options) => {
|
|
1063
|
-
const startTime = Date.now();
|
|
1064
|
-
this.hooks.onToolCallStart?.(agentName, fullName, input);
|
|
1065
|
-
this.telemetry?.emit("igniter.agent.tool.execute.started", {
|
|
1066
|
-
level: "debug",
|
|
1067
|
-
attributes: {
|
|
1068
|
-
"ctx.agent.name": agentName,
|
|
1069
|
-
"ctx.tool.toolset": toolsetName,
|
|
1070
|
-
"ctx.tool.name": toolName,
|
|
1071
|
-
"ctx.tool.fullName": fullName
|
|
1072
|
-
}
|
|
1073
|
-
});
|
|
1074
|
-
this.logger?.debug("IgniterAgent.tool.execute started", {
|
|
1075
|
-
agent: agentName,
|
|
1076
|
-
tool: fullName
|
|
1077
|
-
});
|
|
1078
|
-
try {
|
|
1079
|
-
const result = await execute(input, options);
|
|
1080
|
-
const durationMs = Date.now() - startTime;
|
|
1081
|
-
this.hooks.onToolCallEnd?.(agentName, fullName, result);
|
|
1082
|
-
this.telemetry?.emit("igniter.agent.tool.execute.success", {
|
|
1083
|
-
level: "debug",
|
|
1084
|
-
attributes: {
|
|
1085
|
-
"ctx.agent.name": agentName,
|
|
1086
|
-
"ctx.tool.toolset": toolsetName,
|
|
1087
|
-
"ctx.tool.name": toolName,
|
|
1088
|
-
"ctx.tool.fullName": fullName,
|
|
1089
|
-
"ctx.tool.durationMs": durationMs
|
|
1090
|
-
}
|
|
1091
|
-
});
|
|
1092
|
-
this.logger?.success?.("IgniterAgent.tool.execute success", {
|
|
1093
|
-
agent: agentName,
|
|
1094
|
-
tool: fullName,
|
|
1095
|
-
durationMs
|
|
1096
|
-
});
|
|
1097
|
-
return result;
|
|
1098
|
-
} catch (error) {
|
|
1099
|
-
const err = error instanceof Error ? error : new Error(String(error));
|
|
1100
|
-
this.hooks.onToolCallError?.(agentName, fullName, err);
|
|
1101
|
-
this.telemetry?.emit("igniter.agent.tool.execute.error", {
|
|
1102
|
-
level: "error",
|
|
1103
|
-
attributes: {
|
|
1104
|
-
"ctx.agent.name": agentName,
|
|
1105
|
-
"ctx.tool.toolset": toolsetName,
|
|
1106
|
-
"ctx.tool.name": toolName,
|
|
1107
|
-
"ctx.tool.fullName": fullName,
|
|
1108
|
-
...this.getErrorAttributes(err, "tool.execute")
|
|
1109
|
-
}
|
|
1110
|
-
});
|
|
1111
|
-
this.logger?.error("IgniterAgent.tool.execute failed", err);
|
|
1112
|
-
throw err;
|
|
1113
|
-
}
|
|
1114
|
-
}
|
|
1115
|
-
};
|
|
1116
|
-
}
|
|
1117
|
-
wrapStreamResult(result, onChunk) {
|
|
1118
|
-
if (!result) {
|
|
1119
|
-
return result;
|
|
1120
|
-
}
|
|
1121
|
-
if (typeof result[Symbol.asyncIterator] === "function") {
|
|
1122
|
-
const iterable = result;
|
|
1123
|
-
return {
|
|
1124
|
-
[Symbol.asyncIterator]: async function* () {
|
|
1125
|
-
for await (const chunk of iterable) {
|
|
1126
|
-
onChunk();
|
|
1127
|
-
yield chunk;
|
|
1128
|
-
}
|
|
1129
|
-
}
|
|
1130
|
-
};
|
|
1131
|
-
}
|
|
1132
|
-
const maybeTextStream = result.textStream;
|
|
1133
|
-
if (maybeTextStream && typeof maybeTextStream[Symbol.asyncIterator] === "function") {
|
|
1134
|
-
return {
|
|
1135
|
-
...result,
|
|
1136
|
-
textStream: (async function* () {
|
|
1137
|
-
for await (const chunk of maybeTextStream) {
|
|
1138
|
-
onChunk();
|
|
1139
|
-
yield chunk;
|
|
1140
|
-
}
|
|
1141
|
-
})()
|
|
1142
|
-
};
|
|
1143
|
-
}
|
|
1144
|
-
return result;
|
|
1145
|
-
}
|
|
1300
|
+
/**
|
|
1301
|
+
* Gets error attributes for telemetry.
|
|
1302
|
+
*/
|
|
1146
1303
|
getErrorAttributes(error, operation) {
|
|
1147
1304
|
return {
|
|
1148
1305
|
"ctx.error.code": error.code ?? error.name ?? "IGNITER_AGENT_UNKNOWN_ERROR" /* UNKNOWN */,
|
|
@@ -1151,31 +1308,345 @@ var IgniterAgentCore = class {
|
|
|
1151
1308
|
"ctx.error.component": "agent"
|
|
1152
1309
|
};
|
|
1153
1310
|
}
|
|
1154
|
-
|
|
1155
|
-
|
|
1311
|
+
/**
|
|
1312
|
+
* Gets an agent instance with the given context.
|
|
1313
|
+
*/
|
|
1314
|
+
prepare(params) {
|
|
1315
|
+
const tools = this.initializeTools({
|
|
1316
|
+
chatId: params.chatId,
|
|
1317
|
+
userId: params.userId,
|
|
1318
|
+
agentId: this._agent.name
|
|
1319
|
+
});
|
|
1156
1320
|
if (!this._agent.model) {
|
|
1157
1321
|
throw new IgniterAgentConfigError({
|
|
1158
1322
|
message: "Model is required. Call withModel() before build()",
|
|
1159
1323
|
field: "model"
|
|
1160
1324
|
});
|
|
1161
1325
|
}
|
|
1162
|
-
if (this._agent.schema !== void 0) {
|
|
1163
|
-
const parseResult = this._agent.schema.safeParse(context);
|
|
1164
|
-
if (parseResult.success) {
|
|
1165
|
-
context = parseResult.data;
|
|
1166
|
-
} else {
|
|
1167
|
-
throw new IgniterAgentError({
|
|
1168
|
-
message: "Invalid context schema",
|
|
1169
|
-
code: "IGNITER_AGENT_CONTEXT_SCHEMA_INVALID" /* AGENT_CONTEXT_SCHEMA_INVALID */
|
|
1170
|
-
});
|
|
1171
|
-
}
|
|
1172
|
-
}
|
|
1173
1326
|
return new ToolLoopAgent({
|
|
1327
|
+
id: this._agent.name,
|
|
1174
1328
|
model: this._agent.model,
|
|
1175
|
-
instructions: this._agent.instructions
|
|
1329
|
+
instructions: this._agent.instructions.getTemplate(),
|
|
1176
1330
|
tools,
|
|
1177
|
-
callOptionsSchema: this._agent.schema
|
|
1331
|
+
callOptionsSchema: this._agent.schema,
|
|
1332
|
+
prepareCall: async (options) => {
|
|
1333
|
+
const isStreamed = Boolean(params.streamed);
|
|
1334
|
+
const eventPrefix = isStreamed ? "stream" : "generate";
|
|
1335
|
+
this.logger?.debug(`IgniterAgent.${eventPrefix} started`, {
|
|
1336
|
+
"ctx.agent.name": this.getName(),
|
|
1337
|
+
"ctx.agent.chatId": params.chatId,
|
|
1338
|
+
"ctx.agent.userId": params.userId,
|
|
1339
|
+
"ctx.generation.inputMessages": options.messages?.length || 0,
|
|
1340
|
+
"ctx.generation.streamed": isStreamed
|
|
1341
|
+
});
|
|
1342
|
+
this.telemetry?.emit(`igniter.agent.generation.${eventPrefix}.started`, {
|
|
1343
|
+
level: "debug",
|
|
1344
|
+
attributes: {
|
|
1345
|
+
"ctx.agent.name": this.getName(),
|
|
1346
|
+
"ctx.agent.chatId": params.chatId,
|
|
1347
|
+
"ctx.agent.userId": params.userId,
|
|
1348
|
+
"ctx.generation.inputMessages": options.messages?.length || 0,
|
|
1349
|
+
"ctx.generation.streamed": isStreamed
|
|
1350
|
+
}
|
|
1351
|
+
});
|
|
1352
|
+
if (this._agent.instructions && options.options) {
|
|
1353
|
+
if (this._agent.memory?.working?.enabled && this._agent.memory.working.template) {
|
|
1354
|
+
this._agent.instructions = this._agent.instructions.addAppended(
|
|
1355
|
+
"memory",
|
|
1356
|
+
this._agent.memory.working.template
|
|
1357
|
+
);
|
|
1358
|
+
}
|
|
1359
|
+
options.instructions = this._agent.instructions.build(options.options);
|
|
1360
|
+
}
|
|
1361
|
+
if (params.prepareCall) {
|
|
1362
|
+
return params.prepareCall(options);
|
|
1363
|
+
}
|
|
1364
|
+
return options;
|
|
1365
|
+
},
|
|
1366
|
+
onStepFinish: async (step) => {
|
|
1367
|
+
if (params.streamed) {
|
|
1368
|
+
return;
|
|
1369
|
+
}
|
|
1370
|
+
this.logger?.debug("IgniterAgent.generate step", {
|
|
1371
|
+
"ctx.agent.name": this.getName(),
|
|
1372
|
+
"ctx.chatId": params.chatId,
|
|
1373
|
+
"ctx.userId": params.userId,
|
|
1374
|
+
"ctx.generation.usage.inputTokens": step.usage.inputTokens,
|
|
1375
|
+
"ctx.generation.usage.outputTokens": step.usage.outputTokens,
|
|
1376
|
+
"ctx.generation.usage.totalTokens": step.usage.totalTokens,
|
|
1377
|
+
"ctx.generation.streamed": false
|
|
1378
|
+
});
|
|
1379
|
+
this.telemetry?.emit("igniter.agent.generation.generate.step", {
|
|
1380
|
+
level: "debug",
|
|
1381
|
+
attributes: {
|
|
1382
|
+
"ctx.agent.name": this.getName(),
|
|
1383
|
+
"ctx.chatId": params.chatId,
|
|
1384
|
+
"ctx.userId": params.userId,
|
|
1385
|
+
"ctx.generation.usage.inputTokens": step.usage.inputTokens,
|
|
1386
|
+
"ctx.generation.usage.outputTokens": step.usage.outputTokens,
|
|
1387
|
+
"ctx.generation.usage.totalTokens": step.usage.totalTokens,
|
|
1388
|
+
"ctx.generation.streamed": false
|
|
1389
|
+
}
|
|
1390
|
+
});
|
|
1391
|
+
},
|
|
1392
|
+
onFinish: (result) => {
|
|
1393
|
+
if (params.streamed) {
|
|
1394
|
+
return;
|
|
1395
|
+
}
|
|
1396
|
+
this.logger?.debug("IgniterAgent.generate success", {
|
|
1397
|
+
"ctx.agent.name": this.getName(),
|
|
1398
|
+
"ctx.chatId": params.chatId,
|
|
1399
|
+
"ctx.userId": params.userId,
|
|
1400
|
+
"ctx.generation.usage.inputTokens": result.usage.inputTokens,
|
|
1401
|
+
"ctx.generation.usage.outputTokens": result.usage.outputTokens,
|
|
1402
|
+
"ctx.generation.usage.totalTokens": result.usage.totalTokens,
|
|
1403
|
+
"ctx.generation.streamed": false
|
|
1404
|
+
});
|
|
1405
|
+
this.telemetry?.emit("igniter.agent.generation.generate.success", {
|
|
1406
|
+
level: "debug",
|
|
1407
|
+
attributes: {
|
|
1408
|
+
"ctx.agent.name": this.getName(),
|
|
1409
|
+
"ctx.chatId": params.chatId,
|
|
1410
|
+
"ctx.userId": params.userId,
|
|
1411
|
+
"ctx.generation.usage.inputTokens": result.usage.inputTokens,
|
|
1412
|
+
"ctx.generation.usage.outputTokens": result.usage.outputTokens,
|
|
1413
|
+
"ctx.generation.usage.totalTokens": result.usage.totalTokens,
|
|
1414
|
+
"ctx.generation.streamed": false
|
|
1415
|
+
}
|
|
1416
|
+
});
|
|
1417
|
+
},
|
|
1418
|
+
activeTools: params.activeTools,
|
|
1419
|
+
experimental_context: IgniterAgentContext.create({
|
|
1420
|
+
context: params.context,
|
|
1421
|
+
memory: this._agent.memory,
|
|
1422
|
+
metadata: {
|
|
1423
|
+
agent: this.getName(),
|
|
1424
|
+
chatId: params.chatId,
|
|
1425
|
+
userId: params.userId,
|
|
1426
|
+
requestId: params.requestId,
|
|
1427
|
+
startTime: /* @__PURE__ */ new Date()
|
|
1428
|
+
}
|
|
1429
|
+
}),
|
|
1430
|
+
experimental_download: params.experimental_download,
|
|
1431
|
+
experimental_repairToolCall: params.experimental_repairToolCall,
|
|
1432
|
+
experimental_telemetry: params.experimental_telemetry,
|
|
1433
|
+
frequencyPenalty: params.frequencyPenalty,
|
|
1434
|
+
maxOutputTokens: params.maxOutputTokens,
|
|
1435
|
+
maxRetries: params.maxRetries,
|
|
1436
|
+
output: params.output,
|
|
1437
|
+
prepareStep: params.prepareStep,
|
|
1438
|
+
presencePenalty: params.presencePenalty,
|
|
1439
|
+
providerOptions: params.providerOptions,
|
|
1440
|
+
seed: params.seed,
|
|
1441
|
+
stopSequences: params.stopSequences,
|
|
1442
|
+
stopWhen: params.stopWhen,
|
|
1443
|
+
temperature: params.temperature,
|
|
1444
|
+
toolChoice: params.toolChoice,
|
|
1445
|
+
topK: params.topK,
|
|
1446
|
+
topP: params.topP,
|
|
1447
|
+
headers: params.headers
|
|
1448
|
+
});
|
|
1449
|
+
}
|
|
1450
|
+
async initializeChatMemory({
|
|
1451
|
+
chatId,
|
|
1452
|
+
userId,
|
|
1453
|
+
agentId,
|
|
1454
|
+
message
|
|
1455
|
+
}) {
|
|
1456
|
+
if (!this.memory || !this._agent.memory?.chats?.enabled) {
|
|
1457
|
+
return;
|
|
1458
|
+
}
|
|
1459
|
+
let chat = await this.memory.getChat(chatId);
|
|
1460
|
+
const { generateSuggestions, generateTitle } = this._agent.memory.chats;
|
|
1461
|
+
if (!chat) {
|
|
1462
|
+
let title = "New conversation";
|
|
1463
|
+
if (generateTitle?.enabled) {
|
|
1464
|
+
const response = await generateText({
|
|
1465
|
+
model: generateTitle.model || this._agent.model,
|
|
1466
|
+
messages: [message],
|
|
1467
|
+
system: generateTitle.instructions || "Analyze the chat history and generate a title for the chat",
|
|
1468
|
+
output: Output.object({
|
|
1469
|
+
schema: z.object({
|
|
1470
|
+
title: z.string().min(1).max(100)
|
|
1471
|
+
})
|
|
1472
|
+
})
|
|
1473
|
+
});
|
|
1474
|
+
title = response.output.title;
|
|
1475
|
+
}
|
|
1476
|
+
await this.memory.saveChat({
|
|
1477
|
+
chatId,
|
|
1478
|
+
createdAt: /* @__PURE__ */ new Date(),
|
|
1479
|
+
updatedAt: /* @__PURE__ */ new Date(),
|
|
1480
|
+
messageCount: 0,
|
|
1481
|
+
title
|
|
1482
|
+
});
|
|
1483
|
+
chat = await this.memory.getChat(chatId);
|
|
1484
|
+
}
|
|
1485
|
+
if (!chat) {
|
|
1486
|
+
throw new IgniterAgentError({
|
|
1487
|
+
code: "IGNITER_AGENT_MISSING_REQUIRED" /* MISSING_REQUIRED */,
|
|
1488
|
+
message: "Chat not found and could not be created",
|
|
1489
|
+
metadata: {
|
|
1490
|
+
chatId,
|
|
1491
|
+
userId,
|
|
1492
|
+
agentId
|
|
1493
|
+
}
|
|
1494
|
+
});
|
|
1495
|
+
}
|
|
1496
|
+
if (!this._agent.memory?.history?.enabled) {
|
|
1497
|
+
return;
|
|
1498
|
+
}
|
|
1499
|
+
const messages = await this.memory.getMessages({
|
|
1500
|
+
chatId,
|
|
1501
|
+
limit: this._agent.memory?.history?.limit
|
|
1178
1502
|
});
|
|
1503
|
+
return messages;
|
|
1504
|
+
}
|
|
1505
|
+
resolveMessageInput(params) {
|
|
1506
|
+
const message = params.message ?? params.messages?.[params.messages.length - 1];
|
|
1507
|
+
if (!message) {
|
|
1508
|
+
throw new IgniterAgentError({
|
|
1509
|
+
code: "IGNITER_AGENT_MISSING_REQUIRED" /* MISSING_REQUIRED */,
|
|
1510
|
+
message: "Either 'message' or 'messages' must be provided",
|
|
1511
|
+
metadata: {
|
|
1512
|
+
missing: "message"
|
|
1513
|
+
}
|
|
1514
|
+
});
|
|
1515
|
+
}
|
|
1516
|
+
const messages = params.message ? [message] : params.messages || [];
|
|
1517
|
+
return { message, messages };
|
|
1518
|
+
}
|
|
1519
|
+
initializeTools({
|
|
1520
|
+
chatId,
|
|
1521
|
+
userId,
|
|
1522
|
+
agentId
|
|
1523
|
+
}) {
|
|
1524
|
+
const toolsets = this.getToolsets();
|
|
1525
|
+
const allTools = {};
|
|
1526
|
+
for (const toolset of Object.values(toolsets)) {
|
|
1527
|
+
for (const [toolName, tool3] of Object.entries(toolset.tools)) {
|
|
1528
|
+
allTools[toolName] = {
|
|
1529
|
+
...tool3,
|
|
1530
|
+
execute: async (args, options) => {
|
|
1531
|
+
if (!tool3.execute) {
|
|
1532
|
+
throw new IgniterAgentError({
|
|
1533
|
+
code: "IGNITER_AGENT_MISSING_REQUIRED" /* MISSING_REQUIRED */,
|
|
1534
|
+
message: "Tool does not have an execute function",
|
|
1535
|
+
metadata: { toolName }
|
|
1536
|
+
});
|
|
1537
|
+
}
|
|
1538
|
+
try {
|
|
1539
|
+
const startTime = Date.now();
|
|
1540
|
+
const toolsetName = toolset.name ?? "unknown";
|
|
1541
|
+
const toolAttributes = {
|
|
1542
|
+
"ctx.agent.name": this.getName(),
|
|
1543
|
+
"ctx.tool.toolset": toolsetName,
|
|
1544
|
+
"ctx.tool.name": toolName,
|
|
1545
|
+
"ctx.tool.fullName": `${toolsetName}.${toolName}`
|
|
1546
|
+
};
|
|
1547
|
+
this.hooks.onToolCallStart?.(this.getName(), toolName, args);
|
|
1548
|
+
this.telemetry?.emit("igniter.agent.tool.execute.started", {
|
|
1549
|
+
level: "debug",
|
|
1550
|
+
attributes: toolAttributes
|
|
1551
|
+
});
|
|
1552
|
+
const result = await tool3.execute(args, {
|
|
1553
|
+
...options,
|
|
1554
|
+
experimental_context: {
|
|
1555
|
+
...options.experimental_context || {},
|
|
1556
|
+
chatId,
|
|
1557
|
+
userId,
|
|
1558
|
+
agentId
|
|
1559
|
+
}
|
|
1560
|
+
});
|
|
1561
|
+
this.telemetry?.emit("igniter.agent.tool.execute.success", {
|
|
1562
|
+
level: "debug",
|
|
1563
|
+
attributes: {
|
|
1564
|
+
...toolAttributes,
|
|
1565
|
+
"ctx.tool.durationMs": Date.now() - startTime
|
|
1566
|
+
}
|
|
1567
|
+
});
|
|
1568
|
+
this.hooks.onToolCallEnd?.(this.getName(), toolName, result);
|
|
1569
|
+
return {
|
|
1570
|
+
success: true,
|
|
1571
|
+
result
|
|
1572
|
+
};
|
|
1573
|
+
} catch (error) {
|
|
1574
|
+
const err = error instanceof Error ? error : new Error(String(error));
|
|
1575
|
+
const toolsetName = toolset.name ?? "unknown";
|
|
1576
|
+
this.telemetry?.emit("igniter.agent.tool.execute.error", {
|
|
1577
|
+
level: "error",
|
|
1578
|
+
attributes: {
|
|
1579
|
+
"ctx.agent.name": this.getName(),
|
|
1580
|
+
"ctx.tool.toolset": toolsetName,
|
|
1581
|
+
"ctx.tool.name": toolName,
|
|
1582
|
+
"ctx.tool.fullName": `${toolsetName}.${toolName}`,
|
|
1583
|
+
...this.getErrorAttributes(err, "tool.execute")
|
|
1584
|
+
}
|
|
1585
|
+
});
|
|
1586
|
+
this.hooks.onToolCallError?.(this.getName(), toolName, err);
|
|
1587
|
+
throw err;
|
|
1588
|
+
}
|
|
1589
|
+
}
|
|
1590
|
+
};
|
|
1591
|
+
}
|
|
1592
|
+
}
|
|
1593
|
+
if (this._agent.memory?.working?.enabled) {
|
|
1594
|
+
const scope = this._agent.memory?.working.scope;
|
|
1595
|
+
const isChatMemory = scope === "chat";
|
|
1596
|
+
const identifier = isChatMemory ? chatId : userId;
|
|
1597
|
+
allTools["internal__update_working_memory"] = tool({
|
|
1598
|
+
description: "Remember important information for later in the conversation",
|
|
1599
|
+
inputSchema: z.object({
|
|
1600
|
+
content: z.string().describe("Updated working memory following the template structure")
|
|
1601
|
+
}),
|
|
1602
|
+
execute: async (args, options) => {
|
|
1603
|
+
const { content } = args;
|
|
1604
|
+
if (this.memory) {
|
|
1605
|
+
await this.memory.updateWorkingMemory({
|
|
1606
|
+
scope,
|
|
1607
|
+
identifier,
|
|
1608
|
+
content
|
|
1609
|
+
});
|
|
1610
|
+
} else {
|
|
1611
|
+
await this._agent.memory?.provider.updateWorkingMemory({
|
|
1612
|
+
scope,
|
|
1613
|
+
identifier,
|
|
1614
|
+
content
|
|
1615
|
+
});
|
|
1616
|
+
}
|
|
1617
|
+
return {
|
|
1618
|
+
success: true
|
|
1619
|
+
};
|
|
1620
|
+
}
|
|
1621
|
+
});
|
|
1622
|
+
if (this._agent.memory?.history?.enabled) {
|
|
1623
|
+
allTools["internal__search_on_chat_history"] = tool({
|
|
1624
|
+
description: "Search on chat history",
|
|
1625
|
+
inputSchema: z.object({
|
|
1626
|
+
content: z.string().describe("Search query"),
|
|
1627
|
+
limit: z.number().optional().describe("Limit number of results"),
|
|
1628
|
+
dateFrom: z.date().optional().describe("Search from date"),
|
|
1629
|
+
dateTo: z.date().optional().describe("Search to date")
|
|
1630
|
+
}),
|
|
1631
|
+
execute: async (args, options) => {
|
|
1632
|
+
const { content, limit, dateFrom, dateTo } = args;
|
|
1633
|
+
const result = await this._agent.memory?.provider?.search?.({
|
|
1634
|
+
chatId,
|
|
1635
|
+
userId,
|
|
1636
|
+
limit,
|
|
1637
|
+
search: content,
|
|
1638
|
+
dateFrom,
|
|
1639
|
+
dateTo
|
|
1640
|
+
});
|
|
1641
|
+
return {
|
|
1642
|
+
success: true,
|
|
1643
|
+
result
|
|
1644
|
+
};
|
|
1645
|
+
}
|
|
1646
|
+
});
|
|
1647
|
+
}
|
|
1648
|
+
}
|
|
1649
|
+
return allTools;
|
|
1179
1650
|
}
|
|
1180
1651
|
async initializeMCPClient(mcpConfig) {
|
|
1181
1652
|
if (this._agent.toolsets[mcpConfig.name]) {
|
|
@@ -1355,8 +1826,9 @@ var resolvePath = (value, path) => {
|
|
|
1355
1826
|
}, value);
|
|
1356
1827
|
};
|
|
1357
1828
|
var IgniterAgentPromptBuilder = class _IgniterAgentPromptBuilder {
|
|
1358
|
-
constructor(template) {
|
|
1829
|
+
constructor(template, appended) {
|
|
1359
1830
|
this.template = template;
|
|
1831
|
+
this.appended = appended;
|
|
1360
1832
|
}
|
|
1361
1833
|
/**
|
|
1362
1834
|
* Creates a new prompt builder.
|
|
@@ -1364,9 +1836,10 @@ var IgniterAgentPromptBuilder = class _IgniterAgentPromptBuilder {
|
|
|
1364
1836
|
* @param template - Prompt template string with {{placeholders}}
|
|
1365
1837
|
* @returns A new prompt builder instance
|
|
1366
1838
|
*/
|
|
1367
|
-
static create(template) {
|
|
1839
|
+
static create(template, appended = {}) {
|
|
1368
1840
|
return new _IgniterAgentPromptBuilder(
|
|
1369
|
-
template
|
|
1841
|
+
template,
|
|
1842
|
+
appended
|
|
1370
1843
|
);
|
|
1371
1844
|
}
|
|
1372
1845
|
/**
|
|
@@ -1376,10 +1849,53 @@ var IgniterAgentPromptBuilder = class _IgniterAgentPromptBuilder {
|
|
|
1376
1849
|
* @returns The resolved prompt string
|
|
1377
1850
|
*/
|
|
1378
1851
|
build(context) {
|
|
1379
|
-
|
|
1852
|
+
const resolveTemplate = (template) => template.replace(TEMPLATE_PATTERN, (_match, path) => {
|
|
1380
1853
|
const value = resolvePath(context, String(path));
|
|
1381
1854
|
return value === void 0 || value === null ? "" : String(value);
|
|
1382
1855
|
});
|
|
1856
|
+
const appendedTemplates = Object.values(this.appended).map((prompt) => {
|
|
1857
|
+
if (typeof prompt === "string") {
|
|
1858
|
+
return resolveTemplate(prompt);
|
|
1859
|
+
}
|
|
1860
|
+
if (prompt && typeof prompt === "object" && "build" in prompt) {
|
|
1861
|
+
return prompt.build(context);
|
|
1862
|
+
}
|
|
1863
|
+
return "";
|
|
1864
|
+
});
|
|
1865
|
+
const appendedString = appendedTemplates.filter(Boolean).join("\n\n");
|
|
1866
|
+
const templateString = resolveTemplate(this.template);
|
|
1867
|
+
if (!appendedString) {
|
|
1868
|
+
return templateString;
|
|
1869
|
+
}
|
|
1870
|
+
return templateString + "\n\n" + appendedString;
|
|
1871
|
+
}
|
|
1872
|
+
/**
|
|
1873
|
+
* Appends another prompt template to this one.
|
|
1874
|
+
*/
|
|
1875
|
+
addAppended(key, prompt) {
|
|
1876
|
+
return new _IgniterAgentPromptBuilder(
|
|
1877
|
+
this.template,
|
|
1878
|
+
{
|
|
1879
|
+
...this.appended,
|
|
1880
|
+
[key]: prompt
|
|
1881
|
+
}
|
|
1882
|
+
);
|
|
1883
|
+
}
|
|
1884
|
+
/**
|
|
1885
|
+
* Removes an appended prompt template from this one.
|
|
1886
|
+
*/
|
|
1887
|
+
removeAppended(key) {
|
|
1888
|
+
const { [key]: _, ...rest } = this.appended;
|
|
1889
|
+
return new _IgniterAgentPromptBuilder(
|
|
1890
|
+
this.template,
|
|
1891
|
+
rest
|
|
1892
|
+
);
|
|
1893
|
+
}
|
|
1894
|
+
/**
|
|
1895
|
+
* Returns the appended prompts.
|
|
1896
|
+
*/
|
|
1897
|
+
getAppended() {
|
|
1898
|
+
return this.appended;
|
|
1383
1899
|
}
|
|
1384
1900
|
/**
|
|
1385
1901
|
* Returns the raw prompt template string.
|
|
@@ -1655,13 +2171,13 @@ var IgniterAgentBuilder = class _IgniterAgentBuilder {
|
|
|
1655
2171
|
*
|
|
1656
2172
|
* // Context is type-safe when calling generate
|
|
1657
2173
|
* await agent.generate({
|
|
1658
|
-
*
|
|
1659
|
-
*
|
|
1660
|
-
*
|
|
1661
|
-
* chatId: 'chat_456',
|
|
2174
|
+
* chatId: 'chat_456',
|
|
2175
|
+
* userId: 'user_123',
|
|
2176
|
+
* context: {
|
|
1662
2177
|
* userRole: 'admin',
|
|
1663
2178
|
* preferences: { language: 'pt' }
|
|
1664
|
-
* }
|
|
2179
|
+
* },
|
|
2180
|
+
* message: { role: 'user', content: 'Hello!' }
|
|
1665
2181
|
* });
|
|
1666
2182
|
* ```
|
|
1667
2183
|
*
|
|
@@ -1791,7 +2307,10 @@ var IgniterAgentBuilder = class _IgniterAgentBuilder {
|
|
|
1791
2307
|
*
|
|
1792
2308
|
* // Generate a response
|
|
1793
2309
|
* const result = await agent.generate({
|
|
1794
|
-
*
|
|
2310
|
+
* chatId: 'chat_123',
|
|
2311
|
+
* userId: 'user_123',
|
|
2312
|
+
* context: {},
|
|
2313
|
+
* message: { role: 'user', content: 'Hello!' }
|
|
1795
2314
|
* });
|
|
1796
2315
|
*
|
|
1797
2316
|
* // Access configuration
|
|
@@ -3724,139 +4243,6 @@ var IgniterAgentJSONFileAdapter = class _IgniterAgentJSONFileAdapter {
|
|
|
3724
4243
|
}
|
|
3725
4244
|
};
|
|
3726
4245
|
|
|
3727
|
-
|
|
3728
|
-
var IgniterAgentStringUtils = class {
|
|
3729
|
-
/**
|
|
3730
|
-
* Generates a unique identifier.
|
|
3731
|
-
*/
|
|
3732
|
-
static generateId(prefix) {
|
|
3733
|
-
const random = Math.random().toString(36).substring(2, 12);
|
|
3734
|
-
return prefix ? `${prefix}_${random}` : random;
|
|
3735
|
-
}
|
|
3736
|
-
/**
|
|
3737
|
-
* Truncates a string to a maximum length.
|
|
3738
|
-
*/
|
|
3739
|
-
static truncate(str, maxLength, suffix = "...") {
|
|
3740
|
-
if (str.length <= maxLength) return str;
|
|
3741
|
-
return str.slice(0, maxLength - suffix.length) + suffix;
|
|
3742
|
-
}
|
|
3743
|
-
/**
|
|
3744
|
-
* Converts a string to snake_case.
|
|
3745
|
-
*/
|
|
3746
|
-
static toSnakeCase(str) {
|
|
3747
|
-
return str.replace(/([A-Z])/g, "_$1").toLowerCase().replace(/^_/, "");
|
|
3748
|
-
}
|
|
3749
|
-
/**
|
|
3750
|
-
* Converts a string to camelCase.
|
|
3751
|
-
*/
|
|
3752
|
-
static toCamelCase(str) {
|
|
3753
|
-
return str.replace(/[-_](.)/g, (_, char) => char.toUpperCase()).replace(/^(.)/, (char) => char.toLowerCase());
|
|
3754
|
-
}
|
|
3755
|
-
};
|
|
3756
|
-
|
|
3757
|
-
// src/utils/objects.ts
|
|
3758
|
-
var IgniterAgentObjectUtils = class _IgniterAgentObjectUtils {
|
|
3759
|
-
/**
|
|
3760
|
-
* Deep merges two objects.
|
|
3761
|
-
*/
|
|
3762
|
-
static deepMerge(target, source) {
|
|
3763
|
-
const result = { ...target };
|
|
3764
|
-
for (const key in source) {
|
|
3765
|
-
const sourceValue = source[key];
|
|
3766
|
-
const targetValue = target[key];
|
|
3767
|
-
if (sourceValue !== null && typeof sourceValue === "object" && !Array.isArray(sourceValue) && targetValue !== null && typeof targetValue === "object" && !Array.isArray(targetValue)) {
|
|
3768
|
-
result[key] = _IgniterAgentObjectUtils.deepMerge(
|
|
3769
|
-
targetValue,
|
|
3770
|
-
sourceValue
|
|
3771
|
-
);
|
|
3772
|
-
} else {
|
|
3773
|
-
result[key] = sourceValue;
|
|
3774
|
-
}
|
|
3775
|
-
}
|
|
3776
|
-
return result;
|
|
3777
|
-
}
|
|
3778
|
-
/**
|
|
3779
|
-
* Picks specified keys from an object.
|
|
3780
|
-
*/
|
|
3781
|
-
static pick(obj, keys) {
|
|
3782
|
-
const result = {};
|
|
3783
|
-
for (const key of keys) {
|
|
3784
|
-
if (key in obj) {
|
|
3785
|
-
result[key] = obj[key];
|
|
3786
|
-
}
|
|
3787
|
-
}
|
|
3788
|
-
return result;
|
|
3789
|
-
}
|
|
3790
|
-
/**
|
|
3791
|
-
* Omits specified keys from an object.
|
|
3792
|
-
*/
|
|
3793
|
-
static omit(obj, keys) {
|
|
3794
|
-
const result = { ...obj };
|
|
3795
|
-
for (const key of keys) {
|
|
3796
|
-
delete result[key];
|
|
3797
|
-
}
|
|
3798
|
-
return result;
|
|
3799
|
-
}
|
|
3800
|
-
};
|
|
3801
|
-
|
|
3802
|
-
// src/utils/async.ts
|
|
3803
|
-
var IgniterAgentAsyncUtils = class _IgniterAgentAsyncUtils {
|
|
3804
|
-
/**
|
|
3805
|
-
* Delays execution for a specified duration.
|
|
3806
|
-
*/
|
|
3807
|
-
static delay(ms) {
|
|
3808
|
-
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
3809
|
-
}
|
|
3810
|
-
/**
|
|
3811
|
-
* Retries an async function with exponential backoff.
|
|
3812
|
-
*/
|
|
3813
|
-
static async retry(fn, options = {}) {
|
|
3814
|
-
const {
|
|
3815
|
-
maxAttempts = 3,
|
|
3816
|
-
baseDelay = 1e3,
|
|
3817
|
-
maxDelay = 3e4,
|
|
3818
|
-
onRetry
|
|
3819
|
-
} = options;
|
|
3820
|
-
let lastError;
|
|
3821
|
-
for (let attempt = 1; attempt <= maxAttempts; attempt++) {
|
|
3822
|
-
try {
|
|
3823
|
-
return await fn();
|
|
3824
|
-
} catch (error) {
|
|
3825
|
-
lastError = error instanceof Error ? error : new Error(String(error));
|
|
3826
|
-
if (attempt === maxAttempts) {
|
|
3827
|
-
throw lastError;
|
|
3828
|
-
}
|
|
3829
|
-
onRetry?.(attempt, lastError);
|
|
3830
|
-
const delayMs = Math.min(baseDelay * Math.pow(2, attempt - 1), maxDelay);
|
|
3831
|
-
await _IgniterAgentAsyncUtils.delay(delayMs);
|
|
3832
|
-
}
|
|
3833
|
-
}
|
|
3834
|
-
throw lastError;
|
|
3835
|
-
}
|
|
3836
|
-
};
|
|
3837
|
-
|
|
3838
|
-
// src/utils/validation.ts
|
|
3839
|
-
var IgniterAgentValidationUtils = class {
|
|
3840
|
-
/**
|
|
3841
|
-
* Checks if a value is defined (not null or undefined).
|
|
3842
|
-
*/
|
|
3843
|
-
static isDefined(value) {
|
|
3844
|
-
return value !== null && value !== void 0;
|
|
3845
|
-
}
|
|
3846
|
-
/**
|
|
3847
|
-
* Checks if a value is a non-empty string.
|
|
3848
|
-
*/
|
|
3849
|
-
static isNonEmptyString(value) {
|
|
3850
|
-
return typeof value === "string" && value.length > 0;
|
|
3851
|
-
}
|
|
3852
|
-
/**
|
|
3853
|
-
* Checks if a value is a plain object.
|
|
3854
|
-
*/
|
|
3855
|
-
static isPlainObject(value) {
|
|
3856
|
-
return typeof value === "object" && value !== null && !Array.isArray(value) && Object.getPrototypeOf(value) === Object.prototype;
|
|
3857
|
-
}
|
|
3858
|
-
};
|
|
3859
|
-
|
|
3860
|
-
export { IgniterAgent, IgniterAgentAdapterError, IgniterAgentAsyncUtils, IgniterAgentBuilder, IgniterAgentConfigError, IgniterAgentCore, IgniterAgentError, IgniterAgentErrorCode, IgniterAgentInMemoryAdapter, IgniterAgentJSONFileAdapter, IgniterAgentMCPBuilder, IgniterAgentMCPClient, IgniterAgentMCPError, IgniterAgentManager, IgniterAgentManagerBuilder, IgniterAgentManagerCore, IgniterAgentMemoryCore, IgniterAgentMemoryError, IgniterAgentObjectUtils, IgniterAgentPrompt, IgniterAgentPromptBuilder, IgniterAgentStringUtils, IgniterAgentTool, IgniterAgentToolBuilder, IgniterAgentToolError, IgniterAgentToolset, IgniterAgentToolsetBuilder, IgniterAgentValidationUtils, isIgniterAgentError, isIgniterAgentMCPError, isIgniterAgentToolError, wrapError };
|
|
4246
|
+
export { IgniterAgent, IgniterAgentAdapterError, IgniterAgentAsyncUtils, IgniterAgentBuilder, IgniterAgentConfigError, IgniterAgentContext, IgniterAgentCore, IgniterAgentError, IgniterAgentErrorCode, IgniterAgentInMemoryAdapter, IgniterAgentJSONFileAdapter, IgniterAgentMCPBuilder, IgniterAgentMCPClient, IgniterAgentMCPError, IgniterAgentManager, IgniterAgentManagerBuilder, IgniterAgentManagerCore, IgniterAgentMemoryCore, IgniterAgentMemoryError, IgniterAgentObjectUtils, IgniterAgentPrompt, IgniterAgentPromptBuilder, IgniterAgentStringUtils, IgniterAgentTool, IgniterAgentToolBuilder, IgniterAgentToolError, IgniterAgentToolset, IgniterAgentToolsetBuilder, IgniterAgentValidationUtils, isIgniterAgentError, isIgniterAgentMCPError, isIgniterAgentToolError, wrapError };
|
|
3861
4247
|
//# sourceMappingURL=index.mjs.map
|
|
3862
4248
|
//# sourceMappingURL=index.mjs.map
|