@librechat/agents 3.1.50 → 3.1.52
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 +43 -16
- package/dist/cjs/graphs/Graph.cjs.map +1 -1
- package/dist/cjs/messages/format.cjs +8 -1
- package/dist/cjs/messages/format.cjs.map +1 -1
- package/dist/cjs/run.cjs +32 -2
- package/dist/cjs/run.cjs.map +1 -1
- package/dist/cjs/utils/run.cjs +3 -1
- package/dist/cjs/utils/run.cjs.map +1 -1
- package/dist/esm/graphs/Graph.mjs +43 -16
- package/dist/esm/graphs/Graph.mjs.map +1 -1
- package/dist/esm/messages/format.mjs +8 -1
- package/dist/esm/messages/format.mjs.map +1 -1
- package/dist/esm/run.mjs +32 -2
- package/dist/esm/run.mjs.map +1 -1
- package/dist/esm/utils/run.mjs +3 -1
- package/dist/esm/utils/run.mjs.map +1 -1
- package/dist/types/graphs/Graph.d.ts +7 -0
- package/dist/types/run.d.ts +1 -0
- package/dist/types/types/run.d.ts +2 -0
- package/package.json +1 -1
- package/src/graphs/Graph.ts +49 -20
- package/src/messages/format.ts +12 -1
- package/src/messages/formatAgentMessages.test.ts +184 -0
- package/src/run.ts +40 -2
- package/src/scripts/ant_web_search.ts +1 -0
- package/src/scripts/ant_web_search_edge_case.ts +1 -0
- package/src/scripts/ant_web_search_error_edge_case.ts +1 -0
- package/src/scripts/bedrock-content-aggregation-test.ts +1 -0
- package/src/scripts/bedrock-parallel-tools-test.ts +1 -0
- package/src/scripts/caching.ts +1 -0
- package/src/scripts/code_exec.ts +1 -0
- package/src/scripts/code_exec_files.ts +1 -0
- package/src/scripts/code_exec_multi_session.ts +1 -0
- package/src/scripts/code_exec_ptc.ts +1 -0
- package/src/scripts/code_exec_session.ts +1 -0
- package/src/scripts/code_exec_simple.ts +1 -0
- package/src/scripts/content.ts +1 -0
- package/src/scripts/image.ts +1 -0
- package/src/scripts/memory.ts +16 -6
- package/src/scripts/multi-agent-chain.ts +1 -0
- package/src/scripts/multi-agent-conditional.ts +1 -0
- package/src/scripts/multi-agent-document-review-chain.ts +1 -0
- package/src/scripts/multi-agent-hybrid-flow.ts +1 -0
- package/src/scripts/multi-agent-parallel-start.ts +1 -0
- package/src/scripts/multi-agent-parallel.ts +1 -0
- package/src/scripts/multi-agent-sequence.ts +1 -0
- package/src/scripts/multi-agent-supervisor.ts +1 -0
- package/src/scripts/multi-agent-test.ts +1 -0
- package/src/scripts/parallel-asymmetric-tools-test.ts +1 -0
- package/src/scripts/parallel-full-metadata-test.ts +1 -0
- package/src/scripts/parallel-tools-test.ts +1 -0
- package/src/scripts/programmatic_exec_agent.ts +1 -0
- package/src/scripts/search.ts +1 -0
- package/src/scripts/sequential-full-metadata-test.ts +1 -0
- package/src/scripts/simple.ts +2 -1
- package/src/scripts/single-agent-metadata-test.ts +1 -0
- package/src/scripts/stream.ts +1 -0
- package/src/scripts/test-handoff-preamble.ts +1 -0
- package/src/scripts/test-handoff-steering.ts +3 -0
- package/src/scripts/test-multi-agent-list-handoff.ts +1 -0
- package/src/scripts/test-parallel-agent-labeling.ts +2 -0
- package/src/scripts/test-parallel-handoffs.ts +1 -0
- package/src/scripts/test-thinking-handoff-bedrock.ts +1 -0
- package/src/scripts/test-thinking-handoff.ts +1 -0
- package/src/scripts/test-thinking-to-thinking-handoff-bedrock.ts +1 -0
- package/src/scripts/test-tool-before-handoff-role-order.ts +1 -0
- package/src/scripts/test-tools-before-handoff.ts +1 -0
- package/src/scripts/thinking-bedrock.ts +1 -0
- package/src/scripts/thinking.ts +1 -0
- package/src/scripts/tools.ts +1 -0
- package/src/specs/agent-handoffs.test.ts +1 -0
- package/src/specs/anthropic.simple.test.ts +6 -2
- package/src/specs/azure.simple.test.ts +142 -3
- package/src/specs/cache.simple.test.ts +8 -0
- package/src/specs/custom-event-await.test.ts +2 -0
- package/src/specs/deepseek.simple.test.ts +3 -0
- package/src/specs/moonshot.simple.test.ts +5 -0
- package/src/specs/openai.simple.test.ts +3 -0
- package/src/specs/openrouter.simple.test.ts +1 -0
- package/src/specs/prune.test.ts +1 -0
- package/src/specs/reasoning.test.ts +1 -0
- package/src/specs/thinking-handoff.test.ts +1 -0
- package/src/specs/tool-error.test.ts +1 -0
- package/src/types/run.ts +2 -0
- package/src/utils/run.ts +4 -2
package/src/graphs/Graph.ts
CHANGED
|
@@ -139,6 +139,26 @@ export abstract class Graph<
|
|
|
139
139
|
* Currently supports code execution session tracking (session_id, files).
|
|
140
140
|
*/
|
|
141
141
|
sessions: t.ToolSessionMap = new Map();
|
|
142
|
+
|
|
143
|
+
/**
|
|
144
|
+
* Clears heavy references to allow GC to reclaim memory held by
|
|
145
|
+
* LangGraph's internal config / AsyncLocalStorage RunTree chain.
|
|
146
|
+
* Call after a run completes and content has been extracted.
|
|
147
|
+
*/
|
|
148
|
+
clearHeavyState(): void {
|
|
149
|
+
this.config = undefined;
|
|
150
|
+
this.signal = undefined;
|
|
151
|
+
this.contentData = [];
|
|
152
|
+
this.contentIndexMap = new Map();
|
|
153
|
+
this.stepKeyIds = new Map();
|
|
154
|
+
this.toolCallStepIds.clear();
|
|
155
|
+
this.messageIdsByStepKey = new Map();
|
|
156
|
+
this.messageStepHasToolCalls = new Map();
|
|
157
|
+
this.prelimMessageIdsByStepKey = new Map();
|
|
158
|
+
this.invokedToolIds = undefined;
|
|
159
|
+
this.handlerRegistry = undefined;
|
|
160
|
+
this.sessions.clear();
|
|
161
|
+
}
|
|
142
162
|
}
|
|
143
163
|
|
|
144
164
|
export class StandardGraph extends Graph<t.BaseGraphState, t.GraphNode> {
|
|
@@ -218,6 +238,15 @@ export class StandardGraph extends Graph<t.BaseGraphState, t.GraphNode> {
|
|
|
218
238
|
}
|
|
219
239
|
}
|
|
220
240
|
|
|
241
|
+
override clearHeavyState(): void {
|
|
242
|
+
super.clearHeavyState();
|
|
243
|
+
this.messages = [];
|
|
244
|
+
this.overrideModel = undefined;
|
|
245
|
+
for (const context of this.agentContexts.values()) {
|
|
246
|
+
context.reset();
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
|
|
221
250
|
/* Run Step Processing */
|
|
222
251
|
|
|
223
252
|
getRunStep(stepId: string): t.RunStep | undefined {
|
|
@@ -1039,26 +1068,26 @@ export class StandardGraph extends Graph<t.BaseGraphState, t.GraphNode> {
|
|
|
1039
1068
|
},
|
|
1040
1069
|
metadata
|
|
1041
1070
|
);
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
}
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
)
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
}
|
|
1071
|
+
const stepId = this.getStepIdByKey(stepKey);
|
|
1072
|
+
const content = responseMessage.content;
|
|
1073
|
+
if (typeof content === 'string') {
|
|
1074
|
+
await this.dispatchMessageDelta(stepId, {
|
|
1075
|
+
content: [{ type: ContentTypes.TEXT, text: content }],
|
|
1076
|
+
});
|
|
1077
|
+
} else if (
|
|
1078
|
+
Array.isArray(content) &&
|
|
1079
|
+
content.every(
|
|
1080
|
+
(c) =>
|
|
1081
|
+
typeof c === 'object' &&
|
|
1082
|
+
'type' in c &&
|
|
1083
|
+
typeof c.type === 'string' &&
|
|
1084
|
+
c.type.startsWith('text')
|
|
1085
|
+
)
|
|
1086
|
+
) {
|
|
1087
|
+
await this.dispatchMessageDelta(stepId, {
|
|
1088
|
+
content: content as t.MessageDelta['content'],
|
|
1089
|
+
});
|
|
1090
|
+
}
|
|
1062
1091
|
}
|
|
1063
1092
|
}
|
|
1064
1093
|
|
package/src/messages/format.ts
CHANGED
|
@@ -371,7 +371,12 @@ function formatAssistantMessage(
|
|
|
371
371
|
content: output != null ? output : '',
|
|
372
372
|
})
|
|
373
373
|
);
|
|
374
|
-
} else if (
|
|
374
|
+
} else if (
|
|
375
|
+
part.type === ContentTypes.THINK ||
|
|
376
|
+
part.type === ContentTypes.THINKING ||
|
|
377
|
+
part.type === ContentTypes.REASONING_CONTENT ||
|
|
378
|
+
part.type === 'redacted_thinking'
|
|
379
|
+
) {
|
|
375
380
|
hasReasoning = true;
|
|
376
381
|
continue;
|
|
377
382
|
} else if (
|
|
@@ -380,6 +385,12 @@ function formatAssistantMessage(
|
|
|
380
385
|
) {
|
|
381
386
|
continue;
|
|
382
387
|
} else {
|
|
388
|
+
if (
|
|
389
|
+
part.type === ContentTypes.TEXT &&
|
|
390
|
+
!String(part.text ?? '').trim()
|
|
391
|
+
) {
|
|
392
|
+
continue;
|
|
393
|
+
}
|
|
383
394
|
currentContent.push(part);
|
|
384
395
|
}
|
|
385
396
|
}
|
|
@@ -829,6 +829,190 @@ describe('formatAgentMessages', () => {
|
|
|
829
829
|
);
|
|
830
830
|
});
|
|
831
831
|
|
|
832
|
+
it('should strip reasoning_content blocks and join TEXT parts as string', () => {
|
|
833
|
+
const payload = [
|
|
834
|
+
{
|
|
835
|
+
role: 'assistant',
|
|
836
|
+
content: [
|
|
837
|
+
{ type: ContentTypes.TEXT, [ContentTypes.TEXT]: '\n\n' },
|
|
838
|
+
{
|
|
839
|
+
type: ContentTypes.REASONING_CONTENT,
|
|
840
|
+
reasoningText: { text: 'Thinking deeply...', signature: 'sig123' },
|
|
841
|
+
index: 0,
|
|
842
|
+
},
|
|
843
|
+
{ type: ContentTypes.TEXT, [ContentTypes.TEXT]: 'The answer is 42.' },
|
|
844
|
+
],
|
|
845
|
+
},
|
|
846
|
+
];
|
|
847
|
+
|
|
848
|
+
const result = formatAgentMessages(payload);
|
|
849
|
+
|
|
850
|
+
expect(result.messages).toHaveLength(1);
|
|
851
|
+
expect(result.messages[0]).toBeInstanceOf(AIMessage);
|
|
852
|
+
expect(result.messages[0].content).toBe('The answer is 42.');
|
|
853
|
+
expect(JSON.stringify(result.messages[0].content)).not.toContain(
|
|
854
|
+
'reasoning_content'
|
|
855
|
+
);
|
|
856
|
+
});
|
|
857
|
+
|
|
858
|
+
it('should strip thinking blocks and join TEXT parts as string', () => {
|
|
859
|
+
const payload = [
|
|
860
|
+
{
|
|
861
|
+
role: 'assistant',
|
|
862
|
+
content: [
|
|
863
|
+
{
|
|
864
|
+
type: ContentTypes.THINKING,
|
|
865
|
+
thinking: 'Internal reasoning...',
|
|
866
|
+
signature: 'sig456',
|
|
867
|
+
},
|
|
868
|
+
{
|
|
869
|
+
type: ContentTypes.TEXT,
|
|
870
|
+
[ContentTypes.TEXT]: 'Here is my answer.',
|
|
871
|
+
},
|
|
872
|
+
],
|
|
873
|
+
},
|
|
874
|
+
];
|
|
875
|
+
|
|
876
|
+
const result = formatAgentMessages(payload);
|
|
877
|
+
|
|
878
|
+
expect(result.messages).toHaveLength(1);
|
|
879
|
+
expect(result.messages[0]).toBeInstanceOf(AIMessage);
|
|
880
|
+
expect(result.messages[0].content).toBe('Here is my answer.');
|
|
881
|
+
expect(JSON.stringify(result.messages[0].content)).not.toContain(
|
|
882
|
+
'thinking'
|
|
883
|
+
);
|
|
884
|
+
});
|
|
885
|
+
|
|
886
|
+
it('should strip redacted_thinking blocks and join TEXT parts as string', () => {
|
|
887
|
+
const payload = [
|
|
888
|
+
{
|
|
889
|
+
role: 'assistant',
|
|
890
|
+
content: [
|
|
891
|
+
{ type: 'redacted_thinking', data: 'REDACTED_SIGNATURE' },
|
|
892
|
+
{
|
|
893
|
+
type: ContentTypes.TEXT,
|
|
894
|
+
[ContentTypes.TEXT]: 'Here is my answer.',
|
|
895
|
+
},
|
|
896
|
+
],
|
|
897
|
+
},
|
|
898
|
+
];
|
|
899
|
+
|
|
900
|
+
const result = formatAgentMessages(payload);
|
|
901
|
+
|
|
902
|
+
expect(result.messages).toHaveLength(1);
|
|
903
|
+
expect(result.messages[0]).toBeInstanceOf(AIMessage);
|
|
904
|
+
expect(result.messages[0].content).toBe('Here is my answer.');
|
|
905
|
+
expect(JSON.stringify(result.messages[0].content)).not.toContain(
|
|
906
|
+
'redacted_thinking'
|
|
907
|
+
);
|
|
908
|
+
});
|
|
909
|
+
|
|
910
|
+
it('should produce no AIMessage when only reasoning_content and whitespace text are present', () => {
|
|
911
|
+
const payload = [
|
|
912
|
+
{
|
|
913
|
+
role: 'assistant',
|
|
914
|
+
content: [
|
|
915
|
+
{ type: ContentTypes.TEXT, [ContentTypes.TEXT]: '\n\n' },
|
|
916
|
+
{
|
|
917
|
+
type: ContentTypes.REASONING_CONTENT,
|
|
918
|
+
reasoningText: { text: 'Silent reasoning', signature: 'sig' },
|
|
919
|
+
},
|
|
920
|
+
],
|
|
921
|
+
},
|
|
922
|
+
];
|
|
923
|
+
|
|
924
|
+
const result = formatAgentMessages(payload);
|
|
925
|
+
|
|
926
|
+
expect(result.messages).toHaveLength(0);
|
|
927
|
+
});
|
|
928
|
+
|
|
929
|
+
it('should drop whitespace-only text parts from non-reasoning messages', () => {
|
|
930
|
+
const payload = [
|
|
931
|
+
{
|
|
932
|
+
role: 'assistant',
|
|
933
|
+
content: [
|
|
934
|
+
{ type: ContentTypes.TEXT, [ContentTypes.TEXT]: '\n\n' },
|
|
935
|
+
{
|
|
936
|
+
type: ContentTypes.TEXT,
|
|
937
|
+
[ContentTypes.TEXT]: 'Actual content here.',
|
|
938
|
+
},
|
|
939
|
+
{ type: ContentTypes.TEXT, [ContentTypes.TEXT]: ' ' },
|
|
940
|
+
],
|
|
941
|
+
},
|
|
942
|
+
];
|
|
943
|
+
|
|
944
|
+
const result = formatAgentMessages(payload);
|
|
945
|
+
|
|
946
|
+
expect(result.messages).toHaveLength(1);
|
|
947
|
+
expect(result.messages[0]).toBeInstanceOf(AIMessage);
|
|
948
|
+
const content = result.messages[0].content;
|
|
949
|
+
expect(Array.isArray(content)).toBe(true);
|
|
950
|
+
expect(
|
|
951
|
+
(content as { type: string; text?: string }[]).every(
|
|
952
|
+
(p) => (p.text ?? '').trim() !== ''
|
|
953
|
+
)
|
|
954
|
+
).toBe(true);
|
|
955
|
+
});
|
|
956
|
+
|
|
957
|
+
it('should preserve whitespace-only text that has tool_call_ids (common Bedrock pattern)', () => {
|
|
958
|
+
const payload = [
|
|
959
|
+
{
|
|
960
|
+
role: 'assistant',
|
|
961
|
+
content: [
|
|
962
|
+
{
|
|
963
|
+
type: ContentTypes.TEXT,
|
|
964
|
+
[ContentTypes.TEXT]: '\n\n',
|
|
965
|
+
tool_call_ids: ['tc-1'],
|
|
966
|
+
},
|
|
967
|
+
{
|
|
968
|
+
type: ContentTypes.TOOL_CALL,
|
|
969
|
+
tool_call: {
|
|
970
|
+
id: 'tc-1',
|
|
971
|
+
name: 'search',
|
|
972
|
+
args: '{"query":"test"}',
|
|
973
|
+
output: 'Results here',
|
|
974
|
+
},
|
|
975
|
+
},
|
|
976
|
+
],
|
|
977
|
+
},
|
|
978
|
+
];
|
|
979
|
+
|
|
980
|
+
const result = formatAgentMessages(payload);
|
|
981
|
+
|
|
982
|
+
expect(result.messages).toHaveLength(2);
|
|
983
|
+
expect(result.messages[0]).toBeInstanceOf(AIMessage);
|
|
984
|
+
expect(result.messages[1]).toBeInstanceOf(ToolMessage);
|
|
985
|
+
expect((result.messages[0] as AIMessage).tool_calls).toHaveLength(1);
|
|
986
|
+
expect((result.messages[1] as ToolMessage).tool_call_id).toBe('tc-1');
|
|
987
|
+
});
|
|
988
|
+
|
|
989
|
+
it('should handle whitespace-only text without tool_call_ids before a tool call', () => {
|
|
990
|
+
const payload = [
|
|
991
|
+
{
|
|
992
|
+
role: 'assistant',
|
|
993
|
+
content: [
|
|
994
|
+
{ type: ContentTypes.TEXT, [ContentTypes.TEXT]: '\n\n' },
|
|
995
|
+
{
|
|
996
|
+
type: ContentTypes.TOOL_CALL,
|
|
997
|
+
tool_call: {
|
|
998
|
+
id: 'tc-2',
|
|
999
|
+
name: 'search',
|
|
1000
|
+
args: '{"query":"test"}',
|
|
1001
|
+
output: 'Results here',
|
|
1002
|
+
},
|
|
1003
|
+
},
|
|
1004
|
+
],
|
|
1005
|
+
},
|
|
1006
|
+
];
|
|
1007
|
+
|
|
1008
|
+
const result = formatAgentMessages(payload);
|
|
1009
|
+
|
|
1010
|
+
expect(result.messages).toHaveLength(2);
|
|
1011
|
+
expect(result.messages[0]).toBeInstanceOf(AIMessage);
|
|
1012
|
+
expect(result.messages[1]).toBeInstanceOf(ToolMessage);
|
|
1013
|
+
expect((result.messages[0] as AIMessage).tool_calls).toHaveLength(1);
|
|
1014
|
+
});
|
|
1015
|
+
|
|
832
1016
|
it('should exclude ERROR type content parts', () => {
|
|
833
1017
|
const payload = [
|
|
834
1018
|
{
|
package/src/run.ts
CHANGED
|
@@ -45,6 +45,7 @@ export class Run<_T extends t.BaseGraphState> {
|
|
|
45
45
|
graphRunnable?: t.CompiledStateWorkflow;
|
|
46
46
|
Graph: StandardGraph | MultiAgentGraph | undefined;
|
|
47
47
|
returnContent: boolean = false;
|
|
48
|
+
private skipCleanup: boolean = false;
|
|
48
49
|
|
|
49
50
|
private constructor(config: Partial<t.RunConfig>) {
|
|
50
51
|
const runId = config.runId ?? '';
|
|
@@ -89,6 +90,7 @@ export class Run<_T extends t.BaseGraphState> {
|
|
|
89
90
|
}
|
|
90
91
|
|
|
91
92
|
this.returnContent = config.returnContent ?? false;
|
|
93
|
+
this.skipCleanup = config.skipCleanup ?? false;
|
|
92
94
|
}
|
|
93
95
|
|
|
94
96
|
private createLegacyGraph(
|
|
@@ -303,9 +305,45 @@ export class Run<_T extends t.BaseGraphState> {
|
|
|
303
305
|
}
|
|
304
306
|
}
|
|
305
307
|
|
|
306
|
-
|
|
307
|
-
|
|
308
|
+
/**
|
|
309
|
+
* Break the reference chain that keeps heavy data alive via
|
|
310
|
+
* LangGraph's internal `__pregel_scratchpad.currentTaskInput` →
|
|
311
|
+
* `@langchain/core` `RunTree.extra[lc:child_config]` →
|
|
312
|
+
* Node.js `AsyncLocalStorage` context captured by timers/promises.
|
|
313
|
+
*
|
|
314
|
+
* Without this, base64-encoded images/PDFs in message content remain
|
|
315
|
+
* reachable from lingering `Timeout` handles until GC runs.
|
|
316
|
+
*/
|
|
317
|
+
if (!this.skipCleanup) {
|
|
318
|
+
if (
|
|
319
|
+
(config.configurable as Record<string, unknown> | undefined) != null
|
|
320
|
+
) {
|
|
321
|
+
for (const key of Object.getOwnPropertySymbols(config.configurable)) {
|
|
322
|
+
const val = config.configurable[key as unknown as string] as
|
|
323
|
+
| Record<string, unknown>
|
|
324
|
+
| undefined;
|
|
325
|
+
if (
|
|
326
|
+
val != null &&
|
|
327
|
+
typeof val === 'object' &&
|
|
328
|
+
'currentTaskInput' in val
|
|
329
|
+
) {
|
|
330
|
+
(val as Record<string, unknown>).currentTaskInput = undefined;
|
|
331
|
+
}
|
|
332
|
+
delete config.configurable[key as unknown as string];
|
|
333
|
+
}
|
|
334
|
+
config.configurable = undefined;
|
|
335
|
+
}
|
|
336
|
+
config.callbacks = undefined;
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
const result = this.returnContent
|
|
340
|
+
? this.Graph.getContentParts()
|
|
341
|
+
: undefined;
|
|
342
|
+
|
|
343
|
+
if (!this.skipCleanup) {
|
|
344
|
+
this.Graph.clearHeavyState();
|
|
308
345
|
}
|
|
346
|
+
return result;
|
|
309
347
|
}
|
|
310
348
|
|
|
311
349
|
private createSystemCallback<K extends keyof t.ClientCallbacks>(
|
|
@@ -98,6 +98,7 @@ async function testStandardStreaming(): Promise<void> {
|
|
|
98
98
|
// additional_instructions: `Always address the user by their name. The user's name is ${userName} and they are located in ${location}.`,
|
|
99
99
|
},
|
|
100
100
|
returnContent: true,
|
|
101
|
+
skipCleanup: true,
|
|
101
102
|
customHandlers,
|
|
102
103
|
});
|
|
103
104
|
|
|
@@ -100,6 +100,7 @@ async function testStandardStreaming(): Promise<void> {
|
|
|
100
100
|
// additional_instructions: `Always address the user by their name. The user's name is ${userName} and they are located in ${location}.`,
|
|
101
101
|
},
|
|
102
102
|
returnContent: true,
|
|
103
|
+
skipCleanup: true,
|
|
103
104
|
customHandlers,
|
|
104
105
|
});
|
|
105
106
|
|
package/src/scripts/caching.ts
CHANGED
package/src/scripts/code_exec.ts
CHANGED
|
@@ -127,6 +127,7 @@ async function testCodeExecution(): Promise<void> {
|
|
|
127
127
|
additional_instructions: `The user's name is ${userName} and they are located in ${location}. The current date is ${currentDate}.`,
|
|
128
128
|
},
|
|
129
129
|
returnContent: true,
|
|
130
|
+
skipCleanup: true,
|
|
130
131
|
customHandlers,
|
|
131
132
|
});
|
|
132
133
|
|
package/src/scripts/content.ts
CHANGED
package/src/scripts/image.ts
CHANGED
package/src/scripts/memory.ts
CHANGED
|
@@ -17,19 +17,27 @@ const memoryKv: Record<string, string> = {};
|
|
|
17
17
|
const setMemory = tool(
|
|
18
18
|
async ({ key, value }) => {
|
|
19
19
|
if (!/^[a-z_]+$/.test(key)) {
|
|
20
|
-
throw new Error(
|
|
20
|
+
throw new Error(
|
|
21
|
+
'Key must only contain lowercase letters and underscores'
|
|
22
|
+
);
|
|
21
23
|
}
|
|
22
|
-
|
|
24
|
+
|
|
23
25
|
memoryKv[key] = value;
|
|
24
|
-
|
|
26
|
+
|
|
25
27
|
return { ok: true };
|
|
26
28
|
},
|
|
27
29
|
{
|
|
28
30
|
name: 'set_memory',
|
|
29
31
|
description: 'Saves important data about the user into memory.',
|
|
30
32
|
schema: z.object({
|
|
31
|
-
key: z
|
|
32
|
-
|
|
33
|
+
key: z
|
|
34
|
+
.string()
|
|
35
|
+
.describe(
|
|
36
|
+
'The key of the memory value. Always use lowercase and underscores, no other characters.'
|
|
37
|
+
),
|
|
38
|
+
value: z
|
|
39
|
+
.string()
|
|
40
|
+
.describe('Value can be anything represented as a string'),
|
|
33
41
|
}),
|
|
34
42
|
}
|
|
35
43
|
);
|
|
@@ -48,10 +56,12 @@ async function testStandardStreaming(): Promise<void> {
|
|
|
48
56
|
streaming: false,
|
|
49
57
|
},
|
|
50
58
|
tools: [setMemory],
|
|
51
|
-
instructions:
|
|
59
|
+
instructions:
|
|
60
|
+
'You can use the `set_memory` tool to save important data about the user into memory. If there is nothing to note about the user specifically, respond with `nothing`.',
|
|
52
61
|
toolEnd: true,
|
|
53
62
|
},
|
|
54
63
|
returnContent: true,
|
|
64
|
+
skipCleanup: true,
|
|
55
65
|
});
|
|
56
66
|
|
|
57
67
|
const config = {
|
package/src/scripts/search.ts
CHANGED