converse-mcp-server 2.3.1 → 2.4.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/README.md +771 -738
- package/docs/API.md +10 -1
- package/docs/PROVIDERS.md +8 -4
- package/package.json +12 -12
- package/src/async/asyncJobStore.js +82 -52
- package/src/async/eventBus.js +25 -20
- package/src/async/fileCache.js +121 -40
- package/src/async/jobRunner.js +65 -39
- package/src/async/providerStreamNormalizer.js +203 -117
- package/src/config.js +374 -102
- package/src/continuationStore.js +32 -24
- package/src/index.js +45 -25
- package/src/prompts/helpPrompt.js +328 -305
- package/src/providers/anthropic.js +303 -119
- package/src/providers/codex.js +103 -45
- package/src/providers/deepseek.js +24 -8
- package/src/providers/google.js +323 -93
- package/src/providers/index.js +1 -1
- package/src/providers/interface.js +16 -11
- package/src/providers/mistral.js +179 -69
- package/src/providers/openai-compatible.js +231 -94
- package/src/providers/openai.js +1094 -914
- package/src/providers/openrouter-endpoints-client.js +220 -216
- package/src/providers/openrouter.js +426 -381
- package/src/providers/xai.js +153 -56
- package/src/resources/helpResource.js +70 -67
- package/src/router.js +95 -67
- package/src/services/summarizationService.js +51 -24
- package/src/systemPrompts.js +89 -89
- package/src/tools/cancelJob.js +31 -19
- package/src/tools/chat.js +997 -883
- package/src/tools/checkStatus.js +86 -65
- package/src/tools/consensus.js +400 -234
- package/src/tools/index.js +39 -16
- package/src/transport/httpTransport.js +82 -55
- package/src/utils/contextProcessor.js +54 -37
- package/src/utils/errorHandler.js +95 -45
- package/src/utils/fileValidator.js +107 -98
- package/src/utils/formatStatus.js +122 -64
- package/src/utils/logger.js +459 -449
- package/src/utils/pathUtils.js +2 -2
- package/src/utils/tokenLimiter.js +216 -216
package/src/utils/pathUtils.js
CHANGED
|
@@ -112,7 +112,7 @@ export function getSpawnOptions(additionalOptions = {}) {
|
|
|
112
112
|
const options = {
|
|
113
113
|
...additionalOptions,
|
|
114
114
|
// Ensure proper path resolution on Windows
|
|
115
|
-
windowsVerbatimArguments: false
|
|
115
|
+
windowsVerbatimArguments: false,
|
|
116
116
|
};
|
|
117
117
|
|
|
118
118
|
// On Windows, we might need shell for certain operations
|
|
@@ -193,7 +193,7 @@ export function getPlatformName() {
|
|
|
193
193
|
const platformMap = {
|
|
194
194
|
win32: 'Windows',
|
|
195
195
|
darwin: 'macOS',
|
|
196
|
-
linux: 'Linux'
|
|
196
|
+
linux: 'Linux',
|
|
197
197
|
};
|
|
198
198
|
return platformMap[platform()] || platform();
|
|
199
199
|
}
|
|
@@ -1,217 +1,217 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Token Limiter Utility
|
|
3
|
-
*
|
|
4
|
-
* Implements token limiting for MCP tool responses to prevent excessive output.
|
|
5
|
-
* Based on the Python implementation's token limiting functionality.
|
|
6
|
-
*/
|
|
7
|
-
|
|
8
|
-
import { createLogger } from './logger.js';
|
|
9
|
-
|
|
10
|
-
const logger = createLogger('tokenLimiter');
|
|
11
|
-
|
|
12
|
-
/**
|
|
13
|
-
* Simple token estimation based on character count
|
|
14
|
-
* Rough approximation: 1 token ≈ 4 characters for English text
|
|
15
|
-
* @param {string} text - Text to estimate tokens for
|
|
16
|
-
* @returns {number} Estimated token count
|
|
17
|
-
*/
|
|
18
|
-
function estimateTokens(text) {
|
|
19
|
-
if (!text || typeof text !== 'string') {
|
|
20
|
-
return 0;
|
|
21
|
-
}
|
|
22
|
-
// Average of 4 characters per token for English text
|
|
23
|
-
return Math.ceil(text.length / 4);
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
/**
|
|
27
|
-
* Truncates text to fit within token limit while preserving structure
|
|
28
|
-
* @param {string} text - Text to truncate
|
|
29
|
-
* @param {number} maxTokens - Maximum allowed tokens
|
|
30
|
-
* @returns {object} Object with truncated text and metadata
|
|
31
|
-
*/
|
|
32
|
-
function truncateToTokenLimit(text, maxTokens) {
|
|
33
|
-
if (!text || typeof text !== 'string') {
|
|
34
|
-
return {
|
|
35
|
-
content: text || '',
|
|
36
|
-
truncated: false,
|
|
37
|
-
originalTokens: 0,
|
|
38
|
-
finalTokens: 0,
|
|
39
|
-
truncationReason: null
|
|
40
|
-
};
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
const originalTokens = estimateTokens(text);
|
|
44
|
-
|
|
45
|
-
if (originalTokens <= maxTokens) {
|
|
46
|
-
return {
|
|
47
|
-
content: text,
|
|
48
|
-
truncated: false,
|
|
49
|
-
originalTokens,
|
|
50
|
-
finalTokens: originalTokens,
|
|
51
|
-
truncationReason: null
|
|
52
|
-
};
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
// Calculate maximum characters to keep (with some buffer for safety)
|
|
56
|
-
const maxChars = Math.floor(maxTokens * 3.8); // Slightly less than 4 chars per token
|
|
57
|
-
|
|
58
|
-
// Find a good truncation point (prefer complete sentences or paragraphs)
|
|
59
|
-
const truncationPoint = maxChars;
|
|
60
|
-
const text_substring = text.substring(0, maxChars + 200); // Look ahead a bit
|
|
61
|
-
|
|
62
|
-
// Try to find sentence endings
|
|
63
|
-
const sentenceEndings = ['. ', '.\n', '!\n', '?\n', '! ', '? '];
|
|
64
|
-
let bestTruncation = maxChars;
|
|
65
|
-
|
|
66
|
-
for (const ending of sentenceEndings) {
|
|
67
|
-
const lastIndex = text_substring.lastIndexOf(ending);
|
|
68
|
-
if (lastIndex > maxChars * 0.8 && lastIndex < maxChars) {
|
|
69
|
-
bestTruncation = lastIndex + ending.length;
|
|
70
|
-
break;
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
// If no good sentence ending, try paragraph breaks
|
|
75
|
-
if (bestTruncation === maxChars) {
|
|
76
|
-
const paragraphBreak = text_substring.lastIndexOf('\n\n');
|
|
77
|
-
if (paragraphBreak > maxChars * 0.8 && paragraphBreak < maxChars) {
|
|
78
|
-
bestTruncation = paragraphBreak + 2;
|
|
79
|
-
}
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
// If still no good break, try line breaks
|
|
83
|
-
if (bestTruncation === maxChars) {
|
|
84
|
-
const lineBreak = text_substring.lastIndexOf('\n');
|
|
85
|
-
if (lineBreak > maxChars * 0.9 && lineBreak < maxChars) {
|
|
86
|
-
bestTruncation = lineBreak + 1;
|
|
87
|
-
}
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
const truncatedText = text.substring(0, bestTruncation);
|
|
91
|
-
const finalTokens = estimateTokens(truncatedText);
|
|
92
|
-
|
|
93
|
-
const truncationMessage = `\n\n[Response truncated due to length. Original: ~${originalTokens} tokens, Truncated: ~${finalTokens} tokens, Limit: ${maxTokens} tokens]`;
|
|
94
|
-
|
|
95
|
-
return {
|
|
96
|
-
content: truncatedText + truncationMessage,
|
|
97
|
-
truncated: true,
|
|
98
|
-
originalTokens,
|
|
99
|
-
finalTokens: finalTokens + estimateTokens(truncationMessage),
|
|
100
|
-
truncationReason: 'Exceeded maximum token limit'
|
|
101
|
-
};
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
/**
|
|
105
|
-
* Validates and applies token limits to MCP tool responses
|
|
106
|
-
* @param {any} response - The response content to validate
|
|
107
|
-
* @param {number} maxTokens - Maximum allowed tokens
|
|
108
|
-
* @returns {object} Processed response with token limiting applied
|
|
109
|
-
*/
|
|
110
|
-
export function applyTokenLimit(response, maxTokens) {
|
|
111
|
-
if (!maxTokens || maxTokens <= 0) {
|
|
112
|
-
return {
|
|
113
|
-
content: response,
|
|
114
|
-
metadata: {
|
|
115
|
-
tokenLimitApplied: false,
|
|
116
|
-
originalTokens: 0,
|
|
117
|
-
finalTokens: 0
|
|
118
|
-
}
|
|
119
|
-
};
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
// Handle different response types
|
|
123
|
-
let textContent = '';
|
|
124
|
-
const originalResponse = response;
|
|
125
|
-
|
|
126
|
-
if (typeof response === 'string') {
|
|
127
|
-
textContent = response;
|
|
128
|
-
} else if (response && typeof response === 'object') {
|
|
129
|
-
// Handle structured responses (like consensus tool)
|
|
130
|
-
if (response.content && typeof response.content === 'string') {
|
|
131
|
-
textContent = response.content;
|
|
132
|
-
} else {
|
|
133
|
-
// For complex objects, serialize to JSON for token counting
|
|
134
|
-
textContent = JSON.stringify(response, null, 2);
|
|
135
|
-
}
|
|
136
|
-
} else {
|
|
137
|
-
// Convert other types to string
|
|
138
|
-
textContent = String(response);
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
const result = truncateToTokenLimit(textContent, maxTokens);
|
|
142
|
-
|
|
143
|
-
if (result.truncated) {
|
|
144
|
-
logger.warn('Response truncated due to token limit', {
|
|
145
|
-
originalTokens: result.originalTokens,
|
|
146
|
-
finalTokens: result.finalTokens,
|
|
147
|
-
maxTokens,
|
|
148
|
-
truncationRatio: (result.finalTokens / result.originalTokens).toFixed(3)
|
|
149
|
-
});
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
// Return the processed response
|
|
153
|
-
if (typeof originalResponse === 'string') {
|
|
154
|
-
return {
|
|
155
|
-
content: result.content,
|
|
156
|
-
metadata: {
|
|
157
|
-
tokenLimitApplied: result.truncated,
|
|
158
|
-
originalTokens: result.originalTokens,
|
|
159
|
-
finalTokens: result.finalTokens,
|
|
160
|
-
truncationReason: result.truncationReason
|
|
161
|
-
}
|
|
162
|
-
};
|
|
163
|
-
} else if (originalResponse && typeof originalResponse === 'object') {
|
|
164
|
-
// For structured responses, update the content field
|
|
165
|
-
return {
|
|
166
|
-
...originalResponse,
|
|
167
|
-
content: result.content,
|
|
168
|
-
metadata: {
|
|
169
|
-
...originalResponse.metadata,
|
|
170
|
-
tokenLimitApplied: result.truncated,
|
|
171
|
-
originalTokens: result.originalTokens,
|
|
172
|
-
finalTokens: result.finalTokens,
|
|
173
|
-
truncationReason: result.truncationReason
|
|
174
|
-
}
|
|
175
|
-
};
|
|
176
|
-
} else {
|
|
177
|
-
return {
|
|
178
|
-
content: result.content,
|
|
179
|
-
metadata: {
|
|
180
|
-
tokenLimitApplied: result.truncated,
|
|
181
|
-
originalTokens: result.originalTokens,
|
|
182
|
-
finalTokens: result.finalTokens,
|
|
183
|
-
truncationReason: result.truncationReason
|
|
184
|
-
}
|
|
185
|
-
};
|
|
186
|
-
}
|
|
187
|
-
}
|
|
188
|
-
|
|
189
|
-
/**
|
|
190
|
-
* Gets the configured token limit from environment or config
|
|
191
|
-
* @param {object} config - Configuration object
|
|
192
|
-
* @returns {number} Maximum token limit
|
|
193
|
-
*/
|
|
194
|
-
export function getTokenLimit(config) {
|
|
195
|
-
if (config && config.mcp && config.mcp.max_mcp_output_tokens) {
|
|
196
|
-
return config.mcp.max_mcp_output_tokens;
|
|
197
|
-
}
|
|
198
|
-
|
|
199
|
-
// Fallback to environment variable
|
|
200
|
-
const envLimit = process.env.MAX_MCP_OUTPUT_TOKENS;
|
|
201
|
-
if (envLimit) {
|
|
202
|
-
const limit = parseInt(envLimit, 10);
|
|
203
|
-
if (!isNaN(limit) && limit > 0) {
|
|
204
|
-
return limit;
|
|
205
|
-
}
|
|
206
|
-
}
|
|
207
|
-
|
|
208
|
-
// Default limit
|
|
209
|
-
return 25000;
|
|
210
|
-
}
|
|
211
|
-
|
|
212
|
-
/**
|
|
213
|
-
* Estimates token count for a given text (exported for testing)
|
|
214
|
-
* @param {string} text - Text to estimate
|
|
215
|
-
* @returns {number} Estimated token count
|
|
216
|
-
*/
|
|
1
|
+
/**
|
|
2
|
+
* Token Limiter Utility
|
|
3
|
+
*
|
|
4
|
+
* Implements token limiting for MCP tool responses to prevent excessive output.
|
|
5
|
+
* Based on the Python implementation's token limiting functionality.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { createLogger } from './logger.js';
|
|
9
|
+
|
|
10
|
+
const logger = createLogger('tokenLimiter');
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Simple token estimation based on character count
|
|
14
|
+
* Rough approximation: 1 token ≈ 4 characters for English text
|
|
15
|
+
* @param {string} text - Text to estimate tokens for
|
|
16
|
+
* @returns {number} Estimated token count
|
|
17
|
+
*/
|
|
18
|
+
function estimateTokens(text) {
|
|
19
|
+
if (!text || typeof text !== 'string') {
|
|
20
|
+
return 0;
|
|
21
|
+
}
|
|
22
|
+
// Average of 4 characters per token for English text
|
|
23
|
+
return Math.ceil(text.length / 4);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Truncates text to fit within token limit while preserving structure
|
|
28
|
+
* @param {string} text - Text to truncate
|
|
29
|
+
* @param {number} maxTokens - Maximum allowed tokens
|
|
30
|
+
* @returns {object} Object with truncated text and metadata
|
|
31
|
+
*/
|
|
32
|
+
function truncateToTokenLimit(text, maxTokens) {
|
|
33
|
+
if (!text || typeof text !== 'string') {
|
|
34
|
+
return {
|
|
35
|
+
content: text || '',
|
|
36
|
+
truncated: false,
|
|
37
|
+
originalTokens: 0,
|
|
38
|
+
finalTokens: 0,
|
|
39
|
+
truncationReason: null,
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
const originalTokens = estimateTokens(text);
|
|
44
|
+
|
|
45
|
+
if (originalTokens <= maxTokens) {
|
|
46
|
+
return {
|
|
47
|
+
content: text,
|
|
48
|
+
truncated: false,
|
|
49
|
+
originalTokens,
|
|
50
|
+
finalTokens: originalTokens,
|
|
51
|
+
truncationReason: null,
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
// Calculate maximum characters to keep (with some buffer for safety)
|
|
56
|
+
const maxChars = Math.floor(maxTokens * 3.8); // Slightly less than 4 chars per token
|
|
57
|
+
|
|
58
|
+
// Find a good truncation point (prefer complete sentences or paragraphs)
|
|
59
|
+
const truncationPoint = maxChars;
|
|
60
|
+
const text_substring = text.substring(0, maxChars + 200); // Look ahead a bit
|
|
61
|
+
|
|
62
|
+
// Try to find sentence endings
|
|
63
|
+
const sentenceEndings = ['. ', '.\n', '!\n', '?\n', '! ', '? '];
|
|
64
|
+
let bestTruncation = maxChars;
|
|
65
|
+
|
|
66
|
+
for (const ending of sentenceEndings) {
|
|
67
|
+
const lastIndex = text_substring.lastIndexOf(ending);
|
|
68
|
+
if (lastIndex > maxChars * 0.8 && lastIndex < maxChars) {
|
|
69
|
+
bestTruncation = lastIndex + ending.length;
|
|
70
|
+
break;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
// If no good sentence ending, try paragraph breaks
|
|
75
|
+
if (bestTruncation === maxChars) {
|
|
76
|
+
const paragraphBreak = text_substring.lastIndexOf('\n\n');
|
|
77
|
+
if (paragraphBreak > maxChars * 0.8 && paragraphBreak < maxChars) {
|
|
78
|
+
bestTruncation = paragraphBreak + 2;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
// If still no good break, try line breaks
|
|
83
|
+
if (bestTruncation === maxChars) {
|
|
84
|
+
const lineBreak = text_substring.lastIndexOf('\n');
|
|
85
|
+
if (lineBreak > maxChars * 0.9 && lineBreak < maxChars) {
|
|
86
|
+
bestTruncation = lineBreak + 1;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
const truncatedText = text.substring(0, bestTruncation);
|
|
91
|
+
const finalTokens = estimateTokens(truncatedText);
|
|
92
|
+
|
|
93
|
+
const truncationMessage = `\n\n[Response truncated due to length. Original: ~${originalTokens} tokens, Truncated: ~${finalTokens} tokens, Limit: ${maxTokens} tokens]`;
|
|
94
|
+
|
|
95
|
+
return {
|
|
96
|
+
content: truncatedText + truncationMessage,
|
|
97
|
+
truncated: true,
|
|
98
|
+
originalTokens,
|
|
99
|
+
finalTokens: finalTokens + estimateTokens(truncationMessage),
|
|
100
|
+
truncationReason: 'Exceeded maximum token limit',
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* Validates and applies token limits to MCP tool responses
|
|
106
|
+
* @param {any} response - The response content to validate
|
|
107
|
+
* @param {number} maxTokens - Maximum allowed tokens
|
|
108
|
+
* @returns {object} Processed response with token limiting applied
|
|
109
|
+
*/
|
|
110
|
+
export function applyTokenLimit(response, maxTokens) {
|
|
111
|
+
if (!maxTokens || maxTokens <= 0) {
|
|
112
|
+
return {
|
|
113
|
+
content: response,
|
|
114
|
+
metadata: {
|
|
115
|
+
tokenLimitApplied: false,
|
|
116
|
+
originalTokens: 0,
|
|
117
|
+
finalTokens: 0,
|
|
118
|
+
},
|
|
119
|
+
};
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
// Handle different response types
|
|
123
|
+
let textContent = '';
|
|
124
|
+
const originalResponse = response;
|
|
125
|
+
|
|
126
|
+
if (typeof response === 'string') {
|
|
127
|
+
textContent = response;
|
|
128
|
+
} else if (response && typeof response === 'object') {
|
|
129
|
+
// Handle structured responses (like consensus tool)
|
|
130
|
+
if (response.content && typeof response.content === 'string') {
|
|
131
|
+
textContent = response.content;
|
|
132
|
+
} else {
|
|
133
|
+
// For complex objects, serialize to JSON for token counting
|
|
134
|
+
textContent = JSON.stringify(response, null, 2);
|
|
135
|
+
}
|
|
136
|
+
} else {
|
|
137
|
+
// Convert other types to string
|
|
138
|
+
textContent = String(response);
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
const result = truncateToTokenLimit(textContent, maxTokens);
|
|
142
|
+
|
|
143
|
+
if (result.truncated) {
|
|
144
|
+
logger.warn('Response truncated due to token limit', {
|
|
145
|
+
originalTokens: result.originalTokens,
|
|
146
|
+
finalTokens: result.finalTokens,
|
|
147
|
+
maxTokens,
|
|
148
|
+
truncationRatio: (result.finalTokens / result.originalTokens).toFixed(3),
|
|
149
|
+
});
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
// Return the processed response
|
|
153
|
+
if (typeof originalResponse === 'string') {
|
|
154
|
+
return {
|
|
155
|
+
content: result.content,
|
|
156
|
+
metadata: {
|
|
157
|
+
tokenLimitApplied: result.truncated,
|
|
158
|
+
originalTokens: result.originalTokens,
|
|
159
|
+
finalTokens: result.finalTokens,
|
|
160
|
+
truncationReason: result.truncationReason,
|
|
161
|
+
},
|
|
162
|
+
};
|
|
163
|
+
} else if (originalResponse && typeof originalResponse === 'object') {
|
|
164
|
+
// For structured responses, update the content field
|
|
165
|
+
return {
|
|
166
|
+
...originalResponse,
|
|
167
|
+
content: result.content,
|
|
168
|
+
metadata: {
|
|
169
|
+
...originalResponse.metadata,
|
|
170
|
+
tokenLimitApplied: result.truncated,
|
|
171
|
+
originalTokens: result.originalTokens,
|
|
172
|
+
finalTokens: result.finalTokens,
|
|
173
|
+
truncationReason: result.truncationReason,
|
|
174
|
+
},
|
|
175
|
+
};
|
|
176
|
+
} else {
|
|
177
|
+
return {
|
|
178
|
+
content: result.content,
|
|
179
|
+
metadata: {
|
|
180
|
+
tokenLimitApplied: result.truncated,
|
|
181
|
+
originalTokens: result.originalTokens,
|
|
182
|
+
finalTokens: result.finalTokens,
|
|
183
|
+
truncationReason: result.truncationReason,
|
|
184
|
+
},
|
|
185
|
+
};
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
/**
|
|
190
|
+
* Gets the configured token limit from environment or config
|
|
191
|
+
* @param {object} config - Configuration object
|
|
192
|
+
* @returns {number} Maximum token limit
|
|
193
|
+
*/
|
|
194
|
+
export function getTokenLimit(config) {
|
|
195
|
+
if (config && config.mcp && config.mcp.max_mcp_output_tokens) {
|
|
196
|
+
return config.mcp.max_mcp_output_tokens;
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
// Fallback to environment variable
|
|
200
|
+
const envLimit = process.env.MAX_MCP_OUTPUT_TOKENS;
|
|
201
|
+
if (envLimit) {
|
|
202
|
+
const limit = parseInt(envLimit, 10);
|
|
203
|
+
if (!isNaN(limit) && limit > 0) {
|
|
204
|
+
return limit;
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
// Default limit
|
|
209
|
+
return 25000;
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
/**
|
|
213
|
+
* Estimates token count for a given text (exported for testing)
|
|
214
|
+
* @param {string} text - Text to estimate
|
|
215
|
+
* @returns {number} Estimated token count
|
|
216
|
+
*/
|
|
217
217
|
export { estimateTokens };
|