1use std::time::Duration;
16
17use serde_json::{Value, json};
18
19use crate::agents::{DEFAULT_PROMPT_TIMEOUT, DEFAULT_SIZE, PromptOptions, bedrock};
20use crate::control::artifact::WrapOptions;
21use crate::control::ensure::EnsureImageRequest;
22use crate::control::{CreateImageRequest, DEFAULT_AGENT_PORT};
23use crate::cost::DEFAULT_RESIDENCY_CYCLES;
24use crate::sandbox::{
25 DEFAULT_LIFECYCLE_TIMEOUT, LIFECYCLE_POLL_INTERVAL, RunRequest, TeardownOpts,
26};
27use crate::session::{DEFAULT_CLIENT_GRACE, DEFAULT_EXEC_WAIT, StreamOptions};
28use crate::sizing::SizeClass;
29
30pub fn client_defaults() -> Value {
36 let launch = RunRequest::default();
37 let start = protocol::exec::StartRequest::new(String::new(), Vec::new());
38 let stream = StreamOptions::default();
39 let teardown = TeardownOpts::default();
40 let prompt = PromptOptions::default();
41 let image = CreateImageRequest::new(String::new(), Vec::new(), String::new(), String::new());
42 let ensured = EnsureImageRequest::new(
43 String::new(),
44 Vec::new(),
45 String::new(),
46 String::new(),
47 String::new(),
48 );
49 json!({
50 "sizeMib": SizeClass::DEFAULT.baseline_mib(),
51 "agentSizeMib": DEFAULT_SIZE.baseline_mib(),
52 "agentPort": DEFAULT_AGENT_PORT,
53 "execWaitSeconds": seconds(DEFAULT_EXEC_WAIT),
54 "readyTimeoutSeconds": seconds(crate::session::DEFAULT_BOOTSTRAP_TIMEOUT),
56 "launchTimeoutSeconds": seconds(crate::sandbox::DEFAULT_RUNNING_TIMEOUT),
57 "lifecycleTimeoutSeconds": seconds(DEFAULT_LIFECYCLE_TIMEOUT),
58 "lifecyclePollIntervalSeconds": seconds(LIFECYCLE_POLL_INTERVAL),
59 "promptTimeoutSeconds": seconds(DEFAULT_PROMPT_TIMEOUT),
60 "clientGraceSeconds": seconds(DEFAULT_CLIENT_GRACE),
61 "bedrockTokenTtlHours": bedrock::MAX_LIFETIME.as_secs() / 3600,
62 "residencyCycles": DEFAULT_RESIDENCY_CYCLES,
63 "keepAwakeToleratedErrors": crate::session::keepalive::DEFAULT_TOLERATED_ERRORS,
64 "syncDeleteTimeoutSeconds": seconds(crate::workspace::DEFAULT_SYNC_DELETE_TIMEOUT),
65 "launch": {
66 "maxIdleSeconds": launch.max_idle_sec,
67 "suspendedSeconds": launch.suspended_sec,
68 "maxDurationSeconds": launch.max_duration_sec,
69 "autoResume": launch.auto_resume,
70 "egress": launch.egress,
71 "denyEgress": launch.deny_egress,
72 "identity": launch.identity,
73 "shell": launch.shell,
74 "wait": launch.wait,
75 "loggingDisabled": matches!(
78 launch.logging,
79 Some(crate::control::ops::Logging::Disabled { .. })
80 ),
81 },
82 "exec": {
83 "shell": matches!(start.shell, protocol::exec::Shell::Flag(true)),
84 "stdin": start.stdin,
85 "reapGroupOnExit": start.reap_group_on_exit,
86 "inheritImageEnv": start.inherit_image_env,
87 },
88 "stream": {
89 "reconnect": stream.reconnect,
90 "errorOnGap": stream.error_on_gap,
91 },
92 "teardown": {
93 "deleteImage": teardown.delete_image,
94 "deleteLogGroup": teardown.delete_log_group,
95 "waitForTerminated": teardown.wait_for_terminated.is_some(),
96 },
97 "prompt": {
98 "reapGroupOnExit": prompt.reap_group_on_exit,
99 },
100 "image": {
101 "inheritWorkdir": WrapOptions::default().inherit_workdir,
102 "repairGuestIdentity": image.repair_guest_identity,
103 "force": ensured.force,
104 },
105 })
106}
107
108fn seconds(duration: Duration) -> f64 {
110 duration.as_secs_f64()
111}
112
113#[cfg(test)]
114mod tests {
115 use super::*;
116
117 #[test]
124 fn the_client_defaults_are_cores_own_values() {
125 let defaults = client_defaults();
126 assert_eq!(
127 defaults["execWaitSeconds"],
128 DEFAULT_EXEC_WAIT.as_secs_f64(),
129 "execWaitSeconds"
130 );
131 assert_eq!(defaults["agentPort"], DEFAULT_AGENT_PORT);
132 assert_eq!(defaults["sizeMib"], SizeClass::DEFAULT.baseline_mib());
133 let launch = RunRequest::default();
134 assert_eq!(defaults["launch"]["maxIdleSeconds"], launch.max_idle_sec);
135 assert_eq!(defaults["launch"]["wait"], launch.wait);
136 let start = protocol::exec::StartRequest::new("x", vec!["true".into()]);
137 assert_eq!(defaults["exec"]["stdin"], start.stdin);
138 assert_eq!(defaults["exec"]["shell"], false);
139 assert_eq!(
140 defaults["syncDeleteTimeoutSeconds"],
141 crate::workspace::DEFAULT_SYNC_DELETE_TIMEOUT.as_secs_f64()
142 );
143 }
144}