@1kbirds/chidori 0.1.20 → 0.1.23

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.
@@ -1,10 +1,14 @@
1
1
  use std::cell::RefCell;
2
2
  use std::collections::{HashMap, VecDeque};
3
+ use std::future::Future;
3
4
  use std::marker::PhantomData;
5
+ use std::sync::{Arc};
6
+ use tokio::sync::{mpsc, Mutex};
4
7
  use anyhow::Error;
5
8
  use futures::StreamExt;
6
9
  use log::{debug, info};
7
10
  use neon::{prelude::*, types::Deferred};
11
+ use neon::handle::Managed;
8
12
  use neon::result::Throw;
9
13
  use once_cell::sync::OnceCell;
10
14
  use tokio::runtime::Runtime;
@@ -15,7 +19,9 @@ use prompt_graph_core::proto2::execution_runtime_client::ExecutionRuntimeClient;
15
19
  use prompt_graph_core::proto2::serialized_value::Val;
16
20
  use prompt_graph_exec::tonic_runtime::run_server;
17
21
  use neon_serde3;
22
+ use prost::bytes::Buf;
18
23
  use serde::{Deserialize, Serialize};
24
+ use crate::translations::rust::{Chidori, CustomNodeCreateOpts, DenoCodeNodeCreateOpts, GraphBuilder, Handler, NodeHandle, PromptNodeCreateOpts, VectorMemoryNodeCreateOpts};
19
25
 
20
26
  // Return a global tokio runtime or create one if it doesn't exist.
21
27
  // Throws a JavaScript exception if the `Runtime` fails to create.
@@ -31,25 +37,6 @@ async fn get_client(url: String) -> Result<ExecutionRuntimeClient<tonic::transpo
31
37
  }
32
38
 
33
39
 
34
- async fn push_file_merge(url: &String, file_id: &String, node: Item) -> anyhow::Result<NodeHandle> {
35
- let mut client = get_client(url.clone()).await?;
36
- let exec_status = client.merge(RequestFileMerge {
37
- id: file_id.clone(),
38
- file: Some(File {
39
- nodes: vec![node.clone()],
40
- ..Default::default()
41
- }),
42
- branch: 0,
43
- }).await?.into_inner();
44
- Ok(NodeHandle::from(
45
- url.clone(),
46
- file_id.clone(),
47
- node,
48
- exec_status
49
- )?)
50
- }
51
-
52
-
53
40
  #[derive(Debug)]
54
41
  pub struct SerializedValueWrapper(SerializedValue);
55
42
 
@@ -116,161 +103,69 @@ fn from_js_value<'a, C: Context<'a>>(cx: &mut C, value: Handle<JsValue>) -> Neon
116
103
  cx.throw_error("Unsupported type")
117
104
  }
118
105
 
106
+ macro_rules! return_or_throw_deferred {
107
+ ($channel:expr, $deferred:expr, $m:expr) => {
108
+ if let Ok(result) = $m {
109
+ $deferred.settle_with($channel, move |mut cx| {
110
+ neon_serde3::to_value(&mut cx, &result)
111
+ .or_else(|e| cx.throw_error(e.to_string()))
112
+ });
113
+ } else {
114
+ $deferred.settle_with($channel, move |mut cx| {
115
+ cx.throw_error("Error playing")
116
+ });
117
+ }
118
+ };
119
+ }
120
+
119
121
 
120
122
  // Node handle
121
123
  #[derive(Clone)]
122
- pub struct NodeHandle {
123
- url: String,
124
- file_id: String,
125
- node: Item,
126
- exec_status: ExecutionStatus,
127
- indiv: CleanIndividualNode
124
+ pub struct NodeNodeHandle {
125
+ n: NodeHandle
128
126
  }
129
127
 
130
- impl NodeHandle {
131
- fn example() -> Self{
132
- let node = create_code_node(
133
- "Example".to_string(),
134
- vec![None],
135
- "type O { output: String }".to_string(),
136
- SourceNodeType::Code("DENO".to_string(), r#"return {"output": "hello"}"#.to_string(), false),
137
- vec![],
138
- );
139
- let indiv = derive_for_individual_node(&node).unwrap();
140
- NodeHandle {
141
- url: "localhost:9800".to_string(),
142
- file_id: "0".to_string(),
143
- node: node,
144
- exec_status: Default::default(),
145
- indiv,
146
- }
147
- }
148
-
149
- fn from(url: String, file_id: String, node: Item, exec_status: ExecutionStatus) -> anyhow::Result<NodeHandle> {
150
- let indiv = derive_for_individual_node(&node)?;
151
- Ok(NodeHandle {
152
- url,
153
- file_id,
154
- node,
155
- exec_status,
156
- indiv
157
- })
128
+ impl NodeNodeHandle {
129
+ fn from(n: NodeHandle) -> NodeNodeHandle {
130
+ NodeNodeHandle{ n }
158
131
  }
159
132
  }
160
133
 
161
- impl Finalize for NodeHandle {}
162
-
134
+ impl Finalize for NodeNodeHandle {}
163
135
 
164
- impl NodeHandle {
165
- pub fn js_debug_example(mut cx: FunctionContext) -> JsResult<JsBox<RefCell<NodeHandle>>> {
166
- let nh = NodeHandle::example();
167
- Ok(cx.boxed(RefCell::new(nh)))
168
- }
169
136
 
137
+ impl NodeNodeHandle {
170
138
  fn get_name(&self) -> String {
171
- self.node.core.as_ref().unwrap().name.clone()
139
+ self.n.get_name()
172
140
  }
173
141
 
174
142
  pub fn run_when(mut cx: FunctionContext) -> JsResult<JsPromise> {
175
143
  let channel = cx.channel();
176
144
  let (deferred, promise) = cx.promise();
177
- let other_node = cx.argument::<JsBox<RefCell<NodeHandle>>>(0)?.downcast_or_throw::<JsBox<RefCell<NodeHandle>>, _>(&mut cx)?;
178
-
179
- let self_ = cx.this()
180
- .downcast_or_throw::<JsBox<RefCell<NodeHandle>>, _>(&mut cx)?;
181
-
182
- let mut self_borrow = self_.borrow_mut();
183
- let queries = &mut self_borrow.node.core.as_mut().unwrap().queries;
184
-
185
- // Get the constructed query from the target node
186
- let q = construct_query_from_output_type(
187
- &other_node.borrow().get_name(),
188
- &other_node.borrow().get_name(),
189
- &self_.borrow().indiv.output_path
190
- ).unwrap();
191
-
192
- queries.push(Query { query: Some(q)});
193
-
194
- let url = self_.borrow().url.clone();
195
- let file_id = self_.borrow().file_id.clone();
196
- let node = self_.borrow().node.clone();
197
- let rt = runtime(&mut cx)?;
198
- rt.spawn(async move {
199
- let result = push_file_merge(&url, &file_id, node).await.unwrap();
200
- deferred.settle_with(&channel, move |mut cx| {
201
- Ok(cx.boolean(true))
202
- });
203
- });
204
- Ok(promise)
205
- }
206
-
207
-
208
- pub fn query(mut cx: FunctionContext) -> JsResult<JsPromise> {
209
- let (deferred, promise) = cx.promise();
210
- let channel = cx.channel();
211
-
212
- let branch = cx.argument::<JsNumber>(0)?.value(&mut cx) as u64;
213
- let frame = cx.argument::<JsNumber>(1)?.value(&mut cx) as u64;
214
-
215
145
  let self_ = cx.this()
216
- .downcast_or_throw::<JsBox<RefCell<NodeHandle>>, _>(&mut cx)?;
217
- let mut self_borrow = self_.borrow();
218
- let file_id = self_borrow.file_id.clone();
219
- let url = self_borrow.url.clone();
220
- let name = &self_borrow.node.core.as_ref().unwrap().name;
221
-
222
- let query = construct_query_from_output_type(&name, &name, &self_.borrow().indiv.output_path).unwrap();
223
-
224
- let rt = runtime(&mut cx)?;
225
- rt.spawn(async move {
226
- let mut client = if let Ok(mut client) = get_client(url).await {
227
- client
146
+ .downcast_or_throw::<JsBox<RefCell<NodeNodeHandle>>, _>(&mut cx)?;
147
+
148
+ let graph_builder = cx.argument::<JsBox<NodeGraphBuilder>>(0)?;
149
+ let other_node_handle = cx.argument::<JsBox<RefCell<NodeNodeHandle>>>(1)?;
150
+
151
+ let mut n = &mut self_.borrow_mut().n;
152
+ let g = &graph_builder.g;
153
+ let mut graph_builder = g.blocking_lock();
154
+ let other_node = &other_node_handle.borrow().n;
155
+ let m = n.run_when(&mut graph_builder, &other_node);
156
+ deferred.settle_with((&channel), move |mut cx| {
157
+ if let Ok(result) = m {
158
+ Ok(cx.boolean(result))
228
159
  } else {
229
- deferred.settle_with(&channel, move |mut cx| {
230
- cx.throw_error::<&str, JsUndefined>("Failed to connect to runtime service.");
231
- Ok(cx.undefined())
232
- });
233
- panic!("Failed to connect to runtime service.");
234
- };
235
- let result = client.run_query(QueryAtFrame {
236
- id: file_id,
237
- query: Some(Query {
238
- query: Some(query)
239
- }),
240
- frame,
241
- branch,
242
- }).await;
243
- deferred.settle_with(&channel, move |mut cx| {
244
- if let Ok(result) = result {
245
- let res = result.into_inner();
246
- let mut obj = cx.empty_object();
247
- for value in res.values.iter() {
248
- let c = value.change_value.as_ref().unwrap();
249
- let k = c.path.as_ref().unwrap().address.join(":");
250
- let v = c.value.as_ref().unwrap().clone();
251
- let js = SerializedValueWrapper(v).to_object(&mut cx);
252
- obj.set(&mut cx, k.as_str(), js?).unwrap();
253
- }
254
- Ok(obj)
255
- } else {
256
- cx.throw_error("Failed to query")
257
- }
258
- });
160
+ cx.throw_error("Error playing")
161
+ }
259
162
  });
260
163
  Ok(promise)
261
- }
262
164
 
165
+ }
263
166
 
264
- // fn js_to_string(mut cx: FunctionContext) -> JsResult<JsUndefined> {
265
- // let branch = cx.argument::<JsString>(0)?.value(&mut cx);
266
- // let frame = cx.argument::<JsString>(1)?.value(&mut cx);
167
+ // pub fn query(mut cx: FunctionContext) -> JsResult<JsPromise> {
267
168
  //
268
- // let channel = cx.channel();
269
- //
270
- // // let name = self.get_name();
271
- // Ok(format!("NodeHandle(file_id={}, node={})", self.file_id, name))
272
- // //
273
- // // Ok(cx.undefined())
274
169
  // }
275
170
  }
276
171
 
@@ -305,64 +200,15 @@ fn obj_to_paths<'a, C: Context<'a>>(cx: &mut C, d: Handle<JsObject>) -> NeonResu
305
200
  Ok(paths)
306
201
  }
307
202
 
308
-
309
-
310
-
311
- #[derive(serde::Serialize, serde::Deserialize)]
312
- struct PromptNodeCreateOpts {
313
- name: String,
314
- queries: Option<Vec<String>>,
315
- output_tables: Option<Vec<String>>,
316
- template: String,
317
- model: Option<String>
203
+ struct NodeChidori {
204
+ c: Arc<Mutex<Chidori>>
318
205
  }
319
206
 
207
+ impl Finalize for NodeChidori {}
320
208
 
321
- #[derive(serde::Serialize, serde::Deserialize)]
322
- struct CustomNodeCreateOpts {
323
- name: String,
324
- queries: Option<Vec<String>>,
325
- output_tables: Option<Vec<String>>,
326
- output: Option<String>,
327
- node_type_name: String
328
- }
209
+ impl NodeChidori {
329
210
 
330
- #[derive(serde::Serialize, serde::Deserialize)]
331
- struct DenoCodeNodeCreateOpts {
332
- name: String,
333
- queries: Option<Vec<String>>,
334
- output_tables: Option<Vec<String>>,
335
- output: Option<String>,
336
- code: String,
337
- is_template: Option<bool>
338
- }
339
-
340
- #[derive(serde::Serialize, serde::Deserialize)]
341
- struct VectorMemoryNodeCreateOpts {
342
- name: String,
343
- queries: Option<Vec<String>>,
344
- output_tables: Option<Vec<String>>,
345
- output: Option<String>,
346
- template: Option<String>, // TODO: default is the contents of the query
347
- action: Option<String>, // TODO: default WRITE
348
- embedding_model: Option<String>, // TODO: default TEXT_EMBEDDING_ADA_002
349
- db_vendor: Option<String>, // TODO: default QDRANT
350
- collection_name: String,
351
- }
352
-
353
-
354
- struct Chidori {
355
- file_id: String,
356
- current_head: u64,
357
- current_branch: u64,
358
- url: String
359
- }
360
-
361
- impl Finalize for Chidori {}
362
-
363
- impl Chidori {
364
-
365
- fn js_new(mut cx: FunctionContext) -> JsResult<JsBox<Chidori>> {
211
+ fn js_new(mut cx: FunctionContext) -> JsResult<JsBox<NodeChidori>> {
366
212
  let file_id = cx.argument::<JsString>(0)?.value(&mut cx);
367
213
  let url = cx.argument::<JsString>(1)?.value(&mut cx);
368
214
 
@@ -371,55 +217,29 @@ impl Chidori {
371
217
  }
372
218
  // let api_token = cx.argument_opt(2)?.value(&mut cx);
373
219
  debug!("Creating new Chidori instance with file_id={}, url={}, api_token={:?}", file_id, url, "".to_string());
374
- Ok(cx.boxed(Chidori {
375
- file_id,
376
- current_head: 0,
377
- current_branch: 0,
378
- url,
220
+ Ok(cx.boxed(NodeChidori {
221
+ c: Arc::new(Mutex::new(Chidori::new(file_id, url))),
379
222
  }))
380
223
  }
381
224
 
382
225
  fn start_server(mut cx: FunctionContext) -> JsResult<JsPromise> {
383
226
  let channel = cx.channel();
384
227
  let self_ = cx.this()
385
- .downcast_or_throw::<JsBox<Chidori>, _>(&mut cx)?;
228
+ .downcast_or_throw::<JsBox<NodeChidori>, _>(&mut cx)?;
386
229
  let (deferred, promise) = cx.promise();
387
- let url_server = self_.url.clone();
388
- let file_path: Option<String> = match cx.argument_opt(0) {
389
- Some(v) => Some(v.downcast_or_throw(&mut cx)),
390
- None => None,
391
- }.map(|p: JsResult<JsString>| p.unwrap().value(&mut cx));
392
- std::thread::spawn(move || {
393
- let result = run_server(url_server, file_path);
394
- match result {
395
- Ok(_) => {
396
- println!("Server exited");
397
- },
398
- Err(e) => {
399
- println!("Error running server: {}", e);
400
- },
401
- }
402
- });
403
-
404
- let url = self_.url.clone();
230
+ let file_path = cx.argument_opt(0).map(|x| x.downcast::<JsString, _>(&mut cx).unwrap().value(&mut cx));
231
+ let c = Arc::clone(&self_.c);
405
232
  let rt = runtime(&mut cx)?;
406
233
  rt.spawn(async move {
407
- 'retry: loop {
408
- let client = get_client(url.clone());
409
- match client.await {
410
- Ok(connection) => {
411
- eprintln!("Connection successfully established {:?}", &url);
412
- deferred.settle_with(&channel, move |mut cx| {
413
- Ok(cx.undefined())
414
- });
415
- break 'retry
416
- },
417
- Err(e) => {
418
- eprintln!("Error connecting to server: {} with Error {}. Retrying...", &url, &e.to_string());
419
- std::thread::sleep(std::time::Duration::from_millis(1000));
420
- }
234
+ let mut c = c.lock().await;
235
+ let m = c.start_server(file_path).await;
236
+ deferred.settle_with((&channel), move |mut cx| {
237
+ if let Ok(_) = m {
238
+ Ok(cx.undefined())
239
+ } else {
240
+ cx.throw_error("Error playing")
421
241
  }
422
- }
242
+ });
423
243
  });
424
244
  Ok(promise)
425
245
  }
@@ -428,73 +248,44 @@ impl Chidori {
428
248
  let channel = cx.channel();
429
249
  let (deferred, promise) = cx.promise();
430
250
  let self_ = cx.this()
431
- .downcast_or_throw::<JsBox<Chidori>, _>(&mut cx)?;
251
+ .downcast_or_throw::<JsBox<NodeChidori>, _>(&mut cx)?;
432
252
  let branch = cx.argument::<JsNumber>(0).unwrap_or(JsNumber::new(&mut cx, 0.0)).value(&mut cx) as u64;
433
253
  let frame = cx.argument::<JsNumber>(1).unwrap_or(JsNumber::new(&mut cx, 0.0)).value(&mut cx) as u64;
434
-
435
- let file_id = self_.file_id.clone();
436
- let url = self_.url.clone();
437
-
254
+ let c = Arc::clone(&self_.c);
438
255
  let rt = runtime(&mut cx)?;
439
256
  rt.spawn(async move {
440
- let mut client = if let Ok(mut client) = get_client(url).await {
441
- client
442
- } else {
443
- deferred.settle_with(&channel, move |mut cx| {
444
- cx.throw_error::<&str, JsUndefined>("Failed to connect to runtime service.");
445
- Ok(cx.undefined())
446
- });
447
- panic!("Failed to connect to runtime service.");
448
- };
449
- let result = client.play(RequestAtFrame {
450
- id: file_id,
451
- frame,
452
- branch,
453
- }).await;
454
- deferred.settle_with(&channel, move |mut cx| {
455
- if let Ok(result) = result {
456
- neon_serde3::to_value(&mut cx, &result.into_inner())
257
+ let c = c.lock().await;
258
+ let m = c.play(branch, frame).await;
259
+ deferred.settle_with((&channel), move |mut cx| {
260
+ if let Ok(result) = m {
261
+ neon_serde3::to_value(&mut cx, &result)
457
262
  .or_else(|e| cx.throw_error(e.to_string()))
458
263
  } else {
459
- cx.throw_error("Failed to play runtime.")
264
+ cx.throw_error("Error playing")
460
265
  }
461
266
  });
462
267
  });
463
268
  Ok(promise)
269
+
464
270
  }
465
271
 
466
272
  fn pause(mut cx: FunctionContext) -> JsResult<JsPromise> {
467
273
  let channel = cx.channel();
468
274
  let (deferred, promise) = cx.promise();
469
275
  let self_ = cx.this()
470
- .downcast_or_throw::<JsBox<Chidori>, _>(&mut cx)?;
276
+ .downcast_or_throw::<JsBox<NodeChidori>, _>(&mut cx)?;
471
277
  let frame = cx.argument::<JsNumber>(0).unwrap_or(JsNumber::new(&mut cx, 0.0)).value(&mut cx) as u64;
472
- let file_id = self_.file_id.clone();
473
- let url = self_.url.clone();
474
- let branch = self_.current_branch.clone();
475
-
278
+ let c = Arc::clone(&self_.c);
476
279
  let rt = runtime(&mut cx)?;
477
280
  rt.spawn(async move {
478
- let mut client = if let Ok(mut client) = get_client(url).await {
479
- client
480
- } else {
481
- deferred.settle_with(&channel, move |mut cx| {
482
- cx.throw_error::<&str, JsUndefined>("Failed to connect to runtime service.");
483
- Ok(cx.undefined())
484
- });
485
- panic!("Failed to connect to runtime service.");
486
- };
487
- let result = client.pause(RequestAtFrame {
488
- id: file_id,
489
- frame,
490
- branch,
491
- }).await;
492
- deferred.settle_with(&channel, move |mut cx| {
493
- if let Ok(result) = result {
494
- neon_serde3::to_value(&mut cx, &result.into_inner())
281
+ let c = c.lock().await;
282
+ let m = c.pause(frame).await;
283
+ deferred.settle_with((&channel), move |mut cx| {
284
+ if let Ok(result) = m {
285
+ neon_serde3::to_value(&mut cx, &result)
495
286
  .or_else(|e| cx.throw_error(e.to_string()))
496
287
  } else {
497
- cx.throw_error("Failed to play runtime.")
288
+ cx.throw_error("Error playing")
498
289
  }
499
290
  });
500
291
  });
@@ -505,33 +296,20 @@ impl Chidori {
505
296
  let channel = cx.channel();
506
297
  let (deferred, promise) = cx.promise();
507
298
  let self_ = cx.this()
508
- .downcast_or_throw::<JsBox<Chidori>, _>(&mut cx)?;
509
- let file_id = self_.file_id.clone();
510
- let url = self_.url.clone();
511
- let branch = self_.current_branch.clone();
299
+ .downcast_or_throw::<JsBox<NodeChidori>, _>(&mut cx)?;
300
+ let branch = cx.argument::<JsNumber>(0).unwrap_or(JsNumber::new(&mut cx, 0.0)).value(&mut cx) as u64;
301
+ let frame = cx.argument::<JsNumber>(1).unwrap_or(JsNumber::new(&mut cx, 0.0)).value(&mut cx) as u64;
302
+ let c = Arc::clone(&self_.c);
512
303
  let rt = runtime(&mut cx)?;
513
304
  rt.spawn(async move {
514
- let mut client = if let Ok(mut client) = get_client(url).await {
515
- client
516
- } else {
517
- deferred.settle_with(&channel, move |mut cx| {
518
- cx.throw_error::<&str, JsUndefined>("Failed to connect to runtime service.");
519
- Ok(cx.undefined())
520
- });
521
- panic!("Failed to connect to runtime service.");
522
- };
523
- let result = client.branch(RequestNewBranch {
524
- id: file_id,
525
- source_branch_id: branch,
526
- diverges_at_counter: 0,
527
- }).await;
528
- // TODO: need to somehow handle writing to the current_branch
529
- deferred.settle_with(&channel, move |mut cx| {
530
- if let Ok(result) = result {
531
- neon_serde3::to_value(&mut cx, &result.into_inner())
305
+ let c = c.lock().await;
306
+ let m = c.branch(branch, frame).await;
307
+ deferred.settle_with((&channel), move |mut cx| {
308
+ if let Ok(result) = m {
309
+ neon_serde3::to_value(&mut cx, &result)
532
310
  .or_else(|e| cx.throw_error(e.to_string()))
533
311
  } else {
534
- cx.throw_error("Failed to play runtime.")
312
+ cx.throw_error("Error playing")
535
313
  }
536
314
  });
537
315
  });
@@ -542,37 +320,22 @@ impl Chidori {
542
320
  let channel = cx.channel();
543
321
  let (deferred, promise) = cx.promise();
544
322
  let self_ = cx.this()
545
- .downcast_or_throw::<JsBox<Chidori>, _>(&mut cx)?;
323
+ .downcast_or_throw::<JsBox<NodeChidori>, _>(&mut cx)?;
546
324
  let query = cx.argument::<JsString>(0).unwrap_or(JsString::new(&mut cx, "")).value(&mut cx);
547
325
  let branch = cx.argument::<JsNumber>(1).unwrap_or(JsNumber::new(&mut cx, 0.0)).value(&mut cx) as u64;
548
326
  let frame = cx.argument::<JsNumber>(2).unwrap_or(JsNumber::new(&mut cx, 0.0)).value(&mut cx) as u64;
549
- let file_id = self_.file_id.clone();
550
- let url = self_.url.clone();
327
+
328
+ let c = Arc::clone(&self_.c);
551
329
  let rt = runtime(&mut cx)?;
552
330
  rt.spawn(async move {
553
- let mut client = if let Ok(mut client) = get_client(url).await {
554
- client
555
- } else {
556
- deferred.settle_with(&channel, move |mut cx| {
557
- cx.throw_error::<&str, JsUndefined>("Failed to connect to runtime service.");
558
- Ok(cx.undefined())
559
- });
560
- panic!("Failed to connect to runtime service.");
561
- };
562
- let result = client.run_query(QueryAtFrame {
563
- id: file_id,
564
- query: Some(Query {
565
- query: Some(query)
566
- }),
567
- frame,
568
- branch,
569
- }).await;
570
- deferred.settle_with(&channel, move |mut cx| {
571
- if let Ok(result) = result {
572
- neon_serde3::to_value(&mut cx, &result.into_inner())
331
+ let c = c.lock().await;
332
+ let m = c.query(query, branch, frame).await;
333
+ deferred.settle_with((&channel), move |mut cx| {
334
+ if let Ok(result) = m {
335
+ neon_serde3::to_value(&mut cx, &result)
573
336
  .or_else(|e| cx.throw_error(e.to_string()))
574
337
  } else {
575
- cx.throw_error("Failed to play runtime.")
338
+ cx.throw_error("Error playing")
576
339
  }
577
340
  });
578
341
  });
@@ -583,29 +346,18 @@ impl Chidori {
583
346
  let channel = cx.channel();
584
347
  let (deferred, promise) = cx.promise();
585
348
  let self_ = cx.this()
586
- .downcast_or_throw::<JsBox<Chidori>, _>(&mut cx)?;
587
- let file_id = self_.file_id.clone();
588
- let url = self_.url.clone();
349
+ .downcast_or_throw::<JsBox<NodeChidori>, _>(&mut cx)?;
350
+ let c = Arc::clone(&self_.c);
589
351
  let rt = runtime(&mut cx)?;
590
352
  rt.spawn(async move {
591
- let mut client = if let Ok(mut client) = get_client(url).await {
592
- client
593
- } else {
594
- deferred.settle_with(&channel, move |mut cx| {
595
- cx.throw_error::<&str, JsUndefined>("Failed to connect to runtime service.");
596
- Ok(cx.undefined())
597
- });
598
- panic!("Failed to connect to runtime service.");
599
- };
600
- let result = client.list_branches(RequestListBranches {
601
- id: file_id,
602
- }).await;
603
- deferred.settle_with(&channel, move |mut cx| {
604
- if let Ok(result) = result {
605
- neon_serde3::to_value(&mut cx, &result.into_inner())
353
+ let c = c.lock().await;
354
+ let m = c.list_branches().await;
355
+ deferred.settle_with((&channel), move |mut cx| {
356
+ if let Ok(result) = m {
357
+ neon_serde3::to_value(&mut cx, &result)
606
358
  .or_else(|e| cx.throw_error(e.to_string()))
607
359
  } else {
608
- cx.throw_error("Failed to play runtime.")
360
+ cx.throw_error("Error playing")
609
361
  }
610
362
  });
611
363
  });
@@ -616,82 +368,34 @@ impl Chidori {
616
368
  let channel = cx.channel();
617
369
  let (deferred, promise) = cx.promise();
618
370
  let self_ = cx.this()
619
- .downcast_or_throw::<JsBox<Chidori>, _>(&mut cx)?;
620
- let file_id = self_.file_id.clone();
621
- let url = self_.url.clone();
622
- let branch = self_.current_branch.clone();
371
+ .downcast_or_throw::<JsBox<NodeChidori>, _>(&mut cx)?;
372
+ let branch = cx.argument::<JsNumber>(0).unwrap_or(JsNumber::new(&mut cx, 0.0)).value(&mut cx) as u64;
373
+ let c = Arc::clone(&self_.c);
623
374
  let rt = runtime(&mut cx)?;
624
375
  rt.spawn(async move {
625
- let mut client = if let Ok(mut client) = get_client(url).await {
626
- client
627
- } else {
628
- deferred.settle_with(&channel, move |mut cx| {
629
- cx.throw_error::<&str, JsUndefined>("Failed to connect to runtime service.");
630
- Ok(cx.undefined())
631
- });
632
- panic!("Failed to connect to runtime service.");
633
- };
634
- let file = if let Ok(file) = client.current_file_state(RequestOnlyId {
635
- id: file_id,
636
- branch
637
- }).await {
638
- file
639
- } else {
640
- deferred.settle_with(&channel, move |mut cx| {
641
- cx.throw_error::<&str, JsUndefined>("Failed to get current file state.");
642
- Ok(cx.undefined())
643
- });
644
- panic!("Failed to get current file state.");
645
- };
646
- let mut file = file.into_inner();
647
- let mut g = CleanedDefinitionGraph::zero();
648
- g.merge_file(&mut file).unwrap();
376
+ let c = c.lock().await;
377
+ let r= c.display_graph_structure(branch).await;
649
378
  deferred.settle_with(&channel, move |mut cx| {
650
- Ok(cx.string(g.get_dot_graph()))
379
+ if let Ok(r) = r {
380
+ Ok(cx.string(r))
381
+ } else {
382
+ cx.throw_error("Error displaying graph structure")
383
+ }
651
384
  });
652
385
  });
653
386
  Ok(promise)
654
387
  }
655
388
 
656
- //
657
- // // TODO: some of these register handlers instead
658
- // // TODO: list registered graphs should not stream
659
- // // TODO: add a message that sends the current graph state
660
- //
661
-
662
389
  fn list_registered_graphs(mut cx: FunctionContext) -> JsResult<JsPromise> {
663
390
  let channel = cx.channel();
664
391
  let (deferred, promise) = cx.promise();
665
392
  let self_ = cx.this()
666
- .downcast_or_throw::<JsBox<Chidori>, _>(&mut cx)?;
667
- let file_id = self_.file_id.clone();
668
- let url = self_.url.clone();
393
+ .downcast_or_throw::<JsBox<NodeChidori>, _>(&mut cx)?;
394
+ let c = Arc::clone(&self_.c);
669
395
  let rt = runtime(&mut cx)?;
670
396
  rt.spawn(async move {
671
- let mut client = if let Ok(mut client) = get_client(url).await {
672
- client
673
- } else {
674
- deferred.settle_with(&channel, move |mut cx| {
675
- cx.throw_error::<&str, JsUndefined>("Failed to connect to runtime service.");
676
- Ok(cx.undefined())
677
- });
678
- panic!("Failed to connect to runtime service.");
679
- };
680
- let resp = if let Ok(resp) = client.list_registered_graphs(Empty {
681
- }).await {
682
- resp
683
- } else {
684
- deferred.settle_with(&channel, move |mut cx| {
685
- cx.throw_error::<&str, JsUndefined>("Failed to get registered graph stream.");
686
- Ok(cx.undefined())
687
- });
688
- panic!("Failed to get registered graph stream.");
689
- };
690
- let mut stream = resp.into_inner();
691
- while let Some(x) = stream.next().await {
692
- // callback.call(py, (x,), None);
693
- info!("Registered Graph = {:?}", x);
694
- };
397
+ let c = c.lock().await;
398
+ let _ = c.list_registered_graphs().await;
695
399
  deferred.settle_with(&channel, move |mut cx| {
696
400
  Ok(cx.undefined())
697
401
  });
@@ -753,6 +457,100 @@ impl Chidori {
753
457
  // // }
754
458
  //
755
459
  //
460
+
461
+
462
+
463
+ fn register_custom_node_handle(mut cx: FunctionContext) -> JsResult<JsValue> {
464
+ let channel = cx.channel();
465
+ let self_ = cx.this()
466
+ .downcast_or_throw::<JsBox<NodeChidori>, _>(&mut cx)?;
467
+
468
+ let function_name: String = cx.argument::<JsString>(0)?.value(&mut cx);
469
+ let callback = cx.argument::<JsFunction>(1)?.root(&mut cx);
470
+
471
+ let h = callback.to_inner(&mut cx);
472
+ let callback = Arc::new(callback);
473
+ let c = Arc::clone(&self_.c);
474
+
475
+ let rt = runtime(&mut cx)?;
476
+ rt.spawn(async move {
477
+ let mut c = c.lock().await;
478
+ c.register_custom_node_handle(function_name, Handler::new(
479
+ move |n| {
480
+ let channel_clone = channel.clone();
481
+ let handler_clone = Arc::clone(&callback);
482
+ Box::pin(async move {
483
+ // TODO: clean this up, can't use ?
484
+ let (tx, mut rx) = mpsc::channel::<serde_json::Value>(1);
485
+ if let Ok(_) = channel_clone.send(move |mut cx| {
486
+ if let Ok(v) = neon_serde3::to_value(&mut cx, &n) {
487
+ let js_function = JsFunction::new(&mut cx, move |mut cx| {
488
+ if let Ok(v) = cx.argument::<JsValue>(0) {
489
+ let value: Result<serde_json::Value, _> = neon_serde3::from_value(&mut cx, v);
490
+ if let Ok(value) = value {
491
+ tx.blocking_send(value).unwrap();
492
+ }
493
+ }
494
+ Ok(cx.undefined())
495
+ })?;
496
+ let callback = handler_clone.to_inner(&mut cx);
497
+ let _: JsResult<JsValue> = callback.call_with(&mut cx).arg(v).arg(js_function).apply(&mut cx);
498
+ }
499
+ Ok(serde_json::Value::Null)
500
+ }).join() {
501
+ // block until we receive the result from the channel
502
+ if let Some(value) = rx.recv().await {
503
+ Ok(value)
504
+ } else {
505
+ Ok(serde_json::Value::Null)
506
+ }
507
+ } else {
508
+ Err(anyhow::anyhow!("Failed to send result"))
509
+ }
510
+ })
511
+ }
512
+ ));
513
+ });
514
+ Ok(cx.undefined().upcast())
515
+ }
516
+
517
+
518
+ fn run_custom_node_loop(mut cx: FunctionContext) -> JsResult<JsPromise> {
519
+ let channel = cx.channel();
520
+ let (deferred, promise) = cx.promise();
521
+ let self_ = cx.this()
522
+ .downcast_or_throw::<JsBox<NodeChidori>, _>(&mut cx)?;
523
+ let c = Arc::clone(&self_.c);
524
+ let rt = runtime(&mut cx)?;
525
+ rt.spawn(async move {
526
+ let mut c = c.lock().await;
527
+ let _ = c.run_custom_node_loop().await;
528
+ deferred.settle_with((&channel), move |mut cx| {
529
+ Ok(cx.undefined())
530
+ });
531
+
532
+ });
533
+ // This promise is never resolved
534
+ Ok(promise)
535
+ }
536
+
537
+
538
+
539
+ }
540
+
541
+ struct NodeGraphBuilder {
542
+ g: Arc<Mutex<GraphBuilder>>,
543
+ }
544
+
545
+ impl Finalize for NodeGraphBuilder {}
546
+
547
+ impl NodeGraphBuilder {
548
+ fn js_new(mut cx: FunctionContext) -> JsResult<JsBox<NodeGraphBuilder>> {
549
+ Ok(cx.boxed(NodeGraphBuilder {
550
+ g: Arc::new(Mutex::new(GraphBuilder::new())),
551
+ }))
552
+ }
553
+
756
554
  // // TODO: need to figure out passing a buffer of bytes
757
555
  // // TODO: nodes that are added should return a clean definition of what their addition looks like
758
556
  // // TODO: adding a node should also display any errors
@@ -789,12 +587,9 @@ impl Chidori {
789
587
  // // TODO: adding a node should also display any errors
790
588
 
791
589
 
792
- fn prompt_node(mut cx: FunctionContext) -> JsResult<JsPromise> {
793
- let channel = cx.channel();
794
- let (deferred, promise) = cx.promise();
590
+ fn prompt_node(mut cx: FunctionContext) -> JsResult<JsBox<RefCell<NodeNodeHandle>>> {
795
591
  let self_ = cx.this()
796
- .downcast_or_throw::<JsBox<Chidori>, _>(&mut cx)?;
797
-
592
+ .downcast_or_throw::<JsBox<NodeGraphBuilder>, _>(&mut cx)?;
798
593
  let arg0 = cx.argument::<JsValue>(0)?;
799
594
  let arg0_value: PromptNodeCreateOpts = match neon_serde3::from_value(&mut cx, arg0) {
800
595
  Ok(value) => value,
@@ -802,208 +597,17 @@ impl Chidori {
802
597
  return cx.throw_error(e.to_string());
803
598
  }
804
599
  };
805
-
806
- let queries: Vec<Option<String>> = if let Some(queries) = arg0_value.queries {
807
- queries.into_iter().map(|q| {
808
- if q == "None".to_string() {
809
- None
810
- } else {
811
- Some(q)
812
- }
813
- }).collect()
814
- } else {
815
- vec![None]
816
- };
817
-
818
- let file_id = self_.file_id.clone();
819
- let url = self_.url.clone();
820
- let rt = runtime(&mut cx)?;
821
- rt.spawn(async move {
822
- let prompt_node = create_prompt_node(
823
- arg0_value.name,
824
- queries,
825
- arg0_value.template,
826
- arg0_value.model.unwrap_or("GPT_3_5_TURBO".to_string()),
827
- arg0_value.output_tables.unwrap_or(vec![]));
828
- let node = if let Ok(node) = prompt_node {
829
- node
830
- } else {
831
- deferred.settle_with(&channel, move |mut cx| {
832
- // TODO: throw error
833
- Ok(cx.undefined())
834
- });
835
- panic!("Failed to connect to runtime service.");
836
- };
837
-
838
- if let Ok(result ) = push_file_merge(&url, &file_id, node).await {
839
- deferred.settle_with(&channel, move |mut cx| {
840
- Ok(cx.boxed(RefCell::new(result)))
841
- });
842
- } else {
843
- deferred.settle_with(&channel, move |mut cx| {
844
- // TODO: throw error
845
- Ok(cx.undefined())
846
- });
847
- panic!("Failed to connect to runtime service.");
848
- };
849
- });
850
- Ok(promise)
600
+ let mut g = self_.g.blocking_lock();
601
+ match g.prompt_node(arg0_value) {
602
+ Ok(result) => Ok(cx.boxed(RefCell::new(NodeNodeHandle::from(result)))),
603
+ Err(e) => cx.throw_error(e.to_string())
604
+ }
851
605
  }
852
606
 
853
607
 
854
- fn poll_local_code_node_execution(mut cx: FunctionContext) -> JsResult<JsPromise> {
855
- let channel = cx.channel();
856
- let (deferred, promise) = cx.promise();
608
+ fn custom_node(mut cx: FunctionContext) -> JsResult<JsBox<RefCell<NodeNodeHandle>>> {
857
609
  let self_ = cx.this()
858
- .downcast_or_throw::<JsBox<Chidori>, _>(&mut cx)?;
859
- let file_id = self_.file_id.clone();
860
- let url = self_.url.clone();
861
-
862
- let rt = runtime(&mut cx)?;
863
- rt.spawn(async move {
864
- let mut client = if let Ok(mut client) = get_client(url).await {
865
- client
866
- } else {
867
- deferred.settle_with(&channel, move |mut cx| {
868
- cx.throw_error::<&str, JsUndefined>("Failed to connect to runtime service.");
869
- Ok(cx.undefined())
870
- });
871
- panic!("Failed to connect to runtime service.");
872
- };
873
- if let Ok(result) = client.poll_node_will_execute_events(FilteredPollNodeWillExecuteEventsRequest {
874
- id: file_id.clone(),
875
- }).await {
876
- debug!("poll_local_code_node_execution result = {:?}", result);
877
- deferred.settle_with(&channel, move |mut cx| {
878
- neon_serde3::to_value(&mut cx, &result.into_inner())
879
- .or_else(|e| cx.throw_error(e.to_string()))
880
- });
881
- } else {
882
- deferred.settle_with(&channel, move |mut cx| {
883
- // TODO: throw error
884
- Ok(cx.undefined())
885
- });
886
- };
887
- });
888
- Ok(promise)
889
- }
890
- fn ack_local_code_node_execution(mut cx: FunctionContext) -> JsResult<JsPromise> {
891
- let channel = cx.channel();
892
- let (deferred, promise) = cx.promise();
893
- let self_ = cx.this()
894
- .downcast_or_throw::<JsBox<Chidori>, _>(&mut cx)?;
895
- let file_id = self_.file_id.clone();
896
- let url = self_.url.clone();
897
- let branch = cx.argument::<JsNumber>(0)?.value(&mut cx) as u64;
898
- let counter = cx.argument::<JsNumber>(1)?.value(&mut cx) as u64;
899
- let rt = runtime(&mut cx)?;
900
- rt.spawn(async move {
901
- let mut client = if let Ok(mut client) = get_client(url).await {
902
- client
903
- } else {
904
- deferred.settle_with(&channel, move |mut cx| {
905
- cx.throw_error::<&str, JsUndefined>("Failed to connect to runtime service.");
906
- Ok(cx.undefined())
907
- });
908
- panic!("Failed to connect to runtime service.");
909
- };
910
- if let Ok(result) = client.ack_node_will_execute_event(RequestAckNodeWillExecuteEvent {
911
- id: file_id.clone(),
912
- branch,
913
- counter,
914
- }).await {
915
- deferred.settle_with(&channel, move |mut cx| {
916
- neon_serde3::to_value(&mut cx, &result.into_inner())
917
- .or_else(|e| cx.throw_error(e.to_string()))
918
- });
919
- } else {
920
- deferred.settle_with(&channel, move |mut cx| {
921
- // TODO: throw error
922
- Ok(cx.undefined())
923
- });
924
- }
925
- });
926
- Ok(promise)
927
- }
928
-
929
- fn respond_local_code_node_execution(mut cx: FunctionContext) -> JsResult<JsPromise> {
930
- let channel = cx.channel();
931
- let (deferred, promise) = cx.promise();
932
- let self_ = cx.this()
933
- .downcast_or_throw::<JsBox<Chidori>, _>(&mut cx)?;
934
- let file_id = self_.file_id.clone();
935
- let url = self_.url.clone();
936
-
937
- let branch = cx.argument::<JsNumber>(0)?.value(&mut cx) as u64;
938
- let counter = cx.argument::<JsNumber>(1)?.value(&mut cx) as u64;
939
- let node_name = cx.argument::<JsString>(2)?.value(&mut cx);
940
-
941
- let response: Option<JsResult<JsObject>> = match cx.argument_opt(0) {
942
- Some(v) => Some(v.downcast_or_throw(&mut cx)),
943
- None => None,
944
- };
945
-
946
- // TODO: need parent counters from the original change
947
- // TODO: need source node
948
-
949
- let response_paths = if let Some(response) = response {
950
- // TODO: need better error handling here
951
- obj_to_paths(&mut cx, response.unwrap()).unwrap()
952
- } else {
953
- vec![]
954
- };
955
-
956
- let rt = runtime(&mut cx)?;
957
- rt.spawn(async move {
958
- let mut client = if let Ok(mut client) = get_client(url).await {
959
- client
960
- } else {
961
- deferred.settle_with(&channel, move |mut cx| {
962
- cx.throw_error::<&str, JsUndefined>("Failed to connect to runtime service.");
963
- Ok(cx.undefined())
964
- });
965
- panic!("Failed to connect to runtime service.");
966
- };
967
-
968
- // TODO: need to add the output table paths to these
969
- let filled_values = response_paths.into_iter().map(|path| {
970
- ChangeValue {
971
- path: Some(Path {
972
- address: path.0,
973
- }),
974
- value: Some(path.1),
975
- branch,
976
- }
977
- });
978
-
979
- // TODO: this needs to look more like a real change
980
- client.push_worker_event(FileAddressedChangeValueWithCounter {
981
- branch,
982
- counter,
983
- node_name,
984
- id: file_id.clone(),
985
- change: Some(ChangeValueWithCounter {
986
- filled_values: filled_values.collect(),
987
- parent_monotonic_counters: vec![],
988
- monotonic_counter: counter,
989
- branch,
990
- source_node: "".to_string(),
991
- })
992
- }).await.unwrap();
993
- });
994
- Ok(promise)
995
- }
996
-
997
- // // }
998
- //
999
- // // TODO: handle dispatch to this handler - should accept a callback
1000
- // // https://github.com/PyO3/pyo3/issues/525
1001
- fn custom_node(mut cx: FunctionContext) -> JsResult<JsPromise> {
1002
- let channel = cx.channel();
1003
- let (deferred, promise) = cx.promise();
1004
- let self_ = cx.this()
1005
- .downcast_or_throw::<JsBox<Chidori>, _>(&mut cx)?;
1006
-
610
+ .downcast_or_throw::<JsBox<NodeGraphBuilder>, _>(&mut cx)?;
1007
611
  let arg0 = cx.argument::<JsValue>(0)?;
1008
612
  let arg0_value: CustomNodeCreateOpts = match neon_serde3::from_value(&mut cx, arg0) {
1009
613
  Ok(value) => value,
@@ -1011,53 +615,16 @@ impl Chidori {
1011
615
  return cx.throw_error(e.to_string());
1012
616
  }
1013
617
  };
1014
-
1015
- let queries: Vec<Option<String>> = if let Some(queries) = arg0_value.queries {
1016
- queries.into_iter().map(|q| {
1017
- if q == "None".to_string() {
1018
- None
1019
- } else {
1020
- Some(q)
1021
- }
1022
- }).collect()
1023
- } else {
1024
- vec![]
1025
- };
1026
-
1027
- let file_id = self_.file_id.clone();
1028
- let url = self_.url.clone();
1029
- let branch = self_.current_branch;
1030
- let rt = runtime(&mut cx)?;
1031
- rt.spawn(async move {
1032
- // Register the node with the system
1033
- let node = create_custom_node(
1034
- arg0_value.name,
1035
- queries,
1036
- arg0_value.output.unwrap_or("type O {}".to_string()),
1037
- arg0_value.node_type_name,
1038
- arg0_value.output_tables.unwrap_or(vec![])
1039
- );
1040
- if let Ok(result ) = push_file_merge(&url, &file_id, node).await {
1041
- deferred.settle_with(&channel, move |mut cx| {
1042
- Ok(cx.boxed(RefCell::new(result)))
1043
- });
1044
- } else {
1045
- deferred.settle_with(&channel, move |mut cx| {
1046
- // TODO: throw error
1047
- Ok(cx.undefined())
1048
- });
1049
- panic!("Failed to connect to runtime service.");
1050
- };
1051
- });
1052
- Ok(promise)
618
+ let mut g = self_.g.blocking_lock();
619
+ match g.custom_node(arg0_value) {
620
+ Ok(result) => Ok(cx.boxed(RefCell::new(NodeNodeHandle::from(result)))),
621
+ Err(e) => cx.throw_error(e.to_string())
622
+ }
1053
623
  }
1054
624
 
1055
- fn deno_code_node(mut cx: FunctionContext) -> JsResult<JsPromise> {
1056
- let channel = cx.channel();
1057
- let (deferred, promise) = cx.promise();
625
+ fn deno_code_node(mut cx: FunctionContext) -> JsResult<JsBox<RefCell<NodeNodeHandle>>> {
1058
626
  let self_ = cx.this()
1059
- .downcast_or_throw::<JsBox<Chidori>, _>(&mut cx)?;
1060
-
627
+ .downcast_or_throw::<JsBox<NodeGraphBuilder>, _>(&mut cx)?;
1061
628
  let arg0 = cx.argument::<JsValue>(0)?;
1062
629
  let arg0_value: DenoCodeNodeCreateOpts = match neon_serde3::from_value(&mut cx, arg0) {
1063
630
  Ok(value) => value,
@@ -1065,53 +632,16 @@ impl Chidori {
1065
632
  return cx.throw_error(e.to_string());
1066
633
  }
1067
634
  };
1068
-
1069
- let queries: Vec<Option<String>> = if let Some(queries) = arg0_value.queries {
1070
- queries.into_iter().map(|q| {
1071
- if q == "None".to_string() {
1072
- None
1073
- } else {
1074
- Some(q)
1075
- }
1076
- }).collect()
1077
- } else {
1078
- vec![None]
1079
- };
1080
-
1081
- let file_id = self_.file_id.clone();
1082
- let url = self_.url.clone();
1083
- let branch = self_.current_branch;
1084
-
1085
- let rt = runtime(&mut cx)?;
1086
- rt.spawn(async move {
1087
- let node = create_code_node(
1088
- arg0_value.name,
1089
- queries,
1090
- arg0_value.output.unwrap_or("type O {}".to_string()),
1091
- SourceNodeType::Code("DENO".to_string(), arg0_value.code, arg0_value.is_template.unwrap_or(false)),
1092
- arg0_value.output_tables.unwrap_or(vec![])
1093
- );
1094
- if let Ok(result ) = push_file_merge(&url, &file_id, node).await {
1095
- deferred.settle_with(&channel, move |mut cx| {
1096
- Ok(cx.boxed(RefCell::new(result)))
1097
- });
1098
- } else {
1099
- deferred.settle_with(&channel, move |mut cx| {
1100
- // TODO: throw error
1101
- Ok(cx.undefined())
1102
- });
1103
- panic!("Failed to connect to runtime service.");
1104
- };
1105
- });
1106
- Ok(promise)
635
+ let mut g = self_.g.blocking_lock();
636
+ match g.deno_code_node(arg0_value) {
637
+ Ok(result) => Ok(cx.boxed(RefCell::new(NodeNodeHandle::from(result)))),
638
+ Err(e) => cx.throw_error(e.to_string())
639
+ }
1107
640
  }
1108
641
 
1109
- fn vector_memory_node(mut cx: FunctionContext) -> JsResult<JsPromise> {
1110
- let channel = cx.channel();
1111
- let (deferred, promise) = cx.promise();
642
+ fn vector_memory_node(mut cx: FunctionContext) -> JsResult<JsBox<RefCell<NodeNodeHandle>>> {
1112
643
  let self_ = cx.this()
1113
- .downcast_or_throw::<JsBox<Chidori>, _>(&mut cx)?;
1114
-
644
+ .downcast_or_throw::<JsBox<NodeGraphBuilder>, _>(&mut cx)?;
1115
645
  let arg0 = cx.argument::<JsValue>(0)?;
1116
646
  let arg0_value: VectorMemoryNodeCreateOpts = match neon_serde3::from_value(&mut cx, arg0) {
1117
647
  Ok(value) => value,
@@ -1119,56 +649,39 @@ impl Chidori {
1119
649
  return cx.throw_error(e.to_string());
1120
650
  }
1121
651
  };
652
+ let mut g = self_.g.blocking_lock();
653
+ match g.vector_memory_node(arg0_value) {
654
+ Ok(result) => Ok(cx.boxed(RefCell::new(NodeNodeHandle::from(result)))),
655
+ Err(e) => cx.throw_error(e.to_string())
656
+ }
657
+ }
1122
658
 
1123
- let queries: Vec<Option<String>> = if let Some(queries) = arg0_value.queries {
1124
- queries.into_iter().map(|q| {
1125
- if q == "None".to_string() {
1126
- None
1127
- } else {
1128
- Some(q)
1129
- }
1130
- }).collect()
1131
- } else {
1132
- vec![]
1133
- };
1134
659
 
1135
- let file_id = self_.file_id.clone();
1136
- let url = self_.url.clone();
1137
- let branch = self_.current_branch;
660
+
661
+ fn commit(mut cx: FunctionContext) -> JsResult<JsPromise> {
662
+ let channel = cx.channel();
663
+ let (deferred, promise) = cx.promise();
664
+ let self_ = cx.this()
665
+ .downcast_or_throw::<JsBox<NodeGraphBuilder>, _>(&mut cx)?;
666
+ let node_chidori = cx.argument::<JsBox<NodeChidori>>(0)?;
667
+ let branch = cx.argument::<JsNumber>(1).unwrap_or(JsNumber::new(&mut cx, 0.0)).value(&mut cx) as u64;
668
+
669
+ let c = Arc::clone(&node_chidori.c);
670
+ let g = Arc::clone(&self_.g);
671
+
1138
672
  let rt = runtime(&mut cx)?;
1139
673
  rt.spawn(async move {
1140
- let node = create_vector_memory_node(
1141
- arg0_value.name,
1142
- queries,
1143
- arg0_value.output.unwrap_or("type O {}".to_string()),
1144
- arg0_value.action.unwrap_or("READ".to_string()),
1145
- arg0_value.embedding_model.unwrap_or("TEXT_EMBEDDING_ADA_002".to_string()),
1146
- arg0_value.template.unwrap_or("".to_string()),
1147
- arg0_value.db_vendor.unwrap_or("QDRANT".to_string()),
1148
- arg0_value.collection_name,
1149
- arg0_value.output_tables.unwrap_or(vec![])
1150
- );
1151
- let node = if let Ok(node) = node {
1152
- node
1153
- } else {
1154
- deferred.settle_with(&channel, move |mut cx| {
1155
- // TODO: throw error
1156
- Ok(cx.undefined())
1157
- });
1158
- panic!("Failed to connect to runtime service.");
1159
- };
1160
-
1161
- if let Ok(result ) = push_file_merge(&url, &file_id, node).await {
1162
- deferred.settle_with(&channel, move |mut cx| {
1163
- Ok(cx.boxed(RefCell::new(result)))
1164
- });
1165
- } else {
1166
- deferred.settle_with(&channel, move |mut cx| {
1167
- // TODO: throw error
1168
- Ok(cx.undefined())
1169
- });
1170
- panic!("Failed to connect to runtime service.");
1171
- };
674
+ let mut graph_builder = g.lock().await;
675
+ let mut chidori = c.lock().await;
676
+ let m = graph_builder.commit(&mut chidori, branch).await;
677
+ deferred.settle_with((&channel), move |mut cx| {
678
+ if let Ok(result) = m {
679
+ neon_serde3::to_value(&mut cx, &result)
680
+ .or_else(|e| cx.throw_error(e.to_string()))
681
+ } else {
682
+ cx.throw_error("Error playing")
683
+ }
684
+ });
1172
685
  });
1173
686
  Ok(promise)
1174
687
  }
@@ -1203,22 +716,24 @@ fn neon_simple_fun(mut cx: FunctionContext) -> JsResult<JsString> {
1203
716
  #[neon::main]
1204
717
  fn main(mut cx: ModuleContext) -> NeonResult<()> {
1205
718
  env_logger::init();
1206
- cx.export_function("nodehandleDebugExample", NodeHandle::js_debug_example)?;
1207
- cx.export_function("nodehandleRunWhen", NodeHandle::run_when)?;
1208
- cx.export_function("nodehandleQuery", NodeHandle::query)?;
1209
- cx.export_function("chidoriNew", Chidori::js_new)?;
1210
- cx.export_function("chidoriStartServer", Chidori::start_server)?;
1211
- cx.export_function("chidoriPlay", Chidori::play)?;
1212
- cx.export_function("chidoriPause", Chidori::pause)?;
1213
- cx.export_function("chidoriBranch", Chidori::branch)?;
1214
- cx.export_function("chidoriQuery", Chidori::query)?;
1215
- cx.export_function("chidoriGraphStructure", Chidori::display_graph_structure)?;
1216
- cx.export_function("chidoriCustomNode", Chidori::custom_node)?;
1217
- cx.export_function("chidoriDenoCodeNode", Chidori::deno_code_node)?;
1218
- cx.export_function("chidoriVectorMemoryNode", Chidori::vector_memory_node)?;
1219
- cx.export_function("chidoriPollLocalCodeNodeExecution", Chidori::poll_local_code_node_execution)?;
1220
- cx.export_function("chidoriAckLocalCodeNodeExecution", Chidori::ack_local_code_node_execution)?;
1221
- cx.export_function("chidoriRespondLocalCodeNodeExecution", Chidori::respond_local_code_node_execution)?;
719
+ cx.export_function("nodehandleRunWhen", NodeNodeHandle::run_when)?;
720
+ // cx.export_function("nodehandleQuery", NodeNodeHandle::query)?;
721
+ cx.export_function("chidoriNew", NodeChidori::js_new)?;
722
+ cx.export_function("chidoriStartServer", NodeChidori::start_server)?;
723
+ cx.export_function("chidoriPlay", NodeChidori::play)?;
724
+ cx.export_function("chidoriPause", NodeChidori::pause)?;
725
+ cx.export_function("chidoriBranch", NodeChidori::branch)?;
726
+ cx.export_function("chidoriQuery", NodeChidori::query)?;
727
+ cx.export_function("chidoriGraphStructure", NodeChidori::display_graph_structure)?;
728
+ cx.export_function("chidoriRegisterCustomNodeHandle", NodeChidori::register_custom_node_handle)?;
729
+ cx.export_function("chidoriRunCustomNodeLoop", NodeChidori::run_custom_node_loop)?;
730
+
731
+ cx.export_function("graphbuilderNew", NodeGraphBuilder::js_new)?;
732
+ cx.export_function("graphbuilderCustomNode", NodeGraphBuilder::custom_node)?;
733
+ cx.export_function("graphbuilderDenoCodeNode", NodeGraphBuilder::deno_code_node)?;
734
+ cx.export_function("graphbuilderPromptNode", NodeGraphBuilder::prompt_node)?;
735
+ cx.export_function("graphbuilderVectorMemoryNode", NodeGraphBuilder::vector_memory_node)?;
736
+ cx.export_function("graphbuilderCommit", NodeGraphBuilder::commit)?;
1222
737
  cx.export_function("simpleFun", neon_simple_fun)?;
1223
738
  Ok(())
1224
739
  }