@librechat/agents 3.1.97 → 3.1.99
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/graphs/Graph.cjs +6 -0
- package/dist/cjs/graphs/Graph.cjs.map +1 -1
- package/dist/cjs/langfuseToolOutputTracing.cjs +16 -5
- package/dist/cjs/langfuseToolOutputTracing.cjs.map +1 -1
- package/dist/cjs/llm/bedrock/index.cjs +10 -0
- package/dist/cjs/llm/bedrock/index.cjs.map +1 -1
- package/dist/cjs/llm/bedrock/toolCache.cjs +125 -0
- package/dist/cjs/llm/bedrock/toolCache.cjs.map +1 -0
- package/dist/cjs/messages/cache.cjs +17 -9
- package/dist/cjs/messages/cache.cjs.map +1 -1
- package/dist/cjs/messages/prune.cjs +45 -8
- package/dist/cjs/messages/prune.cjs.map +1 -1
- package/dist/cjs/tools/ToolNode.cjs +6 -1
- package/dist/cjs/tools/ToolNode.cjs.map +1 -1
- package/dist/esm/graphs/Graph.mjs +6 -0
- package/dist/esm/graphs/Graph.mjs.map +1 -1
- package/dist/esm/langfuseToolOutputTracing.mjs +16 -5
- package/dist/esm/langfuseToolOutputTracing.mjs.map +1 -1
- package/dist/esm/llm/bedrock/index.mjs +10 -0
- package/dist/esm/llm/bedrock/index.mjs.map +1 -1
- package/dist/esm/llm/bedrock/toolCache.mjs +122 -0
- package/dist/esm/llm/bedrock/toolCache.mjs.map +1 -0
- package/dist/esm/messages/cache.mjs +17 -9
- package/dist/esm/messages/cache.mjs.map +1 -1
- package/dist/esm/messages/prune.mjs +45 -8
- package/dist/esm/messages/prune.mjs.map +1 -1
- package/dist/esm/tools/ToolNode.mjs +6 -1
- package/dist/esm/tools/ToolNode.mjs.map +1 -1
- package/dist/types/llm/bedrock/index.d.ts +16 -0
- package/dist/types/llm/bedrock/toolCache.d.ts +4 -0
- package/dist/types/messages/cache.d.ts +2 -2
- package/dist/types/types/llm.d.ts +2 -2
- package/package.json +1 -1
- package/src/agents/__tests__/AgentContext.anthropic.live.test.ts +332 -0
- package/src/agents/__tests__/AgentContext.bedrock.live.test.ts +504 -0
- package/src/graphs/Graph.ts +14 -0
- package/src/langfuseToolOutputTracing.ts +26 -7
- package/src/llm/bedrock/index.ts +32 -1
- package/src/llm/bedrock/llm.spec.ts +154 -1
- package/src/llm/bedrock/toolCache.test.ts +131 -0
- package/src/llm/bedrock/toolCache.ts +191 -0
- package/src/messages/cache.test.ts +97 -38
- package/src/messages/cache.ts +18 -10
- package/src/messages/prune.ts +55 -17
- package/src/specs/langfuse-tool-output-tracing.test.ts +28 -0
- package/src/specs/prune.test.ts +193 -0
- package/src/tools/ToolNode.ts +7 -1
- package/src/tools/__tests__/ToolNode.langfuse.test.ts +6 -0
- package/src/types/llm.ts +2 -2
|
@@ -18,14 +18,16 @@ import {
|
|
|
18
18
|
ConverseCommand,
|
|
19
19
|
ConverseStreamCommand,
|
|
20
20
|
} from '@aws-sdk/client-bedrock-runtime';
|
|
21
|
-
import type { ConverseResponse } from '@aws-sdk/client-bedrock-runtime';
|
|
21
|
+
import type { ConverseResponse, Tool } from '@aws-sdk/client-bedrock-runtime';
|
|
22
22
|
import {
|
|
23
23
|
convertConverseMessageToLangChainMessage,
|
|
24
24
|
handleConverseStreamMetadata,
|
|
25
25
|
convertToConverseMessages,
|
|
26
26
|
} from './utils';
|
|
27
|
+
import type { GraphTools } from '@/types';
|
|
27
28
|
import { toLangChainContent } from '@/messages/langchain';
|
|
28
29
|
import { CustomChatBedrockConverse, ServiceTierType } from './index';
|
|
30
|
+
import { partitionAndMarkBedrockToolCache } from './toolCache';
|
|
29
31
|
|
|
30
32
|
jest.setTimeout(120000);
|
|
31
33
|
|
|
@@ -85,6 +87,17 @@ function humanMessageWithContent(
|
|
|
85
87
|
return new HumanMessage({ content: toLangChainContent(content) });
|
|
86
88
|
}
|
|
87
89
|
|
|
90
|
+
function getBedrockToolName(entry: Tool): string {
|
|
91
|
+
if ('cachePoint' in entry) {
|
|
92
|
+
return 'cachePoint';
|
|
93
|
+
}
|
|
94
|
+
return entry.toolSpec?.name ?? 'missing';
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
function getBedrockToolNames(tools: Tool[] | undefined): string[] {
|
|
98
|
+
return (tools ?? []).map(getBedrockToolName);
|
|
99
|
+
}
|
|
100
|
+
|
|
88
101
|
describe('CustomChatBedrockConverse', () => {
|
|
89
102
|
describe('applicationInferenceProfile parameter', () => {
|
|
90
103
|
test('should initialize applicationInferenceProfile from constructor', () => {
|
|
@@ -240,6 +253,51 @@ describe('CustomChatBedrockConverse', () => {
|
|
|
240
253
|
});
|
|
241
254
|
});
|
|
242
255
|
|
|
256
|
+
describe('guardrailConfig configuration', () => {
|
|
257
|
+
test('should pass guardrailConfig through to ConverseStreamCommand', async () => {
|
|
258
|
+
const guardrailConfig = {
|
|
259
|
+
guardrailIdentifier: 'test-guardrail-id',
|
|
260
|
+
guardrailVersion: 'DRAFT',
|
|
261
|
+
trace: 'enabled_full' as const,
|
|
262
|
+
streamProcessingMode: 'sync' as const,
|
|
263
|
+
};
|
|
264
|
+
const mockSend = jest.fn<any>().mockResolvedValue({
|
|
265
|
+
stream: (async function* streamChunks() {
|
|
266
|
+
yield {
|
|
267
|
+
contentBlockDelta: {
|
|
268
|
+
contentBlockIndex: 0,
|
|
269
|
+
delta: { text: 'Guardrail response' },
|
|
270
|
+
},
|
|
271
|
+
};
|
|
272
|
+
})(),
|
|
273
|
+
});
|
|
274
|
+
|
|
275
|
+
const mockClient = {
|
|
276
|
+
send: mockSend,
|
|
277
|
+
} as unknown as BedrockRuntimeClient;
|
|
278
|
+
|
|
279
|
+
const model = new CustomChatBedrockConverse({
|
|
280
|
+
...baseConstructorArgs,
|
|
281
|
+
model: 'anthropic.claude-3-haiku-20240307-v1:0',
|
|
282
|
+
guardrailConfig,
|
|
283
|
+
client: mockClient,
|
|
284
|
+
});
|
|
285
|
+
|
|
286
|
+
let chunks = 0;
|
|
287
|
+
for await (const _chunk of await model.stream([
|
|
288
|
+
new HumanMessage('Hello'),
|
|
289
|
+
])) {
|
|
290
|
+
chunks += 1;
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
expect(mockSend).toHaveBeenCalledTimes(1);
|
|
294
|
+
expect(chunks).toBe(1);
|
|
295
|
+
const commandArg = mockSend.mock.calls[0][0] as ConverseStreamCommand;
|
|
296
|
+
expect(commandArg).toBeInstanceOf(ConverseStreamCommand);
|
|
297
|
+
expect(commandArg.input.guardrailConfig).toEqual(guardrailConfig);
|
|
298
|
+
});
|
|
299
|
+
});
|
|
300
|
+
|
|
243
301
|
describe('serviceTier configuration', () => {
|
|
244
302
|
test('should set serviceTier in constructor', () => {
|
|
245
303
|
const model = new CustomChatBedrockConverse({
|
|
@@ -313,6 +371,101 @@ describe('CustomChatBedrockConverse', () => {
|
|
|
313
371
|
});
|
|
314
372
|
});
|
|
315
373
|
|
|
374
|
+
describe('promptCache tool configuration', () => {
|
|
375
|
+
test('adds a Bedrock cache point for directly-bound tools', () => {
|
|
376
|
+
const model = new CustomChatBedrockConverse({
|
|
377
|
+
...baseConstructorArgs,
|
|
378
|
+
promptCache: true,
|
|
379
|
+
});
|
|
380
|
+
|
|
381
|
+
const params = model.invocationParams({
|
|
382
|
+
tools: [
|
|
383
|
+
{
|
|
384
|
+
type: 'function',
|
|
385
|
+
function: {
|
|
386
|
+
name: 'direct_tool',
|
|
387
|
+
description: 'Direct tool',
|
|
388
|
+
parameters: { type: 'object', properties: {} },
|
|
389
|
+
},
|
|
390
|
+
},
|
|
391
|
+
],
|
|
392
|
+
});
|
|
393
|
+
|
|
394
|
+
expect(getBedrockToolNames(params.toolConfig?.tools)).toEqual([
|
|
395
|
+
'direct_tool',
|
|
396
|
+
'cachePoint',
|
|
397
|
+
]);
|
|
398
|
+
});
|
|
399
|
+
|
|
400
|
+
test('adds the Bedrock cache point before deferred tools', () => {
|
|
401
|
+
const model = new CustomChatBedrockConverse({
|
|
402
|
+
...baseConstructorArgs,
|
|
403
|
+
promptCache: true,
|
|
404
|
+
});
|
|
405
|
+
const tools = partitionAndMarkBedrockToolCache(
|
|
406
|
+
[
|
|
407
|
+
{
|
|
408
|
+
type: 'function',
|
|
409
|
+
function: {
|
|
410
|
+
name: 'static_tool',
|
|
411
|
+
description: 'Static tool',
|
|
412
|
+
parameters: { type: 'object', properties: {} },
|
|
413
|
+
},
|
|
414
|
+
},
|
|
415
|
+
{
|
|
416
|
+
type: 'function',
|
|
417
|
+
function: {
|
|
418
|
+
name: 'deferred_tool',
|
|
419
|
+
description: 'Deferred tool',
|
|
420
|
+
parameters: { type: 'object', properties: {} },
|
|
421
|
+
},
|
|
422
|
+
},
|
|
423
|
+
] as GraphTools,
|
|
424
|
+
(name) => name === 'deferred_tool'
|
|
425
|
+
);
|
|
426
|
+
|
|
427
|
+
const params = model.invocationParams({ tools });
|
|
428
|
+
|
|
429
|
+
expect(getBedrockToolNames(params.toolConfig?.tools)).toEqual([
|
|
430
|
+
'static_tool',
|
|
431
|
+
'cachePoint',
|
|
432
|
+
'deferred_tool',
|
|
433
|
+
]);
|
|
434
|
+
expect(JSON.stringify(params.toolConfig?.tools)).not.toContain(
|
|
435
|
+
'__lc_bedrock_cache_point_after'
|
|
436
|
+
);
|
|
437
|
+
});
|
|
438
|
+
|
|
439
|
+
test('does not fall back to caching when Graph marks all tools deferred', () => {
|
|
440
|
+
const model = new CustomChatBedrockConverse({
|
|
441
|
+
...baseConstructorArgs,
|
|
442
|
+
promptCache: true,
|
|
443
|
+
});
|
|
444
|
+
const tools = partitionAndMarkBedrockToolCache(
|
|
445
|
+
[
|
|
446
|
+
{
|
|
447
|
+
type: 'function',
|
|
448
|
+
function: {
|
|
449
|
+
name: 'deferred_tool',
|
|
450
|
+
description: 'Deferred tool',
|
|
451
|
+
parameters: { type: 'object', properties: {} },
|
|
452
|
+
},
|
|
453
|
+
},
|
|
454
|
+
] as GraphTools,
|
|
455
|
+
() => true
|
|
456
|
+
);
|
|
457
|
+
|
|
458
|
+
const params = model.invocationParams({ tools });
|
|
459
|
+
|
|
460
|
+
expect(getBedrockToolNames(params.toolConfig?.tools)).toEqual([
|
|
461
|
+
'deferred_tool',
|
|
462
|
+
]);
|
|
463
|
+
expect(JSON.stringify(params.toolConfig?.tools)).not.toContain(
|
|
464
|
+
'__lc_bedrock_skip_tool_cache'
|
|
465
|
+
);
|
|
466
|
+
});
|
|
467
|
+
});
|
|
468
|
+
|
|
316
469
|
describe('contentBlockIndex cleanup', () => {
|
|
317
470
|
// Access private methods for testing via any cast
|
|
318
471
|
function getModelWithCleanMethods() {
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
import { tool } from '@langchain/core/tools';
|
|
2
|
+
import type { Tool } from '@aws-sdk/client-bedrock-runtime';
|
|
3
|
+
import type { GraphTools } from '@/types';
|
|
4
|
+
import {
|
|
5
|
+
insertBedrockToolCachePoint,
|
|
6
|
+
partitionAndMarkBedrockToolCache,
|
|
7
|
+
} from './toolCache';
|
|
8
|
+
|
|
9
|
+
type OpenAITool = {
|
|
10
|
+
type: 'function';
|
|
11
|
+
function: {
|
|
12
|
+
name: string;
|
|
13
|
+
description?: string;
|
|
14
|
+
parameters?: object;
|
|
15
|
+
};
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
function createOpenAITool(name: string): OpenAITool {
|
|
19
|
+
return {
|
|
20
|
+
type: 'function',
|
|
21
|
+
function: {
|
|
22
|
+
name,
|
|
23
|
+
description: `${name} description`,
|
|
24
|
+
parameters: {
|
|
25
|
+
type: 'object',
|
|
26
|
+
properties: {},
|
|
27
|
+
},
|
|
28
|
+
},
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
function toolName(entry: Tool): string {
|
|
33
|
+
if ('cachePoint' in entry) {
|
|
34
|
+
return 'cachePoint';
|
|
35
|
+
}
|
|
36
|
+
return entry.toolSpec?.name ?? 'missing';
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
function toolNames(tools: Tool[] | undefined): string[] {
|
|
40
|
+
return (tools ?? []).map(toolName);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
describe('partitionAndMarkBedrockToolCache', () => {
|
|
44
|
+
it('inserts the Bedrock cache point after the last static tool', () => {
|
|
45
|
+
const tools = [
|
|
46
|
+
createOpenAITool('static_one'),
|
|
47
|
+
createOpenAITool('static_two'),
|
|
48
|
+
createOpenAITool('dynamic_one'),
|
|
49
|
+
] as GraphTools;
|
|
50
|
+
|
|
51
|
+
const marked = partitionAndMarkBedrockToolCache(
|
|
52
|
+
tools,
|
|
53
|
+
(name) => name === 'dynamic_one'
|
|
54
|
+
) as Tool[];
|
|
55
|
+
const result = insertBedrockToolCachePoint({ tools: marked }, false);
|
|
56
|
+
|
|
57
|
+
expect(toolNames(result?.tools)).toEqual([
|
|
58
|
+
'static_one',
|
|
59
|
+
'static_two',
|
|
60
|
+
'cachePoint',
|
|
61
|
+
'dynamic_one',
|
|
62
|
+
]);
|
|
63
|
+
expect(JSON.stringify(result?.tools)).not.toContain(
|
|
64
|
+
'__lc_bedrock_cache_point_after'
|
|
65
|
+
);
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
it('converts LangChain tools to Bedrock tool specs before marking', () => {
|
|
69
|
+
const staticTool = tool(async () => 'static', {
|
|
70
|
+
name: 'static_tool',
|
|
71
|
+
description: 'Static tool',
|
|
72
|
+
schema: {
|
|
73
|
+
type: 'object',
|
|
74
|
+
properties: {},
|
|
75
|
+
},
|
|
76
|
+
});
|
|
77
|
+
const dynamicTool = tool(async () => 'dynamic', {
|
|
78
|
+
name: 'dynamic_tool',
|
|
79
|
+
description: 'Dynamic tool',
|
|
80
|
+
schema: {
|
|
81
|
+
type: 'object',
|
|
82
|
+
properties: {},
|
|
83
|
+
},
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
const marked = partitionAndMarkBedrockToolCache(
|
|
87
|
+
[dynamicTool, staticTool] as GraphTools,
|
|
88
|
+
(name) => name === 'dynamic_tool'
|
|
89
|
+
) as Tool[];
|
|
90
|
+
const result = insertBedrockToolCachePoint({ tools: marked }, false);
|
|
91
|
+
|
|
92
|
+
expect(toolNames(result?.tools)).toEqual([
|
|
93
|
+
'static_tool',
|
|
94
|
+
'cachePoint',
|
|
95
|
+
'dynamic_tool',
|
|
96
|
+
]);
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
it('does not add a cache point when every tool is deferred', () => {
|
|
100
|
+
const tools = [createOpenAITool('dynamic_one')] as GraphTools;
|
|
101
|
+
const marked = partitionAndMarkBedrockToolCache(
|
|
102
|
+
tools,
|
|
103
|
+
() => true
|
|
104
|
+
) as Tool[];
|
|
105
|
+
const result = insertBedrockToolCachePoint({ tools: marked }, false);
|
|
106
|
+
|
|
107
|
+
expect(toolNames(result?.tools)).toEqual(['dynamic_one']);
|
|
108
|
+
expect(JSON.stringify(result?.tools)).not.toContain(
|
|
109
|
+
'__lc_bedrock_skip_tool_cache'
|
|
110
|
+
);
|
|
111
|
+
});
|
|
112
|
+
|
|
113
|
+
it('can fall back to caching all directly-bound tools', () => {
|
|
114
|
+
const result = insertBedrockToolCachePoint(
|
|
115
|
+
{
|
|
116
|
+
tools: [
|
|
117
|
+
{
|
|
118
|
+
toolSpec: {
|
|
119
|
+
name: 'direct_tool',
|
|
120
|
+
description: 'Direct tool',
|
|
121
|
+
inputSchema: { json: { type: 'object', properties: {} } },
|
|
122
|
+
},
|
|
123
|
+
},
|
|
124
|
+
],
|
|
125
|
+
},
|
|
126
|
+
true
|
|
127
|
+
);
|
|
128
|
+
|
|
129
|
+
expect(toolNames(result?.tools)).toEqual(['direct_tool', 'cachePoint']);
|
|
130
|
+
});
|
|
131
|
+
});
|
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
import type { Tool, ToolConfiguration } from '@aws-sdk/client-bedrock-runtime';
|
|
2
|
+
import type { BindToolsInput } from '@langchain/core/language_models/chat_models';
|
|
3
|
+
import type { OpenAIClient } from '@langchain/openai';
|
|
4
|
+
import type { DocumentType } from '@smithy/types';
|
|
5
|
+
import type { GraphTools } from '@/types';
|
|
6
|
+
import { _convertToOpenAITool } from '@/llm/openai';
|
|
7
|
+
|
|
8
|
+
const CACHE_POINT: Tool.CachePointMember = {
|
|
9
|
+
cachePoint: { type: 'default' },
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
const BEDROCK_TOOL_CACHE_MARKER = '__lc_bedrock_cache_point_after';
|
|
13
|
+
const BEDROCK_TOOL_CACHE_DISABLED_MARKER = '__lc_bedrock_skip_tool_cache';
|
|
14
|
+
|
|
15
|
+
type BedrockToolWithCacheMarker = Tool & {
|
|
16
|
+
[BEDROCK_TOOL_CACHE_MARKER]?: true;
|
|
17
|
+
[BEDROCK_TOOL_CACHE_DISABLED_MARKER]?: true;
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
type OpenAIFunctionTool = Extract<
|
|
21
|
+
OpenAIClient.ChatCompletionTool,
|
|
22
|
+
{ type: 'function' }
|
|
23
|
+
>;
|
|
24
|
+
|
|
25
|
+
type ToolNameCandidate = {
|
|
26
|
+
name?: unknown;
|
|
27
|
+
function?: {
|
|
28
|
+
name?: unknown;
|
|
29
|
+
};
|
|
30
|
+
toolSpec?: {
|
|
31
|
+
name?: unknown;
|
|
32
|
+
};
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
function isBedrockToolSpec(tool: unknown): tool is Tool.ToolSpecMember {
|
|
36
|
+
return (
|
|
37
|
+
typeof tool === 'object' &&
|
|
38
|
+
tool != null &&
|
|
39
|
+
'toolSpec' in tool &&
|
|
40
|
+
typeof (tool as ToolNameCandidate).toolSpec?.name === 'string'
|
|
41
|
+
);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
function isBedrockCachePoint(tool: Tool): tool is Tool.CachePointMember {
|
|
45
|
+
return 'cachePoint' in tool && tool.cachePoint != null;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
function getToolName(tool: unknown): string | undefined {
|
|
49
|
+
const candidate = tool as ToolNameCandidate;
|
|
50
|
+
if (typeof candidate.toolSpec?.name === 'string') {
|
|
51
|
+
return candidate.toolSpec.name;
|
|
52
|
+
}
|
|
53
|
+
if (typeof candidate.name === 'string') {
|
|
54
|
+
return candidate.name;
|
|
55
|
+
}
|
|
56
|
+
if (typeof candidate.function?.name === 'string') {
|
|
57
|
+
return candidate.function.name;
|
|
58
|
+
}
|
|
59
|
+
return undefined;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
function openAIToBedrockTool(tool: OpenAIFunctionTool): Tool.ToolSpecMember {
|
|
63
|
+
return {
|
|
64
|
+
toolSpec: {
|
|
65
|
+
name: tool.function.name,
|
|
66
|
+
description: tool.function.description,
|
|
67
|
+
inputSchema: { json: tool.function.parameters as DocumentType },
|
|
68
|
+
},
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
function toBedrockTool(tool: unknown): BedrockToolWithCacheMarker {
|
|
73
|
+
if (isBedrockToolSpec(tool)) {
|
|
74
|
+
return { ...tool };
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
return openAIToBedrockTool(
|
|
78
|
+
_convertToOpenAITool(tool as BindToolsInput) as OpenAIFunctionTool
|
|
79
|
+
) as BedrockToolWithCacheMarker;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
function markCachePointAfter(
|
|
83
|
+
tool: BedrockToolWithCacheMarker
|
|
84
|
+
): BedrockToolWithCacheMarker {
|
|
85
|
+
return {
|
|
86
|
+
...tool,
|
|
87
|
+
[BEDROCK_TOOL_CACHE_MARKER]: true,
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
function markToolCacheDisabled(
|
|
92
|
+
tool: BedrockToolWithCacheMarker
|
|
93
|
+
): BedrockToolWithCacheMarker {
|
|
94
|
+
return {
|
|
95
|
+
...tool,
|
|
96
|
+
[BEDROCK_TOOL_CACHE_DISABLED_MARKER]: true,
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
function stripCachePointMarker(tool: BedrockToolWithCacheMarker): Tool {
|
|
101
|
+
const {
|
|
102
|
+
[BEDROCK_TOOL_CACHE_MARKER]: _marker,
|
|
103
|
+
[BEDROCK_TOOL_CACHE_DISABLED_MARKER]: _disabled,
|
|
104
|
+
...rest
|
|
105
|
+
} = tool;
|
|
106
|
+
return rest as Tool;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
export function partitionAndMarkBedrockToolCache(
|
|
110
|
+
tools: GraphTools | undefined,
|
|
111
|
+
isDeferred: (toolName: string) => boolean
|
|
112
|
+
): GraphTools | undefined {
|
|
113
|
+
if (tools == null || tools.length === 0) {
|
|
114
|
+
return tools;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
const staticTools: BedrockToolWithCacheMarker[] = [];
|
|
118
|
+
const deferredTools: BedrockToolWithCacheMarker[] = [];
|
|
119
|
+
|
|
120
|
+
for (const tool of tools as readonly unknown[]) {
|
|
121
|
+
const converted = toBedrockTool(tool);
|
|
122
|
+
const name = getToolName(converted) ?? getToolName(tool);
|
|
123
|
+
|
|
124
|
+
if (name != null && isDeferred(name)) {
|
|
125
|
+
deferredTools.push(converted);
|
|
126
|
+
continue;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
staticTools.push(converted);
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
if (staticTools.length === 0) {
|
|
133
|
+
deferredTools[0] = markToolCacheDisabled(deferredTools[0]);
|
|
134
|
+
return [...deferredTools] as GraphTools;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
staticTools[staticTools.length - 1] = markCachePointAfter(
|
|
138
|
+
staticTools[staticTools.length - 1]
|
|
139
|
+
);
|
|
140
|
+
|
|
141
|
+
return [...staticTools, ...deferredTools] as GraphTools;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
export function insertBedrockToolCachePoint(
|
|
145
|
+
toolConfig: ToolConfiguration | undefined,
|
|
146
|
+
fallbackToEnd: boolean
|
|
147
|
+
): ToolConfiguration | undefined {
|
|
148
|
+
const tools = toolConfig?.tools as BedrockToolWithCacheMarker[] | undefined;
|
|
149
|
+
if (tools == null || tools.length === 0) {
|
|
150
|
+
return toolConfig;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
let markerIndex = -1;
|
|
154
|
+
let hasCachePoint = false;
|
|
155
|
+
let hasDisabledMarker = false;
|
|
156
|
+
const cleanedTools: Tool[] = [];
|
|
157
|
+
|
|
158
|
+
for (let i = 0; i < tools.length; i++) {
|
|
159
|
+
const tool = tools[i];
|
|
160
|
+
if (isBedrockCachePoint(tool)) {
|
|
161
|
+
hasCachePoint = true;
|
|
162
|
+
cleanedTools.push(tool);
|
|
163
|
+
continue;
|
|
164
|
+
}
|
|
165
|
+
if (tool[BEDROCK_TOOL_CACHE_MARKER] === true) {
|
|
166
|
+
markerIndex = cleanedTools.length;
|
|
167
|
+
}
|
|
168
|
+
if (tool[BEDROCK_TOOL_CACHE_DISABLED_MARKER] === true) {
|
|
169
|
+
hasDisabledMarker = true;
|
|
170
|
+
}
|
|
171
|
+
cleanedTools.push(stripCachePointMarker(tool));
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
if (hasCachePoint || hasDisabledMarker) {
|
|
175
|
+
return { ...toolConfig, tools: cleanedTools };
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
const insertionIndex = markerIndex >= 0 ? markerIndex : tools.length - 1;
|
|
179
|
+
if (markerIndex < 0 && !fallbackToEnd) {
|
|
180
|
+
return { ...toolConfig, tools: cleanedTools };
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
return {
|
|
184
|
+
...toolConfig,
|
|
185
|
+
tools: [
|
|
186
|
+
...cleanedTools.slice(0, insertionIndex + 1),
|
|
187
|
+
CACHE_POINT,
|
|
188
|
+
...cleanedTools.slice(insertionIndex + 1),
|
|
189
|
+
],
|
|
190
|
+
};
|
|
191
|
+
}
|