@artinet/sdk 0.6.10 → 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.
@@ -28,405 +28,17 @@
28
28
  * ```
29
29
  *
30
30
  * @module A2ABuilder
31
- * @version 0.6.0-preview
31
+ * @version 0.6
32
32
  * @since 0.5.6
33
33
  * @author The Artinet Project
34
34
  */
35
35
  import { A2A } from "../types/index.js";
36
- import * as transform from "./transform.js";
37
- import { createAgent as createAgentImpl, } from "../services/a2a/factory/service.js";
38
- import { describe } from "./index.js";
39
- import { extractTextContent } from "../services/a2a/helpers/content.js";
36
+ import * as transform from './transform.js';
37
+ import { describe } from './index.js';
38
+ import { extractTextContent } from '../services/a2a/helpers/content.js';
40
39
  import { logger } from "../config/index.js";
41
- import { v4 as uuidv4 } from "uuid";
42
40
  import { formatJson } from "../utils/utils.js";
43
- import { serve } from "../server/express/server.js";
44
41
  import { isProcessing } from "../utils/constants.js";
45
- const toFunction = (function_or_ret) => {
46
- return typeof function_or_ret === "function"
47
- ? function_or_ret
48
- : () => function_or_ret;
49
- };
50
- /**
51
- * Fluent builder for constructing A2A agent execution engines.
52
- *
53
- * AgentFactory provides a type-safe, fluent API for composing multi-step
54
- * agent workflows. It supports method chaining to build complex agent behaviors
55
- * from individual processing steps, with automatic type inference for carried
56
- * arguments between steps.
57
- *
58
- * @template I - The arguments type received from previous steps (inferred automatically)
59
- *
60
- * @example
61
- * ```typescript
62
- * // Basic agent with text steps
63
- * const agent = cr8("MyAgent")
64
- * .text(({ content }) => `You said: ${content}`)
65
- * .agent;
66
- *
67
- * // Agent with carried args between steps
68
- * const agent = cr8("AnalysisAgent")
69
- * .text(({ content }) => ({
70
- * reply: `Analyzing: ${content}`,
71
- * args: { originalContent: content }
72
- * }))
73
- * .data(({ args }) => ({
74
- * wordCount: args?.originalContent?.split(' ').length,
75
- * timestamp: Date.now()
76
- * }))
77
- * .text(({ args }) => `Analysis complete: ${args?.wordCount} words`)
78
- * .agent;
79
- *
80
- * // Agent-to-agent orchestration
81
- * const orchestrator = cr8("Orchestrator")
82
- * .text("Starting multi-agent workflow...")
83
- * .sendMessage({ agent: otherAgent, message: "Process this" })
84
- * .text(({ args }) => `Got result: ${args?.task?.status.state}`)
85
- * .agent;
86
- * ```
87
- *
88
- * @public
89
- * @since 0.5.6
90
- */
91
- export class AgentFactory {
92
- _agentCard;
93
- _params;
94
- _steps;
95
- /**
96
- * Protected constructor to enforce factory method usage.
97
- * @param agentCard - The agent card to use
98
- * @param params - The parameters to use
99
- * @param steps - Initial steps array
100
- */
101
- constructor(_agentCard, _params,
102
- //@typescript-eslint/no-explicit-any
103
- _steps = []) {
104
- this._agentCard = _agentCard;
105
- this._params = _params;
106
- this._steps = _steps;
107
- }
108
- /**
109
- * Builds the step list for the workflow.
110
- *
111
- * @returns Array of workflow steps
112
- * @throws Error if no steps have been added
113
- *
114
- * @example
115
- * ```typescript
116
- * const steps = cr8.steps;
117
- * ```
118
- */
119
- //@typescript-eslint/no-explicit-any
120
- get steps() {
121
- return this._steps;
122
- }
123
- /**
124
- * The {@link A2A.AgentCard} to use
125
- * @returns The {@link A2A.AgentCard}
126
- */
127
- get agentCard() {
128
- return this._agentCard;
129
- }
130
- /**
131
- * The {@link FactoryParams} to use
132
- * @returns The {@link FactoryParams}
133
- */
134
- get params() {
135
- return this._params;
136
- }
137
- /**
138
- * Creates an agent execution engine from the built workflow.
139
- *
140
- * @returns The {@link A2A.Engine}
141
- *
142
- * @example
143
- * ```typescript
144
- * const engine = builder.engine;
145
- * // Use engine with service execution
146
- * ```
147
- */
148
- get engine() {
149
- return createStepEngine(this.steps);
150
- }
151
- /**
152
- * Creates a complete A2A agent using the built workflow.
153
- *
154
- * @param params - The {@link ServiceParams} to use
155
- * @returns The {@link Service}
156
- *
157
- * @example
158
- * ```typescript
159
- * const agent = cr8({
160
- * id: 'my-agent',
161
- * name: 'Assistant Agent',
162
- * capabilities: ['text-processing']
163
- * }).agent;
164
- * ```
165
- */
166
- get agent() {
167
- return createAgentImpl({
168
- ...this._params,
169
- agentCard: this._agentCard,
170
- engine: this.engine,
171
- });
172
- }
173
- get server() {
174
- return serve({
175
- agent: this.agent,
176
- ...this._params,
177
- });
178
- }
179
- from(engine = this.engine) {
180
- return createAgentImpl({
181
- ...this._params,
182
- agentCard: this._agentCard,
183
- engine: engine,
184
- });
185
- }
186
- serve(engine = this.engine) {
187
- return serve({
188
- agent: this.from(engine),
189
- ...this._params,
190
- });
191
- }
192
- addStep(step) {
193
- return new AgentFactory(this._agentCard, this._params, [
194
- ...this.steps,
195
- step,
196
- ]);
197
- }
198
- text(step_or_text) {
199
- const stepFn = toFunction(step_or_text);
200
- return this.addStep({
201
- id: uuidv4(),
202
- step: stepFn,
203
- kind: A2A.Kind["text"],
204
- handler: transform.Parts("text"),
205
- });
206
- }
207
- file(step_or_file) {
208
- const stepFn = toFunction(step_or_file);
209
- return this.addStep({
210
- id: uuidv4(),
211
- step: stepFn,
212
- kind: A2A.Kind["file"],
213
- handler: transform.Parts("file"),
214
- });
215
- }
216
- data(step_or_data) {
217
- const stepFn = toFunction(step_or_data);
218
- return this.addStep({
219
- id: uuidv4(),
220
- step: stepFn,
221
- kind: A2A.Kind["data"],
222
- handler: transform.Parts("data"),
223
- });
224
- }
225
- message(step_or_message) {
226
- const stepFn = toFunction(step_or_message);
227
- return this.addStep({
228
- id: uuidv4(),
229
- step: stepFn,
230
- kind: A2A.Kind["message"],
231
- handler: transform.Message(),
232
- });
233
- }
234
- artifact(step_or_artifact) {
235
- const stepFn = toFunction(step_or_artifact);
236
- return this.addStep({
237
- id: uuidv4(),
238
- step: stepFn,
239
- kind: A2A.Kind["artifact-update"],
240
- handler: transform.Artifact(),
241
- });
242
- }
243
- status(step_or_status) {
244
- const stepFn = toFunction(step_or_status);
245
- return this.addStep({
246
- id: uuidv4(),
247
- step: stepFn,
248
- kind: A2A.Kind["status-update"],
249
- handler: transform.Status(),
250
- });
251
- }
252
- task(step_or_task_or_string) {
253
- const stepFn = toFunction(step_or_task_or_string);
254
- return this.addStep({
255
- id: uuidv4(),
256
- step: stepFn,
257
- kind: "task",
258
- handler: transform.Task(),
259
- });
260
- }
261
- /**
262
- * Adds an agent-to-agent orchestration step to the workflow.
263
- *
264
- * This step sends a message to another agent (local Service or remote A2A Server)
265
- * and yields the response as a task. Enables multi-agent workflows where one
266
- * agent delegates work to others.
267
- *
268
- * **Note:** This is currently a blocking call. Streaming responses are not
269
- * yet supported in orchestration steps.
270
- * @note Args passed from the previous step are inserted, by default,
271
- * (`unshift`) as `DataPart`s onto the forwarded `Message`.`Parts`.
272
- *
273
- * @param agent - The target agent (Agent or AgentMessenger)
274
- * @param message - Message to send (defaults to context.userMessage)
275
- * @returns New builder instance with task carry args (args.task)
276
- *
277
- * @example
278
- * ```typescript
279
- * // Delegate to another agent
280
- * const orchestrator = cr8("Orchestrator")
281
- * .text("Starting workflow...")
282
- * .sendMessage({ agent: analysisAgent, message: "Analyze this data" })
283
- * .text(({ args }) => `Analysis result: ${args?.task?.status.state}`)
284
- * .agent;
285
- *
286
- * // Chain multiple agents
287
- * const pipeline = cr8("Pipeline")
288
- * .sendMessage({ agent: preprocessor })
289
- * .sendMessage({ agent: analyzer })
290
- * .sendMessage({ agent: postprocessor })
291
- * .text(({ args }) => `Final result: ${args?.task?.status.message}`)
292
- * .agent;
293
- *
294
- * // Forward user's message to another agent
295
- * const proxy = cr8("Proxy")
296
- * .sendMessage({ agent: targetAgent }) // uses context.userMessage
297
- * .agent;
298
- * ```
299
- */
300
- sendMessage(agent_and_message) {
301
- const stepFn = async ({ context, args }) => {
302
- logger.info("sendMessage: Sending message: ", {
303
- agent: agent_and_message.agent.constructor.name,
304
- });
305
- const messageSendParams = describe.messageSendParams(agent_and_message.message ?? structuredClone(context.userMessage));
306
- if (args) {
307
- /**We extract the parts of the first A2A protocol object we encounter in the args */
308
- if (args.task || args.message || args.update) {
309
- const parts = [];
310
- if (args.message) {
311
- parts.push(...(A2A.MessageSchema.safeParse(args.message).data?.parts ?? []));
312
- }
313
- if (args.task) {
314
- parts.push(...(A2A.TaskSchema.safeParse(args.task).data?.status?.message
315
- ?.parts ?? []));
316
- }
317
- if (args.update) {
318
- parts.push(...(A2A.TaskStatusUpdateEventSchema.safeParse(args.update).data
319
- ?.status?.message?.parts ?? []));
320
- parts.push(...(A2A.TaskArtifactUpdateEventSchema.safeParse(args.update).data
321
- ?.artifact?.parts ?? []));
322
- }
323
- parts.forEach((part) => {
324
- messageSendParams.message.parts.unshift(part);
325
- });
326
- }
327
- else {
328
- messageSendParams.message.parts.unshift(describe.part.data({ ...args }));
329
- }
330
- }
331
- const response = await agent_and_message.agent
332
- .sendMessage(messageSendParams)
333
- .catch((error) => {
334
- logger.error("sendMessage: Error sending message: ", error);
335
- return null;
336
- });
337
- if (!response) {
338
- logger.warn("sendMessage: No response from agent");
339
- }
340
- const task = response
341
- ? describe.task({
342
- ...response,
343
- taskId: context.taskId,
344
- contextId: context.contextId,
345
- })
346
- : describe.task({
347
- taskId: context.taskId,
348
- contextId: context.contextId,
349
- state: A2A.TaskState.working,
350
- message: describe.message("No response from agent"),
351
- });
352
- return {
353
- reply: task,
354
- args: {
355
- task,
356
- },
357
- };
358
- };
359
- return this.addStep({
360
- id: uuidv4(),
361
- step: stepFn,
362
- kind: "task",
363
- handler: transform.Task(),
364
- });
365
- }
366
- /**
367
- * Creates a new AgentFactory instance.
368
- *
369
- * @template Input - The initial arguments type
370
- * @returns A new AgentFactory instance
371
- *
372
- * @example
373
- * ```typescript
374
- * const factory = AgentFactory.create(myCard, { params });
375
- * ```
376
- */
377
- static create(agentCard, params) {
378
- return new AgentFactory(describe.card(agentCard), params);
379
- }
380
- }
381
- /**
382
- * Creates a new AgentFactory instance for building agent workflows.
383
- *
384
- * This is the primary entry point for the fluent builder API. Accepts an
385
- * agent card (or name string) and optional factory parameters.
386
- *
387
- * @param agentCard - Agent card object or name string
388
- * @param params - Optional factory parameters (basePath, port, etc.)
389
- * @returns New AgentFactory instance
390
- *
391
- * @example
392
- * ```typescript
393
- * // Simple agent with name string
394
- * const agent = cr8("MyAgent")
395
- * .text(({ content }) => `Echo: ${content}`)
396
- * .agent;
397
- *
398
- * // Agent with full card and params
399
- * const agent = cr8(myAgentCard, { basePath: "/api" })
400
- * .text("Hello!")
401
- * .data(({ content }) => analyzeContent(content))
402
- * .agent;
403
- *
404
- * // Get the engine directly
405
- * const engine = cr8("Processor")
406
- * .text("Processing...")
407
- * .engine;
408
- *
409
- * // Create and start server
410
- * const server = cr8("ServerAgent", { port: 3000 })
411
- * .text("Ready to serve!")
412
- * .server.start();
413
- * ```
414
- *
415
- * @public
416
- * @since 0.6.0
417
- */
418
- export const cr8 = AgentFactory.create;
419
- /**
420
- * @deprecated Use {@link cr8} instead
421
- * @note This export exists only to alert users that `AgentBuilder` is deprecated.
422
- * `AgentBuilder` no longer comes with the `createAgent` method.
423
- * @since 0.6.0
424
- */
425
- export class AgentBuilder extends AgentFactory {
426
- constructor(agentCard = "default", params) {
427
- super(describe.card(typeof agentCard === "string" ? { name: agentCard } : agentCard), params);
428
- }
429
- }
430
42
  /**
431
43
  * Creates an agent execution engine from a list of workflow steps.
432
44
  *
@@ -466,7 +78,7 @@ export class AgentBuilder extends AgentFactory {
466
78
  */
467
79
  export function createStepEngine(stepsList) {
468
80
  if (stepsList.length === 0) {
469
- throw new Error("No steps provided");
81
+ throw new Error('No steps provided');
470
82
  }
471
83
  return async function* (context) {
472
84
  logger.info(`engine[context:${context.contextId}]: starting`);