Fix MCP tool calls, approval loop, shutdown, and improve web UI

- Fix MCP tool schema deserialization: rename input_schema to match
  protocol's camelCase inputSchema, so models receive actual parameter
  schemas instead of empty defaults
- Fix conversation history: add tool_calls field to ChatMessage and
  include assistant message with tool_calls before tool results, as
  required by OpenAI-compatible APIs
- Fix approval loop: pass resume_after_tool flag to run_agentic_loop
  so the "force tool use" heuristic doesn't re-trigger after approval
- Fix shutdown: add Submission::Quit, Ctrl+C signal handler, and
  graceful shutdown flow
- Fix MCP activate button: auto-attempt auth flow when activation
  fails due to missing authentication
- Add inline approval cards in chat via SSE ApprovalNeeded events
- Add markdown rendering in chat (marked.js) with proper streaming
- Add structured fields to log entries (key=value pairs from tracing)
- Collapse log entries to single line with click-to-expand

Co-Authored-By: Claude Opus 4.6 <[email protected]>
This commit is contained in:
Illia Polosukhin
2026-02-06 18:04:44 -08:00
co-authored by Claude Opus 4.6
parent 2cdd04a359
commit bf3b8b339f
19 changed files with 958 additions and 148 deletions
+3
View File
@@ -215,6 +215,7 @@ impl ExtensionManager {
name: server.name.clone(),
kind: ExtensionKind::McpServer,
description: server.description.clone(),
url: Some(server.url.clone()),
authenticated,
active,
tools,
@@ -240,6 +241,7 @@ impl ExtensionManager {
name: name.clone(),
kind: ExtensionKind::WasmTool,
description: None,
url: None,
authenticated: true, // WASM tools don't always need auth
active,
tools: if active { vec![name] } else { Vec::new() },
@@ -263,6 +265,7 @@ impl ExtensionManager {
name,
kind: ExtensionKind::WasmChannel,
description: None,
url: None,
authenticated: true,
active: true, // If loaded at startup, they're active
tools: Vec::new(),
+3
View File
@@ -176,6 +176,9 @@ pub struct InstalledExtension {
pub kind: ExtensionKind,
#[serde(skip_serializing_if = "Option::is_none")]
pub description: Option<String>,
/// Server or source URL (e.g. MCP server endpoint).
#[serde(skip_serializing_if = "Option::is_none")]
pub url: Option<String>,
pub authenticated: bool,
pub active: bool,
/// Tool names if active.