@mupt-ai/dari-router 0.1.0

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.
Files changed (179) hide show
  1. package/LICENSE +202 -0
  2. package/README.md +100 -0
  3. package/dist/anonymous_actions.d.ts +55 -0
  4. package/dist/anonymous_actions.js +277 -0
  5. package/dist/anonymous_actions.js.map +1 -0
  6. package/dist/auto_router.d.ts +10 -0
  7. package/dist/auto_router.js +56 -0
  8. package/dist/auto_router.js.map +1 -0
  9. package/dist/cache_behavior.d.ts +14 -0
  10. package/dist/cache_behavior.js +112 -0
  11. package/dist/cache_behavior.js.map +1 -0
  12. package/dist/cache_scope.d.ts +5 -0
  13. package/dist/cache_scope.js +49 -0
  14. package/dist/cache_scope.js.map +1 -0
  15. package/dist/cache_switch_decision.d.ts +24 -0
  16. package/dist/cache_switch_decision.js +21 -0
  17. package/dist/cache_switch_decision.js.map +1 -0
  18. package/dist/candidate_pruning.d.ts +45 -0
  19. package/dist/candidate_pruning.js +154 -0
  20. package/dist/candidate_pruning.js.map +1 -0
  21. package/dist/candidate_resolution.d.ts +41 -0
  22. package/dist/candidate_resolution.js +111 -0
  23. package/dist/candidate_resolution.js.map +1 -0
  24. package/dist/compatibility.d.ts +22 -0
  25. package/dist/compatibility.js +76 -0
  26. package/dist/compatibility.js.map +1 -0
  27. package/dist/continuation_state.d.ts +36 -0
  28. package/dist/continuation_state.js +249 -0
  29. package/dist/continuation_state.js.map +1 -0
  30. package/dist/cost.d.ts +31 -0
  31. package/dist/cost.js +314 -0
  32. package/dist/cost.js.map +1 -0
  33. package/dist/dari_policy.d.ts +34 -0
  34. package/dist/dari_policy.js +267 -0
  35. package/dist/dari_policy.js.map +1 -0
  36. package/dist/errors.d.ts +7 -0
  37. package/dist/errors.js +14 -0
  38. package/dist/errors.js.map +1 -0
  39. package/dist/fingerprint.d.ts +13 -0
  40. package/dist/fingerprint.js +130 -0
  41. package/dist/fingerprint.js.map +1 -0
  42. package/dist/fixed_turn_cost_config.d.ts +9 -0
  43. package/dist/fixed_turn_cost_config.js +22 -0
  44. package/dist/fixed_turn_cost_config.js.map +1 -0
  45. package/dist/framework_error.d.ts +8 -0
  46. package/dist/framework_error.js +24 -0
  47. package/dist/framework_error.js.map +1 -0
  48. package/dist/framework_lifecycle.d.ts +11 -0
  49. package/dist/framework_lifecycle.js +57 -0
  50. package/dist/framework_lifecycle.js.map +1 -0
  51. package/dist/framework_models.d.ts +3 -0
  52. package/dist/framework_models.js +120 -0
  53. package/dist/framework_models.js.map +1 -0
  54. package/dist/framework_router.d.ts +2 -0
  55. package/dist/framework_router.js +384 -0
  56. package/dist/framework_router.js.map +1 -0
  57. package/dist/framework_streaming.d.ts +26 -0
  58. package/dist/framework_streaming.js +486 -0
  59. package/dist/framework_streaming.js.map +1 -0
  60. package/dist/framework_types.d.ts +272 -0
  61. package/dist/framework_types.js +5 -0
  62. package/dist/framework_types.js.map +1 -0
  63. package/dist/framework_validation.d.ts +7 -0
  64. package/dist/framework_validation.js +169 -0
  65. package/dist/framework_validation.js.map +1 -0
  66. package/dist/index.d.ts +35 -0
  67. package/dist/index.js +38 -0
  68. package/dist/index.js.map +1 -0
  69. package/dist/json.d.ts +10 -0
  70. package/dist/json.js +29 -0
  71. package/dist/json.js.map +1 -0
  72. package/dist/model_ids.d.ts +4 -0
  73. package/dist/model_ids.js +26 -0
  74. package/dist/model_ids.js.map +1 -0
  75. package/dist/pi_context.d.ts +4 -0
  76. package/dist/pi_context.js +206 -0
  77. package/dist/pi_context.js.map +1 -0
  78. package/dist/pi_options.d.ts +3 -0
  79. package/dist/pi_options.js +240 -0
  80. package/dist/pi_options.js.map +1 -0
  81. package/dist/pi_output.d.ts +4 -0
  82. package/dist/pi_output.js +328 -0
  83. package/dist/pi_output.js.map +1 -0
  84. package/dist/pi_reasoning_signature.d.ts +10 -0
  85. package/dist/pi_reasoning_signature.js +33 -0
  86. package/dist/pi_reasoning_signature.js.map +1 -0
  87. package/dist/pi_runtime.d.ts +3 -0
  88. package/dist/pi_runtime.js +155 -0
  89. package/dist/pi_runtime.js.map +1 -0
  90. package/dist/pi_types.d.ts +35 -0
  91. package/dist/pi_types.js +2 -0
  92. package/dist/pi_types.js.map +1 -0
  93. package/dist/portable_reasoning_state.d.ts +7 -0
  94. package/dist/portable_reasoning_state.js +81 -0
  95. package/dist/portable_reasoning_state.js.map +1 -0
  96. package/dist/previous_decision.d.ts +13 -0
  97. package/dist/previous_decision.js +82 -0
  98. package/dist/previous_decision.js.map +1 -0
  99. package/dist/prompts.d.ts +3 -0
  100. package/dist/prompts.js +65 -0
  101. package/dist/prompts.js.map +1 -0
  102. package/dist/protocol_anthropic.d.ts +18 -0
  103. package/dist/protocol_anthropic.js +443 -0
  104. package/dist/protocol_anthropic.js.map +1 -0
  105. package/dist/protocol_openai_chat.d.ts +25 -0
  106. package/dist/protocol_openai_chat.js +503 -0
  107. package/dist/protocol_openai_chat.js.map +1 -0
  108. package/dist/protocol_validation.d.ts +23 -0
  109. package/dist/protocol_validation.js +134 -0
  110. package/dist/protocol_validation.js.map +1 -0
  111. package/dist/route.d.ts +105 -0
  112. package/dist/route.js +226 -0
  113. package/dist/route.js.map +1 -0
  114. package/dist/routing_history.d.ts +7 -0
  115. package/dist/routing_history.js +132 -0
  116. package/dist/routing_history.js.map +1 -0
  117. package/dist/selector_input.d.ts +42 -0
  118. package/dist/selector_input.js +153 -0
  119. package/dist/selector_input.js.map +1 -0
  120. package/dist/selector_parse.d.ts +13 -0
  121. package/dist/selector_parse.js +95 -0
  122. package/dist/selector_parse.js.map +1 -0
  123. package/dist/selector_request.d.ts +26 -0
  124. package/dist/selector_request.js +85 -0
  125. package/dist/selector_request.js.map +1 -0
  126. package/dist/selector_truncation.d.ts +2 -0
  127. package/dist/selector_truncation.js +48 -0
  128. package/dist/selector_truncation.js.map +1 -0
  129. package/dist/selector_wire.d.ts +10 -0
  130. package/dist/selector_wire.js +113 -0
  131. package/dist/selector_wire.js.map +1 -0
  132. package/dist/types.d.ts +152 -0
  133. package/dist/types.js +14 -0
  134. package/dist/types.js.map +1 -0
  135. package/package.json +64 -0
  136. package/src/anonymous_actions.ts +434 -0
  137. package/src/auto_router.ts +95 -0
  138. package/src/cache_behavior.ts +130 -0
  139. package/src/cache_scope.ts +58 -0
  140. package/src/cache_switch_decision.ts +53 -0
  141. package/src/candidate_pruning.ts +257 -0
  142. package/src/candidate_resolution.ts +208 -0
  143. package/src/compatibility.ts +162 -0
  144. package/src/continuation_state.ts +368 -0
  145. package/src/cost.ts +455 -0
  146. package/src/dari_policy.ts +360 -0
  147. package/src/errors.ts +27 -0
  148. package/src/fingerprint.ts +148 -0
  149. package/src/fixed_turn_cost_config.ts +24 -0
  150. package/src/framework_error.ts +38 -0
  151. package/src/framework_lifecycle.ts +74 -0
  152. package/src/framework_models.ts +186 -0
  153. package/src/framework_router.ts +490 -0
  154. package/src/framework_streaming.ts +613 -0
  155. package/src/framework_types.ts +372 -0
  156. package/src/framework_validation.ts +235 -0
  157. package/src/index.ts +37 -0
  158. package/src/json.ts +43 -0
  159. package/src/model_ids.ts +29 -0
  160. package/src/pi_context.ts +251 -0
  161. package/src/pi_options.ts +295 -0
  162. package/src/pi_output.ts +387 -0
  163. package/src/pi_reasoning_signature.ts +41 -0
  164. package/src/pi_runtime.ts +238 -0
  165. package/src/pi_types.ts +71 -0
  166. package/src/portable_reasoning_state.ts +129 -0
  167. package/src/previous_decision.ts +109 -0
  168. package/src/prompts.ts +69 -0
  169. package/src/protocol_anthropic.ts +571 -0
  170. package/src/protocol_openai_chat.ts +645 -0
  171. package/src/protocol_validation.ts +202 -0
  172. package/src/route.ts +490 -0
  173. package/src/routing_history.ts +157 -0
  174. package/src/selector_input.ts +246 -0
  175. package/src/selector_parse.ts +138 -0
  176. package/src/selector_request.ts +130 -0
  177. package/src/selector_truncation.ts +48 -0
  178. package/src/selector_wire.ts +167 -0
  179. package/src/types.ts +231 -0
@@ -0,0 +1,134 @@
1
+ import { RouterFrameworkError } from "./framework_error.js";
2
+ import { isRecord } from "./types.js";
3
+ export function invalidProtocolRequest(message, param) {
4
+ return new RouterFrameworkError("invalid_request", message, "invalid_request", param);
5
+ }
6
+ export function rejectUnknownFields(value, allowed, prefix) {
7
+ const field = Object.keys(value).find((name) => !allowed.includes(name));
8
+ if (field === undefined)
9
+ return;
10
+ const param = prefix ? `${prefix}.${field}` : field;
11
+ throw new RouterFrameworkError("invalid_request", `${param} is not supported by the portable router contract.`, "unsupported_field", param);
12
+ }
13
+ export function validateToolChoice(choice, tools) {
14
+ if (choice === undefined || choice === "none" || choice === "auto")
15
+ return;
16
+ if (tools.length === 0) {
17
+ throw invalidProtocolRequest("tool_choice requires at least one tool.", "tool_choice");
18
+ }
19
+ if (typeof choice !== "string" && !tools.some((tool) => tool.name === choice.name)) {
20
+ throw invalidProtocolRequest(`tool_choice references unknown tool '${choice.name}'.`, "tool_choice");
21
+ }
22
+ }
23
+ // `dari_routing` response metadata, matching the managed Dari platform's wire shape.
24
+ export function dariRoutingPayload(requestedModel, selection) {
25
+ return {
26
+ requested_model: requestedModel,
27
+ selected_model: selection.decision.selectedModel,
28
+ reasoning_effort: selection.decision.reasoningEffort,
29
+ reason: selection.decision.reason,
30
+ };
31
+ }
32
+ export function requiredString(value, param) {
33
+ if (typeof value !== "string" || !value.trim()) {
34
+ throw invalidProtocolRequest(`${param} must be a non-empty string.`, param);
35
+ }
36
+ return value;
37
+ }
38
+ export function optionalString(value, param) {
39
+ if (value === undefined || value === null)
40
+ return undefined;
41
+ if (typeof value !== "string") {
42
+ throw invalidProtocolRequest(`${param} must be a string.`, param);
43
+ }
44
+ return value;
45
+ }
46
+ // Empty and whitespace-only cache keys mean "no cache key": preserving them
47
+ // would make every such request share one lease bucket.
48
+ export function optionalCacheKey(value, param) {
49
+ const cacheKey = optionalString(value, param);
50
+ return cacheKey !== undefined && cacheKey.trim() ? cacheKey : undefined;
51
+ }
52
+ export function optionalNumberInRange(value, param, minimum, maximum) {
53
+ if (value === undefined || value === null)
54
+ return undefined;
55
+ if (typeof value !== "number" ||
56
+ !Number.isFinite(value) ||
57
+ value < minimum ||
58
+ value > maximum) {
59
+ throw invalidProtocolRequest(`${param} must be between ${minimum} and ${maximum}.`, param);
60
+ }
61
+ return value;
62
+ }
63
+ export function positiveInteger(value, param) {
64
+ if (typeof value !== "number" || !Number.isInteger(value) || value <= 0) {
65
+ throw invalidProtocolRequest(`${param} must be a positive integer.`, param);
66
+ }
67
+ return value;
68
+ }
69
+ export function optionalPositiveInteger(value, param) {
70
+ if (value === undefined || value === null)
71
+ return undefined;
72
+ return positiveInteger(value, param);
73
+ }
74
+ export function optionalBoolean(value, param) {
75
+ if (value === undefined || value === null)
76
+ return undefined;
77
+ if (typeof value !== "boolean") {
78
+ throw invalidProtocolRequest(`${param} must be a boolean.`, param);
79
+ }
80
+ return value;
81
+ }
82
+ export function optionalRecord(value, param) {
83
+ if (value === undefined || value === null)
84
+ return undefined;
85
+ if (!isRecord(value)) {
86
+ throw invalidProtocolRequest(`${param} must be an object.`, param);
87
+ }
88
+ return value;
89
+ }
90
+ export function stopSequenceValues(value, param, allowBareString) {
91
+ if (value === undefined || value === null)
92
+ return undefined;
93
+ if (typeof value === "string" && allowBareString)
94
+ return value;
95
+ if (!Array.isArray(value) || value.some((entry) => typeof entry !== "string")) {
96
+ throw invalidProtocolRequest(allowBareString
97
+ ? `${param} must be a string or array of strings.`
98
+ : `${param} must be an array of strings.`, param);
99
+ }
100
+ return value;
101
+ }
102
+ export function isAllEmptyText(parts) {
103
+ return parts.every((part) => part.type === "text" && part.text.length === 0);
104
+ }
105
+ export function prefixedWireId(value, prefix) {
106
+ return (value.startsWith(prefix) ? value : `${prefix}${value.replace(/[^A-Za-z0-9_-]/g, "_")}`)
107
+ .slice(0, 64);
108
+ }
109
+ export function portableTool(fields, options) {
110
+ const name = requiredString(fields.name, `${options.param}.name`);
111
+ if (options.names.has(name)) {
112
+ throw invalidProtocolRequest(`Duplicate tool '${name}'.`, `${options.param}.name`);
113
+ }
114
+ options.names.add(name);
115
+ const schemaParam = `${options.param}.${options.schemaField}`;
116
+ const schema = fields[options.schemaField];
117
+ if (schema === undefined) {
118
+ if (options.schemaRequired) {
119
+ throw invalidProtocolRequest(`${schemaParam} must be an object.`, schemaParam);
120
+ }
121
+ }
122
+ else if (!isRecord(schema)) {
123
+ throw invalidProtocolRequest(`${schemaParam} must be an object.`, schemaParam);
124
+ }
125
+ const description = optionalString(fields.description, `${options.param}.description`);
126
+ const strict = optionalBoolean(fields.strict, `${options.param}.strict`);
127
+ return {
128
+ name,
129
+ ...(description === undefined ? {} : { description }),
130
+ inputSchema: schema ?? { type: "object" },
131
+ ...(strict === undefined ? {} : { strict }),
132
+ };
133
+ }
134
+ //# sourceMappingURL=protocol_validation.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"protocol_validation.js","sourceRoot":"","sources":["../src/protocol_validation.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,105 @@
1
+ import { type CandidateMetadataLookup } from "./compatibility.js";
2
+ import { type CandidatePromptEstimate, type PricingLookup } from "./cost.js";
3
+ import type { ReasoningCacheScopeLookup } from "./cache_scope.js";
4
+ import { type ActiveLease, type PendingLease } from "./previous_decision.js";
5
+ import { type StrategyCandidateResolution } from "./candidate_resolution.js";
6
+ import { type BuiltSelectorRequest } from "./selector_request.js";
7
+ import type { CandidateCostEstimate, ChainHits, ChatCompletionRequest, ChatMessage, CustomRouterConfig, HardCapability, PrefixHit, PreviousDecision, ReasoningEffort, RouterEval, RouterModelPrice, RouterPrefixHit, RoutingDecision, RoutingStrategy } from "./types.js";
8
+ export type RoutePreparationWarning = {
9
+ phase: "cost_estimation";
10
+ error: unknown;
11
+ };
12
+ export type CandidatePromptAnchor = {
13
+ hash: string;
14
+ depth: number;
15
+ };
16
+ export type CandidatePromptAccounting = {
17
+ anchorSemantics: "matched_prefix" | "stored_input";
18
+ defaultBlockDepth: number;
19
+ providerBlockDepthFor: (model: string) => number;
20
+ promptEstimateFor: (model: string, anchor?: CandidatePromptAnchor) => CandidatePromptEstimate;
21
+ };
22
+ export type LegacyTailCharsFor = (model: string, hash: string) => number | undefined;
23
+ type CandidatePreparationSharedInput = {
24
+ candidateModels: string[];
25
+ metadataLookup: CandidateMetadataLookup;
26
+ requiredCapabilities: readonly HardCapability[];
27
+ requestedReasoningEffort?: ReasoningEffort;
28
+ thinkingEnabled?: boolean;
29
+ toolChoice?: unknown;
30
+ modelThinkingLevels?: Readonly<Record<string, ReasoningEffort[]>>;
31
+ strategy: RoutingStrategy;
32
+ customConfig?: CustomRouterConfig | null;
33
+ modelPrices?: Record<string, RouterModelPrice>;
34
+ pricing: PricingLookup;
35
+ averageOutputTokensByModel?: Readonly<Record<string, Partial<Record<ReasoningEffort, number>> | null>>;
36
+ chainsByModel: ReadonlyMap<string, string[]>;
37
+ prefixHits?: RouterPrefixHit[];
38
+ nowMs: number;
39
+ looseChain?: readonly string[];
40
+ toolChoiceFp: string;
41
+ responseFormatFp: string;
42
+ previousDecision?: PreviousDecision;
43
+ cacheScope?: ReasoningCacheScopeLookup;
44
+ };
45
+ export type CandidatePreparationInput = CandidatePreparationSharedInput & ({
46
+ promptAccounting: CandidatePromptAccounting;
47
+ messages?: never;
48
+ tailCharsFor?: never;
49
+ } | {
50
+ promptAccounting?: undefined;
51
+ messages: ChatMessage[];
52
+ tailCharsFor?: LegacyTailCharsFor;
53
+ });
54
+ export type CandidatePreparation = {
55
+ blockDepth: number;
56
+ hits: ChainHits;
57
+ conversationId: string | null;
58
+ identityMatchDepth: number | null;
59
+ identityHit?: PrefixHit;
60
+ previousDecision?: PreviousDecision;
61
+ activeLease?: ActiveLease;
62
+ pendingLease?: PendingLease;
63
+ costEstimates: CandidateCostEstimate[];
64
+ candidateResolution: StrategyCandidateResolution;
65
+ warnings: RoutePreparationWarning[];
66
+ };
67
+ export declare function prepareCandidates(input: CandidatePreparationInput): CandidatePreparation;
68
+ export type RouteFallbackConfig = {
69
+ enabled: boolean;
70
+ requiresDifferentProvider: boolean;
71
+ };
72
+ type RouteAccountingInput = {
73
+ promptAccounting: CandidatePromptAccounting;
74
+ tailCharsFor?: never;
75
+ } | {
76
+ promptAccounting?: undefined;
77
+ tailCharsFor?: LegacyTailCharsFor;
78
+ };
79
+ export type RouteInput = CandidatePreparationSharedInput & RouteAccountingInput & {
80
+ messages: ChatMessage[];
81
+ evals?: RouterEval[];
82
+ selectorModel: string;
83
+ selectorContextWindowChars: number;
84
+ modelFallbackEnabled?: boolean;
85
+ fallbackRequiresDifferentProvider?: boolean;
86
+ };
87
+ export type PreparedRoute = CandidatePreparation & {
88
+ fallbackConfig: RouteFallbackConfig;
89
+ selectorPreparation: BuiltSelectorRequest | null;
90
+ };
91
+ export declare function prepareRoute(input: RouteInput): PreparedRoute;
92
+ export type RouteResult = {
93
+ decision: RoutingDecision;
94
+ fallbackDecision?: RoutingDecision;
95
+ outputText: string;
96
+ };
97
+ export declare function finalizeRoute(prepared: Pick<PreparedRoute, "candidateResolution" | "fallbackConfig">, selectorOutputText: string): RouteResult;
98
+ export type Selector = {
99
+ select(request: ChatCompletionRequest, signal?: AbortSignal): Promise<string>;
100
+ };
101
+ export declare function route(input: RouteInput, selector: Selector): Promise<RouteResult & {
102
+ prepared: PreparedRoute;
103
+ }>;
104
+ export declare function chatPromptAccounting(messages: ChatMessage[], tailCharsFor?: LegacyTailCharsFor): CandidatePromptAccounting;
105
+ export {};
package/dist/route.js ADDED
@@ -0,0 +1,226 @@
1
+ // Deterministic route preparation and finalization. These compositions call
2
+ // the same phase functions Dari's hosted runtime executes; hosts with
3
+ // interleaved effects (speculative execution, telemetry) may call the phases
4
+ // directly instead.
5
+ import { resolveCompatibleCandidates } from "./compatibility.js";
6
+ import { conversationBlockCount, conversationMessages } from "./fingerprint.js";
7
+ import { deepestIdentityHit, deriveModelChainHits, estimateCandidateCosts, selectPromptAnchor, } from "./cost.js";
8
+ import { warmPrefixHits } from "./cache_behavior.js";
9
+ import { RouterCoreError } from "./errors.js";
10
+ import { activeLeaseFromHit, compatiblePreviousDecision, pendingLeaseFromHit, previousDecisionFromHit, } from "./previous_decision.js";
11
+ import { resolveStrategyCandidates, } from "./candidate_resolution.js";
12
+ import { selectorSafeMessages } from "./selector_input.js";
13
+ import { buildSizedSelectorRequest } from "./selector_request.js";
14
+ import { parseSelectorDecision, validateSelectorDecisions } from "./selector_parse.js";
15
+ import { routingCandidateKey } from "./types.js";
16
+ // Deterministic candidate preparation: eligibility, cache-aware cost
17
+ // estimates, previous-decision resolution, and strategy resolution/pruning.
18
+ // Cost estimation is best-effort: a failure there surfaces as a warning and
19
+ // leaves estimates empty rather than failing the route.
20
+ export function prepareCandidates(input) {
21
+ return prepareCandidatesWithAccounting(input, resolvePromptAccounting(input));
22
+ }
23
+ function prepareCandidatesWithAccounting(input, promptAccounting) {
24
+ const compatible = resolveCompatibleCandidates({
25
+ requiredCapabilities: input.requiredCapabilities,
26
+ requestedReasoningEffort: input.requestedReasoningEffort,
27
+ thinkingEnabled: input.thinkingEnabled,
28
+ toolChoice: input.toolChoice,
29
+ candidateModels: input.candidateModels,
30
+ metadataLookup: input.metadataLookup,
31
+ modelThinkingLevels: input.modelThinkingLevels,
32
+ });
33
+ const blockDepth = promptAccounting.defaultBlockDepth;
34
+ const warnings = [];
35
+ let hits = { perModel: new Map(), perModelBuckets: new Map() };
36
+ let costEstimates = [];
37
+ let previousDecision = compatiblePreviousDecision(input.previousDecision, compatible.candidates);
38
+ let conversationId = null;
39
+ let identityMatchDepth = null;
40
+ let activeLease;
41
+ let pendingLease;
42
+ let identityHit;
43
+ try {
44
+ // Warmth: strict chains over hits still inside the warmth window — cost
45
+ // estimation and the freshness touch must reflect what the provider cache
46
+ // can actually re-read. Identity: either tier over every recent hit — a
47
+ // stale or loose-only match still names the same conversation.
48
+ hits = deriveModelChainHits(input.chainsByModel, warmPrefixHits(input.prefixHits, input.nowMs));
49
+ identityHit = deepestIdentityHit(input.chainsByModel, input.looseChain, input.prefixHits);
50
+ if (identityHit) {
51
+ conversationId = identityHit.entry.conversation_id;
52
+ identityMatchDepth = identityHit.depth;
53
+ previousDecision ??= previousDecisionFromHit(identityHit.entry, compatible.candidates);
54
+ activeLease = activeLeaseFromHit(identityHit.entry, compatible.candidates);
55
+ // The prefetch write lands on whatever rows existed when the policy
56
+ // finished, and later turns append rows without it, so the pending
57
+ // lease is recovered from any recent row of this conversation — but
58
+ // only when the previous lease ran to completion. The final hold turn
59
+ // writes a zero countdown; a fallback-served turn writes none, and its
60
+ // broken commitment must not be resurrected by a stale prefetch.
61
+ if (identityHit.entry.lease_turns_remaining === 0) {
62
+ const matchConversationId = identityHit.entry.conversation_id;
63
+ const conversationHits = (input.prefixHits ?? [])
64
+ .filter((hit) => hit.conversation_id === matchConversationId)
65
+ .sort((left, right) => right.updated_at.localeCompare(left.updated_at));
66
+ for (const hit of conversationHits) {
67
+ pendingLease = pendingLeaseFromHit(hit, compatible.candidates);
68
+ if (pendingLease !== undefined)
69
+ break;
70
+ }
71
+ }
72
+ }
73
+ const promptEstimatesByCandidate = new Map(compatible.candidates.map((candidate) => {
74
+ const anchor = selectPromptAnchor(hits, candidate.model, candidate.reasoningEffort, input.cacheScope);
75
+ const candidateAnchor = promptAnchorFor({
76
+ accounting: promptAccounting,
77
+ // Stored prompt tokens include the previous response-format schema.
78
+ anchor: anchor?.entry.response_format_fp === input.responseFormatFp
79
+ ? anchor
80
+ : undefined,
81
+ chain: input.chainsByModel.get(candidate.model),
82
+ });
83
+ return [
84
+ routingCandidateKey(candidate),
85
+ promptAccounting.promptEstimateFor(candidate.model, candidateAnchor),
86
+ ];
87
+ }));
88
+ costEstimates = estimateCandidateCosts({
89
+ candidates: compatible.candidates,
90
+ hits,
91
+ incomingBlockCount: blockDepth,
92
+ incomingProviderBlockCountFor: promptAccounting.providerBlockDepthFor,
93
+ promptEstimatesByCandidate,
94
+ toolChoiceFp: input.toolChoiceFp,
95
+ responseFormatFp: input.responseFormatFp,
96
+ pricing: input.pricing,
97
+ averageOutputTokensByModel: input.averageOutputTokensByModel,
98
+ cacheScope: input.cacheScope,
99
+ });
100
+ }
101
+ catch (error) {
102
+ warnings.push({ phase: "cost_estimation", error });
103
+ }
104
+ const candidateResolution = resolveStrategyCandidates({
105
+ strategy: input.strategy,
106
+ candidates: compatible.candidates,
107
+ costEstimates,
108
+ previousDecision,
109
+ customConfig: input.customConfig,
110
+ modelPrices: input.modelPrices ?? {},
111
+ });
112
+ return {
113
+ blockDepth,
114
+ hits,
115
+ conversationId,
116
+ identityMatchDepth,
117
+ ...(identityHit !== undefined ? { identityHit } : {}),
118
+ ...(previousDecision !== undefined ? { previousDecision } : {}),
119
+ ...(activeLease !== undefined ? { activeLease } : {}),
120
+ ...(pendingLease !== undefined ? { pendingLease } : {}),
121
+ costEstimates,
122
+ candidateResolution,
123
+ warnings,
124
+ };
125
+ }
126
+ export function prepareRoute(input) {
127
+ const preparation = prepareCandidatesWithAccounting(input, input.promptAccounting
128
+ ?? chatPromptAccounting(input.messages, input.tailCharsFor));
129
+ const resolution = preparation.candidateResolution;
130
+ const fallbackConfig = {
131
+ enabled: input.modelFallbackEnabled !== false,
132
+ requiresDifferentProvider: input.fallbackRequiresDifferentProvider !== false,
133
+ };
134
+ const custom = resolution.strategy === "custom" ? resolution.custom : undefined;
135
+ if (custom === null) {
136
+ return { ...preparation, fallbackConfig, selectorPreparation: null };
137
+ }
138
+ const selectorPreparation = buildSizedSelectorRequest({
139
+ candidates: resolution.candidates,
140
+ evals: input.evals ?? [],
141
+ ...(preparation.previousDecision !== undefined
142
+ ? { previousDecision: preparation.previousDecision }
143
+ : {}),
144
+ costEstimates: resolution.costEstimates,
145
+ ...(custom ? { customRules: custom.rules, defaultTarget: custom.defaultTarget } : {}),
146
+ selectorModel: input.selectorModel,
147
+ contextWindowChars: input.selectorContextWindowChars,
148
+ messages: selectorSafeMessages(input.messages),
149
+ modelFallbackEnabled: fallbackConfig.enabled,
150
+ fallbackRequiresDifferentProvider: fallbackConfig.requiresDifferentProvider,
151
+ });
152
+ return { ...preparation, fallbackConfig, selectorPreparation };
153
+ }
154
+ // Parses and validates the selector's raw output against the prepared
155
+ // candidate set and fallback policy.
156
+ export function finalizeRoute(prepared, selectorOutputText) {
157
+ const parsed = parseSelectorDecision(selectorOutputText);
158
+ validateSelectorDecisions({
159
+ decision: parsed.decision,
160
+ ...(parsed.fallbackDecision !== undefined
161
+ ? { fallbackDecision: parsed.fallbackDecision }
162
+ : {}),
163
+ candidates: prepared.candidateResolution.candidates,
164
+ modelFallbackEnabled: prepared.fallbackConfig.enabled,
165
+ fallbackRequiresDifferentProvider: prepared.fallbackConfig.requiresDifferentProvider,
166
+ });
167
+ return {
168
+ decision: parsed.decision,
169
+ ...(parsed.fallbackDecision !== undefined
170
+ ? { fallbackDecision: parsed.fallbackDecision }
171
+ : {}),
172
+ outputText: selectorOutputText,
173
+ };
174
+ }
175
+ export async function route(input, selector) {
176
+ const prepared = prepareRoute(input);
177
+ if (prepared.selectorPreparation === null) {
178
+ throw new RouterCoreError("configuration", "Router custom rule configuration is missing.", "custom_config_missing");
179
+ }
180
+ const outputText = await selector.select(prepared.selectorPreparation.selectorRequest);
181
+ return { ...finalizeRoute(prepared, outputText), prepared };
182
+ }
183
+ export function chatPromptAccounting(messages, tailCharsFor) {
184
+ const conversation = conversationMessages({ messages });
185
+ const blockDepth = conversationBlockCount({ messages });
186
+ return {
187
+ anchorSemantics: "matched_prefix",
188
+ defaultBlockDepth: blockDepth,
189
+ providerBlockDepthFor: () => blockDepth,
190
+ promptEstimateFor: (model, anchor) => {
191
+ if (anchor) {
192
+ const exact = tailCharsFor?.(model, anchor.hash);
193
+ if (exact !== undefined) {
194
+ return { chars: exact, reusesStoredPromptTokens: true };
195
+ }
196
+ }
197
+ return {
198
+ chars: JSON.stringify(anchor ? conversation.slice(anchor.depth) : messages).length,
199
+ reusesStoredPromptTokens: anchor !== undefined,
200
+ };
201
+ },
202
+ };
203
+ }
204
+ function promptAnchorFor(args) {
205
+ if (!args.anchor)
206
+ return undefined;
207
+ const depth = args.accounting.anchorSemantics === "stored_input"
208
+ ? args.anchor.entry.prompt_anchor_depth
209
+ : args.anchor.depth;
210
+ if (depth === undefined
211
+ || depth === null
212
+ || depth <= 0) {
213
+ return undefined;
214
+ }
215
+ const hash = args.chain?.[depth - 1];
216
+ return hash === undefined ? undefined : { hash, depth };
217
+ }
218
+ function resolvePromptAccounting(input) {
219
+ if (input.promptAccounting)
220
+ return input.promptAccounting;
221
+ if (input.messages) {
222
+ return chatPromptAccounting(input.messages, input.tailCharsFor);
223
+ }
224
+ throw new RouterCoreError("invalid_request", "Candidate preparation requires promptAccounting or messages", "prompt_accounting_required");
225
+ }
226
+ //# sourceMappingURL=route.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"route.js","sourceRoot":"","sources":["../src/route.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ type RoutingHistoryMessage = {
2
+ role?: unknown;
3
+ content?: unknown;
4
+ [key: string]: unknown;
5
+ };
6
+ export declare function compactRoutingHistory<T extends RoutingHistoryMessage>(messages: T[], historyCharBudget: number | undefined): T[];
7
+ export {};
@@ -0,0 +1,132 @@
1
+ // Router-only history compaction shared by production routing and GRPO
2
+ // training. Provider-bound requests keep the complete conversation.
3
+ export function compactRoutingHistory(messages, historyCharBudget) {
4
+ if (historyCharBudget === undefined || messages.length <= 1)
5
+ return messages;
6
+ if (!Number.isSafeInteger(historyCharBudget) || historyCharBudget < 512) {
7
+ throw new Error("GRPO routing history character budget must be an integer of at least 512");
8
+ }
9
+ const first = messages[0];
10
+ const history = messages.slice(1);
11
+ const totalChars = history.reduce((total, message) => total + JSON.stringify(message).length, 0);
12
+ if (totalChars <= historyCharBudget)
13
+ return messages;
14
+ // The final marker embeds omission counts, so budget the tail against a
15
+ // worst-case-width placeholder to keep the result within the char budget.
16
+ const markerContent = (omittedMessages, omittedChars) => `[Router-only compaction omitted ${omittedMessages} earlier messages (~${omittedChars} chars); ` +
17
+ "retained the task and most recent context.]";
18
+ const markerReserve = JSON.stringify({
19
+ role: "system",
20
+ content: markerContent(99_999_999, 999_999_999),
21
+ }).length;
22
+ let remainingChars = historyCharBudget - markerReserve;
23
+ const tail = [];
24
+ for (let index = history.length - 1; index >= 0 && remainingChars > 0; index -= 1) {
25
+ const message = history[index];
26
+ const serializedChars = JSON.stringify(message).length;
27
+ if (serializedChars <= remainingChars) {
28
+ tail.unshift(message);
29
+ remainingChars -= serializedChars;
30
+ continue;
31
+ }
32
+ const compacted = compactRoutingMessage(message, remainingChars);
33
+ if (compacted !== undefined)
34
+ tail.unshift(compacted);
35
+ break;
36
+ }
37
+ // Providers reject tool results whose originating assistant tool_calls
38
+ // message was compacted away, so the retained tail must never lead with one.
39
+ while (tail.length > 0 && tail[0]?.role === "tool") {
40
+ tail.shift();
41
+ }
42
+ const retainedChars = tail.reduce((total, message) => total + JSON.stringify(message).length, 0);
43
+ const marker = {
44
+ role: "system",
45
+ content: markerContent(history.length - tail.length, Math.max(totalChars - retainedChars, 0)),
46
+ };
47
+ return [first, marker, ...tail];
48
+ }
49
+ function compactRoutingMessage(message, maxChars) {
50
+ const content = message.content;
51
+ if (Array.isArray(content)) {
52
+ return compactRoutingMessageParts(message, content, maxChars);
53
+ }
54
+ const text = contentText(content);
55
+ const shell = { ...message, content: "" };
56
+ // Leave room for JSON escaping introduced by the truncation marker.
57
+ const availableChars = maxChars - JSON.stringify(shell).length - 32;
58
+ if (availableChars < 128 || text.length === 0)
59
+ return undefined;
60
+ const compacted = { ...message, content: elideMiddle(text, availableChars) };
61
+ return JSON.stringify(compacted).length <= maxChars ? compacted : undefined;
62
+ }
63
+ function compactRoutingMessageParts(message, content, maxChars) {
64
+ const text = contentText(content);
65
+ const nonTextContent = content.filter((part) => !isTextPart(part));
66
+ const shell = { ...message, content: nonTextContent };
67
+ const shellChars = JSON.stringify(shell).length;
68
+ if (shellChars > maxChars)
69
+ return undefined;
70
+ if (text.length === 0)
71
+ return shell;
72
+ const availableChars = maxChars - shellChars - 32;
73
+ if (availableChars < 128) {
74
+ return nonTextContent.length > 0 ? shell : undefined;
75
+ }
76
+ const textPart = { type: "text", text: elideMiddle(text, availableChars) };
77
+ const compacted = {
78
+ ...message,
79
+ content: compactContentParts(content, textPart),
80
+ };
81
+ if (JSON.stringify(compacted).length <= maxChars)
82
+ return compacted;
83
+ return nonTextContent.length > 0 ? shell : undefined;
84
+ }
85
+ function compactContentParts(content, textPart) {
86
+ let insertedText = false;
87
+ const compacted = [];
88
+ for (const part of content) {
89
+ if (isTextPart(part)) {
90
+ if (!insertedText)
91
+ compacted.push(textPart);
92
+ insertedText = true;
93
+ continue;
94
+ }
95
+ compacted.push(part);
96
+ }
97
+ if (!insertedText)
98
+ compacted.push(textPart);
99
+ return compacted;
100
+ }
101
+ function isTextPart(value) {
102
+ return (typeof value === "object" &&
103
+ value !== null &&
104
+ !Array.isArray(value) &&
105
+ value.type === "text" &&
106
+ typeof value.text === "string");
107
+ }
108
+ function contentText(content) {
109
+ if (typeof content === "string")
110
+ return content;
111
+ if (!Array.isArray(content))
112
+ return "";
113
+ return content
114
+ .flatMap((block) => {
115
+ if (typeof block !== "object" || block === null || Array.isArray(block))
116
+ return [];
117
+ const text = block.text;
118
+ return typeof text === "string" ? [text] : [];
119
+ })
120
+ .join("\n");
121
+ }
122
+ function elideMiddle(value, maxChars) {
123
+ if (value.length <= maxChars)
124
+ return value;
125
+ const marker = "\n...[router history truncated]...\n";
126
+ if (maxChars <= marker.length)
127
+ return value.slice(-maxChars);
128
+ const retainedChars = maxChars - marker.length;
129
+ const prefixChars = Math.floor(retainedChars / 2);
130
+ return `${value.slice(0, prefixChars)}${marker}${value.slice(-(retainedChars - prefixChars))}`;
131
+ }
132
+ //# sourceMappingURL=routing_history.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"routing_history.js","sourceRoot":"","sources":["../src/routing_history.ts"],"names":[],"mappings":"AAAA,uEAAuE;AACvE,oEAAoE;AAQpE,MAAM,UAAU,qBAAqB,CACnC,QAAa,EACb,iBAAqC;IAErC,IAAI,iBAAiB,KAAK,SAAS,IAAI,QAAQ,CAAC,MAAM,IAAI,CAAC;QAAE,OAAO,QAAQ,CAAC;IAC7E,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC,iBAAiB,CAAC,IAAI,iBAAiB,GAAG,GAAG,EAAE,CAAC;QACxE,MAAM,IAAI,KAAK,CAAC,0EAA0E,CAAC,CAAC;IAC9F,CAAC;IACD,MAAM,KAAK,GAAG,QAAQ,CAAC,CAAC,CAAM,CAAC;IAC/B,MAAM,OAAO,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IAClC,MAAM,UAAU,GAAG,OAAO,CAAC,MAAM,CAC/B,CAAC,KAAK,EAAE,OAAO,EAAE,EAAE,CAAC,KAAK,GAAG,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC,MAAM,EAC1D,CAAC,CACF,CAAC;IACF,IAAI,UAAU,IAAI,iBAAiB;QAAE,OAAO,QAAQ,CAAC;IAErD,wEAAwE;IACxE,0EAA0E;IAC1E,MAAM,aAAa,GAAG,CAAC,eAAuB,EAAE,YAAoB,EAAU,EAAE,CAC9E,mCAAmC,eAAe,uBAAuB,YAAY,WAAW;QAChG,6CAA6C,CAAC;IAChD,MAAM,aAAa,GAAG,IAAI,CAAC,SAAS,CAAC;QACnC,IAAI,EAAE,QAAQ;QACd,OAAO,EAAE,aAAa,CAAC,UAAU,EAAE,WAAW,CAAC;KAChD,CAAC,CAAC,MAAM,CAAC;IACV,IAAI,cAAc,GAAG,iBAAiB,GAAG,aAAa,CAAC;IACvD,MAAM,IAAI,GAAQ,EAAE,CAAC;IACrB,KAAK,IAAI,KAAK,GAAG,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,KAAK,IAAI,CAAC,IAAI,cAAc,GAAG,CAAC,EAAE,KAAK,IAAI,CAAC,EAAE,CAAC;QAClF,MAAM,OAAO,GAAG,OAAO,CAAC,KAAK,CAAM,CAAC;QACpC,MAAM,eAAe,GAAG,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC,MAAM,CAAC;QACvD,IAAI,eAAe,IAAI,cAAc,EAAE,CAAC;YACtC,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;YACtB,cAAc,IAAI,eAAe,CAAC;YAClC,SAAS;QACX,CAAC;QACD,MAAM,SAAS,GAAG,qBAAqB,CAAC,OAAO,EAAE,cAAc,CAAC,CAAC;QACjE,IAAI,SAAS,KAAK,SAAS;YAAE,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;QACrD,MAAM;IACR,CAAC;IACD,uEAAuE;IACvE,6EAA6E;IAC7E,OAAO,IAAI,CAAC,MAAM,GAAG,CAAC,IAAI,IAAI,CAAC,CAAC,CAAC,EAAE,IAAI,KAAK,MAAM,EAAE,CAAC;QACnD,IAAI,CAAC,KAAK,EAAE,CAAC;IACf,CAAC;IACD,MAAM,aAAa,GAAG,IAAI,CAAC,MAAM,CAC/B,CAAC,KAAK,EAAE,OAAO,EAAE,EAAE,CAAC,KAAK,GAAG,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC,MAAM,EAC1D,CAAC,CACF,CAAC;IACF,MAAM,MAAM,GAAG;QACb,IAAI,EAAE,QAAQ;QACd,OAAO,EAAE,aAAa,CACpB,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,MAAM,EAC5B,IAAI,CAAC,GAAG,CAAC,UAAU,GAAG,aAAa,EAAE,CAAC,CAAC,CACxC;KACG,CAAC;IACP,OAAO,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC,CAAC;AAClC,CAAC;AAED,SAAS,qBAAqB,CAC5B,OAAU,EACV,QAAgB;IAEhB,MAAM,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC;IAChC,IAAI,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC;QAC3B,OAAO,0BAA0B,CAAC,OAAO,EAAE,OAAO,EAAE,QAAQ,CAAC,CAAC;IAChE,CAAC;IACD,MAAM,IAAI,GAAG,WAAW,CAAC,OAAO,CAAC,CAAC;IAClC,MAAM,KAAK,GAAG,EAAE,GAAG,OAAO,EAAE,OAAO,EAAE,EAAE,EAAE,CAAC;IAC1C,oEAAoE;IACpE,MAAM,cAAc,GAAG,QAAQ,GAAG,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,MAAM,GAAG,EAAE,CAAC;IACpE,IAAI,cAAc,GAAG,GAAG,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,SAAS,CAAC;IAChE,MAAM,SAAS,GAAG,EAAE,GAAG,OAAO,EAAE,OAAO,EAAE,WAAW,CAAC,IAAI,EAAE,cAAc,CAAC,EAAE,CAAC;IAC7E,OAAO,IAAI,CAAC,SAAS,CAAC,SAAS,CAAC,CAAC,MAAM,IAAI,QAAQ,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC;AAC9E,CAAC;AAED,SAAS,0BAA0B,CACjC,OAAU,EACV,OAAkB,EAClB,QAAgB;IAEhB,MAAM,IAAI,GAAG,WAAW,CAAC,OAAO,CAAC,CAAC;IAClC,MAAM,cAAc,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC;IACnE,MAAM,KAAK,GAAG,EAAE,GAAG,OAAO,EAAE,OAAO,EAAE,cAAc,EAAE,CAAC;IACtD,MAAM,UAAU,GAAG,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC;IAChD,IAAI,UAAU,GAAG,QAAQ;QAAE,OAAO,SAAS,CAAC;IAC5C,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,KAAK,CAAC;IAEpC,MAAM,cAAc,GAAG,QAAQ,GAAG,UAAU,GAAG,EAAE,CAAC;IAClD,IAAI,cAAc,GAAG,GAAG,EAAE,CAAC;QACzB,OAAO,cAAc,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC;IACvD,CAAC;IACD,MAAM,QAAQ,GAAG,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,WAAW,CAAC,IAAI,EAAE,cAAc,CAAC,EAAE,CAAC;IAC3E,MAAM,SAAS,GAAG;QAChB,GAAG,OAAO;QACV,OAAO,EAAE,mBAAmB,CAAC,OAAO,EAAE,QAAQ,CAAC;KAChD,CAAC;IACF,IAAI,IAAI,CAAC,SAAS,CAAC,SAAS,CAAC,CAAC,MAAM,IAAI,QAAQ;QAAE,OAAO,SAAS,CAAC;IACnE,OAAO,cAAc,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC;AACvD,CAAC;AAED,SAAS,mBAAmB,CAC1B,OAAkB,EAClB,QAAiC;IAEjC,IAAI,YAAY,GAAG,KAAK,CAAC;IACzB,MAAM,SAAS,GAAc,EAAE,CAAC;IAChC,KAAK,MAAM,IAAI,IAAI,OAAO,EAAE,CAAC;QAC3B,IAAI,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;YACrB,IAAI,CAAC,YAAY;gBAAE,SAAS,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;YAC5C,YAAY,GAAG,IAAI,CAAC;YACpB,SAAS;QACX,CAAC;QACD,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACvB,CAAC;IACD,IAAI,CAAC,YAAY;QAAE,SAAS,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IAC5C,OAAO,SAAS,CAAC;AACnB,CAAC;AAED,SAAS,UAAU,CAAC,KAAc;IAChC,OAAO,CACL,OAAO,KAAK,KAAK,QAAQ;QACzB,KAAK,KAAK,IAAI;QACd,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC;QACpB,KAAiC,CAAC,IAAI,KAAK,MAAM;QAClD,OAAQ,KAAiC,CAAC,IAAI,KAAK,QAAQ,CAC5D,CAAC;AACJ,CAAC;AAED,SAAS,WAAW,CAAC,OAAgB;IACnC,IAAI,OAAO,OAAO,KAAK,QAAQ;QAAE,OAAO,OAAO,CAAC;IAChD,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC;QAAE,OAAO,EAAE,CAAC;IACvC,OAAO,OAAO;SACX,OAAO,CAAC,CAAC,KAAK,EAAE,EAAE;QACjB,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC;YAAE,OAAO,EAAE,CAAC;QACnF,MAAM,IAAI,GAAI,KAAiC,CAAC,IAAI,CAAC;QACrD,OAAO,OAAO,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;IAChD,CAAC,CAAC;SACD,IAAI,CAAC,IAAI,CAAC,CAAC;AAChB,CAAC;AAED,SAAS,WAAW,CAAC,KAAa,EAAE,QAAgB;IAClD,IAAI,KAAK,CAAC,MAAM,IAAI,QAAQ;QAAE,OAAO,KAAK,CAAC;IAC3C,MAAM,MAAM,GAAG,sCAAsC,CAAC;IACtD,IAAI,QAAQ,IAAI,MAAM,CAAC,MAAM;QAAE,OAAO,KAAK,CAAC,KAAK,CAAC,CAAC,QAAQ,CAAC,CAAC;IAC7D,MAAM,aAAa,GAAG,QAAQ,GAAG,MAAM,CAAC,MAAM,CAAC;IAC/C,MAAM,WAAW,GAAG,IAAI,CAAC,KAAK,CAAC,aAAa,GAAG,CAAC,CAAC,CAAC;IAClD,OAAO,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,WAAW,CAAC,GAAG,MAAM,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,aAAa,GAAG,WAAW,CAAC,CAAC,EAAE,CAAC;AACjG,CAAC"}