@open-mercato/ui 0.6.8-develop.6879.1.9883cf6265 → 0.6.8-develop.6882.1.cd042ac354
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/ai/AiChat.js +34 -11
- package/dist/ai/AiChat.js.map +2 -2
- package/dist/ai/AiChatSessions.js +11 -2
- package/dist/ai/AiChatSessions.js.map +2 -2
- package/dist/ai/parts/useAiPendingActionPolling.js +12 -2
- package/dist/ai/parts/useAiPendingActionPolling.js.map +2 -2
- package/package.json +3 -3
- package/src/ai/AiChat.tsx +56 -27
- package/src/ai/AiChatSessions.tsx +16 -4
- package/src/ai/__tests__/AiChat.test.tsx +147 -2
- package/src/ai/__tests__/AiChatSessions.test.tsx +62 -0
- package/src/ai/parts/__tests__/useAiPendingActionPolling.test.tsx +61 -0
- package/src/ai/parts/useAiPendingActionPolling.ts +21 -6
package/dist/ai/AiChat.js
CHANGED
|
@@ -72,18 +72,34 @@ import { createLogger } from "@open-mercato/shared/lib/logger";
|
|
|
72
72
|
const logger = createLogger("ui").child({ component: "AiChat" });
|
|
73
73
|
const PREVIEW_DATA_URL_MAX_BYTES = 2 * 1024 * 1024;
|
|
74
74
|
const COMPACT_FOOTER_MAX_WIDTH = 640;
|
|
75
|
+
function readErrorStatus(error) {
|
|
76
|
+
if (typeof error !== "object" || error === null) return void 0;
|
|
77
|
+
const { status } = error;
|
|
78
|
+
return typeof status === "number" ? status : void 0;
|
|
79
|
+
}
|
|
80
|
+
function logModelsFailure(status, details) {
|
|
81
|
+
const message = "Failed to load AI agent models";
|
|
82
|
+
if (status === 401 || status === 403) {
|
|
83
|
+
logger.warn(message, details);
|
|
84
|
+
return;
|
|
85
|
+
}
|
|
86
|
+
logger.error(message, details);
|
|
87
|
+
}
|
|
75
88
|
function useAgentModels(agent) {
|
|
76
89
|
const [providers, setProviders] = React.useState([]);
|
|
77
90
|
const [allowRuntimeOverride, setAllowRuntimeOverride] = React.useState(false);
|
|
78
91
|
const [defaultLabel, setDefaultLabel] = React.useState(null);
|
|
79
|
-
const [
|
|
92
|
+
const [status, setStatus] = React.useState("loading");
|
|
80
93
|
React.useEffect(() => {
|
|
94
|
+
let cancelled = false;
|
|
81
95
|
const modelsUrl = `/api/ai_assistant/ai/agents/${encodeURIComponent(agent)}/models`;
|
|
82
|
-
|
|
96
|
+
setStatus("loading");
|
|
83
97
|
setDefaultLabel(null);
|
|
84
|
-
|
|
98
|
+
apiCall(modelsUrl).then((result) => {
|
|
99
|
+
if (cancelled) return;
|
|
85
100
|
if (!result.ok || !result.result) {
|
|
86
|
-
|
|
101
|
+
logModelsFailure(result.status, { agent, status: result.status });
|
|
102
|
+
setStatus("failed");
|
|
87
103
|
return;
|
|
88
104
|
}
|
|
89
105
|
const effectiveAllowRuntimeOverride = result.result.allowRuntimeOverride ?? result.result.allowRuntimeModelOverride ?? false;
|
|
@@ -92,15 +108,22 @@ function useAgentModels(agent) {
|
|
|
92
108
|
setDefaultLabel(
|
|
93
109
|
result.result.defaultProviderName && result.result.defaultModelName ? `${result.result.defaultProviderName} / ${result.result.defaultModelName}` : result.result.defaultProviderId && result.result.defaultModelId ? `${result.result.defaultProviderId} / ${result.result.defaultModelId}` : null
|
|
94
110
|
);
|
|
95
|
-
|
|
111
|
+
setStatus("ready");
|
|
112
|
+
}).catch((err) => {
|
|
113
|
+
if (cancelled) return;
|
|
114
|
+
logModelsFailure(readErrorStatus(err), { agent, err });
|
|
115
|
+
setStatus("failed");
|
|
96
116
|
});
|
|
117
|
+
return () => {
|
|
118
|
+
cancelled = true;
|
|
119
|
+
};
|
|
97
120
|
}, [agent]);
|
|
98
121
|
return {
|
|
99
122
|
providers,
|
|
100
123
|
allowRuntimeOverride,
|
|
101
124
|
allowRuntimeModelOverride: allowRuntimeOverride,
|
|
102
125
|
defaultLabel,
|
|
103
|
-
|
|
126
|
+
status
|
|
104
127
|
};
|
|
105
128
|
}
|
|
106
129
|
function isModelPickerValueAvailable(value, providers) {
|
|
@@ -854,13 +877,13 @@ function AiChat({
|
|
|
854
877
|
allowRuntimeOverride,
|
|
855
878
|
allowRuntimeModelOverride,
|
|
856
879
|
defaultLabel: modelDefaultLabel,
|
|
857
|
-
|
|
880
|
+
status: modelProvidersStatus
|
|
858
881
|
} = useAgentModels(agent);
|
|
859
882
|
const [modelPickerValue, setModelPickerValue] = React.useState(
|
|
860
883
|
() => readModelPickerValue(agent)
|
|
861
884
|
);
|
|
862
885
|
const effectiveModelPickerValue = React.useMemo(() => {
|
|
863
|
-
if (
|
|
886
|
+
if (modelProvidersStatus !== "ready" || !allowRuntimeOverride || modelProviders.length === 0) {
|
|
864
887
|
return null;
|
|
865
888
|
}
|
|
866
889
|
if (modelPickerValue && isModelPickerValueAvailable(modelPickerValue, modelProviders)) {
|
|
@@ -871,13 +894,13 @@ function AiChat({
|
|
|
871
894
|
allowRuntimeOverride,
|
|
872
895
|
modelPickerValue,
|
|
873
896
|
modelProviders,
|
|
874
|
-
|
|
897
|
+
modelProvidersStatus
|
|
875
898
|
]);
|
|
876
899
|
React.useEffect(() => {
|
|
877
900
|
setModelPickerValue(readModelPickerValue(agent));
|
|
878
901
|
}, [agent]);
|
|
879
902
|
React.useEffect(() => {
|
|
880
|
-
if (
|
|
903
|
+
if (modelProvidersStatus !== "ready") return;
|
|
881
904
|
if (!allowRuntimeModelOverride || modelProviders.length === 0) {
|
|
882
905
|
if (modelPickerValue !== null) {
|
|
883
906
|
setModelPickerValue(null);
|
|
@@ -894,7 +917,7 @@ function AiChat({
|
|
|
894
917
|
allowRuntimeModelOverride,
|
|
895
918
|
modelPickerValue,
|
|
896
919
|
modelProviders,
|
|
897
|
-
|
|
920
|
+
modelProvidersStatus
|
|
898
921
|
]);
|
|
899
922
|
const handleModelPickerChange = React.useCallback(
|
|
900
923
|
(value) => {
|