@mastra/client-js 0.1.20-alpha.5 → 0.1.20
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.turbo/turbo-build.log +8 -8
- package/CHANGELOG.md +45 -0
- package/dist/index.cjs +181 -1
- package/dist/index.d.cts +4 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.js +181 -1
- package/package.json +7 -5
- package/src/adapters/agui.test.ts +167 -0
- package/src/adapters/agui.ts +219 -0
- package/src/client.ts +21 -0
package/.turbo/turbo-build.log
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
|
|
2
|
-
> @mastra/client-js@0.1.20-alpha.
|
|
2
|
+
> @mastra/client-js@0.1.20-alpha.6 build /home/runner/work/mastra/mastra/client-sdks/client-js
|
|
3
3
|
> tsup src/index.ts --format esm,cjs --dts --clean --treeshake=smallest --splitting
|
|
4
4
|
|
|
5
5
|
[34mCLI[39m Building entry: src/index.ts
|
|
@@ -9,11 +9,11 @@
|
|
|
9
9
|
[34mCLI[39m Cleaning output folder
|
|
10
10
|
[34mESM[39m Build start
|
|
11
11
|
[34mCJS[39m Build start
|
|
12
|
-
[
|
|
13
|
-
[
|
|
14
|
-
[
|
|
15
|
-
[
|
|
12
|
+
[32mCJS[39m [1mdist/index.cjs [22m[32m34.65 KB[39m
|
|
13
|
+
[32mCJS[39m ⚡️ Build success in 1542ms
|
|
14
|
+
[32mESM[39m [1mdist/index.js [22m[32m34.43 KB[39m
|
|
15
|
+
[32mESM[39m ⚡️ Build success in 1566ms
|
|
16
16
|
[34mDTS[39m Build start
|
|
17
|
-
[32mDTS[39m ⚡️ Build success in
|
|
18
|
-
[32mDTS[39m [1mdist/index.d.ts [22m[
|
|
19
|
-
[32mDTS[39m [1mdist/index.d.cts [22m[
|
|
17
|
+
[32mDTS[39m ⚡️ Build success in 14884ms
|
|
18
|
+
[32mDTS[39m [1mdist/index.d.ts [22m[32m25.12 KB[39m
|
|
19
|
+
[32mDTS[39m [1mdist/index.d.cts [22m[32m25.12 KB[39m
|
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,50 @@
|
|
|
1
1
|
# @mastra/client-js
|
|
2
2
|
|
|
3
|
+
## 0.1.20
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- 2cf3b8f: dependencies updates:
|
|
8
|
+
- Updated dependency [`zod@^3.24.3` ↗︎](https://www.npmjs.com/package/zod/v/3.24.3) (from `^3.24.2`, in `dependencies`)
|
|
9
|
+
- Updated dependency [`zod-to-json-schema@^3.24.5` ↗︎](https://www.npmjs.com/package/zod-to-json-schema/v/3.24.5) (from `^3.24.3`, in `dependencies`)
|
|
10
|
+
- 4155f47: Add parameters to filter workflow runs
|
|
11
|
+
Add fromDate and toDate to telemetry parameters
|
|
12
|
+
- 254f5c3: Audit, cleanup MastraClient
|
|
13
|
+
- 0097d50: Add serializedStepGraph to vNext workflow
|
|
14
|
+
Return serializedStepGraph from vNext workflow
|
|
15
|
+
Use serializedStepGraph in vNext workflow graph
|
|
16
|
+
- 2429c74: Add get workflow runs api to client-js
|
|
17
|
+
- 2e4f8e9: Agui client integration
|
|
18
|
+
- Updated dependencies [6052aa6]
|
|
19
|
+
- Updated dependencies [967b41c]
|
|
20
|
+
- Updated dependencies [3d2fb5c]
|
|
21
|
+
- Updated dependencies [26738f4]
|
|
22
|
+
- Updated dependencies [4155f47]
|
|
23
|
+
- Updated dependencies [7eeb2bc]
|
|
24
|
+
- Updated dependencies [b804723]
|
|
25
|
+
- Updated dependencies [8607972]
|
|
26
|
+
- Updated dependencies [ccef9f9]
|
|
27
|
+
- Updated dependencies [0097d50]
|
|
28
|
+
- Updated dependencies [7eeb2bc]
|
|
29
|
+
- Updated dependencies [17826a9]
|
|
30
|
+
- Updated dependencies [7d8b7c7]
|
|
31
|
+
- Updated dependencies [fba031f]
|
|
32
|
+
- Updated dependencies [3a5f1e1]
|
|
33
|
+
- Updated dependencies [51e6923]
|
|
34
|
+
- Updated dependencies [8398d89]
|
|
35
|
+
- @mastra/core@0.9.2
|
|
36
|
+
|
|
37
|
+
## 0.1.20-alpha.6
|
|
38
|
+
|
|
39
|
+
### Patch Changes
|
|
40
|
+
|
|
41
|
+
- 2e4f8e9: Agui client integration
|
|
42
|
+
- Updated dependencies [6052aa6]
|
|
43
|
+
- Updated dependencies [7d8b7c7]
|
|
44
|
+
- Updated dependencies [3a5f1e1]
|
|
45
|
+
- Updated dependencies [8398d89]
|
|
46
|
+
- @mastra/core@0.9.2-alpha.6
|
|
47
|
+
|
|
3
48
|
## 0.1.20-alpha.5
|
|
4
49
|
|
|
5
50
|
### Patch Changes
|
package/dist/index.cjs
CHANGED
|
@@ -1,10 +1,175 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
+
var client = require('@ag-ui/client');
|
|
4
|
+
var rxjs = require('rxjs');
|
|
3
5
|
var uiUtils = require('@ai-sdk/ui-utils');
|
|
4
6
|
var zod = require('zod');
|
|
5
7
|
var zodToJsonSchema = require('zod-to-json-schema');
|
|
6
8
|
|
|
7
|
-
// src/
|
|
9
|
+
// src/adapters/agui.ts
|
|
10
|
+
var AGUIAdapter = class extends client.AbstractAgent {
|
|
11
|
+
agent;
|
|
12
|
+
resourceId;
|
|
13
|
+
constructor({ agent, agentId, resourceId, ...rest }) {
|
|
14
|
+
super({
|
|
15
|
+
agentId,
|
|
16
|
+
...rest
|
|
17
|
+
});
|
|
18
|
+
this.agent = agent;
|
|
19
|
+
this.resourceId = resourceId;
|
|
20
|
+
}
|
|
21
|
+
run(input) {
|
|
22
|
+
return new rxjs.Observable((subscriber) => {
|
|
23
|
+
const convertedMessages = convertMessagesToMastraMessages(input.messages);
|
|
24
|
+
subscriber.next({
|
|
25
|
+
type: client.EventType.RUN_STARTED,
|
|
26
|
+
threadId: input.threadId,
|
|
27
|
+
runId: input.runId
|
|
28
|
+
});
|
|
29
|
+
this.agent.stream({
|
|
30
|
+
threadId: input.threadId,
|
|
31
|
+
resourceId: this.resourceId ?? "",
|
|
32
|
+
runId: input.runId,
|
|
33
|
+
messages: convertedMessages,
|
|
34
|
+
clientTools: input.tools.reduce(
|
|
35
|
+
(acc, tool) => {
|
|
36
|
+
acc[tool.name] = {
|
|
37
|
+
id: tool.name,
|
|
38
|
+
description: tool.description,
|
|
39
|
+
inputSchema: tool.parameters
|
|
40
|
+
};
|
|
41
|
+
return acc;
|
|
42
|
+
},
|
|
43
|
+
{}
|
|
44
|
+
)
|
|
45
|
+
}).then((response) => {
|
|
46
|
+
let currentMessageId = void 0;
|
|
47
|
+
return response.processDataStream({
|
|
48
|
+
onTextPart: (text) => {
|
|
49
|
+
if (currentMessageId === void 0) {
|
|
50
|
+
currentMessageId = generateUUID();
|
|
51
|
+
const message2 = {
|
|
52
|
+
type: client.EventType.TEXT_MESSAGE_START,
|
|
53
|
+
messageId: currentMessageId,
|
|
54
|
+
role: "assistant"
|
|
55
|
+
};
|
|
56
|
+
subscriber.next(message2);
|
|
57
|
+
}
|
|
58
|
+
const message = {
|
|
59
|
+
type: client.EventType.TEXT_MESSAGE_CONTENT,
|
|
60
|
+
messageId: currentMessageId,
|
|
61
|
+
delta: text
|
|
62
|
+
};
|
|
63
|
+
subscriber.next(message);
|
|
64
|
+
},
|
|
65
|
+
onFinishMessagePart: (message) => {
|
|
66
|
+
console.log("onFinishMessagePart", message);
|
|
67
|
+
if (currentMessageId !== void 0) {
|
|
68
|
+
const message2 = {
|
|
69
|
+
type: client.EventType.TEXT_MESSAGE_END,
|
|
70
|
+
messageId: currentMessageId
|
|
71
|
+
};
|
|
72
|
+
subscriber.next(message2);
|
|
73
|
+
}
|
|
74
|
+
subscriber.next({
|
|
75
|
+
type: client.EventType.RUN_FINISHED,
|
|
76
|
+
threadId: input.threadId,
|
|
77
|
+
runId: input.runId
|
|
78
|
+
});
|
|
79
|
+
subscriber.complete();
|
|
80
|
+
},
|
|
81
|
+
onToolCallPart(streamPart) {
|
|
82
|
+
const parentMessageId = currentMessageId || generateUUID();
|
|
83
|
+
subscriber.next({
|
|
84
|
+
type: client.EventType.TOOL_CALL_START,
|
|
85
|
+
toolCallId: streamPart.toolCallId,
|
|
86
|
+
toolCallName: streamPart.toolName,
|
|
87
|
+
parentMessageId
|
|
88
|
+
});
|
|
89
|
+
subscriber.next({
|
|
90
|
+
type: client.EventType.TOOL_CALL_ARGS,
|
|
91
|
+
toolCallId: streamPart.toolCallId,
|
|
92
|
+
delta: JSON.stringify(streamPart.args),
|
|
93
|
+
parentMessageId
|
|
94
|
+
});
|
|
95
|
+
subscriber.next({
|
|
96
|
+
type: client.EventType.TOOL_CALL_END,
|
|
97
|
+
toolCallId: streamPart.toolCallId,
|
|
98
|
+
parentMessageId
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
});
|
|
102
|
+
}).catch((error) => {
|
|
103
|
+
console.log("error", error);
|
|
104
|
+
subscriber.error(error);
|
|
105
|
+
});
|
|
106
|
+
return () => {
|
|
107
|
+
};
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
};
|
|
111
|
+
function generateUUID() {
|
|
112
|
+
if (typeof crypto !== "undefined") {
|
|
113
|
+
if (typeof crypto.randomUUID === "function") {
|
|
114
|
+
return crypto.randomUUID();
|
|
115
|
+
}
|
|
116
|
+
if (typeof crypto.getRandomValues === "function") {
|
|
117
|
+
const buffer = new Uint8Array(16);
|
|
118
|
+
crypto.getRandomValues(buffer);
|
|
119
|
+
buffer[6] = buffer[6] & 15 | 64;
|
|
120
|
+
buffer[8] = buffer[8] & 63 | 128;
|
|
121
|
+
let hex = "";
|
|
122
|
+
for (let i = 0; i < 16; i++) {
|
|
123
|
+
hex += buffer[i].toString(16).padStart(2, "0");
|
|
124
|
+
if (i === 3 || i === 5 || i === 7 || i === 9) hex += "-";
|
|
125
|
+
}
|
|
126
|
+
return hex;
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, (c) => {
|
|
130
|
+
const r = Math.random() * 16 | 0;
|
|
131
|
+
const v = c === "x" ? r : r & 3 | 8;
|
|
132
|
+
return v.toString(16);
|
|
133
|
+
});
|
|
134
|
+
}
|
|
135
|
+
function convertMessagesToMastraMessages(messages) {
|
|
136
|
+
const result = [];
|
|
137
|
+
for (const message of messages) {
|
|
138
|
+
if (message.role === "assistant") {
|
|
139
|
+
const parts = message.content ? [{ type: "text", text: message.content }] : [];
|
|
140
|
+
for (const toolCall of message.toolCalls ?? []) {
|
|
141
|
+
parts.push({
|
|
142
|
+
type: "tool-call",
|
|
143
|
+
toolCallId: toolCall.id,
|
|
144
|
+
toolName: toolCall.function.name,
|
|
145
|
+
args: JSON.parse(toolCall.function.arguments)
|
|
146
|
+
});
|
|
147
|
+
}
|
|
148
|
+
result.push({
|
|
149
|
+
role: "assistant",
|
|
150
|
+
content: parts
|
|
151
|
+
});
|
|
152
|
+
} else if (message.role === "user") {
|
|
153
|
+
result.push({
|
|
154
|
+
role: "user",
|
|
155
|
+
content: message.content || ""
|
|
156
|
+
});
|
|
157
|
+
} else if (message.role === "tool") {
|
|
158
|
+
result.push({
|
|
159
|
+
role: "tool",
|
|
160
|
+
content: [
|
|
161
|
+
{
|
|
162
|
+
type: "tool-result",
|
|
163
|
+
toolCallId: message.toolCallId,
|
|
164
|
+
toolName: "unknown",
|
|
165
|
+
result: message.content
|
|
166
|
+
}
|
|
167
|
+
]
|
|
168
|
+
});
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
return result;
|
|
172
|
+
}
|
|
8
173
|
|
|
9
174
|
// src/resources/base.ts
|
|
10
175
|
var BaseResource = class {
|
|
@@ -778,6 +943,21 @@ var MastraClient = class extends BaseResource {
|
|
|
778
943
|
getAgents() {
|
|
779
944
|
return this.request("/api/agents");
|
|
780
945
|
}
|
|
946
|
+
async getAGUI({ resourceId }) {
|
|
947
|
+
const agents = await this.getAgents();
|
|
948
|
+
return Object.entries(agents).reduce(
|
|
949
|
+
(acc, [agentId]) => {
|
|
950
|
+
const agent = this.getAgent(agentId);
|
|
951
|
+
acc[agentId] = new AGUIAdapter({
|
|
952
|
+
agentId,
|
|
953
|
+
agent,
|
|
954
|
+
resourceId
|
|
955
|
+
});
|
|
956
|
+
return acc;
|
|
957
|
+
},
|
|
958
|
+
{}
|
|
959
|
+
);
|
|
960
|
+
}
|
|
781
961
|
/**
|
|
782
962
|
* Gets an agent instance by ID
|
|
783
963
|
* @param agentId - ID of the agent to retrieve
|
package/dist/index.d.cts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { AbstractAgent } from '@ag-ui/client';
|
|
1
2
|
import { processDataStream } from '@ai-sdk/ui-utils';
|
|
2
3
|
import { CoreMessage, AiMessageType, StorageThreadType, MessageType, StepAction, StepGraph, WorkflowRuns, WorkflowRunResult as WorkflowRunResult$1, QueryResult, BaseLogMessage, GenerateReturn } from '@mastra/core';
|
|
3
4
|
import { JSONSchema7 } from 'json-schema';
|
|
@@ -609,6 +610,9 @@ declare class MastraClient extends BaseResource {
|
|
|
609
610
|
* @returns Promise containing map of agent IDs to agent details
|
|
610
611
|
*/
|
|
611
612
|
getAgents(): Promise<Record<string, GetAgentResponse>>;
|
|
613
|
+
getAGUI({ resourceId }: {
|
|
614
|
+
resourceId: string;
|
|
615
|
+
}): Promise<Record<string, AbstractAgent>>;
|
|
612
616
|
/**
|
|
613
617
|
* Gets an agent instance by ID
|
|
614
618
|
* @param agentId - ID of the agent to retrieve
|
package/dist/index.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { AbstractAgent } from '@ag-ui/client';
|
|
1
2
|
import { processDataStream } from '@ai-sdk/ui-utils';
|
|
2
3
|
import { CoreMessage, AiMessageType, StorageThreadType, MessageType, StepAction, StepGraph, WorkflowRuns, WorkflowRunResult as WorkflowRunResult$1, QueryResult, BaseLogMessage, GenerateReturn } from '@mastra/core';
|
|
3
4
|
import { JSONSchema7 } from 'json-schema';
|
|
@@ -609,6 +610,9 @@ declare class MastraClient extends BaseResource {
|
|
|
609
610
|
* @returns Promise containing map of agent IDs to agent details
|
|
610
611
|
*/
|
|
611
612
|
getAgents(): Promise<Record<string, GetAgentResponse>>;
|
|
613
|
+
getAGUI({ resourceId }: {
|
|
614
|
+
resourceId: string;
|
|
615
|
+
}): Promise<Record<string, AbstractAgent>>;
|
|
612
616
|
/**
|
|
613
617
|
* Gets an agent instance by ID
|
|
614
618
|
* @param agentId - ID of the agent to retrieve
|
package/dist/index.js
CHANGED
|
@@ -1,8 +1,173 @@
|
|
|
1
|
+
import { AbstractAgent, EventType } from '@ag-ui/client';
|
|
2
|
+
import { Observable } from 'rxjs';
|
|
1
3
|
import { processDataStream } from '@ai-sdk/ui-utils';
|
|
2
4
|
import { ZodSchema } from 'zod';
|
|
3
5
|
import { zodToJsonSchema } from 'zod-to-json-schema';
|
|
4
6
|
|
|
5
|
-
// src/
|
|
7
|
+
// src/adapters/agui.ts
|
|
8
|
+
var AGUIAdapter = class extends AbstractAgent {
|
|
9
|
+
agent;
|
|
10
|
+
resourceId;
|
|
11
|
+
constructor({ agent, agentId, resourceId, ...rest }) {
|
|
12
|
+
super({
|
|
13
|
+
agentId,
|
|
14
|
+
...rest
|
|
15
|
+
});
|
|
16
|
+
this.agent = agent;
|
|
17
|
+
this.resourceId = resourceId;
|
|
18
|
+
}
|
|
19
|
+
run(input) {
|
|
20
|
+
return new Observable((subscriber) => {
|
|
21
|
+
const convertedMessages = convertMessagesToMastraMessages(input.messages);
|
|
22
|
+
subscriber.next({
|
|
23
|
+
type: EventType.RUN_STARTED,
|
|
24
|
+
threadId: input.threadId,
|
|
25
|
+
runId: input.runId
|
|
26
|
+
});
|
|
27
|
+
this.agent.stream({
|
|
28
|
+
threadId: input.threadId,
|
|
29
|
+
resourceId: this.resourceId ?? "",
|
|
30
|
+
runId: input.runId,
|
|
31
|
+
messages: convertedMessages,
|
|
32
|
+
clientTools: input.tools.reduce(
|
|
33
|
+
(acc, tool) => {
|
|
34
|
+
acc[tool.name] = {
|
|
35
|
+
id: tool.name,
|
|
36
|
+
description: tool.description,
|
|
37
|
+
inputSchema: tool.parameters
|
|
38
|
+
};
|
|
39
|
+
return acc;
|
|
40
|
+
},
|
|
41
|
+
{}
|
|
42
|
+
)
|
|
43
|
+
}).then((response) => {
|
|
44
|
+
let currentMessageId = void 0;
|
|
45
|
+
return response.processDataStream({
|
|
46
|
+
onTextPart: (text) => {
|
|
47
|
+
if (currentMessageId === void 0) {
|
|
48
|
+
currentMessageId = generateUUID();
|
|
49
|
+
const message2 = {
|
|
50
|
+
type: EventType.TEXT_MESSAGE_START,
|
|
51
|
+
messageId: currentMessageId,
|
|
52
|
+
role: "assistant"
|
|
53
|
+
};
|
|
54
|
+
subscriber.next(message2);
|
|
55
|
+
}
|
|
56
|
+
const message = {
|
|
57
|
+
type: EventType.TEXT_MESSAGE_CONTENT,
|
|
58
|
+
messageId: currentMessageId,
|
|
59
|
+
delta: text
|
|
60
|
+
};
|
|
61
|
+
subscriber.next(message);
|
|
62
|
+
},
|
|
63
|
+
onFinishMessagePart: (message) => {
|
|
64
|
+
console.log("onFinishMessagePart", message);
|
|
65
|
+
if (currentMessageId !== void 0) {
|
|
66
|
+
const message2 = {
|
|
67
|
+
type: EventType.TEXT_MESSAGE_END,
|
|
68
|
+
messageId: currentMessageId
|
|
69
|
+
};
|
|
70
|
+
subscriber.next(message2);
|
|
71
|
+
}
|
|
72
|
+
subscriber.next({
|
|
73
|
+
type: EventType.RUN_FINISHED,
|
|
74
|
+
threadId: input.threadId,
|
|
75
|
+
runId: input.runId
|
|
76
|
+
});
|
|
77
|
+
subscriber.complete();
|
|
78
|
+
},
|
|
79
|
+
onToolCallPart(streamPart) {
|
|
80
|
+
const parentMessageId = currentMessageId || generateUUID();
|
|
81
|
+
subscriber.next({
|
|
82
|
+
type: EventType.TOOL_CALL_START,
|
|
83
|
+
toolCallId: streamPart.toolCallId,
|
|
84
|
+
toolCallName: streamPart.toolName,
|
|
85
|
+
parentMessageId
|
|
86
|
+
});
|
|
87
|
+
subscriber.next({
|
|
88
|
+
type: EventType.TOOL_CALL_ARGS,
|
|
89
|
+
toolCallId: streamPart.toolCallId,
|
|
90
|
+
delta: JSON.stringify(streamPart.args),
|
|
91
|
+
parentMessageId
|
|
92
|
+
});
|
|
93
|
+
subscriber.next({
|
|
94
|
+
type: EventType.TOOL_CALL_END,
|
|
95
|
+
toolCallId: streamPart.toolCallId,
|
|
96
|
+
parentMessageId
|
|
97
|
+
});
|
|
98
|
+
}
|
|
99
|
+
});
|
|
100
|
+
}).catch((error) => {
|
|
101
|
+
console.log("error", error);
|
|
102
|
+
subscriber.error(error);
|
|
103
|
+
});
|
|
104
|
+
return () => {
|
|
105
|
+
};
|
|
106
|
+
});
|
|
107
|
+
}
|
|
108
|
+
};
|
|
109
|
+
function generateUUID() {
|
|
110
|
+
if (typeof crypto !== "undefined") {
|
|
111
|
+
if (typeof crypto.randomUUID === "function") {
|
|
112
|
+
return crypto.randomUUID();
|
|
113
|
+
}
|
|
114
|
+
if (typeof crypto.getRandomValues === "function") {
|
|
115
|
+
const buffer = new Uint8Array(16);
|
|
116
|
+
crypto.getRandomValues(buffer);
|
|
117
|
+
buffer[6] = buffer[6] & 15 | 64;
|
|
118
|
+
buffer[8] = buffer[8] & 63 | 128;
|
|
119
|
+
let hex = "";
|
|
120
|
+
for (let i = 0; i < 16; i++) {
|
|
121
|
+
hex += buffer[i].toString(16).padStart(2, "0");
|
|
122
|
+
if (i === 3 || i === 5 || i === 7 || i === 9) hex += "-";
|
|
123
|
+
}
|
|
124
|
+
return hex;
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, (c) => {
|
|
128
|
+
const r = Math.random() * 16 | 0;
|
|
129
|
+
const v = c === "x" ? r : r & 3 | 8;
|
|
130
|
+
return v.toString(16);
|
|
131
|
+
});
|
|
132
|
+
}
|
|
133
|
+
function convertMessagesToMastraMessages(messages) {
|
|
134
|
+
const result = [];
|
|
135
|
+
for (const message of messages) {
|
|
136
|
+
if (message.role === "assistant") {
|
|
137
|
+
const parts = message.content ? [{ type: "text", text: message.content }] : [];
|
|
138
|
+
for (const toolCall of message.toolCalls ?? []) {
|
|
139
|
+
parts.push({
|
|
140
|
+
type: "tool-call",
|
|
141
|
+
toolCallId: toolCall.id,
|
|
142
|
+
toolName: toolCall.function.name,
|
|
143
|
+
args: JSON.parse(toolCall.function.arguments)
|
|
144
|
+
});
|
|
145
|
+
}
|
|
146
|
+
result.push({
|
|
147
|
+
role: "assistant",
|
|
148
|
+
content: parts
|
|
149
|
+
});
|
|
150
|
+
} else if (message.role === "user") {
|
|
151
|
+
result.push({
|
|
152
|
+
role: "user",
|
|
153
|
+
content: message.content || ""
|
|
154
|
+
});
|
|
155
|
+
} else if (message.role === "tool") {
|
|
156
|
+
result.push({
|
|
157
|
+
role: "tool",
|
|
158
|
+
content: [
|
|
159
|
+
{
|
|
160
|
+
type: "tool-result",
|
|
161
|
+
toolCallId: message.toolCallId,
|
|
162
|
+
toolName: "unknown",
|
|
163
|
+
result: message.content
|
|
164
|
+
}
|
|
165
|
+
]
|
|
166
|
+
});
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
return result;
|
|
170
|
+
}
|
|
6
171
|
|
|
7
172
|
// src/resources/base.ts
|
|
8
173
|
var BaseResource = class {
|
|
@@ -776,6 +941,21 @@ var MastraClient = class extends BaseResource {
|
|
|
776
941
|
getAgents() {
|
|
777
942
|
return this.request("/api/agents");
|
|
778
943
|
}
|
|
944
|
+
async getAGUI({ resourceId }) {
|
|
945
|
+
const agents = await this.getAgents();
|
|
946
|
+
return Object.entries(agents).reduce(
|
|
947
|
+
(acc, [agentId]) => {
|
|
948
|
+
const agent = this.getAgent(agentId);
|
|
949
|
+
acc[agentId] = new AGUIAdapter({
|
|
950
|
+
agentId,
|
|
951
|
+
agent,
|
|
952
|
+
resourceId
|
|
953
|
+
});
|
|
954
|
+
return acc;
|
|
955
|
+
},
|
|
956
|
+
{}
|
|
957
|
+
);
|
|
958
|
+
}
|
|
779
959
|
/**
|
|
780
960
|
* Gets an agent instance by ID
|
|
781
961
|
* @param agentId - ID of the agent to retrieve
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mastra/client-js",
|
|
3
|
-
"version": "0.1.20
|
|
3
|
+
"version": "0.1.20",
|
|
4
4
|
"description": "The official TypeScript library for the Mastra Client API",
|
|
5
5
|
"author": "",
|
|
6
6
|
"type": "module",
|
|
@@ -22,11 +22,13 @@
|
|
|
22
22
|
"repository": "github:mastra-ai/client-js",
|
|
23
23
|
"license": "Elastic-2.0",
|
|
24
24
|
"dependencies": {
|
|
25
|
+
"@ag-ui/client": "^0.0.27",
|
|
25
26
|
"@ai-sdk/ui-utils": "^1.1.19",
|
|
26
27
|
"json-schema": "^0.4.0",
|
|
27
|
-
"
|
|
28
|
-
"zod
|
|
29
|
-
"
|
|
28
|
+
"rxjs": "7.8.1",
|
|
29
|
+
"zod": "^3.24.3",
|
|
30
|
+
"zod-to-json-schema": "^3.24.5",
|
|
31
|
+
"@mastra/core": "^0.9.2"
|
|
30
32
|
},
|
|
31
33
|
"peerDependencies": {
|
|
32
34
|
"zod": "^3.24.2"
|
|
@@ -40,7 +42,7 @@
|
|
|
40
42
|
"tsup": "^8.4.0",
|
|
41
43
|
"typescript": "^5.8.2",
|
|
42
44
|
"vitest": "^3.1.2",
|
|
43
|
-
"@internal/lint": "0.0.
|
|
45
|
+
"@internal/lint": "0.0.3"
|
|
44
46
|
},
|
|
45
47
|
"scripts": {
|
|
46
48
|
"build": "tsup src/index.ts --format esm,cjs --dts --clean --treeshake=smallest --splitting",
|
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
import type { Message } from '@ag-ui/client';
|
|
2
|
+
import { describe, it, expect } from 'vitest';
|
|
3
|
+
import { generateUUID, convertMessagesToMastraMessages } from './agui';
|
|
4
|
+
|
|
5
|
+
describe('generateUUID', () => {
|
|
6
|
+
it('should generate a valid UUID v4 string', () => {
|
|
7
|
+
const uuid = generateUUID();
|
|
8
|
+
// Check UUID format (8-4-4-4-12 hex digits)
|
|
9
|
+
expect(uuid).toMatch(/^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i);
|
|
10
|
+
});
|
|
11
|
+
|
|
12
|
+
it('should generate unique UUIDs', () => {
|
|
13
|
+
const uuids = new Set();
|
|
14
|
+
for (let i = 0; i < 100; i++) {
|
|
15
|
+
uuids.add(generateUUID());
|
|
16
|
+
}
|
|
17
|
+
// All UUIDs should be unique
|
|
18
|
+
expect(uuids.size).toBe(100);
|
|
19
|
+
});
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
describe('convertMessagesToMastraMessages', () => {
|
|
23
|
+
it('should convert user messages correctly', () => {
|
|
24
|
+
const messages: Message[] = [
|
|
25
|
+
{
|
|
26
|
+
id: '1',
|
|
27
|
+
role: 'user',
|
|
28
|
+
content: 'Hello, world!',
|
|
29
|
+
},
|
|
30
|
+
];
|
|
31
|
+
|
|
32
|
+
const result = convertMessagesToMastraMessages(messages);
|
|
33
|
+
|
|
34
|
+
expect(result).toEqual([
|
|
35
|
+
{
|
|
36
|
+
role: 'user',
|
|
37
|
+
content: 'Hello, world!',
|
|
38
|
+
},
|
|
39
|
+
]);
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
it('should convert assistant messages correctly', () => {
|
|
43
|
+
const messages: Message[] = [
|
|
44
|
+
{
|
|
45
|
+
id: '1',
|
|
46
|
+
role: 'assistant',
|
|
47
|
+
content: 'Hello, I am an assistant',
|
|
48
|
+
},
|
|
49
|
+
];
|
|
50
|
+
|
|
51
|
+
const result = convertMessagesToMastraMessages(messages);
|
|
52
|
+
|
|
53
|
+
expect(result).toEqual([
|
|
54
|
+
{
|
|
55
|
+
role: 'assistant',
|
|
56
|
+
content: [{ type: 'text', text: 'Hello, I am an assistant' }],
|
|
57
|
+
},
|
|
58
|
+
]);
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
it('should convert assistant messages with tool calls correctly', () => {
|
|
62
|
+
const messages: Message[] = [
|
|
63
|
+
{
|
|
64
|
+
id: '1',
|
|
65
|
+
role: 'assistant',
|
|
66
|
+
content: undefined,
|
|
67
|
+
toolCalls: [
|
|
68
|
+
{
|
|
69
|
+
id: 'tool-call-1',
|
|
70
|
+
type: 'function',
|
|
71
|
+
function: {
|
|
72
|
+
name: 'getWeather',
|
|
73
|
+
arguments: '{"location":"San Francisco"}',
|
|
74
|
+
},
|
|
75
|
+
},
|
|
76
|
+
],
|
|
77
|
+
},
|
|
78
|
+
];
|
|
79
|
+
|
|
80
|
+
const result = convertMessagesToMastraMessages(messages);
|
|
81
|
+
|
|
82
|
+
expect(result).toEqual([
|
|
83
|
+
{
|
|
84
|
+
role: 'assistant',
|
|
85
|
+
content: [
|
|
86
|
+
{
|
|
87
|
+
type: 'tool-call',
|
|
88
|
+
toolCallId: 'tool-call-1',
|
|
89
|
+
toolName: 'getWeather',
|
|
90
|
+
args: { location: 'San Francisco' },
|
|
91
|
+
},
|
|
92
|
+
],
|
|
93
|
+
},
|
|
94
|
+
]);
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
it('should convert tool messages correctly', () => {
|
|
98
|
+
const messages: Message[] = [
|
|
99
|
+
{
|
|
100
|
+
id: '1',
|
|
101
|
+
role: 'tool',
|
|
102
|
+
toolCallId: 'tool-call-1',
|
|
103
|
+
content: '{"temperature":72,"unit":"F"}',
|
|
104
|
+
},
|
|
105
|
+
];
|
|
106
|
+
|
|
107
|
+
const result = convertMessagesToMastraMessages(messages);
|
|
108
|
+
|
|
109
|
+
expect(result).toEqual([
|
|
110
|
+
{
|
|
111
|
+
role: 'tool',
|
|
112
|
+
content: [
|
|
113
|
+
{
|
|
114
|
+
type: 'tool-result',
|
|
115
|
+
toolCallId: 'tool-call-1',
|
|
116
|
+
toolName: 'unknown',
|
|
117
|
+
result: '{"temperature":72,"unit":"F"}',
|
|
118
|
+
},
|
|
119
|
+
],
|
|
120
|
+
},
|
|
121
|
+
]);
|
|
122
|
+
});
|
|
123
|
+
|
|
124
|
+
it('should convert a complex conversation correctly', () => {
|
|
125
|
+
const messages: Message[] = [
|
|
126
|
+
{
|
|
127
|
+
id: '1',
|
|
128
|
+
role: 'user',
|
|
129
|
+
content: "What's the weather in San Francisco?",
|
|
130
|
+
},
|
|
131
|
+
{
|
|
132
|
+
id: '2',
|
|
133
|
+
role: 'assistant',
|
|
134
|
+
content: undefined,
|
|
135
|
+
toolCalls: [
|
|
136
|
+
{
|
|
137
|
+
id: 'tool-call-1',
|
|
138
|
+
type: 'function',
|
|
139
|
+
function: {
|
|
140
|
+
name: 'getWeather',
|
|
141
|
+
arguments: '{"location":"San Francisco"}',
|
|
142
|
+
},
|
|
143
|
+
},
|
|
144
|
+
],
|
|
145
|
+
},
|
|
146
|
+
{
|
|
147
|
+
id: '3',
|
|
148
|
+
role: 'tool',
|
|
149
|
+
toolCallId: 'tool-call-1',
|
|
150
|
+
content: '{"temperature":72,"unit":"F"}',
|
|
151
|
+
},
|
|
152
|
+
{
|
|
153
|
+
id: '4',
|
|
154
|
+
role: 'assistant',
|
|
155
|
+
content: 'The weather in San Francisco is 72°F.',
|
|
156
|
+
},
|
|
157
|
+
];
|
|
158
|
+
|
|
159
|
+
const result = convertMessagesToMastraMessages(messages);
|
|
160
|
+
|
|
161
|
+
expect(result).toHaveLength(4);
|
|
162
|
+
expect(result[0].role).toBe('user');
|
|
163
|
+
expect(result[1].role).toBe('assistant');
|
|
164
|
+
expect(result[2].role).toBe('tool');
|
|
165
|
+
expect(result[3].role).toBe('assistant');
|
|
166
|
+
});
|
|
167
|
+
});
|
|
@@ -0,0 +1,219 @@
|
|
|
1
|
+
// Cross-platform UUID generation function
|
|
2
|
+
import { AbstractAgent, EventType } from '@ag-ui/client';
|
|
3
|
+
import type {
|
|
4
|
+
BaseEvent,
|
|
5
|
+
RunAgentInput,
|
|
6
|
+
AgentConfig,
|
|
7
|
+
RunStartedEvent,
|
|
8
|
+
RunFinishedEvent,
|
|
9
|
+
TextMessageStartEvent,
|
|
10
|
+
TextMessageContentEvent,
|
|
11
|
+
TextMessageEndEvent,
|
|
12
|
+
Message,
|
|
13
|
+
ToolCallStartEvent,
|
|
14
|
+
ToolCallArgsEvent,
|
|
15
|
+
ToolCallEndEvent,
|
|
16
|
+
} from '@ag-ui/client';
|
|
17
|
+
import type { CoreMessage } from '@mastra/core';
|
|
18
|
+
import { Observable } from 'rxjs';
|
|
19
|
+
import type { Agent } from '../resources/agent';
|
|
20
|
+
|
|
21
|
+
interface MastraAgentConfig extends AgentConfig {
|
|
22
|
+
agent: Agent;
|
|
23
|
+
agentId: string;
|
|
24
|
+
resourceId?: string;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export class AGUIAdapter extends AbstractAgent {
|
|
28
|
+
agent: Agent;
|
|
29
|
+
resourceId?: string;
|
|
30
|
+
constructor({ agent, agentId, resourceId, ...rest }: MastraAgentConfig) {
|
|
31
|
+
super({
|
|
32
|
+
agentId,
|
|
33
|
+
...rest,
|
|
34
|
+
});
|
|
35
|
+
this.agent = agent;
|
|
36
|
+
this.resourceId = resourceId;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
protected run(input: RunAgentInput): Observable<BaseEvent> {
|
|
40
|
+
return new Observable<BaseEvent>(subscriber => {
|
|
41
|
+
const convertedMessages = convertMessagesToMastraMessages(input.messages);
|
|
42
|
+
|
|
43
|
+
subscriber.next({
|
|
44
|
+
type: EventType.RUN_STARTED,
|
|
45
|
+
threadId: input.threadId,
|
|
46
|
+
runId: input.runId,
|
|
47
|
+
} as RunStartedEvent);
|
|
48
|
+
|
|
49
|
+
this.agent
|
|
50
|
+
.stream({
|
|
51
|
+
threadId: input.threadId,
|
|
52
|
+
resourceId: this.resourceId ?? '',
|
|
53
|
+
runId: input.runId,
|
|
54
|
+
messages: convertedMessages,
|
|
55
|
+
clientTools: input.tools.reduce(
|
|
56
|
+
(acc, tool) => {
|
|
57
|
+
acc[tool.name as string] = {
|
|
58
|
+
id: tool.name,
|
|
59
|
+
description: tool.description,
|
|
60
|
+
inputSchema: tool.parameters,
|
|
61
|
+
};
|
|
62
|
+
return acc;
|
|
63
|
+
},
|
|
64
|
+
{} as Record<string, any>,
|
|
65
|
+
),
|
|
66
|
+
})
|
|
67
|
+
.then(response => {
|
|
68
|
+
let currentMessageId: string | undefined = undefined;
|
|
69
|
+
return response.processDataStream({
|
|
70
|
+
onTextPart: text => {
|
|
71
|
+
if (currentMessageId === undefined) {
|
|
72
|
+
currentMessageId = generateUUID();
|
|
73
|
+
|
|
74
|
+
const message: TextMessageStartEvent = {
|
|
75
|
+
type: EventType.TEXT_MESSAGE_START,
|
|
76
|
+
messageId: currentMessageId,
|
|
77
|
+
role: 'assistant',
|
|
78
|
+
};
|
|
79
|
+
subscriber.next(message);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
const message: TextMessageContentEvent = {
|
|
83
|
+
type: EventType.TEXT_MESSAGE_CONTENT,
|
|
84
|
+
messageId: currentMessageId,
|
|
85
|
+
delta: text,
|
|
86
|
+
};
|
|
87
|
+
subscriber.next(message);
|
|
88
|
+
},
|
|
89
|
+
onFinishMessagePart: message => {
|
|
90
|
+
console.log('onFinishMessagePart', message);
|
|
91
|
+
if (currentMessageId !== undefined) {
|
|
92
|
+
const message: TextMessageEndEvent = {
|
|
93
|
+
type: EventType.TEXT_MESSAGE_END,
|
|
94
|
+
messageId: currentMessageId,
|
|
95
|
+
};
|
|
96
|
+
subscriber.next(message);
|
|
97
|
+
}
|
|
98
|
+
// Emit run finished event
|
|
99
|
+
subscriber.next({
|
|
100
|
+
type: EventType.RUN_FINISHED,
|
|
101
|
+
threadId: input.threadId,
|
|
102
|
+
runId: input.runId,
|
|
103
|
+
} as RunFinishedEvent);
|
|
104
|
+
|
|
105
|
+
// Complete the observable
|
|
106
|
+
subscriber.complete();
|
|
107
|
+
},
|
|
108
|
+
onToolCallPart(streamPart) {
|
|
109
|
+
const parentMessageId = currentMessageId || generateUUID();
|
|
110
|
+
subscriber.next({
|
|
111
|
+
type: EventType.TOOL_CALL_START,
|
|
112
|
+
toolCallId: streamPart.toolCallId,
|
|
113
|
+
toolCallName: streamPart.toolName,
|
|
114
|
+
parentMessageId,
|
|
115
|
+
} as ToolCallStartEvent);
|
|
116
|
+
|
|
117
|
+
subscriber.next({
|
|
118
|
+
type: EventType.TOOL_CALL_ARGS,
|
|
119
|
+
toolCallId: streamPart.toolCallId,
|
|
120
|
+
delta: JSON.stringify(streamPart.args),
|
|
121
|
+
parentMessageId,
|
|
122
|
+
} as ToolCallArgsEvent);
|
|
123
|
+
|
|
124
|
+
subscriber.next({
|
|
125
|
+
type: EventType.TOOL_CALL_END,
|
|
126
|
+
toolCallId: streamPart.toolCallId,
|
|
127
|
+
parentMessageId,
|
|
128
|
+
} as ToolCallEndEvent);
|
|
129
|
+
},
|
|
130
|
+
});
|
|
131
|
+
})
|
|
132
|
+
.catch(error => {
|
|
133
|
+
console.log('error', error);
|
|
134
|
+
// Handle error
|
|
135
|
+
subscriber.error(error);
|
|
136
|
+
});
|
|
137
|
+
|
|
138
|
+
return () => {};
|
|
139
|
+
});
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
/**
|
|
144
|
+
* Generates a UUID v4 that works in both browser and Node.js environments
|
|
145
|
+
*/
|
|
146
|
+
export function generateUUID(): string {
|
|
147
|
+
// Use crypto.randomUUID() if available (Node.js environment or modern browsers)
|
|
148
|
+
if (typeof crypto !== 'undefined') {
|
|
149
|
+
// Browser crypto API or Node.js crypto global
|
|
150
|
+
if (typeof crypto.randomUUID === 'function') {
|
|
151
|
+
return crypto.randomUUID();
|
|
152
|
+
}
|
|
153
|
+
// Fallback for older browsers
|
|
154
|
+
if (typeof crypto.getRandomValues === 'function') {
|
|
155
|
+
const buffer = new Uint8Array(16);
|
|
156
|
+
crypto.getRandomValues(buffer);
|
|
157
|
+
// Set version (4) and variant (8, 9, A, or B)
|
|
158
|
+
buffer[6] = (buffer[6]! & 0x0f) | 0x40; // version 4
|
|
159
|
+
buffer[8] = (buffer[8]! & 0x3f) | 0x80; // variant
|
|
160
|
+
|
|
161
|
+
// Convert to hex string in UUID format
|
|
162
|
+
let hex = '';
|
|
163
|
+
for (let i = 0; i < 16; i++) {
|
|
164
|
+
hex += buffer[i]!.toString(16).padStart(2, '0');
|
|
165
|
+
// Add hyphens at standard positions
|
|
166
|
+
if (i === 3 || i === 5 || i === 7 || i === 9) hex += '-';
|
|
167
|
+
}
|
|
168
|
+
return hex;
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
// Last resort fallback (less secure but works everywhere)
|
|
173
|
+
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, c => {
|
|
174
|
+
const r = (Math.random() * 16) | 0;
|
|
175
|
+
const v = c === 'x' ? r : (r & 0x3) | 0x8;
|
|
176
|
+
return v.toString(16);
|
|
177
|
+
});
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
export function convertMessagesToMastraMessages(messages: Message[]): CoreMessage[] {
|
|
181
|
+
const result: CoreMessage[] = [];
|
|
182
|
+
|
|
183
|
+
for (const message of messages) {
|
|
184
|
+
if (message.role === 'assistant') {
|
|
185
|
+
const parts: any[] = message.content ? [{ type: 'text', text: message.content }] : [];
|
|
186
|
+
for (const toolCall of message.toolCalls ?? []) {
|
|
187
|
+
parts.push({
|
|
188
|
+
type: 'tool-call',
|
|
189
|
+
toolCallId: toolCall.id,
|
|
190
|
+
toolName: toolCall.function.name,
|
|
191
|
+
args: JSON.parse(toolCall.function.arguments),
|
|
192
|
+
});
|
|
193
|
+
}
|
|
194
|
+
result.push({
|
|
195
|
+
role: 'assistant',
|
|
196
|
+
content: parts,
|
|
197
|
+
});
|
|
198
|
+
} else if (message.role === 'user') {
|
|
199
|
+
result.push({
|
|
200
|
+
role: 'user',
|
|
201
|
+
content: message.content || '',
|
|
202
|
+
});
|
|
203
|
+
} else if (message.role === 'tool') {
|
|
204
|
+
result.push({
|
|
205
|
+
role: 'tool',
|
|
206
|
+
content: [
|
|
207
|
+
{
|
|
208
|
+
type: 'tool-result',
|
|
209
|
+
toolCallId: message.toolCallId,
|
|
210
|
+
toolName: 'unknown',
|
|
211
|
+
result: message.content,
|
|
212
|
+
},
|
|
213
|
+
],
|
|
214
|
+
});
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
return result;
|
|
219
|
+
}
|
package/src/client.ts
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import type { AbstractAgent } from '@ag-ui/client';
|
|
2
|
+
import { AGUIAdapter } from './adapters/agui';
|
|
1
3
|
import { Agent, MemoryThread, Tool, Workflow, Vector, BaseResource, Network, VNextWorkflow } from './resources';
|
|
2
4
|
import type {
|
|
3
5
|
ClientOptions,
|
|
@@ -32,6 +34,25 @@ export class MastraClient extends BaseResource {
|
|
|
32
34
|
return this.request('/api/agents');
|
|
33
35
|
}
|
|
34
36
|
|
|
37
|
+
public async getAGUI({ resourceId }: { resourceId: string }): Promise<Record<string, AbstractAgent>> {
|
|
38
|
+
const agents = await this.getAgents();
|
|
39
|
+
|
|
40
|
+
return Object.entries(agents).reduce(
|
|
41
|
+
(acc, [agentId]) => {
|
|
42
|
+
const agent = this.getAgent(agentId);
|
|
43
|
+
|
|
44
|
+
acc[agentId] = new AGUIAdapter({
|
|
45
|
+
agentId,
|
|
46
|
+
agent,
|
|
47
|
+
resourceId,
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
return acc;
|
|
51
|
+
},
|
|
52
|
+
{} as Record<string, AbstractAgent>,
|
|
53
|
+
);
|
|
54
|
+
}
|
|
55
|
+
|
|
35
56
|
/**
|
|
36
57
|
* Gets an agent instance by ID
|
|
37
58
|
* @param agentId - ID of the agent to retrieve
|