agentxjs 2.9.0-dev-20260317033749 → 2.9.0-dev-20260317042246
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.d.ts +49 -81
- package/dist/index.js +98 -112
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
- package/src/index.ts +4 -2
- package/src/presentation/Presentation.ts +162 -160
- package/src/presentation/__tests__/status-transitions.test.ts +205 -0
- package/src/presentation/__tests__/tool-e2e.test.ts +205 -0
- package/src/presentation/__tests__/tool-roundtrip.test.ts +222 -0
- package/src/presentation/__tests__/workspace-init.test.ts +20 -44
- package/src/presentation/index.ts +1 -2
package/dist/index.d.ts
CHANGED
|
@@ -3,7 +3,7 @@ import { AgentXPlatform } from '@agentxjs/core/runtime';
|
|
|
3
3
|
import { UserContentPart, Message } from '@agentxjs/core/agent';
|
|
4
4
|
import { AgentXError } from '@agentxjs/core/error';
|
|
5
5
|
export { AgentXError, AgentXErrorCategory, AgentXErrorCode, AgentXErrorContext } from '@agentxjs/core/error';
|
|
6
|
-
import {
|
|
6
|
+
import { BusEvent, EventBus, BusEventHandler, Unsubscribe } from '@agentxjs/core/event';
|
|
7
7
|
import { LLMProtocol, LLMProviderRecord } from '@agentxjs/core/persistence';
|
|
8
8
|
export { Capability, Context, ContextProvider } from '@agentxjs/core/context';
|
|
9
9
|
|
|
@@ -206,99 +206,67 @@ declare const initialMetrics: PresentationMetrics;
|
|
|
206
206
|
declare const initialPresentationState: PresentationState;
|
|
207
207
|
|
|
208
208
|
/**
|
|
209
|
-
*
|
|
210
|
-
*
|
|
211
|
-
* High-level API for UI integration.
|
|
212
|
-
* Wraps AgentX client and provides presentation state management.
|
|
213
|
-
*/
|
|
214
|
-
|
|
215
|
-
/**
|
|
216
|
-
* Presentation update handler
|
|
217
|
-
*/
|
|
218
|
-
type PresentationUpdateHandler = (state: PresentationState) => void;
|
|
219
|
-
/**
|
|
220
|
-
* Presentation error handler
|
|
209
|
+
* Workspace — file tree + operations, unified.
|
|
221
210
|
*/
|
|
222
|
-
|
|
211
|
+
interface Workspace {
|
|
212
|
+
/** Current file tree (real-time updates) */
|
|
213
|
+
readonly files: readonly FileTreeEntry[];
|
|
214
|
+
/** Read file content */
|
|
215
|
+
read(path: string): Promise<string>;
|
|
216
|
+
/** Write content to file */
|
|
217
|
+
write(path: string, content: string): Promise<void>;
|
|
218
|
+
/** List directory entries */
|
|
219
|
+
list(path?: string): Promise<FileTreeEntry[]>;
|
|
220
|
+
}
|
|
223
221
|
/**
|
|
224
|
-
* Presentation
|
|
222
|
+
* Options for creating a Presentation
|
|
225
223
|
*/
|
|
226
224
|
interface PresentationOptions {
|
|
227
|
-
/**
|
|
228
|
-
|
|
229
|
-
*/
|
|
230
|
-
onUpdate?: PresentationUpdateHandler;
|
|
231
|
-
/**
|
|
232
|
-
* Called on errors
|
|
233
|
-
*/
|
|
234
|
-
onError?: PresentationErrorHandler;
|
|
225
|
+
/** Called on every state change (legacy — prefer subscribe) */
|
|
226
|
+
onUpdate?: (state: PresentationState) => void;
|
|
235
227
|
}
|
|
236
|
-
/**
|
|
237
|
-
* Presentation - UI-friendly wrapper for AgentX
|
|
238
|
-
*/
|
|
239
228
|
declare class Presentation {
|
|
240
|
-
private
|
|
241
|
-
private
|
|
242
|
-
private
|
|
243
|
-
private
|
|
244
|
-
private
|
|
245
|
-
private
|
|
246
|
-
|
|
247
|
-
* Workspace operations — read, write, list files in the agent's workspace.
|
|
248
|
-
* null when the agent has no workspace.
|
|
249
|
-
*/
|
|
250
|
-
readonly workspace: PresentationWorkspace | null;
|
|
229
|
+
private _agentx;
|
|
230
|
+
private _instanceId;
|
|
231
|
+
private _state;
|
|
232
|
+
private _listeners;
|
|
233
|
+
private _legacyHandlers;
|
|
234
|
+
private _eventUnsubscribe;
|
|
235
|
+
private _workspaceOps;
|
|
251
236
|
constructor(agentx: AgentX, instanceId: string, options?: PresentationOptions, initialConversations?: Conversation[], workspace?: PresentationWorkspace | null);
|
|
252
|
-
/**
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
/**
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
/**
|
|
261
|
-
|
|
237
|
+
/** All conversations (user, assistant, error) */
|
|
238
|
+
get conversations(): readonly Conversation[];
|
|
239
|
+
/** Current agent status */
|
|
240
|
+
get status(): PresentationState["status"];
|
|
241
|
+
/** WebSocket connection state */
|
|
242
|
+
get connection(): ConnectionState;
|
|
243
|
+
/** Token usage and context metrics */
|
|
244
|
+
get metrics(): PresentationMetrics;
|
|
245
|
+
/** Workspace — file tree + operations. null if agent has no workspace. */
|
|
246
|
+
get workspace(): Workspace | null;
|
|
247
|
+
/**
|
|
248
|
+
* Subscribe to state changes.
|
|
249
|
+
* Compatible with React's useSyncExternalStore.
|
|
250
|
+
* Does NOT call listener immediately.
|
|
251
|
+
*
|
|
252
|
+
* @returns Unsubscribe function
|
|
262
253
|
*/
|
|
263
|
-
|
|
254
|
+
subscribe(listener: () => void): () => void;
|
|
264
255
|
/**
|
|
265
|
-
*
|
|
256
|
+
* Get state snapshot.
|
|
257
|
+
* Compatible with React's useSyncExternalStore.
|
|
266
258
|
*/
|
|
259
|
+
getSnapshot(): PresentationState;
|
|
260
|
+
/** Send a message */
|
|
267
261
|
send(content: string | UserContentPart[]): Promise<void>;
|
|
268
|
-
/**
|
|
269
|
-
* Interrupt current response
|
|
270
|
-
*/
|
|
262
|
+
/** Interrupt current response */
|
|
271
263
|
interrupt(): Promise<void>;
|
|
272
|
-
/**
|
|
273
|
-
* Rewind conversation to a specific index.
|
|
274
|
-
*
|
|
275
|
-
* Calls runtime.rewind — a system-level operation that:
|
|
276
|
-
* 1. Truncates session messages
|
|
277
|
-
* 2. Resets circuit breaker
|
|
278
|
-
* 3. Emits rewind event → reducer updates state
|
|
279
|
-
*
|
|
280
|
-
* @param index - conversation index to rewind to (0-based, removes this index and after)
|
|
281
|
-
*/
|
|
264
|
+
/** Rewind conversation to a specific index (removes index and everything after) */
|
|
282
265
|
rewind(index: number): Promise<void>;
|
|
283
|
-
/**
|
|
284
|
-
* Edit a user message and resend.
|
|
285
|
-
* Rewinds to the message, replaces it, and sends the new content.
|
|
286
|
-
*
|
|
287
|
-
* @param index - conversation index of the user message to edit (0-based)
|
|
288
|
-
* @param content - new content to send
|
|
289
|
-
*/
|
|
290
|
-
editAndResend(index: number, content: string | UserContentPart[]): Promise<void>;
|
|
291
|
-
/**
|
|
292
|
-
* Reset state
|
|
293
|
-
*/
|
|
294
|
-
reset(): void;
|
|
295
|
-
/**
|
|
296
|
-
* Dispose and cleanup
|
|
297
|
-
*/
|
|
266
|
+
/** Dispose and cleanup all subscriptions */
|
|
298
267
|
dispose(): void;
|
|
299
|
-
private
|
|
300
|
-
private
|
|
301
|
-
private notifyError;
|
|
268
|
+
private _subscribeToEvents;
|
|
269
|
+
private _notify;
|
|
302
270
|
}
|
|
303
271
|
|
|
304
272
|
/**
|
|
@@ -840,4 +808,4 @@ interface PlatformConfig {
|
|
|
840
808
|
*/
|
|
841
809
|
declare function createAgentX(config?: PlatformConfig): AgentXBuilder;
|
|
842
810
|
|
|
843
|
-
export { type AgentConfig, type AgentHandle, type AgentX, type AgentXBuilder, type AgentXServer, type AssistantConversation, type BaseResponse, type Block, type ChatNamespace, type ConnectOptions, type Conversation, type ErrorConversation, type FileBlock, type ImageBlock, type ImageCreateResponse, type ImageGetResponse, type ImageListResponse, type ImageNamespace, type ImageRecord, type ImageUpdateResponse, type InstanceCreateResponse, type InstanceGetResponse, type InstanceInfo, type InstanceListResponse, type LLMNamespace, type LLMProviderCreateResponse, type LLMProviderDefaultResponse, type LLMProviderGetResponse, type LLMProviderListResponse, type LLMProviderUpdateResponse, type MaybeAsync, type MessageSendResponse, type PlatformConfig, Presentation, type
|
|
811
|
+
export { type AgentConfig, type AgentHandle, type AgentX, type AgentXBuilder, type AgentXServer, type AssistantConversation, type BaseResponse, type Block, type ChatNamespace, type ConnectOptions, type Conversation, type ErrorConversation, type FileBlock, type FileTreeEntry, type ImageBlock, type ImageCreateResponse, type ImageGetResponse, type ImageListResponse, type ImageNamespace, type ImageRecord, type ImageUpdateResponse, type InstanceCreateResponse, type InstanceGetResponse, type InstanceInfo, type InstanceListResponse, type LLMNamespace, type LLMProviderCreateResponse, type LLMProviderDefaultResponse, type LLMProviderGetResponse, type LLMProviderListResponse, type LLMProviderUpdateResponse, type MaybeAsync, type MessageSendResponse, type PlatformConfig, Presentation, type PresentationMetrics, type PresentationNamespace, type PresentationOptions, type PresentationState, type PresentationWorkspace, type RuntimeNamespace, type ServeConfig, type SessionNamespace, type TextBlock, type ThinkingBlock, type ToolBlock, type UserConversation, type Workspace, type WorkspaceState, addUserConversation, createAgentX, createInitialState, initialMetrics, initialPresentationState, messagesToConversations, presentationReducer };
|
package/dist/index.js
CHANGED
|
@@ -741,103 +741,111 @@ function messagesToConversations(messages) {
|
|
|
741
741
|
|
|
742
742
|
// src/presentation/Presentation.ts
|
|
743
743
|
var Presentation = class {
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
* Workspace operations — read, write, list files in the agent's workspace.
|
|
752
|
-
* null when the agent has no workspace.
|
|
753
|
-
*/
|
|
754
|
-
workspace;
|
|
744
|
+
_agentx;
|
|
745
|
+
_instanceId;
|
|
746
|
+
_state;
|
|
747
|
+
_listeners = /* @__PURE__ */ new Set();
|
|
748
|
+
_legacyHandlers = /* @__PURE__ */ new Set();
|
|
749
|
+
_eventUnsubscribe = null;
|
|
750
|
+
_workspaceOps;
|
|
755
751
|
constructor(agentx, instanceId, options, initialConversations, workspace) {
|
|
756
|
-
this.
|
|
757
|
-
this.
|
|
758
|
-
this.
|
|
759
|
-
this.
|
|
752
|
+
this._agentx = agentx;
|
|
753
|
+
this._instanceId = instanceId;
|
|
754
|
+
this._workspaceOps = workspace ?? null;
|
|
755
|
+
this._state = initialConversations?.length ? { ...initialPresentationState, conversations: initialConversations } : createInitialState();
|
|
760
756
|
if (options?.onUpdate) {
|
|
761
|
-
this.
|
|
757
|
+
this._legacyHandlers.add(options.onUpdate);
|
|
762
758
|
}
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
this.workspace.list(".").then((files) => {
|
|
769
|
-
this.state = { ...this.state, workspace: { files } };
|
|
770
|
-
this.notify();
|
|
759
|
+
this._subscribeToEvents();
|
|
760
|
+
if (this._workspaceOps) {
|
|
761
|
+
this._workspaceOps.list(".").then((files) => {
|
|
762
|
+
this._state = { ...this._state, workspace: { files } };
|
|
763
|
+
this._notify();
|
|
771
764
|
});
|
|
772
765
|
}
|
|
773
766
|
}
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
return this.state;
|
|
767
|
+
// ==================== State (direct properties) ====================
|
|
768
|
+
/** All conversations (user, assistant, error) */
|
|
769
|
+
get conversations() {
|
|
770
|
+
return this._state.conversations;
|
|
779
771
|
}
|
|
780
|
-
/**
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
return
|
|
787
|
-
|
|
772
|
+
/** Current agent status */
|
|
773
|
+
get status() {
|
|
774
|
+
return this._state.status;
|
|
775
|
+
}
|
|
776
|
+
/** WebSocket connection state */
|
|
777
|
+
get connection() {
|
|
778
|
+
return this._state.connection;
|
|
779
|
+
}
|
|
780
|
+
/** Token usage and context metrics */
|
|
781
|
+
get metrics() {
|
|
782
|
+
return this._state.metrics;
|
|
783
|
+
}
|
|
784
|
+
/** Workspace — file tree + operations. null if agent has no workspace. */
|
|
785
|
+
get workspace() {
|
|
786
|
+
if (!this._workspaceOps) return null;
|
|
787
|
+
const ops = this._workspaceOps;
|
|
788
|
+
const wsState = this._state.workspace;
|
|
789
|
+
return {
|
|
790
|
+
get files() {
|
|
791
|
+
return wsState?.files ?? [];
|
|
792
|
+
},
|
|
793
|
+
read: (path) => ops.read(path),
|
|
794
|
+
write: (path, content) => ops.write(path, content),
|
|
795
|
+
list: (path) => ops.list(path)
|
|
788
796
|
};
|
|
789
797
|
}
|
|
798
|
+
// ==================== Subscribe ====================
|
|
790
799
|
/**
|
|
791
|
-
* Subscribe to
|
|
800
|
+
* Subscribe to state changes.
|
|
801
|
+
* Compatible with React's useSyncExternalStore.
|
|
802
|
+
* Does NOT call listener immediately.
|
|
803
|
+
*
|
|
804
|
+
* @returns Unsubscribe function
|
|
792
805
|
*/
|
|
793
|
-
|
|
794
|
-
this.
|
|
806
|
+
subscribe(listener) {
|
|
807
|
+
this._listeners.add(listener);
|
|
795
808
|
return () => {
|
|
796
|
-
this.
|
|
809
|
+
this._listeners.delete(listener);
|
|
797
810
|
};
|
|
798
811
|
}
|
|
799
812
|
/**
|
|
800
|
-
*
|
|
813
|
+
* Get state snapshot.
|
|
814
|
+
* Compatible with React's useSyncExternalStore.
|
|
801
815
|
*/
|
|
816
|
+
getSnapshot() {
|
|
817
|
+
return this._state;
|
|
818
|
+
}
|
|
819
|
+
// ==================== Actions ====================
|
|
820
|
+
/** Send a message */
|
|
802
821
|
async send(content) {
|
|
803
|
-
this.
|
|
804
|
-
this.
|
|
822
|
+
this._state = addUserConversation(this._state, content);
|
|
823
|
+
this._notify();
|
|
805
824
|
await new Promise((resolve) => setTimeout(resolve, 0));
|
|
806
825
|
try {
|
|
807
|
-
await this.
|
|
826
|
+
await this._agentx.runtime.session.send(this._instanceId, content);
|
|
808
827
|
} catch (error) {
|
|
809
|
-
|
|
828
|
+
console.error("Presentation send error:", error);
|
|
810
829
|
}
|
|
811
830
|
}
|
|
812
|
-
/**
|
|
813
|
-
* Interrupt current response
|
|
814
|
-
*/
|
|
831
|
+
/** Interrupt current response */
|
|
815
832
|
async interrupt() {
|
|
816
833
|
try {
|
|
817
|
-
await this.
|
|
834
|
+
await this._agentx.runtime.session.interrupt(this._instanceId);
|
|
818
835
|
} catch (error) {
|
|
819
|
-
|
|
836
|
+
console.error("Presentation interrupt error:", error);
|
|
820
837
|
}
|
|
821
838
|
}
|
|
822
|
-
/**
|
|
823
|
-
* Rewind conversation to a specific index.
|
|
824
|
-
*
|
|
825
|
-
* Calls runtime.rewind — a system-level operation that:
|
|
826
|
-
* 1. Truncates session messages
|
|
827
|
-
* 2. Resets circuit breaker
|
|
828
|
-
* 3. Emits rewind event → reducer updates state
|
|
829
|
-
*
|
|
830
|
-
* @param index - conversation index to rewind to (0-based, removes this index and after)
|
|
831
|
-
*/
|
|
839
|
+
/** Rewind conversation to a specific index (removes index and everything after) */
|
|
832
840
|
async rewind(index) {
|
|
833
|
-
const conversations = this.
|
|
841
|
+
const conversations = this._state.conversations;
|
|
834
842
|
if (index < 0 || index >= conversations.length) return;
|
|
835
843
|
try {
|
|
836
|
-
const messages = await this.
|
|
844
|
+
const messages = await this._agentx.runtime.session.getMessages(this._instanceId);
|
|
837
845
|
if (messages.length === 0) return;
|
|
838
846
|
if (index === 0) {
|
|
839
|
-
await this.
|
|
840
|
-
imageId: this.
|
|
847
|
+
await this._agentx.rpc("runtime.rewind", {
|
|
848
|
+
imageId: this._instanceId,
|
|
841
849
|
messageId: messages[0].id
|
|
842
850
|
});
|
|
843
851
|
} else {
|
|
@@ -853,78 +861,56 @@ var Presentation = class {
|
|
|
853
861
|
}
|
|
854
862
|
}
|
|
855
863
|
if (msgIndex >= 0 && msgIndex < messages.length) {
|
|
856
|
-
await this.
|
|
857
|
-
imageId: this.
|
|
864
|
+
await this._agentx.rpc("runtime.rewind", {
|
|
865
|
+
imageId: this._instanceId,
|
|
858
866
|
messageId: messages[msgIndex].id
|
|
859
867
|
});
|
|
860
868
|
}
|
|
861
869
|
}
|
|
862
870
|
} catch (error) {
|
|
863
|
-
|
|
871
|
+
console.error("Presentation rewind error:", error);
|
|
864
872
|
}
|
|
865
873
|
}
|
|
866
|
-
/**
|
|
867
|
-
* Edit a user message and resend.
|
|
868
|
-
* Rewinds to the message, replaces it, and sends the new content.
|
|
869
|
-
*
|
|
870
|
-
* @param index - conversation index of the user message to edit (0-based)
|
|
871
|
-
* @param content - new content to send
|
|
872
|
-
*/
|
|
873
|
-
async editAndResend(index, content) {
|
|
874
|
-
await this.rewind(index);
|
|
875
|
-
await this.send(content);
|
|
876
|
-
}
|
|
877
|
-
/**
|
|
878
|
-
* Reset state
|
|
879
|
-
*/
|
|
880
|
-
reset() {
|
|
881
|
-
this.state = createInitialState();
|
|
882
|
-
this.notify();
|
|
883
|
-
}
|
|
884
|
-
/**
|
|
885
|
-
* Dispose and cleanup
|
|
886
|
-
*/
|
|
874
|
+
/** Dispose and cleanup all subscriptions */
|
|
887
875
|
dispose() {
|
|
888
|
-
if (this.
|
|
889
|
-
this.
|
|
890
|
-
this.
|
|
876
|
+
if (this._eventUnsubscribe) {
|
|
877
|
+
this._eventUnsubscribe();
|
|
878
|
+
this._eventUnsubscribe = null;
|
|
891
879
|
}
|
|
892
|
-
this.
|
|
893
|
-
this.
|
|
880
|
+
this._listeners.clear();
|
|
881
|
+
this._legacyHandlers.clear();
|
|
894
882
|
}
|
|
895
883
|
// ==================== Private ====================
|
|
896
|
-
|
|
897
|
-
this.
|
|
884
|
+
_subscribeToEvents() {
|
|
885
|
+
this._eventUnsubscribe = this._agentx.onAny((event) => {
|
|
898
886
|
const eventWithContext = event;
|
|
899
887
|
const eventAgentId = eventWithContext.context?.instanceId;
|
|
900
|
-
if (eventAgentId && eventAgentId !== this.
|
|
888
|
+
if (eventAgentId && eventAgentId !== this._instanceId) {
|
|
901
889
|
const eventImageId = eventWithContext.context?.imageId;
|
|
902
|
-
if (!eventImageId || eventImageId !== this.
|
|
890
|
+
if (!eventImageId || eventImageId !== this._instanceId) {
|
|
903
891
|
return;
|
|
904
892
|
}
|
|
905
893
|
}
|
|
906
|
-
const newState = presentationReducer(this.
|
|
907
|
-
if (newState !== this.
|
|
908
|
-
this.
|
|
909
|
-
this.
|
|
894
|
+
const newState = presentationReducer(this._state, event);
|
|
895
|
+
if (newState !== this._state) {
|
|
896
|
+
this._state = newState;
|
|
897
|
+
this._notify();
|
|
910
898
|
}
|
|
911
899
|
});
|
|
912
900
|
}
|
|
913
|
-
|
|
914
|
-
for (const
|
|
901
|
+
_notify() {
|
|
902
|
+
for (const listener of this._listeners) {
|
|
915
903
|
try {
|
|
916
|
-
|
|
904
|
+
listener();
|
|
917
905
|
} catch (error) {
|
|
918
|
-
console.error("Presentation
|
|
906
|
+
console.error("Presentation listener error:", error);
|
|
919
907
|
}
|
|
920
908
|
}
|
|
921
|
-
|
|
922
|
-
notifyError(error) {
|
|
923
|
-
for (const handler of this.errorHandlers) {
|
|
909
|
+
for (const handler of this._legacyHandlers) {
|
|
924
910
|
try {
|
|
925
|
-
handler(
|
|
926
|
-
} catch (
|
|
927
|
-
console.error("Presentation
|
|
911
|
+
handler(this._state);
|
|
912
|
+
} catch (error) {
|
|
913
|
+
console.error("Presentation handler error:", error);
|
|
928
914
|
}
|
|
929
915
|
}
|
|
930
916
|
}
|