mirror of
https://github.com/aaif-goose/goose.git
synced 2026-07-03 14:10:03 +02:00
step
This commit is contained in:
@@ -13,6 +13,12 @@ use utoipa::ToSchema;
|
||||
use crate::conversation::tool_result_serde;
|
||||
use crate::utils::sanitize_unicode_tags;
|
||||
|
||||
#[derive(ToSchema)]
|
||||
pub enum ToolCallResult<T> {
|
||||
Success { value: T },
|
||||
Error { error: String },
|
||||
}
|
||||
|
||||
/// Custom deserializer for MessageContent that sanitizes Unicode Tags in text content
|
||||
fn deserialize_sanitized_content<'de, D>(deserializer: D) -> Result<Vec<MessageContent>, D::Error>
|
||||
where
|
||||
@@ -39,44 +45,28 @@ where
|
||||
Ok(content)
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, ToSchema)]
|
||||
#[serde(tag = "status", rename_all = "lowercase")]
|
||||
pub enum ToolCallResult<T> {
|
||||
Success { value: T },
|
||||
Error { error: String },
|
||||
}
|
||||
|
||||
impl<T> From<ToolResult<T>> for ToolCallResult<T> {
|
||||
fn from(result: ToolResult<T>) -> Self {
|
||||
match result {
|
||||
Ok(value) => ToolCallResult::Success { value },
|
||||
Err(error) => ToolCallResult::Error {
|
||||
error: error.to_string(),
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
#[derive(ToSchema)]
|
||||
pub struct ToolRequest {
|
||||
pub id: String,
|
||||
pub tool_call: ToolCallResult<CallToolRequestParam>,
|
||||
#[serde(with = "tool_result_serde")]
|
||||
#[schema(value_type = Object)]
|
||||
pub tool_call: ToolResult<CallToolRequestParam>,
|
||||
}
|
||||
|
||||
impl ToolRequest {
|
||||
pub fn to_readable_string(&self) -> String {
|
||||
match &self.tool_call {
|
||||
ToolCallResult::Success { value } => {
|
||||
Ok(tool_call) => {
|
||||
format!(
|
||||
"Tool: {}, Args: {}",
|
||||
value.name,
|
||||
serde_json::to_string_pretty(&value.arguments)
|
||||
tool_call.name,
|
||||
serde_json::to_string_pretty(&tool_call.arguments)
|
||||
.unwrap_or_else(|_| "<<invalid json>>".to_string())
|
||||
)
|
||||
}
|
||||
ToolCallResult::Error { error } => format!("Invalid tool call: {}", error),
|
||||
Err(e) => format!("Invalid tool call: {}", e),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -87,6 +77,7 @@ impl ToolRequest {
|
||||
pub struct ToolResponse {
|
||||
pub id: String,
|
||||
#[serde(with = "tool_result_serde")]
|
||||
#[schema(value_type = Object)]
|
||||
pub tool_result: ToolResult<Vec<Content>>,
|
||||
}
|
||||
|
||||
@@ -115,6 +106,8 @@ pub struct RedactedThinkingContent {
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct FrontendToolRequest {
|
||||
pub id: String,
|
||||
#[serde(with = "tool_result_serde")]
|
||||
#[schema(value_type = Object)]
|
||||
pub tool_call: ToolResult<CallToolRequestParam>,
|
||||
}
|
||||
|
||||
|
||||
@@ -2843,7 +2843,7 @@
|
||||
"type": "string"
|
||||
},
|
||||
"toolCall": {
|
||||
"$ref": "#/components/schemas/ToolResult"
|
||||
"type": "object"
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -4439,7 +4439,7 @@
|
||||
"type": "string"
|
||||
},
|
||||
"toolCall": {
|
||||
"$ref": "#/components/schemas/ToolResult"
|
||||
"type": "object"
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -4454,7 +4454,7 @@
|
||||
"type": "string"
|
||||
},
|
||||
"toolResult": {
|
||||
"$ref": "#/components/schemas/ToolResult"
|
||||
"type": "object"
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
@@ -12,7 +12,7 @@ import { ChevronRight, FlaskConical } from 'lucide-react';
|
||||
import { TooltipWrapper } from './settings/providers/subcomponents/buttons/TooltipWrapper';
|
||||
import MCPUIResourceRenderer from './MCPUIResourceRenderer';
|
||||
import { isUIResource } from '@mcp-ui/client';
|
||||
import { Content } from '../api';
|
||||
import { Content, RawResource } from '../api';
|
||||
|
||||
interface ToolCallWithResponseProps {
|
||||
isCancelledMessage: boolean;
|
||||
@@ -23,6 +23,17 @@ interface ToolCallWithResponseProps {
|
||||
append?: (value: string) => void; // Function to append messages to the chat
|
||||
}
|
||||
|
||||
function getToolResultValue(toolResult: Record<string, unknown>): Content[] | null {
|
||||
if ('value' in toolResult && Array.isArray(toolResult.value)) {
|
||||
return toolResult.value as Content[];
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
function isRawResource(content: Content): content is RawResource {
|
||||
return 'uri' in content && 'name' in content;
|
||||
}
|
||||
|
||||
export default function ToolCallWithResponse({
|
||||
isCancelledMessage,
|
||||
toolRequest,
|
||||
@@ -55,11 +66,10 @@ export default function ToolCallWithResponse({
|
||||
</div>
|
||||
{/* MCP UI — Inline */}
|
||||
{toolResponse?.toolResult &&
|
||||
Array.isArray((toolResponse.toolResult as any).value) &&
|
||||
(toolResponse.toolResult as any).value.map((content: Content, index: number) => {
|
||||
if (isUIResource(content)) {
|
||||
getToolResultValue(toolResponse.toolResult)?.map((content: Content, index: number) => {
|
||||
if (isRawResource(content) && isUIResource(content)) {
|
||||
return (
|
||||
<div key={`${index}`} className="mt-3">
|
||||
<div key={index} className="mt-3">
|
||||
<MCPUIResourceRenderer content={content} appendPromptToChat={append} />
|
||||
<div className="mt-3 p-4 py-3 border border-borderSubtle rounded-lg bg-background-muted flex items-center">
|
||||
<FlaskConical className="mr-2" size={20} />
|
||||
@@ -72,7 +82,7 @@ export default function ToolCallWithResponse({
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
})}
|
||||
})}{' '}
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user