agentxjs 1.9.10-dev → 2.0.1

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/dist/index.js CHANGED
@@ -1,174 +1,237 @@
1
- // src/RemoteClient.ts
2
- import { EventBusImpl } from "@agentxjs/core/event";
3
- import { RpcClient } from "@agentxjs/core/network";
1
+ // src/LocalClient.ts
2
+ import { createLogger } from "commonxjs/logger";
4
3
 
5
- // ../../node_modules/commonxjs/dist/logger/index.js
6
- var ConsoleLogger = class _ConsoleLogger {
7
- name;
8
- level;
9
- colors;
10
- timestamps;
11
- static COLORS = {
12
- DEBUG: "\x1B[36m",
13
- INFO: "\x1B[32m",
14
- WARN: "\x1B[33m",
15
- ERROR: "\x1B[31m",
16
- RESET: "\x1B[0m"
17
- };
18
- constructor(name, options = {}) {
19
- this.name = name;
20
- this.level = options.level ?? "info";
21
- this.colors = options.colors ?? this.isNodeEnvironment();
22
- this.timestamps = options.timestamps ?? true;
23
- }
24
- debug(message, context) {
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);
32
- }
33
- }
34
- warn(message, context) {
35
- if (this.isWarnEnabled()) {
36
- this.log("WARN", message, context);
37
- }
38
- }
39
- error(message, context) {
40
- if (this.isErrorEnabled()) {
41
- if (message instanceof Error) {
42
- this.log("ERROR", message.message, { ...context, stack: message.stack });
43
- } else {
44
- this.log("ERROR", message, context);
4
+ // src/namespaces/agents.ts
5
+ function createLocalAgents(runtime) {
6
+ return {
7
+ async create(params) {
8
+ const existingAgent = runtime.getAgents().find((a) => a.imageId === params.imageId && a.lifecycle === "running");
9
+ if (existingAgent) {
10
+ return {
11
+ agentId: existingAgent.agentId,
12
+ imageId: existingAgent.imageId,
13
+ containerId: existingAgent.containerId,
14
+ sessionId: existingAgent.sessionId,
15
+ requestId: ""
16
+ };
45
17
  }
18
+ const agent = await runtime.createAgent({
19
+ imageId: params.imageId,
20
+ agentId: params.agentId
21
+ });
22
+ return {
23
+ agentId: agent.agentId,
24
+ imageId: agent.imageId,
25
+ containerId: agent.containerId,
26
+ sessionId: agent.sessionId,
27
+ requestId: ""
28
+ };
29
+ },
30
+ async get(agentId) {
31
+ const agent = runtime.getAgent(agentId);
32
+ return {
33
+ agent: agent ? {
34
+ agentId: agent.agentId,
35
+ imageId: agent.imageId,
36
+ containerId: agent.containerId,
37
+ sessionId: agent.sessionId,
38
+ lifecycle: agent.lifecycle
39
+ } : null,
40
+ exists: !!agent,
41
+ requestId: ""
42
+ };
43
+ },
44
+ async list(containerId) {
45
+ const agents = containerId ? runtime.getAgentsByContainer(containerId) : runtime.getAgents();
46
+ return {
47
+ agents: agents.map((a) => ({
48
+ agentId: a.agentId,
49
+ imageId: a.imageId,
50
+ containerId: a.containerId,
51
+ sessionId: a.sessionId,
52
+ lifecycle: a.lifecycle
53
+ })),
54
+ requestId: ""
55
+ };
56
+ },
57
+ async destroy(agentId) {
58
+ const agent = runtime.getAgent(agentId);
59
+ if (agent) {
60
+ await runtime.destroyAgent(agentId);
61
+ }
62
+ return { requestId: "" };
46
63
  }
47
- }
48
- isDebugEnabled() {
49
- return this.getLevelValue(this.level) <= this.getLevelValue("debug");
50
- }
51
- isInfoEnabled() {
52
- return this.getLevelValue(this.level) <= this.getLevelValue("info");
53
- }
54
- isWarnEnabled() {
55
- return this.getLevelValue(this.level) <= this.getLevelValue("warn");
56
- }
57
- isErrorEnabled() {
58
- return this.getLevelValue(this.level) <= this.getLevelValue("error");
59
- }
60
- getLevelValue(level) {
61
- const levels = {
62
- debug: 0,
63
- info: 1,
64
- warn: 2,
65
- error: 3,
66
- silent: 4
67
- };
68
- return levels[level];
69
- }
70
- log(level, message, context) {
71
- const parts = [];
72
- if (this.timestamps) {
73
- parts.push((/* @__PURE__ */ new Date()).toISOString());
74
- }
75
- if (this.colors) {
76
- const color = _ConsoleLogger.COLORS[level];
77
- parts.push(`${color}${level.padEnd(5)}${_ConsoleLogger.COLORS.RESET}`);
78
- } else {
79
- parts.push(level.padEnd(5));
80
- }
81
- parts.push(`[${this.name}]`);
82
- parts.push(message);
83
- const logLine = parts.join(" ");
84
- const consoleMethod = this.getConsoleMethod(level);
85
- if (context && Object.keys(context).length > 0) {
86
- consoleMethod(logLine, context);
87
- } else {
88
- consoleMethod(logLine);
64
+ };
65
+ }
66
+ function createRemoteAgents(rpcClient) {
67
+ return {
68
+ async create(params) {
69
+ const result = await rpcClient.call("image.run", {
70
+ imageId: params.imageId,
71
+ agentId: params.agentId
72
+ });
73
+ return { ...result, requestId: "" };
74
+ },
75
+ async get(agentId) {
76
+ const result = await rpcClient.call("agent.get", { agentId });
77
+ return { ...result, requestId: "" };
78
+ },
79
+ async list(containerId) {
80
+ const result = await rpcClient.call("agent.list", { containerId });
81
+ return { ...result, requestId: "" };
82
+ },
83
+ async destroy(agentId) {
84
+ const result = await rpcClient.call("agent.destroy", { agentId });
85
+ return { ...result, requestId: "" };
89
86
  }
90
- }
91
- getConsoleMethod(level) {
92
- switch (level) {
93
- case "DEBUG":
94
- return console.debug.bind(console);
95
- case "INFO":
96
- return console.info.bind(console);
97
- case "WARN":
98
- return console.warn.bind(console);
99
- case "ERROR":
100
- return console.error.bind(console);
101
- default:
102
- return console.log.bind(console);
87
+ };
88
+ }
89
+
90
+ // src/namespaces/containers.ts
91
+ function createLocalContainers(platform) {
92
+ return {
93
+ async create(containerId) {
94
+ const { getOrCreateContainer } = await import("@agentxjs/core/container");
95
+ const { containerRepository, imageRepository, sessionRepository } = platform;
96
+ const container = await getOrCreateContainer(containerId, {
97
+ containerRepository,
98
+ imageRepository,
99
+ sessionRepository
100
+ });
101
+ return { containerId: container.containerId, requestId: "" };
102
+ },
103
+ async get(containerId) {
104
+ const exists = await platform.containerRepository.containerExists(containerId);
105
+ return { containerId, exists, requestId: "" };
106
+ },
107
+ async list() {
108
+ const containers = await platform.containerRepository.findAllContainers();
109
+ return { containerIds: containers.map((c) => c.containerId), requestId: "" };
103
110
  }
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
111
  };
116
- static getLogger(nameOrClass) {
117
- const name = typeof nameOrClass === "string" ? nameOrClass : nameOrClass.name;
118
- if (this.loggers.has(name)) {
119
- return this.loggers.get(name);
112
+ }
113
+ function createRemoteContainers(rpcClient) {
114
+ return {
115
+ async create(containerId) {
116
+ const result = await rpcClient.call("container.create", {
117
+ containerId
118
+ });
119
+ return { ...result, requestId: "" };
120
+ },
121
+ async get(containerId) {
122
+ const result = await rpcClient.call("container.get", {
123
+ containerId
124
+ });
125
+ return { ...result, requestId: "" };
126
+ },
127
+ async list() {
128
+ const result = await rpcClient.call("container.list", {});
129
+ return { ...result, requestId: "" };
120
130
  }
121
- const lazyLogger = this.createLazyLogger(name);
122
- this.loggers.set(name, lazyLogger);
123
- return lazyLogger;
124
- }
125
- static configure(config) {
126
- this.config = { ...this.config, ...config };
127
- }
128
- static reset() {
129
- this.loggers.clear();
130
- this.config = { defaultLevel: "info" };
131
- externalFactory = null;
132
- factoryVersion++;
133
- }
134
- static createLazyLogger(name) {
135
- let realLogger = null;
136
- let loggerVersion = -1;
137
- const getRealLogger = () => {
138
- if (!realLogger || loggerVersion !== factoryVersion) {
139
- realLogger = this.createLogger(name);
140
- loggerVersion = factoryVersion;
131
+ };
132
+ }
133
+
134
+ // src/namespaces/images.ts
135
+ function createLocalImages(platform) {
136
+ return {
137
+ async create(params) {
138
+ const { imageRepository, sessionRepository } = platform;
139
+ const { createImage } = await import("@agentxjs/core/image");
140
+ const image = await createImage(
141
+ {
142
+ containerId: params.containerId,
143
+ name: params.name,
144
+ description: params.description,
145
+ systemPrompt: params.systemPrompt,
146
+ mcpServers: params.mcpServers,
147
+ customData: params.customData
148
+ },
149
+ { imageRepository, sessionRepository }
150
+ );
151
+ return {
152
+ record: image.toRecord(),
153
+ __subscriptions: [image.sessionId],
154
+ requestId: ""
155
+ };
156
+ },
157
+ async get(imageId) {
158
+ const record = await platform.imageRepository.findImageById(imageId);
159
+ return {
160
+ record,
161
+ __subscriptions: record?.sessionId ? [record.sessionId] : void 0,
162
+ requestId: ""
163
+ };
164
+ },
165
+ async list(containerId) {
166
+ const records = containerId ? await platform.imageRepository.findImagesByContainerId(containerId) : await platform.imageRepository.findAllImages();
167
+ return {
168
+ records,
169
+ __subscriptions: records.map((r) => r.sessionId),
170
+ requestId: ""
171
+ };
172
+ },
173
+ async update(imageId, updates) {
174
+ const { loadImage } = await import("@agentxjs/core/image");
175
+ const { imageRepository, sessionRepository } = platform;
176
+ const image = await loadImage(imageId, { imageRepository, sessionRepository });
177
+ if (!image) {
178
+ throw new Error(`Image not found: ${imageId}`);
141
179
  }
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);
180
+ const updated = await image.update(updates);
181
+ return { record: updated.toRecord(), requestId: "" };
182
+ },
183
+ async delete(imageId) {
184
+ const { loadImage } = await import("@agentxjs/core/image");
185
+ const { imageRepository, sessionRepository } = platform;
186
+ const image = await loadImage(imageId, { imageRepository, sessionRepository });
187
+ if (image) {
188
+ await image.delete();
189
+ }
190
+ return { requestId: "" };
160
191
  }
161
- if (this.config.defaultImplementation) {
162
- return this.config.defaultImplementation(name);
192
+ };
193
+ }
194
+ function createRemoteImages(rpcClient, subscribeFn) {
195
+ return {
196
+ async create(params) {
197
+ const result = await rpcClient.call("image.create", params);
198
+ if (result.__subscriptions) {
199
+ for (const sessionId of result.__subscriptions) {
200
+ subscribeFn(sessionId);
201
+ }
202
+ }
203
+ return { ...result, requestId: "" };
204
+ },
205
+ async get(imageId) {
206
+ const result = await rpcClient.call("image.get", { imageId });
207
+ if (result.__subscriptions) {
208
+ for (const sessionId of result.__subscriptions) {
209
+ subscribeFn(sessionId);
210
+ }
211
+ }
212
+ return { ...result, requestId: "" };
213
+ },
214
+ async list(containerId) {
215
+ const result = await rpcClient.call("image.list", { containerId });
216
+ if (result.__subscriptions) {
217
+ for (const sessionId of result.__subscriptions) {
218
+ subscribeFn(sessionId);
219
+ }
220
+ }
221
+ return { ...result, requestId: "" };
222
+ },
223
+ async update(imageId, updates) {
224
+ const result = await rpcClient.call("image.update", {
225
+ imageId,
226
+ updates
227
+ });
228
+ return { ...result, requestId: "" };
229
+ },
230
+ async delete(imageId) {
231
+ const result = await rpcClient.call("image.delete", { imageId });
232
+ return { ...result, requestId: "" };
163
233
  }
164
- return new ConsoleLogger(name, {
165
- level: this.config.defaultLevel,
166
- ...this.config.consoleOptions
167
- });
168
- }
169
- };
170
- function createLogger(name) {
171
- return LoggerFactoryImpl.getLogger(name);
234
+ };
172
235
  }
173
236
 
174
237
  // src/presentation/types.ts
@@ -181,18 +244,22 @@ var initialPresentationState = {
181
244
  // src/presentation/reducer.ts
182
245
  function presentationReducer(state, event) {
183
246
  switch (event.type) {
247
+ // Stream layer — real-time display
184
248
  case "message_start":
185
249
  return handleMessageStart(state, event.data);
186
250
  case "text_delta":
187
251
  return handleTextDelta(state, event.data);
188
252
  case "tool_use_start":
189
253
  return handleToolUseStart(state, event.data);
190
- case "input_json_delta":
191
- return handleInputJsonDelta(state, event.data);
192
- case "tool_result":
193
- return handleToolResult(state, event.data);
254
+ case "tool_use_stop":
255
+ return handleToolUseStop(state, event.data);
256
+ case "message_delta":
257
+ return handleMessageDelta(state, event.data);
194
258
  case "message_stop":
195
259
  return handleMessageStop(state, event.data);
260
+ // Message layer — tool results from Engine
261
+ case "tool_result_message":
262
+ return handleToolResultMessage(state, event.data);
196
263
  case "error":
197
264
  return handleError(state, event.data);
198
265
  default:
@@ -200,6 +267,10 @@ function presentationReducer(state, event) {
200
267
  }
201
268
  }
202
269
  function handleMessageStart(state, _data) {
270
+ let conversations = state.conversations;
271
+ if (state.streaming && state.streaming.blocks.length > 0) {
272
+ conversations = [...conversations, { ...state.streaming, isStreaming: false }];
273
+ }
203
274
  const streaming = {
204
275
  role: "assistant",
205
276
  blocks: [],
@@ -207,6 +278,7 @@ function handleMessageStart(state, _data) {
207
278
  };
208
279
  return {
209
280
  ...state,
281
+ conversations,
210
282
  streaming,
211
283
  status: "thinking"
212
284
  };
@@ -243,7 +315,7 @@ function handleToolUseStart(state, data) {
243
315
  }
244
316
  const toolBlock = {
245
317
  type: "tool",
246
- toolUseId: data.toolUseId,
318
+ toolUseId: data.toolCallId,
247
319
  toolName: data.toolName,
248
320
  toolInput: {},
249
321
  status: "pending"
@@ -257,46 +329,16 @@ function handleToolUseStart(state, data) {
257
329
  status: "executing"
258
330
  };
259
331
  }
260
- function handleInputJsonDelta(state, data) {
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) {
332
+ function handleToolUseStop(state, data) {
291
333
  if (!state.streaming) {
292
334
  return state;
293
335
  }
294
336
  const blocks = state.streaming.blocks.map((block) => {
295
- if (block.type === "tool" && block.toolUseId === data.toolUseId) {
337
+ if (block.type === "tool" && block.toolUseId === data.toolCallId) {
296
338
  return {
297
339
  ...block,
298
- toolResult: data.result,
299
- status: data.isError ? "error" : "completed"
340
+ toolInput: data.input,
341
+ status: "running"
300
342
  };
301
343
  }
302
344
  return block;
@@ -306,14 +348,36 @@ function handleToolResult(state, data) {
306
348
  streaming: {
307
349
  ...state.streaming,
308
350
  blocks
309
- },
310
- status: "responding"
351
+ }
352
+ };
353
+ }
354
+ function handleMessageDelta(state, data) {
355
+ if (!state.streaming || !data.usage) {
356
+ return state;
357
+ }
358
+ const prev = state.streaming.usage;
359
+ const usage = {
360
+ inputTokens: (prev?.inputTokens ?? 0) + data.usage.inputTokens,
361
+ outputTokens: (prev?.outputTokens ?? 0) + data.usage.outputTokens
362
+ };
363
+ return {
364
+ ...state,
365
+ streaming: {
366
+ ...state.streaming,
367
+ usage
368
+ }
311
369
  };
312
370
  }
313
- function handleMessageStop(state, _data) {
371
+ function handleMessageStop(state, data) {
314
372
  if (!state.streaming) {
315
373
  return state;
316
374
  }
375
+ if (data.stopReason === "tool_use") {
376
+ return {
377
+ ...state,
378
+ status: "executing"
379
+ };
380
+ }
317
381
  const completedConversation = {
318
382
  ...state.streaming,
319
383
  isStreaming: false
@@ -325,6 +389,30 @@ function handleMessageStop(state, _data) {
325
389
  status: "idle"
326
390
  };
327
391
  }
392
+ function handleToolResultMessage(state, data) {
393
+ if (!state.streaming) {
394
+ return state;
395
+ }
396
+ const toolCallId = data.toolCallId;
397
+ const blocks = state.streaming.blocks.map((block) => {
398
+ if (block.type === "tool" && block.toolUseId === toolCallId) {
399
+ return {
400
+ ...block,
401
+ toolResult: formatToolResultOutput(data.toolResult.output),
402
+ status: data.toolResult.output.type === "error-text" || data.toolResult.output.type === "error-json" || data.toolResult.output.type === "execution-denied" ? "error" : "completed"
403
+ };
404
+ }
405
+ return block;
406
+ });
407
+ return {
408
+ ...state,
409
+ streaming: {
410
+ ...state.streaming,
411
+ blocks
412
+ },
413
+ status: "responding"
414
+ };
415
+ }
328
416
  function handleError(state, data) {
329
417
  return {
330
418
  ...state,
@@ -354,6 +442,97 @@ function addUserConversation(state, content) {
354
442
  function createInitialState() {
355
443
  return { ...initialPresentationState };
356
444
  }
445
+ function formatToolResultOutput(output) {
446
+ switch (output.type) {
447
+ case "text":
448
+ case "error-text":
449
+ return output.value;
450
+ case "json":
451
+ case "error-json":
452
+ return JSON.stringify(output.value);
453
+ case "execution-denied":
454
+ return output.reason ?? "Execution denied";
455
+ case "content":
456
+ return output.value.filter((p) => p.type === "text").map((p) => p.text).join("");
457
+ }
458
+ }
459
+ function messagesToConversations(messages) {
460
+ const conversations = [];
461
+ let currentAssistant = null;
462
+ function flushAssistant() {
463
+ if (currentAssistant && currentAssistant.blocks.length > 0) {
464
+ conversations.push(currentAssistant);
465
+ }
466
+ currentAssistant = null;
467
+ }
468
+ for (const msg of messages) {
469
+ switch (msg.subtype) {
470
+ case "user": {
471
+ flushAssistant();
472
+ const m = msg;
473
+ const text = typeof m.content === "string" ? m.content : m.content.filter((p) => p.type === "text").map((p) => p.text).join("");
474
+ conversations.push({
475
+ role: "user",
476
+ blocks: [{ type: "text", content: text }]
477
+ });
478
+ break;
479
+ }
480
+ case "assistant": {
481
+ if (!currentAssistant) {
482
+ currentAssistant = { role: "assistant", blocks: [], isStreaming: false };
483
+ }
484
+ const m = msg;
485
+ if (typeof m.content === "string") {
486
+ if (m.content) {
487
+ currentAssistant.blocks.push({ type: "text", content: m.content });
488
+ }
489
+ } else {
490
+ for (const part of m.content) {
491
+ if (part.type === "text") {
492
+ if (part.text) {
493
+ currentAssistant.blocks.push({ type: "text", content: part.text });
494
+ }
495
+ } else if (part.type === "tool-call") {
496
+ const tc = part;
497
+ currentAssistant.blocks.push({
498
+ type: "tool",
499
+ toolUseId: tc.id,
500
+ toolName: tc.name,
501
+ toolInput: tc.input,
502
+ status: "completed"
503
+ });
504
+ }
505
+ }
506
+ }
507
+ break;
508
+ }
509
+ case "tool-result": {
510
+ const m = msg;
511
+ if (currentAssistant) {
512
+ for (const block of currentAssistant.blocks) {
513
+ if (block.type === "tool" && block.toolUseId === m.toolResult.id) {
514
+ block.toolResult = formatToolResultOutput(m.toolResult.output);
515
+ block.status = m.toolResult.output.type === "error-text" || m.toolResult.output.type === "error-json" || m.toolResult.output.type === "execution-denied" ? "error" : "completed";
516
+ break;
517
+ }
518
+ }
519
+ }
520
+ break;
521
+ }
522
+ case "error": {
523
+ flushAssistant();
524
+ const m = msg;
525
+ conversations.push({
526
+ role: "error",
527
+ message: m.content
528
+ });
529
+ break;
530
+ }
531
+ }
532
+ }
533
+ flushAssistant();
534
+ return conversations;
535
+ }
357
536
 
358
537
  // src/presentation/Presentation.ts
359
538
  var Presentation = class {
@@ -363,10 +542,10 @@ var Presentation = class {
363
542
  updateHandlers = /* @__PURE__ */ new Set();
364
543
  errorHandlers = /* @__PURE__ */ new Set();
365
544
  eventUnsubscribe = null;
366
- constructor(agentx, agentId, options) {
545
+ constructor(agentx, agentId, options, initialConversations) {
367
546
  this.agentx = agentx;
368
547
  this.agentId = agentId;
369
- this.state = createInitialState();
548
+ this.state = initialConversations?.length ? { ...initialPresentationState, conversations: initialConversations } : createInitialState();
370
549
  if (options?.onUpdate) {
371
550
  this.updateHandlers.add(options.onUpdate);
372
551
  }
@@ -407,7 +586,7 @@ var Presentation = class {
407
586
  this.state = addUserConversation(this.state, content);
408
587
  this.notify();
409
588
  try {
410
- await this.agentx.sendMessage(this.agentId, content);
589
+ await this.agentx.sessions.send(this.agentId, content);
411
590
  } catch (error) {
412
591
  this.notifyError(error instanceof Error ? error : new Error(String(error)));
413
592
  }
@@ -417,7 +596,7 @@ var Presentation = class {
417
596
  */
418
597
  async interrupt() {
419
598
  try {
420
- await this.agentx.interrupt(this.agentId);
599
+ await this.agentx.sessions.interrupt(this.agentId);
421
600
  } catch (error) {
422
601
  this.notifyError(error instanceof Error ? error : new Error(String(error)));
423
602
  }
@@ -475,26 +654,140 @@ var Presentation = class {
475
654
  }
476
655
  };
477
656
 
657
+ // src/namespaces/presentations.ts
658
+ function createPresentations(agentx) {
659
+ return {
660
+ async create(agentId, options) {
661
+ const messages = await agentx.sessions.getMessages(agentId);
662
+ const conversations = messagesToConversations(messages);
663
+ return new Presentation(agentx, agentId, options, conversations);
664
+ }
665
+ };
666
+ }
667
+
668
+ // src/namespaces/sessions.ts
669
+ function createLocalSessions(runtime) {
670
+ return {
671
+ async send(agentId, content) {
672
+ await runtime.receive(agentId, content);
673
+ return { agentId, requestId: "" };
674
+ },
675
+ async interrupt(agentId) {
676
+ runtime.interrupt(agentId);
677
+ return { requestId: "" };
678
+ },
679
+ async getMessages(agentId) {
680
+ const agent = runtime.getAgent(agentId);
681
+ if (!agent) return [];
682
+ return runtime.platform.sessionRepository.getMessages(agent.sessionId);
683
+ }
684
+ };
685
+ }
686
+ function createRemoteSessions(rpcClient) {
687
+ return {
688
+ async send(agentId, content) {
689
+ const result = await rpcClient.call("message.send", {
690
+ agentId,
691
+ content
692
+ });
693
+ return { ...result, requestId: "" };
694
+ },
695
+ async interrupt(agentId) {
696
+ const result = await rpcClient.call("agent.interrupt", { agentId });
697
+ return { ...result, requestId: "" };
698
+ },
699
+ async getMessages(agentId) {
700
+ const agentRes = await rpcClient.call("agent.get", { agentId });
701
+ if (!agentRes.agent) return [];
702
+ const msgRes = await rpcClient.call("image.messages", {
703
+ imageId: agentRes.agent.imageId
704
+ });
705
+ return msgRes.messages ?? [];
706
+ }
707
+ };
708
+ }
709
+
710
+ // src/LocalClient.ts
711
+ var logger = createLogger("agentx/LocalClient");
712
+ var LocalClient = class {
713
+ runtime;
714
+ isDisposed = false;
715
+ containers;
716
+ images;
717
+ agents;
718
+ sessions;
719
+ presentations;
720
+ constructor(runtime) {
721
+ this.runtime = runtime;
722
+ const platform = runtime.platform;
723
+ this.containers = createLocalContainers(platform);
724
+ this.images = createLocalImages(platform);
725
+ this.agents = createLocalAgents(runtime);
726
+ this.sessions = createLocalSessions(runtime);
727
+ this.presentations = createPresentations(this);
728
+ logger.info("LocalClient initialized");
729
+ }
730
+ // ==================== Properties ====================
731
+ get connected() {
732
+ return !this.isDisposed;
733
+ }
734
+ get events() {
735
+ return this.runtime.platform.eventBus;
736
+ }
737
+ // ==================== Event Subscription ====================
738
+ on(type, handler) {
739
+ return this.runtime.platform.eventBus.on(type, handler);
740
+ }
741
+ onAny(handler) {
742
+ return this.runtime.platform.eventBus.onAny(handler);
743
+ }
744
+ subscribe(_sessionId) {
745
+ }
746
+ // ==================== Lifecycle ====================
747
+ async disconnect() {
748
+ }
749
+ async dispose() {
750
+ if (this.isDisposed) return;
751
+ await this.runtime.shutdown();
752
+ this.isDisposed = true;
753
+ logger.info("LocalClient disposed");
754
+ }
755
+ };
756
+
478
757
  // src/RemoteClient.ts
479
- var logger = createLogger("agentx/RemoteClient");
758
+ import { EventBusImpl } from "@agentxjs/core/event";
759
+ import { RpcClient } from "@agentxjs/core/network";
760
+ import { createLogger as createLogger2 } from "commonxjs/logger";
761
+ var logger2 = createLogger2("agentx/RemoteClient");
480
762
  var RemoteClient = class {
481
763
  config;
482
764
  eventBus;
483
765
  rpcClient;
766
+ containers;
767
+ images;
768
+ agents;
769
+ sessions;
770
+ presentations;
484
771
  constructor(config) {
485
772
  this.config = config;
486
773
  this.eventBus = new EventBusImpl();
487
774
  this.rpcClient = new RpcClient({
488
775
  url: config.serverUrl,
776
+ createWebSocket: config.customPlatform?.webSocketFactory,
489
777
  timeout: config.timeout ?? 3e4,
490
778
  autoReconnect: config.autoReconnect ?? true,
491
779
  headers: config.headers,
492
780
  debug: false
493
781
  });
494
782
  this.rpcClient.onStreamEvent((topic, event) => {
495
- logger.debug("Received stream event", { topic, type: event.type });
783
+ logger2.debug("Received stream event", { topic, type: event.type });
496
784
  this.eventBus.emit(event);
497
785
  });
786
+ this.containers = createRemoteContainers(this.rpcClient);
787
+ this.images = createRemoteImages(this.rpcClient, (sessionId) => this.subscribe(sessionId));
788
+ this.agents = createRemoteAgents(this.rpcClient);
789
+ this.sessions = createRemoteSessions(this.rpcClient);
790
+ this.presentations = createPresentations(this);
498
791
  }
499
792
  // ==================== Properties ====================
500
793
  get connected() {
@@ -506,97 +799,16 @@ var RemoteClient = class {
506
799
  // ==================== Connection ====================
507
800
  async connect() {
508
801
  await this.rpcClient.connect();
509
- logger.info("Connected to server", { url: this.config.serverUrl });
802
+ logger2.info("Connected to server", { url: this.config.serverUrl });
510
803
  }
511
804
  async disconnect() {
512
805
  this.rpcClient.disconnect();
513
- logger.info("Disconnected from server");
806
+ logger2.info("Disconnected from server");
514
807
  }
515
808
  async dispose() {
516
809
  this.rpcClient.dispose();
517
810
  this.eventBus.destroy();
518
- logger.info("RemoteClient disposed");
519
- }
520
- // ==================== Container Operations ====================
521
- async createContainer(containerId) {
522
- const result = await this.rpcClient.call("container.create", {
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: "" };
576
- }
577
- async getAgent(agentId) {
578
- const result = await this.rpcClient.call("agent.get", { agentId });
579
- return { ...result, requestId: "" };
580
- }
581
- async listAgents(containerId) {
582
- const result = await this.rpcClient.call("agent.list", { containerId });
583
- return { ...result, requestId: "" };
584
- }
585
- async destroyAgent(agentId) {
586
- const result = await this.rpcClient.call("agent.destroy", { agentId });
587
- return { ...result, requestId: "" };
588
- }
589
- // ==================== Message Operations ====================
590
- async sendMessage(agentId, content) {
591
- const result = await this.rpcClient.call("message.send", {
592
- agentId,
593
- content
594
- });
595
- return { ...result, requestId: "" };
596
- }
597
- async interrupt(agentId) {
598
- const result = await this.rpcClient.call("agent.interrupt", { agentId });
599
- return { ...result, requestId: "" };
811
+ logger2.info("RemoteClient disposed");
600
812
  }
601
813
  // ==================== Event Subscription ====================
602
814
  on(type, handler) {
@@ -607,19 +819,76 @@ var RemoteClient = class {
607
819
  }
608
820
  subscribe(sessionId) {
609
821
  this.rpcClient.subscribe(sessionId);
610
- logger.debug("Subscribed to session", { sessionId });
611
- }
612
- // ==================== Presentation ====================
613
- presentation(agentId, options) {
614
- return new Presentation(this, agentId, options);
822
+ logger2.debug("Subscribed to session", { sessionId });
615
823
  }
616
824
  };
617
825
 
618
826
  // src/index.ts
619
827
  async function createAgentX(config) {
620
- const client = new RemoteClient(config);
621
- await client.connect();
622
- return client;
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