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_REPORT_CYCLES, 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 "reportCycles": DEFAULT_REPORT_CYCLES,
64 "keepAwakeToleratedErrors": crate::session::keepalive::DEFAULT_TOLERATED_ERRORS,
65 "syncDeleteTimeoutSeconds": seconds(crate::workspace::DEFAULT_SYNC_DELETE_TIMEOUT),
66 "launch": {
67 "maxIdleSeconds": launch.max_idle_sec,
68 "suspendedSeconds": launch.suspended_sec,
69 "maxDurationSeconds": launch.max_duration_sec,
70 "autoResume": launch.auto_resume,
71 "egress": launch.egress,
72 "denyEgress": launch.deny_egress,
73 "identity": launch.identity,
74 "shell": launch.shell,
75 "wait": launch.wait,
76 "loggingDisabled": matches!(
79 launch.logging,
80 Some(crate::control::ops::Logging::Disabled { .. })
81 ),
82 },
83 "exec": {
84 "shell": matches!(start.shell, protocol::exec::Shell::Flag(true)),
85 "stdin": start.stdin,
86 "reapGroupOnExit": start.reap_group_on_exit,
87 "poweroffOnExit": start.poweroff_on_exit,
88 "inheritImageEnv": start.inherit_image_env,
89 },
90 "stream": {
91 "reconnect": stream.reconnect,
92 "errorOnGap": stream.error_on_gap,
93 },
94 "teardown": {
95 "deleteImage": teardown.delete_image,
96 "deleteLogGroup": teardown.delete_log_group,
97 "waitForTerminated": teardown.wait_for_terminated.is_some(),
98 },
99 "prompt": {
100 "reapGroupOnExit": prompt.reap_group_on_exit,
101 },
102 "image": {
103 "inheritWorkdir": WrapOptions::default().inherit_workdir,
104 "repairGuestIdentity": image.repair_guest_identity,
105 "force": ensured.force,
106 },
107 })
108}
109
110fn seconds(duration: Duration) -> f64 {
112 duration.as_secs_f64()
113}
114
115#[cfg(test)]
116mod tests {
117 use super::*;
118
119 #[test]
126 fn the_client_defaults_are_cores_own_values() {
127 let defaults = client_defaults();
128 assert_eq!(
129 defaults["execWaitSeconds"],
130 DEFAULT_EXEC_WAIT.as_secs_f64(),
131 "execWaitSeconds"
132 );
133 assert_eq!(defaults["agentPort"], DEFAULT_AGENT_PORT);
134 assert_eq!(defaults["sizeMib"], SizeClass::DEFAULT.baseline_mib());
135 let launch = RunRequest::default();
136 assert_eq!(defaults["launch"]["maxIdleSeconds"], launch.max_idle_sec);
137 assert_eq!(defaults["launch"]["wait"], launch.wait);
138 let start = protocol::exec::StartRequest::new("x", vec!["true".into()]);
139 assert_eq!(defaults["exec"]["stdin"], start.stdin);
140 assert_eq!(defaults["exec"]["shell"], false);
141 assert_eq!(
142 defaults["syncDeleteTimeoutSeconds"],
143 crate::workspace::DEFAULT_SYNC_DELETE_TIMEOUT.as_secs_f64()
144 );
145 }
146}