* fix(ai): infer MIME type from file extension for YAML and other code files
When uploading YAML files (and other code/text files) via Electron,
file.type is often empty, causing the system to default to
'application/octet-stream'. AI providers reject this media type
with 'functionality not supported'.
Fix by inferring the correct MIME type from the file extension
when file.type is empty. Includes mappings for YAML, JSON, TOML,
shell scripts, and 50+ common code/text file extensions.
Fixes#1287
* fix(ai): use text/plain for all code/text files to ensure provider compatibility
Change all non-standard MIME types (text/x-*, application/x-*) to
text/plain for maximum provider compatibility. Anthropic and other
providers reject non-standard MIME types like application/x-yaml
with 'UnsupportedFunctionalityError'.
Changes:
- All code files (js, ts, py, rb, rs, go, java, c, cpp, sh, etc.) → text/plain
- Web component/stylesheet files (vue, svelte, scss, sass, less) → text/plain
- yaml/yml → text/plain (was application/x-yaml)
- dockerfile → text/plain (was text/x-dockerfile)
- Standard types (html, css, json, xml, csv, md, txt, pdf) preserved
- persist drafts, panel views, and active sessions per terminal/workspace scope
- restore scoped AI session selection on reconnect and cold mount
- prefer unsent drafts over implicit history fallback
- avoid redundant active session map rewrites during scoped cleanup
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* feat: support multimodal attachments (images, PDFs, files) in AI chat
Previously uploaded images were displayed in the UI but never sent to
the AI model, and non-image files (PDF, text) were silently rejected.
- Rename useImageUpload → useFileUpload; accept image/*, PDF, and text/*
- Rename ChatMessageImage → ChatMessageAttachment with filePath support
- Build multimodal SDK messages (ImagePart/FilePart) for Catty Agent
- Fix ACP agent path: images inline, non-image files via local path hint
so ACP agents (Claude Code, etc.) read them with native file access
- Use Electron webUtils.getPathForFile() for reliable file path capture
- Compact user message bubble padding
Closes#294 (AI file upload issues)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: show real tool names in AI chat instead of ACP wrapper names
- Unwrap ACP dynamic tool calls in serializeStreamChunk to extract
real tool name, args, and toolCallId from chunk.input
- Simplify MCP tool name prefixes (mcp__server__tool → tool)
- Pass toolCallId from ACP tool-call events to match tool results
- Prevent onToolResult from overwriting correct names with wrapper name
- Build toolCallNames map in ChatMessageList for tool result display
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: backward-compatible fallback for legacy `images` field in chat messages
Persisted sessions may still have `images` instead of `attachments`.
Add `?? m.images` fallback in SDK message builder and renderer so
historical image attachments are not silently dropped after upgrade.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: broaden file type support and handle pasted files without path
- Accept all file types except video/audio (instead of allowlist)
so .json, .yaml, .sh, etc. are not silently rejected
- For ACP agents, save pasted/virtual files (no filePath) to temp
directory so the agent can still read them
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: use managed temp dir for pasted ACP attachments
Use tempDirBridge.getTempFilePath() instead of manual os.tmpdir() path
so pasted file attachments are tracked by the app's cleanup system.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>