@@ -34,6 +34,7 @@ export type PlainTextToolCallParseOptions = {
3434} ;
3535
3636const DEFAULT_MAX_PLAIN_TEXT_TOOL_PAYLOAD_BYTES = 256_000 ;
37+ const utf8Encoder = new TextEncoder ( ) ;
3738
3839type PlainTextToolCallOpening = {
3940 allowsOptionalXmlishClose ?: boolean ;
@@ -221,6 +222,15 @@ type XmlishParameterBlockBounds = {
221222 start : number ;
222223} ;
223224
225+ function utf8ByteLengthExceeds (
226+ text : string ,
227+ start : number ,
228+ end : number ,
229+ maxBytes : number ,
230+ ) : boolean {
231+ return end - start > maxBytes || utf8Encoder . encode ( text . slice ( start , end ) ) . byteLength > maxBytes ;
232+ }
233+
224234function findXmlishParameterBlock ( text : string , start : number ) : XmlishParameterBlockBounds | null {
225235 const cursor = skipWhitespace ( text , start ) ;
226236 const openMatch = / ^ < p a r a m e t e r = ( [ A - Z a - z 0 - 9 _ . : - ] { 1 , 120 } ) > / i. exec ( text . slice ( cursor ) ) ;
@@ -252,7 +262,7 @@ function consumeXmlishParameterBlock(
252262 if ( ! bounds ) {
253263 return null ;
254264 }
255- if ( bounds . end - bounds . start > maxPayloadBytes ) {
265+ if ( utf8ByteLengthExceeds ( text , bounds . start , bounds . end , maxPayloadBytes ) ) {
256266 return null ;
257267 }
258268 return {
@@ -344,7 +354,7 @@ function parseXmlishPlainTextToolCallBlockAt(
344354 if ( ! parameter ) {
345355 break ;
346356 }
347- if ( parameter . end - opening . end > maxPayloadBytes ) {
357+ if ( utf8ByteLengthExceeds ( text , opening . end , parameter . end , maxPayloadBytes ) ) {
348358 return null ;
349359 }
350360 args [ parameter . name ] = parameter . value ;
0 commit comments