Add Web Push, guided start screen, SVG icons, chunked uploads, rename
- Web Push (VAPID + RFC 8291, pure Rust): permission/question/finished notifications while no app window is visible; settings with test button - Guided new-session flow: task, craft target (website/app/game/old software/fresh), clean room or deep, description, model, folder (new, existing or cloned git repository); originals upload to original/ - Craft phase bar (craft_phase tool) for study/specify/build/check/ready - Chunked uploads (8 MB) up to server.max_upload_mb (default 500 MB) - All UI glyphs and emojis replaced by themeable SVG icons - Rename dialog with manual name or model-generated suggestion Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
013695722a
commit
a0d0e707f2
48 files changed
+2724
-228
No files matched your search
@@ -55,6 +55,48 @@ impl Tool for TodoWrite {
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
pub const CRAFT_PHASES: &[&str] = &["study", "specify", "build", "check", "ready"];
|
||||
|
||||
/// Craft workflow: report the current phase (shown as a progress bar).
|
||||
pub struct CraftPhase;
|
||||
|
||||
#[async_trait]
|
||||
impl Tool for CraftPhase {
|
||||
fn name(&self) -> &str {
|
||||
"craft_phase"
|
||||
}
|
||||
fn description(&self) -> String {
|
||||
"Report the craft phase you are entering (study, specify, build, check, ready). The user sees it \
|
||||
as a progress bar. Call it at the start of every phase, also when you go back to an earlier one."
|
||||
.into()
|
||||
}
|
||||
fn schema(&self) -> Value {
|
||||
json!({"type": "object", "properties": {
|
||||
"phase": {"type": "string", "enum": CRAFT_PHASES},
|
||||
"note": {"type": "string", "description": "One short sentence: what happens in this phase"}
|
||||
}, "required": ["phase"]})
|
||||
}
|
||||
fn read_only(&self) -> bool {
|
||||
true
|
||||
}
|
||||
fn title(&self, input: &Value) -> String {
|
||||
format!("Phase: {}", input["phase"].as_str().unwrap_or("?"))
|
||||
}
|
||||
async fn run(&self, input: Value, ctx: &ToolCtx) -> Result<ToolOutput> {
|
||||
let phase = arg_str(&input, "phase")?;
|
||||
if !CRAFT_PHASES.contains(&phase) {
|
||||
bail!("unknown phase '{phase}' – use one of {}", CRAFT_PHASES.join(", "));
|
||||
}
|
||||
let root = ctx.app.root_session_id(&ctx.session_id);
|
||||
let mut s = ctx.app.session(&root)?;
|
||||
s.phase = Some(phase.to_string());
|
||||
ctx.app.save_session(s)?;
|
||||
Ok(ToolOutput::text(format!("Phase: {phase}")).with_meta(json!({"phase": phase, "note": input["note"]})))
|
||||
}
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
pub struct AskUser;
|
||||
|
||||
#[async_trait]
|
||||
|
||||
@@ -159,6 +159,7 @@ pub fn builtin_tools() -> Vec<Arc<dyn Tool>> {
|
||||
Arc::new(crate::shells::KillShell),
|
||||
Arc::new(web::WebFetch),
|
||||
Arc::new(web::WebSearch),
|
||||
Arc::new(agent::CraftPhase),
|
||||
Arc::new(crate::lsp::Diagnostics),
|
||||
Arc::new(agent::TodoWrite),
|
||||
Arc::new(agent::AskUser),
|
||||
|
||||
Reference in new issue
Block a user