illuma-agents 1.0.37 → 1.0.39
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 +112 -14
- package/dist/cjs/agents/AgentContext.cjs.map +1 -1
- package/dist/cjs/common/enum.cjs +5 -1
- package/dist/cjs/common/enum.cjs.map +1 -1
- package/dist/cjs/graphs/Graph.cjs +148 -8
- package/dist/cjs/graphs/Graph.cjs.map +1 -1
- package/dist/cjs/graphs/MultiAgentGraph.cjs +277 -11
- package/dist/cjs/graphs/MultiAgentGraph.cjs.map +1 -1
- package/dist/cjs/llm/bedrock/index.cjs +128 -61
- package/dist/cjs/llm/bedrock/index.cjs.map +1 -1
- package/dist/cjs/main.cjs +22 -7
- package/dist/cjs/main.cjs.map +1 -1
- package/dist/cjs/messages/cache.cjs +140 -46
- package/dist/cjs/messages/cache.cjs.map +1 -1
- package/dist/cjs/messages/core.cjs +1 -1
- package/dist/cjs/messages/core.cjs.map +1 -1
- package/dist/cjs/messages/tools.cjs +2 -2
- package/dist/cjs/messages/tools.cjs.map +1 -1
- package/dist/cjs/schemas/validate.cjs +173 -0
- package/dist/cjs/schemas/validate.cjs.map +1 -0
- package/dist/cjs/stream.cjs +4 -2
- package/dist/cjs/stream.cjs.map +1 -1
- package/dist/cjs/tools/BrowserTools.cjs.map +1 -1
- package/dist/cjs/tools/CodeExecutor.cjs +22 -21
- package/dist/cjs/tools/CodeExecutor.cjs.map +1 -1
- package/dist/cjs/tools/ProgrammaticToolCalling.cjs +14 -11
- package/dist/cjs/tools/ProgrammaticToolCalling.cjs.map +1 -1
- package/dist/cjs/tools/ToolNode.cjs +101 -2
- package/dist/cjs/tools/ToolNode.cjs.map +1 -1
- package/dist/cjs/tools/ToolSearch.cjs +862 -0
- package/dist/cjs/tools/ToolSearch.cjs.map +1 -0
- package/dist/esm/agents/AgentContext.mjs +112 -14
- package/dist/esm/agents/AgentContext.mjs.map +1 -1
- package/dist/esm/common/enum.mjs +5 -1
- package/dist/esm/common/enum.mjs.map +1 -1
- package/dist/esm/graphs/Graph.mjs +149 -9
- package/dist/esm/graphs/Graph.mjs.map +1 -1
- package/dist/esm/graphs/MultiAgentGraph.mjs +278 -12
- package/dist/esm/graphs/MultiAgentGraph.mjs.map +1 -1
- package/dist/esm/llm/bedrock/index.mjs +127 -60
- package/dist/esm/llm/bedrock/index.mjs.map +1 -1
- package/dist/esm/main.mjs +2 -1
- package/dist/esm/main.mjs.map +1 -1
- package/dist/esm/messages/cache.mjs +140 -46
- package/dist/esm/messages/cache.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/tools.mjs +2 -2
- package/dist/esm/messages/tools.mjs.map +1 -1
- package/dist/esm/schemas/validate.mjs +167 -0
- package/dist/esm/schemas/validate.mjs.map +1 -0
- package/dist/esm/stream.mjs +4 -2
- package/dist/esm/stream.mjs.map +1 -1
- package/dist/esm/tools/BrowserTools.mjs.map +1 -1
- package/dist/esm/tools/CodeExecutor.mjs +22 -21
- package/dist/esm/tools/CodeExecutor.mjs.map +1 -1
- package/dist/esm/tools/ProgrammaticToolCalling.mjs +14 -11
- package/dist/esm/tools/ProgrammaticToolCalling.mjs.map +1 -1
- package/dist/esm/tools/ToolNode.mjs +102 -3
- package/dist/esm/tools/ToolNode.mjs.map +1 -1
- package/dist/esm/tools/ToolSearch.mjs +827 -0
- package/dist/esm/tools/ToolSearch.mjs.map +1 -0
- package/dist/types/agents/AgentContext.d.ts +51 -1
- package/dist/types/common/enum.d.ts +6 -2
- package/dist/types/graphs/Graph.d.ts +12 -0
- package/dist/types/graphs/MultiAgentGraph.d.ts +16 -0
- package/dist/types/index.d.ts +2 -1
- package/dist/types/llm/bedrock/index.d.ts +89 -11
- package/dist/types/llm/bedrock/types.d.ts +27 -0
- package/dist/types/llm/bedrock/utils/index.d.ts +5 -0
- package/dist/types/llm/bedrock/utils/message_inputs.d.ts +31 -0
- package/dist/types/llm/bedrock/utils/message_outputs.d.ts +33 -0
- package/dist/types/messages/cache.d.ts +4 -1
- package/dist/types/schemas/index.d.ts +1 -0
- package/dist/types/schemas/validate.d.ts +36 -0
- package/dist/types/tools/CodeExecutor.d.ts +0 -3
- package/dist/types/tools/ProgrammaticToolCalling.d.ts +0 -3
- package/dist/types/tools/ToolNode.d.ts +3 -1
- package/dist/types/tools/ToolSearch.d.ts +148 -0
- package/dist/types/types/graph.d.ts +71 -0
- package/dist/types/types/llm.d.ts +3 -1
- package/dist/types/types/tools.d.ts +42 -2
- package/package.json +13 -6
- package/src/agents/AgentContext.test.ts +312 -0
- package/src/agents/AgentContext.ts +144 -16
- package/src/common/enum.ts +5 -1
- package/src/graphs/Graph.ts +214 -13
- package/src/graphs/MultiAgentGraph.ts +350 -13
- package/src/index.ts +4 -1
- package/src/llm/bedrock/index.ts +221 -99
- package/src/llm/bedrock/llm.spec.ts +616 -0
- package/src/llm/bedrock/types.ts +51 -0
- package/src/llm/bedrock/utils/index.ts +18 -0
- package/src/llm/bedrock/utils/message_inputs.ts +563 -0
- package/src/llm/bedrock/utils/message_outputs.ts +310 -0
- package/src/messages/__tests__/tools.test.ts +21 -21
- package/src/messages/cache.test.ts +304 -0
- package/src/messages/cache.ts +183 -53
- package/src/messages/core.ts +1 -1
- package/src/messages/tools.ts +2 -2
- package/src/schemas/index.ts +2 -0
- package/src/schemas/validate.test.ts +358 -0
- package/src/schemas/validate.ts +238 -0
- package/src/scripts/caching.ts +27 -19
- package/src/scripts/code_exec_files.ts +58 -15
- package/src/scripts/code_exec_multi_session.ts +241 -0
- package/src/scripts/code_exec_session.ts +282 -0
- package/src/scripts/multi-agent-conditional.ts +1 -0
- package/src/scripts/multi-agent-supervisor.ts +1 -0
- package/src/scripts/programmatic_exec_agent.ts +4 -4
- package/src/scripts/test-handoff-preamble.ts +277 -0
- package/src/scripts/test-parallel-handoffs.ts +291 -0
- package/src/scripts/test-tools-before-handoff.ts +8 -4
- package/src/scripts/test_code_api.ts +361 -0
- package/src/scripts/thinking-bedrock.ts +159 -0
- package/src/scripts/thinking.ts +39 -18
- package/src/scripts/{tool_search_regex.ts → tool_search.ts} +5 -5
- package/src/scripts/tools.ts +7 -3
- package/src/specs/cache.simple.test.ts +396 -0
- package/src/stream.ts +4 -2
- package/src/tools/BrowserTools.ts +39 -17
- package/src/tools/CodeExecutor.ts +26 -23
- package/src/tools/ProgrammaticToolCalling.ts +18 -14
- package/src/tools/ToolNode.ts +114 -1
- package/src/tools/ToolSearch.ts +1041 -0
- package/src/tools/__tests__/ProgrammaticToolCalling.test.ts +0 -2
- package/src/tools/__tests__/{ToolSearchRegex.integration.test.ts → ToolSearch.integration.test.ts} +6 -6
- package/src/tools/__tests__/ToolSearch.test.ts +1003 -0
- package/src/types/graph.test.ts +183 -0
- package/src/types/graph.ts +73 -0
- package/src/types/llm.ts +3 -1
- package/src/types/tools.ts +51 -2
- package/dist/cjs/tools/ToolSearchRegex.cjs +0 -455
- package/dist/cjs/tools/ToolSearchRegex.cjs.map +0 -1
- package/dist/esm/tools/ToolSearchRegex.mjs +0 -448
- package/dist/esm/tools/ToolSearchRegex.mjs.map +0 -1
- package/dist/types/tools/ToolSearchRegex.d.ts +0 -80
- package/src/tools/ToolSearchRegex.ts +0 -535
- package/src/tools/__tests__/ToolSearchRegex.test.ts +0 -232
|
@@ -0,0 +1,312 @@
|
|
|
1
|
+
// src/agents/AgentContext.test.ts
|
|
2
|
+
import { AgentContext } from './AgentContext';
|
|
3
|
+
import { Providers } from '@/common';
|
|
4
|
+
import type * as t from '@/types';
|
|
5
|
+
|
|
6
|
+
describe('AgentContext', () => {
|
|
7
|
+
describe('structured output', () => {
|
|
8
|
+
const baseConfig: t.AgentInputs = {
|
|
9
|
+
agentId: 'test-agent',
|
|
10
|
+
provider: Providers.OPENAI,
|
|
11
|
+
clientOptions: {
|
|
12
|
+
model: 'gpt-4',
|
|
13
|
+
streaming: true,
|
|
14
|
+
},
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
describe('isStructuredOutputMode', () => {
|
|
18
|
+
it('should return false when structuredOutput is not configured', () => {
|
|
19
|
+
const context = AgentContext.fromConfig(baseConfig);
|
|
20
|
+
expect(context.isStructuredOutputMode).toBe(false);
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
it('should return false when structuredOutput has no schema', () => {
|
|
24
|
+
const config: t.AgentInputs = {
|
|
25
|
+
...baseConfig,
|
|
26
|
+
structuredOutput: {
|
|
27
|
+
schema: undefined as unknown as Record<string, unknown>,
|
|
28
|
+
},
|
|
29
|
+
};
|
|
30
|
+
const context = AgentContext.fromConfig(config);
|
|
31
|
+
expect(context.isStructuredOutputMode).toBe(false);
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
it('should return false when structuredOutput schema is null', () => {
|
|
35
|
+
const config: t.AgentInputs = {
|
|
36
|
+
...baseConfig,
|
|
37
|
+
structuredOutput: {
|
|
38
|
+
schema: null as unknown as Record<string, unknown>,
|
|
39
|
+
},
|
|
40
|
+
};
|
|
41
|
+
const context = AgentContext.fromConfig(config);
|
|
42
|
+
expect(context.isStructuredOutputMode).toBe(false);
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
it('should return true when structuredOutput has a valid schema', () => {
|
|
46
|
+
const config: t.AgentInputs = {
|
|
47
|
+
...baseConfig,
|
|
48
|
+
structuredOutput: {
|
|
49
|
+
schema: {
|
|
50
|
+
type: 'object',
|
|
51
|
+
properties: {
|
|
52
|
+
answer: { type: 'string' },
|
|
53
|
+
},
|
|
54
|
+
},
|
|
55
|
+
},
|
|
56
|
+
};
|
|
57
|
+
const context = AgentContext.fromConfig(config);
|
|
58
|
+
expect(context.isStructuredOutputMode).toBe(true);
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
it('should return true with minimal schema', () => {
|
|
62
|
+
const config: t.AgentInputs = {
|
|
63
|
+
...baseConfig,
|
|
64
|
+
structuredOutput: {
|
|
65
|
+
schema: { type: 'string' },
|
|
66
|
+
},
|
|
67
|
+
};
|
|
68
|
+
const context = AgentContext.fromConfig(config);
|
|
69
|
+
expect(context.isStructuredOutputMode).toBe(true);
|
|
70
|
+
});
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
describe('getStructuredOutputSchema', () => {
|
|
74
|
+
it('should return undefined when structuredOutput is not configured', () => {
|
|
75
|
+
const context = AgentContext.fromConfig(baseConfig);
|
|
76
|
+
expect(context.getStructuredOutputSchema()).toBeUndefined();
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
it('should return undefined when schema is not set', () => {
|
|
80
|
+
const config: t.AgentInputs = {
|
|
81
|
+
...baseConfig,
|
|
82
|
+
structuredOutput: {} as t.StructuredOutputConfig,
|
|
83
|
+
};
|
|
84
|
+
const context = AgentContext.fromConfig(config);
|
|
85
|
+
expect(context.getStructuredOutputSchema()).toBeUndefined();
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
it('should return the schema as-is when properly configured', () => {
|
|
89
|
+
const schema = {
|
|
90
|
+
type: 'object',
|
|
91
|
+
properties: {
|
|
92
|
+
name: { type: 'string' },
|
|
93
|
+
age: { type: 'number' },
|
|
94
|
+
},
|
|
95
|
+
};
|
|
96
|
+
const config: t.AgentInputs = {
|
|
97
|
+
...baseConfig,
|
|
98
|
+
structuredOutput: { schema },
|
|
99
|
+
};
|
|
100
|
+
const context = AgentContext.fromConfig(config);
|
|
101
|
+
const result = context.getStructuredOutputSchema();
|
|
102
|
+
expect(result).toMatchObject(schema);
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
it('should add type: object when properties exist but type is missing', () => {
|
|
106
|
+
const schema = {
|
|
107
|
+
properties: {
|
|
108
|
+
name: { type: 'string' },
|
|
109
|
+
},
|
|
110
|
+
};
|
|
111
|
+
const config: t.AgentInputs = {
|
|
112
|
+
...baseConfig,
|
|
113
|
+
structuredOutput: { schema },
|
|
114
|
+
};
|
|
115
|
+
const context = AgentContext.fromConfig(config);
|
|
116
|
+
const result = context.getStructuredOutputSchema();
|
|
117
|
+
expect(result?.type).toBe('object');
|
|
118
|
+
});
|
|
119
|
+
|
|
120
|
+
it('should add title from config name', () => {
|
|
121
|
+
const config: t.AgentInputs = {
|
|
122
|
+
...baseConfig,
|
|
123
|
+
structuredOutput: {
|
|
124
|
+
schema: { type: 'object' },
|
|
125
|
+
name: 'ResponseSchema',
|
|
126
|
+
},
|
|
127
|
+
};
|
|
128
|
+
const context = AgentContext.fromConfig(config);
|
|
129
|
+
const result = context.getStructuredOutputSchema();
|
|
130
|
+
expect(result?.title).toBe('ResponseSchema');
|
|
131
|
+
});
|
|
132
|
+
|
|
133
|
+
it('should not override existing title', () => {
|
|
134
|
+
const config: t.AgentInputs = {
|
|
135
|
+
...baseConfig,
|
|
136
|
+
structuredOutput: {
|
|
137
|
+
schema: { type: 'object', title: 'ExistingTitle' },
|
|
138
|
+
name: 'NewName',
|
|
139
|
+
},
|
|
140
|
+
};
|
|
141
|
+
const context = AgentContext.fromConfig(config);
|
|
142
|
+
const result = context.getStructuredOutputSchema();
|
|
143
|
+
expect(result?.title).toBe('ExistingTitle');
|
|
144
|
+
});
|
|
145
|
+
|
|
146
|
+
it('should add description from config', () => {
|
|
147
|
+
const config: t.AgentInputs = {
|
|
148
|
+
...baseConfig,
|
|
149
|
+
structuredOutput: {
|
|
150
|
+
schema: { type: 'object' },
|
|
151
|
+
description: 'A structured response',
|
|
152
|
+
},
|
|
153
|
+
};
|
|
154
|
+
const context = AgentContext.fromConfig(config);
|
|
155
|
+
const result = context.getStructuredOutputSchema();
|
|
156
|
+
expect(result?.description).toBe('A structured response');
|
|
157
|
+
});
|
|
158
|
+
|
|
159
|
+
it('should not override existing description', () => {
|
|
160
|
+
const config: t.AgentInputs = {
|
|
161
|
+
...baseConfig,
|
|
162
|
+
structuredOutput: {
|
|
163
|
+
schema: { type: 'object', description: 'Original description' },
|
|
164
|
+
description: 'New description',
|
|
165
|
+
},
|
|
166
|
+
};
|
|
167
|
+
const context = AgentContext.fromConfig(config);
|
|
168
|
+
const result = context.getStructuredOutputSchema();
|
|
169
|
+
expect(result?.description).toBe('Original description');
|
|
170
|
+
});
|
|
171
|
+
|
|
172
|
+
it('should set additionalProperties: false in strict mode by default', () => {
|
|
173
|
+
const config: t.AgentInputs = {
|
|
174
|
+
...baseConfig,
|
|
175
|
+
structuredOutput: {
|
|
176
|
+
schema: { type: 'object', properties: {} },
|
|
177
|
+
},
|
|
178
|
+
};
|
|
179
|
+
const context = AgentContext.fromConfig(config);
|
|
180
|
+
const result = context.getStructuredOutputSchema();
|
|
181
|
+
expect(result?.additionalProperties).toBe(false);
|
|
182
|
+
});
|
|
183
|
+
|
|
184
|
+
it('should set additionalProperties: false when strict is explicitly true', () => {
|
|
185
|
+
const config: t.AgentInputs = {
|
|
186
|
+
...baseConfig,
|
|
187
|
+
structuredOutput: {
|
|
188
|
+
schema: { type: 'object', properties: {} },
|
|
189
|
+
strict: true,
|
|
190
|
+
},
|
|
191
|
+
};
|
|
192
|
+
const context = AgentContext.fromConfig(config);
|
|
193
|
+
const result = context.getStructuredOutputSchema();
|
|
194
|
+
expect(result?.additionalProperties).toBe(false);
|
|
195
|
+
});
|
|
196
|
+
|
|
197
|
+
it('should not set additionalProperties when strict is false', () => {
|
|
198
|
+
const config: t.AgentInputs = {
|
|
199
|
+
...baseConfig,
|
|
200
|
+
structuredOutput: {
|
|
201
|
+
schema: { type: 'object', properties: {} },
|
|
202
|
+
strict: false,
|
|
203
|
+
},
|
|
204
|
+
};
|
|
205
|
+
const context = AgentContext.fromConfig(config);
|
|
206
|
+
const result = context.getStructuredOutputSchema();
|
|
207
|
+
expect(result?.additionalProperties).toBeUndefined();
|
|
208
|
+
});
|
|
209
|
+
|
|
210
|
+
it('should preserve existing additionalProperties value', () => {
|
|
211
|
+
const config: t.AgentInputs = {
|
|
212
|
+
...baseConfig,
|
|
213
|
+
structuredOutput: {
|
|
214
|
+
schema: {
|
|
215
|
+
type: 'object',
|
|
216
|
+
properties: {},
|
|
217
|
+
additionalProperties: true,
|
|
218
|
+
},
|
|
219
|
+
strict: true,
|
|
220
|
+
},
|
|
221
|
+
};
|
|
222
|
+
const context = AgentContext.fromConfig(config);
|
|
223
|
+
const result = context.getStructuredOutputSchema();
|
|
224
|
+
expect(result?.additionalProperties).toBe(true);
|
|
225
|
+
});
|
|
226
|
+
|
|
227
|
+
it('should not affect non-object types', () => {
|
|
228
|
+
const config: t.AgentInputs = {
|
|
229
|
+
...baseConfig,
|
|
230
|
+
structuredOutput: {
|
|
231
|
+
schema: { type: 'array', items: { type: 'string' } },
|
|
232
|
+
},
|
|
233
|
+
};
|
|
234
|
+
const context = AgentContext.fromConfig(config);
|
|
235
|
+
const result = context.getStructuredOutputSchema();
|
|
236
|
+
expect(result?.additionalProperties).toBeUndefined();
|
|
237
|
+
expect(result?.type).toBe('array');
|
|
238
|
+
});
|
|
239
|
+
|
|
240
|
+
it('should not mutate the original schema', () => {
|
|
241
|
+
const originalSchema = {
|
|
242
|
+
type: 'object',
|
|
243
|
+
properties: { name: { type: 'string' } },
|
|
244
|
+
};
|
|
245
|
+
const config: t.AgentInputs = {
|
|
246
|
+
...baseConfig,
|
|
247
|
+
structuredOutput: {
|
|
248
|
+
schema: originalSchema,
|
|
249
|
+
name: 'TestSchema',
|
|
250
|
+
description: 'Test description',
|
|
251
|
+
},
|
|
252
|
+
};
|
|
253
|
+
const context = AgentContext.fromConfig(config);
|
|
254
|
+
context.getStructuredOutputSchema();
|
|
255
|
+
|
|
256
|
+
// Original should not have been modified
|
|
257
|
+
expect(originalSchema).not.toHaveProperty('title');
|
|
258
|
+
expect(originalSchema).not.toHaveProperty('description');
|
|
259
|
+
expect(originalSchema).not.toHaveProperty('additionalProperties');
|
|
260
|
+
});
|
|
261
|
+
});
|
|
262
|
+
|
|
263
|
+
describe('fromConfig with structuredOutput', () => {
|
|
264
|
+
it('should properly initialize structuredOutput from config', () => {
|
|
265
|
+
const structuredOutput: t.StructuredOutputConfig = {
|
|
266
|
+
schema: {
|
|
267
|
+
type: 'object',
|
|
268
|
+
properties: {
|
|
269
|
+
response: { type: 'string' },
|
|
270
|
+
confidence: { type: 'number' },
|
|
271
|
+
},
|
|
272
|
+
required: ['response'],
|
|
273
|
+
},
|
|
274
|
+
name: 'AnalysisResult',
|
|
275
|
+
description: 'The analysis result',
|
|
276
|
+
mode: 'auto',
|
|
277
|
+
strict: true,
|
|
278
|
+
};
|
|
279
|
+
|
|
280
|
+
const config: t.AgentInputs = {
|
|
281
|
+
...baseConfig,
|
|
282
|
+
structuredOutput,
|
|
283
|
+
};
|
|
284
|
+
|
|
285
|
+
const context = AgentContext.fromConfig(config);
|
|
286
|
+
|
|
287
|
+
expect(context.isStructuredOutputMode).toBe(true);
|
|
288
|
+
expect(context.structuredOutput).toEqual(structuredOutput);
|
|
289
|
+
});
|
|
290
|
+
|
|
291
|
+
it('should handle all mode options', () => {
|
|
292
|
+
const modes: Array<t.StructuredOutputMode> = [
|
|
293
|
+
'auto',
|
|
294
|
+
'tool',
|
|
295
|
+
'provider',
|
|
296
|
+
];
|
|
297
|
+
|
|
298
|
+
for (const mode of modes) {
|
|
299
|
+
const config: t.AgentInputs = {
|
|
300
|
+
...baseConfig,
|
|
301
|
+
structuredOutput: {
|
|
302
|
+
schema: { type: 'object' },
|
|
303
|
+
mode,
|
|
304
|
+
},
|
|
305
|
+
};
|
|
306
|
+
const context = AgentContext.fromConfig(config);
|
|
307
|
+
expect(context.structuredOutput?.mode).toBe(mode);
|
|
308
|
+
}
|
|
309
|
+
});
|
|
310
|
+
});
|
|
311
|
+
});
|
|
312
|
+
});
|
|
@@ -27,6 +27,7 @@ export class AgentContext {
|
|
|
27
27
|
): AgentContext {
|
|
28
28
|
const {
|
|
29
29
|
agentId,
|
|
30
|
+
name,
|
|
30
31
|
provider,
|
|
31
32
|
clientOptions,
|
|
32
33
|
tools,
|
|
@@ -40,10 +41,12 @@ export class AgentContext {
|
|
|
40
41
|
reasoningKey,
|
|
41
42
|
useLegacyContent,
|
|
42
43
|
dynamicContext,
|
|
44
|
+
structuredOutput,
|
|
43
45
|
} = agentConfig;
|
|
44
46
|
|
|
45
47
|
const agentContext = new AgentContext({
|
|
46
48
|
agentId,
|
|
49
|
+
name: name ?? agentId,
|
|
47
50
|
provider,
|
|
48
51
|
clientOptions,
|
|
49
52
|
maxContextTokens,
|
|
@@ -59,6 +62,7 @@ export class AgentContext {
|
|
|
59
62
|
tokenCounter,
|
|
60
63
|
useLegacyContent,
|
|
61
64
|
dynamicContext,
|
|
65
|
+
structuredOutput,
|
|
62
66
|
});
|
|
63
67
|
|
|
64
68
|
if (tokenCounter) {
|
|
@@ -87,6 +91,8 @@ export class AgentContext {
|
|
|
87
91
|
|
|
88
92
|
/** Agent identifier */
|
|
89
93
|
agentId: string;
|
|
94
|
+
/** Human-readable name for this agent (used in handoff context). Falls back to agentId if not provided. */
|
|
95
|
+
name?: string;
|
|
90
96
|
/** Provider for this specific agent */
|
|
91
97
|
provider: Providers;
|
|
92
98
|
/** Client options for this agent */
|
|
@@ -173,9 +179,26 @@ export class AgentContext {
|
|
|
173
179
|
artifacts: 0,
|
|
174
180
|
memory: 0,
|
|
175
181
|
};
|
|
182
|
+
/**
|
|
183
|
+
* Handoff context when this agent receives control via handoff.
|
|
184
|
+
* Contains source and parallel execution info for system message context.
|
|
185
|
+
*/
|
|
186
|
+
handoffContext?: {
|
|
187
|
+
/** Source agent that transferred control */
|
|
188
|
+
sourceAgentName: string;
|
|
189
|
+
/** Names of sibling agents executing in parallel (empty if sequential) */
|
|
190
|
+
parallelSiblings: string[];
|
|
191
|
+
};
|
|
192
|
+
/**
|
|
193
|
+
* Structured output configuration.
|
|
194
|
+
* When set, the agent will return a validated JSON response
|
|
195
|
+
* instead of streaming text.
|
|
196
|
+
*/
|
|
197
|
+
structuredOutput?: t.StructuredOutputConfig;
|
|
176
198
|
|
|
177
199
|
constructor({
|
|
178
200
|
agentId,
|
|
201
|
+
name,
|
|
179
202
|
provider,
|
|
180
203
|
clientOptions,
|
|
181
204
|
maxContextTokens,
|
|
@@ -191,8 +214,10 @@ export class AgentContext {
|
|
|
191
214
|
toolEnd,
|
|
192
215
|
instructionTokens,
|
|
193
216
|
useLegacyContent,
|
|
217
|
+
structuredOutput,
|
|
194
218
|
}: {
|
|
195
219
|
agentId: string;
|
|
220
|
+
name?: string;
|
|
196
221
|
provider: Providers;
|
|
197
222
|
clientOptions?: t.ClientOptions;
|
|
198
223
|
maxContextTokens?: number;
|
|
@@ -208,8 +233,10 @@ export class AgentContext {
|
|
|
208
233
|
toolEnd?: boolean;
|
|
209
234
|
instructionTokens?: number;
|
|
210
235
|
useLegacyContent?: boolean;
|
|
236
|
+
structuredOutput?: t.StructuredOutputConfig;
|
|
211
237
|
}) {
|
|
212
238
|
this.agentId = agentId;
|
|
239
|
+
this.name = name;
|
|
213
240
|
this.provider = provider;
|
|
214
241
|
this.clientOptions = clientOptions;
|
|
215
242
|
this.maxContextTokens = maxContextTokens;
|
|
@@ -221,6 +248,7 @@ export class AgentContext {
|
|
|
221
248
|
this.instructions = instructions;
|
|
222
249
|
this.additionalInstructions = additionalInstructions;
|
|
223
250
|
this.dynamicContext = dynamicContext;
|
|
251
|
+
this.structuredOutput = structuredOutput;
|
|
224
252
|
if (reasoningKey) {
|
|
225
253
|
this.reasoningKey = reasoningKey;
|
|
226
254
|
}
|
|
@@ -234,6 +262,51 @@ export class AgentContext {
|
|
|
234
262
|
this.useLegacyContent = useLegacyContent ?? false;
|
|
235
263
|
}
|
|
236
264
|
|
|
265
|
+
/**
|
|
266
|
+
* Checks if structured output mode is enabled for this agent.
|
|
267
|
+
* When enabled, the agent will use model.invoke() instead of streaming
|
|
268
|
+
* and return a validated JSON response.
|
|
269
|
+
*/
|
|
270
|
+
get isStructuredOutputMode(): boolean {
|
|
271
|
+
return (
|
|
272
|
+
this.structuredOutput != null && this.structuredOutput.schema != null
|
|
273
|
+
);
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
/**
|
|
277
|
+
* Gets the structured output schema with normalized defaults.
|
|
278
|
+
* Returns undefined if structured output is not configured.
|
|
279
|
+
*/
|
|
280
|
+
getStructuredOutputSchema(): Record<string, unknown> | undefined {
|
|
281
|
+
if (!this.structuredOutput?.schema) {
|
|
282
|
+
return undefined;
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
const schema = { ...this.structuredOutput.schema };
|
|
286
|
+
|
|
287
|
+
// Ensure type is set
|
|
288
|
+
if (!schema.type && schema.properties) {
|
|
289
|
+
schema.type = 'object';
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
// Add title from config name
|
|
293
|
+
if (this.structuredOutput.name && !schema.title) {
|
|
294
|
+
schema.title = this.structuredOutput.name;
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
// Add description from config
|
|
298
|
+
if (this.structuredOutput.description && !schema.description) {
|
|
299
|
+
schema.description = this.structuredOutput.description;
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
// Enable strict mode by default
|
|
303
|
+
if (this.structuredOutput.strict !== false && schema.type === 'object') {
|
|
304
|
+
schema.additionalProperties = schema.additionalProperties ?? false;
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
return schema;
|
|
308
|
+
}
|
|
309
|
+
|
|
237
310
|
/**
|
|
238
311
|
* Builds instructions text for tools that are ONLY callable via programmatic code execution.
|
|
239
312
|
* These tools cannot be called directly by the LLM but are available through the
|
|
@@ -324,27 +397,65 @@ export class AgentContext {
|
|
|
324
397
|
|
|
325
398
|
/**
|
|
326
399
|
* Builds the raw instructions string (without creating SystemMessage).
|
|
400
|
+
* Includes agent identity preamble and handoff context when available.
|
|
327
401
|
*/
|
|
328
402
|
private buildInstructionsString(): string {
|
|
329
|
-
|
|
403
|
+
const parts: string[] = [];
|
|
404
|
+
|
|
405
|
+
/** Build agent identity and handoff context preamble */
|
|
406
|
+
const identityPreamble = this.buildIdentityPreamble();
|
|
407
|
+
if (identityPreamble) {
|
|
408
|
+
parts.push(identityPreamble);
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
/** Add main instructions */
|
|
412
|
+
if (this.instructions != null && this.instructions !== '') {
|
|
413
|
+
parts.push(this.instructions);
|
|
414
|
+
}
|
|
330
415
|
|
|
416
|
+
/** Add additional instructions */
|
|
331
417
|
if (
|
|
332
418
|
this.additionalInstructions != null &&
|
|
333
419
|
this.additionalInstructions !== ''
|
|
334
420
|
) {
|
|
335
|
-
|
|
336
|
-
? `${result}\n\n${this.additionalInstructions}`
|
|
337
|
-
: this.additionalInstructions;
|
|
421
|
+
parts.push(this.additionalInstructions);
|
|
338
422
|
}
|
|
339
423
|
|
|
424
|
+
/** Add programmatic tools documentation */
|
|
340
425
|
const programmaticToolsDoc = this.buildProgrammaticOnlyToolsInstructions();
|
|
341
426
|
if (programmaticToolsDoc) {
|
|
342
|
-
|
|
343
|
-
? `${result}${programmaticToolsDoc}`
|
|
344
|
-
: programmaticToolsDoc;
|
|
427
|
+
parts.push(programmaticToolsDoc);
|
|
345
428
|
}
|
|
346
429
|
|
|
347
|
-
return
|
|
430
|
+
return parts.join('\n\n');
|
|
431
|
+
}
|
|
432
|
+
|
|
433
|
+
/**
|
|
434
|
+
* Builds the agent identity preamble including handoff context if present.
|
|
435
|
+
* This helps the agent understand its role in the multi-agent workflow.
|
|
436
|
+
*/
|
|
437
|
+
private buildIdentityPreamble(): string {
|
|
438
|
+
if (!this.handoffContext) return '';
|
|
439
|
+
|
|
440
|
+
const displayName = this.name ?? this.agentId;
|
|
441
|
+
const { sourceAgentName, parallelSiblings } = this.handoffContext;
|
|
442
|
+
const isParallel = parallelSiblings.length > 0;
|
|
443
|
+
|
|
444
|
+
const lines: string[] = [];
|
|
445
|
+
lines.push('## Multi-Agent Workflow');
|
|
446
|
+
lines.push(
|
|
447
|
+
`You are "${displayName}", transferred from "${sourceAgentName}".`
|
|
448
|
+
);
|
|
449
|
+
|
|
450
|
+
if (isParallel) {
|
|
451
|
+
lines.push(`Running in parallel with: ${parallelSiblings.join(', ')}.`);
|
|
452
|
+
}
|
|
453
|
+
|
|
454
|
+
lines.push(
|
|
455
|
+
'Execute only tasks relevant to your role. Routing is already handled if requested, unless you can route further.'
|
|
456
|
+
);
|
|
457
|
+
|
|
458
|
+
return lines.join('\n');
|
|
348
459
|
}
|
|
349
460
|
|
|
350
461
|
/**
|
|
@@ -374,14 +485,7 @@ export class AgentContext {
|
|
|
374
485
|
const anthropicOptions = this.clientOptions as
|
|
375
486
|
| t.AnthropicClientOptions
|
|
376
487
|
| undefined;
|
|
377
|
-
|
|
378
|
-
| Record<string, string>
|
|
379
|
-
| undefined;
|
|
380
|
-
const anthropicBeta = defaultHeaders?.['anthropic-beta'];
|
|
381
|
-
if (
|
|
382
|
-
typeof anthropicBeta === 'string' &&
|
|
383
|
-
anthropicBeta.includes('prompt-caching')
|
|
384
|
-
) {
|
|
488
|
+
if (anthropicOptions?.promptCache === true) {
|
|
385
489
|
finalInstructions = {
|
|
386
490
|
content: [
|
|
387
491
|
{
|
|
@@ -455,6 +559,7 @@ export class AgentContext {
|
|
|
455
559
|
this.tokenTypeSwitch = undefined;
|
|
456
560
|
this.currentTokenType = ContentTypes.TEXT;
|
|
457
561
|
this.discoveredToolNames.clear();
|
|
562
|
+
this.handoffContext = undefined;
|
|
458
563
|
}
|
|
459
564
|
|
|
460
565
|
/**
|
|
@@ -626,6 +731,29 @@ export class AgentContext {
|
|
|
626
731
|
return registry;
|
|
627
732
|
}
|
|
628
733
|
|
|
734
|
+
/**
|
|
735
|
+
* Sets the handoff context for this agent.
|
|
736
|
+
* Call this when the agent receives control via handoff from another agent.
|
|
737
|
+
* Marks system runnable as stale to include handoff context in system message.
|
|
738
|
+
* @param sourceAgentName - Name of the agent that transferred control
|
|
739
|
+
* @param parallelSiblings - Names of other agents executing in parallel with this one
|
|
740
|
+
*/
|
|
741
|
+
setHandoffContext(sourceAgentName: string, parallelSiblings: string[]): void {
|
|
742
|
+
this.handoffContext = { sourceAgentName, parallelSiblings };
|
|
743
|
+
this.systemRunnableStale = true;
|
|
744
|
+
}
|
|
745
|
+
|
|
746
|
+
/**
|
|
747
|
+
* Clears any handoff context.
|
|
748
|
+
* Call this when resetting the agent or when handoff context is no longer relevant.
|
|
749
|
+
*/
|
|
750
|
+
clearHandoffContext(): void {
|
|
751
|
+
if (this.handoffContext) {
|
|
752
|
+
this.handoffContext = undefined;
|
|
753
|
+
this.systemRunnableStale = true;
|
|
754
|
+
}
|
|
755
|
+
}
|
|
756
|
+
|
|
629
757
|
/**
|
|
630
758
|
* Marks tools as discovered via tool search.
|
|
631
759
|
* Discovered tools will be included in the next model binding.
|
package/src/common/enum.ts
CHANGED
|
@@ -21,6 +21,8 @@ export enum GraphEvents {
|
|
|
21
21
|
ON_REASONING_DELTA = 'on_reasoning_delta',
|
|
22
22
|
/** [Custom] Context analytics event for traces */
|
|
23
23
|
ON_CONTEXT_ANALYTICS = 'on_context_analytics',
|
|
24
|
+
/** [Custom] Structured output event - emitted when agent returns structured JSON */
|
|
25
|
+
ON_STRUCTURED_OUTPUT = 'on_structured_output',
|
|
24
26
|
|
|
25
27
|
/* Official Events */
|
|
26
28
|
|
|
@@ -161,11 +163,13 @@ export enum Callback {
|
|
|
161
163
|
export enum Constants {
|
|
162
164
|
OFFICIAL_CODE_BASEURL = 'https://api.illuma.ai/v1',
|
|
163
165
|
EXECUTE_CODE = 'execute_code',
|
|
164
|
-
|
|
166
|
+
TOOL_SEARCH = 'tool_search',
|
|
165
167
|
PROGRAMMATIC_TOOL_CALLING = 'run_tools_with_code',
|
|
166
168
|
WEB_SEARCH = 'web_search',
|
|
167
169
|
CONTENT_AND_ARTIFACT = 'content_and_artifact',
|
|
168
170
|
LC_TRANSFER_TO_ = 'lc_transfer_to_',
|
|
171
|
+
/** Delimiter for MCP tools: toolName_mcp_serverName */
|
|
172
|
+
MCP_DELIMITER = '_mcp_',
|
|
169
173
|
}
|
|
170
174
|
|
|
171
175
|
export enum TitleMethod {
|