@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,81 @@
|
|
|
1
|
+
import { isRecord } from "@mupt-ai/dari-router/policy-engine";
|
|
2
|
+
// Claude Code's auto mode asks the Anthropic API to run its dangerous-tool-use
|
|
3
|
+
// classifier server-side, at no charge, by sending `safeguards` with a paired
|
|
4
|
+
// beta. The API answers with `safeguard_results`, keyed by tool_use ID, on the
|
|
5
|
+
// final message_delta. Pi drops both, so the request is patched at the payload
|
|
6
|
+
// boundary and the results are read off the raw SSE bytes. Other providers
|
|
7
|
+
// never see the field; Claude Code then runs its own classifier for that turn.
|
|
8
|
+
export function forwardsAnthropicSafeguards(request, model) {
|
|
9
|
+
return (request.anthropicSafeguards !== undefined &&
|
|
10
|
+
model.provider === "anthropic" &&
|
|
11
|
+
model.api === "anthropic-messages");
|
|
12
|
+
}
|
|
13
|
+
export function payloadWithSafeguards(payload, safeguards) {
|
|
14
|
+
const betas = Array.isArray(payload.betas) ? payload.betas : [];
|
|
15
|
+
return {
|
|
16
|
+
...payload,
|
|
17
|
+
safeguards: safeguards.safeguards,
|
|
18
|
+
betas: [...new Set([...betas, ...safeguards.betas])],
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
export function safeguardResultsTap(fetch = globalThis.fetch) {
|
|
22
|
+
let results;
|
|
23
|
+
return {
|
|
24
|
+
results: () => results,
|
|
25
|
+
fetch: async (input, init) => {
|
|
26
|
+
const response = await fetch(input, init);
|
|
27
|
+
if (!response.ok || response.body === null)
|
|
28
|
+
return response;
|
|
29
|
+
results = undefined;
|
|
30
|
+
return new Response(response.body.pipeThrough(safeguardResultsScanner((value) => {
|
|
31
|
+
results = value;
|
|
32
|
+
})), { status: response.status, statusText: response.statusText, headers: response.headers });
|
|
33
|
+
},
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
export function messageWithSafeguardResults(message, results) {
|
|
37
|
+
return results === undefined ? message : { ...message, safeguardResults: results };
|
|
38
|
+
}
|
|
39
|
+
export async function* eventsWithSafeguardResults(events, tap) {
|
|
40
|
+
for await (const event of events) {
|
|
41
|
+
if (event.type === "done" && isRecord(event.message)) {
|
|
42
|
+
yield { ...event, message: messageWithSafeguardResults(event.message, tap.results()) };
|
|
43
|
+
continue;
|
|
44
|
+
}
|
|
45
|
+
yield event;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
function safeguardResultsScanner(onResults) {
|
|
49
|
+
const decoder = new TextDecoder();
|
|
50
|
+
let pending = "";
|
|
51
|
+
const scan = (line) => {
|
|
52
|
+
if (!line.startsWith("data:") || !line.includes("\"safeguard_results\""))
|
|
53
|
+
return;
|
|
54
|
+
let event;
|
|
55
|
+
try {
|
|
56
|
+
event = JSON.parse(line.slice("data:".length));
|
|
57
|
+
}
|
|
58
|
+
catch {
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
61
|
+
if (isRecord(event) &&
|
|
62
|
+
event.type === "message_delta" &&
|
|
63
|
+
isRecord(event.delta) &&
|
|
64
|
+
Array.isArray(event.delta.safeguard_results)) {
|
|
65
|
+
onResults(event.delta.safeguard_results);
|
|
66
|
+
}
|
|
67
|
+
};
|
|
68
|
+
return new TransformStream({
|
|
69
|
+
transform(chunk, controller) {
|
|
70
|
+
controller.enqueue(chunk);
|
|
71
|
+
pending += decoder.decode(chunk, { stream: true });
|
|
72
|
+
const lines = pending.split("\n");
|
|
73
|
+
pending = lines.pop() ?? "";
|
|
74
|
+
for (const line of lines)
|
|
75
|
+
scan(line.trimEnd());
|
|
76
|
+
},
|
|
77
|
+
flush() {
|
|
78
|
+
scan((pending + decoder.decode()).trimEnd());
|
|
79
|
+
},
|
|
80
|
+
});
|
|
81
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { AwsAssumeRoleProviderAuth, AwsSigV4ProviderAuth, ProviderAuth, ResolvedProviderAuth } from "../types.js";
|
|
2
|
+
export type AssumedRoleCredentials = AwsSigV4ProviderAuth & {
|
|
3
|
+
session_token: string;
|
|
4
|
+
expires_at: number;
|
|
5
|
+
};
|
|
6
|
+
export type AssumeRoleFn = (auth: AwsAssumeRoleProviderAuth) => Promise<AssumedRoleCredentials>;
|
|
7
|
+
export type AwsRoleCredentials = {
|
|
8
|
+
/** Swap an AssumeRole auth for temporary SigV4 credentials; other auth passes through. */
|
|
9
|
+
resolve(auth: ProviderAuth): Promise<ResolvedProviderAuth>;
|
|
10
|
+
/** Temporary credential values already issued for this role, for log scrubbing. */
|
|
11
|
+
secrets(auth: AwsAssumeRoleProviderAuth): string[];
|
|
12
|
+
};
|
|
13
|
+
export declare function createAwsRoleCredentials(deps: {
|
|
14
|
+
assumeRole: AssumeRoleFn;
|
|
15
|
+
now?: () => number;
|
|
16
|
+
}): AwsRoleCredentials;
|
|
17
|
+
export declare const awsRoleCredentials: AwsRoleCredentials;
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
import { AssumeRoleCommand, STSClient } from "@aws-sdk/client-sts";
|
|
2
|
+
import { HttpError } from "../http/errors.js";
|
|
3
|
+
const ROLE_SESSION_NAME = "dari-routing";
|
|
4
|
+
// AssumeRole always goes through this regional STS endpoint. The customer's
|
|
5
|
+
// Bedrock region may be an opt-in region Dari's own account has not enabled,
|
|
6
|
+
// where a regional STS call would fail. Regional endpoints issue v2 tokens
|
|
7
|
+
// that are valid in every region, so the temporary credentials still sign
|
|
8
|
+
// Bedrock requests in the customer's region.
|
|
9
|
+
const STS_REGION = "us-east-1";
|
|
10
|
+
// Re-assume the role this long before the temporary credentials expire so a
|
|
11
|
+
// long Bedrock stream never starts on credentials that lapse mid-request.
|
|
12
|
+
const REFRESH_MARGIN_MS = 5 * 60_000;
|
|
13
|
+
export function createAwsRoleCredentials(deps) {
|
|
14
|
+
const now = deps.now ?? Date.now;
|
|
15
|
+
const issued = new Map();
|
|
16
|
+
// Credentials replaced by a refresh stay scrubbable until they expire:
|
|
17
|
+
// a stream that started before the refresh still signs with them.
|
|
18
|
+
const retired = new Map();
|
|
19
|
+
const inflight = new Map();
|
|
20
|
+
function assume(auth) {
|
|
21
|
+
const key = cacheKey(auth);
|
|
22
|
+
const cached = issued.get(key);
|
|
23
|
+
if (cached && cached.expires_at - now() > REFRESH_MARGIN_MS) {
|
|
24
|
+
return Promise.resolve(cached);
|
|
25
|
+
}
|
|
26
|
+
let pending = inflight.get(key);
|
|
27
|
+
if (!pending) {
|
|
28
|
+
pending = deps.assumeRole(auth)
|
|
29
|
+
.then((credentials) => {
|
|
30
|
+
const previous = issued.get(key);
|
|
31
|
+
if (previous) {
|
|
32
|
+
retired.set(key, [
|
|
33
|
+
...(retired.get(key) ?? []).filter((c) => c.expires_at > now()),
|
|
34
|
+
previous,
|
|
35
|
+
]);
|
|
36
|
+
}
|
|
37
|
+
issued.set(key, credentials);
|
|
38
|
+
return credentials;
|
|
39
|
+
})
|
|
40
|
+
.finally(() => inflight.delete(key));
|
|
41
|
+
inflight.set(key, pending);
|
|
42
|
+
}
|
|
43
|
+
return pending;
|
|
44
|
+
}
|
|
45
|
+
return {
|
|
46
|
+
async resolve(auth) {
|
|
47
|
+
if (auth.type !== "aws_assume_role")
|
|
48
|
+
return auth;
|
|
49
|
+
const { expires_at: _expiresAt, ...credentials } = await assume(auth);
|
|
50
|
+
return credentials;
|
|
51
|
+
},
|
|
52
|
+
secrets(auth) {
|
|
53
|
+
const key = cacheKey(auth);
|
|
54
|
+
const current = issued.get(key);
|
|
55
|
+
const live = [
|
|
56
|
+
...(current ? [current] : []),
|
|
57
|
+
...(retired.get(key) ?? []).filter((c) => c.expires_at > now()),
|
|
58
|
+
];
|
|
59
|
+
return live.flatMap((c) => [c.access_key_id, c.secret_access_key, c.session_token]);
|
|
60
|
+
},
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
function cacheKey(auth) {
|
|
64
|
+
return `${auth.role_arn}\n${auth.external_id}\n${auth.region}`;
|
|
65
|
+
}
|
|
66
|
+
async function stsAssumeRole(auth) {
|
|
67
|
+
const accessKeyId = process.env.DARI_AWS_ASSUME_ROLE_ACCESS_KEY_ID?.trim();
|
|
68
|
+
const secretAccessKey = process.env.DARI_AWS_ASSUME_ROLE_SECRET_ACCESS_KEY?.trim();
|
|
69
|
+
if (!accessKeyId || !secretAccessKey) {
|
|
70
|
+
throw new HttpError(500, "DARI_AWS_ASSUME_ROLE_ACCESS_KEY_ID and DARI_AWS_ASSUME_ROLE_SECRET_ACCESS_KEY are not configured.", "configuration_error");
|
|
71
|
+
}
|
|
72
|
+
const client = new STSClient({
|
|
73
|
+
region: STS_REGION,
|
|
74
|
+
credentials: { accessKeyId, secretAccessKey },
|
|
75
|
+
});
|
|
76
|
+
let result;
|
|
77
|
+
try {
|
|
78
|
+
result = await client.send(new AssumeRoleCommand({
|
|
79
|
+
RoleArn: auth.role_arn,
|
|
80
|
+
ExternalId: auth.external_id,
|
|
81
|
+
RoleSessionName: ROLE_SESSION_NAME,
|
|
82
|
+
}));
|
|
83
|
+
}
|
|
84
|
+
catch (error) {
|
|
85
|
+
const reason = error instanceof Error ? error.message : String(error);
|
|
86
|
+
throw new Error(`AWS AssumeRole for ${auth.role_arn} failed: ${reason}`);
|
|
87
|
+
}
|
|
88
|
+
finally {
|
|
89
|
+
client.destroy();
|
|
90
|
+
}
|
|
91
|
+
const credentials = result.Credentials;
|
|
92
|
+
if (!credentials?.AccessKeyId
|
|
93
|
+
|| !credentials.SecretAccessKey
|
|
94
|
+
|| !credentials.SessionToken
|
|
95
|
+
|| !credentials.Expiration) {
|
|
96
|
+
throw new Error(`AWS AssumeRole for ${auth.role_arn} returned incomplete credentials.`);
|
|
97
|
+
}
|
|
98
|
+
return {
|
|
99
|
+
type: "aws_sigv4",
|
|
100
|
+
access_key_id: credentials.AccessKeyId,
|
|
101
|
+
secret_access_key: credentials.SecretAccessKey,
|
|
102
|
+
session_token: credentials.SessionToken,
|
|
103
|
+
region: auth.region,
|
|
104
|
+
expires_at: credentials.Expiration.getTime(),
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
export const awsRoleCredentials = createAwsRoleCredentials({ assumeRole: stsAssumeRole });
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import type { CandidateCostEstimate, ModelPricing, ReasoningEffort } from "@mupt-ai/dari-router/policy-engine";
|
|
2
|
+
import type { InteractionOutput, InteractionUsage, ProviderIdentity } from "../interaction/types.js";
|
|
3
|
+
/** Prose from current models averages about 4.8 characters per token. */
|
|
4
|
+
export declare const ESTIMATED_CHARS_PER_TOKEN = 4.8;
|
|
5
|
+
export type PromptTokenEstimate = {
|
|
6
|
+
promptTokens: number;
|
|
7
|
+
warmTokens: number;
|
|
8
|
+
};
|
|
9
|
+
export type DeliveredOutput = {
|
|
10
|
+
text: string;
|
|
11
|
+
textChars: number;
|
|
12
|
+
reasoningChars: number;
|
|
13
|
+
};
|
|
14
|
+
export declare const NO_DELIVERED_OUTPUT: DeliveredOutput;
|
|
15
|
+
export declare function promptTokenEstimateFor(estimates: readonly CandidateCostEstimate[] | undefined, model: string, reasoningEffort: ReasoningEffort): PromptTokenEstimate | undefined;
|
|
16
|
+
/** Measure the provider text the protocol actually consumed for the client. */
|
|
17
|
+
export declare function observeDeliveredOutput(events: AsyncIterable<Record<string, unknown>>): {
|
|
18
|
+
events: AsyncIterable<Record<string, unknown>>;
|
|
19
|
+
delivered: () => DeliveredOutput;
|
|
20
|
+
};
|
|
21
|
+
/**
|
|
22
|
+
* Usage for a cancelled attempt: prompt tokens from the selector's estimate,
|
|
23
|
+
* output tokens from the characters delivered before the abort. Reasoning the
|
|
24
|
+
* provider never surfaced is not counted, so the estimate errs in the
|
|
25
|
+
* customer's favor. Cost is zero when the model has no known pricing.
|
|
26
|
+
*/
|
|
27
|
+
export declare function estimatedCancelUsage(args: {
|
|
28
|
+
pricing: ModelPricing | null;
|
|
29
|
+
promptEstimate: PromptTokenEstimate | undefined;
|
|
30
|
+
delivered: DeliveredOutput;
|
|
31
|
+
}): InteractionUsage & {
|
|
32
|
+
estimated: true;
|
|
33
|
+
};
|
|
34
|
+
/**
|
|
35
|
+
* The delivered partial as an assistant turn, so the interrupted request can
|
|
36
|
+
* still write a prefix entry that the follow-up turn may match.
|
|
37
|
+
*/
|
|
38
|
+
export declare function partialInteractionOutput(args: {
|
|
39
|
+
delivered: DeliveredOutput;
|
|
40
|
+
usage: InteractionUsage;
|
|
41
|
+
source: ProviderIdentity;
|
|
42
|
+
createdAtMs: number;
|
|
43
|
+
}): InteractionOutput | null;
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import { pricingForPrompt } from "@mupt-ai/dari-router/policy-engine";
|
|
2
|
+
/** Prose from current models averages about 4.8 characters per token. */
|
|
3
|
+
export const ESTIMATED_CHARS_PER_TOKEN = 4.8;
|
|
4
|
+
const MTOK = 1_000_000;
|
|
5
|
+
const MAX_RETAINED_TEXT_CHARS = 512 * 1024;
|
|
6
|
+
export const NO_DELIVERED_OUTPUT = {
|
|
7
|
+
text: "",
|
|
8
|
+
textChars: 0,
|
|
9
|
+
reasoningChars: 0,
|
|
10
|
+
};
|
|
11
|
+
export function promptTokenEstimateFor(estimates, model, reasoningEffort) {
|
|
12
|
+
const match = estimates?.find((item) => item.model === model && item.reasoning_effort === reasoningEffort) ?? estimates?.find((item) => item.model === model);
|
|
13
|
+
return match
|
|
14
|
+
? { promptTokens: match.est_prompt_tokens, warmTokens: match.warm_tokens }
|
|
15
|
+
: undefined;
|
|
16
|
+
}
|
|
17
|
+
/** Measure the provider text the protocol actually consumed for the client. */
|
|
18
|
+
export function observeDeliveredOutput(events) {
|
|
19
|
+
const state = { text: "", textChars: 0, reasoningChars: 0 };
|
|
20
|
+
async function* observed() {
|
|
21
|
+
for await (const event of events) {
|
|
22
|
+
if (typeof event.delta === "string") {
|
|
23
|
+
if (event.type === "text_delta") {
|
|
24
|
+
state.textChars += event.delta.length;
|
|
25
|
+
if (state.text.length < MAX_RETAINED_TEXT_CHARS) {
|
|
26
|
+
state.text += event.delta.slice(0, MAX_RETAINED_TEXT_CHARS - state.text.length);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
else if (event.type === "thinking_delta") {
|
|
30
|
+
state.reasoningChars += event.delta.length;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
yield event;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
return { events: observed(), delivered: () => ({ ...state }) };
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Usage for a cancelled attempt: prompt tokens from the selector's estimate,
|
|
40
|
+
* output tokens from the characters delivered before the abort. Reasoning the
|
|
41
|
+
* provider never surfaced is not counted, so the estimate errs in the
|
|
42
|
+
* customer's favor. Cost is zero when the model has no known pricing.
|
|
43
|
+
*/
|
|
44
|
+
export function estimatedCancelUsage(args) {
|
|
45
|
+
const cacheRead = Math.max(0, Math.round(args.promptEstimate?.warmTokens ?? 0));
|
|
46
|
+
const input = Math.max(0, Math.round((args.promptEstimate?.promptTokens ?? 0) - cacheRead));
|
|
47
|
+
const output = Math.round((args.delivered.textChars + args.delivered.reasoningChars) /
|
|
48
|
+
ESTIMATED_CHARS_PER_TOKEN);
|
|
49
|
+
const price = pricingForPrompt(args.pricing ?? { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 }, input + cacheRead);
|
|
50
|
+
const cost = {
|
|
51
|
+
input: (input * price.input) / MTOK,
|
|
52
|
+
output: (output * price.output) / MTOK,
|
|
53
|
+
cacheRead: (cacheRead * price.cacheRead) / MTOK,
|
|
54
|
+
cacheWrite: 0,
|
|
55
|
+
total: 0,
|
|
56
|
+
};
|
|
57
|
+
cost.total = cost.input + cost.output + cost.cacheRead;
|
|
58
|
+
return {
|
|
59
|
+
input,
|
|
60
|
+
output,
|
|
61
|
+
cacheRead,
|
|
62
|
+
cacheWrite: 0,
|
|
63
|
+
totalTokens: input + cacheRead + output,
|
|
64
|
+
cost,
|
|
65
|
+
estimated: true,
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* The delivered partial as an assistant turn, so the interrupted request can
|
|
70
|
+
* still write a prefix entry that the follow-up turn may match.
|
|
71
|
+
*/
|
|
72
|
+
export function partialInteractionOutput(args) {
|
|
73
|
+
if (args.delivered.text.length === 0)
|
|
74
|
+
return null;
|
|
75
|
+
return {
|
|
76
|
+
createdAtMs: args.createdAtMs,
|
|
77
|
+
source: args.source,
|
|
78
|
+
items: [
|
|
79
|
+
{
|
|
80
|
+
type: "message",
|
|
81
|
+
role: "assistant",
|
|
82
|
+
content: [{ type: "text", text: args.delivered.text }],
|
|
83
|
+
contentShape: "parts",
|
|
84
|
+
},
|
|
85
|
+
],
|
|
86
|
+
usage: args.usage,
|
|
87
|
+
stopReason: "aborted",
|
|
88
|
+
};
|
|
89
|
+
}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import type { RoutingDecision } from "@mupt-ai/dari-router/policy-engine";
|
|
2
|
+
import { piMessageToInteractionOutput } from "./pi_output.js";
|
|
3
|
+
import type { InteractionRequest } from "../interaction/types.js";
|
|
4
|
+
import { type RoutedRuntimeReporter } from "../runtime/runtime_reporter.js";
|
|
5
|
+
import type { RoutedProtocol } from "../runtime/routed_protocol.js";
|
|
6
|
+
import { type ProviderExecution, type StartedCompletion, type StartedStream } from "./provider_call.js";
|
|
7
|
+
export type ProviderChoice = {
|
|
8
|
+
decision: RoutingDecision;
|
|
9
|
+
execution: ProviderExecution;
|
|
10
|
+
role: "primary" | "fallback";
|
|
11
|
+
};
|
|
12
|
+
export type ResolveFallbackChoice = () => Promise<ProviderChoice | null>;
|
|
13
|
+
export type PreparedStreamExecution = {
|
|
14
|
+
choice: ProviderChoice;
|
|
15
|
+
started: StartedStream;
|
|
16
|
+
attempt: number;
|
|
17
|
+
failedSetupLatencyMs: number;
|
|
18
|
+
};
|
|
19
|
+
export type CompletedNonStreamingExecution = {
|
|
20
|
+
choice: ProviderChoice;
|
|
21
|
+
output: ReturnType<typeof piMessageToInteractionOutput>;
|
|
22
|
+
responseBody: Record<string, unknown>;
|
|
23
|
+
reportBarrierError?: unknown;
|
|
24
|
+
};
|
|
25
|
+
export declare function executeNonStreaming(args: {
|
|
26
|
+
requestId: string;
|
|
27
|
+
interaction: InteractionRequest;
|
|
28
|
+
primary: ProviderChoice;
|
|
29
|
+
primaryRetries: number;
|
|
30
|
+
resolveFallback: ResolveFallbackChoice;
|
|
31
|
+
reporter: RoutedRuntimeReporter;
|
|
32
|
+
protocol: RoutedProtocol;
|
|
33
|
+
startedCompletion?: StartedCompletion;
|
|
34
|
+
reportBarrier?: Promise<unknown>;
|
|
35
|
+
clientSignal?: AbortSignal;
|
|
36
|
+
}): Promise<Response>;
|
|
37
|
+
export declare function completeNonStreaming(args: {
|
|
38
|
+
requestId: string;
|
|
39
|
+
interaction: InteractionRequest;
|
|
40
|
+
primary: ProviderChoice;
|
|
41
|
+
primaryRetries: number;
|
|
42
|
+
resolveFallback: ResolveFallbackChoice;
|
|
43
|
+
reporter: RoutedRuntimeReporter;
|
|
44
|
+
protocol: RoutedProtocol;
|
|
45
|
+
startedCompletion?: StartedCompletion;
|
|
46
|
+
reportBarrier?: Promise<unknown>;
|
|
47
|
+
clientSignal?: AbortSignal;
|
|
48
|
+
}): Promise<CompletedNonStreamingExecution>;
|
|
49
|
+
export declare function prepareStreamingExecution(args: {
|
|
50
|
+
requestId: string;
|
|
51
|
+
interaction: InteractionRequest;
|
|
52
|
+
primary: ProviderChoice;
|
|
53
|
+
primaryRetries: number;
|
|
54
|
+
resolveFallback: ResolveFallbackChoice;
|
|
55
|
+
reporter: RoutedRuntimeReporter;
|
|
56
|
+
startedStream?: StartedStream;
|
|
57
|
+
initialError?: unknown;
|
|
58
|
+
reportBarrier?: Promise<unknown>;
|
|
59
|
+
clientSignal?: AbortSignal;
|
|
60
|
+
}): Promise<PreparedStreamExecution>;
|
|
61
|
+
export declare function executeStreaming(args: {
|
|
62
|
+
requestId: string;
|
|
63
|
+
interaction: InteractionRequest;
|
|
64
|
+
choice: ProviderChoice;
|
|
65
|
+
reporter: RoutedRuntimeReporter;
|
|
66
|
+
protocol: RoutedProtocol;
|
|
67
|
+
startedStream: StartedStream;
|
|
68
|
+
attempt: number;
|
|
69
|
+
failedSetupLatencyMs: number;
|
|
70
|
+
reportBarrier?: Promise<unknown>;
|
|
71
|
+
clientSignal?: AbortSignal;
|
|
72
|
+
}): Promise<Response>;
|