@artinet/sdk 0.6.11 → 0.6.12

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.
@@ -0,0 +1,395 @@
1
+ /**
2
+ * Copyright 2025 The Artinet Project
3
+ * SPDX-License-Identifier: Apache-2.0
4
+ */
5
+ /**
6
+ * @fileoverview Agent Factory
7
+ *
8
+ * This module provides a fluent builder API for constructing A2A agents and
9
+ * execution engines. It enables declarative definition of multi-step agent
10
+ * workflows with type-safe step composition and automatic execution orchestration.
11
+ *
12
+ * **Key Features:**
13
+ * - Fluent API with method chaining (`.text()`, `.data()`, `.file()`, etc.)
14
+ * - Type-safe argument passing between steps via `args` carry pattern
15
+ * - Multiple output types: text, file, data, message, artifact, status, task
16
+ * - Agent-to-agent orchestration via `.sendMessage()`
17
+ * - Static value shortcuts for simple steps
18
+ * - Step skipping via `skip()` function
19
+ *
20
+ * @module AgentFactory
21
+ * @version 0.6
22
+ * @since 0.5.6
23
+ * @author The Artinet Project
24
+ */
25
+ import { A2A } from "../types/index.js";
26
+ import * as A from './agent-builder.js';
27
+ import { Service } from "../services/a2a/service.js";
28
+ import { TaskParams } from './task-builder.js';
29
+ import { ServerParams as BaseServerParams } from "../server/params.js";
30
+ import { FactoryParams, textStep, fileStep, dataStep, messageStep, artifactStep, statusStep, taskStep, MessageSender } from './create.js';
31
+ /**
32
+ * Fluent builder for constructing A2A agent execution engines.
33
+ *
34
+ * AgentFactory provides a type-safe, fluent API for composing multi-step
35
+ * agent workflows. It supports method chaining to build complex agent behaviors
36
+ * from individual processing steps, with automatic type inference for carried
37
+ * arguments between steps.
38
+ *
39
+ * @template I - The arguments type received from previous steps (inferred automatically)
40
+ *
41
+ * @example
42
+ * ```typescript
43
+ * // Basic agent with text steps
44
+ * const agent = cr8("MyAgent")
45
+ * .text(({ content }) => `You said: ${content}`)
46
+ * .agent;
47
+ *
48
+ * // Agent with carried args between steps
49
+ * const agent = cr8("AnalysisAgent")
50
+ * .text(({ content }) => ({
51
+ * reply: `Analyzing: ${content}`,
52
+ * args: { originalContent: content }
53
+ * }))
54
+ * .data(({ args }) => ({
55
+ * wordCount: args?.originalContent?.split(' ').length,
56
+ * timestamp: Date.now()
57
+ * }))
58
+ * .text(({ args }) => `Analysis complete: ${args?.wordCount} words`)
59
+ * .agent;
60
+ *
61
+ * // Agent-to-agent orchestration
62
+ * const orchestrator = cr8("Orchestrator")
63
+ * .text("Starting multi-agent workflow...")
64
+ * .sendMessage({ agent: otherAgent, message: "Process this" })
65
+ * .text(({ args }) => `Got result: ${args?.task?.status.state}`)
66
+ * .agent;
67
+ * ```
68
+ *
69
+ * @public
70
+ * @since 0.5.6
71
+ */
72
+ export declare class AgentFactory<ServerParams extends BaseServerParams, ServerType, I extends A.bargs = A.empty> implements A.AgentBuilder<I> {
73
+ private readonly _agentCard;
74
+ private readonly _params?;
75
+ private readonly _steps;
76
+ private readonly _serve;
77
+ /**
78
+ * Protected constructor to enforce factory method usage.
79
+ * @param agentCard - The agent card to use
80
+ * @param params - The parameters to use
81
+ * @param steps - Initial steps array
82
+ */
83
+ protected constructor(_agentCard: A2A.AgentCard, _params?: FactoryParams<ServerParams> | undefined, _steps?: Array<A.Resolved<any, any, any, any, any>>, _serve?: (params: {
84
+ agent: Service;
85
+ serverParams?: FactoryParams<ServerParams>;
86
+ }) => ServerType);
87
+ /**
88
+ * Builds the step list for the workflow.
89
+ *
90
+ * @returns Array of workflow steps
91
+ * @throws Error if no steps have been added
92
+ *
93
+ * @example
94
+ * ```typescript
95
+ * const steps = cr8.steps;
96
+ * ```
97
+ */
98
+ get steps(): Array<A.Resolved<any, any, any, any, any>>;
99
+ /**
100
+ * The {@link A2A.AgentCard} to use
101
+ * @returns The {@link A2A.AgentCard}
102
+ */
103
+ get agentCard(): A2A.AgentCard;
104
+ /**
105
+ * The {@link FactoryParams} to use
106
+ * @returns The {@link FactoryParams}
107
+ */
108
+ get params(): FactoryParams<ServerParams> | undefined;
109
+ /**
110
+ * Creates an agent execution engine from the built workflow.
111
+ *
112
+ * @returns The {@link A2A.Engine}
113
+ *
114
+ * @example
115
+ * ```typescript
116
+ * const engine = builder.engine;
117
+ * // Use engine with service execution
118
+ * ```
119
+ */
120
+ get engine(): A2A.Engine;
121
+ /**
122
+ * Creates a complete A2A agent using the built workflow.
123
+ *
124
+ * @param params - The {@link ServiceParams} to use
125
+ * @returns The {@link Service}
126
+ *
127
+ * @example
128
+ * ```typescript
129
+ * const agent = cr8({
130
+ * id: 'my-agent',
131
+ * name: 'Assistant Agent',
132
+ * capabilities: ['text-processing']
133
+ * }).agent;
134
+ * ```
135
+ */
136
+ get agent(): Service;
137
+ get server(): ServerType;
138
+ from(engine?: A2A.Engine): Service;
139
+ serve(engine?: A2A.Engine): ServerType;
140
+ addStep<Ret extends A.AcceptedReturnValues = A.text, C extends A.bargs = A.empty, R extends A.rep<Ret, C> = A.rep<Ret, C>, Kind extends A.AcceptedKinds = 'text'>(step: A.Resolved<Ret, I, C, R, Kind>): AgentFactory<ServerParams, ServerType, A.inferCarry<R>>;
141
+ /**
142
+ * Adds a text processing step to the workflow.
143
+ *
144
+ * Text steps are the most common step type, producing text content that
145
+ * becomes a TextPart in the agent's response message.
146
+ *
147
+ * @param step - A text step function or static string value
148
+ * @returns New builder instance with updated type parameters
149
+ *
150
+ * @example
151
+ * ```typescript
152
+ * // Static text
153
+ * builder.text("Hello, world!")
154
+ *
155
+ * // Dynamic text from content
156
+ * builder.text(({ content }) => `You said: ${content}`)
157
+ *
158
+ * // With carried args
159
+ * builder.text(({ args }) => ({
160
+ * reply: `Processing ${args?.itemCount} items`,
161
+ * args: { processedAt: Date.now() }
162
+ * }))
163
+ * ```
164
+ */
165
+ text<C extends A.bargs = A.empty>(text: A.text): AgentFactory<ServerParams, ServerType, A.inC<A.rep<A.text, C>>>;
166
+ text<C extends A.bargs = A.empty>(step: textStep<I, C>): AgentFactory<ServerParams, ServerType, A.inC<A.rep<A.text, C>>>;
167
+ /**
168
+ * Adds a file processing step to the workflow.
169
+ *
170
+ * File steps produce file content that becomes a FilePart in the agent's
171
+ * response. Files can be specified by URI or inline bytes/base64 content.
172
+ *
173
+ * @param step - A file step function or static file object
174
+ * @returns New builder instance with updated type parameters
175
+ *
176
+ * @example
177
+ * ```typescript
178
+ * // Static file by URI
179
+ * builder.file({ uri: "https://example.com/doc.pdf" })
180
+ *
181
+ * // Dynamic file generation
182
+ * builder.file(async ({ args }) => ({
183
+ * name: 'report.pdf',
184
+ * mimeType: 'application/pdf',
185
+ * bytes: await generatePDF(args?.data)
186
+ * }))
187
+ *
188
+ * // Multiple files
189
+ * builder.file(() => [
190
+ * { uri: "https://example.com/file1.pdf" },
191
+ * { uri: "https://example.com/file2.pdf" }
192
+ * ])
193
+ * ```
194
+ */
195
+ file<C extends A.bargs = A.empty, R extends A.rep<A.file, C> = A.rep<A.file, C>>(file: A.file): AgentFactory<ServerParams, ServerType, A.inC<A.rep<A.file, C>>>;
196
+ file<C extends A.bargs = A.empty, R extends A.rep<A.file, C> = A.rep<A.file, C>>(step: fileStep<I, C>): AgentFactory<ServerParams, ServerType, A.inC<A.rep<A.file, C>>>;
197
+ /**
198
+ * Adds a data processing step to the workflow.
199
+ *
200
+ * Data steps produce structured JSON data that becomes a DataPart in the
201
+ * agent's response. Useful for returning complex objects, API responses,
202
+ * or any structured data.
203
+ *
204
+ * @param step - A data step function or static data object
205
+ * @returns New builder instance with updated type parameters
206
+ *
207
+ * @example
208
+ * ```typescript
209
+ * // Static data
210
+ * builder.data({ status: "ok", version: "1.0.0" })
211
+ *
212
+ * // Dynamic data
213
+ * builder.data(async ({ content }) => ({
214
+ * analysis: await analyzeText(content),
215
+ * timestamp: Date.now()
216
+ * }))
217
+ *
218
+ * // With carried args
219
+ * builder.data(({ args }) => ({
220
+ * reply: { result: args?.computedValue * 2 },
221
+ * args: { doubled: true }
222
+ * }))
223
+ * ```
224
+ */
225
+ data<C extends A.bargs = A.empty>(data: A.data): AgentFactory<ServerParams, ServerType, A.inC<A.rep<A.data, C>>>;
226
+ data<C extends A.bargs = A.empty>(step: dataStep<I, C>): AgentFactory<ServerParams, ServerType, A.inC<A.rep<A.data, C>>>;
227
+ /**
228
+ * Adds a message step to the workflow.
229
+ *
230
+ * Message steps yield complete A2A messages with full control over role,
231
+ * parts, and metadata. Use when you need to construct complex multi-part
232
+ * messages or control the message structure directly.
233
+ *
234
+ * @param step - A message step function or static message/string
235
+ * @returns New builder instance with updated type parameters
236
+ *
237
+ * @example
238
+ * ```typescript
239
+ * // Simple string message
240
+ * builder.message("Hello from the agent!")
241
+ *
242
+ * // Full message with parts
243
+ * builder.message(({ context }) => ({
244
+ * role: "agent",
245
+ * parts: [
246
+ * { kind: "text", text: "Here are your files:" },
247
+ * { kind: "file", file: { uri: "https://example.com/doc.pdf" } }
248
+ * ]
249
+ * }))
250
+ *
251
+ * // Using describe helper
252
+ * builder.message(({ args }) => describe.message({
253
+ * role: "agent",
254
+ * parts: [{ kind: "text", text: args?.greeting }]
255
+ * }))
256
+ * ```
257
+ */
258
+ message<C extends A.bargs = A.empty>(message: A.sMessage): AgentFactory<ServerParams, ServerType, A.inC<A.rep<A.sMessage, C>>>;
259
+ message<C extends A.bargs = A.empty>(step: messageStep<I, C>): AgentFactory<ServerParams, ServerType, A.inC<A.rep<A.sMessage, C>>>;
260
+ /**
261
+ * Adds an artifact step to the workflow.
262
+ *
263
+ * Artifact steps create persistent, versioned outputs that can be referenced
264
+ * across task sessions. Use for documents, generated files, or content that
265
+ * clients may need to retrieve later.
266
+ *
267
+ * @param step - An artifact step function or static artifact object
268
+ * @returns New builder instance with updated type parameters
269
+ *
270
+ * @example
271
+ * ```typescript
272
+ * // Static artifact
273
+ * builder.artifact(describe.artifact({
274
+ * artifactId: "report-001",
275
+ * parts: [{ kind: "text", text: "Report content" }]
276
+ * }))
277
+ *
278
+ * // Dynamic artifact
279
+ * builder.artifact(async ({ context, args }) => ({
280
+ * artifactId: `analysis-${context.taskId}`,
281
+ * name: "Analysis Results",
282
+ * parts: [{ kind: "data", data: args?.analysisData }]
283
+ * }))
284
+ * ```
285
+ */
286
+ artifact<C extends A.bargs = A.empty>(step: artifactStep<I, C>): AgentFactory<ServerParams, ServerType, A.inC<A.rep<A.sArtifact, C>>>;
287
+ artifact<C extends A.bargs = A.empty>(artifact: A.sArtifact): AgentFactory<ServerParams, ServerType, A.inC<A.rep<A.sArtifact, C>>>;
288
+ /**
289
+ * Adds a status update step to the workflow.
290
+ *
291
+ * Status steps emit task state updates during execution. Use to communicate
292
+ * progress, intermediate states, or completion to clients. Supports simple
293
+ * state strings or full status objects with messages.
294
+ *
295
+ * @param step - A status step function, status object, or state string
296
+ * @returns New builder instance with updated type parameters
297
+ *
298
+ * @example
299
+ * ```typescript
300
+ * // Simple state string
301
+ * builder.status("working")
302
+ *
303
+ * // Status with message
304
+ * builder.status(({ args }) => ({
305
+ * status: {
306
+ * state: A2A.TaskState.working,
307
+ * message: describe.message(`Step ${args?.step} of 5 complete`)
308
+ * }
309
+ * }))
310
+ *
311
+ * // Mark completion
312
+ * builder.status(() => ({
313
+ * status: { state: A2A.TaskState.completed }
314
+ * }))
315
+ * ```
316
+ */
317
+ status<C extends A.bargs = A.empty>(status: A.sUpdate): AgentFactory<ServerParams, ServerType, A.inC<A.rep<A.sUpdate, C>>>;
318
+ status<C extends A.bargs = A.empty>(step: statusStep<I, C>): AgentFactory<ServerParams, ServerType, A.inC<A.rep<A.sUpdate, C>>>;
319
+ /**
320
+ * Adds a task step to the workflow.
321
+ *
322
+ * Task steps yield complete A2A task objects. Use when you need full control
323
+ * over the task representation, including status, artifacts, and history.
324
+ * Particularly useful for orchestration scenarios or final task construction.
325
+ *
326
+ * @param step - A task step function, task object, or string
327
+ * @returns New builder instance with updated type parameters
328
+ *
329
+ * @example
330
+ * ```typescript
331
+ * // Simple string (auto-converted to task)
332
+ * builder.task("Operation completed")
333
+ *
334
+ * // Full task object
335
+ * builder.task(({ context }) => describe.task({
336
+ * id: context.taskId,
337
+ * contextId: context.contextId,
338
+ * status: { state: A2A.TaskState.completed }
339
+ * }))
340
+ *
341
+ * // With carried args
342
+ * builder.task(({ context }) => ({
343
+ * reply: describe.task({ id: context.taskId }),
344
+ * args: { completedAt: Date.now() }
345
+ * }))
346
+ * ```
347
+ */
348
+ task<C extends A.bargs = A.empty>(task: A.sTask): AgentFactory<ServerParams, ServerType, A.inC<A.rep<A.sTask, C>>>;
349
+ task<C extends A.bargs = A.empty>(step: taskStep<I, C>): AgentFactory<ServerParams, ServerType, A.inC<A.rep<A.sTask, C>>>;
350
+ /**
351
+ * Adds an agent-to-agent orchestration step to the workflow.
352
+ *
353
+ * This step sends a message to another agent (local Service or remote A2A Server)
354
+ * and yields the response as a task. Enables multi-agent workflows where one
355
+ * agent delegates work to others.
356
+ *
357
+ * **Note:** This is currently a blocking call. Streaming responses are not
358
+ * yet supported in orchestration steps.
359
+ * @note Args passed from the previous step are inserted, by default,
360
+ * (`unshift`) as `DataPart`s onto the forwarded `Message`.`Parts`.
361
+ *
362
+ * @param agent - The target agent (Agent or AgentMessenger)
363
+ * @param message - Message to send (defaults to context.userMessage)
364
+ * @returns New builder instance with task carry args (args.task)
365
+ *
366
+ * @example
367
+ * ```typescript
368
+ * // Delegate to another agent
369
+ * const orchestrator = cr8("Orchestrator")
370
+ * .text("Starting workflow...")
371
+ * .sendMessage({ agent: analysisAgent, message: "Analyze this data" })
372
+ * .text(({ args }) => `Analysis result: ${args?.task?.status.state}`)
373
+ * .agent;
374
+ *
375
+ * // Chain multiple agents
376
+ * const pipeline = cr8("Pipeline")
377
+ * .sendMessage({ agent: preprocessor })
378
+ * .sendMessage({ agent: analyzer })
379
+ * .sendMessage({ agent: postprocessor })
380
+ * .text(({ args }) => `Final result: ${args?.task?.status.message}`)
381
+ * .agent;
382
+ *
383
+ * // Forward user's message to another agent
384
+ * const proxy = cr8("Proxy")
385
+ * .sendMessage({ agent: targetAgent }) // uses context.userMessage
386
+ * .agent;
387
+ * ```
388
+ */
389
+ sendMessage<Carry extends A.BaseArgs = {
390
+ task?: A2A.Task;
391
+ }>(agent_and_message: {
392
+ agent: MessageSender;
393
+ message?: A.sMessage | string;
394
+ }): AgentFactory<ServerParams, ServerType, A.inferCarry<A.Reply<A.Stateless<TaskParams>, Carry>>>;
395
+ }