Skip to content

Commit 074696c

Browse files
mios-devclaude
andcommitted
mios-show-image: one canonical call for "show me a picture of X"
Operator chat 2026-05-17 paste -- "Bring up a picture of cute dog on the left of my screen" -- ran 13 tool calls (skill_view + skill_manage + web_extract loops + terminal pipelines), tried to download/save the image, hit WSL filesystem read-only errors, then declared defeat with "I'm sorry, but I couldn't capture a screenshot due to technical issues with the Windows filesystem". The operator's correction: "Should just open the image directly in a browser window then!! (localhost browser on windows or Local MiOS linux browser(s)(if multiple present))". mios-show-image collapses the whole flow to one tool call: 1. SearXNG image search via probe-list (local containers + DNS aliases) 2. Pick first usable img_src / thumbnail_src / url 3. mios-open-url <img> -- uses the operator's MiOS-defined default browser (mios.toml [[desktop.apps]] role=browser default=true) 4. Optional --position left|right|center|top|bottom|maximize: waits 1.2s for the window to surface, then mios-window <pos> "<host-pattern>" against the URL's hostname. Probe list defaults to all common searxng endpoints (loopback + container DNS); MIOS_SEARXNG_URL overrides. Exit codes: 0 = opened (+ optional position applied) 1 = no results 2 = searxng unreachable / non-JSON 3 = mios-open-url failed -- so the agent can distinguish "nothing matched" from "infrastructure down" without parsing prose. SOUL.md additions: * New section "Show me an image / picture of X" -- one-call rule with the Crew Motorfest-style "Don't" list (no curl -O, no browser_navigate, no mios-screenshot, no /mnt/c writes). Falls back to web_search categories=images manually if mios-show-image exits 2. * Helpers table picks up the four new shims it didn't have yet: mios-show-image, mios-discord-status, mios-hermes-browser ensure, mios-cache-clear. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent 441fd1a commit 074696c

2 files changed

Lines changed: 192 additions & 0 deletions

File tree

usr/libexec/mios/mios-show-image

Lines changed: 164 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,164 @@
1+
#!/bin/bash
2+
# /usr/libexec/mios/mios-show-image <query> [--position left|right|center|top|bottom] [--engine images|videos]
3+
#
4+
# Operator directive 2026-05-17: "should just open the image directly
5+
# in a browser window then!! (localhost browser on windows or Local
6+
# MiOS linux browser(s)(if multiple present))". The agent was running
7+
# 13 tool calls trying to download + save + screenshot images, hitting
8+
# WSL filesystem read-only errors, when the operator's actual ask was:
9+
# search -> open URL in browser. Done.
10+
#
11+
# Flow:
12+
# 1. SearXNG image search via the local mios-searxng service
13+
# (NO cloud APIs, NO file downloads, NO image saves)
14+
# 2. Pick the top result's img_src
15+
# 3. Open that URL via mios-open-url (resolves the MiOS-defined
16+
# default browser per mios.toml -- could be Windows-side Chrome
17+
# or a Linux flatpak; operator's choice)
18+
# 4. (optional) After 1.2s, mios-window move "<title-pattern>" to
19+
# the requested screen-half via mios-window
20+
#
21+
# Exit codes:
22+
# 0 = found + opened (+ optional position applied)
23+
# 1 = searxng returned no images
24+
# 2 = searxng unreachable / parse failure
25+
# 3 = mios-open-url failed
26+
#
27+
# Env-overridable:
28+
# MIOS_SEARXNG_URL probe-list, comma-separated. Defaults:
29+
# "http://127.0.0.1:8888,http://mios-searxng:8888,
30+
# http://mios-searxng:8080,http://localhost:8888"
31+
# MIOS_IMAGE_TIMEOUT seconds per searxng call (default 8)
32+
33+
set -uo pipefail
34+
35+
usage() {
36+
cat <<'USAGE'
37+
usage: mios-show-image <query> [options]
38+
39+
<query> Image search query (quote multi-word).
40+
41+
Options:
42+
--position <pos> Move the browser window after open. One of:
43+
left | right | center | top | bottom | maximize.
44+
Default: no positioning.
45+
--engine <engine> SearXNG category. Default: images.
46+
Also: videos (some engines support).
47+
--browser <name> Override the default browser (passed to
48+
mios-open-url). Useful when multiple browsers
49+
exist (e.g. windows-chrome vs chromedev).
50+
-h, --help Show this help.
51+
52+
Examples:
53+
mios-show-image "cute dog"
54+
mios-show-image "cute dog" --position left
55+
mios-show-image "neon city" --position right --browser chromedev
56+
USAGE
57+
}
58+
59+
if [ "$#" -lt 1 ] || [ "$1" = "-h" ] || [ "$1" = "--help" ]; then
60+
usage
61+
[ "$#" -lt 1 ] && exit 64 || exit 0
62+
fi
63+
64+
QUERY="$1"
65+
shift
66+
POSITION=""
67+
ENGINE="images"
68+
BROWSER=""
69+
70+
while [ "$#" -gt 0 ]; do
71+
case "$1" in
72+
--position) POSITION="${2:-}"; shift 2 ;;
73+
--engine) ENGINE="${2:-images}"; shift 2 ;;
74+
--browser) BROWSER="${2:-}"; shift 2 ;;
75+
*) echo "mios-show-image: unknown arg: $1" >&2; exit 64 ;;
76+
esac
77+
done
78+
79+
TIMEOUT="${MIOS_IMAGE_TIMEOUT:-8}"
80+
PROBE_LIST="${MIOS_SEARXNG_URL:-http://127.0.0.1:8888,http://mios-searxng:8888,http://mios-searxng:8080,http://localhost:8888}"
81+
82+
# --- 1. SearXNG image search -------------------------------------
83+
84+
pick_img_src() {
85+
# Parse JSON, surface the first usable image URL. Prefers
86+
# img_src (full-res) over thumbnail_src; falls back to url.
87+
python3 - <<'PY'
88+
import json, sys
89+
try:
90+
d = json.load(sys.stdin)
91+
except Exception as e:
92+
print("", file=sys.stderr); sys.exit(2)
93+
for r in (d.get("results") or []):
94+
for k in ("img_src", "thumbnail_src", "url"):
95+
v = (r.get(k) or "").strip()
96+
if v.startswith(("http://", "https://")):
97+
print(v); sys.exit(0)
98+
sys.exit(1)
99+
PY
100+
}
101+
102+
IMG_URL=""
103+
for url in ${PROBE_LIST//,/ }; do
104+
body=$(curl -sS --max-time "$TIMEOUT" -G "$url/search" \
105+
--data-urlencode "q=$QUERY" \
106+
--data-urlencode "format=json" \
107+
--data-urlencode "categories=$ENGINE" \
108+
--data-urlencode "safesearch=1" 2>/dev/null) || continue
109+
[ -z "$body" ] && continue
110+
candidate=$(printf '%s' "$body" | pick_img_src 2>/dev/null) || continue
111+
if [ -n "$candidate" ]; then
112+
IMG_URL="$candidate"
113+
echo "[mios-show-image] using searxng=$url"
114+
break
115+
fi
116+
done
117+
118+
if [ -z "$IMG_URL" ]; then
119+
echo "mios-show-image: no image results from any SearXNG endpoint" >&2
120+
echo " probed: $PROBE_LIST" >&2
121+
echo " hint: curl '$PROBE_LIST/search?q=test&format=json&categories=images' to debug" >&2
122+
exit 2
123+
fi
124+
125+
echo "[mios-show-image] query=$QUERY -> $IMG_URL"
126+
127+
# --- 2. Open in default browser ----------------------------------
128+
129+
OPEN_ARGS=("$IMG_URL")
130+
[ -n "$BROWSER" ] && OPEN_ARGS+=("$BROWSER")
131+
if ! mios-open-url "${OPEN_ARGS[@]}"; then
132+
echo "mios-show-image: mios-open-url failed for $IMG_URL" >&2
133+
exit 3
134+
fi
135+
echo "[mios-show-image] opened in default browser"
136+
137+
# --- 3. Optional positioning -------------------------------------
138+
139+
if [ -n "$POSITION" ]; then
140+
# Browser takes a moment to render the window. mios-window-active
141+
# --present waits for the window to actually surface before
142+
# mios-window can target it.
143+
sleep 1.2
144+
# Pull the browser window by host title (image hostname or "image")
145+
HOST=$(printf '%s' "$IMG_URL" | sed -nE 's|^https?://([^/]+).*|\1|p')
146+
TITLE_PAT="${HOST:-image}"
147+
case "$POSITION" in
148+
left|right|top|bottom|center|maximize)
149+
if mios-window "$POSITION" "$TITLE_PAT" 2>/dev/null; then
150+
echo "[mios-show-image] positioned: $POSITION"
151+
else
152+
# Fallback: try by short title fragments most browsers use
153+
for pat in "$QUERY" "image" "search"; do
154+
mios-window "$POSITION" "$pat" 2>/dev/null && break
155+
done
156+
fi
157+
;;
158+
*)
159+
echo "mios-show-image: unknown --position '$POSITION' (left|right|top|bottom|center|maximize)" >&2
160+
;;
161+
esac
162+
fi
163+
164+
exit 0

usr/share/mios/ai/hermes-soul.md

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,10 @@ fields. If you don't have the number from a tool's stdout, say
154154
| `mios-env-probe` | Runtime snapshot. |
155155
| `mios-skill-clone <name> [--as <new>]` | Fork a vendor skill into `$HERMES_HOME/skills/` so you can edit it. Same-name fork overrides on next load. |
156156
| `mios-tool-clone <name> [--as <new>]` | Fork a vendor shim into `/usr/local/bin/` (precedes `/usr/libexec/mios` on PATH). |
157+
| `mios-show-image "<q>" [--position left\|right\|center]` | Image search + open in operator's default browser. Single canonical call for "show me a picture of X". |
158+
| `mios-discord-status` | Self-check the Discord integration (token, guilds, default channel, directory mtime). |
159+
| `mios-hermes-browser ensure` | Idempotent: bring CDP up on :9222 if not responding. Required before any `browser_*` tool call. |
160+
| `mios-cache-clear [--dry-run] [--all]` | Wipe regenerable state (chats/sessions/caches); preserves users, models, tools, ollama, skills, configs. |
157161

158162
State paths (read freely):
159163
- `/var/lib/mios/scratch/` — inter-agent shared scratch (mode 1777)
@@ -228,6 +232,30 @@ in the user's tone (1-2 sentences). DO NOT:
228232
"what GPU do I have", "list ollama models", "what services are
229233
running", "how much disk left", "system status".
230234

235+
## Show me an image / picture of X
236+
237+
ONE call: `terminal: mios-show-image "<query>" [--position left|right|center]`.
238+
239+
That helper does: SearXNG image search → first result's `img_src`
240+
opens via `mios-open-url` (uses the operator's MiOS-defined default
241+
browser). No file download, no screenshot, no save-to-disk path.
242+
243+
Operator-flagged 2026-05-17: agent ran 13 tool calls trying to
244+
download + save + screenshot a "cute dog" image, hit "WSL filesystem
245+
read-only" errors, and declared defeat. The operator's actual ask
246+
was "open in browser" -- exactly one tool call's worth of work.
247+
248+
Don't:
249+
* `web_search` then try to fetch the URL with `terminal: curl -O`
250+
* `browser_navigate` (CDP headless -- operator can't see it)
251+
* `mios-screenshot` (that's for capturing the operator's screen,
252+
not for fetching a remote image)
253+
* Anything writing to `/mnt/c/Users/...` -- you don't need a file
254+
255+
If `mios-show-image` returns exit 2 ("no image results"), THEN
256+
fall back to `web_search categories=images` and pass any returned
257+
URL through `mios-open-url` manually.
258+
231259
## Native tools vs `terminal` — don't confuse the surfaces
232260

233261
Native tools (`memory_save`, `kanban_create`, `web_search`,

0 commit comments

Comments
 (0)