Skip invalid app records when listing library apps
Build Claw Telegram / build (push) Successful in 5m53s
Build Claw Telegram / cleanup (push) Successful in 2s

This commit is contained in:
Wylabb
2026-04-05 23:04:54 +02:00
parent 2b86743d8d
commit 44f21595db
@@ -724,10 +724,17 @@ impl ArtifactLibraryStore {
let Some(app_id) = path.file_name().and_then(|value| value.to_str()) else {
continue;
};
if let Some(app) = self.get_app(app_id)? {
if app.manifest.visibility != AppVisibility::Archived {
match self.get_app(app_id) {
Ok(Some(app)) if app.manifest.visibility != AppVisibility::Archived => {
apps.push(app);
}
Ok(Some(_)) | Ok(None) => {}
Err(error) => {
eprintln!(
"artifact library: skipping unreadable app `{}` while listing apps: {}",
app_id, error
);
}
}
}
apps.sort_by(|left, right| {
@@ -2016,4 +2023,61 @@ mod tests {
std::env::remove_var("CLAW_WORKER_DEFAULT_CWD");
let _ = std::fs::remove_dir_all(&state_root);
}
#[test]
fn list_apps_skips_invalid_app_directories() {
let _lock = test_env_lock();
let state_root =
std::env::temp_dir().join(format!("artifact-lib-list-{}", super::now_secs()));
let workspace = state_root.join("workspace");
let _ = std::fs::remove_dir_all(&state_root);
std::fs::create_dir_all(&workspace).expect("workspace should exist");
std::env::set_var("CLAW_WORKER_STATE_ROOT", &state_root);
std::env::set_var("CLAW_WORKER_DEFAULT_CWD", &workspace);
let source = workspace.join("dashboard.html");
std::fs::write(&source, "<!doctype html><body>one</body>").expect("html source should write");
let store = ArtifactLibraryStore::new();
let feed = store
.record_turn(
"turn-3",
vec![FeedFileInput {
title: "dashboard.html".to_string(),
file_name: "dashboard.html".to_string(),
source_kind: FeedItemSourceKind::Generated,
source_turn_id: Some("turn-3".to_string()),
source_file_id: Some("generated-3".to_string()),
source_files: vec!["dashboard.html".to_string()],
change_kind: Some(FeedItemChangeKind::Created),
media_type: Some("text/html".to_string()),
source_path: Some(source),
preview_text: Some("Initial dashboard".to_string()),
deleted: false,
}],
)
.expect("turn should record");
let packaged = store
.package_feed_item(AppPackageRequest {
feed_item_id: feed[0].feed_item_id.clone(),
requested_app_id: Some("dash".to_string()),
title: Some("Dash".to_string()),
description: None,
})
.expect("packaging should succeed")
.expect("app should package");
let broken_dir = super::library_apps_dir()
.expect("library apps dir")
.join("broken-app");
std::fs::create_dir_all(&broken_dir).expect("create broken dir");
std::fs::write(broken_dir.join("manifest.json"), "{not-json").expect("write broken manifest");
let apps = store.list_apps().expect("listing should skip broken app");
assert_eq!(apps.len(), 1);
assert_eq!(apps[0].manifest.app_id, packaged.app.manifest.app_id);
std::env::remove_var("CLAW_WORKER_STATE_ROOT");
std::env::remove_var("CLAW_WORKER_DEFAULT_CWD");
let _ = std::fs::remove_dir_all(&state_root);
}
}