Skip to content

Commit c5815c2

Browse files
committed
Add marimo.restartKernel command
Adds the ability to restart an active marimo kernel from both the UI and quick action.
1 parent c0502b2 commit c5815c2

File tree

6 files changed

+98
-4
lines changed

6 files changed

+98
-4
lines changed

extension/package.json

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,12 @@
156156
"shortTitle": "On cell change: Lazy",
157157
"category": "marimo",
158158
"icon": "$(symbol-interface)"
159+
},
160+
{
161+
"command": "marimo.restartKernel",
162+
"title": "Restart Notebook Kernel",
163+
"shortTitle": "Restart Kernel",
164+
"category": "marimo"
159165
}
160166
],
161167
"viewsContainers": {
@@ -216,15 +222,20 @@
216222
"when": "notebookType == 'marimo-notebook' && marimo.notebook.hasStaleCells",
217223
"group": "navigation@1"
218224
},
225+
{
226+
"command": "marimo.restartKernel",
227+
"when": "notebookType == 'marimo-notebook'",
228+
"group": "navigation@2"
229+
},
219230
{
220231
"command": "marimo.toggleOnCellChangeAutoRun",
221232
"when": "notebookType == 'marimo-notebook' && marimo.config.runtime.on_cell_change != 'lazy'",
222-
"group": "navigation@2"
233+
"group": "navigation@3"
223234
},
224235
{
225236
"command": "marimo.toggleOnCellChangeLazy",
226237
"when": "notebookType == 'marimo-notebook' && marimo.config.runtime.on_cell_change == 'lazy'",
227-
"group": "navigation@2"
238+
"group": "navigation@3"
228239
}
229240
]
230241
}

extension/src/constants.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ export type MarimoCommand =
77
| "marimo.publishMarimoNotebook"
88
| "marimo.publishMarimoNotebookGist"
99
| "marimo.refreshPackages"
10+
| "marimo.restartKernel"
1011
| "marimo.runStale"
1112
| "marimo.showMarimoMenu"
1213
| "marimo.toggleOnCellChangeAutoRun"
@@ -21,5 +22,5 @@ export type MarimoView =
2122
export const NOTEBOOK_TYPE = "marimo-notebook";
2223

2324
export type MarimoContextKey =
24-
| "marimo.notebook.hasStaleCells"
25-
| "marimo.config.runtime.on_cell_change";
25+
| "marimo.config.runtime.on_cell_change"
26+
| "marimo.notebook.hasStaleCells";

extension/src/layers/RegisterCommands.ts

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,9 @@ import { Cause, Chunk, Effect, Either, Layer, Option } from "effect";
33
import { decodeCellMetadata, isStaleCellMetadata } from "../schemas.ts";
44
import { ConfigContextManager } from "../services/config/ConfigContextManager.ts";
55
import { MarimoConfigurationService } from "../services/config/MarimoConfigurationService.ts";
6+
import { ExecutionRegistry } from "../services/ExecutionRegistry.ts";
67
import { GitHubClient } from "../services/GitHubClient.ts";
8+
import { LanguageClient } from "../services/LanguageClient.ts";
79
import { NotebookSerializer } from "../services/NotebookSerializer.ts";
810
import { OutputChannel } from "../services/OutputChannel.ts";
911
import { VsCode } from "../services/VsCode.ts";
@@ -17,10 +19,12 @@ export const RegisterCommandsLive = Layer.scopedDiscard(
1719
Effect.gen(function* () {
1820
const gh = yield* GitHubClient;
1921
const code = yield* VsCode;
22+
const client = yield* LanguageClient;
2023
const channel = yield* OutputChannel;
2124
const serializer = yield* NotebookSerializer;
2225
const configService = yield* MarimoConfigurationService;
2326
const configContextManager = yield* ConfigContextManager;
27+
const executions = yield* ExecutionRegistry;
2428

2529
yield* code.commands.registerCommand(
2630
"marimo.newMarimoNotebook",
@@ -78,6 +82,61 @@ export const RegisterCommandsLive = Layer.scopedDiscard(
7882
configContextManager,
7983
}),
8084
);
85+
86+
yield* code.commands.registerCommand(
87+
"marimo.restartKernel",
88+
Effect.gen(function* () {
89+
const editor = yield* code.window.getActiveNotebookEditor();
90+
if (Option.isNone(editor)) {
91+
yield* code.window.showInformationMessage(
92+
"No marimo notebook is currently open",
93+
);
94+
return;
95+
}
96+
97+
yield* code.window.withProgress(
98+
{
99+
location: code.ProgressLocation.Window,
100+
title: "Restarting kernel",
101+
cancellable: true,
102+
},
103+
Effect.fnUntraced(function* (progress) {
104+
progress.report({ message: "Closing session..." });
105+
106+
const result = yield* client
107+
.executeCommand({
108+
command: "marimo.api",
109+
params: {
110+
method: "close_session",
111+
params: {
112+
notebookUri: getNotebookUri(editor.value.notebook),
113+
inner: {},
114+
},
115+
},
116+
})
117+
.pipe(Effect.either);
118+
119+
if (Either.isLeft(result)) {
120+
yield* Effect.logFatal("Failed to restart kernel", result.left);
121+
yield* showErrorAndPromptLogs("Failed to restart kernel.", {
122+
channel,
123+
code,
124+
});
125+
return;
126+
}
127+
128+
yield* executions.handleInterrupted(editor.value);
129+
130+
progress.report({ message: "Kernel restarted." });
131+
yield* Effect.sleep("500 millis");
132+
}),
133+
);
134+
135+
yield* code.window.showInformationMessage(
136+
"Kernel restarted successfully",
137+
);
138+
}),
139+
);
81140
}),
82141
);
83142

extension/src/types.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,9 @@ type ListPackagesRequest = {};
6464
type DependencyTreeRequest = {};
6565
// biome-ignore lint/complexity/noBannedTypes: We need this for over the wire
6666
type GetConfigurationRequest = {};
67+
// biome-ignore lint/complexity/noBannedTypes: We need this for over the wire
68+
type CloseSessionRequest = {};
69+
6770
interface UpdateConfigurationRequest {
6871
config: Record<string, unknown>;
6972
}
@@ -81,6 +84,7 @@ type MarimoApiMethodMap = {
8184
get_dependency_tree: SessionScoped<DependencyTreeRequest>;
8285
get_configuration: NotebookScoped<GetConfigurationRequest>;
8386
update_configuration: NotebookScoped<UpdateConfigurationRequest>;
87+
close_session: NotebookScoped<CloseSessionRequest>;
8488
};
8589

8690
type ApiRequest<K extends keyof MarimoApiMethodMap> = {

src/marimo_lsp/api.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
from marimo_lsp.debug_adapter import handle_debug_adapter_request
1717
from marimo_lsp.loggers import get_logger
1818
from marimo_lsp.models import (
19+
CloseSessionRequest,
1920
DebugAdapterRequest,
2021
DependencyTreeRequest,
2122
DeserializeRequest,
@@ -111,6 +112,14 @@ async def interrupt(
111112
logger.warning(f"No session found for {args.notebook_uri}")
112113

113114

115+
async def close_session(
116+
manager: LspSessionManager,
117+
args: NotebookCommand[CloseSessionRequest],
118+
):
119+
logger.info(f"close_session for {args.notebook_uri}")
120+
manager.close_session(args.notebook_uri)
121+
122+
114123
async def get_package_list(
115124
manager: LspSessionManager,
116125
args: SessionCommand[ListPackagesRequest],
@@ -258,6 +267,12 @@ async def handle_api_command( # noqa: C901, PLR0911
258267
msgspec.convert(params, type=NotebookCommand[DebugAdapterRequest]),
259268
)
260269

270+
if method == "close_session":
271+
return await close_session(
272+
manager,
273+
msgspec.convert(params, type=NotebookCommand[CloseSessionRequest]),
274+
)
275+
261276
if method == "serialize":
262277
return await serialize(msgspec.convert(params, type=SerializeRequest))
263278

src/marimo_lsp/models.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,10 @@ class GetConfigurationRequest(msgspec.Struct, rename="camel"):
8888
"""A request to get the current configuration."""
8989

9090

91+
class CloseSessionRequest(msgspec.Struct, rename="camel"):
92+
"""A request to close the current session."""
93+
94+
9195
class UpdateConfigurationRequest(msgspec.Struct, rename="camel"):
9296
"""A request to update the user configuration."""
9397

0 commit comments

Comments
 (0)