@informedai/react 0.2.5 → 0.3.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/dist/index.d.mts +35 -4
- package/dist/index.d.ts +35 -4
- package/dist/index.js +119 -24
- package/dist/index.mjs +119 -24
- package/package.json +1 -1
package/dist/index.d.mts
CHANGED
|
@@ -76,8 +76,27 @@ interface InformedAssistantConfig {
|
|
|
76
76
|
documentTypeId: string;
|
|
77
77
|
/** API base URL (defaults to https://api.informedassistant.ai/api/v1) */
|
|
78
78
|
apiUrl?: string;
|
|
79
|
-
/**
|
|
79
|
+
/**
|
|
80
|
+
* External ID for idempotency - your object's ID in your system.
|
|
81
|
+
* If provided, the widget will find or create a document linked to this ID.
|
|
82
|
+
* This allows resuming work on the same document across sessions.
|
|
83
|
+
*/
|
|
84
|
+
externalId?: string;
|
|
85
|
+
/**
|
|
86
|
+
* Your current field values to sync before starting.
|
|
87
|
+
* Since you're the source of truth, this data will be written to our document.
|
|
88
|
+
* Use this to ensure the assistant sees your latest data.
|
|
89
|
+
*/
|
|
90
|
+
initialData?: Record<string, unknown>;
|
|
91
|
+
/**
|
|
92
|
+
* Whether to persist sessions in localStorage for resumption.
|
|
93
|
+
* Defaults to true when externalId is provided, false otherwise.
|
|
94
|
+
*/
|
|
95
|
+
persistSession?: boolean;
|
|
96
|
+
/** Optional: Existing session ID to resume (overrides localStorage) */
|
|
80
97
|
sessionId?: string;
|
|
98
|
+
/** Callback when widget is ready with document type schema */
|
|
99
|
+
onReady?: (context: WidgetReadyContext) => void;
|
|
81
100
|
/** Callback when a field value is applied */
|
|
82
101
|
onFieldApply?: (fieldName: string, value: unknown) => void;
|
|
83
102
|
/** Callback when session state changes */
|
|
@@ -91,6 +110,11 @@ interface InformedAssistantConfig {
|
|
|
91
110
|
/** Initial collapsed state */
|
|
92
111
|
defaultCollapsed?: boolean;
|
|
93
112
|
}
|
|
113
|
+
interface WidgetReadyContext {
|
|
114
|
+
session: Session;
|
|
115
|
+
document: Document;
|
|
116
|
+
documentType: DocumentType;
|
|
117
|
+
}
|
|
94
118
|
interface WidgetTheme {
|
|
95
119
|
/** Primary accent color */
|
|
96
120
|
primaryColor: string;
|
|
@@ -149,6 +173,7 @@ interface InformedAIContextValue {
|
|
|
149
173
|
sendQuickAction: (action: string, payload?: Record<string, unknown>) => Promise<void>;
|
|
150
174
|
applyPendingValue: () => Promise<void>;
|
|
151
175
|
skipTask: () => Promise<void>;
|
|
176
|
+
startNewSession: () => Promise<void>;
|
|
152
177
|
clearError: () => void;
|
|
153
178
|
}
|
|
154
179
|
declare function useInformedAI(): InformedAIContextValue;
|
|
@@ -206,9 +231,15 @@ declare class InformedAIClient {
|
|
|
206
231
|
private request;
|
|
207
232
|
/**
|
|
208
233
|
* Create a new session for a document type.
|
|
209
|
-
*
|
|
234
|
+
*
|
|
235
|
+
* @param documentTypeId - The document type to create a session for
|
|
236
|
+
* @param options.externalId - Your object's ID for idempotency (finds or creates document)
|
|
237
|
+
* @param options.initialData - Your current field values to sync (you're the source of truth)
|
|
210
238
|
*/
|
|
211
|
-
createSession(documentTypeId: string
|
|
239
|
+
createSession(documentTypeId: string, options?: {
|
|
240
|
+
externalId?: string;
|
|
241
|
+
initialData?: Record<string, unknown>;
|
|
242
|
+
}): Promise<CreateSessionResponse>;
|
|
212
243
|
/**
|
|
213
244
|
* Get an existing session.
|
|
214
245
|
*/
|
|
@@ -234,4 +265,4 @@ declare class InformedAIClient {
|
|
|
234
265
|
private processSSEStream;
|
|
235
266
|
}
|
|
236
267
|
|
|
237
|
-
export { type ChatMessage, type Document, type DocumentType, type DocumentTypeSchema, type FieldDefinition, InformedAIClient, InformedAIProvider, InformedAssistant, type InformedAssistantConfig, type QuickAction, type SSEEvent, type Session, type TaskConfig, type TaskState, type UseSessionReturn, type WidgetMessage, type WidgetTheme, useInformedAI, useSession };
|
|
268
|
+
export { type ChatMessage, type Document, type DocumentType, type DocumentTypeSchema, type FieldDefinition, InformedAIClient, InformedAIProvider, InformedAssistant, type InformedAssistantConfig, type QuickAction, type SSEEvent, type Session, type TaskConfig, type TaskState, type UseSessionReturn, type WidgetMessage, type WidgetReadyContext, type WidgetTheme, useInformedAI, useSession };
|
package/dist/index.d.ts
CHANGED
|
@@ -76,8 +76,27 @@ interface InformedAssistantConfig {
|
|
|
76
76
|
documentTypeId: string;
|
|
77
77
|
/** API base URL (defaults to https://api.informedassistant.ai/api/v1) */
|
|
78
78
|
apiUrl?: string;
|
|
79
|
-
/**
|
|
79
|
+
/**
|
|
80
|
+
* External ID for idempotency - your object's ID in your system.
|
|
81
|
+
* If provided, the widget will find or create a document linked to this ID.
|
|
82
|
+
* This allows resuming work on the same document across sessions.
|
|
83
|
+
*/
|
|
84
|
+
externalId?: string;
|
|
85
|
+
/**
|
|
86
|
+
* Your current field values to sync before starting.
|
|
87
|
+
* Since you're the source of truth, this data will be written to our document.
|
|
88
|
+
* Use this to ensure the assistant sees your latest data.
|
|
89
|
+
*/
|
|
90
|
+
initialData?: Record<string, unknown>;
|
|
91
|
+
/**
|
|
92
|
+
* Whether to persist sessions in localStorage for resumption.
|
|
93
|
+
* Defaults to true when externalId is provided, false otherwise.
|
|
94
|
+
*/
|
|
95
|
+
persistSession?: boolean;
|
|
96
|
+
/** Optional: Existing session ID to resume (overrides localStorage) */
|
|
80
97
|
sessionId?: string;
|
|
98
|
+
/** Callback when widget is ready with document type schema */
|
|
99
|
+
onReady?: (context: WidgetReadyContext) => void;
|
|
81
100
|
/** Callback when a field value is applied */
|
|
82
101
|
onFieldApply?: (fieldName: string, value: unknown) => void;
|
|
83
102
|
/** Callback when session state changes */
|
|
@@ -91,6 +110,11 @@ interface InformedAssistantConfig {
|
|
|
91
110
|
/** Initial collapsed state */
|
|
92
111
|
defaultCollapsed?: boolean;
|
|
93
112
|
}
|
|
113
|
+
interface WidgetReadyContext {
|
|
114
|
+
session: Session;
|
|
115
|
+
document: Document;
|
|
116
|
+
documentType: DocumentType;
|
|
117
|
+
}
|
|
94
118
|
interface WidgetTheme {
|
|
95
119
|
/** Primary accent color */
|
|
96
120
|
primaryColor: string;
|
|
@@ -149,6 +173,7 @@ interface InformedAIContextValue {
|
|
|
149
173
|
sendQuickAction: (action: string, payload?: Record<string, unknown>) => Promise<void>;
|
|
150
174
|
applyPendingValue: () => Promise<void>;
|
|
151
175
|
skipTask: () => Promise<void>;
|
|
176
|
+
startNewSession: () => Promise<void>;
|
|
152
177
|
clearError: () => void;
|
|
153
178
|
}
|
|
154
179
|
declare function useInformedAI(): InformedAIContextValue;
|
|
@@ -206,9 +231,15 @@ declare class InformedAIClient {
|
|
|
206
231
|
private request;
|
|
207
232
|
/**
|
|
208
233
|
* Create a new session for a document type.
|
|
209
|
-
*
|
|
234
|
+
*
|
|
235
|
+
* @param documentTypeId - The document type to create a session for
|
|
236
|
+
* @param options.externalId - Your object's ID for idempotency (finds or creates document)
|
|
237
|
+
* @param options.initialData - Your current field values to sync (you're the source of truth)
|
|
210
238
|
*/
|
|
211
|
-
createSession(documentTypeId: string
|
|
239
|
+
createSession(documentTypeId: string, options?: {
|
|
240
|
+
externalId?: string;
|
|
241
|
+
initialData?: Record<string, unknown>;
|
|
242
|
+
}): Promise<CreateSessionResponse>;
|
|
212
243
|
/**
|
|
213
244
|
* Get an existing session.
|
|
214
245
|
*/
|
|
@@ -234,4 +265,4 @@ declare class InformedAIClient {
|
|
|
234
265
|
private processSSEStream;
|
|
235
266
|
}
|
|
236
267
|
|
|
237
|
-
export { type ChatMessage, type Document, type DocumentType, type DocumentTypeSchema, type FieldDefinition, InformedAIClient, InformedAIProvider, InformedAssistant, type InformedAssistantConfig, type QuickAction, type SSEEvent, type Session, type TaskConfig, type TaskState, type UseSessionReturn, type WidgetMessage, type WidgetTheme, useInformedAI, useSession };
|
|
268
|
+
export { type ChatMessage, type Document, type DocumentType, type DocumentTypeSchema, type FieldDefinition, InformedAIClient, InformedAIProvider, InformedAssistant, type InformedAssistantConfig, type QuickAction, type SSEEvent, type Session, type TaskConfig, type TaskState, type UseSessionReturn, type WidgetMessage, type WidgetReadyContext, type WidgetTheme, useInformedAI, useSession };
|
package/dist/index.js
CHANGED
|
@@ -67,12 +67,19 @@ var InformedAIClient = class {
|
|
|
67
67
|
// ========================================================================
|
|
68
68
|
/**
|
|
69
69
|
* Create a new session for a document type.
|
|
70
|
-
*
|
|
70
|
+
*
|
|
71
|
+
* @param documentTypeId - The document type to create a session for
|
|
72
|
+
* @param options.externalId - Your object's ID for idempotency (finds or creates document)
|
|
73
|
+
* @param options.initialData - Your current field values to sync (you're the source of truth)
|
|
71
74
|
*/
|
|
72
|
-
async createSession(documentTypeId) {
|
|
75
|
+
async createSession(documentTypeId, options) {
|
|
73
76
|
return this.request("/widget/sessions", {
|
|
74
77
|
method: "POST",
|
|
75
|
-
body: JSON.stringify({
|
|
78
|
+
body: JSON.stringify({
|
|
79
|
+
documentTypeId,
|
|
80
|
+
externalId: options?.externalId,
|
|
81
|
+
initialData: options?.initialData
|
|
82
|
+
})
|
|
76
83
|
});
|
|
77
84
|
}
|
|
78
85
|
/**
|
|
@@ -186,6 +193,7 @@ var InformedAIClient = class {
|
|
|
186
193
|
|
|
187
194
|
// src/context/InformedAIContext.tsx
|
|
188
195
|
var import_jsx_runtime = require("react/jsx-runtime");
|
|
196
|
+
var getStorageKey = (documentTypeId, externalId) => `informedai_session_${documentTypeId}${externalId ? `_${externalId}` : ""}`;
|
|
189
197
|
var InformedAIContext = (0, import_react.createContext)(null);
|
|
190
198
|
function useInformedAI() {
|
|
191
199
|
const context = (0, import_react.useContext)(InformedAIContext);
|
|
@@ -203,39 +211,94 @@ function InformedAIProvider({ config, children }) {
|
|
|
203
211
|
const [error, setError] = (0, import_react.useState)(null);
|
|
204
212
|
const [streamingContent, setStreamingContent] = (0, import_react.useState)("");
|
|
205
213
|
const clientRef = (0, import_react.useRef)(null);
|
|
214
|
+
const initRef = (0, import_react.useRef)(false);
|
|
215
|
+
const shouldPersist = config.persistSession ?? !!config.externalId;
|
|
216
|
+
const storageKey = getStorageKey(config.documentTypeId, config.externalId);
|
|
206
217
|
(0, import_react.useEffect)(() => {
|
|
207
218
|
clientRef.current = new InformedAIClient(config.apiUrl);
|
|
208
219
|
}, [config.apiUrl]);
|
|
220
|
+
const createNewSession = (0, import_react.useCallback)(async () => {
|
|
221
|
+
if (!clientRef.current) return null;
|
|
222
|
+
const result = await clientRef.current.createSession(
|
|
223
|
+
config.documentTypeId,
|
|
224
|
+
{
|
|
225
|
+
externalId: config.externalId,
|
|
226
|
+
initialData: config.initialData
|
|
227
|
+
}
|
|
228
|
+
);
|
|
229
|
+
const dt = {
|
|
230
|
+
id: result.documentType.id,
|
|
231
|
+
name: result.documentType.name,
|
|
232
|
+
displayName: result.documentType.displayName,
|
|
233
|
+
schema: result.documentType.schema,
|
|
234
|
+
workspaceId: "",
|
|
235
|
+
taskConfigs: {},
|
|
236
|
+
createdAt: "",
|
|
237
|
+
updatedAt: ""
|
|
238
|
+
};
|
|
239
|
+
if (shouldPersist && typeof window !== "undefined") {
|
|
240
|
+
try {
|
|
241
|
+
localStorage.setItem(storageKey, result.session.id);
|
|
242
|
+
} catch (e) {
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
return { session: result.session, document: result.document, documentType: dt };
|
|
246
|
+
}, [config.documentTypeId, config.externalId, config.initialData, shouldPersist, storageKey]);
|
|
209
247
|
(0, import_react.useEffect)(() => {
|
|
248
|
+
if (initRef.current) return;
|
|
249
|
+
initRef.current = true;
|
|
210
250
|
async function initialize() {
|
|
211
251
|
if (!clientRef.current) return;
|
|
212
252
|
try {
|
|
213
253
|
setIsLoading(true);
|
|
214
254
|
setError(null);
|
|
215
|
-
let sess;
|
|
255
|
+
let sess = null;
|
|
216
256
|
let doc = null;
|
|
217
257
|
let dt = null;
|
|
218
|
-
|
|
219
|
-
|
|
258
|
+
let sessionIdToResume = config.sessionId;
|
|
259
|
+
if (!sessionIdToResume && shouldPersist && typeof window !== "undefined") {
|
|
260
|
+
try {
|
|
261
|
+
sessionIdToResume = localStorage.getItem(storageKey) || void 0;
|
|
262
|
+
} catch (e) {
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
if (sessionIdToResume) {
|
|
266
|
+
try {
|
|
267
|
+
sess = await clientRef.current.getSession(sessionIdToResume);
|
|
268
|
+
} catch (e) {
|
|
269
|
+
console.warn("Failed to resume session, creating new one");
|
|
270
|
+
if (shouldPersist && typeof window !== "undefined") {
|
|
271
|
+
try {
|
|
272
|
+
localStorage.removeItem(storageKey);
|
|
273
|
+
} catch (e2) {
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
if (!sess) {
|
|
279
|
+
const result = await createNewSession();
|
|
280
|
+
if (result) {
|
|
281
|
+
sess = result.session;
|
|
282
|
+
doc = result.document;
|
|
283
|
+
dt = result.documentType;
|
|
284
|
+
}
|
|
220
285
|
} else {
|
|
221
|
-
const result = await
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
286
|
+
const result = await createNewSession();
|
|
287
|
+
if (result) {
|
|
288
|
+
sess = result.session;
|
|
289
|
+
doc = result.document;
|
|
290
|
+
dt = result.documentType;
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
if (sess) {
|
|
294
|
+
setSession(sess);
|
|
295
|
+
if (doc) setDocument(doc);
|
|
296
|
+
if (dt) setDocumentType(dt);
|
|
297
|
+
config.onSessionChange?.(sess);
|
|
298
|
+
if (doc && dt) {
|
|
299
|
+
config.onReady?.({ session: sess, document: doc, documentType: dt });
|
|
300
|
+
}
|
|
234
301
|
}
|
|
235
|
-
setSession(sess);
|
|
236
|
-
if (doc) setDocument(doc);
|
|
237
|
-
if (dt) setDocumentType(dt);
|
|
238
|
-
config.onSessionChange?.(sess);
|
|
239
302
|
} catch (err) {
|
|
240
303
|
const error2 = err instanceof Error ? err : new Error("Initialization failed");
|
|
241
304
|
setError(error2);
|
|
@@ -245,7 +308,7 @@ function InformedAIProvider({ config, children }) {
|
|
|
245
308
|
}
|
|
246
309
|
}
|
|
247
310
|
initialize();
|
|
248
|
-
}, [config.documentTypeId, config.sessionId]);
|
|
311
|
+
}, [config.documentTypeId, config.sessionId, config.externalId]);
|
|
249
312
|
const handleSSEEvent = (0, import_react.useCallback)((event) => {
|
|
250
313
|
if (event.type === "content" && event.content) {
|
|
251
314
|
setStreamingContent((prev) => prev + event.content);
|
|
@@ -327,6 +390,37 @@ function InformedAIProvider({ config, children }) {
|
|
|
327
390
|
config.onError?.(error2);
|
|
328
391
|
}
|
|
329
392
|
}, [session, config]);
|
|
393
|
+
const startNewSession = (0, import_react.useCallback)(async () => {
|
|
394
|
+
if (!clientRef.current) return;
|
|
395
|
+
try {
|
|
396
|
+
setIsLoading(true);
|
|
397
|
+
setError(null);
|
|
398
|
+
if (shouldPersist && typeof window !== "undefined") {
|
|
399
|
+
try {
|
|
400
|
+
localStorage.removeItem(storageKey);
|
|
401
|
+
} catch (e) {
|
|
402
|
+
}
|
|
403
|
+
}
|
|
404
|
+
const result = await createNewSession();
|
|
405
|
+
if (result) {
|
|
406
|
+
setSession(result.session);
|
|
407
|
+
setDocument(result.document);
|
|
408
|
+
setDocumentType(result.documentType);
|
|
409
|
+
config.onSessionChange?.(result.session);
|
|
410
|
+
config.onReady?.({
|
|
411
|
+
session: result.session,
|
|
412
|
+
document: result.document,
|
|
413
|
+
documentType: result.documentType
|
|
414
|
+
});
|
|
415
|
+
}
|
|
416
|
+
} catch (err) {
|
|
417
|
+
const error2 = err instanceof Error ? err : new Error("Failed to start new session");
|
|
418
|
+
setError(error2);
|
|
419
|
+
config.onError?.(error2);
|
|
420
|
+
} finally {
|
|
421
|
+
setIsLoading(false);
|
|
422
|
+
}
|
|
423
|
+
}, [createNewSession, shouldPersist, storageKey, config]);
|
|
330
424
|
const clearError = (0, import_react.useCallback)(() => {
|
|
331
425
|
setError(null);
|
|
332
426
|
}, []);
|
|
@@ -342,6 +436,7 @@ function InformedAIProvider({ config, children }) {
|
|
|
342
436
|
sendQuickAction,
|
|
343
437
|
applyPendingValue,
|
|
344
438
|
skipTask,
|
|
439
|
+
startNewSession,
|
|
345
440
|
clearError
|
|
346
441
|
};
|
|
347
442
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(InformedAIContext.Provider, { value, children });
|
package/dist/index.mjs
CHANGED
|
@@ -37,12 +37,19 @@ var InformedAIClient = class {
|
|
|
37
37
|
// ========================================================================
|
|
38
38
|
/**
|
|
39
39
|
* Create a new session for a document type.
|
|
40
|
-
*
|
|
40
|
+
*
|
|
41
|
+
* @param documentTypeId - The document type to create a session for
|
|
42
|
+
* @param options.externalId - Your object's ID for idempotency (finds or creates document)
|
|
43
|
+
* @param options.initialData - Your current field values to sync (you're the source of truth)
|
|
41
44
|
*/
|
|
42
|
-
async createSession(documentTypeId) {
|
|
45
|
+
async createSession(documentTypeId, options) {
|
|
43
46
|
return this.request("/widget/sessions", {
|
|
44
47
|
method: "POST",
|
|
45
|
-
body: JSON.stringify({
|
|
48
|
+
body: JSON.stringify({
|
|
49
|
+
documentTypeId,
|
|
50
|
+
externalId: options?.externalId,
|
|
51
|
+
initialData: options?.initialData
|
|
52
|
+
})
|
|
46
53
|
});
|
|
47
54
|
}
|
|
48
55
|
/**
|
|
@@ -156,6 +163,7 @@ var InformedAIClient = class {
|
|
|
156
163
|
|
|
157
164
|
// src/context/InformedAIContext.tsx
|
|
158
165
|
import { jsx } from "react/jsx-runtime";
|
|
166
|
+
var getStorageKey = (documentTypeId, externalId) => `informedai_session_${documentTypeId}${externalId ? `_${externalId}` : ""}`;
|
|
159
167
|
var InformedAIContext = createContext(null);
|
|
160
168
|
function useInformedAI() {
|
|
161
169
|
const context = useContext(InformedAIContext);
|
|
@@ -173,39 +181,94 @@ function InformedAIProvider({ config, children }) {
|
|
|
173
181
|
const [error, setError] = useState(null);
|
|
174
182
|
const [streamingContent, setStreamingContent] = useState("");
|
|
175
183
|
const clientRef = useRef(null);
|
|
184
|
+
const initRef = useRef(false);
|
|
185
|
+
const shouldPersist = config.persistSession ?? !!config.externalId;
|
|
186
|
+
const storageKey = getStorageKey(config.documentTypeId, config.externalId);
|
|
176
187
|
useEffect(() => {
|
|
177
188
|
clientRef.current = new InformedAIClient(config.apiUrl);
|
|
178
189
|
}, [config.apiUrl]);
|
|
190
|
+
const createNewSession = useCallback(async () => {
|
|
191
|
+
if (!clientRef.current) return null;
|
|
192
|
+
const result = await clientRef.current.createSession(
|
|
193
|
+
config.documentTypeId,
|
|
194
|
+
{
|
|
195
|
+
externalId: config.externalId,
|
|
196
|
+
initialData: config.initialData
|
|
197
|
+
}
|
|
198
|
+
);
|
|
199
|
+
const dt = {
|
|
200
|
+
id: result.documentType.id,
|
|
201
|
+
name: result.documentType.name,
|
|
202
|
+
displayName: result.documentType.displayName,
|
|
203
|
+
schema: result.documentType.schema,
|
|
204
|
+
workspaceId: "",
|
|
205
|
+
taskConfigs: {},
|
|
206
|
+
createdAt: "",
|
|
207
|
+
updatedAt: ""
|
|
208
|
+
};
|
|
209
|
+
if (shouldPersist && typeof window !== "undefined") {
|
|
210
|
+
try {
|
|
211
|
+
localStorage.setItem(storageKey, result.session.id);
|
|
212
|
+
} catch (e) {
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
return { session: result.session, document: result.document, documentType: dt };
|
|
216
|
+
}, [config.documentTypeId, config.externalId, config.initialData, shouldPersist, storageKey]);
|
|
179
217
|
useEffect(() => {
|
|
218
|
+
if (initRef.current) return;
|
|
219
|
+
initRef.current = true;
|
|
180
220
|
async function initialize() {
|
|
181
221
|
if (!clientRef.current) return;
|
|
182
222
|
try {
|
|
183
223
|
setIsLoading(true);
|
|
184
224
|
setError(null);
|
|
185
|
-
let sess;
|
|
225
|
+
let sess = null;
|
|
186
226
|
let doc = null;
|
|
187
227
|
let dt = null;
|
|
188
|
-
|
|
189
|
-
|
|
228
|
+
let sessionIdToResume = config.sessionId;
|
|
229
|
+
if (!sessionIdToResume && shouldPersist && typeof window !== "undefined") {
|
|
230
|
+
try {
|
|
231
|
+
sessionIdToResume = localStorage.getItem(storageKey) || void 0;
|
|
232
|
+
} catch (e) {
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
if (sessionIdToResume) {
|
|
236
|
+
try {
|
|
237
|
+
sess = await clientRef.current.getSession(sessionIdToResume);
|
|
238
|
+
} catch (e) {
|
|
239
|
+
console.warn("Failed to resume session, creating new one");
|
|
240
|
+
if (shouldPersist && typeof window !== "undefined") {
|
|
241
|
+
try {
|
|
242
|
+
localStorage.removeItem(storageKey);
|
|
243
|
+
} catch (e2) {
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
if (!sess) {
|
|
249
|
+
const result = await createNewSession();
|
|
250
|
+
if (result) {
|
|
251
|
+
sess = result.session;
|
|
252
|
+
doc = result.document;
|
|
253
|
+
dt = result.documentType;
|
|
254
|
+
}
|
|
190
255
|
} else {
|
|
191
|
-
const result = await
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
256
|
+
const result = await createNewSession();
|
|
257
|
+
if (result) {
|
|
258
|
+
sess = result.session;
|
|
259
|
+
doc = result.document;
|
|
260
|
+
dt = result.documentType;
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
if (sess) {
|
|
264
|
+
setSession(sess);
|
|
265
|
+
if (doc) setDocument(doc);
|
|
266
|
+
if (dt) setDocumentType(dt);
|
|
267
|
+
config.onSessionChange?.(sess);
|
|
268
|
+
if (doc && dt) {
|
|
269
|
+
config.onReady?.({ session: sess, document: doc, documentType: dt });
|
|
270
|
+
}
|
|
204
271
|
}
|
|
205
|
-
setSession(sess);
|
|
206
|
-
if (doc) setDocument(doc);
|
|
207
|
-
if (dt) setDocumentType(dt);
|
|
208
|
-
config.onSessionChange?.(sess);
|
|
209
272
|
} catch (err) {
|
|
210
273
|
const error2 = err instanceof Error ? err : new Error("Initialization failed");
|
|
211
274
|
setError(error2);
|
|
@@ -215,7 +278,7 @@ function InformedAIProvider({ config, children }) {
|
|
|
215
278
|
}
|
|
216
279
|
}
|
|
217
280
|
initialize();
|
|
218
|
-
}, [config.documentTypeId, config.sessionId]);
|
|
281
|
+
}, [config.documentTypeId, config.sessionId, config.externalId]);
|
|
219
282
|
const handleSSEEvent = useCallback((event) => {
|
|
220
283
|
if (event.type === "content" && event.content) {
|
|
221
284
|
setStreamingContent((prev) => prev + event.content);
|
|
@@ -297,6 +360,37 @@ function InformedAIProvider({ config, children }) {
|
|
|
297
360
|
config.onError?.(error2);
|
|
298
361
|
}
|
|
299
362
|
}, [session, config]);
|
|
363
|
+
const startNewSession = useCallback(async () => {
|
|
364
|
+
if (!clientRef.current) return;
|
|
365
|
+
try {
|
|
366
|
+
setIsLoading(true);
|
|
367
|
+
setError(null);
|
|
368
|
+
if (shouldPersist && typeof window !== "undefined") {
|
|
369
|
+
try {
|
|
370
|
+
localStorage.removeItem(storageKey);
|
|
371
|
+
} catch (e) {
|
|
372
|
+
}
|
|
373
|
+
}
|
|
374
|
+
const result = await createNewSession();
|
|
375
|
+
if (result) {
|
|
376
|
+
setSession(result.session);
|
|
377
|
+
setDocument(result.document);
|
|
378
|
+
setDocumentType(result.documentType);
|
|
379
|
+
config.onSessionChange?.(result.session);
|
|
380
|
+
config.onReady?.({
|
|
381
|
+
session: result.session,
|
|
382
|
+
document: result.document,
|
|
383
|
+
documentType: result.documentType
|
|
384
|
+
});
|
|
385
|
+
}
|
|
386
|
+
} catch (err) {
|
|
387
|
+
const error2 = err instanceof Error ? err : new Error("Failed to start new session");
|
|
388
|
+
setError(error2);
|
|
389
|
+
config.onError?.(error2);
|
|
390
|
+
} finally {
|
|
391
|
+
setIsLoading(false);
|
|
392
|
+
}
|
|
393
|
+
}, [createNewSession, shouldPersist, storageKey, config]);
|
|
300
394
|
const clearError = useCallback(() => {
|
|
301
395
|
setError(null);
|
|
302
396
|
}, []);
|
|
@@ -312,6 +406,7 @@ function InformedAIProvider({ config, children }) {
|
|
|
312
406
|
sendQuickAction,
|
|
313
407
|
applyPendingValue,
|
|
314
408
|
skipTask,
|
|
409
|
+
startNewSession,
|
|
315
410
|
clearError
|
|
316
411
|
};
|
|
317
412
|
return /* @__PURE__ */ jsx(InformedAIContext.Provider, { value, children });
|