@juspay/neurolink 9.1.1 → 9.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +6 -0
- package/README.md +54 -7
- package/dist/agent/directTools.d.ts +3 -3
- package/dist/cli/commands/config.d.ts +6 -6
- package/dist/image-gen/ImageGenService.d.ts +143 -0
- package/dist/image-gen/ImageGenService.js +345 -0
- package/dist/image-gen/imageGenTools.d.ts +126 -0
- package/dist/image-gen/imageGenTools.js +304 -0
- package/dist/image-gen/index.d.ts +46 -0
- package/dist/image-gen/index.js +48 -0
- package/dist/image-gen/types.d.ts +237 -0
- package/dist/image-gen/types.js +24 -0
- package/dist/lib/agent/directTools.d.ts +3 -3
- package/dist/lib/image-gen/ImageGenService.d.ts +143 -0
- package/dist/lib/image-gen/ImageGenService.js +346 -0
- package/dist/lib/image-gen/imageGenTools.d.ts +126 -0
- package/dist/lib/image-gen/imageGenTools.js +305 -0
- package/dist/lib/image-gen/index.d.ts +46 -0
- package/dist/lib/image-gen/index.js +49 -0
- package/dist/lib/image-gen/types.d.ts +237 -0
- package/dist/lib/image-gen/types.js +25 -0
- package/dist/lib/processors/base/BaseFileProcessor.d.ts +273 -0
- package/dist/lib/processors/base/BaseFileProcessor.js +614 -0
- package/dist/lib/processors/base/index.d.ts +14 -0
- package/dist/lib/processors/base/index.js +20 -0
- package/dist/lib/processors/base/types.d.ts +593 -0
- package/dist/lib/processors/base/types.js +77 -0
- package/dist/lib/processors/cli/fileProcessorCli.d.ts +163 -0
- package/dist/lib/processors/cli/fileProcessorCli.js +389 -0
- package/dist/lib/processors/cli/index.d.ts +37 -0
- package/dist/lib/processors/cli/index.js +50 -0
- package/dist/lib/processors/code/ConfigProcessor.d.ts +171 -0
- package/dist/lib/processors/code/ConfigProcessor.js +401 -0
- package/dist/lib/processors/code/SourceCodeProcessor.d.ts +174 -0
- package/dist/lib/processors/code/SourceCodeProcessor.js +305 -0
- package/dist/lib/processors/code/index.d.ts +44 -0
- package/dist/lib/processors/code/index.js +61 -0
- package/dist/lib/processors/config/fileTypes.d.ts +283 -0
- package/dist/lib/processors/config/fileTypes.js +521 -0
- package/dist/lib/processors/config/index.d.ts +32 -0
- package/dist/lib/processors/config/index.js +93 -0
- package/dist/lib/processors/config/languageMap.d.ts +66 -0
- package/dist/lib/processors/config/languageMap.js +411 -0
- package/dist/lib/processors/config/mimeTypes.d.ts +376 -0
- package/dist/lib/processors/config/mimeTypes.js +339 -0
- package/dist/lib/processors/config/sizeLimits.d.ts +194 -0
- package/dist/lib/processors/config/sizeLimits.js +247 -0
- package/dist/lib/processors/data/JsonProcessor.d.ts +122 -0
- package/dist/lib/processors/data/JsonProcessor.js +204 -0
- package/dist/lib/processors/data/XmlProcessor.d.ts +160 -0
- package/dist/lib/processors/data/XmlProcessor.js +284 -0
- package/dist/lib/processors/data/YamlProcessor.d.ts +163 -0
- package/dist/lib/processors/data/YamlProcessor.js +295 -0
- package/dist/lib/processors/data/index.d.ts +49 -0
- package/dist/lib/processors/data/index.js +77 -0
- package/dist/lib/processors/document/ExcelProcessor.d.ts +238 -0
- package/dist/lib/processors/document/ExcelProcessor.js +520 -0
- package/dist/lib/processors/document/OpenDocumentProcessor.d.ts +69 -0
- package/dist/lib/processors/document/OpenDocumentProcessor.js +211 -0
- package/dist/lib/processors/document/RtfProcessor.d.ts +152 -0
- package/dist/lib/processors/document/RtfProcessor.js +362 -0
- package/dist/lib/processors/document/WordProcessor.d.ts +168 -0
- package/dist/lib/processors/document/WordProcessor.js +354 -0
- package/dist/lib/processors/document/index.d.ts +54 -0
- package/dist/lib/processors/document/index.js +91 -0
- package/dist/lib/processors/errors/FileErrorCode.d.ts +98 -0
- package/dist/lib/processors/errors/FileErrorCode.js +256 -0
- package/dist/lib/processors/errors/errorHelpers.d.ts +151 -0
- package/dist/lib/processors/errors/errorHelpers.js +379 -0
- package/dist/lib/processors/errors/errorSerializer.d.ts +139 -0
- package/dist/lib/processors/errors/errorSerializer.js +508 -0
- package/dist/lib/processors/errors/index.d.ts +46 -0
- package/dist/lib/processors/errors/index.js +50 -0
- package/dist/lib/processors/index.d.ts +76 -0
- package/dist/lib/processors/index.js +113 -0
- package/dist/lib/processors/integration/FileProcessorIntegration.d.ts +244 -0
- package/dist/lib/processors/integration/FileProcessorIntegration.js +273 -0
- package/dist/lib/processors/integration/index.d.ts +42 -0
- package/dist/lib/processors/integration/index.js +45 -0
- package/dist/lib/processors/markup/HtmlProcessor.d.ts +169 -0
- package/dist/lib/processors/markup/HtmlProcessor.js +250 -0
- package/dist/lib/processors/markup/MarkdownProcessor.d.ts +165 -0
- package/dist/lib/processors/markup/MarkdownProcessor.js +245 -0
- package/dist/lib/processors/markup/SvgProcessor.d.ts +156 -0
- package/dist/lib/processors/markup/SvgProcessor.js +241 -0
- package/dist/lib/processors/markup/TextProcessor.d.ts +135 -0
- package/dist/lib/processors/markup/TextProcessor.js +189 -0
- package/dist/lib/processors/markup/index.d.ts +66 -0
- package/dist/lib/processors/markup/index.js +103 -0
- package/dist/lib/processors/registry/ProcessorRegistry.d.ts +334 -0
- package/dist/lib/processors/registry/ProcessorRegistry.js +609 -0
- package/dist/lib/processors/registry/index.d.ts +12 -0
- package/dist/lib/processors/registry/index.js +17 -0
- package/dist/lib/processors/registry/types.d.ts +53 -0
- package/dist/lib/processors/registry/types.js +11 -0
- package/dist/lib/providers/sagemaker/language-model.d.ts +2 -2
- package/dist/lib/server/utils/validation.d.ts +6 -6
- package/dist/lib/types/fileTypes.d.ts +1 -1
- package/dist/lib/types/index.d.ts +25 -24
- package/dist/lib/types/index.js +21 -20
- package/dist/lib/types/modelTypes.d.ts +18 -18
- package/dist/lib/types/pptTypes.d.ts +14 -2
- package/dist/lib/types/pptTypes.js +16 -0
- package/dist/lib/utils/async/delay.d.ts +40 -0
- package/dist/lib/utils/async/delay.js +43 -0
- package/dist/lib/utils/async/index.d.ts +23 -0
- package/dist/lib/utils/async/index.js +24 -0
- package/dist/lib/utils/async/retry.d.ts +141 -0
- package/dist/lib/utils/async/retry.js +172 -0
- package/dist/lib/utils/async/withTimeout.d.ts +73 -0
- package/dist/lib/utils/async/withTimeout.js +97 -0
- package/dist/lib/utils/fileDetector.d.ts +7 -1
- package/dist/lib/utils/fileDetector.js +91 -18
- package/dist/lib/utils/json/extract.d.ts +103 -0
- package/dist/lib/utils/json/extract.js +249 -0
- package/dist/lib/utils/json/index.d.ts +36 -0
- package/dist/lib/utils/json/index.js +37 -0
- package/dist/lib/utils/json/safeParse.d.ts +137 -0
- package/dist/lib/utils/json/safeParse.js +191 -0
- package/dist/lib/utils/messageBuilder.d.ts +2 -2
- package/dist/lib/utils/messageBuilder.js +15 -7
- package/dist/lib/utils/sanitizers/filename.d.ts +137 -0
- package/dist/lib/utils/sanitizers/filename.js +366 -0
- package/dist/lib/utils/sanitizers/html.d.ts +170 -0
- package/dist/lib/utils/sanitizers/html.js +326 -0
- package/dist/lib/utils/sanitizers/index.d.ts +26 -0
- package/dist/lib/utils/sanitizers/index.js +30 -0
- package/dist/lib/utils/sanitizers/svg.d.ts +81 -0
- package/dist/lib/utils/sanitizers/svg.js +483 -0
- package/dist/processors/base/BaseFileProcessor.d.ts +273 -0
- package/dist/processors/base/BaseFileProcessor.js +613 -0
- package/dist/processors/base/index.d.ts +14 -0
- package/dist/processors/base/index.js +19 -0
- package/dist/processors/base/types.d.ts +593 -0
- package/dist/processors/base/types.js +76 -0
- package/dist/processors/cli/fileProcessorCli.d.ts +163 -0
- package/dist/processors/cli/fileProcessorCli.js +388 -0
- package/dist/processors/cli/index.d.ts +37 -0
- package/dist/processors/cli/index.js +49 -0
- package/dist/processors/code/ConfigProcessor.d.ts +171 -0
- package/dist/processors/code/ConfigProcessor.js +400 -0
- package/dist/processors/code/SourceCodeProcessor.d.ts +174 -0
- package/dist/processors/code/SourceCodeProcessor.js +304 -0
- package/dist/processors/code/index.d.ts +44 -0
- package/dist/processors/code/index.js +60 -0
- package/dist/processors/config/fileTypes.d.ts +283 -0
- package/dist/processors/config/fileTypes.js +520 -0
- package/dist/processors/config/index.d.ts +32 -0
- package/dist/processors/config/index.js +92 -0
- package/dist/processors/config/languageMap.d.ts +66 -0
- package/dist/processors/config/languageMap.js +410 -0
- package/dist/processors/config/mimeTypes.d.ts +376 -0
- package/dist/processors/config/mimeTypes.js +338 -0
- package/dist/processors/config/sizeLimits.d.ts +194 -0
- package/dist/processors/config/sizeLimits.js +246 -0
- package/dist/processors/data/JsonProcessor.d.ts +122 -0
- package/dist/processors/data/JsonProcessor.js +203 -0
- package/dist/processors/data/XmlProcessor.d.ts +160 -0
- package/dist/processors/data/XmlProcessor.js +283 -0
- package/dist/processors/data/YamlProcessor.d.ts +163 -0
- package/dist/processors/data/YamlProcessor.js +294 -0
- package/dist/processors/data/index.d.ts +49 -0
- package/dist/processors/data/index.js +76 -0
- package/dist/processors/document/ExcelProcessor.d.ts +238 -0
- package/dist/processors/document/ExcelProcessor.js +519 -0
- package/dist/processors/document/OpenDocumentProcessor.d.ts +69 -0
- package/dist/processors/document/OpenDocumentProcessor.js +210 -0
- package/dist/processors/document/RtfProcessor.d.ts +152 -0
- package/dist/processors/document/RtfProcessor.js +361 -0
- package/dist/processors/document/WordProcessor.d.ts +168 -0
- package/dist/processors/document/WordProcessor.js +353 -0
- package/dist/processors/document/index.d.ts +54 -0
- package/dist/processors/document/index.js +90 -0
- package/dist/processors/errors/FileErrorCode.d.ts +98 -0
- package/dist/processors/errors/FileErrorCode.js +255 -0
- package/dist/processors/errors/errorHelpers.d.ts +151 -0
- package/dist/processors/errors/errorHelpers.js +378 -0
- package/dist/processors/errors/errorSerializer.d.ts +139 -0
- package/dist/processors/errors/errorSerializer.js +507 -0
- package/dist/processors/errors/index.d.ts +46 -0
- package/dist/processors/errors/index.js +49 -0
- package/dist/processors/index.d.ts +76 -0
- package/dist/processors/index.js +112 -0
- package/dist/processors/integration/FileProcessorIntegration.d.ts +244 -0
- package/dist/processors/integration/FileProcessorIntegration.js +272 -0
- package/dist/processors/integration/index.d.ts +42 -0
- package/dist/processors/integration/index.js +44 -0
- package/dist/processors/markup/HtmlProcessor.d.ts +169 -0
- package/dist/processors/markup/HtmlProcessor.js +249 -0
- package/dist/processors/markup/MarkdownProcessor.d.ts +165 -0
- package/dist/processors/markup/MarkdownProcessor.js +244 -0
- package/dist/processors/markup/SvgProcessor.d.ts +156 -0
- package/dist/processors/markup/SvgProcessor.js +240 -0
- package/dist/processors/markup/TextProcessor.d.ts +135 -0
- package/dist/processors/markup/TextProcessor.js +188 -0
- package/dist/processors/markup/index.d.ts +66 -0
- package/dist/processors/markup/index.js +102 -0
- package/dist/processors/registry/ProcessorRegistry.d.ts +334 -0
- package/dist/processors/registry/ProcessorRegistry.js +608 -0
- package/dist/processors/registry/index.d.ts +12 -0
- package/dist/processors/registry/index.js +16 -0
- package/dist/processors/registry/types.d.ts +53 -0
- package/dist/processors/registry/types.js +10 -0
- package/dist/server/utils/validation.d.ts +6 -6
- package/dist/types/fileTypes.d.ts +1 -1
- package/dist/types/index.d.ts +25 -24
- package/dist/types/index.js +21 -20
- package/dist/types/modelTypes.d.ts +10 -10
- package/dist/types/pptTypes.d.ts +14 -2
- package/dist/types/pptTypes.js +16 -0
- package/dist/utils/async/delay.d.ts +40 -0
- package/dist/utils/async/delay.js +42 -0
- package/dist/utils/async/index.d.ts +23 -0
- package/dist/utils/async/index.js +23 -0
- package/dist/utils/async/retry.d.ts +141 -0
- package/dist/utils/async/retry.js +171 -0
- package/dist/utils/async/withTimeout.d.ts +73 -0
- package/dist/utils/async/withTimeout.js +96 -0
- package/dist/utils/fileDetector.d.ts +7 -1
- package/dist/utils/fileDetector.js +91 -18
- package/dist/utils/json/extract.d.ts +103 -0
- package/dist/utils/json/extract.js +248 -0
- package/dist/utils/json/index.d.ts +36 -0
- package/dist/utils/json/index.js +36 -0
- package/dist/utils/json/safeParse.d.ts +137 -0
- package/dist/utils/json/safeParse.js +190 -0
- package/dist/utils/messageBuilder.d.ts +2 -2
- package/dist/utils/messageBuilder.js +15 -7
- package/dist/utils/sanitizers/filename.d.ts +137 -0
- package/dist/utils/sanitizers/filename.js +365 -0
- package/dist/utils/sanitizers/html.d.ts +170 -0
- package/dist/utils/sanitizers/html.js +325 -0
- package/dist/utils/sanitizers/index.d.ts +26 -0
- package/dist/utils/sanitizers/index.js +29 -0
- package/dist/utils/sanitizers/svg.d.ts +81 -0
- package/dist/utils/sanitizers/svg.js +482 -0
- package/package.json +2 -2
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Retry Utilities
|
|
3
|
+
*
|
|
4
|
+
* Provides retry logic with exponential backoff for resilient async operations.
|
|
5
|
+
*/
|
|
6
|
+
import { delay } from "./delay.js";
|
|
7
|
+
/**
|
|
8
|
+
* Default retry configuration.
|
|
9
|
+
*/
|
|
10
|
+
export const DEFAULT_RETRY_OPTIONS = {
|
|
11
|
+
maxRetries: 3,
|
|
12
|
+
baseDelayMs: 1000,
|
|
13
|
+
maxDelayMs: 30000,
|
|
14
|
+
backoffMultiplier: 2,
|
|
15
|
+
};
|
|
16
|
+
/**
|
|
17
|
+
* Calculate exponential backoff delay with optional jitter.
|
|
18
|
+
*
|
|
19
|
+
* Uses the formula: min(baseDelay * 2^(attempt-1) + jitter, maxDelay)
|
|
20
|
+
*
|
|
21
|
+
* @param attempt - Current attempt number (1-based)
|
|
22
|
+
* @param baseDelayMs - Base delay in milliseconds
|
|
23
|
+
* @param maxDelayMs - Maximum delay cap in milliseconds
|
|
24
|
+
* @param addJitter - Whether to add random jitter (default: true)
|
|
25
|
+
* @returns Calculated delay in milliseconds
|
|
26
|
+
*
|
|
27
|
+
* @example
|
|
28
|
+
* ```typescript
|
|
29
|
+
* // Without jitter
|
|
30
|
+
* calculateBackoff(1, 1000, 30000, false); // 1000ms
|
|
31
|
+
* calculateBackoff(2, 1000, 30000, false); // 2000ms
|
|
32
|
+
* calculateBackoff(3, 1000, 30000, false); // 4000ms
|
|
33
|
+
*
|
|
34
|
+
* // With jitter (adds up to 10% random delay)
|
|
35
|
+
* calculateBackoff(3, 1000, 30000, true); // ~4000-4400ms
|
|
36
|
+
* ```
|
|
37
|
+
*/
|
|
38
|
+
export function calculateBackoff(attempt, baseDelayMs, maxDelayMs, addJitter = true) {
|
|
39
|
+
const exponentialDelay = baseDelayMs * 2 ** (attempt - 1);
|
|
40
|
+
if (addJitter) {
|
|
41
|
+
// Add up to 10% jitter to prevent thundering herd
|
|
42
|
+
const jitter = Math.random() * 0.1 * exponentialDelay;
|
|
43
|
+
return Math.min(exponentialDelay + jitter, maxDelayMs);
|
|
44
|
+
}
|
|
45
|
+
return Math.min(exponentialDelay, maxDelayMs);
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Error thrown when all retry attempts are exhausted.
|
|
49
|
+
*/
|
|
50
|
+
export class RetryExhaustedError extends Error {
|
|
51
|
+
attempts;
|
|
52
|
+
lastError;
|
|
53
|
+
/**
|
|
54
|
+
* Creates a new RetryExhaustedError.
|
|
55
|
+
*
|
|
56
|
+
* @param message - Error message
|
|
57
|
+
* @param attempts - Total number of attempts made
|
|
58
|
+
* @param lastError - The last error that caused the final failure
|
|
59
|
+
*/
|
|
60
|
+
constructor(message, attempts, lastError) {
|
|
61
|
+
super(message);
|
|
62
|
+
this.attempts = attempts;
|
|
63
|
+
this.lastError = lastError;
|
|
64
|
+
this.name = "RetryExhaustedError";
|
|
65
|
+
if (Error.captureStackTrace) {
|
|
66
|
+
Error.captureStackTrace(this, RetryExhaustedError);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Retry an async function with exponential backoff.
|
|
72
|
+
*
|
|
73
|
+
* Executes the provided function and retries on failure according to
|
|
74
|
+
* the specified options. Uses exponential backoff between retries.
|
|
75
|
+
*
|
|
76
|
+
* @param fn - Async function to execute
|
|
77
|
+
* @param options - Retry configuration (merged with defaults)
|
|
78
|
+
* @returns Promise that resolves with the function result
|
|
79
|
+
* @throws The last error if all retries are exhausted
|
|
80
|
+
*
|
|
81
|
+
* @example
|
|
82
|
+
* ```typescript
|
|
83
|
+
* // Basic usage with defaults
|
|
84
|
+
* const data = await retry(() => fetchFromAPI());
|
|
85
|
+
* ```
|
|
86
|
+
*
|
|
87
|
+
* @example
|
|
88
|
+
* ```typescript
|
|
89
|
+
* // With custom options
|
|
90
|
+
* const data = await retry(
|
|
91
|
+
* () => fetchFromAPI(),
|
|
92
|
+
* {
|
|
93
|
+
* maxRetries: 5,
|
|
94
|
+
* baseDelayMs: 500,
|
|
95
|
+
* maxDelayMs: 10000,
|
|
96
|
+
* onRetry: (err, attempt, delay) => {
|
|
97
|
+
* console.log(`Retry ${attempt} after ${delay}ms: ${err.message}`);
|
|
98
|
+
* },
|
|
99
|
+
* shouldRetry: (err) => {
|
|
100
|
+
* // Only retry on network errors
|
|
101
|
+
* return err.name === 'NetworkError';
|
|
102
|
+
* }
|
|
103
|
+
* }
|
|
104
|
+
* );
|
|
105
|
+
* ```
|
|
106
|
+
*/
|
|
107
|
+
export async function retry(fn, options = {}) {
|
|
108
|
+
const config = {
|
|
109
|
+
...DEFAULT_RETRY_OPTIONS,
|
|
110
|
+
...options,
|
|
111
|
+
};
|
|
112
|
+
const { maxRetries, baseDelayMs, maxDelayMs, backoffMultiplier = 2, shouldRetry = () => true, onRetry, } = config;
|
|
113
|
+
let lastError = new Error("Retry failed");
|
|
114
|
+
let currentDelay = baseDelayMs;
|
|
115
|
+
// Total attempts = initial attempt + retries
|
|
116
|
+
const totalAttempts = maxRetries + 1;
|
|
117
|
+
for (let attempt = 1; attempt <= totalAttempts; attempt++) {
|
|
118
|
+
try {
|
|
119
|
+
return await fn();
|
|
120
|
+
}
|
|
121
|
+
catch (error) {
|
|
122
|
+
const err = error instanceof Error ? error : new Error(String(error));
|
|
123
|
+
lastError = err;
|
|
124
|
+
// Check if we've exhausted all retries
|
|
125
|
+
if (attempt >= totalAttempts) {
|
|
126
|
+
throw new RetryExhaustedError(`All ${totalAttempts} retry attempts exhausted`, totalAttempts, err);
|
|
127
|
+
}
|
|
128
|
+
// Check if we should retry this error
|
|
129
|
+
if (!shouldRetry(err, attempt)) {
|
|
130
|
+
throw err;
|
|
131
|
+
}
|
|
132
|
+
// Calculate delay with exponential backoff (capped at maxDelay)
|
|
133
|
+
const delayMs = Math.min(currentDelay, maxDelayMs);
|
|
134
|
+
// Notify about retry
|
|
135
|
+
if (onRetry) {
|
|
136
|
+
onRetry(err, attempt, delayMs);
|
|
137
|
+
}
|
|
138
|
+
// Wait before next attempt
|
|
139
|
+
await delay(delayMs);
|
|
140
|
+
// Increase delay for next iteration
|
|
141
|
+
currentDelay = currentDelay * backoffMultiplier;
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
// This should never be reached, but TypeScript needs it
|
|
145
|
+
throw new RetryExhaustedError(`All ${totalAttempts} retry attempts exhausted`, totalAttempts, lastError || new Error("Unknown retry failure"));
|
|
146
|
+
}
|
|
147
|
+
/**
|
|
148
|
+
* Create a retry wrapper with pre-configured options.
|
|
149
|
+
*
|
|
150
|
+
* Useful for creating reusable retry strategies.
|
|
151
|
+
*
|
|
152
|
+
* @param defaultOptions - Default retry options for the wrapper
|
|
153
|
+
* @returns A retry function with the specified defaults
|
|
154
|
+
*
|
|
155
|
+
* @example
|
|
156
|
+
* ```typescript
|
|
157
|
+
* const apiRetry = createRetry({
|
|
158
|
+
* maxRetries: 5,
|
|
159
|
+
* baseDelayMs: 100,
|
|
160
|
+
* onRetry: (err, attempt) => logger.warn(`API retry ${attempt}`)
|
|
161
|
+
* });
|
|
162
|
+
*
|
|
163
|
+
* // Use the configured retry
|
|
164
|
+
* const data = await apiRetry(() => fetchFromAPI());
|
|
165
|
+
* ```
|
|
166
|
+
*/
|
|
167
|
+
export function createRetry(defaultOptions) {
|
|
168
|
+
return (fn, overrideOptions) => {
|
|
169
|
+
return retry(fn, { ...defaultOptions, ...overrideOptions });
|
|
170
|
+
};
|
|
171
|
+
}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Timeout Utilities
|
|
3
|
+
*
|
|
4
|
+
* Wrapper functions for adding timeout protection to async operations.
|
|
5
|
+
*/
|
|
6
|
+
/**
|
|
7
|
+
* Error thrown when an operation times out.
|
|
8
|
+
*/
|
|
9
|
+
export declare class TimeoutError extends Error {
|
|
10
|
+
readonly timeoutMs: number;
|
|
11
|
+
/**
|
|
12
|
+
* Creates a new TimeoutError.
|
|
13
|
+
*
|
|
14
|
+
* @param message - Error message describing the timeout
|
|
15
|
+
* @param timeoutMs - The timeout duration that was exceeded
|
|
16
|
+
*/
|
|
17
|
+
constructor(message: string, timeoutMs: number);
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Execute a promise with timeout protection.
|
|
21
|
+
*
|
|
22
|
+
* Wraps a promise and rejects with a TimeoutError if the operation
|
|
23
|
+
* takes longer than the specified duration.
|
|
24
|
+
*
|
|
25
|
+
* @param promise - The promise to wrap with timeout
|
|
26
|
+
* @param ms - Maximum time to wait in milliseconds
|
|
27
|
+
* @param message - Optional custom error message for timeout
|
|
28
|
+
* @returns Promise that resolves with the result or rejects on timeout
|
|
29
|
+
* @throws {TimeoutError} If the operation exceeds the timeout duration
|
|
30
|
+
*
|
|
31
|
+
* @example
|
|
32
|
+
* ```typescript
|
|
33
|
+
* const result = await withTimeout(
|
|
34
|
+
* fetchData(),
|
|
35
|
+
* 5000,
|
|
36
|
+
* 'Data fetch timed out'
|
|
37
|
+
* );
|
|
38
|
+
* ```
|
|
39
|
+
*
|
|
40
|
+
* @example
|
|
41
|
+
* ```typescript
|
|
42
|
+
* try {
|
|
43
|
+
* const data = await withTimeout(slowOperation(), 3000);
|
|
44
|
+
* } catch (error) {
|
|
45
|
+
* if (error instanceof TimeoutError) {
|
|
46
|
+
* console.log(`Timed out after ${error.timeoutMs}ms`);
|
|
47
|
+
* }
|
|
48
|
+
* }
|
|
49
|
+
* ```
|
|
50
|
+
*/
|
|
51
|
+
export declare function withTimeout<T>(promise: Promise<T>, ms: number, message?: string): Promise<T>;
|
|
52
|
+
/**
|
|
53
|
+
* Execute a function with timeout protection.
|
|
54
|
+
*
|
|
55
|
+
* Alternative signature that accepts a function instead of a promise,
|
|
56
|
+
* useful when you want to delay starting the operation.
|
|
57
|
+
*
|
|
58
|
+
* @param fn - Async function to execute
|
|
59
|
+
* @param ms - Maximum time to wait in milliseconds
|
|
60
|
+
* @param message - Optional custom error message for timeout
|
|
61
|
+
* @returns Promise that resolves with the function result or rejects on timeout
|
|
62
|
+
* @throws {TimeoutError} If the operation exceeds the timeout duration
|
|
63
|
+
*
|
|
64
|
+
* @example
|
|
65
|
+
* ```typescript
|
|
66
|
+
* const result = await withTimeoutFn(
|
|
67
|
+
* () => fetchData(),
|
|
68
|
+
* 5000,
|
|
69
|
+
* 'Data fetch timed out'
|
|
70
|
+
* );
|
|
71
|
+
* ```
|
|
72
|
+
*/
|
|
73
|
+
export declare function withTimeoutFn<T>(fn: () => Promise<T>, ms: number, message?: string): Promise<T>;
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Timeout Utilities
|
|
3
|
+
*
|
|
4
|
+
* Wrapper functions for adding timeout protection to async operations.
|
|
5
|
+
*/
|
|
6
|
+
/**
|
|
7
|
+
* Error thrown when an operation times out.
|
|
8
|
+
*/
|
|
9
|
+
export class TimeoutError extends Error {
|
|
10
|
+
timeoutMs;
|
|
11
|
+
/**
|
|
12
|
+
* Creates a new TimeoutError.
|
|
13
|
+
*
|
|
14
|
+
* @param message - Error message describing the timeout
|
|
15
|
+
* @param timeoutMs - The timeout duration that was exceeded
|
|
16
|
+
*/
|
|
17
|
+
constructor(message, timeoutMs) {
|
|
18
|
+
super(message);
|
|
19
|
+
this.timeoutMs = timeoutMs;
|
|
20
|
+
this.name = "TimeoutError";
|
|
21
|
+
// Maintains proper stack trace for where error was thrown (V8 engines)
|
|
22
|
+
if (Error.captureStackTrace) {
|
|
23
|
+
Error.captureStackTrace(this, TimeoutError);
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Execute a promise with timeout protection.
|
|
29
|
+
*
|
|
30
|
+
* Wraps a promise and rejects with a TimeoutError if the operation
|
|
31
|
+
* takes longer than the specified duration.
|
|
32
|
+
*
|
|
33
|
+
* @param promise - The promise to wrap with timeout
|
|
34
|
+
* @param ms - Maximum time to wait in milliseconds
|
|
35
|
+
* @param message - Optional custom error message for timeout
|
|
36
|
+
* @returns Promise that resolves with the result or rejects on timeout
|
|
37
|
+
* @throws {TimeoutError} If the operation exceeds the timeout duration
|
|
38
|
+
*
|
|
39
|
+
* @example
|
|
40
|
+
* ```typescript
|
|
41
|
+
* const result = await withTimeout(
|
|
42
|
+
* fetchData(),
|
|
43
|
+
* 5000,
|
|
44
|
+
* 'Data fetch timed out'
|
|
45
|
+
* );
|
|
46
|
+
* ```
|
|
47
|
+
*
|
|
48
|
+
* @example
|
|
49
|
+
* ```typescript
|
|
50
|
+
* try {
|
|
51
|
+
* const data = await withTimeout(slowOperation(), 3000);
|
|
52
|
+
* } catch (error) {
|
|
53
|
+
* if (error instanceof TimeoutError) {
|
|
54
|
+
* console.log(`Timed out after ${error.timeoutMs}ms`);
|
|
55
|
+
* }
|
|
56
|
+
* }
|
|
57
|
+
* ```
|
|
58
|
+
*/
|
|
59
|
+
export async function withTimeout(promise, ms, message) {
|
|
60
|
+
let timeoutId;
|
|
61
|
+
const timeoutPromise = new Promise((_, reject) => {
|
|
62
|
+
timeoutId = setTimeout(() => {
|
|
63
|
+
reject(new TimeoutError(message || `Operation timed out after ${ms}ms`, ms));
|
|
64
|
+
}, ms);
|
|
65
|
+
});
|
|
66
|
+
try {
|
|
67
|
+
return await Promise.race([promise, timeoutPromise]);
|
|
68
|
+
}
|
|
69
|
+
finally {
|
|
70
|
+
clearTimeout(timeoutId);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Execute a function with timeout protection.
|
|
75
|
+
*
|
|
76
|
+
* Alternative signature that accepts a function instead of a promise,
|
|
77
|
+
* useful when you want to delay starting the operation.
|
|
78
|
+
*
|
|
79
|
+
* @param fn - Async function to execute
|
|
80
|
+
* @param ms - Maximum time to wait in milliseconds
|
|
81
|
+
* @param message - Optional custom error message for timeout
|
|
82
|
+
* @returns Promise that resolves with the function result or rejects on timeout
|
|
83
|
+
* @throws {TimeoutError} If the operation exceeds the timeout duration
|
|
84
|
+
*
|
|
85
|
+
* @example
|
|
86
|
+
* ```typescript
|
|
87
|
+
* const result = await withTimeoutFn(
|
|
88
|
+
* () => fetchData(),
|
|
89
|
+
* 5000,
|
|
90
|
+
* 'Data fetch timed out'
|
|
91
|
+
* );
|
|
92
|
+
* ```
|
|
93
|
+
*/
|
|
94
|
+
export async function withTimeoutFn(fn, ms, message) {
|
|
95
|
+
return withTimeout(fn(), ms, message);
|
|
96
|
+
}
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
* Centralized file detection for all multimodal file types
|
|
4
4
|
* Uses multi-strategy approach for reliable type identification
|
|
5
5
|
*/
|
|
6
|
-
import type { FileInput, FileProcessingResult
|
|
6
|
+
import type { FileDetectorOptions, FileInput, FileProcessingResult } from "../types/fileTypes.js";
|
|
7
7
|
/**
|
|
8
8
|
* Centralized file type detection and processing
|
|
9
9
|
*
|
|
@@ -69,6 +69,12 @@ export declare class FileDetector {
|
|
|
69
69
|
* Route to appropriate processor
|
|
70
70
|
*/
|
|
71
71
|
private static processFile;
|
|
72
|
+
/**
|
|
73
|
+
* Process SVG file as text content
|
|
74
|
+
* Uses SvgProcessor for security sanitization (removes XSS vectors)
|
|
75
|
+
* Returns sanitized SVG markup as text for AI analysis
|
|
76
|
+
*/
|
|
77
|
+
private static processSvgAsText;
|
|
72
78
|
/**
|
|
73
79
|
* Load file from URL with automatic retry on transient network errors
|
|
74
80
|
*/
|
|
@@ -3,11 +3,11 @@
|
|
|
3
3
|
* Centralized file detection for all multimodal file types
|
|
4
4
|
* Uses multi-strategy approach for reliable type identification
|
|
5
5
|
*/
|
|
6
|
-
import { request, getGlobalDispatcher, interceptors } from "undici";
|
|
7
6
|
import { readFile, stat } from "fs/promises";
|
|
8
|
-
import {
|
|
7
|
+
import { getGlobalDispatcher, interceptors, request } from "undici";
|
|
9
8
|
import { CSVProcessor } from "./csvProcessor.js";
|
|
10
9
|
import { ImageProcessor } from "./imageProcessor.js";
|
|
10
|
+
import { logger } from "./logger.js";
|
|
11
11
|
import { PDFProcessor } from "./pdfProcessor.js";
|
|
12
12
|
/**
|
|
13
13
|
* Default retry configuration constants
|
|
@@ -106,7 +106,7 @@ async function withRetry(operation, options = {}) {
|
|
|
106
106
|
throw error;
|
|
107
107
|
}
|
|
108
108
|
// Calculate exponential backoff delay
|
|
109
|
-
const delay = retryDelay *
|
|
109
|
+
const delay = retryDelay * 2 ** attempt;
|
|
110
110
|
logger.debug("Retrying network operation after transient error", {
|
|
111
111
|
attempt: attempt + 1,
|
|
112
112
|
maxRetries,
|
|
@@ -186,7 +186,7 @@ export class FileDetector {
|
|
|
186
186
|
* @returns Processed file result with type and content
|
|
187
187
|
*/
|
|
188
188
|
static async detectAndProcess(input, options) {
|
|
189
|
-
const detection = await
|
|
189
|
+
const detection = await FileDetector.detect(input, options);
|
|
190
190
|
// FD-018: Comprehensive fallback parsing for extension-less files
|
|
191
191
|
// When file detection returns "unknown" or doesn't match allowedTypes,
|
|
192
192
|
// attempt parsing for each allowed type before failing. This handles cases like Slack
|
|
@@ -194,12 +194,12 @@ export class FileDetector {
|
|
|
194
194
|
if (options?.allowedTypes &&
|
|
195
195
|
!options.allowedTypes.includes(detection.type)) {
|
|
196
196
|
// Try fallback parsing for both "unknown" types and when detection doesn't match allowed types
|
|
197
|
-
const content = await
|
|
197
|
+
const content = await FileDetector.loadContent(input, detection, options);
|
|
198
198
|
const errors = [];
|
|
199
199
|
// Try each allowed type in order of specificity
|
|
200
200
|
for (const allowedType of options.allowedTypes) {
|
|
201
201
|
try {
|
|
202
|
-
const result = await
|
|
202
|
+
const result = await FileDetector.tryFallbackParsing(content, allowedType, options);
|
|
203
203
|
if (result) {
|
|
204
204
|
logger.info(`[FileDetector] ✅ ${allowedType.toUpperCase()} fallback successful`);
|
|
205
205
|
return result;
|
|
@@ -214,10 +214,10 @@ export class FileDetector {
|
|
|
214
214
|
// All fallbacks failed
|
|
215
215
|
throw new Error(`File type detection failed and all fallback parsing attempts failed. Original detection: ${detection.type}. Attempted types: ${options.allowedTypes.join(", ")}. Errors: ${errors.join("; ")}`);
|
|
216
216
|
}
|
|
217
|
-
const content = await
|
|
217
|
+
const content = await FileDetector.loadContent(input, detection, options);
|
|
218
218
|
// Extract CSV-specific options from FileDetectorOptions
|
|
219
219
|
const csvOptions = options?.csvOptions;
|
|
220
|
-
return await
|
|
220
|
+
return await FileDetector.processFile(content, detection, csvOptions, options?.provider);
|
|
221
221
|
}
|
|
222
222
|
/**
|
|
223
223
|
* Try fallback parsing for a specific file type
|
|
@@ -237,11 +237,11 @@ export class FileDetector {
|
|
|
237
237
|
// Try text parsing - check if content is valid UTF-8 text
|
|
238
238
|
const textContent = content.toString("utf-8");
|
|
239
239
|
// Validate it's actually text (no null bytes, mostly printable)
|
|
240
|
-
if (
|
|
240
|
+
if (FileDetector.isValidText(textContent)) {
|
|
241
241
|
return {
|
|
242
242
|
type: "text",
|
|
243
243
|
content: textContent,
|
|
244
|
-
mimeType:
|
|
244
|
+
mimeType: FileDetector.guessTextMimeType(textContent),
|
|
245
245
|
metadata: {
|
|
246
246
|
confidence: 70,
|
|
247
247
|
size: content.length,
|
|
@@ -307,7 +307,7 @@ export class FileDetector {
|
|
|
307
307
|
}
|
|
308
308
|
}
|
|
309
309
|
// Check for XML/HTML using stricter detection
|
|
310
|
-
if (
|
|
310
|
+
if (FileDetector.looksLikeXMLStrict(trimmed)) {
|
|
311
311
|
const isHTML = trimmed.includes("<!DOCTYPE html") ||
|
|
312
312
|
trimmed.toLowerCase().includes("<html") ||
|
|
313
313
|
trimmed.includes("<head") ||
|
|
@@ -315,7 +315,7 @@ export class FileDetector {
|
|
|
315
315
|
return isHTML ? "text/html" : "application/xml";
|
|
316
316
|
}
|
|
317
317
|
// Check for YAML using robust multi-indicator detection
|
|
318
|
-
if (
|
|
318
|
+
if (FileDetector.looksLikeYAMLStrict(trimmed)) {
|
|
319
319
|
return "application/yaml";
|
|
320
320
|
}
|
|
321
321
|
// Default to plain text
|
|
@@ -427,13 +427,13 @@ export class FileDetector {
|
|
|
427
427
|
}
|
|
428
428
|
switch (source) {
|
|
429
429
|
case "url":
|
|
430
|
-
return await
|
|
430
|
+
return await FileDetector.loadFromURL(input, options);
|
|
431
431
|
case "path":
|
|
432
|
-
return await
|
|
432
|
+
return await FileDetector.loadFromPath(input, options);
|
|
433
433
|
case "buffer":
|
|
434
434
|
return input;
|
|
435
435
|
case "datauri":
|
|
436
|
-
return
|
|
436
|
+
return FileDetector.loadFromDataURI(input);
|
|
437
437
|
default:
|
|
438
438
|
throw new Error(`Unknown source: ${source}`);
|
|
439
439
|
}
|
|
@@ -454,6 +454,10 @@ export class FileDetector {
|
|
|
454
454
|
return await ImageProcessor.process(content);
|
|
455
455
|
case "pdf":
|
|
456
456
|
return await PDFProcessor.process(content, { provider });
|
|
457
|
+
case "svg":
|
|
458
|
+
// SVG is processed as text content (sanitized XML markup)
|
|
459
|
+
// AI providers don't support SVG as image format, so we extract text content
|
|
460
|
+
return await FileDetector.processSvgAsText(content, detection);
|
|
457
461
|
case "text":
|
|
458
462
|
return {
|
|
459
463
|
type: "text",
|
|
@@ -465,12 +469,74 @@ export class FileDetector {
|
|
|
465
469
|
throw new Error(`Unsupported file type: ${detection.type}`);
|
|
466
470
|
}
|
|
467
471
|
}
|
|
472
|
+
/**
|
|
473
|
+
* Process SVG file as text content
|
|
474
|
+
* Uses SvgProcessor for security sanitization (removes XSS vectors)
|
|
475
|
+
* Returns sanitized SVG markup as text for AI analysis
|
|
476
|
+
*/
|
|
477
|
+
static async processSvgAsText(content, detection) {
|
|
478
|
+
try {
|
|
479
|
+
// Dynamic import to avoid circular dependencies
|
|
480
|
+
const { processSvg } = await import("../processors/markup/SvgProcessor.js");
|
|
481
|
+
const result = await processSvg({
|
|
482
|
+
id: "svg-file",
|
|
483
|
+
name: detection.metadata.filename || "image.svg",
|
|
484
|
+
mimetype: "image/svg+xml",
|
|
485
|
+
size: content.length,
|
|
486
|
+
buffer: content,
|
|
487
|
+
});
|
|
488
|
+
if (result.success && result.data) {
|
|
489
|
+
logger.info(`[FileDetector] SVG processed as text: ${detection.metadata.filename || "image.svg"}`);
|
|
490
|
+
return {
|
|
491
|
+
type: "svg",
|
|
492
|
+
content: result.data.textContent, // Sanitized SVG content
|
|
493
|
+
mimeType: "image/svg+xml",
|
|
494
|
+
metadata: {
|
|
495
|
+
confidence: detection.metadata.confidence,
|
|
496
|
+
size: content.length,
|
|
497
|
+
filename: detection.metadata.filename,
|
|
498
|
+
extension: detection.extension,
|
|
499
|
+
},
|
|
500
|
+
};
|
|
501
|
+
}
|
|
502
|
+
else {
|
|
503
|
+
// Fail closed: return safe empty SVG instead of raw unsanitized content
|
|
504
|
+
logger.warn(`[FileDetector] SVG processor failed, returning safe empty SVG: ${result.error?.userMessage}`);
|
|
505
|
+
return {
|
|
506
|
+
type: "svg",
|
|
507
|
+
content: '<svg xmlns="http://www.w3.org/2000/svg"></svg>',
|
|
508
|
+
mimeType: "image/svg+xml",
|
|
509
|
+
metadata: {
|
|
510
|
+
confidence: detection.metadata.confidence,
|
|
511
|
+
size: content.length,
|
|
512
|
+
filename: detection.metadata.filename,
|
|
513
|
+
extension: detection.extension,
|
|
514
|
+
},
|
|
515
|
+
};
|
|
516
|
+
}
|
|
517
|
+
}
|
|
518
|
+
catch (error) {
|
|
519
|
+
// Fail closed: return safe empty SVG instead of raw unsanitized content
|
|
520
|
+
logger.warn(`[FileDetector] SVG processor not available, returning safe empty SVG: ${error instanceof Error ? error.message : String(error)}`);
|
|
521
|
+
return {
|
|
522
|
+
type: "svg",
|
|
523
|
+
content: '<svg xmlns="http://www.w3.org/2000/svg"></svg>',
|
|
524
|
+
mimeType: "image/svg+xml",
|
|
525
|
+
metadata: {
|
|
526
|
+
confidence: detection.metadata.confidence,
|
|
527
|
+
size: content.length,
|
|
528
|
+
filename: detection.metadata.filename,
|
|
529
|
+
extension: detection.extension,
|
|
530
|
+
},
|
|
531
|
+
};
|
|
532
|
+
}
|
|
533
|
+
}
|
|
468
534
|
/**
|
|
469
535
|
* Load file from URL with automatic retry on transient network errors
|
|
470
536
|
*/
|
|
471
537
|
static async loadFromURL(url, options) {
|
|
472
538
|
const maxSize = options?.maxSize || 10 * 1024 * 1024;
|
|
473
|
-
const timeout = options?.timeout ||
|
|
539
|
+
const timeout = options?.timeout || FileDetector.DEFAULT_NETWORK_TIMEOUT;
|
|
474
540
|
const maxRetries = options?.maxRetries ?? DEFAULT_MAX_RETRIES;
|
|
475
541
|
const retryDelay = options?.retryDelay ?? DEFAULT_RETRY_DELAY;
|
|
476
542
|
return withRetry(async () => {
|
|
@@ -627,6 +693,11 @@ class MimeTypeStrategy {
|
|
|
627
693
|
if (mime.includes("text/tab-separated-values")) {
|
|
628
694
|
return "csv";
|
|
629
695
|
}
|
|
696
|
+
// SVG is processed as text/markup, NOT as image
|
|
697
|
+
// Must check before generic image/ check
|
|
698
|
+
if (mime.includes("image/svg+xml")) {
|
|
699
|
+
return "svg";
|
|
700
|
+
}
|
|
630
701
|
if (mime.includes("image/")) {
|
|
631
702
|
return "image";
|
|
632
703
|
}
|
|
@@ -675,7 +746,9 @@ class ExtensionStrategy {
|
|
|
675
746
|
bmp: "image",
|
|
676
747
|
tiff: "image",
|
|
677
748
|
tif: "image",
|
|
678
|
-
|
|
749
|
+
// SVG is handled as text/markup, NOT as image
|
|
750
|
+
// AI providers don't support SVG format, so we process it as sanitized text
|
|
751
|
+
svg: "svg",
|
|
679
752
|
avif: "image",
|
|
680
753
|
pdf: "pdf",
|
|
681
754
|
txt: "text",
|
|
@@ -865,7 +938,7 @@ class ContentHeuristicStrategy {
|
|
|
865
938
|
// (data values like IDs, codes, numbers - not varied content)
|
|
866
939
|
const lengths = lines.map((l) => l.length);
|
|
867
940
|
const avgLength = lengths.reduce((a, b) => a + b, 0) / lengths.length;
|
|
868
|
-
const variance = lengths.reduce((sum, len) => sum +
|
|
941
|
+
const variance = lengths.reduce((sum, len) => sum + (len - avgLength) ** 2, 0) /
|
|
869
942
|
lengths.length;
|
|
870
943
|
const stdDev = Math.sqrt(variance);
|
|
871
944
|
// Single-column CSVs can contain varied data (names, cities, emails, etc.)
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* JSON Extraction Utilities
|
|
3
|
+
*
|
|
4
|
+
* Utilities for extracting JSON from mixed text content.
|
|
5
|
+
* Particularly useful for parsing AI responses that contain JSON within prose.
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* Extract JSON string from text that may contain surrounding content.
|
|
9
|
+
*
|
|
10
|
+
* Searches for valid JSON in the following order:
|
|
11
|
+
* 1. Direct parse of the entire text
|
|
12
|
+
* 2. JSON within markdown code blocks (```json ... ``` or ``` ... ```)
|
|
13
|
+
* 3. JSON object pattern ({ ... })
|
|
14
|
+
* 4. JSON array pattern ([ ... ])
|
|
15
|
+
*
|
|
16
|
+
* @param text - Text that may contain JSON
|
|
17
|
+
* @returns Extracted JSON string or null if none found
|
|
18
|
+
*
|
|
19
|
+
* @example
|
|
20
|
+
* ```typescript
|
|
21
|
+
* const response = "Here's the data: {\"name\": \"test\"} Let me know if you need more.";
|
|
22
|
+
* const json = extractJsonStringFromText(response);
|
|
23
|
+
* // Returns: '{"name": "test"}'
|
|
24
|
+
* ```
|
|
25
|
+
*/
|
|
26
|
+
export declare function extractJsonStringFromText(text: string): string | null;
|
|
27
|
+
/**
|
|
28
|
+
* Extract and parse JSON from mixed text content.
|
|
29
|
+
*
|
|
30
|
+
* Useful for parsing AI responses that contain JSON within prose.
|
|
31
|
+
* Combines extraction and parsing in one step.
|
|
32
|
+
*
|
|
33
|
+
* @param text - Text that may contain JSON
|
|
34
|
+
* @returns Parsed JSON value or null if not found/invalid
|
|
35
|
+
*
|
|
36
|
+
* @example
|
|
37
|
+
* ```typescript
|
|
38
|
+
* const response = `
|
|
39
|
+
* Here is your configuration:
|
|
40
|
+
* \`\`\`json
|
|
41
|
+
* {"theme": "dark", "fontSize": 14}
|
|
42
|
+
* \`\`\`
|
|
43
|
+
* Let me know if you need changes.
|
|
44
|
+
* `;
|
|
45
|
+
* const config = extractJsonFromText(response);
|
|
46
|
+
* // Returns: { theme: "dark", fontSize: 14 }
|
|
47
|
+
* ```
|
|
48
|
+
*/
|
|
49
|
+
export declare function extractJsonFromText(text: string): unknown | null;
|
|
50
|
+
export type { JsonTypeGuard } from "../../processors/base/types.js";
|
|
51
|
+
import type { JsonTypeGuard } from "../../processors/base/types.js";
|
|
52
|
+
/**
|
|
53
|
+
* Parse JSON from text with optional type validation.
|
|
54
|
+
*
|
|
55
|
+
* Extracts JSON from text and optionally validates it against a type guard.
|
|
56
|
+
* Useful when you need type-safe parsing of AI responses.
|
|
57
|
+
*
|
|
58
|
+
* @param text - Text that may contain JSON
|
|
59
|
+
* @param validator - Optional type guard to validate the parsed result
|
|
60
|
+
* @returns Parsed and validated JSON or null if not found/invalid/fails validation
|
|
61
|
+
*
|
|
62
|
+
* @example
|
|
63
|
+
* ```typescript
|
|
64
|
+
* interface UserConfig {
|
|
65
|
+
* theme: string;
|
|
66
|
+
* fontSize: number;
|
|
67
|
+
* }
|
|
68
|
+
*
|
|
69
|
+
* function isUserConfig(obj: unknown): obj is UserConfig {
|
|
70
|
+
* return (
|
|
71
|
+
* typeof obj === 'object' &&
|
|
72
|
+
* obj !== null &&
|
|
73
|
+
* 'theme' in obj &&
|
|
74
|
+
* 'fontSize' in obj &&
|
|
75
|
+
* typeof (obj as UserConfig).theme === 'string' &&
|
|
76
|
+
* typeof (obj as UserConfig).fontSize === 'number'
|
|
77
|
+
* );
|
|
78
|
+
* }
|
|
79
|
+
*
|
|
80
|
+
* const config = parseJsonFromText<UserConfig>(aiResponse, isUserConfig);
|
|
81
|
+
* if (config) {
|
|
82
|
+
* // config is typed as UserConfig
|
|
83
|
+
* console.log(config.theme, config.fontSize);
|
|
84
|
+
* }
|
|
85
|
+
* ```
|
|
86
|
+
*/
|
|
87
|
+
export declare function parseJsonFromText<T>(text: string, validator?: JsonTypeGuard<T>): T | null;
|
|
88
|
+
/**
|
|
89
|
+
* Extract all JSON objects/arrays from text.
|
|
90
|
+
*
|
|
91
|
+
* Useful when text contains multiple JSON blocks.
|
|
92
|
+
*
|
|
93
|
+
* @param text - Text that may contain multiple JSON values
|
|
94
|
+
* @returns Array of parsed JSON values
|
|
95
|
+
*
|
|
96
|
+
* @example
|
|
97
|
+
* ```typescript
|
|
98
|
+
* const text = 'First: {"a": 1} Second: {"b": 2}';
|
|
99
|
+
* const results = extractAllJsonFromText(text);
|
|
100
|
+
* // Returns: [{ a: 1 }, { b: 2 }]
|
|
101
|
+
* ```
|
|
102
|
+
*/
|
|
103
|
+
export declare function extractAllJsonFromText(text: string): unknown[];
|