miloco v2026.8.6
Since v2026.7.17: 175 commits, 29 PRs, 250 files changed (+27,347 / −2,886).
Hotfix for v2026.8.5. On v2026.8.5 the camera process could die with SIGSEGV on some older camera models, taking perception down with it; newer models were unaffected. The cause was traced to the updated
missnative library that shipped alongside camera IP direct-connect, so that feature is reverted in full (@Zirconi) and will come back once the library is fixed. If your cameras are already stable on v2026.8.5, the only other change here is the Smart Crop scaling rework listed under Perception Stability. Everything else from v2026.8.5 is intact and listed below.If the crash took your backend down with it, the dashboard's upgrade banner won't reach you — upgrade from the command line instead:
curl -LsSf https://github.com/XiaoMi/xiaomi-miloco/releases/latest/download/install.sh | bashOn a healthy v2026.8.5 the banner appears on its own, but the release check is cached for 6 hours — click "check for updates" in the sidebar to see it immediately.
🎯 New Features
- Pet recognition (experimental, off by default) (@ExWang): the largest change in this release. Pets become first-class family members — a pet roster with structured identities, multi-image registration with reference crops persisted and injected into the fused perception prompt, appearance-text matching with an explicit abstain discipline, and body grounding for non-cat/dog species. Ships with a full Web management UI (registration flow, auto-generated appearance, editable profiles, reference-image counts), a CLI command group, and a
miloco-miot-pet-registeragent skill. Gated behindfeatures.*flags, get/set-able from the CLI. - Smart Crop — adaptive resolution before OMNI inference (@Molly-3000): crops the active region out of each perception window before inference, so the model sees the subject at usable resolution instead of a full frame downscaled. Two independent config switches, the crop scaled proportionally until it just fits the panorama frame of the same
video_short_edgetier, crop video + full-frame reference persisted side by side, and crop coordinates recorded into the trace. Frame selection uses per-frame human/cat/dog detection boxes inside the window and excludesno_personfalse detections. Enabled by default. - Upgrade notice and one-click self-upgrade in Web (@hlccd): opening the dashboard checks GitHub
releases/latestonce (server-side cached, with aforcere-check) and shows a dot next to the sidebar version plus a dismissible top banner; confirming runs the officialinstall.shin non-interactive agent mode, detached so it survives the backend restarting itself, and the front end polls/upgrade/statusthrough download → install → restart. Release deployments only — dev (git) deployments are pointed atgit pull. If GitHub is unreachable it degrades silently rather than erroring. - Process CPU and thread-count charts on the Perf page (@Zirconi): per-process CPU and thread count tracked as a time series with dual axes, CPU normalized to 0–100%, and in-bucket peaks surfaced so a one-minute full-core spike isn't averaged away in the 24h / 3d views.
- Agent action ledger (@LeonJoeeee): persistent audit of every agent-initiated device control, TTS, and scene trigger, merged into the event page timeline.
- On-demand perception log (@Molly-3000): actively querying the log now persists its result with artifact storage, front-end display, clip playback, and feedback.
- Per-camera perception prompt (@HCl8): each camera can carry its own perception-guidance prompt, injected at the tail of the system prompt for both video and audio paths.
- Urgency filter for suggestion → agent dispatch (@Molly-3000):
perception.min_suggestion_urgencyfilters which suggestions reach the agent, exposed through the admin API and CLI, and surfaced in Web as a 3-stop slider plus an "agent interruption threshold" three-way selector in the settings drawer. - Task name and trigger status in rule-reminder logs (@Molly-3000): logs now show which task and which rule fired, with a collapsed-state badge for the backend's trigger verdict.
- Editable task trigger conditions in Web (@idootop): task detail consolidated into a single edit entry point.
- Manual avatar replacement for family members (@ExWang): explicit avatars are stored separately under
avatars/, with in-browser cropping.
🧠 Perception Stability
- Latent memory leaks hardened, and the stale match / centroid cache on cluster-centroid change fixed (@idootop):
_match_cacheinvalidation widened from member-set to centroid change and extended to fetch-side embedding backfill and partial cluster-member eviction; dead clusters evicted from_centroid_cache;_drainedtrimmed regardless offull_action. - Decoder worker leak on reconnect fixed (@Zirconi):
stop()now joins before clearing the reference, returnsFalseon timeout so the camera can consume it concurrently, and a failure mid-stop no longer aborts the rest of the cleanup. - KleidiAI disabled on the silero VAD CPU-EP session and the EventEmbedder session, via a shared
apply_kleidiai_opt_outhelper with CI-enforced spy tests (@idootop). - Smart Crop robustness: bad config now fails closed, crop rejection reasons are observable, degenerate/out-of-bounds coordinates fold into a single 410, and a corrupt trace no longer swallows the entire reference-frame card (@Molly-3000).
- Smart Crop scaling rewritten around one geometric rule (@Molly-3000): the short-edge budget is gone — a crop is now scaled proportionally until it just fits the panorama frame the same native frame would produce at the same
video_short_edgetier. Verified by exhaustive check over 4 source resolutions × 4 tiers × ~890k region sizes: encoded pixels never exceed the same-tier panorama, and subject pixel density is never lower than it. Behavior change: the ceiling is now the same-tier panorama frame rather than the native frame, so a crop can exceed native pixel count whenvideo_short_edgeis set above the source's short edge — same as panorama encoding already did. Thecrop_enhance.crop_short_edgeconfig key is removed; a leftover key inconfig.jsonis silently dropped by the existing unknown-key filter and does not block startup. - Pet-recognition correctness: the registration size gate switched to absolute size + linear area ratio (large sharp pets no longer rejected),
multiple_petsnow requires same-frame co-occurrence (a broken track no longer reports one pet as many), subject tracks count real frames, and pool eviction keeps gate-passers first (@ExWang). - Plugins grant butler capabilities without overriding the host agent's identity; the backend event body and the habit-suggest skill no longer make the agent refer to itself as miloco (@idootop).
- Deploy-timezone handling aligned with the CLI write path via
ZoneInfofor UTC configs (@HCl8).
🚀 Performance
- Idle thread pools trimmed across libraries (@Zirconi): every library defaulted to one thread per CPU core, which sits mostly idle on a single low-quality stream. swscale pixel conversion pinned to 2 threads, video decode to 4, OpenCV to 4, the ONNX detector / reid down from 4 to 2, and a new
TINY_MODEL_THREADS=1used by dedup and VAD, where fork-join costs more than it saves. - SQLite free pages actually reclaimed now (@Zirconi):
PRAGMA incremental_vacuumis driven by consuming its result set, and the missingfetchallmeant each cleanup reclaimed exactly one page while pages freed byDELETEpiled up — a productionobservability.dbhad 142.5 MB of free pages inside 222.8 MB. Reclaim is now capped per run, split into short write transactions, validated against theauto_vacuummode, and moved to a worker thread since it is real blocking I/O.
⚙️ Improvements: CLI / Web
- Habit-suggestion state machine moved from the plugin tool into
miloco-cli(@HCl8), for both the OpenClaw and Hermes plugins, which is what letsplugins/openclawandplugins/hermesshed ~1,900 lines between them. - Web loading behavior reworked: skeleton placeholders instead of a permanent skeleton on API failure,
loadinginitialized totrueto kill the first-frame "load failed" flash, the settings drawer no longer exposes default slider values before data arrives, and the log tab no longer flashes stale history before going blank (@Molly-3000). - Device status semantics clarified in Web (@wei-dou).
- Pet reference-image lookup switched to
functools.lru_cache, dropping a module-level try-once global (@ExWang). - Rule-reminder log labels trimmed to "task / rule" across backend and front end (@Molly-3000).
🔒 Security / Supply Chain
- Avatar and pet reference-image endpoints hardened (@ExWang): on-disk extension decided by content magic bytes rather than the filename,
realpathcontainment checks on avatar paths,subject_idvalidated in the storage layer, uploaded bytes verified as images,person_idanchored with\Zto reject trailing newlines, and a size gate applied before the body is read into memory instead of after. - Log-injection fixes flagged by CodeQL: CR/LF stripped from
read_crop_metalogging (@Molly-3000); path and log injection closed in the pet and avatar paths (@ExWang); an emptyexceptin perf sampling given a debug log (@Zirconi). - Rule short-name stripping now collapses whitespace before matching and narrows its regex to ASCII on both sides, closing a
task_idleak through whitespace-leading names, plus free-text prompt-injection guards (@Molly-3000). - PR AI-review job timeout raised 30 → 60 minutes (@ExWang); offline eval artifacts and sampling lists added to
.gitignoreso subject labels can't leak through (@Molly-3000).
📚 Docs
- Full-chain resolution table added — capture / streaming / omni / crop / provider, with the source and conversion at each tier (@Molly-3000).
- Smart Crop's two config switches renamed by configuration layer, with the CLI-writes-
config.jsonfailure path documented (@Molly-3000). create-taskskill tightened (@Zirconi): the TTS action JSON contract documented,Rule.action"play fixed text" scoped to speakers, the perception-viewpoint section given a "no single camera subject" branch, and cross-references realigned.- One-click upgrade documented as a feature page, with troubleshooting entries (@hlccd).
- Perception-guidance injection wording aligned between the system-prompt tail and the video+audio paths (@HCl8).
- The candidate-bbox comment in
prompt_buildercorrected — coasting tracks are not filtered upstream, so a Kalman-only phantom box can still reach the remap decision; tracked as #494 (@Molly-3000).
🙏 Acknowledgements
Special thanks to @ExWang for landing experimental pet recognition — the biggest change in this release — and to @Molly-3000 for Smart Crop.
Thanks as well to everyone else who contributed: @Zirconi, @hlccd, @LeonJoeeee, @HCl8, @idootop, @wei-dou