mrmd-editor 0.5.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/config/schema.js +4 -3
- package/src/ctrl-k-modal.js +190 -14
- package/src/document-languages.js +105 -0
- package/src/execution.js +50 -13
- package/src/frontmatter-updater.js +224 -0
- package/src/index.js +162 -97
- package/src/markdown/block-decorations.js +103 -0
- package/src/markdown/renderer.js +52 -3
- package/src/markdown/styles.js +126 -0
- package/src/markdown/widgets/frontmatter.js +438 -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 +818 -123
- 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
|
@@ -0,0 +1,438 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Frontmatter Widget
|
|
3
|
+
*
|
|
4
|
+
* Renders YAML frontmatter as a styled document header.
|
|
5
|
+
* Shows title, subtitle, author, date, and abstract.
|
|
6
|
+
* Session/runtime config keys are skipped (handled by runtime-codelens).
|
|
7
|
+
*
|
|
8
|
+
* @module markdown/widgets/frontmatter
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
import { WidgetType } from '@codemirror/view';
|
|
12
|
+
import yaml from 'yaml';
|
|
13
|
+
|
|
14
|
+
// Keys that are handled by runtime-codelens (not rendered here)
|
|
15
|
+
const RUNTIME_KEYS = new Set([
|
|
16
|
+
'session', 'python', 'bash', 'node', 'julia', 'r', 'shell', 'term',
|
|
17
|
+
]);
|
|
18
|
+
|
|
19
|
+
const TITLE_COMMIT_EVENT = 'mrmd:frontmatter-title-commit';
|
|
20
|
+
|
|
21
|
+
let stylesInjected = false;
|
|
22
|
+
|
|
23
|
+
function injectStyles() {
|
|
24
|
+
if (stylesInjected) return;
|
|
25
|
+
stylesInjected = true;
|
|
26
|
+
|
|
27
|
+
const css = `
|
|
28
|
+
.cm-frontmatter-widget {
|
|
29
|
+
padding: 20px 0 16px;
|
|
30
|
+
margin-bottom: 4px;
|
|
31
|
+
border-bottom: 1px solid var(--frontmatter-border, rgba(128, 128, 128, 0.15));
|
|
32
|
+
line-height: 1.4;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
.cm-frontmatter-title-row {
|
|
36
|
+
display: flex;
|
|
37
|
+
align-items: baseline;
|
|
38
|
+
gap: 10px;
|
|
39
|
+
margin: 0 0 4px;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
.cm-frontmatter-title-input {
|
|
43
|
+
flex: 1;
|
|
44
|
+
font-size: 2em;
|
|
45
|
+
font-weight: 700;
|
|
46
|
+
color: var(--text-primary, var(--text, #e0e0e0));
|
|
47
|
+
margin: 0;
|
|
48
|
+
padding: 0;
|
|
49
|
+
width: 100%;
|
|
50
|
+
border: none;
|
|
51
|
+
outline: none;
|
|
52
|
+
background: transparent;
|
|
53
|
+
line-height: 1.15;
|
|
54
|
+
letter-spacing: -0.02em;
|
|
55
|
+
font-family: inherit;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
.cm-frontmatter-title-input::placeholder {
|
|
59
|
+
color: var(--text-dim, #808080);
|
|
60
|
+
opacity: 0.7;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
.cm-frontmatter-title-input:focus {
|
|
64
|
+
text-decoration: underline;
|
|
65
|
+
text-underline-offset: 5px;
|
|
66
|
+
text-decoration-color: var(--accent, #4a9eff);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
.cm-frontmatter-title-hint {
|
|
70
|
+
font-size: 0.7em;
|
|
71
|
+
color: var(--text-dim, #808080);
|
|
72
|
+
white-space: nowrap;
|
|
73
|
+
opacity: 0;
|
|
74
|
+
transition: opacity 120ms ease;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
.cm-frontmatter-title-row:focus-within .cm-frontmatter-title-hint {
|
|
78
|
+
opacity: 0.8;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
.cm-frontmatter-subtitle {
|
|
82
|
+
font-size: 1.25em;
|
|
83
|
+
font-weight: 400;
|
|
84
|
+
color: var(--text-secondary, var(--text-muted, #a0a0a0));
|
|
85
|
+
margin: 0 0 12px;
|
|
86
|
+
line-height: 1.3;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
.cm-frontmatter-authors {
|
|
90
|
+
display: flex;
|
|
91
|
+
flex-wrap: wrap;
|
|
92
|
+
gap: 6px 16px;
|
|
93
|
+
margin-bottom: 6px;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
.cm-frontmatter-author {
|
|
97
|
+
font-size: 0.9em;
|
|
98
|
+
color: var(--text, #e0e0e0);
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
.cm-frontmatter-author-affiliation {
|
|
102
|
+
font-size: 0.8em;
|
|
103
|
+
color: var(--text-dim, #808080);
|
|
104
|
+
margin-left: 2px;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
.cm-frontmatter-date {
|
|
108
|
+
font-size: 0.85em;
|
|
109
|
+
color: var(--text-dim, #808080);
|
|
110
|
+
margin-bottom: 4px;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
.cm-frontmatter-abstract {
|
|
114
|
+
margin-top: 12px;
|
|
115
|
+
padding: 10px 14px;
|
|
116
|
+
border-left: 3px solid var(--accent, #4a9eff);
|
|
117
|
+
font-size: 0.9em;
|
|
118
|
+
color: var(--text-secondary, var(--text-muted, #a0a0a0));
|
|
119
|
+
line-height: 1.6;
|
|
120
|
+
background: var(--frontmatter-abstract-bg, rgba(128, 128, 128, 0.04));
|
|
121
|
+
border-radius: 0 4px 4px 0;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
.cm-frontmatter-keywords {
|
|
125
|
+
margin-top: 10px;
|
|
126
|
+
display: flex;
|
|
127
|
+
flex-wrap: wrap;
|
|
128
|
+
gap: 6px;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
.cm-frontmatter-keyword {
|
|
132
|
+
display: inline-block;
|
|
133
|
+
padding: 2px 10px;
|
|
134
|
+
border-radius: 12px;
|
|
135
|
+
font-size: 0.78em;
|
|
136
|
+
background: var(--frontmatter-keyword-bg, rgba(128, 128, 128, 0.12));
|
|
137
|
+
color: var(--text-dim, #808080);
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
.cm-frontmatter-empty {
|
|
141
|
+
padding: 4px 0;
|
|
142
|
+
}
|
|
143
|
+
`;
|
|
144
|
+
|
|
145
|
+
const style = document.createElement('style');
|
|
146
|
+
style.textContent = css;
|
|
147
|
+
document.head.appendChild(style);
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
/**
|
|
151
|
+
* Extract author name(s) from Quarto's various author formats.
|
|
152
|
+
* Supports: string, array of strings, array of objects with name/given/family.
|
|
153
|
+
*/
|
|
154
|
+
function extractAuthors(authorVal) {
|
|
155
|
+
if (!authorVal) return [];
|
|
156
|
+
if (typeof authorVal === 'string') return [{ name: authorVal }];
|
|
157
|
+
if (Array.isArray(authorVal)) {
|
|
158
|
+
return authorVal.map(a => {
|
|
159
|
+
if (typeof a === 'string') return { name: a };
|
|
160
|
+
if (a && typeof a === 'object') {
|
|
161
|
+
const name = a.name || [a.given, a.family].filter(Boolean).join(' ') || 'Unknown';
|
|
162
|
+
const affiliation = extractAffiliation(a.affiliation);
|
|
163
|
+
return { name, affiliation };
|
|
164
|
+
}
|
|
165
|
+
return { name: String(a) };
|
|
166
|
+
});
|
|
167
|
+
}
|
|
168
|
+
if (typeof authorVal === 'object') {
|
|
169
|
+
const name = authorVal.name || [authorVal.given, authorVal.family].filter(Boolean).join(' ');
|
|
170
|
+
const affiliation = extractAffiliation(authorVal.affiliation);
|
|
171
|
+
return [{ name, affiliation }];
|
|
172
|
+
}
|
|
173
|
+
return [];
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
function extractAffiliation(aff) {
|
|
177
|
+
if (!aff) return '';
|
|
178
|
+
if (typeof aff === 'string') return aff;
|
|
179
|
+
if (Array.isArray(aff)) {
|
|
180
|
+
return aff.map(a => typeof a === 'string' ? a : a?.name || '').filter(Boolean).join(', ');
|
|
181
|
+
}
|
|
182
|
+
if (typeof aff === 'object') return aff.name || '';
|
|
183
|
+
return '';
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
/**
|
|
187
|
+
* Format a date string for display.
|
|
188
|
+
*/
|
|
189
|
+
function formatDate(dateVal) {
|
|
190
|
+
if (!dateVal) return '';
|
|
191
|
+
const str = String(dateVal);
|
|
192
|
+
if (str.toLowerCase() === 'today') {
|
|
193
|
+
return new Date().toLocaleDateString('en-US', {
|
|
194
|
+
year: 'numeric', month: 'long', day: 'numeric',
|
|
195
|
+
});
|
|
196
|
+
}
|
|
197
|
+
const d = new Date(str);
|
|
198
|
+
if (!isNaN(d.getTime())) {
|
|
199
|
+
return d.toLocaleDateString('en-US', {
|
|
200
|
+
year: 'numeric', month: 'long', day: 'numeric',
|
|
201
|
+
});
|
|
202
|
+
}
|
|
203
|
+
return str;
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
/**
|
|
207
|
+
* Extract keywords from various formats.
|
|
208
|
+
*/
|
|
209
|
+
function extractKeywords(kw) {
|
|
210
|
+
if (!kw) return [];
|
|
211
|
+
if (Array.isArray(kw)) return kw.map(String);
|
|
212
|
+
if (typeof kw === 'string') return kw.split(/[,;]\s*/).filter(Boolean);
|
|
213
|
+
return [];
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
function escapeYamlDoubleQuoted(value) {
|
|
217
|
+
return String(value)
|
|
218
|
+
.replace(/\\/g, '\\\\')
|
|
219
|
+
.replace(/"/g, '\\"');
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
function replaceFrontmatterTitleInBlock(frontmatterBlock, title) {
|
|
223
|
+
if (!frontmatterBlock || typeof frontmatterBlock !== 'string') return frontmatterBlock;
|
|
224
|
+
const eol = frontmatterBlock.includes('\r\n') ? '\r\n' : '\n';
|
|
225
|
+
if (!frontmatterBlock.startsWith(`---${eol}`) || !frontmatterBlock.endsWith(`${eol}---`)) {
|
|
226
|
+
return frontmatterBlock;
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
const openingLen = `---${eol}`.length;
|
|
230
|
+
const closingLen = `${eol}---`.length;
|
|
231
|
+
const body = frontmatterBlock.slice(openingLen, frontmatterBlock.length - closingLen);
|
|
232
|
+
const escapedTitle = escapeYamlDoubleQuoted(title.trim());
|
|
233
|
+
|
|
234
|
+
let nextBody;
|
|
235
|
+
if (/^\s*title\s*:/mi.test(body)) {
|
|
236
|
+
nextBody = body.replace(/^\s*title\s*:\s*.*$/mi, `title: "${escapedTitle}"`);
|
|
237
|
+
} else if (!body.trim()) {
|
|
238
|
+
nextBody = `title: "${escapedTitle}"`;
|
|
239
|
+
} else {
|
|
240
|
+
nextBody = `title: "${escapedTitle}"${eol}${body}`;
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
return `---${eol}${nextBody}${eol}---`;
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
/**
|
|
247
|
+
* Frontmatter WidgetType for CodeMirror 6.
|
|
248
|
+
* Renders document metadata as a styled header block.
|
|
249
|
+
*/
|
|
250
|
+
export class FrontmatterWidget extends WidgetType {
|
|
251
|
+
constructor(yamlContent, contentHash, sourceFrom = null, sourceTo = null) {
|
|
252
|
+
super();
|
|
253
|
+
this.yamlContent = yamlContent;
|
|
254
|
+
this.contentHash = contentHash;
|
|
255
|
+
this.sourceFrom = sourceFrom;
|
|
256
|
+
this.sourceTo = sourceTo;
|
|
257
|
+
this.parsed = null;
|
|
258
|
+
|
|
259
|
+
try {
|
|
260
|
+
this.parsed = yaml.parse(yamlContent);
|
|
261
|
+
} catch (e) {
|
|
262
|
+
// Invalid YAML — will render empty
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
eq(other) {
|
|
267
|
+
return other.contentHash === this.contentHash;
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
commitTitle(view, nextTitle) {
|
|
271
|
+
if (
|
|
272
|
+
!view ||
|
|
273
|
+
typeof this.sourceFrom !== 'number' ||
|
|
274
|
+
typeof this.sourceTo !== 'number'
|
|
275
|
+
) {
|
|
276
|
+
return false;
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
const trimmed = String(nextTitle || '').trim();
|
|
280
|
+
if (!trimmed) return false;
|
|
281
|
+
|
|
282
|
+
const currentBlock = view.state.doc.sliceString(this.sourceFrom, this.sourceTo);
|
|
283
|
+
const nextBlock = replaceFrontmatterTitleInBlock(currentBlock, trimmed);
|
|
284
|
+
if (!nextBlock || nextBlock === currentBlock) return false;
|
|
285
|
+
|
|
286
|
+
view.dispatch({
|
|
287
|
+
changes: {
|
|
288
|
+
from: this.sourceFrom,
|
|
289
|
+
to: this.sourceTo,
|
|
290
|
+
insert: nextBlock,
|
|
291
|
+
},
|
|
292
|
+
});
|
|
293
|
+
|
|
294
|
+
view.dom.dispatchEvent(new CustomEvent(TITLE_COMMIT_EVENT, {
|
|
295
|
+
bubbles: true,
|
|
296
|
+
detail: { title: trimmed },
|
|
297
|
+
}));
|
|
298
|
+
|
|
299
|
+
return true;
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
toDOM(view) {
|
|
303
|
+
injectStyles();
|
|
304
|
+
|
|
305
|
+
const container = document.createElement('div');
|
|
306
|
+
container.className = 'cm-frontmatter-widget';
|
|
307
|
+
|
|
308
|
+
const p = this.parsed;
|
|
309
|
+
if (!p || typeof p !== 'object') {
|
|
310
|
+
container.classList.add('cm-frontmatter-empty');
|
|
311
|
+
return container;
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
// Check if there's any renderable metadata (skip runtime-only frontmatter)
|
|
315
|
+
const hasMetadata = p.title || p.subtitle || p.author || p.date || p.abstract || p.keywords;
|
|
316
|
+
if (!hasMetadata) {
|
|
317
|
+
container.classList.add('cm-frontmatter-empty');
|
|
318
|
+
return container;
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
const titleRow = document.createElement('div');
|
|
322
|
+
titleRow.className = 'cm-frontmatter-title-row';
|
|
323
|
+
|
|
324
|
+
const titleInput = document.createElement('input');
|
|
325
|
+
titleInput.className = 'cm-frontmatter-title-input';
|
|
326
|
+
titleInput.type = 'text';
|
|
327
|
+
titleInput.placeholder = 'Untitled';
|
|
328
|
+
titleInput.value = p.title ? String(p.title) : '';
|
|
329
|
+
titleInput.setAttribute('aria-label', 'Frontmatter title');
|
|
330
|
+
|
|
331
|
+
const commitTitle = () => {
|
|
332
|
+
const nextTitle = titleInput.value.trim();
|
|
333
|
+
if (!nextTitle) {
|
|
334
|
+
titleInput.value = p.title ? String(p.title) : '';
|
|
335
|
+
return;
|
|
336
|
+
}
|
|
337
|
+
if (nextTitle === (p.title ? String(p.title).trim() : '')) return;
|
|
338
|
+
const committed = this.commitTitle(view, nextTitle);
|
|
339
|
+
if (!committed) {
|
|
340
|
+
titleInput.value = p.title ? String(p.title) : '';
|
|
341
|
+
}
|
|
342
|
+
};
|
|
343
|
+
|
|
344
|
+
titleInput.addEventListener('keydown', (event) => {
|
|
345
|
+
event.stopPropagation();
|
|
346
|
+
if (event.key === 'Enter') {
|
|
347
|
+
event.preventDefault();
|
|
348
|
+
commitTitle();
|
|
349
|
+
view.focus();
|
|
350
|
+
} else if (event.key === 'Escape') {
|
|
351
|
+
event.preventDefault();
|
|
352
|
+
titleInput.value = p.title ? String(p.title) : '';
|
|
353
|
+
titleInput.blur();
|
|
354
|
+
view.focus();
|
|
355
|
+
}
|
|
356
|
+
});
|
|
357
|
+
|
|
358
|
+
titleInput.addEventListener('blur', commitTitle);
|
|
359
|
+
titleInput.addEventListener('mousedown', (event) => event.stopPropagation());
|
|
360
|
+
titleInput.addEventListener('click', (event) => event.stopPropagation());
|
|
361
|
+
titleInput.addEventListener('focus', () => titleInput.select());
|
|
362
|
+
|
|
363
|
+
const hint = document.createElement('span');
|
|
364
|
+
hint.className = 'cm-frontmatter-title-hint';
|
|
365
|
+
hint.textContent = 'Enter to commit';
|
|
366
|
+
|
|
367
|
+
titleRow.appendChild(titleInput);
|
|
368
|
+
titleRow.appendChild(hint);
|
|
369
|
+
container.appendChild(titleRow);
|
|
370
|
+
|
|
371
|
+
// Subtitle
|
|
372
|
+
if (p.subtitle) {
|
|
373
|
+
const el = document.createElement('div');
|
|
374
|
+
el.className = 'cm-frontmatter-subtitle';
|
|
375
|
+
el.textContent = String(p.subtitle);
|
|
376
|
+
container.appendChild(el);
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
// Authors
|
|
380
|
+
const authors = extractAuthors(p.author);
|
|
381
|
+
if (authors.length > 0) {
|
|
382
|
+
const authorsDiv = document.createElement('div');
|
|
383
|
+
authorsDiv.className = 'cm-frontmatter-authors';
|
|
384
|
+
|
|
385
|
+
for (const author of authors) {
|
|
386
|
+
const span = document.createElement('span');
|
|
387
|
+
span.className = 'cm-frontmatter-author';
|
|
388
|
+
span.textContent = author.name;
|
|
389
|
+
|
|
390
|
+
if (author.affiliation) {
|
|
391
|
+
const aff = document.createElement('span');
|
|
392
|
+
aff.className = 'cm-frontmatter-author-affiliation';
|
|
393
|
+
aff.textContent = `(${author.affiliation})`;
|
|
394
|
+
span.appendChild(aff);
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
authorsDiv.appendChild(span);
|
|
398
|
+
}
|
|
399
|
+
container.appendChild(authorsDiv);
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
// Date
|
|
403
|
+
if (p.date) {
|
|
404
|
+
const el = document.createElement('div');
|
|
405
|
+
el.className = 'cm-frontmatter-date';
|
|
406
|
+
el.textContent = formatDate(p.date);
|
|
407
|
+
container.appendChild(el);
|
|
408
|
+
}
|
|
409
|
+
|
|
410
|
+
// Abstract
|
|
411
|
+
if (p.abstract) {
|
|
412
|
+
const el = document.createElement('div');
|
|
413
|
+
el.className = 'cm-frontmatter-abstract';
|
|
414
|
+
el.textContent = String(p.abstract);
|
|
415
|
+
container.appendChild(el);
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
// Keywords
|
|
419
|
+
const keywords = extractKeywords(p.keywords);
|
|
420
|
+
if (keywords.length > 0) {
|
|
421
|
+
const kwContainer = document.createElement('div');
|
|
422
|
+
kwContainer.className = 'cm-frontmatter-keywords';
|
|
423
|
+
for (const kw of keywords) {
|
|
424
|
+
const badge = document.createElement('span');
|
|
425
|
+
badge.className = 'cm-frontmatter-keyword';
|
|
426
|
+
badge.textContent = kw.trim();
|
|
427
|
+
kwContainer.appendChild(badge);
|
|
428
|
+
}
|
|
429
|
+
container.appendChild(kwContainer);
|
|
430
|
+
}
|
|
431
|
+
|
|
432
|
+
return container;
|
|
433
|
+
}
|
|
434
|
+
|
|
435
|
+
ignoreEvent() {
|
|
436
|
+
return false;
|
|
437
|
+
}
|
|
438
|
+
}
|
|
@@ -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(),
|