psadk 1.1.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 (48) hide show
  1. package/CHANGELOG.md +11 -0
  2. package/LICENSE +21 -0
  3. package/README.md +205 -0
  4. package/build/main/index.d.ts +6 -0
  5. package/build/main/index.js +23 -0
  6. package/build/main/lib/ILogger.d.ts +9 -0
  7. package/build/main/lib/ILogger.js +25 -0
  8. package/build/main/lib/PSAI.d.ts +29 -0
  9. package/build/main/lib/PSAI.js +383 -0
  10. package/build/main/lib/PSAgent.d.ts +215 -0
  11. package/build/main/lib/PSAgent.js +990 -0
  12. package/build/main/lib/PSAgentConfig.d.ts +23 -0
  13. package/build/main/lib/PSAgentConfig.js +3 -0
  14. package/build/main/lib/PSAgentLogger.d.ts +13 -0
  15. package/build/main/lib/PSAgentLogger.js +33 -0
  16. package/build/main/lib/PSAgentTask.d.ts +12 -0
  17. package/build/main/lib/PSAgentTask.js +30 -0
  18. package/build/main/lib/PSAgentTool.d.ts +56 -0
  19. package/build/main/lib/PSAgentTool.js +84 -0
  20. package/build/main/lib/ai.d.ts +11 -0
  21. package/build/main/lib/ai.js +127 -0
  22. package/build/main/lib/async.d.ts +20 -0
  23. package/build/main/lib/async.js +36 -0
  24. package/build/main/lib/getServiceToken.d.ts +1 -0
  25. package/build/main/lib/getServiceToken.js +3 -0
  26. package/build/main/lib/jwt.d.ts +41 -0
  27. package/build/main/lib/jwt.js +73 -0
  28. package/build/main/lib/number.d.ts +43 -0
  29. package/build/main/lib/number.js +56 -0
  30. package/build/main/lib/tools/PSAentTool.d.ts +7 -0
  31. package/build/main/lib/tools/PSAentTool.js +78 -0
  32. package/build/main/lib/tools/PSArtifactTool copy.d.ts +7 -0
  33. package/build/main/lib/tools/PSArtifactTool copy.js +78 -0
  34. package/build/main/lib/tools/PSArtifactTool.d.ts +7 -0
  35. package/build/main/lib/tools/PSArtifactTool.js +79 -0
  36. package/build/main/lib/tools/PSSubAgentTool.d.ts +20 -0
  37. package/build/main/lib/tools/PSSubAgentTool.js +163 -0
  38. package/build/module/index.d.ts +6 -0
  39. package/build/module/index.js +7 -0
  40. package/build/module/lib/PSAI.d.ts +25 -0
  41. package/build/module/lib/PSAI.js +314 -0
  42. package/build/module/lib/PSAgent.d.ts +215 -0
  43. package/build/module/lib/PSAgent.js +992 -0
  44. package/build/module/lib/async.d.ts +20 -0
  45. package/build/module/lib/async.js +32 -0
  46. package/build/module/lib/number.d.ts +43 -0
  47. package/build/module/lib/number.js +51 -0
  48. package/package.json +122 -0
@@ -0,0 +1,992 @@
1
+ import { PSAgentTool } from "./PSAgentTool";
2
+ import { z } from "zod/v4";
3
+ import { v4 as uuidv4 } from 'uuid'; // For generating unique IDs
4
+ import os from "os";
5
+ import { PSAgentTask } from "./PSAgentTask";
6
+ import { DefaultRequestHandler, InMemoryTaskStore, } from "@a2a-js/sdk/server";
7
+ import { A2AExpressApp } from "@a2a-js/sdk/server/express";
8
+ import express from "express";
9
+ import fs from "node:fs";
10
+ import path from "node:path";
11
+ import yaml from "yaml";
12
+ import { PSAI } from "./PSAI";
13
+ // fetch-retry can also wrap Node.js's native fetch API implementation:
14
+ const fetch = require('fetch-retry')(global.fetch);
15
+ export async function sleep(ms) {
16
+ return new Promise((resolve) => setTimeout(resolve, ms));
17
+ }
18
+ /**
19
+ * PSAgent class to manage AI agents with tools and tasks
20
+ * Implements AgentExecutor interface from A2A SDK
21
+ * Supports starting, resuming, cancelling agents and executing tools
22
+ * Manages agent state, tools, tasks and interactions with A2A platform
23
+ * Includes methods for A2A server setup and event fetching
24
+ *
25
+ * uses the token from config if not PS_API_TOKEN env variable
26
+ * adds x-client-id, x-project-id, x-workspace-id from env variables
27
+ * PS_CLIENT_ID, PS_PROJECT_ID, PS_WORKSPACE_ID respectively for authentication headers
28
+ *
29
+ * @example
30
+ * ```typescript
31
+ * import { PSAI, PSAgent, PSAgentLogger } from 'psadk';
32
+ * import dotenv from 'dotenv';
33
+ * dotenv.config();
34
+ * async function main() {
35
+ * const token = await PSAI.getServiceToken({});
36
+ * const HelloAgent = new PSAgent({
37
+ * name: 'HelloAgent',
38
+ * description: 'A simple hello world agent',
39
+ * system_prompt: 'You are a helpful assistant that greets users.',
40
+ * model: 'gpt-5',
41
+ * tools: [],
42
+ * log: new PSAgentLogger({ level: 'info' }),
43
+ * token: token,
44
+ * port: 41241,
45
+ * });
46
+ * const { app, port } = HelloAgent.getServer();
47
+ * app.listen(port, () => {
48
+ * console.log('HelloAgent is running on http://localhost:${port}');
49
+ * });
50
+ * }
51
+ * main();
52
+ * ```
53
+ * @see PSAgentConfig, PSAgentTool, PSAgentTask
54
+ *
55
+ * @see
56
+ * https://dev.lionis.ai/docs/api/v1/agents/create-agent
57
+ * https://pscode.lioncloud.net/ai-tso/psadk_samples
58
+ * https://a2aproject.com/docs/getting-started/quickstart
59
+ *
60
+ */
61
+ export class PSAgent {
62
+ config;
63
+ tools = [];
64
+ tasks = [];
65
+ agentId;
66
+ correlationId;
67
+ log;
68
+ cancelledTasks = new Set();
69
+ cancelTask = async (taskId, _eventBus) => {
70
+ this.cancelledTasks.add(taskId);
71
+ // The execute loop is responsible for publishing the final state
72
+ };
73
+ /**
74
+ * create a new PSAgent with the given config
75
+ * @param config PSAgentConfig with optional logger
76
+ */
77
+ constructor(config) {
78
+ this.config = config;
79
+ this.log = config.log;
80
+ }
81
+ /**
82
+ * Get the Agent Class
83
+ * @returns Agent class from config or default "LlmAgent"
84
+ */
85
+ get AgentClass() {
86
+ return this.config.agent_class || "LlmAgent";
87
+ }
88
+ /**
89
+ * Get the Name of the Agent
90
+ *
91
+ * @returns Name of the agent from config
92
+ */
93
+ get Name() {
94
+ return this.config.name;
95
+ }
96
+ /**
97
+ * Get the Description of the Agent
98
+ * @returns Description of the agent from config
99
+ */
100
+ get Description() {
101
+ return this.config.description;
102
+ }
103
+ /**
104
+ * Get the Instruction(System Prompt) of the Agent
105
+ * @returns Instruction(System prompt) of the agent from config
106
+ */
107
+ get Instruction() {
108
+ return this.config.instruction;
109
+ }
110
+ /**
111
+ * Get the Model of the Agent
112
+ * @returns Model of the agent from config
113
+ */
114
+ get Model() {
115
+ return this.config.model;
116
+ }
117
+ /**
118
+ * Get the Input Schema of the Agent
119
+ * @returns Input schema of the agent from config
120
+ */
121
+ get InputSchema() {
122
+ return this.config.input_schema;
123
+ }
124
+ /**
125
+ * Get the Output Schema of the Agent
126
+ * @returns Output schema of the agent from config
127
+ */
128
+ get OutputSchema() {
129
+ return this.config.output_schema;
130
+ }
131
+ /**
132
+ * Get the Token for the Agent
133
+ * @returns Token of the agent from config
134
+ */
135
+ get Token() {
136
+ return this.config.token;
137
+ }
138
+ /**
139
+ * Set the Token for the Agent
140
+ * @param value Token string to set in config
141
+ */
142
+ set Token(value) {
143
+ this.config.token = value;
144
+ }
145
+ /**
146
+ * Get the Tools for the Agent
147
+ * Includes both config tools and dynamically added tools
148
+ * @returns Array of PSAgentTool instances
149
+ */
150
+ get Tools() {
151
+ return [...this.config.tools || [], ...this.tools];
152
+ }
153
+ /**
154
+ * Get the Tasks for the Agent
155
+ * Includes both config tasks and dynamically added tasks
156
+ * @returns Array of PSAgentTask instances
157
+ */
158
+ get Tasks() {
159
+ return [...this.config.tasks || [], ...this.tasks];
160
+ }
161
+ /**
162
+ * Get the Agent ID after starting the agent
163
+ * @returns Agent ID string or undefined if not started
164
+ */
165
+ get AgentId() {
166
+ return this.agentId;
167
+ }
168
+ /**
169
+ * Get the Correlation ID after starting the agent
170
+ * @returns Correlation ID string or undefined if not started
171
+ */
172
+ get CorrelationId() {
173
+ return this.correlationId;
174
+ }
175
+ /**
176
+ * Add tools to the agent dynamically
177
+ * @param tool PSAgentTool to add to the agent
178
+ */
179
+ addTool(tool) {
180
+ if (!this.tools) {
181
+ this.tools = [];
182
+ }
183
+ let toolIndex = this.config.tools?.findIndex(t => t.Name === tool.Name) || -1;
184
+ if (toolIndex !== -1) {
185
+ throw new Error(`Tool with name ${tool.Name} already exists in config`);
186
+ }
187
+ toolIndex = this.tools.findIndex(t => t.Name === tool.Name);
188
+ if (toolIndex !== -1) {
189
+ throw new Error(`Tool with name ${tool.Name} already exists in agent`);
190
+ }
191
+ else {
192
+ this.tools.push(tool);
193
+ }
194
+ }
195
+ // get token from config or environment variable
196
+ async getToken() {
197
+ if (this.config.token)
198
+ return this.config.token;
199
+ if (this.config.getToken)
200
+ return await this.config.getToken();
201
+ return process.env.PS_API_TOKEN || '';
202
+ }
203
+ // Private method to get auth headers
204
+ // uses the token from config if not PS_API_TOKEN env variable
205
+ // adds x-client-id, x-project-id, x-workspace-id from env variables
206
+ // PS_CLIENT_ID, PS_PROJECT_ID, PS_WORKSPACE_ID respectively
207
+ async getAuthHeaders() {
208
+ const headers = {};
209
+ headers['Authorization'] = `Bearer ${await this.getToken()}`;
210
+ headers["x-client-id"] = process.env.PS_CLIENT_ID || "";
211
+ headers["x-project-id"] = process.env.PS_PROJECT_ID || "";
212
+ headers["x-workspace-id"] = process.env.PS_WORKSPACE_ID || "";
213
+ if (this.config.additional_headers) {
214
+ Object.assign(headers, this.config.additional_headers);
215
+ }
216
+ return headers;
217
+ }
218
+ // Get base URL from environment variable or use default
219
+ // uses env variable PS_API_URL if set, otherwise defaults to https://dev.lionis.ai
220
+ getBaseUrl() {
221
+ const baseUrl = process.env.PS_API_URL || 'https://dev.lionis.ai';
222
+ return baseUrl.replace(/\/+$/, ''); // Remove trailing slashes
223
+ }
224
+ /**
225
+ * start a new temp agent on the agent platform
226
+ * @param input input to the agent the schema should match InputSchema if provided
227
+ * @param history history of messages for agent context
228
+ * @param log logger to use for logging, defaults to agent's logger
229
+ * @returns Correlation ID of the started agent
230
+ */
231
+ async start(input, history, log) {
232
+ log = log || this.log;
233
+ const ischema = this.InputSchema ? this.InputSchema : z.toJSONSchema(z.object({
234
+ query: z.string().meta({
235
+ title: "query",
236
+ description: "The query by the user."
237
+ }),
238
+ // history: z.array(z.object({
239
+ // role: z.enum(["user", "model"]).meta({
240
+ // title: "role",
241
+ // description: "Role of the message sender"
242
+ // }),
243
+ // content: z.string().meta({
244
+ // title: "content",
245
+ // description: "Content of the message"
246
+ // })
247
+ // })).optional().meta({
248
+ // title: "history",
249
+ // description: "List of the User and Assistant chat history"
250
+ // })
251
+ }).meta({
252
+ title: "request_body",
253
+ description: "The request body parameters for the agent.",
254
+ }), { "io": "input" });
255
+ //check if the input confirms to the input schema
256
+ // const parseResult = z.object(ischema).safeParse(input);
257
+ // if (!parseResult.success) {
258
+ // log?.error('Input validation failed:', parseResult.error.message);
259
+ // throw new Error(`Input validation failed: ${parseResult.error.issues.map(issue=>issue.message).join(', ')}`);
260
+ // }
261
+ if (ischema.properties) {
262
+ Object.assign(ischema.properties, {
263
+ history: {
264
+ type: "array",
265
+ items: {
266
+ type: "object"
267
+ },
268
+ description: "List of the User and Assistant chat history",
269
+ title: "Chat history"
270
+ }
271
+ });
272
+ }
273
+ // console.log("input schema:", JSON.stringify(ischema, null, 2));
274
+ const output_schema = this.OutputSchema || z.toJSONSchema(z.object({
275
+ response: z.string().meta({
276
+ title: "Response",
277
+ description: "The response from the agent",
278
+ }),
279
+ }).meta({
280
+ title: "Agent_Response",
281
+ description: "The response from the agent after processing the input",
282
+ }), { io: "output" });
283
+ const body = {
284
+ agent: {
285
+ name: this.Name,
286
+ description: this.Description,
287
+ system_prompt: this.Instruction,
288
+ llm: this.Model || "gpt-5",
289
+ input_schema: ischema,
290
+ output_schema: output_schema,
291
+ },
292
+ input_params: Object.assign(input, { history: history || [] }),
293
+ tasks: this.Tasks.map(task => ({
294
+ name: task.Name,
295
+ description: task.Description
296
+ })),
297
+ tools: {
298
+ new_tools: this.Tools.map(tool => ({
299
+ name: tool.Name,
300
+ description: tool.Description,
301
+ type: tool.Type,
302
+ local_execution: tool.LocalExecution,
303
+ hitl: tool.HITL,
304
+ inputs: tool.Inputs
305
+ })),
306
+ existing_tools: []
307
+ },
308
+ planning: {
309
+ plan_required: this.config.show_plan || false,
310
+ hitl: this.config.hitl_for_plan || false
311
+ },
312
+ };
313
+ try {
314
+ const headers = await this.getAuthHeaders();
315
+ // log?.debug('Starting agent with headers:', headers);
316
+ // log?.debug('Starting agent with body:', JSON.stringify(body.input_params, null, 2));
317
+ const response = await fetch(`${this.getBaseUrl()}/api/v1/agents/temp_agent`, {
318
+ method: 'POST',
319
+ headers: {
320
+ 'Content-Type': 'application/json',
321
+ ...headers
322
+ },
323
+ body: JSON.stringify(body),
324
+ retries: 3,
325
+ retryOn: function (attempt, error, response) {
326
+ // retry on any network error, or 4xx or 5xx status codes
327
+ if (error !== null || response.status > 400 && attempt < 4) {
328
+ log?.warn(`retrying execute agent, attempt number ${attempt + 1}, status: ${response.status}`, error);
329
+ return true;
330
+ }
331
+ return false;
332
+ },
333
+ retryDelay: function (attempt, _error, _response) {
334
+ return Math.pow(2, attempt) * 1000; // 1000, 2000, 4000
335
+ }
336
+ });
337
+ if (!response.ok) {
338
+ let errorDetails;
339
+ try {
340
+ errorDetails = await response.text();
341
+ }
342
+ catch (e) {
343
+ throw new Error(`Unable to start agent. status: ${response.status}`);
344
+ }
345
+ if (errorDetails) {
346
+ throw new Error(`Unable to start agent. status: ${response.status}, details: ${JSON.stringify(errorDetails)}`);
347
+ }
348
+ }
349
+ const responseData = (await response.json());
350
+ this.agentId = responseData.data.agent_id;
351
+ this.correlationId = responseData.data.correlation_id;
352
+ log?.info(`Agent started with ID: ${this.agentId}, Correlation ID: ${this.correlationId}`);
353
+ return this.correlationId;
354
+ }
355
+ catch (error) {
356
+ log?.error('Unable to start agent:', error);
357
+ throw error;
358
+ }
359
+ }
360
+ /**
361
+ * resume the agent with tool output after a tool execution or human input
362
+ * @param tooloutput output from the tool execution to send back to the agent
363
+ * @returns
364
+ */
365
+ async resume(tooloutput) {
366
+ const log = this.log;
367
+ if (!this.agentId) {
368
+ throw new Error("Agent ID is not set");
369
+ }
370
+ try {
371
+ const response = await fetch(`${this.getBaseUrl()}/api/v1/agents/${this.agentId}/resume`, {
372
+ method: 'POST',
373
+ headers: {
374
+ 'Content-Type': 'application/json',
375
+ ...await this.getAuthHeaders()
376
+ },
377
+ body: JSON.stringify({
378
+ "correlation_id": this.CorrelationId,
379
+ "tool_output_override": tooloutput,
380
+ }),
381
+ retries: 3,
382
+ retryOn: function (attempt, error, response) {
383
+ // retry on any network error, or 4xx or 5xx status codes
384
+ if (error !== null || response.status >= 400 && attempt < 4) {
385
+ log?.warn(`retrying resume, attempt number ${attempt + 1} ${response.status}`, error);
386
+ return true;
387
+ }
388
+ return false;
389
+ },
390
+ retryDelay: function (attempt, _error, _response) {
391
+ return Math.pow(2, attempt) * 1000; // 1000, 2000, 4000
392
+ }
393
+ });
394
+ if (!response.ok) {
395
+ log?.error("Error resuming agent:", await response.json());
396
+ throw new Error(`HTTP error! status: ${response.status}`);
397
+ }
398
+ const resumeData = await response.json();
399
+ return resumeData;
400
+ }
401
+ catch (error) {
402
+ log?.error("Error resuming agent:", error);
403
+ log?.error("Correlation ID:", this.correlationId);
404
+ log?.error("Tool Output:", tooloutput);
405
+ throw new Error(`Failed to resume agent: ${error instanceof Error ? error.message : String(error)}`);
406
+ }
407
+ }
408
+ /**
409
+ * deletes the agent running on the platform
410
+ * @param log optional logger to use for logging, defaults to agent's logger
411
+ */
412
+ async cancel(log) {
413
+ if (!this.AgentId) {
414
+ throw new Error("Agent is not started");
415
+ }
416
+ try {
417
+ const response = await fetch(`${this.getBaseUrl()}/api/v1/agents/${this.agentId}`, {
418
+ method: 'DELETE',
419
+ headers: {
420
+ 'Content-Type': 'application/json',
421
+ ...await this.getAuthHeaders()
422
+ },
423
+ retries: 3,
424
+ retryOn: function (attempt, error, response) {
425
+ // retry on any network error, or 4xx or 5xx status codes
426
+ if (error !== null || response.status >= 400 && attempt < 4) {
427
+ log?.warn(`retrying cancel agent, attempt number ${attempt + 1}`);
428
+ return true;
429
+ }
430
+ return false;
431
+ },
432
+ retryDelay: function (attempt, _error, _response) {
433
+ return Math.pow(2, attempt) * 1000; // 1000, 2000, 4000
434
+ }
435
+ });
436
+ if (!response.ok) {
437
+ let errorDetails;
438
+ try {
439
+ errorDetails = await response.json();
440
+ log?.error(await response.json());
441
+ }
442
+ catch (e) {
443
+ throw new Error(`Unable to cancel agent status: ${response.status}`);
444
+ }
445
+ if (errorDetails) {
446
+ throw new Error(`Unable to cancel agent status: ${response.status}, details: ${JSON.stringify(errorDetails)}`);
447
+ }
448
+ }
449
+ log?.info(`Agent ${this.agentId} cancelled successfully`);
450
+ }
451
+ catch (error) {
452
+ log?.error('Error cancelling agent:', error);
453
+ throw error;
454
+ }
455
+ }
456
+ /**
457
+ * Gets all the events for the current agent run identified correlation ID
458
+ * @returns Array of event objects for the current agent's correlation ID
459
+ * @see https://dev.lionis.ai/api/v1/events/events?correlationId={{correlation_id}}
460
+ */
461
+ async getEvents() {
462
+ if (!this.CorrelationId) {
463
+ throw new Error("Correlation ID is not set");
464
+ }
465
+ try {
466
+ const response = await fetch(`${this.getBaseUrl()}/api/v1/events/events?correlationId=${this.correlationId}`, {
467
+ method: 'GET',
468
+ headers: {
469
+ 'Content-Type': 'application/json',
470
+ ...await this.getAuthHeaders()
471
+ },
472
+ retries: 3,
473
+ retryOn: function (attempt, error, response) {
474
+ // retry on any network error, or 4xx or 5xx status codes
475
+ if (error !== null || response.status >= 400 && attempt < 4) {
476
+ //log?.warn(`retrying getEvents, attempt number ${attempt + 1}`);
477
+ return true;
478
+ }
479
+ return false;
480
+ },
481
+ retryDelay: function (attempt, _error, _response) {
482
+ return Math.pow(2, attempt) * 1000; // 1000, 2000, 4000
483
+ }
484
+ });
485
+ if (!response.ok) {
486
+ //log.error("Error fetching agent events:", await response.json());
487
+ throw new Error(`HTTP error! status: ${response.status}`);
488
+ }
489
+ const eventsData = await response.json();
490
+ return eventsData;
491
+ }
492
+ catch (error) {
493
+ //log.error("Error fetching agent events:", error);
494
+ throw new Error(`Failed to fetch agent events: ${error instanceof Error ? error.message : String(error)}`);
495
+ }
496
+ }
497
+ /**
498
+ * Invoke the tool with the given name and input
499
+ * @remarks
500
+ * The input object should match the tool's input schema
501
+ *
502
+ * @param toolName name of the tool to execute
503
+ * @param input input object for the tool execution should match tool's input schema
504
+ * @param log logger to use for logging, defaults to agent's logger
505
+ * @returns output from the tool execution or error if any
506
+ *
507
+ * @example
508
+ * Example input for PSArtifactTool:
509
+ * ```json
510
+ * {
511
+ * "name": "example_artifact",
512
+ * "action": "write",
513
+ * "content": "This is an example artifact content."
514
+ * }
515
+ * ```
516
+ */
517
+ async executeTool(toolName, input, log) {
518
+ let results = { error: null };
519
+ const tool = this.Tools.find(t => t.Name === toolName);
520
+ if (!tool) {
521
+ results.error = new Error(`Tool with name ${toolName} not found`);
522
+ }
523
+ else {
524
+ try {
525
+ results.result = await tool.run(input, log);
526
+ }
527
+ catch (error) {
528
+ results.result = undefined;
529
+ results.error = new Error(`${error instanceof Error ? error.message : String(error)}`);
530
+ }
531
+ }
532
+ try {
533
+ if (results.error) {
534
+ await this.resume({ error: results.error.message || results.error.toString() });
535
+ }
536
+ else {
537
+ await this.resume(results.result || { output: "No result returned from tool execution" });
538
+ }
539
+ }
540
+ catch (error) {
541
+ results.error = new Error(`Error resuming agent after tool execution: ${error instanceof Error ? error.message : String(error)}`);
542
+ }
543
+ return results;
544
+ }
545
+ /**
546
+ *
547
+ * @param requestContext
548
+ * @param eventBus
549
+ * @returns
550
+ */
551
+ async execute(requestContext, eventBus) {
552
+ const log = this.log;
553
+ const userMessage = requestContext.userMessage;
554
+ const existingTask = requestContext.task;
555
+ const taskId = existingTask?.id || uuidv4();
556
+ const contextId = userMessage.contextId || existingTask?.contextId || uuidv4();
557
+ log?.info(`[${this.Name}:AgentExecutor] Processing message ${userMessage.messageId} for task ${taskId} (context: ${contextId})`);
558
+ // 1. Publish initial Task event if it's a new task
559
+ if (!existingTask) {
560
+ const initialTask = {
561
+ kind: 'task',
562
+ id: taskId,
563
+ contextId: contextId,
564
+ status: {
565
+ state: 'submitted',
566
+ timestamp: new Date().toISOString(),
567
+ },
568
+ history: [userMessage],
569
+ metadata: userMessage.metadata,
570
+ artifacts: [], // Initialize artifacts array
571
+ };
572
+ eventBus.publish(initialTask);
573
+ }
574
+ // 2. Publish "working" status update
575
+ let workingStatusUpdate = {
576
+ kind: 'status-update',
577
+ taskId: taskId,
578
+ contextId: contextId,
579
+ status: {
580
+ state: 'working',
581
+ message: {
582
+ kind: 'message',
583
+ role: 'agent',
584
+ messageId: uuidv4(),
585
+ parts: [{ kind: 'text', text: 'Initializing the agent...' }],
586
+ taskId: taskId,
587
+ contextId: contextId,
588
+ },
589
+ timestamp: new Date().toISOString(),
590
+ },
591
+ final: false,
592
+ };
593
+ eventBus.publish(workingStatusUpdate);
594
+ // 3. Prepare messages for history
595
+ const history = existingTask?.history ? [...existingTask.history] : [];
596
+ if (!history.find(m => m.messageId === userMessage.messageId)) {
597
+ history.push(userMessage);
598
+ }
599
+ log?.debug(`[${this.Name}:AgentExecutor] Total messages in history: ${history.length}`);
600
+ const messages = history
601
+ .map((m) => ({
602
+ role: (m.role === 'agent' ? 'model' : 'user'),
603
+ content: m.parts
604
+ .filter((p) => p.kind === 'text' && !!p.text)
605
+ .map((p) => p.text).join('\n'),
606
+ // .map((p) => ({
607
+ // text: (p as TextPart).text,
608
+ // })),
609
+ }))
610
+ .filter((m) => m.content.length > 0);
611
+ if (messages.length === 0) {
612
+ log?.warn(`[${this.Name}:AgentExecutor] No valid text messages found in history for task ${taskId}.`);
613
+ const failureUpdate = {
614
+ kind: 'status-update',
615
+ taskId: taskId,
616
+ contextId: contextId,
617
+ status: {
618
+ state: 'failed',
619
+ message: {
620
+ kind: 'message',
621
+ role: 'agent',
622
+ messageId: uuidv4(),
623
+ parts: [{ kind: 'text', text: 'No input message found to process.' }],
624
+ taskId: taskId,
625
+ contextId: contextId,
626
+ },
627
+ timestamp: new Date().toISOString(),
628
+ },
629
+ final: true,
630
+ };
631
+ eventBus.publish(failureUpdate);
632
+ return;
633
+ }
634
+ try {
635
+ let input = {};
636
+ if (userMessage.parts && userMessage.parts.length > 0) {
637
+ for (const part of userMessage.parts) {
638
+ if (part.kind === 'text' && part.text) {
639
+ input['query'] = part.text;
640
+ }
641
+ // TODO: handle other part kinds (e.g., images, files) here as needed
642
+ }
643
+ }
644
+ if (this.Tools.length === 0) {
645
+ const ai = new PSAI(this.Token || '', this.getBaseUrl(), log);
646
+ const llmResponse = await ai.llm(input.query, this.Model);
647
+ //console.log("llmResponse:", llmResponse);
648
+ const completedUpdate = {
649
+ kind: 'status-update',
650
+ taskId: taskId,
651
+ contextId: contextId,
652
+ status: {
653
+ state: 'completed',
654
+ message: {
655
+ kind: 'message',
656
+ role: 'agent',
657
+ messageId: uuidv4(),
658
+ parts: [{ kind: 'text', text: llmResponse.choices[0].message.content }],
659
+ taskId: taskId,
660
+ contextId: contextId,
661
+ },
662
+ timestamp: new Date().toISOString(),
663
+ },
664
+ final: true,
665
+ };
666
+ eventBus.publish(completedUpdate);
667
+ return;
668
+ }
669
+ this.log?.debug(`Agent input: ${JSON.stringify(input)}`);
670
+ await this.start(input, messages.slice(0, -1), log);
671
+ workingStatusUpdate = {
672
+ kind: 'status-update',
673
+ taskId: taskId,
674
+ contextId: contextId,
675
+ status: {
676
+ state: 'working',
677
+ message: {
678
+ kind: 'message',
679
+ role: 'agent',
680
+ messageId: uuidv4(),
681
+ parts: [{ kind: 'text', text: `started new agent ${this.AgentId}, correlationid: ${this.correlationId}` }],
682
+ taskId: taskId,
683
+ contextId: contextId,
684
+ },
685
+ timestamp: new Date().toISOString(),
686
+ },
687
+ final: false,
688
+ };
689
+ eventBus.publish(workingStatusUpdate);
690
+ let events;
691
+ let lastevent = {
692
+ timestamp: Date.now(),
693
+ };
694
+ let processedEvents = 0;
695
+ do {
696
+ do {
697
+ if (this.cancelledTasks.has(taskId)) {
698
+ log?.info(`[${this.Name}:AgentExecutor] Task ${taskId} has been cancelled.`);
699
+ // Publish the final 'canceled' status.
700
+ const cancelledUpdate = {
701
+ kind: "status-update",
702
+ taskId: taskId,
703
+ contextId: contextId,
704
+ status: { state: "canceled", timestamp: new Date().toISOString() },
705
+ final: true,
706
+ };
707
+ eventBus.publish(cancelledUpdate);
708
+ eventBus.finished();
709
+ // Clean up and exit.
710
+ this.cancelledTasks.delete(taskId);
711
+ return;
712
+ }
713
+ await sleep(500);
714
+ //log?.info(`[${this.Name}:AgentExecutor] Fetching events for correlation ID ${this.CorrelationId}`);
715
+ events = await this.getEvents();
716
+ if (events.length > processedEvents) {
717
+ events = events.slice(processedEvents); // get only new events
718
+ }
719
+ } while (events.length === 0);
720
+ const event = events[0];
721
+ if (lastevent.timestamp !== event.timestamp) {
722
+ //log?.debug(`[${this.Name}:AgentExecutor] New event: ${event.timestamp} Last Event: ${lastevent.timestamp} `);
723
+ lastevent = event;
724
+ if (lastevent.agentStatus === "waiting") {
725
+ if (lastevent.tool.startsWith('mcp_')) {
726
+ }
727
+ else if (lastevent.tool) {
728
+ log?.info(`[${this.Name}:AgentExecutor] toolcall: ${lastevent.tool}, ts:${lastevent.timestamp}, c:${processedEvents}\n`);
729
+ let workingStatusUpdate = {
730
+ kind: 'status-update',
731
+ taskId: taskId,
732
+ contextId: contextId,
733
+ status: {
734
+ state: 'working',
735
+ message: {
736
+ kind: 'message',
737
+ role: 'agent',
738
+ messageId: uuidv4(),
739
+ parts: [{ kind: 'text', text: `invoking tool ${lastevent.tool}(${JSON.stringify(lastevent.toolInput.request_body)})...\n` }],
740
+ taskId: taskId,
741
+ contextId: contextId,
742
+ metadata: {
743
+ data: lastevent.toolInput.request_body
744
+ }
745
+ },
746
+ timestamp: new Date().toISOString(),
747
+ },
748
+ final: false,
749
+ };
750
+ eventBus.publish(workingStatusUpdate);
751
+ const res = await this.executeTool(lastevent.tool, lastevent.toolInput.request_body, log);
752
+ let statusMsg = `Tool ${lastevent.tool} executed `;
753
+ if (res.error) {
754
+ log?.error(`${res.error}`);
755
+ statusMsg += `with error: ${res.error.message || res.error.toString()}`;
756
+ }
757
+ else {
758
+ statusMsg += `successfully.`;
759
+ }
760
+ workingStatusUpdate = {
761
+ kind: 'status-update',
762
+ taskId: taskId,
763
+ contextId: contextId,
764
+ status: {
765
+ state: 'working',
766
+ message: {
767
+ kind: 'message',
768
+ role: 'agent',
769
+ messageId: uuidv4(),
770
+ parts: [{ kind: 'text', text: statusMsg }],
771
+ taskId: taskId,
772
+ contextId: contextId,
773
+ },
774
+ timestamp: new Date().toISOString(),
775
+ },
776
+ final: false,
777
+ };
778
+ eventBus.publish(workingStatusUpdate);
779
+ }
780
+ }
781
+ else if (lastevent.agentStatus === "pending") {
782
+ //log(`\n\n#### ${lastevent.agentStatus}:\n`);
783
+ }
784
+ else if (lastevent.agentStatus === "in-progress") {
785
+ if (lastevent.tool === 'generate_plan_tool' && lastevent.toolOutput) {
786
+ log?.info("```log-Agent_Plan\n" + lastevent.toolOutput + "\n```");
787
+ }
788
+ else if (lastevent.message.indexOf("resume")) {
789
+ //log.info(`.`);
790
+ }
791
+ else
792
+ log?.info(`\n\n#### ${lastevent.message}:\n`);
793
+ }
794
+ else if (lastevent.agentStatus === "completed") {
795
+ log?.info(`Agent Execution Completed`);
796
+ log?.info(`---`);
797
+ log?.done(lastevent.output.response);
798
+ }
799
+ else {
800
+ log?.warn(`#### ${lastevent.agentStatus}`);
801
+ log?.warn('last event:', lastevent);
802
+ log?.error(`Agent execution failed: ${JSON.stringify(lastevent)}`);
803
+ log?.done(' Agent execution failed ');
804
+ }
805
+ processedEvents++;
806
+ }
807
+ } while (lastevent?.agentStatus !== "failed" && lastevent?.agentStatus !== "completed");
808
+ if (lastevent?.agentStatus === "failed") {
809
+ const failureUpdate = {
810
+ kind: 'status-update',
811
+ taskId: taskId,
812
+ contextId: contextId,
813
+ status: {
814
+ state: 'failed',
815
+ message: {
816
+ kind: 'message',
817
+ role: 'agent',
818
+ messageId: uuidv4(),
819
+ parts: [{ kind: 'text', text: `Agent execution failed: ${lastevent?.message || ''}` }],
820
+ taskId: taskId,
821
+ contextId: contextId,
822
+ },
823
+ timestamp: new Date().toISOString(),
824
+ },
825
+ final: true,
826
+ };
827
+ eventBus.publish(failureUpdate);
828
+ }
829
+ else if (lastevent?.agentStatus === "completed") {
830
+ const completedUpdate = {
831
+ kind: 'status-update',
832
+ taskId: taskId,
833
+ contextId: contextId,
834
+ status: {
835
+ state: 'completed',
836
+ message: {
837
+ kind: 'message',
838
+ role: 'agent',
839
+ messageId: uuidv4(),
840
+ parts: [{ kind: 'text', text: lastevent.output.response }],
841
+ taskId: taskId,
842
+ contextId: contextId,
843
+ },
844
+ timestamp: new Date().toISOString(),
845
+ },
846
+ final: true,
847
+ };
848
+ eventBus.publish(completedUpdate);
849
+ }
850
+ return;
851
+ }
852
+ catch (error) {
853
+ log?.error(`[${this.Name}:AgentExecutor] Error processing task ${taskId}:`, error);
854
+ const errorUpdate = {
855
+ kind: 'status-update',
856
+ taskId: taskId,
857
+ contextId: contextId,
858
+ status: {
859
+ state: 'failed',
860
+ message: {
861
+ kind: 'message',
862
+ role: 'agent',
863
+ messageId: uuidv4(),
864
+ parts: [{ kind: 'text', text: `Error processing your message: ${error instanceof Error ? error.message : String(error)}` }],
865
+ taskId: taskId,
866
+ contextId: contextId,
867
+ },
868
+ timestamp: new Date().toISOString(),
869
+ },
870
+ final: true,
871
+ };
872
+ eventBus.publish(errorUpdate);
873
+ }
874
+ }
875
+ // Function to get the host IP address
876
+ getHostIPAddress() {
877
+ const interfaces = os.networkInterfaces();
878
+ for (const interfaceName in interfaces) {
879
+ for (const interfaceInfo of interfaces[interfaceName] || []) {
880
+ if (interfaceInfo.family === 'IPv4' && !interfaceInfo.internal) {
881
+ return interfaceInfo.address;
882
+ }
883
+ }
884
+ }
885
+ return 'localhost';
886
+ }
887
+ /**
888
+ * Port for A2A express server
889
+ * @returns Port number from config or default 41241
890
+ */
891
+ getPort() {
892
+ return this.config.port || 41241;
893
+ }
894
+ /**
895
+ *
896
+ * @param taskStore Optional TaskStore, defaults to InMemoryTaskStore
897
+ * @returns A2A Express app
898
+ */
899
+ getServer(taskStore = new InMemoryTaskStore()) {
900
+ // Set up the server.
901
+ const agentExecutor = this;
902
+ const requestHandler = new DefaultRequestHandler(this.getAgentCard(), taskStore, agentExecutor);
903
+ const appBuilder = new A2AExpressApp(requestHandler);
904
+ const expressApp = appBuilder.setupRoutes(express());
905
+ return { app: expressApp, port: this.getPort() };
906
+ }
907
+ getAgentCard() {
908
+ return {
909
+ version: '0.0.1', // Incremented version
910
+ protocolVersion: '0.3.0',
911
+ name: this.Name,
912
+ description: this.Description,
913
+ // Adjust the base URL and port in A2AExpressApp
914
+ url: `http://${this.getHostIPAddress()}:${this.getPort()}/`,
915
+ provider: {
916
+ organization: 'PS',
917
+ url: 'https://example.com/a2a-agent' // Added provider URL
918
+ },
919
+ capabilities: {
920
+ streaming: true, // The new framework supports streaming
921
+ pushNotifications: false, // Assuming not implemented for this agent yet
922
+ stateTransitionHistory: true, // Agent uses history
923
+ },
924
+ // authentication: null, // Property 'authentication' does not exist on type 'AgentCard'.
925
+ securitySchemes: undefined, // Or define actual security schemes if any
926
+ security: undefined,
927
+ defaultInputModes: ['text'],
928
+ defaultOutputModes: ['text', 'task-status'], // task-status is a common output mode
929
+ skills: [
930
+ {
931
+ id: this.Name.toLowerCase().replace(/\s+/g, '-'),
932
+ name: this.Name,
933
+ description: this.Description,
934
+ tags: ['psagent'],
935
+ examples: this.config.examples || [],
936
+ inputModes: ['text'], // Explicitly defining for skill
937
+ outputModes: ['text', 'task-status'] // Explicitly defining for skill
938
+ },
939
+ ...this.tasks.map(task => ({
940
+ id: task.Name.toLowerCase().replace(/\s+/g, '-'),
941
+ name: task.Name,
942
+ description: task.Description,
943
+ tags: ['psagent-task'],
944
+ examples: task.Examples,
945
+ inputModes: ['text'], // Assuming text input for tasks
946
+ outputModes: ['text', 'task-status'] // Assuming text and status output for tasks
947
+ }))
948
+ ],
949
+ supportsAuthenticatedExtendedCard: false,
950
+ };
951
+ }
952
+ static FromConfigFile(config_path) {
953
+ if (!fs.existsSync(config_path)) {
954
+ throw new Error(`Config file ${config_path} does not exist`);
955
+ }
956
+ const ext = path.extname(config_path).toLowerCase();
957
+ let configData;
958
+ if (ext === '.json') {
959
+ const fileContent = fs.readFileSync(config_path, 'utf-8');
960
+ configData = JSON.parse(fileContent);
961
+ }
962
+ else if (ext === '.yaml' || ext === '.yml') {
963
+ const fileContent = fs.readFileSync(config_path, 'utf-8');
964
+ configData = yaml.parse(fileContent);
965
+ }
966
+ else {
967
+ throw new Error('Unsupported config file format. Use JSON or YAML.');
968
+ }
969
+ // Basic validation of required fields
970
+ const requiredFields = ['name', 'description', 'instruction'];
971
+ for (const field of requiredFields) {
972
+ if (!configData[field]) {
973
+ throw new Error(`Missing required field '${field}' in config file.`);
974
+ }
975
+ }
976
+ // Convert tools and tasks if present
977
+ if (configData.tools && Array.isArray(configData.tools)) {
978
+ configData.tools = configData.tools.map((toolConfig) => new PSAgentTool(toolConfig));
979
+ }
980
+ else {
981
+ configData.tools = [];
982
+ }
983
+ if (configData.tasks && Array.isArray(configData.tasks)) {
984
+ configData.tasks = configData.tasks.map((taskConfig) => new PSAgentTask(taskConfig.name, taskConfig.description));
985
+ }
986
+ else {
987
+ configData.tasks = [];
988
+ }
989
+ return new PSAgent(configData);
990
+ }
991
+ }
992
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiUFNBZ2VudC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9saWIvUFNBZ2VudC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFDQSxPQUFPLEVBQXNCLFdBQVcsRUFBRSxNQUFNLGVBQWUsQ0FBQztBQUVoRSxPQUFPLEVBQUUsQ0FBQyxFQUFFLE1BQU0sUUFBUSxDQUFDO0FBQzNCLE9BQU8sRUFBRSxFQUFFLElBQUksTUFBTSxFQUFFLE1BQU0sTUFBTSxDQUFDLENBQUMsNEJBQTRCO0FBQ2pFLE9BQU8sRUFBRSxNQUFNLElBQUksQ0FBQztBQUNwQixPQUFPLEVBQUUsV0FBVyxFQUFFLE1BQU0sZUFBZSxDQUFDO0FBTzVDLE9BQU8sRUFJTCxxQkFBcUIsRUFFckIsaUJBQWlCLEdBQ2xCLE1BQU0sb0JBQW9CLENBQUM7QUFDNUIsT0FBTyxFQUFFLGFBQWEsRUFBRSxNQUFNLDRCQUE0QixDQUFDO0FBQzNELE9BQU8sT0FBTyxNQUFNLFNBQVMsQ0FBQztBQUM5QixPQUFPLEVBQUUsTUFBTSxTQUFTLENBQUM7QUFDekIsT0FBTyxJQUFJLE1BQU0sV0FBVyxDQUFDO0FBQzdCLE9BQU8sSUFBSSxNQUFNLE1BQU0sQ0FBQztBQUN4QixPQUFPLEVBQUUsSUFBSSxFQUFFLE1BQU0sUUFBUSxDQUFDO0FBQzlCLHVFQUF1RTtBQUN2RSxNQUFNLEtBQUssR0FBRyxPQUFPLENBQUMsYUFBYSxDQUFDLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxDQUFDO0FBRW5ELE1BQU0sQ0FBQyxLQUFLLFVBQVUsS0FBSyxDQUFDLEVBQVU7SUFDcEMsT0FBTyxJQUFJLE9BQU8sQ0FBQyxDQUFDLE9BQU8sRUFBRSxFQUFFLENBQUMsVUFBVSxDQUFDLE9BQU8sRUFBRSxFQUFFLENBQUMsQ0FBQyxDQUFDO0FBQzNELENBQUM7QUFFRDs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0dBMENHO0FBQ0gsTUFBTSxPQUFPLE9BQU87SUFD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