@mupt-ai/dari-gateway 0.2.0 → 0.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/bun.d.ts +2 -0
- package/dist/bun.js +4 -0
- package/dist/context/eval_catalog.d.ts +3 -0
- package/dist/context/eval_catalog.js +7 -0
- package/dist/context/interaction_fingerprint.d.ts +27 -0
- package/dist/context/interaction_fingerprint.js +519 -0
- package/dist/context/interaction_fingerprint_format.d.ts +42 -0
- package/dist/context/interaction_fingerprint_format.js +113 -0
- package/dist/context/interaction_lease_depth.d.ts +2 -0
- package/dist/context/interaction_lease_depth.js +110 -0
- package/dist/context/lease_history.d.ts +7 -0
- package/dist/context/lease_history.js +158 -0
- package/dist/context/pricing.d.ts +4 -0
- package/dist/context/pricing.js +23 -0
- package/dist/context/provider_prompt_accounting.d.ts +14 -0
- package/dist/context/provider_prompt_accounting.js +187 -0
- package/dist/context/routing_context.d.ts +40 -0
- package/dist/context/routing_context.js +211 -0
- package/dist/http/auth.d.ts +2 -0
- package/dist/http/auth.js +35 -0
- package/dist/http/errors.d.ts +19 -0
- package/dist/http/errors.js +89 -0
- package/dist/http/handler.d.ts +12 -0
- package/dist/http/handler.js +81 -0
- package/dist/http/http2_server.d.ts +6 -0
- package/dist/http/http2_server.js +103 -0
- package/dist/http/serve.d.ts +20 -0
- package/dist/http/serve.js +78 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.js +8 -0
- package/dist/ingress/anthropic_messages.d.ts +3 -0
- package/dist/ingress/anthropic_messages.js +122 -0
- package/dist/ingress/anthropic_models.d.ts +1 -0
- package/dist/ingress/anthropic_models.js +23 -0
- package/dist/ingress/chat_completions.d.ts +2 -0
- package/dist/ingress/chat_completions.js +37 -0
- package/dist/ingress/claude_code/request_context.d.ts +2 -0
- package/dist/ingress/claude_code/request_context.js +31 -0
- package/dist/ingress/codex.d.ts +3 -0
- package/dist/ingress/codex.js +65 -0
- package/dist/ingress/codex_models.d.ts +2 -0
- package/dist/ingress/codex_models.js +89 -0
- package/dist/ingress/json.d.ts +1 -0
- package/dist/ingress/json.js +95 -0
- package/dist/ingress/models.d.ts +1 -0
- package/dist/ingress/models.js +53 -0
- package/dist/interaction/capabilities.d.ts +3 -0
- package/dist/interaction/capabilities.js +24 -0
- package/dist/interaction/image.d.ts +4 -0
- package/dist/interaction/image.js +13 -0
- package/dist/interaction/portable_reasoning_state.d.ts +4 -0
- package/dist/interaction/portable_reasoning_state.js +18 -0
- package/dist/interaction/provider_continuation_state.d.ts +6 -0
- package/dist/interaction/provider_continuation_state.js +27 -0
- package/dist/interaction/tool_identity.d.ts +10 -0
- package/dist/interaction/tool_identity.js +41 -0
- package/dist/interaction/types.d.ts +203 -0
- package/dist/interaction/types.js +5 -0
- package/dist/models/context_limits.d.ts +2 -0
- package/dist/models/context_limits.js +7 -0
- package/dist/models/execution_provider.d.ts +8 -0
- package/dist/models/execution_provider.js +13 -0
- package/dist/models/gateways.d.ts +11 -0
- package/dist/models/gateways.js +45 -0
- package/dist/models/ids.d.ts +1 -0
- package/dist/models/ids.js +15 -0
- package/dist/models/provider_defaults.d.ts +4 -0
- package/dist/models/provider_defaults.js +41 -0
- package/dist/models/runtime_overrides.d.ts +4 -0
- package/dist/models/runtime_overrides.js +209 -0
- package/dist/observability/errors.d.ts +8 -0
- package/dist/observability/errors.js +11 -0
- package/dist/platform/platform.d.ts +152 -0
- package/dist/platform/platform.js +11 -0
- package/dist/platform/routing_contract.d.ts +2 -0
- package/dist/platform/routing_contract.js +5 -0
- package/dist/protocol/input/anthropic_messages.d.ts +2 -0
- package/dist/protocol/input/anthropic_messages.js +494 -0
- package/dist/protocol/input/chat_completions.d.ts +4 -0
- package/dist/protocol/input/chat_completions.js +212 -0
- package/dist/protocol/input/chat_completions_validation.d.ts +2 -0
- package/dist/protocol/input/chat_completions_validation.js +257 -0
- package/dist/protocol/input/openai_responses.d.ts +2 -0
- package/dist/protocol/input/openai_responses.js +666 -0
- package/dist/protocol/input/router_model.d.ts +7 -0
- package/dist/protocol/input/router_model.js +43 -0
- package/dist/protocol/output/anthropic_messages.d.ts +10 -0
- package/dist/protocol/output/anthropic_messages.js +15 -0
- package/dist/protocol/output/anthropic_messages_output.d.ts +10 -0
- package/dist/protocol/output/anthropic_messages_output.js +124 -0
- package/dist/protocol/output/anthropic_messages_stream.d.ts +16 -0
- package/dist/protocol/output/anthropic_messages_stream.js +267 -0
- package/dist/protocol/output/chat_completions.d.ts +29 -0
- package/dist/protocol/output/chat_completions.js +406 -0
- package/dist/protocol/output/chat_reasoning_detail.d.ts +2 -0
- package/dist/protocol/output/chat_reasoning_detail.js +13 -0
- package/dist/protocol/output/delivered_stream_snapshot.d.ts +10 -0
- package/dist/protocol/output/delivered_stream_snapshot.js +31 -0
- package/dist/protocol/output/openai_responses.d.ts +10 -0
- package/dist/protocol/output/openai_responses.js +14 -0
- package/dist/protocol/output/openai_responses_output.d.ts +14 -0
- package/dist/protocol/output/openai_responses_output.js +125 -0
- package/dist/protocol/output/openai_responses_stream.d.ts +18 -0
- package/dist/protocol/output/openai_responses_stream.js +546 -0
- package/dist/protocol/output/sse_stream.d.ts +31 -0
- package/dist/protocol/output/sse_stream.js +67 -0
- package/dist/providers/anthropic_safeguards.d.ts +11 -0
- package/dist/providers/anthropic_safeguards.js +81 -0
- package/dist/providers/aws_assume_role.d.ts +17 -0
- package/dist/providers/aws_assume_role.js +107 -0
- package/dist/providers/cancel_estimate.d.ts +43 -0
- package/dist/providers/cancel_estimate.js +89 -0
- package/dist/providers/execution.d.ts +72 -0
- package/dist/providers/execution.js +491 -0
- package/dist/providers/model_capabilities.d.ts +11 -0
- package/dist/providers/model_capabilities.js +29 -0
- package/dist/providers/pi.d.ts +65 -0
- package/dist/providers/pi.js +319 -0
- package/dist/providers/pi_context.d.ts +7 -0
- package/dist/providers/pi_context.js +405 -0
- package/dist/providers/pi_options.d.ts +11 -0
- package/dist/providers/pi_options.js +398 -0
- package/dist/providers/pi_output.d.ts +2 -0
- package/dist/providers/pi_output.js +453 -0
- package/dist/providers/provider_attempt_runner.d.ts +55 -0
- package/dist/providers/provider_attempt_runner.js +90 -0
- package/dist/providers/provider_call.d.ts +77 -0
- package/dist/providers/provider_call.js +292 -0
- package/dist/providers/provider_reported_cost.d.ts +10 -0
- package/dist/providers/provider_reported_cost.js +123 -0
- package/dist/providers/reasoning.d.ts +12 -0
- package/dist/providers/reasoning.js +30 -0
- package/dist/providers/response_capture.d.ts +23 -0
- package/dist/providers/response_capture.js +47 -0
- package/dist/providers/stream_finalization.d.ts +46 -0
- package/dist/providers/stream_finalization.js +165 -0
- package/dist/providers/subscription_limits.d.ts +31 -0
- package/dist/providers/subscription_limits.js +163 -0
- package/dist/providers/subscription_usage.d.ts +10 -0
- package/dist/providers/subscription_usage.js +79 -0
- package/dist/runtime/claude_code/auxiliary_routing.d.ts +3 -0
- package/dist/runtime/claude_code/auxiliary_routing.js +60 -0
- package/dist/runtime/customer_disconnect.d.ts +20 -0
- package/dist/runtime/customer_disconnect.js +49 -0
- package/dist/runtime/explicit_model.d.ts +4 -0
- package/dist/runtime/explicit_model.js +53 -0
- package/dist/runtime/harness_identity/conversation.d.ts +33 -0
- package/dist/runtime/harness_identity/conversation.js +39 -0
- package/dist/runtime/harness_identity/extract.d.ts +8 -0
- package/dist/runtime/harness_identity/extract.js +214 -0
- package/dist/runtime/harness_identity/index.d.ts +2 -0
- package/dist/runtime/harness_identity/index.js +2 -0
- package/dist/runtime/prepare_routed_completion.d.ts +33 -0
- package/dist/runtime/prepare_routed_completion.js +167 -0
- package/dist/runtime/provider_stream_lifecycle.d.ts +31 -0
- package/dist/runtime/provider_stream_lifecycle.js +88 -0
- package/dist/runtime/provider_stream_outcome.d.ts +23 -0
- package/dist/runtime/provider_stream_outcome.js +55 -0
- package/dist/runtime/request_tags.d.ts +7 -0
- package/dist/runtime/request_tags.js +33 -0
- package/dist/runtime/routed_completion.d.ts +17 -0
- package/dist/runtime/routed_completion.js +80 -0
- package/dist/runtime/routed_protocol.d.ts +30 -0
- package/dist/runtime/routed_protocol.js +1 -0
- package/dist/runtime/routed_runtime.d.ts +40 -0
- package/dist/runtime/routed_runtime.js +535 -0
- package/dist/runtime/routing_lease.d.ts +26 -0
- package/dist/runtime/routing_lease.js +210 -0
- package/dist/runtime/runtime_reporter.d.ts +71 -0
- package/dist/runtime/runtime_reporter.js +35 -0
- package/dist/self_host/config.d.ts +46 -0
- package/dist/self_host/config.js +105 -0
- package/dist/self_host/main.d.ts +16 -0
- package/dist/self_host/main.js +95 -0
- package/dist/self_host/platform.d.ts +13 -0
- package/dist/self_host/platform.js +50 -0
- package/dist/self_host/prefix_store.d.ts +46 -0
- package/dist/self_host/prefix_store.js +261 -0
- package/dist/self_host/resolve.d.ts +28 -0
- package/dist/self_host/resolve.js +171 -0
- package/dist/self_host/subscriptions/access.d.ts +10 -0
- package/dist/self_host/subscriptions/access.js +37 -0
- package/dist/self_host/subscriptions/http.d.ts +15 -0
- package/dist/self_host/subscriptions/http.js +187 -0
- package/dist/self_host/subscriptions/index.d.ts +24 -0
- package/dist/self_host/subscriptions/index.js +24 -0
- package/dist/self_host/subscriptions/oauth.d.ts +55 -0
- package/dist/self_host/subscriptions/oauth.js +281 -0
- package/dist/self_host/subscriptions/store.d.ts +78 -0
- package/dist/self_host/subscriptions/store.js +235 -0
- package/dist/strategies/auto_routing_selector.d.ts +12 -0
- package/dist/strategies/auto_routing_selector.js +61 -0
- package/dist/strategies/eval_relevance.d.ts +17 -0
- package/dist/strategies/eval_relevance.js +32 -0
- package/dist/strategies/fallback_decision.d.ts +8 -0
- package/dist/strategies/fallback_decision.js +17 -0
- package/dist/strategies/priority_selector.d.ts +7 -0
- package/dist/strategies/priority_selector.js +37 -0
- package/dist/strategies/route_decision.d.ts +22 -0
- package/dist/strategies/route_decision.js +65 -0
- package/dist/strategies/routing.d.ts +74 -0
- package/dist/strategies/routing.js +280 -0
- package/dist/strategies/selector_projection.d.ts +15 -0
- package/dist/strategies/selector_projection.js +161 -0
- package/dist/telemetry/background.d.ts +7 -0
- package/dist/telemetry/background.js +33 -0
- package/dist/telemetry/benchmark_replay.d.ts +37 -0
- package/dist/telemetry/benchmark_replay.js +108 -0
- package/dist/telemetry/billing_finalization.d.ts +64 -0
- package/dist/telemetry/billing_finalization.js +96 -0
- package/dist/telemetry/ingest_values.d.ts +4 -0
- package/dist/telemetry/ingest_values.js +12 -0
- package/dist/telemetry/model_cost.d.ts +3 -0
- package/dist/telemetry/model_cost.js +15 -0
- package/dist/telemetry/prefix_state.d.ts +47 -0
- package/dist/telemetry/prefix_state.js +116 -0
- package/dist/telemetry/report.d.ts +88 -0
- package/dist/telemetry/report.js +621 -0
- package/dist/telemetry/requests/interaction_observability.d.ts +45 -0
- package/dist/telemetry/requests/interaction_observability.js +180 -0
- package/dist/telemetry/requests/retained_interaction_request.d.ts +8 -0
- package/dist/telemetry/requests/retained_interaction_request.js +10 -0
- package/dist/telemetry/scrub.d.ts +2 -0
- package/dist/telemetry/scrub.js +31 -0
- package/dist/telemetry/skills/claude/catalog.d.ts +6 -0
- package/dist/telemetry/skills/claude/catalog.js +99 -0
- package/dist/telemetry/skills/claude/file_reads.d.ts +4 -0
- package/dist/telemetry/skills/claude/file_reads.js +110 -0
- package/dist/telemetry/skills/claude/observations.d.ts +3 -0
- package/dist/telemetry/skills/claude/observations.js +366 -0
- package/dist/telemetry/skills/codex/catalog.d.ts +11 -0
- package/dist/telemetry/skills/codex/catalog.js +138 -0
- package/dist/telemetry/skills/codex/exec_file_reads.d.ts +9 -0
- package/dist/telemetry/skills/codex/exec_file_reads.js +36 -0
- package/dist/telemetry/skills/codex/explicit.d.ts +3 -0
- package/dist/telemetry/skills/codex/explicit.js +90 -0
- package/dist/telemetry/skills/codex/file_reads.d.ts +4 -0
- package/dist/telemetry/skills/codex/file_reads.js +37 -0
- package/dist/telemetry/skills/codex/identity.d.ts +2 -0
- package/dist/telemetry/skills/codex/identity.js +20 -0
- package/dist/telemetry/skills/observations.d.ts +21 -0
- package/dist/telemetry/skills/observations.js +41 -0
- package/dist/telemetry/skills/paths.d.ts +11 -0
- package/dist/telemetry/skills/paths.js +61 -0
- package/dist/telemetry/skills/pi.d.ts +6 -0
- package/dist/telemetry/skills/pi.js +223 -0
- package/dist/telemetry/skills/shell_file_reads.d.ts +7 -0
- package/dist/telemetry/skills/shell_file_reads.js +226 -0
- package/dist/telemetry/skills/shell_words.d.ts +13 -0
- package/dist/telemetry/skills/shell_words.js +189 -0
- package/dist/telemetry/tools/input.d.ts +2 -0
- package/dist/telemetry/tools/input.js +14 -0
- package/dist/telemetry/tools/observations.d.ts +29 -0
- package/dist/telemetry/tools/observations.js +247 -0
- package/dist/telemetry/usage.d.ts +57 -0
- package/dist/telemetry/usage.js +136 -0
- package/dist/types.d.ts +94 -0
- package/dist/types.js +1 -0
- package/package.json +21 -6
- package/src/bun.ts +2 -2
- package/src/context/eval_catalog.ts +1 -1
- package/src/context/interaction_fingerprint.ts +9 -9
- package/src/context/interaction_fingerprint_format.ts +1 -1
- package/src/context/interaction_lease_depth.ts +1 -1
- package/src/context/pricing.ts +1 -1
- package/src/context/provider_prompt_accounting.ts +5 -5
- package/src/context/routing_context.ts +16 -16
- package/src/http/auth.ts +1 -1
- package/src/http/handler.ts +8 -8
- package/src/http/serve.ts +3 -3
- package/src/index.ts +6 -6
- package/src/ingress/anthropic_messages.ts +12 -12
- package/src/ingress/anthropic_models.ts +1 -1
- package/src/ingress/chat_completions.ts +9 -9
- package/src/ingress/claude_code/request_context.ts +2 -2
- package/src/ingress/codex.ts +10 -10
- package/src/ingress/codex_models.ts +4 -4
- package/src/ingress/json.ts +1 -1
- package/src/ingress/models.ts +9 -9
- package/src/interaction/capabilities.ts +1 -1
- package/src/interaction/portable_reasoning_state.ts +1 -1
- package/src/interaction/provider_continuation_state.ts +1 -1
- package/src/interaction/tool_identity.ts +2 -2
- package/src/models/context_limits.ts +1 -1
- package/src/models/execution_provider.ts +1 -1
- package/src/models/ids.ts +1 -1
- package/src/models/provider_defaults.ts +1 -1
- package/src/models/runtime_overrides.ts +1 -1
- package/src/observability/errors.ts +2 -2
- package/src/platform/platform.ts +4 -4
- package/src/protocol/input/anthropic_messages.ts +7 -7
- package/src/protocol/input/chat_completions.ts +5 -5
- package/src/protocol/input/chat_completions_validation.ts +4 -4
- package/src/protocol/input/openai_responses.ts +6 -6
- package/src/protocol/output/anthropic_messages.ts +3 -3
- package/src/protocol/output/anthropic_messages_output.ts +6 -4
- package/src/protocol/output/anthropic_messages_stream.ts +7 -7
- package/src/protocol/output/chat_completions.ts +13 -13
- package/src/protocol/output/chat_reasoning_detail.ts +1 -1
- package/src/protocol/output/openai_responses.ts +3 -3
- package/src/protocol/output/openai_responses_output.ts +4 -2
- package/src/protocol/output/openai_responses_stream.ts +6 -6
- package/src/protocol/output/sse_stream.ts +3 -3
- package/src/providers/anthropic_safeguards.ts +2 -2
- package/src/providers/aws_assume_role.ts +2 -2
- package/src/providers/cancel_estimate.ts +1 -1
- package/src/providers/execution.ts +17 -17
- package/src/providers/pi.ts +14 -14
- package/src/providers/pi_context.ts +6 -6
- package/src/providers/pi_options.ts +10 -10
- package/src/providers/pi_output.ts +5 -5
- package/src/providers/provider_attempt_runner.ts +1 -1
- package/src/providers/provider_call.ts +14 -14
- package/src/providers/provider_reported_cost.ts +3 -3
- package/src/providers/reasoning.ts +2 -2
- package/src/providers/stream_finalization.ts +9 -9
- package/src/providers/subscription_limits.ts +3 -3
- package/src/runtime/claude_code/auxiliary_routing.ts +5 -5
- package/src/runtime/customer_disconnect.ts +1 -1
- package/src/runtime/explicit_model.ts +4 -4
- package/src/runtime/harness_identity/conversation.ts +1 -1
- package/src/runtime/harness_identity/extract.ts +3 -3
- package/src/runtime/harness_identity/index.ts +2 -2
- package/src/runtime/prepare_routed_completion.ts +13 -13
- package/src/runtime/provider_stream_lifecycle.ts +1 -1
- package/src/runtime/provider_stream_outcome.ts +2 -2
- package/src/runtime/request_tags.ts +2 -2
- package/src/runtime/routed_completion.ts +11 -11
- package/src/runtime/routed_protocol.ts +2 -2
- package/src/runtime/routed_runtime.ts +20 -19
- package/src/runtime/routing_lease.ts +7 -7
- package/src/runtime/runtime_reporter.ts +3 -3
- package/src/self_host/main.ts +12 -12
- package/src/self_host/platform.ts +5 -5
- package/src/self_host/prefix_store.ts +2 -2
- package/src/self_host/resolve.ts +6 -6
- package/src/self_host/subscriptions/access.ts +2 -2
- package/src/self_host/subscriptions/http.ts +2 -2
- package/src/self_host/subscriptions/index.ts +4 -4
- package/src/self_host/subscriptions/store.ts +1 -1
- package/src/strategies/auto_routing_selector.ts +2 -2
- package/src/strategies/eval_relevance.ts +3 -3
- package/src/strategies/priority_selector.ts +1 -1
- package/src/strategies/route_decision.ts +7 -7
- package/src/strategies/routing.ts +10 -10
- package/src/strategies/selector_projection.ts +2 -2
- package/src/telemetry/billing_finalization.ts +3 -3
- package/src/telemetry/model_cost.ts +1 -1
- package/src/telemetry/prefix_state.ts +4 -4
- package/src/telemetry/report.ts +21 -21
- package/src/telemetry/requests/interaction_observability.ts +1 -1
- package/src/telemetry/requests/retained_interaction_request.ts +1 -1
- package/src/telemetry/skills/claude/catalog.ts +1 -1
- package/src/telemetry/skills/claude/file_reads.ts +6 -6
- package/src/telemetry/skills/claude/observations.ts +3 -3
- package/src/telemetry/skills/codex/catalog.ts +3 -3
- package/src/telemetry/skills/codex/exec_file_reads.ts +4 -4
- package/src/telemetry/skills/codex/explicit.ts +3 -3
- package/src/telemetry/skills/codex/file_reads.ts +5 -5
- package/src/telemetry/skills/observations.ts +7 -7
- package/src/telemetry/skills/pi.ts +3 -3
- package/src/telemetry/skills/shell_file_reads.ts +2 -2
- package/src/telemetry/skills/shell_words.ts +1 -1
- package/src/telemetry/tools/input.ts +1 -1
- package/src/telemetry/tools/observations.ts +9 -9
- package/src/telemetry/usage.ts +5 -5
|
@@ -0,0 +1,535 @@
|
|
|
1
|
+
import { randomUUID } from "node:crypto";
|
|
2
|
+
import { isRecord, sameRoutingCandidate, } from "@mupt-ai/dari-router/policy-engine";
|
|
3
|
+
import { buildRoutingContext } from "../context/routing_context.js";
|
|
4
|
+
import { completeNonStreaming, executeNonStreaming, executeStreaming, prepareStreamingExecution, } from "../providers/execution.js";
|
|
5
|
+
import { prepareProviderExecution, startProviderCompletion, startProviderStream, } from "../providers/provider_call.js";
|
|
6
|
+
import { routeDecision } from "../strategies/route_decision.js";
|
|
7
|
+
import { executionProviderForModel } from "../models/execution_provider.js";
|
|
8
|
+
import { trackBackgroundTelemetry } from "../telemetry/background.js";
|
|
9
|
+
import { estimateBenchmarkReplay } from "../telemetry/benchmark_replay.js";
|
|
10
|
+
import { buildCompletedPrefixHit } from "../telemetry/prefix_state.js";
|
|
11
|
+
import { scrubSecrets } from "../telemetry/scrub.js";
|
|
12
|
+
import { auxiliaryDecision } from "./claude_code/auxiliary_routing.js";
|
|
13
|
+
import { explicitModelDecision, strictModelDecision } from "./explicit_model.js";
|
|
14
|
+
import { clearPendingLease, committedLeaseDecision, leaseHoldDecision, leasePrefetchDue, leasedDecision, pendingLeaseDecision, prefetchNextLease, selectorNegotiatesLeases, } from "./routing_lease.js";
|
|
15
|
+
import { createExperimentRoutedRuntimeReporter, } from "./runtime_reporter.js";
|
|
16
|
+
import { HttpError } from "../http/errors.js";
|
|
17
|
+
export class RoutedRuntimeProviderSettledError extends Error {
|
|
18
|
+
name = "RoutedRuntimeProviderSettledError";
|
|
19
|
+
runtimeResult;
|
|
20
|
+
cause;
|
|
21
|
+
constructor(message, runtimeResult, cause) {
|
|
22
|
+
super(message);
|
|
23
|
+
this.runtimeResult = runtimeResult;
|
|
24
|
+
this.cause = cause;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
export { createExperimentRoutedRuntimeReporter } from "./runtime_reporter.js";
|
|
28
|
+
export async function runPreparedRoutedCompletion(args) {
|
|
29
|
+
const plan = await prepareRuntimeExecution({
|
|
30
|
+
prepared: args.prepared,
|
|
31
|
+
selectorBackend: args.selectorBackend,
|
|
32
|
+
clientSignal: args.clientSignal,
|
|
33
|
+
});
|
|
34
|
+
const { prepared } = args;
|
|
35
|
+
if (!prepared.interaction.stream) {
|
|
36
|
+
return executeNonStreaming({
|
|
37
|
+
requestId: prepared.requestId,
|
|
38
|
+
interaction: prepared.interaction,
|
|
39
|
+
primary: plan.primary,
|
|
40
|
+
primaryRetries: plan.primaryRetries,
|
|
41
|
+
resolveFallback: plan.resolveFallback,
|
|
42
|
+
reporter: prepared.reporter,
|
|
43
|
+
protocol: prepared.protocol,
|
|
44
|
+
startedCompletion: plan.startedCompletion,
|
|
45
|
+
reportBarrier: plan.reportBarrier,
|
|
46
|
+
clientSignal: args.clientSignal,
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
const streaming = await prepareStreamingExecution({
|
|
50
|
+
requestId: prepared.requestId,
|
|
51
|
+
interaction: prepared.interaction,
|
|
52
|
+
primary: plan.primary,
|
|
53
|
+
primaryRetries: plan.primaryRetries,
|
|
54
|
+
resolveFallback: plan.resolveFallback,
|
|
55
|
+
reporter: prepared.reporter,
|
|
56
|
+
startedStream: plan.startedStream,
|
|
57
|
+
initialError: plan.initialStreamError,
|
|
58
|
+
reportBarrier: plan.reportBarrier,
|
|
59
|
+
clientSignal: args.clientSignal,
|
|
60
|
+
});
|
|
61
|
+
return executeStreaming({
|
|
62
|
+
requestId: prepared.requestId,
|
|
63
|
+
interaction: prepared.interaction,
|
|
64
|
+
choice: streaming.choice,
|
|
65
|
+
reporter: prepared.reporter,
|
|
66
|
+
protocol: prepared.protocol,
|
|
67
|
+
startedStream: streaming.started,
|
|
68
|
+
attempt: streaming.attempt,
|
|
69
|
+
failedSetupLatencyMs: streaming.failedSetupLatencyMs,
|
|
70
|
+
reportBarrier: plan.reportBarrier,
|
|
71
|
+
clientSignal: args.clientSignal,
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
export async function runPreparedRoutedInteraction(args) {
|
|
75
|
+
if (args.prepared.interaction.stream) {
|
|
76
|
+
throw new HttpError(400, "In-process routed runtime results only support non-streaming interactions.", "streaming_not_supported");
|
|
77
|
+
}
|
|
78
|
+
const plan = await prepareRuntimeExecution({
|
|
79
|
+
...args,
|
|
80
|
+
requireSelectorDecision: true,
|
|
81
|
+
});
|
|
82
|
+
const result = await completeNonStreaming({
|
|
83
|
+
requestId: args.prepared.requestId,
|
|
84
|
+
interaction: args.prepared.interaction,
|
|
85
|
+
primary: plan.primary,
|
|
86
|
+
primaryRetries: plan.primaryRetries,
|
|
87
|
+
resolveFallback: plan.resolveFallback,
|
|
88
|
+
reporter: args.prepared.reporter,
|
|
89
|
+
protocol: args.prepared.protocol,
|
|
90
|
+
startedCompletion: plan.startedCompletion,
|
|
91
|
+
reportBarrier: plan.reportBarrier,
|
|
92
|
+
});
|
|
93
|
+
const routedResult = runtimeResult(result, args.prepared);
|
|
94
|
+
if (result.reportBarrierError !== undefined) {
|
|
95
|
+
throw new RoutedRuntimeProviderSettledError(errorMessage(result.reportBarrierError), routedResult, result.reportBarrierError);
|
|
96
|
+
}
|
|
97
|
+
return routedResult;
|
|
98
|
+
}
|
|
99
|
+
export async function runExplicitRoutedInteraction(args) {
|
|
100
|
+
const prepared = await prepareExplicitRoutedCompletion(args);
|
|
101
|
+
return runPreparedRoutedInteraction({
|
|
102
|
+
prepared,
|
|
103
|
+
selectorBackend: args.selectorBackend,
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
async function prepareExplicitRoutedCompletion(args) {
|
|
107
|
+
const receivedAt = new Date();
|
|
108
|
+
const requestId = randomUUID();
|
|
109
|
+
const routing = await buildRoutingContext({
|
|
110
|
+
routerId: args.routerId,
|
|
111
|
+
interaction: args.interaction,
|
|
112
|
+
credentials: args.credentials,
|
|
113
|
+
previousDecision: args.previousDecision,
|
|
114
|
+
receivedAt,
|
|
115
|
+
});
|
|
116
|
+
return {
|
|
117
|
+
requestId,
|
|
118
|
+
routerId: args.routerId,
|
|
119
|
+
receivedAt,
|
|
120
|
+
interaction: args.interaction,
|
|
121
|
+
protocol: inProcessProtocol,
|
|
122
|
+
credentials: args.credentials,
|
|
123
|
+
billable: args.billable ?? false,
|
|
124
|
+
tags: {},
|
|
125
|
+
harnessConversationIdentity: undefined,
|
|
126
|
+
routing,
|
|
127
|
+
reporter: args.reporter ?? createExperimentRoutedRuntimeReporter(),
|
|
128
|
+
};
|
|
129
|
+
}
|
|
130
|
+
async function prepareRuntimeExecution(args) {
|
|
131
|
+
const { prepared } = args;
|
|
132
|
+
// A strict router never selects, leases, or falls back: the pinned pair or
|
|
133
|
+
// an error.
|
|
134
|
+
if (prepared.credentials.strict === true) {
|
|
135
|
+
const pinned = strictModelDecision(prepared);
|
|
136
|
+
prepared.reporter.attachServingDecision(pinned.decision);
|
|
137
|
+
prepared.reporter.attachDecisionDetails({
|
|
138
|
+
decision_source: "strict_model",
|
|
139
|
+
explicit_model: {
|
|
140
|
+
model: pinned.decision.selectedModel,
|
|
141
|
+
reasoning_effort: pinned.decision.reasoningEffort,
|
|
142
|
+
},
|
|
143
|
+
});
|
|
144
|
+
return selectedExecutionPlan(prepared, pinned);
|
|
145
|
+
}
|
|
146
|
+
// A requested `dari/model/<id>` is served as chosen, before any lease.
|
|
147
|
+
const explicit = args.requireSelectorDecision ? null : explicitModelDecision(prepared);
|
|
148
|
+
if (explicit) {
|
|
149
|
+
prepared.reporter.attachServingDecision(explicit.decision);
|
|
150
|
+
prepared.reporter.attachDecisionDetails({
|
|
151
|
+
decision_source: "explicit_model",
|
|
152
|
+
explicit_model: {
|
|
153
|
+
model: explicit.decision.selectedModel,
|
|
154
|
+
reasoning_effort: explicit.decision.reasoningEffort,
|
|
155
|
+
},
|
|
156
|
+
});
|
|
157
|
+
return selectedExecutionPlan(prepared, explicit);
|
|
158
|
+
}
|
|
159
|
+
// Live background work bypasses task selection; explicit experiments
|
|
160
|
+
// still require a selector observation and never consume live leases.
|
|
161
|
+
const auxiliary = args.requireSelectorDecision ? null : auxiliaryDecision(prepared);
|
|
162
|
+
if (auxiliary) {
|
|
163
|
+
prepared.reporter.attachServingDecision(auxiliary.decision);
|
|
164
|
+
prepared.reporter.attachDecisionDetails({
|
|
165
|
+
decision_source: "auxiliary_request",
|
|
166
|
+
auxiliary_request: {
|
|
167
|
+
request_class: prepared.interaction.agentContext?.requestClass,
|
|
168
|
+
model: auxiliary.decision.selectedModel,
|
|
169
|
+
reasoning_effort: auxiliary.decision.reasoningEffort,
|
|
170
|
+
},
|
|
171
|
+
});
|
|
172
|
+
return selectedExecutionPlan(prepared, auxiliary);
|
|
173
|
+
}
|
|
174
|
+
// Persisted policy leases (negotiated {action, turns}) take precedence.
|
|
175
|
+
// Explicit in-process runs are selector experiments: they must observe the
|
|
176
|
+
// selector and must not consume or prefetch live conversations' leases.
|
|
177
|
+
const held = args.requireSelectorDecision ? null : leaseHoldDecision(prepared);
|
|
178
|
+
if (held) {
|
|
179
|
+
// Serving-only attach: nextDecision stays unset so if a fallback serves
|
|
180
|
+
// this turn, execution's attachServingDecision moves both the prefix's
|
|
181
|
+
// next_model and inherited countdown onto the healthy serving pair.
|
|
182
|
+
prepared.reporter.attachServingDecision(held);
|
|
183
|
+
prepared.reporter.attachDecisionDetails({
|
|
184
|
+
decision_source: "lease_hold",
|
|
185
|
+
lease_hold: {
|
|
186
|
+
model: held.selectedModel,
|
|
187
|
+
reasoning_effort: held.reasoningEffort,
|
|
188
|
+
turns_remaining_after: held.leaseTurnsRemaining ?? 0,
|
|
189
|
+
},
|
|
190
|
+
});
|
|
191
|
+
// Prefetch fires on the turn that leaves lag turns of lease including
|
|
192
|
+
// itself — training stashes at turnIndex === endTurn - lag, and this
|
|
193
|
+
// turn's pre-decrement countdown equals the lag exactly then. Firing
|
|
194
|
+
// unconditionally (rather than skipping when a pending lease exists)
|
|
195
|
+
// means a stale pending from a failed consume is overwritten with a
|
|
196
|
+
// fresh decision before the next expiry can re-adopt it.
|
|
197
|
+
if (leasePrefetchDue(prepared)) {
|
|
198
|
+
trackBackgroundTelemetry(prefetchNextLease(prepared, args.selectorBackend));
|
|
199
|
+
}
|
|
200
|
+
return selectedExecutionPlan(prepared, committedLeaseDecision(prepared, held));
|
|
201
|
+
}
|
|
202
|
+
const adopted = args.requireSelectorDecision ? null : pendingLeaseDecision(prepared);
|
|
203
|
+
if (adopted) {
|
|
204
|
+
prepared.reporter.attachServingDecision(adopted);
|
|
205
|
+
prepared.reporter.attachDecisionDetails({
|
|
206
|
+
decision_source: "prefetched_lease",
|
|
207
|
+
selector_lease_turns: prepared.routing.pendingLease?.turns ?? null,
|
|
208
|
+
lease_prefetch_adopted: {
|
|
209
|
+
model: adopted.selectedModel,
|
|
210
|
+
reasoning_effort: adopted.reasoningEffort,
|
|
211
|
+
turns_remaining_after: adopted.leaseTurnsRemaining ?? 0,
|
|
212
|
+
},
|
|
213
|
+
});
|
|
214
|
+
prepared.reporter.attachAdoptedSelectorOutput({
|
|
215
|
+
outputText: prepared.routing.pendingLease?.outputText ?? null,
|
|
216
|
+
reason: adopted.reason,
|
|
217
|
+
candidates: prepared.routing.candidateResolution.candidates,
|
|
218
|
+
});
|
|
219
|
+
// Consume the prefetched decision so a later expiry cannot re-adopt it.
|
|
220
|
+
// Awaited with a cap: the clear is one small internal write, and losing
|
|
221
|
+
// it silently would leave the stale lease adoptable. Even if the capped
|
|
222
|
+
// wait elapses, the next lease's own prefetch overwrites the stale rows
|
|
223
|
+
// before its expiry (the menu's shortest lease exceeds the lag).
|
|
224
|
+
await clearPendingLease(prepared);
|
|
225
|
+
return selectedExecutionPlan(prepared, committedLeaseDecision(prepared, adopted));
|
|
226
|
+
}
|
|
227
|
+
// The stateless ten-turn hold covers per-turn policies. A lease-negotiating
|
|
228
|
+
// backend must reach the selector at expiry — the modulo hold would mask it
|
|
229
|
+
// — so the negotiated protocol bypasses it entirely.
|
|
230
|
+
const leased = args.requireSelectorDecision || (await selectorNegotiatesLeases(args.selectorBackend))
|
|
231
|
+
? null
|
|
232
|
+
: leasedDecision(prepared);
|
|
233
|
+
const speculative = leased
|
|
234
|
+
? null
|
|
235
|
+
: await startSpeculativeExecution(prepared, args.selectorBackend, args.clientSignal);
|
|
236
|
+
if (!speculative) {
|
|
237
|
+
const selected = leased
|
|
238
|
+
?? await selectDecision(prepared, null, args.selectorBackend);
|
|
239
|
+
if (!leased) {
|
|
240
|
+
prepared.reporter.attachDecisionDetails({
|
|
241
|
+
decision_source: "selector",
|
|
242
|
+
selector_lease_turns: selected.decision.leaseTurnsRemaining === undefined
|
|
243
|
+
? null
|
|
244
|
+
: selected.decision.leaseTurnsRemaining + 1,
|
|
245
|
+
});
|
|
246
|
+
}
|
|
247
|
+
return selectedExecutionPlan(prepared, selected);
|
|
248
|
+
}
|
|
249
|
+
prepared.reporter.attachDecision(speculative.decision);
|
|
250
|
+
const primary = {
|
|
251
|
+
decision: speculative.decision,
|
|
252
|
+
execution: speculative.execution,
|
|
253
|
+
role: "primary",
|
|
254
|
+
};
|
|
255
|
+
const selectionPromise = selectDecision(prepared, speculative.decision, args.selectorBackend, args.requireSelectorDecision === true);
|
|
256
|
+
// The execution layer awaits selection as its report barrier only after the
|
|
257
|
+
// provider settles, which can be long after a rejection. Mark the promise
|
|
258
|
+
// handled now; fallback still consumes the original and its rejection.
|
|
259
|
+
selectionPromise.catch(() => undefined);
|
|
260
|
+
let fallbackPromise = null;
|
|
261
|
+
const resolveFallback = () => {
|
|
262
|
+
fallbackPromise ??= selectionPromise.then((selected) => {
|
|
263
|
+
const decision = fallbackForPrimary(prepared, primary.decision, selected);
|
|
264
|
+
if (decision)
|
|
265
|
+
prepared.reporter.attachFallbackDecision(decision);
|
|
266
|
+
return decision ? providerChoice(prepared, decision, "fallback") : null;
|
|
267
|
+
});
|
|
268
|
+
return fallbackPromise;
|
|
269
|
+
};
|
|
270
|
+
return {
|
|
271
|
+
primary,
|
|
272
|
+
primaryRetries: configuredPrimaryRetries(prepared.credentials.primary_retries),
|
|
273
|
+
resolveFallback,
|
|
274
|
+
reportBarrier: selectionPromise,
|
|
275
|
+
startedCompletion: speculative.transport === "completion" ? speculative.started : undefined,
|
|
276
|
+
startedStream: speculative.transport === "stream" ? speculative.started : undefined,
|
|
277
|
+
initialStreamError: speculative.transport === "stream"
|
|
278
|
+
? speculative.initialError
|
|
279
|
+
: undefined,
|
|
280
|
+
};
|
|
281
|
+
}
|
|
282
|
+
function selectedExecutionPlan(prepared, selected) {
|
|
283
|
+
return {
|
|
284
|
+
primary: providerChoice(prepared, selected.decision, "primary"),
|
|
285
|
+
primaryRetries: configuredPrimaryRetries(prepared.credentials.primary_retries),
|
|
286
|
+
resolveFallback: async () => {
|
|
287
|
+
if (!selected.fallbackDecision)
|
|
288
|
+
return null;
|
|
289
|
+
const fallbackDecision = selected.decision.leaseTurnsRemaining === undefined
|
|
290
|
+
? selected.fallbackDecision
|
|
291
|
+
: {
|
|
292
|
+
...selected.fallbackDecision,
|
|
293
|
+
leaseTurnsRemaining: selected.decision.leaseTurnsRemaining,
|
|
294
|
+
};
|
|
295
|
+
return providerChoice(prepared, fallbackDecision, "fallback");
|
|
296
|
+
},
|
|
297
|
+
};
|
|
298
|
+
}
|
|
299
|
+
async function startSpeculativeExecution(prepared, selectorBackend, clientSignal) {
|
|
300
|
+
// Speculation is a new dispatch. A client already gone during request
|
|
301
|
+
// preparation must never cause fresh paid provider work.
|
|
302
|
+
if (clientSignal?.aborted === true)
|
|
303
|
+
return null;
|
|
304
|
+
const { credentials, interaction, routing } = prepared;
|
|
305
|
+
const resolution = routing.candidateResolution;
|
|
306
|
+
if (credentials.speculative_routing !== true ||
|
|
307
|
+
selectorBackend.supportsSpeculativeRouting === false ||
|
|
308
|
+
credentials.credit_exhausted ||
|
|
309
|
+
!routing.previousDecision) {
|
|
310
|
+
return null;
|
|
311
|
+
}
|
|
312
|
+
const previous = {
|
|
313
|
+
model: routing.previousDecision.model,
|
|
314
|
+
reasoningEffort: routing.previousDecision.reasoningEffort,
|
|
315
|
+
};
|
|
316
|
+
if (!resolution.candidates.some((candidate) => sameRoutingCandidate(candidate, previous))) {
|
|
317
|
+
return null;
|
|
318
|
+
}
|
|
319
|
+
const decision = {
|
|
320
|
+
selectedModel: previous.model,
|
|
321
|
+
reasoningEffort: previous.reasoningEffort,
|
|
322
|
+
reason: routing.previousDecision.reason ||
|
|
323
|
+
"Continuing the previous model while selecting the next route.",
|
|
324
|
+
};
|
|
325
|
+
try {
|
|
326
|
+
const execution = providerExecution(prepared, decision);
|
|
327
|
+
if (interaction.stream) {
|
|
328
|
+
try {
|
|
329
|
+
const started = await startProviderStream({
|
|
330
|
+
interaction,
|
|
331
|
+
execution,
|
|
332
|
+
clientSignal,
|
|
333
|
+
});
|
|
334
|
+
return { transport: "stream", decision, execution, started };
|
|
335
|
+
}
|
|
336
|
+
catch (initialError) {
|
|
337
|
+
return { transport: "stream", decision, execution, initialError };
|
|
338
|
+
}
|
|
339
|
+
}
|
|
340
|
+
const started = startProviderCompletion({
|
|
341
|
+
interaction,
|
|
342
|
+
execution,
|
|
343
|
+
clientSignal,
|
|
344
|
+
});
|
|
345
|
+
return { transport: "completion", decision, execution, started };
|
|
346
|
+
}
|
|
347
|
+
catch (error) {
|
|
348
|
+
console.error("speculative provider setup failed", scrubSecrets(error instanceof Error ? error.message : String(error)));
|
|
349
|
+
return null;
|
|
350
|
+
}
|
|
351
|
+
}
|
|
352
|
+
async function selectDecision(prepared, servingDecision, selectorBackend, requireSelectorDecision = false) {
|
|
353
|
+
const { credentials, reporter, routing } = prepared;
|
|
354
|
+
try {
|
|
355
|
+
const routed = await routeDecision({
|
|
356
|
+
selectorMessages: routing.selectorMessages,
|
|
357
|
+
selectorImages: routing.selectorImages,
|
|
358
|
+
resolution: routing.candidateResolution,
|
|
359
|
+
credentials,
|
|
360
|
+
previousDecision: routing.previousDecision,
|
|
361
|
+
conversationId: routing.conversationId,
|
|
362
|
+
selectorBackend,
|
|
363
|
+
leaseHistory: routing.leaseHistory,
|
|
364
|
+
});
|
|
365
|
+
if (routed.details)
|
|
366
|
+
reporter.attachDecisionDetails(routed.details);
|
|
367
|
+
if (servingDecision) {
|
|
368
|
+
if (!routed.run) {
|
|
369
|
+
throw new Error("Speculative routing completed without a selector run.");
|
|
370
|
+
}
|
|
371
|
+
reporter.attachSpeculativeSelectorRun(routed.run, servingDecision);
|
|
372
|
+
reporter.attachDecisionDetails({
|
|
373
|
+
decision_source: "speculative_selector",
|
|
374
|
+
selector_lease_turns: routed.decision.leaseTurnsRemaining === undefined
|
|
375
|
+
? null
|
|
376
|
+
: routed.decision.leaseTurnsRemaining + 1,
|
|
377
|
+
speculative_routing: {
|
|
378
|
+
serving_model: servingDecision.selectedModel,
|
|
379
|
+
serving_reasoning_effort: servingDecision.reasoningEffort,
|
|
380
|
+
next_model: routed.decision.selectedModel,
|
|
381
|
+
next_reasoning_effort: routed.decision.reasoningEffort,
|
|
382
|
+
},
|
|
383
|
+
});
|
|
384
|
+
}
|
|
385
|
+
else if (routed.run) {
|
|
386
|
+
reporter.attachSelectorRun(routed.run);
|
|
387
|
+
}
|
|
388
|
+
else {
|
|
389
|
+
reporter.attachDecision(routed.decision);
|
|
390
|
+
reporter.attachFallbackDecision(routed.fallbackDecision);
|
|
391
|
+
}
|
|
392
|
+
return routed;
|
|
393
|
+
}
|
|
394
|
+
catch (error) {
|
|
395
|
+
const details = isRecord(error) && isRecord(error.decisionDetails)
|
|
396
|
+
? error.decisionDetails
|
|
397
|
+
: null;
|
|
398
|
+
if (details)
|
|
399
|
+
reporter.attachDecisionDetails(details);
|
|
400
|
+
if (!servingDecision) {
|
|
401
|
+
reporter.reportSelectorFailure(error);
|
|
402
|
+
throw error;
|
|
403
|
+
}
|
|
404
|
+
if (requireSelectorDecision) {
|
|
405
|
+
throw error;
|
|
406
|
+
}
|
|
407
|
+
const code = error instanceof HttpError ? error.code : "selector_execution_failed";
|
|
408
|
+
console.error("speculative routing selector failed", JSON.stringify({
|
|
409
|
+
code,
|
|
410
|
+
message: scrubSecrets(error instanceof Error ? error.message : String(error)),
|
|
411
|
+
}));
|
|
412
|
+
reporter.attachDecision(servingDecision);
|
|
413
|
+
reporter.attachDecisionDetails({
|
|
414
|
+
decision_source: "speculative_selector",
|
|
415
|
+
speculative_routing: {
|
|
416
|
+
serving_model: servingDecision.selectedModel,
|
|
417
|
+
serving_reasoning_effort: servingDecision.reasoningEffort,
|
|
418
|
+
next_model: servingDecision.selectedModel,
|
|
419
|
+
next_reasoning_effort: servingDecision.reasoningEffort,
|
|
420
|
+
selector_error_code: code,
|
|
421
|
+
},
|
|
422
|
+
});
|
|
423
|
+
return { decision: servingDecision };
|
|
424
|
+
}
|
|
425
|
+
}
|
|
426
|
+
function errorMessage(error) {
|
|
427
|
+
return error instanceof Error ? error.message : String(error);
|
|
428
|
+
}
|
|
429
|
+
function configuredPrimaryRetries(value) {
|
|
430
|
+
const retries = value ?? 1;
|
|
431
|
+
return Number.isInteger(retries) && retries >= 0 && retries <= 5 ? retries : 1;
|
|
432
|
+
}
|
|
433
|
+
function fallbackForPrimary(prepared, primary, selected) {
|
|
434
|
+
if (prepared.credentials.model_fallback_enabled === false)
|
|
435
|
+
return undefined;
|
|
436
|
+
const fallback = [selected.fallbackDecision, selected.decision].find((candidate) => candidate !== undefined &&
|
|
437
|
+
candidate.selectedModel !== primary.selectedModel);
|
|
438
|
+
if (!fallback || selected.decision.leaseTurnsRemaining === undefined) {
|
|
439
|
+
return fallback;
|
|
440
|
+
}
|
|
441
|
+
return {
|
|
442
|
+
...fallback,
|
|
443
|
+
leaseTurnsRemaining: selected.decision.leaseTurnsRemaining,
|
|
444
|
+
};
|
|
445
|
+
}
|
|
446
|
+
function providerChoice(prepared, decision, role) {
|
|
447
|
+
return {
|
|
448
|
+
decision,
|
|
449
|
+
execution: providerExecution(prepared, decision),
|
|
450
|
+
role,
|
|
451
|
+
};
|
|
452
|
+
}
|
|
453
|
+
function providerExecution(prepared, decision) {
|
|
454
|
+
return prepareProviderExecution({
|
|
455
|
+
decision,
|
|
456
|
+
credentials: prepared.credentials,
|
|
457
|
+
billable: prepared.billable,
|
|
458
|
+
routerId: prepared.routerId,
|
|
459
|
+
pricing: prepared.routing.pricing,
|
|
460
|
+
conversationId: prepared.routing.conversationId,
|
|
461
|
+
costEstimates: prepared.routing.reportingCostEstimates,
|
|
462
|
+
promptCacheKey: prepared.interaction.promptCacheKey,
|
|
463
|
+
tags: prepared.tags,
|
|
464
|
+
});
|
|
465
|
+
}
|
|
466
|
+
function tokenCount(value) {
|
|
467
|
+
return typeof value === "number" && Number.isFinite(value)
|
|
468
|
+
? Math.max(0, Math.trunc(value))
|
|
469
|
+
: 0;
|
|
470
|
+
}
|
|
471
|
+
function runtimeResult(result, prepared) {
|
|
472
|
+
const decision = result.choice.decision;
|
|
473
|
+
const chain = prepared.routing.prefix.chainByModel.get(decision.selectedModel);
|
|
474
|
+
const target = prepared.routing.targetsByModel.get(decision.selectedModel);
|
|
475
|
+
const usage = result.output.usage;
|
|
476
|
+
const inputTokens = tokenCount(usage.input);
|
|
477
|
+
const cacheReadTokens = tokenCount(usage.cacheRead);
|
|
478
|
+
const cacheWriteTokens = tokenCount(usage.cacheWrite);
|
|
479
|
+
const outputTokens = tokenCount(usage.output);
|
|
480
|
+
const benchmarkReplay = estimateBenchmarkReplay({
|
|
481
|
+
enabledModels: prepared.credentials.enabled_models,
|
|
482
|
+
modelPrices: prepared.credentials.model_prices ?? {},
|
|
483
|
+
executionProvider: (model) => executionProviderForModel(prepared.credentials, model),
|
|
484
|
+
priorHit: prepared.routing.identityHit,
|
|
485
|
+
receivedAtMs: prepared.receivedAt.getTime(),
|
|
486
|
+
promptTokens: inputTokens + cacheReadTokens + cacheWriteTokens,
|
|
487
|
+
outputTokens,
|
|
488
|
+
});
|
|
489
|
+
const completedPrefix = chain === undefined || target === undefined
|
|
490
|
+
? null
|
|
491
|
+
: buildCompletedPrefixHit({
|
|
492
|
+
request: prepared.interaction,
|
|
493
|
+
output: result.output,
|
|
494
|
+
model: decision.selectedModel,
|
|
495
|
+
nextModel: decision.selectedModel,
|
|
496
|
+
nextReasoningEffort: decision.reasoningEffort,
|
|
497
|
+
reasoningBucket: decision.reasoningEffort,
|
|
498
|
+
leaseTurnsRemaining: decision.leaseTurnsRemaining ?? null,
|
|
499
|
+
reason: decision.reason,
|
|
500
|
+
chain,
|
|
501
|
+
looseChain: prepared.routing.prefix.looseChain,
|
|
502
|
+
target,
|
|
503
|
+
conversationId: prepared.routing.conversationId,
|
|
504
|
+
leaseDepth: prepared.routing.leaseDepth,
|
|
505
|
+
providerBlockDepth: prepared.routing.providerBlockDepthFor(decision.selectedModel),
|
|
506
|
+
fingerprints: prepared.routing.prefix.fingerprints,
|
|
507
|
+
usage,
|
|
508
|
+
benchmarkReplayDepth: benchmarkReplay.depth,
|
|
509
|
+
});
|
|
510
|
+
return {
|
|
511
|
+
routing: decision,
|
|
512
|
+
output: result.output,
|
|
513
|
+
...(completedPrefix === null
|
|
514
|
+
? {}
|
|
515
|
+
: { prefixHit: { ...completedPrefix, updated_at: new Date().toISOString() } }),
|
|
516
|
+
};
|
|
517
|
+
}
|
|
518
|
+
const inProcessProtocol = {
|
|
519
|
+
responseBody: (args) => ({
|
|
520
|
+
id: args.id,
|
|
521
|
+
model: args.model,
|
|
522
|
+
output: args.output,
|
|
523
|
+
usage: args.output.usage,
|
|
524
|
+
dari_routing: {
|
|
525
|
+
selected_model: args.routing.selectedModel,
|
|
526
|
+
reasoning_effort: args.routing.reasoningEffort,
|
|
527
|
+
reason: args.routing.reason,
|
|
528
|
+
request_id: args.id,
|
|
529
|
+
...(args.conversationId ? { conversation_id: args.conversationId } : {}),
|
|
530
|
+
},
|
|
531
|
+
}),
|
|
532
|
+
streamBody: () => {
|
|
533
|
+
throw new HttpError(400, "In-process routed runtime results only support non-streaming interactions.", "streaming_not_supported");
|
|
534
|
+
},
|
|
535
|
+
};
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { type ChatMessage, type PreviousDecision, type RoutingDecision } from "@mupt-ai/dari-router/policy-engine";
|
|
2
|
+
import type { SelectorBackend } from "../strategies/routing.js";
|
|
3
|
+
import { type RoutedDecision } from "../strategies/route_decision.js";
|
|
4
|
+
import type { PreparedRoutedCompletion } from "./prepare_routed_completion.js";
|
|
5
|
+
export type RoutingLeaseDecision = {
|
|
6
|
+
decision: RoutingDecision;
|
|
7
|
+
completedTurns: number;
|
|
8
|
+
turnInLease: number;
|
|
9
|
+
};
|
|
10
|
+
export declare function leasedRoutingDecision(args: {
|
|
11
|
+
messages: ChatMessage[];
|
|
12
|
+
previousDecision?: PreviousDecision;
|
|
13
|
+
}): RoutingLeaseDecision | null;
|
|
14
|
+
export declare function leasedDecision(prepared: PreparedRoutedCompletion): RoutedDecision | null;
|
|
15
|
+
export declare function committedLeaseDecision(prepared: PreparedRoutedCompletion, decision: RoutingDecision): RoutedDecision;
|
|
16
|
+
export declare function leaseFallbackDecision(args: {
|
|
17
|
+
candidates: PreparedRoutedCompletion["routing"]["candidateResolution"]["candidates"];
|
|
18
|
+
decision: RoutingDecision;
|
|
19
|
+
credentials: PreparedRoutedCompletion["credentials"];
|
|
20
|
+
}): RoutingDecision | undefined;
|
|
21
|
+
export declare function selectorNegotiatesLeases(backend: SelectorBackend): Promise<boolean>;
|
|
22
|
+
export declare function prefetchNextLease(prepared: PreparedRoutedCompletion, selectorBackend: SelectorBackend): Promise<void>;
|
|
23
|
+
export declare function leasePrefetchDue(prepared: PreparedRoutedCompletion): boolean;
|
|
24
|
+
export declare function clearPendingLease(prepared: PreparedRoutedCompletion): Promise<void>;
|
|
25
|
+
export declare function pendingLeaseDecision(prepared: PreparedRoutedCompletion): RoutingDecision | null;
|
|
26
|
+
export declare function leaseHoldDecision(prepared: PreparedRoutedCompletion): RoutingDecision | null;
|