simple-agents-wasm 0.3.7 → 0.3.9
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
CHANGED
|
@@ -38,6 +38,7 @@ export interface InitOutput {
|
|
|
38
38
|
readonly wasmclient_streamEvents: (a: number, b: number, c: number, d: any, e: any, f: number) => any;
|
|
39
39
|
readonly wasm_bindgen__convert__closures_____invoke__h9f53f643b01d7c8e: (a: number, b: number, c: any) => [number, number];
|
|
40
40
|
readonly wasm_bindgen__convert__closures_____invoke__h05acb8c479b21d4b: (a: number, b: number, c: any, d: any) => void;
|
|
41
|
+
readonly wasm_bindgen__convert__closures_____invoke__hcbe4158cf6f0da5b: (a: number, b: number, c: any) => void;
|
|
41
42
|
readonly __wbindgen_malloc: (a: number, b: number) => number;
|
|
42
43
|
readonly __wbindgen_realloc: (a: number, b: number, c: number, d: number) => number;
|
|
43
44
|
readonly __wbindgen_exn_store: (a: number) => void;
|
|
@@ -409,26 +409,31 @@ function __wbg_get_imports() {
|
|
|
409
409
|
return ret;
|
|
410
410
|
},
|
|
411
411
|
__wbindgen_cast_0000000000000001: function(arg0, arg1) {
|
|
412
|
-
// Cast intrinsic for `Closure(Closure { owned: true, function: Function { arguments: [Externref], shim_idx:
|
|
412
|
+
// Cast intrinsic for `Closure(Closure { owned: true, function: Function { arguments: [Externref], shim_idx: 157, ret: Result(Unit), inner_ret: Some(Result(Unit)) }, mutable: true }) -> Externref`.
|
|
413
413
|
const ret = makeMutClosure(arg0, arg1, wasm_bindgen__convert__closures_____invoke__h9f53f643b01d7c8e);
|
|
414
414
|
return ret;
|
|
415
415
|
},
|
|
416
|
-
__wbindgen_cast_0000000000000002: function(arg0) {
|
|
416
|
+
__wbindgen_cast_0000000000000002: function(arg0, arg1) {
|
|
417
|
+
// Cast intrinsic for `Closure(Closure { owned: true, function: Function { arguments: [Externref], shim_idx: 78, ret: Unit, inner_ret: Some(Unit) }, mutable: true }) -> Externref`.
|
|
418
|
+
const ret = makeMutClosure(arg0, arg1, wasm_bindgen__convert__closures_____invoke__hcbe4158cf6f0da5b);
|
|
419
|
+
return ret;
|
|
420
|
+
},
|
|
421
|
+
__wbindgen_cast_0000000000000003: function(arg0) {
|
|
417
422
|
// Cast intrinsic for `F64 -> Externref`.
|
|
418
423
|
const ret = arg0;
|
|
419
424
|
return ret;
|
|
420
425
|
},
|
|
421
|
-
|
|
426
|
+
__wbindgen_cast_0000000000000004: function(arg0) {
|
|
422
427
|
// Cast intrinsic for `I64 -> Externref`.
|
|
423
428
|
const ret = arg0;
|
|
424
429
|
return ret;
|
|
425
430
|
},
|
|
426
|
-
|
|
431
|
+
__wbindgen_cast_0000000000000005: function(arg0, arg1) {
|
|
427
432
|
// Cast intrinsic for `Ref(String) -> Externref`.
|
|
428
433
|
const ret = getStringFromWasm0(arg0, arg1);
|
|
429
434
|
return ret;
|
|
430
435
|
},
|
|
431
|
-
|
|
436
|
+
__wbindgen_cast_0000000000000006: function(arg0) {
|
|
432
437
|
// Cast intrinsic for `U64 -> Externref`.
|
|
433
438
|
const ret = BigInt.asUintN(64, arg0);
|
|
434
439
|
return ret;
|
|
@@ -449,6 +454,10 @@ function __wbg_get_imports() {
|
|
|
449
454
|
};
|
|
450
455
|
}
|
|
451
456
|
|
|
457
|
+
function wasm_bindgen__convert__closures_____invoke__hcbe4158cf6f0da5b(arg0, arg1, arg2) {
|
|
458
|
+
wasm.wasm_bindgen__convert__closures_____invoke__hcbe4158cf6f0da5b(arg0, arg1, arg2);
|
|
459
|
+
}
|
|
460
|
+
|
|
452
461
|
function wasm_bindgen__convert__closures_____invoke__h9f53f643b01d7c8e(arg0, arg1, arg2) {
|
|
453
462
|
const ret = wasm.wasm_bindgen__convert__closures_____invoke__h9f53f643b01d7c8e(arg0, arg1, arg2);
|
|
454
463
|
if (ret[1]) {
|
|
Binary file
|
|
@@ -11,6 +11,7 @@ export const wasmclient_runYamlString: (a: number, b: number, c: number, d: any,
|
|
|
11
11
|
export const wasmclient_streamEvents: (a: number, b: number, c: number, d: any, e: any, f: number) => any;
|
|
12
12
|
export const wasm_bindgen__convert__closures_____invoke__h9f53f643b01d7c8e: (a: number, b: number, c: any) => [number, number];
|
|
13
13
|
export const wasm_bindgen__convert__closures_____invoke__h05acb8c479b21d4b: (a: number, b: number, c: any, d: any) => void;
|
|
14
|
+
export const wasm_bindgen__convert__closures_____invoke__hcbe4158cf6f0da5b: (a: number, b: number, c: any) => void;
|
|
14
15
|
export const __wbindgen_malloc: (a: number, b: number) => number;
|
|
15
16
|
export const __wbindgen_realloc: (a: number, b: number, c: number, d: number) => number;
|
|
16
17
|
export const __wbindgen_exn_store: (a: number) => void;
|
package/rust/Cargo.toml
CHANGED
package/rust/src/lib.rs
CHANGED
|
@@ -3,6 +3,7 @@ use serde::{Deserialize, Serialize};
|
|
|
3
3
|
use serde_json::{json, Map as JsonMap, Value as JsonValue};
|
|
4
4
|
use std::cell::RefCell;
|
|
5
5
|
use std::collections::HashMap;
|
|
6
|
+
use wasm_bindgen::closure::Closure;
|
|
6
7
|
use wasm_bindgen::prelude::*;
|
|
7
8
|
use wasm_bindgen::JsCast;
|
|
8
9
|
use wasm_bindgen_futures::JsFuture;
|
|
@@ -87,6 +88,7 @@ struct WorkflowDoc {
|
|
|
87
88
|
|
|
88
89
|
#[derive(Deserialize, Clone)]
|
|
89
90
|
struct GraphWorkflowDoc {
|
|
91
|
+
id: Option<String>,
|
|
90
92
|
model: Option<String>,
|
|
91
93
|
entry_node: String,
|
|
92
94
|
nodes: Vec<GraphWorkflowNode>,
|
|
@@ -126,6 +128,7 @@ struct GraphLlmCall {
|
|
|
126
128
|
temperature: Option<f64>,
|
|
127
129
|
messages_path: Option<String>,
|
|
128
130
|
append_prompt_as_user: Option<bool>,
|
|
131
|
+
stream: Option<bool>,
|
|
129
132
|
}
|
|
130
133
|
|
|
131
134
|
#[derive(Deserialize, Clone)]
|
|
@@ -272,6 +275,8 @@ struct WorkflowRunOptions {
|
|
|
272
275
|
trace: Option<JsonValue>,
|
|
273
276
|
#[serde(skip)]
|
|
274
277
|
functions_js: Option<JsValue>,
|
|
278
|
+
#[serde(skip)]
|
|
279
|
+
on_event_js: Option<Function>,
|
|
275
280
|
/// Injected by JS as `__fetchImpl` so HTTP calls use the same fetch as tests (no global race).
|
|
276
281
|
#[serde(skip)]
|
|
277
282
|
fetch_js: Option<JsValue>,
|
|
@@ -319,6 +324,16 @@ fn json_value_to_js_plain(value: &JsonValue) -> Result<JsValue, JsValue> {
|
|
|
319
324
|
js_sys::JSON::parse(&s).map_err(|_| js_error("failed to parse JSON for JS"))
|
|
320
325
|
}
|
|
321
326
|
|
|
327
|
+
fn emit_workflow_event(on_event: &Option<Function>, event: JsonValue) -> Result<(), JsValue> {
|
|
328
|
+
if let Some(callback) = on_event {
|
|
329
|
+
let event_js = json_value_to_js_plain(&event)?;
|
|
330
|
+
callback
|
|
331
|
+
.call1(&JsValue::NULL, &event_js)
|
|
332
|
+
.map_err(|_| js_error("failed to call workflow stream callback"))?;
|
|
333
|
+
}
|
|
334
|
+
Ok(())
|
|
335
|
+
}
|
|
336
|
+
|
|
322
337
|
fn now_millis() -> f64 {
|
|
323
338
|
let global = js_sys::global();
|
|
324
339
|
let performance = Reflect::get(&global, &JsValue::from_str("performance")).ok();
|
|
@@ -1439,6 +1454,7 @@ impl WasmClient {
|
|
|
1439
1454
|
telemetry: None,
|
|
1440
1455
|
trace: None,
|
|
1441
1456
|
functions_js: None,
|
|
1457
|
+
on_event_js: None,
|
|
1442
1458
|
fetch_js: None,
|
|
1443
1459
|
};
|
|
1444
1460
|
if let Some(options_js) = workflow_options {
|
|
@@ -1452,6 +1468,14 @@ impl WasmClient {
|
|
|
1452
1468
|
Some(v)
|
|
1453
1469
|
}
|
|
1454
1470
|
});
|
|
1471
|
+
let on_event_value = Reflect::get(&options_js, &JsValue::from_str("onEvent")).ok();
|
|
1472
|
+
options.on_event_js = on_event_value.and_then(|v| {
|
|
1473
|
+
if v.is_undefined() || v.is_null() {
|
|
1474
|
+
None
|
|
1475
|
+
} else {
|
|
1476
|
+
v.dyn_into::<Function>().ok()
|
|
1477
|
+
}
|
|
1478
|
+
});
|
|
1455
1479
|
let fetch_js = Reflect::get(&options_js, &JsValue::from_str("__fetchImpl")).ok();
|
|
1456
1480
|
options.fetch_js = fetch_js;
|
|
1457
1481
|
}
|
|
@@ -1499,6 +1523,14 @@ impl WasmClient {
|
|
|
1499
1523
|
let total_reasoning_tokens: u64 = 0;
|
|
1500
1524
|
let mut llm_nodes_without_usage: Vec<String> = Vec::new();
|
|
1501
1525
|
|
|
1526
|
+
emit_workflow_event(
|
|
1527
|
+
&options.on_event_js,
|
|
1528
|
+
json!({
|
|
1529
|
+
"event_type": "workflow_started",
|
|
1530
|
+
"workflow_id": graph_doc.id.clone().unwrap_or_else(|| "wasm_workflow".to_string())
|
|
1531
|
+
}),
|
|
1532
|
+
)?;
|
|
1533
|
+
|
|
1502
1534
|
while !pointer.is_empty() {
|
|
1503
1535
|
iterations += 1;
|
|
1504
1536
|
if iterations > 1000 {
|
|
@@ -1582,13 +1614,65 @@ impl WasmClient {
|
|
|
1582
1614
|
};
|
|
1583
1615
|
|
|
1584
1616
|
let opts = json!({ "temperature": llm.temperature });
|
|
1585
|
-
let completion_js =
|
|
1586
|
-
.
|
|
1587
|
-
|
|
1588
|
-
|
|
1589
|
-
|
|
1590
|
-
|
|
1591
|
-
|
|
1617
|
+
let completion_js = if llm.stream.unwrap_or(false) && options.on_event_js.is_some() {
|
|
1618
|
+
let node_id = node.id.clone();
|
|
1619
|
+
let step_id = node.id.clone();
|
|
1620
|
+
let workflow_on_event = options
|
|
1621
|
+
.on_event_js
|
|
1622
|
+
.clone()
|
|
1623
|
+
.ok_or_else(|| js_error("missing workflow stream callback"))?;
|
|
1624
|
+
let mapped_stream_cb = Closure::wrap(Box::new(move |stream_event_js: JsValue| {
|
|
1625
|
+
let stream_event: JsonValue =
|
|
1626
|
+
serde_wasm_bindgen::from_value(stream_event_js).unwrap_or(JsonValue::Null);
|
|
1627
|
+
let stream_event_type = stream_event
|
|
1628
|
+
.get("eventType")
|
|
1629
|
+
.and_then(JsonValue::as_str)
|
|
1630
|
+
.unwrap_or_default();
|
|
1631
|
+
|
|
1632
|
+
if stream_event_type == "delta" {
|
|
1633
|
+
if let Some(delta) = stream_event
|
|
1634
|
+
.get("delta")
|
|
1635
|
+
.and_then(|v| v.get("content"))
|
|
1636
|
+
.and_then(JsonValue::as_str)
|
|
1637
|
+
{
|
|
1638
|
+
let workflow_event = json!({
|
|
1639
|
+
"event_type": "node_stream_delta",
|
|
1640
|
+
"node_id": node_id.clone(),
|
|
1641
|
+
"step_id": step_id.clone(),
|
|
1642
|
+
"delta": delta
|
|
1643
|
+
});
|
|
1644
|
+
if let Ok(event_js) = json_value_to_js_plain(&workflow_event) {
|
|
1645
|
+
let _ = workflow_on_event.call1(&JsValue::NULL, &event_js);
|
|
1646
|
+
}
|
|
1647
|
+
}
|
|
1648
|
+
} else if stream_event_type == "done" {
|
|
1649
|
+
let workflow_event = json!({
|
|
1650
|
+
"event_type": "node_stream_snapshot",
|
|
1651
|
+
"node_id": node_id.clone(),
|
|
1652
|
+
"step_id": step_id.clone(),
|
|
1653
|
+
"metadata": { "is_complete": true }
|
|
1654
|
+
});
|
|
1655
|
+
if let Ok(event_js) = json_value_to_js_plain(&workflow_event) {
|
|
1656
|
+
let _ = workflow_on_event.call1(&JsValue::NULL, &event_js);
|
|
1657
|
+
}
|
|
1658
|
+
}
|
|
1659
|
+
}) as Box<dyn FnMut(JsValue)>);
|
|
1660
|
+
let stream_callback_fn: Function =
|
|
1661
|
+
mapped_stream_cb.as_ref().unchecked_ref::<Function>().clone();
|
|
1662
|
+
let result = self
|
|
1663
|
+
.stream_events(
|
|
1664
|
+
model,
|
|
1665
|
+
prompt_js,
|
|
1666
|
+
stream_callback_fn,
|
|
1667
|
+
Some(json_value_to_js_plain(&opts)?),
|
|
1668
|
+
)
|
|
1669
|
+
.await;
|
|
1670
|
+
drop(mapped_stream_cb);
|
|
1671
|
+
result?
|
|
1672
|
+
} else {
|
|
1673
|
+
self.complete(model, prompt_js, Some(json_value_to_js_plain(&opts)?))
|
|
1674
|
+
.await?
|
|
1675
|
+
};
|
|
1592
1676
|
let completion: JsonValue = serde_wasm_bindgen::from_value(completion_js)
|
|
1593
1677
|
.map_err(|_| js_error("failed to parse completion result"))?;
|
|
1594
1678
|
|
|
@@ -1797,6 +1881,17 @@ impl WasmClient {
|
|
|
1797
1881
|
trace.push(node.id.clone());
|
|
1798
1882
|
}
|
|
1799
1883
|
|
|
1884
|
+
emit_workflow_event(
|
|
1885
|
+
&options.on_event_js,
|
|
1886
|
+
json!({
|
|
1887
|
+
"event_type": "workflow_completed",
|
|
1888
|
+
"workflow_id": raw_doc
|
|
1889
|
+
.get("id")
|
|
1890
|
+
.and_then(JsonValue::as_str)
|
|
1891
|
+
.unwrap_or("wasm_workflow")
|
|
1892
|
+
}),
|
|
1893
|
+
)?;
|
|
1894
|
+
|
|
1800
1895
|
let total_elapsed_ms = (now_millis() - workflow_started).max(0.0) as u64;
|
|
1801
1896
|
let terminal_node = trace.last().cloned().unwrap_or_default();
|
|
1802
1897
|
let workflow_id = raw_doc
|