Compare commits
2
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b5e2ef146c | ||
|
|
a2b9528e0b |
No files matched your search
@@ -3,6 +3,13 @@
|
||||
All notable changes to CodeCraft. Versions follow [Semantic Versioning](https://semver.org/);
|
||||
until 1.0, minor versions may contain breaking changes.
|
||||
|
||||
## [v202611-00040] – 2026-11-15
|
||||
|
||||
### Fixed
|
||||
|
||||
- **Images you upload reach Claude Code**: its chats read the history without the image bytes, so the
|
||||
files it was pointed to were empty. Images without data are no longer written as empty files.
|
||||
|
||||
## [v202611-00039] – 2026-11-15
|
||||
|
||||
### Changed
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
</p>
|
||||
|
||||
<p align="center">
|
||||
<img alt="Version v202611-00039" src="https://img.shields.io/badge/version-v202611--00039-d69e2e?style=flat-square">
|
||||
<img alt="Version v202611-00040" src="https://img.shields.io/badge/version-v202611--00040-d69e2e?style=flat-square">
|
||||
<img alt="License: MIT" src="https://img.shields.io/badge/license-MIT-689d6a?style=flat-square">
|
||||
<img alt="Rust backend" src="https://img.shields.io/badge/backend-Rust-b7410e?style=flat-square&logo=rust">
|
||||
<img alt="React PWA" src="https://img.shields.io/badge/frontend-React%20PWA-2d81ff?style=flat-square&logo=react">
|
||||
|
||||
@@ -361,7 +361,12 @@ fn save_images(cwd: &str, parts: &[Part]) -> Vec<String> {
|
||||
let mut out = Vec::new();
|
||||
for (i, p) in parts.iter().enumerate() {
|
||||
let Part::Image { image } = p else { continue };
|
||||
// An image without bytes (an unresolved reference) would become an empty file.
|
||||
let Ok(bytes) = base64::engine::general_purpose::STANDARD.decode(&image.data) else { continue };
|
||||
if bytes.is_empty() {
|
||||
tracing::warn!("claude code: image {i} of the message has no data – not saved");
|
||||
continue;
|
||||
}
|
||||
let ext = image.media_type.split('/').nth(1).unwrap_or("png").split('+').next().unwrap_or("png");
|
||||
let path = dir.join(format!("chat-{}-{i}.{ext}", now_ms()));
|
||||
if std::fs::create_dir_all(&dir).is_ok() {
|
||||
@@ -379,7 +384,8 @@ pub async fn run(app: Arc<App>, session_id: &str, cancel: CancellationToken) ->
|
||||
let session = app.session(session_id)?;
|
||||
let owner = session.owner_id.clone();
|
||||
let model_id = session.model.strip_prefix("claude-code/").unwrap_or("default").to_string();
|
||||
let history = crate::runner::active_history(app.store.messages(session_id)?);
|
||||
// With the bytes of the images filled in (they are stored as references).
|
||||
let history = crate::runner::active_history(app.store.messages_for_model(session_id)?);
|
||||
let Some(last_user) = history.iter().rposition(|m| m.role == Role::User && m.parts.iter().any(|p| matches!(p, Part::Text { .. } | Part::Image { .. }))) else {
|
||||
bail!("nothing to do: no user message");
|
||||
};
|
||||
@@ -956,6 +962,21 @@ pub async fn update() -> Result<String> {
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
#[test]
|
||||
fn uploaded_images_are_saved_with_their_bytes_only() {
|
||||
let dir = std::env::temp_dir().join(format!("cc-uploads-{}", std::process::id()));
|
||||
std::fs::create_dir_all(&dir).unwrap();
|
||||
let parts = vec![
|
||||
Part::Image { image: ImageData { media_type: "image/png".into(), data: "QUJD".into(), blob: None, size: None } },
|
||||
// A reference whose bytes were not filled in: must not become an empty file.
|
||||
Part::Image { image: ImageData { media_type: "image/png".into(), data: String::new(), blob: Some("x".into()), size: None } },
|
||||
];
|
||||
let saved = save_images(&dir.display().to_string(), &parts);
|
||||
assert_eq!(saved.len(), 1);
|
||||
assert_eq!(std::fs::read(&saved[0]).unwrap(), b"ABC");
|
||||
std::fs::remove_dir_all(&dir).unwrap();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn questions_roundtrip_with_the_cli_format() {
|
||||
let input = json!({"questions": [
|
||||
|
||||
@@ -3,6 +3,10 @@
|
||||
* under "unreleased"; scripts/release.sh renames the key to the release version.
|
||||
*/
|
||||
export const WHATS_NEW: Record<string, { en: string[]; de: string[] }> = {
|
||||
"202611-00040": {
|
||||
en: ["Images you upload are now visible to Claude Code (they arrived empty before)"],
|
||||
de: ["Hochgeladene Bilder sind für Claude Code jetzt sichtbar (sie kamen vorher leer an)"],
|
||||
},
|
||||
"202611-00039": {
|
||||
en: ["The chat colour no longer tints the chat background", "Claude Code can ask you questions again (question card in the chat)"],
|
||||
de: ["Die Chat-Farbe färbt den Hintergrund des Chats nicht mehr ein", "Claude Code kann dir wieder Fragen stellen (Fragenkarte im Chat)"],
|
||||
|
||||
Reference in new issue
Block a user