(
&self,
dir: String,
workspace: String,
options: Option<SessionOptions>,
)
| 3037 | /// NOT overridden so a host can pin them per schedule |
| 3038 | #[napi] |
| 3039 | pub async fn serve_agent_dir( |
| 3040 | &self, |
| 3041 | dir: String, |
| 3042 | workspace: String, |
| 3043 | options: Option<SessionOptions>, |
| 3044 | ) -> napi::Result<ServeHandle> { |
| 3045 | let agent_dir = RustAgentDir::load(&dir) |
| 3046 | .map_err(|e| napi::Error::from_reason(format!("Failed to load agent dir: {e}")))?; |
| 3047 | let extra = js_session_options_to_rust(options)?; |
| 3048 | |
| 3049 | // The daemon runs until cancelled; spawn it so control returns to JS |
| 3050 | // immediately and the event loop is not blocked. The token, owned by the |
| 3051 | // returned ServeHandle, drives graceful shutdown. |
| 3052 | let cancel = CancellationToken::new(); |
| 3053 | let agent = self.inner.clone(); |
| 3054 | let handle_token = cancel.clone(); |
| 3055 | |
| 3056 | get_runtime().spawn(async move { |
| 3057 | // Spawned task bodies are NOT panic-safe (a panic here is swallowed, |
| 3058 | // never surfaced). `serve_agent_dir` returns Result and never panics |
| 3059 | // by construction; a scheduling error is reported, not propagated. |
| 3060 | if let Err(e) = |
| 3061 | rust_serve_agent_dir(&agent, &agent_dir, workspace, Some(extra), cancel).await |
| 3062 | { |
| 3063 | eprintln!("a3s-code: serve_agent_dir daemon exited with error: {e}"); |
| 3064 | } |
| 3065 | }); |
| 3066 | |
| 3067 | Ok(ServeHandle { |
| 3068 | cancel: handle_token, |
| 3069 | }) |
| 3070 | } |
| 3071 | } |
| 3072 | |
| 3073 | // ============================================================================ |
nothing calls this directly
no test coverage detected