agentxjs 1.9.9-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/src/index.ts CHANGED
@@ -1,82 +1,160 @@
1
1
  /**
2
2
  * agentxjs - AgentX Client SDK
3
3
  *
4
- * Connect to AgentX servers from Node.js and browsers.
4
+ * Unified entry point supporting local and remote modes.
5
5
  *
6
- * @example
6
+ * @example Local mode (embedded runtime)
7
7
  * ```typescript
8
8
  * import { createAgentX } from "agentxjs";
9
9
  *
10
- * // Connect to server
11
10
  * const agentx = await createAgentX({
12
- * serverUrl: "ws://localhost:5200",
13
- * headers: { Authorization: "Bearer sk-xxx" },
14
- * context: { userId: "123", tenantId: "abc" },
15
- * });
16
- *
17
- * // Create container and image
18
- * await agentx.createContainer("my-container");
19
- * const { record: image } = await agentx.createImage({
20
- * containerId: "my-container",
21
- * name: "Assistant",
22
- * systemPrompt: "You are a helpful assistant",
11
+ * apiKey: process.env.ANTHROPIC_API_KEY,
12
+ * provider: "anthropic",
23
13
  * });
24
14
  *
25
- * // Create agent and send message
26
- * const { agentId } = await agentx.createAgent({ imageId: image.imageId });
27
- *
28
- * // Subscribe to events
29
- * agentx.on("text_delta", (event) => {
30
- * process.stdout.write(event.data.text);
15
+ * await agentx.containers.create("my-app");
16
+ * const { record: image } = await agentx.images.create({
17
+ * containerId: "my-app",
18
+ * systemPrompt: "You are helpful",
31
19
  * });
20
+ * const { agentId } = await agentx.agents.create({ imageId: image.imageId });
32
21
  *
33
- * agentx.on("assistant_message", (event) => {
34
- * console.log("Complete:", event.data.content);
35
- * });
36
- *
37
- * // Send message
38
- * await agentx.sendMessage(agentId, "Hello!");
39
- *
40
- * // Cleanup
41
- * await agentx.dispose();
22
+ * agentx.on("text_delta", (e) => process.stdout.write(e.data.text));
23
+ * await agentx.sessions.send(agentId, "Hello!");
42
24
  * ```
43
25
  *
44
- * @example Dynamic headers and context
26
+ * @example Remote mode (WebSocket client)
45
27
  * ```typescript
28
+ * import { createAgentX } from "agentxjs";
29
+ *
46
30
  * const agentx = await createAgentX({
47
31
  * serverUrl: "ws://localhost:5200",
48
- * headers: () => ({ Authorization: `Bearer ${getToken()}` }),
49
- * context: async () => ({
50
- * userId: await getUserId(),
51
- * permissions: await getPermissions(),
52
- * }),
53
32
  * });
54
33
  * ```
55
34
  */
56
35
 
57
36
  import { RemoteClient } from "./RemoteClient";
37
+ import { LocalClient } from "./LocalClient";
58
38
  import type { AgentX, AgentXConfig } from "./types";
59
39
 
60
40
  /**
61
41
  * Create an AgentX client
62
42
  *
43
+ * Mode detection:
44
+ * - `serverUrl` present → **Remote mode** (WebSocket client)
45
+ * - `apiKey` present → **Local mode** (embedded Runtime + MonoDriver)
46
+ *
63
47
  * @param config - Client configuration
64
48
  * @returns Connected AgentX client
65
49
  */
66
50
  export async function createAgentX(config: AgentXConfig): Promise<AgentX> {
67
- const client = new RemoteClient(config);
68
- await client.connect();
69
- return client;
51
+ if (config.serverUrl) {
52
+ // Remote mode — resolve platform for WebSocket factory if needed
53
+ const resolvedConfig = await resolvePlatformForRemote(config);
54
+ const client = new RemoteClient(resolvedConfig);
55
+ await client.connect();
56
+ return client;
57
+ }
58
+
59
+ if (config.apiKey || config.createDriver || config.customPlatform) {
60
+ // Local mode
61
+ return createLocalClient(config);
62
+ }
63
+
64
+ throw new Error(
65
+ "Invalid AgentX config: provide either 'serverUrl' (remote mode) or 'apiKey' (local mode)"
66
+ );
67
+ }
68
+
69
+ /**
70
+ * Resolve platform for remote mode
71
+ *
72
+ * In Node.js: auto-import node-platform to get webSocketFactory
73
+ * In browser: no platform needed (native WebSocket is the default)
74
+ */
75
+ async function resolvePlatformForRemote(config: AgentXConfig): Promise<AgentXConfig> {
76
+ if (config.customPlatform?.webSocketFactory) {
77
+ return config;
78
+ }
79
+
80
+ // In browser, native WebSocket works — no platform needed
81
+ if (typeof globalThis !== "undefined" && (globalThis as any).window?.document !== undefined) {
82
+ return config;
83
+ }
84
+
85
+ // Node.js — auto-resolve webSocketFactory from node-platform
86
+ try {
87
+ const { createNodeWebSocket } = await import("@agentxjs/node-platform/network");
88
+ return {
89
+ ...config,
90
+ customPlatform: {
91
+ ...config.customPlatform,
92
+ webSocketFactory: createNodeWebSocket,
93
+ } as any,
94
+ };
95
+ } catch {
96
+ // node-platform not available, fall back to global WebSocket
97
+ return config;
98
+ }
99
+ }
100
+
101
+ /**
102
+ * Create a local client with embedded runtime
103
+ */
104
+ async function createLocalClient(config: AgentXConfig): Promise<AgentX> {
105
+ const { createAgentXRuntime } = await import("@agentxjs/core/runtime");
106
+
107
+ // Resolve platform
108
+ let platform;
109
+ if (config.customPlatform) {
110
+ platform = config.customPlatform;
111
+ } else {
112
+ const { createNodePlatform } = await import("@agentxjs/node-platform");
113
+ platform = await createNodePlatform({
114
+ dataPath: config.dataPath ?? ":memory:",
115
+ logLevel: config.logLevel ?? (config.debug ? "debug" : undefined),
116
+ });
117
+ }
118
+
119
+ // Resolve createDriver
120
+ let createDriver = config.createDriver;
121
+ if (!createDriver) {
122
+ const { createMonoDriver } = await import("@agentxjs/mono-driver");
123
+ createDriver = (driverConfig: import("@agentxjs/core/driver").DriverConfig) => {
124
+ const existingOptions = (driverConfig as any).options ?? {};
125
+ return createMonoDriver({
126
+ ...driverConfig,
127
+ apiKey: config.apiKey ?? driverConfig.apiKey,
128
+ baseUrl: config.baseUrl ?? driverConfig.baseUrl,
129
+ model: config.model ?? driverConfig.model,
130
+ options: {
131
+ ...existingOptions,
132
+ provider: config.provider ?? existingOptions.provider ?? "anthropic",
133
+ },
134
+ });
135
+ };
136
+ }
137
+
138
+ // Create runtime
139
+ const runtime = createAgentXRuntime(platform, createDriver);
140
+
141
+ return new LocalClient(runtime);
70
142
  }
71
143
 
72
144
  // Re-export types
73
145
  export type {
74
146
  AgentX,
75
147
  AgentXConfig,
148
+ LLMProvider,
76
149
  MaybeAsync,
77
150
  AgentInfo,
78
151
  ImageRecord,
79
152
  ContainerInfo,
153
+ ContainerNamespace,
154
+ ImageNamespace,
155
+ AgentNamespace,
156
+ SessionNamespace,
157
+ PresentationNamespace,
80
158
  AgentCreateResponse,
81
159
  AgentGetResponse,
82
160
  AgentListResponse,
@@ -112,4 +190,5 @@ export {
112
190
  addUserConversation,
113
191
  createInitialState,
114
192
  initialPresentationState,
193
+ messagesToConversations,
115
194
  } from "./presentation";
@@ -0,0 +1,121 @@
1
+ /**
2
+ * Agent namespace factories
3
+ */
4
+
5
+ import type { AgentXRuntime } from "@agentxjs/core/runtime";
6
+ import type { RpcClient, RpcMethod } from "@agentxjs/core/network";
7
+ import type {
8
+ AgentNamespace,
9
+ AgentCreateResponse,
10
+ AgentGetResponse,
11
+ AgentListResponse,
12
+ BaseResponse,
13
+ } from "../types";
14
+
15
+ /**
16
+ * Create local agent namespace backed by embedded runtime
17
+ */
18
+ export function createLocalAgents(runtime: AgentXRuntime): AgentNamespace {
19
+ return {
20
+ async create(params: { imageId: string; agentId?: string }): Promise<AgentCreateResponse> {
21
+ // Reuse existing running agent for this image
22
+ const existingAgent = runtime
23
+ .getAgents()
24
+ .find((a) => a.imageId === params.imageId && a.lifecycle === "running");
25
+
26
+ if (existingAgent) {
27
+ return {
28
+ agentId: existingAgent.agentId,
29
+ imageId: existingAgent.imageId,
30
+ containerId: existingAgent.containerId,
31
+ sessionId: existingAgent.sessionId,
32
+ requestId: "",
33
+ };
34
+ }
35
+
36
+ const agent = await runtime.createAgent({
37
+ imageId: params.imageId,
38
+ agentId: params.agentId,
39
+ });
40
+
41
+ return {
42
+ agentId: agent.agentId,
43
+ imageId: agent.imageId,
44
+ containerId: agent.containerId,
45
+ sessionId: agent.sessionId,
46
+ requestId: "",
47
+ };
48
+ },
49
+
50
+ async get(agentId: string): Promise<AgentGetResponse> {
51
+ const agent = runtime.getAgent(agentId);
52
+ return {
53
+ agent: agent
54
+ ? {
55
+ agentId: agent.agentId,
56
+ imageId: agent.imageId,
57
+ containerId: agent.containerId,
58
+ sessionId: agent.sessionId,
59
+ lifecycle: agent.lifecycle,
60
+ }
61
+ : null,
62
+ exists: !!agent,
63
+ requestId: "",
64
+ };
65
+ },
66
+
67
+ async list(containerId?: string): Promise<AgentListResponse> {
68
+ const agents = containerId ? runtime.getAgentsByContainer(containerId) : runtime.getAgents();
69
+
70
+ return {
71
+ agents: agents.map((a) => ({
72
+ agentId: a.agentId,
73
+ imageId: a.imageId,
74
+ containerId: a.containerId,
75
+ sessionId: a.sessionId,
76
+ lifecycle: a.lifecycle,
77
+ })),
78
+ requestId: "",
79
+ };
80
+ },
81
+
82
+ async destroy(agentId: string): Promise<BaseResponse> {
83
+ const agent = runtime.getAgent(agentId);
84
+ if (agent) {
85
+ await runtime.destroyAgent(agentId);
86
+ }
87
+ return { requestId: "" };
88
+ },
89
+ };
90
+ }
91
+
92
+ /**
93
+ * Create remote agent namespace backed by RPC client
94
+ */
95
+ export function createRemoteAgents(rpcClient: RpcClient): AgentNamespace {
96
+ return {
97
+ async create(params: { imageId: string; agentId?: string }): Promise<AgentCreateResponse> {
98
+ // Agent creation via image.run RPC
99
+ const result = await rpcClient.call<AgentCreateResponse>("image.run" as RpcMethod, {
100
+ imageId: params.imageId,
101
+ agentId: params.agentId,
102
+ });
103
+ return { ...result, requestId: "" };
104
+ },
105
+
106
+ async get(agentId: string): Promise<AgentGetResponse> {
107
+ const result = await rpcClient.call<AgentGetResponse>("agent.get", { agentId });
108
+ return { ...result, requestId: "" };
109
+ },
110
+
111
+ async list(containerId?: string): Promise<AgentListResponse> {
112
+ const result = await rpcClient.call<AgentListResponse>("agent.list", { containerId });
113
+ return { ...result, requestId: "" };
114
+ },
115
+
116
+ async destroy(agentId: string): Promise<BaseResponse> {
117
+ const result = await rpcClient.call<BaseResponse>("agent.destroy", { agentId });
118
+ return { ...result, requestId: "" };
119
+ },
120
+ };
121
+ }
@@ -0,0 +1,68 @@
1
+ /**
2
+ * Container namespace factories
3
+ */
4
+
5
+ import type { AgentXPlatform } from "@agentxjs/core/runtime";
6
+ import type { RpcClient } from "@agentxjs/core/network";
7
+ import type {
8
+ ContainerNamespace,
9
+ ContainerCreateResponse,
10
+ ContainerGetResponse,
11
+ ContainerListResponse,
12
+ } from "../types";
13
+
14
+ /**
15
+ * Create local container namespace backed by embedded runtime
16
+ */
17
+ export function createLocalContainers(platform: AgentXPlatform): ContainerNamespace {
18
+ return {
19
+ async create(containerId: string): Promise<ContainerCreateResponse> {
20
+ const { getOrCreateContainer } = await import("@agentxjs/core/container");
21
+ const { containerRepository, imageRepository, sessionRepository } = platform;
22
+
23
+ const container = await getOrCreateContainer(containerId, {
24
+ containerRepository,
25
+ imageRepository,
26
+ sessionRepository,
27
+ });
28
+
29
+ return { containerId: container.containerId, requestId: "" };
30
+ },
31
+
32
+ async get(containerId: string): Promise<ContainerGetResponse> {
33
+ const exists = await platform.containerRepository.containerExists(containerId);
34
+ return { containerId, exists, requestId: "" };
35
+ },
36
+
37
+ async list(): Promise<ContainerListResponse> {
38
+ const containers = await platform.containerRepository.findAllContainers();
39
+ return { containerIds: containers.map((c) => c.containerId), requestId: "" };
40
+ },
41
+ };
42
+ }
43
+
44
+ /**
45
+ * Create remote container namespace backed by RPC client
46
+ */
47
+ export function createRemoteContainers(rpcClient: RpcClient): ContainerNamespace {
48
+ return {
49
+ async create(containerId: string): Promise<ContainerCreateResponse> {
50
+ const result = await rpcClient.call<ContainerCreateResponse>("container.create", {
51
+ containerId,
52
+ });
53
+ return { ...result, requestId: "" };
54
+ },
55
+
56
+ async get(containerId: string): Promise<ContainerGetResponse> {
57
+ const result = await rpcClient.call<ContainerGetResponse>("container.get", {
58
+ containerId,
59
+ });
60
+ return { ...result, requestId: "" };
61
+ },
62
+
63
+ async list(): Promise<ContainerListResponse> {
64
+ const result = await rpcClient.call<ContainerListResponse>("container.list", {});
65
+ return { ...result, requestId: "" };
66
+ },
67
+ };
68
+ }
@@ -0,0 +1,180 @@
1
+ /**
2
+ * Image namespace factories
3
+ */
4
+
5
+ import type { AgentXPlatform } from "@agentxjs/core/runtime";
6
+ import type { RpcClient } from "@agentxjs/core/network";
7
+ import type {
8
+ ImageNamespace,
9
+ ImageCreateResponse,
10
+ ImageGetResponse,
11
+ ImageListResponse,
12
+ ImageUpdateResponse,
13
+ BaseResponse,
14
+ } from "../types";
15
+
16
+ /**
17
+ * Create local image namespace backed by embedded runtime
18
+ */
19
+ export function createLocalImages(platform: AgentXPlatform): ImageNamespace {
20
+ return {
21
+ async create(params: {
22
+ containerId: string;
23
+ name?: string;
24
+ description?: string;
25
+ systemPrompt?: string;
26
+ mcpServers?: Record<string, unknown>;
27
+ customData?: Record<string, unknown>;
28
+ }): Promise<ImageCreateResponse> {
29
+ const { imageRepository, sessionRepository } = platform;
30
+ const { createImage } = await import("@agentxjs/core/image");
31
+
32
+ const image = await createImage(
33
+ {
34
+ containerId: params.containerId,
35
+ name: params.name,
36
+ description: params.description,
37
+ systemPrompt: params.systemPrompt,
38
+ mcpServers: params.mcpServers as any,
39
+ customData: params.customData,
40
+ },
41
+ { imageRepository, sessionRepository }
42
+ );
43
+
44
+ return {
45
+ record: image.toRecord(),
46
+ __subscriptions: [image.sessionId],
47
+ requestId: "",
48
+ };
49
+ },
50
+
51
+ async get(imageId: string): Promise<ImageGetResponse> {
52
+ const record = await platform.imageRepository.findImageById(imageId);
53
+ return {
54
+ record,
55
+ __subscriptions: record?.sessionId ? [record.sessionId] : undefined,
56
+ requestId: "",
57
+ };
58
+ },
59
+
60
+ async list(containerId?: string): Promise<ImageListResponse> {
61
+ const records = containerId
62
+ ? await platform.imageRepository.findImagesByContainerId(containerId)
63
+ : await platform.imageRepository.findAllImages();
64
+
65
+ return {
66
+ records,
67
+ __subscriptions: records.map((r) => r.sessionId),
68
+ requestId: "",
69
+ };
70
+ },
71
+
72
+ async update(
73
+ imageId: string,
74
+ updates: {
75
+ name?: string;
76
+ description?: string;
77
+ customData?: Record<string, unknown>;
78
+ }
79
+ ): Promise<ImageUpdateResponse> {
80
+ const { loadImage } = await import("@agentxjs/core/image");
81
+ const { imageRepository, sessionRepository } = platform;
82
+
83
+ const image = await loadImage(imageId, { imageRepository, sessionRepository });
84
+ if (!image) {
85
+ throw new Error(`Image not found: ${imageId}`);
86
+ }
87
+
88
+ const updated = await image.update(updates);
89
+ return { record: updated.toRecord(), requestId: "" };
90
+ },
91
+
92
+ async delete(imageId: string): Promise<BaseResponse> {
93
+ const { loadImage } = await import("@agentxjs/core/image");
94
+ const { imageRepository, sessionRepository } = platform;
95
+
96
+ const image = await loadImage(imageId, { imageRepository, sessionRepository });
97
+ if (image) {
98
+ await image.delete();
99
+ }
100
+
101
+ return { requestId: "" };
102
+ },
103
+ };
104
+ }
105
+
106
+ /**
107
+ * Create remote image namespace backed by RPC client
108
+ */
109
+ export function createRemoteImages(
110
+ rpcClient: RpcClient,
111
+ subscribeFn: (sessionId: string) => void
112
+ ): ImageNamespace {
113
+ return {
114
+ async create(params: {
115
+ containerId: string;
116
+ name?: string;
117
+ description?: string;
118
+ systemPrompt?: string;
119
+ mcpServers?: Record<string, unknown>;
120
+ customData?: Record<string, unknown>;
121
+ }): Promise<ImageCreateResponse> {
122
+ const result = await rpcClient.call<ImageCreateResponse>("image.create", params);
123
+
124
+ // Auto subscribe to session events
125
+ if (result.__subscriptions) {
126
+ for (const sessionId of result.__subscriptions) {
127
+ subscribeFn(sessionId);
128
+ }
129
+ }
130
+
131
+ return { ...result, requestId: "" };
132
+ },
133
+
134
+ async get(imageId: string): Promise<ImageGetResponse> {
135
+ const result = await rpcClient.call<ImageGetResponse>("image.get", { imageId });
136
+
137
+ // Auto subscribe
138
+ if (result.__subscriptions) {
139
+ for (const sessionId of result.__subscriptions) {
140
+ subscribeFn(sessionId);
141
+ }
142
+ }
143
+
144
+ return { ...result, requestId: "" };
145
+ },
146
+
147
+ async list(containerId?: string): Promise<ImageListResponse> {
148
+ const result = await rpcClient.call<ImageListResponse>("image.list", { containerId });
149
+
150
+ // Auto subscribe
151
+ if (result.__subscriptions) {
152
+ for (const sessionId of result.__subscriptions) {
153
+ subscribeFn(sessionId);
154
+ }
155
+ }
156
+
157
+ return { ...result, requestId: "" };
158
+ },
159
+
160
+ async update(
161
+ imageId: string,
162
+ updates: {
163
+ name?: string;
164
+ description?: string;
165
+ customData?: Record<string, unknown>;
166
+ }
167
+ ): Promise<ImageUpdateResponse> {
168
+ const result = await rpcClient.call<ImageUpdateResponse>("image.update", {
169
+ imageId,
170
+ updates,
171
+ });
172
+ return { ...result, requestId: "" };
173
+ },
174
+
175
+ async delete(imageId: string): Promise<BaseResponse> {
176
+ const result = await rpcClient.call<BaseResponse>("image.delete", { imageId });
177
+ return { ...result, requestId: "" };
178
+ },
179
+ };
180
+ }
@@ -0,0 +1,22 @@
1
+ /**
2
+ * Presentation namespace factory
3
+ *
4
+ * Single factory for both local and remote modes —
5
+ * Presentation only depends on the AgentX interface.
6
+ */
7
+
8
+ import type { AgentX, PresentationNamespace } from "../types";
9
+ import { Presentation, type PresentationOptions, messagesToConversations } from "../presentation";
10
+
11
+ /**
12
+ * Create presentation namespace backed by any AgentX client
13
+ */
14
+ export function createPresentations(agentx: AgentX): PresentationNamespace {
15
+ return {
16
+ async create(agentId: string, options?: PresentationOptions): Promise<Presentation> {
17
+ const messages = await agentx.sessions.getMessages(agentId);
18
+ const conversations = messagesToConversations(messages);
19
+ return new Presentation(agentx, agentId, options, conversations);
20
+ },
21
+ };
22
+ }
@@ -0,0 +1,60 @@
1
+ /**
2
+ * Session namespace factories (messaging)
3
+ */
4
+
5
+ import type { AgentXRuntime } from "@agentxjs/core/runtime";
6
+ import type { UserContentPart, Message } from "@agentxjs/core/agent";
7
+ import type { RpcClient } from "@agentxjs/core/network";
8
+ import type { SessionNamespace, MessageSendResponse, BaseResponse, AgentInfo } from "../types";
9
+
10
+ /**
11
+ * Create local session namespace backed by embedded runtime
12
+ */
13
+ export function createLocalSessions(runtime: AgentXRuntime): SessionNamespace {
14
+ return {
15
+ async send(agentId: string, content: string | unknown[]): Promise<MessageSendResponse> {
16
+ await runtime.receive(agentId, content as string | UserContentPart[]);
17
+ return { agentId, requestId: "" };
18
+ },
19
+
20
+ async interrupt(agentId: string): Promise<BaseResponse> {
21
+ runtime.interrupt(agentId);
22
+ return { requestId: "" };
23
+ },
24
+
25
+ async getMessages(agentId: string): Promise<Message[]> {
26
+ const agent = runtime.getAgent(agentId);
27
+ if (!agent) return [];
28
+ return runtime.platform.sessionRepository.getMessages(agent.sessionId);
29
+ },
30
+ };
31
+ }
32
+
33
+ /**
34
+ * Create remote session namespace backed by RPC client
35
+ */
36
+ export function createRemoteSessions(rpcClient: RpcClient): SessionNamespace {
37
+ return {
38
+ async send(agentId: string, content: string | unknown[]): Promise<MessageSendResponse> {
39
+ const result = await rpcClient.call<MessageSendResponse>("message.send", {
40
+ agentId,
41
+ content,
42
+ });
43
+ return { ...result, requestId: "" };
44
+ },
45
+
46
+ async interrupt(agentId: string): Promise<BaseResponse> {
47
+ const result = await rpcClient.call<BaseResponse>("agent.interrupt", { agentId });
48
+ return { ...result, requestId: "" };
49
+ },
50
+
51
+ async getMessages(agentId: string): Promise<Message[]> {
52
+ const agentRes = await rpcClient.call<{ agent: AgentInfo | null }>("agent.get", { agentId });
53
+ if (!agentRes.agent) return [];
54
+ const msgRes = await rpcClient.call<{ messages: Message[] }>("image.messages", {
55
+ imageId: agentRes.agent.imageId,
56
+ });
57
+ return msgRes.messages ?? [];
58
+ },
59
+ };
60
+ }