agentxjs 1.9.10-dev → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +257 -0
- package/dist/index.d.ts +223 -96
- package/dist/index.js +559 -289
- package/dist/index.js.map +1 -1
- package/package.json +12 -4
- package/src/LocalClient.ts +89 -0
- package/src/RemoteClient.ts +27 -135
- package/src/index.ts +117 -38
- package/src/namespaces/agents.ts +121 -0
- package/src/namespaces/containers.ts +68 -0
- package/src/namespaces/images.ts +180 -0
- package/src/namespaces/presentations.ts +22 -0
- package/src/namespaces/sessions.ts +60 -0
- package/src/presentation/Presentation.ts +14 -10
- package/src/presentation/index.ts +2 -0
- package/src/presentation/reducer.ts +272 -103
- package/src/presentation/types.ts +10 -0
- package/src/types.ts +200 -61
package/dist/index.js
CHANGED
|
@@ -1,174 +1,281 @@
|
|
|
1
1
|
// src/RemoteClient.ts
|
|
2
2
|
import { EventBusImpl } from "@agentxjs/core/event";
|
|
3
3
|
import { RpcClient } from "@agentxjs/core/network";
|
|
4
|
+
import { createLogger } from "commonxjs/logger";
|
|
4
5
|
|
|
5
|
-
//
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
if (this.isDebugEnabled()) {
|
|
26
|
-
this.log("DEBUG", message, context);
|
|
27
|
-
}
|
|
28
|
-
}
|
|
29
|
-
info(message, context) {
|
|
30
|
-
if (this.isInfoEnabled()) {
|
|
31
|
-
this.log("INFO", message, context);
|
|
6
|
+
// src/namespaces/containers.ts
|
|
7
|
+
function createLocalContainers(platform) {
|
|
8
|
+
return {
|
|
9
|
+
async create(containerId) {
|
|
10
|
+
const { getOrCreateContainer } = await import("@agentxjs/core/container");
|
|
11
|
+
const { containerRepository, imageRepository, sessionRepository } = platform;
|
|
12
|
+
const container = await getOrCreateContainer(containerId, {
|
|
13
|
+
containerRepository,
|
|
14
|
+
imageRepository,
|
|
15
|
+
sessionRepository
|
|
16
|
+
});
|
|
17
|
+
return { containerId: container.containerId, requestId: "" };
|
|
18
|
+
},
|
|
19
|
+
async get(containerId) {
|
|
20
|
+
const exists = await platform.containerRepository.containerExists(containerId);
|
|
21
|
+
return { containerId, exists, requestId: "" };
|
|
22
|
+
},
|
|
23
|
+
async list() {
|
|
24
|
+
const containers = await platform.containerRepository.findAllContainers();
|
|
25
|
+
return { containerIds: containers.map((c) => c.containerId), requestId: "" };
|
|
32
26
|
}
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
function createRemoteContainers(rpcClient) {
|
|
30
|
+
return {
|
|
31
|
+
async create(containerId) {
|
|
32
|
+
const result = await rpcClient.call("container.create", {
|
|
33
|
+
containerId
|
|
34
|
+
});
|
|
35
|
+
return { ...result, requestId: "" };
|
|
36
|
+
},
|
|
37
|
+
async get(containerId) {
|
|
38
|
+
const result = await rpcClient.call("container.get", {
|
|
39
|
+
containerId
|
|
40
|
+
});
|
|
41
|
+
return { ...result, requestId: "" };
|
|
42
|
+
},
|
|
43
|
+
async list() {
|
|
44
|
+
const result = await rpcClient.call("container.list", {});
|
|
45
|
+
return { ...result, requestId: "" };
|
|
37
46
|
}
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// src/namespaces/images.ts
|
|
51
|
+
function createLocalImages(platform) {
|
|
52
|
+
return {
|
|
53
|
+
async create(params) {
|
|
54
|
+
const { imageRepository, sessionRepository } = platform;
|
|
55
|
+
const { createImage } = await import("@agentxjs/core/image");
|
|
56
|
+
const image = await createImage(
|
|
57
|
+
{
|
|
58
|
+
containerId: params.containerId,
|
|
59
|
+
name: params.name,
|
|
60
|
+
description: params.description,
|
|
61
|
+
systemPrompt: params.systemPrompt,
|
|
62
|
+
mcpServers: params.mcpServers,
|
|
63
|
+
customData: params.customData
|
|
64
|
+
},
|
|
65
|
+
{ imageRepository, sessionRepository }
|
|
66
|
+
);
|
|
67
|
+
return {
|
|
68
|
+
record: image.toRecord(),
|
|
69
|
+
__subscriptions: [image.sessionId],
|
|
70
|
+
requestId: ""
|
|
71
|
+
};
|
|
72
|
+
},
|
|
73
|
+
async get(imageId) {
|
|
74
|
+
const record = await platform.imageRepository.findImageById(imageId);
|
|
75
|
+
return {
|
|
76
|
+
record,
|
|
77
|
+
__subscriptions: record?.sessionId ? [record.sessionId] : void 0,
|
|
78
|
+
requestId: ""
|
|
79
|
+
};
|
|
80
|
+
},
|
|
81
|
+
async list(containerId) {
|
|
82
|
+
const records = containerId ? await platform.imageRepository.findImagesByContainerId(containerId) : await platform.imageRepository.findAllImages();
|
|
83
|
+
return {
|
|
84
|
+
records,
|
|
85
|
+
__subscriptions: records.map((r) => r.sessionId),
|
|
86
|
+
requestId: ""
|
|
87
|
+
};
|
|
88
|
+
},
|
|
89
|
+
async update(imageId, updates) {
|
|
90
|
+
const { loadImage } = await import("@agentxjs/core/image");
|
|
91
|
+
const { imageRepository, sessionRepository } = platform;
|
|
92
|
+
const image = await loadImage(imageId, { imageRepository, sessionRepository });
|
|
93
|
+
if (!image) {
|
|
94
|
+
throw new Error(`Image not found: ${imageId}`);
|
|
45
95
|
}
|
|
96
|
+
const updated = await image.update(updates);
|
|
97
|
+
return { record: updated.toRecord(), requestId: "" };
|
|
98
|
+
},
|
|
99
|
+
async delete(imageId) {
|
|
100
|
+
const { loadImage } = await import("@agentxjs/core/image");
|
|
101
|
+
const { imageRepository, sessionRepository } = platform;
|
|
102
|
+
const image = await loadImage(imageId, { imageRepository, sessionRepository });
|
|
103
|
+
if (image) {
|
|
104
|
+
await image.delete();
|
|
105
|
+
}
|
|
106
|
+
return { requestId: "" };
|
|
46
107
|
}
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
consoleMethod(logLine);
|
|
108
|
+
};
|
|
109
|
+
}
|
|
110
|
+
function createRemoteImages(rpcClient, subscribeFn) {
|
|
111
|
+
return {
|
|
112
|
+
async create(params) {
|
|
113
|
+
const result = await rpcClient.call("image.create", params);
|
|
114
|
+
if (result.__subscriptions) {
|
|
115
|
+
for (const sessionId of result.__subscriptions) {
|
|
116
|
+
subscribeFn(sessionId);
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
return { ...result, requestId: "" };
|
|
120
|
+
},
|
|
121
|
+
async get(imageId) {
|
|
122
|
+
const result = await rpcClient.call("image.get", { imageId });
|
|
123
|
+
if (result.__subscriptions) {
|
|
124
|
+
for (const sessionId of result.__subscriptions) {
|
|
125
|
+
subscribeFn(sessionId);
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
return { ...result, requestId: "" };
|
|
129
|
+
},
|
|
130
|
+
async list(containerId) {
|
|
131
|
+
const result = await rpcClient.call("image.list", { containerId });
|
|
132
|
+
if (result.__subscriptions) {
|
|
133
|
+
for (const sessionId of result.__subscriptions) {
|
|
134
|
+
subscribeFn(sessionId);
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
return { ...result, requestId: "" };
|
|
138
|
+
},
|
|
139
|
+
async update(imageId, updates) {
|
|
140
|
+
const result = await rpcClient.call("image.update", {
|
|
141
|
+
imageId,
|
|
142
|
+
updates
|
|
143
|
+
});
|
|
144
|
+
return { ...result, requestId: "" };
|
|
145
|
+
},
|
|
146
|
+
async delete(imageId) {
|
|
147
|
+
const result = await rpcClient.call("image.delete", { imageId });
|
|
148
|
+
return { ...result, requestId: "" };
|
|
89
149
|
}
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
150
|
+
};
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
// src/namespaces/agents.ts
|
|
154
|
+
function createLocalAgents(runtime) {
|
|
155
|
+
return {
|
|
156
|
+
async create(params) {
|
|
157
|
+
const existingAgent = runtime.getAgents().find((a) => a.imageId === params.imageId && a.lifecycle === "running");
|
|
158
|
+
if (existingAgent) {
|
|
159
|
+
return {
|
|
160
|
+
agentId: existingAgent.agentId,
|
|
161
|
+
imageId: existingAgent.imageId,
|
|
162
|
+
containerId: existingAgent.containerId,
|
|
163
|
+
sessionId: existingAgent.sessionId,
|
|
164
|
+
requestId: ""
|
|
165
|
+
};
|
|
166
|
+
}
|
|
167
|
+
const agent = await runtime.createAgent({
|
|
168
|
+
imageId: params.imageId,
|
|
169
|
+
agentId: params.agentId
|
|
170
|
+
});
|
|
171
|
+
return {
|
|
172
|
+
agentId: agent.agentId,
|
|
173
|
+
imageId: agent.imageId,
|
|
174
|
+
containerId: agent.containerId,
|
|
175
|
+
sessionId: agent.sessionId,
|
|
176
|
+
requestId: ""
|
|
177
|
+
};
|
|
178
|
+
},
|
|
179
|
+
async get(agentId) {
|
|
180
|
+
const agent = runtime.getAgent(agentId);
|
|
181
|
+
return {
|
|
182
|
+
agent: agent ? {
|
|
183
|
+
agentId: agent.agentId,
|
|
184
|
+
imageId: agent.imageId,
|
|
185
|
+
containerId: agent.containerId,
|
|
186
|
+
sessionId: agent.sessionId,
|
|
187
|
+
lifecycle: agent.lifecycle
|
|
188
|
+
} : null,
|
|
189
|
+
exists: !!agent,
|
|
190
|
+
requestId: ""
|
|
191
|
+
};
|
|
192
|
+
},
|
|
193
|
+
async list(containerId) {
|
|
194
|
+
const agents = containerId ? runtime.getAgentsByContainer(containerId) : runtime.getAgents();
|
|
195
|
+
return {
|
|
196
|
+
agents: agents.map((a) => ({
|
|
197
|
+
agentId: a.agentId,
|
|
198
|
+
imageId: a.imageId,
|
|
199
|
+
containerId: a.containerId,
|
|
200
|
+
sessionId: a.sessionId,
|
|
201
|
+
lifecycle: a.lifecycle
|
|
202
|
+
})),
|
|
203
|
+
requestId: ""
|
|
204
|
+
};
|
|
205
|
+
},
|
|
206
|
+
async destroy(agentId) {
|
|
207
|
+
const agent = runtime.getAgent(agentId);
|
|
208
|
+
if (agent) {
|
|
209
|
+
await runtime.destroyAgent(agentId);
|
|
210
|
+
}
|
|
211
|
+
return { requestId: "" };
|
|
103
212
|
}
|
|
104
|
-
}
|
|
105
|
-
isNodeEnvironment() {
|
|
106
|
-
return typeof process !== "undefined" && process.versions?.node !== void 0;
|
|
107
|
-
}
|
|
108
|
-
};
|
|
109
|
-
var externalFactory = null;
|
|
110
|
-
var factoryVersion = 0;
|
|
111
|
-
var LoggerFactoryImpl = class {
|
|
112
|
-
static loggers = /* @__PURE__ */ new Map();
|
|
113
|
-
static config = {
|
|
114
|
-
defaultLevel: "info"
|
|
115
213
|
};
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
214
|
+
}
|
|
215
|
+
function createRemoteAgents(rpcClient) {
|
|
216
|
+
return {
|
|
217
|
+
async create(params) {
|
|
218
|
+
const result = await rpcClient.call("image.run", {
|
|
219
|
+
imageId: params.imageId,
|
|
220
|
+
agentId: params.agentId
|
|
221
|
+
});
|
|
222
|
+
return { ...result, requestId: "" };
|
|
223
|
+
},
|
|
224
|
+
async get(agentId) {
|
|
225
|
+
const result = await rpcClient.call("agent.get", { agentId });
|
|
226
|
+
return { ...result, requestId: "" };
|
|
227
|
+
},
|
|
228
|
+
async list(containerId) {
|
|
229
|
+
const result = await rpcClient.call("agent.list", { containerId });
|
|
230
|
+
return { ...result, requestId: "" };
|
|
231
|
+
},
|
|
232
|
+
async destroy(agentId) {
|
|
233
|
+
const result = await rpcClient.call("agent.destroy", { agentId });
|
|
234
|
+
return { ...result, requestId: "" };
|
|
120
235
|
}
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
realLogger = this.createLogger(name);
|
|
140
|
-
loggerVersion = factoryVersion;
|
|
141
|
-
}
|
|
142
|
-
return realLogger;
|
|
143
|
-
};
|
|
144
|
-
return {
|
|
145
|
-
name,
|
|
146
|
-
level: this.config.defaultLevel || "info",
|
|
147
|
-
debug: (message, context) => getRealLogger().debug(message, context),
|
|
148
|
-
info: (message, context) => getRealLogger().info(message, context),
|
|
149
|
-
warn: (message, context) => getRealLogger().warn(message, context),
|
|
150
|
-
error: (message, context) => getRealLogger().error(message, context),
|
|
151
|
-
isDebugEnabled: () => getRealLogger().isDebugEnabled(),
|
|
152
|
-
isInfoEnabled: () => getRealLogger().isInfoEnabled(),
|
|
153
|
-
isWarnEnabled: () => getRealLogger().isWarnEnabled(),
|
|
154
|
-
isErrorEnabled: () => getRealLogger().isErrorEnabled()
|
|
155
|
-
};
|
|
156
|
-
}
|
|
157
|
-
static createLogger(name) {
|
|
158
|
-
if (externalFactory) {
|
|
159
|
-
return externalFactory.getLogger(name);
|
|
236
|
+
};
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
// src/namespaces/sessions.ts
|
|
240
|
+
function createLocalSessions(runtime) {
|
|
241
|
+
return {
|
|
242
|
+
async send(agentId, content) {
|
|
243
|
+
await runtime.receive(agentId, content);
|
|
244
|
+
return { agentId, requestId: "" };
|
|
245
|
+
},
|
|
246
|
+
async interrupt(agentId) {
|
|
247
|
+
runtime.interrupt(agentId);
|
|
248
|
+
return { requestId: "" };
|
|
249
|
+
},
|
|
250
|
+
async getMessages(agentId) {
|
|
251
|
+
const agent = runtime.getAgent(agentId);
|
|
252
|
+
if (!agent) return [];
|
|
253
|
+
return runtime.platform.sessionRepository.getMessages(agent.sessionId);
|
|
160
254
|
}
|
|
161
|
-
|
|
162
|
-
|
|
255
|
+
};
|
|
256
|
+
}
|
|
257
|
+
function createRemoteSessions(rpcClient) {
|
|
258
|
+
return {
|
|
259
|
+
async send(agentId, content) {
|
|
260
|
+
const result = await rpcClient.call("message.send", {
|
|
261
|
+
agentId,
|
|
262
|
+
content
|
|
263
|
+
});
|
|
264
|
+
return { ...result, requestId: "" };
|
|
265
|
+
},
|
|
266
|
+
async interrupt(agentId) {
|
|
267
|
+
const result = await rpcClient.call("agent.interrupt", { agentId });
|
|
268
|
+
return { ...result, requestId: "" };
|
|
269
|
+
},
|
|
270
|
+
async getMessages(agentId) {
|
|
271
|
+
const agentRes = await rpcClient.call("agent.get", { agentId });
|
|
272
|
+
if (!agentRes.agent) return [];
|
|
273
|
+
const msgRes = await rpcClient.call("image.messages", {
|
|
274
|
+
imageId: agentRes.agent.imageId
|
|
275
|
+
});
|
|
276
|
+
return msgRes.messages ?? [];
|
|
163
277
|
}
|
|
164
|
-
|
|
165
|
-
level: this.config.defaultLevel,
|
|
166
|
-
...this.config.consoleOptions
|
|
167
|
-
});
|
|
168
|
-
}
|
|
169
|
-
};
|
|
170
|
-
function createLogger(name) {
|
|
171
|
-
return LoggerFactoryImpl.getLogger(name);
|
|
278
|
+
};
|
|
172
279
|
}
|
|
173
280
|
|
|
174
281
|
// src/presentation/types.ts
|
|
@@ -181,18 +288,22 @@ var initialPresentationState = {
|
|
|
181
288
|
// src/presentation/reducer.ts
|
|
182
289
|
function presentationReducer(state, event) {
|
|
183
290
|
switch (event.type) {
|
|
291
|
+
// Stream layer — real-time display
|
|
184
292
|
case "message_start":
|
|
185
293
|
return handleMessageStart(state, event.data);
|
|
186
294
|
case "text_delta":
|
|
187
295
|
return handleTextDelta(state, event.data);
|
|
188
296
|
case "tool_use_start":
|
|
189
297
|
return handleToolUseStart(state, event.data);
|
|
190
|
-
case "
|
|
191
|
-
return
|
|
192
|
-
case "
|
|
193
|
-
return
|
|
298
|
+
case "tool_use_stop":
|
|
299
|
+
return handleToolUseStop(state, event.data);
|
|
300
|
+
case "message_delta":
|
|
301
|
+
return handleMessageDelta(state, event.data);
|
|
194
302
|
case "message_stop":
|
|
195
303
|
return handleMessageStop(state, event.data);
|
|
304
|
+
// Message layer — tool results from Engine
|
|
305
|
+
case "tool_result_message":
|
|
306
|
+
return handleToolResultMessage(state, event.data);
|
|
196
307
|
case "error":
|
|
197
308
|
return handleError(state, event.data);
|
|
198
309
|
default:
|
|
@@ -200,6 +311,10 @@ function presentationReducer(state, event) {
|
|
|
200
311
|
}
|
|
201
312
|
}
|
|
202
313
|
function handleMessageStart(state, _data) {
|
|
314
|
+
let conversations = state.conversations;
|
|
315
|
+
if (state.streaming && state.streaming.blocks.length > 0) {
|
|
316
|
+
conversations = [...conversations, { ...state.streaming, isStreaming: false }];
|
|
317
|
+
}
|
|
203
318
|
const streaming = {
|
|
204
319
|
role: "assistant",
|
|
205
320
|
blocks: [],
|
|
@@ -207,6 +322,7 @@ function handleMessageStart(state, _data) {
|
|
|
207
322
|
};
|
|
208
323
|
return {
|
|
209
324
|
...state,
|
|
325
|
+
conversations,
|
|
210
326
|
streaming,
|
|
211
327
|
status: "thinking"
|
|
212
328
|
};
|
|
@@ -243,7 +359,7 @@ function handleToolUseStart(state, data) {
|
|
|
243
359
|
}
|
|
244
360
|
const toolBlock = {
|
|
245
361
|
type: "tool",
|
|
246
|
-
toolUseId: data.
|
|
362
|
+
toolUseId: data.toolCallId,
|
|
247
363
|
toolName: data.toolName,
|
|
248
364
|
toolInput: {},
|
|
249
365
|
status: "pending"
|
|
@@ -257,46 +373,16 @@ function handleToolUseStart(state, data) {
|
|
|
257
373
|
status: "executing"
|
|
258
374
|
};
|
|
259
375
|
}
|
|
260
|
-
function
|
|
261
|
-
if (!state.streaming) {
|
|
262
|
-
return state;
|
|
263
|
-
}
|
|
264
|
-
const blocks = [...state.streaming.blocks];
|
|
265
|
-
const lastBlock = blocks[blocks.length - 1];
|
|
266
|
-
if (lastBlock && lastBlock.type === "tool") {
|
|
267
|
-
const currentInput = lastBlock._rawInput || "";
|
|
268
|
-
const newInput = currentInput + data.delta;
|
|
269
|
-
let toolInput = lastBlock.toolInput;
|
|
270
|
-
try {
|
|
271
|
-
toolInput = JSON.parse(newInput);
|
|
272
|
-
} catch {
|
|
273
|
-
}
|
|
274
|
-
blocks[blocks.length - 1] = {
|
|
275
|
-
...lastBlock,
|
|
276
|
-
toolInput,
|
|
277
|
-
_rawInput: newInput,
|
|
278
|
-
status: "running"
|
|
279
|
-
};
|
|
280
|
-
return {
|
|
281
|
-
...state,
|
|
282
|
-
streaming: {
|
|
283
|
-
...state.streaming,
|
|
284
|
-
blocks
|
|
285
|
-
}
|
|
286
|
-
};
|
|
287
|
-
}
|
|
288
|
-
return state;
|
|
289
|
-
}
|
|
290
|
-
function handleToolResult(state, data) {
|
|
376
|
+
function handleToolUseStop(state, data) {
|
|
291
377
|
if (!state.streaming) {
|
|
292
378
|
return state;
|
|
293
379
|
}
|
|
294
380
|
const blocks = state.streaming.blocks.map((block) => {
|
|
295
|
-
if (block.type === "tool" && block.toolUseId === data.
|
|
381
|
+
if (block.type === "tool" && block.toolUseId === data.toolCallId) {
|
|
296
382
|
return {
|
|
297
383
|
...block,
|
|
298
|
-
|
|
299
|
-
status:
|
|
384
|
+
toolInput: data.input,
|
|
385
|
+
status: "running"
|
|
300
386
|
};
|
|
301
387
|
}
|
|
302
388
|
return block;
|
|
@@ -306,14 +392,36 @@ function handleToolResult(state, data) {
|
|
|
306
392
|
streaming: {
|
|
307
393
|
...state.streaming,
|
|
308
394
|
blocks
|
|
309
|
-
}
|
|
310
|
-
|
|
395
|
+
}
|
|
396
|
+
};
|
|
397
|
+
}
|
|
398
|
+
function handleMessageDelta(state, data) {
|
|
399
|
+
if (!state.streaming || !data.usage) {
|
|
400
|
+
return state;
|
|
401
|
+
}
|
|
402
|
+
const prev = state.streaming.usage;
|
|
403
|
+
const usage = {
|
|
404
|
+
inputTokens: (prev?.inputTokens ?? 0) + data.usage.inputTokens,
|
|
405
|
+
outputTokens: (prev?.outputTokens ?? 0) + data.usage.outputTokens
|
|
406
|
+
};
|
|
407
|
+
return {
|
|
408
|
+
...state,
|
|
409
|
+
streaming: {
|
|
410
|
+
...state.streaming,
|
|
411
|
+
usage
|
|
412
|
+
}
|
|
311
413
|
};
|
|
312
414
|
}
|
|
313
|
-
function handleMessageStop(state,
|
|
415
|
+
function handleMessageStop(state, data) {
|
|
314
416
|
if (!state.streaming) {
|
|
315
417
|
return state;
|
|
316
418
|
}
|
|
419
|
+
if (data.stopReason === "tool_use") {
|
|
420
|
+
return {
|
|
421
|
+
...state,
|
|
422
|
+
status: "executing"
|
|
423
|
+
};
|
|
424
|
+
}
|
|
317
425
|
const completedConversation = {
|
|
318
426
|
...state.streaming,
|
|
319
427
|
isStreaming: false
|
|
@@ -325,6 +433,30 @@ function handleMessageStop(state, _data) {
|
|
|
325
433
|
status: "idle"
|
|
326
434
|
};
|
|
327
435
|
}
|
|
436
|
+
function handleToolResultMessage(state, data) {
|
|
437
|
+
if (!state.streaming) {
|
|
438
|
+
return state;
|
|
439
|
+
}
|
|
440
|
+
const toolCallId = data.toolCallId;
|
|
441
|
+
const blocks = state.streaming.blocks.map((block) => {
|
|
442
|
+
if (block.type === "tool" && block.toolUseId === toolCallId) {
|
|
443
|
+
return {
|
|
444
|
+
...block,
|
|
445
|
+
toolResult: formatToolResultOutput(data.toolResult.output),
|
|
446
|
+
status: data.toolResult.output.type === "error-text" || data.toolResult.output.type === "error-json" || data.toolResult.output.type === "execution-denied" ? "error" : "completed"
|
|
447
|
+
};
|
|
448
|
+
}
|
|
449
|
+
return block;
|
|
450
|
+
});
|
|
451
|
+
return {
|
|
452
|
+
...state,
|
|
453
|
+
streaming: {
|
|
454
|
+
...state.streaming,
|
|
455
|
+
blocks
|
|
456
|
+
},
|
|
457
|
+
status: "responding"
|
|
458
|
+
};
|
|
459
|
+
}
|
|
328
460
|
function handleError(state, data) {
|
|
329
461
|
return {
|
|
330
462
|
...state,
|
|
@@ -354,6 +486,97 @@ function addUserConversation(state, content) {
|
|
|
354
486
|
function createInitialState() {
|
|
355
487
|
return { ...initialPresentationState };
|
|
356
488
|
}
|
|
489
|
+
function formatToolResultOutput(output) {
|
|
490
|
+
switch (output.type) {
|
|
491
|
+
case "text":
|
|
492
|
+
case "error-text":
|
|
493
|
+
return output.value;
|
|
494
|
+
case "json":
|
|
495
|
+
case "error-json":
|
|
496
|
+
return JSON.stringify(output.value);
|
|
497
|
+
case "execution-denied":
|
|
498
|
+
return output.reason ?? "Execution denied";
|
|
499
|
+
case "content":
|
|
500
|
+
return output.value.filter((p) => p.type === "text").map((p) => p.text).join("");
|
|
501
|
+
}
|
|
502
|
+
}
|
|
503
|
+
function messagesToConversations(messages) {
|
|
504
|
+
const conversations = [];
|
|
505
|
+
let currentAssistant = null;
|
|
506
|
+
function flushAssistant() {
|
|
507
|
+
if (currentAssistant && currentAssistant.blocks.length > 0) {
|
|
508
|
+
conversations.push(currentAssistant);
|
|
509
|
+
}
|
|
510
|
+
currentAssistant = null;
|
|
511
|
+
}
|
|
512
|
+
for (const msg of messages) {
|
|
513
|
+
switch (msg.subtype) {
|
|
514
|
+
case "user": {
|
|
515
|
+
flushAssistant();
|
|
516
|
+
const m = msg;
|
|
517
|
+
const text = typeof m.content === "string" ? m.content : m.content.filter((p) => p.type === "text").map((p) => p.text).join("");
|
|
518
|
+
conversations.push({
|
|
519
|
+
role: "user",
|
|
520
|
+
blocks: [{ type: "text", content: text }]
|
|
521
|
+
});
|
|
522
|
+
break;
|
|
523
|
+
}
|
|
524
|
+
case "assistant": {
|
|
525
|
+
if (!currentAssistant) {
|
|
526
|
+
currentAssistant = { role: "assistant", blocks: [], isStreaming: false };
|
|
527
|
+
}
|
|
528
|
+
const m = msg;
|
|
529
|
+
if (typeof m.content === "string") {
|
|
530
|
+
if (m.content) {
|
|
531
|
+
currentAssistant.blocks.push({ type: "text", content: m.content });
|
|
532
|
+
}
|
|
533
|
+
} else {
|
|
534
|
+
for (const part of m.content) {
|
|
535
|
+
if (part.type === "text") {
|
|
536
|
+
if (part.text) {
|
|
537
|
+
currentAssistant.blocks.push({ type: "text", content: part.text });
|
|
538
|
+
}
|
|
539
|
+
} else if (part.type === "tool-call") {
|
|
540
|
+
const tc = part;
|
|
541
|
+
currentAssistant.blocks.push({
|
|
542
|
+
type: "tool",
|
|
543
|
+
toolUseId: tc.id,
|
|
544
|
+
toolName: tc.name,
|
|
545
|
+
toolInput: tc.input,
|
|
546
|
+
status: "completed"
|
|
547
|
+
});
|
|
548
|
+
}
|
|
549
|
+
}
|
|
550
|
+
}
|
|
551
|
+
break;
|
|
552
|
+
}
|
|
553
|
+
case "tool-result": {
|
|
554
|
+
const m = msg;
|
|
555
|
+
if (currentAssistant) {
|
|
556
|
+
for (const block of currentAssistant.blocks) {
|
|
557
|
+
if (block.type === "tool" && block.toolUseId === m.toolResult.id) {
|
|
558
|
+
block.toolResult = formatToolResultOutput(m.toolResult.output);
|
|
559
|
+
block.status = m.toolResult.output.type === "error-text" || m.toolResult.output.type === "error-json" || m.toolResult.output.type === "execution-denied" ? "error" : "completed";
|
|
560
|
+
break;
|
|
561
|
+
}
|
|
562
|
+
}
|
|
563
|
+
}
|
|
564
|
+
break;
|
|
565
|
+
}
|
|
566
|
+
case "error": {
|
|
567
|
+
flushAssistant();
|
|
568
|
+
const m = msg;
|
|
569
|
+
conversations.push({
|
|
570
|
+
role: "error",
|
|
571
|
+
message: m.content
|
|
572
|
+
});
|
|
573
|
+
break;
|
|
574
|
+
}
|
|
575
|
+
}
|
|
576
|
+
}
|
|
577
|
+
flushAssistant();
|
|
578
|
+
return conversations;
|
|
579
|
+
}
|
|
357
580
|
|
|
358
581
|
// src/presentation/Presentation.ts
|
|
359
582
|
var Presentation = class {
|
|
@@ -363,10 +586,10 @@ var Presentation = class {
|
|
|
363
586
|
updateHandlers = /* @__PURE__ */ new Set();
|
|
364
587
|
errorHandlers = /* @__PURE__ */ new Set();
|
|
365
588
|
eventUnsubscribe = null;
|
|
366
|
-
constructor(agentx, agentId, options) {
|
|
589
|
+
constructor(agentx, agentId, options, initialConversations) {
|
|
367
590
|
this.agentx = agentx;
|
|
368
591
|
this.agentId = agentId;
|
|
369
|
-
this.state = createInitialState();
|
|
592
|
+
this.state = initialConversations?.length ? { ...initialPresentationState, conversations: initialConversations } : createInitialState();
|
|
370
593
|
if (options?.onUpdate) {
|
|
371
594
|
this.updateHandlers.add(options.onUpdate);
|
|
372
595
|
}
|
|
@@ -407,7 +630,7 @@ var Presentation = class {
|
|
|
407
630
|
this.state = addUserConversation(this.state, content);
|
|
408
631
|
this.notify();
|
|
409
632
|
try {
|
|
410
|
-
await this.agentx.
|
|
633
|
+
await this.agentx.sessions.send(this.agentId, content);
|
|
411
634
|
} catch (error) {
|
|
412
635
|
this.notifyError(error instanceof Error ? error : new Error(String(error)));
|
|
413
636
|
}
|
|
@@ -417,7 +640,7 @@ var Presentation = class {
|
|
|
417
640
|
*/
|
|
418
641
|
async interrupt() {
|
|
419
642
|
try {
|
|
420
|
-
await this.agentx.interrupt(this.agentId);
|
|
643
|
+
await this.agentx.sessions.interrupt(this.agentId);
|
|
421
644
|
} catch (error) {
|
|
422
645
|
this.notifyError(error instanceof Error ? error : new Error(String(error)));
|
|
423
646
|
}
|
|
@@ -475,17 +698,34 @@ var Presentation = class {
|
|
|
475
698
|
}
|
|
476
699
|
};
|
|
477
700
|
|
|
701
|
+
// src/namespaces/presentations.ts
|
|
702
|
+
function createPresentations(agentx) {
|
|
703
|
+
return {
|
|
704
|
+
async create(agentId, options) {
|
|
705
|
+
const messages = await agentx.sessions.getMessages(agentId);
|
|
706
|
+
const conversations = messagesToConversations(messages);
|
|
707
|
+
return new Presentation(agentx, agentId, options, conversations);
|
|
708
|
+
}
|
|
709
|
+
};
|
|
710
|
+
}
|
|
711
|
+
|
|
478
712
|
// src/RemoteClient.ts
|
|
479
713
|
var logger = createLogger("agentx/RemoteClient");
|
|
480
714
|
var RemoteClient = class {
|
|
481
715
|
config;
|
|
482
716
|
eventBus;
|
|
483
717
|
rpcClient;
|
|
718
|
+
containers;
|
|
719
|
+
images;
|
|
720
|
+
agents;
|
|
721
|
+
sessions;
|
|
722
|
+
presentations;
|
|
484
723
|
constructor(config) {
|
|
485
724
|
this.config = config;
|
|
486
725
|
this.eventBus = new EventBusImpl();
|
|
487
726
|
this.rpcClient = new RpcClient({
|
|
488
727
|
url: config.serverUrl,
|
|
728
|
+
createWebSocket: config.customPlatform?.webSocketFactory,
|
|
489
729
|
timeout: config.timeout ?? 3e4,
|
|
490
730
|
autoReconnect: config.autoReconnect ?? true,
|
|
491
731
|
headers: config.headers,
|
|
@@ -495,6 +735,11 @@ var RemoteClient = class {
|
|
|
495
735
|
logger.debug("Received stream event", { topic, type: event.type });
|
|
496
736
|
this.eventBus.emit(event);
|
|
497
737
|
});
|
|
738
|
+
this.containers = createRemoteContainers(this.rpcClient);
|
|
739
|
+
this.images = createRemoteImages(this.rpcClient, (sessionId) => this.subscribe(sessionId));
|
|
740
|
+
this.agents = createRemoteAgents(this.rpcClient);
|
|
741
|
+
this.sessions = createRemoteSessions(this.rpcClient);
|
|
742
|
+
this.presentations = createPresentations(this);
|
|
498
743
|
}
|
|
499
744
|
// ==================== Properties ====================
|
|
500
745
|
get connected() {
|
|
@@ -517,109 +762,133 @@ var RemoteClient = class {
|
|
|
517
762
|
this.eventBus.destroy();
|
|
518
763
|
logger.info("RemoteClient disposed");
|
|
519
764
|
}
|
|
520
|
-
// ====================
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
containerId
|
|
524
|
-
});
|
|
525
|
-
return { ...result, requestId: "" };
|
|
526
|
-
}
|
|
527
|
-
async getContainer(containerId) {
|
|
528
|
-
const result = await this.rpcClient.call("container.get", {
|
|
529
|
-
containerId
|
|
530
|
-
});
|
|
531
|
-
return { ...result, requestId: "" };
|
|
532
|
-
}
|
|
533
|
-
async listContainers() {
|
|
534
|
-
const result = await this.rpcClient.call("container.list", {});
|
|
535
|
-
return { ...result, requestId: "" };
|
|
536
|
-
}
|
|
537
|
-
// ==================== Image Operations ====================
|
|
538
|
-
async createImage(params) {
|
|
539
|
-
const result = await this.rpcClient.call("image.create", params);
|
|
540
|
-
if (result.__subscriptions) {
|
|
541
|
-
for (const sessionId of result.__subscriptions) {
|
|
542
|
-
this.subscribe(sessionId);
|
|
543
|
-
}
|
|
544
|
-
}
|
|
545
|
-
return { ...result, requestId: "" };
|
|
546
|
-
}
|
|
547
|
-
async getImage(imageId) {
|
|
548
|
-
const result = await this.rpcClient.call("image.get", { imageId });
|
|
549
|
-
if (result.__subscriptions) {
|
|
550
|
-
for (const sessionId of result.__subscriptions) {
|
|
551
|
-
this.subscribe(sessionId);
|
|
552
|
-
}
|
|
553
|
-
}
|
|
554
|
-
return { ...result, requestId: "" };
|
|
555
|
-
}
|
|
556
|
-
async listImages(containerId) {
|
|
557
|
-
const result = await this.rpcClient.call("image.list", { containerId });
|
|
558
|
-
if (result.__subscriptions) {
|
|
559
|
-
for (const sessionId of result.__subscriptions) {
|
|
560
|
-
this.subscribe(sessionId);
|
|
561
|
-
}
|
|
562
|
-
}
|
|
563
|
-
return { ...result, requestId: "" };
|
|
564
|
-
}
|
|
565
|
-
async deleteImage(imageId) {
|
|
566
|
-
const result = await this.rpcClient.call("image.delete", { imageId });
|
|
567
|
-
return { ...result, requestId: "" };
|
|
568
|
-
}
|
|
569
|
-
// ==================== Agent Operations ====================
|
|
570
|
-
async createAgent(params) {
|
|
571
|
-
const result = await this.rpcClient.call("image.run", {
|
|
572
|
-
imageId: params.imageId,
|
|
573
|
-
agentId: params.agentId
|
|
574
|
-
});
|
|
575
|
-
return { ...result, requestId: "" };
|
|
765
|
+
// ==================== Event Subscription ====================
|
|
766
|
+
on(type, handler) {
|
|
767
|
+
return this.eventBus.on(type, handler);
|
|
576
768
|
}
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
return { ...result, requestId: "" };
|
|
769
|
+
onAny(handler) {
|
|
770
|
+
return this.eventBus.onAny(handler);
|
|
580
771
|
}
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
772
|
+
subscribe(sessionId) {
|
|
773
|
+
this.rpcClient.subscribe(sessionId);
|
|
774
|
+
logger.debug("Subscribed to session", { sessionId });
|
|
584
775
|
}
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
776
|
+
};
|
|
777
|
+
|
|
778
|
+
// src/LocalClient.ts
|
|
779
|
+
import { createLogger as createLogger2 } from "commonxjs/logger";
|
|
780
|
+
var logger2 = createLogger2("agentx/LocalClient");
|
|
781
|
+
var LocalClient = class {
|
|
782
|
+
runtime;
|
|
783
|
+
isDisposed = false;
|
|
784
|
+
containers;
|
|
785
|
+
images;
|
|
786
|
+
agents;
|
|
787
|
+
sessions;
|
|
788
|
+
presentations;
|
|
789
|
+
constructor(runtime) {
|
|
790
|
+
this.runtime = runtime;
|
|
791
|
+
const platform = runtime.platform;
|
|
792
|
+
this.containers = createLocalContainers(platform);
|
|
793
|
+
this.images = createLocalImages(platform);
|
|
794
|
+
this.agents = createLocalAgents(runtime);
|
|
795
|
+
this.sessions = createLocalSessions(runtime);
|
|
796
|
+
this.presentations = createPresentations(this);
|
|
797
|
+
logger2.info("LocalClient initialized");
|
|
588
798
|
}
|
|
589
|
-
// ====================
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
agentId,
|
|
593
|
-
content
|
|
594
|
-
});
|
|
595
|
-
return { ...result, requestId: "" };
|
|
799
|
+
// ==================== Properties ====================
|
|
800
|
+
get connected() {
|
|
801
|
+
return !this.isDisposed;
|
|
596
802
|
}
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
return { ...result, requestId: "" };
|
|
803
|
+
get events() {
|
|
804
|
+
return this.runtime.platform.eventBus;
|
|
600
805
|
}
|
|
601
806
|
// ==================== Event Subscription ====================
|
|
602
807
|
on(type, handler) {
|
|
603
|
-
return this.eventBus.on(type, handler);
|
|
808
|
+
return this.runtime.platform.eventBus.on(type, handler);
|
|
604
809
|
}
|
|
605
810
|
onAny(handler) {
|
|
606
|
-
return this.eventBus.onAny(handler);
|
|
811
|
+
return this.runtime.platform.eventBus.onAny(handler);
|
|
607
812
|
}
|
|
608
|
-
subscribe(
|
|
609
|
-
this.rpcClient.subscribe(sessionId);
|
|
610
|
-
logger.debug("Subscribed to session", { sessionId });
|
|
813
|
+
subscribe(_sessionId) {
|
|
611
814
|
}
|
|
612
|
-
// ====================
|
|
613
|
-
|
|
614
|
-
|
|
815
|
+
// ==================== Lifecycle ====================
|
|
816
|
+
async disconnect() {
|
|
817
|
+
}
|
|
818
|
+
async dispose() {
|
|
819
|
+
if (this.isDisposed) return;
|
|
820
|
+
await this.runtime.shutdown();
|
|
821
|
+
this.isDisposed = true;
|
|
822
|
+
logger2.info("LocalClient disposed");
|
|
615
823
|
}
|
|
616
824
|
};
|
|
617
825
|
|
|
618
826
|
// src/index.ts
|
|
619
827
|
async function createAgentX(config) {
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
828
|
+
if (config.serverUrl) {
|
|
829
|
+
const resolvedConfig = await resolvePlatformForRemote(config);
|
|
830
|
+
const client = new RemoteClient(resolvedConfig);
|
|
831
|
+
await client.connect();
|
|
832
|
+
return client;
|
|
833
|
+
}
|
|
834
|
+
if (config.apiKey || config.createDriver || config.customPlatform) {
|
|
835
|
+
return createLocalClient(config);
|
|
836
|
+
}
|
|
837
|
+
throw new Error(
|
|
838
|
+
"Invalid AgentX config: provide either 'serverUrl' (remote mode) or 'apiKey' (local mode)"
|
|
839
|
+
);
|
|
840
|
+
}
|
|
841
|
+
async function resolvePlatformForRemote(config) {
|
|
842
|
+
if (config.customPlatform?.webSocketFactory) {
|
|
843
|
+
return config;
|
|
844
|
+
}
|
|
845
|
+
if (typeof globalThis !== "undefined" && globalThis.window?.document !== void 0) {
|
|
846
|
+
return config;
|
|
847
|
+
}
|
|
848
|
+
try {
|
|
849
|
+
const { createNodeWebSocket } = await import("@agentxjs/node-platform/network");
|
|
850
|
+
return {
|
|
851
|
+
...config,
|
|
852
|
+
customPlatform: {
|
|
853
|
+
...config.customPlatform,
|
|
854
|
+
webSocketFactory: createNodeWebSocket
|
|
855
|
+
}
|
|
856
|
+
};
|
|
857
|
+
} catch {
|
|
858
|
+
return config;
|
|
859
|
+
}
|
|
860
|
+
}
|
|
861
|
+
async function createLocalClient(config) {
|
|
862
|
+
const { createAgentXRuntime } = await import("@agentxjs/core/runtime");
|
|
863
|
+
let platform;
|
|
864
|
+
if (config.customPlatform) {
|
|
865
|
+
platform = config.customPlatform;
|
|
866
|
+
} else {
|
|
867
|
+
const { createNodePlatform } = await import("@agentxjs/node-platform");
|
|
868
|
+
platform = await createNodePlatform({
|
|
869
|
+
dataPath: config.dataPath ?? ":memory:",
|
|
870
|
+
logLevel: config.logLevel ?? (config.debug ? "debug" : void 0)
|
|
871
|
+
});
|
|
872
|
+
}
|
|
873
|
+
let createDriver = config.createDriver;
|
|
874
|
+
if (!createDriver) {
|
|
875
|
+
const { createMonoDriver } = await import("@agentxjs/mono-driver");
|
|
876
|
+
createDriver = (driverConfig) => {
|
|
877
|
+
const existingOptions = driverConfig.options ?? {};
|
|
878
|
+
return createMonoDriver({
|
|
879
|
+
...driverConfig,
|
|
880
|
+
apiKey: config.apiKey ?? driverConfig.apiKey,
|
|
881
|
+
baseUrl: config.baseUrl ?? driverConfig.baseUrl,
|
|
882
|
+
model: config.model ?? driverConfig.model,
|
|
883
|
+
options: {
|
|
884
|
+
...existingOptions,
|
|
885
|
+
provider: config.provider ?? existingOptions.provider ?? "anthropic"
|
|
886
|
+
}
|
|
887
|
+
});
|
|
888
|
+
};
|
|
889
|
+
}
|
|
890
|
+
const runtime = createAgentXRuntime(platform, createDriver);
|
|
891
|
+
return new LocalClient(runtime);
|
|
623
892
|
}
|
|
624
893
|
export {
|
|
625
894
|
Presentation,
|
|
@@ -627,6 +896,7 @@ export {
|
|
|
627
896
|
createAgentX,
|
|
628
897
|
createInitialState,
|
|
629
898
|
initialPresentationState,
|
|
899
|
+
messagesToConversations,
|
|
630
900
|
presentationReducer
|
|
631
901
|
};
|
|
632
902
|
//# sourceMappingURL=index.js.map
|