@librechat/agents 3.1.54 → 3.1.56
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/dist/cjs/agents/AgentContext.cjs.map +1 -1
- package/dist/cjs/common/enum.cjs.map +1 -1
- package/dist/cjs/events.cjs.map +1 -1
- package/dist/cjs/graphs/Graph.cjs +1 -1
- package/dist/cjs/graphs/Graph.cjs.map +1 -1
- package/dist/cjs/graphs/MultiAgentGraph.cjs.map +1 -1
- package/dist/cjs/llm/anthropic/index.cjs.map +1 -1
- package/dist/cjs/llm/anthropic/types.cjs.map +1 -1
- package/dist/cjs/llm/anthropic/utils/message_inputs.cjs.map +1 -1
- package/dist/cjs/llm/anthropic/utils/message_outputs.cjs.map +1 -1
- package/dist/cjs/llm/anthropic/utils/tools.cjs.map +1 -1
- package/dist/cjs/llm/bedrock/index.cjs.map +1 -1
- package/dist/cjs/llm/bedrock/utils/message_inputs.cjs.map +1 -1
- package/dist/cjs/llm/bedrock/utils/message_outputs.cjs.map +1 -1
- package/dist/cjs/llm/fake.cjs.map +1 -1
- package/dist/cjs/llm/google/index.cjs.map +1 -1
- package/dist/cjs/llm/google/utils/common.cjs.map +1 -1
- package/dist/cjs/llm/openai/index.cjs +1 -1
- package/dist/cjs/llm/openai/index.cjs.map +1 -1
- package/dist/cjs/llm/openai/utils/index.cjs.map +1 -1
- package/dist/cjs/llm/openrouter/index.cjs.map +1 -1
- package/dist/cjs/llm/providers.cjs.map +1 -1
- package/dist/cjs/llm/text.cjs.map +1 -1
- package/dist/cjs/llm/vertexai/index.cjs +68 -4
- package/dist/cjs/llm/vertexai/index.cjs.map +1 -1
- package/dist/cjs/main.cjs +29 -28
- package/dist/cjs/main.cjs.map +1 -1
- package/dist/cjs/messages/cache.cjs.map +1 -1
- package/dist/cjs/messages/content.cjs.map +1 -1
- package/dist/cjs/messages/core.cjs.map +1 -1
- package/dist/cjs/messages/format.cjs +118 -32
- package/dist/cjs/messages/format.cjs.map +1 -1
- package/dist/cjs/messages/ids.cjs.map +1 -1
- package/dist/cjs/messages/prune.cjs.map +1 -1
- package/dist/cjs/messages/tools.cjs.map +1 -1
- package/dist/cjs/run.cjs +5 -2
- package/dist/cjs/run.cjs.map +1 -1
- package/dist/cjs/splitStream.cjs.map +1 -1
- package/dist/cjs/stream.cjs +9 -0
- package/dist/cjs/stream.cjs.map +1 -1
- package/dist/cjs/tools/Calculator.cjs.map +1 -1
- package/dist/cjs/tools/CodeExecutor.cjs.map +1 -1
- package/dist/cjs/tools/ProgrammaticToolCalling.cjs.map +1 -1
- package/dist/cjs/tools/ToolNode.cjs +1 -1
- package/dist/cjs/tools/ToolNode.cjs.map +1 -1
- package/dist/cjs/tools/ToolSearch.cjs.map +1 -1
- package/dist/cjs/tools/handlers.cjs.map +1 -1
- package/dist/cjs/tools/schema.cjs.map +1 -1
- package/dist/cjs/tools/search/content.cjs.map +1 -1
- package/dist/cjs/tools/search/firecrawl.cjs.map +1 -1
- package/dist/cjs/tools/search/format.cjs.map +1 -1
- package/dist/cjs/tools/search/highlights.cjs.map +1 -1
- package/dist/cjs/tools/search/rerankers.cjs.map +1 -1
- package/dist/cjs/tools/search/schema.cjs.map +1 -1
- package/dist/cjs/tools/search/search.cjs +1 -0
- package/dist/cjs/tools/search/search.cjs.map +1 -1
- package/dist/cjs/tools/search/serper-scraper.cjs.map +1 -1
- package/dist/cjs/tools/search/tool.cjs.map +1 -1
- package/dist/cjs/tools/search/utils.cjs.map +1 -1
- package/dist/cjs/utils/events.cjs.map +1 -1
- package/dist/cjs/utils/graph.cjs.map +1 -1
- package/dist/cjs/utils/handlers.cjs.map +1 -1
- package/dist/cjs/utils/llm.cjs.map +1 -1
- package/dist/cjs/utils/misc.cjs.map +1 -1
- package/dist/cjs/utils/run.cjs.map +1 -1
- package/dist/cjs/utils/schema.cjs.map +1 -1
- package/dist/cjs/utils/title.cjs.map +1 -1
- package/dist/cjs/utils/tokens.cjs +33 -45
- package/dist/cjs/utils/tokens.cjs.map +1 -1
- package/dist/esm/agents/AgentContext.mjs.map +1 -1
- package/dist/esm/common/enum.mjs.map +1 -1
- package/dist/esm/events.mjs.map +1 -1
- package/dist/esm/graphs/Graph.mjs +1 -1
- package/dist/esm/graphs/Graph.mjs.map +1 -1
- package/dist/esm/graphs/MultiAgentGraph.mjs.map +1 -1
- package/dist/esm/llm/anthropic/index.mjs.map +1 -1
- package/dist/esm/llm/anthropic/types.mjs.map +1 -1
- package/dist/esm/llm/anthropic/utils/message_inputs.mjs.map +1 -1
- package/dist/esm/llm/anthropic/utils/message_outputs.mjs.map +1 -1
- package/dist/esm/llm/anthropic/utils/tools.mjs.map +1 -1
- package/dist/esm/llm/bedrock/index.mjs.map +1 -1
- package/dist/esm/llm/bedrock/utils/message_inputs.mjs.map +1 -1
- package/dist/esm/llm/bedrock/utils/message_outputs.mjs.map +1 -1
- package/dist/esm/llm/fake.mjs.map +1 -1
- package/dist/esm/llm/google/index.mjs.map +1 -1
- package/dist/esm/llm/google/utils/common.mjs.map +1 -1
- package/dist/esm/llm/openai/index.mjs +1 -1
- package/dist/esm/llm/openai/index.mjs.map +1 -1
- package/dist/esm/llm/openai/utils/index.mjs.map +1 -1
- package/dist/esm/llm/openrouter/index.mjs.map +1 -1
- package/dist/esm/llm/providers.mjs.map +1 -1
- package/dist/esm/llm/text.mjs.map +1 -1
- package/dist/esm/llm/vertexai/index.mjs +68 -4
- package/dist/esm/llm/vertexai/index.mjs.map +1 -1
- package/dist/esm/main.mjs +1 -1
- package/dist/esm/messages/cache.mjs.map +1 -1
- package/dist/esm/messages/content.mjs.map +1 -1
- package/dist/esm/messages/core.mjs +1 -1
- package/dist/esm/messages/core.mjs.map +1 -1
- package/dist/esm/messages/format.mjs +120 -34
- package/dist/esm/messages/format.mjs.map +1 -1
- package/dist/esm/messages/ids.mjs.map +1 -1
- package/dist/esm/messages/prune.mjs +1 -1
- package/dist/esm/messages/prune.mjs.map +1 -1
- package/dist/esm/messages/tools.mjs.map +1 -1
- package/dist/esm/run.mjs +5 -2
- package/dist/esm/run.mjs.map +1 -1
- package/dist/esm/splitStream.mjs.map +1 -1
- package/dist/esm/stream.mjs +10 -1
- package/dist/esm/stream.mjs.map +1 -1
- package/dist/esm/tools/Calculator.mjs.map +1 -1
- package/dist/esm/tools/CodeExecutor.mjs.map +1 -1
- package/dist/esm/tools/ProgrammaticToolCalling.mjs +1 -1
- package/dist/esm/tools/ProgrammaticToolCalling.mjs.map +1 -1
- package/dist/esm/tools/ToolNode.mjs +1 -1
- package/dist/esm/tools/ToolNode.mjs.map +1 -1
- package/dist/esm/tools/ToolSearch.mjs.map +1 -1
- package/dist/esm/tools/handlers.mjs +1 -1
- package/dist/esm/tools/handlers.mjs.map +1 -1
- package/dist/esm/tools/schema.mjs.map +1 -1
- package/dist/esm/tools/search/content.mjs.map +1 -1
- package/dist/esm/tools/search/firecrawl.mjs.map +1 -1
- package/dist/esm/tools/search/format.mjs.map +1 -1
- package/dist/esm/tools/search/highlights.mjs.map +1 -1
- package/dist/esm/tools/search/rerankers.mjs.map +1 -1
- package/dist/esm/tools/search/schema.mjs.map +1 -1
- package/dist/esm/tools/search/search.mjs +1 -0
- package/dist/esm/tools/search/search.mjs.map +1 -1
- package/dist/esm/tools/search/serper-scraper.mjs.map +1 -1
- package/dist/esm/tools/search/tool.mjs.map +1 -1
- package/dist/esm/tools/search/utils.mjs.map +1 -1
- package/dist/esm/utils/events.mjs.map +1 -1
- package/dist/esm/utils/graph.mjs.map +1 -1
- package/dist/esm/utils/handlers.mjs.map +1 -1
- package/dist/esm/utils/llm.mjs.map +1 -1
- package/dist/esm/utils/misc.mjs.map +1 -1
- package/dist/esm/utils/run.mjs.map +1 -1
- package/dist/esm/utils/schema.mjs.map +1 -1
- package/dist/esm/utils/title.mjs.map +1 -1
- package/dist/esm/utils/tokens.mjs +33 -46
- package/dist/esm/utils/tokens.mjs.map +1 -1
- package/dist/types/llm/vertexai/index.d.ts +1 -1
- package/dist/types/types/graph.d.ts +2 -0
- package/dist/types/types/stream.d.ts +2 -0
- package/dist/types/utils/tokens.d.ts +6 -18
- package/package.json +7 -3
- package/src/llm/vertexai/index.ts +99 -6
- package/src/llm/vertexai/llm.spec.ts +114 -0
- package/src/messages/ensureThinkingBlock.test.ts +502 -27
- package/src/messages/format.ts +155 -44
- package/src/run.ts +6 -2
- package/src/scripts/bedrock-cache-debug.ts +15 -15
- package/src/scripts/code_exec_multi_session.ts +8 -13
- package/src/scripts/image.ts +2 -1
- package/src/scripts/multi-agent-parallel-start.ts +3 -4
- package/src/scripts/multi-agent-sequence.ts +3 -4
- package/src/scripts/single-agent-metadata-test.ts +3 -6
- package/src/scripts/test-tool-before-handoff-role-order.ts +2 -3
- package/src/scripts/test-tools-before-handoff.ts +2 -3
- package/src/scripts/thinking-vertexai.ts +168 -0
- package/src/scripts/tools.ts +1 -7
- package/src/specs/token-memoization.test.ts +35 -34
- package/src/specs/tokens.test.ts +64 -0
- package/src/stream.ts +12 -0
- package/src/types/graph.ts +2 -0
- package/src/types/stream.ts +2 -0
- package/src/utils/tokens.ts +43 -54
package/src/scripts/tools.ts
CHANGED
|
@@ -18,13 +18,7 @@ async function testStandardStreaming(): Promise<void> {
|
|
|
18
18
|
const { userName, location, provider, currentDate } = await getArgs();
|
|
19
19
|
const { contentParts, aggregateContent } = createContentAggregator();
|
|
20
20
|
const customHandlers = {
|
|
21
|
-
[GraphEvents.TOOL_END]: new ToolEndHandler(
|
|
22
|
-
undefined,
|
|
23
|
-
undefined,
|
|
24
|
-
(name?: string) => {
|
|
25
|
-
return true;
|
|
26
|
-
}
|
|
27
|
-
),
|
|
21
|
+
[GraphEvents.TOOL_END]: new ToolEndHandler(),
|
|
28
22
|
[GraphEvents.CHAT_MODEL_END]: new ModelEndHandler(),
|
|
29
23
|
[GraphEvents.CHAT_MODEL_START]: {
|
|
30
24
|
handle: (
|
|
@@ -1,39 +1,40 @@
|
|
|
1
1
|
import { HumanMessage } from '@langchain/core/messages';
|
|
2
|
-
import { createTokenCounter } from '@/utils/tokens';
|
|
2
|
+
import { createTokenCounter, TokenEncoderManager } from '@/utils/tokens';
|
|
3
|
+
|
|
4
|
+
jest.setTimeout(5000);
|
|
3
5
|
|
|
4
6
|
describe('Token encoder memoization', () => {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
}
|
|
7
|
+
beforeEach(() => {
|
|
8
|
+
TokenEncoderManager.reset();
|
|
9
|
+
});
|
|
10
|
+
|
|
11
|
+
test('reuses the same tokenizer across counter calls', async () => {
|
|
12
|
+
expect(TokenEncoderManager.isInitialized()).toBe(false);
|
|
13
|
+
|
|
14
|
+
const counter1 = await createTokenCounter();
|
|
15
|
+
expect(TokenEncoderManager.isInitialized()).toBe(true);
|
|
16
|
+
|
|
17
|
+
const counter2 = await createTokenCounter();
|
|
18
|
+
|
|
19
|
+
const m1 = new HumanMessage('hello world');
|
|
20
|
+
const m2 = new HumanMessage('another short text');
|
|
21
|
+
|
|
22
|
+
const c11 = counter1(m1);
|
|
23
|
+
const c12 = counter1(m2);
|
|
24
|
+
const c21 = counter2(m1);
|
|
25
|
+
const c22 = counter2(m2);
|
|
26
|
+
|
|
27
|
+
expect(c11).toBeGreaterThan(0);
|
|
28
|
+
expect(c12).toBeGreaterThan(0);
|
|
29
|
+
expect(c21).toBe(c11);
|
|
30
|
+
expect(c22).toBe(c12);
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
test('reset clears cached tokenizers', async () => {
|
|
34
|
+
await createTokenCounter();
|
|
35
|
+
expect(TokenEncoderManager.isInitialized()).toBe(true);
|
|
36
|
+
|
|
37
|
+
TokenEncoderManager.reset();
|
|
38
|
+
expect(TokenEncoderManager.isInitialized()).toBe(false);
|
|
38
39
|
});
|
|
39
40
|
});
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { HumanMessage } from '@langchain/core/messages';
|
|
2
|
+
import {
|
|
3
|
+
encodingForModel,
|
|
4
|
+
createTokenCounter,
|
|
5
|
+
TokenEncoderManager,
|
|
6
|
+
} from '@/utils/tokens';
|
|
7
|
+
|
|
8
|
+
describe('encodingForModel', () => {
|
|
9
|
+
test('returns claude for Claude model strings', () => {
|
|
10
|
+
expect(encodingForModel('claude-3-5-sonnet-20241022')).toBe('claude');
|
|
11
|
+
expect(encodingForModel('claude-3-haiku-20240307')).toBe('claude');
|
|
12
|
+
});
|
|
13
|
+
|
|
14
|
+
test('handles Bedrock Claude ARNs', () => {
|
|
15
|
+
expect(encodingForModel('anthropic.claude-3-5-sonnet-20241022-v2:0')).toBe(
|
|
16
|
+
'claude'
|
|
17
|
+
);
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
test('is case-insensitive', () => {
|
|
21
|
+
expect(encodingForModel('CLAUDE-3-HAIKU')).toBe('claude');
|
|
22
|
+
expect(encodingForModel('Claude-3-Opus')).toBe('claude');
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
test('returns o200k_base for non-Claude models', () => {
|
|
26
|
+
expect(encodingForModel('gpt-4o')).toBe('o200k_base');
|
|
27
|
+
expect(encodingForModel('gemini-2.0-flash')).toBe('o200k_base');
|
|
28
|
+
expect(encodingForModel('mistral-large')).toBe('o200k_base');
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
test('returns o200k_base for empty string', () => {
|
|
32
|
+
expect(encodingForModel('')).toBe('o200k_base');
|
|
33
|
+
});
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
describe('createTokenCounter with different encodings', () => {
|
|
37
|
+
beforeEach(() => {
|
|
38
|
+
TokenEncoderManager.reset();
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
test('claude encoding produces valid token counts', async () => {
|
|
42
|
+
const counter = await createTokenCounter('claude');
|
|
43
|
+
const msg = new HumanMessage('Hello, world!');
|
|
44
|
+
const count = counter(msg);
|
|
45
|
+
expect(count).toBeGreaterThan(0);
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
test('o200k_base encoding produces valid token counts', async () => {
|
|
49
|
+
const counter = await createTokenCounter('o200k_base');
|
|
50
|
+
const msg = new HumanMessage('Hello, world!');
|
|
51
|
+
const count = counter(msg);
|
|
52
|
+
expect(count).toBeGreaterThan(0);
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
test('both encodings can be initialized and used independently', async () => {
|
|
56
|
+
const claudeCounter = await createTokenCounter('claude');
|
|
57
|
+
const o200kCounter = await createTokenCounter('o200k_base');
|
|
58
|
+
expect(TokenEncoderManager.isInitialized()).toBe(true);
|
|
59
|
+
|
|
60
|
+
const msg = new HumanMessage('Test message for both encodings');
|
|
61
|
+
expect(claudeCounter(msg)).toBeGreaterThan(0);
|
|
62
|
+
expect(o200kCounter(msg)).toBeGreaterThan(0);
|
|
63
|
+
});
|
|
64
|
+
});
|
package/src/stream.ts
CHANGED
|
@@ -576,6 +576,16 @@ export function createContentAggregator(): t.ContentAggregatorResult {
|
|
|
576
576
|
type: ToolCallTypes.TOOL_CALL,
|
|
577
577
|
};
|
|
578
578
|
|
|
579
|
+
const auth =
|
|
580
|
+
contentPart.tool_call.auth ?? existingContent?.tool_call?.auth;
|
|
581
|
+
const expiresAt =
|
|
582
|
+
contentPart.tool_call.expires_at ??
|
|
583
|
+
existingContent?.tool_call?.expires_at;
|
|
584
|
+
if (auth != null) {
|
|
585
|
+
newToolCall.auth = auth;
|
|
586
|
+
newToolCall.expires_at = expiresAt;
|
|
587
|
+
}
|
|
588
|
+
|
|
579
589
|
if (finalUpdate) {
|
|
580
590
|
newToolCall.progress = 1;
|
|
581
591
|
newToolCall.output = contentPart.tool_call.output;
|
|
@@ -713,6 +723,8 @@ export function createContentAggregator(): t.ContentAggregatorResult {
|
|
|
713
723
|
args: toolCallDelta.args ?? '',
|
|
714
724
|
name: toolCallDelta.name,
|
|
715
725
|
id: toolCallId,
|
|
726
|
+
auth: runStepDelta.delta.auth,
|
|
727
|
+
expires_at: runStepDelta.delta.expires_at,
|
|
716
728
|
},
|
|
717
729
|
};
|
|
718
730
|
|
package/src/types/graph.ts
CHANGED
package/src/types/stream.ts
CHANGED
package/src/utils/tokens.ts
CHANGED
|
@@ -1,7 +1,34 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { Tokenizer } from 'ai-tokenizer';
|
|
2
2
|
import type { BaseMessage } from '@langchain/core/messages';
|
|
3
3
|
import { ContentTypes } from '@/common/enum';
|
|
4
4
|
|
|
5
|
+
export type EncodingName = 'o200k_base' | 'claude';
|
|
6
|
+
|
|
7
|
+
const tokenizers: Partial<Record<EncodingName, Tokenizer>> = {};
|
|
8
|
+
|
|
9
|
+
async function getTokenizer(
|
|
10
|
+
encoding: EncodingName = 'o200k_base'
|
|
11
|
+
): Promise<Tokenizer> {
|
|
12
|
+
const cached = tokenizers[encoding];
|
|
13
|
+
if (cached) {
|
|
14
|
+
return cached;
|
|
15
|
+
}
|
|
16
|
+
const data =
|
|
17
|
+
encoding === 'claude'
|
|
18
|
+
? await import('ai-tokenizer/encoding/claude')
|
|
19
|
+
: await import('ai-tokenizer/encoding/o200k_base');
|
|
20
|
+
const instance = new Tokenizer(data);
|
|
21
|
+
tokenizers[encoding] = instance;
|
|
22
|
+
return instance;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export function encodingForModel(model: string): EncodingName {
|
|
26
|
+
if (model.toLowerCase().includes('claude')) {
|
|
27
|
+
return 'claude';
|
|
28
|
+
}
|
|
29
|
+
return 'o200k_base';
|
|
30
|
+
}
|
|
31
|
+
|
|
5
32
|
export function getTokenCountForMessage(
|
|
6
33
|
message: BaseMessage,
|
|
7
34
|
getTokenCount: (text: string) => number
|
|
@@ -60,70 +87,32 @@ export function getTokenCountForMessage(
|
|
|
60
87
|
return numTokens;
|
|
61
88
|
}
|
|
62
89
|
|
|
63
|
-
let encoderPromise: Promise<Tiktoken> | undefined;
|
|
64
|
-
let tokenCounterPromise: Promise<(message: BaseMessage) => number> | undefined;
|
|
65
|
-
|
|
66
|
-
async function getSharedEncoder(): Promise<Tiktoken> {
|
|
67
|
-
if (encoderPromise) {
|
|
68
|
-
return encoderPromise;
|
|
69
|
-
}
|
|
70
|
-
encoderPromise = (async (): Promise<Tiktoken> => {
|
|
71
|
-
const res = await fetch('https://tiktoken.pages.dev/js/o200k_base.json');
|
|
72
|
-
const o200k_base = await res.json();
|
|
73
|
-
return new Tiktoken(o200k_base);
|
|
74
|
-
})();
|
|
75
|
-
return encoderPromise;
|
|
76
|
-
}
|
|
77
|
-
|
|
78
90
|
/**
|
|
79
|
-
* Creates a
|
|
80
|
-
*
|
|
91
|
+
* Creates a token counter function using the specified encoding.
|
|
92
|
+
* Lazily loads the encoding data on first use via dynamic import.
|
|
81
93
|
*/
|
|
82
|
-
export const createTokenCounter = async (
|
|
83
|
-
|
|
84
|
-
> => {
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
tokenCounterPromise = (async (): Promise<
|
|
90
|
-
(message: BaseMessage) => number
|
|
91
|
-
> => {
|
|
92
|
-
const enc = await getSharedEncoder();
|
|
93
|
-
const countTokens = (text: string): number => enc.encode(text).length;
|
|
94
|
-
return (message: BaseMessage): number =>
|
|
95
|
-
getTokenCountForMessage(message, countTokens);
|
|
96
|
-
})();
|
|
97
|
-
|
|
98
|
-
return tokenCounterPromise;
|
|
94
|
+
export const createTokenCounter = async (
|
|
95
|
+
encoding: EncodingName = 'o200k_base'
|
|
96
|
+
): Promise<(message: BaseMessage) => number> => {
|
|
97
|
+
const tok = await getTokenizer(encoding);
|
|
98
|
+
const countTokens = (text: string): number => tok.count(text);
|
|
99
|
+
return (message: BaseMessage): number =>
|
|
100
|
+
getTokenCountForMessage(message, countTokens);
|
|
99
101
|
};
|
|
100
102
|
|
|
101
|
-
/**
|
|
102
|
-
* Utility to manage the token encoder lifecycle explicitly.
|
|
103
|
-
* Useful for applications that need fine-grained control over resource management.
|
|
104
|
-
*/
|
|
103
|
+
/** Utility to manage the token encoder lifecycle explicitly. */
|
|
105
104
|
export const TokenEncoderManager = {
|
|
106
|
-
/**
|
|
107
|
-
* Pre-initializes the encoder. This can be called during app startup
|
|
108
|
-
* to avoid lazy loading delays later.
|
|
109
|
-
*/
|
|
110
105
|
async initialize(): Promise<void> {
|
|
111
|
-
|
|
106
|
+
// No-op: ai-tokenizer is synchronously initialized from bundled data.
|
|
112
107
|
},
|
|
113
108
|
|
|
114
|
-
/**
|
|
115
|
-
* Clears the cached encoder and token counter.
|
|
116
|
-
* Useful for testing or when you need to force a fresh reload.
|
|
117
|
-
*/
|
|
118
109
|
reset(): void {
|
|
119
|
-
|
|
120
|
-
|
|
110
|
+
for (const key of Object.keys(tokenizers)) {
|
|
111
|
+
delete tokenizers[key as EncodingName];
|
|
112
|
+
}
|
|
121
113
|
},
|
|
122
114
|
|
|
123
|
-
/**
|
|
124
|
-
* Checks if the encoder has been initialized.
|
|
125
|
-
*/
|
|
126
115
|
isInitialized(): boolean {
|
|
127
|
-
return
|
|
116
|
+
return Object.keys(tokenizers).length > 0;
|
|
128
117
|
},
|
|
129
118
|
};
|