@gotza02/seq-thinking 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (106) hide show
  1. package/README.md +149 -0
  2. package/SYSTEM_INSTRUCTIONS.md +50 -0
  3. package/agents_test.log +15 -0
  4. package/dist/__tests__/agents.test.d.ts +2 -0
  5. package/dist/__tests__/agents.test.d.ts.map +1 -0
  6. package/dist/__tests__/agents.test.js +673 -0
  7. package/dist/__tests__/agents.test.js.map +1 -0
  8. package/dist/__tests__/mcp-server.test.d.ts +2 -0
  9. package/dist/__tests__/mcp-server.test.d.ts.map +1 -0
  10. package/dist/__tests__/mcp-server.test.js +315 -0
  11. package/dist/__tests__/mcp-server.test.js.map +1 -0
  12. package/dist/__tests__/sequential-thinking.test.d.ts +2 -0
  13. package/dist/__tests__/sequential-thinking.test.d.ts.map +1 -0
  14. package/dist/__tests__/sequential-thinking.test.js +545 -0
  15. package/dist/__tests__/sequential-thinking.test.js.map +1 -0
  16. package/dist/__tests__/swarm-coordinator.test.d.ts +2 -0
  17. package/dist/__tests__/swarm-coordinator.test.d.ts.map +1 -0
  18. package/dist/__tests__/swarm-coordinator.test.js +606 -0
  19. package/dist/__tests__/swarm-coordinator.test.js.map +1 -0
  20. package/dist/__tests__/types.test.d.ts +2 -0
  21. package/dist/__tests__/types.test.d.ts.map +1 -0
  22. package/dist/__tests__/types.test.js +741 -0
  23. package/dist/__tests__/types.test.js.map +1 -0
  24. package/dist/__tests__/utils.test.d.ts +2 -0
  25. package/dist/__tests__/utils.test.d.ts.map +1 -0
  26. package/dist/__tests__/utils.test.js +264 -0
  27. package/dist/__tests__/utils.test.js.map +1 -0
  28. package/dist/agents/base-agent.d.ts +126 -0
  29. package/dist/agents/base-agent.d.ts.map +1 -0
  30. package/dist/agents/base-agent.js +214 -0
  31. package/dist/agents/base-agent.js.map +1 -0
  32. package/dist/agents/critic-agent.d.ts +134 -0
  33. package/dist/agents/critic-agent.d.ts.map +1 -0
  34. package/dist/agents/critic-agent.js +484 -0
  35. package/dist/agents/critic-agent.js.map +1 -0
  36. package/dist/agents/index.d.ts +11 -0
  37. package/dist/agents/index.d.ts.map +1 -0
  38. package/dist/agents/index.js +11 -0
  39. package/dist/agents/index.js.map +1 -0
  40. package/dist/agents/meta-reasoning-agent.d.ts +143 -0
  41. package/dist/agents/meta-reasoning-agent.d.ts.map +1 -0
  42. package/dist/agents/meta-reasoning-agent.js +532 -0
  43. package/dist/agents/meta-reasoning-agent.js.map +1 -0
  44. package/dist/agents/reasoner-agent.d.ts +75 -0
  45. package/dist/agents/reasoner-agent.d.ts.map +1 -0
  46. package/dist/agents/reasoner-agent.js +226 -0
  47. package/dist/agents/reasoner-agent.js.map +1 -0
  48. package/dist/agents/synthesizer-agent.d.ts +174 -0
  49. package/dist/agents/synthesizer-agent.d.ts.map +1 -0
  50. package/dist/agents/synthesizer-agent.js +583 -0
  51. package/dist/agents/synthesizer-agent.js.map +1 -0
  52. package/dist/index.d.ts +21 -0
  53. package/dist/index.d.ts.map +1 -0
  54. package/dist/index.js +27 -0
  55. package/dist/index.js.map +1 -0
  56. package/dist/mcp-server.d.ts +823 -0
  57. package/dist/mcp-server.d.ts.map +1 -0
  58. package/dist/mcp-server.js +377 -0
  59. package/dist/mcp-server.js.map +1 -0
  60. package/dist/sequential-thinking.d.ts +91 -0
  61. package/dist/sequential-thinking.d.ts.map +1 -0
  62. package/dist/sequential-thinking.js +540 -0
  63. package/dist/sequential-thinking.js.map +1 -0
  64. package/dist/swarm-coordinator.d.ts +188 -0
  65. package/dist/swarm-coordinator.d.ts.map +1 -0
  66. package/dist/swarm-coordinator.js +627 -0
  67. package/dist/swarm-coordinator.js.map +1 -0
  68. package/dist/types/index.d.ts +806 -0
  69. package/dist/types/index.d.ts.map +1 -0
  70. package/dist/types/index.js +279 -0
  71. package/dist/types/index.js.map +1 -0
  72. package/dist/utils/index.d.ts +421 -0
  73. package/dist/utils/index.d.ts.map +1 -0
  74. package/dist/utils/index.js +864 -0
  75. package/dist/utils/index.js.map +1 -0
  76. package/dist/utils/llm-adapter.d.ts +23 -0
  77. package/dist/utils/llm-adapter.d.ts.map +1 -0
  78. package/dist/utils/llm-adapter.js +68 -0
  79. package/dist/utils/llm-adapter.js.map +1 -0
  80. package/dist/utils/persistence.d.ts +33 -0
  81. package/dist/utils/persistence.d.ts.map +1 -0
  82. package/dist/utils/persistence.js +108 -0
  83. package/dist/utils/persistence.js.map +1 -0
  84. package/package.json +41 -0
  85. package/src/__tests__/agents.test.ts +858 -0
  86. package/src/__tests__/mcp-server.test.ts +380 -0
  87. package/src/__tests__/sequential-thinking.test.ts +687 -0
  88. package/src/__tests__/swarm-coordinator.test.ts +903 -0
  89. package/src/__tests__/types.test.ts +839 -0
  90. package/src/__tests__/utils.test.ts +322 -0
  91. package/src/agents/base-agent.ts +285 -0
  92. package/src/agents/critic-agent.ts +582 -0
  93. package/src/agents/index.ts +11 -0
  94. package/src/agents/meta-reasoning-agent.ts +672 -0
  95. package/src/agents/reasoner-agent.ts +312 -0
  96. package/src/agents/synthesizer-agent.ts +758 -0
  97. package/src/index.ts +118 -0
  98. package/src/mcp-server.ts +387 -0
  99. package/src/sequential-thinking.ts +560 -0
  100. package/src/swarm-coordinator.ts +744 -0
  101. package/src/types/index.ts +915 -0
  102. package/src/utils/index.ts +1004 -0
  103. package/src/utils/llm-adapter.ts +76 -0
  104. package/src/utils/persistence.ts +108 -0
  105. package/test_output.log +0 -0
  106. package/tsconfig.json +21 -0
@@ -0,0 +1,864 @@
1
+ /**
2
+ * Utility Functions for MCP Sequential Thinking System
3
+ * @module utils
4
+ * @version 1.0.0
5
+ */
6
+ import { v4 as uuidv4 } from 'uuid';
7
+ // ============================================================================
8
+ // ID Generation
9
+ // ============================================================================
10
+ /**
11
+ * Generate a unique ID based on timestamp and random string
12
+ * @returns Unique ID string
13
+ */
14
+ export function generateId() {
15
+ const timestamp = Date.now().toString();
16
+ const random = Math.random().toString(36).substring(2, 9).padEnd(7, '0');
17
+ return `${timestamp}-${random}`;
18
+ }
19
+ /**
20
+ * Generate a UUID v4
21
+ * @returns UUID string
22
+ */
23
+ export function generateUUID() {
24
+ return uuidv4();
25
+ }
26
+ /**
27
+ * Generate a short 8-character ID
28
+ * @returns Short ID string
29
+ */
30
+ export function generateShortId() {
31
+ return Math.random().toString(36).substring(2, 10);
32
+ }
33
+ // ============================================================================
34
+ // Numeric Utilities
35
+ // ============================================================================
36
+ /**
37
+ * Clamp a value between min and max
38
+ * @param value - Value to clamp
39
+ * @param min - Minimum value
40
+ * @param max - Maximum value
41
+ * @returns Clamped value
42
+ */
43
+ export function clamp(value, min, max) {
44
+ return Math.min(max, Math.max(min, value));
45
+ }
46
+ /**
47
+ * Clamp a confidence score to [0, 1]
48
+ * @param confidence - Confidence score
49
+ * @returns Clamped confidence
50
+ */
51
+ export function clampConfidence(confidence) {
52
+ return clamp(confidence, 0, 1);
53
+ }
54
+ /**
55
+ * Linear interpolation between two values
56
+ * @param a - Start value
57
+ * @param b - End value
58
+ * @param t - Interpolation factor (0-1)
59
+ * @returns Interpolated value
60
+ */
61
+ export function lerp(a, b, t) {
62
+ return a + (b - a) * clamp(t, 0, 1);
63
+ }
64
+ /**
65
+ * Round a number to specified decimal places
66
+ * @param value - Value to round
67
+ * @param decimals - Number of decimal places
68
+ * @returns Rounded value
69
+ */
70
+ export function roundTo(value, decimals) {
71
+ const factor = Math.pow(10, decimals);
72
+ return Math.round(value * factor) / factor;
73
+ }
74
+ // ============================================================================
75
+ // Similarity Calculation
76
+ // ============================================================================
77
+ /**
78
+ * Extract words from text
79
+ * @param text - Input text
80
+ * @returns Array of words
81
+ */
82
+ export function extractWords(text) {
83
+ return text.toLowerCase().match(/\b\w+\b/g) || [];
84
+ }
85
+ /**
86
+ * Calculate Jaccard similarity between two sets
87
+ * @param setA - First set
88
+ * @param setB - Second set
89
+ * @returns Jaccard similarity (0-1)
90
+ */
91
+ export function calculateJaccardSimilarity(setA, setB) {
92
+ const intersection = new Set([...setA].filter(x => setB.has(x)));
93
+ const union = new Set([...setA, ...setB]);
94
+ return union.size === 0 ? 0 : intersection.size / union.size;
95
+ }
96
+ /**
97
+ * Calculate Levenshtein distance between two strings
98
+ * @param a - First string
99
+ * @param b - Second string
100
+ * @returns Levenshtein distance
101
+ */
102
+ export function levenshteinDistance(a, b) {
103
+ const matrix = [];
104
+ for (let i = 0; i <= b.length; i++) {
105
+ matrix[i] = [i];
106
+ }
107
+ for (let j = 0; j <= a.length; j++) {
108
+ matrix[0][j] = j;
109
+ }
110
+ for (let i = 1; i <= b.length; i++) {
111
+ for (let j = 1; j <= a.length; j++) {
112
+ if (b.charAt(i - 1) === a.charAt(j - 1)) {
113
+ matrix[i][j] = matrix[i - 1][j - 1];
114
+ }
115
+ else {
116
+ matrix[i][j] = Math.min(matrix[i - 1][j - 1] + 1, // substitution
117
+ matrix[i][j - 1] + 1, // insertion
118
+ matrix[i - 1][j] + 1 // deletion
119
+ );
120
+ }
121
+ }
122
+ }
123
+ return matrix[b.length][a.length];
124
+ }
125
+ /**
126
+ * Calculate text similarity using Levenshtein distance
127
+ * @param a - First text
128
+ * @param b - Second text
129
+ * @returns Similarity score (0-1)
130
+ */
131
+ export function calculateSimilarity(a, b) {
132
+ if (a === b)
133
+ return 1;
134
+ if (a.length === 0 || b.length === 0)
135
+ return 0;
136
+ // Optimization: return 0 if no common characters
137
+ const setA = new Set(a.split(''));
138
+ const hasCommon = b.split('').some(char => setA.has(char));
139
+ if (!hasCommon)
140
+ return 0;
141
+ const distance = levenshteinDistance(a, b);
142
+ const longestLength = Math.max(a.length, b.length);
143
+ return (longestLength - distance) / longestLength;
144
+ }
145
+ /**
146
+ * Calculate cosine similarity between two vectors
147
+ * @param a - First vector
148
+ * @param b - Second vector
149
+ * @returns Cosine similarity (-1 to 1)
150
+ */
151
+ export function calculateCosineSimilarity(a, b) {
152
+ if (a.length !== b.length) {
153
+ throw new Error('Vectors must have same length');
154
+ }
155
+ let dotProduct = 0;
156
+ let normA = 0;
157
+ let normB = 0;
158
+ for (let i = 0; i < a.length; i++) {
159
+ dotProduct += a[i] * b[i];
160
+ normA += a[i] * a[i];
161
+ normB += b[i] * b[i];
162
+ }
163
+ if (normA === 0 || normB === 0) {
164
+ return 0;
165
+ }
166
+ return dotProduct / (Math.sqrt(normA) * Math.sqrt(normB));
167
+ }
168
+ /**
169
+ * Extract n-grams from text
170
+ * @param text - Input text
171
+ * @param n - N-gram size
172
+ * @returns Array of n-grams
173
+ */
174
+ export function extractNGrams(text, n) {
175
+ const words = extractWords(text);
176
+ const ngrams = [];
177
+ for (let i = 0; i <= words.length - n; i++) {
178
+ ngrams.push(words.slice(i, i + n).join(' '));
179
+ }
180
+ return ngrams;
181
+ }
182
+ /**
183
+ * Calculate n-gram similarity between two texts
184
+ * @param a - First text
185
+ * @param b - Second text
186
+ * @param n - N-gram size (default: 2)
187
+ * @returns Similarity score (0-1)
188
+ */
189
+ export function calculateNGramSimilarity(a, b, n = 2) {
190
+ const ngramsA = new Set(extractNGrams(a, n));
191
+ const ngramsB = new Set(extractNGrams(b, n));
192
+ return calculateJaccardSimilarity(ngramsA, ngramsB);
193
+ }
194
+ // ============================================================================
195
+ // Statistical Utilities
196
+ // ============================================================================
197
+ /**
198
+ * Calculate mean of an array of numbers
199
+ * @param values - Array of numbers
200
+ * @returns Mean value
201
+ */
202
+ export function calculateMean(values) {
203
+ if (values.length === 0)
204
+ return NaN;
205
+ return values.reduce((sum, v) => sum + v, 0) / values.length;
206
+ }
207
+ /**
208
+ * Calculate weighted average
209
+ * @param values - Array of values
210
+ * @param weights - Array of weights
211
+ * @returns Weighted average
212
+ */
213
+ export function calculateWeightedAverage(values, weights) {
214
+ if (values.length !== weights.length) {
215
+ throw new Error('Values and weights must have same length');
216
+ }
217
+ if (values.length === 0)
218
+ return NaN;
219
+ const totalWeight = weights.reduce((sum, w) => sum + w, 0);
220
+ if (totalWeight === 0)
221
+ return 0;
222
+ const weightedSum = values.reduce((sum, v, i) => sum + v * weights[i], 0);
223
+ return weightedSum / totalWeight;
224
+ }
225
+ /**
226
+ * Calculate median of an array of numbers
227
+ * @param values - Array of numbers
228
+ * @returns Median value
229
+ */
230
+ export function calculateMedian(values) {
231
+ if (values.length === 0)
232
+ return 0;
233
+ const sorted = [...values].sort((a, b) => a - b);
234
+ const mid = Math.floor(sorted.length / 2);
235
+ if (sorted.length % 2 === 0) {
236
+ return (sorted[mid - 1] + sorted[mid]) / 2;
237
+ }
238
+ return sorted[mid];
239
+ }
240
+ /**
241
+ * Calculate standard deviation
242
+ * @param values - Array of numbers
243
+ * @returns Standard deviation
244
+ */
245
+ export function calculateStandardDeviation(values) {
246
+ if (values.length === 0)
247
+ return 0;
248
+ const mean = calculateMean(values);
249
+ const squaredDiffs = values.map(v => Math.pow(v - mean, 2));
250
+ const variance = calculateMean(squaredDiffs);
251
+ return Math.sqrt(variance);
252
+ }
253
+ /**
254
+ * Calculate variance
255
+ * @param values - Array of numbers
256
+ * @returns Variance
257
+ */
258
+ export function calculateVariance(values) {
259
+ if (values.length === 0)
260
+ return 0;
261
+ const mean = calculateMean(values);
262
+ const squaredDiffs = values.map(v => Math.pow(v - mean, 2));
263
+ return calculateMean(squaredDiffs);
264
+ }
265
+ /**
266
+ * Find minimum value
267
+ * @param values - Array of numbers
268
+ * @returns Minimum value
269
+ */
270
+ export function findMin(values) {
271
+ if (values.length === 0)
272
+ return 0;
273
+ return Math.min(...values);
274
+ }
275
+ /**
276
+ * Find maximum value
277
+ * @param values - Array of numbers
278
+ * @returns Maximum value
279
+ */
280
+ export function findMax(values) {
281
+ if (values.length === 0)
282
+ return 0;
283
+ return Math.max(...values);
284
+ }
285
+ /**
286
+ * Normalize values to [0, 1] range
287
+ * @param values - Array of numbers
288
+ * @returns Normalized values
289
+ */
290
+ export function normalizeValues(values) {
291
+ if (values.length === 0)
292
+ return [];
293
+ const min = findMin(values);
294
+ const max = findMax(values);
295
+ const range = max - min;
296
+ if (range === 0)
297
+ return values.map(() => 0.5);
298
+ return values.map(v => (v - min) / range);
299
+ }
300
+ /**
301
+ * Calculate percentile
302
+ * @param values - Array of numbers
303
+ * @param percentile - Percentile (0-100)
304
+ * @returns Percentile value
305
+ */
306
+ export function calculatePercentile(values, percentile) {
307
+ if (values.length === 0)
308
+ return 0;
309
+ const sorted = [...values].sort((a, b) => a - b);
310
+ const index = (percentile / 100) * (sorted.length - 1);
311
+ const lower = Math.floor(index);
312
+ const upper = Math.ceil(index);
313
+ const weight = index - lower;
314
+ return sorted[lower] * (1 - weight) + sorted[upper] * weight;
315
+ }
316
+ // ============================================================================
317
+ // Time Formatting
318
+ // ============================================================================
319
+ /**
320
+ * Format duration in milliseconds to human-readable string
321
+ * @param ms - Duration in milliseconds
322
+ * @returns Formatted string
323
+ */
324
+ export function formatDuration(ms) {
325
+ const isNegative = ms < 0;
326
+ const absMs = Math.abs(Math.floor(ms));
327
+ const sign = isNegative ? '-' : '';
328
+ if (absMs < 1000) {
329
+ return `${sign}${absMs}ms`;
330
+ }
331
+ const seconds = Math.floor(absMs / 1000);
332
+ if (seconds < 60) {
333
+ return `${sign}${seconds}s`;
334
+ }
335
+ const minutes = Math.floor(seconds / 60);
336
+ if (minutes < 60) {
337
+ return `${sign}${minutes}m`;
338
+ }
339
+ const hours = Math.floor(minutes / 60);
340
+ return `${sign}${hours}h`;
341
+ }
342
+ /**
343
+ * Format timestamp to ISO string
344
+ * @param timestamp - Timestamp (Date or number)
345
+ * @returns ISO string
346
+ */
347
+ export function formatTimestamp(timestamp) {
348
+ const date = timestamp instanceof Date ? timestamp : new Date(timestamp);
349
+ return date.toISOString();
350
+ }
351
+ /**
352
+ * Format relative time (e.g., "2m ago")
353
+ * @param timestamp - Timestamp (Date or number)
354
+ * @returns Relative time string
355
+ */
356
+ export function formatRelativeTime(timestamp) {
357
+ const date = timestamp instanceof Date ? timestamp : new Date(timestamp);
358
+ const now = new Date();
359
+ const diffMs = now.getTime() - date.getTime();
360
+ const seconds = Math.floor(diffMs / 1000);
361
+ const minutes = Math.floor(seconds / 60);
362
+ const hours = Math.floor(minutes / 60);
363
+ const days = Math.floor(hours / 24);
364
+ if (days > 0)
365
+ return `${days}d ago`;
366
+ if (hours > 0)
367
+ return `${hours}h ago`;
368
+ if (minutes > 0)
369
+ return `${minutes}m ago`;
370
+ return `${seconds}s ago`;
371
+ }
372
+ // ============================================================================
373
+ // Object Utilities
374
+ // ============================================================================
375
+ /**
376
+ * Deep clone an object
377
+ * @param obj - Object to clone
378
+ * @returns Cloned object
379
+ */
380
+ export function deepClone(obj) {
381
+ if (obj === null || typeof obj !== 'object')
382
+ return obj;
383
+ if (obj instanceof Date)
384
+ return new Date(obj.getTime());
385
+ if (Array.isArray(obj))
386
+ return obj.map(deepClone);
387
+ const cloned = {};
388
+ for (const key in obj) {
389
+ if (Object.prototype.hasOwnProperty.call(obj, key)) {
390
+ cloned[key] = deepClone(obj[key]);
391
+ }
392
+ }
393
+ return cloned;
394
+ }
395
+ /**
396
+ * Deep clone with Date support
397
+ * @param obj - Object to clone
398
+ * @returns Cloned object with Dates preserved
399
+ */
400
+ export function deepCloneWithDates(obj) {
401
+ return deepClone(obj);
402
+ }
403
+ /**
404
+ * Deep merge two objects
405
+ * @param target - Target object
406
+ * @param source - Source object
407
+ * @returns Merged object
408
+ */
409
+ export function deepMerge(target, source) {
410
+ const result = { ...target };
411
+ for (const key in source) {
412
+ if (Object.prototype.hasOwnProperty.call(source, key)) {
413
+ const sourceValue = source[key];
414
+ const targetValue = result[key];
415
+ if (typeof sourceValue === 'object' &&
416
+ sourceValue !== null &&
417
+ !Array.isArray(sourceValue) &&
418
+ typeof targetValue === 'object' &&
419
+ targetValue !== null &&
420
+ !Array.isArray(targetValue)) {
421
+ result[key] = deepMerge(targetValue, sourceValue);
422
+ }
423
+ else {
424
+ result[key] = sourceValue;
425
+ }
426
+ }
427
+ }
428
+ return result;
429
+ }
430
+ /**
431
+ * Deep equality check
432
+ * @param a - First object
433
+ * @param b - Second object
434
+ * @returns True if equal
435
+ */
436
+ export function deepEqual(a, b) {
437
+ if (a === b)
438
+ return true;
439
+ if (a === null || b === null)
440
+ return false;
441
+ if (typeof a !== typeof b)
442
+ return false;
443
+ if (typeof a !== 'object')
444
+ return false;
445
+ if (a instanceof Date && b instanceof Date) {
446
+ return a.getTime() === b.getTime();
447
+ }
448
+ if (Array.isArray(a) && Array.isArray(b)) {
449
+ if (a.length !== b.length)
450
+ return false;
451
+ return a.every((item, i) => deepEqual(item, b[i]));
452
+ }
453
+ const aObj = a;
454
+ const bObj = b;
455
+ const aKeys = Object.keys(aObj);
456
+ const bKeys = Object.keys(bObj);
457
+ if (aKeys.length !== bKeys.length)
458
+ return false;
459
+ return aKeys.every(key => deepEqual(aObj[key], bObj[key]));
460
+ }
461
+ /**
462
+ * Pick specific keys from an object
463
+ * @param obj - Source object
464
+ * @param keys - Keys to pick
465
+ * @returns Object with picked keys
466
+ */
467
+ export function pick(obj, keys) {
468
+ const result = {};
469
+ for (const key of keys) {
470
+ if (Object.prototype.hasOwnProperty.call(obj, key)) {
471
+ result[key] = obj[key];
472
+ }
473
+ }
474
+ return result;
475
+ }
476
+ /**
477
+ * Omit specific keys from an object
478
+ * @param obj - Source object
479
+ * @param keys - Keys to omit
480
+ * @returns Object without omitted keys
481
+ */
482
+ export function omit(obj, keys) {
483
+ const result = { ...obj };
484
+ for (const key of keys) {
485
+ delete result[key];
486
+ }
487
+ return result;
488
+ }
489
+ // ============================================================================
490
+ // Validation Utilities
491
+ // ============================================================================
492
+ /**
493
+ * Validate UUID format
494
+ * @param uuid - String to validate
495
+ * @returns True if valid UUID
496
+ */
497
+ export function validateUUID(uuid) {
498
+ const uuidRegex = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
499
+ return uuidRegex.test(uuid);
500
+ }
501
+ /**
502
+ * Check if value is a non-empty string
503
+ * @param value - Value to check
504
+ * @returns True if non-empty string
505
+ */
506
+ export function isNonEmptyString(value) {
507
+ return typeof value === 'string' && value.length > 0;
508
+ }
509
+ /**
510
+ * Check if value is a positive number
511
+ * @param value - Value to check
512
+ * @returns True if positive number
513
+ */
514
+ export function isPositiveNumber(value) {
515
+ return typeof value === 'number' && !isNaN(value) && value > 0;
516
+ }
517
+ /**
518
+ * Check if value is in range
519
+ * @param value - Value to check
520
+ * @param min - Minimum value
521
+ * @param max - Maximum value
522
+ * @returns True if in range
523
+ */
524
+ export function isInRange(value, min, max) {
525
+ return value >= min && value <= max;
526
+ }
527
+ /**
528
+ * Check if value is a non-empty array
529
+ * @param value - Value to check
530
+ * @returns True if non-empty array
531
+ */
532
+ export function isNonEmptyArray(value) {
533
+ return Array.isArray(value) && value.length > 0;
534
+ }
535
+ /**
536
+ * Check if value is a plain object
537
+ * @param value - Value to check
538
+ * @returns True if plain object
539
+ */
540
+ export function isPlainObject(value) {
541
+ return typeof value === 'object' && value !== null && !Array.isArray(value);
542
+ }
543
+ // ============================================================================
544
+ // String Utilities
545
+ // ============================================================================
546
+ /**
547
+ * Sanitize input string (remove special characters)
548
+ * @param input - Input string
549
+ * @returns Sanitized string
550
+ */
551
+ export function sanitizeString(input) {
552
+ return input.replace(/[<>\"']/g, '');
553
+ }
554
+ /**
555
+ * Truncate string with ellipsis
556
+ * @param str - String to truncate
557
+ * @param maxLength - Maximum length
558
+ * @returns Truncated string
559
+ */
560
+ export function truncateString(str, maxLength) {
561
+ if (str.length <= maxLength)
562
+ return str;
563
+ return str.substring(0, maxLength - 3) + '...';
564
+ }
565
+ /**
566
+ * Convert string to camelCase
567
+ * @param str - Input string
568
+ * @returns camelCase string
569
+ */
570
+ export function toCamelCase(str) {
571
+ return str
572
+ .replace(/(?:^\w|[A-Z]|\b\w)/g, (word, index) => index === 0 ? word.toLowerCase() : word.toUpperCase())
573
+ .replace(/\s+/g, '');
574
+ }
575
+ /**
576
+ * Convert string to PascalCase
577
+ * @param str - Input string
578
+ * @returns PascalCase string
579
+ */
580
+ export function toPascalCase(str) {
581
+ return str
582
+ .replace(/(?:^\w|[A-Z]|\b\w)/g, word => word.toUpperCase())
583
+ .replace(/\s+/g, '');
584
+ }
585
+ /**
586
+ * Convert string to snake_case
587
+ * @param str - Input string
588
+ * @returns snake_case string
589
+ */
590
+ export function toSnakeCase(str) {
591
+ return str
592
+ .replace(/\W+/g, ' ')
593
+ .split(/ |\B(?=[A-Z])/)
594
+ .map(word => word.toLowerCase())
595
+ .join('_');
596
+ }
597
+ /**
598
+ * Convert string to kebab-case
599
+ * @param str - Input string
600
+ * @returns kebab-case string
601
+ */
602
+ export function toKebabCase(str) {
603
+ return str
604
+ .replace(/\W+/g, ' ')
605
+ .split(/ |\B(?=[A-Z])/)
606
+ .map(word => word.toLowerCase())
607
+ .join('-');
608
+ }
609
+ /**
610
+ * Escape regex special characters
611
+ * @param str - Input string
612
+ * @returns Escaped string
613
+ */
614
+ export function escapeRegExp(str) {
615
+ return str.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
616
+ }
617
+ // ============================================================================
618
+ // Array Utilities
619
+ // ============================================================================
620
+ /**
621
+ * Remove duplicates from array
622
+ * @param arr - Input array
623
+ * @returns Array without duplicates
624
+ */
625
+ export function unique(arr) {
626
+ return [...new Set(arr)];
627
+ }
628
+ /**
629
+ * Remove duplicates by key function
630
+ * @param arr - Input array
631
+ * @param keyFn - Key function
632
+ * @returns Array without duplicates
633
+ */
634
+ export function uniqueBy(arr, keyFn) {
635
+ const seen = new Set();
636
+ return arr.filter(item => {
637
+ const key = keyFn(item);
638
+ if (seen.has(key))
639
+ return false;
640
+ seen.add(key);
641
+ return true;
642
+ });
643
+ }
644
+ /**
645
+ * Group array by key function
646
+ * @param arr - Input array
647
+ * @param keyFn - Key function
648
+ * @returns Grouped object
649
+ */
650
+ export function groupBy(arr, keyFn) {
651
+ return arr.reduce((groups, item) => {
652
+ const key = keyFn(item);
653
+ if (!groups[key])
654
+ groups[key] = [];
655
+ groups[key].push(item);
656
+ return groups;
657
+ }, {});
658
+ }
659
+ /**
660
+ * Partition array by predicate
661
+ * @param arr - Input array
662
+ * @param predicate - Predicate function
663
+ * @returns [passing, failing] arrays
664
+ */
665
+ export function partition(arr, predicate) {
666
+ const passing = [];
667
+ const failing = [];
668
+ for (const item of arr) {
669
+ if (predicate(item)) {
670
+ passing.push(item);
671
+ }
672
+ else {
673
+ failing.push(item);
674
+ }
675
+ }
676
+ return [passing, failing];
677
+ }
678
+ /**
679
+ * Shuffle array (Fisher-Yates algorithm)
680
+ * @param arr - Input array
681
+ * @returns Shuffled array
682
+ */
683
+ export function shuffle(arr) {
684
+ const result = [...arr];
685
+ for (let i = result.length - 1; i > 0; i--) {
686
+ const j = Math.floor(Math.random() * (i + 1));
687
+ [result[i], result[j]] = [result[j], result[i]];
688
+ }
689
+ return result;
690
+ }
691
+ /**
692
+ * Sample random element from array
693
+ * @param arr - Input array
694
+ * @returns Random element
695
+ */
696
+ export function sample(arr) {
697
+ if (arr.length === 0)
698
+ return undefined;
699
+ return arr[Math.floor(Math.random() * arr.length)];
700
+ }
701
+ /**
702
+ * Split array into chunks
703
+ * @param arr - Input array
704
+ * @param size - Chunk size
705
+ * @returns Array of chunks
706
+ */
707
+ export function chunk(arr, size) {
708
+ const result = [];
709
+ for (let i = 0; i < arr.length; i += size) {
710
+ result.push(arr.slice(i, i + size));
711
+ }
712
+ return result;
713
+ }
714
+ /**
715
+ * Flatten array one level
716
+ * @param arr - Input array
717
+ * @returns Flattened array
718
+ */
719
+ export function flatten(arr) {
720
+ return arr.reduce((flat, item) => flat.concat(item), []);
721
+ }
722
+ /**
723
+ * Deep flatten array
724
+ * @param arr - Input array
725
+ * @returns Deeply flattened array
726
+ */
727
+ export function deepFlatten(arr) {
728
+ const result = [];
729
+ for (const item of arr) {
730
+ if (Array.isArray(item)) {
731
+ result.push(...deepFlatten(item));
732
+ }
733
+ else {
734
+ result.push(item);
735
+ }
736
+ }
737
+ return result;
738
+ }
739
+ // ============================================================================
740
+ // Async Utilities
741
+ // ============================================================================
742
+ /**
743
+ * Sleep for specified milliseconds
744
+ * @param ms - Milliseconds to sleep
745
+ * @returns Promise that resolves after ms
746
+ */
747
+ export function sleep(ms) {
748
+ return new Promise(resolve => setTimeout(resolve, ms));
749
+ }
750
+ /**
751
+ * Create a timeout promise
752
+ * @param ms - Timeout in milliseconds
753
+ * @param message - Error message
754
+ * @returns Promise that rejects after ms
755
+ */
756
+ export function createTimeoutPromise(ms, message = 'Operation timed out') {
757
+ return new Promise((_, reject) => {
758
+ setTimeout(() => reject(new Error(message)), ms);
759
+ });
760
+ }
761
+ /**
762
+ * Wrap promise with timeout
763
+ * @param promise - Promise to wrap
764
+ * @param ms - Timeout in milliseconds
765
+ * @returns Promise with timeout
766
+ */
767
+ export async function withTimeout(promise, ms) {
768
+ return Promise.race([promise, createTimeoutPromise(ms)]);
769
+ }
770
+ /**
771
+ * Retry a function with exponential backoff
772
+ * @param fn - Function to retry
773
+ * @param maxRetries - Maximum retries
774
+ * @param delayMs - Initial delay
775
+ * @returns Function result
776
+ */
777
+ export async function retry(fn, maxRetries = 3, delayMs = 1000) {
778
+ let lastError;
779
+ for (let i = 0; i < maxRetries; i++) {
780
+ try {
781
+ return await fn();
782
+ }
783
+ catch (error) {
784
+ lastError = error instanceof Error ? error : new Error(String(error));
785
+ if (i < maxRetries - 1) {
786
+ await sleep(delayMs * Math.pow(2, i));
787
+ }
788
+ }
789
+ }
790
+ throw lastError || new Error('Retry failed');
791
+ }
792
+ /**
793
+ * Debounce a function
794
+ * @param fn - Function to debounce
795
+ * @param ms - Debounce delay
796
+ * @returns Debounced function
797
+ */
798
+ export function debounce(fn, ms) {
799
+ let timeoutId = null;
800
+ return (...args) => {
801
+ if (timeoutId)
802
+ clearTimeout(timeoutId);
803
+ timeoutId = setTimeout(() => fn(...args), ms);
804
+ };
805
+ }
806
+ /**
807
+ * Throttle a function
808
+ * @param fn - Function to throttle
809
+ * @param ms - Throttle interval
810
+ * @returns Throttled function
811
+ */
812
+ export function throttle(fn, ms) {
813
+ let lastTime = 0;
814
+ return (...args) => {
815
+ const now = Date.now();
816
+ if (now - lastTime >= ms) {
817
+ lastTime = now;
818
+ fn(...args);
819
+ }
820
+ };
821
+ }
822
+ // ============================================================================
823
+ // Error Handling
824
+ // ============================================================================
825
+ /**
826
+ * Try-catch wrapper for synchronous functions
827
+ * @param fn - Function to wrap
828
+ * @returns Result object
829
+ */
830
+ export function tryCatch(fn) {
831
+ try {
832
+ return { success: true, data: fn() };
833
+ }
834
+ catch (error) {
835
+ return { success: false, error: error };
836
+ }
837
+ }
838
+ /**
839
+ * Try-catch wrapper for async functions
840
+ * @param fn - Async function to wrap
841
+ * @returns Result object
842
+ */
843
+ export async function tryCatchAsync(fn) {
844
+ try {
845
+ return { success: true, data: await fn() };
846
+ }
847
+ catch (error) {
848
+ return { success: false, error: error };
849
+ }
850
+ }
851
+ /**
852
+ * Create enhanced error with context
853
+ * @param message - Error message
854
+ * @param context - Error context
855
+ * @returns Enhanced error
856
+ */
857
+ export function createError(message, context) {
858
+ const error = new Error(message);
859
+ if (context) {
860
+ error.context = context;
861
+ }
862
+ return error;
863
+ }
864
+ //# sourceMappingURL=index.js.map