19 virtual void set_runtime_interposition(
20 std::shared_ptr<RuntimeInterpositionController> controller) {
21 runtime_interposition_ = std::move(controller);
25 asio::awaitable<sp::runtime::Result> invoke_provider(
26 std::shared_ptr<Provider> provider,
28 std::vector<sp::Message> host_instructions = {},
29 std::vector<sp::Message> trusted_supplemental = {},
30 std::shared_ptr<graph::ProviderCallBroker> broker = {},
34 if (broker && runtime_interposition_) {
35 throw std::logic_error(
"Provider broker conflicts with Strict Runtime interposition");
38 if (identity.thread_id.empty() || identity.task_id.empty() ||
39 identity.node_name.empty()) {
40 throw std::invalid_argument(
"Provider broker requires a Core task identity");
42 return broker->invoke(std::move(identity), std::move(provider),
45 if (runtime_interposition_) {
46 return runtime_interposition_->invoke_async(
47 std::move(request), std::move(host_instructions),
48 std::move(trusted_supplemental), std::move(identity));
50 if (identity.model_token_budget == 0 && !identity.managed_budget_lease) {
51 return provider->invoke_async(std::move(request));
55 -> asio::awaitable<sp::runtime::Result> {
56 auto prepared = provider->prepare(std::move(request));
57 if (
const auto* error = prepared.error()) {
58 co_return std::make_shared<const sp::Outcome>(sp::Failure{*error, {}});
60 ProviderBudgetClaim claim;
62 claim = reserve_provider_dispatch(prepared,
63 ProviderDispatchBudget{identity.usage, identity.model_token_budget,
64 identity.budget_exhausted, identity.budget_cancel_token,
65 identity.managed_budget_lease, identity.managed_budget_store});
67 co_return failure.outcome();
69 co_await claim.begin_managed_effect(
70 prepared, graph::managed_provider_effect_id(identity));
71 claim.mark_dispatched();
72 sp::runtime::Result outcome;
73 std::exception_ptr dispatch_error;
75 outcome =
co_await provider->dispatch_async(std::move(prepared));
77 outcome = error.outcome();
78 dispatch_error = std::current_exception();
80 outcome = error.outcome();
81 dispatch_error = std::current_exception();
84 co_await claim.settle_managed(outcome, dispatch_error);
89 throw ProviderBudgetSettlementError(outcome, std::current_exception(), dispatch_error);
91 if (dispatch_error) std::rethrow_exception(dispatch_error);
93 }(std::move(provider), std::move(request), std::move(identity));
97 std::shared_ptr<RuntimeInterpositionController> runtime_interposition_;