@clinebot/agents 0.0.0 → 0.0.3
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/agent.d.ts +4 -0
- package/dist/index.browser.js +20 -17
- package/dist/index.d.ts +1 -1
- package/dist/index.js +18 -15
- package/dist/index.node.js +18 -15
- package/dist/runtime/turn-processor.d.ts +1 -0
- package/dist/teams/multi-agent.d.ts +6 -0
- package/dist/teams/spawn-agent-tool.d.ts +10 -6
- package/dist/types.d.ts +66 -1
- package/package.json +7 -7
- package/src/agent.test.ts +186 -0
- package/src/agent.ts +255 -8
- package/src/hooks/engine.test.ts +1 -0
- package/src/index.ts +2 -0
- package/src/runtime/tool-orchestrator.test.ts +53 -0
- package/src/runtime/tool-orchestrator.ts +12 -1
- package/src/runtime/turn-processor.ts +56 -5
- package/src/teams/multi-agent.ts +96 -15
- package/src/teams/spawn-agent-tool.test.ts +92 -0
- package/src/teams/spawn-agent-tool.ts +65 -31
- package/src/teams/team-tools.test.ts +18 -0
- package/src/teams/team-tools.ts +12 -4
- package/src/types.ts +90 -2
|
@@ -75,6 +75,7 @@ export type TeamEvent = {
|
|
|
75
75
|
agentId: string;
|
|
76
76
|
result?: AgentResult;
|
|
77
77
|
error?: Error;
|
|
78
|
+
messages?: AgentResult["messages"];
|
|
78
79
|
} | {
|
|
79
80
|
type: TeamMessageType.AgentEvent;
|
|
80
81
|
agentId: string;
|
|
@@ -414,6 +415,9 @@ export interface TeamRunRecord {
|
|
|
414
415
|
endedAt?: Date;
|
|
415
416
|
leaseOwner?: string;
|
|
416
417
|
heartbeatAt?: Date;
|
|
418
|
+
lastProgressAt?: Date;
|
|
419
|
+
lastProgressMessage?: string;
|
|
420
|
+
currentActivity?: string;
|
|
417
421
|
result?: AgentResult;
|
|
418
422
|
error?: string;
|
|
419
423
|
}
|
|
@@ -561,6 +565,8 @@ export declare class AgentTeamsRuntime {
|
|
|
561
565
|
private requireTask;
|
|
562
566
|
private assertDependenciesResolved;
|
|
563
567
|
private trackMeaningfulEvent;
|
|
568
|
+
private recordRunActivityFromAgentEvent;
|
|
569
|
+
private recordRunProgress;
|
|
564
570
|
private recordProgressStep;
|
|
565
571
|
private emitEvent;
|
|
566
572
|
}
|
|
@@ -2,13 +2,15 @@
|
|
|
2
2
|
* Reusable spawn_agent tool for delegating tasks to sub-agents.
|
|
3
3
|
*/
|
|
4
4
|
import type { providers as LlmsProviders } from "@clinebot/llms";
|
|
5
|
-
import type
|
|
5
|
+
import { type Tool, type ToolApprovalRequest, type ToolApprovalResult, type ToolContext, type ToolPolicy } from "@clinebot/shared";
|
|
6
|
+
import { z } from "zod";
|
|
6
7
|
import type { AgentEvent, AgentExtension, AgentFinishReason, AgentHooks, BasicLogger, HookErrorMode } from "../types.js";
|
|
7
|
-
export
|
|
8
|
-
systemPrompt:
|
|
9
|
-
task:
|
|
10
|
-
maxIterations
|
|
11
|
-
}
|
|
8
|
+
export declare const SpawnAgentInputSchema: z.ZodObject<{
|
|
9
|
+
systemPrompt: z.ZodString;
|
|
10
|
+
task: z.ZodString;
|
|
11
|
+
maxIterations: z.ZodOptional<z.ZodNumber>;
|
|
12
|
+
}, z.core.$strip>;
|
|
13
|
+
export type SpawnAgentInput = z.infer<typeof SpawnAgentInputSchema>;
|
|
12
14
|
export interface SpawnAgentOutput {
|
|
13
15
|
text: string;
|
|
14
16
|
iterations: number;
|
|
@@ -35,11 +37,13 @@ export interface SubAgentEndContext {
|
|
|
35
37
|
export interface SpawnAgentToolConfig {
|
|
36
38
|
providerId: string;
|
|
37
39
|
modelId: string;
|
|
40
|
+
cwd?: string;
|
|
38
41
|
apiKey?: string;
|
|
39
42
|
baseUrl?: string;
|
|
40
43
|
providerConfig?: LlmsProviders.ProviderConfig;
|
|
41
44
|
knownModels?: Record<string, LlmsProviders.ModelInfo>;
|
|
42
45
|
thinking?: boolean;
|
|
46
|
+
clineWorkspaceMetadata?: string;
|
|
43
47
|
defaultMaxIterations?: number;
|
|
44
48
|
subAgentTools?: Tool[];
|
|
45
49
|
createSubAgentTools?: (input: SpawnAgentInput, context: ToolContext) => Tool[] | Promise<Tool[]>;
|
package/dist/types.d.ts
CHANGED
|
@@ -89,6 +89,8 @@ export interface AgentDoneEvent {
|
|
|
89
89
|
text: string;
|
|
90
90
|
/** Total number of iterations */
|
|
91
91
|
iterations: number;
|
|
92
|
+
/** Aggregated usage information */
|
|
93
|
+
usage?: AgentUsage;
|
|
92
94
|
}
|
|
93
95
|
export interface AgentErrorEvent {
|
|
94
96
|
type: "error";
|
|
@@ -99,6 +101,26 @@ export interface AgentErrorEvent {
|
|
|
99
101
|
/** Current iteration when error occurred */
|
|
100
102
|
iteration: number;
|
|
101
103
|
}
|
|
104
|
+
export interface ConsecutiveMistakeLimitContext {
|
|
105
|
+
iteration: number;
|
|
106
|
+
consecutiveMistakes: number;
|
|
107
|
+
maxConsecutiveMistakes: number;
|
|
108
|
+
reason: "api_error" | "invalid_tool_call" | "tool_execution_failed";
|
|
109
|
+
details?: string;
|
|
110
|
+
}
|
|
111
|
+
export type ConsecutiveMistakeLimitDecision = {
|
|
112
|
+
action: "continue";
|
|
113
|
+
/**
|
|
114
|
+
* Optional guidance appended as a user message before continuing.
|
|
115
|
+
*/
|
|
116
|
+
guidance?: string;
|
|
117
|
+
} | {
|
|
118
|
+
action: "stop";
|
|
119
|
+
/**
|
|
120
|
+
* Optional reason surfaced when stopping due to the limit.
|
|
121
|
+
*/
|
|
122
|
+
reason?: string;
|
|
123
|
+
};
|
|
102
124
|
/**
|
|
103
125
|
* Hook error handling behavior.
|
|
104
126
|
* - "ignore": swallow hook errors and continue agent execution
|
|
@@ -539,11 +561,12 @@ export declare const AgentResultSchema: z.ZodObject<{
|
|
|
539
561
|
/**
|
|
540
562
|
* Reasoning effort level for capable models
|
|
541
563
|
*/
|
|
542
|
-
export type ReasoningEffort = "low" | "medium" | "high";
|
|
564
|
+
export type ReasoningEffort = "low" | "medium" | "high" | "xhigh";
|
|
543
565
|
export declare const ReasoningEffortSchema: z.ZodEnum<{
|
|
544
566
|
low: "low";
|
|
545
567
|
high: "high";
|
|
546
568
|
medium: "medium";
|
|
569
|
+
xhigh: "xhigh";
|
|
547
570
|
}>;
|
|
548
571
|
/**
|
|
549
572
|
* Configuration for creating an Agent
|
|
@@ -603,6 +626,13 @@ export interface AgentConfig {
|
|
|
603
626
|
* @default 120000 (2 minutes)
|
|
604
627
|
*/
|
|
605
628
|
apiTimeoutMs?: number;
|
|
629
|
+
/**
|
|
630
|
+
* Maximum consecutive internal mistakes before escalation.
|
|
631
|
+
* Mistakes include API turn failures, invalid/missing tool-call arguments,
|
|
632
|
+
* and iterations where every executed tool call fails.
|
|
633
|
+
* @default 3
|
|
634
|
+
*/
|
|
635
|
+
maxConsecutiveMistakes?: number;
|
|
606
636
|
/**
|
|
607
637
|
* Optional runtime file-content loader used when user files are attached.
|
|
608
638
|
* When omitted, attached files will be represented as loader errors.
|
|
@@ -659,6 +689,10 @@ export interface AgentConfig {
|
|
|
659
689
|
* Optional callback to request client approval when a tool policy disables auto-approval.
|
|
660
690
|
*/
|
|
661
691
|
requestToolApproval?: (request: ToolApprovalRequest) => Promise<ToolApprovalResult> | ToolApprovalResult;
|
|
692
|
+
/**
|
|
693
|
+
* Optional callback invoked when consecutive mistakes reach maxConsecutiveMistakes.
|
|
694
|
+
*/
|
|
695
|
+
onConsecutiveMistakeLimitReached?: (context: ConsecutiveMistakeLimitContext) => Promise<ConsecutiveMistakeLimitDecision> | ConsecutiveMistakeLimitDecision;
|
|
662
696
|
/**
|
|
663
697
|
* Optional logger for tracing agent loop lifecycle and recoverable failures.
|
|
664
698
|
*/
|
|
@@ -743,6 +777,7 @@ export declare const AgentConfigSchema: z.ZodObject<{
|
|
|
743
777
|
maxParallelToolCalls: z.ZodDefault<z.ZodNumber>;
|
|
744
778
|
maxTokensPerTurn: z.ZodOptional<z.ZodNumber>;
|
|
745
779
|
apiTimeoutMs: z.ZodDefault<z.ZodNumber>;
|
|
780
|
+
maxConsecutiveMistakes: z.ZodDefault<z.ZodNumber>;
|
|
746
781
|
userFileContentLoader: z.ZodOptional<z.ZodFunction<z.core.$ZodTuple<readonly [z.ZodString], z.core.$ZodFunctionOut>, z.ZodPromise<z.ZodString>>>;
|
|
747
782
|
reminderAfterIterations: z.ZodDefault<z.ZodNumber>;
|
|
748
783
|
reminderText: z.ZodOptional<z.ZodString>;
|
|
@@ -750,6 +785,7 @@ export declare const AgentConfigSchema: z.ZodObject<{
|
|
|
750
785
|
low: "low";
|
|
751
786
|
high: "high";
|
|
752
787
|
medium: "medium";
|
|
788
|
+
xhigh: "xhigh";
|
|
753
789
|
}>>;
|
|
754
790
|
thinkingBudgetTokens: z.ZodOptional<z.ZodNumber>;
|
|
755
791
|
thinking: z.ZodOptional<z.ZodBoolean>;
|
|
@@ -784,6 +820,29 @@ export declare const AgentConfigSchema: z.ZodObject<{
|
|
|
784
820
|
approved: z.ZodBoolean;
|
|
785
821
|
reason: z.ZodOptional<z.ZodString>;
|
|
786
822
|
}, z.core.$strip>>]>>>;
|
|
823
|
+
onConsecutiveMistakeLimitReached: z.ZodOptional<z.ZodFunction<z.core.$ZodTuple<readonly [z.ZodObject<{
|
|
824
|
+
iteration: z.ZodNumber;
|
|
825
|
+
consecutiveMistakes: z.ZodNumber;
|
|
826
|
+
maxConsecutiveMistakes: z.ZodNumber;
|
|
827
|
+
reason: z.ZodEnum<{
|
|
828
|
+
api_error: "api_error";
|
|
829
|
+
invalid_tool_call: "invalid_tool_call";
|
|
830
|
+
tool_execution_failed: "tool_execution_failed";
|
|
831
|
+
}>;
|
|
832
|
+
details: z.ZodOptional<z.ZodString>;
|
|
833
|
+
}, z.core.$strip>], z.core.$ZodFunctionOut>, z.ZodUnion<readonly [z.ZodObject<{
|
|
834
|
+
action: z.ZodLiteral<"continue">;
|
|
835
|
+
guidance: z.ZodOptional<z.ZodString>;
|
|
836
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
837
|
+
action: z.ZodLiteral<"stop">;
|
|
838
|
+
reason: z.ZodOptional<z.ZodString>;
|
|
839
|
+
}, z.core.$strip>, z.ZodPromise<z.ZodUnion<readonly [z.ZodObject<{
|
|
840
|
+
action: z.ZodLiteral<"continue">;
|
|
841
|
+
guidance: z.ZodOptional<z.ZodString>;
|
|
842
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
843
|
+
action: z.ZodLiteral<"stop">;
|
|
844
|
+
reason: z.ZodOptional<z.ZodString>;
|
|
845
|
+
}, z.core.$strip>]>>]>>>;
|
|
787
846
|
logger: z.ZodOptional<z.ZodCustom<BasicLogger, BasicLogger>>;
|
|
788
847
|
abortSignal: z.ZodOptional<z.ZodCustom<AbortSignal, AbortSignal>>;
|
|
789
848
|
}, z.core.$strip>;
|
|
@@ -807,6 +866,12 @@ export interface ProcessedTurn {
|
|
|
807
866
|
reasoning?: string;
|
|
808
867
|
/** Tool calls requested by the model */
|
|
809
868
|
toolCalls: PendingToolCall[];
|
|
869
|
+
/** Model-emitted tool calls that were invalid or missing required fields */
|
|
870
|
+
invalidToolCalls: Array<{
|
|
871
|
+
id: string;
|
|
872
|
+
name?: string;
|
|
873
|
+
reason: "missing_name" | "missing_arguments" | "invalid_arguments";
|
|
874
|
+
}>;
|
|
810
875
|
/** Token usage for this turn */
|
|
811
876
|
usage: {
|
|
812
877
|
inputTokens: number;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@clinebot/agents",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.3",
|
|
4
4
|
"repository": {
|
|
5
5
|
"type": "git",
|
|
6
6
|
"url": "https://github.com/cline/cline.git",
|
|
@@ -8,23 +8,23 @@
|
|
|
8
8
|
},
|
|
9
9
|
"main": "dist/index.js",
|
|
10
10
|
"dependencies": {
|
|
11
|
-
"@clinebot/llms": "
|
|
12
|
-
"@clinebot/shared": "workspace:*",
|
|
11
|
+
"@clinebot/llms": "0.0.3",
|
|
13
12
|
"zod": "^4.3.6"
|
|
14
13
|
},
|
|
15
14
|
"exports": {
|
|
16
15
|
".": {
|
|
17
|
-
"
|
|
16
|
+
"browser": "./dist/index.browser.js",
|
|
17
|
+
"development": "./dist/index.js",
|
|
18
18
|
"types": "./dist/index.d.ts",
|
|
19
19
|
"import": "./dist/index.js"
|
|
20
20
|
},
|
|
21
21
|
"./node": {
|
|
22
|
-
"development": "./
|
|
23
|
-
"types": "./
|
|
22
|
+
"development": "./dist/index.node.js",
|
|
23
|
+
"types": "./dist/index.node.d.ts",
|
|
24
24
|
"import": "./dist/index.node.js"
|
|
25
25
|
},
|
|
26
26
|
"./browser": {
|
|
27
|
-
"development": "./
|
|
27
|
+
"development": "./dist/index.browser.js",
|
|
28
28
|
"types": "./dist/index.browser.d.ts",
|
|
29
29
|
"import": "./dist/index.browser.js"
|
|
30
30
|
}
|
package/src/agent.test.ts
CHANGED
|
@@ -197,6 +197,120 @@ describe("Agent", () => {
|
|
|
197
197
|
expect(logger.error).not.toHaveBeenCalled();
|
|
198
198
|
});
|
|
199
199
|
|
|
200
|
+
it("fails after reaching max consecutive mistakes by default", async () => {
|
|
201
|
+
const { Agent } = await import("./agent.js");
|
|
202
|
+
const handler = makeHandler([
|
|
203
|
+
[
|
|
204
|
+
{
|
|
205
|
+
type: "done",
|
|
206
|
+
id: "r1",
|
|
207
|
+
success: false,
|
|
208
|
+
error: "upstream api timeout",
|
|
209
|
+
},
|
|
210
|
+
],
|
|
211
|
+
[
|
|
212
|
+
{
|
|
213
|
+
type: "done",
|
|
214
|
+
id: "r2",
|
|
215
|
+
success: false,
|
|
216
|
+
error: "upstream api timeout",
|
|
217
|
+
},
|
|
218
|
+
],
|
|
219
|
+
]);
|
|
220
|
+
createHandlerMock.mockReturnValue(handler);
|
|
221
|
+
|
|
222
|
+
const agent = new Agent({
|
|
223
|
+
providerId: "anthropic",
|
|
224
|
+
modelId: "mock-model",
|
|
225
|
+
systemPrompt: "Handle retries",
|
|
226
|
+
tools: [],
|
|
227
|
+
maxConsecutiveMistakes: 2,
|
|
228
|
+
});
|
|
229
|
+
|
|
230
|
+
await expect(agent.run("retry")).rejects.toThrow("upstream api timeout");
|
|
231
|
+
expect(handler.createMessage).toHaveBeenCalledTimes(2);
|
|
232
|
+
});
|
|
233
|
+
|
|
234
|
+
it("fails immediately on non-recoverable API errors", async () => {
|
|
235
|
+
const { Agent } = await import("./agent.js");
|
|
236
|
+
const handler = makeHandler([
|
|
237
|
+
[
|
|
238
|
+
{
|
|
239
|
+
type: "done",
|
|
240
|
+
id: "r1",
|
|
241
|
+
success: false,
|
|
242
|
+
error:
|
|
243
|
+
'{"error":{"code":404,"message":"models/gemini-flash-latest-1 is not found"}}',
|
|
244
|
+
},
|
|
245
|
+
],
|
|
246
|
+
]);
|
|
247
|
+
createHandlerMock.mockReturnValue(handler);
|
|
248
|
+
|
|
249
|
+
const agent = new Agent({
|
|
250
|
+
providerId: "gemini",
|
|
251
|
+
modelId: "gemini-flash-latest-1",
|
|
252
|
+
systemPrompt: "Handle retries",
|
|
253
|
+
tools: [],
|
|
254
|
+
maxConsecutiveMistakes: 3,
|
|
255
|
+
});
|
|
256
|
+
|
|
257
|
+
await expect(agent.run("retry")).rejects.toThrow("404");
|
|
258
|
+
expect(handler.createMessage).toHaveBeenCalledTimes(1);
|
|
259
|
+
expect(
|
|
260
|
+
agent
|
|
261
|
+
.getMessages()
|
|
262
|
+
.some((message) =>
|
|
263
|
+
JSON.stringify(message).includes("previous turn failed"),
|
|
264
|
+
),
|
|
265
|
+
).toBe(false);
|
|
266
|
+
});
|
|
267
|
+
|
|
268
|
+
it("continues after mistake limit when callback returns continue", async () => {
|
|
269
|
+
const { Agent } = await import("./agent.js");
|
|
270
|
+
const handler = makeHandler([
|
|
271
|
+
[
|
|
272
|
+
{
|
|
273
|
+
type: "done",
|
|
274
|
+
id: "r1",
|
|
275
|
+
success: false,
|
|
276
|
+
error: "temporary api failure",
|
|
277
|
+
},
|
|
278
|
+
],
|
|
279
|
+
[
|
|
280
|
+
{
|
|
281
|
+
type: "done",
|
|
282
|
+
id: "r2",
|
|
283
|
+
success: false,
|
|
284
|
+
error: "temporary api failure",
|
|
285
|
+
},
|
|
286
|
+
],
|
|
287
|
+
[
|
|
288
|
+
{ type: "text", id: "r3", text: "Recovered" },
|
|
289
|
+
{ type: "usage", id: "r3", inputTokens: 3, outputTokens: 2 },
|
|
290
|
+
{ type: "done", id: "r3", success: true },
|
|
291
|
+
],
|
|
292
|
+
]);
|
|
293
|
+
createHandlerMock.mockReturnValue(handler);
|
|
294
|
+
|
|
295
|
+
const onConsecutiveMistakeLimitReached = vi.fn().mockResolvedValue({
|
|
296
|
+
action: "continue",
|
|
297
|
+
guidance: "mistake_limit_reached: continue and recover",
|
|
298
|
+
});
|
|
299
|
+
const agent = new Agent({
|
|
300
|
+
providerId: "anthropic",
|
|
301
|
+
modelId: "mock-model",
|
|
302
|
+
systemPrompt: "Handle retries",
|
|
303
|
+
tools: [],
|
|
304
|
+
maxConsecutiveMistakes: 2,
|
|
305
|
+
onConsecutiveMistakeLimitReached,
|
|
306
|
+
});
|
|
307
|
+
|
|
308
|
+
const result = await agent.run("retry");
|
|
309
|
+
expect(onConsecutiveMistakeLimitReached).toHaveBeenCalledTimes(1);
|
|
310
|
+
expect(result.finishReason).toBe("completed");
|
|
311
|
+
expect(result.text).toBe("Recovered");
|
|
312
|
+
});
|
|
313
|
+
|
|
200
314
|
it("executes tool calls and applies tool policy approval", async () => {
|
|
201
315
|
const { Agent } = await import("./agent.js");
|
|
202
316
|
const mathTool: Tool<{ a: number; b: number }, { total: number }> =
|
|
@@ -451,6 +565,78 @@ describe("Agent", () => {
|
|
|
451
565
|
});
|
|
452
566
|
});
|
|
453
567
|
|
|
568
|
+
it("deduplicates streamed tool calls when function.id and call_id both appear", async () => {
|
|
569
|
+
const { Agent } = await import("./agent.js");
|
|
570
|
+
const executeRunCommands = vi.fn(
|
|
571
|
+
async ({ commands }: { commands: string[] }) => commands,
|
|
572
|
+
);
|
|
573
|
+
const runCommandsTool = createTool({
|
|
574
|
+
name: "run_commands",
|
|
575
|
+
description: "Run commands",
|
|
576
|
+
inputSchema: {
|
|
577
|
+
type: "object",
|
|
578
|
+
properties: {
|
|
579
|
+
commands: {
|
|
580
|
+
type: "array",
|
|
581
|
+
items: { type: "string" },
|
|
582
|
+
},
|
|
583
|
+
},
|
|
584
|
+
required: ["commands"],
|
|
585
|
+
},
|
|
586
|
+
execute: executeRunCommands,
|
|
587
|
+
}) as Tool;
|
|
588
|
+
|
|
589
|
+
const handler = makeHandler([
|
|
590
|
+
[
|
|
591
|
+
{
|
|
592
|
+
type: "tool_calls",
|
|
593
|
+
id: "r1",
|
|
594
|
+
tool_call: {
|
|
595
|
+
function: {
|
|
596
|
+
id: "fc_1",
|
|
597
|
+
name: "run_commands",
|
|
598
|
+
arguments: '{"commands":["pwd"]}',
|
|
599
|
+
},
|
|
600
|
+
},
|
|
601
|
+
},
|
|
602
|
+
{
|
|
603
|
+
type: "tool_calls",
|
|
604
|
+
id: "r1",
|
|
605
|
+
tool_call: {
|
|
606
|
+
call_id: "call_1",
|
|
607
|
+
function: {
|
|
608
|
+
id: "fc_1",
|
|
609
|
+
name: "run_commands",
|
|
610
|
+
arguments: '{"commands":["pwd"]}',
|
|
611
|
+
},
|
|
612
|
+
},
|
|
613
|
+
},
|
|
614
|
+
{ type: "usage", id: "r1", inputTokens: 4, outputTokens: 2 },
|
|
615
|
+
{ type: "done", id: "r1", success: true },
|
|
616
|
+
],
|
|
617
|
+
[
|
|
618
|
+
{ type: "text", id: "r2", text: "Done" },
|
|
619
|
+
{ type: "usage", id: "r2", inputTokens: 2, outputTokens: 1 },
|
|
620
|
+
{ type: "done", id: "r2", success: true },
|
|
621
|
+
],
|
|
622
|
+
]);
|
|
623
|
+
createHandlerMock.mockReturnValue(handler);
|
|
624
|
+
|
|
625
|
+
const agent = new Agent({
|
|
626
|
+
providerId: "anthropic",
|
|
627
|
+
modelId: "mock-model",
|
|
628
|
+
systemPrompt: "Use tools",
|
|
629
|
+
tools: [runCommandsTool],
|
|
630
|
+
});
|
|
631
|
+
|
|
632
|
+
const result = await agent.run("run a command");
|
|
633
|
+
expect(result.finishReason).toBe("completed");
|
|
634
|
+
expect(result.toolCalls).toHaveLength(1);
|
|
635
|
+
expect(result.toolCalls[0]?.error).toBeUndefined();
|
|
636
|
+
expect(result.toolCalls[0]?.output).toEqual(["pwd"]);
|
|
637
|
+
expect(executeRunCommands).toHaveBeenCalledTimes(1);
|
|
638
|
+
});
|
|
639
|
+
|
|
454
640
|
it("passes through array-shaped read_files tool args", async () => {
|
|
455
641
|
const { Agent } = await import("./agent.js");
|
|
456
642
|
const readFilesTool = createTool({
|