@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
package/dist/cost.js ADDED
@@ -0,0 +1,314 @@
1
+ // Routing-only cost estimates for comparing candidate models before selection.
2
+ import { ANTHROPIC_LOOKBACK_BLOCKS, CROSS_TOKENIZER_RATIO, isAnthropicFamily, isOpenAiFamily, openAiCachedPrefixTokens, promptCacheProviderForModel, providerCacheableTokens, providerMinCacheTokens, tokenizerFamily, } from "./cache_behavior.js";
3
+ import { reasoningCacheScope } from "./cache_scope.js";
4
+ import { FIXED_TURN_CACHE_HIT_PROBABILITY, FIXED_TURN_COST_PROJECTED_TURNS, } from "./fixed_turn_cost_config.js";
5
+ import { routingCandidateKey } from "./types.js";
6
+ export const CHARS_PER_TOKEN = 4;
7
+ const MTOK = 1_000_000;
8
+ // perModel/perModelBuckets key on raw model-id strings deliberately:
9
+ // entry.model is a verbatim copy of the router's enabled_models entry that
10
+ // served the turn, and candidate lookups use members of the same list, so
11
+ // both sides are byte-identical by construction. Canonicalizing here could
12
+ // merge two distinct custom model ids differing only in provider-prefix case
13
+ // and cross-contaminate their warm prefixes (an unsafe over-claim), whereas
14
+ // raw keying can at worst under-claim warmth if an id is ever re-spelled
15
+ // mid-conversation.
16
+ // Provider-visible chains can differ when one candidate receives compatible
17
+ // opaque continuation state and another sees readable history only. A hit is
18
+ // accepted solely against the chain for the model that originally wrote it;
19
+ // client-declared continuation provenance cannot make another candidate warm.
20
+ export function deriveModelChainHits(chainsByModel, hits) {
21
+ const depthsByModel = new Map([...chainsByModel].map(([model, chain]) => [
22
+ model,
23
+ new Map(chain.map((hash, index) => [hash, index + 1])),
24
+ ]));
25
+ return collectChainHits(hits, (entry) => depthsByModel.get(entry.model)?.get(entry.hash));
26
+ }
27
+ // Conversation identity accepts either hash tier: the strict per-model chain
28
+ // (byte-faithful echoes) or the host's loose chain (clients that drop
29
+ // reasoning payloads or rewrite item ids). Warmth estimation must NOT use
30
+ // this — a loose-only match means the provider-visible bytes diverged, so
31
+ // the cache is cold even though the conversation is the same.
32
+ // Loose hashes are not unique: two transcript twins (identical runs whose
33
+ // bytes differ only in reasoning payloads, item ids, or whitespace) can both
34
+ // match at the same depth. Ties are content-equivalent, but the pick must be
35
+ // deterministic: a strict match (byte-identical, provably this transcript)
36
+ // beats a loose-only one, then the most recently active entry wins.
37
+ export function deepestIdentityHit(chainsByModel, looseChain, hits) {
38
+ const depthsByModel = new Map([...chainsByModel].map(([model, chain]) => [
39
+ model,
40
+ new Map(chain.map((hash, index) => [hash, index + 1])),
41
+ ]));
42
+ const looseDepths = new Map((looseChain ?? []).map((hash, index) => [hash, index + 1]));
43
+ let deepest;
44
+ let deepestStrict = false;
45
+ let deepestUpdatedAtMs = Number.NEGATIVE_INFINITY;
46
+ for (const entry of hits ?? []) {
47
+ const strictDepth = depthsByModel.get(entry.model)?.get(entry.hash) ?? 0;
48
+ const looseDepth = (entry.loose_hash && looseDepths.get(entry.loose_hash)) || 0;
49
+ const depth = Math.max(strictDepth, looseDepth);
50
+ if (depth === 0)
51
+ continue;
52
+ const strict = strictDepth > 0;
53
+ const parsedUpdatedAtMs = Date.parse(entry.updated_at);
54
+ const updatedAtMs = Number.isFinite(parsedUpdatedAtMs)
55
+ ? parsedUpdatedAtMs
56
+ : Number.NEGATIVE_INFINITY;
57
+ const wins = !deepest ||
58
+ depth > deepest.depth ||
59
+ (depth === deepest.depth &&
60
+ (strict !== deepestStrict
61
+ ? strict
62
+ : updatedAtMs > deepestUpdatedAtMs));
63
+ if (wins) {
64
+ deepest = { entry, depth };
65
+ deepestStrict = strict;
66
+ deepestUpdatedAtMs = updatedAtMs;
67
+ }
68
+ }
69
+ return deepest;
70
+ }
71
+ function collectChainHits(hits, depthFor) {
72
+ let deepest;
73
+ const perModel = new Map();
74
+ const perModelBuckets = new Map();
75
+ for (const entry of hits ?? []) {
76
+ const depth = depthFor(entry);
77
+ if (depth === undefined)
78
+ continue;
79
+ const hit = { entry, depth };
80
+ if (!deepest || depth > deepest.depth)
81
+ deepest = hit;
82
+ const existing = perModel.get(entry.model);
83
+ if (!existing || depth > existing.depth)
84
+ perModel.set(entry.model, hit);
85
+ const bucket = entry.reasoning_bucket ?? null;
86
+ let byBucket = perModelBuckets.get(entry.model);
87
+ if (!byBucket) {
88
+ byBucket = new Map();
89
+ perModelBuckets.set(entry.model, byBucket);
90
+ }
91
+ const existingBucketHit = byBucket.get(bucket);
92
+ if (!existingBucketHit || depth > existingBucketHit.depth)
93
+ byBucket.set(bucket, hit);
94
+ }
95
+ return { deepest, perModel, perModelBuckets };
96
+ }
97
+ // The warm-prefix hit a candidate can actually re-read, given how its
98
+ // provider scopes cache identity across reasoning payloads. Shared-scope
99
+ // providers reuse one partition regardless of effort; effort-keyed providers
100
+ // only re-read the partition warmed under the same effective effort, so the
101
+ // hit must come from the matching bucket. Entries written before buckets
102
+ // existed (null) are accepted for any effort so a rollout never estimates a
103
+ // genuinely warm prefix as cold.
104
+ export function selectPrefixHit(hits, model, reasoningBucket, cacheScope = reasoningCacheScope) {
105
+ if (cacheScope(model) === "shared")
106
+ return hits.perModel.get(model);
107
+ const byBucket = hits.perModelBuckets.get(model);
108
+ if (!byBucket)
109
+ return undefined;
110
+ const matched = byBucket.get(reasoningBucket);
111
+ const legacy = byBucket.get(null);
112
+ if (matched)
113
+ return matched;
114
+ return legacy;
115
+ }
116
+ export function selectPromptAnchor(hits, model, reasoningBucket, cacheScope = reasoningCacheScope) {
117
+ // Prompt-token baselines are provider/model-specific. Cross-model hits can
118
+ // recover conversation identity elsewhere, but cannot anchor this model's
119
+ // provider-visible prompt estimate.
120
+ return selectPrefixHit(hits, model, reasoningBucket, cacheScope);
121
+ }
122
+ export function estimateCandidateCosts(args) {
123
+ const cacheScope = args.cacheScope ?? reasoningCacheScope;
124
+ return args.candidates.map((candidate) => {
125
+ const { model, reasoningEffort } = candidate;
126
+ const price = args.pricing(model);
127
+ const anthropicStyle = isAnthropicFamily(model);
128
+ const openAiStyle = isOpenAiFamily(model);
129
+ const promptEstimate = args.promptEstimatesByCandidate.get(routingCandidateKey(candidate));
130
+ if (promptEstimate === undefined) {
131
+ throw new Error(`missing prompt estimate for ${model}/${reasoningEffort}`);
132
+ }
133
+ const anchor = selectPromptAnchor(args.hits, model, reasoningEffort, cacheScope);
134
+ const reusesStoredPromptTokens = promptEstimate.reusesStoredPromptTokens;
135
+ const serializedTokens = Math.ceil(promptEstimate.chars / CHARS_PER_TOKEN);
136
+ const tokenizerReference = anchor ?? args.hits.deepest;
137
+ const crossesTokenizerFamilies = tokenizerReference !== undefined
138
+ && tokenizerFamily(model)
139
+ !== tokenizerFamily(tokenizerReference.entry.model);
140
+ // Candidate-specific serialization captures provider wire-shape
141
+ // differences. Preserve the separate pessimistic margin for tokenizer
142
+ // differences without borrowing the foreign model's measured token count.
143
+ const newTokens = crossesTokenizerFamilies
144
+ ? Math.round(serializedTokens * CROSS_TOKENIZER_RATIO)
145
+ : serializedTokens;
146
+ let estPrompt = newTokens;
147
+ if (anchor && reusesStoredPromptTokens) {
148
+ const knownTokens = anchor.entry.prompt_tokens;
149
+ estPrompt = knownTokens + newTokens;
150
+ }
151
+ const hit = selectPrefixHit(args.hits, model, reasoningEffort, cacheScope);
152
+ let warmTokens = 0;
153
+ if (hit) {
154
+ // tool_choice flips bust Anthropic's message cache but not automatic
155
+ // vendor caches; response_format schemas are prompt content everywhere.
156
+ const fingerprintsMatch = anthropicStyle
157
+ ? hit.entry.tool_choice_fp === args.toolChoiceFp &&
158
+ hit.entry.response_format_fp === args.responseFormatFp
159
+ : hit.entry.response_format_fp === args.responseFormatFp;
160
+ const withinLookback = !anthropicStyle
161
+ || withinAnthropicLookback({
162
+ hit: hit.entry,
163
+ incomingLegacyDepth: args.incomingBlockCount,
164
+ incomingProviderDepth: args.incomingProviderBlockCountFor?.(model),
165
+ });
166
+ // Provider minimums apply to the cached prefix being re-read — this
167
+ // candidate's own hit, counted by its own provider — not to the global
168
+ // prompt estimate (which may anchor on another provider's deeper entry).
169
+ const meetsMinimum = hit.entry.prompt_tokens >= providerMinCacheTokens(model);
170
+ if (fingerprintsMatch && withinLookback && meetsMinimum) {
171
+ warmTokens = openAiStyle
172
+ ? openAiCachedPrefixTokens(hit.entry.prompt_tokens)
173
+ : hit.entry.prompt_tokens;
174
+ }
175
+ }
176
+ // Anchored estimates contain only a fresh suffix; complete-prompt
177
+ // estimates (used for legacy rows without an input depth) already include
178
+ // the warm prefix and must not add it a second time.
179
+ estPrompt = Math.max(estPrompt, reusesStoredPromptTokens ? warmTokens + newTokens : warmTokens);
180
+ // An unanchored hit (for example, a legacy row) leaves only a coarse
181
+ // complete-prompt estimate. If that estimate undercuts the confirmed warm
182
+ // prefix, its fresh/cached split is unknowable. Conservatively charge the
183
+ // coarse estimate as fresh instead of making the fresh portion free.
184
+ if (warmTokens > 0
185
+ && !reusesStoredPromptTokens
186
+ && newTokens <= warmTokens) {
187
+ estPrompt = warmTokens + newTokens;
188
+ }
189
+ let estCost = null;
190
+ if (price) {
191
+ const remainder = Math.max(0, estPrompt - warmTokens);
192
+ estCost =
193
+ (warmTokens * price.cacheRead + remainder * freshInputRate(model, price, estPrompt)) /
194
+ 1_000_000;
195
+ }
196
+ return {
197
+ model,
198
+ reasoning_effort: reasoningEffort,
199
+ warm_tokens: warmTokens,
200
+ est_prompt_tokens: estPrompt,
201
+ est_input_cost_usd: estCost,
202
+ output_cost_per_mtok: price?.output ?? null,
203
+ pricing_known: price !== null,
204
+ fixed_turn_cost_estimate: price
205
+ ? fixedTurnCostEstimate({
206
+ model,
207
+ price,
208
+ estPromptTokens: estPrompt,
209
+ warmTokens,
210
+ reasoningEffort,
211
+ outputTokens: args.averageOutputTokensByModel?.[model]?.[reasoningEffort],
212
+ })
213
+ : null,
214
+ };
215
+ });
216
+ }
217
+ function withinAnthropicLookback(args) {
218
+ const storedProviderDepth = args.hit.provider_block_depth;
219
+ if (storedProviderDepth !== undefined
220
+ && storedProviderDepth !== null) {
221
+ if (args.incomingProviderDepth === undefined)
222
+ return false;
223
+ const delta = args.incomingProviderDepth - storedProviderDepth;
224
+ return delta >= 0 && delta <= ANTHROPIC_LOOKBACK_BLOCKS;
225
+ }
226
+ const delta = args.incomingLegacyDepth - args.hit.block_depth;
227
+ return delta >= 0 && delta <= ANTHROPIC_LOOKBACK_BLOCKS;
228
+ }
229
+ function fixedTurnCostEstimate(args) {
230
+ const provider = promptCacheProviderForModel(args.model);
231
+ if (!provider || args.outputTokens === undefined)
232
+ return null;
233
+ // One pass to the longest horizon, snapshotting the running total at each
234
+ // shorter one: turn N's cost depends on every turn before it, so the
235
+ // horizons are prefixes of the same accumulation rather than separate runs.
236
+ const horizons = [...FIXED_TURN_COST_PROJECTED_TURNS].sort((left, right) => left - right);
237
+ const longestHorizon = horizons[horizons.length - 1] ?? 0;
238
+ const projections = [];
239
+ const outputTokens = args.outputTokens;
240
+ let totalCost = 0;
241
+ for (let turn = 1; turn <= longestHorizon; turn += 1) {
242
+ const inputTokens = args.estPromptTokens + (turn - 1) * outputTokens;
243
+ totalCost +=
244
+ turn === 1
245
+ ? deterministicTurnCost({
246
+ model: args.model,
247
+ price: args.price,
248
+ inputTokens,
249
+ cachedTokens: args.warmTokens,
250
+ outputTokens,
251
+ })
252
+ : laterTurnCost({
253
+ model: args.model,
254
+ price: args.price,
255
+ provider,
256
+ inputTokens,
257
+ // Later requests can only read prefixes that appeared in prior
258
+ // request inputs. The immediately previous output is fresh on the
259
+ // next request.
260
+ reusablePrefix: args.estPromptTokens + (turn - 2) * outputTokens,
261
+ outputTokens,
262
+ });
263
+ if (horizons.includes(turn)) {
264
+ projections.push({ projected_turns: turn, total_cost_usd: totalCost });
265
+ }
266
+ }
267
+ return {
268
+ output_tokens_per_turn: outputTokens,
269
+ assumed_reasoning_effort: args.reasoningEffort,
270
+ projections,
271
+ };
272
+ }
273
+ function laterTurnCost(args) {
274
+ const cacheableTokens = providerCacheableTokens(args.model, args.provider, args.reusablePrefix);
275
+ const missCost = deterministicTurnCost({
276
+ model: args.model,
277
+ price: args.price,
278
+ inputTokens: args.inputTokens,
279
+ cachedTokens: 0,
280
+ outputTokens: args.outputTokens,
281
+ });
282
+ if (cacheableTokens <= 0)
283
+ return missCost;
284
+ const hitCost = deterministicTurnCost({
285
+ model: args.model,
286
+ price: args.price,
287
+ inputTokens: args.inputTokens,
288
+ cachedTokens: cacheableTokens,
289
+ outputTokens: args.outputTokens,
290
+ });
291
+ const hitProbability = FIXED_TURN_CACHE_HIT_PROBABILITY[args.provider];
292
+ return hitCost * hitProbability + missCost * (1 - hitProbability);
293
+ }
294
+ // The loop cost at one horizon, for callers that need a single scalar rather
295
+ // than the whole curve.
296
+ export function turnCostUsdAt(estimate, turns) {
297
+ const projection = estimate?.projections.find((entry) => entry.projected_turns === turns);
298
+ return projection?.total_cost_usd ?? null;
299
+ }
300
+ // A caching provider writes whatever the prompt did not read, and several bill
301
+ // that write above their input rate. An effort-keyed cache partitions on effort,
302
+ // so a switch of either model or effort leaves nothing warm and writes it all.
303
+ function freshInputRate(model, price, promptTokens) {
304
+ return price.cacheWrite > 0 && promptTokens >= providerMinCacheTokens(model)
305
+ ? price.cacheWrite
306
+ : price.input;
307
+ }
308
+ function deterministicTurnCost(args) {
309
+ const freshTokens = args.inputTokens - args.cachedTokens;
310
+ return ((args.cachedTokens * args.price.cacheRead) / MTOK +
311
+ (freshTokens * freshInputRate(args.model, args.price, args.inputTokens)) / MTOK +
312
+ (args.outputTokens * args.price.output) / MTOK);
313
+ }
314
+ //# sourceMappingURL=cost.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cost.js","sourceRoot":"","sources":["../src/cost.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,34 @@
1
+ import type { CandidateModelMetadata } from "./compatibility.js";
2
+ import type { PricingLookup } from "./cost.js";
3
+ import type { RouterCandidate, RoutingPolicy, RoutingPolicyInput } from "./framework_types.js";
4
+ import { type PreparedRoute, type RouteInput, type Selector } from "./route.js";
5
+ import type { ChatCompletionRequest, CustomRouterConfig, RouterEval, RouterModelPrice, RouterPrefixHit } from "./types.js";
6
+ export type DariPolicyState = {
7
+ chainsByModel?: ReadonlyMap<string, string[]>;
8
+ prefixHits?: RouterPrefixHit[];
9
+ looseChain?: readonly string[];
10
+ nowMs?: number;
11
+ toolChoiceFingerprint?: string;
12
+ responseFormatFingerprint?: string;
13
+ };
14
+ export type DariRoutingPolicyOptions<Metadata = unknown> = {
15
+ selector?: Selector | ((request: ChatCompletionRequest, signal: AbortSignal) => Promise<string>);
16
+ runtime?: {
17
+ select(request: ChatCompletionRequest, signal?: AbortSignal): Promise<string>;
18
+ };
19
+ selectorModel: string;
20
+ selectorContextWindowChars: number;
21
+ metadata?: (model: RouterCandidate<Metadata>) => CandidateModelMetadata;
22
+ pricing?: PricingLookup;
23
+ evals?: RouterEval[] | ((input: RoutingPolicyInput<Metadata>) => RouterEval[] | Promise<RouterEval[]>);
24
+ state?: (input: RoutingPolicyInput<Metadata>) => DariPolicyState | Promise<DariPolicyState>;
25
+ strategy?: "slm" | "custom";
26
+ customConfig?: CustomRouterConfig | null;
27
+ modelPrices?: Record<string, RouterModelPrice>;
28
+ averageOutputTokensByModel?: RouteInput["averageOutputTokensByModel"];
29
+ };
30
+ export type DariPolicyDetails = {
31
+ prepared: PreparedRoute;
32
+ selectorOutput: string;
33
+ };
34
+ export declare function createDariRoutingPolicy<Metadata = unknown>(options: DariRoutingPolicyOptions<Metadata>): RoutingPolicy<Metadata>;
@@ -0,0 +1,267 @@
1
+ import { RouterCoreError } from "./errors.js";
2
+ import { RouterFrameworkError } from "./framework_error.js";
3
+ import { optionsFingerprints } from "./fingerprint.js";
4
+ import { finalizeRoute, prepareRoute, } from "./route.js";
5
+ export function createDariRoutingPolicy(options) {
6
+ const selector = options.selector ?? options.runtime;
7
+ if (selector === undefined) {
8
+ throw new RouterFrameworkError("configuration", "Dari routing requires a selector or Pi runtime.", "selector_missing");
9
+ }
10
+ return async (input) => {
11
+ const chatRequest = routerRequestToChat(input.request);
12
+ const state = await options.state?.(input) ?? {};
13
+ const evals = typeof options.evals === "function"
14
+ ? await options.evals(input)
15
+ : options.evals ?? [];
16
+ const fingerprints = optionsFingerprints(chatRequest);
17
+ const candidateModels = input.candidates.map((candidate) => candidate.id);
18
+ const metadataByModel = new Map(input.candidates.map((candidate) => [
19
+ candidate.id,
20
+ options.metadata?.(candidate) ?? defaultDariMetadata(candidate),
21
+ ]));
22
+ let prepared;
23
+ try {
24
+ prepared = prepareRoute({
25
+ candidateModels,
26
+ metadataLookup: (model) => metadataByModel.get(model),
27
+ requiredCapabilities: [],
28
+ ...(input.request.reasoning?.effort === undefined
29
+ ? {}
30
+ : { requestedReasoningEffort: input.request.reasoning.effort }),
31
+ ...(input.request.reasoning?.enabled === undefined
32
+ ? {}
33
+ : { thinkingEnabled: input.request.reasoning.enabled }),
34
+ ...(chatRequest.tool_choice === undefined ? {} : { toolChoice: chatRequest.tool_choice }),
35
+ modelThinkingLevels: Object.fromEntries(input.candidates.map((candidate) => [candidate.id, [...candidate.reasoningEfforts]])),
36
+ strategy: options.strategy ?? "slm",
37
+ ...(options.customConfig === undefined ? {} : { customConfig: options.customConfig }),
38
+ modelPrices: options.modelPrices ?? {},
39
+ pricing: options.pricing ?? (() => null),
40
+ ...(options.averageOutputTokensByModel === undefined
41
+ ? {}
42
+ : { averageOutputTokensByModel: options.averageOutputTokensByModel }),
43
+ messages: chatRequest.messages ?? [],
44
+ chainsByModel: state.chainsByModel ?? new Map(candidateModels.map((model) => [model, []])),
45
+ prefixHits: state.prefixHits ?? [],
46
+ nowMs: state.nowMs ?? Date.now(),
47
+ ...(state.looseChain === undefined ? {} : { looseChain: state.looseChain }),
48
+ toolChoiceFp: state.toolChoiceFingerprint ?? fingerprints.tool_choice_fp,
49
+ responseFormatFp: state.responseFormatFingerprint ?? fingerprints.response_format_fp,
50
+ evals,
51
+ selectorModel: options.selectorModel,
52
+ selectorContextWindowChars: options.selectorContextWindowChars,
53
+ // Selection fallback is deliberately not provider retry. The framework
54
+ // dispatches one chosen candidate and leaves retries to its executor.
55
+ modelFallbackEnabled: false,
56
+ });
57
+ }
58
+ catch (error) {
59
+ throw mapDariPolicyError(error);
60
+ }
61
+ if (prepared.selectorPreparation === null) {
62
+ throw new RouterFrameworkError("configuration", "Dari custom routing requires a non-empty customConfig.", "custom_config_missing");
63
+ }
64
+ const selectorRequest = prepared.selectorPreparation.selectorRequest;
65
+ let selectorOutput;
66
+ try {
67
+ selectorOutput = typeof selector === "function"
68
+ ? await selector(selectorRequest, input.signal)
69
+ : await selector.select(selectorRequest, input.signal);
70
+ }
71
+ catch (error) {
72
+ throw mapSelectorError(error);
73
+ }
74
+ let result;
75
+ try {
76
+ result = finalizeRoute(prepared, selectorOutput);
77
+ }
78
+ catch (error) {
79
+ throw mapDariPolicyError(error);
80
+ }
81
+ return {
82
+ model: result.decision.selectedModel,
83
+ reasoningEffort: result.decision.reasoningEffort,
84
+ reason: result.decision.reason,
85
+ ...(result.decision.leaseTurnsRemaining === undefined
86
+ ? {}
87
+ : { leaseTurnsRemaining: result.decision.leaseTurnsRemaining }),
88
+ details: { prepared, selectorOutput },
89
+ };
90
+ };
91
+ }
92
+ function mapSelectorError(error) {
93
+ if (!(error instanceof RouterFrameworkError) || error.kind !== "executor")
94
+ return error;
95
+ return new RouterFrameworkError("policy", error.message, error.code, error.param, { cause: error });
96
+ }
97
+ function mapDariPolicyError(error) {
98
+ if (!(error instanceof RouterCoreError))
99
+ return error;
100
+ const kind = error.kind === "invalid_request"
101
+ ? "invalid_request"
102
+ : error.kind === "configuration"
103
+ ? "configuration"
104
+ : "policy";
105
+ return new RouterFrameworkError(kind, error.message, error.code, error.param, { cause: error });
106
+ }
107
+ function defaultDariMetadata(candidate) {
108
+ return {
109
+ provider: candidate.provider,
110
+ api: candidate.api,
111
+ supportsImageInput: candidate.capabilities.imageInput,
112
+ supportsHostedWebSearch: false,
113
+ supportsStructuredOutput: candidate.capabilities.structuredOutput,
114
+ supportedThinkingLevels: [...candidate.reasoningEfforts],
115
+ };
116
+ }
117
+ function routerRequestToChat(request) {
118
+ const messages = [];
119
+ for (const item of request.items) {
120
+ if (item.type === "message") {
121
+ const content = chatContent(item.content);
122
+ const previous = messages.at(-1);
123
+ if (item.role === "assistant" && previous?.role === "assistant") {
124
+ const previousContent = previous.content;
125
+ previous.content = Array.isArray(previousContent)
126
+ ? [...previousContent, ...content]
127
+ : content;
128
+ }
129
+ else {
130
+ messages.push({ role: item.role, content });
131
+ }
132
+ continue;
133
+ }
134
+ if (item.type === "reasoning") {
135
+ const readable = [...(item.summary ?? []), ...item.content].join("\n");
136
+ let assistant = messages.at(-1);
137
+ if (!assistant || assistant.role !== "assistant" || hasAssistantContent(assistant)) {
138
+ assistant = { role: "assistant", content: null };
139
+ messages.push(assistant);
140
+ }
141
+ if (readable) {
142
+ assistant.reasoning_content = appendReasoningText(assistant.reasoning_content, readable);
143
+ }
144
+ continue;
145
+ }
146
+ if (item.type === "tool_result") {
147
+ messages.push({
148
+ role: "tool",
149
+ tool_call_id: item.toolCallId,
150
+ content: chatContent(item.content),
151
+ });
152
+ continue;
153
+ }
154
+ let assistant = messages.at(-1);
155
+ if (assistant?.role !== "assistant") {
156
+ assistant = { role: "assistant", content: null, tool_calls: [] };
157
+ messages.push(assistant);
158
+ }
159
+ assistant.tool_calls ??= [];
160
+ if (item.type === "hosted_tool_call") {
161
+ const payload = {
162
+ ...item.payload,
163
+ type: item.providerType,
164
+ id: item.id,
165
+ };
166
+ if (item.status)
167
+ payload.status = item.status;
168
+ else
169
+ delete payload.status;
170
+ assistant.tool_calls.push({
171
+ id: item.id,
172
+ type: "function",
173
+ function: { name: item.tool, arguments: JSON.stringify(payload) },
174
+ });
175
+ continue;
176
+ }
177
+ assistant.tool_calls.push({
178
+ id: item.id,
179
+ type: "function",
180
+ function: {
181
+ name: item.name,
182
+ arguments: typeof item.arguments === "string"
183
+ ? item.arguments
184
+ : JSON.stringify(item.arguments),
185
+ },
186
+ });
187
+ }
188
+ return {
189
+ model: request.requestedModel,
190
+ messages,
191
+ stream: request.stream,
192
+ source_protocol: request.protocol === "anthropic_messages"
193
+ ? "anthropic_messages"
194
+ : "openai_chat",
195
+ ...(request.cacheKey === undefined ? {} : { prompt_cache_key: request.cacheKey }),
196
+ ...(request.generation.temperature === undefined
197
+ ? {}
198
+ : { temperature: request.generation.temperature }),
199
+ ...(request.generation.topP === undefined ? {} : { top_p: request.generation.topP }),
200
+ ...(request.generation.maxOutputTokens === undefined
201
+ ? {}
202
+ : { max_completion_tokens: request.generation.maxOutputTokens }),
203
+ ...(request.generation.stop === undefined ? {} : { stop: request.generation.stop }),
204
+ ...(request.tools.length === 0 ? {} : { tools: request.tools.map(chatTool) }),
205
+ ...(request.toolChoice === undefined ? {} : { tool_choice: chatToolChoice(request.toolChoice) }),
206
+ ...(request.parallelToolCalls === undefined
207
+ ? {}
208
+ : { parallel_tool_calls: request.parallelToolCalls }),
209
+ ...(request.responseFormat === undefined
210
+ ? {}
211
+ : { response_format: chatResponseFormat(request.responseFormat) }),
212
+ ...(request.reasoning?.effort === undefined
213
+ ? {}
214
+ : { reasoning_effort: request.reasoning.effort }),
215
+ ...(request.metadata === undefined ? {} : { metadata: request.metadata }),
216
+ ...(request.user === undefined ? {} : { user: request.user }),
217
+ };
218
+ }
219
+ function chatContent(content) {
220
+ return content.map((part) => part.type === "text"
221
+ ? { type: "text", text: part.text }
222
+ : {
223
+ type: "image_url",
224
+ image_url: {
225
+ url: part.url,
226
+ ...(part.detail === undefined ? {} : { detail: part.detail }),
227
+ },
228
+ });
229
+ }
230
+ function hasAssistantContent(message) {
231
+ if (message.content !== undefined && message.content !== null)
232
+ return true;
233
+ return (message.tool_calls?.length ?? 0) > 0;
234
+ }
235
+ function appendReasoningText(existing, text) {
236
+ return existing ? `${existing}\n${text}` : text;
237
+ }
238
+ function chatTool(tool) {
239
+ return {
240
+ type: "function",
241
+ function: {
242
+ name: tool.name,
243
+ ...(tool.description === undefined ? {} : { description: tool.description }),
244
+ parameters: tool.inputSchema,
245
+ ...(tool.strict === undefined ? {} : { strict: tool.strict }),
246
+ },
247
+ };
248
+ }
249
+ function chatToolChoice(choice) {
250
+ if (typeof choice === "string")
251
+ return choice;
252
+ return { type: "function", function: { name: choice.name } };
253
+ }
254
+ function chatResponseFormat(format) {
255
+ if (format.type !== "json_schema")
256
+ return format;
257
+ return {
258
+ type: "json_schema",
259
+ json_schema: {
260
+ name: format.name,
261
+ schema: format.schema,
262
+ ...(format.description === undefined ? {} : { description: format.description }),
263
+ ...(format.strict === undefined ? {} : { strict: format.strict }),
264
+ },
265
+ };
266
+ }
267
+ //# sourceMappingURL=dari_policy.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dari_policy.js","sourceRoot":"","sources":["../src/dari_policy.ts"],"names":[],"mappings":"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"}