@@ -12,13 +12,18 @@ const TOKEN_FUDGE_FACTOR = 1.5
1212 * Base class for API providers that implements common functionality
1313 */
1414export abstract class BaseProvider implements ApiHandler {
15+ // Cache the Tiktoken encoder instance since it's stateless
16+ private encoder : Tiktoken | null = null
1517 abstract createMessage ( systemPrompt : string , messages : Anthropic . Messages . MessageParam [ ] ) : ApiStream
1618 abstract getModel ( ) : { id : string ; info : ModelInfo }
1719
1820 /**
1921 * Default token counting implementation using tiktoken
2022 * Providers can override this to use their native token counting endpoints
2123 *
24+ * Uses a cached Tiktoken encoder instance for performance since it's stateless.
25+ * The encoder is created lazily on first use and reused for subsequent calls.
26+ *
2227 * @param content The content to count tokens for
2328 * @returns A promise resolving to the token count
2429 */
@@ -27,17 +32,18 @@ export abstract class BaseProvider implements ApiHandler {
2732
2833 let totalTokens = 0
2934
30- // Create encoder - currently we only use o200kBase
31- // In the future, providers could override this method to use more specific tokenizers
32- const encoder = new Tiktoken ( o200kBase )
35+ // Lazily create and cache the encoder if it doesn't exist
36+ if ( ! this . encoder ) {
37+ this . encoder = new Tiktoken ( o200kBase )
38+ }
3339
34- // Process each content block
40+ // Process each content block using the cached encoder
3541 for ( const block of content ) {
3642 if ( block . type === "text" ) {
3743 // Use tiktoken for text token counting
3844 const text = block . text || ""
3945 if ( text . length > 0 ) {
40- const tokens = encoder . encode ( text )
46+ const tokens = this . encoder . encode ( text )
4147 totalTokens += tokens . length
4248 }
4349 } else if ( block . type === "image" ) {
0 commit comments