mrmd-editor 0.6.0 → 0.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/src/cell-controls/widgets.js +30 -0
- package/src/cells.js +9 -9
- package/src/ctrl-k-modal.js +190 -14
- package/src/document-languages.js +105 -0
- package/src/execution.js +4 -10
- package/src/frontmatter-updater.js +224 -0
- package/src/index.js +127 -86
- package/src/markdown/renderer.js +52 -3
- package/src/markdown/styles.js +126 -0
- package/src/monitor-coordination.js +1 -3
- package/src/mrp-client.js +36 -169
- package/src/mrp-types.js +1 -37
- package/src/output-widget.js +54 -0
- package/src/runtime-codelens/index.js +3 -3
- package/src/shell/ai-menu.js +70 -0
- package/src/shell/components/menu.js +39 -1
- package/src/shell/components/status-bar.js +5 -5
- package/src/shell/dialogs/file-picker.js +167 -6
- package/src/shell/layouts/studio.js +8 -9
- package/src/shell/orchestrator-client.js +60 -18
- package/src/shell/state.js +63 -42
- package/src/shell/styles.js +266 -0
package/src/markdown/styles.js
CHANGED
|
@@ -1015,6 +1015,132 @@ export const markdownStyles = `
|
|
|
1015
1015
|
.cm-inline-html bdo {
|
|
1016
1016
|
unicode-bidi: bidi-override;
|
|
1017
1017
|
}
|
|
1018
|
+
|
|
1019
|
+
/* ==========================================================================
|
|
1020
|
+
MOBILE RESPONSIVE
|
|
1021
|
+
|
|
1022
|
+
Quarto/Astro-inspired: content reads beautifully on narrow screens.
|
|
1023
|
+
Tables scroll horizontally, images scale, code wraps or scrolls.
|
|
1024
|
+
========================================================================== */
|
|
1025
|
+
|
|
1026
|
+
@media (max-width: 768px) {
|
|
1027
|
+
|
|
1028
|
+
/* Tables: horizontal scroll when they're wider than the viewport.
|
|
1029
|
+
This is the exact pattern Quarto and MkDocs Material use. */
|
|
1030
|
+
.cm-table-widget {
|
|
1031
|
+
overflow-x: auto;
|
|
1032
|
+
-webkit-overflow-scrolling: touch;
|
|
1033
|
+
margin-left: -4px;
|
|
1034
|
+
margin-right: -4px;
|
|
1035
|
+
padding-left: 4px;
|
|
1036
|
+
padding-right: 4px;
|
|
1037
|
+
}
|
|
1038
|
+
|
|
1039
|
+
/* Subtle fade on the right edge when table overflows */
|
|
1040
|
+
.cm-table-widget::after {
|
|
1041
|
+
content: '';
|
|
1042
|
+
position: sticky;
|
|
1043
|
+
right: 0;
|
|
1044
|
+
display: block;
|
|
1045
|
+
width: 16px;
|
|
1046
|
+
margin-top: -100%;
|
|
1047
|
+
height: 100%;
|
|
1048
|
+
background: linear-gradient(to right, transparent, var(--editor-background, #fff) 80%);
|
|
1049
|
+
pointer-events: none;
|
|
1050
|
+
float: right;
|
|
1051
|
+
opacity: 0.5;
|
|
1052
|
+
}
|
|
1053
|
+
|
|
1054
|
+
.cm-table {
|
|
1055
|
+
font-size: 0.88em;
|
|
1056
|
+
}
|
|
1057
|
+
|
|
1058
|
+
.cm-table th,
|
|
1059
|
+
.cm-table td {
|
|
1060
|
+
padding: 0.4em 0.65em;
|
|
1061
|
+
white-space: nowrap;
|
|
1062
|
+
}
|
|
1063
|
+
|
|
1064
|
+
/* Images: full-width, never overflow the screen */
|
|
1065
|
+
.cm-image-block-img {
|
|
1066
|
+
max-width: 100%;
|
|
1067
|
+
max-height: 50vh;
|
|
1068
|
+
}
|
|
1069
|
+
|
|
1070
|
+
.cm-image-inline-img {
|
|
1071
|
+
max-width: 100%;
|
|
1072
|
+
}
|
|
1073
|
+
|
|
1074
|
+
/* Wide images: don't break out of viewport */
|
|
1075
|
+
.cm-image-pos-wide {
|
|
1076
|
+
width: 100%;
|
|
1077
|
+
max-width: 100%;
|
|
1078
|
+
margin-left: 0;
|
|
1079
|
+
margin-right: 0;
|
|
1080
|
+
}
|
|
1081
|
+
|
|
1082
|
+
.cm-image-pos-wide .cm-image-block-img {
|
|
1083
|
+
max-width: 100%;
|
|
1084
|
+
}
|
|
1085
|
+
|
|
1086
|
+
/* Right/left aligned images: go full width on mobile */
|
|
1087
|
+
.cm-image-pos-right,
|
|
1088
|
+
.cm-image-pos-left {
|
|
1089
|
+
text-align: center;
|
|
1090
|
+
padding-left: 0;
|
|
1091
|
+
padding-right: 0;
|
|
1092
|
+
}
|
|
1093
|
+
|
|
1094
|
+
.cm-image-pos-right .cm-image-block-img,
|
|
1095
|
+
.cm-image-pos-left .cm-image-block-img {
|
|
1096
|
+
max-width: 100%;
|
|
1097
|
+
}
|
|
1098
|
+
|
|
1099
|
+
/* Display math: horizontal scroll for wide equations */
|
|
1100
|
+
.cm-math-display {
|
|
1101
|
+
overflow-x: auto;
|
|
1102
|
+
-webkit-overflow-scrolling: touch;
|
|
1103
|
+
}
|
|
1104
|
+
|
|
1105
|
+
/* Blockquotes: slightly tighter */
|
|
1106
|
+
.cm-md-blockquote-line {
|
|
1107
|
+
padding-left: 0.75em;
|
|
1108
|
+
}
|
|
1109
|
+
|
|
1110
|
+
/* Headings: slightly smaller on mobile for better fit */
|
|
1111
|
+
.cm-md-h1 {
|
|
1112
|
+
font-size: clamp(1.4em, 5vw, var(--md-heading-1-size, 1.75em));
|
|
1113
|
+
}
|
|
1114
|
+
|
|
1115
|
+
.cm-md-h2 {
|
|
1116
|
+
font-size: clamp(1.2em, 4vw, var(--md-heading-2-size, 1.4em));
|
|
1117
|
+
}
|
|
1118
|
+
|
|
1119
|
+
/* Horizontal rule: full width */
|
|
1120
|
+
.cm-md-hr-line::after {
|
|
1121
|
+
left: 0;
|
|
1122
|
+
right: 0;
|
|
1123
|
+
}
|
|
1124
|
+
}
|
|
1125
|
+
|
|
1126
|
+
/* Touch-specific: make interactive elements more tappable */
|
|
1127
|
+
@media (pointer: coarse) {
|
|
1128
|
+
|
|
1129
|
+
/* Checkboxes: bigger for finger tapping */
|
|
1130
|
+
.cm-task-checkbox {
|
|
1131
|
+
width: 1.2em;
|
|
1132
|
+
height: 1.2em;
|
|
1133
|
+
margin-right: 0.5em;
|
|
1134
|
+
}
|
|
1135
|
+
|
|
1136
|
+
/* Links: slightly more padding to enlarge tap area */
|
|
1137
|
+
.cm-md-link-text,
|
|
1138
|
+
.cm-external-link,
|
|
1139
|
+
.cm-file-link,
|
|
1140
|
+
.cm-wiki-link {
|
|
1141
|
+
padding: 2px 0;
|
|
1142
|
+
}
|
|
1143
|
+
}
|
|
1018
1144
|
`;
|
|
1019
1145
|
|
|
1020
1146
|
/**
|
|
@@ -99,11 +99,10 @@ export class MonitorCoordination {
|
|
|
99
99
|
* @param {string} options.code - Code to execute
|
|
100
100
|
* @param {string} options.language - Language identifier
|
|
101
101
|
* @param {string} options.runtimeUrl - MRP runtime URL
|
|
102
|
-
* @param {string} [options.session] - MRP session ID
|
|
103
102
|
* @param {string} [options.cellId] - Cell ID for tracking
|
|
104
103
|
* @returns {string} execId
|
|
105
104
|
*/
|
|
106
|
-
requestExecution({ code, language, runtimeUrl,
|
|
105
|
+
requestExecution({ code, language, runtimeUrl, cellId }) {
|
|
107
106
|
const execId = MonitorCoordination.generateExecId();
|
|
108
107
|
|
|
109
108
|
this.executions.set(execId, {
|
|
@@ -112,7 +111,6 @@ export class MonitorCoordination {
|
|
|
112
111
|
code,
|
|
113
112
|
language,
|
|
114
113
|
runtimeUrl,
|
|
115
|
-
session,
|
|
116
114
|
status: EXECUTION_STATUS.REQUESTED,
|
|
117
115
|
requestedBy: this.clientId,
|
|
118
116
|
requestedAt: Date.now(),
|
package/src/mrp-client.js
CHANGED
|
@@ -3,12 +3,14 @@
|
|
|
3
3
|
*
|
|
4
4
|
* Connects mrmd-editor to any MRMD Runtime Protocol server.
|
|
5
5
|
*
|
|
6
|
+
* Runtime model (simplified): one runtime process = one REPL namespace.
|
|
7
|
+
* There are no client-managed MRP sessions.
|
|
8
|
+
*
|
|
6
9
|
* @module mrp-client
|
|
7
10
|
*/
|
|
8
11
|
|
|
9
12
|
// JSDoc imports for type hints
|
|
10
13
|
/** @typedef {import('./mrp-types.js').Capabilities} Capabilities */
|
|
11
|
-
/** @typedef {import('./mrp-types.js').Session} Session */
|
|
12
14
|
/** @typedef {import('./mrp-types.js').ExecuteRequest} ExecuteRequest */
|
|
13
15
|
/** @typedef {import('./mrp-types.js').ExecuteResult} ExecuteResult */
|
|
14
16
|
/** @typedef {import('./mrp-types.js').CompleteRequest} CompleteRequest */
|
|
@@ -34,9 +36,6 @@ export class MRPClient {
|
|
|
34
36
|
/** @type {string} */
|
|
35
37
|
#endpoint;
|
|
36
38
|
|
|
37
|
-
/** @type {string} */
|
|
38
|
-
#defaultSession;
|
|
39
|
-
|
|
40
39
|
/** @type {Capabilities|null} */
|
|
41
40
|
#capabilities = null;
|
|
42
41
|
|
|
@@ -54,13 +53,11 @@ export class MRPClient {
|
|
|
54
53
|
*
|
|
55
54
|
* @param {string} endpoint - Base URL for MRP endpoints (e.g., "http://localhost:8000/mrp/v1")
|
|
56
55
|
* @param {Object} [options]
|
|
57
|
-
* @param {string} [options.session='default'] - Default session ID
|
|
58
56
|
* @param {string[]} [options.languages] - Fallback languages if capabilities haven't loaded yet
|
|
59
57
|
* @param {boolean} [options.prefetch=true] - Auto-fetch capabilities on construction
|
|
60
58
|
*/
|
|
61
59
|
constructor(endpoint, options = {}) {
|
|
62
60
|
this.#endpoint = endpoint.replace(/\/$/, ''); // Remove trailing slash
|
|
63
|
-
this.#defaultSession = options.session || 'default';
|
|
64
61
|
this.#fallbackLanguages = options.languages || null;
|
|
65
62
|
|
|
66
63
|
// Expose runtime URL for ExecutionManager to use in monitor mode routing
|
|
@@ -157,79 +154,6 @@ export class MRPClient {
|
|
|
157
154
|
return this.#capabilities?.features?.[feature] ?? false;
|
|
158
155
|
}
|
|
159
156
|
|
|
160
|
-
// ===========================================================================
|
|
161
|
-
// Sessions
|
|
162
|
-
// ===========================================================================
|
|
163
|
-
|
|
164
|
-
/**
|
|
165
|
-
* List active sessions
|
|
166
|
-
*
|
|
167
|
-
* @returns {Promise<Session[]>}
|
|
168
|
-
*/
|
|
169
|
-
async listSessions() {
|
|
170
|
-
const res = await fetch(`${this.#endpoint}/sessions`);
|
|
171
|
-
if (!res.ok) throw new Error(`Failed to list sessions: ${res.status}`);
|
|
172
|
-
const data = await res.json();
|
|
173
|
-
return data.sessions;
|
|
174
|
-
}
|
|
175
|
-
|
|
176
|
-
/**
|
|
177
|
-
* Create a new session
|
|
178
|
-
*
|
|
179
|
-
* @param {import('./mrp-types.js').CreateSessionRequest} request
|
|
180
|
-
* @returns {Promise<Session>}
|
|
181
|
-
*/
|
|
182
|
-
async createSession(request) {
|
|
183
|
-
const res = await fetch(`${this.#endpoint}/sessions`, {
|
|
184
|
-
method: 'POST',
|
|
185
|
-
headers: { 'Content-Type': 'application/json' },
|
|
186
|
-
body: JSON.stringify(request),
|
|
187
|
-
});
|
|
188
|
-
if (!res.ok) throw new Error(`Failed to create session: ${res.status}`);
|
|
189
|
-
return res.json();
|
|
190
|
-
}
|
|
191
|
-
|
|
192
|
-
/**
|
|
193
|
-
* Get session info
|
|
194
|
-
*
|
|
195
|
-
* @param {string} [session]
|
|
196
|
-
* @returns {Promise<Session>}
|
|
197
|
-
*/
|
|
198
|
-
async getSession(session) {
|
|
199
|
-
const sid = session || this.#defaultSession;
|
|
200
|
-
const res = await fetch(`${this.#endpoint}/sessions/${encodeURIComponent(sid)}`);
|
|
201
|
-
if (!res.ok) throw new Error(`Failed to get session: ${res.status}`);
|
|
202
|
-
return res.json();
|
|
203
|
-
}
|
|
204
|
-
|
|
205
|
-
/**
|
|
206
|
-
* Destroy a session
|
|
207
|
-
*
|
|
208
|
-
* @param {string} [session]
|
|
209
|
-
* @returns {Promise<void>}
|
|
210
|
-
*/
|
|
211
|
-
async destroySession(session) {
|
|
212
|
-
const sid = session || this.#defaultSession;
|
|
213
|
-
const res = await fetch(`${this.#endpoint}/sessions/${encodeURIComponent(sid)}`, {
|
|
214
|
-
method: 'DELETE',
|
|
215
|
-
});
|
|
216
|
-
if (!res.ok) throw new Error(`Failed to destroy session: ${res.status}`);
|
|
217
|
-
}
|
|
218
|
-
|
|
219
|
-
/**
|
|
220
|
-
* Reset session (clear namespace)
|
|
221
|
-
*
|
|
222
|
-
* @param {string} [session]
|
|
223
|
-
* @returns {Promise<void>}
|
|
224
|
-
*/
|
|
225
|
-
async reset(session) {
|
|
226
|
-
const sid = session || this.#defaultSession;
|
|
227
|
-
const res = await fetch(`${this.#endpoint}/sessions/${encodeURIComponent(sid)}/reset`, {
|
|
228
|
-
method: 'POST',
|
|
229
|
-
});
|
|
230
|
-
if (!res.ok) throw new Error(`Failed to reset session: ${res.status}`);
|
|
231
|
-
}
|
|
232
|
-
|
|
233
157
|
// ===========================================================================
|
|
234
158
|
// Execution
|
|
235
159
|
// ===========================================================================
|
|
@@ -248,7 +172,6 @@ export class MRPClient {
|
|
|
248
172
|
headers: { 'Content-Type': 'application/json' },
|
|
249
173
|
body: JSON.stringify({
|
|
250
174
|
code,
|
|
251
|
-
session: this.#defaultSession,
|
|
252
175
|
...options,
|
|
253
176
|
}),
|
|
254
177
|
});
|
|
@@ -300,7 +223,6 @@ export class MRPClient {
|
|
|
300
223
|
headers: { 'Content-Type': 'application/json' },
|
|
301
224
|
body: JSON.stringify({
|
|
302
225
|
code,
|
|
303
|
-
session: this.#defaultSession,
|
|
304
226
|
...executeOptions,
|
|
305
227
|
}),
|
|
306
228
|
signal: controller.signal,
|
|
@@ -339,14 +261,8 @@ export class MRPClient {
|
|
|
339
261
|
} else if (currentEvent === 'stdin_request') {
|
|
340
262
|
// Runtime needs user input - call handler and send response
|
|
341
263
|
if (onStdinRequest) {
|
|
342
|
-
// onStdinRequest returns Promise<string> with user's input
|
|
343
|
-
// We handle this async but don't block the SSE reading
|
|
344
|
-
// The server will wait for our /input POST
|
|
345
264
|
Promise.resolve(onStdinRequest(data))
|
|
346
|
-
.then((input) =>
|
|
347
|
-
// Send the input back to the server
|
|
348
|
-
return this.sendInput(data.execId, input);
|
|
349
|
-
})
|
|
265
|
+
.then((input) => this.sendInput(data.execId, input))
|
|
350
266
|
.catch((err) => {
|
|
351
267
|
// User cancelled input (e.g., pressed Escape)
|
|
352
268
|
// Notify server to unblock the waiting execution
|
|
@@ -357,9 +273,6 @@ export class MRPClient {
|
|
|
357
273
|
});
|
|
358
274
|
}
|
|
359
275
|
} else if (currentEvent === 'asset' || currentEvent === 'display') {
|
|
360
|
-
// Rich output: images, plots, HTML, etc.
|
|
361
|
-
// data contains: { path, url, mimeType, assetType, size } for assets
|
|
362
|
-
// or { data: { 'image/png': base64, ... }, metadata } for display
|
|
363
276
|
if (onAsset) {
|
|
364
277
|
onAsset(data, currentEvent);
|
|
365
278
|
}
|
|
@@ -403,15 +316,13 @@ export class MRPClient {
|
|
|
403
316
|
*
|
|
404
317
|
* @param {string} execId - Execution ID waiting for input
|
|
405
318
|
* @param {string} text - User input (include \n if submitting)
|
|
406
|
-
* @param {string} [session] - Session ID
|
|
407
319
|
* @returns {Promise<SendInputResult>}
|
|
408
320
|
*/
|
|
409
|
-
async sendInput(execId, text
|
|
321
|
+
async sendInput(execId, text) {
|
|
410
322
|
const res = await fetch(`${this.#endpoint}/input`, {
|
|
411
323
|
method: 'POST',
|
|
412
324
|
headers: { 'Content-Type': 'application/json' },
|
|
413
325
|
body: JSON.stringify({
|
|
414
|
-
session: session || this.#defaultSession,
|
|
415
326
|
exec_id: execId,
|
|
416
327
|
text,
|
|
417
328
|
}),
|
|
@@ -423,10 +334,9 @@ export class MRPClient {
|
|
|
423
334
|
/**
|
|
424
335
|
* Interrupt running execution
|
|
425
336
|
*
|
|
426
|
-
* @param {string} [session]
|
|
427
337
|
* @returns {Promise<void>}
|
|
428
338
|
*/
|
|
429
|
-
async interrupt(
|
|
339
|
+
async interrupt() {
|
|
430
340
|
// Abort fetch if in progress
|
|
431
341
|
if (this.#currentExecution) {
|
|
432
342
|
this.#currentExecution.abort();
|
|
@@ -437,65 +347,58 @@ export class MRPClient {
|
|
|
437
347
|
const res = await fetch(`${this.#endpoint}/interrupt`, {
|
|
438
348
|
method: 'POST',
|
|
439
349
|
headers: { 'Content-Type': 'application/json' },
|
|
440
|
-
body: JSON.stringify({
|
|
350
|
+
body: JSON.stringify({}),
|
|
441
351
|
});
|
|
442
352
|
if (!res.ok) throw new Error(`Failed to interrupt: ${res.status}`);
|
|
443
353
|
}
|
|
444
354
|
|
|
445
|
-
// ===========================================================================
|
|
446
|
-
// Input
|
|
447
|
-
// ===========================================================================
|
|
448
|
-
|
|
449
355
|
/**
|
|
450
|
-
*
|
|
356
|
+
* Cancel a pending input request
|
|
357
|
+
*
|
|
358
|
+
* Called when the user dismisses the input field without providing input.
|
|
359
|
+
* This unblocks the waiting execution on the server.
|
|
451
360
|
*
|
|
452
|
-
* @param {string} execId - The execution ID
|
|
453
|
-
* @
|
|
454
|
-
* @param {string} [session]
|
|
455
|
-
* @returns {Promise<{accepted: boolean, error?: string}>}
|
|
361
|
+
* @param {string} execId - The execution ID waiting for input
|
|
362
|
+
* @returns {Promise<{cancelled: boolean, error?: string}>}
|
|
456
363
|
*/
|
|
457
|
-
async
|
|
458
|
-
const res = await fetch(`${this.#endpoint}/input`, {
|
|
364
|
+
async cancelInput(execId) {
|
|
365
|
+
const res = await fetch(`${this.#endpoint}/input/cancel`, {
|
|
459
366
|
method: 'POST',
|
|
460
367
|
headers: { 'Content-Type': 'application/json' },
|
|
461
368
|
body: JSON.stringify({
|
|
462
|
-
session: session || this.#defaultSession,
|
|
463
369
|
exec_id: execId,
|
|
464
|
-
text,
|
|
465
370
|
}),
|
|
466
371
|
});
|
|
467
372
|
|
|
468
373
|
if (!res.ok) {
|
|
469
|
-
throw new Error(`Failed to
|
|
374
|
+
throw new Error(`Failed to cancel input: ${res.status}`);
|
|
470
375
|
}
|
|
471
376
|
|
|
472
377
|
return res.json();
|
|
473
378
|
}
|
|
474
379
|
|
|
475
380
|
/**
|
|
476
|
-
*
|
|
381
|
+
* Reset runtime namespace (clear variables)
|
|
477
382
|
*
|
|
478
|
-
*
|
|
479
|
-
* This unblocks the waiting execution on the server.
|
|
480
|
-
*
|
|
481
|
-
* @param {string} execId - The execution ID waiting for input
|
|
482
|
-
* @param {string} [session]
|
|
483
|
-
* @returns {Promise<{cancelled: boolean, error?: string}>}
|
|
383
|
+
* @returns {Promise<{success: boolean}>}
|
|
484
384
|
*/
|
|
485
|
-
async
|
|
486
|
-
|
|
385
|
+
async reset() {
|
|
386
|
+
let res = await fetch(`${this.#endpoint}/reset`, {
|
|
487
387
|
method: 'POST',
|
|
488
388
|
headers: { 'Content-Type': 'application/json' },
|
|
489
|
-
body: JSON.stringify({
|
|
490
|
-
session: session || this.#defaultSession,
|
|
491
|
-
exec_id: execId,
|
|
492
|
-
}),
|
|
389
|
+
body: JSON.stringify({}),
|
|
493
390
|
});
|
|
494
391
|
|
|
495
|
-
|
|
496
|
-
|
|
392
|
+
// Backward compatibility for runtimes that still expose session reset
|
|
393
|
+
if (!res.ok && res.status === 404) {
|
|
394
|
+
res = await fetch(`${this.#endpoint}/sessions/default/reset`, {
|
|
395
|
+
method: 'POST',
|
|
396
|
+
headers: { 'Content-Type': 'application/json' },
|
|
397
|
+
body: JSON.stringify({}),
|
|
398
|
+
});
|
|
497
399
|
}
|
|
498
400
|
|
|
401
|
+
if (!res.ok) throw new Error(`Failed to reset runtime: ${res.status}`);
|
|
499
402
|
return res.json();
|
|
500
403
|
}
|
|
501
404
|
|
|
@@ -521,7 +424,6 @@ export class MRPClient {
|
|
|
521
424
|
headers: { 'Content-Type': 'application/json' },
|
|
522
425
|
body: JSON.stringify({
|
|
523
426
|
...request,
|
|
524
|
-
session: request.session || this.#defaultSession,
|
|
525
427
|
}),
|
|
526
428
|
});
|
|
527
429
|
|
|
@@ -551,7 +453,6 @@ export class MRPClient {
|
|
|
551
453
|
headers: { 'Content-Type': 'application/json' },
|
|
552
454
|
body: JSON.stringify({
|
|
553
455
|
...request,
|
|
554
|
-
session: request.session || this.#defaultSession,
|
|
555
456
|
}),
|
|
556
457
|
});
|
|
557
458
|
|
|
@@ -577,7 +478,6 @@ export class MRPClient {
|
|
|
577
478
|
headers: { 'Content-Type': 'application/json' },
|
|
578
479
|
body: JSON.stringify({
|
|
579
480
|
...request,
|
|
580
|
-
session: request.session || this.#defaultSession,
|
|
581
481
|
}),
|
|
582
482
|
});
|
|
583
483
|
|
|
@@ -590,13 +490,12 @@ export class MRPClient {
|
|
|
590
490
|
// ===========================================================================
|
|
591
491
|
|
|
592
492
|
/**
|
|
593
|
-
* List variables in
|
|
493
|
+
* List variables in runtime namespace
|
|
594
494
|
*
|
|
595
|
-
* @param {string} [session]
|
|
596
495
|
* @param {import('./mrp-types.js').VariablesFilter} [filter]
|
|
597
496
|
* @returns {Promise<VariablesResult>}
|
|
598
497
|
*/
|
|
599
|
-
async getVariables(
|
|
498
|
+
async getVariables(filter) {
|
|
600
499
|
const caps = await this.getCapabilities();
|
|
601
500
|
|
|
602
501
|
if (!caps.features.variables) {
|
|
@@ -606,10 +505,7 @@ export class MRPClient {
|
|
|
606
505
|
const res = await fetch(`${this.#endpoint}/variables`, {
|
|
607
506
|
method: 'POST',
|
|
608
507
|
headers: { 'Content-Type': 'application/json' },
|
|
609
|
-
body: JSON.stringify({
|
|
610
|
-
session: session || this.#defaultSession,
|
|
611
|
-
filter,
|
|
612
|
-
}),
|
|
508
|
+
body: JSON.stringify({ filter }),
|
|
613
509
|
});
|
|
614
510
|
|
|
615
511
|
if (!res.ok) throw new Error(`Variables failed: ${res.status}`);
|
|
@@ -621,7 +517,6 @@ export class MRPClient {
|
|
|
621
517
|
*
|
|
622
518
|
* @param {string} name - Variable name
|
|
623
519
|
* @param {Object} [options]
|
|
624
|
-
* @param {string} [options.session] - Session ID
|
|
625
520
|
* @param {string[]} [options.path] - Drill-down path
|
|
626
521
|
* @param {number} [options.maxChildren] - Max children to return
|
|
627
522
|
* @param {number} [options.maxValueLength] - Max value length
|
|
@@ -638,7 +533,6 @@ export class MRPClient {
|
|
|
638
533
|
method: 'POST',
|
|
639
534
|
headers: { 'Content-Type': 'application/json' },
|
|
640
535
|
body: JSON.stringify({
|
|
641
|
-
session: options.session || this.#defaultSession,
|
|
642
536
|
path: options.path,
|
|
643
537
|
maxChildren: options.maxChildren,
|
|
644
538
|
maxValueLength: options.maxValueLength,
|
|
@@ -657,10 +551,9 @@ export class MRPClient {
|
|
|
657
551
|
* Check if code is a complete statement
|
|
658
552
|
*
|
|
659
553
|
* @param {string} code
|
|
660
|
-
* @param {string} [session]
|
|
661
554
|
* @returns {Promise<IsCompleteResult>}
|
|
662
555
|
*/
|
|
663
|
-
async isComplete(code
|
|
556
|
+
async isComplete(code) {
|
|
664
557
|
const caps = await this.getCapabilities();
|
|
665
558
|
|
|
666
559
|
if (!caps.features.isComplete) {
|
|
@@ -670,10 +563,7 @@ export class MRPClient {
|
|
|
670
563
|
const res = await fetch(`${this.#endpoint}/is_complete`, {
|
|
671
564
|
method: 'POST',
|
|
672
565
|
headers: { 'Content-Type': 'application/json' },
|
|
673
|
-
body: JSON.stringify({
|
|
674
|
-
code,
|
|
675
|
-
session: session || this.#defaultSession,
|
|
676
|
-
}),
|
|
566
|
+
body: JSON.stringify({ code }),
|
|
677
567
|
});
|
|
678
568
|
|
|
679
569
|
if (!res.ok) throw new Error(`isComplete failed: ${res.status}`);
|
|
@@ -684,10 +574,9 @@ export class MRPClient {
|
|
|
684
574
|
* Format code
|
|
685
575
|
*
|
|
686
576
|
* @param {string} code
|
|
687
|
-
* @param {string} [session]
|
|
688
577
|
* @returns {Promise<FormatResult>}
|
|
689
578
|
*/
|
|
690
|
-
async format(code
|
|
579
|
+
async format(code) {
|
|
691
580
|
const caps = await this.getCapabilities();
|
|
692
581
|
|
|
693
582
|
if (!caps.features.format) {
|
|
@@ -697,10 +586,7 @@ export class MRPClient {
|
|
|
697
586
|
const res = await fetch(`${this.#endpoint}/format`, {
|
|
698
587
|
method: 'POST',
|
|
699
588
|
headers: { 'Content-Type': 'application/json' },
|
|
700
|
-
body: JSON.stringify({
|
|
701
|
-
code,
|
|
702
|
-
session: session || this.#defaultSession,
|
|
703
|
-
}),
|
|
589
|
+
body: JSON.stringify({ code }),
|
|
704
590
|
});
|
|
705
591
|
|
|
706
592
|
if (!res.ok) throw new Error(`Format failed: ${res.status}`);
|
|
@@ -729,24 +615,6 @@ export class MRPClient {
|
|
|
729
615
|
get endpoint() {
|
|
730
616
|
return this.#endpoint;
|
|
731
617
|
}
|
|
732
|
-
|
|
733
|
-
/**
|
|
734
|
-
* Get the default session ID
|
|
735
|
-
*
|
|
736
|
-
* @returns {string}
|
|
737
|
-
*/
|
|
738
|
-
get defaultSession() {
|
|
739
|
-
return this.#defaultSession;
|
|
740
|
-
}
|
|
741
|
-
|
|
742
|
-
/**
|
|
743
|
-
* Set the default session ID
|
|
744
|
-
*
|
|
745
|
-
* @param {string} session
|
|
746
|
-
*/
|
|
747
|
-
set defaultSession(session) {
|
|
748
|
-
this.#defaultSession = session;
|
|
749
|
-
}
|
|
750
618
|
}
|
|
751
619
|
|
|
752
620
|
// #endregion MRP_CLIENT
|
|
@@ -758,7 +626,6 @@ export class MRPClient {
|
|
|
758
626
|
*
|
|
759
627
|
* @param {string} endpoint - Base URL for MRP endpoints
|
|
760
628
|
* @param {Object} [options]
|
|
761
|
-
* @param {string} [options.session='default'] - Default session ID
|
|
762
629
|
* @returns {MRPClient}
|
|
763
630
|
*/
|
|
764
631
|
export function createMRPClient(endpoint, options = {}) {
|
package/src/mrp-types.js
CHANGED
|
@@ -17,8 +17,6 @@
|
|
|
17
17
|
* @property {string[]} languages - Supported language identifiers: ["python", "py", "python3"]
|
|
18
18
|
* @property {CapabilityFeatures} features - What this runtime can do
|
|
19
19
|
* @property {string} [lspFallback] - WebSocket URL for fallback LSP
|
|
20
|
-
* @property {string} defaultSession - Default session ID
|
|
21
|
-
* @property {number} [maxSessions] - Maximum concurrent sessions
|
|
22
20
|
* @property {RuntimeEnvironment} [environment] - Execution environment info
|
|
23
21
|
*/
|
|
24
22
|
|
|
@@ -28,7 +26,7 @@
|
|
|
28
26
|
* @property {boolean} execute - Run code and return result (always true)
|
|
29
27
|
* @property {boolean} executeStream - Stream output via SSE
|
|
30
28
|
* @property {boolean} interrupt - Cancel running execution
|
|
31
|
-
* @property {boolean} complete - Tab completion from live
|
|
29
|
+
* @property {boolean} complete - Tab completion from the live runtime namespace
|
|
32
30
|
* @property {boolean} inspect - Get symbol info (signature, docs, source)
|
|
33
31
|
* @property {boolean} hover - Quick value/type preview
|
|
34
32
|
* @property {boolean} variables - List variables in namespace
|
|
@@ -50,31 +48,6 @@
|
|
|
50
48
|
|
|
51
49
|
// #endregion CAPABILITIES
|
|
52
50
|
|
|
53
|
-
// #region SESSIONS
|
|
54
|
-
|
|
55
|
-
/**
|
|
56
|
-
* Session info
|
|
57
|
-
* @typedef {Object} Session
|
|
58
|
-
* @property {string} id - Session identifier
|
|
59
|
-
* @property {string} language - Primary language
|
|
60
|
-
* @property {string} created - ISO timestamp
|
|
61
|
-
* @property {string} lastActivity - ISO timestamp
|
|
62
|
-
* @property {number} executionCount - Number of executions
|
|
63
|
-
* @property {number} variableCount - Number of variables in namespace
|
|
64
|
-
* @property {RuntimeEnvironment} [environment] - Session environment
|
|
65
|
-
*/
|
|
66
|
-
|
|
67
|
-
/**
|
|
68
|
-
* Create session request
|
|
69
|
-
* @typedef {Object} CreateSessionRequest
|
|
70
|
-
* @property {string} [id] - Session ID (auto-generated if omitted)
|
|
71
|
-
* @property {string} language - Language for this session
|
|
72
|
-
* @property {Partial<RuntimeEnvironment>} [environment] - Environment overrides
|
|
73
|
-
* @property {string[]} [dependencies] - Package dependencies (for UV export)
|
|
74
|
-
* @property {string} [pythonVersion] - Python version constraint
|
|
75
|
-
*/
|
|
76
|
-
|
|
77
|
-
// #endregion SESSIONS
|
|
78
51
|
|
|
79
52
|
// #region EXECUTION
|
|
80
53
|
|
|
@@ -82,7 +55,6 @@
|
|
|
82
55
|
* Execute request
|
|
83
56
|
* @typedef {Object} ExecuteRequest
|
|
84
57
|
* @property {string} code - Code to execute
|
|
85
|
-
* @property {string} [session] - Session ID (default: "default")
|
|
86
58
|
* @property {boolean} [storeHistory] - Add to execution history (default: true)
|
|
87
59
|
* @property {boolean} [silent] - Suppress output (default: false)
|
|
88
60
|
* @property {string} [assetDir] - Where to save figures/assets
|
|
@@ -226,7 +198,6 @@
|
|
|
226
198
|
/**
|
|
227
199
|
* Send input request
|
|
228
200
|
* @typedef {Object} SendInputRequest
|
|
229
|
-
* @property {string} [session] - Session ID
|
|
230
201
|
* @property {string} execId - Execution ID waiting for input
|
|
231
202
|
* @property {string} text - User input (include \n if submitting)
|
|
232
203
|
*/
|
|
@@ -247,7 +218,6 @@
|
|
|
247
218
|
* @typedef {Object} CompleteRequest
|
|
248
219
|
* @property {string} code - Code in cell
|
|
249
220
|
* @property {number} cursor - Cursor position (character offset)
|
|
250
|
-
* @property {string} [session] - Session ID
|
|
251
221
|
* @property {'invoked'|'character'|'incomplete'} [triggerKind] - What triggered completion
|
|
252
222
|
* @property {string} [triggerCharacter] - Character that triggered (".", "[", etc.)
|
|
253
223
|
*/
|
|
@@ -289,7 +259,6 @@
|
|
|
289
259
|
* @typedef {Object} InspectRequest
|
|
290
260
|
* @property {string} code - Code in cell
|
|
291
261
|
* @property {number} cursor - Cursor position
|
|
292
|
-
* @property {string} [session] - Session ID
|
|
293
262
|
* @property {0|1|2} [detail] - Detail level: 0=signature, 1=+docs, 2=+source
|
|
294
263
|
*/
|
|
295
264
|
|
|
@@ -320,7 +289,6 @@
|
|
|
320
289
|
* @typedef {Object} HoverRequest
|
|
321
290
|
* @property {string} code - Code in cell
|
|
322
291
|
* @property {number} cursor - Cursor position
|
|
323
|
-
* @property {string} [session] - Session ID
|
|
324
292
|
*/
|
|
325
293
|
|
|
326
294
|
/**
|
|
@@ -340,7 +308,6 @@
|
|
|
340
308
|
/**
|
|
341
309
|
* Variables request
|
|
342
310
|
* @typedef {Object} VariablesRequest
|
|
343
|
-
* @property {string} [session] - Session ID
|
|
344
311
|
* @property {VariablesFilter} [filter] - Filter options
|
|
345
312
|
*/
|
|
346
313
|
|
|
@@ -377,7 +344,6 @@
|
|
|
377
344
|
/**
|
|
378
345
|
* Variable detail request
|
|
379
346
|
* @typedef {Object} VariableDetailRequest
|
|
380
|
-
* @property {string} [session] - Session ID
|
|
381
347
|
* @property {string[]} [path] - Drill-down path: ["key", "0", "attr"]
|
|
382
348
|
* @property {number} [maxChildren] - Max children to return
|
|
383
349
|
* @property {number} [maxValueLength] - Max chars for value repr
|
|
@@ -410,7 +376,6 @@
|
|
|
410
376
|
* Is-complete request
|
|
411
377
|
* @typedef {Object} IsCompleteRequest
|
|
412
378
|
* @property {string} code - Code to check
|
|
413
|
-
* @property {string} [session] - Session ID
|
|
414
379
|
*/
|
|
415
380
|
|
|
416
381
|
/**
|
|
@@ -424,7 +389,6 @@
|
|
|
424
389
|
* Format request
|
|
425
390
|
* @typedef {Object} FormatRequest
|
|
426
391
|
* @property {string} code - Code to format
|
|
427
|
-
* @property {string} [session] - Session ID
|
|
428
392
|
*/
|
|
429
393
|
|
|
430
394
|
/**
|