feat(desktop): keep multiple Runtime Hosts connected - #3097
Conversation
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (4)
🚧 Files skipped from review as they are similar to previous changes (4)
Included review availability: Your plan includes up to 3 reviews per rolling hour; 0 remain after this review. 📝 WalkthroughSummaryThis PR allows Desktop to keep Local and multiple remote Runtime Hosts connected independently. Failed remote Hosts no longer block Local work. Sessions use stable The default Host applies only to new or unscoped work. Existing Sessions remain attached to their owning Host. CLI and TUI retain single-Host behavior. Design assessment
Validation
Review-relevant risks
WalkthroughDesktop Runtime Host support now manages multiple local and remote targets concurrently. Sessions, IPC, transcripts, browser state, connections, and renderer data now use host-qualified identities and session-aware routing. ChangesMulti-host runtime and session routing
Estimated code review effort: 5 (Critical) | ~120 minutes Merge Risk: 🟡 Moderate · up to This PR changes Desktop to aggregate and route work across multiple Runtime Hosts, but unresolved issues can hide remote session search results, discard refreshed model choices, emit incorrect profile-change state, or misroute sessions if identity formats drift; merge is not ready until these bounded correctness and validation risks are fixed or explicitly accepted. Sequence Diagram(s)sequenceDiagram
participant Renderer
participant Preload
participant RuntimeHostManager
participant RuntimeHost
Renderer->>Preload: Invoke session operation with desktop session ID
Preload->>Preload: Resolve host and local session ID
Preload->>RuntimeHostManager: Route operation with target scope
RuntimeHostManager->>RuntimeHost: Execute operation on owning Host
RuntimeHost-->>RuntimeHostManager: Return Host-local result
RuntimeHostManager-->>Preload: Return scoped result
Preload-->>Renderer: Project Host-qualified session data
Possibly related PRs
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Comment |
9b18ee9 to
74e8319
Compare
c33d0da to
5ed2f08
Compare
There was a problem hiding this comment.
Actionable comments posted: 8
🧹 Nitpick comments (10)
apps/desktop/src/main/runtime-host-reconnecting-ipc-main.ts (1)
183-192: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low valueRead the epoch handler once.
slot.handlers.get(epoch)runs three times and forces a non-null assertion. One lookup removes the assertion and the repeated map reads.♻️ Proposed simplification
- if ( - slot.handlers.get(epoch) !== undefined && - slot.handlers.get(epoch) !== previous - ) { - return Promise.resolve(slot.handlers.get(epoch)!); - } + const current = slot.handlers.get(epoch); + if (current !== undefined && current !== previous) { + return Promise.resolve(current); + }apps/desktop/src/renderer/desktop-transcript-range-store.ts (1)
341-358: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winReuse the shared Host/Session key codec.
Import
desktopSessionKeyandparseDesktopSessionKeyfrom../preload/runtime-host-identity.js. Adapt the parser result from a tuple to{ hostId, sessionId }, then remove both local helpers.apps/desktop/src/main/runtime-host-native-capabilities.ts (1)
81-81: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low valueEncode the
additionalServices/targetScopepairing in the types.
targetScopestays optional, butrequireTargetScopeturns a missing value into a runtime throw wheneverinput.additionalServicesexists. A discriminated options type, or passing the scope as a second argument ofadditionalServicesfrom a required field, would move this to compile time. The single production caller already supplies both, so this is preventive only.Also applies to: 98-101, 185-188
apps/desktop/src/preload/desktop-session-projection.ts (1)
106-109: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low valueDrop the optional wrapper and the non-null assertions.
Each call site already guards
=== undefinedbefore spreading, soprojectRelatedSessionIdnever receivesundefinedand the two!operators are noise.♻️ Proposed simplification
- const projectRelatedSessionId = (value: string | undefined): string | undefined => - value === undefined - ? undefined - : projectSessionId(host, value);Then call
projectSessionId(host, …)directly at each guarded site and remove the!operators.As per path instructions: "Flag concrete cases where code can be deleted or simplified."
Also applies to: 127-127, 135-135
Source: Path instructions
apps/desktop/src/main/__tests__/runtime-host-profile-service.test.ts (2)
46-49: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winAssert the parsed field, not the serialized text.
The regex
/"schemaVersion": 2/depends on the writer's JSON indentation. A change fromJSON.stringify(value, null, 2)to any other spacing breaks this test without any behavior change.♻️ Proposed fix
- assert.match( - await readFile(join(root, "runtime-host-profile-selection.json"), "utf8"), - /"schemaVersion": 2/, - ); + assert.equal( + JSON.parse(await readFile(join(root, "runtime-host-profile-selection.json"), "utf8")) + .schemaVersion, + 2, + );As per path instructions: "Flag tests that duplicate existing coverage, assert implementation details, or do not protect observable behavior."
Source: Path instructions
165-166: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winMove removal coverage into its own test.
The test is named "separates enabled Hosts from the default Host". Lines 165-166 then exercise
service.remove, which is a different behavior.
removeinapps/desktop/src/main/runtime-host-profile-service.tshas three rules: reject the local profile, reject an enabled profile, and reject the default profile. Only the happy path is exercised here, as a tail of an unrelated test. The three rejection rules have no coverage.Extract a
removes a disabled remote Hosttest, and add cases for the three rejections.As per path instructions: "Flag tests that duplicate existing coverage, assert implementation details, or do not protect observable behavior."
Source: Path instructions
apps/desktop/src/main/__tests__/runtime-host-native-capabilities.test.ts (1)
152-169: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winAdd a case for the missing
targetScope.
createDesktopNativeCapabilityProvidernow callsrequireTargetScope(providerOptions.targetScope)wheneveradditionalServicesis present (apps/desktop/src/main/runtime-host-native-capabilities.tsLine 98-100). That call throws whentargetScopeis absent.This test only covers the success path. A caller that supplies
additionalServiceswithouttargetScopenow fails at construction time, and no test protects that contract.Add a case that constructs the provider with
additionalServicesand notargetScope, and asserts the throw.As per path instructions: "Flag tests that duplicate existing coverage, assert implementation details, or do not protect observable behavior."
Source: Path instructions
apps/desktop/src/renderer/locales/settings-projects-copy.ts (1)
44-44: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winRename
runtimeHost.activetodefaultBadge.The badge renders for
entry.isDefault, and both locale values say “Default.” Update the type, locale objects, and consumer.apps/desktop/src/renderer/settings/runtime-host-profiles-section.tsx (1)
300-306: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winExplain why the default Runtime Host is disabled.
When
entry.isDefaultis true, pass a localized reason through the supporteddisabledMessageprop.Switchalready uses this prop elsewhere; do not rely on a tooltip or title.apps/desktop/e2e/streaming-remount.spec.ts (1)
9-18: 🩺 Stability & Availability | 🔵 Trivial | ⚡ Quick winPreserve Playwright auto-waiting in
sessionRow
Locator.evaluateAllqueries the current DOM once. It can return no rows while the sidebar remounts, so Line 16 can throw before.click()retries. Returnsidebar.locator(\[data-session-id=${JSON.stringify(sessionId)}]`)and removeawait` at the call sites.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro Plus
Run ID: 38a9af7b-7010-48f8-8515-e7089344e9f7
📒 Files selected for processing (47)
apps/desktop/e2e/streaming-remount.spec.tsapps/desktop/src/main/__tests__/app-shell-session-ui-state.test.tsapps/desktop/src/main/__tests__/desktop-session-projection.test.tsapps/desktop/src/main/__tests__/desktop-transcript-range-store.test.tsapps/desktop/src/main/__tests__/runtime-host-desktop-manager.test.tsapps/desktop/src/main/__tests__/runtime-host-native-capabilities.test.tsapps/desktop/src/main/__tests__/runtime-host-profile-service.test.tsapps/desktop/src/main/__tests__/runtime-host-reconnecting-ipc-main.test.tsapps/desktop/src/main/__tests__/use-onboarding-snapshot.test.tsapps/desktop/src/main/browser-ipc-main.tsapps/desktop/src/main/desktop-diagnostics-ipc-main.tsapps/desktop/src/main/main-window.tsapps/desktop/src/main/runtime-host-boot.tsapps/desktop/src/main/runtime-host-desktop-candidate.tsapps/desktop/src/main/runtime-host-desktop-manager.tsapps/desktop/src/main/runtime-host-native-capabilities.tsapps/desktop/src/main/runtime-host-profile-service.tsapps/desktop/src/main/runtime-host-reconnecting-ipc-main.tsapps/desktop/src/main/runtime-host-upgrade-dialog.tsapps/desktop/src/preload/bridge-contract.d.tsapps/desktop/src/preload/desktop-session-projection.tsapps/desktop/src/preload/preload.tsapps/desktop/src/preload/runtime-host-identity.tsapps/desktop/src/renderer/app-shell-effects.tsapps/desktop/src/renderer/app-shell-session-ui-state.tsapps/desktop/src/renderer/app-shell.tsxapps/desktop/src/renderer/app.tsxapps/desktop/src/renderer/desktop-transcript-range-store.tsapps/desktop/src/renderer/locales/settings-navigation-copy.tsapps/desktop/src/renderer/locales/settings-projects-copy.tsapps/desktop/src/renderer/main.tsxapps/desktop/src/renderer/session-message-settlement.tsapps/desktop/src/renderer/settings/projects-settings-page.tsxapps/desktop/src/renderer/settings/runtime-host-profiles-section.tsxapps/desktop/src/renderer/settings/tasks-settings-page.tsxapps/desktop/src/renderer/use-app-shell-session-list.tsapps/desktop/src/renderer/use-app-shell-session-workspace.tsapps/desktop/src/renderer/use-module-data.tsapps/desktop/src/renderer/use-project-context.tsapps/desktop/src/renderer/use-shell-connections.tsapps/desktop/src/renderer/use-task-submission-readiness.tsdocs/architecture/runtime-host-architecture.mddocs/architecture/runtime-host-architecture.zh-CN.mddocs/runtime-host-remote-access.mddocs/runtime-host-remote-access.zh-CN.mdpackages/ui/src/session-history-list.tsxpackages/ui/src/session-list-panel.tsx
💤 Files with no reviewable changes (5)
- apps/desktop/src/main/tests/app-shell-session-ui-state.test.ts
- apps/desktop/src/renderer/app-shell-session-ui-state.ts
- apps/desktop/src/renderer/use-app-shell-session-list.ts
- apps/desktop/src/renderer/use-module-data.ts
- apps/desktop/src/renderer/use-app-shell-session-workspace.ts
Included review availability: Your plan includes up to 3 reviews per rolling hour; 1 remains after this review.
9089836 to
88a866e
Compare
There was a problem hiding this comment.
Actionable comments posted: 2
🧹 Nitpick comments (3)
docs/architecture/runtime-host-architecture.zh-CN.md (1)
194-200: 🗄️ Data Integrity & Integration | 🔵 Trivial | ⚡ Quick winDocument the duplicate State Root invariant.
The profile service and
RuntimeHostDesktopManagerreject a second enabled profile with the samerootId, including local/remote conflicts. State this invariant here and add a remote/remote regression test.apps/desktop/src/main/runtime-host-boot.ts (1)
414-421: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low valueDelete the redundant epoch comparison.
The lookup key at Line 415 is
scope.targetEpoch, and Line 742 registers each context under its ownscope.targetEpoch. Thereforetarget.scope.targetEpoch === scope.targetEpochis always true here. Only thehostIdcheck adds information.
resolveRuntimeHostDiagnosticsat Lines 1152-1156 already uses the shorter form.♻️ Proposed simplification
isHostActive: (scope) => { const target = runtimePolicyTargetsByEpoch.get(scope.targetEpoch); - return Boolean( - target?.isActive() && - target.scope.hostId === scope.hostId && - target.scope.targetEpoch === scope.targetEpoch, - ); + return Boolean(target?.isActive() && target.scope.hostId === scope.hostId); },As per path instructions: "Flag concrete cases where code can be deleted or simplified."
Source: Path instructions
apps/desktop/src/renderer/use-shell-connections.ts (1)
48-63: 🗄️ Data Integrity & Integration | 🔵 Trivial | ⚡ Quick winThe identity-preserving update ignores
chatModelChoices.The bail-out compares
defaultConnectionand connectionslug/updatedAtonly. If a Host returns the same connections with a differentchatModelChoiceslist, the hook returnspreviousand discards the new choices. The model picker then shows a stale catalog until the next connection mutation. Include the choices in the comparison, or compare the whole snapshot.Proposed fix
setSnapshot((previous) => previous.defaultConnection === next.defaultConnection && - connectionsEqual(previous.connections, next.connections) + connectionsEqual(previous.connections, next.connections) && + choicesEqual(previous.chatModelChoices, next.chatModelChoices) ? previous : next, );function choicesEqual( a: DesktopConnectionSnapshot['chatModelChoices'], b: DesktopConnectionSnapshot['chatModelChoices'], ): boolean { if (a.length !== b.length) return false; return a.every((choice, index) => choice.connectionSlug === b[index].connectionSlug && choice.model === b[index].model); }
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro Plus
Run ID: d565591c-fbfd-4efc-8ea4-3779736ec339
📒 Files selected for processing (42)
apps/desktop/e2e/streaming-remount.spec.tsapps/desktop/src/main/__tests__/desktop-session-projection.test.tsapps/desktop/src/main/__tests__/runtime-host-connections-ipc-main.test.tsapps/desktop/src/main/__tests__/runtime-host-desktop-candidate.test.tsapps/desktop/src/main/__tests__/runtime-host-profile-service.test.tsapps/desktop/src/main/__tests__/stale-sessions.test.tsapps/desktop/src/main/__tests__/use-onboarding-snapshot.test.tsapps/desktop/src/main/browser-ipc-main.tsapps/desktop/src/main/desktop-diagnostics-ipc-main.tsapps/desktop/src/main/main-window.tsapps/desktop/src/main/onboarding-service.tsapps/desktop/src/main/runtime-host-boot.tsapps/desktop/src/main/runtime-host-connections-ipc-main.tsapps/desktop/src/main/runtime-host-desktop-candidate.tsapps/desktop/src/main/runtime-host-desktop-manager.tsapps/desktop/src/main/runtime-host-native-capabilities.tsapps/desktop/src/main/runtime-host-profile-service.tsapps/desktop/src/main/runtime-host-reconnecting-ipc-main.tsapps/desktop/src/main/runtime-host-settings-ipc-main.tsapps/desktop/src/preload/bridge-contract.d.tsapps/desktop/src/preload/preload.tsapps/desktop/src/renderer/app-shell-effects.tsapps/desktop/src/renderer/app-shell.tsxapps/desktop/src/renderer/desktop-transcript-range-store.tsapps/desktop/src/renderer/locales/settings-projects-copy.tsapps/desktop/src/renderer/settings/provider-panel-shared.tsapps/desktop/src/renderer/settings/providers-panel.tsxapps/desktop/src/renderer/settings/runtime-host-profiles-section.tsxapps/desktop/src/renderer/stale-sessions.tsapps/desktop/src/renderer/use-onboarding-snapshot.tsapps/desktop/src/renderer/use-shell-chat-model.tsapps/desktop/src/renderer/use-shell-connections.tsapps/desktop/src/renderer/use-shell-memory-pill.tsapps/desktop/src/shared/desktop-connection-snapshot.tsapps/desktop/src/shared/desktop-session-projection.tsapps/desktop/src/shared/runtime-host-identity.tsapps/desktop/stories/settings/provider-settings.stories.tsxapps/desktop/stories/settings/settings-pages.stories.tsxapps/desktop/tsconfig.preload.jsonapps/desktop/tsconfig.renderer.jsondocs/architecture/runtime-host-architecture.mddocs/architecture/runtime-host-architecture.zh-CN.md
💤 Files with no reviewable changes (1)
- apps/desktop/src/main/runtime-host-settings-ipc-main.ts
🚧 Files skipped from review as they are similar to previous changes (17)
- apps/desktop/src/main/tests/use-onboarding-snapshot.test.ts
- apps/desktop/e2e/streaming-remount.spec.ts
- docs/architecture/runtime-host-architecture.md
- apps/desktop/src/main/desktop-diagnostics-ipc-main.ts
- apps/desktop/src/main/browser-ipc-main.ts
- apps/desktop/src/main/runtime-host-native-capabilities.ts
- apps/desktop/src/renderer/locales/settings-projects-copy.ts
- apps/desktop/src/main/runtime-host-reconnecting-ipc-main.ts
- apps/desktop/src/renderer/settings/runtime-host-profiles-section.tsx
- apps/desktop/src/main/main-window.ts
- apps/desktop/src/renderer/app-shell-effects.ts
- apps/desktop/src/renderer/desktop-transcript-range-store.ts
- apps/desktop/src/main/runtime-host-desktop-candidate.ts
- apps/desktop/src/preload/bridge-contract.d.ts
- apps/desktop/src/main/runtime-host-profile-service.ts
- apps/desktop/src/main/runtime-host-desktop-manager.ts
- apps/desktop/src/preload/preload.ts
Included review availability: Your plan includes up to 3 reviews per rolling hour; 1 remains after this review.
88a866e to
0c4ccb4
Compare
There was a problem hiding this comment.
Actionable comments posted: 2
🧹 Nitpick comments (3)
apps/desktop/src/main/__tests__/multi-host-thread-search.test.ts (1)
11-30: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winAdd the "all Hosts returned errors" case.
The two assertions cover total rejection and partial success. The remaining observable branch in
collectThreadSearchResponsesis the one where every Host fulfills with aSearchError. That branch returns the first error object, or[]when none is found. Without a test, a regression there would return an empty result list and hide the failure from the user.♻️ Suggested extra assertion
assert.deepEqual( await collectThreadSearchResponses( [Promise.reject(new Error('Host A unavailable')), Promise.resolve([RESULT])], 10, ), [RESULT], ); + + assert.deepEqual( + await collectThreadSearchResponses( + [Promise.resolve({ ok: false, reason: 'provider_error', message: 'Host A failed' })], + 10, + ), + { ok: false, reason: 'provider_error', message: 'Host A failed' }, + ); });apps/desktop/src/main/runtime-host-boot.ts (1)
676-682: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick winResolve the failing profile by ID, not by
isDefault.
resolveDesktopRuntimeHostStartupforcesdefaultProfileIdto Local when the profile catalog cannot be read. In that pathentry.isDefaultmatches the Local entry, soprofileNamedescribes Local whileprofileIdnames the unavailable remote. The fallback then shows a raw profile ID in the dialog. Matching on the profile ID is exact in every path.♻️ Proposed change
- const entry = snapshot.entries.find((candidate) => candidate.isDefault); + const entry = snapshot.entries.find( + (candidate) => + candidate.profile.id === runtimeHostStartup.preferences.defaultProfileId, + );apps/desktop/src/renderer/use-shell-connections.ts (1)
39-49: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick winRemove the render-time
currentKeymutation.Capture
snapshotKeyinsetSnapshotand usesnapshotKey !== keyin the error guard. A discarded render can otherwise change the shared ref before a callback from the committed render writes the snapshot, which can select the wrong Host bucket.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro Plus
Run ID: 62f95c1c-a4d5-4436-9fce-f748ef3fb480
📒 Files selected for processing (15)
apps/desktop/src/main/__tests__/multi-host-thread-search.test.tsapps/desktop/src/main/__tests__/runtime-host-default-recovery.test.tsapps/desktop/src/main/__tests__/runtime-host-desktop-manager.test.tsapps/desktop/src/main/__tests__/runtime-host-profile-service.test.tsapps/desktop/src/main/__tests__/use-shell-connections.test.tsapps/desktop/src/main/runtime-host-boot.tsapps/desktop/src/main/runtime-host-default-recovery.tsapps/desktop/src/main/runtime-host-desktop-manager.tsapps/desktop/src/main/runtime-host-profile-service.tsapps/desktop/src/preload/multi-host-thread-search.tsapps/desktop/src/preload/preload.tsapps/desktop/src/renderer/app-shell.tsxapps/desktop/src/renderer/use-shell-connections.tsdocs/architecture/runtime-host-architecture.mddocs/architecture/runtime-host-architecture.zh-CN.md
🚧 Files skipped from review as they are similar to previous changes (5)
- docs/architecture/runtime-host-architecture.zh-CN.md
- apps/desktop/src/main/runtime-host-profile-service.ts
- apps/desktop/src/main/runtime-host-desktop-manager.ts
- apps/desktop/src/renderer/app-shell.tsx
- apps/desktop/src/preload/preload.ts
Included review availability: Your plan includes up to 3 reviews per rolling hour; 1 remains after this review.
Keep Local and enabled remote targets independent, aggregate Sessions with stable Host-scoped identities, and route existing Session operations and Client-local resources back to their owning Host. The default Host now controls only new and otherwise unscoped work. CLI and TUI remain single-Host clients. Generated-by: OpenAI Codex
Keep startup interaction and connection data scoped to the intended Host, recover safely from corrupt Client preferences, and make Host metadata mandatory at the Desktop projection boundary. Preserve explicit unavailable defaults instead of silently moving new work to Local. Generated-by: OpenAI Codex
Separate default-Host settings from the active Session Host, and derive model, memory, readiness, diagnostics, and attachment views from the owning Host. Centralize Desktop Session identity projection so raw Host-local ids cannot leak into renderer state. Generated-by: OpenAI Codex
Restore an actionable recovery choice when the default remote Host is unavailable, while keeping other enabled Hosts usable. Preserve Host scope across reconnect diagnostics, deferred subscriptions, and connection projection changes. Generated-by: OpenAI Codex
Keep Local usable when remote profile metadata cannot be read without erasing the saved remote enablement state. Settle fire-and-forget Host projections and preserve total thread-search failures while retaining partial results. Generated-by: Codex
Make the bootstrap effect own its animation-frame callback so StrictMode cleanup cannot leave a second fixture or startup refresh running after remount. Generated-by: Codex
Keep the Local startup fallback read-only when durable Runtime Host preferences cannot be read, preventing later settings actions from replacing unknown saved configuration. Commit Host projection identity only after React accepts a render, and retain structured all-Host search failures. Generated-by: Codex
Decode active and enumerated Runtime Host identities through one metadata path so early Session creation no longer depends on cache warmup. Preserve live scopes across non-authoritative profile events and deliver scheduled-task notifications from every enabled Host. Generated-by: Codex
Wait for the search dialog to enter its native modal state before sending Escape. CSS visibility can precede showModal(), making the prior E2E assertion timing-dependent. Generated-by: Codex
Interleave per-Host thread matches before applying the global limit so one full result page cannot hide every later Host. Strengthen the connection projection regression to verify a cached Host returns without an empty frame. Generated-by: Codex
Use Local for unscoped work while the preferred default Host is not available without changing the saved default. Roll back only newly created profiles whose add flow fails before connection handling, while retaining unavailable profiles for retry. Generated-by: Codex
Treat an unreadable remote profile catalog as transient availability state rather than replacing the persisted default with Local. Local remains the effective fallback while the catalog is unavailable. Generated-by: Codex
Keep the saved default profile as the user's durable preference when its target is removed, while publishing the removal as a default-target change so stale renderer scope is discarded and Local fallback remains usable. Generated-by: Codex
Remove duplicated projection fixtures, direct mapper assertions, and render-level details already covered by stronger Host identity and isolation tests. Keep coverage focused on stable cross-Host boundaries and configuration safety. Generated-by: Codex
The localized Plan Mode copy landed on main with an import from a package root that core does not export, breaking Desktop builds and Windows recovery CI. Use the existing plan and locale entry points instead. Generated-by: Codex
Keep default-Host work, Session-owned work, and Desktop-only UI cleanup on separate routing paths. Unavailable defaults no longer silently fall back to Local, copy cleanup and Project reads retain their owning Session, and retired Hosts cannot leave an unroutable active task or Browser view behind. Preserve Desktop Session identity through renderer projections so future Host-scoped code cannot accidentally erase the routing metadata. Generated-by: Codex
f1d4049 to
c5e3943
Compare
Order Browser selection updates across asynchronous Session resolution so stale work cannot restore a hidden native view. Keep the Local Project catalog independent from the default and active remote Hosts for grouping and archived labels. Generated-by: Codex
Keep Browser selection valid across Host reconnects and renderer reloads, and funnel default Project context through one latest-wins snapshot authority. Local Project row actions remain unavailable when another Host is the default, avoiding cross-catalog mutations until explicit Host selection lands.\n\nGenerated-by: Codex
|
I have manually verified the current revision and consider it to have reached a usable standard for the intended scope of this PR. There are currently no existing remote Runtime Host users whose established workflow could be regressed by this change. The rollout impact is therefore controlled, while the existing local Runtime Host path remains the supported baseline. Posted by Codex on behalf of the maintainer. |

English
Summary
(Host, Session)identity and routing every existing Session action, event, diagnostic, Browser, and Computer Use resource back to its ownerRefs #2522
Verification
npm test -w @maka/desktop— 862 passednpm test -w @maka/ui— 167 passedgit diff --checkpassed中文
摘要
(Host, Session)身份隔离同 ID Session,并将已有 Session 的操作、事件、诊断、Browser 与 Computer Use 资源严格路由回所属 Host关联 #2522
验证
npm test -w @maka/desktop— 862 项通过npm test -w @maka/ui— 167 项通过git diff --check均通过AI use
Tool(s) and scope: OpenAI Codex assisted with implementation, tests, documentation, and validation. The commit includes the required
Generated-bytrailer.Checklist
Does this PR entail a change in behavior?