@@ -16,163 +16,40 @@ export interface CreateKernelProps {
1616 */
1717export class CodeInterpreter extends Sandbox {
1818 private static template = 'code-interpreter-stateful'
19- public notebook : JupyterExtension
19+
20+ readonly notebook = new JupyterExtension ( this )
2021
2122 constructor ( opts ?: SandboxOpts ) {
2223 super ( { template : opts ?. template || CodeInterpreter . template , ...opts } )
23- this . notebook = new JupyterExtension ( this )
24- }
25-
26- /**
27- * Creates a new CodeInterpreter sandbox.
28- * @returns New CodeInterpreter sandbox
29- *
30- * @example
31- * ```ts
32- * const sandbox = await CodeInterpreter.create()
33- * ```
34- * @constructs CodeInterpreter
35- */
36- static async create < S extends typeof CodeInterpreter > (
37- this : S
38- ) : Promise < InstanceType < S > >
39- /**
40- * Creates a new CodeInterpreter sandbox from the template with the specified ID.
41- * @param template Sandbox template ID or name (this extension has some specific requirements for the template, refer to docs for more info)
42- * @returns New CodeInterpreter sandbox
43- *
44- * @example
45- * ```ts
46- * const sandbox = await CodeInterpreter.create("sandboxTemplateID")
47- * ```
48- */
49- static async create < S extends typeof CodeInterpreter > (
50- this : S ,
51- template : string
52- ) : Promise < InstanceType < S > >
53- /**
54- * Creates a new CodeInterpreter from the specified options.
55- * @param opts Sandbox options
56- * @returns New CodeInterpreter
57- *
58- * @example
59- * ```ts
60- * const sandbox = await CodeInterpreter.create({
61- * onStdout: console.log,
62- * })
63- * ```
64- */
65- static async create < S extends typeof CodeInterpreter > (
66- this : S ,
67- opts : SandboxOpts
68- ) : Promise < InstanceType < S > >
69- static async create ( optsOrTemplate ?: string | SandboxOpts ) {
70- const opts : SandboxOpts | undefined =
71- typeof optsOrTemplate === 'string'
72- ? { template : optsOrTemplate }
73- : optsOrTemplate
74- const sandbox = new this ( opts )
75- await sandbox . _open ( { timeout : opts ?. timeout } )
76-
77- // Connect to the default kernel, do this in the background
78- sandbox . notebook . connect ( )
79-
80- return sandbox
8124 }
8225
83- /**
84- * Reconnects to an existing CodeInterpreter.
85- * @param sandboxID Sandbox ID
86- * @returns Existing CodeInterpreter
87- *
88- * @example
89- * ```ts
90- * const sandbox = await CodeInterpreter.create()
91- * const sandboxID = sandbox.id
92- *
93- * await sandbox.keepAlive(300 * 1000)
94- * await sandbox.close()
95- *
96- * const reconnectedSandbox = await CodeInterpreter.reconnect(sandboxID)
97- * ```
98- */
99- static async reconnect < S extends typeof CodeInterpreter > (
100- this : S ,
101- sandboxID : string
102- ) : Promise < InstanceType < S > >
103- /**
104- * Reconnects to an existing CodeInterpreter.
105- * @param opts Sandbox options
106- * @returns Existing CodeInterpreter
107- *
108- * @example
109- * ```ts
110- * const sandbox = await CodeInterpreter.create()
111- * const sandboxID = sandbox.id
112- *
113- * await sandbox.keepAlive(300 * 1000)
114- * await sandbox.close()
115- *
116- * const reconnectedSandbox = await CodeInterpreter.reconnect({
117- * sandboxID,
118- * })
119- * ```
120- */
121- static async reconnect < S extends typeof CodeInterpreter > (
122- this : S ,
123- opts : Omit < SandboxOpts , 'id' | 'template' > & { sandboxID : string }
124- ) : Promise < InstanceType < S > >
125- static async reconnect < S extends typeof CodeInterpreter > (
126- this : S ,
127- sandboxIDorOpts :
128- | string
129- | ( Omit < SandboxOpts , 'id' | 'template' > & { sandboxID : string } )
130- ) : Promise < InstanceType < S > > {
131- let id : string
132- let opts : SandboxOpts
133- if ( typeof sandboxIDorOpts === 'string' ) {
134- id = sandboxIDorOpts
135- opts = { }
136- } else {
137- id = sandboxIDorOpts . sandboxID
138- opts = sandboxIDorOpts
139- }
140-
141- const sandboxIDAndClientID = id . split ( '-' )
142- const sandboxID = sandboxIDAndClientID [ 0 ]
143- const clientID = sandboxIDAndClientID [ 1 ]
144- opts . __sandbox = { sandboxID, clientID, templateID : 'unknown' }
26+ override async _open ( opts ?: { timeout ?: number } ) {
27+ await super . _open ( { timeout : opts ?. timeout } )
28+ await this . notebook . connect ( opts ?. timeout )
14529
146- const sandbox = new this ( opts ) as InstanceType < S >
147- await sandbox . _open ( { timeout : opts ?. timeout } )
148-
149- sandbox . notebook . connect ( )
150- return sandbox
30+ return this
15131 }
15232
153- async close ( ) {
33+ override async close ( ) {
15434 await this . notebook . close ( )
15535 await super . close ( )
15636 }
15737}
15838
15939export class JupyterExtension {
160- private readonly defaultKernelID : Promise < string >
161- private readonly setDefaultKernelID : ( kernelID : string ) => void
162- private connectedKernels : Kernels = { }
163- private sandbox : CodeInterpreter
164-
165- constructor ( sandbox : CodeInterpreter ) {
166- this . sandbox = sandbox
167- const { promise, resolve } = createDeferredPromise < string > ( )
168- this . defaultKernelID = promise
169- this . setDefaultKernelID = resolve
40+ private readonly connectedKernels : Kernels = { }
41+
42+ private readonly kernelIDPromise = createDeferredPromise < string > ( )
43+ private readonly setDefaultKernelID = this . kernelIDPromise . resolve
44+
45+ private get defaultKernelID ( ) {
46+ return this . kernelIDPromise . promise
17047 }
17148
49+ constructor ( private sandbox : CodeInterpreter ) { }
50+
17251 async connect ( timeout ?: number ) {
173- return this . startConnectingToDefaultKernel ( this . setDefaultKernelID , {
174- timeout : timeout
175- } )
52+ return this . startConnectingToDefaultKernel ( this . setDefaultKernelID , { timeout } )
17653 }
17754
17855 /**
@@ -192,24 +69,15 @@ export class JupyterExtension {
19269 onStdout ?: ( msg : ProcessMessage ) => any ,
19370 onStderr ?: ( msg : ProcessMessage ) => any
19471 ) : Promise < Result > {
195- kernelID = kernelID || ( await this . defaultKernelID )
196- let ws = this . connectedKernels [ kernelID ]
197-
198- if ( ! ws ) {
199- const url = `${ this . sandbox . getProtocol (
200- 'ws'
201- ) } ://${ this . sandbox . getHostname ( 8888 ) } /api/kernels/${ kernelID } /channels`
202- ws = new JupyterKernelWebSocket ( url )
203- await ws . connect ( )
204- this . connectedKernels [ kernelID ] = ws
205- }
72+ kernelID = kernelID || await this . defaultKernelID
73+ const ws = this . connectedKernels [ kernelID ] || await this . connectToKernelWS ( kernelID )
20674
20775 return await ws . sendExecutionMessage ( code , onStdout , onStderr )
20876 }
20977
21078 private async startConnectingToDefaultKernel (
21179 resolve : ( value : string ) => void ,
212- opts ?: { timeout ?: number }
80+ opts ?: { timeout ?: number } ,
21381 ) {
21482 const kernelID = (
21583 await this . sandbox . filesystem . read ( '/root/.jupyter/kernel_id' , opts )
@@ -236,6 +104,8 @@ export class JupyterExtension {
236104 const ws = new JupyterKernelWebSocket ( url )
237105 await ws . connect ( )
238106 this . connectedKernels [ kernelID ] = ws
107+
108+ return ws
239109 }
240110
241111 /**
@@ -361,7 +231,7 @@ export class JupyterExtension {
361231 * Close all the websocket connections to the kernels. It doesn't shutdown the kernels.
362232 */
363233 async close ( ) {
364- for ( const kernelID in this . connectedKernels ) {
234+ for ( const kernelID of Object . keys ( this . connectedKernels ) ) {
365235 this . connectedKernels [ kernelID ] . close ( )
366236 }
367237 }
0 commit comments