Repository navigation
chore: sync upstream (file editing, image paste, schedule fixes) - #18
Merged
Merged
Conversation
Three file polls between the app and the in-guest agent ran for the life of the process, waking it every few hundred milliseconds whether or not anything could have been written: - Claude Code permission bridge: every 250 ms, started by the first session and never cancelled, even after every session had ended. - Schedule bridge: every 800 ms on the application scope. - Guest browser command watcher: every 1 s from a LaunchedEffect, which keeps running while the activity is stopped. Add Flow<Boolean>.pollWhileActive (poll at once when the gate opens, then every interval, and stay suspended with no timer while it is closed) and gate each loop on the condition under which a writer can exist: - permission bridge: a CLI process is registered. The hook that parks a request dies with its process, so with none alive nothing can appear. - schedule bridge: the app is in the foreground or runtimeWork is active. With neither, the device may suspend and the guest freezes with it. - browser command watcher: the app is in the foreground. ScheduleBridge.run now requires the gate rather than defaulting to "always" so a future call site cannot quietly bring the unbounded loop back. Covered by PollWhileActiveTest plus a gating test each for the schedule bridge and the browser watcher. Disabling the gate makes exactly those five fail. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
…ption-optimization-961b0f
Follow-ups from the pre-PR review of the polling gate. - ScheduleBridge: with the poll parked while the app is backgrounded and idle, a request written in that window used to run on the way back in even though the guest MCP had already given up after 90 s and told the agent the call failed. A create/delete/runNow the agent was told did not happen would then happen anyway, and a retry could duplicate it. Requests older than two minutes are now answered with an "expired" error and discarded. A missing or zero createdAtMs is "unknown" and still runs. - ClaudeCodeRuntime: route every change to the session map through registerSession/unregisterSession, which keep hasLiveSessions in step, so a future edit cannot forget to publish and leave permission prompts silently unanswered. - KDoc: say what pollWhileActive does to a suspending action, and that the browser watcher's foreground flow must be a stable reference. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Review follow-up. The expiry added for requests that sat unanswered while the bridge poll was parked was two minutes against the guest's 90 s reply timeout, which left a 90-120 s window where a request ran after its caller had already given up. The stated reason for the extra headroom, clock drift, does not apply: the guest runs under PRoot and reads the same kernel clock as the app. - REQUEST_EXPIRES_AFTER_MILLIS is now 95 s, with a note to keep it in step with RESPONSE_TIMEOUT_S in andcode-schedule-mcp.py. - Tests pin the boundary and the cases that must still run: a timestamp in the future and a request with no timestamp at all. - docs/LOCAL_RUNTIME.md says when the bridge polls and that stale requests are discarded. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
…ery-consumption-optimization-961b0f perf: park always-on bridge polls while nothing can write to them
A copied screenshot or image gave the message field nothing to paste, so it had to be saved and re-attached from the gallery. The field now offers Paste in its selection toolbar when the clipboard holds an image and no text, and Ctrl+V / Shift+Insert attach it from a hardware keyboard. The image goes through the same decode-and-attach path as the gallery picker, so it shows the usual thumbnail before sending. A clipboard that carries text keeps the normal text paste. The gallery picker now shares decodeImageUri with the paste path, which reads through the existing 25 MB readLimited cap instead of readBytes(). Closes yuga-hashimoto#401 Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
- Resolve the clip's URI types off the main thread: getType() calls into the app that copied the image, which can be slow to answer. - Accept only content:// URIs from the clipboard, so a file:// URI chosen by the clip's owner cannot point at this app's own files. - Attach on the first KeyDown only, so holding Ctrl+V does not attach the same image repeatedly. - Tell the user when a pasted or gallery image cannot be attached, using the existing attachment_load_failed string. - Move decodeImageUri next to decodeSampledBitmap/readLimited and cover the 25 MB readLimited boundary with unit tests. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
…ew-new-issues-9d0867 feat(chat): paste clipboard images into the composer
Adds an Edit action to the code viewer for runtimes whose workspace is a folder on the device (OpenCode local, Claude Code, Codex, Antigravity). Remote OpenCode servers have no write endpoint, so they stay read-only (RuntimeCapabilities.fileEditing). Writes go through the host path of the guest folder via WorkspaceFileWriter (plain Kotlin, unit tested): - root and target are canonicalised, so `..` and symlinks cannot leave the selected workspace; `/` is never an editing root - only existing UTF-8 text up to 256 KB; binary, non-UTF-8, read-only files and directories are refused - temp file + fsync + atomic move; the original survives any failure and permission bits are preserved - the editor starts from the exact on-disk text and the save is refused if the file changed meanwhile, so an agent's concurrent edit is not lost The viewer guards unsaved changes on back, system back and stop-editing, and shows localized errors (15 new strings in all 8 locale files). Refs yuga-hashimoto#402 (file-editing part only). Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
…it-local-workspace-files feat: edit files in local workspaces from the code viewer (refs yuga-hashimoto#402)
Brings in yuga-hashimoto/and-code up to 414c780: - edit files in local workspaces from the code viewer - paste clipboard images into the composer - schedule bridge expiry and polling fixes Conflict resolution: - CodeViewerViewModel: upstream's editing backend (exact on-disk read, write refused when the file changed underneath, workspace bound) with the fork's undo/redo, replace-all and save confirmation on top. The fork's shell-based save is no longer used by the viewer. - CodeViewerScreen: the fork's editor UI, now on upstream's state and strings; the fork-only duplicates are removed. The instrumented editing test follows the fork's behaviour, where back closes the editor before it leaves the screen. - ChatComposer: upstream's image paste (toolbar and Ctrl+V) moved into the composer file the fork split out of ChatHomeScreen. - strings: both sides kept. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BJMh6NPYDcxwnfsgGh54JU
Back during a save could open the discard dialog and then lose to the save landing; it now waits. The editor is read-only while saving, turns off autocorrect and auto-capitals for code, and a test pins that a save confirms once and clears the undo history. Two imports the merge left unused are dropped. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BJMh6NPYDcxwnfsgGh54JU
Demonic1594
marked this pull request as ready for review
October 26, 2026 19:54
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Merges yuga-hashimoto/and-code
mainup to 414c780 (6 commits):Merge with
--no-ffper docs/FORK.md, so upstream history is kept. Please merge this PR with a merge commit, not squash, so the next sync starts from here.Conflict resolution
CodeViewerViewModel: upstream's editing backend plus the fork's editor features.readFileForEditing);expectedContent);editTargetOf);savedCountconfirmation. The fork's shell-based save is no longer used by the viewer.CodeViewerScreen: the fork's editor UI on upstream's state (isEditing,editError) and strings. The fork-only duplicate strings are removed. Start-edit failures now show in the viewer.ChatComposer: upstream's image paste (text toolbar and Ctrl+V) moved into the composer file the fork split out ofChatHomeScreen. TheChatHomeScreenside (gallery helper,onPasteImage) came through the merge.CodeViewerEditingInstrumentedTest: follows the fork's behaviour, where back closes the editor before it leaves the screen.Follow-up commit (from review)
FORK.md post-sync checks: the debug-variant files are present,
largeHeapappears once, and the.heapsuffix and runtime port offset are intact.Pre-PR review (repo-reviewer)
Verdict: APPROVE. Applied from it: back and typing are held during save, the keyboard options, the unused imports, and the
savedCounttest.Left as is:
WorkspaceShell.writeFileis now only used by its own test. It will be revisited in the upcoming editor rework.replaceAllignore-case counting differs from the replacement count for non-ASCII. This is pre-existing fork behaviour.Local checks
./gradlew detekt spotlessCheck :app:lintGithubDebug :app:testGithubDebugUnitTest :app:assembleGithubDebug :app:assembleGithubDebugAndroidTestpasses.Generated by Claude Code