@jataware/beaker-client 2.0.0-b.1
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/README.md +24 -0
- package/dist/extension.d.ts +21 -0
- package/dist/extension.js +3 -0
- package/dist/history.d.ts +39 -0
- package/dist/history.js +16 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.js +10 -0
- package/dist/notebook.d.ts +192 -0
- package/dist/notebook.js +690 -0
- package/dist/render.d.ts +38 -0
- package/dist/render.js +84 -0
- package/dist/session.d.ts +166 -0
- package/dist/session.js +418 -0
- package/dist/util.d.ts +50 -0
- package/dist/util.js +112 -0
- package/package.json +39 -0
- package/src/extension.ts +34 -0
- package/src/history.ts +61 -0
- package/src/index.ts +12 -0
- package/src/notebook.ts +949 -0
- package/src/render.ts +121 -0
- package/src/session.ts +504 -0
- package/src/util.ts +173 -0
package/dist/notebook.js
ADDED
|
@@ -0,0 +1,690 @@
|
|
|
1
|
+
import * as messages from '@jupyterlab/services/lib/kernel/messages';
|
|
2
|
+
import { v4 } from 'uuid';
|
|
3
|
+
import { BeakerCellFutures, BeakerCellFuture } from './util.js';
|
|
4
|
+
|
|
5
|
+
class BeakerBaseCell {
|
|
6
|
+
// Override index type to allow methods to be defined on the class
|
|
7
|
+
static IPYNB_KEYS = ["cell_type", "source", "metadata", "id", "attachments", "outputs", "execution_count"];
|
|
8
|
+
id = BeakerBaseCell.generateId();
|
|
9
|
+
metadata = {};
|
|
10
|
+
source = "";
|
|
11
|
+
status = "idle";
|
|
12
|
+
children = [];
|
|
13
|
+
constructor(content) {
|
|
14
|
+
Object.assign(this, content);
|
|
15
|
+
if (content.id === void 0) {
|
|
16
|
+
this.id = BeakerBaseCell.generateId();
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
static generateId() {
|
|
20
|
+
return v4();
|
|
21
|
+
}
|
|
22
|
+
fromJSON(obj) {
|
|
23
|
+
Object.keys(obj).forEach((key) => {
|
|
24
|
+
this[key] = obj[key];
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
toJSON() {
|
|
28
|
+
return { ...this };
|
|
29
|
+
}
|
|
30
|
+
fromIPynb(obj) {
|
|
31
|
+
Object.keys(obj).forEach((key) => {
|
|
32
|
+
this[key] = obj[key];
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
toIPynb() {
|
|
36
|
+
const output = {};
|
|
37
|
+
for (const key of Object.keys(this)) {
|
|
38
|
+
if (BeakerBaseCell.IPYNB_KEYS.includes(key)) {
|
|
39
|
+
output[key] = this[key];
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
return output;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
class BeakerRawCell extends BeakerBaseCell {
|
|
46
|
+
cell_type = "raw";
|
|
47
|
+
attachments;
|
|
48
|
+
constructor(content) {
|
|
49
|
+
super(content);
|
|
50
|
+
Object.assign(this, content);
|
|
51
|
+
}
|
|
52
|
+
execute(session) {
|
|
53
|
+
return null;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
class BeakerCodeCell extends BeakerBaseCell {
|
|
57
|
+
cell_type = "code";
|
|
58
|
+
outputs = [];
|
|
59
|
+
execution_count = null;
|
|
60
|
+
last_execution = { status: "none" };
|
|
61
|
+
busy = false;
|
|
62
|
+
constructor(content) {
|
|
63
|
+
super({ ...content });
|
|
64
|
+
Object.assign(this, content);
|
|
65
|
+
}
|
|
66
|
+
execute(session, syntheticFuture) {
|
|
67
|
+
this.busy = true;
|
|
68
|
+
var future;
|
|
69
|
+
this.outputs.splice(0, this.outputs.length);
|
|
70
|
+
if (syntheticFuture !== void 0) {
|
|
71
|
+
future = syntheticFuture;
|
|
72
|
+
} else {
|
|
73
|
+
future = session.sendBeakerMessage(
|
|
74
|
+
"execute_request",
|
|
75
|
+
{
|
|
76
|
+
code: this.source,
|
|
77
|
+
silent: false,
|
|
78
|
+
store_history: true,
|
|
79
|
+
user_expressions: {},
|
|
80
|
+
allow_stdin: true,
|
|
81
|
+
stop_on_error: false
|
|
82
|
+
}
|
|
83
|
+
);
|
|
84
|
+
future.onIOPub = (msg) => BeakerCellFutures.handleIOPub(msg, this);
|
|
85
|
+
future.onReply = (msg) => BeakerCellFutures.handleReply(msg, this);
|
|
86
|
+
}
|
|
87
|
+
return future;
|
|
88
|
+
}
|
|
89
|
+
rollback(session) {
|
|
90
|
+
if (this?.last_execution?.status === "ok") {
|
|
91
|
+
const future = session.executeAction(
|
|
92
|
+
"rollback",
|
|
93
|
+
{
|
|
94
|
+
checkpoint_index: this.last_execution.checkpoint_index || null
|
|
95
|
+
}
|
|
96
|
+
);
|
|
97
|
+
this.busy = true;
|
|
98
|
+
future.done.then((reply_msg) => {
|
|
99
|
+
if (reply_msg.content.status === "ok") {
|
|
100
|
+
this.busy = false;
|
|
101
|
+
this.last_execution = { "status": "none" };
|
|
102
|
+
this.execution_count = null;
|
|
103
|
+
this.outputs.splice(0, this.outputs.length);
|
|
104
|
+
this.children.splice(0, this.children.length);
|
|
105
|
+
} else if (reply_msg.content.status === "error") {
|
|
106
|
+
this.last_execution = reply_msg.content;
|
|
107
|
+
this.outputs.push({ ...reply_msg.content, output_type: "error" });
|
|
108
|
+
}
|
|
109
|
+
});
|
|
110
|
+
return future;
|
|
111
|
+
}
|
|
112
|
+
return null;
|
|
113
|
+
}
|
|
114
|
+
reset_execution_state() {
|
|
115
|
+
this.last_execution = { status: "modified" };
|
|
116
|
+
}
|
|
117
|
+
toIPynb() {
|
|
118
|
+
const result = {
|
|
119
|
+
...super.toIPynb(),
|
|
120
|
+
cell_type: "code",
|
|
121
|
+
outputs: this.outputs.map(
|
|
122
|
+
(output) => {
|
|
123
|
+
return {
|
|
124
|
+
...output,
|
|
125
|
+
transient: void 0
|
|
126
|
+
};
|
|
127
|
+
}
|
|
128
|
+
),
|
|
129
|
+
execution_count: this.execution_count
|
|
130
|
+
};
|
|
131
|
+
return result;
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
class BeakerMarkdownCell extends BeakerBaseCell {
|
|
135
|
+
static IPYNB_KEYS = ["cell_type", "source", "metadata", "id", "attachments"];
|
|
136
|
+
cell_type = "markdown";
|
|
137
|
+
attachments;
|
|
138
|
+
constructor(content) {
|
|
139
|
+
super({ ...content });
|
|
140
|
+
Object.assign(this, content);
|
|
141
|
+
}
|
|
142
|
+
execute(session) {
|
|
143
|
+
return null;
|
|
144
|
+
}
|
|
145
|
+
toIPynb() {
|
|
146
|
+
const output = {};
|
|
147
|
+
for (const key of Object.keys(this)) {
|
|
148
|
+
if (BeakerMarkdownCell.IPYNB_KEYS.includes(key)) {
|
|
149
|
+
output[key] = this[key];
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
return output;
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
class BeakerQueryCell extends BeakerBaseCell {
|
|
156
|
+
cell_type = "query";
|
|
157
|
+
events = [];
|
|
158
|
+
_current_input_request_message;
|
|
159
|
+
_toolCallIndex = /* @__PURE__ */ new Map();
|
|
160
|
+
constructor(content) {
|
|
161
|
+
super({ cell_type: "query", ...content });
|
|
162
|
+
Object.assign(this, content);
|
|
163
|
+
}
|
|
164
|
+
execute(session, includeNotebookState = true) {
|
|
165
|
+
this.events.splice(0, this.events.length);
|
|
166
|
+
this.children.splice(0, this.children.length);
|
|
167
|
+
this._toolCallIndex.clear();
|
|
168
|
+
const handleIOPub = async (msg) => {
|
|
169
|
+
const msg_type = msg.header.msg_type;
|
|
170
|
+
const content = msg.content;
|
|
171
|
+
if (msg_type === "status") {
|
|
172
|
+
this.status = content.execution_state;
|
|
173
|
+
} else if (msg_type === "llm_thought") {
|
|
174
|
+
const tool_calls = (content.tool_calls || []).map(
|
|
175
|
+
(tc) => ({
|
|
176
|
+
tool_call_id: tc.tool_call_id,
|
|
177
|
+
tool_name: tc.tool_name,
|
|
178
|
+
tool_input: tc.tool_input,
|
|
179
|
+
state: tc.state || "pending"
|
|
180
|
+
})
|
|
181
|
+
);
|
|
182
|
+
if (!content.thought && tool_calls.length === 0) {
|
|
183
|
+
return;
|
|
184
|
+
}
|
|
185
|
+
const event = {
|
|
186
|
+
type: "thought",
|
|
187
|
+
content: {
|
|
188
|
+
thought: content.thought || "",
|
|
189
|
+
thought_id: content.thought_id,
|
|
190
|
+
tool_calls
|
|
191
|
+
}
|
|
192
|
+
};
|
|
193
|
+
this.events.push(event);
|
|
194
|
+
const eventIndex = this.events.length - 1;
|
|
195
|
+
tool_calls.forEach((tc, slot) => {
|
|
196
|
+
if (tc.tool_call_id) {
|
|
197
|
+
this._toolCallIndex.set(tc.tool_call_id, { eventIndex, slot });
|
|
198
|
+
}
|
|
199
|
+
});
|
|
200
|
+
} else if (msg_type === "tool_call_update") {
|
|
201
|
+
const entry = this._toolCallIndex.get(content.tool_call_id);
|
|
202
|
+
if (entry === void 0) {
|
|
203
|
+
return;
|
|
204
|
+
}
|
|
205
|
+
const { eventIndex, slot } = entry;
|
|
206
|
+
const event = this.events[eventIndex];
|
|
207
|
+
if (!event || event.type !== "thought") {
|
|
208
|
+
return;
|
|
209
|
+
}
|
|
210
|
+
const existing = event.content.tool_calls[slot];
|
|
211
|
+
const { tool_call_id: _id, ...updateFields } = content;
|
|
212
|
+
event.content.tool_calls = [
|
|
213
|
+
...event.content.tool_calls.slice(0, slot),
|
|
214
|
+
{ ...existing, ...updateFields },
|
|
215
|
+
...event.content.tool_calls.slice(slot + 1)
|
|
216
|
+
];
|
|
217
|
+
} else if (msg_type === "llm_response" && content.name === "response_text") {
|
|
218
|
+
this.events.push({
|
|
219
|
+
type: "response",
|
|
220
|
+
content: content.text
|
|
221
|
+
});
|
|
222
|
+
} else if (msg_type === "code_cell") {
|
|
223
|
+
const nb = session.notebook;
|
|
224
|
+
const codeCell = new BeakerCodeCell({
|
|
225
|
+
cell_type: "code",
|
|
226
|
+
source: content.code,
|
|
227
|
+
metadata: {
|
|
228
|
+
parent_cell: this.id
|
|
229
|
+
},
|
|
230
|
+
outputs: []
|
|
231
|
+
});
|
|
232
|
+
const queryCellIndex = nb.cells.findIndex((cell) => cell.id === this.id);
|
|
233
|
+
if (queryCellIndex >= 0) {
|
|
234
|
+
session.notebook.cells.splice(queryCellIndex + 1, 0, codeCell);
|
|
235
|
+
} else {
|
|
236
|
+
nb.addCell(codeCell);
|
|
237
|
+
}
|
|
238
|
+
} else if (msg_type === "add_child_codecell") {
|
|
239
|
+
const autoexecute = content.autoexecute;
|
|
240
|
+
const codeCell = new BeakerCodeCell({
|
|
241
|
+
cell_type: "code",
|
|
242
|
+
source: content.code,
|
|
243
|
+
metadata: {
|
|
244
|
+
parent_cell: this.id
|
|
245
|
+
},
|
|
246
|
+
outputs: [],
|
|
247
|
+
busy: true
|
|
248
|
+
});
|
|
249
|
+
codeCell.last_execution = {
|
|
250
|
+
status: "pending",
|
|
251
|
+
checkpoint_index: content.checkpoint_index
|
|
252
|
+
};
|
|
253
|
+
this.events.push({
|
|
254
|
+
type: "code_cell",
|
|
255
|
+
content: {
|
|
256
|
+
parent_id: this.id,
|
|
257
|
+
cell_id: codeCell.id,
|
|
258
|
+
metadata: {}
|
|
259
|
+
}
|
|
260
|
+
});
|
|
261
|
+
this.children.push(codeCell);
|
|
262
|
+
const reactiveCell = this.children[this.children.length - 1];
|
|
263
|
+
if (autoexecute && content.execute_request_msg) {
|
|
264
|
+
const executeRequest = content.execute_request_msg;
|
|
265
|
+
new BeakerCellFuture(
|
|
266
|
+
executeRequest,
|
|
267
|
+
// Message that is presumably sent
|
|
268
|
+
true,
|
|
269
|
+
// expectReply
|
|
270
|
+
true,
|
|
271
|
+
// disposeOnDone
|
|
272
|
+
session.kernel,
|
|
273
|
+
// kernel
|
|
274
|
+
reactiveCell
|
|
275
|
+
// relatedCodecell
|
|
276
|
+
);
|
|
277
|
+
}
|
|
278
|
+
} else if (msg_type == "update_child_codecell") {
|
|
279
|
+
const cellId = content.id;
|
|
280
|
+
const cell = this.children.find((value) => value.id === cellId);
|
|
281
|
+
if (cell === void 0 || cell === null) {
|
|
282
|
+
console.log("Can't find cell");
|
|
283
|
+
throw Error("Cell to be updated not found ");
|
|
284
|
+
}
|
|
285
|
+
cell.execution_count = content.execution_count;
|
|
286
|
+
let status = {
|
|
287
|
+
status: content.execution_status
|
|
288
|
+
};
|
|
289
|
+
if (content.execution_status === "error") {
|
|
290
|
+
const error_details = {
|
|
291
|
+
ename: msg.content.ename,
|
|
292
|
+
evalue: msg.content.evalue,
|
|
293
|
+
traceback: msg.content.traceback
|
|
294
|
+
};
|
|
295
|
+
cell.outputs.push({
|
|
296
|
+
output_type: "error",
|
|
297
|
+
...error_details
|
|
298
|
+
});
|
|
299
|
+
status = { ...status, ...error_details };
|
|
300
|
+
} else if (status.status === "ok") {
|
|
301
|
+
status = { ...status, checkpoint_index: content.checkpoint_index };
|
|
302
|
+
cell.outputs.push({
|
|
303
|
+
output_type: "execute_result",
|
|
304
|
+
data: {
|
|
305
|
+
"text/plain": content.execution_return
|
|
306
|
+
}
|
|
307
|
+
});
|
|
308
|
+
}
|
|
309
|
+
cell.last_execution = status;
|
|
310
|
+
}
|
|
311
|
+
};
|
|
312
|
+
const handleStdin = async (msg) => {
|
|
313
|
+
if (messages.isInputRequestMsg(msg)) {
|
|
314
|
+
this.events.push({
|
|
315
|
+
type: "user_question",
|
|
316
|
+
content: msg.content.prompt
|
|
317
|
+
});
|
|
318
|
+
this.status = "awaiting_input";
|
|
319
|
+
this._current_input_request_message = msg;
|
|
320
|
+
}
|
|
321
|
+
};
|
|
322
|
+
const handleReply = async (msg) => {
|
|
323
|
+
if (msg.content.status === "ok") {
|
|
324
|
+
this.last_execution = {
|
|
325
|
+
status: "ok"
|
|
326
|
+
};
|
|
327
|
+
} else if (msg.content.status === "error") {
|
|
328
|
+
const error_details = {
|
|
329
|
+
ename: msg.content.ename,
|
|
330
|
+
evalue: msg.content.evalue,
|
|
331
|
+
traceback: msg.content.traceback
|
|
332
|
+
};
|
|
333
|
+
this.last_execution = {
|
|
334
|
+
status: "error",
|
|
335
|
+
...error_details
|
|
336
|
+
};
|
|
337
|
+
this.events.push({
|
|
338
|
+
type: "error",
|
|
339
|
+
content: { ...msg.content }
|
|
340
|
+
});
|
|
341
|
+
} else if (msg.content.status === "abort") {
|
|
342
|
+
this.last_execution = {
|
|
343
|
+
status: "abort"
|
|
344
|
+
};
|
|
345
|
+
this.events.push({
|
|
346
|
+
type: "abort",
|
|
347
|
+
content: "Request aborted"
|
|
348
|
+
});
|
|
349
|
+
}
|
|
350
|
+
};
|
|
351
|
+
var metadata = {};
|
|
352
|
+
if (includeNotebookState) {
|
|
353
|
+
const notebookState = session.notebook.toIPynb();
|
|
354
|
+
notebookState.cells = notebookState.cells.filter(
|
|
355
|
+
// Skip this cell and any children of this cell
|
|
356
|
+
(cell) => cell.id !== this.id && cell.metadata?.parent_cell !== this.id
|
|
357
|
+
);
|
|
358
|
+
metadata["notebook_state"] = notebookState;
|
|
359
|
+
}
|
|
360
|
+
const future = session.sendBeakerMessage(
|
|
361
|
+
"llm_request",
|
|
362
|
+
{
|
|
363
|
+
request: this.source
|
|
364
|
+
},
|
|
365
|
+
void 0,
|
|
366
|
+
metadata
|
|
367
|
+
);
|
|
368
|
+
future.onIOPub = handleIOPub;
|
|
369
|
+
future.onStdin = handleStdin;
|
|
370
|
+
future.onReply = handleReply;
|
|
371
|
+
return future;
|
|
372
|
+
}
|
|
373
|
+
respond(response, session) {
|
|
374
|
+
if (this.status !== "awaiting_input" || !this._current_input_request_message) {
|
|
375
|
+
return;
|
|
376
|
+
}
|
|
377
|
+
this.events.push({
|
|
378
|
+
type: "user_answer",
|
|
379
|
+
content: response
|
|
380
|
+
});
|
|
381
|
+
session.kernel?.sendInputReply(
|
|
382
|
+
{
|
|
383
|
+
"value": response,
|
|
384
|
+
"status": "ok"
|
|
385
|
+
},
|
|
386
|
+
this._current_input_request_message.header
|
|
387
|
+
);
|
|
388
|
+
this.status = "busy";
|
|
389
|
+
this._current_input_request_message = void 0;
|
|
390
|
+
}
|
|
391
|
+
toMultipleCells() {
|
|
392
|
+
class JoinableMarkdown extends String {
|
|
393
|
+
prefix = "";
|
|
394
|
+
suffix = "";
|
|
395
|
+
}
|
|
396
|
+
class AgentMarkdown extends JoinableMarkdown {
|
|
397
|
+
prefix = `
|
|
398
|
+
### Agent:
|
|
399
|
+
<div style="display: flex; width: 100%;">
|
|
400
|
+
<div style="padding: 0.2rem; margin: 0.2rem; margin-left: 4rem;">
|
|
401
|
+
|
|
402
|
+
`;
|
|
403
|
+
suffix = `</div></div>
|
|
404
|
+
|
|
405
|
+
`;
|
|
406
|
+
}
|
|
407
|
+
class FinalResponseMarkdown extends AgentMarkdown {
|
|
408
|
+
}
|
|
409
|
+
class UserMarkdown extends JoinableMarkdown {
|
|
410
|
+
prefix = `
|
|
411
|
+
### User:
|
|
412
|
+
<div style="display: flex; width: 100%;">
|
|
413
|
+
<div style="padding: 0.2rem; margin: 0.2rem; margin-left: 4rem;">
|
|
414
|
+
|
|
415
|
+
`;
|
|
416
|
+
suffix = `</div></div>
|
|
417
|
+
|
|
418
|
+
`;
|
|
419
|
+
}
|
|
420
|
+
const parentMetadata = {
|
|
421
|
+
...this.metadata,
|
|
422
|
+
beaker_cell_type: "query",
|
|
423
|
+
prompt: this.source,
|
|
424
|
+
events: this.events
|
|
425
|
+
};
|
|
426
|
+
const eventElements = this.events.map((event) => {
|
|
427
|
+
if (event.type === "thought") {
|
|
428
|
+
const lines = [];
|
|
429
|
+
if (event.content.thought) {
|
|
430
|
+
lines.push(`${event.content.thought} `);
|
|
431
|
+
}
|
|
432
|
+
for (const tc of event.content.tool_calls || []) {
|
|
433
|
+
const argsBlob = JSON.stringify(tc.tool_input ?? {});
|
|
434
|
+
const stateLabel = tc.state ? ` [${tc.state}]` : "";
|
|
435
|
+
lines.push(`- \`${tc.tool_name}\`${stateLabel} — \`${argsBlob}\``);
|
|
436
|
+
if (tc.output_preview) {
|
|
437
|
+
const previewSuffix = tc.output_truncated ? "…" : "";
|
|
438
|
+
lines.push(` - output: \`${tc.output_preview}${previewSuffix}\``);
|
|
439
|
+
}
|
|
440
|
+
if (tc.error) {
|
|
441
|
+
lines.push(` - error: \`${tc.error.ename}: ${tc.error.evalue}\``);
|
|
442
|
+
}
|
|
443
|
+
}
|
|
444
|
+
return new AgentMarkdown(`${lines.join("\n")}
|
|
445
|
+
`);
|
|
446
|
+
} else if (event.type === "user_question") {
|
|
447
|
+
return new AgentMarkdown(`**Agent Question:**
|
|
448
|
+
> ${event.content}
|
|
449
|
+
`);
|
|
450
|
+
} else if (event.type === "user_answer") {
|
|
451
|
+
return new UserMarkdown(`**User Response:**
|
|
452
|
+
> ${event.content}
|
|
453
|
+
`);
|
|
454
|
+
} else if (event.type === "code_cell") {
|
|
455
|
+
const childCell = this.children.find((child) => child.id === event.content.cell_id);
|
|
456
|
+
if (childCell === void 0) {
|
|
457
|
+
throw `Failed to find child cell ${event.content.cell_id} in children`;
|
|
458
|
+
}
|
|
459
|
+
childCell.metadata.beaker_child_of = this.id;
|
|
460
|
+
childCell.metadata.beakerQueryCellChild = true;
|
|
461
|
+
return childCell;
|
|
462
|
+
} else if (event.type === "response") {
|
|
463
|
+
var output;
|
|
464
|
+
if (typeof event.content === "string") {
|
|
465
|
+
const lines = event.content.split("\n").map((line) => /^\s*$/.test(line) ? "" : `${line}`).map((line) => /^#+\s+/.test(line) ? `###${line}` : line);
|
|
466
|
+
output = `
|
|
467
|
+
${lines.join("\n")}`;
|
|
468
|
+
} else {
|
|
469
|
+
output = `
|
|
470
|
+
${event.content}`;
|
|
471
|
+
}
|
|
472
|
+
return new FinalResponseMarkdown(output);
|
|
473
|
+
} else if (event.type === "abort") {
|
|
474
|
+
return new JoinableMarkdown(event.content);
|
|
475
|
+
} else if (event.type === "error") {
|
|
476
|
+
return new BeakerMarkdownCell({
|
|
477
|
+
cell_type: "markdown",
|
|
478
|
+
id: v4(),
|
|
479
|
+
source: [JSON.stringify(event.content, void 0, 2)],
|
|
480
|
+
metadata: { ...parentMetadata, parentQueryCell: true, beakerQueryCellChild: true }
|
|
481
|
+
});
|
|
482
|
+
} else {
|
|
483
|
+
return new JoinableMarkdown(`Error: Unhandled query event type "${event.type}".`);
|
|
484
|
+
}
|
|
485
|
+
});
|
|
486
|
+
let outputElements = [
|
|
487
|
+
// new JoinableMarkdown('### User:'),
|
|
488
|
+
new UserMarkdown(`${this.source}`),
|
|
489
|
+
...eventElements
|
|
490
|
+
];
|
|
491
|
+
let lastSeenElement = null;
|
|
492
|
+
let cell = new BeakerMarkdownCell(
|
|
493
|
+
{
|
|
494
|
+
cell_type: "markdown",
|
|
495
|
+
id: this.id,
|
|
496
|
+
source: [],
|
|
497
|
+
// contains all parent metadata
|
|
498
|
+
metadata: { ...parentMetadata, parentQueryCell: true }
|
|
499
|
+
}
|
|
500
|
+
);
|
|
501
|
+
const outputCells = [
|
|
502
|
+
cell
|
|
503
|
+
];
|
|
504
|
+
for (let element of outputElements) {
|
|
505
|
+
if (element instanceof JoinableMarkdown) {
|
|
506
|
+
if (lastSeenElement === null && element.prefix) {
|
|
507
|
+
if (element.prefix) {
|
|
508
|
+
cell.source.push(element.prefix);
|
|
509
|
+
}
|
|
510
|
+
}
|
|
511
|
+
if (lastSeenElement === null || lastSeenElement.constructor === element.constructor) {
|
|
512
|
+
cell.source.push(element);
|
|
513
|
+
} else if (!(lastSeenElement instanceof JoinableMarkdown)) {
|
|
514
|
+
cell = new BeakerMarkdownCell({
|
|
515
|
+
cell_type: "markdown",
|
|
516
|
+
id: v4(),
|
|
517
|
+
source: [],
|
|
518
|
+
metadata: { skipWhenLoading: true, beakerQueryCellChild: true }
|
|
519
|
+
});
|
|
520
|
+
if (element instanceof FinalResponseMarkdown) {
|
|
521
|
+
cell.metadata.finalResponse = true;
|
|
522
|
+
}
|
|
523
|
+
if (element.prefix) {
|
|
524
|
+
cell.source.push(element.prefix);
|
|
525
|
+
}
|
|
526
|
+
cell.source.push(element);
|
|
527
|
+
outputCells.push(cell);
|
|
528
|
+
} else {
|
|
529
|
+
if (lastSeenElement.suffix) {
|
|
530
|
+
cell.source.push(lastSeenElement.suffix);
|
|
531
|
+
}
|
|
532
|
+
if (element.prefix) {
|
|
533
|
+
cell.source.push(element.prefix);
|
|
534
|
+
}
|
|
535
|
+
cell.source.push(element);
|
|
536
|
+
}
|
|
537
|
+
} else {
|
|
538
|
+
if (lastSeenElement instanceof JoinableMarkdown && lastSeenElement.suffix) {
|
|
539
|
+
cell.source.push(lastSeenElement.suffix);
|
|
540
|
+
}
|
|
541
|
+
outputCells.push(element);
|
|
542
|
+
}
|
|
543
|
+
lastSeenElement = element;
|
|
544
|
+
}
|
|
545
|
+
return outputCells;
|
|
546
|
+
}
|
|
547
|
+
// public fromJSON(obj: any) {
|
|
548
|
+
// if (this.metadata.beaker_cell_type !== "query") {
|
|
549
|
+
// throw TypeError("Cell is trying to be parsed as a query cell, but doesn't have the required metadata.")
|
|
550
|
+
// }
|
|
551
|
+
// this.source = obj.metadata.prompt;
|
|
552
|
+
// this.events = obj.metadata.events;
|
|
553
|
+
// }
|
|
554
|
+
// public toJSON() {
|
|
555
|
+
// return this.toMarkdownCell();
|
|
556
|
+
// }
|
|
557
|
+
fromIPynb(obj) {
|
|
558
|
+
if (this.metadata.beaker_cell_type !== "query") {
|
|
559
|
+
throw TypeError("Cell is trying to be parsed as a query cell, but doesn't have the required metadata.");
|
|
560
|
+
}
|
|
561
|
+
this.source = obj.metadata.prompt;
|
|
562
|
+
this.events = obj.metadata.events;
|
|
563
|
+
}
|
|
564
|
+
toIPynb() {
|
|
565
|
+
return this.toMultipleCells().flatMap((cell) => cell.toIPynb());
|
|
566
|
+
}
|
|
567
|
+
}
|
|
568
|
+
class BeakerNotebookContent {
|
|
569
|
+
nbformat = 4;
|
|
570
|
+
nbformat_minor = 5;
|
|
571
|
+
metadata = {};
|
|
572
|
+
cells = [];
|
|
573
|
+
}
|
|
574
|
+
class BeakerNotebook {
|
|
575
|
+
constructor() {
|
|
576
|
+
this.content = {
|
|
577
|
+
nbformat: 4,
|
|
578
|
+
nbformat_minor: 5,
|
|
579
|
+
cells: [],
|
|
580
|
+
metadata: {
|
|
581
|
+
"kernelspec": {
|
|
582
|
+
"display_name": "Beaker Kernel",
|
|
583
|
+
"name": "beaker",
|
|
584
|
+
"language": "beaker"
|
|
585
|
+
},
|
|
586
|
+
"language_info": this.subkernelInfo
|
|
587
|
+
}
|
|
588
|
+
};
|
|
589
|
+
this.cells = new Proxy(this.content.cells, {});
|
|
590
|
+
}
|
|
591
|
+
toJSON() {
|
|
592
|
+
this.content.metadata.language_info = this.subkernelInfo;
|
|
593
|
+
return { ...this.content };
|
|
594
|
+
}
|
|
595
|
+
fromJSON(obj) {
|
|
596
|
+
Object.keys(obj).forEach((key) => {
|
|
597
|
+
this.content[key] = obj[key];
|
|
598
|
+
});
|
|
599
|
+
this.cells = new Proxy(this.content.cells, {});
|
|
600
|
+
}
|
|
601
|
+
loadFromIPynb(obj) {
|
|
602
|
+
this.content.nbformat = obj.nbformat;
|
|
603
|
+
this.content.nbformat_minor = obj.nbformat_minor;
|
|
604
|
+
const cellList = obj.cells.map((cell) => {
|
|
605
|
+
if (cell.cell_type === "raw") {
|
|
606
|
+
return new BeakerRawCell(cell);
|
|
607
|
+
} else if (cell.cell_type === "code") {
|
|
608
|
+
return new BeakerCodeCell(cell);
|
|
609
|
+
} else if (cell.metadata.beaker_cell_type === "query") {
|
|
610
|
+
return new BeakerQueryCell({
|
|
611
|
+
cell_type: "query",
|
|
612
|
+
id: cell.id,
|
|
613
|
+
source: cell.metadata.prompt,
|
|
614
|
+
events: cell.metadata.events,
|
|
615
|
+
metadata: cell.metadata
|
|
616
|
+
});
|
|
617
|
+
} else if (cell.cell_type === "markdown") {
|
|
618
|
+
if (cell.metadata?.skipWhenLoading === true) {
|
|
619
|
+
return;
|
|
620
|
+
}
|
|
621
|
+
return new BeakerMarkdownCell(cell);
|
|
622
|
+
} else {
|
|
623
|
+
return new BeakerRawCell(cell);
|
|
624
|
+
}
|
|
625
|
+
}).filter((cell) => cell);
|
|
626
|
+
let cellMap = {};
|
|
627
|
+
cellList.forEach((cell) => {
|
|
628
|
+
cellMap[cell.id] = cell;
|
|
629
|
+
});
|
|
630
|
+
let i = 0;
|
|
631
|
+
while (i < cellList.length) {
|
|
632
|
+
const cell = cellList[i];
|
|
633
|
+
if (typeof cell.metadata.beaker_child_of !== "undefined") {
|
|
634
|
+
cellMap[cell.metadata.beaker_child_of].children.push(cellList.splice(i, 1)[0]);
|
|
635
|
+
} else {
|
|
636
|
+
i++;
|
|
637
|
+
}
|
|
638
|
+
}
|
|
639
|
+
this.cells.splice(
|
|
640
|
+
0,
|
|
641
|
+
this.cells.length,
|
|
642
|
+
...cellList
|
|
643
|
+
);
|
|
644
|
+
this.content.metadata = obj.metadata;
|
|
645
|
+
}
|
|
646
|
+
toIPynb() {
|
|
647
|
+
this.content.metadata.language_info = this.subkernelInfo;
|
|
648
|
+
return {
|
|
649
|
+
nbformat: this.content.nbformat,
|
|
650
|
+
nbformat_minor: this.content.nbformat_minor,
|
|
651
|
+
cells: this.content.cells.flatMap((cell) => cell.toIPynb()),
|
|
652
|
+
metadata: this.content.metadata
|
|
653
|
+
};
|
|
654
|
+
}
|
|
655
|
+
addCell(cell) {
|
|
656
|
+
this.cells.push(cell);
|
|
657
|
+
}
|
|
658
|
+
insertCell(cell, position) {
|
|
659
|
+
this.cells.splice(position, 0, cell);
|
|
660
|
+
}
|
|
661
|
+
removeCell(index) {
|
|
662
|
+
this.cells.splice(index, 1);
|
|
663
|
+
}
|
|
664
|
+
cutCell(index) {
|
|
665
|
+
const removedValues = this.cells.splice(index, 1);
|
|
666
|
+
if (removedValues.length > 0) {
|
|
667
|
+
return removedValues[0];
|
|
668
|
+
}
|
|
669
|
+
return null;
|
|
670
|
+
}
|
|
671
|
+
moveCell(fromIndex, toIndex) {
|
|
672
|
+
if (fromIndex !== toIndex) {
|
|
673
|
+
const cell = this.cutCell(fromIndex);
|
|
674
|
+
if (cell) {
|
|
675
|
+
this.insertCell(cell, toIndex);
|
|
676
|
+
}
|
|
677
|
+
}
|
|
678
|
+
}
|
|
679
|
+
setSubkernelInfo(sessionInfo) {
|
|
680
|
+
this.subkernelInfo = {
|
|
681
|
+
"name": sessionInfo.subkernel,
|
|
682
|
+
"display_name": sessionInfo.language
|
|
683
|
+
};
|
|
684
|
+
}
|
|
685
|
+
content;
|
|
686
|
+
cells;
|
|
687
|
+
subkernelInfo;
|
|
688
|
+
}
|
|
689
|
+
|
|
690
|
+
export { BeakerBaseCell, BeakerCodeCell, BeakerMarkdownCell, BeakerNotebook, BeakerNotebookContent, BeakerQueryCell, BeakerRawCell };
|