Conversation
Code Review SummaryStatus: No Issues Found | Recommendation: Merge Incremental review at Files Reviewed (101 files)
Previous Review Summary (commit 3de8bde)Current summary above is authoritative. Previous snapshots are kept for context only. Previous review (commit 3de8bde)Status: No Issues Found | Recommendation: Merge Executive SummaryReviewed the mobile picture-to-new-agent entry (picker refactor, source-sheet index mapping, surface union, share-payload staging, Android pending-picker recovery) with its tests and 87 locale catalogs at Files Reviewed (101 files)
Non-blocking notes, not findings: the PR itself declares the Android recovery and iOS camera paths as built but not proved live, and the locale catalogs were inspected by key count rather than machine-validated JSON in this read-only pass. Reviewed by deepseek-v4.1-flash · Input: 0 · Output: 0 · Cached: 0 Review guidance: REVIEW.md from base branch |
|
bot: Rejected, no code change (kwf Why: (already implemented, verified live: no change needed: No code change needed: the picture entry is one implementation for both iOS and Android (shared source sheet, staging, and navigation), the only platform-guarded code is the Android Activity-recreation recovery, kept and named in code comments, and the |
3de8bde to
c83a0a6
Compare
Changelog for users
Changelog for maintainers
pickAgentPictureshares the composer's source sheet but offers camera and library only.stagePictureForNewSessionstages the picked files in the existing share payload and returns the new-agent route the composer consumes.AttachmentSurfaceaddsagent-picture, shared by the launch context, both entry points, and the Android recovery hook, which matches it after an Activity recreation.apps/mobile/src/**/kiloclaw/**is touched.E2E proof
[e1] Start an agent from an existing screenshot: home -> 'New task from a picture' -> Photo Library -> the seeded screenshot lands attached in the composer -> typed text -> Start session -> the session's… — android emulator-5554: the seeded screenshot (e1-picker.xml content-desc="Photo taken on Sep 16, 2026, 5:35:26" at bounds="[0,1409][354,1763]") picked through the OS photo picker landed in the composer as 'android.widget.Button 1000000018.png, Uploaded' with 'Remove attachment 1000000018.png' (e1-composer-run.log, capture e1-composer.png); after the typed prompt the session screen's first message carries it — 'android.widget.ImageView Image output, e4b01550-4206-4077-b5d4-dc01a3b2ba2b.png' beside 'android.widget.TextView Describe this picture' (e1-session-run.log, capture e1-session.png)…
Recording of the verified flow (waits trimmed)
scripted-shard1.mp4.trim.mp4
[e1] Start an agent from an existing screenshot: home -> 'New task from a picture' -> Photo Library -> the seeded screenshot lands attached in the composer -> typed text -> Start session -> the session's… — android emulator-5554: the seeded screenshot (e1-picker.xml content-desc="Photo taken on Sep 16, 2026, 5:35:26" at bounds="[0,1409][354,1763]") picked through the OS photo picker landed in the composer as 'android.widget.Button 1000000018.png, Uploaded' with 'Remove attachment 1000000018.png' (e1-composer-run.log, capture e1-composer.png); after the typed prompt the session screen's first message carries it — 'android.widget.ImageView Image output, e4b01550-4206-4077-b5d4-dc01a3b2ba2b.png' beside 'android.widget.TextView Describe this picture' (e1-session-run.log, capture e1-session.png)…
[e1] Start an agent from an existing screenshot: home -> 'New task from a picture' -> Photo Library -> the seeded screenshot lands attached in the composer -> typed text -> Start session -> the session's… — android emulator-5554: the seeded screenshot (e1-picker.xml content-desc="Photo taken on Sep 16, 2026, 5:35:26" at bounds="[0,1409][354,1763]") picked through the OS photo picker landed in the composer as 'android.widget.Button 1000000018.png, Uploaded' with 'Remove attachment 1000000018.png' (e1-composer-run.log, capture e1-composer.png); after the typed prompt the session screen's first message carries it — 'android.widget.ImageView Image output, e4b01550-4206-4077-b5d4-dc01a3b2ba2b.png' beside 'android.widget.TextView Describe this picture' (e1-session-run.log, capture e1-session.png)…
E2E proof — log excerpts
/home/igor_kilocode_ai/.local/share/kwf/sections/picture-to-new-agent-9c36/e2e-mobile-app/e1-composer-run.log/home/igor_kilocode_ai/.local/share/kwf/sections/picture-to-new-agent-9c36/e2e-mobile-app/e1-session-run.log/home/igor_kilocode_ai/.local/share/kwf/sections/picture-to-new-agent-9c36/e2e-mobile-app/e1-session-row.txt/home/igor_kilocode_ai/.local/share/kwf/sections/picture-to-new-agent-9c36/e2e-mobile-app/e1-cancel-after.txt/home/igor_kilocode_ai/.local/share/kwf/sections/picture-to-new-agent-9c36/e2e-mobile-app/e1-picker-cancel-after.txtOwner request
[e1] Start an agent from an existing screenshot: home -> 'New task from a picture' -> Photo Library -> the seeded screenshot lands attached in the composer -> typed text -> Start session -> the session's… — android emulator-5554: the seeded screenshot (e1-picker.xml content-desc="Photo taken on Sep 16, 2026, 5:35:26" at bounds="[0,1409][354,1763]") picked through the OS photo picker landed in the composer as 'android.widget.Button 1000000018.png, Uploaded' with 'Remove attachment 1000000018.png' (e1-composer-run.log, capture e1-composer.png); after the typed prompt the session screen's first message carries it — 'android.widget.ImageView Image output, e4b01550-4206-4077-b5d4-dc01a3b2ba2b.png' beside 'android.widget.TextView Describe this picture' (e1-session-run.log, capture e1-session.png)…
[e1] Start an agent from an existing screenshot: home -> 'New task from a picture' -> Photo Library -> the seeded screenshot lands attached in the composer -> typed text -> Start session -> the session's… — android emulator-5554: the seeded screenshot (e1-picker.xml content-desc="Photo taken on Sep 16, 2026, 5:35:26" at bounds="[0,1409][354,1763]") picked through the OS photo picker landed in the composer as 'android.widget.Button 1000000018.png, Uploaded' with 'Remove attachment 1000000018.png' (e1-composer-run.log, capture e1-composer.png); after the typed prompt the session screen's first message carries it — 'android.widget.ImageView Image output, e4b01550-4206-4077-b5d4-dc01a3b2ba2b.png' beside 'android.widget.TextView Describe this picture' (e1-session-run.log, capture e1-session.png)…
Follow-ups (not changed here)
pnpm dev:mobile:android adb -s <serial> shell pm revoke com.kilocode.kiloapp android.permission.CAMERAbefore step 1 so the OS permission dialog is part of the run. Steps 1-5 replay in the harness; the remaining surfaces are the OS ones - tap the camera permission dialog's 'While using the app' (or 'Allow'), take the shot in the platform camera withpnpm dev:mobile:android adb -s <serial> shell input keyevent 27(KEYCODE_CAMERA) or by tapping the shutter, then confirm on the camera app's review control ('Done'). Expected: the new-session composer with an image chip whose name is synthesized as image. (attachment-picker.ts:23-57) - assert '/image/' and 'Start session' - capture $OUT/e3-composer.png. Layout stability: the chip fills reserved strip space without moving the prompt field. (no capture cited it)pnpm dev:mobile:android adb -s <serial> shell pm revoke com.kilocode.kiloapp android.permission.CAMERAandpnpm dev:mobile:android adb -s <serial> shell appops set com.kilocode.kiloapp CAMERA denybefore step 1. Steps 1-6 replay in the harness; if the OS dialog still appears after step 5, tap 'Don't allow' and tap 'Camera' again - Android auto-denies once the refusal is recorded, which is the state this scenario needs. Expected: the app's own alert 'Camera Access Disabled' with 'Allow camera access in Settings to take a photo.' and the 'Open Settings' action - capture $OUT/e4-alert.png. Expected after tapping 'Cancel': Home unchanged ('/Home, tab, 1 of [0-9]+/'), the composer placeholder absent, the staged picture store empty (no chip and no push) - capture $OUT/e4-after.png. This is the denied branch ofpickAgentCameraImage(attachment-picker.ts:84-96) and proves a denial never creates a half-made agent. (no capture cited it)image-picker.ts:11-28), so every later launch rejects until the process restarts; the app toasts the recovery copy and attaches nothing. Trigger: force an Activity recreation withpnpm dev:mobile:android adb -s <serial> shell settings put system accelerometer_rotation 0then... shell settings put system user_rotation 1and back to 0, then run the steps. Expected: the toast 'Could not open the photo picker. Restart Kilo and try again.', Home unchanged, the composer placeholder absent, no chip; thenpnpm dev:mobile:android adb -s <serial> shell am force-stop com.kilocode.kiloapp, relaunch, sign in, and the same pick reaches the composer (the retry). Advisory: it depends on the platform bug reproducing on this emulator image - if it does not reproduce, report it as not proved, never as failed. (no capture cited it)Open findings (not fixed here)