@memori.ai/memori-react 8.38.8 → 8.40.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/CHANGELOG.md +20 -0
- package/dist/components/MemoriWidget/MemoriWidget.js +401 -87
- package/dist/components/MemoriWidget/MemoriWidget.js.map +1 -1
- package/dist/helpers/credits.d.ts +5 -2
- package/dist/helpers/credits.js +5 -1
- package/dist/helpers/credits.js.map +1 -1
- package/dist/helpers/nats/getNatsConfig.d.ts +5 -0
- package/dist/helpers/nats/getNatsConfig.js +29 -0
- package/dist/helpers/nats/getNatsConfig.js.map +1 -0
- package/dist/helpers/nats/useNats.d.ts +12 -0
- package/dist/helpers/nats/useNats.js +72 -0
- package/dist/helpers/nats/useNats.js.map +1 -0
- package/dist/helpers/nats/useNatsSession.d.ts +27 -0
- package/dist/helpers/nats/useNatsSession.js +108 -0
- package/dist/helpers/nats/useNatsSession.js.map +1 -0
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/esm/components/MemoriWidget/MemoriWidget.js +401 -87
- package/esm/components/MemoriWidget/MemoriWidget.js.map +1 -1
- package/esm/helpers/credits.d.ts +5 -2
- package/esm/helpers/credits.js +5 -1
- package/esm/helpers/credits.js.map +1 -1
- package/esm/helpers/nats/getNatsConfig.d.ts +5 -0
- package/esm/helpers/nats/getNatsConfig.js +25 -0
- package/esm/helpers/nats/getNatsConfig.js.map +1 -0
- package/esm/helpers/nats/useNats.d.ts +12 -0
- package/esm/helpers/nats/useNats.js +68 -0
- package/esm/helpers/nats/useNats.js.map +1 -0
- package/esm/helpers/nats/useNatsSession.d.ts +27 -0
- package/esm/helpers/nats/useNatsSession.js +103 -0
- package/esm/helpers/nats/useNatsSession.js.map +1 -0
- package/esm/version.d.ts +1 -1
- package/esm/version.js +1 -1
- package/package.json +3 -2
- package/src/components/MemoriWidget/MemoriWidget.tsx +546 -140
- package/src/components/StartPanel/StartPanel.stories.tsx +21 -0
- package/src/components/StartPanel/StartPanel.test.tsx +66 -1
- package/src/components/StartPanel/__snapshots__/StartPanel.test.tsx.snap +156 -0
- package/src/components/layouts/layouts.stories.tsx +28 -34
- package/src/helpers/credits.ts +16 -1
- package/src/helpers/nats/getNatsConfig.ts +69 -0
- package/src/helpers/nats/useNats.ts +122 -0
- package/src/helpers/nats/useNatsSession.ts +210 -0
- package/src/index.stories.tsx +19 -3
- package/src/version.ts +1 -1
|
@@ -0,0 +1,210 @@
|
|
|
1
|
+
// helpers/nats/useNatsSession.ts - Subscribe to a session's NATS channel.
|
|
2
|
+
//
|
|
3
|
+
// Opens a W3C WebSocket connection (via `wsconnect`), subscribes to the
|
|
4
|
+
// session subject (`sessions.<sessionId>`) and forwards every decoded event to
|
|
5
|
+
// `onMessage`. The cleanup (`nc.close()`) is essential: without it, every
|
|
6
|
+
// `sessionId` change would leave orphan connections / iterators.
|
|
7
|
+
import { useEffect, useRef } from 'react';
|
|
8
|
+
import { wsconnect, NatsConnection } from '@nats-io/nats-core';
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* `progress` event: job advancement updates.
|
|
12
|
+
*/
|
|
13
|
+
export interface NatsProgressEvent {
|
|
14
|
+
eventType: 'progress';
|
|
15
|
+
jobId?: string;
|
|
16
|
+
currentStep?: number;
|
|
17
|
+
finalStep?: number;
|
|
18
|
+
message?: string;
|
|
19
|
+
startingTime?: string;
|
|
20
|
+
correlationID?: string;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* `dialog.text_entered_response` event: same body returned by
|
|
25
|
+
* `POST /memori/v2/EnterTextAsync/{sessionId}` (via NATS).
|
|
26
|
+
*/
|
|
27
|
+
export interface NatsDialogResponseEvent {
|
|
28
|
+
eventType: 'dialog_text_entered_response';
|
|
29
|
+
requestID?: string;
|
|
30
|
+
resultCode?: number;
|
|
31
|
+
resultMessage?: string;
|
|
32
|
+
currentState?: any;
|
|
33
|
+
correlationID?: string;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* `error` event.
|
|
38
|
+
*/
|
|
39
|
+
export interface NatsErrorEvent {
|
|
40
|
+
eventType: 'error';
|
|
41
|
+
errorCode?: string | number;
|
|
42
|
+
errorMessage?: string;
|
|
43
|
+
backtrace?: string;
|
|
44
|
+
correlationID?: string;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Discriminated union of all events received on the session subject.
|
|
49
|
+
*/
|
|
50
|
+
export type NatsSessionEvent =
|
|
51
|
+
| NatsProgressEvent
|
|
52
|
+
| NatsDialogResponseEvent
|
|
53
|
+
| NatsErrorEvent;
|
|
54
|
+
|
|
55
|
+
function readString(
|
|
56
|
+
raw: Record<string, unknown>,
|
|
57
|
+
camelKey: string,
|
|
58
|
+
snakeKey: string
|
|
59
|
+
): string | undefined {
|
|
60
|
+
const value = raw[camelKey] ?? raw[snakeKey];
|
|
61
|
+
return typeof value === 'string' ? value : undefined;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
function readNumber(
|
|
65
|
+
raw: Record<string, unknown>,
|
|
66
|
+
camelKey: string,
|
|
67
|
+
snakeKey: string
|
|
68
|
+
): number | undefined {
|
|
69
|
+
const value = raw[camelKey] ?? raw[snakeKey];
|
|
70
|
+
return typeof value === 'number' ? value : undefined;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* Normalizes raw NATS payloads (snake_case or camelCase) into typed events.
|
|
75
|
+
*/
|
|
76
|
+
export function normalizeNatsEvent(raw: Record<string, unknown>): NatsSessionEvent {
|
|
77
|
+
const eventType = (readString(raw, 'eventType', 'event_type') ??
|
|
78
|
+
'unknown') as NatsSessionEvent['eventType'];
|
|
79
|
+
|
|
80
|
+
const correlationID =
|
|
81
|
+
readString(raw, 'correlationID', 'correlation_id') ??
|
|
82
|
+
readString(raw, 'correlationId', 'correlation_id');
|
|
83
|
+
|
|
84
|
+
if (eventType === 'progress') {
|
|
85
|
+
return {
|
|
86
|
+
eventType: 'progress',
|
|
87
|
+
jobId: readString(raw, 'jobId', 'job_id'),
|
|
88
|
+
currentStep: readNumber(raw, 'currentStep', 'current_step'),
|
|
89
|
+
finalStep: readNumber(raw, 'finalStep', 'final_step'),
|
|
90
|
+
message: typeof raw.message === 'string' ? raw.message : undefined,
|
|
91
|
+
startingTime: readString(raw, 'startingTime', 'starting_time'),
|
|
92
|
+
correlationID,
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
if (eventType === 'dialog_text_entered_response') {
|
|
97
|
+
return {
|
|
98
|
+
eventType: 'dialog_text_entered_response',
|
|
99
|
+
requestID:
|
|
100
|
+
typeof raw.requestID === 'string' ? raw.requestID : undefined,
|
|
101
|
+
resultCode:
|
|
102
|
+
typeof raw.resultCode === 'number' ? raw.resultCode : undefined,
|
|
103
|
+
resultMessage:
|
|
104
|
+
typeof raw.resultMessage === 'string' ? raw.resultMessage : undefined,
|
|
105
|
+
currentState: raw.currentState,
|
|
106
|
+
correlationID,
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
if (eventType === 'error') {
|
|
111
|
+
return {
|
|
112
|
+
eventType: 'error',
|
|
113
|
+
errorCode: (raw.errorCode ?? raw.error_code) as string | number | undefined,
|
|
114
|
+
errorMessage: readString(raw, 'errorMessage', 'error_message'),
|
|
115
|
+
backtrace: typeof raw.backtrace === 'string' ? raw.backtrace : undefined,
|
|
116
|
+
correlationID,
|
|
117
|
+
};
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
return {
|
|
121
|
+
eventType,
|
|
122
|
+
correlationID,
|
|
123
|
+
} as NatsSessionEvent;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* Open a NATS WebSocket connection, subscribe to the session subject and
|
|
128
|
+
* forward decoded events to `onMessage`.
|
|
129
|
+
*
|
|
130
|
+
* `onMessage` is kept in a ref so callers do not need to memoize it: the
|
|
131
|
+
* connection is only (re)opened when `sessionId`, `natsWsUrl` or `natsToken`
|
|
132
|
+
* change.
|
|
133
|
+
*
|
|
134
|
+
* @param sessionId Current session UUID (subscription is skipped when falsy).
|
|
135
|
+
* @param natsWsUrl WebSocket URL of the NATS server.
|
|
136
|
+
* @param natsToken Bearer token for authentication.
|
|
137
|
+
* @param onMessage Callback invoked for each decoded event.
|
|
138
|
+
*/
|
|
139
|
+
export function useNatsSession(
|
|
140
|
+
sessionId: string | undefined,
|
|
141
|
+
natsWsUrl: string | undefined,
|
|
142
|
+
natsToken: string | undefined,
|
|
143
|
+
onMessage: (event: NatsSessionEvent) => void
|
|
144
|
+
) {
|
|
145
|
+
const connRef = useRef<NatsConnection | null>(null);
|
|
146
|
+
const onMessageRef = useRef(onMessage);
|
|
147
|
+
|
|
148
|
+
// Keep the latest callback without retriggering the connection effect.
|
|
149
|
+
useEffect(() => {
|
|
150
|
+
onMessageRef.current = onMessage;
|
|
151
|
+
}, [onMessage]);
|
|
152
|
+
|
|
153
|
+
useEffect(() => {
|
|
154
|
+
if (!sessionId || !natsWsUrl || !natsToken) {
|
|
155
|
+
console.debug(
|
|
156
|
+
'[NATS] subscription skipped (missing sessionId/url/token)',
|
|
157
|
+
{ sessionId, hasUrl: !!natsWsUrl, hasToken: !!natsToken }
|
|
158
|
+
);
|
|
159
|
+
return;
|
|
160
|
+
}
|
|
161
|
+
let closed = false;
|
|
162
|
+
const subject = sessionId;
|
|
163
|
+
|
|
164
|
+
(async () => {
|
|
165
|
+
console.info('[NATS] connecting to', natsWsUrl, 'for session', sessionId);
|
|
166
|
+
const nc = await wsconnect({
|
|
167
|
+
servers: [natsWsUrl],
|
|
168
|
+
token: natsToken,
|
|
169
|
+
});
|
|
170
|
+
if (closed) {
|
|
171
|
+
console.debug(
|
|
172
|
+
'[NATS] connection established after cleanup, closing immediately'
|
|
173
|
+
);
|
|
174
|
+
await nc.close();
|
|
175
|
+
return;
|
|
176
|
+
}
|
|
177
|
+
connRef.current = nc;
|
|
178
|
+
console.info('[NATS] connected to', nc.getServer());
|
|
179
|
+
|
|
180
|
+
const sub = nc.subscribe(subject);
|
|
181
|
+
console.info('[NATS] subscribed to subject', subject);
|
|
182
|
+
let received = 0;
|
|
183
|
+
for await (const msg of sub) {
|
|
184
|
+
received += 1;
|
|
185
|
+
try {
|
|
186
|
+
const payload = normalizeNatsEvent(
|
|
187
|
+
msg.json<Record<string, unknown>>()
|
|
188
|
+
);
|
|
189
|
+
console.debug(
|
|
190
|
+
`[NATS] message #${received} on ${subject} (eventType=${payload.eventType})`,
|
|
191
|
+
payload
|
|
192
|
+
);
|
|
193
|
+
onMessageRef.current(payload);
|
|
194
|
+
} catch (err) {
|
|
195
|
+
console.error('[NATS] message decode error', err);
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
console.info(
|
|
199
|
+
`[NATS] subscription on ${subject} closed (received ${received} messages)`
|
|
200
|
+
);
|
|
201
|
+
})().catch(err => console.error('[NATS] connection error', err));
|
|
202
|
+
|
|
203
|
+
return () => {
|
|
204
|
+
console.info('[NATS] cleanup: closing connection for subject', subject);
|
|
205
|
+
closed = true;
|
|
206
|
+
connRef.current?.close();
|
|
207
|
+
connRef.current = null;
|
|
208
|
+
};
|
|
209
|
+
}, [sessionId, natsWsUrl, natsToken]);
|
|
210
|
+
}
|
package/src/index.stories.tsx
CHANGED
|
@@ -22,7 +22,6 @@ export default meta;
|
|
|
22
22
|
|
|
23
23
|
const Template: Story<Props> = args => <Memori {...args} />;
|
|
24
24
|
|
|
25
|
-
|
|
26
25
|
export const WithInitialContextAndQuestion = Template.bind({});
|
|
27
26
|
WithInitialContextAndQuestion.args = {
|
|
28
27
|
ownerUserName: 'nzambello',
|
|
@@ -150,7 +149,8 @@ const piiDetectionConfig = {
|
|
|
150
149
|
{
|
|
151
150
|
id: 'iban',
|
|
152
151
|
label: { it: 'IBAN', en: 'IBAN' },
|
|
153
|
-
pattern:
|
|
152
|
+
pattern:
|
|
153
|
+
'\\b[A-Z]{2}\\d{2}(?:[ ]?[A-Z0-9]{4}){3,7}(?:[ ]?[A-Z0-9]{1,4})?\\b',
|
|
154
154
|
message: {
|
|
155
155
|
it: 'Il messaggio contiene un codice IBAN.',
|
|
156
156
|
en: 'The message contains an IBAN code.',
|
|
@@ -185,4 +185,20 @@ WithPiiDetection.args = {
|
|
|
185
185
|
lang: 'it',
|
|
186
186
|
}),
|
|
187
187
|
},
|
|
188
|
-
};
|
|
188
|
+
};
|
|
189
|
+
|
|
190
|
+
export const WithLocalNats = Template.bind({});
|
|
191
|
+
WithLocalNats.args = {
|
|
192
|
+
memoriName: 'test324',
|
|
193
|
+
ownerUserName: 'andrea.patini',
|
|
194
|
+
memoriID: 'd661a9ca-e907-4396-a986-5095ccd582d6',
|
|
195
|
+
ownerUserID: '69fcc557-9cb6-4e5e-b8ab-140cff975492',
|
|
196
|
+
tenantID: 'localhost:3000',
|
|
197
|
+
engineURL: 'http://localhost:7778/memori/v2',
|
|
198
|
+
apiURL: 'http://localhost:7778/api/v2',
|
|
199
|
+
baseURL: 'http://localhost:3000',
|
|
200
|
+
layout: 'FULLPAGE',
|
|
201
|
+
uiLang: 'IT',
|
|
202
|
+
spokenLang: 'IT',
|
|
203
|
+
integrationID: 'ee1c3d98-7819-4506-ba28-818e79ba86cb',
|
|
204
|
+
};
|
package/src/version.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
// This file is auto-generated. Do not edit manually.
|
|
2
|
-
export const version = '8.
|
|
2
|
+
export const version = '8.40.0';
|