Disable chat input while extensions load (#4417)
This commit is contained in:
+16
-10
@@ -45,11 +45,13 @@ const HubRouteWrapper = ({
|
|||||||
setChat,
|
setChat,
|
||||||
setPairChat,
|
setPairChat,
|
||||||
setIsGoosehintsModalOpen,
|
setIsGoosehintsModalOpen,
|
||||||
|
isExtensionsLoading,
|
||||||
}: {
|
}: {
|
||||||
chat: ChatType;
|
chat: ChatType;
|
||||||
setChat: (chat: ChatType) => void;
|
setChat: (chat: ChatType) => void;
|
||||||
setPairChat: (chat: ChatType) => void;
|
setPairChat: (chat: ChatType) => void;
|
||||||
setIsGoosehintsModalOpen: (isOpen: boolean) => void;
|
setIsGoosehintsModalOpen: (isOpen: boolean) => void;
|
||||||
|
isExtensionsLoading: boolean;
|
||||||
}) => {
|
}) => {
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
const setView = createNavigationHandler(navigate);
|
const setView = createNavigationHandler(navigate);
|
||||||
@@ -62,6 +64,7 @@ const HubRouteWrapper = ({
|
|||||||
setPairChat={setPairChat}
|
setPairChat={setPairChat}
|
||||||
setView={setView}
|
setView={setView}
|
||||||
setIsGoosehintsModalOpen={setIsGoosehintsModalOpen}
|
setIsGoosehintsModalOpen={setIsGoosehintsModalOpen}
|
||||||
|
isExtensionsLoading={isExtensionsLoading}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
@@ -400,6 +403,7 @@ export default function App() {
|
|||||||
const [agentWaitingMessage, setAgentWaitingMessage] = useState<string | null>(null);
|
const [agentWaitingMessage, setAgentWaitingMessage] = useState<string | null>(null);
|
||||||
const [isLoadingSharedSession, setIsLoadingSharedSession] = useState(false);
|
const [isLoadingSharedSession, setIsLoadingSharedSession] = useState(false);
|
||||||
const [sharedSessionError, setSharedSessionError] = useState<string | null>(null);
|
const [sharedSessionError, setSharedSessionError] = useState<string | null>(null);
|
||||||
|
const [isExtensionsLoading, setIsExtensionsLoading] = useState(false);
|
||||||
|
|
||||||
// Add separate state for pair chat to maintain its own conversation
|
// Add separate state for pair chat to maintain its own conversation
|
||||||
const [pairChat, setPairChat] = useState<ChatType>({
|
const [pairChat, setPairChat] = useState<ChatType>({
|
||||||
@@ -482,6 +486,7 @@ export default function App() {
|
|||||||
addExtension,
|
addExtension,
|
||||||
setPairChat,
|
setPairChat,
|
||||||
setMessage: setAgentWaitingMessage,
|
setMessage: setAgentWaitingMessage,
|
||||||
|
setIsExtensionsLoading,
|
||||||
provider: provider as string,
|
provider: provider as string,
|
||||||
model: model as string,
|
model: model as string,
|
||||||
});
|
});
|
||||||
@@ -802,12 +807,13 @@ export default function App() {
|
|||||||
<Route
|
<Route
|
||||||
index
|
index
|
||||||
element={
|
element={
|
||||||
<ProviderGuard>
|
<ProviderGuard setIsExtensionsLoading={setIsExtensionsLoading}>
|
||||||
<HubRouteWrapper
|
<HubRouteWrapper
|
||||||
chat={chat}
|
chat={chat}
|
||||||
setChat={setChat}
|
setChat={setChat}
|
||||||
setPairChat={setPairChat}
|
setPairChat={setPairChat}
|
||||||
setIsGoosehintsModalOpen={setIsGoosehintsModalOpen}
|
setIsGoosehintsModalOpen={setIsGoosehintsModalOpen}
|
||||||
|
isExtensionsLoading={isExtensionsLoading}
|
||||||
/>
|
/>
|
||||||
</ProviderGuard>
|
</ProviderGuard>
|
||||||
}
|
}
|
||||||
@@ -815,7 +821,7 @@ export default function App() {
|
|||||||
<Route
|
<Route
|
||||||
path="pair"
|
path="pair"
|
||||||
element={
|
element={
|
||||||
<ProviderGuard>
|
<ProviderGuard setIsExtensionsLoading={setIsExtensionsLoading}>
|
||||||
<ChatProvider
|
<ChatProvider
|
||||||
chat={pairChat}
|
chat={pairChat}
|
||||||
setChat={setPairChat}
|
setChat={setPairChat}
|
||||||
@@ -836,7 +842,7 @@ export default function App() {
|
|||||||
<Route
|
<Route
|
||||||
path="settings"
|
path="settings"
|
||||||
element={
|
element={
|
||||||
<ProviderGuard>
|
<ProviderGuard setIsExtensionsLoading={setIsExtensionsLoading}>
|
||||||
<SettingsRoute />
|
<SettingsRoute />
|
||||||
</ProviderGuard>
|
</ProviderGuard>
|
||||||
}
|
}
|
||||||
@@ -844,7 +850,7 @@ export default function App() {
|
|||||||
<Route
|
<Route
|
||||||
path="extensions"
|
path="extensions"
|
||||||
element={
|
element={
|
||||||
<ProviderGuard>
|
<ProviderGuard setIsExtensionsLoading={setIsExtensionsLoading}>
|
||||||
<ExtensionsRoute />
|
<ExtensionsRoute />
|
||||||
</ProviderGuard>
|
</ProviderGuard>
|
||||||
}
|
}
|
||||||
@@ -852,7 +858,7 @@ export default function App() {
|
|||||||
<Route
|
<Route
|
||||||
path="sessions"
|
path="sessions"
|
||||||
element={
|
element={
|
||||||
<ProviderGuard>
|
<ProviderGuard setIsExtensionsLoading={setIsExtensionsLoading}>
|
||||||
<SessionsRoute />
|
<SessionsRoute />
|
||||||
</ProviderGuard>
|
</ProviderGuard>
|
||||||
}
|
}
|
||||||
@@ -860,7 +866,7 @@ export default function App() {
|
|||||||
<Route
|
<Route
|
||||||
path="schedules"
|
path="schedules"
|
||||||
element={
|
element={
|
||||||
<ProviderGuard>
|
<ProviderGuard setIsExtensionsLoading={setIsExtensionsLoading}>
|
||||||
<SchedulesRoute />
|
<SchedulesRoute />
|
||||||
</ProviderGuard>
|
</ProviderGuard>
|
||||||
}
|
}
|
||||||
@@ -868,7 +874,7 @@ export default function App() {
|
|||||||
<Route
|
<Route
|
||||||
path="recipes"
|
path="recipes"
|
||||||
element={
|
element={
|
||||||
<ProviderGuard>
|
<ProviderGuard setIsExtensionsLoading={setIsExtensionsLoading}>
|
||||||
<RecipesRoute />
|
<RecipesRoute />
|
||||||
</ProviderGuard>
|
</ProviderGuard>
|
||||||
}
|
}
|
||||||
@@ -876,7 +882,7 @@ export default function App() {
|
|||||||
<Route
|
<Route
|
||||||
path="recipe-editor"
|
path="recipe-editor"
|
||||||
element={
|
element={
|
||||||
<ProviderGuard>
|
<ProviderGuard setIsExtensionsLoading={setIsExtensionsLoading}>
|
||||||
<RecipeEditorRoute />
|
<RecipeEditorRoute />
|
||||||
</ProviderGuard>
|
</ProviderGuard>
|
||||||
}
|
}
|
||||||
@@ -884,7 +890,7 @@ export default function App() {
|
|||||||
<Route
|
<Route
|
||||||
path="shared-session"
|
path="shared-session"
|
||||||
element={
|
element={
|
||||||
<ProviderGuard>
|
<ProviderGuard setIsExtensionsLoading={setIsExtensionsLoading}>
|
||||||
<SharedSessionRouteWrapper
|
<SharedSessionRouteWrapper
|
||||||
isLoadingSharedSession={isLoadingSharedSession}
|
isLoadingSharedSession={isLoadingSharedSession}
|
||||||
setIsLoadingSharedSession={setIsLoadingSharedSession}
|
setIsLoadingSharedSession={setIsLoadingSharedSession}
|
||||||
@@ -896,7 +902,7 @@ export default function App() {
|
|||||||
<Route
|
<Route
|
||||||
path="permission"
|
path="permission"
|
||||||
element={
|
element={
|
||||||
<ProviderGuard>
|
<ProviderGuard setIsExtensionsLoading={setIsExtensionsLoading}>
|
||||||
<PermissionRoute />
|
<PermissionRoute />
|
||||||
</ProviderGuard>
|
</ProviderGuard>
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -86,6 +86,7 @@ interface ChatInputProps {
|
|||||||
autoSubmit: boolean;
|
autoSubmit: boolean;
|
||||||
setAncestorMessages?: (messages: Message[]) => void;
|
setAncestorMessages?: (messages: Message[]) => void;
|
||||||
append?: (message: Message) => void;
|
append?: (message: Message) => void;
|
||||||
|
isExtensionsLoading?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function ChatInput({
|
export default function ChatInput({
|
||||||
@@ -111,6 +112,7 @@ export default function ChatInput({
|
|||||||
autoSubmit = false,
|
autoSubmit = false,
|
||||||
append,
|
append,
|
||||||
setAncestorMessages,
|
setAncestorMessages,
|
||||||
|
isExtensionsLoading = false,
|
||||||
}: ChatInputProps) {
|
}: ChatInputProps) {
|
||||||
const [_value, setValue] = useState(initialValue);
|
const [_value, setValue] = useState(initialValue);
|
||||||
const [displayValue, setDisplayValue] = useState(initialValue); // For immediate visual feedback
|
const [displayValue, setDisplayValue] = useState(initialValue); // For immediate visual feedback
|
||||||
@@ -1125,6 +1127,25 @@ export default function ChatInput({
|
|||||||
const isAnyImageLoading = pastedImages.some((img) => img.isLoading);
|
const isAnyImageLoading = pastedImages.some((img) => img.isLoading);
|
||||||
const isAnyDroppedFileLoading = allDroppedFiles.some((file) => file.isLoading);
|
const isAnyDroppedFileLoading = allDroppedFiles.some((file) => file.isLoading);
|
||||||
|
|
||||||
|
const isSubmitButtonDisabled =
|
||||||
|
!hasSubmittableContent ||
|
||||||
|
isAnyImageLoading ||
|
||||||
|
isAnyDroppedFileLoading ||
|
||||||
|
isRecording ||
|
||||||
|
isTranscribing ||
|
||||||
|
isCompacting ||
|
||||||
|
!agentIsReady ||
|
||||||
|
isExtensionsLoading;
|
||||||
|
|
||||||
|
const isUserInputDisabled =
|
||||||
|
isAnyImageLoading ||
|
||||||
|
isAnyDroppedFileLoading ||
|
||||||
|
isRecording ||
|
||||||
|
isTranscribing ||
|
||||||
|
isCompacting ||
|
||||||
|
!agentIsReady ||
|
||||||
|
isExtensionsLoading;
|
||||||
|
|
||||||
// Queue management functions - no storage persistence, only in-memory
|
// Queue management functions - no storage persistence, only in-memory
|
||||||
const handleRemoveQueuedMessage = (messageId: string) => {
|
const handleRemoveQueuedMessage = (messageId: string) => {
|
||||||
setQueuedMessages((prev) => prev.filter((msg) => msg.id !== messageId));
|
setQueuedMessages((prev) => prev.filter((msg) => msg.id !== messageId));
|
||||||
@@ -1239,6 +1260,7 @@ export default function ChatInput({
|
|||||||
onBlur={() => setIsFocused(false)}
|
onBlur={() => setIsFocused(false)}
|
||||||
ref={textAreaRef}
|
ref={textAreaRef}
|
||||||
rows={1}
|
rows={1}
|
||||||
|
disabled={isUserInputDisabled}
|
||||||
style={{
|
style={{
|
||||||
maxHeight: `${maxHeight}px`,
|
maxHeight: `${maxHeight}px`,
|
||||||
overflowY: 'auto',
|
overflowY: 'auto',
|
||||||
@@ -1349,23 +1371,9 @@ export default function ChatInput({
|
|||||||
size="sm"
|
size="sm"
|
||||||
shape="round"
|
shape="round"
|
||||||
variant="outline"
|
variant="outline"
|
||||||
disabled={
|
disabled={isSubmitButtonDisabled}
|
||||||
!hasSubmittableContent ||
|
|
||||||
isAnyImageLoading ||
|
|
||||||
isAnyDroppedFileLoading ||
|
|
||||||
isRecording ||
|
|
||||||
isTranscribing ||
|
|
||||||
isCompacting ||
|
|
||||||
!agentIsReady
|
|
||||||
}
|
|
||||||
className={`rounded-full px-10 py-2 flex items-center gap-2 ${
|
className={`rounded-full px-10 py-2 flex items-center gap-2 ${
|
||||||
!hasSubmittableContent ||
|
isSubmitButtonDisabled
|
||||||
isAnyImageLoading ||
|
|
||||||
isAnyDroppedFileLoading ||
|
|
||||||
isRecording ||
|
|
||||||
isTranscribing ||
|
|
||||||
isCompacting ||
|
|
||||||
!agentIsReady
|
|
||||||
? 'bg-slate-600 text-white cursor-not-allowed opacity-50 border-slate-600'
|
? 'bg-slate-600 text-white cursor-not-allowed opacity-50 border-slate-600'
|
||||||
: 'bg-slate-600 text-white hover:bg-slate-700 border-slate-600 hover:cursor-pointer'
|
: 'bg-slate-600 text-white hover:bg-slate-700 border-slate-600 hover:cursor-pointer'
|
||||||
}`}
|
}`}
|
||||||
@@ -1377,17 +1385,19 @@ export default function ChatInput({
|
|||||||
</TooltipTrigger>
|
</TooltipTrigger>
|
||||||
<TooltipContent>
|
<TooltipContent>
|
||||||
<p>
|
<p>
|
||||||
{isCompacting
|
{isExtensionsLoading
|
||||||
? 'Compacting conversation...'
|
? 'Loading extensions...'
|
||||||
: isAnyImageLoading
|
: isCompacting
|
||||||
? 'Waiting for images to save...'
|
? 'Compacting conversation...'
|
||||||
: isAnyDroppedFileLoading
|
: isAnyImageLoading
|
||||||
? 'Processing dropped files...'
|
? 'Waiting for images to save...'
|
||||||
: isRecording
|
: isAnyDroppedFileLoading
|
||||||
? 'Recording...'
|
? 'Processing dropped files...'
|
||||||
: isTranscribing
|
: isRecording
|
||||||
? 'Transcribing...'
|
? 'Recording...'
|
||||||
: (chatContext?.agentWaitingMessage ?? 'Send')}
|
: isTranscribing
|
||||||
|
? 'Transcribing...'
|
||||||
|
: (chatContext?.agentWaitingMessage ?? 'Send')}
|
||||||
</p>
|
</p>
|
||||||
</TooltipContent>
|
</TooltipContent>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
|
|||||||
@@ -16,9 +16,10 @@ import { Ollama } from './icons';
|
|||||||
interface OllamaSetupProps {
|
interface OllamaSetupProps {
|
||||||
onSuccess: () => void;
|
onSuccess: () => void;
|
||||||
onCancel: () => void;
|
onCancel: () => void;
|
||||||
|
setIsExtensionsLoading?: (loading: boolean) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function OllamaSetup({ onSuccess, onCancel }: OllamaSetupProps) {
|
export function OllamaSetup({ onSuccess, onCancel, setIsExtensionsLoading }: OllamaSetupProps) {
|
||||||
const { addExtension, getExtensions, upsert } = useConfig();
|
const { addExtension, getExtensions, upsert } = useConfig();
|
||||||
const [isChecking, setIsChecking] = useState(true);
|
const [isChecking, setIsChecking] = useState(true);
|
||||||
const [ollamaDetected, setOllamaDetected] = useState(false);
|
const [ollamaDetected, setOllamaDetected] = useState(false);
|
||||||
@@ -113,6 +114,7 @@ export function OllamaSetup({ onSuccess, onCancel }: OllamaSetupProps) {
|
|||||||
await initializeSystem('ollama', getPreferredModel(), {
|
await initializeSystem('ollama', getPreferredModel(), {
|
||||||
getExtensions,
|
getExtensions,
|
||||||
addExtension,
|
addExtension,
|
||||||
|
setIsExtensionsLoading,
|
||||||
});
|
});
|
||||||
|
|
||||||
toastService.success({
|
toastService.success({
|
||||||
@@ -157,7 +159,9 @@ export function OllamaSetup({ onSuccess, onCancel }: OllamaSetupProps) {
|
|||||||
{ollamaDetected ? (
|
{ollamaDetected ? (
|
||||||
<div className="space-y-4">
|
<div className="space-y-4">
|
||||||
<div className="flex items-start mb-16">
|
<div className="flex items-start mb-16">
|
||||||
<span className="inline-block px-2 py-1 text-xs font-medium bg-green-600 text-white rounded-full">Ollama is detected and running</span>
|
<span className="inline-block px-2 py-1 text-xs font-medium bg-green-600 text-white rounded-full">
|
||||||
|
Ollama is detected and running
|
||||||
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{modelStatus === 'checking' ? (
|
{modelStatus === 'checking' ? (
|
||||||
@@ -185,14 +189,10 @@ export function OllamaSetup({ onSuccess, onCancel }: OllamaSetupProps) {
|
|||||||
) : modelStatus === 'downloading' ? (
|
) : modelStatus === 'downloading' ? (
|
||||||
<div className="space-y-4">
|
<div className="space-y-4">
|
||||||
<div className="bg-background-info/10 border border-border-info rounded-lg p-4">
|
<div className="bg-background-info/10 border border-border-info rounded-lg p-4">
|
||||||
<p className="text-text-info text-sm">
|
<p className="text-text-info text-sm">Downloading {getPreferredModel()}...</p>
|
||||||
Downloading {getPreferredModel()}...
|
|
||||||
</p>
|
|
||||||
{downloadProgress && (
|
{downloadProgress && (
|
||||||
<>
|
<>
|
||||||
<p className="text-text-muted text-xs mt-2">
|
<p className="text-text-muted text-xs mt-2">{downloadProgress.status}</p>
|
||||||
{downloadProgress.status}
|
|
||||||
</p>
|
|
||||||
{downloadProgress.total && downloadProgress.completed && (
|
{downloadProgress.total && downloadProgress.completed && (
|
||||||
<div className="mt-3">
|
<div className="mt-3">
|
||||||
<div className="bg-background-muted rounded-full h-2 overflow-hidden">
|
<div className="bg-background-muted rounded-full h-2 overflow-hidden">
|
||||||
@@ -225,7 +225,9 @@ export function OllamaSetup({ onSuccess, onCancel }: OllamaSetupProps) {
|
|||||||
) : (
|
) : (
|
||||||
<div className="space-y-4">
|
<div className="space-y-4">
|
||||||
<div className="flex items-start mb-16">
|
<div className="flex items-start mb-16">
|
||||||
<span className="inline-block px-2 py-1 text-xs font-medium bg-orange-600 text-white rounded-full">Ollama is not detected on your system</span>
|
<span className="inline-block px-2 py-1 text-xs font-medium bg-orange-600 text-white rounded-full">
|
||||||
|
Ollama is not detected on your system
|
||||||
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{isPolling ? (
|
{isPolling ? (
|
||||||
|
|||||||
@@ -14,9 +14,10 @@ import { OpenRouter } from './icons';
|
|||||||
|
|
||||||
interface ProviderGuardProps {
|
interface ProviderGuardProps {
|
||||||
children: React.ReactNode;
|
children: React.ReactNode;
|
||||||
|
setIsExtensionsLoading?: (loading: boolean) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function ProviderGuard({ children }: ProviderGuardProps) {
|
export default function ProviderGuard({ children, setIsExtensionsLoading }: ProviderGuardProps) {
|
||||||
const { read, getExtensions, addExtension } = useConfig();
|
const { read, getExtensions, addExtension } = useConfig();
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
const [isChecking, setIsChecking] = useState(true);
|
const [isChecking, setIsChecking] = useState(true);
|
||||||
@@ -72,6 +73,7 @@ export default function ProviderGuard({ children }: ProviderGuardProps) {
|
|||||||
await initializeSystem(provider as string, model as string, {
|
await initializeSystem(provider as string, model as string, {
|
||||||
getExtensions,
|
getExtensions,
|
||||||
addExtension,
|
addExtension,
|
||||||
|
setIsExtensionsLoading,
|
||||||
});
|
});
|
||||||
|
|
||||||
toastService.configure({ silent: false });
|
toastService.configure({ silent: false });
|
||||||
@@ -138,6 +140,7 @@ export default function ProviderGuard({ children }: ProviderGuardProps) {
|
|||||||
await initializeSystem(provider as string, model as string, {
|
await initializeSystem(provider as string, model as string, {
|
||||||
getExtensions,
|
getExtensions,
|
||||||
addExtension,
|
addExtension,
|
||||||
|
setIsExtensionsLoading,
|
||||||
});
|
});
|
||||||
|
|
||||||
toastService.configure({ silent: false });
|
toastService.configure({ silent: false });
|
||||||
@@ -267,6 +270,7 @@ export default function ProviderGuard({ children }: ProviderGuardProps) {
|
|||||||
setShowOllamaSetup(false);
|
setShowOllamaSetup(false);
|
||||||
setShowFirstTimeSetup(true);
|
setShowFirstTimeSetup(true);
|
||||||
}}
|
}}
|
||||||
|
setIsExtensionsLoading={setIsExtensionsLoading}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -36,6 +36,7 @@ export default function Hub({
|
|||||||
setPairChat,
|
setPairChat,
|
||||||
setView,
|
setView,
|
||||||
setIsGoosehintsModalOpen,
|
setIsGoosehintsModalOpen,
|
||||||
|
isExtensionsLoading,
|
||||||
}: {
|
}: {
|
||||||
readyForAutoUserPrompt: boolean;
|
readyForAutoUserPrompt: boolean;
|
||||||
chat: ChatType;
|
chat: ChatType;
|
||||||
@@ -43,6 +44,7 @@ export default function Hub({
|
|||||||
setPairChat: (chat: ChatType) => void;
|
setPairChat: (chat: ChatType) => void;
|
||||||
setView: (view: View, viewOptions?: ViewOptions) => void;
|
setView: (view: View, viewOptions?: ViewOptions) => void;
|
||||||
setIsGoosehintsModalOpen: (isOpen: boolean) => void;
|
setIsGoosehintsModalOpen: (isOpen: boolean) => void;
|
||||||
|
isExtensionsLoading: boolean;
|
||||||
}) {
|
}) {
|
||||||
// Handle chat input submission - create new chat and navigate to pair
|
// Handle chat input submission - create new chat and navigate to pair
|
||||||
const handleSubmit = (e: React.FormEvent) => {
|
const handleSubmit = (e: React.FormEvent) => {
|
||||||
@@ -101,6 +103,7 @@ export default function Hub({
|
|||||||
disableAnimation={false}
|
disableAnimation={false}
|
||||||
sessionCosts={undefined}
|
sessionCosts={undefined}
|
||||||
setIsGoosehintsModalOpen={setIsGoosehintsModalOpen}
|
setIsGoosehintsModalOpen={setIsGoosehintsModalOpen}
|
||||||
|
isExtensionsLoading={isExtensionsLoading}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</ContextManagerProvider>
|
</ContextManagerProvider>
|
||||||
|
|||||||
@@ -10,9 +10,14 @@ import { toastService } from '../../../toasts';
|
|||||||
interface ProviderSettingsProps {
|
interface ProviderSettingsProps {
|
||||||
onClose: () => void;
|
onClose: () => void;
|
||||||
isOnboarding: boolean;
|
isOnboarding: boolean;
|
||||||
|
setIsExtensionsLoading?: (loading: boolean) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function ProviderSettings({ onClose, isOnboarding }: ProviderSettingsProps) {
|
export default function ProviderSettings({
|
||||||
|
onClose,
|
||||||
|
isOnboarding,
|
||||||
|
setIsExtensionsLoading,
|
||||||
|
}: ProviderSettingsProps) {
|
||||||
const { getProviders, upsert, getExtensions, addExtension } = useConfig();
|
const { getProviders, upsert, getExtensions, addExtension } = useConfig();
|
||||||
const [loading, setLoading] = useState(true);
|
const [loading, setLoading] = useState(true);
|
||||||
const [providers, setProviders] = useState<ProviderDetails[]>([]);
|
const [providers, setProviders] = useState<ProviderDetails[]>([]);
|
||||||
@@ -71,6 +76,7 @@ export default function ProviderSettings({ onClose, isOnboarding }: ProviderSett
|
|||||||
await initializeSystem(provider.name, model, {
|
await initializeSystem(provider.name, model, {
|
||||||
getExtensions,
|
getExtensions,
|
||||||
addExtension,
|
addExtension,
|
||||||
|
setIsExtensionsLoading,
|
||||||
});
|
});
|
||||||
|
|
||||||
toastService.configure({ silent: false });
|
toastService.configure({ silent: false });
|
||||||
@@ -92,7 +98,7 @@ export default function ProviderSettings({ onClose, isOnboarding }: ProviderSett
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
[onClose, upsert, getExtensions, addExtension]
|
[onClose, upsert, getExtensions, addExtension, setIsExtensionsLoading]
|
||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ interface InitializationDependencies {
|
|||||||
addExtension?: (name: string, config: ExtensionConfig, enabled: boolean) => Promise<void>;
|
addExtension?: (name: string, config: ExtensionConfig, enabled: boolean) => Promise<void>;
|
||||||
setPairChat: (chat: ChatType | ((prev: ChatType) => ChatType)) => void;
|
setPairChat: (chat: ChatType | ((prev: ChatType) => ChatType)) => void;
|
||||||
setMessage: (message: string | null) => void;
|
setMessage: (message: string | null) => void;
|
||||||
|
setIsExtensionsLoading: (loading: boolean) => void;
|
||||||
provider: string;
|
provider: string;
|
||||||
model: string;
|
model: string;
|
||||||
}
|
}
|
||||||
@@ -24,6 +25,7 @@ export const initializeApp = async ({
|
|||||||
addExtension,
|
addExtension,
|
||||||
setPairChat,
|
setPairChat,
|
||||||
setMessage,
|
setMessage,
|
||||||
|
setIsExtensionsLoading,
|
||||||
provider,
|
provider,
|
||||||
model,
|
model,
|
||||||
}: InitializationDependencies) => {
|
}: InitializationDependencies) => {
|
||||||
@@ -36,7 +38,13 @@ export const initializeApp = async ({
|
|||||||
|
|
||||||
if (resumeSessionId) {
|
if (resumeSessionId) {
|
||||||
console.log('Session resume detected, letting useChat hook handle navigation');
|
console.log('Session resume detected, letting useChat hook handle navigation');
|
||||||
await initializeForSessionResume({ getExtensions, addExtension, provider, model });
|
await initializeForSessionResume({
|
||||||
|
getExtensions,
|
||||||
|
addExtension,
|
||||||
|
setIsExtensionsLoading,
|
||||||
|
provider,
|
||||||
|
model,
|
||||||
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -47,6 +55,7 @@ export const initializeApp = async ({
|
|||||||
getExtensions,
|
getExtensions,
|
||||||
addExtension,
|
addExtension,
|
||||||
setPairChat,
|
setPairChat,
|
||||||
|
setIsExtensionsLoading,
|
||||||
provider,
|
provider,
|
||||||
model,
|
model,
|
||||||
});
|
});
|
||||||
@@ -82,6 +91,7 @@ export const initializeApp = async ({
|
|||||||
initializeSystem(provider, model, {
|
initializeSystem(provider, model, {
|
||||||
getExtensions,
|
getExtensions,
|
||||||
addExtension,
|
addExtension,
|
||||||
|
setIsExtensionsLoading,
|
||||||
}),
|
}),
|
||||||
];
|
];
|
||||||
|
|
||||||
@@ -115,15 +125,20 @@ export const initializeApp = async ({
|
|||||||
const initializeForSessionResume = async ({
|
const initializeForSessionResume = async ({
|
||||||
getExtensions,
|
getExtensions,
|
||||||
addExtension,
|
addExtension,
|
||||||
|
setIsExtensionsLoading,
|
||||||
provider,
|
provider,
|
||||||
model,
|
model,
|
||||||
}: Pick<InitializationDependencies, 'getExtensions' | 'addExtension' | 'provider' | 'model'>) => {
|
}: Pick<
|
||||||
|
InitializationDependencies,
|
||||||
|
'getExtensions' | 'addExtension' | 'setIsExtensionsLoading' | 'provider' | 'model'
|
||||||
|
>) => {
|
||||||
await initConfig();
|
await initConfig();
|
||||||
await readAllConfig({ throwOnError: true });
|
await readAllConfig({ throwOnError: true });
|
||||||
|
|
||||||
await initializeSystem(provider, model, {
|
await initializeSystem(provider, model, {
|
||||||
getExtensions,
|
getExtensions,
|
||||||
addExtension,
|
addExtension,
|
||||||
|
setIsExtensionsLoading,
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -132,11 +147,12 @@ const initializeForRecipe = async ({
|
|||||||
getExtensions,
|
getExtensions,
|
||||||
addExtension,
|
addExtension,
|
||||||
setPairChat,
|
setPairChat,
|
||||||
|
setIsExtensionsLoading,
|
||||||
provider,
|
provider,
|
||||||
model,
|
model,
|
||||||
}: Pick<
|
}: Pick<
|
||||||
InitializationDependencies,
|
InitializationDependencies,
|
||||||
'getExtensions' | 'addExtension' | 'setPairChat' | 'provider' | 'model'
|
'getExtensions' | 'addExtension' | 'setPairChat' | 'setIsExtensionsLoading' | 'provider' | 'model'
|
||||||
> & {
|
> & {
|
||||||
recipeConfig: Recipe;
|
recipeConfig: Recipe;
|
||||||
}) => {
|
}) => {
|
||||||
@@ -146,6 +162,7 @@ const initializeForRecipe = async ({
|
|||||||
await initializeSystem(provider, model, {
|
await initializeSystem(provider, model, {
|
||||||
getExtensions,
|
getExtensions,
|
||||||
addExtension,
|
addExtension,
|
||||||
|
setIsExtensionsLoading,
|
||||||
});
|
});
|
||||||
|
|
||||||
setPairChat((prevChat) => ({
|
setPairChat((prevChat) => ({
|
||||||
|
|||||||
@@ -115,6 +115,7 @@ export const initializeSystem = async (
|
|||||||
options?: {
|
options?: {
|
||||||
getExtensions?: (b: boolean) => Promise<FixedExtensionEntry[]>;
|
getExtensions?: (b: boolean) => Promise<FixedExtensionEntry[]>;
|
||||||
addExtension?: (name: string, config: ExtensionConfig, enabled: boolean) => Promise<void>;
|
addExtension?: (name: string, config: ExtensionConfig, enabled: boolean) => Promise<void>;
|
||||||
|
setIsExtensionsLoading?: (loading: boolean) => void;
|
||||||
}
|
}
|
||||||
) => {
|
) => {
|
||||||
try {
|
try {
|
||||||
@@ -182,6 +183,8 @@ export const initializeSystem = async (
|
|||||||
// Add enabled extensions to agent in parallel
|
// Add enabled extensions to agent in parallel
|
||||||
const enabledExtensions = refreshedExtensions.filter((ext) => ext.enabled);
|
const enabledExtensions = refreshedExtensions.filter((ext) => ext.enabled);
|
||||||
|
|
||||||
|
options?.setIsExtensionsLoading?.(true);
|
||||||
|
|
||||||
const extensionLoadingPromises = enabledExtensions.map(async (extensionEntry) => {
|
const extensionLoadingPromises = enabledExtensions.map(async (extensionEntry) => {
|
||||||
const extensionConfig = extractExtensionConfig(extensionEntry);
|
const extensionConfig = extractExtensionConfig(extensionEntry);
|
||||||
const extensionName = extensionConfig.name;
|
const extensionName = extensionConfig.name;
|
||||||
@@ -198,8 +201,10 @@ export const initializeSystem = async (
|
|||||||
});
|
});
|
||||||
|
|
||||||
await Promise.allSettled(extensionLoadingPromises);
|
await Promise.allSettled(extensionLoadingPromises);
|
||||||
|
options?.setIsExtensionsLoading?.(false);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Failed to initialize agent:', error);
|
console.error('Failed to initialize agent:', error);
|
||||||
|
options?.setIsExtensionsLoading?.(false);
|
||||||
throw error;
|
throw error;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user