agentxjs 2.3.1 → 2.5.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.
@@ -10,6 +10,7 @@ import type { BusEvent, BusEventHandler, EventBus, Unsubscribe } from "@agentxjs
10
10
  import type { RpcMethod } from "@agentxjs/core/network";
11
11
  import type { AgentXRuntime } from "@agentxjs/core/runtime";
12
12
  import { createLogger } from "commonxjs/logger";
13
+ import { AgentHandleImpl } from "./AgentHandle";
13
14
  import { CommandHandler } from "./CommandHandler";
14
15
  import { createLocalAgents } from "./namespaces/agents";
15
16
  import { createLocalContainers } from "./namespaces/containers";
@@ -18,13 +19,12 @@ import { createLocalLLM } from "./namespaces/llm";
18
19
  import { createPresentations } from "./namespaces/presentations";
19
20
  import { createLocalSessions } from "./namespaces/sessions";
20
21
  import type {
21
- AgentNamespace,
22
+ AgentHandle,
22
23
  AgentX,
23
- ContainerNamespace,
24
- ImageNamespace,
24
+ Embodiment,
25
+ ImageListResponse,
26
+ InstanceNamespace,
25
27
  LLMNamespace,
26
- PresentationNamespace,
27
- SessionNamespace,
28
28
  } from "./types";
29
29
 
30
30
  const logger = createLogger("agentx/LocalClient");
@@ -37,23 +37,22 @@ export class LocalClient implements AgentX {
37
37
  private commandHandler: CommandHandler | null = null;
38
38
  private isDisposed = false;
39
39
 
40
- readonly container: ContainerNamespace;
41
- readonly image: ImageNamespace;
42
- readonly agent: AgentNamespace;
43
- readonly session: SessionNamespace;
44
- readonly presentation: PresentationNamespace;
45
- readonly llm: LLMNamespace;
40
+ readonly instance: InstanceNamespace;
41
+ readonly provider: LLMNamespace;
46
42
 
47
43
  constructor(runtime: AgentXRuntime) {
48
44
  this.runtime = runtime;
49
45
  const platform = runtime.platform;
50
46
 
51
- this.container = createLocalContainers(platform);
52
- this.image = createLocalImages(platform);
53
- this.agent = createLocalAgents(runtime);
54
- this.session = createLocalSessions(runtime);
55
- this.presentation = createPresentations(this);
56
- this.llm = createLocalLLM(platform);
47
+ const container = createLocalContainers(platform);
48
+ const image = createLocalImages(platform);
49
+ const agent = createLocalAgents(runtime);
50
+ const session = createLocalSessions(runtime);
51
+ const llm = createLocalLLM(platform);
52
+ const present = createPresentations(this, image);
53
+
54
+ this.instance = { container, image, agent, session, present, llm };
55
+ this.provider = llm;
57
56
 
58
57
  logger.info("LocalClient initialized");
59
58
  }
@@ -68,6 +67,48 @@ export class LocalClient implements AgentX {
68
67
  return this.runtime.platform.eventBus;
69
68
  }
70
69
 
70
+ // ==================== Top-level Agent API ====================
71
+
72
+ async create(params: {
73
+ name?: string;
74
+ description?: string;
75
+ contextId?: string;
76
+ embody?: Embodiment;
77
+ customData?: Record<string, unknown>;
78
+ }): Promise<AgentHandle> {
79
+ const containerId = "default";
80
+ const imgRes = await this.instance.image.create({ containerId, ...params });
81
+ const agentRes = await this.instance.agent.create({ imageId: imgRes.record.imageId });
82
+ return new AgentHandleImpl(
83
+ {
84
+ agentId: agentRes.agentId,
85
+ imageId: agentRes.imageId,
86
+ containerId: agentRes.containerId,
87
+ sessionId: agentRes.sessionId,
88
+ },
89
+ this.instance
90
+ );
91
+ }
92
+
93
+ async list(): Promise<ImageListResponse> {
94
+ return this.instance.image.list();
95
+ }
96
+
97
+ async get(agentId: string): Promise<AgentHandle | null> {
98
+ const res = await this.instance.image.get(agentId);
99
+ if (!res.record) return null;
100
+ const r = res.record;
101
+ return new AgentHandleImpl(
102
+ {
103
+ agentId: r.imageId,
104
+ imageId: r.imageId,
105
+ containerId: r.containerId,
106
+ sessionId: r.sessionId,
107
+ },
108
+ this.instance
109
+ );
110
+ }
111
+
71
112
  // ==================== Event Subscription ====================
72
113
 
73
114
  on<T extends string>(type: T, handler: BusEventHandler<BusEvent & { type: T }>): Unsubscribe {
@@ -8,8 +8,9 @@
8
8
  import type { AgentXError } from "@agentxjs/core/error";
9
9
  import type { BusEvent, BusEventHandler, EventBus, Unsubscribe } from "@agentxjs/core/event";
10
10
  import { EventBusImpl } from "@agentxjs/core/event";
11
- import { RpcClient } from "@agentxjs/core/network";
11
+ import { RpcClient, type RpcMethod } from "@agentxjs/core/network";
12
12
  import { createLogger } from "commonxjs/logger";
13
+ import { AgentHandleImpl } from "./AgentHandle";
13
14
  import { createRemoteAgents } from "./namespaces/agents";
14
15
  import { createRemoteContainers } from "./namespaces/containers";
15
16
  import { createRemoteImages } from "./namespaces/images";
@@ -17,14 +18,13 @@ import { createRemoteLLM } from "./namespaces/llm";
17
18
  import { createPresentations } from "./namespaces/presentations";
18
19
  import { createRemoteSessions } from "./namespaces/sessions";
19
20
  import type {
20
- AgentNamespace,
21
+ AgentHandle,
21
22
  AgentX,
22
- ContainerNamespace,
23
- ImageNamespace,
23
+ Embodiment,
24
+ ImageListResponse,
25
+ InstanceNamespace,
24
26
  LLMNamespace,
25
- PresentationNamespace,
26
27
  RemoteClientConfig,
27
- SessionNamespace,
28
28
  } from "./types";
29
29
 
30
30
  const logger = createLogger("agentx/RemoteClient");
@@ -37,12 +37,8 @@ export class RemoteClient implements AgentX {
37
37
  private readonly eventBus: EventBus;
38
38
  private readonly rpcClient: RpcClient;
39
39
 
40
- readonly container: ContainerNamespace;
41
- readonly image: ImageNamespace;
42
- readonly agent: AgentNamespace;
43
- readonly session: SessionNamespace;
44
- readonly presentation: PresentationNamespace;
45
- readonly llm: LLMNamespace;
40
+ readonly instance: InstanceNamespace;
41
+ readonly provider: LLMNamespace;
46
42
 
47
43
  constructor(config: RemoteClientConfig) {
48
44
  this.config = config;
@@ -65,12 +61,15 @@ export class RemoteClient implements AgentX {
65
61
  });
66
62
 
67
63
  // Assemble namespaces
68
- this.container = createRemoteContainers(this.rpcClient);
69
- this.image = createRemoteImages(this.rpcClient, (sessionId) => this.subscribe(sessionId));
70
- this.agent = createRemoteAgents(this.rpcClient);
71
- this.session = createRemoteSessions(this.rpcClient);
72
- this.presentation = createPresentations(this);
73
- this.llm = createRemoteLLM(this.rpcClient);
64
+ const container = createRemoteContainers(this.rpcClient);
65
+ const image = createRemoteImages(this.rpcClient, (sessionId) => this.subscribe(sessionId));
66
+ const agent = createRemoteAgents(this.rpcClient);
67
+ const session = createRemoteSessions(this.rpcClient);
68
+ const llm = createRemoteLLM(this.rpcClient);
69
+ const present = createPresentations(this, image);
70
+
71
+ this.instance = { container, image, agent, session, present, llm };
72
+ this.provider = llm;
74
73
  }
75
74
 
76
75
  // ==================== Properties ====================
@@ -83,6 +82,48 @@ export class RemoteClient implements AgentX {
83
82
  return this.eventBus;
84
83
  }
85
84
 
85
+ // ==================== Top-level Agent API ====================
86
+
87
+ async create(params: {
88
+ name?: string;
89
+ description?: string;
90
+ contextId?: string;
91
+ embody?: Embodiment;
92
+ customData?: Record<string, unknown>;
93
+ }): Promise<AgentHandle> {
94
+ const containerId = "default";
95
+ const imgRes = await this.instance.image.create({ containerId, ...params });
96
+ const agentRes = await this.instance.agent.create({ imageId: imgRes.record.imageId });
97
+ return new AgentHandleImpl(
98
+ {
99
+ agentId: agentRes.agentId,
100
+ imageId: agentRes.imageId,
101
+ containerId: agentRes.containerId,
102
+ sessionId: agentRes.sessionId,
103
+ },
104
+ this.instance
105
+ );
106
+ }
107
+
108
+ async list(): Promise<ImageListResponse> {
109
+ return this.instance.image.list();
110
+ }
111
+
112
+ async get(agentId: string): Promise<AgentHandle | null> {
113
+ const res = await this.instance.image.get(agentId);
114
+ if (!res.record) return null;
115
+ const r = res.record;
116
+ return new AgentHandleImpl(
117
+ {
118
+ agentId: r.imageId,
119
+ imageId: r.imageId,
120
+ containerId: r.containerId,
121
+ sessionId: r.sessionId,
122
+ },
123
+ this.instance
124
+ );
125
+ }
126
+
86
127
  // ==================== Connection ====================
87
128
 
88
129
  async connect(): Promise<void> {
@@ -127,6 +168,6 @@ export class RemoteClient implements AgentX {
127
168
  // ==================== RPC ====================
128
169
 
129
170
  async rpc<T = unknown>(method: string, params?: unknown): Promise<T> {
130
- return this.rpcClient.call<T>(method, params);
171
+ return this.rpcClient.call<T>(method as RpcMethod, params);
131
172
  }
132
173
  }
package/src/index.ts CHANGED
@@ -9,7 +9,8 @@
9
9
  * import { nodePlatform } from "@agentxjs/node-platform";
10
10
  *
11
11
  * const ax = createAgentX(nodePlatform({ createDriver }));
12
- * await ax.agent.create({ imageId: "..." });
12
+ * const agent = await ax.create({ name: "Aristotle", embody: { model: "claude-sonnet-4-6" } });
13
+ * await agent.send("Hello!");
13
14
  * ```
14
15
  *
15
16
  * @example Remote mode
@@ -74,29 +75,18 @@ export function createAgentX(config?: PlatformConfig): AgentXBuilder {
74
75
  return getLocalClient().events;
75
76
  },
76
77
 
77
- get container() {
78
- return getLocalClient().container;
78
+ get instance() {
79
+ return getLocalClient().instance;
79
80
  },
80
81
 
81
- get image() {
82
- return getLocalClient().image;
82
+ get provider() {
83
+ return getLocalClient().provider;
83
84
  },
84
85
 
85
- get agent() {
86
- return getLocalClient().agent;
87
- },
88
-
89
- get session() {
90
- return getLocalClient().session;
91
- },
92
-
93
- get presentation() {
94
- return getLocalClient().presentation;
95
- },
96
-
97
- get llm() {
98
- return getLocalClient().llm;
99
- },
86
+ // Top-level Agent API
87
+ create: (params) => getLocalClient().create(params),
88
+ list: () => getLocalClient().list(),
89
+ get: (agentId) => getLocalClient().get(agentId),
100
90
 
101
91
  on(type, handler) {
102
92
  return getLocalClient().on(type, handler);
@@ -196,6 +186,7 @@ export { createServer, type ServerConfig } from "./server";
196
186
  export type {
197
187
  AgentCreateResponse,
198
188
  AgentGetResponse,
189
+ AgentHandle,
199
190
  AgentInfo,
200
191
  AgentListResponse,
201
192
  AgentNamespace,
@@ -209,11 +200,13 @@ export type {
209
200
  ContainerInfo,
210
201
  ContainerListResponse,
211
202
  ContainerNamespace,
203
+ Embodiment,
212
204
  ImageCreateResponse,
213
205
  ImageGetResponse,
214
206
  ImageListResponse,
215
207
  ImageNamespace,
216
208
  ImageRecord,
209
+ InstanceNamespace,
217
210
  LLMNamespace,
218
211
  LLMProviderCreateResponse,
219
212
  LLMProviderDefaultResponse,
@@ -1,20 +1,25 @@
1
1
  /**
2
2
  * Presentation namespace factory
3
3
  *
4
- * Single factory for both local and remote modes
5
- * Presentation only depends on the AgentX interface.
4
+ * Single factory for both local and remote modes.
6
5
  */
7
6
 
8
7
  import { messagesToConversations, Presentation, type PresentationOptions } from "../presentation";
9
- import type { AgentX, PresentationNamespace } from "../types";
8
+ import type { AgentX, ImageNamespace, PresentationNamespace } from "../types";
10
9
 
11
10
  /**
12
- * Create presentation namespace backed by any AgentX client
11
+ * Create presentation namespace.
12
+ *
13
+ * Takes the full AgentX (for Presentation event wiring) and the ImageNamespace
14
+ * (for message history), avoiding circular access to `instance` during construction.
13
15
  */
14
- export function createPresentations(agentx: AgentX): PresentationNamespace {
16
+ export function createPresentations(
17
+ agentx: AgentX,
18
+ imageNs: ImageNamespace
19
+ ): PresentationNamespace {
15
20
  return {
16
21
  async create(agentId: string, options?: PresentationOptions): Promise<Presentation> {
17
- const messages = await agentx.session.getMessages(agentId);
22
+ const messages = await imageNs.getMessages(agentId);
18
23
  const conversations = messagesToConversations(messages);
19
24
  return new Presentation(agentx, agentId, options, conversations);
20
25
  },
@@ -110,7 +110,7 @@ export class Presentation {
110
110
 
111
111
  try {
112
112
  // Send message via agentx
113
- await this.agentx.session.send(this.agentId, content);
113
+ await this.agentx.instance.session.send(this.agentId, content);
114
114
  } catch (error) {
115
115
  this.notifyError(error instanceof Error ? error : new Error(String(error)));
116
116
  }
@@ -121,7 +121,7 @@ export class Presentation {
121
121
  */
122
122
  async interrupt(): Promise<void> {
123
123
  try {
124
- await this.agentx.session.interrupt(this.agentId);
124
+ await this.agentx.instance.session.interrupt(this.agentId);
125
125
  } catch (error) {
126
126
  this.notifyError(error instanceof Error ? error : new Error(String(error)));
127
127
  }
package/src/types.ts CHANGED
@@ -46,6 +46,15 @@ export interface AgentInfo {
46
46
  lifecycle?: string;
47
47
  }
48
48
 
49
+ /**
50
+ * Embodiment — runtime configuration for an agent's "body".
51
+ */
52
+ export interface Embodiment {
53
+ model?: string;
54
+ systemPrompt?: string;
55
+ mcpServers?: Record<string, unknown>;
56
+ }
57
+
49
58
  /**
50
59
  * Image record from server
51
60
  */
@@ -55,7 +64,12 @@ export interface ImageRecord {
55
64
  sessionId: string;
56
65
  name?: string;
57
66
  description?: string;
67
+ contextId?: string;
68
+ embody?: Embodiment;
69
+ /** @deprecated Use `embody.systemPrompt` instead. */
58
70
  systemPrompt?: string;
71
+ /** @deprecated Use `embody.mcpServers` instead. */
72
+ mcpServers?: Record<string, unknown>;
59
73
  customData?: Record<string, unknown>;
60
74
  createdAt: number;
61
75
  updatedAt: number;
@@ -229,14 +243,14 @@ export interface ContainerNamespace {
229
243
  */
230
244
  export interface ImageNamespace {
231
245
  /**
232
- * Create a new image
246
+ * Create a new image from an Agent blueprint
233
247
  */
234
248
  create(params: {
235
249
  containerId: string;
236
250
  name?: string;
237
251
  description?: string;
238
- systemPrompt?: string;
239
- mcpServers?: Record<string, unknown>;
252
+ contextId?: string;
253
+ embody?: Embodiment;
240
254
  customData?: Record<string, unknown>;
241
255
  }): Promise<ImageCreateResponse>;
242
256
 
@@ -258,6 +272,7 @@ export interface ImageNamespace {
258
272
  updates: {
259
273
  name?: string;
260
274
  description?: string;
275
+ embody?: Embodiment;
261
276
  customData?: Record<string, unknown>;
262
277
  }
263
278
  ): Promise<ImageUpdateResponse>;
@@ -385,7 +400,7 @@ export interface PresentationNamespace {
385
400
  *
386
401
  * @example
387
402
  * ```typescript
388
- * const pres = agentx.presentation.create(agentId, {
403
+ * const pres = ax.present(agentId, {
389
404
  * onUpdate: (state) => renderUI(state),
390
405
  * onError: (error) => console.error(error),
391
406
  * });
@@ -397,12 +412,100 @@ export interface PresentationNamespace {
397
412
  create(agentId: string, options?: PresentationOptions): Promise<Presentation>;
398
413
  }
399
414
 
415
+ // ============================================================================
416
+ // Instance Namespace — internal implementation details
417
+ // ============================================================================
418
+
419
+ /**
420
+ * Instance — low-level access to internal subsystems.
421
+ *
422
+ * Most users should use the top-level Agent API (ax.create, ax.send, etc.).
423
+ * Instance exposes the underlying image, agent, session, container, llm,
424
+ * and presentation subsystems for advanced use cases.
425
+ */
426
+ export interface InstanceNamespace {
427
+ readonly container: ContainerNamespace;
428
+ readonly image: ImageNamespace;
429
+ readonly agent: AgentNamespace;
430
+ readonly session: SessionNamespace;
431
+ readonly present: PresentationNamespace;
432
+ readonly llm: LLMNamespace;
433
+ }
434
+
435
+ // ============================================================================
436
+ // Agent Handle
437
+ // ============================================================================
438
+
439
+ /**
440
+ * AgentHandle — a live reference to a created agent.
441
+ *
442
+ * Returned by `ax.create()` and `ax.get()`. Holds the agent's identity
443
+ * and provides instance-level operations (send, interrupt, etc.).
444
+ *
445
+ * @example
446
+ * ```typescript
447
+ * const agent = await ax.create({ name: "Aristotle", embody: { model: "claude-sonnet-4-6" } });
448
+ * await agent.send("Hello!");
449
+ * const messages = await agent.history();
450
+ * ```
451
+ */
452
+ export interface AgentHandle {
453
+ readonly agentId: string;
454
+ readonly imageId: string;
455
+ readonly containerId: string;
456
+ readonly sessionId: string;
457
+
458
+ /**
459
+ * Send a message to this agent
460
+ */
461
+ send(content: string | unknown[]): Promise<MessageSendResponse>;
462
+
463
+ /**
464
+ * Interrupt this agent's current response
465
+ */
466
+ interrupt(): Promise<BaseResponse>;
467
+
468
+ /**
469
+ * Get message history
470
+ */
471
+ history(): Promise<Message[]>;
472
+
473
+ /**
474
+ * Create a presentation for UI integration
475
+ */
476
+ present(options?: PresentationOptions): Promise<Presentation>;
477
+
478
+ /**
479
+ * Update this agent's metadata
480
+ */
481
+ update(updates: {
482
+ name?: string;
483
+ description?: string;
484
+ embody?: Embodiment;
485
+ customData?: Record<string, unknown>;
486
+ }): Promise<void>;
487
+
488
+ /**
489
+ * Delete this agent
490
+ */
491
+ delete(): Promise<void>;
492
+ }
493
+
400
494
  // ============================================================================
401
495
  // AgentX Client Interface
402
496
  // ============================================================================
403
497
 
404
498
  /**
405
- * AgentX Client SDK — unified interface for local, remote, and server modes
499
+ * AgentX Client SDK — unified interface for local, remote, and server modes.
500
+ *
501
+ * @example
502
+ * ```typescript
503
+ * const ax = createAgentX(config);
504
+ * const agent = await ax.create({ name: "Aristotle", embody: { model: "claude-sonnet-4-6" } });
505
+ * await agent.send("Hello!");
506
+ * ```
507
+ *
508
+ * For advanced use cases, access `ax.instance.*` for low-level subsystems.
406
509
  */
407
510
  export interface AgentX {
408
511
  /**
@@ -415,14 +518,42 @@ export interface AgentX {
415
518
  */
416
519
  readonly events: EventBus;
417
520
 
418
- // ==================== Namespaced Operations ====================
521
+ // ==================== Agent API (top-level) ====================
419
522
 
420
- readonly container: ContainerNamespace;
421
- readonly image: ImageNamespace;
422
- readonly agent: AgentNamespace;
423
- readonly session: SessionNamespace;
424
- readonly presentation: PresentationNamespace;
425
- readonly llm: LLMNamespace;
523
+ /**
524
+ * Create a new agent from a blueprint
525
+ */
526
+ create(params: {
527
+ name?: string;
528
+ description?: string;
529
+ contextId?: string;
530
+ embody?: Embodiment;
531
+ customData?: Record<string, unknown>;
532
+ }): Promise<AgentHandle>;
533
+
534
+ /**
535
+ * List all agents
536
+ */
537
+ list(): Promise<ImageListResponse>;
538
+
539
+ /**
540
+ * Get agent by ID
541
+ */
542
+ get(agentId: string): Promise<AgentHandle | null>;
543
+
544
+ // ==================== Instance (low-level) ====================
545
+
546
+ /**
547
+ * Low-level access to internal subsystems (image, agent, session, container, llm).
548
+ */
549
+ readonly instance: InstanceNamespace;
550
+
551
+ // ==================== LLM Provider (system-level) ====================
552
+
553
+ /**
554
+ * LLM provider management (system-level, not per-agent)
555
+ */
556
+ readonly provider: LLMNamespace;
426
557
 
427
558
  // ==================== Event Subscription ====================
428
559
 
@@ -432,35 +563,12 @@ export interface AgentX {
432
563
 
433
564
  // ==================== Error Handling ====================
434
565
 
435
- /**
436
- * Top-level error handler — receives all AgentXError instances from any layer.
437
- *
438
- * Independent of `on("error", ...)` (stream events) and `presentation.onError` (UI errors).
439
- *
440
- * @example
441
- * ```typescript
442
- * ax.onError((error) => {
443
- * console.error(`[${error.category}] ${error.code}: ${error.message}`);
444
- * if (!error.recoverable) {
445
- * // Circuit is open, stop sending requests
446
- * }
447
- * });
448
- * ```
449
- */
450
566
  onError(handler: (error: AgentXError) => void): Unsubscribe;
451
567
 
452
568
  // ==================== RPC ====================
453
569
 
454
570
  /**
455
- * Universal JSON-RPC entry point — works in all modes:
456
- * - Local: dispatches to CommandHandler directly
457
- * - Remote: forwards to the remote server via RPC client
458
- *
459
- * @example
460
- * ```typescript
461
- * const result = await ax.rpc("container.create", { containerId: "default" });
462
- * const { records } = await ax.rpc<{ records: ImageRecord[] }>("image.list");
463
- * ```
571
+ * Universal JSON-RPC entry point
464
572
  */
465
573
  rpc<T = unknown>(method: string, params?: unknown): Promise<T>;
466
574
 
@@ -523,7 +631,8 @@ export interface AgentXServer {
523
631
  * const ax = createAgentX(node({ createDriver }))
524
632
  *
525
633
  * // Local use
526
- * await ax.agent.create({ imageId: "..." })
634
+ * const agent = await ax.create({ name: "Aristotle" })
635
+ * await agent.send("Hello!")
527
636
  *
528
637
  * // Connect to remote server
529
638
  * const client = await ax.connect("wss://...")