agentxjs 0.0.0-dev-20260312143810

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.
@@ -0,0 +1,192 @@
1
+ /**
2
+ * Image namespace factories
3
+ */
4
+
5
+ import type { Message } from "@agentxjs/core/agent";
6
+ import type { RpcClient } from "@agentxjs/core/network";
7
+ import type { AgentXPlatform } from "@agentxjs/core/runtime";
8
+ import type {
9
+ BaseResponse,
10
+ ImageCreateResponse,
11
+ ImageGetResponse,
12
+ ImageListResponse,
13
+ ImageNamespace,
14
+ ImageUpdateResponse,
15
+ } from "../types";
16
+
17
+ /**
18
+ * Create local image namespace backed by embedded runtime
19
+ */
20
+ export function createLocalImages(platform: AgentXPlatform): ImageNamespace {
21
+ return {
22
+ async create(params: {
23
+ containerId: string;
24
+ name?: string;
25
+ description?: string;
26
+ systemPrompt?: string;
27
+ mcpServers?: Record<string, unknown>;
28
+ customData?: Record<string, unknown>;
29
+ }): Promise<ImageCreateResponse> {
30
+ const { imageRepository, sessionRepository } = platform;
31
+ const { createImage } = await import("@agentxjs/core/image");
32
+
33
+ const image = await createImage(
34
+ {
35
+ containerId: params.containerId,
36
+ name: params.name,
37
+ description: params.description,
38
+ systemPrompt: params.systemPrompt,
39
+ mcpServers: params.mcpServers as any,
40
+ customData: params.customData,
41
+ },
42
+ { imageRepository, sessionRepository }
43
+ );
44
+
45
+ return {
46
+ record: image.toRecord(),
47
+ __subscriptions: [image.sessionId],
48
+ requestId: "",
49
+ };
50
+ },
51
+
52
+ async get(imageId: string): Promise<ImageGetResponse> {
53
+ const record = await platform.imageRepository.findImageById(imageId);
54
+ return {
55
+ record,
56
+ __subscriptions: record?.sessionId ? [record.sessionId] : undefined,
57
+ requestId: "",
58
+ };
59
+ },
60
+
61
+ async list(containerId?: string): Promise<ImageListResponse> {
62
+ const records = containerId
63
+ ? await platform.imageRepository.findImagesByContainerId(containerId)
64
+ : await platform.imageRepository.findAllImages();
65
+
66
+ return {
67
+ records,
68
+ __subscriptions: records.map((r) => r.sessionId),
69
+ requestId: "",
70
+ };
71
+ },
72
+
73
+ async update(
74
+ imageId: string,
75
+ updates: {
76
+ name?: string;
77
+ description?: string;
78
+ customData?: Record<string, unknown>;
79
+ }
80
+ ): Promise<ImageUpdateResponse> {
81
+ const { loadImage } = await import("@agentxjs/core/image");
82
+ const { imageRepository, sessionRepository } = platform;
83
+
84
+ const image = await loadImage(imageId, { imageRepository, sessionRepository });
85
+ if (!image) {
86
+ throw new Error(`Image not found: ${imageId}`);
87
+ }
88
+
89
+ const updated = await image.update(updates);
90
+ return { record: updated.toRecord(), requestId: "" };
91
+ },
92
+
93
+ async delete(imageId: string): Promise<BaseResponse> {
94
+ const { loadImage } = await import("@agentxjs/core/image");
95
+ const { imageRepository, sessionRepository } = platform;
96
+
97
+ const image = await loadImage(imageId, { imageRepository, sessionRepository });
98
+ if (image) {
99
+ await image.delete();
100
+ }
101
+
102
+ return { requestId: "" };
103
+ },
104
+
105
+ async getMessages(imageId: string): Promise<Message[]> {
106
+ const imageRecord = await platform.imageRepository.findImageById(imageId);
107
+ if (!imageRecord) return [];
108
+ return platform.sessionRepository.getMessages(imageRecord.sessionId);
109
+ },
110
+ };
111
+ }
112
+
113
+ /**
114
+ * Create remote image namespace backed by RPC client
115
+ */
116
+ export function createRemoteImages(
117
+ rpcClient: RpcClient,
118
+ subscribeFn: (sessionId: string) => void
119
+ ): ImageNamespace {
120
+ return {
121
+ async create(params: {
122
+ containerId: string;
123
+ name?: string;
124
+ description?: string;
125
+ systemPrompt?: string;
126
+ mcpServers?: Record<string, unknown>;
127
+ customData?: Record<string, unknown>;
128
+ }): Promise<ImageCreateResponse> {
129
+ const result = await rpcClient.call<ImageCreateResponse>("image.create", params);
130
+
131
+ // Auto subscribe to session events
132
+ if (result.__subscriptions) {
133
+ for (const sessionId of result.__subscriptions) {
134
+ subscribeFn(sessionId);
135
+ }
136
+ }
137
+
138
+ return { ...result, requestId: "" };
139
+ },
140
+
141
+ async get(imageId: string): Promise<ImageGetResponse> {
142
+ const result = await rpcClient.call<ImageGetResponse>("image.get", { imageId });
143
+
144
+ // Auto subscribe
145
+ if (result.__subscriptions) {
146
+ for (const sessionId of result.__subscriptions) {
147
+ subscribeFn(sessionId);
148
+ }
149
+ }
150
+
151
+ return { ...result, requestId: "" };
152
+ },
153
+
154
+ async list(containerId?: string): Promise<ImageListResponse> {
155
+ const result = await rpcClient.call<ImageListResponse>("image.list", { containerId });
156
+
157
+ // Auto subscribe
158
+ if (result.__subscriptions) {
159
+ for (const sessionId of result.__subscriptions) {
160
+ subscribeFn(sessionId);
161
+ }
162
+ }
163
+
164
+ return { ...result, requestId: "" };
165
+ },
166
+
167
+ async update(
168
+ imageId: string,
169
+ updates: {
170
+ name?: string;
171
+ description?: string;
172
+ customData?: Record<string, unknown>;
173
+ }
174
+ ): Promise<ImageUpdateResponse> {
175
+ const result = await rpcClient.call<ImageUpdateResponse>("image.update", {
176
+ imageId,
177
+ updates,
178
+ });
179
+ return { ...result, requestId: "" };
180
+ },
181
+
182
+ async delete(imageId: string): Promise<BaseResponse> {
183
+ const result = await rpcClient.call<BaseResponse>("image.delete", { imageId });
184
+ return { ...result, requestId: "" };
185
+ },
186
+
187
+ async getMessages(imageId: string): Promise<Message[]> {
188
+ const result = await rpcClient.call<{ messages: Message[] }>("image.messages", { imageId });
189
+ return result.messages ?? [];
190
+ },
191
+ };
192
+ }
@@ -0,0 +1,140 @@
1
+ /**
2
+ * LLM Provider namespace factories
3
+ */
4
+
5
+ import type { RpcClient } from "@agentxjs/core/network";
6
+ import type { LLMProviderRecord } from "@agentxjs/core/persistence";
7
+ import type { AgentXPlatform } from "@agentxjs/core/runtime";
8
+ import { generateId } from "@deepracticex/id";
9
+ import type {
10
+ BaseResponse,
11
+ LLMNamespace,
12
+ LLMProviderCreateResponse,
13
+ LLMProviderDefaultResponse,
14
+ LLMProviderGetResponse,
15
+ LLMProviderListResponse,
16
+ LLMProviderUpdateResponse,
17
+ } from "../types";
18
+
19
+ /**
20
+ * Create local LLM namespace backed by platform repository
21
+ */
22
+ export function createLocalLLM(platform: AgentXPlatform): LLMNamespace {
23
+ const repo = platform.llmProviderRepository;
24
+ if (!repo) {
25
+ throw new Error("LLM provider repository not available on this platform");
26
+ }
27
+
28
+ return {
29
+ async create(params): Promise<LLMProviderCreateResponse> {
30
+ const now = Date.now();
31
+ const record: LLMProviderRecord = {
32
+ id: generateId("llm"),
33
+ containerId: params.containerId,
34
+ name: params.name,
35
+ vendor: params.vendor,
36
+ protocol: params.protocol,
37
+ apiKey: params.apiKey,
38
+ baseUrl: params.baseUrl,
39
+ model: params.model,
40
+ isDefault: false,
41
+ createdAt: now,
42
+ updatedAt: now,
43
+ };
44
+
45
+ await repo.saveLLMProvider(record);
46
+ return { record, requestId: "" };
47
+ },
48
+
49
+ async get(id: string): Promise<LLMProviderGetResponse> {
50
+ const record = await repo.findLLMProviderById(id);
51
+ return { record, requestId: "" };
52
+ },
53
+
54
+ async list(containerId: string): Promise<LLMProviderListResponse> {
55
+ const records = await repo.findLLMProvidersByContainerId(containerId);
56
+ return { records, requestId: "" };
57
+ },
58
+
59
+ async update(id, updates): Promise<LLMProviderUpdateResponse> {
60
+ const existing = await repo.findLLMProviderById(id);
61
+ if (!existing) {
62
+ throw new Error(`LLM provider not found: ${id}`);
63
+ }
64
+
65
+ const updated: LLMProviderRecord = {
66
+ ...existing,
67
+ ...updates,
68
+ id: existing.id,
69
+ containerId: existing.containerId,
70
+ createdAt: existing.createdAt,
71
+ updatedAt: Date.now(),
72
+ };
73
+
74
+ await repo.saveLLMProvider(updated);
75
+ return { record: updated, requestId: "" };
76
+ },
77
+
78
+ async delete(id: string): Promise<BaseResponse> {
79
+ await repo.deleteLLMProvider(id);
80
+ return { requestId: "" };
81
+ },
82
+
83
+ async setDefault(id: string): Promise<BaseResponse> {
84
+ await repo.setDefaultLLMProvider(id);
85
+ return { requestId: "" };
86
+ },
87
+
88
+ async getDefault(containerId: string): Promise<LLMProviderDefaultResponse> {
89
+ const record = await repo.findDefaultLLMProvider(containerId);
90
+ return { record, requestId: "" };
91
+ },
92
+ };
93
+ }
94
+
95
+ /**
96
+ * Create remote LLM namespace backed by RPC client
97
+ */
98
+ export function createRemoteLLM(rpcClient: RpcClient): LLMNamespace {
99
+ return {
100
+ async create(params): Promise<LLMProviderCreateResponse> {
101
+ const result = await rpcClient.call<LLMProviderCreateResponse>("llm.create", params);
102
+ return { ...result, requestId: "" };
103
+ },
104
+
105
+ async get(id: string): Promise<LLMProviderGetResponse> {
106
+ const result = await rpcClient.call<LLMProviderGetResponse>("llm.get", { id });
107
+ return { ...result, requestId: "" };
108
+ },
109
+
110
+ async list(containerId: string): Promise<LLMProviderListResponse> {
111
+ const result = await rpcClient.call<LLMProviderListResponse>("llm.list", { containerId });
112
+ return { ...result, requestId: "" };
113
+ },
114
+
115
+ async update(id, updates): Promise<LLMProviderUpdateResponse> {
116
+ const result = await rpcClient.call<LLMProviderUpdateResponse>("llm.update", {
117
+ id,
118
+ updates,
119
+ });
120
+ return { ...result, requestId: "" };
121
+ },
122
+
123
+ async delete(id: string): Promise<BaseResponse> {
124
+ const result = await rpcClient.call<BaseResponse>("llm.delete", { id });
125
+ return { ...result, requestId: "" };
126
+ },
127
+
128
+ async setDefault(id: string): Promise<BaseResponse> {
129
+ const result = await rpcClient.call<BaseResponse>("llm.default", { id });
130
+ return { ...result, requestId: "" };
131
+ },
132
+
133
+ async getDefault(containerId: string): Promise<LLMProviderDefaultResponse> {
134
+ const result = await rpcClient.call<LLMProviderDefaultResponse>("llm.default", {
135
+ containerId,
136
+ });
137
+ return { ...result, requestId: "" };
138
+ },
139
+ };
140
+ }
@@ -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 { messagesToConversations, Presentation, type PresentationOptions } from "../presentation";
9
+ import type { AgentX, PresentationNamespace } from "../types";
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.session.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 { Message, UserContentPart } from "@agentxjs/core/agent";
6
+ import type { RpcClient } from "@agentxjs/core/network";
7
+ import type { AgentXRuntime } from "@agentxjs/core/runtime";
8
+ import type { AgentInfo, BaseResponse, MessageSendResponse, SessionNamespace } 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
+ }
@@ -0,0 +1,193 @@
1
+ /**
2
+ * Presentation Class
3
+ *
4
+ * High-level API for UI integration.
5
+ * Wraps AgentX client and provides presentation state management.
6
+ */
7
+
8
+ import type { BusEvent, Unsubscribe } from "@agentxjs/core/event";
9
+ import type { AgentX } from "../types";
10
+ import { addUserConversation, createInitialState, presentationReducer } from "./reducer";
11
+ import type { Conversation, PresentationState } from "./types";
12
+ import { initialPresentationState } from "./types";
13
+
14
+ /**
15
+ * Presentation update handler
16
+ */
17
+ export type PresentationUpdateHandler = (state: PresentationState) => void;
18
+
19
+ /**
20
+ * Presentation error handler
21
+ */
22
+ export type PresentationErrorHandler = (error: Error) => void;
23
+
24
+ /**
25
+ * Presentation options
26
+ */
27
+ export interface PresentationOptions {
28
+ /**
29
+ * Called on every state update
30
+ */
31
+ onUpdate?: PresentationUpdateHandler;
32
+
33
+ /**
34
+ * Called on errors
35
+ */
36
+ onError?: PresentationErrorHandler;
37
+ }
38
+
39
+ /**
40
+ * Presentation - UI-friendly wrapper for AgentX
41
+ */
42
+ export class Presentation {
43
+ private agentx: AgentX;
44
+ private agentId: string;
45
+ private state: PresentationState;
46
+ private updateHandlers: Set<PresentationUpdateHandler> = new Set();
47
+ private errorHandlers: Set<PresentationErrorHandler> = new Set();
48
+ private eventUnsubscribe: Unsubscribe | null = null;
49
+
50
+ constructor(
51
+ agentx: AgentX,
52
+ agentId: string,
53
+ options?: PresentationOptions,
54
+ initialConversations?: Conversation[]
55
+ ) {
56
+ this.agentx = agentx;
57
+ this.agentId = agentId;
58
+ this.state = initialConversations?.length
59
+ ? { ...initialPresentationState, conversations: initialConversations }
60
+ : createInitialState();
61
+
62
+ // Register initial handlers
63
+ if (options?.onUpdate) {
64
+ this.updateHandlers.add(options.onUpdate);
65
+ }
66
+ if (options?.onError) {
67
+ this.errorHandlers.add(options.onError);
68
+ }
69
+
70
+ // Subscribe to all events
71
+ this.subscribeToEvents();
72
+ }
73
+
74
+ /**
75
+ * Get current state
76
+ */
77
+ getState(): PresentationState {
78
+ return this.state;
79
+ }
80
+
81
+ /**
82
+ * Subscribe to state updates
83
+ */
84
+ onUpdate(handler: PresentationUpdateHandler): Unsubscribe {
85
+ this.updateHandlers.add(handler);
86
+ // Immediately call with current state
87
+ handler(this.state);
88
+ return () => {
89
+ this.updateHandlers.delete(handler);
90
+ };
91
+ }
92
+
93
+ /**
94
+ * Subscribe to errors
95
+ */
96
+ onError(handler: PresentationErrorHandler): Unsubscribe {
97
+ this.errorHandlers.add(handler);
98
+ return () => {
99
+ this.errorHandlers.delete(handler);
100
+ };
101
+ }
102
+
103
+ /**
104
+ * Send a message
105
+ */
106
+ async send(content: string): Promise<void> {
107
+ // Add user conversation
108
+ this.state = addUserConversation(this.state, content);
109
+ this.notify();
110
+
111
+ try {
112
+ // Send message via agentx
113
+ await this.agentx.session.send(this.agentId, content);
114
+ } catch (error) {
115
+ this.notifyError(error instanceof Error ? error : new Error(String(error)));
116
+ }
117
+ }
118
+
119
+ /**
120
+ * Interrupt current response
121
+ */
122
+ async interrupt(): Promise<void> {
123
+ try {
124
+ await this.agentx.session.interrupt(this.agentId);
125
+ } catch (error) {
126
+ this.notifyError(error instanceof Error ? error : new Error(String(error)));
127
+ }
128
+ }
129
+
130
+ /**
131
+ * Reset state
132
+ */
133
+ reset(): void {
134
+ this.state = createInitialState();
135
+ this.notify();
136
+ }
137
+
138
+ /**
139
+ * Dispose and cleanup
140
+ */
141
+ dispose(): void {
142
+ if (this.eventUnsubscribe) {
143
+ this.eventUnsubscribe();
144
+ this.eventUnsubscribe = null;
145
+ }
146
+ this.updateHandlers.clear();
147
+ this.errorHandlers.clear();
148
+ }
149
+
150
+ // ==================== Private ====================
151
+
152
+ private subscribeToEvents(): void {
153
+ // Subscribe to all events and filter by agentId
154
+ this.eventUnsubscribe = this.agentx.onAny((event: BusEvent) => {
155
+ // Filter events for this agent (if context is available)
156
+ // Note: Events from server may or may not include context with agentId
157
+ const eventWithContext = event as BusEvent & { context?: { agentId?: string } };
158
+ const eventAgentId = eventWithContext.context?.agentId;
159
+
160
+ // Only filter if event has agentId and it doesn't match
161
+ if (eventAgentId && eventAgentId !== this.agentId) {
162
+ return;
163
+ }
164
+
165
+ // Reduce event into state
166
+ const newState = presentationReducer(this.state, event);
167
+ if (newState !== this.state) {
168
+ this.state = newState;
169
+ this.notify();
170
+ }
171
+ });
172
+ }
173
+
174
+ private notify(): void {
175
+ for (const handler of this.updateHandlers) {
176
+ try {
177
+ handler(this.state);
178
+ } catch (error) {
179
+ console.error("Presentation update handler error:", error);
180
+ }
181
+ }
182
+ }
183
+
184
+ private notifyError(error: Error): void {
185
+ for (const handler of this.errorHandlers) {
186
+ try {
187
+ handler(error);
188
+ } catch (e) {
189
+ console.error("Presentation error handler error:", e);
190
+ }
191
+ }
192
+ }
193
+ }
@@ -0,0 +1,31 @@
1
+ /**
2
+ * Presentation Module
3
+ *
4
+ * UI-friendly data model and state management.
5
+ */
6
+
7
+ export {
8
+ Presentation,
9
+ type PresentationErrorHandler,
10
+ type PresentationOptions,
11
+ type PresentationUpdateHandler,
12
+ } from "./Presentation";
13
+ export {
14
+ addUserConversation,
15
+ createInitialState,
16
+ messagesToConversations,
17
+ presentationReducer,
18
+ } from "./reducer";
19
+ export type {
20
+ AssistantConversation,
21
+ Block,
22
+ Conversation,
23
+ ErrorConversation,
24
+ ImageBlock,
25
+ PresentationState,
26
+ TextBlock,
27
+ TokenUsage,
28
+ ToolBlock,
29
+ UserConversation,
30
+ } from "./types";
31
+ export { initialPresentationState } from "./types";