@informedai/react 0.4.12 → 0.4.14
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 +18 -2
- package/dist/index.d.ts +18 -2
- package/dist/index.js +35 -16
- package/dist/index.mjs +35 -16
- package/package.json +1 -1
package/dist/index.d.mts
CHANGED
|
@@ -109,6 +109,12 @@ interface InformedAssistantConfig {
|
|
|
109
109
|
onSessionChange?: (session: Session) => void;
|
|
110
110
|
/** Callback when an error occurs */
|
|
111
111
|
onError?: (error: Error) => void;
|
|
112
|
+
/**
|
|
113
|
+
* Callback to get current field values from your form.
|
|
114
|
+
* Called before each message is sent so the AI knows about unsaved changes.
|
|
115
|
+
* Return the current values of all fields as they appear in your UI.
|
|
116
|
+
*/
|
|
117
|
+
getCurrentFieldValues?: () => Record<string, unknown>;
|
|
112
118
|
/** Custom theme overrides */
|
|
113
119
|
theme?: Partial<WidgetTheme>;
|
|
114
120
|
/** Position of the widget (for floating mode) */
|
|
@@ -267,14 +273,24 @@ declare class InformedAIClient {
|
|
|
267
273
|
getSession(id: string): Promise<GetSessionResponse>;
|
|
268
274
|
/**
|
|
269
275
|
* Send a message to the session with SSE streaming.
|
|
276
|
+
*
|
|
277
|
+
* @param sessionId - The session ID
|
|
278
|
+
* @param message - The user's message
|
|
279
|
+
* @param onEvent - SSE event handler
|
|
280
|
+
* @param currentFieldValues - Current values from the UI form (for unsaved changes context)
|
|
270
281
|
*/
|
|
271
|
-
sendMessage(sessionId: string, message: string, onEvent: (event: SSEEvent) => void): Promise<void>;
|
|
282
|
+
sendMessage(sessionId: string, message: string, onEvent: (event: SSEEvent) => void, currentFieldValues?: Record<string, unknown>): Promise<void>;
|
|
272
283
|
/**
|
|
273
284
|
* Send a quick action to the session.
|
|
274
285
|
* For actions that trigger AI (task_action:*), returns SSE stream.
|
|
275
286
|
* For other actions (select_task:*, resume_task:*), returns session directly.
|
|
287
|
+
*
|
|
288
|
+
* @param sessionId - The session ID
|
|
289
|
+
* @param action - The quick action string
|
|
290
|
+
* @param onEvent - Optional SSE event handler
|
|
291
|
+
* @param currentFieldValues - Current values from the UI form (for task_action context)
|
|
276
292
|
*/
|
|
277
|
-
sendQuickAction(sessionId: string, action: string, onEvent?: (event: SSEEvent) => void): Promise<Session>;
|
|
293
|
+
sendQuickAction(sessionId: string, action: string, onEvent?: (event: SSEEvent) => void, currentFieldValues?: Record<string, unknown>): Promise<Session>;
|
|
278
294
|
/**
|
|
279
295
|
* Apply the pending value for the active task.
|
|
280
296
|
*/
|
package/dist/index.d.ts
CHANGED
|
@@ -109,6 +109,12 @@ interface InformedAssistantConfig {
|
|
|
109
109
|
onSessionChange?: (session: Session) => void;
|
|
110
110
|
/** Callback when an error occurs */
|
|
111
111
|
onError?: (error: Error) => void;
|
|
112
|
+
/**
|
|
113
|
+
* Callback to get current field values from your form.
|
|
114
|
+
* Called before each message is sent so the AI knows about unsaved changes.
|
|
115
|
+
* Return the current values of all fields as they appear in your UI.
|
|
116
|
+
*/
|
|
117
|
+
getCurrentFieldValues?: () => Record<string, unknown>;
|
|
112
118
|
/** Custom theme overrides */
|
|
113
119
|
theme?: Partial<WidgetTheme>;
|
|
114
120
|
/** Position of the widget (for floating mode) */
|
|
@@ -267,14 +273,24 @@ declare class InformedAIClient {
|
|
|
267
273
|
getSession(id: string): Promise<GetSessionResponse>;
|
|
268
274
|
/**
|
|
269
275
|
* Send a message to the session with SSE streaming.
|
|
276
|
+
*
|
|
277
|
+
* @param sessionId - The session ID
|
|
278
|
+
* @param message - The user's message
|
|
279
|
+
* @param onEvent - SSE event handler
|
|
280
|
+
* @param currentFieldValues - Current values from the UI form (for unsaved changes context)
|
|
270
281
|
*/
|
|
271
|
-
sendMessage(sessionId: string, message: string, onEvent: (event: SSEEvent) => void): Promise<void>;
|
|
282
|
+
sendMessage(sessionId: string, message: string, onEvent: (event: SSEEvent) => void, currentFieldValues?: Record<string, unknown>): Promise<void>;
|
|
272
283
|
/**
|
|
273
284
|
* Send a quick action to the session.
|
|
274
285
|
* For actions that trigger AI (task_action:*), returns SSE stream.
|
|
275
286
|
* For other actions (select_task:*, resume_task:*), returns session directly.
|
|
287
|
+
*
|
|
288
|
+
* @param sessionId - The session ID
|
|
289
|
+
* @param action - The quick action string
|
|
290
|
+
* @param onEvent - Optional SSE event handler
|
|
291
|
+
* @param currentFieldValues - Current values from the UI form (for task_action context)
|
|
276
292
|
*/
|
|
277
|
-
sendQuickAction(sessionId: string, action: string, onEvent?: (event: SSEEvent) => void): Promise<Session>;
|
|
293
|
+
sendQuickAction(sessionId: string, action: string, onEvent?: (event: SSEEvent) => void, currentFieldValues?: Record<string, unknown>): Promise<Session>;
|
|
278
294
|
/**
|
|
279
295
|
* Apply the pending value for the active task.
|
|
280
296
|
*/
|
package/dist/index.js
CHANGED
|
@@ -91,12 +91,17 @@ var InformedAIClient = class {
|
|
|
91
91
|
}
|
|
92
92
|
/**
|
|
93
93
|
* Send a message to the session with SSE streaming.
|
|
94
|
+
*
|
|
95
|
+
* @param sessionId - The session ID
|
|
96
|
+
* @param message - The user's message
|
|
97
|
+
* @param onEvent - SSE event handler
|
|
98
|
+
* @param currentFieldValues - Current values from the UI form (for unsaved changes context)
|
|
94
99
|
*/
|
|
95
|
-
async sendMessage(sessionId, message, onEvent) {
|
|
100
|
+
async sendMessage(sessionId, message, onEvent, currentFieldValues) {
|
|
96
101
|
const response = await fetch(`${this.apiUrl}/widget/sessions/${sessionId}/message`, {
|
|
97
102
|
method: "POST",
|
|
98
103
|
headers: this.getHeaders(),
|
|
99
|
-
body: JSON.stringify({ message })
|
|
104
|
+
body: JSON.stringify({ message, currentFieldValues })
|
|
100
105
|
});
|
|
101
106
|
if (!response.ok) {
|
|
102
107
|
const error = await response.json().catch(() => ({ error: "Request failed" }));
|
|
@@ -108,12 +113,17 @@ var InformedAIClient = class {
|
|
|
108
113
|
* Send a quick action to the session.
|
|
109
114
|
* For actions that trigger AI (task_action:*), returns SSE stream.
|
|
110
115
|
* For other actions (select_task:*, resume_task:*), returns session directly.
|
|
116
|
+
*
|
|
117
|
+
* @param sessionId - The session ID
|
|
118
|
+
* @param action - The quick action string
|
|
119
|
+
* @param onEvent - Optional SSE event handler
|
|
120
|
+
* @param currentFieldValues - Current values from the UI form (for task_action context)
|
|
111
121
|
*/
|
|
112
|
-
async sendQuickAction(sessionId, action, onEvent) {
|
|
122
|
+
async sendQuickAction(sessionId, action, onEvent, currentFieldValues) {
|
|
113
123
|
const response = await fetch(`${this.apiUrl}/widget/sessions/${sessionId}/quick-action`, {
|
|
114
124
|
method: "POST",
|
|
115
125
|
headers: this.getHeaders(),
|
|
116
|
-
body: JSON.stringify({ action })
|
|
126
|
+
body: JSON.stringify({ action, currentFieldValues })
|
|
117
127
|
});
|
|
118
128
|
if (!response.ok) {
|
|
119
129
|
const error = await response.json().catch(() => ({ error: "Request failed" }));
|
|
@@ -575,7 +585,8 @@ function InformedAIProvider({ config, children }) {
|
|
|
575
585
|
setIsStreaming(true);
|
|
576
586
|
setStreamingContent("");
|
|
577
587
|
setError(null);
|
|
578
|
-
|
|
588
|
+
const currentFieldValues = config.getCurrentFieldValues?.();
|
|
589
|
+
await clientRef.current.sendMessage(session.id, message, handleSSEEvent, currentFieldValues);
|
|
579
590
|
} catch (err) {
|
|
580
591
|
if (isSessionNotFoundError(err)) {
|
|
581
592
|
await handleSessionDeleted();
|
|
@@ -594,10 +605,12 @@ function InformedAIProvider({ config, children }) {
|
|
|
594
605
|
setIsStreaming(true);
|
|
595
606
|
setStreamingContent("");
|
|
596
607
|
setError(null);
|
|
608
|
+
const currentFieldValues = action.startsWith("task_action:") ? config.getCurrentFieldValues?.() : void 0;
|
|
597
609
|
const newSession = await clientRef.current.sendQuickAction(
|
|
598
610
|
session.id,
|
|
599
611
|
action,
|
|
600
|
-
handleSSEEvent
|
|
612
|
+
handleSSEEvent,
|
|
613
|
+
currentFieldValues
|
|
601
614
|
);
|
|
602
615
|
setSession(newSession);
|
|
603
616
|
config.onSessionChange?.(newSession);
|
|
@@ -742,14 +755,15 @@ function AssistantWidget({ className, theme, position = "inline", defaultCollaps
|
|
|
742
755
|
streamingContent,
|
|
743
756
|
sendMessage,
|
|
744
757
|
sendQuickAction,
|
|
745
|
-
applyPendingValue
|
|
746
|
-
skipTask
|
|
758
|
+
applyPendingValue
|
|
747
759
|
} = useInformedAI();
|
|
748
760
|
const [isCollapsed, setIsCollapsed] = (0, import_react2.useState)(defaultCollapsed);
|
|
749
761
|
const [inputValue, setInputValue] = (0, import_react2.useState)("");
|
|
762
|
+
const [showPendingActions, setShowPendingActions] = (0, import_react2.useState)(true);
|
|
750
763
|
const messagesEndRef = (0, import_react2.useRef)(null);
|
|
751
764
|
const inputRef = (0, import_react2.useRef)(null);
|
|
752
765
|
const wasStreamingRef = (0, import_react2.useRef)(false);
|
|
766
|
+
const lastPendingValueRef = (0, import_react2.useRef)(void 0);
|
|
753
767
|
(0, import_react2.useEffect)(() => {
|
|
754
768
|
messagesEndRef.current?.scrollIntoView({ behavior: "smooth" });
|
|
755
769
|
}, [session?.widgetMessages, streamingContent]);
|
|
@@ -759,6 +773,15 @@ function AssistantWidget({ className, theme, position = "inline", defaultCollaps
|
|
|
759
773
|
}
|
|
760
774
|
wasStreamingRef.current = isStreaming;
|
|
761
775
|
}, [isStreaming]);
|
|
776
|
+
const activeTask = session?.activeTask;
|
|
777
|
+
const pendingValue = activeTask ? session?.taskStates[activeTask]?.pendingValue : void 0;
|
|
778
|
+
const hasPendingValue = pendingValue !== void 0 && pendingValue !== null;
|
|
779
|
+
(0, import_react2.useEffect)(() => {
|
|
780
|
+
if (hasPendingValue && pendingValue !== lastPendingValueRef.current) {
|
|
781
|
+
setShowPendingActions(true);
|
|
782
|
+
}
|
|
783
|
+
lastPendingValueRef.current = pendingValue;
|
|
784
|
+
}, [hasPendingValue, pendingValue]);
|
|
762
785
|
const handleSubmit = async (e) => {
|
|
763
786
|
e.preventDefault();
|
|
764
787
|
if (!inputValue.trim() || isStreaming) return;
|
|
@@ -769,9 +792,6 @@ function AssistantWidget({ className, theme, position = "inline", defaultCollaps
|
|
|
769
792
|
const handleQuickAction = async (action) => {
|
|
770
793
|
await sendQuickAction(action.action, action.payload);
|
|
771
794
|
};
|
|
772
|
-
const activeTask = session?.activeTask;
|
|
773
|
-
const pendingValue = activeTask ? session?.taskStates[activeTask]?.pendingValue : void 0;
|
|
774
|
-
const hasPendingValue = pendingValue !== void 0 && pendingValue !== null;
|
|
775
795
|
const cssVars = {
|
|
776
796
|
"--ia-primary": theme.primaryColor,
|
|
777
797
|
"--ia-bg": theme.backgroundColor,
|
|
@@ -968,7 +988,7 @@ function AssistantWidget({ className, theme, position = "inline", defaultCollaps
|
|
|
968
988
|
]
|
|
969
989
|
}
|
|
970
990
|
),
|
|
971
|
-
hasPendingValue && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
|
|
991
|
+
hasPendingValue && showPendingActions ? /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
|
|
972
992
|
"div",
|
|
973
993
|
{
|
|
974
994
|
style: {
|
|
@@ -1002,7 +1022,7 @@ function AssistantWidget({ className, theme, position = "inline", defaultCollaps
|
|
|
1002
1022
|
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
1003
1023
|
"button",
|
|
1004
1024
|
{
|
|
1005
|
-
onClick:
|
|
1025
|
+
onClick: () => setShowPendingActions(false),
|
|
1006
1026
|
disabled: isStreaming,
|
|
1007
1027
|
style: {
|
|
1008
1028
|
padding: "10px 16px",
|
|
@@ -1015,13 +1035,12 @@ function AssistantWidget({ className, theme, position = "inline", defaultCollaps
|
|
|
1015
1035
|
fontSize: "14px",
|
|
1016
1036
|
opacity: isStreaming ? 0.5 : 1
|
|
1017
1037
|
},
|
|
1018
|
-
children: "
|
|
1038
|
+
children: "Not yet"
|
|
1019
1039
|
}
|
|
1020
1040
|
)
|
|
1021
1041
|
]
|
|
1022
1042
|
}
|
|
1023
|
-
),
|
|
1024
|
-
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
|
|
1043
|
+
) : /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
|
|
1025
1044
|
"form",
|
|
1026
1045
|
{
|
|
1027
1046
|
onSubmit: handleSubmit,
|
package/dist/index.mjs
CHANGED
|
@@ -61,12 +61,17 @@ var InformedAIClient = class {
|
|
|
61
61
|
}
|
|
62
62
|
/**
|
|
63
63
|
* Send a message to the session with SSE streaming.
|
|
64
|
+
*
|
|
65
|
+
* @param sessionId - The session ID
|
|
66
|
+
* @param message - The user's message
|
|
67
|
+
* @param onEvent - SSE event handler
|
|
68
|
+
* @param currentFieldValues - Current values from the UI form (for unsaved changes context)
|
|
64
69
|
*/
|
|
65
|
-
async sendMessage(sessionId, message, onEvent) {
|
|
70
|
+
async sendMessage(sessionId, message, onEvent, currentFieldValues) {
|
|
66
71
|
const response = await fetch(`${this.apiUrl}/widget/sessions/${sessionId}/message`, {
|
|
67
72
|
method: "POST",
|
|
68
73
|
headers: this.getHeaders(),
|
|
69
|
-
body: JSON.stringify({ message })
|
|
74
|
+
body: JSON.stringify({ message, currentFieldValues })
|
|
70
75
|
});
|
|
71
76
|
if (!response.ok) {
|
|
72
77
|
const error = await response.json().catch(() => ({ error: "Request failed" }));
|
|
@@ -78,12 +83,17 @@ var InformedAIClient = class {
|
|
|
78
83
|
* Send a quick action to the session.
|
|
79
84
|
* For actions that trigger AI (task_action:*), returns SSE stream.
|
|
80
85
|
* For other actions (select_task:*, resume_task:*), returns session directly.
|
|
86
|
+
*
|
|
87
|
+
* @param sessionId - The session ID
|
|
88
|
+
* @param action - The quick action string
|
|
89
|
+
* @param onEvent - Optional SSE event handler
|
|
90
|
+
* @param currentFieldValues - Current values from the UI form (for task_action context)
|
|
81
91
|
*/
|
|
82
|
-
async sendQuickAction(sessionId, action, onEvent) {
|
|
92
|
+
async sendQuickAction(sessionId, action, onEvent, currentFieldValues) {
|
|
83
93
|
const response = await fetch(`${this.apiUrl}/widget/sessions/${sessionId}/quick-action`, {
|
|
84
94
|
method: "POST",
|
|
85
95
|
headers: this.getHeaders(),
|
|
86
|
-
body: JSON.stringify({ action })
|
|
96
|
+
body: JSON.stringify({ action, currentFieldValues })
|
|
87
97
|
});
|
|
88
98
|
if (!response.ok) {
|
|
89
99
|
const error = await response.json().catch(() => ({ error: "Request failed" }));
|
|
@@ -545,7 +555,8 @@ function InformedAIProvider({ config, children }) {
|
|
|
545
555
|
setIsStreaming(true);
|
|
546
556
|
setStreamingContent("");
|
|
547
557
|
setError(null);
|
|
548
|
-
|
|
558
|
+
const currentFieldValues = config.getCurrentFieldValues?.();
|
|
559
|
+
await clientRef.current.sendMessage(session.id, message, handleSSEEvent, currentFieldValues);
|
|
549
560
|
} catch (err) {
|
|
550
561
|
if (isSessionNotFoundError(err)) {
|
|
551
562
|
await handleSessionDeleted();
|
|
@@ -564,10 +575,12 @@ function InformedAIProvider({ config, children }) {
|
|
|
564
575
|
setIsStreaming(true);
|
|
565
576
|
setStreamingContent("");
|
|
566
577
|
setError(null);
|
|
578
|
+
const currentFieldValues = action.startsWith("task_action:") ? config.getCurrentFieldValues?.() : void 0;
|
|
567
579
|
const newSession = await clientRef.current.sendQuickAction(
|
|
568
580
|
session.id,
|
|
569
581
|
action,
|
|
570
|
-
handleSSEEvent
|
|
582
|
+
handleSSEEvent,
|
|
583
|
+
currentFieldValues
|
|
571
584
|
);
|
|
572
585
|
setSession(newSession);
|
|
573
586
|
config.onSessionChange?.(newSession);
|
|
@@ -712,14 +725,15 @@ function AssistantWidget({ className, theme, position = "inline", defaultCollaps
|
|
|
712
725
|
streamingContent,
|
|
713
726
|
sendMessage,
|
|
714
727
|
sendQuickAction,
|
|
715
|
-
applyPendingValue
|
|
716
|
-
skipTask
|
|
728
|
+
applyPendingValue
|
|
717
729
|
} = useInformedAI();
|
|
718
730
|
const [isCollapsed, setIsCollapsed] = useState2(defaultCollapsed);
|
|
719
731
|
const [inputValue, setInputValue] = useState2("");
|
|
732
|
+
const [showPendingActions, setShowPendingActions] = useState2(true);
|
|
720
733
|
const messagesEndRef = useRef2(null);
|
|
721
734
|
const inputRef = useRef2(null);
|
|
722
735
|
const wasStreamingRef = useRef2(false);
|
|
736
|
+
const lastPendingValueRef = useRef2(void 0);
|
|
723
737
|
useEffect2(() => {
|
|
724
738
|
messagesEndRef.current?.scrollIntoView({ behavior: "smooth" });
|
|
725
739
|
}, [session?.widgetMessages, streamingContent]);
|
|
@@ -729,6 +743,15 @@ function AssistantWidget({ className, theme, position = "inline", defaultCollaps
|
|
|
729
743
|
}
|
|
730
744
|
wasStreamingRef.current = isStreaming;
|
|
731
745
|
}, [isStreaming]);
|
|
746
|
+
const activeTask = session?.activeTask;
|
|
747
|
+
const pendingValue = activeTask ? session?.taskStates[activeTask]?.pendingValue : void 0;
|
|
748
|
+
const hasPendingValue = pendingValue !== void 0 && pendingValue !== null;
|
|
749
|
+
useEffect2(() => {
|
|
750
|
+
if (hasPendingValue && pendingValue !== lastPendingValueRef.current) {
|
|
751
|
+
setShowPendingActions(true);
|
|
752
|
+
}
|
|
753
|
+
lastPendingValueRef.current = pendingValue;
|
|
754
|
+
}, [hasPendingValue, pendingValue]);
|
|
732
755
|
const handleSubmit = async (e) => {
|
|
733
756
|
e.preventDefault();
|
|
734
757
|
if (!inputValue.trim() || isStreaming) return;
|
|
@@ -739,9 +762,6 @@ function AssistantWidget({ className, theme, position = "inline", defaultCollaps
|
|
|
739
762
|
const handleQuickAction = async (action) => {
|
|
740
763
|
await sendQuickAction(action.action, action.payload);
|
|
741
764
|
};
|
|
742
|
-
const activeTask = session?.activeTask;
|
|
743
|
-
const pendingValue = activeTask ? session?.taskStates[activeTask]?.pendingValue : void 0;
|
|
744
|
-
const hasPendingValue = pendingValue !== void 0 && pendingValue !== null;
|
|
745
765
|
const cssVars = {
|
|
746
766
|
"--ia-primary": theme.primaryColor,
|
|
747
767
|
"--ia-bg": theme.backgroundColor,
|
|
@@ -938,7 +958,7 @@ function AssistantWidget({ className, theme, position = "inline", defaultCollaps
|
|
|
938
958
|
]
|
|
939
959
|
}
|
|
940
960
|
),
|
|
941
|
-
hasPendingValue && /* @__PURE__ */ jsxs(
|
|
961
|
+
hasPendingValue && showPendingActions ? /* @__PURE__ */ jsxs(
|
|
942
962
|
"div",
|
|
943
963
|
{
|
|
944
964
|
style: {
|
|
@@ -972,7 +992,7 @@ function AssistantWidget({ className, theme, position = "inline", defaultCollaps
|
|
|
972
992
|
/* @__PURE__ */ jsx2(
|
|
973
993
|
"button",
|
|
974
994
|
{
|
|
975
|
-
onClick:
|
|
995
|
+
onClick: () => setShowPendingActions(false),
|
|
976
996
|
disabled: isStreaming,
|
|
977
997
|
style: {
|
|
978
998
|
padding: "10px 16px",
|
|
@@ -985,13 +1005,12 @@ function AssistantWidget({ className, theme, position = "inline", defaultCollaps
|
|
|
985
1005
|
fontSize: "14px",
|
|
986
1006
|
opacity: isStreaming ? 0.5 : 1
|
|
987
1007
|
},
|
|
988
|
-
children: "
|
|
1008
|
+
children: "Not yet"
|
|
989
1009
|
}
|
|
990
1010
|
)
|
|
991
1011
|
]
|
|
992
1012
|
}
|
|
993
|
-
)
|
|
994
|
-
/* @__PURE__ */ jsxs(
|
|
1013
|
+
) : /* @__PURE__ */ jsxs(
|
|
995
1014
|
"form",
|
|
996
1015
|
{
|
|
997
1016
|
onSubmit: handleSubmit,
|