Register as external task and wait for completion
(&self)
| 108 | |
| 109 | /// Register as external task and wait for completion |
| 110 | async fn register_and_wait(&self) -> LaneResult<Value> { |
| 111 | let (tx, rx) = oneshot::channel(); |
| 112 | let task = ExternalTask { |
| 113 | task_id: self.task_id.clone(), |
| 114 | session_id: self.session_id.clone(), |
| 115 | lane: self.lane, |
| 116 | command_type: self.inner.command_type().to_string(), |
| 117 | payload: self.inner.payload(), |
| 118 | timeout_ms: self.timeout_ms, |
| 119 | created_at: Some(Instant::now()), |
| 120 | }; |
| 121 | { |
| 122 | let mut tasks = self.external_tasks.write().await; |
| 123 | tasks.insert( |
| 124 | self.task_id.clone(), |
| 125 | PendingExternalTask { |
| 126 | task: task.clone(), |
| 127 | result_tx: tx, |
| 128 | }, |
| 129 | ); |
| 130 | } |
| 131 | let _ = self.event_tx.send(AgentEvent::ExternalTaskPending { |
| 132 | task_id: task.task_id.clone(), |
| 133 | session_id: task.session_id.clone(), |
| 134 | lane: task.lane, |
| 135 | command_type: task.command_type.clone(), |
| 136 | payload: task.payload.clone(), |
| 137 | timeout_ms: task.timeout_ms, |
| 138 | }); |
| 139 | match tokio::time::timeout(Duration::from_millis(self.timeout_ms), rx).await { |
| 140 | Ok(Ok(result)) => result.map_err(|e| LaneError::CommandError(e.to_string())), |
| 141 | Ok(Err(_)) => Err(LaneError::CommandError("Channel closed".to_string())), |
| 142 | Err(_) => { |
| 143 | let mut tasks = self.external_tasks.write().await; |
| 144 | tasks.remove(&self.task_id); |
| 145 | Err(LaneError::Timeout(Duration::from_millis(self.timeout_ms))) |
| 146 | } |
| 147 | } |
| 148 | } |
| 149 | |
| 150 | /// Execute internally with external notification (Hybrid mode) |
| 151 | async fn execute_with_notification(&self) -> LaneResult<Value> { |