@clinebot/agents 0.0.0

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.
Files changed (90) hide show
  1. package/README.md +145 -0
  2. package/dist/agent-input.d.ts +2 -0
  3. package/dist/agent.d.ts +56 -0
  4. package/dist/extensions.d.ts +21 -0
  5. package/dist/hooks/engine.d.ts +42 -0
  6. package/dist/hooks/index.d.ts +2 -0
  7. package/dist/hooks/lifecycle.d.ts +5 -0
  8. package/dist/hooks/node.d.ts +2 -0
  9. package/dist/hooks/subprocess-runner.d.ts +16 -0
  10. package/dist/hooks/subprocess.d.ts +268 -0
  11. package/dist/index.browser.d.ts +1 -0
  12. package/dist/index.browser.js +49 -0
  13. package/dist/index.d.ts +15 -0
  14. package/dist/index.js +49 -0
  15. package/dist/index.node.d.ts +5 -0
  16. package/dist/index.node.js +49 -0
  17. package/dist/mcp/index.d.ts +4 -0
  18. package/dist/mcp/policies.d.ts +14 -0
  19. package/dist/mcp/tools.d.ts +9 -0
  20. package/dist/mcp/types.d.ts +35 -0
  21. package/dist/message-builder.d.ts +31 -0
  22. package/dist/prompts/cline.d.ts +1 -0
  23. package/dist/prompts/index.d.ts +1 -0
  24. package/dist/runtime/agent-runtime-bus.d.ts +13 -0
  25. package/dist/runtime/conversation-store.d.ts +16 -0
  26. package/dist/runtime/lifecycle-orchestrator.d.ts +28 -0
  27. package/dist/runtime/tool-orchestrator.d.ts +39 -0
  28. package/dist/runtime/turn-processor.d.ts +21 -0
  29. package/dist/teams/index.d.ts +3 -0
  30. package/dist/teams/multi-agent.d.ts +566 -0
  31. package/dist/teams/spawn-agent-tool.d.ts +85 -0
  32. package/dist/teams/team-tools.d.ts +51 -0
  33. package/dist/tools/ask-question.d.ts +12 -0
  34. package/dist/tools/create.d.ts +59 -0
  35. package/dist/tools/execution.d.ts +61 -0
  36. package/dist/tools/formatting.d.ts +20 -0
  37. package/dist/tools/index.d.ts +11 -0
  38. package/dist/tools/registry.d.ts +26 -0
  39. package/dist/tools/validation.d.ts +27 -0
  40. package/dist/types.d.ts +826 -0
  41. package/package.json +54 -0
  42. package/src/agent-input.ts +116 -0
  43. package/src/agent.test.ts +931 -0
  44. package/src/agent.ts +1050 -0
  45. package/src/example.test.ts +564 -0
  46. package/src/extensions.ts +337 -0
  47. package/src/hooks/engine.test.ts +163 -0
  48. package/src/hooks/engine.ts +537 -0
  49. package/src/hooks/index.ts +6 -0
  50. package/src/hooks/lifecycle.ts +239 -0
  51. package/src/hooks/node.ts +18 -0
  52. package/src/hooks/subprocess-runner.ts +140 -0
  53. package/src/hooks/subprocess.test.ts +180 -0
  54. package/src/hooks/subprocess.ts +620 -0
  55. package/src/index.browser.ts +1 -0
  56. package/src/index.node.ts +21 -0
  57. package/src/index.ts +133 -0
  58. package/src/mcp/index.ts +17 -0
  59. package/src/mcp/policies.test.ts +51 -0
  60. package/src/mcp/policies.ts +53 -0
  61. package/src/mcp/tools.test.ts +76 -0
  62. package/src/mcp/tools.ts +60 -0
  63. package/src/mcp/types.ts +41 -0
  64. package/src/message-builder.test.ts +175 -0
  65. package/src/message-builder.ts +429 -0
  66. package/src/prompts/cline.ts +49 -0
  67. package/src/prompts/index.ts +1 -0
  68. package/src/runtime/agent-runtime-bus.ts +53 -0
  69. package/src/runtime/conversation-store.ts +61 -0
  70. package/src/runtime/lifecycle-orchestrator.ts +90 -0
  71. package/src/runtime/tool-orchestrator.ts +177 -0
  72. package/src/runtime/turn-processor.ts +250 -0
  73. package/src/streaming.test.ts +197 -0
  74. package/src/streaming.ts +307 -0
  75. package/src/teams/index.ts +63 -0
  76. package/src/teams/multi-agent.lifecycle.test.ts +48 -0
  77. package/src/teams/multi-agent.ts +1866 -0
  78. package/src/teams/spawn-agent-tool.test.ts +172 -0
  79. package/src/teams/spawn-agent-tool.ts +223 -0
  80. package/src/teams/team-tools.test.ts +448 -0
  81. package/src/teams/team-tools.ts +929 -0
  82. package/src/tools/ask-question.ts +78 -0
  83. package/src/tools/create.ts +104 -0
  84. package/src/tools/execution.ts +311 -0
  85. package/src/tools/formatting.ts +73 -0
  86. package/src/tools/index.ts +45 -0
  87. package/src/tools/registry.ts +52 -0
  88. package/src/tools/tools.test.ts +292 -0
  89. package/src/tools/validation.ts +73 -0
  90. package/src/types.ts +966 -0
package/src/types.ts ADDED
@@ -0,0 +1,966 @@
1
+ /**
2
+ * Types and Zod Schemas for the Agent Package
3
+ *
4
+ * This module defines all TypeScript types and Zod validation schemas
5
+ * for agent configuration, tools, events, and results.
6
+ */
7
+
8
+ import type { providers as LlmsProviders } from "@clinebot/llms";
9
+ import {
10
+ type BasicLogger,
11
+ type Tool,
12
+ type ToolApprovalRequest,
13
+ type ToolApprovalResult,
14
+ type ToolCallRecord,
15
+ ToolCallRecordSchema,
16
+ type ToolPolicy,
17
+ } from "@clinebot/shared";
18
+ import { z } from "zod";
19
+
20
+ export type {
21
+ BasicLogger,
22
+ Tool,
23
+ ToolApprovalRequest,
24
+ ToolApprovalResult,
25
+ ToolCallRecord,
26
+ ToolContext,
27
+ ToolPolicy,
28
+ } from "@clinebot/shared";
29
+ export { ToolCallRecordSchema, ToolContextSchema } from "@clinebot/shared";
30
+
31
+ // =============================================================================
32
+ // Agent Events
33
+ // =============================================================================
34
+
35
+ /**
36
+ * Events emitted during agent execution
37
+ */
38
+ export type AgentEvent =
39
+ | AgentContentStartEvent
40
+ | AgentContentEndEvent
41
+ | AgentIterationStartEvent
42
+ | AgentIterationEndEvent
43
+ | AgentUsageEvent
44
+ | AgentDoneEvent
45
+ | AgentErrorEvent;
46
+
47
+ export type AgentContentType = "text" | "reasoning" | "tool";
48
+
49
+ export interface AgentContentStartEvent {
50
+ type: "content_start";
51
+ contentType: AgentContentType;
52
+ /** The text chunk received from the model */
53
+ text?: string;
54
+ /** Accumulated text so far in this turn */
55
+ accumulated?: string;
56
+ /** The reasoning/thinking text from the model */
57
+ reasoning?: string;
58
+ /** Whether this is redacted reasoning */
59
+ redacted?: boolean;
60
+ /** Name of the tool being called */
61
+ toolName?: string;
62
+ /** Unique identifier for this tool call */
63
+ toolCallId?: string;
64
+ /** Input being passed to the tool */
65
+ input?: unknown;
66
+ }
67
+
68
+ export interface AgentContentEndEvent {
69
+ type: "content_end";
70
+ contentType: AgentContentType;
71
+ /** Final text generated for this turn */
72
+ text?: string;
73
+ /** Final reasoning/thinking text generated for this turn */
74
+ reasoning?: string;
75
+ /** Name of the tool that completed */
76
+ toolName?: string;
77
+ /** Unique identifier for this tool call */
78
+ toolCallId?: string;
79
+ /** Output from the tool */
80
+ output?: unknown;
81
+ /** Error message if the tool failed */
82
+ error?: string;
83
+ /** Time taken in milliseconds for tool content */
84
+ durationMs?: number;
85
+ }
86
+
87
+ export interface AgentIterationStartEvent {
88
+ type: "iteration_start";
89
+ /** The iteration number (1-based) */
90
+ iteration: number;
91
+ }
92
+
93
+ export interface AgentIterationEndEvent {
94
+ type: "iteration_end";
95
+ /** The iteration number that just completed */
96
+ iteration: number;
97
+ /** Whether this iteration had any tool calls */
98
+ hadToolCalls: boolean;
99
+ /** Number of tool calls in this iteration */
100
+ toolCallCount: number;
101
+ }
102
+
103
+ export interface AgentUsageEvent {
104
+ type: "usage";
105
+ /** Number of input tokens for this turn */
106
+ inputTokens: number;
107
+ /** Number of output tokens for this turn */
108
+ outputTokens: number;
109
+ /** Tokens read from cache */
110
+ cacheReadTokens?: number;
111
+ /** Tokens written to cache */
112
+ cacheWriteTokens?: number;
113
+ /** Cost for this turn */
114
+ cost?: number;
115
+ /** Accumulated totals */
116
+ totalInputTokens: number;
117
+ totalOutputTokens: number;
118
+ totalCost?: number;
119
+ }
120
+
121
+ export interface AgentDoneEvent {
122
+ type: "done";
123
+ /** The reason the agent stopped */
124
+ reason: AgentFinishReason;
125
+ /** Final text output */
126
+ text: string;
127
+ /** Total number of iterations */
128
+ iterations: number;
129
+ }
130
+
131
+ export interface AgentErrorEvent {
132
+ type: "error";
133
+ /** The error that occurred */
134
+ error: Error;
135
+ /** Whether the error is recoverable */
136
+ recoverable: boolean;
137
+ /** Current iteration when error occurred */
138
+ iteration: number;
139
+ }
140
+
141
+ // =============================================================================
142
+ // Hooks
143
+ // =============================================================================
144
+
145
+ /**
146
+ * Hook error handling behavior.
147
+ * - "ignore": swallow hook errors and continue agent execution
148
+ * - "throw": fail agent execution when a hook throws
149
+ */
150
+ export type HookErrorMode = "ignore" | "throw";
151
+
152
+ /**
153
+ * Common controls supported by lifecycle hooks.
154
+ */
155
+ export interface AgentHookControl {
156
+ /**
157
+ * Cancel the active run after this hook.
158
+ * When true, finishReason becomes "aborted".
159
+ */
160
+ cancel?: boolean;
161
+ /**
162
+ * Request explicit approval before executing the active tool call.
163
+ * Only applied for `onToolCallStart`.
164
+ */
165
+ review?: boolean;
166
+ /**
167
+ * Optional context appended to the conversation as a user text block.
168
+ */
169
+ context?: string;
170
+ /**
171
+ * Optional replacement input for the active tool call.
172
+ * Only applied for `onToolCallStart`.
173
+ */
174
+ overrideInput?: unknown;
175
+ /**
176
+ * Optional replacement system prompt.
177
+ * Primarily used by before-agent-start hook stages.
178
+ */
179
+ systemPrompt?: string;
180
+ /**
181
+ * Optional messages to append before model turn execution.
182
+ * Primarily used by before-agent-start hook stages.
183
+ */
184
+ appendMessages?: LlmsProviders.Message[];
185
+ }
186
+
187
+ export interface AgentHookRunStartContext {
188
+ agentId: string;
189
+ conversationId: string;
190
+ parentAgentId: string | null;
191
+ userMessage: string;
192
+ }
193
+
194
+ export interface AgentHookScheduleContext {
195
+ scheduleId: string;
196
+ executionId?: string;
197
+ trigger: "scheduled" | "manual";
198
+ triggeredAt?: string;
199
+ }
200
+
201
+ export interface AgentHookSessionStartContext {
202
+ agentId: string;
203
+ conversationId: string;
204
+ parentAgentId: string | null;
205
+ schedule?: AgentHookScheduleContext;
206
+ }
207
+
208
+ export interface AgentHookRunEndContext {
209
+ agentId: string;
210
+ conversationId: string;
211
+ parentAgentId: string | null;
212
+ result: AgentResult;
213
+ }
214
+
215
+ export interface AgentHookIterationStartContext {
216
+ agentId: string;
217
+ conversationId: string;
218
+ parentAgentId: string | null;
219
+ iteration: number;
220
+ }
221
+
222
+ export interface AgentHookIterationEndContext {
223
+ agentId: string;
224
+ conversationId: string;
225
+ parentAgentId: string | null;
226
+ iteration: number;
227
+ hadToolCalls: boolean;
228
+ toolCallCount: number;
229
+ }
230
+
231
+ export interface AgentHookTurnStartContext {
232
+ agentId: string;
233
+ conversationId: string;
234
+ parentAgentId: string | null;
235
+ iteration: number;
236
+ messages: LlmsProviders.Message[];
237
+ }
238
+
239
+ export interface AgentHookTurnEndContext {
240
+ agentId: string;
241
+ conversationId: string;
242
+ parentAgentId: string | null;
243
+ iteration: number;
244
+ turn: ProcessedTurn;
245
+ }
246
+
247
+ export interface AgentHookToolCallStartContext {
248
+ agentId: string;
249
+ conversationId: string;
250
+ parentAgentId: string | null;
251
+ iteration: number;
252
+ call: PendingToolCall;
253
+ }
254
+
255
+ export interface AgentHookToolCallEndContext {
256
+ agentId: string;
257
+ conversationId: string;
258
+ parentAgentId: string | null;
259
+ iteration: number;
260
+ record: ToolCallRecord;
261
+ }
262
+
263
+ export interface AgentHookErrorContext {
264
+ agentId: string;
265
+ conversationId: string;
266
+ parentAgentId: string | null;
267
+ iteration: number;
268
+ error: Error;
269
+ }
270
+
271
+ export interface AgentHookSessionShutdownContext {
272
+ agentId: string;
273
+ conversationId: string;
274
+ parentAgentId: string | null;
275
+ /**
276
+ * Optional reason for shutdown (e.g. "ctrl_d", "process_exit")
277
+ */
278
+ reason?: string;
279
+ }
280
+
281
+ export type HookStage =
282
+ | "input"
283
+ | "runtime_event"
284
+ | "session_start"
285
+ | "run_start"
286
+ | "iteration_start"
287
+ | "turn_start"
288
+ | "before_agent_start"
289
+ | "tool_call_before"
290
+ | "tool_call_after"
291
+ | "turn_end"
292
+ | "iteration_end"
293
+ | "run_end"
294
+ | "session_shutdown"
295
+ | "error";
296
+
297
+ export type HookMode = "blocking" | "async";
298
+ export type HookFailureMode = "fail_open" | "fail_closed";
299
+
300
+ export interface HookStagePolicy {
301
+ mode: HookMode;
302
+ timeoutMs: number;
303
+ retries: number;
304
+ retryDelayMs: number;
305
+ failureMode: HookFailureMode;
306
+ maxConcurrency: number;
307
+ queueLimit: number;
308
+ }
309
+
310
+ export type HookStagePolicyInput = Partial<HookStagePolicy>;
311
+
312
+ export interface HookPolicies {
313
+ defaultPolicy?: HookStagePolicyInput;
314
+ stages?: Partial<Record<HookStage, HookStagePolicyInput>>;
315
+ handlers?: Record<string, HookStagePolicyInput>;
316
+ }
317
+
318
+ export interface HookEventEnvelope<TPayload = unknown> {
319
+ eventId: string;
320
+ stage: HookStage;
321
+ createdAt: Date;
322
+ sequence: number;
323
+ runId: string;
324
+ agentId: string;
325
+ conversationId: string;
326
+ parentAgentId: string | null;
327
+ iteration?: number;
328
+ parentEventId?: string;
329
+ payload: TPayload;
330
+ }
331
+
332
+ export type HookAttemptStatus = "ok" | "timeout" | "error" | "skipped";
333
+
334
+ export interface HookHandlerResult {
335
+ handlerName: string;
336
+ stage: HookStage;
337
+ status: HookAttemptStatus;
338
+ attempts: number;
339
+ durationMs: number;
340
+ error?: Error;
341
+ control?: AgentHookControl;
342
+ }
343
+
344
+ export interface HookDispatchResult {
345
+ event: HookEventEnvelope;
346
+ queued: boolean;
347
+ dropped: boolean;
348
+ control?: AgentHookControl;
349
+ results: HookHandlerResult[];
350
+ }
351
+
352
+ // =============================================================================
353
+ // Extensions
354
+ // =============================================================================
355
+
356
+ export interface AgentExtensionCommand {
357
+ name: string;
358
+ description?: string;
359
+ handler?: (input: string) => Promise<string> | string;
360
+ }
361
+
362
+ export interface AgentExtensionShortcut {
363
+ name: string;
364
+ value: string;
365
+ description?: string;
366
+ }
367
+
368
+ export interface AgentExtensionFlag {
369
+ name: string;
370
+ description?: string;
371
+ defaultValue?: boolean | string | number;
372
+ }
373
+
374
+ export interface AgentExtensionMessageRenderer {
375
+ name: string;
376
+ render: (message: LlmsProviders.Message) => string;
377
+ }
378
+
379
+ export interface AgentExtensionProvider {
380
+ name: string;
381
+ description?: string;
382
+ metadata?: Record<string, unknown>;
383
+ }
384
+
385
+ export interface AgentExtensionRuntimeEventContext {
386
+ agentId: string;
387
+ conversationId: string;
388
+ parentAgentId: string | null;
389
+ event: AgentEvent;
390
+ }
391
+
392
+ export interface AgentExtensionSessionStartContext {
393
+ agentId: string;
394
+ conversationId: string;
395
+ parentAgentId: string | null;
396
+ schedule?: AgentHookScheduleContext;
397
+ }
398
+
399
+ export interface AgentExtensionSessionShutdownContext {
400
+ agentId: string;
401
+ conversationId: string;
402
+ parentAgentId: string | null;
403
+ reason?: string;
404
+ }
405
+
406
+ export interface AgentExtensionInputContext {
407
+ agentId: string;
408
+ conversationId: string;
409
+ parentAgentId: string | null;
410
+ mode: "run" | "continue";
411
+ input: string;
412
+ }
413
+
414
+ export interface AgentExtensionBeforeAgentStartContext {
415
+ agentId: string;
416
+ conversationId: string;
417
+ parentAgentId: string | null;
418
+ iteration: number;
419
+ systemPrompt: string;
420
+ messages: LlmsProviders.Message[];
421
+ }
422
+
423
+ export interface AgentExtensionBeforeAgentStartControl
424
+ extends AgentHookControl {
425
+ systemPrompt?: string;
426
+ appendMessages?: LlmsProviders.Message[];
427
+ }
428
+
429
+ export interface AgentExtensionApi {
430
+ registerTool: (tool: Tool) => void;
431
+ registerCommand: (command: AgentExtensionCommand) => void;
432
+ registerShortcut: (shortcut: AgentExtensionShortcut) => void;
433
+ registerFlag: (flag: AgentExtensionFlag) => void;
434
+ registerMessageRenderer: (renderer: AgentExtensionMessageRenderer) => void;
435
+ registerProvider: (provider: AgentExtensionProvider) => void;
436
+ }
437
+
438
+ export type AgentExtensionCapability =
439
+ | "hooks"
440
+ | "tools"
441
+ | "commands"
442
+ | "shortcuts"
443
+ | "flags"
444
+ | "message_renderers"
445
+ | "providers";
446
+
447
+ export type AgentExtensionHookStage =
448
+ | "input"
449
+ | "runtime_event"
450
+ | "session_start"
451
+ | "run_start"
452
+ | "iteration_start"
453
+ | "turn_start"
454
+ | "before_agent_start"
455
+ | "tool_call_before"
456
+ | "tool_call_after"
457
+ | "turn_end"
458
+ | "iteration_end"
459
+ | "run_end"
460
+ | "session_shutdown"
461
+ | "error";
462
+
463
+ export interface PluginManifest {
464
+ capabilities: AgentExtensionCapability[];
465
+ hookStages?: AgentExtensionHookStage[];
466
+ }
467
+
468
+ export interface AgentExtension {
469
+ name: string;
470
+ manifest: PluginManifest;
471
+ setup?: (api: AgentExtensionApi) => void | Promise<void>;
472
+ onSessionStart?: (
473
+ ctx: AgentExtensionSessionStartContext,
474
+ ) => undefined | AgentHookControl | Promise<undefined | AgentHookControl>;
475
+ onRunStart?: (
476
+ ctx: AgentHookRunStartContext,
477
+ ) => undefined | AgentHookControl | Promise<undefined | AgentHookControl>;
478
+ onIterationStart?: (
479
+ ctx: AgentHookIterationStartContext,
480
+ ) => undefined | AgentHookControl | Promise<undefined | AgentHookControl>;
481
+ onTurnStart?: (
482
+ ctx: AgentHookTurnStartContext,
483
+ ) => undefined | AgentHookControl | Promise<undefined | AgentHookControl>;
484
+ onInput?: (
485
+ ctx: AgentExtensionInputContext,
486
+ ) => undefined | AgentHookControl | Promise<undefined | AgentHookControl>;
487
+ onBeforeAgentStart?: (
488
+ ctx: AgentExtensionBeforeAgentStartContext,
489
+ ) =>
490
+ | undefined
491
+ | AgentExtensionBeforeAgentStartControl
492
+ | Promise<undefined | AgentExtensionBeforeAgentStartControl>;
493
+ onToolCall?: (
494
+ ctx: AgentHookToolCallStartContext,
495
+ ) => undefined | AgentHookControl | Promise<undefined | AgentHookControl>;
496
+ onToolResult?: (
497
+ ctx: AgentHookToolCallEndContext,
498
+ ) => undefined | AgentHookControl | Promise<undefined | AgentHookControl>;
499
+ onAgentEnd?: (
500
+ ctx: AgentHookTurnEndContext,
501
+ ) => undefined | AgentHookControl | Promise<undefined | AgentHookControl>;
502
+ onIterationEnd?: (ctx: AgentHookIterationEndContext) => void | Promise<void>;
503
+ onRunEnd?: (ctx: AgentHookRunEndContext) => void | Promise<void>;
504
+ onSessionShutdown?: (
505
+ ctx: AgentExtensionSessionShutdownContext,
506
+ ) => undefined | AgentHookControl | Promise<undefined | AgentHookControl>;
507
+ onRuntimeEvent?: (
508
+ ctx: AgentExtensionRuntimeEventContext,
509
+ ) => void | Promise<void>;
510
+ onError?: (ctx: AgentHookErrorContext) => void | Promise<void>;
511
+ }
512
+
513
+ export interface AgentExtensionRegistry {
514
+ tools: Tool[];
515
+ commands: AgentExtensionCommand[];
516
+ shortcuts: AgentExtensionShortcut[];
517
+ flags: AgentExtensionFlag[];
518
+ messageRenderers: AgentExtensionMessageRenderer[];
519
+ providers: AgentExtensionProvider[];
520
+ }
521
+
522
+ /**
523
+ * Lifecycle hooks for observing or influencing agent execution.
524
+ */
525
+ export interface AgentHooks {
526
+ onSessionStart?: (
527
+ ctx: AgentHookSessionStartContext,
528
+ ) => undefined | AgentHookControl | Promise<undefined | AgentHookControl>;
529
+ onRunStart?: (
530
+ ctx: AgentHookRunStartContext,
531
+ ) => undefined | AgentHookControl | Promise<undefined | AgentHookControl>;
532
+ onRunEnd?: (ctx: AgentHookRunEndContext) => void | Promise<void>;
533
+ onIterationStart?: (
534
+ ctx: AgentHookIterationStartContext,
535
+ ) => undefined | AgentHookControl | Promise<undefined | AgentHookControl>;
536
+ onIterationEnd?: (ctx: AgentHookIterationEndContext) => void | Promise<void>;
537
+ onTurnStart?: (
538
+ ctx: AgentHookTurnStartContext,
539
+ ) => undefined | AgentHookControl | Promise<undefined | AgentHookControl>;
540
+ onTurnEnd?: (
541
+ ctx: AgentHookTurnEndContext,
542
+ ) => undefined | AgentHookControl | Promise<undefined | AgentHookControl>;
543
+ onToolCallStart?: (
544
+ ctx: AgentHookToolCallStartContext,
545
+ ) => undefined | AgentHookControl | Promise<undefined | AgentHookControl>;
546
+ onToolCallEnd?: (
547
+ ctx: AgentHookToolCallEndContext,
548
+ ) => undefined | AgentHookControl | Promise<undefined | AgentHookControl>;
549
+ onSessionShutdown?: (
550
+ ctx: AgentHookSessionShutdownContext,
551
+ ) => undefined | AgentHookControl | Promise<undefined | AgentHookControl>;
552
+ onError?: (ctx: AgentHookErrorContext) => void | Promise<void>;
553
+ }
554
+
555
+ // =============================================================================
556
+ // Agent Finish Reasons
557
+ // =============================================================================
558
+
559
+ /**
560
+ * Reasons why the agent stopped executing
561
+ */
562
+ export type AgentFinishReason =
563
+ | "completed" // Normal completion (no more tool calls)
564
+ | "max_iterations" // Hit the maximum iteration limit
565
+ | "aborted" // User or system aborted
566
+ | "error"; // Unrecoverable error occurred
567
+
568
+ export const AgentFinishReasonSchema = z.enum([
569
+ "completed",
570
+ "max_iterations",
571
+ "aborted",
572
+ "error",
573
+ ]);
574
+
575
+ // =============================================================================
576
+ // Agent Usage
577
+ // =============================================================================
578
+
579
+ /**
580
+ * Aggregated token usage and cost information
581
+ */
582
+ export interface AgentUsage {
583
+ /** Total input tokens across all iterations */
584
+ inputTokens: number;
585
+ /** Total output tokens across all iterations */
586
+ outputTokens: number;
587
+ /** Total tokens read from cache */
588
+ cacheReadTokens?: number;
589
+ /** Total tokens written to cache */
590
+ cacheWriteTokens?: number;
591
+ /** Total cost in dollars */
592
+ totalCost?: number;
593
+ }
594
+
595
+ export const AgentUsageSchema = z.object({
596
+ inputTokens: z.number(),
597
+ outputTokens: z.number(),
598
+ cacheReadTokens: z.number().optional(),
599
+ cacheWriteTokens: z.number().optional(),
600
+ totalCost: z.number().optional(),
601
+ });
602
+
603
+ // =============================================================================
604
+ // Agent Result
605
+ // =============================================================================
606
+
607
+ /**
608
+ * Result returned from Agent.run()
609
+ */
610
+ export interface AgentResult {
611
+ /** Final text output from the agent */
612
+ text: string;
613
+ /** Aggregated token usage and cost */
614
+ usage: AgentUsage;
615
+ /** Full conversation history */
616
+ messages: LlmsProviders.Message[];
617
+ /** All tool calls made during execution */
618
+ toolCalls: ToolCallRecord[];
619
+ /** Number of loop iterations */
620
+ iterations: number;
621
+ /** Why the agent stopped */
622
+ finishReason: AgentFinishReason;
623
+ /** Model information used */
624
+ model: {
625
+ id: string;
626
+ provider: string;
627
+ info?: LlmsProviders.ModelInfo;
628
+ };
629
+ /** Start time of the run */
630
+ startedAt: Date;
631
+ /** End time of the run */
632
+ endedAt: Date;
633
+ /** Total duration in milliseconds */
634
+ durationMs: number;
635
+ }
636
+
637
+ export const AgentResultSchema = z.object({
638
+ text: z.string(),
639
+ usage: AgentUsageSchema,
640
+ messages: z.array(z.custom<LlmsProviders.Message>()),
641
+ toolCalls: z.array(ToolCallRecordSchema),
642
+ iterations: z.number(),
643
+ finishReason: AgentFinishReasonSchema,
644
+ model: z.object({
645
+ id: z.string(),
646
+ provider: z.string(),
647
+ info: z.custom<LlmsProviders.ModelInfo>().optional(),
648
+ }),
649
+ startedAt: z.date(),
650
+ endedAt: z.date(),
651
+ durationMs: z.number(),
652
+ });
653
+
654
+ // =============================================================================
655
+ // Agent Configuration
656
+ // =============================================================================
657
+
658
+ /**
659
+ * Reasoning effort level for capable models
660
+ */
661
+ export type ReasoningEffort = "low" | "medium" | "high";
662
+
663
+ export const ReasoningEffortSchema = z.enum(["low", "medium", "high"]);
664
+
665
+ /**
666
+ * Configuration for creating an Agent
667
+ */
668
+ export interface AgentConfig {
669
+ // -------------------------------------------------------------------------
670
+ // Provider Settings
671
+ // -------------------------------------------------------------------------
672
+
673
+ /** Provider ID (e.g., "anthropic", "openai", "gemini") */
674
+ providerId: string;
675
+ /** Model ID to use */
676
+ modelId: string;
677
+ /** API key for the provider */
678
+ apiKey?: string;
679
+ /** Custom base URL for the API */
680
+ baseUrl?: string;
681
+ /** Additional headers for API requests */
682
+ headers?: Record<string, string>;
683
+ /** Optional provider model catalog overrides */
684
+ knownModels?: Record<string, LlmsProviders.ModelInfo>;
685
+ /** Optional pre-resolved provider configuration (includes provider-specific fields like aws/gcp). */
686
+ providerConfig?: LlmsProviders.ProviderConfig;
687
+ /**
688
+ * Optional preloaded conversation history for resume flows.
689
+ * When provided, start by calling continue() to preserve history.
690
+ */
691
+ initialMessages?: LlmsProviders.Message[];
692
+
693
+ // -------------------------------------------------------------------------
694
+ // Agent Behavior
695
+ // -------------------------------------------------------------------------
696
+
697
+ /** System prompt for the agent */
698
+ systemPrompt: string;
699
+ /** Tools available to the agent */
700
+ tools: Tool[];
701
+ /**
702
+ * Maximum number of loop iterations
703
+ * If undefined, no iteration cap is enforced.
704
+ */
705
+ maxIterations?: number;
706
+ /**
707
+ * Maximum number of tool calls to execute concurrently in a single iteration.
708
+ * @default 8
709
+ */
710
+ maxParallelToolCalls?: number;
711
+ /**
712
+ * Maximum output tokens per API call
713
+ */
714
+ maxTokensPerTurn?: number;
715
+ /**
716
+ * After this many consecutive iterations with tool calls,
717
+ * inject a reminder text block asking the agent to answer if it has enough info.
718
+ * Set to 0 to disable.
719
+ * @default 6
720
+ */
721
+ reminderAfterIterations?: number;
722
+ /**
723
+ * Custom reminder text to inject after reminderAfterIterations.
724
+ * @default "REMINDER: If you have gathered enough information to answer the user's question, please provide your final answer now without using any more tools."
725
+ */
726
+ reminderText?: string;
727
+ /**
728
+ * Timeout for each API call in milliseconds
729
+ * @default 120000 (2 minutes)
730
+ */
731
+ apiTimeoutMs?: number;
732
+ /**
733
+ * Optional runtime file-content loader used when user files are attached.
734
+ * When omitted, attached files will be represented as loader errors.
735
+ */
736
+ userFileContentLoader?: (path: string) => Promise<string>;
737
+
738
+ // -------------------------------------------------------------------------
739
+ // Reasoning Settings (for capable models)
740
+ // -------------------------------------------------------------------------
741
+
742
+ /**
743
+ * Reasoning effort level
744
+ */
745
+ reasoningEffort?: ReasoningEffort;
746
+ /**
747
+ * Maximum tokens for thinking/reasoning
748
+ */
749
+ thinkingBudgetTokens?: number;
750
+ /**
751
+ * Enable default thinking/reasoning behavior for supported models.
752
+ */
753
+ thinking?: boolean;
754
+
755
+ // -------------------------------------------------------------------------
756
+ // Callbacks
757
+ // -------------------------------------------------------------------------
758
+
759
+ /**
760
+ * Callback for agent events (streaming, progress, etc.)
761
+ */
762
+ onEvent?: (event: AgentEvent) => void;
763
+ /**
764
+ * Lifecycle hooks for observing or influencing agent execution.
765
+ */
766
+ hooks?: AgentHooks;
767
+ /**
768
+ * Optional parent agent ID for spawned/delegated runs.
769
+ * Root agents should leave this undefined.
770
+ */
771
+ parentAgentId?: string;
772
+ /**
773
+ * Extension modules that can intercept lifecycle events and register tools/commands.
774
+ */
775
+ extensions?: AgentExtension[];
776
+ /**
777
+ * How hook errors should be handled.
778
+ * @default "ignore"
779
+ */
780
+ hookErrorMode?: HookErrorMode;
781
+ /**
782
+ * Optional deterministic hook execution policies.
783
+ */
784
+ hookPolicies?: HookPolicies;
785
+ /**
786
+ * Optional schedule metadata for runs initiated by scheduler services.
787
+ * Used by session_start lifecycle hooks.
788
+ */
789
+ schedule?: AgentHookScheduleContext;
790
+ /**
791
+ * Per-tool execution policy. Tool names not listed here default to enabled + autoApprove.
792
+ */
793
+ toolPolicies?: Record<string, ToolPolicy>;
794
+ /**
795
+ * Optional callback to request client approval when a tool policy disables auto-approval.
796
+ */
797
+ requestToolApproval?: (
798
+ request: ToolApprovalRequest,
799
+ ) => Promise<ToolApprovalResult> | ToolApprovalResult;
800
+ /**
801
+ * Optional logger for tracing agent loop lifecycle and recoverable failures.
802
+ */
803
+ logger?: BasicLogger;
804
+
805
+ // -------------------------------------------------------------------------
806
+ // Completion Guard
807
+ // -------------------------------------------------------------------------
808
+
809
+ /**
810
+ * Optional guard that runs when the model returns no tool calls.
811
+ * If it returns a non-empty string, that string is injected as a
812
+ * system-level nudge and the loop continues instead of completing.
813
+ * Use this to prevent premature exit when the agent has unfinished
814
+ * obligations (e.g. in-progress team tasks).
815
+ */
816
+ completionGuard?: () => string | undefined;
817
+
818
+ // -------------------------------------------------------------------------
819
+ // Cancellation
820
+ // -------------------------------------------------------------------------
821
+
822
+ /**
823
+ * Abort signal for cancellation
824
+ */
825
+ abortSignal?: AbortSignal;
826
+ }
827
+
828
+ export const AgentConfigSchema = z.object({
829
+ // Provider Settings
830
+ providerId: z.string(),
831
+ modelId: z.string(),
832
+ apiKey: z.string().optional(),
833
+ baseUrl: z.string().url().optional(),
834
+ headers: z.record(z.string(), z.string()).optional(),
835
+ knownModels: z
836
+ .record(z.string(), z.custom<LlmsProviders.ModelInfo>())
837
+ .optional(),
838
+ providerConfig: z.custom<LlmsProviders.ProviderConfig>().optional(),
839
+ initialMessages: z.array(z.custom<LlmsProviders.Message>()).optional(),
840
+
841
+ // Agent Behavior
842
+ systemPrompt: z.string(),
843
+ tools: z.array(z.custom<Tool>()),
844
+ maxIterations: z.number().positive().optional(),
845
+ maxParallelToolCalls: z.number().int().positive().default(8),
846
+ maxTokensPerTurn: z.number().positive().optional(),
847
+ apiTimeoutMs: z.number().positive().default(120000),
848
+ userFileContentLoader: z
849
+ .function()
850
+ .input([z.string()])
851
+ .output(z.promise(z.string()))
852
+ .optional(),
853
+ reminderAfterIterations: z.number().nonnegative().default(6),
854
+ reminderText: z.string().optional(),
855
+
856
+ // Reasoning Settings
857
+ reasoningEffort: ReasoningEffortSchema.optional(),
858
+ thinkingBudgetTokens: z.number().positive().optional(),
859
+ thinking: z.boolean().optional(),
860
+
861
+ // Callbacks
862
+ onEvent: z
863
+ .function()
864
+ .input([z.custom<AgentEvent>()])
865
+ .output(z.void())
866
+ .optional(),
867
+ hooks: z.custom<AgentHooks>().optional(),
868
+ parentAgentId: z.string().optional(),
869
+ extensions: z.array(z.custom<AgentExtension>()).optional(),
870
+ hookErrorMode: z.enum(["ignore", "throw"]).default("ignore"),
871
+ hookPolicies: z.custom<HookPolicies>().optional(),
872
+ toolPolicies: z
873
+ .record(
874
+ z.string(),
875
+ z.object({
876
+ enabled: z.boolean().optional(),
877
+ autoApprove: z.boolean().optional(),
878
+ }),
879
+ )
880
+ .optional(),
881
+ requestToolApproval: z
882
+ .function()
883
+ .input([
884
+ z.object({
885
+ agentId: z.string(),
886
+ conversationId: z.string(),
887
+ iteration: z.number(),
888
+ toolCallId: z.string(),
889
+ toolName: z.string(),
890
+ input: z.unknown(),
891
+ policy: z
892
+ .object({
893
+ enabled: z.boolean().optional(),
894
+ autoApprove: z.boolean().optional(),
895
+ })
896
+ .default({}),
897
+ }),
898
+ ])
899
+ .output(
900
+ z.union([
901
+ z.object({
902
+ approved: z.boolean(),
903
+ reason: z.string().optional(),
904
+ }),
905
+ z.promise(
906
+ z.object({
907
+ approved: z.boolean(),
908
+ reason: z.string().optional(),
909
+ }),
910
+ ),
911
+ ]),
912
+ )
913
+ .optional(),
914
+ logger: z.custom<BasicLogger>().optional(),
915
+
916
+ // Cancellation
917
+ abortSignal: z.custom<AbortSignal>().optional(),
918
+ });
919
+
920
+ // =============================================================================
921
+ // Internal Types
922
+ // =============================================================================
923
+
924
+ /**
925
+ * Pending tool call from the model
926
+ */
927
+ export interface PendingToolCall {
928
+ id: string;
929
+ name: string;
930
+ input: unknown;
931
+ signature?: string;
932
+ review?: boolean;
933
+ }
934
+
935
+ /**
936
+ * Processed response from one turn of the loop
937
+ */
938
+ export interface ProcessedTurn {
939
+ /** Text output from the model */
940
+ text: string;
941
+ /** Reasoning/thinking content */
942
+ reasoning?: string;
943
+ /** Tool calls requested by the model */
944
+ toolCalls: PendingToolCall[];
945
+ /** Token usage for this turn */
946
+ usage: {
947
+ inputTokens: number;
948
+ outputTokens: number;
949
+ cacheReadTokens?: number;
950
+ cacheWriteTokens?: number;
951
+ cost?: number;
952
+ };
953
+ /** Whether the response was truncated */
954
+ truncated: boolean;
955
+ /** Response ID from the API */
956
+ responseId?: string;
957
+ }
958
+
959
+ // =============================================================================
960
+ // Re-exports from providers for convenience
961
+ // =============================================================================
962
+
963
+ export type ContentBlock = LlmsProviders.ContentBlock;
964
+ export type Message = LlmsProviders.Message;
965
+ export type ModelInfo = LlmsProviders.ModelInfo;
966
+ export type ToolDefinition = LlmsProviders.ToolDefinition;