diff --git a/web/backend/api/tools.go b/web/backend/api/tools.go
index 289ea5035..629d5f43d 100644
--- a/web/backend/api/tools.go
+++ b/web/backend/api/tools.go
@@ -193,6 +193,12 @@ var toolCatalog = []toolCatalogEntry{
Category: "discovery",
ConfigKey: "mcp.discovery.use_bm25",
},
+ {
+ Name: "request_permission",
+ Description: "Request user permission for accessing paths outside workspace.",
+ Category: "system",
+ ConfigKey: "request_permission",
+ },
}
func (h *Handler) registerToolRoutes(mux *http.ServeMux) {
diff --git a/web/frontend/src/components/chat/assistant-message.tsx b/web/frontend/src/components/chat/assistant-message.tsx
index 07a3c0abc..4ca1167c7 100644
--- a/web/frontend/src/components/chat/assistant-message.tsx
+++ b/web/frontend/src/components/chat/assistant-message.tsx
@@ -23,6 +23,7 @@ import {
type ChatAttachment,
type ChatToolCall,
} from "@/store/chat"
+import { CompactToolCall } from "@/components/chat/compact-tool-call"
interface AssistantMessageProps {
content: string
@@ -114,71 +115,17 @@ export function AssistantMessage({
)}
{(!isCollapsedBlock || isExpanded) && isToolCalls && hasToolCalls && (
-
+
{toolCalls.map((toolCall, index) => {
- const explanation =
- toolCall.extraContent?.toolFeedbackExplanation?.trim() ?? ""
const toolName = toolCall.function?.name?.trim() ?? ""
- const toolArguments = toolCall.function?.arguments?.trim() ?? ""
- const hasFunctionSummary = toolName || toolArguments
-
- if (!explanation && !hasFunctionSummary) {
- return null
- }
-
+ const isRequestPermission = toolName === "request_permission"
+
return (
-
0 && "border-border/20 border-t pt-3",
- )}
- >
- {explanation && (
-
-
- {t("chat.toolCallExplanationLabel")}
-
-
-
- {explanation}
-
-
-
- )}
-
- {hasFunctionSummary && (
-
-
- {t("chat.toolCallFunctionLabel")}
-
-
- {toolName && (
-
- {toolName}
-
- )}
- {toolArguments && (
-
- {toolArguments}
-
- )}
-
-
- )}
-
+ toolCall={toolCall}
+ isRequestPermission={isRequestPermission}
+ />
)
})}
diff --git a/web/frontend/src/components/chat/chat-page.tsx b/web/frontend/src/components/chat/chat-page.tsx
index aa479d776..3031e9c9e 100644
--- a/web/frontend/src/components/chat/chat-page.tsx
+++ b/web/frontend/src/components/chat/chat-page.tsx
@@ -369,18 +369,6 @@ export function ChatPage() {
/>
)}
- {permissionRequest && (
-
- )}
-
{messages.map((msg) => {
if (
!showAssistantDetails &&
@@ -421,6 +409,18 @@ export function ChatPage() {
onChange={handleImageSelection}
/>
+ {permissionRequest && (
+
+ )}
+
| null = null
+ if (toolArguments) {
+ try {
+ parsedArgs = JSON.parse(toolArguments)
+ } catch {
+ // ignore
+ }
+ }
+
+ // Status icon
+ const isError = explanation.toLowerCase().includes("error") || explanation.toLowerCase().includes("denied")
+
+ return (
+
+
+
+ {isExpanded && (explanation || toolArguments) && (
+
+ {explanation && (
+
+ {explanation}
+
+ )}
+ {toolArguments && (
+
+ )}
+
+ )}
+
+ )
+}