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 const MAX_LANES: usize = 4_096;
38
39pub const MAX_CHANNELS: usize = 4_096;
41
42pub const MAX_PROMISES: usize = 100_000;
49
50pub const MAX_SETTLED_PROMISES: usize = 1_024;
57
58pub const MAX_SETTLED_BYTES: usize = 64 << 20;
64
65pub const MAX_EVENTS: usize = 16_384;
71
72pub trait Provider {
74 fn name(&self) -> &'static str;
76 fn methods(&self) -> Vec<String>;
78 fn has_method(&self, method: &str) -> bool {
80 self.methods().iter().any(|name| name == method)
81 }
82 fn mutating(&self, method: &str) -> bool;
84 fn invoke(&mut self, object: u64, call: &Call) -> Result<Response>;
86 fn on_drop(&mut self, _object: u64, _cap: CapId) {}
88
89 fn take_drop_notifications(&mut self) -> Vec<(u64, CapId)> {
94 Vec::new()
95 }
96}
97
98#[derive(Debug, Clone, PartialEq)]
100pub enum Event {
101 CapMinted {
103 cap: CapId,
105 provider: ProviderId,
107 },
108 CapRetained(CapId),
110 CapReleased(CapId),
112 CapDropped(CapId),
114 CapRevoked(CapId),
116 LaneCreated(LaneId),
118 LaneDestroyed(LaneId),
120 CallQueued {
122 job: u64,
124 lane: LaneId,
126 cap: CapId,
128 },
129 BatchDispatched {
131 provider: ProviderId,
133 jobs: usize,
135 lanes: BTreeSet<u64>,
137 },
138 JobCompleted {
140 job: u64,
142 lane: LaneId,
144 },
145 PromiseResolved(PromiseId),
147 PromiseRejected {
149 promise: PromiseId,
151 code: String,
153 },
154 ChannelSend {
156 channel: ChannelId,
158 sequence: u64,
160 },
161 ChannelRecv {
163 channel: ChannelId,
165 sequence: u64,
167 },
168 CapTransferred {
170 cap: CapId,
172 channel: ChannelId,
174 },
175 CallRefused {
177 lane: LaneId,
179 cap: CapId,
181 code: String,
183 },
184 BudgetExhausted {
186 cap: CapId,
188 dimension: String,
190 },
191 ToolRefused {
193 cap: CapId,
195 reason: String,
197 },
198}
199
200#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
205pub struct Metrics {
206 pub calls_queued: u64,
208 pub calls_refused: u64,
210 pub budget_exhaustions: u64,
212 pub tool_refusals: u64,
214 pub revocations: u64,
216 pub promises_resolved: u64,
218 pub promises_rejected: u64,
220 pub round_trips: u64,
222 pub transfers: u64,
224 pub promises_double_settled: u64,
226}
227
228#[derive(Debug, Clone, Copy, PartialEq, Eq)]
229enum JobState {
230 Queued,
231 Done,
232}
233
234#[derive(Debug, Clone)]
235struct Job {
236 #[allow(dead_code)]
237 id: u64,
238 lane: LaneId,
239 cap: CapId,
240 call: Call,
241 deps: Vec<PromiseId>,
242 promise: PromiseId,
243 state: JobState,
244}
245
246pub struct Kernel {
251 secret: [u8; 32],
252 providers: BTreeMap<ProviderId, Box<dyn Provider>>,
253 caps: BTreeMap<CapId, CapRecord>,
254 meters: BTreeMap<CapId, BudgetMeter>,
255 promises: BTreeMap<PromiseId, PromiseRecord>,
256 lanes: BTreeMap<LaneId, Lane>,
257 channels: BTreeMap<ChannelId, Channel>,
258 jobs: BTreeMap<u64, Job>,
259 queue: VecDeque<u64>,
260 events: VecDeque<Event>,
261 settled: VecDeque<(PromiseId, usize)>,
263 settled_bytes: usize,
264 metrics: Metrics,
265 round_trips: u64,
266 next_promise: u64,
267 next_job: u64,
268 next_lane: u64,
269 next_channel: u64,
270 next_serial: u64,
271 next_provider: u64,
272 now_ms: u64,
273 latency_ms: u64,
274 transfers: u64,
275}
276
277pub(crate) struct HandleControl {
281 cell: KernelCell,
282}
283
284impl HandleControl {
285 fn new(cell: KernelCell) -> Self {
286 Self { cell }
287 }
288}
289
290impl CapControl for HandleControl {
291 fn retain(&self, id: CapId) {
292 if let Ok(mut kernel) = self.cell.try_borrow_mut() {
293 if let Some(record) = kernel.caps.get_mut(&id) {
294 record.refs = record.refs.saturating_add(1);
295 kernel.push_event(Event::CapRetained(id));
296 }
297 }
298 }
299
300 fn release(&self, id: CapId) {
301 let dropped = {
302 let Ok(mut kernel) = self.cell.try_borrow_mut() else {
303 return;
304 };
305 let Some(record) = kernel.caps.get_mut(&id) else {
306 return;
307 };
308 record.refs = record.refs.saturating_sub(1);
309 let last = record.refs == 0;
310 kernel.push_event(Event::CapReleased(id));
311 last
312 };
313 if !dropped {
314 return;
315 }
316 let mut kernel = self.cell.borrow_mut();
317 let Some(record) = kernel.caps.remove(&id) else {
318 return;
319 };
320 kernel.meters.remove(&id);
321 kernel.push_event(Event::CapDropped(id));
322 if let Some(provider) = kernel.providers.get_mut(&record.provider) {
323 provider.on_drop(record.object, id);
324 }
325 }
326}
327
328pub type KernelCell = Rc<RefCell<Kernel>>;
330
331#[derive(Clone)]
333pub struct Agent {
334 cell: KernelCell,
335 control: Rc<dyn CapControl>,
336}
337
338impl Default for Agent {
339 fn default() -> Self {
340 Self::new()
341 }
342}
343
344impl Agent {
345 pub fn new() -> Self {
351 let mut seed = [0u8; 32];
352 getrandom::fill(&mut seed).expect("the operating system CSPRNG must be available");
353 Self::with_secret(seed)
354 }
355
356 pub fn with_secret(secret: [u8; 32]) -> Self {
358 let kernel = Kernel {
359 secret,
360 providers: BTreeMap::new(),
361 caps: BTreeMap::new(),
362 meters: BTreeMap::new(),
363 promises: BTreeMap::new(),
364 lanes: BTreeMap::new(),
365 channels: BTreeMap::new(),
366 jobs: BTreeMap::new(),
367 queue: VecDeque::new(),
368 events: VecDeque::new(),
369 settled: VecDeque::new(),
370 settled_bytes: 0,
371 metrics: Metrics::default(),
372 round_trips: 0,
373 next_promise: 0,
374 next_job: 0,
375 next_lane: 0,
376 next_channel: 0,
377 next_serial: 0,
378 next_provider: 0,
379 now_ms: 0,
380 latency_ms: 1,
381 transfers: 0,
382 };
383 let cell: KernelCell = Rc::new(RefCell::new(kernel));
384 let control: Rc<dyn CapControl> = Rc::new(HandleControl::new(Rc::clone(&cell)));
385 Agent { cell, control }
386 }
387
388 pub fn cell(&self) -> &KernelCell {
390 &self.cell
391 }
392
393 pub fn register(&self, provider: Box<dyn Provider>) -> ProviderId {
395 let mut kernel = self.cell.borrow_mut();
396 let id = ProviderId(kernel.next_provider);
397 kernel.next_provider += 1;
398 kernel.providers.insert(id, provider);
399 id
400 }
401
402 pub fn set_latency(&self, latency_ms: u64) {
404 self.cell.borrow_mut().latency_ms = latency_ms;
405 }
406
407 pub fn mint(&self, provider: ProviderId, object: u64, attrs: CapAttrs) -> Result<CapHandle> {
409 attrs.budget.check()?;
410 if attrs.methods.is_empty() {
411 return Err(Error::InvalidArgument("capability grants no methods"));
412 }
413 let mut kernel = self.cell.borrow_mut();
414 if !kernel.providers.contains_key(&provider) {
415 return Err(Error::InvalidArgument("unknown provider"));
416 }
417 let serial = kernel.next_serial;
418 kernel.next_serial += 1;
419 let id = CapId::derive(&kernel.secret, serial, None);
420 let record = CapRecord::new(id, provider, object, attrs.clone());
421 kernel.meters.insert(id, BudgetMeter::new(attrs.budget));
422 kernel.caps.insert(id, record);
423 kernel.push_event(Event::CapMinted { cap: id, provider });
424 Ok(CapHandle::new(Rc::clone(&self.control), id))
425 }
426
427 pub fn attenuate(&self, parent: &CapHandle, attrs: CapAttrs) -> Result<CapHandle> {
429 let parent_id = parent.id();
430 let mut kernel = self.cell.borrow_mut();
431 let record = kernel
432 .caps
433 .get(&parent_id)
434 .ok_or(Error::UnknownCapability(cap_token(parent_id)))?
435 .clone();
436 if record.revoked {
437 return Err(Error::Revoked(cap_token(parent_id)));
438 }
439 attrs.budget.check()?;
440 let attrs = record.attrs.attenuate(attrs)?;
441 let serial = kernel.next_serial;
442 kernel.next_serial += 1;
443 let id = CapId::derive(&kernel.secret, serial, Some(&parent_id));
444 let mut child = CapRecord::new(id, record.provider, record.object, attrs.clone());
445 child.parent = Some(parent_id);
446 kernel.meters.insert(id, BudgetMeter::new(attrs.budget));
447 kernel.caps.insert(id, child);
448 kernel.push_event(Event::CapMinted {
449 cap: id,
450 provider: record.provider,
451 });
452 Ok(CapHandle::new(Rc::clone(&self.control), id))
453 }
454
455 pub fn import(&self, id: CapId) -> CapHandle {
462 CapHandle::borrowed(Rc::clone(&self.control), id)
463 }
464
465 pub fn revoke(&self, cap: &CapHandle) {
467 let mut kernel = self.cell.borrow_mut();
468 let mut doomed = BTreeSet::new();
469 let mut stack = vec![cap.id()];
470 while let Some(id) = stack.pop() {
471 if !doomed.insert(id) {
472 continue;
473 }
474 for (child, record) in &kernel.caps {
475 if record.parent == Some(id) {
476 stack.push(*child);
477 }
478 }
479 }
480 for id in doomed {
481 if let Some(record) = kernel.caps.get_mut(&id) {
482 record.revoked = true;
483 }
484 kernel.push_event(Event::CapRevoked(id));
485 kernel.metrics.revocations = kernel.metrics.revocations.saturating_add(1);
486 }
487 }
488
489 pub fn create_lane(&self, name: impl Into<String>, budget: Budget) -> Result<LaneId> {
491 budget.check()?;
492 let mut kernel = self.cell.borrow_mut();
493 let open = kernel.lanes.values().filter(|lane| !lane.closed).count();
494 if open >= MAX_LANES {
495 return Err(Error::BudgetExceeded("lanes"));
496 }
497 let id = LaneId(kernel.next_lane);
498 kernel.next_lane += 1;
499 kernel.lanes.insert(id, Lane::new(id, name, budget));
500 kernel.push_event(Event::LaneCreated(id));
501 Ok(id)
502 }
503
504 pub fn attenuate_lane(&self, lane: LaneId, budget: Budget) -> Result<()> {
506 budget.check()?;
507 let mut kernel = self.cell.borrow_mut();
508 let record = kernel
509 .lanes
510 .get_mut(&lane)
511 .ok_or(Error::UnknownLane(lane.0))?;
512 record.attenuate(budget)
513 }
514
515 pub fn destroy_lane(&self, lane: LaneId) -> Result<()> {
521 let mut kernel = self.cell.borrow_mut();
522 {
523 let record = kernel
524 .lanes
525 .get_mut(&lane)
526 .ok_or(Error::UnknownLane(lane.0))?;
527 record.destroy();
528 }
529 let doomed: Vec<u64> = kernel
530 .jobs
531 .iter()
532 .filter(|(_, job)| job.lane == lane && job.state == JobState::Queued)
533 .map(|(id, _)| *id)
534 .collect();
535 kernel.queue.retain(|id| !doomed.contains(id));
536 for job_id in doomed {
537 kernel.fail_job(job_id, Error::UnknownLane(lane.0));
538 }
539 kernel.jobs.retain(|_, job| job.lane != lane);
544 for channel in kernel.channels.values_mut() {
545 channel.subscribers.remove(&lane.0);
546 }
547 kernel.lanes.remove(&lane);
548 kernel.push_event(Event::LaneDestroyed(lane));
549 Ok(())
550 }
551
552 pub fn destroy_channel(&self, channel: ChannelId) -> Result<()> {
554 let mut kernel = self.cell.borrow_mut();
555 kernel
556 .channels
557 .remove(&channel)
558 .ok_or(Error::UnknownChannel(channel.0))?;
559 for lane in kernel.lanes.values_mut() {
560 lane.channels.remove(&channel.0);
561 }
562 Ok(())
563 }
564
565 pub fn create_channel(
567 &self,
568 name: impl Into<String>,
569 direction: Direction,
570 ) -> Result<ChannelId> {
571 let mut kernel = self.cell.borrow_mut();
572 if kernel.channels.len() >= MAX_CHANNELS {
573 return Err(Error::BudgetExceeded("channels"));
574 }
575 let id = ChannelId(kernel.next_channel);
576 kernel.next_channel += 1;
577 kernel
578 .channels
579 .insert(id, Channel::new(id, name, direction));
580 Ok(id)
581 }
582
583 pub fn subscribe(&self, lane: LaneId, channel: ChannelId) -> Result<()> {
585 let mut kernel = self.cell.borrow_mut();
586 let lane_record = kernel.lanes.get(&lane).ok_or(Error::UnknownLane(lane.0))?;
587 if lane_record.closed {
588 return Err(Error::UnknownLane(lane.0));
589 }
590 let record = kernel
591 .channels
592 .get_mut(&channel)
593 .ok_or(Error::UnknownChannel(channel.0))?;
594 record.subscribers.insert(lane.0);
595 if let Some(lane) = kernel.lanes.get_mut(&lane) {
596 lane.channels.insert(channel.0);
597 }
598 Ok(())
599 }
600
601 pub fn send(
603 &self,
604 lane: LaneId,
605 channel: ChannelId,
606 payload: Value,
607 caps: &[CapHandle],
608 ) -> Result<u64> {
609 let mut kernel = self.cell.borrow_mut();
610 let lane_record = kernel.lanes.get(&lane).ok_or(Error::UnknownLane(lane.0))?;
611 if lane_record.closed {
612 return Err(Error::UnknownLane(lane.0));
613 }
614 let mut cap_ids = Vec::with_capacity(caps.len());
615 for cap in caps {
616 let record = kernel
617 .caps
618 .get(&cap.id())
619 .ok_or(Error::InvalidArgument("unknown capability"))?;
620 if record.revoked {
621 return Err(Error::Revoked(cap_token(cap.id())));
622 }
623 cap_ids.push(cap.id());
628 }
629 let record = kernel
630 .channels
631 .get_mut(&channel)
632 .ok_or(Error::UnknownChannel(channel.0))?;
633 let message = record.send(lane, payload, cap_ids.clone())?;
634 kernel.push_event(Event::ChannelSend {
635 channel,
636 sequence: message.sequence,
637 });
638 for id in cap_ids {
639 kernel.transfers += 1;
640 kernel.push_event(Event::CapTransferred { cap: id, channel });
641 }
642 Ok(message.sequence)
643 }
644
645 pub fn recv(&self, channel: ChannelId) -> Result<Option<Message>> {
647 let mut kernel = self.cell.borrow_mut();
648 let record = kernel
649 .channels
650 .get_mut(&channel)
651 .ok_or(Error::UnknownChannel(channel.0))?;
652 let message = record.recv()?;
653 if let Some(message) = &message {
654 kernel.push_event(Event::ChannelRecv {
655 channel,
656 sequence: message.sequence,
657 });
658 }
659 Ok(message)
660 }
661
662 pub fn call(
668 &self,
669 lane: LaneId,
670 cap: &CapHandle,
671 method: &str,
672 args: Vec<Arg>,
673 ) -> Result<PromiseHandle> {
674 let cap_id = cap.id();
675 let result = self.call_inner(lane, cap, method, args);
676 if let Err(error) = &result {
677 let mut kernel = self.cell.borrow_mut();
678 kernel.metrics.calls_refused = kernel.metrics.calls_refused.saturating_add(1);
679 kernel.push_event(Event::CallRefused {
680 lane,
681 cap: cap_id,
682 code: error.code().to_string(),
683 });
684 match error {
685 Error::BudgetExceeded(dimension) => {
686 kernel.metrics.budget_exhaustions =
687 kernel.metrics.budget_exhaustions.saturating_add(1);
688 kernel.push_event(Event::BudgetExhausted {
689 cap: cap_id,
690 dimension: (*dimension).to_string(),
691 });
692 }
693 Error::ToolPolicy(reason) => {
694 kernel.metrics.tool_refusals = kernel.metrics.tool_refusals.saturating_add(1);
695 kernel.push_event(Event::ToolRefused {
696 cap: cap_id,
697 reason: (*reason).to_string(),
698 });
699 }
700 _ => {}
701 }
702 }
703 result
704 }
705
706 fn call_inner(
707 &self,
708 lane: LaneId,
709 cap: &CapHandle,
710 method: &str,
711 args: Vec<Arg>,
712 ) -> Result<PromiseHandle> {
713 let mut kernel = self.cell.borrow_mut();
714 let cap_id = cap.id();
715 let record = kernel
716 .caps
717 .get(&cap_id)
718 .ok_or(Error::UnknownCapability(cap_token(cap_id)))?
719 .clone();
720 if record.revoked {
721 return Err(Error::Revoked(cap_token(cap_id)));
722 }
723 let (lane_closed, lane_capacity, lane_budget) = {
724 let lane_record = kernel.lanes.get(&lane).ok_or(Error::UnknownLane(lane.0))?;
725 (
726 lane_record.closed,
727 lane_record.has_capacity(),
728 lane_record.budget,
729 )
730 };
731 if lane_closed {
732 return Err(Error::UnknownLane(lane.0));
733 }
734 if !lane_capacity {
735 return Err(Error::BudgetExceeded("lane call"));
736 }
737 if !record.attrs.grants(method) {
738 return Err(Error::MethodNotGranted {
739 method: method.to_string(),
740 });
741 }
742 let provider = kernel
743 .providers
744 .get(&record.provider)
745 .ok_or(Error::InvalidArgument("provider disappeared"))?;
746 if !provider.has_method(method) {
747 return Err(Error::MethodNotGranted {
748 method: method.to_string(),
749 });
750 }
751 if record.attrs.read_only && provider.mutating(method) {
752 return Err(Error::ReadOnly);
753 }
754 if let Some(scope) = &record.attrs.path_scope {
756 for arg in &args {
757 if let Arg::Value(Value::Path(path)) = arg {
758 if !crate::cap::is_path_prefix(scope, path) {
759 return Err(Error::PathNotGranted(path.clone()));
760 }
761 }
762 }
763 }
764 if let Some(policy) = &record.attrs.tool_policy {
766 if !policy.allowed.contains(method) {
767 return Err(Error::ToolPolicy("tool not allowed"));
768 }
769 let bytes: u64 = args.iter().map(Arg::wire_size).sum();
772 if bytes > policy.max_arg_bytes {
773 return Err(Error::ToolPolicy("argument too large"));
774 }
775 }
776 let call_bytes: u64 = args.iter().map(|arg| arg.wire_size()).sum();
777 let effective = record.attrs.budget.intersect(&lane_budget);
778 if call_bytes > effective.max_bytes {
779 return Err(Error::BudgetExceeded("byte"));
780 }
781 if kernel.promises.len() >= MAX_PROMISES {
785 return Err(Error::BudgetExceeded("promises"));
786 }
787 if kernel.jobs.len() >= MAX_PROMISES {
788 return Err(Error::BudgetExceeded("jobs"));
789 }
790 let meter = kernel
791 .meters
792 .get_mut(&cap_id)
793 .ok_or(Error::InvalidArgument("capability has no meter"))?;
794 meter.charge(call_bytes)?;
795
796 let promise_id = PromiseId(kernel.next_promise);
797 kernel.next_promise += 1;
798 kernel
799 .promises
800 .insert(promise_id, PromiseRecord::new(promise_id, lane.0));
801
802 let job_id = kernel.next_job;
803 kernel.next_job += 1;
804 let deps: Vec<PromiseId> = args.iter().filter_map(|arg| arg.promise()).collect();
805 for dep in &deps {
806 if !kernel.promises.contains_key(dep) {
807 return Err(Error::UnknownPromise(dep.0));
808 }
809 if let Some(record) = kernel.promises.get_mut(dep) {
810 record.waiters += 1;
811 }
812 }
813 let call = Call {
814 method: method.to_string(),
815 args,
816 path_scope: record.attrs.path_scope.clone(),
817 redact: record.attrs.redact,
818 read_only: record.attrs.read_only,
819 tool_allows_process: record
820 .attrs
821 .tool_policy
822 .as_ref()
823 .map(|policy| policy.allow_process)
824 .unwrap_or(false),
825 budget: effective,
826 };
827 let job = Job {
828 id: job_id,
829 lane,
830 cap: cap_id,
831 call,
832 deps,
833 promise: promise_id,
834 state: JobState::Queued,
835 };
836 kernel.jobs.insert(job_id, job);
837 kernel.queue.push_back(job_id);
838 if let Some(lane_record) = kernel.lanes.get_mut(&lane) {
839 lane_record.pending += 1;
840 }
841 kernel.push_event(Event::CallQueued {
842 job: job_id,
843 lane,
844 cap: cap_id,
845 });
846 kernel.metrics.calls_queued = kernel.metrics.calls_queued.saturating_add(1);
847 if let Some(record) = kernel.promises.get_mut(&promise_id) {
855 record.handles = 1;
856 }
857 Ok(PromiseHandle {
858 agent: self.clone(),
859 id: promise_id,
860 })
861 }
862
863 pub fn run(&self) -> u64 {
865 loop {
866 let batch = {
867 let mut kernel = self.cell.borrow_mut();
868 if kernel.queue.is_empty() {
869 kernel.trim_settled();
870 return kernel.round_trips;
871 }
872 match kernel.next_batch() {
873 Ok(batch) => batch,
874 Err(stuck) => {
875 for job_id in stuck {
878 let error = kernel
879 .jobs
880 .get(&job_id)
881 .map(|job| Error::UnknownCapability(cap_token(job.cap)))
882 .unwrap_or(Error::PipelinedCycle);
883 kernel.fail_job(job_id, error);
884 }
885 continue;
886 }
887 }
888 };
889 self.dispatch(batch);
890 }
891 }
892
893 pub fn round_trips(&self) -> u64 {
895 self.cell.borrow().round_trips
896 }
897
898 pub fn await_promise(&self, promise: &PromiseHandle) -> Result<Value> {
900 loop {
901 {
902 let kernel = self.cell.borrow();
903 let record = kernel
904 .promises
905 .get(&promise.id)
906 .ok_or(Error::UnknownPromise(promise.id.0))?;
907 if record.state.is_settled() {
908 return record.value();
909 }
910 }
911 if self.cell.borrow().queue.is_empty() {
912 return Err(Error::UnresolvablePromise(promise.id.0));
913 }
914 self.run();
915 }
916 }
917
918 pub fn resolve(&self, promise: &PromiseHandle, value: Value) -> Result<()> {
920 let mut kernel = self.cell.borrow_mut();
921 let record = kernel
922 .promises
923 .get_mut(&promise.id)
924 .ok_or(Error::UnknownPromise(promise.id.0))?;
925 let settled = record.resolve(value);
926 if settled.is_err() {
927 kernel.metrics.promises_double_settled =
928 kernel.metrics.promises_double_settled.saturating_add(1);
929 }
930 settled?;
931 kernel.push_event(Event::PromiseResolved(promise.id));
932 kernel.metrics.promises_resolved = kernel.metrics.promises_resolved.saturating_add(1);
933 kernel.record_settled(promise.id);
934 Ok(())
935 }
936
937 pub fn cancel(&self, promise: &PromiseHandle) -> Result<()> {
943 let mut kernel = self.cell.borrow_mut();
944 {
945 let record = kernel
946 .promises
947 .get_mut(&promise.id)
948 .ok_or(Error::UnknownPromise(promise.id.0))?;
949 record.cancel()?;
950 }
951 let queued: Option<u64> = kernel
952 .jobs
953 .iter()
954 .find(|(_, job)| job.promise == promise.id && job.state == JobState::Queued)
955 .map(|(id, _)| *id);
956 if let Some(job_id) = queued {
957 kernel.queue.retain(|id| *id != job_id);
958 let lane = kernel.jobs.get(&job_id).map(|job| job.lane);
959 kernel.jobs.remove(&job_id);
960 kernel.record_settled(promise.id);
961 if let Some(lane) = lane {
962 if let Some(lane_record) = kernel.lanes.get_mut(&lane) {
963 lane_record.complete();
964 }
965 }
966 }
967 Ok(())
968 }
969
970 fn retain_promise(&self, id: PromiseId) {
972 if let Ok(mut kernel) = self.cell.try_borrow_mut() {
973 if let Some(record) = kernel.promises.get_mut(&id) {
974 record.handles = record.handles.saturating_add(1);
975 }
976 }
977 }
978
979 fn release_promise(&self, id: PromiseId) {
981 if let Ok(mut kernel) = self.cell.try_borrow_mut() {
982 if let Some(record) = kernel.promises.get_mut(&id) {
983 record.handles = record.handles.saturating_sub(1);
984 }
985 }
986 }
987
988 pub fn take_drops(&self, provider: ProviderId) -> Vec<(u64, CapId)> {
990 self.cell
991 .borrow_mut()
992 .providers
993 .get_mut(&provider)
994 .map(|provider| provider.take_drop_notifications())
995 .unwrap_or_default()
996 }
997
998 pub fn events(&self) -> Vec<Event> {
1000 self.cell.borrow().events.iter().cloned().collect()
1001 }
1002
1003 pub fn metrics(&self) -> Metrics {
1005 let kernel = self.cell.borrow();
1006 Metrics {
1007 round_trips: kernel.round_trips,
1008 transfers: kernel.transfers,
1009 ..kernel.metrics
1010 }
1011 }
1012
1013 pub fn promise_count(&self) -> usize {
1015 self.cell.borrow().promises.len()
1016 }
1017
1018 pub fn job_count(&self) -> usize {
1020 self.cell.borrow().jobs.len()
1021 }
1022
1023 pub fn lane(&self, lane: LaneId) -> Result<Lane> {
1025 self.cell
1026 .borrow()
1027 .lanes
1028 .get(&lane)
1029 .cloned()
1030 .ok_or(Error::UnknownLane(lane.0))
1031 }
1032
1033 pub fn channel(&self, channel: ChannelId) -> Result<Channel> {
1035 self.cell
1036 .borrow()
1037 .channels
1038 .get(&channel)
1039 .cloned()
1040 .ok_or(Error::UnknownChannel(channel.0))
1041 }
1042
1043 pub fn cap_attrs(&self, cap: &CapHandle) -> Result<CapAttrs> {
1045 self.cell
1046 .borrow()
1047 .caps
1048 .get(&cap.id())
1049 .map(|record| record.attrs.clone())
1050 .ok_or(Error::UnknownCapability(cap_token(cap.id())))
1051 }
1052
1053 fn dispatch(&self, batch: Vec<u64>) {
1054 let (provider_id, provider) = {
1059 let mut kernel = self.cell.borrow_mut();
1060 kernel.round_trips += 1;
1061 kernel.now_ms = kernel.now_ms.saturating_add(kernel.latency_ms);
1062 let Some(first) = batch.first().and_then(|id| kernel.jobs.get(id)) else {
1063 return;
1064 };
1065 let provider_id = kernel
1066 .caps
1067 .get(&first.cap)
1068 .map(|record| record.provider)
1069 .unwrap_or(ProviderId(u64::MAX));
1070 let lanes: BTreeSet<u64> = batch
1071 .iter()
1072 .filter_map(|id| kernel.jobs.get(id).map(|job| job.lane.0))
1073 .collect();
1074 kernel.push_event(Event::BatchDispatched {
1075 provider: provider_id,
1076 jobs: batch.len(),
1077 lanes,
1078 });
1079 let provider = kernel.providers.remove(&provider_id);
1080 (provider_id, provider)
1081 };
1082 let Some(mut provider) = provider else {
1083 let mut kernel = self.cell.borrow_mut();
1084 for job_id in batch {
1085 kernel.fail_job(
1086 job_id,
1087 Error::Provider {
1088 code: "rpc/provider".to_string(),
1089 },
1090 );
1091 }
1092 return;
1093 };
1094
1095 for job_id in &batch {
1096 let prepared = {
1098 let kernel = self.cell.borrow();
1099 let Some(job) = kernel.jobs.get(job_id).cloned() else {
1100 continue;
1101 };
1102 if job.state == JobState::Done {
1103 continue;
1104 }
1105 let mut args = Vec::with_capacity(job.call.args.len());
1106 let mut failure = None;
1107 for arg in &job.call.args {
1108 match arg {
1109 Arg::Promise(id) => match kernel.promises.get(id) {
1110 Some(record) if record.state.is_settled() => match record.value() {
1111 Ok(value) => args.push(Arg::Value(value)),
1112 Err(error) => {
1113 failure = Some(error);
1114 break;
1115 }
1116 },
1117 Some(_) => {
1118 failure = Some(Error::UnresolvablePromise(id.0));
1119 break;
1120 }
1121 None => {
1122 failure = Some(Error::UnknownPromise(id.0));
1123 break;
1124 }
1125 },
1126 other => args.push(other.clone()),
1127 }
1128 }
1129 let record = kernel.caps.get(&job.cap).cloned();
1132 let failure = match &record {
1133 None => Some(Error::UnknownCapability(cap_token(job.cap))),
1134 Some(record) if record.revoked => Some(Error::Revoked(cap_token(record.id))),
1135 Some(_) => failure,
1136 };
1137 Some((
1138 job,
1139 args,
1140 failure,
1141 record.map(|record| record.object).unwrap_or(0),
1142 ))
1143 };
1144 let Some((job, args, failure, object)) = prepared else {
1145 continue;
1146 };
1147
1148 let outcome = match failure {
1150 Some(error) => Err(error),
1151 None => {
1152 let call = Call {
1153 args,
1154 ..job.call.clone()
1155 };
1156 provider.invoke(object, &call).map(Response::into_value)
1157 }
1158 };
1159
1160 let mut kernel = self.cell.borrow_mut();
1162 let mut settled_now = false;
1163 match &outcome {
1164 Ok(value) => {
1165 if let Some(record) = kernel.promises.get_mut(&job.promise) {
1166 if record.resolve(value.clone()).is_ok() {
1167 settled_now = true;
1168 } else {
1169 kernel.metrics.promises_double_settled =
1170 kernel.metrics.promises_double_settled.saturating_add(1);
1171 }
1172 }
1173 kernel.push_event(Event::PromiseResolved(job.promise));
1174 kernel.metrics.promises_resolved =
1175 kernel.metrics.promises_resolved.saturating_add(1);
1176 }
1177 Err(error) => {
1178 if let Some(record) = kernel.promises.get_mut(&job.promise) {
1179 if record.reject(error.clone()).is_ok() {
1180 settled_now = true;
1181 } else {
1182 kernel.metrics.promises_double_settled =
1183 kernel.metrics.promises_double_settled.saturating_add(1);
1184 }
1185 }
1186 kernel.push_event(Event::PromiseRejected {
1187 promise: job.promise,
1188 code: error.code().to_string(),
1189 });
1190 kernel.metrics.promises_rejected =
1191 kernel.metrics.promises_rejected.saturating_add(1);
1192 }
1193 }
1194 if settled_now {
1195 kernel.record_settled(job.promise);
1196 }
1197 kernel.jobs.remove(job_id);
1201 if let Some(lane_record) = kernel.lanes.get_mut(&job.lane) {
1202 lane_record.complete();
1203 }
1204 kernel.push_event(Event::JobCompleted {
1205 job: *job_id,
1206 lane: job.lane,
1207 });
1208 }
1209
1210 self.cell
1211 .borrow_mut()
1212 .providers
1213 .insert(provider_id, provider);
1214 }
1215}
1216
1217impl Kernel {
1218 fn push_event(&mut self, event: Event) {
1220 if self.events.len() >= MAX_EVENTS {
1221 self.events.pop_front();
1222 }
1223 self.events.push_back(event);
1224 }
1225
1226 fn record_settled(&mut self, id: PromiseId) {
1228 let size = self
1229 .promises
1230 .get(&id)
1231 .and_then(|record| record.value().ok())
1232 .map(|value| value.wire_size() as usize)
1233 .unwrap_or(0);
1234 self.settled.push_back((id, size));
1235 self.settled_bytes = self.settled_bytes.saturating_add(size);
1236 }
1237
1238 fn trim_settled(&mut self) {
1245 while (self.settled.len() > MAX_SETTLED_PROMISES || self.settled_bytes > MAX_SETTLED_BYTES)
1246 && self.settled.len() > 1
1247 {
1248 let mut victim = None;
1249 for (index, (id, _)) in self.settled.iter().enumerate() {
1250 let pinned = self
1251 .promises
1252 .get(id)
1253 .map(|record| record.handles > 0)
1254 .unwrap_or(false);
1255 if !pinned {
1256 victim = Some(index);
1257 break;
1258 }
1259 }
1260 let Some(index) = victim else {
1261 break;
1262 };
1263 let Some((id, size)) = self.settled.remove(index) else {
1264 break;
1265 };
1266 self.settled_bytes = self.settled_bytes.saturating_sub(size);
1267 self.promises.remove(&id);
1268 }
1269 }
1270
1271 fn next_batch(&mut self) -> std::result::Result<Vec<u64>, Vec<u64>> {
1274 let Some(head) = self.queue.front().copied() else {
1275 return Ok(Vec::new());
1276 };
1277 let Some(head_job) = self.jobs.get(&head) else {
1278 self.queue.pop_front();
1279 return Ok(Vec::new());
1280 };
1281 let Some(provider) = self.caps.get(&head_job.cap).map(|record| record.provider) else {
1282 self.queue.pop_front();
1284 return Err(vec![head]);
1285 };
1286 let mut candidates: Vec<u64> = self
1287 .queue
1288 .iter()
1289 .copied()
1290 .filter(|id| {
1291 self.jobs
1292 .get(id)
1293 .and_then(|job| self.caps.get(&job.cap))
1294 .map(|record| record.provider == provider)
1295 .unwrap_or(false)
1296 })
1297 .collect();
1298 let mut ordered: Vec<u64> = Vec::new();
1300 let mut pending = candidates.clone();
1301 let mut progress = true;
1302 while progress && !pending.is_empty() {
1303 progress = false;
1304 let mut index = 0;
1305 while index < pending.len() {
1306 let id = pending[index];
1307 let job = self.jobs.get(&id).cloned();
1308 let ready = match &job {
1309 Some(job) => job.deps.iter().all(|dep| {
1310 match self.promises.get(dep) {
1312 Some(record) if record.state.is_settled() => true,
1313 _ => ordered
1314 .iter()
1315 .any(|other| self.jobs.get(other).map(|j| j.promise) == Some(*dep)),
1316 }
1317 }),
1318 None => true,
1319 };
1320 if ready {
1321 ordered.push(id);
1322 pending.remove(index);
1323 progress = true;
1324 } else {
1325 index += 1;
1326 }
1327 }
1328 }
1329 if !pending.is_empty() {
1330 for id in &pending {
1332 self.queue.retain(|queued| queued != id);
1333 }
1334 return Err(pending);
1335 }
1336 candidates.clear();
1337 self.queue.retain(|id| !ordered.contains(id));
1338 Ok(ordered)
1339 }
1340
1341 fn fail_job(&mut self, job_id: u64, error: Error) {
1342 if let Some(job) = self.jobs.get_mut(&job_id) {
1343 job.state = JobState::Done;
1344 let promise = job.promise;
1345 let lane = job.lane;
1346 let code = error.code().to_string();
1347 let mut settled_now = false;
1348 if let Some(record) = self.promises.get_mut(&promise) {
1349 if record.reject(error).is_ok() {
1350 settled_now = true;
1351 } else {
1352 self.metrics.promises_double_settled =
1353 self.metrics.promises_double_settled.saturating_add(1);
1354 }
1355 }
1356 if let Some(lane_record) = self.lanes.get_mut(&lane) {
1357 lane_record.complete();
1358 }
1359 self.push_event(Event::PromiseRejected { promise, code });
1360 self.metrics.promises_rejected = self.metrics.promises_rejected.saturating_add(1);
1361 if settled_now {
1362 self.record_settled(promise);
1363 }
1364 self.jobs.remove(&job_id);
1365 self.push_event(Event::JobCompleted { job: job_id, lane });
1366 }
1367 }
1368}
1369
1370fn pad128(id: CapId) -> [u8; 16] {
1371 id.0
1372}
1373
1374fn cap_token(id: CapId) -> crate::cap::CapToken {
1375 crate::cap::CapToken(u128::from_be_bytes(pad128(id)))
1376}
1377
1378pub struct PromiseHandle {
1380 agent: Agent,
1381 id: PromiseId,
1382}
1383
1384impl Clone for PromiseHandle {
1385 fn clone(&self) -> Self {
1386 self.agent.retain_promise(self.id);
1387 Self {
1388 agent: self.agent.clone(),
1389 id: self.id,
1390 }
1391 }
1392}
1393
1394impl Drop for PromiseHandle {
1395 fn drop(&mut self) {
1396 self.agent.release_promise(self.id);
1397 }
1398}
1399
1400impl PromiseHandle {
1401 pub fn id(&self) -> PromiseId {
1403 self.id
1404 }
1405
1406 pub fn agent(&self) -> &Agent {
1408 &self.agent
1409 }
1410
1411 pub fn value(&self) -> Result<Value> {
1413 self.agent.await_promise(self)
1414 }
1415
1416 pub fn peek(&self) -> Result<Value> {
1418 self.agent
1419 .cell
1420 .borrow()
1421 .promises
1422 .get(&self.id)
1423 .ok_or(Error::UnknownPromise(self.id.0))?
1424 .value()
1425 }
1426
1427 pub fn is_settled(&self) -> bool {
1429 self.agent
1430 .cell
1431 .borrow()
1432 .promises
1433 .get(&self.id)
1434 .map(|record| record.state.is_settled())
1435 .unwrap_or(false)
1436 }
1437}
1438
1439impl std::fmt::Debug for PromiseHandle {
1440 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1441 f.debug_struct("PromiseHandle")
1442 .field("id", &self.id)
1443 .field("settled", &self.is_settled())
1444 .finish()
1445 }
1446}
1447
1448pub fn tool_policy_for(methods: &[&str]) -> ToolPolicy {
1450 ToolPolicy::allow(methods)
1451}
1452
1453pub fn promise_state(agent: &Agent, id: PromiseId) -> Option<PromiseState> {
1455 agent
1456 .cell
1457 .borrow()
1458 .promises
1459 .get(&id)
1460 .map(|record| record.state.clone())
1461}