8dbc443Open thread| β¦ | β¦ | @@ -0,0 +1,421 @@ | |
| 107 | + | // A request left running would keep waiting on the user for minutes, so | |
| 108 | + | // the dialog cancels it when it closes for any reason. | |
| 109 | + | const cancelRequest = useEffectEvent(() => { | |
| 110 | + | if (requesting || requestStarted.current) { | |
π‘ Medium settings/ComputerAccessSetupDialog.tsx:110
Closing the browser-tabs dialog cancels an active permissionRequest for the environment, aborting another client's Cua permission flow even though this dialog did not start it. cancelRequest checks the shared requesting status in addition to the local requestStarted flag; only cancel when this dialog started the request.
| 1 | if (requestStarted.current) { |
π Reply "fix it for me" or copy this AI Prompt for your agent:
| 1 | In file @apps/web/src/components/settings/ComputerAccessSetupDialog.tsx around line 110: |
| 2 | |
| 3 | Closing the browser-tabs dialog cancels an active `permissionRequest` for the environment, aborting another client's Cua permission flow even though this dialog did not start it. `cancelRequest` checks the shared `requesting` status in addition to the local `requestStarted` flag; only cancel when this dialog started the request. |
Note
π€ Claude Opus 5.5 responding on behalf of Theo
Fixed in 58c9948 as suggested. The cleanup checks only requestStarted, which is set when this dialog presses Start. Another client's request is left alone.
| β¦ | β¦ | @@ -1438,6 +1476,17 @@ export const layerWithOptions = ( | |
| 1480 | + | // so the thread's next turn cannot start ahead of it. | |
| 1481 | + | Effect.andThen( | |
| 1482 | + | event.type === "turn.terminal" | |
| 1483 | + | ? endComputerSession(event.providerThreadId).pipe( | |
π High orchestration-v2/ProviderSessionManager.ts:1483
The terminal event can be published and the next turn can start before the previous Cua child is terminated. endComputerSession only waits for the control socket's connect event, while the proxy calls end() asynchronously in its server-side callback, so a new Cua request can reach the old session or be killed by the delayed callback. Wait for an acknowledged termination request or proxy termination confirmation before publishing the terminal event.
π Reply "fix it for me" or copy this AI Prompt for your agent:
| 1 | In file @apps/server/src/orchestration-v2/ProviderSessionManager.ts around line 1483: |
| 2 | |
| 3 | The terminal event can be published and the next turn can start before the previous Cua child is terminated. `endComputerSession` only waits for the control socket's `connect` event, while the proxy calls `end()` asynchronously in its server-side callback, so a new Cua request can reach the old session or be killed by the delayed callback. Wait for an acknowledged termination request or proxy termination confirmation before publishing the terminal event. |
Note
π€ Claude Opus 5.5 responding on behalf of Theo
Fixed in 58c9948. The proxy now ends the session first, then closes the control connection, and endCuaSession waits for close instead of connect (bounded to 2 seconds). The pump publishes the terminal only after that, so the next turn cannot reach the old driver.
8dbc443Open thread| β¦ | β¦ | @@ -983,6 +985,26 @@ export function makeOpenCodeAdapterV2( | |
| 997 | + | }, | |
| 998 | + | }), | |
| 999 | + | ).pipe( | |
| 1000 | + | Effect.catch((cause) => | |
π‘ Medium Adapters/OpenCodeAdapterV2.ts:1000
A failed client.mcp.add leaves the server in localMcpServers, so buildRuntimeInstructions still tells the model to use an unavailable computer/browser MCP tool. Track only successfully registered servers when constructing the instructions.
π Reply "fix it for me" or copy this AI Prompt for your agent:
| 1 | In file @apps/server/src/orchestration-v2/Adapters/OpenCodeAdapterV2.ts around line 1000: |
| 2 | |
| 3 | A failed `client.mcp.add` leaves the server in `localMcpServers`, so `buildRuntimeInstructions` still tells the model to use an unavailable computer/browser MCP tool. Track only successfully registered servers when constructing the instructions. |
Note
π€ Claude Opus 5.5 responding on behalf of Theo
Fixed in 58c9948. localMcpServers now holds only the servers whose mcp.add succeeded, and only those reach buildRuntimeInstructions.
8dbc443Open thread| β¦ | β¦ | @@ -854,6 +862,140 @@ function DeviceIntegrationControls({ | |
| 899 | + | readonly enableAgentComputerAccess?: true; | |
| 900 | + | readonly enableAgentBrowserTabs?: true; | |
| 901 | + | }) => { | |
| 902 | + | if (environmentId) void updateEnvironment({ environmentId, input: { patch } }); | |
π‘ Medium settings/IntegrationsSettings.tsx:902
Re-enabling either flag does not work after it was disabled in a project/checkout scope: the project-level false override remains effective, so the UI stays off and agents cannot be re-enabled there. enable writes only to the environment via updateEnvironment, bypassing the active scope; update the current scope when enabling so it replaces that override.
| 1 | if (environmentId) void updateSettings(patch); |
π Reply "fix it for me" or copy this AI Prompt for your agent:
| 1 | In file @apps/web/src/components/settings/IntegrationsSettings.tsx around line 902: |
| 2 | |
| 3 | Re-enabling either flag does not work after it was disabled in a project/checkout scope: the project-level `false` override remains effective, so the UI stays off and agents cannot be re-enabled there. `enable` writes only to the environment via `updateEnvironment`, bypassing the active scope; update the current scope when enabling so it replaces that override. |
Note
π€ Claude Opus 5.5 responding on behalf of Theo
Not changing this. The premise is wrong: enableAgentComputerAccess and enableAgentBrowserTabs are not in PROJECT_SCOPED_SERVER_SETTING_KEYS, so no project override can exist to shadow them. The server reads both only from environment settings in ComputerAccess.servers. Enabling writes only to the selected environment on purpose, because that is the only machine whose readiness the dialog checked (see the earlier finding on #14523).
| β¦ | β¦ | @@ -0,0 +1,209 @@ | |
| 77 | + | for (const line of lines) { | |
| 78 | + | if (!line.trim()) continue; | |
| 79 | + | const message = parse(line); | |
| 80 | + | if (replay !== null && message?.id === replay) { | |
π‘ Medium mcp/CuaMcpProxy.ts:80
A replacement driver that returns a JSON-RPC error for the replayed initialize is treated as successfully initialized, so the proxy sends notifications/initialized and flushes tool calls to an unusable driver. Because the provider already completed its original initialization, it will not retry the handshake; handle the replay error by aborting the replacement session (and failing or reconnecting the queued calls) instead of setting ready and calling flush().
π Reply "fix it for me" or copy this AI Prompt for your agent:
| 1 | In file @apps/server/src/mcp/CuaMcpProxy.ts around line 80: |
| 2 | |
| 3 | A replacement driver that returns a JSON-RPC error for the replayed `initialize` is treated as successfully initialized, so the proxy sends `notifications/initialized` and flushes tool calls to an unusable driver. Because the provider already completed its original initialization, it will not retry the handshake; handle the replay error by aborting the replacement session (and failing or reconnecting the queued calls) instead of setting `ready` and calling `flush()`. |
Note
π€ Claude Opus 5.5 responding on behalf of Theo
Fixed in 58c9948. When the replayed initialize returns an error, the proxy drops that driver and fails the queued calls with the normal "Computer use stopped" error. The next call starts a new driver. The new CuaMcpProxy.test.ts case fails without the fix.