Move per-session permission auto-accept policy ownership from the UI to the OpenChamber server so enabled sessions continue running when clients disconnect or the server restarts. - persist explicit per-session policies in OpenChamber settings - inherit the nearest explicit policy across subagent session hierarchies - allow child sessions to opt out of an inherited parent policy - immediately accept matching global and directory-scoped pending requests - process future requests without requiring a connected UI client - reconcile pending permissions after startup and event-stream reconnects - deduplicate concurrent requests and retry transient reply failures - synchronize policy updates across connected clients - migrate existing browser-persisted policies to server storage - suppress auto-accepted permission cards before they enter UI state - show deduplicated permission toasts for inactive sessions - preserve foreground-only permission handling in VS Code - integrate directory-aware notification routing from main - add coverage for persistence, inheritance, retries, reconciliation, pending requests, client hydration, and inactive-session toasts
52 lines
2.5 KiB
TypeScript
52 lines
2.5 KiB
TypeScript
import { opencodeClient } from '@/lib/opencode/client';
|
|
import type { RuntimeEndpointChangedDetail } from '@/lib/runtime-switch';
|
|
import { disposeTerminalInputTransport } from '@/lib/terminalApi';
|
|
import { useConfigStore } from '@/stores/useConfigStore';
|
|
import { useProjectsStore } from '@/stores/useProjectsStore';
|
|
import { useGlobalSessionsStore } from '@/stores/useGlobalSessionsStore';
|
|
import { useAutoReviewStore } from '@/stores/useAutoReviewStore';
|
|
import { useUIStore } from '@/stores/useUIStore';
|
|
import { usePermissionStore } from '@/stores/permissionStore';
|
|
import { useSessionUIStore } from '@/sync/session-ui-store';
|
|
import { resetStreamingState } from '@/sync/streaming';
|
|
|
|
// Same-device transport switch (LAN⇄relay for one paired device): rebind the SDK
|
|
// to the new transport WITHOUT tearing down connection/session state or remounting
|
|
// the sync layer. `reconnectToRuntimeBaseUrl` swaps in a fresh SDK client; the
|
|
// caller then forces a re-render so SyncProvider receives it as a new `sdk` prop,
|
|
// which re-runs its event-pipeline + bootstrap effects (keyed on `sdk`) to
|
|
// reconnect over the new transport IN PLACE. Message-pagination refs, the open
|
|
// session, and the whole view are preserved — no reconnecting screen, no flash,
|
|
// no bounce back to the draft.
|
|
export const reconnectAppForTransportSwitch = (): void => {
|
|
disposeTerminalInputTransport();
|
|
opencodeClient.reconnectToRuntimeBaseUrl();
|
|
resetStreamingState();
|
|
};
|
|
|
|
export const resetAppForRuntimeEndpointChange = (detail: RuntimeEndpointChangedDetail): void => {
|
|
useSessionUIStore.getState().prepareForRuntimeSwitch(detail.previousRuntimeKey);
|
|
useUIStore.getState().prepareForRuntimeSwitch(detail.previousRuntimeKey);
|
|
if (detail.previousRuntimeKey) {
|
|
useAutoReviewStore.getState().stopRunningRunsForRuntime(detail.previousRuntimeKey);
|
|
}
|
|
disposeTerminalInputTransport();
|
|
opencodeClient.reconnectToRuntimeBaseUrl();
|
|
useConfigStore.setState({
|
|
providers: [],
|
|
agents: [],
|
|
isConnected: false,
|
|
isInitialized: false,
|
|
connectionPhase: 'connecting',
|
|
lastDisconnectReason: null,
|
|
});
|
|
useProjectsStore.getState().resetForRuntimeSwitch();
|
|
// Cross-project session list (mobile sessions sheet & co) belongs to the
|
|
// previous instance — drop it so stale sessions can't linger after a switch.
|
|
useGlobalSessionsStore.getState().resetForRuntimeSwitch();
|
|
usePermissionStore.getState().reset();
|
|
useSessionUIStore.getState().restoreForRuntimeSwitch(detail.runtimeKey);
|
|
useUIStore.getState().restoreForRuntimeSwitch(detail.runtimeKey);
|
|
resetStreamingState();
|
|
};
|