app
Shotlog - Screenshot Log
Public Made by Adomby adom
See the shots your AI never showed you, and know it actually SAW them. adom-shotlog streams every screenshot the AI gathers into a live gallery (webview/pup/browser/phone), reports whether a human is really watching and on which surface, and ingests Adom Bridge child-window arrays via --meta.
← Commit history
Publish 0.18.1
8 files changed
+42−12
Cargo.lock+1−1@@ -10,7 +10,7 @@ checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa" [[package]] name = "adom-shotlog"-version = "0.18.0"+version = "0.18.1" dependencies = [ "axum", "base64",
Cargo.toml+1−1@@ -1,6 +1,6 @@ [package] name = "adom-shotlog"-version = "0.18.0"+version = "0.18.1" edition = "2021" description = "Screenshot log viewer and CLI for Adom" license = "MIT"
VERSION+1−1@@ -1 +1 @@-0.18.0+0.18.1
bin/adom-shotlog⋯ 1 unchanged line ⋯
package.json+1−1@@ -1,6 +1,6 @@ { "slug": "adom-shotlog",- "version": "0.18.0",+ "version": "0.18.1", "type": "app", "title": "Adom Shotlog", "description": "See the shots your AI never showed you, and know it actually SAW them. adom-shotlog streams every screenshot the AI gathers into a live gallery (webview/pup/browser/phone), reports whether a human is really watching and on which surface, and ingests Adom Desktop child-window arrays via --meta.",
page.json+1−1@@ -1,6 +1,6 @@ { "slug": "adom-shotlog",- "version": "0.18.0",+ "version": "0.18.1", "type": "app", "title": "Adom Shotlog", "description": "See the shots your AI never showed you, and know it actually SAW them. adom-shotlog streams every screenshot the AI gathers into a live gallery (webview/pup/browser/phone), reports whether a human is really watching and on which surface, and ingests Adom Desktop child-window arrays via --meta.",
src/main.rs+21−6@@ -189,6 +189,10 @@ enum Commands { /// comes from the broker's webview_width preference (20% unless changed). #[arg(long)] ratio: Option<f64>,+ /// Explicitly open the WEBVIEW canvas (same as --skinny). Without any+ /// canvas flag, `open` follows the human's default_canvas preference.+ #[arg(long)]+ webview: bool, /// Open in the FULL-BROWSER pup canvas instead: one shared pup window /// ('shotlog') with a tab per channel. Real zoom at near-full screen, /// and the broker flashes the window's taskbar orange on every update.@@ -411,24 +415,35 @@ async fn main() { run_inject(&channel, &desc, &source, port, &file, false, orig_w, orig_h, cap_meta, popups); } Commands::Open {- channel, name, icon, port, skinny, ratio, pup, swap,+ channel, name, icon, port, skinny, ratio, pup, swap, webview, } => { // NOTE: a CLI open does NOT record a canvas choice. Only the human's // explicit clicks in the viewer (canvas buttons) set the in-memory // note; everything else follows the global default. AI threads // opening channels must never masquerade as user preference.- if pup {+ let prefs = http_get(port, "/api/prefs").ok();+ let default_canvas = prefs.as_ref()+ .and_then(|v| v.get("default_canvas").and_then(|c| c.as_str()).map(String::from))+ .unwrap_or_else(|| "webview".into());+ // Canvas resolution: explicit flag wins; otherwise the HUMAN'S+ // default. A plain `open` must never bypass their setting.+ let use_pup = pup || (!skinny && !webview && default_canvas == "pup");+ let _ = http_post(port, "/api/log", &serde_json::json!({"line": format!(+ "CLI open '{}' canvas={} ({})", channel,+ if use_pup {"pup"} else {"webview"},+ if pup {"--pup"} else if skinny || webview {"explicit webview"} else {"followed default"})}));+ if use_pup { open::open_pup(&channel, port, swap); } else {- // Resolve the panel width: explicit --ratio wins, else the- // broker's webview_width pref, else 20%.+ // Webview is ALWAYS the managed slim panel at the preferred+ // width - an unmanaged add-tab once landed at 50% of the screen. let ratio = ratio.unwrap_or_else(|| {- http_get(port, "/api/prefs").ok()+ prefs.as_ref() .and_then(|v| v.get("webview_width").and_then(|w| w.as_u64())) .map(|w| (w as f64 / 100.0).clamp(0.10, 0.50)) .unwrap_or(0.2) });- open::open_webview(&channel, name.as_deref(), icon.as_deref(), port, skinny, ratio);+ open::open_webview(&channel, name.as_deref(), icon.as_deref(), port, true, ratio); if swap { if open::close_pup_tab(&channel) { ok(&format!("closed the pup tab for '{channel}' - webview is now this channel's canvas."));
src/server.rs+16−1@@ -82,6 +82,7 @@ pub fn create_router(state: Arc<AppState>) -> Router { .route("/api/canvas-pref", post(set_canvas_pref)) .route("/api/prefs", get(get_prefs)) .route("/api/prefs", post(set_prefs))+ .route("/api/log", post(post_log)) .route("/prompt", get(serve_prompt)) .route("/api/paste", post(post_paste)) .route("/api/open", post(open_in_vscode))@@ -255,6 +256,20 @@ struct CanvasSwitchRequest { to: String, } +#[derive(Deserialize)]+struct LogRequest {+ line: String,+}++/// Append a one-line event to the broker's audit trail (stdout). Used by the+/// CLI so "who opened what, how" is greppable in ONE place.+async fn post_log(Json(req): Json<LogRequest>) -> Json<serde_json::Value> {+ let mut line = req.line.replace(['\n', '\r'], " ");+ line.truncate(300);+ println!("{} {}", ts(), line);+ Json(serde_json::json!({"ok": true}))+}+ #[derive(Deserialize)] struct CanvasPrefRequest { channel: String,@@ -878,7 +893,7 @@ async fn post_shots( let mut hints: Vec<String> = Vec::new(); if entry.id == 1 && hint_gate(&format!("teach:new-channel:{}", req.channel), 1) { hints.push(format!(- "mini-skill [surfacing]: first shot in '{ch}'. The human watches via a slim right-side webview (`shotlog open -c {ch} --skinny`), a pup window, or their phone. I auto-open a 20% webview when nobody is watching, pull the channel's tab to the front with an orange alert on updates, and flash pup taskbars — never foreground anything yourself. Gate on visibility with `shotlog viewers -c {ch}` (exit 0=on-screen, 4=backgrounded, 3=nobody); see every channel with `shotlog channels`.",+ "mini-skill [surfacing]: first shot in '{ch}'. To open a viewer use PLAIN `shotlog open -c {ch}` - it follows the human's default canvas (webview or pup); only pass --skinny/--pup when the human explicitly asked for that canvas. I auto-open a 20% webview when nobody is watching, pull the channel's tab to the front with an orange alert on updates, and flash pup taskbars — never foreground anything yourself. Gate on visibility with `shotlog viewers -c {ch}` (exit 0=on-screen, 4=backgrounded, 3=nobody); see every channel with `shotlog channels`.", ch = req.channel)); } if source_str.contains("desktop_screenshot") && !had_meta && hint_gate(&format!("teach:meta:{}", req.channel), 2) {