1use futures::{channel::mpsc, StreamExt as _};
2use gpui::AppContext;
3use jupyter_protocol::{ExecutionState, JupyterMessage, KernelInfoReply};
4// todo(kyle): figure out if this needs to be different
5use runtimelib::JupyterKernelspec;
6
7use super::RunningKernel;
8use jupyter_websocket_client::RemoteServer;
9use std::fmt::Debug;
10
11#[derive(Debug, Clone)]
12pub struct RemoteKernelSpecification {
13 pub name: String,
14 pub url: String,
15 pub token: String,
16 pub kernelspec: JupyterKernelspec,
17}
18
19impl PartialEq for RemoteKernelSpecification {
20 fn eq(&self, other: &Self) -> bool {
21 self.name == other.name && self.url == other.url
22 }
23}
24
25impl Eq for RemoteKernelSpecification {}
26
27pub struct RemoteRunningKernel {
28 remote_server: RemoteServer,
29 pub working_directory: std::path::PathBuf,
30 pub request_tx: mpsc::Sender<JupyterMessage>,
31 pub execution_state: ExecutionState,
32 pub kernel_info: Option<KernelInfoReply>,
33}
34
35impl RemoteRunningKernel {
36 pub async fn new(
37 kernelspec: RemoteKernelSpecification,
38 working_directory: std::path::PathBuf,
39 request_tx: mpsc::Sender<JupyterMessage>,
40 _cx: &mut AppContext,
41 ) -> anyhow::Result<(
42 Self,
43 (), // Stream<Item=JupyterMessage>
44 )> {
45 let remote_server = RemoteServer {
46 base_url: kernelspec.url,
47 token: kernelspec.token,
48 };
49
50 // todo: launch a kernel to get a kernel ID
51 let kernel_id = "not-implemented";
52
53 let kernel_socket = remote_server.connect_to_kernel(kernel_id).await?;
54
55 let (mut _w, mut _r) = kernel_socket.split();
56
57 let (_messages_tx, _messages_rx) = mpsc::channel::<JupyterMessage>(100);
58
59 // let routing_task = cx.background_executor().spawn({
60 // async move {
61 // while let Some(message) = request_rx.next().await {
62 // w.send(message).await;
63 // }
64 // }
65 // });
66 // let messages_rx = r.into();
67
68 anyhow::Ok((
69 Self {
70 remote_server,
71 working_directory,
72 request_tx,
73 execution_state: ExecutionState::Idle,
74 kernel_info: None,
75 },
76 (),
77 ))
78 }
79}
80
81impl Debug for RemoteRunningKernel {
82 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
83 f.debug_struct("RemoteRunningKernel")
84 // custom debug that keeps tokens out of logs
85 .field("remote_server url", &self.remote_server.base_url)
86 .field("working_directory", &self.working_directory)
87 .field("request_tx", &self.request_tx)
88 .field("execution_state", &self.execution_state)
89 .field("kernel_info", &self.kernel_info)
90 .finish()
91 }
92}
93
94impl RunningKernel for RemoteRunningKernel {
95 fn request_tx(&self) -> futures::channel::mpsc::Sender<runtimelib::JupyterMessage> {
96 self.request_tx.clone()
97 }
98
99 fn working_directory(&self) -> &std::path::PathBuf {
100 &self.working_directory
101 }
102
103 fn execution_state(&self) -> &runtimelib::ExecutionState {
104 &self.execution_state
105 }
106
107 fn set_execution_state(&mut self, state: runtimelib::ExecutionState) {
108 self.execution_state = state;
109 }
110
111 fn kernel_info(&self) -> Option<&runtimelib::KernelInfoReply> {
112 self.kernel_info.as_ref()
113 }
114
115 fn set_kernel_info(&mut self, info: runtimelib::KernelInfoReply) {
116 self.kernel_info = Some(info);
117 }
118
119 fn force_shutdown(&mut self) -> anyhow::Result<()> {
120 unimplemented!("force_shutdown")
121 }
122}