1use std::cell::RefCell;
21use std::collections::{BTreeMap, BTreeSet, VecDeque};
22use std::rc::Rc;
23
24use crate::budget::{Budget, BudgetMeter};
25use crate::cap::{CapAttrs, CapControl, CapHandle, CapId, CapRecord, ProviderId, ToolPolicy};
26use crate::channel::{Channel, ChannelId, Direction, Message};
27use crate::error::{Error, Result};
28use crate::lane::{Lane, LaneId};
29use crate::promise::{PromiseId, PromiseRecord, PromiseState};
30use crate::value::{Arg, Call, Response, Value};
31
32pub trait Provider {
34 fn name(&self) -> &'static str;
36 fn methods(&self) -> Vec<String>;
38 fn has_method(&self, method: &str) -> bool {
40 self.methods().iter().any(|name| name == method)
41 }
42 fn mutating(&self, method: &str) -> bool;
44 fn invoke(&mut self, object: u64, call: &Call) -> Result<Response>;
46 fn on_drop(&mut self, _object: u64, _cap: CapId) {}
48
49 fn take_drop_notifications(&mut self) -> Vec<(u64, CapId)> {
54 Vec::new()
55 }
56}
57
58#[derive(Debug, Clone, PartialEq)]
60pub enum Event {
61 CapMinted {
63 cap: CapId,
65 provider: ProviderId,
67 },
68 CapRetained(CapId),
70 CapReleased(CapId),
72 CapDropped(CapId),
74 CapRevoked(CapId),
76 LaneCreated(LaneId),
78 LaneDestroyed(LaneId),
80 CallQueued {
82 job: u64,
84 lane: LaneId,
86 cap: CapId,
88 },
89 BatchDispatched {
91 provider: ProviderId,
93 jobs: usize,
95 lanes: BTreeSet<u64>,
97 },
98 JobCompleted {
100 job: u64,
102 lane: LaneId,
104 },
105 PromiseResolved(PromiseId),
107 PromiseRejected {
109 promise: PromiseId,
111 code: String,
113 },
114 ChannelSend {
116 channel: ChannelId,
118 sequence: u64,
120 },
121 ChannelRecv {
123 channel: ChannelId,
125 sequence: u64,
127 },
128 CapTransferred {
130 cap: CapId,
132 channel: ChannelId,
134 },
135}
136
137#[derive(Debug, Clone, Copy, PartialEq, Eq)]
138enum JobState {
139 Queued,
140 Done,
141}
142
143#[derive(Debug, Clone)]
144struct Job {
145 #[allow(dead_code)]
146 id: u64,
147 lane: LaneId,
148 cap: CapId,
149 call: Call,
150 deps: Vec<PromiseId>,
151 promise: PromiseId,
152 state: JobState,
153}
154
155pub struct Kernel {
156 secret: [u8; 32],
157 providers: BTreeMap<ProviderId, Box<dyn Provider>>,
158 caps: BTreeMap<CapId, CapRecord>,
159 meters: BTreeMap<CapId, BudgetMeter>,
160 promises: BTreeMap<PromiseId, PromiseRecord>,
161 lanes: BTreeMap<LaneId, Lane>,
162 channels: BTreeMap<ChannelId, Channel>,
163 jobs: BTreeMap<u64, Job>,
164 queue: VecDeque<u64>,
165 events: Vec<Event>,
166 round_trips: u64,
167 next_promise: u64,
168 next_job: u64,
169 next_lane: u64,
170 next_channel: u64,
171 next_serial: u64,
172 next_provider: u64,
173 now_ms: u64,
174 latency_ms: u64,
175 transfers: u64,
176}
177
178pub(crate) struct HandleControl {
182 cell: KernelCell,
183}
184
185impl HandleControl {
186 fn new(cell: KernelCell) -> Self {
187 Self { cell }
188 }
189}
190
191impl CapControl for HandleControl {
192 fn retain(&self, id: CapId) {
193 if let Ok(mut kernel) = self.cell.try_borrow_mut() {
194 if let Some(record) = kernel.caps.get_mut(&id) {
195 record.refs = record.refs.saturating_add(1);
196 kernel.events.push(Event::CapRetained(id));
197 }
198 }
199 }
200
201 fn release(&self, id: CapId) {
202 let dropped = {
203 let Ok(mut kernel) = self.cell.try_borrow_mut() else {
204 return;
205 };
206 let Some(record) = kernel.caps.get_mut(&id) else {
207 return;
208 };
209 record.refs = record.refs.saturating_sub(1);
210 let last = record.refs == 0;
211 kernel.events.push(Event::CapReleased(id));
212 last
213 };
214 if !dropped {
215 return;
216 }
217 let mut kernel = self.cell.borrow_mut();
218 let Some(record) = kernel.caps.remove(&id) else {
219 return;
220 };
221 kernel.meters.remove(&id);
222 kernel.events.push(Event::CapDropped(id));
223 if let Some(provider) = kernel.providers.get_mut(&record.provider) {
224 provider.on_drop(record.object, id);
225 }
226 }
227}
228
229pub type KernelCell = Rc<RefCell<Kernel>>;
231
232#[derive(Clone)]
234pub struct Agent {
235 cell: KernelCell,
236 control: Rc<dyn CapControl>,
237}
238
239impl Default for Agent {
240 fn default() -> Self {
241 Self::new()
242 }
243}
244
245impl Agent {
246 pub fn new() -> Self {
248 let mut seed = [0u8; 32];
249 let nanos = std::time::SystemTime::now()
250 .duration_since(std::time::UNIX_EPOCH)
251 .map(|duration| duration.as_nanos())
252 .unwrap_or(0);
253 let counter = NEXT_AGENT.with(|value| {
254 let mut value = value.borrow_mut();
255 *value += 1;
256 *value
257 });
258 let mut hasher = blake3::Hasher::new();
259 hasher.update(b"active-rpc/agent");
260 hasher.update(&nanos.to_le_bytes());
261 hasher.update(&counter.to_le_bytes());
262 seed.copy_from_slice(&hasher.finalize().as_bytes()[..32]);
263 Self::with_secret(seed)
264 }
265
266 pub fn with_secret(secret: [u8; 32]) -> Self {
268 let kernel = Kernel {
269 secret,
270 providers: BTreeMap::new(),
271 caps: BTreeMap::new(),
272 meters: BTreeMap::new(),
273 promises: BTreeMap::new(),
274 lanes: BTreeMap::new(),
275 channels: BTreeMap::new(),
276 jobs: BTreeMap::new(),
277 queue: VecDeque::new(),
278 events: Vec::new(),
279 round_trips: 0,
280 next_promise: 0,
281 next_job: 0,
282 next_lane: 0,
283 next_channel: 0,
284 next_serial: 0,
285 next_provider: 0,
286 now_ms: 0,
287 latency_ms: 1,
288 transfers: 0,
289 };
290 let cell: KernelCell = Rc::new(RefCell::new(kernel));
291 let control: Rc<dyn CapControl> = Rc::new(HandleControl::new(Rc::clone(&cell)));
292 Agent { cell, control }
293 }
294
295 pub fn cell(&self) -> &KernelCell {
297 &self.cell
298 }
299
300 pub fn register(&self, provider: Box<dyn Provider>) -> ProviderId {
302 let mut kernel = self.cell.borrow_mut();
303 let id = ProviderId(kernel.next_provider);
304 kernel.next_provider += 1;
305 kernel.providers.insert(id, provider);
306 id
307 }
308
309 pub fn set_latency(&self, latency_ms: u64) {
311 self.cell.borrow_mut().latency_ms = latency_ms;
312 }
313
314 pub fn mint(&self, provider: ProviderId, object: u64, attrs: CapAttrs) -> Result<CapHandle> {
316 attrs.budget.check()?;
317 if attrs.methods.is_empty() {
318 return Err(Error::InvalidArgument("capability grants no methods"));
319 }
320 let mut kernel = self.cell.borrow_mut();
321 if !kernel.providers.contains_key(&provider) {
322 return Err(Error::InvalidArgument("unknown provider"));
323 }
324 let serial = kernel.next_serial;
325 kernel.next_serial += 1;
326 let id = CapId::derive(&kernel.secret, serial, None);
327 let record = CapRecord::new(id, provider, object, attrs.clone());
328 kernel.meters.insert(id, BudgetMeter::new(attrs.budget));
329 kernel.caps.insert(id, record);
330 kernel.events.push(Event::CapMinted { cap: id, provider });
331 Ok(CapHandle::new(Rc::clone(&self.control), id))
332 }
333
334 pub fn attenuate(&self, parent: &CapHandle, attrs: CapAttrs) -> Result<CapHandle> {
336 let parent_id = parent.id();
337 let mut kernel = self.cell.borrow_mut();
338 let record = kernel
339 .caps
340 .get(&parent_id)
341 .ok_or(Error::UnknownCapability(u128::from_be_bytes(pad128(
342 parent_id,
343 ))))?
344 .clone();
345 if record.revoked {
346 return Err(Error::Revoked(u128::from_be_bytes(pad128(parent_id))));
347 }
348 let attrs = record.attrs.attenuate(attrs)?;
349 let serial = kernel.next_serial;
350 kernel.next_serial += 1;
351 let id = CapId::derive(&kernel.secret, serial, Some(&parent_id));
352 let mut child = CapRecord::new(id, record.provider, record.object, attrs.clone());
353 child.parent = Some(parent_id);
354 kernel.meters.insert(id, BudgetMeter::new(attrs.budget));
355 kernel.caps.insert(id, child);
356 kernel.events.push(Event::CapMinted {
357 cap: id,
358 provider: record.provider,
359 });
360 Ok(CapHandle::new(Rc::clone(&self.control), id))
361 }
362
363 pub fn import(&self, id: CapId) -> CapHandle {
370 CapHandle::borrowed(Rc::clone(&self.control), id)
371 }
372
373 pub fn revoke(&self, cap: &CapHandle) {
375 let mut kernel = self.cell.borrow_mut();
376 let mut doomed = BTreeSet::new();
377 let mut stack = vec![cap.id()];
378 while let Some(id) = stack.pop() {
379 if !doomed.insert(id) {
380 continue;
381 }
382 for (child, record) in &kernel.caps {
383 if record.parent == Some(id) {
384 stack.push(*child);
385 }
386 }
387 }
388 for id in doomed {
389 if let Some(record) = kernel.caps.get_mut(&id) {
390 record.revoked = true;
391 }
392 kernel.events.push(Event::CapRevoked(id));
393 }
394 }
395
396 pub fn create_lane(&self, name: impl Into<String>, budget: Budget) -> Result<LaneId> {
398 budget.check()?;
399 let mut kernel = self.cell.borrow_mut();
400 let id = LaneId(kernel.next_lane);
401 kernel.next_lane += 1;
402 kernel.lanes.insert(id, Lane::new(id, name, budget));
403 kernel.events.push(Event::LaneCreated(id));
404 Ok(id)
405 }
406
407 pub fn attenuate_lane(&self, lane: LaneId, budget: Budget) -> Result<()> {
409 let mut kernel = self.cell.borrow_mut();
410 let record = kernel
411 .lanes
412 .get_mut(&lane)
413 .ok_or(Error::UnknownLane(lane.0))?;
414 record.attenuate(budget)
415 }
416
417 pub fn destroy_lane(&self, lane: LaneId) -> Result<()> {
419 let mut kernel = self.cell.borrow_mut();
420 let record = kernel
421 .lanes
422 .get_mut(&lane)
423 .ok_or(Error::UnknownLane(lane.0))?;
424 record.destroy();
425 kernel.events.push(Event::LaneDestroyed(lane));
426 Ok(())
427 }
428
429 pub fn create_channel(
431 &self,
432 name: impl Into<String>,
433 direction: Direction,
434 ) -> Result<ChannelId> {
435 let mut kernel = self.cell.borrow_mut();
436 let id = ChannelId(kernel.next_channel);
437 kernel.next_channel += 1;
438 kernel
439 .channels
440 .insert(id, Channel::new(id, name, direction));
441 Ok(id)
442 }
443
444 pub fn subscribe(&self, lane: LaneId, channel: ChannelId) -> Result<()> {
446 let mut kernel = self.cell.borrow_mut();
447 if !kernel.lanes.contains_key(&lane) {
448 return Err(Error::UnknownLane(lane.0));
449 }
450 let record = kernel
451 .channels
452 .get_mut(&channel)
453 .ok_or(Error::UnknownChannel(channel.0))?;
454 record.subscribers.insert(lane.0);
455 if let Some(lane) = kernel.lanes.get_mut(&lane) {
456 lane.channels.insert(channel.0);
457 }
458 Ok(())
459 }
460
461 pub fn send(
463 &self,
464 lane: LaneId,
465 channel: ChannelId,
466 payload: Value,
467 caps: &[CapHandle],
468 ) -> Result<u64> {
469 let mut kernel = self.cell.borrow_mut();
470 if !kernel.lanes.contains_key(&lane) {
471 return Err(Error::UnknownLane(lane.0));
472 }
473 let mut cap_ids = Vec::with_capacity(caps.len());
474 for cap in caps {
475 let record = kernel
476 .caps
477 .get(&cap.id())
478 .ok_or(Error::InvalidArgument("unknown capability"))?;
479 if record.revoked {
480 return Err(Error::Revoked(u128::from_be_bytes(pad128(cap.id()))));
481 }
482 cap_ids.push(cap.id());
486 }
487 let record = kernel
488 .channels
489 .get_mut(&channel)
490 .ok_or(Error::UnknownChannel(channel.0))?;
491 let message = record.send(lane, payload, cap_ids.clone())?;
492 kernel.events.push(Event::ChannelSend {
493 channel,
494 sequence: message.sequence,
495 });
496 for id in cap_ids {
497 if let Some(record) = kernel.caps.get_mut(&id) {
498 record.refs = record.refs.saturating_add(1);
499 }
500 kernel.transfers += 1;
501 kernel
502 .events
503 .push(Event::CapTransferred { cap: id, channel });
504 }
505 Ok(message.sequence)
506 }
507
508 pub fn recv(&self, channel: ChannelId) -> Result<Option<Message>> {
510 let mut kernel = self.cell.borrow_mut();
511 let record = kernel
512 .channels
513 .get_mut(&channel)
514 .ok_or(Error::UnknownChannel(channel.0))?;
515 let message = record.recv()?;
516 if let Some(message) = &message {
517 kernel.events.push(Event::ChannelRecv {
518 channel,
519 sequence: message.sequence,
520 });
521 }
522 Ok(message)
523 }
524
525 pub fn call(
527 &self,
528 lane: LaneId,
529 cap: &CapHandle,
530 method: &str,
531 args: Vec<Arg>,
532 ) -> Result<PromiseHandle> {
533 let mut kernel = self.cell.borrow_mut();
534 let cap_id = cap.id();
535 let record = kernel
536 .caps
537 .get(&cap_id)
538 .ok_or(Error::UnknownCapability(u128::from_be_bytes(pad128(
539 cap_id,
540 ))))?
541 .clone();
542 if record.revoked {
543 return Err(Error::Revoked(u128::from_be_bytes(pad128(cap_id))));
544 }
545 let (lane_closed, lane_capacity, lane_budget) = {
546 let lane_record = kernel.lanes.get(&lane).ok_or(Error::UnknownLane(lane.0))?;
547 (
548 lane_record.closed,
549 lane_record.has_capacity(),
550 lane_record.budget,
551 )
552 };
553 if lane_closed {
554 return Err(Error::UnknownLane(lane.0));
555 }
556 if !lane_capacity {
557 return Err(Error::BudgetExceeded("lane call"));
558 }
559 if !record.attrs.grants(method) {
560 return Err(Error::MethodNotGranted {
561 method: method.to_string(),
562 });
563 }
564 let provider = kernel
565 .providers
566 .get(&record.provider)
567 .ok_or(Error::InvalidArgument("provider disappeared"))?;
568 if !provider.has_method(method) {
569 return Err(Error::MethodNotGranted {
570 method: method.to_string(),
571 });
572 }
573 if record.attrs.read_only && provider.mutating(method) {
574 return Err(Error::ReadOnly);
575 }
576 if let Some(scope) = &record.attrs.path_scope {
578 for arg in &args {
579 if let Arg::Value(Value::Path(path)) = arg {
580 if !crate::cap::is_path_prefix(scope, path) {
581 return Err(Error::PathNotGranted(path.clone()));
582 }
583 }
584 }
585 }
586 if let Some(policy) = &record.attrs.tool_policy {
588 if !policy.allowed.contains(method) {
589 return Err(Error::ToolPolicy("tool not allowed"));
590 }
591 let bytes: u64 = args
592 .iter()
593 .map(|arg| match arg {
594 Arg::Value(Value::Text(text)) => text.len() as u64,
595 Arg::Value(Value::Module(bytes)) => bytes.len() as u64,
596 _ => 0,
597 })
598 .sum();
599 if bytes > policy.max_arg_bytes {
600 return Err(Error::ToolPolicy("argument too large"));
601 }
602 }
603 let meter = kernel
604 .meters
605 .get_mut(&cap_id)
606 .ok_or(Error::InvalidArgument("capability has no meter"))?;
607 meter.charge(0)?;
608 let effective = record.attrs.budget.intersect(&lane_budget);
609
610 let promise_id = PromiseId(kernel.next_promise);
611 kernel.next_promise += 1;
612 kernel
613 .promises
614 .insert(promise_id, PromiseRecord::new(promise_id, lane.0));
615 let job_id = kernel.next_job;
616 kernel.next_job += 1;
617 let deps: Vec<PromiseId> = args.iter().filter_map(|arg| arg.promise()).collect();
618 for dep in &deps {
619 if !kernel.promises.contains_key(dep) {
620 return Err(Error::UnknownPromise(dep.0));
621 }
622 if let Some(record) = kernel.promises.get_mut(dep) {
623 record.waiters += 1;
624 }
625 }
626 let call = Call {
627 method: method.to_string(),
628 args,
629 path_scope: record.attrs.path_scope.clone(),
630 redact: record.attrs.redact,
631 read_only: record.attrs.read_only,
632 tool_allows_process: record
633 .attrs
634 .tool_policy
635 .as_ref()
636 .map(|policy| policy.allow_process)
637 .unwrap_or(false),
638 budget: effective,
639 };
640 let job = Job {
641 id: job_id,
642 lane,
643 cap: cap_id,
644 call,
645 deps,
646 promise: promise_id,
647 state: JobState::Queued,
648 };
649 kernel.jobs.insert(job_id, job);
650 kernel.queue.push_back(job_id);
651 if let Some(lane_record) = kernel.lanes.get_mut(&lane) {
652 lane_record.pending += 1;
653 }
654 kernel.events.push(Event::CallQueued {
655 job: job_id,
656 lane,
657 cap: cap_id,
658 });
659 let _ = effective;
661 Ok(PromiseHandle {
662 agent: self.clone(),
663 id: promise_id,
664 })
665 }
666
667 pub fn run(&self) -> u64 {
669 loop {
670 let batch = {
671 let mut kernel = self.cell.borrow_mut();
672 if kernel.queue.is_empty() {
673 return kernel.round_trips;
674 }
675 match kernel.next_batch() {
676 Ok(batch) => batch,
677 Err(_) => {
678 let jobs: Vec<u64> = kernel.queue.drain(..).collect();
680 for job_id in jobs {
681 kernel.fail_job(job_id, "rpc/pipelined-cycle");
682 }
683 return kernel.round_trips;
684 }
685 }
686 };
687 self.dispatch(batch);
688 }
689 }
690
691 pub fn round_trips(&self) -> u64 {
693 self.cell.borrow().round_trips
694 }
695
696 pub fn await_promise(&self, promise: &PromiseHandle) -> Result<Value> {
698 loop {
699 {
700 let kernel = self.cell.borrow();
701 let record = kernel
702 .promises
703 .get(&promise.id)
704 .ok_or(Error::UnknownPromise(promise.id.0))?;
705 if record.state.is_settled() {
706 return record.value();
707 }
708 }
709 if self.cell.borrow().queue.is_empty() {
710 return Err(Error::UnresolvablePromise(promise.id.0));
711 }
712 self.run();
713 }
714 }
715
716 pub fn resolve(&self, promise: &PromiseHandle, value: Value) -> Result<()> {
718 let mut kernel = self.cell.borrow_mut();
719 let record = kernel
720 .promises
721 .get_mut(&promise.id)
722 .ok_or(Error::UnknownPromise(promise.id.0))?;
723 record.resolve(value)?;
724 kernel.events.push(Event::PromiseResolved(promise.id));
725 Ok(())
726 }
727
728 pub fn cancel(&self, promise: &PromiseHandle) -> Result<()> {
730 let mut kernel = self.cell.borrow_mut();
731 let record = kernel
732 .promises
733 .get_mut(&promise.id)
734 .ok_or(Error::UnknownPromise(promise.id.0))?;
735 record.cancel()
736 }
737
738 pub fn take_drops(&self, provider: ProviderId) -> Vec<(u64, CapId)> {
740 self.cell
741 .borrow_mut()
742 .providers
743 .get_mut(&provider)
744 .map(|provider| provider.take_drop_notifications())
745 .unwrap_or_default()
746 }
747
748 pub fn events(&self) -> Vec<Event> {
750 self.cell.borrow().events.clone()
751 }
752
753 pub fn lane(&self, lane: LaneId) -> Result<Lane> {
755 self.cell
756 .borrow()
757 .lanes
758 .get(&lane)
759 .cloned()
760 .ok_or(Error::UnknownLane(lane.0))
761 }
762
763 pub fn channel(&self, channel: ChannelId) -> Result<Channel> {
765 self.cell
766 .borrow()
767 .channels
768 .get(&channel)
769 .cloned()
770 .ok_or(Error::UnknownChannel(channel.0))
771 }
772
773 pub fn cap_attrs(&self, cap: &CapHandle) -> Result<CapAttrs> {
775 self.cell
776 .borrow()
777 .caps
778 .get(&cap.id())
779 .map(|record| record.attrs.clone())
780 .ok_or(Error::UnknownCapability(u128::from_be_bytes(pad128(
781 cap.id(),
782 ))))
783 }
784
785 fn dispatch(&self, batch: Vec<u64>) {
786 let mut kernel = self.cell.borrow_mut();
787 kernel.round_trips += 1;
788 kernel.now_ms = kernel.now_ms.saturating_add(kernel.latency_ms);
789 let Some(first) = batch.first().and_then(|id| kernel.jobs.get(id)) else {
790 return;
791 };
792 let provider_id = kernel
793 .caps
794 .get(&first.cap)
795 .map(|record| record.provider)
796 .unwrap_or(ProviderId(u64::MAX));
797 let lanes: BTreeSet<u64> = batch
798 .iter()
799 .filter_map(|id| kernel.jobs.get(id).map(|job| job.lane.0))
800 .collect();
801 kernel.events.push(Event::BatchDispatched {
802 provider: provider_id,
803 jobs: batch.len(),
804 lanes,
805 });
806 let Some(mut provider) = kernel.providers.remove(&provider_id) else {
809 for job_id in batch {
810 kernel.fail_job(job_id, "rpc/provider");
811 }
812 return;
813 };
814 let mut results: Vec<(u64, Result<Value>, LaneId, PromiseId)> = Vec::new();
815 for job_id in &batch {
816 let Some(job) = kernel.jobs.get(job_id).cloned() else {
817 continue;
818 };
819 if job.state == JobState::Done {
820 continue;
821 }
822 let mut args = Vec::with_capacity(job.call.args.len());
825 let mut failure = None;
826 for arg in &job.call.args {
827 match arg {
828 Arg::Promise(id) => match kernel.promises.get(id) {
829 Some(record) if record.state.is_settled() => match record.value() {
830 Ok(value) => args.push(Arg::Value(value)),
831 Err(error) => {
832 failure = Some(error);
833 break;
834 }
835 },
836 Some(_) => {
837 failure = Some(Error::UnresolvablePromise(id.0));
838 break;
839 }
840 None => {
841 failure = Some(Error::UnknownPromise(id.0));
842 break;
843 }
844 },
845 other => args.push(other.clone()),
846 }
847 }
848 let outcome = match failure {
849 Some(error) => Err(error),
850 None => {
851 let call = Call {
852 args,
853 ..job.call.clone()
854 };
855 let object = kernel
856 .caps
857 .get(&job.cap)
858 .map(|record| record.object)
859 .unwrap_or(0);
860 provider.invoke(object, &call).map(Response::into_value)
861 }
862 };
863 match &outcome {
865 Ok(value) => {
866 if let Some(record) = kernel.promises.get_mut(&job.promise) {
867 let _ = record.resolve(value.clone());
868 }
869 kernel.events.push(Event::PromiseResolved(job.promise));
870 }
871 Err(error) => {
872 if let Some(record) = kernel.promises.get_mut(&job.promise) {
873 let _ = record.reject(error.clone());
874 }
875 kernel.events.push(Event::PromiseRejected {
876 promise: job.promise,
877 code: error.code().to_string(),
878 });
879 }
880 }
881 results.push((*job_id, outcome, job.lane, job.promise));
882 }
883 kernel.providers.insert(provider_id, provider);
884 for (job_id, outcome, lane, _promise) in results {
885 if let Some(job) = kernel.jobs.get_mut(&job_id) {
886 job.state = JobState::Done;
887 }
888 if let Some(lane_record) = kernel.lanes.get_mut(&lane) {
889 lane_record.complete();
890 }
891 kernel
892 .events
893 .push(Event::JobCompleted { job: job_id, lane });
894 if outcome.is_err() {
895 }
898 }
899 }
900}
901
902impl Kernel {
903 fn next_batch(&mut self) -> Result<Vec<u64>> {
906 let Some(head) = self.queue.front().copied() else {
907 return Ok(Vec::new());
908 };
909 let Some(head_job) = self.jobs.get(&head) else {
910 self.queue.pop_front();
911 return Ok(Vec::new());
912 };
913 let provider = self
914 .caps
915 .get(&head_job.cap)
916 .map(|record| record.provider)
917 .ok_or(Error::InvalidArgument("job capability disappeared"))?;
918 let mut candidates: Vec<u64> = self
919 .queue
920 .iter()
921 .copied()
922 .filter(|id| {
923 self.jobs
924 .get(id)
925 .and_then(|job| self.caps.get(&job.cap))
926 .map(|record| record.provider == provider)
927 .unwrap_or(false)
928 })
929 .collect();
930 let mut ordered: Vec<u64> = Vec::new();
932 let mut pending = candidates.clone();
933 let mut progress = true;
934 while progress && !pending.is_empty() {
935 progress = false;
936 let mut index = 0;
937 while index < pending.len() {
938 let id = pending[index];
939 let job = self.jobs.get(&id).cloned();
940 let ready = match &job {
941 Some(job) => job.deps.iter().all(|dep| {
942 match self.promises.get(dep) {
944 Some(record) if record.state.is_settled() => true,
945 _ => ordered
946 .iter()
947 .any(|other| self.jobs.get(other).map(|j| j.promise) == Some(*dep)),
948 }
949 }),
950 None => true,
951 };
952 if ready {
953 ordered.push(id);
954 pending.remove(index);
955 progress = true;
956 } else {
957 index += 1;
958 }
959 }
960 }
961 if !pending.is_empty() {
962 return Err(Error::PipelinedCycle);
963 }
964 candidates.clear();
965 self.queue.retain(|id| !ordered.contains(id));
966 Ok(ordered)
967 }
968
969 fn fail_job(&mut self, job_id: u64, code: &str) {
970 if let Some(job) = self.jobs.get_mut(&job_id) {
971 job.state = JobState::Done;
972 let promise = job.promise;
973 let lane = job.lane;
974 if let Some(record) = self.promises.get_mut(&promise) {
975 let _ = record.reject(Error::Provider {
976 code: code.to_string(),
977 });
978 }
979 if let Some(lane_record) = self.lanes.get_mut(&lane) {
980 lane_record.complete();
981 }
982 self.events.push(Event::PromiseRejected {
983 promise,
984 code: code.to_string(),
985 });
986 self.events.push(Event::JobCompleted { job: job_id, lane });
987 }
988 }
989}
990
991thread_local! {
992 static NEXT_AGENT: RefCell<u64> = const { RefCell::new(0) };
993}
994
995fn pad128(id: CapId) -> [u8; 16] {
996 id.0
997}
998
999#[derive(Clone)]
1001pub struct PromiseHandle {
1002 agent: Agent,
1003 id: PromiseId,
1004}
1005
1006impl PromiseHandle {
1007 pub fn id(&self) -> PromiseId {
1009 self.id
1010 }
1011
1012 pub fn agent(&self) -> &Agent {
1014 &self.agent
1015 }
1016
1017 pub fn value(&self) -> Result<Value> {
1019 self.agent.await_promise(self)
1020 }
1021
1022 pub fn peek(&self) -> Result<Value> {
1024 self.agent
1025 .cell
1026 .borrow()
1027 .promises
1028 .get(&self.id)
1029 .ok_or(Error::UnknownPromise(self.id.0))?
1030 .value()
1031 }
1032
1033 pub fn is_settled(&self) -> bool {
1035 self.agent
1036 .cell
1037 .borrow()
1038 .promises
1039 .get(&self.id)
1040 .map(|record| record.state.is_settled())
1041 .unwrap_or(false)
1042 }
1043}
1044
1045impl std::fmt::Debug for PromiseHandle {
1046 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1047 f.debug_struct("PromiseHandle")
1048 .field("id", &self.id)
1049 .field("settled", &self.is_settled())
1050 .finish()
1051 }
1052}
1053
1054pub fn tool_policy_for(methods: &[&str]) -> ToolPolicy {
1056 ToolPolicy::allow(methods)
1057}
1058
1059pub fn promise_state(agent: &Agent, id: PromiseId) -> Option<PromiseState> {
1061 agent
1062 .cell
1063 .borrow()
1064 .promises
1065 .get(&id)
1066 .map(|record| record.state.clone())
1067}