@mupt-ai/dari-gateway 0.3.1 → 0.3.3

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 (110) hide show
  1. package/README.md +18 -11
  2. package/dari-gateway.example.yaml +3 -2
  3. package/dist/context/interaction_fingerprint.js +10 -1
  4. package/dist/http/auth.js +2 -2
  5. package/dist/http/http2_server.d.ts +1 -1
  6. package/dist/http/http2_server.js +3 -3
  7. package/dist/http/serve.d.ts +1 -0
  8. package/dist/http/serve.js +5 -4
  9. package/dist/ingress/chat_completions.js +2 -2
  10. package/dist/ingress/codex.js +7 -3
  11. package/dist/ingress/codex_models.d.ts +1 -1
  12. package/dist/ingress/codex_models.js +22 -13
  13. package/dist/platform/platform.d.ts +13 -3
  14. package/dist/protocol/input/openai_responses.js +2 -4
  15. package/dist/protocol/output/anthropic_messages_output.d.ts +2 -2
  16. package/dist/protocol/output/anthropic_messages_output.js +1 -0
  17. package/dist/protocol/output/openai_responses_stream.js +19 -1
  18. package/dist/providers/execution.d.ts +0 -5
  19. package/dist/providers/execution.js +5 -8
  20. package/dist/providers/pi_output.d.ts +4 -0
  21. package/dist/providers/pi_output.js +1 -1
  22. package/dist/providers/provider_attempt_runner.d.ts +2 -3
  23. package/dist/providers/provider_attempt_runner.js +14 -24
  24. package/dist/providers/provider_call.d.ts +3 -3
  25. package/dist/providers/provider_call.js +1 -0
  26. package/dist/providers/stream_finalization.d.ts +0 -1
  27. package/dist/providers/stream_finalization.js +0 -1
  28. package/dist/runtime/claude_code/auxiliary_routing.js +1 -9
  29. package/dist/runtime/explicit_model.js +1 -1
  30. package/dist/runtime/harness_identity/conversation.d.ts +9 -0
  31. package/dist/runtime/harness_identity/conversation.js +6 -0
  32. package/dist/runtime/harness_identity/extract.d.ts +2 -0
  33. package/dist/runtime/harness_identity/extract.js +20 -5
  34. package/dist/runtime/harness_identity/index.d.ts +2 -2
  35. package/dist/runtime/harness_identity/index.js +2 -2
  36. package/dist/runtime/prepare_routed_completion.d.ts +5 -1
  37. package/dist/runtime/prepare_routed_completion.js +26 -2
  38. package/dist/runtime/routed_runtime.js +33 -53
  39. package/dist/runtime/routing_lease.d.ts +4 -6
  40. package/dist/runtime/routing_lease.js +2 -47
  41. package/dist/runtime/runtime_reporter.d.ts +0 -2
  42. package/dist/runtime/runtime_reporter.js +0 -1
  43. package/dist/runtime/session_pin.d.ts +7 -0
  44. package/dist/runtime/session_pin.js +51 -0
  45. package/dist/self_host/config.d.ts +2 -3
  46. package/dist/self_host/config.js +3 -3
  47. package/dist/self_host/main.d.ts +2 -1
  48. package/dist/self_host/main.js +26 -6
  49. package/dist/self_host/platform.d.ts +4 -2
  50. package/dist/self_host/platform.js +6 -2
  51. package/dist/self_host/resolve.d.ts +8 -1
  52. package/dist/self_host/resolve.js +31 -8
  53. package/dist/self_host/session_pin_store.d.ts +14 -0
  54. package/dist/self_host/session_pin_store.js +44 -0
  55. package/dist/strategies/priority_selector.d.ts +1 -2
  56. package/dist/strategies/priority_selector.js +1 -2
  57. package/dist/strategies/route_decision.d.ts +0 -1
  58. package/dist/strategies/route_decision.js +0 -3
  59. package/dist/strategies/routing.d.ts +0 -3
  60. package/dist/strategies/routing.js +1 -14
  61. package/dist/telemetry/billing_finalization.d.ts +1 -2
  62. package/dist/telemetry/billing_finalization.js +1 -1
  63. package/dist/telemetry/prefix_state.d.ts +0 -1
  64. package/dist/telemetry/prefix_state.js +1 -3
  65. package/dist/telemetry/report.d.ts +0 -2
  66. package/dist/telemetry/report.js +5 -41
  67. package/dist/types.d.ts +5 -3
  68. package/package.json +2 -2
  69. package/src/context/interaction_fingerprint.ts +15 -1
  70. package/src/http/auth.ts +2 -2
  71. package/src/http/http2_server.ts +7 -3
  72. package/src/http/serve.ts +6 -5
  73. package/src/ingress/chat_completions.ts +2 -1
  74. package/src/ingress/codex.ts +8 -5
  75. package/src/ingress/codex_models.ts +18 -7
  76. package/src/platform/platform.ts +16 -2
  77. package/src/protocol/input/openai_responses.ts +2 -9
  78. package/src/protocol/output/anthropic_messages_output.ts +3 -2
  79. package/src/protocol/output/openai_responses_stream.ts +17 -1
  80. package/src/providers/execution.ts +5 -15
  81. package/src/providers/pi_output.ts +1 -1
  82. package/src/providers/provider_attempt_runner.ts +10 -21
  83. package/src/providers/provider_call.ts +3 -1
  84. package/src/providers/stream_finalization.ts +0 -2
  85. package/src/providers/subscription_limits.ts +1 -1
  86. package/src/runtime/claude_code/auxiliary_routing.ts +1 -8
  87. package/src/runtime/explicit_model.ts +1 -1
  88. package/src/runtime/harness_identity/conversation.ts +16 -0
  89. package/src/runtime/harness_identity/extract.ts +24 -5
  90. package/src/runtime/harness_identity/index.ts +3 -0
  91. package/src/runtime/prepare_routed_completion.ts +32 -2
  92. package/src/runtime/routed_runtime.ts +39 -59
  93. package/src/runtime/routing_lease.ts +2 -56
  94. package/src/runtime/runtime_reporter.ts +0 -3
  95. package/src/runtime/session_pin.ts +61 -0
  96. package/src/self_host/config.ts +7 -7
  97. package/src/self_host/main.ts +29 -6
  98. package/src/self_host/platform.ts +8 -2
  99. package/src/self_host/resolve.ts +37 -7
  100. package/src/self_host/session_pin_store.ts +58 -0
  101. package/src/strategies/priority_selector.ts +1 -2
  102. package/src/strategies/route_decision.ts +0 -5
  103. package/src/strategies/routing.ts +1 -17
  104. package/src/telemetry/billing_finalization.ts +4 -3
  105. package/src/telemetry/prefix_state.ts +1 -6
  106. package/src/telemetry/report.ts +4 -48
  107. package/src/types.ts +12 -6
  108. package/dist/strategies/fallback_decision.d.ts +0 -8
  109. package/dist/strategies/fallback_decision.js +0 -17
  110. package/src/strategies/fallback_decision.ts +0 -30
@@ -62,7 +62,6 @@ import {
62
62
  buildCompletedPrefixHit,
63
63
  leaseCountdownForPrefix,
64
64
  prefixEntryForIngest,
65
- reportPendingLease,
66
65
  reportPrefixState,
67
66
  } from "./prefix_state.js";
68
67
  import { subscriptionUsageLimitFromFailure } from "../providers/subscription_limits.js";
@@ -149,7 +148,6 @@ export class RequestReporter {
149
148
  private selectorOutputAccepted = false;
150
149
  private decision: RoutingDecision | null = null;
151
150
  private nextDecision: RoutingDecision | null = null;
152
- private fallbackDecision: RoutingDecision | null = null;
153
151
  private providerAttempts: ProviderAttemptReport[] = [];
154
152
  private billingProviderAttempts: RoutingBillingProviderAttemptFacts[] = [];
155
153
  private decisionDetails: Record<string, unknown> = {};
@@ -202,7 +200,6 @@ export class RequestReporter {
202
200
  this.selectorOutputAccepted = true;
203
201
  this.decision = run.decision;
204
202
  this.nextDecision = run.decision;
205
- this.fallbackDecision = run.fallbackDecision ?? null;
206
203
  }
207
204
 
208
205
  attachSpeculativeSelectorRun(run: SelectorRun, servingDecision: RoutingDecision): void {
@@ -211,7 +208,6 @@ export class RequestReporter {
211
208
  this.selectorOutputAccepted = true;
212
209
  this.decision = servingDecision;
213
210
  this.nextDecision = run.decision;
214
- this.fallbackDecision = run.fallbackDecision ?? null;
215
211
  }
216
212
 
217
213
  // Speculative execution can begin before a selector run; its serving
@@ -221,10 +217,6 @@ export class RequestReporter {
221
217
  this.nextDecision = decision;
222
218
  }
223
219
 
224
- attachFallbackDecision(decision: RoutingDecision | undefined): void {
225
- this.fallbackDecision = decision ?? null;
226
- }
227
-
228
220
  attachServingDecision(decision: RoutingDecision): void {
229
221
  this.decision = decision;
230
222
  }
@@ -239,10 +231,10 @@ export class RequestReporter {
239
231
  return modelCost(attempt ? [...this.billingProviderAttempts, this.billingFacts(attempt)] : this.billingProviderAttempts);
240
232
  }
241
233
 
242
- private billingFacts({ execution, message, role, attempt, billingOutcome }: ProviderAttemptRecord): RoutingBillingProviderAttemptFacts {
234
+ private billingFacts({ execution, message, attempt, billingOutcome }: ProviderAttemptRecord): RoutingBillingProviderAttemptFacts {
243
235
  return routingBillingProviderAttemptFacts({
244
236
  provider: execution.provider, model: execution.model,
245
- providerKeySource: execution.providerKeySource, role, attempt, outcome: billingOutcome,
237
+ providerKeySource: execution.providerKeySource, attempt, outcome: billingOutcome,
246
238
  providerMessage: message, usage: isRecord(message.usage) ? message.usage : null,
247
239
  providerPricingKnown: this.pricingKnown(execution.model),
248
240
  });
@@ -388,18 +380,8 @@ export class RequestReporter {
388
380
  const decision = this.decision;
389
381
  const selectedModel = outcome.providerExecution?.model ?? decision?.selectedModel ?? null;
390
382
  const reasoningBucket = decision?.reasoningEffort ?? null;
391
- // A completed fallback attempt means the intended pair failed this
392
- // turn: the next-turn recommendation and any lease countdown follow the
393
- // pair that actually served instead of re-pinning the failed one.
394
- const fallbackServed = this.providerAttempts.some(
395
- (attempt) => attempt.role === "fallback" && attempt.outcome === "completed",
396
- );
397
- const nextModel = fallbackServed
398
- ? selectedModel
399
- : this.nextDecision?.selectedModel ?? selectedModel;
400
- const nextReasoningEffort = fallbackServed
401
- ? reasoningBucket
402
- : this.nextDecision?.reasoningEffort ?? reasoningBucket;
383
+ const nextModel = this.nextDecision?.selectedModel ?? selectedModel;
384
+ const nextReasoningEffort = this.nextDecision?.reasoningEffort ?? reasoningBucket;
403
385
  const selectedProvider = outcome.providerExecution?.provider ?? (selectedModel
404
386
  ? executionProviderForModel(a.credentials, selectedModel)
405
387
  : null);
@@ -470,7 +452,6 @@ export class RequestReporter {
470
452
  leaseTurnsRemaining: leaseCountdownForPrefix({
471
453
  served: decision ?? null,
472
454
  next: this.nextDecision,
473
- fallbackServed,
474
455
  }),
475
456
  reason: this.nextDecision?.reason ?? decision?.reason ?? null,
476
457
  chain: selectedChain,
@@ -506,21 +487,6 @@ export class RequestReporter {
506
487
  // resolves this turn's conversation id and next-model prediction.
507
488
  // The full report below re-applies the same state idempotently, so a
508
489
  // lost or timed-out fast write only degrades to the old ordering.
509
- // An ordinary fallback breaks any lease commitment, prefetched ones
510
- // included. A lease-aware fallback transfers the active countdown to
511
- // the serving pair, so only clear pending state when no countdown was
512
- // transferred. The depth fence orders the clear safely against
513
- // in-flight prefetch writes.
514
- if (!backgroundRequest && fallbackServed && decision?.leaseTurnsRemaining === undefined) {
515
- trackBackgroundTelemetry(
516
- reportPendingLease({
517
- routerId: a.routerId,
518
- conversationId: a.conversationId,
519
- decidedAtDepth: a.leaseDepth,
520
- lease: null,
521
- }),
522
- );
523
- }
524
490
  if (prefixEntry !== null || touchedHash !== null) {
525
491
  this.prefixStatePromise = reportPrefixState({
526
492
  organization_id: a.credentials.organization_id,
@@ -592,13 +558,6 @@ export class RequestReporter {
592
558
  strategy: a.strategy,
593
559
  selected_reasoning_effort: reasoningBucket,
594
560
  next_reasoning_effort: nextReasoningEffort,
595
- ...(this.fallbackDecision
596
- ? {
597
- fallback_model: this.fallbackDecision.selectedModel,
598
- fallback_reasoning_effort:
599
- this.fallbackDecision.reasoningEffort,
600
- }
601
- : {}),
602
561
  ...(this.providerAttempts.length > 0
603
562
  ? { provider_attempts: this.providerAttempts }
604
563
  : {}),
@@ -662,9 +621,6 @@ export class RequestReporter {
662
621
  selected_reasoning_effort: reasoningBucket,
663
622
  next_model: nextModel,
664
623
  next_reasoning_effort: nextReasoningEffort,
665
- fallback_model: this.fallbackDecision?.selectedModel ?? null,
666
- fallback_reasoning_effort:
667
- this.fallbackDecision?.reasoningEffort ?? null,
668
624
  provider_key_source: keySource,
669
625
  message_count: observability.messageCount,
670
626
  tool_count: observability.metadata.declared_tool_counts.total,
package/src/types.ts CHANGED
@@ -6,6 +6,7 @@ import type {
6
6
  RouterEvalScore,
7
7
  RouterModelPrice,
8
8
  RouterPrefixHit,
9
+ RoutingDecision,
9
10
  RoutingStrategy,
10
11
  } from "@mupt-ai/dari-router/policy-engine";
11
12
  // The router resolution contract between the gateway runtime and its
@@ -83,6 +84,10 @@ export type PublicEvalCatalogCard = Omit<RouterEval, "scores"> & {
83
84
  scores: PublicEvalCatalogScore[];
84
85
  };
85
86
 
87
+ // A decision as served: session-pinned decisions say so in response headers
88
+ // and Anthropic routing metadata.
89
+ export type ServedDecision = RoutingDecision & { sessionPinned?: boolean };
90
+
86
91
  export type ClientHarness = "claude_code" | "muse_code";
87
92
 
88
93
  export type ResolvedRouterModelConfig = {
@@ -122,17 +127,18 @@ export type ResolvedRouter = {
122
127
  zdr?: boolean;
123
128
  allow_long_context?: boolean;
124
129
  speculative_routing?: boolean;
130
+ // Route each session's (and each subagent's) first turn, then serve that
131
+ // pair for the rest of the session instead of selecting or leasing.
132
+ session_pinning?: boolean;
125
133
  primary_retries?: number;
126
134
  // Serve only the requested `dari/model/<id>` at the requested thinking
127
- // level: no selector, lease, fallback, or personal subscription the
128
- // platform did not supply through resolveProviderCredential, and an error
129
- // for anything else, whatever the client sends.
135
+ // level: no selector, lease, or personal subscription the platform did not
136
+ // supply through resolveProviderCredential, and an error for anything
137
+ // else, whatever the client sends.
130
138
  strict?: boolean;
131
139
  // On strict routers only, allow requested catalog models of these providers.
132
- // Requires dari/model/<provider>/<id>; never enables fallback.
140
+ // Requires dari/model/<provider>/<id>.
133
141
  strict_providers?: string[];
134
- model_fallback_enabled?: boolean;
135
- fallback_requires_different_provider?: boolean;
136
142
  evals?: RouterEval[];
137
143
  // When true, fill missing eval scores using thinking-level ratios or an
138
144
  // explicitly mapped predecessor model.
@@ -1,8 +0,0 @@
1
- import { type RoutingCandidate, type RoutingDecision } from "@mupt-ai/dari-router/policy-engine";
2
- export declare function deriveFallbackDecision(args: {
3
- candidates: RoutingCandidate[];
4
- selected: RoutingCandidate;
5
- enabled?: boolean;
6
- requiresDifferentProvider?: boolean;
7
- providerForModel?: (model: string) => string;
8
- }): RoutingDecision | undefined;
@@ -1,17 +0,0 @@
1
- import { providerForModel, } from "@mupt-ai/dari-router/policy-engine";
2
- export function deriveFallbackDecision(args) {
3
- if (!args.enabled)
4
- return undefined;
5
- const resolveProvider = args.providerForModel ?? providerForModel;
6
- const selectedProvider = resolveProvider(args.selected.model);
7
- const fallback = args.candidates.find((candidate) => candidate.model !== args.selected.model &&
8
- (!args.requiresDifferentProvider ||
9
- resolveProvider(candidate.model) !== selectedProvider));
10
- return fallback
11
- ? {
12
- selectedModel: fallback.model,
13
- reasoningEffort: fallback.reasoningEffort,
14
- reason: "Runtime-selected fallback for the routed primary decision.",
15
- }
16
- : undefined;
17
- }
@@ -1,30 +0,0 @@
1
- import {
2
- providerForModel,
3
- type RoutingCandidate,
4
- type RoutingDecision,
5
- } from "@mupt-ai/dari-router/policy-engine";
6
-
7
- export function deriveFallbackDecision(args: {
8
- candidates: RoutingCandidate[];
9
- selected: RoutingCandidate;
10
- enabled?: boolean;
11
- requiresDifferentProvider?: boolean;
12
- providerForModel?: (model: string) => string;
13
- }): RoutingDecision | undefined {
14
- if (!args.enabled) return undefined;
15
- const resolveProvider = args.providerForModel ?? providerForModel;
16
- const selectedProvider = resolveProvider(args.selected.model);
17
- const fallback = args.candidates.find(
18
- (candidate) =>
19
- candidate.model !== args.selected.model &&
20
- (!args.requiresDifferentProvider ||
21
- resolveProvider(candidate.model) !== selectedProvider),
22
- );
23
- return fallback
24
- ? {
25
- selectedModel: fallback.model,
26
- reasoningEffort: fallback.reasoningEffort,
27
- reason: "Runtime-selected fallback for the routed primary decision.",
28
- }
29
- : undefined;
30
- }