From f3482cac1e59e55e0e182be7b41c069ac7ef0d04 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 27 Oct 2025 07:08:41 +0000 Subject: [PATCH 1/6] Initial plan From 9ce1e57e629b6e98ef8d898090aa8de957392a34 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 27 Oct 2025 07:16:31 +0000 Subject: [PATCH 2/6] Add Restart and Force Rebuild menu items to Tsunami view Co-authored-by: sawka <2722291+sawka@users.noreply.github.com> --- frontend/app/view/tsunami/tsunami.tsx | 46 ++++++++++++++++++++++++++- 1 file changed, 45 insertions(+), 1 deletion(-) diff --git a/frontend/app/view/tsunami/tsunami.tsx b/frontend/app/view/tsunami/tsunami.tsx index 42d22181aa..724b57cb2a 100644 --- a/frontend/app/view/tsunami/tsunami.tsx +++ b/frontend/app/view/tsunami/tsunami.tsx @@ -81,7 +81,34 @@ class TsunamiViewModel extends WebViewModel { prtn.catch((e) => console.log("error controller resync", e)); } + restartController() { + if (globalStore.get(this.isRestarting)) { + return; + } + this.triggerRestartAtom(); + const prtn = RpcApi.ControllerResyncCommand(TabRpcClient, { + tabid: globalStore.get(atoms.staticTabId), + blockid: this.blockId, + forcerestart: false, + }); + prtn.catch((e) => console.log("error controller resync (restart)", e)); + } + + restartAndForceRebuild() { + if (globalStore.get(this.isRestarting)) { + return; + } + this.triggerRestartAtom(); + const prtn = RpcApi.ControllerResyncCommand(TabRpcClient, { + tabid: globalStore.get(atoms.staticTabId), + blockid: this.blockId, + forcerestart: true, + }); + prtn.catch((e) => console.log("error controller resync (force rebuild)", e)); + } + forceRestartController() { + // Keep this for backward compatibility with the Start button if (globalStore.get(this.isRestarting)) { return; } @@ -125,7 +152,7 @@ class TsunamiViewModel extends WebViewModel { getSettingsMenuItems(): ContextMenuItem[] { const items = super.getSettingsMenuItems(); // Filter out homepage and navigation-related menu items for tsunami view - return items.filter((item) => { + const filteredItems = items.filter((item) => { const label = item.label?.toLowerCase() || ""; return ( !label.includes("homepage") && @@ -134,6 +161,23 @@ class TsunamiViewModel extends WebViewModel { !label.includes("nav") ); }); + + // Add tsunami-specific menu items at the beginning + const tsunamiItems: ContextMenuItem[] = [ + { + label: "Restart", + click: () => this.restartController(), + }, + { + label: "Restart and Force Rebuild", + click: () => this.restartAndForceRebuild(), + }, + { + type: "separator", + }, + ]; + + return [...tsunamiItems, ...filteredItems]; } } From de006621c6e37eaf30a538a49569fc0638ebfb6b Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 27 Oct 2025 07:20:16 +0000 Subject: [PATCH 3/6] Refactor to reduce code duplication in controller resync methods Co-authored-by: sawka <2722291+sawka@users.noreply.github.com> --- frontend/app/view/tsunami/tsunami.tsx | 32 ++++++++------------------- 1 file changed, 9 insertions(+), 23 deletions(-) diff --git a/frontend/app/view/tsunami/tsunami.tsx b/frontend/app/view/tsunami/tsunami.tsx index 724b57cb2a..ea2381d734 100644 --- a/frontend/app/view/tsunami/tsunami.tsx +++ b/frontend/app/view/tsunami/tsunami.tsx @@ -81,7 +81,7 @@ class TsunamiViewModel extends WebViewModel { prtn.catch((e) => console.log("error controller resync", e)); } - restartController() { + private doControllerResync(forceRestart: boolean, logContext: string) { if (globalStore.get(this.isRestarting)) { return; } @@ -89,36 +89,22 @@ class TsunamiViewModel extends WebViewModel { const prtn = RpcApi.ControllerResyncCommand(TabRpcClient, { tabid: globalStore.get(atoms.staticTabId), blockid: this.blockId, - forcerestart: false, + forcerestart: forceRestart, }); - prtn.catch((e) => console.log("error controller resync (restart)", e)); + prtn.catch((e) => console.log(`error controller resync (${logContext})`, e)); + } + + restartController() { + this.doControllerResync(false, "restart"); } restartAndForceRebuild() { - if (globalStore.get(this.isRestarting)) { - return; - } - this.triggerRestartAtom(); - const prtn = RpcApi.ControllerResyncCommand(TabRpcClient, { - tabid: globalStore.get(atoms.staticTabId), - blockid: this.blockId, - forcerestart: true, - }); - prtn.catch((e) => console.log("error controller resync (force rebuild)", e)); + this.doControllerResync(true, "force rebuild"); } forceRestartController() { // Keep this for backward compatibility with the Start button - if (globalStore.get(this.isRestarting)) { - return; - } - this.triggerRestartAtom(); - const prtn = RpcApi.ControllerResyncCommand(TabRpcClient, { - tabid: globalStore.get(atoms.staticTabId), - blockid: this.blockId, - forcerestart: true, - }); - prtn.catch((e) => console.log("error controller resync (force restart)", e)); + this.doControllerResync(true, "force restart"); } setAppMeta(meta: TsunamiAppMeta) { From cd01857fde78b8df24209db272861859ecd4ebca Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 27 Oct 2025 07:22:37 +0000 Subject: [PATCH 4/6] Further refactor resyncController to use common helper method Co-authored-by: sawka <2722291+sawka@users.noreply.github.com> --- frontend/app/view/tsunami/tsunami.tsx | 23 ++++++++++------------- 1 file changed, 10 insertions(+), 13 deletions(-) diff --git a/frontend/app/view/tsunami/tsunami.tsx b/frontend/app/view/tsunami/tsunami.tsx index ea2381d734..65099e3f3c 100644 --- a/frontend/app/view/tsunami/tsunami.tsx +++ b/frontend/app/view/tsunami/tsunami.tsx @@ -72,20 +72,13 @@ class TsunamiViewModel extends WebViewModel { }, 300); } - resyncController() { - const prtn = RpcApi.ControllerResyncCommand(TabRpcClient, { - tabid: globalStore.get(atoms.staticTabId), - blockid: this.blockId, - forcerestart: false, - }); - prtn.catch((e) => console.log("error controller resync", e)); - } - - private doControllerResync(forceRestart: boolean, logContext: string) { - if (globalStore.get(this.isRestarting)) { - return; + private doControllerResync(forceRestart: boolean, logContext: string, triggerRestart: boolean = true) { + if (triggerRestart) { + if (globalStore.get(this.isRestarting)) { + return; + } + this.triggerRestartAtom(); } - this.triggerRestartAtom(); const prtn = RpcApi.ControllerResyncCommand(TabRpcClient, { tabid: globalStore.get(atoms.staticTabId), blockid: this.blockId, @@ -94,6 +87,10 @@ class TsunamiViewModel extends WebViewModel { prtn.catch((e) => console.log(`error controller resync (${logContext})`, e)); } + resyncController() { + this.doControllerResync(false, "resync", false); + } + restartController() { this.doControllerResync(false, "restart"); } From f889657d131f3014ca89b6d61bb8b94f8aafd7a3 Mon Sep 17 00:00:00 2001 From: sawka Date: Mon, 27 Oct 2025 10:25:15 -0700 Subject: [PATCH 5/6] add WaveApp to labels --- frontend/app/view/tsunami/tsunami.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/frontend/app/view/tsunami/tsunami.tsx b/frontend/app/view/tsunami/tsunami.tsx index 65099e3f3c..c884920d6b 100644 --- a/frontend/app/view/tsunami/tsunami.tsx +++ b/frontend/app/view/tsunami/tsunami.tsx @@ -148,11 +148,11 @@ class TsunamiViewModel extends WebViewModel { // Add tsunami-specific menu items at the beginning const tsunamiItems: ContextMenuItem[] = [ { - label: "Restart", + label: "Restart WaveApp", click: () => this.restartController(), }, { - label: "Restart and Force Rebuild", + label: "Restart WaveApp and Force Rebuild", click: () => this.restartAndForceRebuild(), }, { From 9cee89ac5d457c5731d607e395200c76092c01d5 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 27 Oct 2025 17:34:41 +0000 Subject: [PATCH 6/6] Add Stop WaveApp menu item and implement proper restart logic Co-authored-by: sawka <2722291+sawka@users.noreply.github.com> --- frontend/app/view/tsunami/tsunami.tsx | 30 +++++++++++++++++++++++++-- 1 file changed, 28 insertions(+), 2 deletions(-) diff --git a/frontend/app/view/tsunami/tsunami.tsx b/frontend/app/view/tsunami/tsunami.tsx index c884920d6b..05f715b7ba 100644 --- a/frontend/app/view/tsunami/tsunami.tsx +++ b/frontend/app/view/tsunami/tsunami.tsx @@ -91,8 +91,30 @@ class TsunamiViewModel extends WebViewModel { this.doControllerResync(false, "resync", false); } - restartController() { - this.doControllerResync(false, "restart"); + stopController() { + const prtn = RpcApi.ControllerStopCommand(TabRpcClient, this.blockId); + prtn.catch((e) => console.log("error stopping controller", e)); + } + + async restartController() { + if (globalStore.get(this.isRestarting)) { + return; + } + this.triggerRestartAtom(); + try { + // Stop the controller first + await RpcApi.ControllerStopCommand(TabRpcClient, this.blockId); + // Wait a bit for the controller to fully stop + await new Promise((resolve) => setTimeout(resolve, 300)); + // Then resync to restart it + await RpcApi.ControllerResyncCommand(TabRpcClient, { + tabid: globalStore.get(atoms.staticTabId), + blockid: this.blockId, + forcerestart: false, + }); + } catch (e) { + console.log("error restarting controller", e); + } } restartAndForceRebuild() { @@ -147,6 +169,10 @@ class TsunamiViewModel extends WebViewModel { // Add tsunami-specific menu items at the beginning const tsunamiItems: ContextMenuItem[] = [ + { + label: "Stop WaveApp", + click: () => this.stopController(), + }, { label: "Restart WaveApp", click: () => this.restartController(),