Skip to content

Commit d8e573d

Browse files
wuzixuan06EtienneLescot
authored andcommitted
fix: update agent undo docs and keep Stop tooltip accessible
1 parent 7632d5c commit d8e573d

4 files changed

Lines changed: 29 additions & 11 deletions

File tree

‎src/components/ai-edition/LeftPanel.stop.test.tsx‎

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,22 @@ function emit(
126126
}
127127

128128
describe("composer Stop", () => {
129+
it("keeps the Stopping tooltip keyboard-accessible without sending another cancel", async () => {
130+
panel();
131+
await start();
132+
const stop = screen.getByRole("button", { name: "chat.stop" });
133+
fireEvent.click(stop);
134+
expect(stop).toHaveAttribute("aria-disabled", "true");
135+
expect(stop).not.toBeDisabled();
136+
fireEvent.keyDown(window, { key: "Tab" });
137+
act(() => stop.focus());
138+
expect(await screen.findByRole("tooltip")).toHaveTextContent("chat.stopping");
139+
expect(stop).toHaveFocus();
140+
fireEvent.click(stop);
141+
expect(api.cancel).toHaveBeenCalledOnce();
142+
await act(async () => replies[0](result("Partial", true)));
143+
});
144+
129145
it("commits stopped edits once, retains the live reply, ignores old events and starts the next turn", async () => {
130146
panel();
131147
const id = await start();

‎src/components/ai-edition/LeftPanel.tsx‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1696,8 +1696,8 @@ export function ChatStripPanel() {
16961696
type="button"
16971697
className={styles.sendBtn}
16981698
aria-label={t("chat.stop")}
1699-
disabled={stopping}
1700-
onClick={() => void stop()}
1699+
aria-disabled={stopping || undefined}
1700+
onClick={stopping ? undefined : () => void stop()}
17011701
>
17021702
<Square size={14} fill="currentColor" />
17031703
</button>

‎technical-documentation/architecture/ai-agent.md‎

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -79,10 +79,12 @@ Clips and trims use source time. Zoom, speed, annotation, camera-fullscreen, and
7979
Before a user message starts an agent turn, `chat-service.ts` clones the current
8080
document and associates it with that user message. Explicit message rewind restores
8181
that snapshot and truncates the later conversation. It is separate from Ctrl+Z:
82-
completed tool edits stream to `AgentDocumentStream`, which serializes them through
83-
`applyAgentDocumentIfCurrent` and the existing project store save/history boundary.
84-
Each applied tool edit keeps its own undo step. The final aggregate document is not
85-
applied again after streamed edits.
82+
completed tool edits accumulate in the agent's working document. `runAgentTurn`
83+
captures the live document and its revision before the turn starts. On normal
84+
completion or Stop, `runChat` returns the accumulated document, which the panel
85+
applies once through `applyAgentDocumentIfCurrent` and the existing project store
86+
save/history boundary. Each turn that applies edits has one project save and one
87+
undo step. A revision conflict preserves the live document and offers Apply anyway.
8688

8789
## Stopping a turn
8890

@@ -100,10 +102,10 @@ in the background; their results cannot commit edits or emit tool success after
100102
The turn lifetime seals queued tools on every exit, including normal completion.
101103

102104
Every streamed event carries the project, session and run ID. The panel ignores
103-
foreign or stale events, cancels on project/session change or unmount, and closes
104-
its edit queue when abandoned. Window destruction aborts its run in main as well.
105-
Stop stays in a stopping state until the turn replies and already-received completed
106-
edit saves settle. It preserves those edits and their undo entries, partial answer,
105+
foreign or stale events, cancels on project/session change or unmount, and discards
106+
an abandoned turn's result. Window destruction aborts its run in main as well.
107+
Stop stays in a stopping state until the turn replies and the accumulated document's
108+
save settles. It preserves completed tool edits in one undo step, the partial answer,
107109
and completed tool summaries. A stopped assistant message has `stopped: true` in the
108110
existing chat sidecar, so reopening the conversation still distinguishes a user stop
109111
from a provider failure. A later normal completion can win the race with a stop;

‎technical-documentation/testing/manual-e2e-checklist.md‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -999,5 +999,5 @@ These checks are the human slice: an agent cannot click Apple's picker (see abov
999999
| 2026-10-17 | PR #1319 (`2236580`), artifact `openscreen-linux` of build run 39046512213, AppImage run directly. Reference: the `v2.1.0` AppImage from the GitHub release | Ubuntu 24.04.4, GNOME 46 Wayland, AMD Radeon 610M (RADV); `[d3d] … -> backend Hardware`, no CPU fallback | **Partial — fix slice only, no defect** | Same MCP pass and project as the rows above, on the hardware Vulkan backend. `orbit` (12 frames) and `left` (4 s, 6 s): the whole card with four rounded corners, no flat cut. `v2.1.0` reproduces the bug (top and bottom edges flat, corners cut from 1.5 s). `none` and the flat frames at 1.0 and 9.5 s are byte-identical to `v2.1.0` (equal md5). **Not covered:** the editor preview; `right`; a full MP4 export. |
10001000
| 2026-10-17 | `v2.1.1-rc.1`, `release/v2.1.1` @ `6ec38bf` (= `v2.1.0` + #1319), assets of the GitHub pre-release (build run 39069024444). Windows: `Openscreen.Setup.2.1.1-rc.1-x64.exe`, sha512 matched `latest.yml`, unpacked with 7-Zip and run in place, version 2.1.1. macOS: `Openscreen-macOS-Apple-Silicon-2.1.1-rc.1.dmg`, sha256 matched the asset digest; `spctl` accepted, Notarized Developer ID, on the DMG and the app; ticket stapled to the DMG only, as on 2.1.0-rc.6; `CFBundleShortVersionString` 2.1.1-rc.1. Linux: `Openscreen-Linux-2.1.1-rc.1.AppImage`, sha512 matched `latest-linux.yml` | Windows 11 Home 26200, RTX 4070 Ti; macOS 27.0.1 (26A434), Mac mini M1 8 GB; Ubuntu 24.04.4, GNOME 46 Wayland, Radeon 610M, hardware Vulkan backend | **Partial — patch pass toward stable: no defect on any of the three** | Scoped to what the patch changes (the compositor geometry of a tilted filled card), in MCP over stdio with an isolated `--user-data-dir`, on the project of the PR rows above. On all three: `orbit` (12 frames) and `left` show the whole card with four rounded corners and no flat cut; `none` is a flat zoom in a rounded card (byte-identical to `v2.1.0` on Windows and Linux; on Windows every checked frame is byte-identical to the PR build). `exportVideo` at 1080p30: 10.00 s, 1920×1080 H.264 with an AAC track, decodes without error, and its frame at 5 s shows the tilted card with rounded corners. Before the cut, on a dev build of the PR: the four device frames, dual-frame and vertical-stack, under `orbit`, `left` and `none`, rendered byte-identical to `v2.1.0` (49 of 49 frames). **Not covered:** recording, playback and the editor preview, which the patch does not touch; the rest of the checklist (the `v2.1.0-rc.6` rows). |
10011001
| 2026-10-19 | `v2.1.2-rc.1`, `release/v2.1.2` @ `c4ef8fd` (= `v2.1.1` + #1344), assets of the GitHub pre-release (build run 39224311283). Windows: `Openscreen.Setup.2.1.2-rc.1-x64.exe` unpacked with 7-Zip and run in place. macOS: `Openscreen-Mac-arm64-2.1.2-rc.1.zip`, run in place. Linux: the AppImage, run directly with `--no-sandbox` | Windows 11 Home 26200; macOS 27.0.1, Mac mini M1; Ubuntu 24.04 GNOME Wayland (Xwayland `:0`) | **Partial: fix slice only, no defect** | `openscreen mcp` over stdio, scripted, with a fresh `--user-data-dir` per run. On all three platforms it answered `initialize`, and `usage-ping.json` held today's day, which is saved only once PostHog accepted the event. With `DO_NOT_TRACK=1` no state file was written. stdout held only JSON-RPC on macOS and Linux. On Windows it starts with one `\r\n` that Electron 41 itself writes during browser-process startup, before `main.js` loads: a bare `app.exit(0)` script prints it too, `ELECTRON_RUN_AS_NODE` does not. It predates this change, and the MCP SDK clients skip it with one parse error. Not covered: everything else in this file, including recording, editing, export, the GUI ping and the tray toggle. These runs sent eight real `surface: mcp` events to PostHog on 19/10. |
1002-
| 2026-10-22 | Dev `d8bf2d81` + issue #1260 patch (`fix/agent-stop-1260`), Electron 41.2.1; Vite `127.0.0.1:5186`, private `openscreen1260-ui-*` userData, local controlled OpenAI-compatible provider | macOS 15.8, Apple Silicon | Partial — Agent Stop passed | Real Electron operated through computer-use: sent a first turn, observed Stop while the provider held its SSE response open, applied two `setVocabulary` edits, clicked Stop, saw the stopped status and Send return, confirmed the provider connection closed and the partial answer plus `stopped: true` reached the chat sidecar. Document bytes stayed at `Second edit`; one Undo restored `First edit`, a second restored the initial document. A new turn completed with `Next turn works.` Screenshots captured for running and continued states. Skipped: paid/remote providers, Windows/Linux desktop UI, capture, media preview and export (this patch changes Agent chat only). |
1002+
| 2026-10-22 | Dev `d8bf2d81` + issue #1260 patch (`fix/agent-stop-1260`), Electron 41.2.1; Vite `127.0.0.1:5186`, private `openscreen1260-ui-*` userData, local controlled OpenAI-compatible provider | macOS 15.8, Apple Silicon | Superseded — pre-`0cb26e07` Agent Stop check | **Superseded by `0cb26e07`:** the two-Undo observation below records the old per-tool behavior. The current implementation applies the accumulated document once on completion or Stop, with one save and one undo step per turn. Automated regressions cover normal and stopped turns with 60 tool edits; this desktop check has not been rerun on the new head. **Historical run:** Real Electron operated through computer-use: sent a first turn, observed Stop while the provider held its SSE response open, applied two `setVocabulary` edits, clicked Stop, saw the stopped status and Send return, confirmed the provider connection closed and the partial answer plus `stopped: true` reached the chat sidecar. Document bytes stayed at `Second edit`; one Undo restored `First edit`, a second restored the initial document. A new turn completed with `Next turn works.` Screenshots captured for running and continued states. Skipped: paid/remote providers, Windows/Linux desktop UI, capture, media preview and export (this patch changes Agent chat only). |
10031003
| 2026-10-23 | `fix/mac-mic-silent-with-system-audio` on `main` @ `264975d`, dev build (`npm run dev`), capture helper built locally with Xcode 27 and copied from `out/Products/Release` by hand | macOS 26.6.2 (25G83), MacBook Pro M2 Pro; built-in microphone and a USB Audio CODEC (08bb:2902) | **Partial: fix slice only, pass** | #1173, Apple's picker, system audio on, output device idle (after `sudo killall coreaudiod`, or checked idle). Before the fix: the microphone delivered nothing until another app played a sound, 56 s (built-in) and 14 s (USB) into the take; without system audio it started at 0.17 s. With the tap merely started after the stream, four takes (built-in twice, USB twice) recorded the microphone from 0.17–0.18 s, but only 12–30 ms ahead of the tap. With this branch's version, the tap waiting for the first microphone buffer: one USB take recorded the microphone from 0.18 s and the tap started 27 ms after it; one take with the microphone off. In both, a sound played mid-take was in system audio. Measured with temporary per-source buffer counters in the helper, not shipped. **Not covered:** this branch's version with the built-in microphone, a legacy-picker take, macOS 15, an Intel Mac, a microphone that never delivers (the 1 s fallback), pause before the first microphone buffer, a CI-built artifact. |

0 commit comments

Comments
 (0)