@kjerneverk/agentic 1.0.5-dev.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.
Files changed (58) hide show
  1. package/.kodrdriv-test-cache.json +6 -0
  2. package/LICENSE +18 -0
  3. package/README.md +167 -0
  4. package/SECURITY.md +94 -0
  5. package/dist/index.d.ts +770 -0
  6. package/dist/index.js +1822 -0
  7. package/dist/index.js.map +1 -0
  8. package/output/kodrdriv/260110-1207-commit-message.md +1 -0
  9. package/output/kodrdriv/260110-1208-commit-message.md +1 -0
  10. package/output/kodrdriv/260110-1210-release-notes.md +27 -0
  11. package/output/kodrdriv/260110-1232-commit-message.md +1 -0
  12. package/output/kodrdriv/260110-1234-release-notes.md +46 -0
  13. package/output/kodrdriv/260110-1308-release-notes.md +20 -0
  14. package/output/kodrdriv/260112-2155-commit-message.md +1 -0
  15. package/output/kodrdriv/260112-2156-release-notes.md +33 -0
  16. package/output/kodrdriv/260112-2340-commit-message.md +1 -0
  17. package/output/kodrdriv/260113-0017-commit-message.md +1 -0
  18. package/output/kodrdriv/260113-0017-release-notes.md +53 -0
  19. package/output/kodrdriv/260115-0616-commit-message.md +4 -0
  20. package/output/kodrdriv/260115-0739-commit-message.md +1 -0
  21. package/output/kodrdriv/260115-0746-commit-message.md +1 -0
  22. package/output/kodrdriv/260115-0747-release-notes.md +91 -0
  23. package/output/kodrdriv/260126-0851-commit-message.md +1 -0
  24. package/output/kodrdriv/260128-0900-commit-message.md +1 -0
  25. package/output/kodrdriv/260128-0900-release-notes.md +29 -0
  26. package/output/kodrdriv/260128-0905-commit-message.md +1 -0
  27. package/output/kodrdriv/260128-0913-commit-message.md +1 -0
  28. package/output/kodrdriv/260128-0913-release-notes.md +23 -0
  29. package/output/kodrdriv/260128-0919-commit-message.md +1 -0
  30. package/output/kodrdriv/260128-0919-release-notes.md +21 -0
  31. package/output/kodrdriv/260130-1642-commit-message.md +1 -0
  32. package/output/kodrdriv/260130-1642-release-notes.md +29 -0
  33. package/output/kodrdriv/RELEASE_NOTES.md +27 -0
  34. package/output/kodrdriv/RELEASE_TITLE.md +1 -0
  35. package/output/kodrdriv/agentic-reflection-commit-2026-01-10T19-18-11-913Z.md +187 -0
  36. package/output/kodrdriv/agentic-reflection-commit-2026-01-10T20-03-27-409Z.md +121 -0
  37. package/output/kodrdriv/agentic-reflection-commit-2026-01-10T20-07-27-813Z.md +114 -0
  38. package/output/kodrdriv/agentic-reflection-commit-2026-01-10T20-08-06-279Z.md +97 -0
  39. package/output/kodrdriv/agentic-reflection-commit-2026-01-10T20-32-25-791Z.md +114 -0
  40. package/output/kodrdriv/agentic-reflection-commit-2026-01-13T05-55-30-733Z.md +97 -0
  41. package/output/kodrdriv/agentic-reflection-commit-2026-01-13T07-40-28-878Z.md +97 -0
  42. package/output/kodrdriv/agentic-reflection-commit-2026-01-13T08-17-22-230Z.md +114 -0
  43. package/output/kodrdriv/agentic-reflection-commit-2026-01-14T14-55-10-122Z.md +177 -0
  44. package/output/kodrdriv/agentic-reflection-commit-2026-01-15T14-16-05-605Z.md +100 -0
  45. package/output/kodrdriv/agentic-reflection-commit-2026-01-15T15-39-32-200Z.md +97 -0
  46. package/output/kodrdriv/agentic-reflection-commit-2026-01-15T15-46-32-840Z.md +114 -0
  47. package/output/kodrdriv/agentic-reflection-commit-2026-01-26T16-51-00-446Z.md +152 -0
  48. package/output/kodrdriv/agentic-reflection-commit-2026-01-31T00-38-59-868Z.md +236 -0
  49. package/output/kodrdriv/agentic-reflection-commit-2026-01-31T00-42-31-993Z.md +152 -0
  50. package/output/kodrdriv/agentic-reflection-release-2026-01-10T20-10-49-531Z.md +329 -0
  51. package/output/kodrdriv/agentic-reflection-release-2026-01-10T20-34-32-038Z.md +319 -0
  52. package/output/kodrdriv/agentic-reflection-release-2026-01-10T21-08-36-314Z.md +168 -0
  53. package/output/kodrdriv/agentic-reflection-release-2026-01-13T05-56-04-802Z.md +264 -0
  54. package/output/kodrdriv/agentic-reflection-release-2026-01-13T08-17-56-556Z.md +255 -0
  55. package/output/kodrdriv/agentic-reflection-release-2026-01-15T15-47-32-509Z.md +460 -0
  56. package/output/kodrdriv/agentic-reflection-release-2026-01-31T00-42-59-683Z.md +400 -0
  57. package/package.json +59 -0
  58. package/package.json~ +58 -0
package/dist/index.js ADDED
@@ -0,0 +1,1822 @@
1
+ import { z, ZodError } from "zod";
2
+ var __defProp = Object.defineProperty;
3
+ var __export = (target, all) => {
4
+ for (var name in all)
5
+ __defProp(target, name, { get: all[name], enumerable: true });
6
+ };
7
+ var LogFormat_exports = {};
8
+ __export(LogFormat_exports, {
9
+ LogFormats: () => LogFormats,
10
+ STRUCTURED: () => STRUCTURED,
11
+ TEXT: () => TEXT,
12
+ getConfig: () => getConfig
13
+ });
14
+ var TEXT = {
15
+ name: "TEXT",
16
+ description: "Text format"
17
+ };
18
+ var STRUCTURED = {
19
+ name: "STRUCTURED",
20
+ description: "Structured format"
21
+ };
22
+ var LogFormats = [
23
+ TEXT,
24
+ STRUCTURED
25
+ ];
26
+ var getConfig = (name) => {
27
+ const config = LogFormats.find((config2) => config2.name === name);
28
+ if (!config) {
29
+ throw new Error(`Invalid Log Format Supplied to Logging Configuration '${name}'`);
30
+ }
31
+ return config;
32
+ };
33
+ var LogLevel_exports = {};
34
+ __export(LogLevel_exports, {
35
+ ALERT: () => ALERT,
36
+ CRITICAL: () => CRITICAL,
37
+ DEBUG: () => DEBUG,
38
+ DEFAULT: () => DEFAULT,
39
+ EMERGENCY: () => EMERGENCY,
40
+ ERROR: () => ERROR,
41
+ INFO: () => INFO,
42
+ LogLevels: () => LogLevels,
43
+ NOTICE: () => NOTICE,
44
+ TRACE: () => TRACE,
45
+ WARNING: () => WARNING,
46
+ getConfig: () => getConfig2
47
+ });
48
+ var EMERGENCY = {
49
+ name: "EMERGENCY",
50
+ value: 0
51
+ };
52
+ var ALERT = {
53
+ name: "ALERT",
54
+ value: 1
55
+ };
56
+ var CRITICAL = {
57
+ name: "CRITICAL",
58
+ value: 2
59
+ };
60
+ var ERROR = {
61
+ name: "ERROR",
62
+ value: 3
63
+ };
64
+ var WARNING = {
65
+ name: "WARNING",
66
+ value: 4
67
+ };
68
+ var NOTICE = {
69
+ name: "NOTICE",
70
+ value: 5
71
+ };
72
+ var INFO = {
73
+ name: "INFO",
74
+ value: 6
75
+ };
76
+ var DEBUG = {
77
+ name: "DEBUG",
78
+ value: 7
79
+ };
80
+ var TRACE = {
81
+ name: "TRACE",
82
+ value: 8
83
+ };
84
+ var DEFAULT = {
85
+ name: "DEFAULT",
86
+ value: 9
87
+ };
88
+ var LogLevels = [
89
+ EMERGENCY,
90
+ ALERT,
91
+ CRITICAL,
92
+ ERROR,
93
+ WARNING,
94
+ NOTICE,
95
+ INFO,
96
+ DEBUG,
97
+ TRACE,
98
+ DEFAULT
99
+ ];
100
+ var getConfig2 = (name) => {
101
+ const config = LogLevels.find((config2) => config2.name === name);
102
+ if (!config) {
103
+ throw new Error(`Invalid Log Level Supplied to Logging Configuration '${name}'`);
104
+ }
105
+ return config;
106
+ };
107
+ var defaultMaskingConfig = {
108
+ enabled: false,
109
+ maskEmails: true,
110
+ maskSSNs: true,
111
+ maskPrivateKeys: true,
112
+ maskBase64Blobs: true,
113
+ maskJWTs: true,
114
+ maxDepth: 8,
115
+ // New security-focused defaults (all true when masking is enabled)
116
+ maskApiKeys: true,
117
+ maskBearerTokens: true,
118
+ maskPasswords: true,
119
+ maskGenericSecrets: true
120
+ };
121
+ var defaultLogLevel = INFO;
122
+ var defaultLogFormat = TEXT;
123
+ var defaultLoggingConfig = {
124
+ logLevel: defaultLogLevel,
125
+ logFormat: defaultLogFormat,
126
+ overrides: {},
127
+ floodControl: {
128
+ enabled: false,
129
+ threshold: 10,
130
+ timeframe: 1e3
131
+ // 1 second
132
+ },
133
+ masking: defaultMaskingConfig
134
+ };
135
+ var convertComponentOverride = (override) => {
136
+ const result = {
137
+ logLevel: override.logLevel ? getConfig2(override.logLevel) : defaultLogLevel
138
+ };
139
+ if (override.components && typeof override.components === "object") {
140
+ result.components = {};
141
+ Object.entries(override.components).forEach(([componentName, componentOverride]) => {
142
+ result.components[componentName] = convertComponentOverride(componentOverride);
143
+ });
144
+ }
145
+ return result;
146
+ };
147
+ var convertOverrides = (overrides) => {
148
+ const convertedOverrides = {};
149
+ if (overrides) {
150
+ Object.entries(overrides).forEach(([key, value]) => {
151
+ convertedOverrides[key] = convertComponentOverride(value);
152
+ });
153
+ }
154
+ return convertedOverrides;
155
+ };
156
+ var convertConfig = (config) => {
157
+ return {
158
+ logLevel: config.logLevel ? getConfig2(config.logLevel) : defaultLogLevel,
159
+ logFormat: config.logFormat ? getConfig(config.logFormat) : defaultLogFormat,
160
+ overrides: convertOverrides(config.overrides),
161
+ floodControl: {
162
+ ...defaultLoggingConfig.floodControl,
163
+ ...config.floodControl || {}
164
+ },
165
+ masking: {
166
+ ...defaultLoggingConfig.masking,
167
+ ...config.masking || {}
168
+ }
169
+ };
170
+ };
171
+ var resolveLogLevel = (config, category, components) => {
172
+ let logLevel = config.logLevel;
173
+ const overrides = config.overrides;
174
+ if (!overrides || !overrides[category]) {
175
+ return logLevel;
176
+ }
177
+ let currentOverride = overrides[category];
178
+ logLevel = currentOverride.logLevel;
179
+ for (const component of components) {
180
+ if (!currentOverride.components || !currentOverride.components[component]) {
181
+ break;
182
+ }
183
+ currentOverride = currentOverride.components[component];
184
+ logLevel = currentOverride.logLevel;
185
+ }
186
+ return logLevel;
187
+ };
188
+ var configureLogging = () => {
189
+ let config = {};
190
+ const loggingConfigEnv = process.env.LOGGING_CONFIG;
191
+ const expoLoggingConfigEnv = process.env.EXPO_PUBLIC_LOGGING_CONFIG;
192
+ const nextLoggingConfigEnv = process.env.NEXT_PUBLIC_LOGGING_CONFIG;
193
+ let logLevelEnv = process.env.LOG_LEVEL;
194
+ let logFormatEnv = process.env.LOG_FORMAT;
195
+ if (loggingConfigEnv) {
196
+ try {
197
+ config = JSON.parse(loggingConfigEnv);
198
+ } catch (error) {
199
+ console.error("Invalid JSON in LOGGING_CONFIG environment variable:", error);
200
+ config = {};
201
+ }
202
+ } else if (expoLoggingConfigEnv) {
203
+ try {
204
+ config = JSON.parse(expoLoggingConfigEnv);
205
+ } catch (error) {
206
+ console.error("Invalid JSON in EXPO_PUBLIC_LOGGING_CONFIG environment variable:", error);
207
+ config = {};
208
+ }
209
+ } else if (nextLoggingConfigEnv) {
210
+ try {
211
+ config = JSON.parse(nextLoggingConfigEnv);
212
+ } catch (error) {
213
+ console.error("Invalid JSON in NEXT_PUBLIC_LOGGING_CONFIG environment variable:", error);
214
+ config = {};
215
+ }
216
+ }
217
+ const convertedConfig = convertConfig(config);
218
+ if (logLevelEnv) {
219
+ logLevelEnv = logLevelEnv?.toUpperCase();
220
+ const logLevelConfig = getConfig2(logLevelEnv);
221
+ convertedConfig.logLevel = logLevelConfig;
222
+ }
223
+ if (logFormatEnv) {
224
+ logFormatEnv = logFormatEnv.toUpperCase();
225
+ const logFormatConfig = getConfig(logFormatEnv);
226
+ convertedConfig.logFormat = logFormatConfig;
227
+ }
228
+ const finalConfig = { ...defaultLoggingConfig, ...convertedConfig };
229
+ return finalConfig;
230
+ };
231
+ var createWriter = (formatter, logMethod, options = {}) => {
232
+ const {
233
+ respectInjectedMethod = false,
234
+ errorMethod = console.error,
235
+ warningMethod = console.warn,
236
+ infoMethod = console.log
237
+ } = options;
238
+ return {
239
+ write: (level, coordinates, payload) => {
240
+ let finalLogMethod = logMethod;
241
+ if (!respectInjectedMethod) {
242
+ if (level.name === ERROR.name || level.name === CRITICAL.name || level.name === ALERT.name || level.name === EMERGENCY.name) {
243
+ finalLogMethod = errorMethod;
244
+ } else if (level.name === WARNING.name) {
245
+ finalLogMethod = warningMethod;
246
+ } else {
247
+ finalLogMethod = infoMethod;
248
+ }
249
+ }
250
+ finalLogMethod(formatter.formatLog(level, coordinates, payload));
251
+ }
252
+ };
253
+ };
254
+ var stringifyJSON = function(obj, visited = /* @__PURE__ */ new Set()) {
255
+ try {
256
+ return stringifyJSONCustom(obj, visited);
257
+ } catch (error) {
258
+ console.error("[Fjell Logging] Critical error in stringifyJSON, using ultimate fallback:", error);
259
+ try {
260
+ return `"[Object: ${typeof obj}]"`;
261
+ } catch {
262
+ return '"[Object: unknown]"';
263
+ }
264
+ }
265
+ };
266
+ var STRINGIFY_CONFIG = {
267
+ MAX_ARRAY_ELEMENTS: 100,
268
+ MAX_OBJECT_PROPERTIES: 100,
269
+ TRUNCATION_MESSAGE: "...[truncated]"
270
+ };
271
+ var stringifyJSONCustom = function(obj, visited = /* @__PURE__ */ new Set()) {
272
+ try {
273
+ const arrOfKeyVals = [];
274
+ const arrVals = [];
275
+ let objKeys = [];
276
+ if (typeof obj === "number" || typeof obj === "boolean" || obj === null)
277
+ return "" + obj;
278
+ else if (typeof obj === "string")
279
+ return '"' + obj + '"';
280
+ else if (typeof obj === "symbol")
281
+ return "";
282
+ else if (typeof obj === "function")
283
+ return "";
284
+ else if (obj instanceof Date)
285
+ return "{}";
286
+ else if (obj instanceof RegExp)
287
+ return "{}";
288
+ else if (obj instanceof Error)
289
+ return "{}";
290
+ else if (typeof obj === "object" && obj.constructor && obj.constructor.name === "Buffer") {
291
+ const result = {};
292
+ for (let i = 0; i < obj.length; i++) {
293
+ result[i] = obj[i];
294
+ }
295
+ return stringifyJSONCustom(result, visited);
296
+ }
297
+ if (obj instanceof Object && visited.has(obj)) {
298
+ return '"(circular)"';
299
+ } else if (Array.isArray(obj)) {
300
+ if (obj.length === 0)
301
+ return "[]";
302
+ else {
303
+ visited.add(obj);
304
+ try {
305
+ const maxElements = STRINGIFY_CONFIG.MAX_ARRAY_ELEMENTS;
306
+ const shouldTruncate = obj.length > maxElements;
307
+ const elementsToProcess = shouldTruncate ? maxElements : obj.length;
308
+ for (let i = 0; i < elementsToProcess; i++) {
309
+ try {
310
+ arrVals.push(stringifyJSONCustom(obj[i], visited));
311
+ } catch {
312
+ arrVals.push('"[Error serializing array element]"');
313
+ }
314
+ }
315
+ if (shouldTruncate) {
316
+ arrVals.push(`"${STRINGIFY_CONFIG.TRUNCATION_MESSAGE} (${obj.length - maxElements} more items)"`);
317
+ }
318
+ } finally {
319
+ visited.delete(obj);
320
+ }
321
+ try {
322
+ return "[" + arrVals.join(",") + "]";
323
+ } catch {
324
+ console.warn("[Fjell Logging] Array too large to serialize completely, using truncated representation");
325
+ return `[${arrVals.slice(0, 10).join(",")},${STRINGIFY_CONFIG.TRUNCATION_MESSAGE}]`;
326
+ }
327
+ }
328
+ } else if (obj instanceof Object) {
329
+ visited.add(obj);
330
+ try {
331
+ objKeys = Object.keys(obj);
332
+ const maxProperties = STRINGIFY_CONFIG.MAX_OBJECT_PROPERTIES;
333
+ const shouldTruncate = objKeys.length > maxProperties;
334
+ const propertiesToProcess = shouldTruncate ? maxProperties : objKeys.length;
335
+ for (let i = 0; i < propertiesToProcess; i++) {
336
+ const key = objKeys[i];
337
+ try {
338
+ const keyOut = '"' + key + '":';
339
+ const keyValOut = obj[key];
340
+ if (keyValOut instanceof Function || typeof keyValOut === "undefined")
341
+ continue;
342
+ else if (typeof keyValOut === "string")
343
+ arrOfKeyVals.push(keyOut + '"' + keyValOut + '"');
344
+ else if (typeof keyValOut === "boolean" || typeof keyValOut === "number" || keyValOut === null)
345
+ arrOfKeyVals.push(keyOut + keyValOut);
346
+ else if (keyValOut instanceof Object) {
347
+ arrOfKeyVals.push(keyOut + stringifyJSONCustom(keyValOut, visited));
348
+ }
349
+ } catch {
350
+ arrOfKeyVals.push('"' + key + '":"[Error serializing property]"');
351
+ }
352
+ }
353
+ if (shouldTruncate) {
354
+ arrOfKeyVals.push(`"${STRINGIFY_CONFIG.TRUNCATION_MESSAGE}":"(${objKeys.length - maxProperties} more properties)"`);
355
+ }
356
+ } finally {
357
+ visited.delete(obj);
358
+ }
359
+ try {
360
+ return "{" + arrOfKeyVals.join(",") + "}";
361
+ } catch {
362
+ console.warn("[Fjell Logging] Object too large to serialize completely, using truncated representation");
363
+ return `{${arrOfKeyVals.slice(0, 10).join(",")},${STRINGIFY_CONFIG.TRUNCATION_MESSAGE}}`;
364
+ }
365
+ }
366
+ return "";
367
+ } catch (error) {
368
+ console.error("[Fjell Logging] Error in stringifyJSONCustom, using fallback:", error);
369
+ return "[Object: serialization failed]";
370
+ }
371
+ };
372
+ var safeFormat = (message, ...args) => {
373
+ let result = message;
374
+ let argIndex = 0;
375
+ result = result.replace(/%([sdjifoO%])/g, (match, specifier) => {
376
+ if (specifier === "%") {
377
+ return "%";
378
+ }
379
+ if (argIndex >= args.length) {
380
+ return match;
381
+ }
382
+ const arg = args[argIndex++];
383
+ switch (specifier) {
384
+ case "s":
385
+ return String(arg);
386
+ case "d":
387
+ return String(parseInt(arg, 10));
388
+ case "i":
389
+ return String(parseInt(arg, 10));
390
+ case "f":
391
+ return String(parseFloat(arg));
392
+ case "j":
393
+ try {
394
+ return stringifyJSON(arg);
395
+ } catch {
396
+ return String(arg);
397
+ }
398
+ case "o":
399
+ return stringifyJSON(arg);
400
+ case "O":
401
+ return stringifyJSON(arg);
402
+ default:
403
+ return String(arg);
404
+ }
405
+ });
406
+ return result;
407
+ };
408
+ var safeInspect = (obj) => {
409
+ try {
410
+ if (obj && typeof obj === "object" && obj.problematic && typeof obj.problematic === "object") {
411
+ return "[Object: object]";
412
+ }
413
+ return stringifyJSON(obj);
414
+ } catch {
415
+ return `[Object: ${typeof obj}]`;
416
+ }
417
+ };
418
+ var safeJSONStringify = (obj) => {
419
+ try {
420
+ const seen = /* @__PURE__ */ new WeakSet();
421
+ return JSON.stringify(obj, (key, value) => {
422
+ try {
423
+ if (typeof value === "symbol") {
424
+ return String(value);
425
+ }
426
+ if (typeof value === "function") {
427
+ return "[Function]";
428
+ }
429
+ if (typeof value === "object" && value !== null) {
430
+ if (seen.has(value)) {
431
+ return "[Circular Reference]";
432
+ }
433
+ seen.add(value);
434
+ }
435
+ if (value instanceof Error) {
436
+ return {
437
+ name: value.name,
438
+ message: value.message,
439
+ stack: value.stack
440
+ };
441
+ }
442
+ if (value instanceof RegExp) {
443
+ return value.toString();
444
+ }
445
+ if (value instanceof Date) {
446
+ return value.toISOString();
447
+ }
448
+ return value;
449
+ } catch (error) {
450
+ console.error("[Fjell Logging] Error processing value in replacer:", error);
451
+ return "[Error: unable to serialize value]";
452
+ }
453
+ });
454
+ } catch (error) {
455
+ console.error("[Fjell Logging] CRITICAL: safeJSONStringify failed, returning fallback:", error);
456
+ try {
457
+ const message = obj?.message || obj?.severity || "Unknown";
458
+ return JSON.stringify({
459
+ severity: "ERROR",
460
+ message: "[Fjell Logging] Failed to serialize log entry",
461
+ originalMessage: String(message),
462
+ error: "Circular reference or non-serializable object detected"
463
+ });
464
+ } catch {
465
+ return '{"severity":"ERROR","message":"[Fjell Logging] Critical serialization failure"}';
466
+ }
467
+ }
468
+ };
469
+ var createFormatter = (logFormat) => {
470
+ if (logFormat.name === "TEXT") {
471
+ return getTextFormatter();
472
+ } else if (logFormat.name === "STRUCTURED") {
473
+ return getStructuredFormatter();
474
+ }
475
+ throw new Error(`Unknown log format: ${logFormat.name}`);
476
+ };
477
+ var getTextFormatter = () => {
478
+ const formatLog = (level, coordinates, payload) => {
479
+ const hasSpecifiers = /%[sdjifoO%]/.test(payload.message);
480
+ let logMessage;
481
+ if (payload.data.length === 0) {
482
+ logMessage = payload.message;
483
+ } else if (hasSpecifiers) {
484
+ logMessage = safeFormat(payload.message, ...payload.data);
485
+ } else {
486
+ logMessage = `${payload.message} ${safeInspect(payload.data)}`;
487
+ }
488
+ return `(${(/* @__PURE__ */ new Date()).valueOf()}) [${level.name}] - [${coordinates.category}] ${coordinates.components.map((c) => `[${c}]`)} ${logMessage}`;
489
+ };
490
+ const timerMessage = (level, coordinates, payload) => {
491
+ const randomInt = Math.floor(Math.random() * 1e6);
492
+ const timerMessage2 = `(${(/* @__PURE__ */ new Date()).valueOf()}) [${level.name}] - [${coordinates.category}] ${coordinates.components.map((c) => `[${c}]`)} ${safeFormat(payload.message, ...payload.data)} ${safeInspect(payload.data)} ${randomInt}`;
493
+ return timerMessage2;
494
+ };
495
+ return { formatLog, timerMessage, getLogFormat: () => TEXT };
496
+ };
497
+ var getStructuredFormatter = () => {
498
+ const formatLog = (level, coordinates, payload) => {
499
+ const severity = level.name;
500
+ const hasSpecifiers = /%[sdjifoO%]/.test(payload.message);
501
+ return safeJSONStringify({
502
+ severity,
503
+ message: hasSpecifiers ? safeFormat(payload.message, ...payload.data) : payload.message,
504
+ "logging.googleapis.com/labels": {
505
+ category: coordinates.category,
506
+ components: `${coordinates.components.map((c) => `[${c}]`)}`
507
+ },
508
+ ...!hasSpecifiers && payload.data.length > 0 && { data: safeInspect(payload.data) }
509
+ });
510
+ };
511
+ const timerMessage = (level, coordinates, payload) => {
512
+ const severity = level.name;
513
+ const randomInt = Math.floor(Math.random() * 1e6);
514
+ return safeJSONStringify({
515
+ severity,
516
+ message: safeFormat(payload.message, ...payload.data),
517
+ "logging.googleapis.com/labels": {
518
+ category: coordinates.category,
519
+ components: `${coordinates.components.map((c) => `[${c}]`)}`
520
+ },
521
+ data: safeInspect(payload.data),
522
+ "logging.googleapis.com/spanId": String(randomInt)
523
+ });
524
+ };
525
+ return { formatLog, timerMessage, getLogFormat: () => STRUCTURED };
526
+ };
527
+ var hash = (message, data) => {
528
+ const dataString = data.map((item) => {
529
+ try {
530
+ return JSON.stringify(item);
531
+ } catch {
532
+ return stringifyJSON(item);
533
+ }
534
+ }).join("");
535
+ return `${message}${dataString}`;
536
+ };
537
+ var FloodControl = class {
538
+ config;
539
+ history = /* @__PURE__ */ new Map();
540
+ suppressed = /* @__PURE__ */ new Map();
541
+ cleanupTimer = null;
542
+ constructor(config) {
543
+ this.config = config;
544
+ if (this.config.enabled) {
545
+ this.cleanupTimer = setInterval(() => this.cleanup(), this.config.timeframe * 2);
546
+ }
547
+ }
548
+ destroy() {
549
+ if (this.cleanupTimer) {
550
+ clearInterval(this.cleanupTimer);
551
+ this.cleanupTimer = null;
552
+ }
553
+ }
554
+ cleanup() {
555
+ const now = Date.now();
556
+ for (const [hash2, timestamps] of this.history.entries()) {
557
+ const recentTimestamps = timestamps.filter(
558
+ (timestamp) => now - timestamp < this.config.timeframe
559
+ );
560
+ if (recentTimestamps.length > 0) {
561
+ this.history.set(hash2, recentTimestamps);
562
+ } else {
563
+ this.history.delete(hash2);
564
+ this.suppressed.delete(hash2);
565
+ }
566
+ }
567
+ }
568
+ check(message, data) {
569
+ if (!this.config.enabled) {
570
+ return "log";
571
+ }
572
+ const messageHash = hash(message, data);
573
+ const now = Date.now();
574
+ const timestamps = (this.history.get(messageHash) || []).filter(
575
+ (timestamp) => now - timestamp < this.config.timeframe
576
+ );
577
+ timestamps.push(now);
578
+ this.history.set(messageHash, timestamps);
579
+ if (timestamps.length > this.config.threshold) {
580
+ const suppressedInfo = this.suppressed.get(messageHash);
581
+ if (suppressedInfo) {
582
+ suppressedInfo.count++;
583
+ return "suppress";
584
+ } else {
585
+ this.suppressed.set(messageHash, { count: 1, firstTimestamp: timestamps[0], summaryLogged: false });
586
+ return "suppress";
587
+ }
588
+ } else {
589
+ if (this.suppressed.has(messageHash)) {
590
+ this.suppressed.delete(messageHash);
591
+ return "resume";
592
+ }
593
+ }
594
+ return "log";
595
+ }
596
+ getSuppressedCount(message, data) {
597
+ const messageHash = hash(message, data);
598
+ return this.suppressed.get(messageHash)?.count || 0;
599
+ }
600
+ };
601
+ var createLogger = (logFormat, logLevel, coordinates, floodControlConfig, loggingConfig, writerOptions, options) => {
602
+ const formatter = createFormatter(logFormat);
603
+ const floodControl = floodControlConfig.enabled ? new FloodControl(floodControlConfig) : null;
604
+ const logFunction = console.log;
605
+ const writer = createWriter(formatter, logFunction, writerOptions);
606
+ const asyncLogging = options?.asyncLogging !== false;
607
+ const enableDebugBuffering = asyncLogging;
608
+ const debugBuffer = [];
609
+ const DEBUG_BUFFER_SIZE = 100;
610
+ const DEBUG_FLUSH_INTERVAL = 100;
611
+ let debugFlushTimer = null;
612
+ const flushDebugBuffer = () => {
613
+ if (debugBuffer.length === 0) return;
614
+ try {
615
+ const messagesToFlush = [...debugBuffer];
616
+ debugBuffer.length = 0;
617
+ messagesToFlush.forEach(({ level, coordinates: coordinates2, payload }) => {
618
+ try {
619
+ writer.write(level, coordinates2, payload);
620
+ } catch (error) {
621
+ console.error("[Fjell Logging] Error writing buffered log message:", error);
622
+ }
623
+ });
624
+ } catch (error) {
625
+ console.error("[Fjell Logging] Error flushing debug buffer:", error);
626
+ } finally {
627
+ if (debugFlushTimer) {
628
+ clearTimeout(debugFlushTimer);
629
+ debugFlushTimer = null;
630
+ }
631
+ }
632
+ };
633
+ const scheduleDebugFlush = () => {
634
+ if (debugFlushTimer) return;
635
+ try {
636
+ debugFlushTimer = setTimeout(() => {
637
+ try {
638
+ flushDebugBuffer();
639
+ } catch (error) {
640
+ console.error("[Fjell Logging] Error in scheduled debug flush:", error);
641
+ }
642
+ }, DEBUG_FLUSH_INTERVAL);
643
+ } catch (error) {
644
+ console.error("[Fjell Logging] Error scheduling debug flush:", error);
645
+ }
646
+ };
647
+ const writeImmediate = (level, coordinates2, payload) => {
648
+ try {
649
+ writer.write(level, coordinates2, payload);
650
+ } catch (error) {
651
+ console.error("[Fjell Logging] Error writing log message:", error);
652
+ }
653
+ };
654
+ const handleDebugBuffering = (level, coordinates2, payload) => {
655
+ try {
656
+ debugBuffer.push({ level, coordinates: coordinates2, payload });
657
+ if (debugBuffer.length >= DEBUG_BUFFER_SIZE) {
658
+ flushDebugBuffer();
659
+ } else {
660
+ scheduleDebugFlush();
661
+ }
662
+ } catch (error) {
663
+ console.error("[Fjell Logging] Error buffering debug message, falling back to immediate write:", error);
664
+ writeImmediate(level, coordinates2, payload);
665
+ }
666
+ };
667
+ const write = (level, message, data) => {
668
+ if (logLevel.value < level.value) {
669
+ return;
670
+ }
671
+ const check = floodControl ? floodControl.check(message, data) : "log";
672
+ const payload = { message, data };
673
+ const asyncWrite = () => {
674
+ try {
675
+ switch (check) {
676
+ case "log":
677
+ if (enableDebugBuffering && (level.name === "TRACE" || level.name === "DEFAULT" || level.name === "DEBUG")) {
678
+ handleDebugBuffering(level, coordinates, payload);
679
+ } else {
680
+ writeImmediate(level, coordinates, payload);
681
+ }
682
+ break;
683
+ case "suppress":
684
+ if (floodControl && floodControl.getSuppressedCount(message, data) === 1) {
685
+ try {
686
+ const originalLevel = level;
687
+ const newPayload = { message: `Started suppressing repeated log message`, data: [] };
688
+ writer.write(originalLevel, coordinates, newPayload);
689
+ } catch (error) {
690
+ console.error("[Fjell Logging] Error writing suppress message:", error);
691
+ }
692
+ }
693
+ break;
694
+ case "resume": {
695
+ try {
696
+ const count = floodControl ? floodControl.getSuppressedCount(message, data) : 0;
697
+ const resumePayload = {
698
+ message: `Stopped suppressing repeated log message. Suppressed ${count} times.`,
699
+ data: []
700
+ };
701
+ writer.write(level, coordinates, resumePayload);
702
+ writer.write(level, coordinates, payload);
703
+ } catch (error) {
704
+ console.error("[Fjell Logging] Error writing resume messages:", error);
705
+ }
706
+ break;
707
+ }
708
+ }
709
+ } catch (error) {
710
+ console.error("[Fjell Logging] Error in async write operation:", error);
711
+ }
712
+ };
713
+ if (asyncLogging) {
714
+ try {
715
+ if (typeof setImmediate !== "undefined") {
716
+ setImmediate(asyncWrite);
717
+ } else {
718
+ setTimeout(asyncWrite, 0);
719
+ }
720
+ } catch (error) {
721
+ console.error("[Fjell Logging] Error scheduling async write, falling back to sync:", error);
722
+ try {
723
+ asyncWrite();
724
+ } catch (syncError) {
725
+ console.error("[Fjell Logging] Error in synchronous fallback write:", syncError);
726
+ }
727
+ }
728
+ } else {
729
+ asyncWrite();
730
+ }
731
+ };
732
+ const startTimeLogger = (logLevel2, coordinates2, payload) => {
733
+ const timerMessage = formatter.timerMessage(logLevel2, coordinates2, payload);
734
+ logLevel2.value >= DEBUG.value && console.time(timerMessage);
735
+ return {
736
+ end: () => {
737
+ logLevel2.value >= DEBUG.value && console.timeEnd(timerMessage);
738
+ },
739
+ log: (...data) => {
740
+ logLevel2.value >= DEBUG.value && console.timeLog(timerMessage, ...data);
741
+ }
742
+ };
743
+ };
744
+ return {
745
+ emergency: (message, ...data) => {
746
+ write(EMERGENCY, message, data);
747
+ },
748
+ alert: (message, ...data) => {
749
+ write(ALERT, message, data);
750
+ },
751
+ critical: (message, ...data) => {
752
+ write(CRITICAL, message, data);
753
+ },
754
+ error: (message, ...data) => {
755
+ write(ERROR, message, data);
756
+ },
757
+ warning: (message, ...data) => {
758
+ write(WARNING, message, data);
759
+ },
760
+ notice: (message, ...data) => {
761
+ write(NOTICE, message, data);
762
+ },
763
+ info: (message, ...data) => {
764
+ write(INFO, message, data);
765
+ },
766
+ debug: (message, ...data) => {
767
+ write(DEBUG, message, data);
768
+ },
769
+ trace: (message, ...data) => {
770
+ write(TRACE, message, data);
771
+ },
772
+ default: (message, ...data) => {
773
+ write(DEFAULT, message, data);
774
+ },
775
+ time: (message, ...data) => {
776
+ const payload = { message, data };
777
+ return startTimeLogger(logLevel, coordinates, payload);
778
+ },
779
+ get: (...additionalComponents) => {
780
+ const newComponents = [...coordinates.components, ...additionalComponents];
781
+ let childLogLevel = logLevel;
782
+ if (loggingConfig) {
783
+ childLogLevel = resolveLogLevel(loggingConfig, coordinates.category, newComponents);
784
+ }
785
+ return createLogger(logFormat, childLogLevel, {
786
+ category: coordinates.category,
787
+ components: newComponents
788
+ }, floodControlConfig, loggingConfig, writerOptions, options);
789
+ },
790
+ destroy: () => {
791
+ try {
792
+ flushDebugBuffer();
793
+ } catch (error) {
794
+ console.error("[Fjell Logging] Error flushing debug buffer during destroy:", error);
795
+ }
796
+ try {
797
+ if (debugFlushTimer) {
798
+ clearTimeout(debugFlushTimer);
799
+ debugFlushTimer = null;
800
+ }
801
+ } catch (error) {
802
+ console.error("[Fjell Logging] Error clearing debug flush timer during destroy:", error);
803
+ }
804
+ try {
805
+ if (floodControl) {
806
+ floodControl.destroy();
807
+ }
808
+ } catch (error) {
809
+ console.error("[Fjell Logging] Error destroying flood control during destroy:", error);
810
+ }
811
+ }
812
+ };
813
+ };
814
+ var getLogger = (name) => {
815
+ const config = configureLogging();
816
+ const logger = createBaseLogger(name, config);
817
+ return logger;
818
+ };
819
+ var createBaseLogger = (name, config) => {
820
+ const { logFormat, floodControl } = config;
821
+ const coordinates = { category: name, components: [] };
822
+ const logLevel = resolveLogLevel(config, name, []);
823
+ return createLogger(logFormat, logLevel, coordinates, floodControl, config, void 0, {
824
+ asyncLogging: false
825
+ });
826
+ };
827
+ var index_default = { getLogger };
828
+ const LIBRARY_NAME = "agentic";
829
+ const LibLogger = index_default.getLogger("@riotprompt/agentic");
830
+ function createSilentLogger(name) {
831
+ return {
832
+ name,
833
+ debug: () => {
834
+ },
835
+ info: () => {
836
+ },
837
+ warn: () => {
838
+ },
839
+ error: () => {
840
+ },
841
+ verbose: () => {
842
+ },
843
+ silly: () => {
844
+ },
845
+ get: (...components) => createSilentLogger(`${name}:${components.join(":")}`)
846
+ };
847
+ }
848
+ const SILENT_LOGGER = createSilentLogger("silent");
849
+ const isLoggingEnabled = () => {
850
+ return process.env.AGENTIC_LOGGING === "true" || process.env.DEBUG?.includes("agentic") || process.env.NODE_ENV === "development";
851
+ };
852
+ function createLoggerFromFjell(fjellLogger, name) {
853
+ return {
854
+ name,
855
+ debug: (message, ...args) => fjellLogger.debug(message, ...args),
856
+ info: (message, ...args) => fjellLogger.info(message, ...args),
857
+ warn: (message, ...args) => fjellLogger.warning(message, ...args),
858
+ error: (message, ...args) => fjellLogger.error(message, ...args),
859
+ verbose: (message, ...args) => fjellLogger.debug(message, ...args),
860
+ silly: (message, ...args) => fjellLogger.debug(message, ...args),
861
+ get: (...components) => {
862
+ const childLogger = fjellLogger.get(...components);
863
+ return createLoggerFromFjell(childLogger, `${name}:${components.join(":")}`);
864
+ }
865
+ };
866
+ }
867
+ const FJELL_LOGGER = {
868
+ name: "fjell",
869
+ debug: (message, ...args) => LibLogger.debug(message, ...args),
870
+ info: (message, ...args) => LibLogger.info(message, ...args),
871
+ warn: (message, ...args) => LibLogger.warning(message, ...args),
872
+ error: (message, ...args) => LibLogger.error(message, ...args),
873
+ verbose: (message, ...args) => LibLogger.debug(message, ...args),
874
+ silly: (message, ...args) => LibLogger.debug(message, ...args),
875
+ get: (...components) => {
876
+ const childLogger = LibLogger.get(...components);
877
+ return createLoggerFromFjell(childLogger, components.join(":"));
878
+ }
879
+ };
880
+ const DEFAULT_LOGGER = isLoggingEnabled() ? FJELL_LOGGER : SILENT_LOGGER;
881
+ function wrapLogger(toWrap, name) {
882
+ const requiredMethods = [
883
+ "debug",
884
+ "info",
885
+ "warn",
886
+ "error",
887
+ "verbose",
888
+ "silly"
889
+ ];
890
+ const missingMethods = requiredMethods.filter(
891
+ (method) => typeof toWrap[method] !== "function"
892
+ );
893
+ if (missingMethods.length > 0) {
894
+ throw new Error(
895
+ `Logger is missing required methods: ${missingMethods.join(", ")}`
896
+ );
897
+ }
898
+ const log = (level, message, ...args) => {
899
+ message = `[${LIBRARY_NAME}] ${name ? `[${name}]` : ""}: ${message}`;
900
+ if (level === "debug") toWrap.debug(message, ...args);
901
+ else if (level === "info") toWrap.info(message, ...args);
902
+ else if (level === "warn") toWrap.warn(message, ...args);
903
+ else if (level === "error") toWrap.error(message, ...args);
904
+ else if (level === "verbose") toWrap.verbose(message, ...args);
905
+ else if (level === "silly") toWrap.silly(message, ...args);
906
+ };
907
+ return {
908
+ name: name || "wrapped",
909
+ debug: (message, ...args) => log("debug", message, ...args),
910
+ info: (message, ...args) => log("info", message, ...args),
911
+ warn: (message, ...args) => log("warn", message, ...args),
912
+ error: (message, ...args) => log("error", message, ...args),
913
+ verbose: (message, ...args) => log("verbose", message, ...args),
914
+ silly: (message, ...args) => log("silly", message, ...args),
915
+ get: (...components) => wrapLogger(toWrap, name ? `${name}:${components.join(":")}` : components.join(":"))
916
+ };
917
+ }
918
+ const ToolSchema = z.object({
919
+ name: z.string().min(1),
920
+ description: z.string().min(1),
921
+ parameters: z.object({
922
+ type: z.literal("object"),
923
+ properties: z.record(z.string(), z.any()).default({}),
924
+ required: z.array(z.string()).optional()
925
+ }).passthrough(),
926
+ execute: z.custom(
927
+ (val) => typeof val === "function",
928
+ { message: "execute must be a function" }
929
+ ),
930
+ category: z.string().optional(),
931
+ cost: z.enum(["cheap", "moderate", "expensive"]).optional(),
932
+ examples: z.array(
933
+ z.object({
934
+ scenario: z.string(),
935
+ params: z.any(),
936
+ expectedResult: z.string()
937
+ })
938
+ ).optional()
939
+ }).passthrough();
940
+ class ToolRegistry {
941
+ tools;
942
+ context;
943
+ logger;
944
+ usageStats;
945
+ toolGuard;
946
+ toolSandbox;
947
+ constructor(context = {}, logger) {
948
+ this.tools = /* @__PURE__ */ new Map();
949
+ this.context = context;
950
+ this.logger = wrapLogger(logger || DEFAULT_LOGGER, "ToolRegistry");
951
+ this.usageStats = /* @__PURE__ */ new Map();
952
+ this.logger.debug("Created ToolRegistry");
953
+ }
954
+ /**
955
+ * Create a new ToolRegistry instance
956
+ */
957
+ static create(context, logger) {
958
+ return new ToolRegistry(context, logger);
959
+ }
960
+ /**
961
+ * Configure security guard for tool execution
962
+ */
963
+ withSecurity(guard) {
964
+ this.toolGuard = guard;
965
+ this.logger.debug("Security guard configured");
966
+ return this;
967
+ }
968
+ /**
969
+ * Get the configured security guard
970
+ */
971
+ getSecurityGuard() {
972
+ return this.toolGuard;
973
+ }
974
+ /**
975
+ * Configure sandbox for tool execution
976
+ */
977
+ withSandbox(sandbox) {
978
+ this.toolSandbox = sandbox;
979
+ this.logger.debug("Sandbox configured");
980
+ return this;
981
+ }
982
+ /**
983
+ * Get the configured sandbox
984
+ */
985
+ getSandbox() {
986
+ return this.toolSandbox;
987
+ }
988
+ /**
989
+ * Register a single tool
990
+ */
991
+ register(tool) {
992
+ try {
993
+ ToolSchema.parse(tool);
994
+ } catch (error) {
995
+ throw new Error(`Invalid tool definition for "${tool.name}": ${error}`);
996
+ }
997
+ if (this.tools.has(tool.name)) {
998
+ this.logger.warn(`Tool "${tool.name}" already registered, overwriting`);
999
+ }
1000
+ this.tools.set(tool.name, tool);
1001
+ this.usageStats.set(tool.name, { calls: 0, failures: 0, totalDuration: 0 });
1002
+ this.logger.debug("Registered tool", {
1003
+ name: tool.name,
1004
+ category: tool.category
1005
+ });
1006
+ }
1007
+ /**
1008
+ * Register multiple tools at once
1009
+ */
1010
+ registerAll(tools) {
1011
+ this.logger.debug("Registering multiple tools", { count: tools.length });
1012
+ tools.forEach((tool) => this.register(tool));
1013
+ }
1014
+ /**
1015
+ * Get a tool by name
1016
+ */
1017
+ get(name) {
1018
+ return this.tools.get(name);
1019
+ }
1020
+ /**
1021
+ * Get all registered tools
1022
+ */
1023
+ getAll() {
1024
+ return Array.from(this.tools.values());
1025
+ }
1026
+ /**
1027
+ * Get tools by category
1028
+ */
1029
+ getByCategory(category) {
1030
+ return this.getAll().filter((tool) => tool.category === category);
1031
+ }
1032
+ /**
1033
+ * Check if a tool is registered
1034
+ */
1035
+ has(name) {
1036
+ return this.tools.has(name);
1037
+ }
1038
+ /**
1039
+ * Get number of registered tools
1040
+ */
1041
+ count() {
1042
+ return this.tools.size;
1043
+ }
1044
+ /**
1045
+ * Execute a tool by name
1046
+ */
1047
+ async execute(name, params) {
1048
+ const tool = this.tools.get(name);
1049
+ if (!tool) {
1050
+ throw new Error(`Tool "${name}" not found`);
1051
+ }
1052
+ if (this.toolGuard && !this.toolGuard.isToolAllowed(name)) {
1053
+ throw new Error(`Tool "${name}" is not allowed`);
1054
+ }
1055
+ if (this.toolGuard && tool.schema) {
1056
+ const validation = this.toolGuard.validateParams(
1057
+ name,
1058
+ params,
1059
+ tool.schema
1060
+ );
1061
+ if (!validation.success) {
1062
+ throw new Error(`Tool "${name}": ${validation.error}`);
1063
+ }
1064
+ params = validation.data;
1065
+ }
1066
+ this.logger.debug("Executing tool", { name, params });
1067
+ const startTime = Date.now();
1068
+ const stats = this.usageStats.get(name);
1069
+ stats.calls++;
1070
+ try {
1071
+ let result;
1072
+ if (this.toolSandbox) {
1073
+ result = await this.toolSandbox.execute(
1074
+ tool,
1075
+ params,
1076
+ this.context
1077
+ );
1078
+ } else {
1079
+ result = await tool.execute(params, this.context);
1080
+ }
1081
+ const duration = Date.now() - startTime;
1082
+ stats.totalDuration += duration;
1083
+ this.logger.debug("Tool execution succeeded", { name, duration });
1084
+ return result;
1085
+ } catch (error) {
1086
+ stats.failures++;
1087
+ this.logger.error("Tool execution failed", { name, error });
1088
+ throw error;
1089
+ }
1090
+ }
1091
+ /**
1092
+ * Safely parse and execute a tool from JSON arguments
1093
+ */
1094
+ async executeFromJSON(name, jsonArgs) {
1095
+ if (this.toolGuard) {
1096
+ const parseResult = this.toolGuard.parseToolArguments(name, jsonArgs);
1097
+ if (!parseResult.success) {
1098
+ throw new Error(`Tool "${name}": ${parseResult.error}`);
1099
+ }
1100
+ return this.execute(name, parseResult.data);
1101
+ }
1102
+ const params = JSON.parse(jsonArgs);
1103
+ return this.execute(name, params);
1104
+ }
1105
+ /**
1106
+ * Execute multiple tools in sequence
1107
+ */
1108
+ async executeBatch(calls) {
1109
+ this.logger.debug("Executing batch", { count: calls.length });
1110
+ const results = [];
1111
+ for (const call of calls) {
1112
+ try {
1113
+ const result = await this.execute(call.name, call.params);
1114
+ results.push(result);
1115
+ } catch (error) {
1116
+ results.push({ error: String(error) });
1117
+ }
1118
+ }
1119
+ return results;
1120
+ }
1121
+ /**
1122
+ * Export tools in OpenAI format
1123
+ */
1124
+ toOpenAIFormat() {
1125
+ return this.getAll().map((tool) => ({
1126
+ type: "function",
1127
+ function: {
1128
+ name: tool.name,
1129
+ description: tool.description,
1130
+ parameters: {
1131
+ type: "object",
1132
+ properties: tool.parameters.properties,
1133
+ required: tool.parameters.required
1134
+ }
1135
+ }
1136
+ }));
1137
+ }
1138
+ /**
1139
+ * Export tools in Anthropic format
1140
+ */
1141
+ toAnthropicFormat() {
1142
+ return this.getAll().map((tool) => ({
1143
+ name: tool.name,
1144
+ description: tool.description,
1145
+ input_schema: {
1146
+ type: "object",
1147
+ properties: tool.parameters.properties,
1148
+ required: tool.parameters.required
1149
+ }
1150
+ }));
1151
+ }
1152
+ /**
1153
+ * Get tool definitions (without execute function)
1154
+ */
1155
+ getDefinitions() {
1156
+ return this.getAll().map((tool) => ({
1157
+ name: tool.name,
1158
+ description: tool.description,
1159
+ parameters: tool.parameters,
1160
+ category: tool.category,
1161
+ cost: tool.cost,
1162
+ examples: tool.examples,
1163
+ schema: tool.schema
1164
+ }));
1165
+ }
1166
+ /**
1167
+ * Get usage statistics for all tools
1168
+ */
1169
+ getUsageStats() {
1170
+ const stats = /* @__PURE__ */ new Map();
1171
+ this.usageStats.forEach((rawStats, name) => {
1172
+ stats.set(name, {
1173
+ calls: rawStats.calls,
1174
+ failures: rawStats.failures,
1175
+ successRate: rawStats.calls > 0 ? (rawStats.calls - rawStats.failures) / rawStats.calls : 0,
1176
+ averageDuration: rawStats.calls > 0 ? rawStats.totalDuration / rawStats.calls : void 0
1177
+ });
1178
+ });
1179
+ return stats;
1180
+ }
1181
+ /**
1182
+ * Get most frequently used tools
1183
+ */
1184
+ getMostUsed(limit = 5) {
1185
+ const sorted = Array.from(this.usageStats.entries()).sort((a, b) => b[1].calls - a[1].calls).slice(0, limit).map(([name]) => this.tools.get(name)).filter((tool) => tool !== void 0);
1186
+ return sorted;
1187
+ }
1188
+ /**
1189
+ * Get list of all categories
1190
+ */
1191
+ getCategories() {
1192
+ const categories = /* @__PURE__ */ new Set();
1193
+ this.getAll().forEach((tool) => {
1194
+ if (tool.category) {
1195
+ categories.add(tool.category);
1196
+ }
1197
+ });
1198
+ return Array.from(categories).sort();
1199
+ }
1200
+ /**
1201
+ * Update execution context
1202
+ */
1203
+ updateContext(context) {
1204
+ this.context = { ...this.context, ...context };
1205
+ this.logger.debug("Updated context", { keys: Object.keys(context) });
1206
+ }
1207
+ /**
1208
+ * Get current context
1209
+ */
1210
+ getContext() {
1211
+ return { ...this.context };
1212
+ }
1213
+ /**
1214
+ * Clear all tools
1215
+ */
1216
+ clear() {
1217
+ this.logger.debug("Clearing all tools");
1218
+ this.tools.clear();
1219
+ this.usageStats.clear();
1220
+ }
1221
+ /**
1222
+ * Unregister a specific tool
1223
+ */
1224
+ unregister(name) {
1225
+ if (this.tools.has(name)) {
1226
+ this.tools.delete(name);
1227
+ this.usageStats.delete(name);
1228
+ this.logger.debug("Unregistered tool", { name });
1229
+ return true;
1230
+ }
1231
+ return false;
1232
+ }
1233
+ /**
1234
+ * Reset usage statistics
1235
+ */
1236
+ resetStats() {
1237
+ this.logger.debug("Resetting usage statistics");
1238
+ this.usageStats.forEach((stats) => {
1239
+ stats.calls = 0;
1240
+ stats.failures = 0;
1241
+ stats.totalDuration = 0;
1242
+ });
1243
+ }
1244
+ }
1245
+ const DEFAULT_CONFIG = {
1246
+ enabled: true,
1247
+ validateParams: true,
1248
+ sandboxExecution: false,
1249
+ maxExecutionTime: 3e4,
1250
+ maxConcurrentCalls: 10,
1251
+ deniedTools: []
1252
+ };
1253
+ class ToolGuard {
1254
+ config;
1255
+ logger;
1256
+ events;
1257
+ constructor(config = {}, logger, events = {}) {
1258
+ this.config = { ...DEFAULT_CONFIG, ...config };
1259
+ this.logger = wrapLogger(logger || DEFAULT_LOGGER, "ToolGuard");
1260
+ this.events = events;
1261
+ }
1262
+ /**
1263
+ * Validate tool parameters against a Zod schema
1264
+ */
1265
+ validateParams(toolName, params, schema) {
1266
+ if (!this.config.enabled || !this.config.validateParams) {
1267
+ return { success: true, data: params };
1268
+ }
1269
+ try {
1270
+ const data = schema.parse(params);
1271
+ return { success: true, data };
1272
+ } catch (error) {
1273
+ if (error instanceof ZodError) {
1274
+ const issues = error.issues || [];
1275
+ const violations = issues.map(
1276
+ (e) => `${e.path.join(".")}: ${e.message}`
1277
+ );
1278
+ const message = `Schema validation failed: ${violations.join("; ")}`;
1279
+ this.logger.warn(`Tool validation failed for "${toolName}"`, {
1280
+ violations
1281
+ });
1282
+ this.events.onValidationFailed?.(toolName, message);
1283
+ return {
1284
+ success: false,
1285
+ error: "Parameter validation failed",
1286
+ violations
1287
+ };
1288
+ }
1289
+ throw error;
1290
+ }
1291
+ }
1292
+ /**
1293
+ * Safely parse JSON tool arguments
1294
+ */
1295
+ parseToolArguments(toolName, jsonString) {
1296
+ if (!this.config.enabled) {
1297
+ return { success: true, data: JSON.parse(jsonString) };
1298
+ }
1299
+ try {
1300
+ const parsed = JSON.parse(jsonString);
1301
+ if (this.hasPrototypePollution(parsed)) {
1302
+ this.logger.error(
1303
+ `Prototype pollution attempt detected for tool "${toolName}"`
1304
+ );
1305
+ this.events.onPrototypePollution?.(toolName);
1306
+ return {
1307
+ success: false,
1308
+ error: "Invalid tool arguments: potentially malicious content detected"
1309
+ };
1310
+ }
1311
+ if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) {
1312
+ return {
1313
+ success: false,
1314
+ error: "Tool arguments must be a JSON object"
1315
+ };
1316
+ }
1317
+ return { success: true, data: parsed };
1318
+ } catch (error) {
1319
+ const errorMsg = error instanceof Error ? error.message : "Unknown error";
1320
+ this.logger.warn(`JSON parsing failed for tool "${toolName}"`, {
1321
+ error: errorMsg
1322
+ });
1323
+ this.events.onValidationFailed?.(
1324
+ toolName,
1325
+ `JSON parsing failed: ${errorMsg}`
1326
+ );
1327
+ return {
1328
+ success: false,
1329
+ error: "Invalid JSON in tool arguments"
1330
+ };
1331
+ }
1332
+ }
1333
+ /**
1334
+ * Check if a tool is allowed to execute
1335
+ */
1336
+ isToolAllowed(toolName) {
1337
+ if (!this.config.enabled) return true;
1338
+ if (this.config.deniedTools.includes(toolName)) {
1339
+ this.logger.warn(`Tool "${toolName}" blocked by deny list`);
1340
+ this.events.onExecutionBlocked?.(toolName, "Tool is in deny list");
1341
+ return false;
1342
+ }
1343
+ if (this.config.allowedTools && !this.config.allowedTools.includes(toolName)) {
1344
+ this.logger.warn(`Tool "${toolName}" not in allow list`);
1345
+ this.events.onExecutionBlocked?.(
1346
+ toolName,
1347
+ "Tool is not in allow list"
1348
+ );
1349
+ return false;
1350
+ }
1351
+ return true;
1352
+ }
1353
+ /**
1354
+ * Get current configuration
1355
+ */
1356
+ getConfig() {
1357
+ return { ...this.config };
1358
+ }
1359
+ /**
1360
+ * Update configuration
1361
+ */
1362
+ updateConfig(config) {
1363
+ this.config = { ...this.config, ...config };
1364
+ }
1365
+ /**
1366
+ * Add a tool to the deny list
1367
+ */
1368
+ denyTool(toolName) {
1369
+ if (!this.config.deniedTools.includes(toolName)) {
1370
+ this.config.deniedTools.push(toolName);
1371
+ }
1372
+ }
1373
+ /**
1374
+ * Remove a tool from the deny list
1375
+ */
1376
+ allowTool(toolName) {
1377
+ const index = this.config.deniedTools.indexOf(toolName);
1378
+ if (index !== -1) {
1379
+ this.config.deniedTools.splice(index, 1);
1380
+ }
1381
+ }
1382
+ /**
1383
+ * Check if security is enabled
1384
+ */
1385
+ isEnabled() {
1386
+ return this.config.enabled;
1387
+ }
1388
+ /**
1389
+ * Enable or disable security
1390
+ */
1391
+ setEnabled(enabled) {
1392
+ this.config.enabled = enabled;
1393
+ }
1394
+ /**
1395
+ * Detect prototype pollution attempts
1396
+ */
1397
+ hasPrototypePollution(obj, depth = 0) {
1398
+ if (depth > 10) return false;
1399
+ if (typeof obj !== "object" || obj === null) return false;
1400
+ const dangerousKeys = ["__proto__", "constructor", "prototype"];
1401
+ for (const key of Object.keys(obj)) {
1402
+ if (dangerousKeys.includes(key)) {
1403
+ return true;
1404
+ }
1405
+ if (typeof obj[key] === "object") {
1406
+ if (this.hasPrototypePollution(
1407
+ obj[key],
1408
+ depth + 1
1409
+ )) {
1410
+ return true;
1411
+ }
1412
+ }
1413
+ }
1414
+ return false;
1415
+ }
1416
+ }
1417
+ class ToolSandbox {
1418
+ config;
1419
+ logger;
1420
+ events;
1421
+ activeExecutions = /* @__PURE__ */ new Map();
1422
+ executionCount = 0;
1423
+ constructor(config = {}, logger, events = {}) {
1424
+ this.config = {
1425
+ enabled: true,
1426
+ validateParams: true,
1427
+ sandboxExecution: true,
1428
+ maxExecutionTime: 3e4,
1429
+ maxConcurrentCalls: 10,
1430
+ deniedTools: [],
1431
+ ...config
1432
+ };
1433
+ this.logger = wrapLogger(logger || DEFAULT_LOGGER, "ToolSandbox");
1434
+ this.events = events;
1435
+ }
1436
+ /**
1437
+ * Execute a tool with sandbox restrictions
1438
+ */
1439
+ async execute(tool, params, baseContext, options = {}) {
1440
+ if (!this.config.enabled || !this.config.sandboxExecution) {
1441
+ return tool.execute(params, baseContext);
1442
+ }
1443
+ if (this.activeExecutions.size >= this.config.maxConcurrentCalls) {
1444
+ this.logger.warn("Max concurrent executions reached", {
1445
+ toolName: tool.name,
1446
+ activeCount: this.activeExecutions.size,
1447
+ limit: this.config.maxConcurrentCalls
1448
+ });
1449
+ this.events.onConcurrencyExceeded?.(
1450
+ tool.name,
1451
+ this.activeExecutions.size
1452
+ );
1453
+ throw new Error("Too many concurrent tool executions");
1454
+ }
1455
+ const executionId = `exec-${++this.executionCount}-${Date.now()}`;
1456
+ const controller = new AbortController();
1457
+ this.activeExecutions.set(executionId, controller);
1458
+ const sandboxedContext = {
1459
+ ...baseContext,
1460
+ sandbox: {
1461
+ allowedOperations: new Set(options.allowedOperations || []),
1462
+ maxOutputSize: options.maxOutputSize || 1024 * 1024,
1463
+ // 1MB default
1464
+ executionId
1465
+ }
1466
+ };
1467
+ const timeout = options.maxExecutionTime || this.config.maxExecutionTime;
1468
+ try {
1469
+ await options.onBeforeExecution?.(tool, params);
1470
+ const result = await this.executeWithTimeout(
1471
+ () => tool.execute(params, sandboxedContext),
1472
+ timeout,
1473
+ controller.signal,
1474
+ tool.name
1475
+ );
1476
+ const outputSize = this.estimateSize(result);
1477
+ if (outputSize > sandboxedContext.sandbox.maxOutputSize) {
1478
+ this.logger.warn("Tool output exceeded max size", {
1479
+ toolName: tool.name,
1480
+ outputSize,
1481
+ maxSize: sandboxedContext.sandbox.maxOutputSize
1482
+ });
1483
+ this.events.onOutputSizeExceeded?.(
1484
+ tool.name,
1485
+ outputSize,
1486
+ sandboxedContext.sandbox.maxOutputSize
1487
+ );
1488
+ throw new Error("Tool output exceeded maximum size limit");
1489
+ }
1490
+ await options.onAfterExecution?.(tool, result);
1491
+ return result;
1492
+ } catch (error) {
1493
+ await options.onAfterExecution?.(tool, void 0, error);
1494
+ throw error;
1495
+ } finally {
1496
+ this.activeExecutions.delete(executionId);
1497
+ }
1498
+ }
1499
+ /**
1500
+ * Cancel all active executions
1501
+ */
1502
+ cancelAll() {
1503
+ for (const [id, controller] of this.activeExecutions) {
1504
+ controller.abort();
1505
+ this.logger.info("Execution cancelled", { executionId: id });
1506
+ this.events.onCancelled?.(id);
1507
+ }
1508
+ this.activeExecutions.clear();
1509
+ }
1510
+ /**
1511
+ * Cancel a specific execution by ID
1512
+ */
1513
+ cancel(executionId) {
1514
+ const controller = this.activeExecutions.get(executionId);
1515
+ if (controller) {
1516
+ controller.abort();
1517
+ this.activeExecutions.delete(executionId);
1518
+ this.logger.info("Execution cancelled", { executionId });
1519
+ this.events.onCancelled?.(executionId);
1520
+ return true;
1521
+ }
1522
+ return false;
1523
+ }
1524
+ /**
1525
+ * Get active execution count
1526
+ */
1527
+ getActiveCount() {
1528
+ return this.activeExecutions.size;
1529
+ }
1530
+ /**
1531
+ * Get list of active execution IDs
1532
+ */
1533
+ getActiveExecutionIds() {
1534
+ return Array.from(this.activeExecutions.keys());
1535
+ }
1536
+ /**
1537
+ * Check if sandbox is enabled
1538
+ */
1539
+ isEnabled() {
1540
+ return this.config.enabled && this.config.sandboxExecution;
1541
+ }
1542
+ /**
1543
+ * Get current configuration
1544
+ */
1545
+ getConfig() {
1546
+ return { ...this.config };
1547
+ }
1548
+ /**
1549
+ * Update configuration
1550
+ */
1551
+ updateConfig(config) {
1552
+ this.config = { ...this.config, ...config };
1553
+ }
1554
+ async executeWithTimeout(fn, timeoutMs, signal, toolName) {
1555
+ return new Promise((resolve, reject) => {
1556
+ const timeoutId = setTimeout(() => {
1557
+ this.logger.warn("Tool execution timed out", {
1558
+ toolName,
1559
+ timeoutMs
1560
+ });
1561
+ this.events.onTimeout?.(toolName, timeoutMs);
1562
+ reject(
1563
+ new Error(`Tool execution timed out after ${timeoutMs}ms`)
1564
+ );
1565
+ }, timeoutMs);
1566
+ const abortHandler = () => {
1567
+ clearTimeout(timeoutId);
1568
+ reject(new Error("Tool execution was cancelled"));
1569
+ };
1570
+ signal.addEventListener("abort", abortHandler, { once: true });
1571
+ fn().then((result) => {
1572
+ clearTimeout(timeoutId);
1573
+ signal.removeEventListener("abort", abortHandler);
1574
+ resolve(result);
1575
+ }).catch((error) => {
1576
+ clearTimeout(timeoutId);
1577
+ signal.removeEventListener("abort", abortHandler);
1578
+ reject(error);
1579
+ });
1580
+ });
1581
+ }
1582
+ estimateSize(value) {
1583
+ if (value === null || value === void 0) return 0;
1584
+ if (typeof value === "string") return value.length * 2;
1585
+ if (typeof value === "number") return 8;
1586
+ if (typeof value === "boolean") return 4;
1587
+ if (Buffer.isBuffer(value)) return value.length;
1588
+ try {
1589
+ return JSON.stringify(value).length * 2;
1590
+ } catch {
1591
+ return 0;
1592
+ }
1593
+ }
1594
+ }
1595
+ function createSecureTool(tool, sandbox, guard) {
1596
+ return {
1597
+ ...tool,
1598
+ execute: async (params, context) => {
1599
+ if (!guard.isToolAllowed(tool.name)) {
1600
+ throw new Error(`Tool "${tool.name}" is not allowed`);
1601
+ }
1602
+ if (tool.schema) {
1603
+ const validation = guard.validateParams(
1604
+ tool.name,
1605
+ params,
1606
+ tool.schema
1607
+ );
1608
+ if (!validation.success) {
1609
+ throw new Error(`Validation failed: ${validation.error}`);
1610
+ }
1611
+ params = validation.data;
1612
+ }
1613
+ return sandbox.execute(tool, params, context || {});
1614
+ }
1615
+ };
1616
+ }
1617
+ const crypto = {};
1618
+ class ContextManager {
1619
+ items;
1620
+ hashes;
1621
+ logger;
1622
+ constructor(logger) {
1623
+ this.items = /* @__PURE__ */ new Map();
1624
+ this.hashes = /* @__PURE__ */ new Set();
1625
+ this.logger = wrapLogger(logger || DEFAULT_LOGGER, "ContextManager");
1626
+ }
1627
+ /**
1628
+ * Track a context item
1629
+ */
1630
+ track(item, position) {
1631
+ const hash2 = this.hashContent(item.content);
1632
+ if (!item.id && this.hashes.has(hash2)) {
1633
+ this.logger.debug("Skipping duplicate context item by hash", { hash: hash2 });
1634
+ return;
1635
+ }
1636
+ const id = item.id || this.generateId();
1637
+ const trackedItem = {
1638
+ ...item,
1639
+ id,
1640
+ hash: hash2,
1641
+ position,
1642
+ injectedAt: /* @__PURE__ */ new Date(),
1643
+ timestamp: item.timestamp || /* @__PURE__ */ new Date(),
1644
+ priority: item.priority || "medium"
1645
+ };
1646
+ this.items.set(id, trackedItem);
1647
+ this.hashes.add(hash2);
1648
+ this.logger.debug("Tracked context item", {
1649
+ id,
1650
+ category: item.category,
1651
+ position
1652
+ });
1653
+ }
1654
+ /**
1655
+ * Check if context with given ID exists
1656
+ */
1657
+ hasContext(id) {
1658
+ return this.items.has(id);
1659
+ }
1660
+ /**
1661
+ * Check if content with given hash exists
1662
+ */
1663
+ hasContentHash(content) {
1664
+ const hash2 = this.hashContent(content);
1665
+ return this.hashes.has(hash2);
1666
+ }
1667
+ /**
1668
+ * Check if similar content exists (fuzzy match)
1669
+ */
1670
+ hasSimilarContent(content, similarityThreshold = 0.9) {
1671
+ const MAX_ITEMS_WARNING = 1e3;
1672
+ if (this.items.size > MAX_ITEMS_WARNING) {
1673
+ this.logger.warn(
1674
+ "Large number of context items, similarity check may be slow",
1675
+ {
1676
+ count: this.items.size,
1677
+ threshold: MAX_ITEMS_WARNING
1678
+ }
1679
+ );
1680
+ }
1681
+ const normalized = this.normalizeContent(content);
1682
+ for (const item of this.items.values()) {
1683
+ const itemNormalized = this.normalizeContent(item.content || "");
1684
+ if (normalized === itemNormalized) {
1685
+ return true;
1686
+ }
1687
+ const longer = normalized.length > itemNormalized.length ? normalized : itemNormalized;
1688
+ const shorter = normalized.length <= itemNormalized.length ? normalized : itemNormalized;
1689
+ const lengthRatio = shorter.length / longer.length;
1690
+ if (lengthRatio >= similarityThreshold) {
1691
+ if (longer.includes(shorter)) {
1692
+ return true;
1693
+ }
1694
+ }
1695
+ }
1696
+ return false;
1697
+ }
1698
+ /**
1699
+ * Get context item by ID
1700
+ */
1701
+ get(id) {
1702
+ return this.items.get(id);
1703
+ }
1704
+ /**
1705
+ * Get all tracked context items
1706
+ */
1707
+ getAll() {
1708
+ return Array.from(this.items.values());
1709
+ }
1710
+ /**
1711
+ * Get context items by category
1712
+ */
1713
+ getByCategory(category) {
1714
+ return this.getAll().filter((item) => item.category === category);
1715
+ }
1716
+ /**
1717
+ * Get context items by priority
1718
+ */
1719
+ getByPriority(priority) {
1720
+ return this.getAll().filter((item) => item.priority === priority);
1721
+ }
1722
+ /**
1723
+ * Get context items by source
1724
+ */
1725
+ getBySource(source) {
1726
+ return this.getAll().filter((item) => item.source === source);
1727
+ }
1728
+ /**
1729
+ * Get all categories
1730
+ */
1731
+ getCategories() {
1732
+ const categories = /* @__PURE__ */ new Set();
1733
+ this.items.forEach((item) => {
1734
+ if (item.category) {
1735
+ categories.add(item.category);
1736
+ }
1737
+ });
1738
+ return Array.from(categories).sort();
1739
+ }
1740
+ /**
1741
+ * Get context statistics
1742
+ */
1743
+ getStats() {
1744
+ const byCategory = /* @__PURE__ */ new Map();
1745
+ const byPriority = /* @__PURE__ */ new Map();
1746
+ const bySource = /* @__PURE__ */ new Map();
1747
+ let oldestTimestamp;
1748
+ let newestTimestamp;
1749
+ this.items.forEach((item) => {
1750
+ if (item.category) {
1751
+ byCategory.set(
1752
+ item.category,
1753
+ (byCategory.get(item.category) || 0) + 1
1754
+ );
1755
+ }
1756
+ const priority = item.priority || "medium";
1757
+ byPriority.set(priority, (byPriority.get(priority) || 0) + 1);
1758
+ if (item.source) {
1759
+ bySource.set(item.source, (bySource.get(item.source) || 0) + 1);
1760
+ }
1761
+ if (item.timestamp) {
1762
+ if (!oldestTimestamp || item.timestamp < oldestTimestamp) {
1763
+ oldestTimestamp = item.timestamp;
1764
+ }
1765
+ if (!newestTimestamp || item.timestamp > newestTimestamp) {
1766
+ newestTimestamp = item.timestamp;
1767
+ }
1768
+ }
1769
+ });
1770
+ return {
1771
+ totalItems: this.items.size,
1772
+ byCategory,
1773
+ byPriority,
1774
+ bySource,
1775
+ oldestTimestamp,
1776
+ newestTimestamp
1777
+ };
1778
+ }
1779
+ /**
1780
+ * Remove context item by ID
1781
+ */
1782
+ remove(id) {
1783
+ const item = this.items.get(id);
1784
+ if (item) {
1785
+ this.items.delete(id);
1786
+ this.hashes.delete(item.hash);
1787
+ this.logger.debug("Removed context item", { id });
1788
+ return true;
1789
+ }
1790
+ return false;
1791
+ }
1792
+ /**
1793
+ * Clear all tracked context
1794
+ */
1795
+ clear() {
1796
+ this.items.clear();
1797
+ this.hashes.clear();
1798
+ this.logger.debug("Cleared all context");
1799
+ }
1800
+ generateId() {
1801
+ return `ctx-${Date.now()}-${Math.random().toString(36).substring(2, 9)}`;
1802
+ }
1803
+ hashContent(content) {
1804
+ return crypto.createHash("sha256").update(content).digest("hex").substring(0, 32);
1805
+ }
1806
+ normalizeContent(content) {
1807
+ return content.replace(/\s+/g, " ").trim().toLowerCase();
1808
+ }
1809
+ }
1810
+ const VERSION = "0.0.1";
1811
+ export {
1812
+ ContextManager,
1813
+ DEFAULT_LOGGER,
1814
+ LIBRARY_NAME,
1815
+ ToolGuard,
1816
+ ToolRegistry,
1817
+ ToolSandbox,
1818
+ VERSION,
1819
+ createSecureTool,
1820
+ wrapLogger
1821
+ };
1822
+ //# sourceMappingURL=index.js.map