fix tool confirmations not showing up mid chat (#6935)
This commit is contained in:
@@ -38,7 +38,9 @@ const isUserMessage = (message: Message): boolean => {
|
|||||||
if (message.role === 'assistant') {
|
if (message.role === 'assistant') {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return !message.content.every((c) => c.type === 'toolConfirmationRequest');
|
return !message.content.every(
|
||||||
|
(c) => c.type === 'actionRequired' && c.data.actionType === 'toolConfirmation'
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const filterMessagesForDisplay = (messages: Message[]): Message[] => {
|
const filterMessagesForDisplay = (messages: Message[]): Message[] => {
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { useEffect, useMemo, useState } from 'react';
|
import { useEffect, useMemo, useState } from 'react';
|
||||||
import { Button } from '../../ui/button';
|
import { Button } from '../../ui/button';
|
||||||
import { ChevronDownIcon, SlidersHorizontal } from 'lucide-react';
|
import { ChevronDownIcon, SlidersHorizontal, AlertCircle } from 'lucide-react';
|
||||||
import { getTools, PermissionLevel, ToolInfo, upsertPermissions } from '../../../api';
|
import { getTools, PermissionLevel, ToolInfo, upsertPermissions } from '../../../api';
|
||||||
import { Dialog, DialogContent, DialogFooter, DialogHeader, DialogTitle } from '../../ui/dialog';
|
import { Dialog, DialogContent, DialogFooter, DialogHeader, DialogTitle } from '../../ui/dialog';
|
||||||
import {
|
import {
|
||||||
@@ -33,6 +33,8 @@ export default function PermissionModal({ extensionName, onClose }: PermissionMo
|
|||||||
|
|
||||||
const [tools, setTools] = useState<ToolInfo[]>([]);
|
const [tools, setTools] = useState<ToolInfo[]>([]);
|
||||||
const [updatedPermissions, setUpdatedPermissions] = useState<Record<string, string>>({});
|
const [updatedPermissions, setUpdatedPermissions] = useState<Record<string, string>>({});
|
||||||
|
const [isLoading, setIsLoading] = useState(true);
|
||||||
|
const [loadError, setLoadError] = useState<string | null>(null);
|
||||||
|
|
||||||
const hasChanges = useMemo(() => {
|
const hasChanges = useMemo(() => {
|
||||||
return Object.keys(updatedPermissions).some(
|
return Object.keys(updatedPermissions).some(
|
||||||
@@ -43,12 +45,22 @@ export default function PermissionModal({ extensionName, onClose }: PermissionMo
|
|||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const fetchTools = async () => {
|
const fetchTools = async () => {
|
||||||
|
if (!sessionId) {
|
||||||
|
setIsLoading(false);
|
||||||
|
setLoadError('no_session');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
setIsLoading(true);
|
||||||
|
setLoadError(null);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const response = await getTools({
|
const response = await getTools({
|
||||||
query: { extension_name: extensionName, session_id: sessionId },
|
query: { extension_name: extensionName, session_id: sessionId },
|
||||||
});
|
});
|
||||||
if (response.error) {
|
if (response.error) {
|
||||||
console.error('Failed to get tools');
|
console.error('Failed to get tools:', response.error);
|
||||||
|
setLoadError('fetch_failed');
|
||||||
} else {
|
} else {
|
||||||
const filteredTools = (response.data || []).filter(
|
const filteredTools = (response.data || []).filter(
|
||||||
(tool: ToolInfo) =>
|
(tool: ToolInfo) =>
|
||||||
@@ -58,6 +70,9 @@ export default function PermissionModal({ extensionName, onClose }: PermissionMo
|
|||||||
}
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error('Error fetching tools:', err);
|
console.error('Error fetching tools:', err);
|
||||||
|
setLoadError('fetch_failed');
|
||||||
|
} finally {
|
||||||
|
setIsLoading(false);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -121,9 +136,8 @@ export default function PermissionModal({ extensionName, onClose }: PermissionMo
|
|||||||
</DialogHeader>
|
</DialogHeader>
|
||||||
|
|
||||||
<div className="py-4">
|
<div className="py-4">
|
||||||
{tools.length === 0 ? (
|
{isLoading ? (
|
||||||
<div className="flex items-center justify-center">
|
<div className="flex items-center justify-center py-8">
|
||||||
{/* Loading spinner */}
|
|
||||||
<svg
|
<svg
|
||||||
className="animate-spin h-8 w-8 text-grey-50 dark:text-white"
|
className="animate-spin h-8 w-8 text-grey-50 dark:text-white"
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
@@ -141,6 +155,28 @@ export default function PermissionModal({ extensionName, onClose }: PermissionMo
|
|||||||
<path className="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8v8H4z"></path>
|
<path className="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8v8H4z"></path>
|
||||||
</svg>
|
</svg>
|
||||||
</div>
|
</div>
|
||||||
|
) : loadError === 'no_session' ? (
|
||||||
|
<div className="flex flex-col items-center justify-center py-8 text-center">
|
||||||
|
<AlertCircle className="h-12 w-12 text-textSubtle mb-4" />
|
||||||
|
<p className="text-textStandard font-medium mb-2">No active session</p>
|
||||||
|
<p className="text-sm text-textSubtle max-w-sm">
|
||||||
|
Start a chat session first to configure tool permissions for this extension. Tool
|
||||||
|
permissions are loaded from the active session's extensions.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
) : loadError === 'fetch_failed' ? (
|
||||||
|
<div className="flex flex-col items-center justify-center py-8 text-center">
|
||||||
|
<AlertCircle className="h-12 w-12 text-textSubtle mb-4" />
|
||||||
|
<p className="text-textStandard font-medium mb-2">Failed to load tools</p>
|
||||||
|
<p className="text-sm text-textSubtle max-w-sm">
|
||||||
|
Could not load tools for this extension. The extension may not be loaded in the
|
||||||
|
current session.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
) : tools.length === 0 ? (
|
||||||
|
<div className="flex flex-col items-center justify-center py-8 text-center">
|
||||||
|
<p className="text-textSubtle">No tools available for this extension.</p>
|
||||||
|
</div>
|
||||||
) : (
|
) : (
|
||||||
<div className="space-y-4">
|
<div className="space-y-4">
|
||||||
{tools.map((tool) => (
|
{tools.map((tool) => (
|
||||||
@@ -187,11 +223,13 @@ export default function PermissionModal({ extensionName, onClose }: PermissionMo
|
|||||||
|
|
||||||
<DialogFooter>
|
<DialogFooter>
|
||||||
<Button variant="outline" onClick={handleClose}>
|
<Button variant="outline" onClick={handleClose}>
|
||||||
Cancel
|
{loadError ? 'Close' : 'Cancel'}
|
||||||
</Button>
|
|
||||||
<Button disabled={!hasChanges} onClick={handleSave}>
|
|
||||||
Save Changes
|
|
||||||
</Button>
|
</Button>
|
||||||
|
{!loadError && (
|
||||||
|
<Button disabled={!hasChanges} onClick={handleSave}>
|
||||||
|
Save Changes
|
||||||
|
</Button>
|
||||||
|
)}
|
||||||
</DialogFooter>
|
</DialogFooter>
|
||||||
</DialogContent>
|
</DialogContent>
|
||||||
</Dialog>
|
</Dialog>
|
||||||
|
|||||||
@@ -257,7 +257,8 @@ async function streamFromResponse(
|
|||||||
currentMessages = pushMessage(currentMessages, msg);
|
currentMessages = pushMessage(currentMessages, msg);
|
||||||
|
|
||||||
const hasToolConfirmation = msg.content.some(
|
const hasToolConfirmation = msg.content.some(
|
||||||
(content) => content.type === 'toolConfirmationRequest'
|
(content) =>
|
||||||
|
content.type === 'actionRequired' && content.data.actionType === 'toolConfirmation'
|
||||||
);
|
);
|
||||||
|
|
||||||
const hasElicitation = msg.content.some(
|
const hasElicitation = msg.content.some(
|
||||||
|
|||||||
Reference in New Issue
Block a user