- 1001
assert!(!super::references_control_file("echo ok > result.txt")); - 1002
} - 1003
- 1004
#[tokio::test] - 1005
async fn cwd_dot_runs_in_the_workspace_root() { - 1006
use crate::{Tool, ToolContext, sandbox_events::SandboxEventSink}; - 1007
let workspace = tempfile::tempdir().unwrap(); - 1008
let test_file = workspace.path().join("marker.txt"); - 1009
std::fs::write(&test_file, "workspace-marker").unwrap(); - 1010
- 1011
let (sink, _rx) = SandboxEventSink::new_with_id("test-quarantine-false".into()); - 1012
let ctx = ToolContext::new(workspace.path().to_path_buf()).with_sandbox_sink(sink); - 1013
- 1014
let tool = super::BashTool; - 1015
let out = tool - 1016
.execute( - 1017
&serde_json::json!({ - 1018
"command": "cat marker.txt", - 1019
"cwd": "." - 1020
}), - 1021
&ctx, - 1022
) - 1023
.await; - 1024
assert!(!out.is_error, "{}", out.content); - 1025
assert!(out.content.contains("workspace-marker")); - 1026
} - 1027
- 1028
#[tokio::test] - 1029
async fn a_command_works_in_the_workspace_and_keeps_temp_files_in_scratch() { - 1030
use crate::{Tool, ToolContext, sandbox_events::SandboxEventSink}; - 1031
let workspace = tempfile::tempdir().unwrap(); - 1032
std::fs::write(workspace.path().join("unsorted.txt"), "delta\nalpha\n").unwrap(); - 1033
- 1034
let (sink, mut events) = SandboxEventSink::new_with_id("sort-1".into()); - 1035
let ctx = ToolContext::new(workspace.path().to_path_buf()).with_sandbox_sink(sink); - 1036
let out = super::BashTool - 1037
.execute( - 1038
&serde_json::json!({ - 1039
"command": "sort unsorted.txt > sorted.txt && echo \"tmp=$TMPDIR\"" - 1040
}), - 1041
&ctx, - 1042
) - 1043
.await; - 1044
assert!(!out.is_error, "{}", out.content); - 1045
assert_eq!( - 1046
std::fs::read_to_string(workspace.path().join("sorted.txt")).unwrap(), - 1047
"alpha\ndelta\n", - 1048
"the output is where `read` looks for it" - 1049
); - 1050
let temp = workspace.path().join(".vak/scratch/vak/sort-1/tmp"); - 1051
assert!( - 1052
out.content.contains(&format!("tmp={}", temp.display())), - 1053
"{}", - 1054
out.content - 1055
); - 1056
let mut reported = false; - 1057
while let Ok(event) = events.try_recv() { - 1058
if let crate::SandboxEvent::ArtifactGenerated { path, .. } = event { - 1059
reported |= path == "sorted.txt"; - 1060
} - 1061
} - 1062
assert!(reported, "a new deliverable is reported to the Workbench"); - 1063
} - 1064
- 1065
#[tokio::test] - 1066
async fn custom_cwd_is_respected() { - 1067
use crate::{Tool, ToolContext, sandbox_events::SandboxEventSink}; - 1068
let workspace = tempfile::tempdir().unwrap(); - 1069
let sub = workspace - 1070
.path() - 1071
.join(".vak/scratch/vak/test-custom-cwd/sub_module"); - 1072
std::fs::create_dir_all(&sub).unwrap(); - 1073
std::fs::write(sub.join("sub.txt"), "in-sub").unwrap(); - 1074
- 1075
let (sink, _rx) = SandboxEventSink::new_with_id("test-custom-cwd".into()); - 1076
let ctx = ToolContext::new(workspace.path().to_path_buf()).with_sandbox_sink(sink); - 1077
- 1078
let tool = super::BashTool; - 1079
let out = tool - 1080
.execute( - 1081
&serde_json::json!({ - 1082
"command": "cat sub.txt", - 1083
"cwd": ".vak/scratch/vak/test-custom-cwd/sub_module" - 1084
}), - 1085
&ctx, - 1086
) - 1087
.await; - 1088
assert!(!out.is_error, "{}", out.content); - 1089
assert!(out.content.contains("in-sub")); - 1090
} - 1091
- 1092
#[tokio::test] - 1093
async fn custom_cwd_rejects_workspace_escape() { - 1094
use crate::{Tool, ToolContext, sandbox_events::SandboxEventSink}; - 1095
let workspace = tempfile::tempdir().unwrap(); - 1096
let (sink, _rx) = SandboxEventSink::new_with_id("test-cwd-escape".into()); - 1097
let ctx = ToolContext::new(workspace.path().to_path_buf()).with_sandbox_sink(sink); - 1098
let out = super::BashTool - 1099
.execute( - 1100
&serde_json::json!({ - 1101
"command": "pwd", - 1102
"cwd": ".." - 1103
}), - 1104
&ctx, - 1105
) - 1106
.await; - 1107
assert!(out.is_error); - 1108
assert!(out.content.contains("inside the workspace")); - 1109
} - 1110
- 1111
#[tokio::test] - 1112
async fn temp_files_are_scoped_to_the_agent() { - 1113
use crate::{Tool, ToolContext, sandbox_events::SandboxEventSink}; - 1114
let workspace = tempfile::tempdir().unwrap(); - 1115
let (sink, _events) = SandboxEventSink::new_with_id("test-agent-scratch".into()); - 1116
let ctx = ToolContext::new(workspace.path().to_path_buf()) - 1117
.with_agent_id("researcher-99") - 1118
.with_sandbox_sink(sink); - 1119
- 1120
let out = super::BashTool - 1121
.execute(&serde_json::json!({"command": "echo \"$TMPDIR\""}), &ctx) - 1122
.await; - 1123
assert!(!out.is_error, "stdout/stderr: {}", out.content); - 1124
assert!( - 1125
out.content - 1126
.contains(".vak/scratch/researcher-99/test-agent-scratch/tmp"), - 1127
"{}", - 1128
out.content - 1129
); - 1130
} - 1131
- 1132
#[tokio::test] - 1133
async fn workspace_command_promotes_user_visible_result() { - 1134
use crate::{Tool, ToolContext, sandbox_events::SandboxEventSink}; - 1135
let workspace = tempfile::tempdir().unwrap(); - 1136
let (sink, mut events) = SandboxEventSink::new_with_id("test-workspace-result".into()); - 1137
let ctx = ToolContext::new(workspace.path().to_path_buf()).with_sandbox_sink(sink); - 1138
- 1139
let out = super::BashTool - 1140
.execute( - 1141
&serde_json::json!({ - 1142
"command": "printf '<h1>India market</h1>\\n' > index.html", - 1143
"cwd": "." - 1144
}), - 1145
&ctx, - 1146
) - 1147
.await; - 1148
assert!(!out.is_error, "stdout/stderr: {}", out.content); - 1149
assert!(workspace.path().join("index.html").is_file()); - 1150
let mut saw_result = false; - 1151
while let Ok(event) = events.try_recv() { - 1152
if let crate::SandboxEvent::ArtifactGenerated { path, .. } = event { - 1153
saw_result |= path == "index.html"; - 1154
} - 1155
} - 1156
assert!( - 1157
saw_result, - 1158
"workspace result should be emitted as an artifact" - 1159
); - 1160
} - 1161
} - 1162
Indexing the workspace…
Vakyartha documentation is discovering safe artifacts, anchors, and source references.