@mupt-ai/dari-gateway 0.1.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/README.md +8 -1
- 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 +22 -5
- package/src/bun.ts +4 -0
- 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 +17 -17
- 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 +10 -9
- 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 +10 -10
- 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/interaction/types.ts +3 -0
- 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 +36 -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 +115 -41
- package/src/providers/pi_context.ts +6 -6
- package/src/providers/pi_options.ts +283 -453
- package/src/providers/pi_output.ts +6 -5
- package/src/providers/provider_attempt_runner.ts +1 -1
- package/src/providers/provider_call.ts +37 -18
- package/src/providers/provider_reported_cost.ts +138 -0
- package/src/providers/reasoning.ts +2 -2
- package/src/providers/stream_finalization.ts +10 -10
- 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 +31 -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 +46 -10
- package/src/runtime/provider_stream_lifecycle.ts +1 -1
- package/src/runtime/provider_stream_outcome.ts +2 -2
- package/src/runtime/request_tags.ts +34 -0
- package/src/runtime/routed_completion.ts +13 -11
- package/src/runtime/routed_protocol.ts +2 -2
- package/src/runtime/routed_runtime.ts +38 -20
- package/src/runtime/routing_lease.ts +7 -7
- package/src/runtime/runtime_reporter.ts +3 -3
- package/src/self_host/main.ts +19 -14
- package/src/self_host/platform.ts +5 -5
- package/src/self_host/prefix_store.ts +2 -2
- package/src/self_host/resolve.ts +11 -11
- 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 +11 -11
- 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 +30 -25
- 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 +9 -5
- package/src/types.ts +15 -0
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { isRecord } from "@mupt-ai/dari-router/policy-engine";
|
|
2
2
|
|
|
3
|
-
import { HttpError } from "../http/errors";
|
|
4
|
-
import { providerToolCallIdentity, toolsByWireName } from "../interaction/tool_identity";
|
|
5
|
-
import { isAnthropicEffort } from "../interaction/provider_continuation_state";
|
|
6
|
-
import { isBedrockApi, isOpenAIResponsesApi } from "./model_capabilities";
|
|
3
|
+
import { HttpError } from "../http/errors.js";
|
|
4
|
+
import { providerToolCallIdentity, toolsByWireName } from "../interaction/tool_identity.js";
|
|
5
|
+
import { isAnthropicEffort } from "../interaction/provider_continuation_state.js";
|
|
6
|
+
import { isBedrockApi, isOpenAIResponsesApi } from "./model_capabilities.js";
|
|
7
7
|
import type {
|
|
8
8
|
InteractionItem,
|
|
9
9
|
InteractionOutput,
|
|
@@ -13,7 +13,7 @@ import type {
|
|
|
13
13
|
ProviderContinuationState,
|
|
14
14
|
ProviderIdentity,
|
|
15
15
|
ToolKind,
|
|
16
|
-
} from "../interaction/types";
|
|
16
|
+
} from "../interaction/types.js";
|
|
17
17
|
|
|
18
18
|
export function piMessageToInteractionOutput(
|
|
19
19
|
message: Record<string, unknown>,
|
|
@@ -465,6 +465,7 @@ function interactionUsage(value: unknown, source: ProviderIdentity): Interaction
|
|
|
465
465
|
? calculatedTotalCost
|
|
466
466
|
: finiteNumber(cost.total) ?? calculatedTotalCost,
|
|
467
467
|
},
|
|
468
|
+
...(usage.costSource === "provider" ? { costSource: "provider" as const } : {}),
|
|
468
469
|
};
|
|
469
470
|
}
|
|
470
471
|
|
|
@@ -8,44 +8,46 @@ import {
|
|
|
8
8
|
type RoutingDecision,
|
|
9
9
|
} from "@mupt-ai/dari-router/policy-engine";
|
|
10
10
|
|
|
11
|
-
import { executionProviderForModel, keySourceForModel } from "../models/execution_provider";
|
|
12
|
-
import { HttpError } from "../http/errors";
|
|
13
|
-
import type {
|
|
11
|
+
import { executionProviderForModel, keySourceForModel } from "../models/execution_provider.js";
|
|
12
|
+
import { HttpError } from "../http/errors.js";
|
|
13
|
+
import type { RequestTags } from "../platform/platform.js";
|
|
14
|
+
import type { InteractionRequest, ProviderIdentity } from "../interaction/types.js";
|
|
14
15
|
import {
|
|
15
16
|
CustomerDisconnectedError,
|
|
16
17
|
createProviderAttemptAbort,
|
|
17
18
|
type ProviderAttemptAbort,
|
|
18
|
-
} from "../runtime/customer_disconnect";
|
|
19
|
+
} from "../runtime/customer_disconnect.js";
|
|
19
20
|
import {
|
|
20
21
|
isProviderFailureMessage,
|
|
21
22
|
providerFailureFromCaught,
|
|
22
23
|
providerFailureFromEvent,
|
|
23
|
-
} from "../runtime/provider_stream_outcome";
|
|
24
|
-
import { providerAuthForSelectedModel } from "../strategies/routing";
|
|
25
|
-
import { scrubSecretValues } from "../telemetry/scrub";
|
|
24
|
+
} from "../runtime/provider_stream_outcome.js";
|
|
25
|
+
import { providerAuthForSelectedModel } from "../strategies/routing.js";
|
|
26
|
+
import { scrubSecretValues } from "../telemetry/scrub.js";
|
|
26
27
|
import {
|
|
27
28
|
usageContextFor,
|
|
28
29
|
type RoutingUsageContext,
|
|
29
|
-
} from "../telemetry/usage";
|
|
30
|
+
} from "../telemetry/usage.js";
|
|
30
31
|
import type {
|
|
31
32
|
ProviderAuth,
|
|
32
33
|
ProviderKeySource,
|
|
33
34
|
ResolvedRouter,
|
|
34
35
|
ResolvedRouterModelConfig,
|
|
35
|
-
} from "../types";
|
|
36
|
-
import { awsRoleCredentials } from "./aws_assume_role";
|
|
36
|
+
} from "../types.js";
|
|
37
|
+
import { awsRoleCredentials } from "./aws_assume_role.js";
|
|
37
38
|
import {
|
|
38
39
|
attachProviderResponseCapture,
|
|
39
40
|
createProviderResponseCapture,
|
|
40
41
|
type ProviderFetch,
|
|
41
42
|
type ProviderResponseCapture,
|
|
42
|
-
} from "./response_capture";
|
|
43
|
+
} from "./response_capture.js";
|
|
43
44
|
import {
|
|
44
45
|
completeInteractionModel,
|
|
45
46
|
streamInteractionModel,
|
|
47
|
+
type ProviderEndpoint,
|
|
46
48
|
type ProviderEventStream,
|
|
47
|
-
} from "./pi";
|
|
48
|
-
import { promptTokenEstimateFor, type PromptTokenEstimate } from "./cancel_estimate";
|
|
49
|
+
} from "./pi.js";
|
|
50
|
+
import { promptTokenEstimateFor, type PromptTokenEstimate } from "./cancel_estimate.js";
|
|
49
51
|
|
|
50
52
|
type ProviderCallConfig = {
|
|
51
53
|
model: string;
|
|
@@ -57,6 +59,8 @@ type ProviderCallConfig = {
|
|
|
57
59
|
sessionId: string;
|
|
58
60
|
reasoningEffort: ReasoningEffort;
|
|
59
61
|
promptEstimate: PromptTokenEstimate | undefined;
|
|
62
|
+
// A platform-supplied endpoint replacing the model's configured one.
|
|
63
|
+
endpoint?: ProviderEndpoint;
|
|
60
64
|
};
|
|
61
65
|
|
|
62
66
|
export type ProviderExecution = ProviderCallConfig & {
|
|
@@ -101,6 +105,7 @@ export function prepareProviderExecution(args: {
|
|
|
101
105
|
conversationId: string;
|
|
102
106
|
promptCacheKey?: string;
|
|
103
107
|
costEstimates?: readonly CandidateCostEstimate[];
|
|
108
|
+
tags?: RequestTags;
|
|
104
109
|
}): ProviderExecution {
|
|
105
110
|
const model = args.decision.selectedModel;
|
|
106
111
|
const promptEstimate = promptTokenEstimateFor(args.costEstimates, model, args.decision.reasoningEffort);
|
|
@@ -109,11 +114,19 @@ export function prepareProviderExecution(args: {
|
|
|
109
114
|
throw new HttpError(400, "The prompt exceeds this model's standard-price context range. Shorten or compact the conversation.", "context_length_exceeded");
|
|
110
115
|
}
|
|
111
116
|
const provider = executionProviderForModel(args.credentials, model);
|
|
112
|
-
const
|
|
113
|
-
const
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
+
const supplied = args.credentials.provider_credentials?.[model];
|
|
118
|
+
const providerKeySource = supplied ? "user" : keySourceForModel(args.credentials, model);
|
|
119
|
+
if (args.credentials.strict === true && providerKeySource === "subscription") {
|
|
120
|
+
throw new HttpError(
|
|
121
|
+
400,
|
|
122
|
+
`Strict routers do not serve '${model}' from a personal subscription.`,
|
|
123
|
+
"strict_subscription_refused",
|
|
124
|
+
"model",
|
|
125
|
+
);
|
|
126
|
+
}
|
|
127
|
+
const auth: ProviderAuth = supplied
|
|
128
|
+
? { type: "bearer", apiKey: supplied.apiKey.trim() }
|
|
129
|
+
: providerAuthForSelectedModel({ selectedModel: model, credentials: args.credentials });
|
|
117
130
|
return {
|
|
118
131
|
model,
|
|
119
132
|
apiKey: auth.type === "bearer" ? auth.apiKey : "",
|
|
@@ -130,6 +143,9 @@ export function prepareProviderExecution(args: {
|
|
|
130
143
|
: args.conversationId,
|
|
131
144
|
reasoningEffort: args.decision.reasoningEffort,
|
|
132
145
|
promptEstimate,
|
|
146
|
+
...(supplied?.baseUrl || supplied?.headers
|
|
147
|
+
? { endpoint: { baseUrl: supplied.baseUrl, headers: supplied.headers } }
|
|
148
|
+
: {}),
|
|
133
149
|
provider,
|
|
134
150
|
providerKeySource,
|
|
135
151
|
...(providerKeySource === "subscription" && args.credentials.attributed_user_id
|
|
@@ -144,6 +160,7 @@ export function prepareProviderExecution(args: {
|
|
|
144
160
|
routerId: args.routerId,
|
|
145
161
|
selectedModel: model,
|
|
146
162
|
keySource: providerKeySource,
|
|
163
|
+
tags: args.tags ?? {},
|
|
147
164
|
}),
|
|
148
165
|
headers: {
|
|
149
166
|
"X-Dari-Selected-Model": model,
|
|
@@ -212,6 +229,7 @@ export async function startProviderStream(args: {
|
|
|
212
229
|
config: args.execution.config,
|
|
213
230
|
sessionId: args.execution.sessionId,
|
|
214
231
|
selectedReasoningEffort: args.execution.reasoningEffort,
|
|
232
|
+
endpoint: args.execution.endpoint,
|
|
215
233
|
signal: customerAbort.signal,
|
|
216
234
|
fetch: responseCapture?.fetch,
|
|
217
235
|
});
|
|
@@ -306,6 +324,7 @@ async function completeProvider(args: {
|
|
|
306
324
|
config: args.execution.config,
|
|
307
325
|
sessionId: args.execution.sessionId,
|
|
308
326
|
selectedReasoningEffort: args.execution.reasoningEffort,
|
|
327
|
+
endpoint: args.execution.endpoint,
|
|
309
328
|
signal: args.signal,
|
|
310
329
|
fetch: args.fetch,
|
|
311
330
|
});
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
import { isRecord } from "@mupt-ai/dari-router/policy-engine";
|
|
2
|
+
|
|
3
|
+
import { gatewayFor } from "../models/gateways.js";
|
|
4
|
+
import { providerFailureFromCaught } from "../runtime/provider_stream_outcome.js";
|
|
5
|
+
import type { ProviderFetch } from "./response_capture.js";
|
|
6
|
+
|
|
7
|
+
// Gateways bill per call and say what they billed: OpenRouter as `usage.cost`
|
|
8
|
+
// on the final chunk, Vercel AI Gateway as `providerMetadata.gateway.cost`.
|
|
9
|
+
// Pi prices usage from model rates and drops both, so the amount is read off
|
|
10
|
+
// the raw response bytes and replaces the priced total.
|
|
11
|
+
|
|
12
|
+
export function reportsProviderCost(model: Record<string, unknown>): boolean {
|
|
13
|
+
return gatewayFor(model.provider) !== undefined;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export type ProviderReportedCostTap = {
|
|
17
|
+
fetch: ProviderFetch;
|
|
18
|
+
cost: () => number | undefined;
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
export function providerReportedCostTap(
|
|
22
|
+
fetch: ProviderFetch = globalThis.fetch,
|
|
23
|
+
): ProviderReportedCostTap {
|
|
24
|
+
let cost: number | undefined;
|
|
25
|
+
return {
|
|
26
|
+
cost: () => cost,
|
|
27
|
+
fetch: async (input, init) => {
|
|
28
|
+
const response = await fetch(input, init);
|
|
29
|
+
if (!response.ok || response.body === null) return response;
|
|
30
|
+
cost = undefined;
|
|
31
|
+
return new Response(
|
|
32
|
+
response.body.pipeThrough(costScanner((value) => {
|
|
33
|
+
cost = value;
|
|
34
|
+
})),
|
|
35
|
+
{ status: response.status, statusText: response.statusText, headers: response.headers },
|
|
36
|
+
);
|
|
37
|
+
},
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export function messageWithProviderReportedCost(
|
|
42
|
+
message: Record<string, unknown>,
|
|
43
|
+
cost: number | undefined,
|
|
44
|
+
): Record<string, unknown> {
|
|
45
|
+
if (cost === undefined) return message;
|
|
46
|
+
// A thrown error (or other record without a stop reason) becomes a failure
|
|
47
|
+
// message first: spreading an Error drops its non-enumerable `message`, and
|
|
48
|
+
// failure handling keeps usage only on messages that stopped in error.
|
|
49
|
+
const base = message.stopReason === undefined
|
|
50
|
+
? { ...providerFailureFromCaught(message), ...(isRecord(message.usage) ? { usage: message.usage } : {}) }
|
|
51
|
+
: message;
|
|
52
|
+
const usage = isRecord(base.usage) ? base.usage : {};
|
|
53
|
+
return {
|
|
54
|
+
...base,
|
|
55
|
+
usage: {
|
|
56
|
+
...usage,
|
|
57
|
+
cost: { ...(isRecord(usage.cost) ? usage.cost : {}), total: cost },
|
|
58
|
+
costSource: "provider",
|
|
59
|
+
},
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
// Aborted and failed calls end in an error event carrying the partial
|
|
64
|
+
// message; it keeps whatever cost the provider reported before the end.
|
|
65
|
+
export async function* eventsWithProviderReportedCost(
|
|
66
|
+
events: AsyncIterable<Record<string, unknown>>,
|
|
67
|
+
tap: ProviderReportedCostTap,
|
|
68
|
+
): AsyncIterable<Record<string, unknown>> {
|
|
69
|
+
for await (const event of events) {
|
|
70
|
+
if (event.type === "done" && isRecord(event.message)) {
|
|
71
|
+
yield { ...event, message: messageWithProviderReportedCost(event.message, tap.cost()) };
|
|
72
|
+
continue;
|
|
73
|
+
}
|
|
74
|
+
if (event.type === "error" && isRecord(event.error)) {
|
|
75
|
+
yield { ...event, error: messageWithProviderReportedCost(event.error, tap.cost()) };
|
|
76
|
+
continue;
|
|
77
|
+
}
|
|
78
|
+
yield event;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
export function reportedCost(body: unknown): number | undefined {
|
|
83
|
+
if (!isRecord(body)) return undefined;
|
|
84
|
+
const gateway = isRecord(body.providerMetadata) && isRecord(body.providerMetadata.gateway)
|
|
85
|
+
? body.providerMetadata.gateway
|
|
86
|
+
: undefined;
|
|
87
|
+
return usd(isRecord(body.usage) ? body.usage.cost : undefined) ?? usd(gateway?.cost);
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
function usd(value: unknown): number | undefined {
|
|
91
|
+
const amount = typeof value === "string" && value.trim() !== "" ? Number(value) : value;
|
|
92
|
+
return typeof amount === "number" && Number.isFinite(amount) && amount >= 0 ? amount : undefined;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
// Reads SSE `data:` lines and plain JSON bodies alike; the last reported
|
|
96
|
+
// amount wins.
|
|
97
|
+
function costScanner(onCost: (cost: number) => void): TransformStream<Uint8Array, Uint8Array> {
|
|
98
|
+
const decoder = new TextDecoder();
|
|
99
|
+
let pending = "";
|
|
100
|
+
let body = "";
|
|
101
|
+
let sse = false;
|
|
102
|
+
const scan = (line: string) => {
|
|
103
|
+
if (!line.startsWith("data:") || !line.includes("cost")) return;
|
|
104
|
+
try {
|
|
105
|
+
const cost = reportedCost(JSON.parse(line.slice("data:".length)));
|
|
106
|
+
if (cost !== undefined) onCost(cost);
|
|
107
|
+
} catch {
|
|
108
|
+
// Not JSON: [DONE] or a keep-alive.
|
|
109
|
+
}
|
|
110
|
+
};
|
|
111
|
+
return new TransformStream({
|
|
112
|
+
transform(chunk, controller) {
|
|
113
|
+
controller.enqueue(chunk);
|
|
114
|
+
const text = decoder.decode(chunk, { stream: true });
|
|
115
|
+
pending += text;
|
|
116
|
+
const lines = pending.split("\n");
|
|
117
|
+
pending = lines.pop() ?? "";
|
|
118
|
+
for (const line of lines) {
|
|
119
|
+
const trimmed = line.trimEnd();
|
|
120
|
+
if (trimmed.startsWith("data:")) sse = true;
|
|
121
|
+
scan(trimmed);
|
|
122
|
+
}
|
|
123
|
+
if (!sse && body.length < 1024 * 1024) body += text;
|
|
124
|
+
},
|
|
125
|
+
flush() {
|
|
126
|
+
const tail = decoder.decode();
|
|
127
|
+
scan((pending + tail).trimEnd());
|
|
128
|
+
body += tail;
|
|
129
|
+
if (sse || !body.includes("cost")) return;
|
|
130
|
+
try {
|
|
131
|
+
const cost = reportedCost(JSON.parse(body));
|
|
132
|
+
if (cost !== undefined) onCost(cost);
|
|
133
|
+
} catch {
|
|
134
|
+
// Not a JSON body.
|
|
135
|
+
}
|
|
136
|
+
},
|
|
137
|
+
});
|
|
138
|
+
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { ReasoningEffort } from "@mupt-ai/dari-router/policy-engine";
|
|
2
|
-
import { HttpError } from "../http/errors";
|
|
3
|
-
import type { InteractionRequest } from "../interaction/types";
|
|
2
|
+
import { HttpError } from "../http/errors.js";
|
|
3
|
+
import type { InteractionRequest } from "../interaction/types.js";
|
|
4
4
|
|
|
5
5
|
type ReasoningRequest = Pick<InteractionRequest, "reasoning">;
|
|
6
6
|
|
|
@@ -3,32 +3,32 @@ import type {
|
|
|
3
3
|
RoutingDecision,
|
|
4
4
|
} from "@mupt-ai/dari-router/policy-engine";
|
|
5
5
|
|
|
6
|
-
import type { InteractionRequest, ProviderIdentity } from "../interaction/types";
|
|
6
|
+
import type { InteractionRequest, ProviderIdentity } from "../interaction/types.js";
|
|
7
7
|
import {
|
|
8
8
|
captureOperationalError,
|
|
9
9
|
type OperationalErrorCode,
|
|
10
|
-
} from "../observability/errors";
|
|
11
|
-
import type { ProviderStreamOutcome } from "../runtime/provider_stream_outcome";
|
|
12
|
-
import type { RoutedProtocol } from "../runtime/routed_protocol";
|
|
10
|
+
} from "../observability/errors.js";
|
|
11
|
+
import type { ProviderStreamOutcome } from "../runtime/provider_stream_outcome.js";
|
|
12
|
+
import type { RoutedProtocol } from "../runtime/routed_protocol.js";
|
|
13
13
|
import {
|
|
14
14
|
reportedExecution,
|
|
15
15
|
type FrozenProviderTerminal,
|
|
16
16
|
type ProviderAttemptRecord,
|
|
17
17
|
type ReportableProviderOutcome,
|
|
18
18
|
type RoutedRuntimeReporter,
|
|
19
|
-
} from "../runtime/runtime_reporter";
|
|
20
|
-
import type { ProviderKeySource } from "../types";
|
|
19
|
+
} from "../runtime/runtime_reporter.js";
|
|
20
|
+
import type { ProviderKeySource } from "../types.js";
|
|
21
21
|
import {
|
|
22
22
|
reportRoutingUsage,
|
|
23
23
|
type RoutingUsageContext,
|
|
24
|
-
} from "../telemetry/usage";
|
|
25
|
-
import { customerCanceledProviderMessage } from "../runtime/customer_disconnect";
|
|
24
|
+
} from "../telemetry/usage.js";
|
|
25
|
+
import { customerCanceledProviderMessage } from "../runtime/customer_disconnect.js";
|
|
26
26
|
import {
|
|
27
27
|
estimatedCancelUsage,
|
|
28
28
|
partialInteractionOutput,
|
|
29
29
|
type DeliveredOutput,
|
|
30
30
|
type PromptTokenEstimate,
|
|
31
|
-
} from "./cancel_estimate";
|
|
31
|
+
} from "./cancel_estimate.js";
|
|
32
32
|
|
|
33
33
|
// Structurally a subset of ProviderExecution. The narrowing is deliberate: it
|
|
34
34
|
// keeps apiKey and auth out of the finalizer.
|
|
@@ -138,7 +138,7 @@ async function reportTerminalOnce(
|
|
|
138
138
|
? args.reportBarrier
|
|
139
139
|
: Promise.race([
|
|
140
140
|
args.reportBarrier,
|
|
141
|
-
|
|
141
|
+
new Promise((resolve) => setTimeout(resolve, args.cancelBarrierCapMs ?? CANCEL_REPORT_BARRIER_CAP_MS)),
|
|
142
142
|
]));
|
|
143
143
|
} catch (error) {
|
|
144
144
|
capture(error, "routing_report_barrier_failed");
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { isRecord } from "@mupt-ai/dari-router/policy-engine";
|
|
2
2
|
|
|
3
|
-
import { providerFailureMessage } from "../runtime/provider_stream_outcome";
|
|
4
|
-
import type { ProviderKeySource } from "../types";
|
|
5
|
-
import type { CapturedProviderResponse } from "./response_capture";
|
|
3
|
+
import { providerFailureMessage } from "../runtime/provider_stream_outcome.js";
|
|
4
|
+
import type { ProviderKeySource } from "../types.js";
|
|
5
|
+
import type { CapturedProviderResponse } from "./response_capture.js";
|
|
6
6
|
|
|
7
7
|
export type SubscriptionOAuthProvider = "anthropic_claude_code" | "openai_codex";
|
|
8
8
|
|
|
@@ -4,11 +4,11 @@ import {
|
|
|
4
4
|
type RoutingDecision,
|
|
5
5
|
} from "@mupt-ai/dari-router/policy-engine";
|
|
6
6
|
|
|
7
|
-
import type { RoutedDecision } from "../../strategies/route_decision";
|
|
8
|
-
import { isBackgroundRequest } from "../../interaction/types";
|
|
9
|
-
import { HttpError } from "../../http/errors";
|
|
10
|
-
import { assertCreditAvailableBeforeRouting } from "../../telemetry/usage";
|
|
11
|
-
import type { PreparedRoutedCompletion } from "../prepare_routed_completion";
|
|
7
|
+
import type { RoutedDecision } from "../../strategies/route_decision.js";
|
|
8
|
+
import { isBackgroundRequest } from "../../interaction/types.js";
|
|
9
|
+
import { HttpError } from "../../http/errors.js";
|
|
10
|
+
import { assertCreditAvailableBeforeRouting } from "../../telemetry/usage.js";
|
|
11
|
+
import type { PreparedRoutedCompletion } from "../prepare_routed_completion.js";
|
|
12
12
|
import { leaseFallbackDecision } from "../routing_lease.js";
|
|
13
13
|
|
|
14
14
|
// Explicit background classes bypass the selector and every lease path.
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import type { RoutingCandidate, RoutingDecision } from "@mupt-ai/dari-router/policy-engine";
|
|
2
2
|
|
|
3
|
-
import { HttpError } from "../http/errors";
|
|
4
|
-
import { explicitModelId } from "../protocol/input/router_model";
|
|
5
|
-
import type { RoutedDecision } from "../strategies/route_decision";
|
|
6
|
-
import type { PreparedRoutedCompletion } from "./prepare_routed_completion";
|
|
3
|
+
import { HttpError } from "../http/errors.js";
|
|
4
|
+
import { explicitModelId } from "../protocol/input/router_model.js";
|
|
5
|
+
import type { RoutedDecision } from "../strategies/route_decision.js";
|
|
6
|
+
import type { PreparedRoutedCompletion } from "./prepare_routed_completion.js";
|
|
7
7
|
|
|
8
8
|
/* A request for `dari/model/<id>` is served by exactly that enabled model,
|
|
9
9
|
with no selector, lease, or fallback: the user chose it, like picking a
|
|
@@ -57,3 +57,30 @@ function pickCandidate(
|
|
|
57
57
|
}
|
|
58
58
|
return candidates[0]!;
|
|
59
59
|
}
|
|
60
|
+
|
|
61
|
+
/* A strict router serves only the pinned `dari/model/<id>` at exactly the
|
|
62
|
+
requested thinking level (the model's default when none is sent), and
|
|
63
|
+
refuses everything else instead of substituting. */
|
|
64
|
+
export function strictModelDecision(prepared: PreparedRoutedCompletion): RoutedDecision {
|
|
65
|
+
const modelId = explicitModelId(prepared.interaction.model);
|
|
66
|
+
if (modelId === null) {
|
|
67
|
+
throw new HttpError(
|
|
68
|
+
400,
|
|
69
|
+
"This router is strict: request a pinned model as 'dari/model/<id>'.",
|
|
70
|
+
"strict_model_required",
|
|
71
|
+
"model",
|
|
72
|
+
);
|
|
73
|
+
}
|
|
74
|
+
const { decision } = explicitModelDecision(prepared)!;
|
|
75
|
+
const requested = prepared.interaction.reasoning?.effort
|
|
76
|
+
?? prepared.credentials.model_configs?.[modelId]?.default_thinking_level;
|
|
77
|
+
if (requested !== undefined && requested !== null && decision.reasoningEffort !== requested) {
|
|
78
|
+
throw new HttpError(
|
|
79
|
+
400,
|
|
80
|
+
`Model '${modelId}' cannot serve thinking level '${requested}' on this router.`,
|
|
81
|
+
"thinking_level_unavailable",
|
|
82
|
+
"reasoning_effort",
|
|
83
|
+
);
|
|
84
|
+
}
|
|
85
|
+
return { decision };
|
|
86
|
+
}
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import { isRecord } from "@mupt-ai/dari-router/policy-engine";
|
|
2
2
|
|
|
3
|
-
import { HttpError } from "../../http/errors";
|
|
3
|
+
import { HttpError } from "../../http/errors.js";
|
|
4
4
|
import type {
|
|
5
5
|
AgentRequestClass,
|
|
6
6
|
AgentRequestContext,
|
|
7
7
|
InteractionRequestPurpose,
|
|
8
|
-
} from "../../interaction/types";
|
|
9
|
-
import type { HarnessConversationIdentity } from "./conversation";
|
|
8
|
+
} from "../../interaction/types.js";
|
|
9
|
+
import type { HarnessConversationIdentity } from "./conversation.js";
|
|
10
10
|
|
|
11
11
|
const MAX_ID_CHARS = 200;
|
|
12
12
|
|
|
@@ -3,7 +3,7 @@ export {
|
|
|
3
3
|
scopedHarnessSessionId,
|
|
4
4
|
type HarnessConversationIdentity,
|
|
5
5
|
type HarnessConversationScope,
|
|
6
|
-
} from "./conversation";
|
|
6
|
+
} from "./conversation.js";
|
|
7
7
|
export {
|
|
8
8
|
chatCompletionsConversationIdentity,
|
|
9
9
|
claudeCodeConversationIdentity,
|
|
@@ -11,4 +11,4 @@ export {
|
|
|
11
11
|
codexRequestPurpose,
|
|
12
12
|
codexRequestContext,
|
|
13
13
|
openCodeRequestContext,
|
|
14
|
-
} from "./extract";
|
|
14
|
+
} from "./extract.js";
|
|
@@ -1,24 +1,27 @@
|
|
|
1
1
|
import type { CandidatePruningAudit } from "@mupt-ai/dari-router/policy-engine";
|
|
2
2
|
|
|
3
|
-
import { interactionConversationPrefix } from "../context/interaction_fingerprint";
|
|
3
|
+
import { interactionConversationPrefix } from "../context/interaction_fingerprint.js";
|
|
4
4
|
import {
|
|
5
5
|
buildRoutingContext,
|
|
6
6
|
derivePrefixLookupHashes,
|
|
7
7
|
type ImageCapabilityPrunedModel,
|
|
8
8
|
type RoutingContext,
|
|
9
|
-
} from "../context/routing_context";
|
|
10
|
-
import { isBackgroundRequest, type InteractionRequest } from "../interaction/types";
|
|
11
|
-
import {
|
|
12
|
-
import {
|
|
13
|
-
import {
|
|
14
|
-
import
|
|
15
|
-
import
|
|
16
|
-
import type {
|
|
9
|
+
} from "../context/routing_context.js";
|
|
10
|
+
import { isBackgroundRequest, type InteractionRequest } from "../interaction/types.js";
|
|
11
|
+
import { executionProviderForModel } from "../models/execution_provider.js";
|
|
12
|
+
import { gatewayPlatform, type RequestTags } from "../platform/platform.js";
|
|
13
|
+
import { resolveRouter } from "../strategies/routing.js";
|
|
14
|
+
import { RequestReporter, type ReportedCandidatePruning } from "../telemetry/report.js";
|
|
15
|
+
import { RoutingBillingFinalization } from "../telemetry/billing_finalization.js";
|
|
16
|
+
import type { ClientHarness, ProviderCredential, ResolvedRouter } from "../types.js";
|
|
17
|
+
import { requestTags } from "./request_tags.js";
|
|
18
|
+
import type { RoutedRuntimeReporter } from "./runtime_reporter.js";
|
|
19
|
+
import type { RoutedProtocol } from "./routed_protocol.js";
|
|
17
20
|
import {
|
|
18
21
|
scopedHarnessConversationId,
|
|
19
22
|
scopedHarnessSessionId,
|
|
20
23
|
type HarnessConversationIdentity,
|
|
21
|
-
} from "./harness_identity";
|
|
24
|
+
} from "./harness_identity/index.js";
|
|
22
25
|
|
|
23
26
|
export type PreparedRoutedCompletion = {
|
|
24
27
|
requestId: string;
|
|
@@ -28,6 +31,7 @@ export type PreparedRoutedCompletion = {
|
|
|
28
31
|
protocol: RoutedProtocol;
|
|
29
32
|
credentials: ResolvedRouter;
|
|
30
33
|
billable: boolean;
|
|
34
|
+
tags: RequestTags;
|
|
31
35
|
harnessConversationIdentity?: HarnessConversationIdentity;
|
|
32
36
|
routing: RoutingContext;
|
|
33
37
|
reporter: RoutedRuntimeReporter;
|
|
@@ -42,9 +46,11 @@ export async function prepareRoutedCompletion(args: {
|
|
|
42
46
|
startedMs: number;
|
|
43
47
|
requestId: string;
|
|
44
48
|
clientRequestId: string | null;
|
|
49
|
+
tagsHeader: string | null;
|
|
45
50
|
clientHarness?: ClientHarness;
|
|
46
51
|
harnessConversationIdentity?: HarnessConversationIdentity;
|
|
47
52
|
}): Promise<PreparedRoutedCompletion> {
|
|
53
|
+
const tags = requestTags(args.tagsHeader);
|
|
48
54
|
// Eval relevance draws from the public catalog, which resolve only returns
|
|
49
55
|
// on request.
|
|
50
56
|
const resolveRequest = {
|
|
@@ -119,6 +125,7 @@ export async function prepareRoutedCompletion(args: {
|
|
|
119
125
|
}
|
|
120
126
|
credentials = conversationCredentials;
|
|
121
127
|
}
|
|
128
|
+
credentials = await withProviderCredentials(credentials, args.apiKey);
|
|
122
129
|
const billable = true;
|
|
123
130
|
const routing = await buildRoutingContext({
|
|
124
131
|
routerId: prefixFingerprintRouterId,
|
|
@@ -131,6 +138,7 @@ export async function prepareRoutedCompletion(args: {
|
|
|
131
138
|
const reporter = new RequestReporter({
|
|
132
139
|
requestId: args.requestId,
|
|
133
140
|
clientRequestId: args.clientRequestId,
|
|
141
|
+
tags,
|
|
134
142
|
credentials,
|
|
135
143
|
routerId: canonicalRouterId,
|
|
136
144
|
interaction: args.interaction,
|
|
@@ -168,12 +176,40 @@ export async function prepareRoutedCompletion(args: {
|
|
|
168
176
|
protocol: args.protocol,
|
|
169
177
|
credentials,
|
|
170
178
|
billable,
|
|
179
|
+
tags,
|
|
171
180
|
harnessConversationIdentity: args.harnessConversationIdentity,
|
|
172
181
|
routing,
|
|
173
182
|
reporter,
|
|
174
183
|
};
|
|
175
184
|
}
|
|
176
185
|
|
|
186
|
+
// Ask the platform for each enabled model's credential up front, so provider
|
|
187
|
+
// execution and fallback stay synchronous.
|
|
188
|
+
async function withProviderCredentials(
|
|
189
|
+
credentials: ResolvedRouter,
|
|
190
|
+
apiKey: string,
|
|
191
|
+
): Promise<ResolvedRouter> {
|
|
192
|
+
const platform = gatewayPlatform();
|
|
193
|
+
if (platform.resolveProviderCredential === undefined) return credentials;
|
|
194
|
+
const resolved = await Promise.all(
|
|
195
|
+
credentials.enabled_models.map(async (model) => [
|
|
196
|
+
model,
|
|
197
|
+
await platform.resolveProviderCredential!({
|
|
198
|
+
provider: executionProviderForModel(credentials, model),
|
|
199
|
+
model,
|
|
200
|
+
routerId: credentials.router_id,
|
|
201
|
+
organizationId: credentials.organization_id,
|
|
202
|
+
apiKey,
|
|
203
|
+
}),
|
|
204
|
+
] as const),
|
|
205
|
+
);
|
|
206
|
+
const provider_credentials: Record<string, ProviderCredential> = {};
|
|
207
|
+
for (const [model, credential] of resolved) {
|
|
208
|
+
if (credential?.apiKey.trim()) provider_credentials[model] = credential;
|
|
209
|
+
}
|
|
210
|
+
return { ...credentials, provider_credentials };
|
|
211
|
+
}
|
|
212
|
+
|
|
177
213
|
// Core's cache-aware pruning audit, extended with the context layer's image
|
|
178
214
|
// capability exclusions. The exclusions survive on their own when custom
|
|
179
215
|
// routing produced no core audit (missing config), so the error path keeps
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { isRecord } from "@mupt-ai/dari-router/policy-engine";
|
|
2
|
-
import type { InteractionOutput } from "../interaction/types";
|
|
3
|
-
import { scrubSecrets } from "../telemetry/scrub";
|
|
2
|
+
import type { InteractionOutput } from "../interaction/types.js";
|
|
3
|
+
import { scrubSecrets } from "../telemetry/scrub.js";
|
|
4
4
|
|
|
5
5
|
export type ProviderStreamOutcome =
|
|
6
6
|
| {
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { HttpError } from "../http/errors.js";
|
|
2
|
+
import type { RequestTags } from "../platform/platform.js";
|
|
3
|
+
|
|
4
|
+
const TAGS_MAX_CHARS = 2048;
|
|
5
|
+
const TAGS_MAX_COUNT = 32;
|
|
6
|
+
const TAG_KEY = /^[A-Za-z0-9_.:-]{1,64}$/;
|
|
7
|
+
const TAG_VALUE_MAX_CHARS = 256;
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Parse `X-Dari-Tags: run=r1,trial=3,setting=low` into attribution labels for
|
|
11
|
+
* the platform's request and usage records. Malformed or oversized headers
|
|
12
|
+
* are refused rather than silently dropped, so cost is never misattributed.
|
|
13
|
+
*/
|
|
14
|
+
export function requestTags(header: string | null): RequestTags {
|
|
15
|
+
const tags: RequestTags = {};
|
|
16
|
+
if (header === null || header.trim() === "") return tags;
|
|
17
|
+
if (header.length > TAGS_MAX_CHARS) throw invalidTags(`X-Dari-Tags exceeds ${TAGS_MAX_CHARS} characters.`);
|
|
18
|
+
const pairs = header.split(",");
|
|
19
|
+
if (pairs.length > TAGS_MAX_COUNT) throw invalidTags(`X-Dari-Tags has more than ${TAGS_MAX_COUNT} tags.`);
|
|
20
|
+
for (const pair of pairs) {
|
|
21
|
+
const separator = pair.indexOf("=");
|
|
22
|
+
const key = pair.slice(0, separator).trim();
|
|
23
|
+
const value = pair.slice(separator + 1).trim();
|
|
24
|
+
if (separator < 0 || !TAG_KEY.test(key) || value.length > TAG_VALUE_MAX_CHARS) {
|
|
25
|
+
throw invalidTags("X-Dari-Tags must be comma-separated key=value pairs.");
|
|
26
|
+
}
|
|
27
|
+
tags[key] = value;
|
|
28
|
+
}
|
|
29
|
+
return tags;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
function invalidTags(message: string): HttpError {
|
|
33
|
+
return new HttpError(400, message, "invalid_tags");
|
|
34
|
+
}
|