@asgard-js/core 0.0.43-canary.9 → 0.0.44-canary.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.
@@ -1 +1 @@
1
- {"version":3,"file":"create-sse-observable.d.ts","sourceRoot":"","sources":["../../src/lib/create-sse-observable.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,MAAM,CAAC;AAKlC,OAAO,EAAE,eAAe,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AACxD,OAAO,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AAE9C,UAAU,0BAA0B;IAClC,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,OAAO,EAAE,eAAe,CAAC;CAC1B;AAED,wBAAgB,mBAAmB,CACjC,OAAO,EAAE,0BAA0B,GAClC,UAAU,CAAC,WAAW,CAAC,SAAS,CAAC,CAAC,CA8EpC"}
1
+ {"version":3,"file":"create-sse-observable.d.ts","sourceRoot":"","sources":["../../src/lib/create-sse-observable.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,MAAM,CAAC;AAKlC,OAAO,EAAE,eAAe,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AACxD,OAAO,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AAE9C,UAAU,0BAA0B;IAClC,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,OAAO,EAAE,eAAe,CAAC;CAC1B;AAED,wBAAgB,mBAAmB,CACjC,OAAO,EAAE,0BAA0B,GAClC,UAAU,CAAC,WAAW,CAAC,SAAS,CAAC,CAAC,CA2DpC"}
@@ -0,0 +1,2 @@
1
+ export type AuthState = 'loading' | 'needApiKey' | 'authenticated' | 'error' | 'invalidApiKey';
2
+ //# sourceMappingURL=auth.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../../src/types/auth.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,SAAS,GAAG,SAAS,GAAG,YAAY,GAAG,eAAe,GAAG,OAAO,GAAG,eAAe,CAAC"}
@@ -1,3 +1,4 @@
1
+ export type * from './auth';
1
2
  export type * from './client';
2
3
  export type * from './channel';
3
4
  export type * from './sse-response';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/types/index.ts"],"names":[],"mappings":"AAAA,mBAAmB,UAAU,CAAC;AAC9B,mBAAmB,WAAW,CAAC;AAC/B,mBAAmB,gBAAgB,CAAC;AACpC,mBAAmB,iBAAiB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/types/index.ts"],"names":[],"mappings":"AAAA,mBAAmB,QAAQ,CAAC;AAC5B,mBAAmB,UAAU,CAAC;AAC9B,mBAAmB,WAAW,CAAC;AAC/B,mBAAmB,gBAAgB,CAAC;AACpC,mBAAmB,iBAAiB,CAAC"}
package/package.json CHANGED
@@ -1,14 +1,18 @@
1
1
  {
2
2
  "name": "@asgard-js/core",
3
- "version": "0.0.43-canary.9",
3
+ "version": "0.0.44-canary.1",
4
4
  "dependencies": {
5
5
  "@microsoft/fetch-event-source": "^2.0.1",
6
6
  "rxjs": "^7.8.1"
7
7
  },
8
8
  "devDependencies": {
9
+ "@nx/js": "^21.5.3",
10
+ "@nx/react": "^21.5.3",
11
+ "@nx/vite": "^21.5.3",
9
12
  "@types/jsdom": "^21.1.6",
10
13
  "@vitest/ui": "^1.6.0",
11
14
  "jsdom": "^24.0.0",
15
+ "nx": "^21.5.3",
12
16
  "vitest": "^1.6.0"
13
17
  },
14
18
  "scripts": {
package/eslint.config.cjs DELETED
@@ -1,22 +0,0 @@
1
- const baseConfig = require('../../eslint.config.cjs');
2
-
3
- module.exports = [
4
- ...baseConfig,
5
- {
6
- files: ['**/*.json'],
7
- rules: {
8
- '@nx/dependency-checks': [
9
- 'error',
10
- {
11
- ignoredFiles: [
12
- '{projectRoot}/eslint.config.{js,cjs,mjs}',
13
- '{projectRoot}/vite.config.{js,ts,mjs,mts}',
14
- ],
15
- },
16
- ],
17
- },
18
- languageOptions: {
19
- parser: require('jsonc-eslint-parser'),
20
- },
21
- },
22
- ];
@@ -1,32 +0,0 @@
1
- export enum FetchSseAction {
2
- RESET_CHANNEL = 'RESET_CHANNEL',
3
- NONE = 'NONE',
4
- }
5
-
6
- export enum EventType {
7
- INIT = 'asgard.run.init',
8
- PROCESS = 'asgard.process',
9
- PROCESS_START = 'asgard.process.start',
10
- PROCESS_COMPLETE = 'asgard.process.complete',
11
- MESSAGE = 'asgard.message',
12
- MESSAGE_START = 'asgard.message.start',
13
- MESSAGE_DELTA = 'asgard.message.delta',
14
- MESSAGE_COMPLETE = 'asgard.message.complete',
15
- TOOL_CALL = 'asgard.tool_call',
16
- TOOL_CALL_START = 'asgard.tool_call.start',
17
- TOOL_CALL_COMPLETE = 'asgard.tool_call.complete',
18
- DONE = 'asgard.run.done',
19
- ERROR = 'asgard.run.error',
20
- }
21
-
22
- export enum MessageTemplateType {
23
- TEXT = 'TEXT',
24
- HINT = 'HINT',
25
- BUTTON = 'BUTTON',
26
- IMAGE = 'IMAGE',
27
- VIDEO = 'VIDEO',
28
- AUDIO = 'AUDIO',
29
- LOCATION = 'LOCATION',
30
- CAROUSEL = 'CAROUSEL',
31
- CHART = 'CHART',
32
- }
package/src/index.ts DELETED
@@ -1,11 +0,0 @@
1
- export type { Subscription } from 'rxjs';
2
-
3
- export type * from './types';
4
-
5
- export * from './constants/enum';
6
-
7
- export { default as AsgardServiceClient } from './lib/client';
8
-
9
- export { default as Channel } from './lib/channel';
10
-
11
- export { default as Conversation } from './lib/conversation';
@@ -1,153 +0,0 @@
1
- import { BehaviorSubject, combineLatest, map, Subscription } from 'rxjs';
2
- import {
3
- ChannelConfig,
4
- ChannelStates,
5
- FetchSseOptions,
6
- FetchSsePayload,
7
- IAsgardServiceClient,
8
- ObserverOrNext,
9
- SseResponse,
10
- } from '../types';
11
- import { FetchSseAction, EventType } from '../constants/enum';
12
- import Conversation from './conversation';
13
-
14
- export default class Channel {
15
- private client: IAsgardServiceClient;
16
-
17
- public customChannelId: string;
18
- public customMessageId?: string;
19
-
20
- private isConnecting$: BehaviorSubject<boolean>;
21
- private conversation$: BehaviorSubject<Conversation>;
22
- private statesObserver?: ObserverOrNext<ChannelStates>;
23
- private statesSubscription?: Subscription;
24
-
25
- private constructor(config: ChannelConfig) {
26
- if (!config.client) {
27
- throw new Error('client must be required');
28
- }
29
-
30
- if (!config.customChannelId) {
31
- throw new Error('customChannelId must be required');
32
- }
33
-
34
- this.client = config.client;
35
- this.customChannelId = config.customChannelId;
36
- this.customMessageId = config.customMessageId;
37
-
38
- this.isConnecting$ = new BehaviorSubject(false);
39
- this.conversation$ = new BehaviorSubject(config.conversation);
40
- this.statesObserver = config.statesObserver;
41
- }
42
-
43
- public static async reset(
44
- config: ChannelConfig,
45
- payload?: Pick<FetchSsePayload, 'text' | 'payload'>,
46
- options?: FetchSseOptions
47
- ): Promise<Channel> {
48
- const channel = new Channel(config);
49
-
50
- try {
51
- channel.subscribe();
52
-
53
- await channel.resetChannel(payload, options);
54
-
55
- return channel;
56
- } catch (error) {
57
- channel.close();
58
-
59
- throw error;
60
- }
61
- }
62
-
63
- private subscribe(): void {
64
- this.statesSubscription = combineLatest([
65
- this.isConnecting$,
66
- this.conversation$,
67
- ])
68
- .pipe(
69
- map(([isConnecting, conversation]) => ({
70
- isConnecting,
71
- conversation,
72
- }))
73
- )
74
- .subscribe(this.statesObserver);
75
- }
76
-
77
- private fetchSse(
78
- payload: FetchSsePayload,
79
- options?: FetchSseOptions
80
- ): Promise<void> {
81
- return new Promise((resolve, reject) => {
82
- this.isConnecting$.next(true);
83
-
84
- this.client.fetchSse(payload, {
85
- onSseStart: options?.onSseStart,
86
- onSseMessage: (response: SseResponse<EventType>) => {
87
- options?.onSseMessage?.(response);
88
- this.conversation$.next(this.conversation$.value.onMessage(response));
89
- },
90
- onSseError: (err: unknown) => {
91
- options?.onSseError?.(err);
92
- this.isConnecting$.next(false);
93
- reject(err);
94
- },
95
- onSseCompleted: () => {
96
- options?.onSseCompleted?.();
97
- this.isConnecting$.next(false);
98
- resolve();
99
- },
100
- });
101
- });
102
- }
103
-
104
- private resetChannel(
105
- payload?: Pick<FetchSsePayload, 'text' | 'payload'>,
106
- options?: FetchSseOptions
107
- ): Promise<void> {
108
- return this.fetchSse(
109
- {
110
- action: FetchSseAction.RESET_CHANNEL,
111
- customChannelId: this.customChannelId,
112
- customMessageId: this.customMessageId,
113
- text: payload?.text || '',
114
- payload: payload?.payload,
115
- },
116
- options
117
- );
118
- }
119
-
120
- public sendMessage(
121
- payload: Pick<FetchSsePayload, 'customMessageId' | 'text' | 'payload'>,
122
- options?: FetchSseOptions
123
- ): Promise<void> {
124
- const text = payload.text.trim();
125
- const messageId = payload.customMessageId ?? crypto.randomUUID();
126
-
127
- this.conversation$.next(
128
- this.conversation$.value.pushMessage({
129
- type: 'user',
130
- messageId,
131
- text,
132
- time: new Date(),
133
- })
134
- );
135
-
136
- return this.fetchSse(
137
- {
138
- action: FetchSseAction.NONE,
139
- customChannelId: this.customChannelId,
140
- customMessageId: messageId,
141
- payload: payload?.payload,
142
- text,
143
- },
144
- options
145
- );
146
- }
147
-
148
- public close(): void {
149
- this.isConnecting$.complete();
150
- this.conversation$.complete();
151
- this.statesSubscription?.unsubscribe();
152
- }
153
- }
@@ -1,150 +0,0 @@
1
- import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
2
- import AsgardServiceClient from './client';
3
- import { ClientConfig } from '../types/client';
4
-
5
- describe('AsgardServiceClient', () => {
6
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
7
- let consoleSpy: any;
8
-
9
- beforeEach(() => {
10
- // eslint-disable-next-line @typescript-eslint/no-empty-function
11
- consoleSpy = vi.spyOn(console, 'warn').mockImplementation(() => {});
12
- });
13
-
14
- afterEach(() => {
15
- consoleSpy.mockRestore();
16
- });
17
-
18
- describe('constructor', () => {
19
- it('should throw error when neither endpoint nor botProviderEndpoint is provided', () => {
20
- const config = {
21
- apiKey: 'test-key',
22
- } as unknown as ClientConfig;
23
-
24
- expect(() => new AsgardServiceClient(config)).toThrow(
25
- 'Either endpoint or botProviderEndpoint must be provided'
26
- );
27
- });
28
-
29
- it('should derive endpoint from botProviderEndpoint when only botProviderEndpoint is provided', () => {
30
- const config: ClientConfig = {
31
- botProviderEndpoint: 'https://api.example.com/bot-provider/bp-123',
32
- apiKey: 'test-key',
33
- };
34
-
35
- const client = new AsgardServiceClient(config);
36
-
37
- // Access private endpoint field for testing
38
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
39
- expect((client as any).endpoint).toBe('https://api.example.com/bot-provider/bp-123/message/sse');
40
- expect(consoleSpy).not.toHaveBeenCalled();
41
- });
42
-
43
- it('should use provided endpoint when only endpoint is provided', () => {
44
- const config: ClientConfig = {
45
- endpoint: 'https://api.example.com/custom/sse',
46
- apiKey: 'test-key',
47
- };
48
-
49
- const client = new AsgardServiceClient(config);
50
-
51
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
52
- expect((client as any).endpoint).toBe('https://api.example.com/custom/sse');
53
- expect(consoleSpy).not.toHaveBeenCalled();
54
- });
55
-
56
- it('should use provided endpoint and warn about deprecation when debugMode is enabled', () => {
57
- const config: ClientConfig = {
58
- endpoint: 'https://api.example.com/custom/sse',
59
- apiKey: 'test-key',
60
- debugMode: true,
61
- };
62
-
63
- const client = new AsgardServiceClient(config);
64
-
65
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
66
- expect((client as any).endpoint).toBe('https://api.example.com/custom/sse');
67
- expect(consoleSpy).toHaveBeenCalledWith(
68
- '[AsgardServiceClient] The "endpoint" option is deprecated and will be removed in the next major version. ' +
69
- 'Please use "botProviderEndpoint" instead. The SSE endpoint will be automatically derived as "${botProviderEndpoint}/message/sse".'
70
- );
71
- });
72
-
73
- it('should use provided endpoint without warning when debugMode is disabled', () => {
74
- const config: ClientConfig = {
75
- endpoint: 'https://api.example.com/custom/sse',
76
- apiKey: 'test-key',
77
- debugMode: false,
78
- };
79
-
80
- const client = new AsgardServiceClient(config);
81
-
82
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
83
- expect((client as any).endpoint).toBe('https://api.example.com/custom/sse');
84
- expect(consoleSpy).not.toHaveBeenCalled();
85
- });
86
-
87
- it('should prioritize endpoint over botProviderEndpoint when both are provided', () => {
88
- const config: ClientConfig = {
89
- endpoint: 'https://api.example.com/custom/sse',
90
- botProviderEndpoint: 'https://api.example.com/bot-provider/bp-123',
91
- apiKey: 'test-key',
92
- debugMode: true,
93
- };
94
-
95
- const client = new AsgardServiceClient(config);
96
-
97
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
98
- expect((client as any).endpoint).toBe('https://api.example.com/custom/sse');
99
- expect(consoleSpy).toHaveBeenCalledWith(
100
- '[AsgardServiceClient] The "endpoint" option is deprecated and will be removed in the next major version. ' +
101
- 'Please use "botProviderEndpoint" instead. The SSE endpoint will be automatically derived as "${botProviderEndpoint}/message/sse".'
102
- );
103
- });
104
-
105
- it('should correctly set other configuration properties', () => {
106
- const transformSsePayload = vi.fn();
107
- const config: ClientConfig = {
108
- botProviderEndpoint: 'https://api.example.com/bot-provider/bp-123',
109
- apiKey: 'test-key',
110
- debugMode: true,
111
- transformSsePayload,
112
- };
113
-
114
- const client = new AsgardServiceClient(config);
115
-
116
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
117
- expect((client as any).apiKey).toBe('test-key');
118
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
119
- expect((client as any).debugMode).toBe(true);
120
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
121
- expect((client as any).transformSsePayload).toBe(transformSsePayload);
122
- });
123
-
124
- it('should handle trailing slash in botProviderEndpoint correctly', () => {
125
- const config: ClientConfig = {
126
- botProviderEndpoint: 'https://api.example.com/bot-provider/bp-123/',
127
- apiKey: 'test-key',
128
- };
129
-
130
- const client = new AsgardServiceClient(config);
131
-
132
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
133
- expect((client as any).endpoint).toBe('https://api.example.com/bot-provider/bp-123/message/sse');
134
- expect(consoleSpy).not.toHaveBeenCalled();
135
- });
136
-
137
- it('should handle multiple trailing slashes in botProviderEndpoint', () => {
138
- const config: ClientConfig = {
139
- botProviderEndpoint: 'https://api.example.com/bot-provider/bp-123///',
140
- apiKey: 'test-key',
141
- };
142
-
143
- const client = new AsgardServiceClient(config);
144
-
145
- // Should remove all trailing slashes
146
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
147
- expect((client as any).endpoint).toBe('https://api.example.com/bot-provider/bp-123/message/sse');
148
- });
149
- });
150
- });
package/src/lib/client.ts DELETED
@@ -1,141 +0,0 @@
1
- import {
2
- ClientConfig,
3
- IAsgardServiceClient,
4
- FetchSsePayload,
5
- FetchSseOptions,
6
- SseResponse,
7
- SseEvents,
8
- } from '../types';
9
- import { createSseObservable } from './create-sse-observable';
10
- import { concatMap, delay, of, retry, Subject, takeUntil } from 'rxjs';
11
- import { EventType } from '../constants/enum';
12
- import { EventEmitter } from './event-emitter';
13
-
14
- export default class AsgardServiceClient implements IAsgardServiceClient {
15
- private apiKey?: string;
16
- private endpoint!: string;
17
- private debugMode?: boolean;
18
- private destroy$ = new Subject<void>();
19
- private sseEmitter = new EventEmitter<SseEvents>();
20
- private transformSsePayload?: (payload: FetchSsePayload) => FetchSsePayload;
21
-
22
- constructor(config: ClientConfig) {
23
- // Validate that either endpoint or botProviderEndpoint is provided
24
- if (!config.endpoint && !config.botProviderEndpoint) {
25
- throw new Error('Either endpoint or botProviderEndpoint must be provided');
26
- }
27
-
28
- this.apiKey = config.apiKey;
29
- this.debugMode = config.debugMode;
30
- this.transformSsePayload = config.transformSsePayload;
31
-
32
- // Handle endpoint derivation and deprecation
33
- if (!config.endpoint && config.botProviderEndpoint) {
34
- // Derive endpoint from botProviderEndpoint (new recommended way)
35
- // Handle trailing slashes to prevent double slashes
36
- const baseEndpoint = config.botProviderEndpoint.replace(/\/+$/, '');
37
- this.endpoint = `${baseEndpoint}/message/sse`;
38
- } else if (config.endpoint) {
39
- // Use provided endpoint but warn about deprecation
40
- this.endpoint = config.endpoint;
41
- if (this.debugMode) {
42
- // eslint-disable-next-line no-console
43
- console.warn(
44
- '[AsgardServiceClient] The "endpoint" option is deprecated and will be removed in the next major version. ' +
45
- `Please use "botProviderEndpoint" instead. The SSE endpoint will be automatically derived as "\${botProviderEndpoint}/message/sse".`
46
- );
47
- }
48
- }
49
- }
50
-
51
- on<K extends keyof SseEvents>(event: K, listener: SseEvents[K]): void {
52
- this.sseEmitter.remove(event);
53
- this.sseEmitter.on(event, listener);
54
- }
55
-
56
- handleEvent(response: SseResponse<EventType>): void {
57
- switch (response.eventType) {
58
- case EventType.INIT:
59
- this.sseEmitter.emit(
60
- EventType.INIT,
61
- response as SseResponse<EventType.INIT>
62
- );
63
-
64
- break;
65
- case EventType.PROCESS_START:
66
- case EventType.PROCESS_COMPLETE:
67
- this.sseEmitter.emit(
68
- EventType.PROCESS,
69
- response as Parameters<SseEvents[EventType.PROCESS]>[0]
70
- );
71
-
72
- break;
73
- case EventType.MESSAGE_START:
74
- case EventType.MESSAGE_DELTA:
75
- case EventType.MESSAGE_COMPLETE:
76
- this.sseEmitter.emit(
77
- EventType.MESSAGE,
78
- response as Parameters<SseEvents[EventType.MESSAGE]>[0]
79
- );
80
-
81
- break;
82
- case EventType.TOOL_CALL_START:
83
- case EventType.TOOL_CALL_COMPLETE:
84
- this.sseEmitter.emit(
85
- EventType.TOOL_CALL,
86
- response as Parameters<SseEvents[EventType.TOOL_CALL]>[0]
87
- );
88
-
89
- break;
90
- case EventType.DONE:
91
- this.sseEmitter.emit(
92
- EventType.DONE,
93
- response as SseResponse<EventType.DONE>
94
- );
95
-
96
- break;
97
- case EventType.ERROR:
98
- this.sseEmitter.emit(
99
- EventType.ERROR,
100
- response as SseResponse<EventType.ERROR>
101
- );
102
-
103
- break;
104
- default:
105
- break;
106
- }
107
- }
108
-
109
- fetchSse(payload: FetchSsePayload, options?: FetchSseOptions): void {
110
- options?.onSseStart?.();
111
-
112
- createSseObservable({
113
- apiKey: this.apiKey,
114
- endpoint: this.endpoint,
115
- debugMode: this.debugMode,
116
- payload: this.transformSsePayload?.(payload) ?? payload,
117
- })
118
- .pipe(
119
- concatMap((event) => of(event).pipe(delay(options?.delayTime ?? 50))),
120
- takeUntil(this.destroy$),
121
- retry(3)
122
- )
123
- .subscribe({
124
- next: (response) => {
125
- options?.onSseMessage?.(response);
126
- this.handleEvent(response);
127
- },
128
- error: (error) => {
129
- options?.onSseError?.(error);
130
- },
131
- complete: () => {
132
- options?.onSseCompleted?.();
133
- },
134
- });
135
- }
136
-
137
- close(): void {
138
- this.destroy$.next();
139
- this.destroy$.complete();
140
- }
141
- }
@@ -1,120 +0,0 @@
1
- import { EventType } from '../constants/enum';
2
- import { ConversationMessage, SseResponse } from '../types';
3
-
4
- interface IConversation {
5
- messages: Map<string, ConversationMessage> | null;
6
- }
7
-
8
- export default class Conversation implements IConversation {
9
- public messages: Map<string, ConversationMessage> | null = null;
10
-
11
- constructor({ messages }: IConversation) {
12
- this.messages = messages;
13
- }
14
-
15
- pushMessage(message: ConversationMessage): Conversation {
16
- const messages = new Map(this.messages);
17
- messages.set(message.messageId, message);
18
-
19
- return new Conversation({ messages });
20
- }
21
-
22
- onMessage(response: SseResponse<EventType>): Conversation {
23
- switch (response.eventType) {
24
- case EventType.MESSAGE_START:
25
- return this.onMessageStart(
26
- response as SseResponse<EventType.MESSAGE_START>
27
- );
28
- case EventType.MESSAGE_DELTA:
29
- return this.onMessageDelta(
30
- response as SseResponse<EventType.MESSAGE_DELTA>
31
- );
32
- case EventType.MESSAGE_COMPLETE:
33
- return this.onMessageComplete(
34
- response as SseResponse<EventType.MESSAGE_COMPLETE>
35
- );
36
- case EventType.ERROR:
37
- return this.onMessageError(response as SseResponse<EventType.ERROR>);
38
- default:
39
- return this;
40
- }
41
- }
42
-
43
- onMessageStart(response: SseResponse<EventType.MESSAGE_START>): Conversation {
44
- const message = response.fact.messageStart.message;
45
- const messages = new Map(this.messages);
46
-
47
- messages.set(message.messageId, {
48
- type: 'bot',
49
- eventType: EventType.MESSAGE_START,
50
- isTyping: true,
51
- typingText: '',
52
- messageId: message.messageId,
53
- message,
54
- time: new Date(),
55
- });
56
-
57
- return new Conversation({ messages });
58
- }
59
-
60
- onMessageDelta(response: SseResponse<EventType.MESSAGE_DELTA>): Conversation {
61
- const message = response.fact.messageDelta.message;
62
-
63
- const messages = new Map(this.messages);
64
-
65
- const currentMessage = messages.get(message.messageId);
66
-
67
- if (currentMessage?.type !== 'bot') return this;
68
-
69
- const typingText = `${currentMessage?.typingText ?? ''}${message.text}`;
70
-
71
- messages.set(message.messageId, {
72
- type: 'bot',
73
- eventType: EventType.MESSAGE_DELTA,
74
- isTyping: true,
75
- typingText,
76
- messageId: message.messageId,
77
- message,
78
- time: new Date(),
79
- });
80
-
81
- return new Conversation({ messages });
82
- }
83
-
84
- onMessageComplete(
85
- response: SseResponse<EventType.MESSAGE_COMPLETE>
86
- ): Conversation {
87
- const message = response.fact.messageComplete.message;
88
-
89
- const messages = new Map(this.messages);
90
-
91
- messages.set(message.messageId, {
92
- type: 'bot',
93
- eventType: EventType.MESSAGE_COMPLETE,
94
- isTyping: false,
95
- typingText: null,
96
- messageId: message.messageId,
97
- message,
98
- time: new Date(),
99
- });
100
-
101
- return new Conversation({ messages });
102
- }
103
-
104
- onMessageError(response: SseResponse<EventType.ERROR>): Conversation {
105
- const messageId = crypto.randomUUID();
106
- const error = response.fact.runError.error;
107
-
108
- const messages = new Map(this.messages);
109
-
110
- messages.set(messageId, {
111
- type: 'error',
112
- eventType: EventType.ERROR,
113
- messageId,
114
- error,
115
- time: new Date(),
116
- });
117
-
118
- return new Conversation({ messages });
119
- }
120
- }