Skip to content

Commit 91fe973

Browse files
committed
f
1 parent 36343de commit 91fe973

File tree

4 files changed

+96
-61
lines changed

4 files changed

+96
-61
lines changed

.github/workflows/release.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -85,8 +85,8 @@ jobs:
8585
echo "Processing directory: $dir"
8686
bin=$(ls "$dir")
8787
echo "Found binary: $bin in $dir"
88-
echo "Copying $dir/$bin to dist/final/$bin"
89-
cp "$dir/$bin" "dist/final/$bin"
88+
echo "Copying $dir/$bin to dist/final/$bin-$dir"
89+
cp "$dir/$bin" "dist/final/$bin-$dir"
9090
fi
9191
done
9292

server/src/main.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -36,10 +36,10 @@ async fn main() -> Result<()> {
3636

3737
tracing::info!(?cli, "Starting MCP server with CLI arguments");
3838

39-
let heap_storage = if cli.s3_bucket.is_some() {
40-
AnyHeapStorage::S3(S3HeapStorage::new(cli.s3_bucket.unwrap()).await)
41-
} else if cli.directory_path.is_some() {
42-
AnyHeapStorage::File(FileHeapStorage::new(cli.directory_path.unwrap()))
39+
let heap_storage = if let Some(bucket) = cli.s3_bucket {
40+
AnyHeapStorage::S3(S3HeapStorage::new(bucket).await)
41+
} else if let Some(dir) = cli.directory_path {
42+
AnyHeapStorage::File(FileHeapStorage::new(dir))
4343
} else {
4444
// default to s3
4545
AnyHeapStorage::S3(S3HeapStorage::new("test-mcp-js-bucket").await)

server/src/mcp.rs

Lines changed: 50 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,12 @@ use crate::mcp::heap_storage::{HeapStorage, AnyHeapStorage};
1616

1717

1818

19-
fn eval<'s>(scope: &mut v8::HandleScope<'s>, code: &str) -> Option<v8::Local<'s, v8::Value>> {
19+
fn eval<'s>(scope: &mut v8::HandleScope<'s>, code: &str) -> Result<v8::Local<'s, v8::Value>, String> {
2020
let scope = &mut v8::EscapableHandleScope::new(scope);
21-
let source = v8::String::new(scope, code).unwrap();
22-
let script = v8::Script::compile(scope, source, None).unwrap();
23-
let r = script.run(scope);
24-
r.map(|v| scope.escape(v))
21+
let source = v8::String::new(scope, code).ok_or("Failed to create V8 string")?;
22+
let script = v8::Script::compile(scope, source, None).ok_or("Failed to compile script")?;
23+
let r = script.run(scope).ok_or("Failed to run script")?;
24+
Ok(scope.escape(r))
2525
}
2626

2727
static INIT: Once = Once::new();
@@ -60,12 +60,13 @@ pub struct RunJsResponse {
6060

6161
impl IntoContents for RunJsResponse {
6262
fn into_contents(self) -> Vec<Content> {
63-
vec![Content::json(
64-
json!({
65-
"output": self.output,
66-
"heap": self.heap,
67-
})
68-
).expect("failed to convert run_js response to content")]
63+
match Content::json(json!({
64+
"output": self.output,
65+
"heap": self.heap,
66+
})) {
67+
Ok(content) => vec![content],
68+
Err(e) => vec![Content::text(format!("Failed to convert run_js response to content: {}", e))],
69+
}
6970
}
7071
}
7172

@@ -81,12 +82,9 @@ impl GenericService {
8182

8283
#[tool(description = "run javascript code in v8\n\nparams:\n- code: the javascript code to run\n- heap: the path to the heap file\n\nreturns:\n- output: the output of the javascript code\n- heap: the path to the heap file\n\nyou must send a heap file to the client. \n\n\nThe way the runtime works, is that there is no console.log. If you want the results of an execution, you must return it in the last line of code. \n\neg:\n\n```js\nconst result = 1 + 1;\nresult;\n```\n\nwould return:\n\n```\n2\n```\n\n")]
8384
pub async fn run_js(&self, #[tool(param)] code: String, #[tool(param)] heap: String) -> RunJsResponse {
84-
// 1. Get snapshot data (if any) from heap_storage (async)
8585
let snapshot = self.heap_storage.get(&heap).await.ok();
86-
// 2. Run V8 logic in blocking thread
8786
let code_clone = code.clone();
8887
let v8_result = tokio::task::spawn_blocking(move || {
89-
// Re-implement the V8 logic here, using snapshot if available
9088
let mut snapshot_creator = match snapshot {
9189
Some(snapshot) => {
9290
eprintln!("creating isolate from snapshot...");
@@ -97,32 +95,45 @@ impl GenericService {
9795
v8::Isolate::snapshot_creator(Default::default(), Default::default())
9896
}
9997
};
100-
let output;
101-
{
102-
let scope = &mut v8::HandleScope::new(&mut snapshot_creator);
103-
let context = v8::Context::new(scope, Default::default());
104-
let scope = &mut v8::ContextScope::new(scope, context);
105-
106-
let result = eval(scope, &code_clone).unwrap();
107-
108-
let result_str = result
109-
.to_string(scope)
110-
.ok_or_else(|| "Failed to convert result to string".to_string())?;
111-
output = result_str.to_rust_string_lossy(scope);
112-
scope.set_default_context(context);
98+
let output = (|| {
99+
let output;
100+
{
101+
let scope = &mut v8::HandleScope::new(&mut snapshot_creator);
102+
let context = v8::Context::new(scope, Default::default());
103+
let scope = &mut v8::ContextScope::new(scope, context);
104+
let result = eval(scope, &code_clone)?;
105+
let result_str = result
106+
.to_string(scope)
107+
.ok_or_else(|| "Failed to convert result to string".to_string())?;
108+
output = result_str.to_rust_string_lossy(scope);
109+
scope.set_default_context(context);
110+
} // All borrows of snapshot_creator end here
111+
let startup_data = snapshot_creator
112+
.create_blob(v8::FunctionCodeHandling::Clear)
113+
.ok_or("Failed to create V8 snapshot blob")?;
114+
let startup_data_vec = startup_data.to_vec();
115+
Ok::<_, String>((output, startup_data_vec))
116+
})();
117+
output
118+
}).await;
119+
match v8_result {
120+
Ok(Ok((output, startup_data))) => {
121+
if let Err(e) = self.heap_storage.put(&heap, &startup_data).await {
122+
return RunJsResponse {
123+
output: format!("Error saving heap: {}", e),
124+
heap,
125+
};
126+
}
127+
RunJsResponse { output, heap }
113128
}
114-
let startup_data = snapshot_creator
115-
.create_blob(v8::FunctionCodeHandling::Clear)
116-
.unwrap();
117-
let startup_data_vec = startup_data.to_vec();
118-
Ok::<_, String>((output, startup_data_vec))
119-
}).await.unwrap();
120-
let (output, startup_data) = v8_result.unwrap();
121-
// 3. Save new snapshot to heap_storage (async)
122-
self.heap_storage.put(&heap, &startup_data).await.unwrap();
123-
RunJsResponse {
124-
output,
125-
heap,
129+
Ok(Err(e)) => RunJsResponse {
130+
output: format!("V8 error: {}", e),
131+
heap,
132+
},
133+
Err(e) => RunJsResponse {
134+
output: format!("Task join error: {}", e),
135+
heap,
136+
},
126137
}
127138
}
128139

snapshot/src/main.rs

Lines changed: 40 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
use std::io::Write;
22

3-
fn eval<'s>(scope: &mut v8::HandleScope<'s>, code: &str) -> Option<v8::Local<'s, v8::Value>> {
3+
fn eval<'s>(scope: &mut v8::HandleScope<'s>, code: &str) -> Result<v8::Local<'s, v8::Value>, String> {
44
let scope = &mut v8::EscapableHandleScope::new(scope);
5-
let source = v8::String::new(scope, code).unwrap();
6-
let script = v8::Script::compile(scope, source, None).unwrap();
7-
let r = script.run(scope);
8-
r.map(|v| scope.escape(v))
5+
let source = v8::String::new(scope, code).ok_or("Failed to create V8 string")?;
6+
let script = v8::Script::compile(scope, source, None).ok_or("Failed to compile script")?;
7+
let r = script.run(scope).ok_or("Failed to run script")?;
8+
Ok(scope.escape(r))
99
}
1010

1111
fn main() {
@@ -34,7 +34,7 @@ fn main() {
3434
let scope = &mut v8::HandleScope::new(&mut snapshot_creator);
3535
let context = v8::Context::new(scope, Default::default());
3636
let scope = &mut v8::ContextScope::new(scope, context);
37-
let out = eval(
37+
let out = match eval(
3838
scope,
3939
"
4040
try {
@@ -43,24 +43,48 @@ try {
4343
x = 1
4444
}
4545
x;
46-
",
47-
)
48-
.unwrap();
46+
",
47+
) {
48+
Ok(val) => val,
49+
Err(e) => {
50+
eprintln!("eval error: {}", e);
51+
return;
52+
}
53+
};
54+
let out_str = match out.to_string(scope) {
55+
Some(s) => s.to_rust_string_lossy(scope),
56+
None => {
57+
eprintln!("Failed to convert result to string");
58+
return;
59+
}
60+
};
4961
eprintln!(
5062
"x = {}",
51-
out.to_string(scope).unwrap().to_rust_string_lossy(scope)
63+
out_str
5264
);
53-
5465
scope.set_default_context(context);
5566
}
56-
snapshot_creator
57-
.create_blob(v8::FunctionCodeHandling::Clear)
58-
.unwrap()
67+
match snapshot_creator
68+
.create_blob(v8::FunctionCodeHandling::Clear) {
69+
Some(blob) => blob,
70+
None => {
71+
eprintln!("Failed to create V8 snapshot blob");
72+
return;
73+
}
74+
}
5975
};
6076

6177
// Write snapshot to file
6278
eprintln!("snapshot created");
6379
eprintln!("writing snapshot to file snapshot.bin in current directory");
64-
let mut file = std::fs::File::create("snapshot.bin").unwrap();
65-
file.write_all(&startup_data).unwrap();
80+
let mut file = match std::fs::File::create("snapshot.bin") {
81+
Ok(f) => f,
82+
Err(e) => {
83+
eprintln!("Failed to create snapshot.bin: {}", e);
84+
return;
85+
}
86+
};
87+
if let Err(e) = file.write_all(&startup_data) {
88+
eprintln!("Failed to write snapshot data: {}", e);
89+
}
6690
}

0 commit comments

Comments
 (0)