@ljwei-stak/dsh-model-router 0.14.0 → 0.16.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.
@@ -174,7 +174,7 @@ function nonnegative(value, label) {
174
174
  function normalizeProfile(entry, index) {
175
175
  const label = `\u7B2C ${index + 1} \u4E2A\u6A21\u578B`;
176
176
  if (!entry || typeof entry !== "object" || Array.isArray(entry)) throw new Error(`${label} \u5FC5\u987B\u662F\u5BF9\u8C61`);
177
- const allowed = /* @__PURE__ */ new Set(["provider", "model", "quality", "pricing", "specialties", "cliModel", "execution", "billing", "subscription", "apiRoute"]);
177
+ const allowed = /* @__PURE__ */ new Set(["provider", "model", "benchmarkModel", "quality", "pricing", "specialties", "cliModel", "execution", "billing", "subscription", "apiRoute"]);
178
178
  const unknown = Object.keys(entry).find((key) => !allowed.has(key));
179
179
  if (unknown) throw new Error(`${label} \u542B\u4E0D\u652F\u6301\u7684\u5B57\u6BB5 ${unknown}\uFF1B\u4E0D\u8981\u5728\u8FD9\u91CC\u586B\u5199\u5BC6\u94A5\u6216\u547D\u4EE4`);
180
180
  const provider = id(entry.provider);
@@ -183,6 +183,11 @@ function normalizeProfile(entry, index) {
183
183
  throw new Error(`${label} \u9700\u8981\u6A21\u578B\u76EE\u5F55\u4E2D\u7684\u51C6\u786E provider \u548C model`);
184
184
  }
185
185
  const profile = { provider, model };
186
+ if (entry.benchmarkModel !== void 0) {
187
+ const benchmarkModel = id(entry.benchmarkModel);
188
+ if (!benchmarkModel || benchmarkModel.length > 240 || /[\u0000-\u001f]/u.test(benchmarkModel)) throw new Error(`${label} \u7684 benchmarkModel \u9700\u8981\u51C6\u786E\u7684\u57FA\u51C6\u6A21\u578B\u540D\u79F0`);
189
+ profile.benchmarkModel = benchmarkModel;
190
+ }
186
191
  if (entry.quality !== void 0) {
187
192
  const value = nonnegative(entry.quality, `${label} \u7684 quality`);
188
193
  if (value > 100) throw new Error(`${label} \u7684 quality \u5E94\u5728 0 \u5230 100 \u4E4B\u95F4`);
@@ -278,6 +283,7 @@ function applyModelProfiles(routes, profiles) {
278
283
  if (!profile) return route;
279
284
  return {
280
285
  ...route,
286
+ ...profile.benchmarkModel === void 0 ? {} : { benchmarkModel: profile.benchmarkModel },
281
287
  ...profile.quality === void 0 ? {} : { quality: profile.quality, qualitySource: "user" },
282
288
  ...profile.pricing === void 0 ? {} : { pricing: { ...profile.pricing }, pricingSource: "user" },
283
289
  ...profile.specialties === void 0 ? {} : { specialties: [...profile.specialties] },
@@ -466,7 +472,7 @@ var TASK_ALIASES = Object.freeze({
466
472
  var CATEGORY_TO_TASK = Object.freeze({
467
473
  reasoning: "reasoning",
468
474
  coding: "code",
469
- "agentic coding": "code",
475
+ // Agentic Coding is a different task family, not silently a Coding score.
470
476
  mathematics: "math",
471
477
  "data analysis": "research",
472
478
  language: "writing",
@@ -478,7 +484,85 @@ function normalized(value) {
478
484
  return String(value ?? "").toLowerCase().replace(/[^a-z0-9]+/g, "");
479
485
  }
480
486
  function liveBenchRow(snapshot, model) {
481
- return snapshot?.models?.[normalized(model)] ?? null;
487
+ const row = snapshot?.models?.[normalized(model)] ?? null;
488
+ return snapshot?.exactModelMatch === true && row?.model !== model ? null : row;
489
+ }
490
+
491
+ // .dsh-plugin/shared/assignment-solver.mjs
492
+ var EPSILON = 1e-12;
493
+ var compareText = (a, b2) => a < b2 ? -1 : a > b2 ? 1 : 0;
494
+ var signature = (state) => JSON.stringify(state.choices.map((option) => option.route));
495
+ function compareStates(left, right, minimizeCost = false) {
496
+ return left.relaxedCount - right.relaxedCount || left.qualityShortfall - right.qualityShortfall || (minimizeCost ? left.cost - right.cost : right.score - left.score) || (minimizeCost ? right.score - left.score : left.cost - right.cost) || left.switches - right.switches || compareText(signature(left), signature(right));
497
+ }
498
+ function solveCandidateAssignments({ tasks = [], pools = [], budget = Infinity, beamWidth = 256, exactLimit = 4096, handoffPenalty = 0.015, minimizeCost = false } = {}) {
499
+ if (!tasks.length || tasks.length !== pools.length) return null;
500
+ const preceding = /* @__PURE__ */ new Set();
501
+ for (const task of tasks) {
502
+ if (!task.id || preceding.has(task.id) || (task.dependsOn ?? []).some((id2) => !preceding.has(id2))) {
503
+ throw new RangeError("Assignment tasks must have unique ids and known dependencies in topological order");
504
+ }
505
+ preceding.add(task.id);
506
+ }
507
+ const constrained = Number.isFinite(budget);
508
+ const options = pools.map((pool) => (Array.isArray(pool) ? pool : []).filter((option) => Number.isFinite(option.cost) && option.cost >= 0 && Number.isFinite(option.score) && (!constrained || option.pricingKnown === true)));
509
+ if (options.some((pool) => pool.length === 0)) return null;
510
+ const suffixMinimum = Array(tasks.length + 1).fill(0);
511
+ let searchSpace = 1;
512
+ let searchSpaceCapped = false;
513
+ for (let index = tasks.length - 1; index >= 0; index--) {
514
+ suffixMinimum[index] = suffixMinimum[index + 1] + Math.min(...options[index].map((option) => option.cost));
515
+ const product = searchSpace * options[index].length;
516
+ if (product > Number.MAX_SAFE_INTEGER) searchSpaceCapped = true;
517
+ searchSpace = Math.min(Number.MAX_SAFE_INTEGER, product);
518
+ }
519
+ if (constrained && suffixMinimum[0] > budget + EPSILON) return null;
520
+ const exact = !searchSpaceCapped && searchSpace <= Math.max(1, exactLimit);
521
+ const width = Math.max(1, Math.floor(beamWidth) || 256);
522
+ const search = { method: exact ? "exact" : "beam", exact, searchSpace, searchSpaceCapped, expandedStates: 0, beamPruned: 0 };
523
+ let states = [{ choices: [], routesByTask: /* @__PURE__ */ new Map(), score: 0, cost: 0, switches: 0, relaxedCount: 0, qualityShortfall: 0 }];
524
+ for (let index = 0; index < tasks.length; index++) {
525
+ const task = tasks[index];
526
+ const expanded = [];
527
+ for (const state of states) {
528
+ for (const option of options[index]) {
529
+ const cost = state.cost + option.cost;
530
+ if (constrained && cost + suffixMinimum[index + 1] > budget + EPSILON) continue;
531
+ const switches = (task.dependsOn ?? []).reduce((count, dependency) => {
532
+ const route = state.routesByTask.get(dependency);
533
+ return count + (route !== void 0 && route !== option.route ? 1 : 0);
534
+ }, 0);
535
+ const penalty = switches * handoffPenalty;
536
+ const shortfall = Math.max(0, Number(option.qualityShortfall) || 0);
537
+ const routesByTask2 = new Map(state.routesByTask);
538
+ routesByTask2.set(task.id, option.route);
539
+ expanded.push({
540
+ choices: [...state.choices, { ...option, handoffPenalty: penalty }],
541
+ routesByTask: routesByTask2,
542
+ score: state.score + option.score - penalty,
543
+ cost,
544
+ switches: state.switches + switches,
545
+ relaxedCount: state.relaxedCount + (shortfall > 0 ? 1 : 0),
546
+ qualityShortfall: state.qualityShortfall + shortfall
547
+ });
548
+ search.expandedStates++;
549
+ }
550
+ }
551
+ if (!expanded.length) return null;
552
+ expanded.sort((left, right) => compareStates(left, right, minimizeCost));
553
+ if (!exact && expanded.length > width) {
554
+ states = expanded.slice(0, width);
555
+ if (constrained && index < tasks.length - 1) {
556
+ const cheapest = expanded.reduce((best2, state) => compareStates(state, best2, true) < 0 ? state : best2);
557
+ if (!states.includes(cheapest)) states[width - 1] = cheapest;
558
+ }
559
+ search.beamPruned += expanded.length - states.length;
560
+ } else states = expanded;
561
+ }
562
+ states.sort((left, right) => compareStates(left, right, minimizeCost));
563
+ const best = states[0];
564
+ const { routesByTask, ...result } = best;
565
+ return { ...result, minimumCostLowerBound: suffixMinimum[0], search };
482
566
  }
483
567
 
484
568
  // .dsh-plugin/shared/router.mjs
@@ -590,9 +674,12 @@ function specialtyMatch(model, taskType, liveScores = {}) {
590
674
  return 0.38;
591
675
  }
592
676
  function qualityForTask(row, taskType) {
593
- const base = asScore(row?.liveScores?.[taskType]) ?? asScore(row?.liveOverall) ?? row?.metadata?.quality ?? row?.quality ?? 0;
677
+ const base = asScore(row?.liveScores?.[taskType]) ?? asScore(row?.liveOverall) ?? row?.metadata?.quality ?? row?.baseQuality ?? row?.quality ?? 0;
594
678
  return row?.qualityBias ? clamp(base + row.qualityBias) : base;
595
679
  }
680
+ function qualitySourceForTask(row, taskType) {
681
+ return asScore(row?.liveScores?.[taskType]) !== void 0 || asScore(row?.liveOverall) !== void 0 ? "livebench" : row?.fallbackQualitySource ?? row?.qualitySource ?? "unknown";
682
+ }
596
683
  function specialtyForTask(row, taskType) {
597
684
  return specialtyMatch(row.metadata, taskType, row.liveScores);
598
685
  }
@@ -644,20 +731,7 @@ function normalizedCacheRatios(cacheReadRatio = 0, cacheWriteRatio = 0) {
644
731
  const write = Number.isFinite(Number(cacheWriteRatio)) ? Math.min(clamp(Number(cacheWriteRatio)), 1 - read) : 0;
645
732
  return { read, write };
646
733
  }
647
- function effectivePricing(pricing, cacheReadRatio = 0, cacheWriteRatio = 0) {
648
- const { read, write } = normalizedCacheRatios(cacheReadRatio, cacheWriteRatio);
649
- return {
650
- input: (1 - read - write) * Number(pricing.input) + read * Number(pricing.cacheRead) + write * Number(pricing.cacheWrite),
651
- output: Number(pricing.output)
652
- };
653
- }
654
- function costScore(pricing, maxCost, cacheReadRatio = 0, cacheWriteRatio = 0) {
655
- if (pricing === null) return 0;
656
- const effective = effectivePricing(pricing, cacheReadRatio, cacheWriteRatio);
657
- const mean = (effective.input + effective.output) / 2;
658
- if (maxCost <= 0) return mean === 0 ? 1 : 0;
659
- return clamp(1 - mean / maxCost);
660
- }
734
+ var COST_REFERENCE_PRICING = Object.freeze({ input: 1, output: 5, cacheRead: 1, cacheWrite: 1, currency: "USD" });
661
735
  function estimateCost(model, text6, outputTokens = 900, pricingOverrides = {}, cacheReadRatio = 0, cacheWriteRatio = 0) {
662
736
  const pricing = pricingFor(model, pricingOverrides);
663
737
  if (pricing === null) return null;
@@ -898,13 +972,13 @@ function weightsForTask(weights, task) {
898
972
  if (task.weights) return task.weights;
899
973
  return task.purpose === "synthesis" ? SYNTHESIS_WEIGHTS : OBJECTIVE_WEIGHTS[task.difficulty] ?? weights;
900
974
  }
901
- function compareText(left, right) {
975
+ function compareText2(left, right) {
902
976
  const a = String(left);
903
977
  const b2 = String(right);
904
978
  return a < b2 ? -1 : a > b2 ? 1 : 0;
905
979
  }
906
980
  function compareRowsStable(left, right) {
907
- return compareText(routeKey(left.provider, left.model), routeKey(right.provider, right.model));
981
+ return compareText2(routeKey(left.provider, left.model), routeKey(right.provider, right.model));
908
982
  }
909
983
  function reasoningEffortRank(effort) {
910
984
  const normalized2 = String(effort ?? "").trim().toLowerCase().replace(/[\s_-]+/g, "");
@@ -925,7 +999,7 @@ function selectReasoningEffort(efforts, preferred = "medium") {
925
999
  return exact.slice().sort((left, right) => {
926
1000
  const distance = Math.abs(reasoningEffortRank(left) - preferredRank) - Math.abs(reasoningEffortRank(right) - preferredRank);
927
1001
  if (distance !== 0) return distance;
928
- return reasoningEffortRank(left) - reasoningEffortRank(right) || compareText(left, right);
1002
+ return reasoningEffortRank(left) - reasoningEffortRank(right) || compareText2(left, right);
929
1003
  })[0];
930
1004
  }
931
1005
  function reasoningDecision(row, task) {
@@ -951,16 +1025,17 @@ function reasoningDecision(row, task) {
951
1025
  multiplier: reasoningEffortMultiplier(chosen)
952
1026
  };
953
1027
  }
954
- function candidateUtility(row, task, weights, maxCost, usedRoutes, cacheReadRatio = 0, cacheWriteRatio = 0) {
1028
+ function candidateUtility(row, task, weights, cacheReadRatio = 0, cacheWriteRatio = 0, text6 = "", complexity = "balanced") {
955
1029
  const quality = qualityForTask(row, task.type);
1030
+ const rawPreference = row.preferenceAdjustments?.[task.type];
1031
+ const preferenceAdjustment = Number.isFinite(rawPreference) ? clamp(rawPreference, -0.1, 0.1) : 0;
956
1032
  const floor = Number(task.qualityFloor ?? taskQualityFloor("complex", task));
957
1033
  const qualityGap = Math.max(0, floor - quality);
958
- const duplicatePenalty = 0;
959
- const synthesisPreference = task.purpose === "synthesis" && /deepseek[- ]?v4[- ]?pro/i.test(row.model) ? 0.025 : 0;
960
1034
  const reasoning = reasoningDecision(row, task);
961
- const cost = clamp(costScore(row.pricing, maxCost, cacheReadRatio, cacheWriteRatio) / Math.sqrt(reasoning.multiplier.output));
962
- const score = weights.quality * quality + weights.cost * cost + weights.latency * (1 - clamp(row.latency * reasoning.multiplier.latency)) + weights.specialty * specialtyForTask(row, task.type) + (weights.reasoning ?? 0) * reasoning.reasoningFit - weights.risk * row.risk - duplicatePenalty - qualityGap * (task.criticality ?? 0.75) + synthesisPreference;
963
- return { score, floor, qualityGap, ...reasoning };
1035
+ const reference = taskCost({ pricing: COST_REFERENCE_PRICING, reasoningKnown: true, reasoningEfforts: [] }, task, text6, complexity, cacheReadRatio, cacheWriteRatio);
1036
+ const cost = row.pricing === null ? 0 : 1 / (1 + taskCost(row, task, text6, complexity, cacheReadRatio, cacheWriteRatio) / Math.max(reference, 1e-12));
1037
+ const score = weights.quality * quality + weights.cost * cost + weights.latency * (1 - clamp(row.latency * reasoning.multiplier.latency)) + weights.specialty * specialtyForTask(row, task.type) + (weights.reasoning ?? 0) * reasoning.reasoningFit - weights.risk * row.risk - qualityGap * (task.criticality ?? 0.75) + preferenceAdjustment;
1038
+ return { score, floor, qualityGap, preferenceAdjustment, ...reasoning };
964
1039
  }
965
1040
  function taskCost(row, task, text6, complexity, cacheReadRatio = 0, cacheWriteRatio = 0) {
966
1041
  if (row?.pricing === null) return 0;
@@ -992,96 +1067,65 @@ function dominates(left, right, task, text6, complexity, cacheReadRatio, cacheWr
992
1067
  const strictlyBetter = leftValues.quality > rightValues.quality || leftValues.cost < rightValues.cost || leftValues.latency < rightValues.latency || leftValues.specialty > rightValues.specialty || leftValues.reasoning > rightValues.reasoning || leftValues.risk < rightValues.risk;
993
1068
  return noWorse && strictlyBetter;
994
1069
  }
995
- function candidatePool(rows, task, weights, maxCost, text6, complexity, cacheReadRatio, cacheWriteRatio) {
996
- const eligibleRows = task.type === "vision" ? rows.filter((row) => row.inputModalities.length === 0 || row.inputModalities.includes("image")) : rows;
1070
+ function eligibleRowsForTask(rows, task) {
1071
+ return task.type === "vision" ? rows.filter((row) => row.inputModalities.length === 0 || row.inputModalities.includes("image")) : rows;
1072
+ }
1073
+ function candidatePool(rows, task, weights, text6, complexity, cacheReadRatio, cacheWriteRatio, dependencySensitive = false) {
1074
+ const eligibleRows = eligibleRowsForTask(rows, task);
997
1075
  const floor = Number(task.qualityFloor ?? 0);
998
1076
  const feasible = eligibleRows.filter((row) => qualityForTask(row, task.type) >= floor);
999
1077
  const source = feasible.length > 0 ? feasible : eligibleRows.slice().sort((left, right) => qualityForTask(right, task.type) - qualityForTask(left, task.type) || compareRowsStable(left, right)).slice(0, 3);
1000
1078
  const taskWeights = weightsForTask(weights, task);
1001
1079
  const scored = source.map((row) => ({
1002
1080
  row,
1003
- decision: candidateUtility(row, task, taskWeights, maxCost, /* @__PURE__ */ new Set(), cacheReadRatio, cacheWriteRatio),
1081
+ decision: candidateUtility(row, task, taskWeights, cacheReadRatio, cacheWriteRatio, text6, complexity),
1004
1082
  cost: taskCost(row, task, text6, complexity, cacheReadRatio, cacheWriteRatio)
1005
1083
  }));
1006
- const frontier = scored.filter((item) => !source.some((other) => other !== item.row && dominates(other, item.row, task, text6, complexity, cacheReadRatio, cacheWriteRatio)));
1084
+ const frontier = dependencySensitive ? scored : scored.filter((item) => !scored.some((other) => other !== item && other.decision.score >= item.decision.score && dominates(other.row, item.row, task, text6, complexity, cacheReadRatio, cacheWriteRatio)));
1007
1085
  const essential = [
1008
- scored.slice().sort((left, right) => left.cost - right.cost || compareRowsStable(left.row, right.row))[0],
1086
+ scored.filter((item) => item.row.pricing !== null).sort((left, right) => left.cost - right.cost || compareRowsStable(left.row, right.row))[0],
1009
1087
  scored.slice().sort((left, right) => right.decision.score - left.decision.score || compareRowsStable(left.row, right.row))[0],
1010
1088
  scored.slice().sort((left, right) => qualityForTask(right.row, task.type) - qualityForTask(left.row, task.type) || compareRowsStable(left.row, right.row))[0]
1011
1089
  ].filter(Boolean);
1012
- const ordered = [...frontier, ...essential].filter((item, index, all) => all.findIndex((candidate) => candidate.row === item.row) === index).sort((left, right) => right.decision.score - left.decision.score || left.cost - right.cost || compareRowsStable(left.row, right.row)).slice(0, ROUTING_CANDIDATE_LIMIT);
1090
+ const all = [...frontier, ...essential].filter((item, index, all2) => all2.findIndex((candidate) => candidate.row === item.row) === index).sort((left, right) => right.decision.score - left.decision.score || left.cost - right.cost || compareRowsStable(left.row, right.row));
1091
+ const anchors = [...new Set(essential)];
1092
+ const ordered = [...anchors, ...all.filter((item) => !anchors.includes(item))].slice(0, ROUTING_CANDIDATE_LIMIT).sort((left, right) => right.decision.score - left.decision.score || left.cost - right.cost || compareRowsStable(left.row, right.row));
1013
1093
  return {
1014
1094
  options: ordered,
1015
1095
  relaxed: feasible.length === 0,
1016
- pruned: Math.max(0, eligibleRows.length - ordered.length)
1096
+ pruned: Math.max(0, scored.length - all.length),
1097
+ filtered: Math.max(0, eligibleRows.length - source.length),
1098
+ truncated: Math.max(0, all.length - ordered.length),
1099
+ dependencySensitive
1017
1100
  };
1018
1101
  }
1019
- function stateSignature(state) {
1020
- return state.assignments.map((assignment) => `${routeKey(assignment.row?.provider, assignment.row?.model)}@${assignment.decision?.reasoningEffort ?? "provider-default"}`).join("|");
1021
- }
1022
- function compareUtilityStates(left, right) {
1023
- return left.relaxedCount - right.relaxedCount || left.qualityShortfall - right.qualityShortfall || right.score - left.score || left.cost - right.cost || left.switches - right.switches || compareText(stateSignature(left), stateSignature(right));
1024
- }
1025
- function compareCostStates(left, right) {
1026
- return left.relaxedCount - right.relaxedCount || left.qualityShortfall - right.qualityShortfall || left.cost - right.cost || right.score - left.score || left.switches - right.switches || compareText(stateSignature(left), stateSignature(right));
1027
- }
1028
- function solveAssignments({ rows, tasks, weights, maxCost, text: text6, complexity, budget, cacheReadRatio, cacheWriteRatio, minimizeCost = false }) {
1029
- const pools = tasks.map((task) => candidatePool(rows, task, weights, maxCost, text6, complexity, cacheReadRatio, cacheWriteRatio));
1030
- if (pools.some((pool) => pool.options.length === 0)) return null;
1031
- const suffixMinimum = Array(tasks.length + 1).fill(0);
1032
- for (let index = tasks.length - 1; index >= 0; index -= 1) {
1033
- const costOptions = Number.isFinite(budget) ? pools[index].options.filter((option) => option.row.pricing !== null) : pools[index].options;
1034
- if (costOptions.length === 0) return null;
1035
- suffixMinimum[index] = suffixMinimum[index + 1] + Math.min(...costOptions.map((option) => option.cost));
1036
- }
1037
- if (Number.isFinite(budget) && suffixMinimum[0] > budget + 1e-12) return null;
1038
- let states = [{ assignments: [], routesByTask: /* @__PURE__ */ new Map(), usedRoutes: /* @__PURE__ */ new Set(), score: 0, cost: 0, switches: 0, relaxedCount: 0, qualityShortfall: 0 }];
1039
- for (let index = 0; index < tasks.length; index += 1) {
1040
- const task = tasks[index];
1041
- const pool = pools[index];
1042
- const expanded = [];
1043
- for (const state of states) {
1044
- for (const option of pool.options) {
1045
- if (Number.isFinite(budget) && option.row.pricing === null) continue;
1046
- const nextCost = state.cost + option.cost;
1047
- if (Number.isFinite(budget) && nextCost + suffixMinimum[index + 1] > budget + 1e-12) continue;
1048
- const taskWeights = weightsForTask(weights, task);
1049
- const decision = candidateUtility(option.row, task, taskWeights, maxCost, state.usedRoutes, cacheReadRatio, cacheWriteRatio);
1050
- const route = routeKey(option.row.provider, option.row.model);
1051
- const dependencySwitches = (task.dependsOn ?? []).reduce((count, dependency) => {
1052
- const dependencyRoute = state.routesByTask.get(dependency);
1053
- return count + (dependencyRoute !== void 0 && dependencyRoute !== route ? 1 : 0);
1054
- }, 0);
1055
- const handoffPenalty = dependencySwitches * 0.015;
1056
- const qualityShortfall = Math.max(0, decision.floor - qualityForTask(option.row, task.type));
1057
- const usedRoutes = new Set(state.usedRoutes);
1058
- usedRoutes.add(route);
1059
- const routesByTask = new Map(state.routesByTask);
1060
- routesByTask.set(task.id, route);
1061
- expanded.push({
1062
- assignments: [...state.assignments, { task, row: option.row, decision: { ...decision, relaxed: qualityShortfall > 0 }, estimatedCost: option.cost, handoffPenalty }],
1063
- routesByTask,
1064
- usedRoutes,
1065
- score: state.score + decision.score - handoffPenalty,
1066
- cost: nextCost,
1067
- switches: state.switches + dependencySwitches,
1068
- relaxedCount: state.relaxedCount + (qualityShortfall > 0 ? 1 : 0),
1069
- qualityShortfall: state.qualityShortfall + qualityShortfall
1070
- });
1071
- }
1072
- }
1073
- if (expanded.length === 0) return null;
1074
- expanded.sort(minimizeCost ? compareCostStates : compareUtilityStates);
1075
- states = expanded.slice(0, ROUTING_BEAM_WIDTH);
1076
- }
1077
- states.sort(minimizeCost ? compareCostStates : compareUtilityStates);
1102
+ function solveAssignments({ rows, tasks, weights, text: text6, complexity, budget, cacheReadRatio, cacheWriteRatio, minimizeCost = false }) {
1103
+ const dependencySensitive = tasks.some((task) => (task.dependsOn ?? []).length > 0);
1104
+ const pools = tasks.map((task) => candidatePool(rows, task, weights, text6, complexity, cacheReadRatio, cacheWriteRatio, dependencySensitive));
1105
+ const result = solveCandidateAssignments({ tasks, pools: pools.map((pool, index) => pool.options.map((option) => ({
1106
+ route: routeKey(option.row.provider, option.row.model),
1107
+ score: option.decision.score,
1108
+ cost: option.cost,
1109
+ qualityShortfall: Math.max(0, option.decision.floor - qualityForTask(option.row, tasks[index].type)),
1110
+ pricingKnown: option.row.pricing !== null,
1111
+ payload: option
1112
+ }))), budget, beamWidth: ROUTING_BEAM_WIDTH, minimizeCost });
1113
+ if (!result) return null;
1078
1114
  return {
1079
- ...states[0],
1115
+ ...result,
1116
+ assignments: result.choices.map((choice, index) => ({
1117
+ task: tasks[index],
1118
+ row: choice.payload.row,
1119
+ decision: { ...choice.payload.decision, relaxed: choice.qualityShortfall > 0 },
1120
+ estimatedCost: choice.cost,
1121
+ handoffPenalty: choice.handoffPenalty
1122
+ })),
1123
+ usedRoutes: new Set(result.choices.map((choice) => choice.route)),
1080
1124
  candidatePools: pools,
1081
- minimumFeasibleCost: suffixMinimum[0]
1125
+ minimumFeasibleCost: result.minimumCostLowerBound
1082
1126
  };
1083
1127
  }
1084
- function buildPlan({ text: text6 = "", available = [], mode = "collective", pricing = {}, liveBench = null, liveBenchError = "", budgetUsd = 0, cacheReadRatio = 0, cacheWriteRatio = 0, preset = DEFAULT_ROUTING_PRESET } = {}) {
1128
+ function buildPlan({ text: text6 = "", available = [], mode = "collective", pricing = {}, liveBench = null, liveBenchError = "", dataVersions = null, learning = null, budgetUsd = 0, cacheReadRatio = 0, cacheWriteRatio = 0, preset = DEFAULT_ROUTING_PRESET } = {}) {
1085
1129
  const presetId = normalizeRoutingPreset(preset);
1086
1130
  const firstLine = String(text6 ?? "").split(/\r?\n/u)[0].trim();
1087
1131
  const transformOnly = /^(?:请|帮我)?(?:总结|概括|翻译|摘要|解释)(?:以下|下列|下面|这份|这些)/u.test(firstLine) && !/(?:执行|完成|实施|分配)/u.test(firstLine);
@@ -1097,17 +1141,21 @@ function buildPlan({ text: text6 = "", available = [], mode = "collective", pric
1097
1141
  return {
1098
1142
  provider: String(entry.provider ?? ""),
1099
1143
  model: String(entry.model ?? ""),
1144
+ benchmarkModel: typeof entry.benchmarkModel === "string" ? entry.benchmarkModel : void 0,
1100
1145
  reasoningEfforts: [...new Set(reasoningEfforts)],
1101
1146
  defaultReasoningEffort: entry.defaultReasoningEffort === void 0 ? void 0 : String(entry.defaultReasoningEffort),
1102
1147
  reasoningKnown: entry.reasoningKnown === true || entry.reasoningKnown === void 0 && Array.isArray(entry.reasoningEfforts),
1103
1148
  quality: asScore(entry.quality),
1104
1149
  qualityBias: Number.isFinite(entry.qualityBias) ? clamp(entry.qualityBias, -0.05, 0.05) : 0,
1150
+ preferenceAdjustments: entry.preferenceAdjustments ?? null,
1105
1151
  qualitySource: entry.qualitySource === "user" ? "user" : "route",
1106
1152
  latency: asScore(entry.latency),
1107
1153
  risk: asScore(entry.risk),
1108
1154
  specialties: Array.isArray(entry.specialties) ? entry.specialties.filter((item) => typeof item === "string") : null,
1109
1155
  pricing: normalizePricing({ route: entry.pricing ?? entry.price }).route ?? null,
1110
- pricingSource: entry.pricingSource === "user" ? "user" : "route",
1156
+ pricingSource: entry.pricingSource === "user" ? "user" : entry.pricingSource === "dynamic" ? "dynamic" : "route",
1157
+ pricingVersion: entry.pricingVersion ?? null,
1158
+ snapshotAsOf: entry.snapshotAsOf ?? null,
1111
1159
  inputModalities: Array.isArray(entry.inputModalities) ? entry.inputModalities.map((item) => String(item).toLowerCase()) : []
1112
1160
  };
1113
1161
  }) : [];
@@ -1123,10 +1171,12 @@ function buildPlan({ text: text6 = "", available = [], mode = "collective", pric
1123
1171
  ...route.risk === void 0 ? {} : { risk: route.risk },
1124
1172
  ...route.specialties === null ? {} : { specialties: route.specialties }
1125
1173
  };
1126
- const live = liveBenchRow(liveBench, route.model);
1174
+ const live = liveBenchRow(liveBench, route.benchmarkModel ?? route.model);
1127
1175
  const liveScores = live?.scores ?? {};
1128
- const liveOverall = asScore(live?.overall);
1129
- const quality = clamp((asScore(liveScores?.[taskType]) ?? liveOverall ?? asScore(metadata.quality) ?? 0) + route.qualityBias);
1176
+ const liveOverall = live?.overallSource === "explicit" || live?.overallSource === void 0 && Object.keys(liveScores).length === 0 ? asScore(live?.overall) : void 0;
1177
+ const baseQuality = asScore(metadata.quality) ?? 0;
1178
+ const quality = clamp((asScore(liveScores?.[taskType]) ?? liveOverall ?? baseQuality) + route.qualityBias);
1179
+ const fallbackQualitySource = route.quality !== void 0 ? route.qualitySource : catalog ? "catalog-heuristic" : "unknown";
1130
1180
  const qualitySource = liveOverall !== void 0 || asScore(liveScores?.[taskType]) !== void 0 ? "livebench" : route.quality !== void 0 ? route.qualitySource : catalog ? "catalog-heuristic" : "unknown";
1131
1181
  const userPrice = normalizedPrices[normalize(`${route.provider}/${route.model}`)] ?? normalizedPrices[normalize(route.model)];
1132
1182
  const pricingRow = userPrice ?? route.pricing ?? null;
@@ -1137,9 +1187,14 @@ function buildPlan({ text: text6 = "", available = [], mode = "collective", pric
1137
1187
  model: route.model,
1138
1188
  metadata,
1139
1189
  quality,
1190
+ baseQuality,
1191
+ fallbackQualitySource,
1140
1192
  qualityBias: route.qualityBias,
1193
+ preferenceAdjustments: route.preferenceAdjustments,
1141
1194
  qualitySource,
1142
1195
  pricingSource,
1196
+ pricingVersion: route.pricingVersion,
1197
+ snapshotAsOf: route.snapshotAsOf,
1143
1198
  liveScores,
1144
1199
  liveOverall,
1145
1200
  latency: metadata.latency ?? 0.5,
@@ -1160,10 +1215,6 @@ function buildPlan({ text: text6 = "", available = [], mode = "collective", pric
1160
1215
  }, text6, 900, {}, cacheReadRatio, cacheWriteRatio)
1161
1216
  });
1162
1217
  }
1163
- const maxCost = Math.max(1, ...rows.filter((row) => row.pricing !== null).map((row) => {
1164
- const effective = effectivePricing(row.pricing, cacheReadRatio, cacheWriteRatio);
1165
- return effective.input + effective.output;
1166
- }));
1167
1218
  const taskNodes = taskPackages(taskType, text6, complexity.band).map((task) => presetId === DEFAULT_ROUTING_PRESET ? task : {
1168
1219
  ...task,
1169
1220
  qualityFloor: presetFloor(task.qualityFloor, presetId),
@@ -1175,7 +1226,6 @@ function buildPlan({ text: text6 = "", available = [], mode = "collective", pric
1175
1226
  rows,
1176
1227
  tasks: taskNodes,
1177
1228
  weights,
1178
- maxCost,
1179
1229
  text: text6,
1180
1230
  complexity: complexity.band,
1181
1231
  budget: Number.POSITIVE_INFINITY,
@@ -1186,7 +1236,6 @@ function buildPlan({ text: text6 = "", available = [], mode = "collective", pric
1186
1236
  rows,
1187
1237
  tasks: taskNodes,
1188
1238
  weights,
1189
- maxCost,
1190
1239
  text: text6,
1191
1240
  complexity: complexity.band,
1192
1241
  budget,
@@ -1197,7 +1246,6 @@ function buildPlan({ text: text6 = "", available = [], mode = "collective", pric
1197
1246
  rows,
1198
1247
  tasks: taskNodes,
1199
1248
  weights,
1200
- maxCost,
1201
1249
  text: text6,
1202
1250
  complexity: complexity.band,
1203
1251
  budget: Number.POSITIVE_INFINITY,
@@ -1210,7 +1258,8 @@ function buildPlan({ text: text6 = "", available = [], mode = "collective", pric
1210
1258
  const usedRoutes = optimized?.usedRoutes ?? /* @__PURE__ */ new Set();
1211
1259
  const constraintRelaxed = (optimized?.relaxedCount ?? 0) > 0;
1212
1260
  for (const row of rows) {
1213
- row.score = candidateUtility(row, taskNodes[0] ?? { type: taskType, qualityFloor: QUALITY_FLOORS[complexity.band] }, weights, maxCost, /* @__PURE__ */ new Set(), cacheReadRatio, cacheWriteRatio).score;
1261
+ row.score = candidateUtility(row, taskNodes[0] ?? { type: taskType, qualityFloor: QUALITY_FLOORS[complexity.band] }, weights, cacheReadRatio, cacheWriteRatio, text6, complexity.band).score;
1262
+ if (row.pricing !== null && taskNodes[0]) row.estimatedCost = taskCost(row, taskNodes[0], text6, complexity.band, cacheReadRatio, cacheWriteRatio);
1214
1263
  }
1215
1264
  rows.sort((left, right) => right.score - left.score || compareRowsStable(left, right));
1216
1265
  const selectedAssignment = assignments[0];
@@ -1225,7 +1274,7 @@ function buildPlan({ text: text6 = "", available = [], mode = "collective", pric
1225
1274
  difficulty: task.difficulty,
1226
1275
  recommended: row?.model ?? "\u5F85\u53D1\u73B0\u6A21\u578B",
1227
1276
  recommendedProvider: row?.provider ?? "",
1228
- qualitySource: row?.qualitySource ?? "unknown",
1277
+ qualitySource: qualitySourceForTask(row, task.type),
1229
1278
  pricingSource: row?.pricingSource ?? "unknown",
1230
1279
  recommendedReasoningEffort: decision?.reasoningEffort,
1231
1280
  preferredReasoningEffort: decision?.preferredReasoningEffort ?? task.preferredReasoningEffort,
@@ -1253,25 +1302,25 @@ function buildPlan({ text: text6 = "", available = [], mode = "collective", pric
1253
1302
  cacheWriteTokens: tokens.cacheWriteTokens,
1254
1303
  outputTokens: tokens.outputTokens,
1255
1304
  estimatedCost: row?.pricing === null || row === null ? null : Number(taskEstimate.toFixed(6)),
1256
- quality: row?.qualitySource === "unknown" || row === null ? null : Number(qualityForTask(row, task.type).toFixed(3)),
1257
- qualitySource: row?.qualitySource ?? "unknown",
1305
+ quality: qualitySourceForTask(row, task.type) === "unknown" || row === null ? null : Number(qualityForTask(row, task.type).toFixed(3)),
1306
+ qualitySource: qualitySourceForTask(row, task.type),
1258
1307
  pricingSource: row?.pricingSource ?? "unknown",
1259
1308
  handoffPenalty: Number(Number(handoffPenalty ?? 0).toFixed(3))
1260
1309
  };
1261
1310
  });
1262
1311
  const pricingComplete = assignments.length > 0 && assignments.every(({ row }) => row?.pricing !== null);
1263
- const totalEstimate = pricingComplete ? costBreakdown.reduce((sum, row) => sum + row.estimatedCost, 0) : null;
1312
+ const totalEstimate = pricingComplete ? assignments.reduce((sum, { task, row, estimatedCost }) => sum + (estimatedCost ?? taskCost(row, task, text6, complexity.band, cacheReadRatio, cacheWriteRatio)), 0) : null;
1264
1313
  const baselineRows = assignments.map(({ task }) => {
1265
- const strongest = rows.reduce((best, row) => qualityForTask(row, task.type) > (best === null ? -1 : qualityForTask(best, task.type)) ? row : best, null);
1314
+ const strongest = eligibleRowsForTask(rows, task).reduce((best, row) => qualityForTask(row, task.type) > (best === null ? -1 : qualityForTask(best, task.type)) ? row : best, null);
1266
1315
  return { task, strongest };
1267
1316
  });
1268
1317
  const baselineCost = baselineRows.every((item) => item.strongest?.pricing !== null && item.strongest !== null) ? baselineRows.reduce((sum, { task, strongest }) => sum + taskCost(strongest, task, text6, complexity.band, cacheReadRatio, cacheWriteRatio), 0) : null;
1269
- const qualityEvidenceComplete = assignments.length > 0 && assignments.every(({ row }) => ["livebench", "route", "user"].includes(row?.qualitySource)) && baselineRows.every(({ strongest }) => ["livebench", "route", "user"].includes(strongest?.qualitySource));
1318
+ const qualityEvidenceComplete = assignments.length > 0 && assignments.every(({ row, task }) => ["livebench", "route", "user"].includes(qualitySourceForTask(row, task.type))) && baselineRows.every(({ strongest, task }) => ["livebench", "route", "user"].includes(qualitySourceForTask(strongest, task.type)));
1270
1319
  const budgetExceeded = Number(budgetUsd) > 0 && totalEstimate !== null ? totalEstimate > Number(budgetUsd) : null;
1271
1320
  const savings = baselineCost === null || totalEstimate === null || !qualityEvidenceComplete ? null : baselineCost <= 0 ? 0 : clamp((baselineCost - totalEstimate) / baselineCost);
1272
1321
  const paretoPruned = (optimized?.candidatePools ?? []).reduce((sum, pool) => sum + pool.pruned, 0);
1273
1322
  const minimumFeasibleCost = rows.every((row) => row.pricing !== null) ? optimized?.minimumFeasibleCost ?? minimumCostPlan?.cost ?? 0 : null;
1274
- const reason = selected === null ? unassignableTasks.length > 0 ? `\u56FE\u50CF\u5DE5\u4F5C\u5305 ${unassignableTasks.join("\u3001")} \u6CA1\u6709\u53EF\u7528\u7684\u56FE\u50CF\u6A21\u578B\uFF0C\u65E0\u6CD5\u5F62\u6210\u5B8C\u6574\u5206\u914D\u8BA1\u5212\u3002` : "\u5C1A\u672A\u53D1\u73B0\u53EF\u7528\u6A21\u578B\uFF0C\u4FDD\u7559 Harness \u539F\u59CB\u6A21\u578B\u9009\u62E9\u3002" : `${complexity.band === "simple" ? "\u4F4E\u590D\u6742\u5EA6\u4F18\u5148\u6210\u672C\u3001\u54CD\u5E94\u901F\u5EA6\u4E0E\u8F83\u4F4E\u63A8\u7406\u5F00\u9500" : complexity.band === "balanced" ? "\u5728\u8D28\u91CF\u3001\u6210\u672C\u3001\u63A8\u7406\u7B49\u7EA7\u3001\u5EF6\u8FDF\u4E0E\u98CE\u9669\u4E4B\u95F4\u5E73\u8861" : "\u9AD8\u590D\u6742\u5EA6\u6267\u884C\u5305\u542B\u63A8\u7406\u7B49\u7EA7\u7684\u4F9D\u8D56\u611F\u77E5\u5168\u5C40\u7EA6\u675F\u5206\u914D"}\uFF1B\u4EFB\u52A1\u7C7B\u578B\u4E3A ${taskType}\uFF0C\u5DF2\u5BF9 ${String(subtasks.length)} \u4E2A\u5DE5\u4F5C\u5305\u8FDB\u884C Pareto \u526A\u679D\u548C\u6709\u754C\u7EC4\u5408\u641C\u7D22\u3002`;
1323
+ const reason = selected === null ? unassignableTasks.length > 0 ? `\u56FE\u50CF\u5DE5\u4F5C\u5305 ${unassignableTasks.join("\u3001")} \u6CA1\u6709\u53EF\u7528\u7684\u56FE\u50CF\u6A21\u578B\uFF0C\u65E0\u6CD5\u5F62\u6210\u5B8C\u6574\u5206\u914D\u8BA1\u5212\u3002` : "\u5C1A\u672A\u53D1\u73B0\u53EF\u7528\u6A21\u578B\uFF0C\u4FDD\u7559 Harness \u539F\u59CB\u6A21\u578B\u9009\u62E9\u3002" : `${complexity.band === "simple" ? "\u4F4E\u590D\u6742\u5EA6\u4F18\u5148\u6210\u672C\u3001\u54CD\u5E94\u901F\u5EA6\u4E0E\u8F83\u4F4E\u63A8\u7406\u5F00\u9500" : complexity.band === "balanced" ? "\u5728\u8D28\u91CF\u3001\u6210\u672C\u3001\u63A8\u7406\u7B49\u7EA7\u3001\u5EF6\u8FDF\u4E0E\u98CE\u9669\u4E4B\u95F4\u5E73\u8861" : "\u9AD8\u590D\u6742\u5EA6\u6267\u884C\u5305\u542B\u63A8\u7406\u7B49\u7EA7\u7684\u4F9D\u8D56\u611F\u77E5\u7EA6\u675F\u5206\u914D"}\uFF1B\u4EFB\u52A1\u7C7B\u578B\u4E3A ${taskType}\uFF0C${String(subtasks.length)} \u4E2A\u5DE5\u4F5C\u5305\u91C7\u7528${optimized?.search?.exact ? "\u4FDD\u7559\u5019\u9009\u7A7A\u95F4\u5185\u7684\u7CBE\u786E\u641C\u7D22" : "\u4FDD\u7559\u5019\u9009\u7A7A\u95F4\u5185\u7684\u6709\u754C\u8FD1\u4F3C\u641C\u7D22"}\u3002\u8D28\u91CF\u5206\u4E0E\u95E8\u69DB\u662F\u672A\u6821\u51C6\u7684\u4F30\u8BA1\uFF0C\u4E0D\u662F\u7B54\u5BF9\u6982\u7387\u3002`;
1275
1324
  return {
1276
1325
  mode,
1277
1326
  preset: presetId,
@@ -1282,16 +1331,39 @@ function buildPlan({ text: text6 = "", available = [], mode = "collective", pric
1282
1331
  taskTypes: [...new Set(taskNodes.map((task) => task.type).filter((type) => type !== "reasoning"))],
1283
1332
  objectiveWeights: weights,
1284
1333
  candidates: rows.slice(0, 8).map((row) => {
1285
- const decision = candidateUtility(row, taskNodes[0] ?? { type: taskType, qualityFloor: QUALITY_FLOORS[complexity.band], preferredReasoningEffort: complexity.band === "simple" ? "low" : "medium" }, weights, maxCost, /* @__PURE__ */ new Set(), cacheReadRatio, cacheWriteRatio);
1286
- return { provider: row.provider, model: row.model, score: Number(row.score.toFixed(3)), quality: row.qualitySource === "unknown" ? null : Number(row.quality.toFixed(3)), qualitySource: row.qualitySource, specialty: Number(row.specialty.toFixed(3)), reasoningEffort: decision.reasoningEffort, preferredReasoningEffort: decision.preferredReasoningEffort, reasoningFit: Number(decision.reasoningFit.toFixed(3)), reasoningKnown: row.reasoningKnown, reasoningEfforts: row.reasoningEfforts, estimatedCost: row.estimatedCost === null ? null : Number(row.estimatedCost.toFixed(6)), inputPrice: row.pricing?.input ?? null, outputPrice: row.pricing?.output ?? null, pricingSource: row.pricingSource };
1334
+ const decision = candidateUtility(row, taskNodes[0] ?? { type: taskType, qualityFloor: QUALITY_FLOORS[complexity.band], preferredReasoningEffort: complexity.band === "simple" ? "low" : "medium" }, weights, cacheReadRatio, cacheWriteRatio, text6, complexity.band);
1335
+ return { provider: row.provider, model: row.model, score: Number(row.score.toFixed(3)), preferenceAdjustment: decision.preferenceAdjustment, quality: row.qualitySource === "unknown" ? null : Number(row.quality.toFixed(3)), qualitySource: row.qualitySource, specialty: Number(row.specialty.toFixed(3)), reasoningEffort: decision.reasoningEffort, preferredReasoningEffort: decision.preferredReasoningEffort, reasoningFit: Number(decision.reasoningFit.toFixed(3)), reasoningKnown: row.reasoningKnown, reasoningEfforts: row.reasoningEfforts, estimatedCost: row.estimatedCost === null ? null : Number(row.estimatedCost.toFixed(6)), inputPrice: row.pricing?.input ?? null, outputPrice: row.pricing?.output ?? null, pricingSource: row.pricingSource, pricingVersion: row.pricingVersion, pricingAsOf: row.snapshotAsOf };
1287
1336
  }),
1288
- selected: selected === null ? null : { provider: selected.provider, model: selected.model, reasoningEffort: selectedAssignment?.decision?.reasoningEffort, estimatedCost: selected.estimatedCost === null ? null : Number(selected.estimatedCost.toFixed(6)), qualitySource: selected.qualitySource, pricingSource: selected.pricingSource },
1337
+ selected: selected === null ? null : { provider: selected.provider, model: selected.model, reasoningEffort: selectedAssignment?.decision?.reasoningEffort, estimatedCost: selected.estimatedCost === null ? null : Number(selected.estimatedCost.toFixed(6)), qualitySource: qualitySourceForTask(selected, selectedAssignment?.task.type ?? taskType), pricingSource: selected.pricingSource },
1289
1338
  subtasks,
1290
1339
  synthesizer: synthesizer == null ? null : { provider: synthesizer.provider, model: synthesizer.model, reasoningEffort: synthesizerAssignment?.decision?.reasoningEffort },
1291
- estimatedCost: totalEstimate === null ? null : Number(totalEstimate.toFixed(6)),
1340
+ // Preserve precision for downstream budget gates; formatting belongs to UI.
1341
+ estimatedCost: totalEstimate,
1292
1342
  costBreakdown,
1293
1343
  optimization: {
1294
- solver: "pareto-pruned quality-constrained beam assignment",
1344
+ dataVersions,
1345
+ personalization: learning ? {
1346
+ policyVersion: learning.policyVersion,
1347
+ revision: learning.revision,
1348
+ enabled: learning.enabled,
1349
+ scope: learning.scope,
1350
+ window: learning.window,
1351
+ feedbackCount: learning.feedbackCount,
1352
+ effectiveWeight: learning.effectiveWeight,
1353
+ halfLifeDays: learning.halfLifeDays,
1354
+ priorWeight: learning.priorWeight,
1355
+ maxAdjustment: learning.maxAdjustment,
1356
+ resetAt: learning.resetAt,
1357
+ semantics: "subjective-utility-not-objective-quality"
1358
+ } : null,
1359
+ solver: "dependency-safe quality-constrained exact/beam assignment",
1360
+ qualitySemantics: "uncalibrated-surrogate",
1361
+ costUtility: { method: "1/(1+estimated-task-cost/reference-task-cost)", referencePricing: COST_REFERENCE_PRICING },
1362
+ search: optimized?.search ?? null,
1363
+ optimalityScope: "retained-candidates-and-surrogate-objective",
1364
+ candidateTruncated: (optimized?.candidatePools ?? []).reduce((sum, pool) => sum + pool.truncated, 0),
1365
+ qualityFiltered: (optimized?.candidatePools ?? []).reduce((sum, pool) => sum + pool.filtered, 0),
1366
+ localParetoDisabled: (optimized?.candidatePools ?? []).some((pool) => pool.dependencySensitive),
1295
1367
  qualityFloor: QUALITY_FLOORS[complexity.band],
1296
1368
  budgetUsd: Number(Number(budgetUsd) > 0 ? Number(budgetUsd) : 0),
1297
1369
  cacheReadRatio: normalizedCacheRatios(cacheReadRatio, cacheWriteRatio).read,
@@ -1308,7 +1380,7 @@ function buildPlan({ text: text6 = "", available = [], mode = "collective", pric
1308
1380
  beamWidth: ROUTING_BEAM_WIDTH,
1309
1381
  budgetFeasible: budget <= 0 ? pricingComplete ? true : null : budgetPlan !== null,
1310
1382
  minimumFeasibleCost: minimumFeasibleCost === null ? null : Number(Number(minimumFeasibleCost).toFixed(6)),
1311
- liveBench: liveBench?.fetchedAt ? { source: liveBench.source ?? "livebench", fetchedAt: liveBench.fetchedAt, models: Object.keys(liveBench.models ?? {}).length, stale: String(liveBenchError).length > 0, error: String(liveBenchError || "") } : { source: "experimental-baseline", fetchedAt: null, models: 0, stale: false, error: String(liveBenchError || "") }
1383
+ liveBench: liveBench?.fetchedAt ?? liveBench?.verifiedAt ? { source: liveBench.source ?? "livebench", fetchedAt: liveBench.fetchedAt ?? liveBench.verifiedAt, verifiedAt: liveBench.verifiedAt ?? liveBench.fetchedAt, publishedAt: liveBench.publishedAt ?? null, version: liveBench.version ?? null, models: Object.keys(liveBench.models ?? {}).length, stale: String(liveBenchError).length > 0, error: String(liveBenchError || "") } : { source: "experimental-baseline", fetchedAt: null, models: 0, stale: false, error: String(liveBenchError || "") }
1312
1384
  },
1313
1385
  reason,
1314
1386
  generatedAt: (/* @__PURE__ */ new Date()).toISOString()
@@ -1379,6 +1451,9 @@ function createPlanFromRoutes(task, availableRoutes, {
1379
1451
  runnableToolIds = [],
1380
1452
  pricing = {},
1381
1453
  liveBench = null,
1454
+ liveBenchError = "",
1455
+ dataVersions = null,
1456
+ learning = null,
1382
1457
  cacheReadRatio = 0,
1383
1458
  cacheWriteRatio = 0,
1384
1459
  directProvider = "",
@@ -1417,6 +1492,9 @@ function createPlanFromRoutes(task, availableRoutes, {
1417
1492
  budgetUsd: Math.max(0, Number.isFinite(budgetUsd) ? budgetUsd : 0),
1418
1493
  pricing,
1419
1494
  liveBench,
1495
+ liveBenchError,
1496
+ dataVersions,
1497
+ learning,
1420
1498
  cacheReadRatio,
1421
1499
  cacheWriteRatio,
1422
1500
  preset
@@ -1433,7 +1511,7 @@ function createPlanFromRoutes(task, availableRoutes, {
1433
1511
  ...selectedChannel ? annotate(selectedChannel) : {},
1434
1512
  availabilityNotice: "\u6A21\u578B\u76EE\u5F55\u5217\u51FA\u7684\u8DEF\u7EBF\u5C1A\u672A\u9A8C\u8BC1\u5F53\u524D\u51ED\u636E\u548C\u7F51\u7EDC\uFF1B\u5B9E\u9645\u53EF\u7528\u6027\u4EE5\u5B98\u65B9\u9002\u914D\u5668\u8C03\u7528\u7ED3\u679C\u4E3A\u51C6\u3002",
1435
1513
  pricingNotice: plan.estimatedCost === null ? "\u90E8\u5206\u8DEF\u7EBF\u5C1A\u672A\u914D\u7F6E\u8BE5\u4F9B\u5E94\u5546\u7684\u7F8E\u5143\u8F93\u5165/\u8F93\u51FA\u5355\u4EF7\uFF0C\u65E0\u6CD5\u8BA1\u7B97\u53EF\u9760\u7684\u603B\u8D39\u7528\u4E0E\u8282\u7701\u6BD4\u4F8B\uFF1B\u8BF7\u5728\u6A21\u578B\u4EF7\u683C\u8BBE\u7F6E\u4E2D\u8865\u9F50\u3002" : "\u8D39\u7528\u6309\u5DF2\u63D0\u4F9B\u7684\u7F8E\u5143\u5355\u4EF7\u548C\u4F30\u8BA1 token \u6570\u8BA1\u7B97\uFF0C\u4E0D\u662F\u4F9B\u5E94\u5546\u8D26\u5355\uFF0C\u4E5F\u4E0D\u662F\u786C\u6027\u652F\u51FA\u4E0A\u9650\u3002",
1436
- qualityNotice: plan.optimization.qualityEvidenceComplete ? "\u6A21\u578B\u8D28\u91CF\u4F7F\u7528\u5DF2\u63D0\u4F9B\u8BC4\u5206\u6216\u57FA\u51C6\u6570\u636E\u4F30\u8BA1\uFF0C\u4ECD\u9700\u5B9E\u9645\u4EFB\u52A1\u9A8C\u8BC1\u3002" : "\u90E8\u5206\u6A21\u578B\u8D28\u91CF\u7F3A\u5C11\u53EF\u6838\u9A8C\u8BC4\u5206\uFF1B\u76EE\u5F55\u542F\u53D1\u5F0F\u53EA\u4F9B\u9009\u62E9\u53C2\u8003\uFF0C\u8D28\u91CF\u95E8\u69DB\u548C\u8282\u7701\u6BD4\u4F8B\u65E0\u6CD5\u4FDD\u8BC1\u3002",
1514
+ qualityNotice: plan.optimization.qualityEvidenceComplete ? "\u6A21\u578B\u8D28\u91CF\u4F7F\u7528\u5DF2\u63D0\u4F9B\u8BC4\u5206\u6216\u57FA\u51C6\u6570\u636E\u4F30\u8BA1\uFF1B\u5206\u6570\u4E0E\u95E8\u69DB\u4E0D\u662F\u7B54\u5BF9\u6982\u7387\uFF0C\u4E5F\u4E0D\u4FDD\u8BC1\u5B9E\u9645\u8D28\u91CF\uFF0C\u4ECD\u9700\u72EC\u7ACB\u4EFB\u52A1\u9A8C\u8BC1\u3002" : "\u90E8\u5206\u6A21\u578B\u8D28\u91CF\u7F3A\u5C11\u53EF\u6838\u9A8C\u8BC4\u5206\uFF1B\u76EE\u5F55\u542F\u53D1\u5F0F\u53EA\u4F9B\u9009\u62E9\u53C2\u8003\uFF0C\u8D28\u91CF\u95E8\u69DB\u548C\u8282\u7701\u6BD4\u4F8B\u65E0\u6CD5\u4FDD\u8BC1\u3002",
1437
1515
  modalityNotice: needsImage ? plan.unassignableTasks.length > 0 ? "\u56FE\u50CF\u5DE5\u4F5C\u5305\u6CA1\u6709\u53EF\u786E\u8BA4\u652F\u6301\u56FE\u50CF\u8F93\u5165\u7684\u8DEF\u7EBF\uFF0C\u5F53\u524D\u8BA1\u5212\u65E0\u6CD5\u5B8C\u6574\u5206\u914D\uFF1B\u8BF7\u5728\u5B98\u65B9\u6A21\u578B\u76EE\u5F55\u914D\u7F6E\u652F\u6301\u56FE\u50CF\u7684\u6A21\u578B\u3002" : routes.some((route) => !Array.isArray(route.inputModalities) || route.inputModalities.length === 0) ? "\u56FE\u50CF\u5DE5\u4F5C\u5305\u53EA\u5206\u7ED9\u5DF2\u58F0\u660E\u56FE\u50CF\u80FD\u529B\u6216\u672A\u58F0\u660E\u8F93\u5165\u80FD\u529B\u7684\u6A21\u578B\uFF1B\u672A\u58F0\u660E\u80FD\u529B\u7684\u6A21\u578B\u4ECD\u9700\u5B9E\u9645\u9A8C\u8BC1\u3002\u5176\u4ED6\u6587\u672C\u5DE5\u4F5C\u5305\u53EF\u7EE7\u7EED\u4F7F\u7528\u7ECF\u6D4E\u578B\u6587\u672C\u6A21\u578B\u3002" : "\u56FE\u50CF\u5DE5\u4F5C\u5305\u53EA\u5206\u7ED9\u660E\u786E\u652F\u6301\u56FE\u50CF\u8F93\u5165\u7684\u6A21\u578B\uFF1B\u5176\u4ED6\u6587\u672C\u5DE5\u4F5C\u5305\u53EF\u7EE7\u7EED\u4F7F\u7528\u7ECF\u6D4E\u578B\u6587\u672C\u6A21\u578B\u3002" : null,
1438
1516
  toolNotice: "\u6267\u884C\u6E20\u9053\u6309\u5B98\u65B9\u5DE5\u5177\u6CE8\u518C\u8868\u548C\u5DF2\u6838\u9A8C\u9002\u914D\u5668\u6807\u6CE8\uFF1Aofficial-cli \u8868\u793A\u8BE5\u5382\u5546\u5B98\u65B9 CLI \u5DF2\u5B89\u88C5\u4E14\u53EF\u6258\u7BA1\u6267\u884C\uFF1Bharness-llm \u8868\u793A\u901A\u8FC7\u5B98\u65B9\u6A21\u578B\u76EE\u5F55\u8C03\u7528\u3002\u53EF\u5728\u5DE5\u4F5C\u53F0\u67E5\u770B\u5B89\u88C5\u4E0E\u6267\u884C\u652F\u6301\u72B6\u6001\u3002",
1439
1517
  team: {
@@ -1464,6 +1542,24 @@ function createPlanFromRoutes(task, availableRoutes, {
1464
1542
  // .dsh-plugin/shared/run-ledger.mjs
1465
1543
  var finite = (value) => typeof value === "number" && Number.isFinite(value);
1466
1544
  var routeKey2 = (provider, model) => `${String(provider ?? "")}\0${String(model ?? "")}`;
1545
+ var MAX_SPENDING_DAYS = 90;
1546
+ var MAX_SPENDING_MONTHS = 24;
1547
+ function periodSpending(value) {
1548
+ const amount = (field2) => finite(value?.[field2]) && value[field2] >= 0 ? value[field2] : 0;
1549
+ return {
1550
+ costUsd: amount("costUsd"),
1551
+ unknown: Math.floor(amount("unknown")),
1552
+ subscriptionUsd: amount("subscriptionUsd"),
1553
+ subscriptionRuns: Math.floor(amount("subscriptionRuns"))
1554
+ };
1555
+ }
1556
+ function sanitizeArchivedSpending(value) {
1557
+ const periods = (entries, pattern, limit) => Object.fromEntries(Object.entries(entries && typeof entries === "object" && !Array.isArray(entries) ? entries : {}).filter(([key, entry]) => pattern.test(key) && entry && typeof entry === "object" && !Array.isArray(entry)).sort(([left], [right]) => left.localeCompare(right)).slice(-limit).map(([key, entry]) => [key, periodSpending(entry)]));
1558
+ return {
1559
+ days: periods(value?.days, /^\d{4}-(?:0[1-9]|1[0-2])-(?:0[1-9]|[12]\d|3[01])$/, MAX_SPENDING_DAYS),
1560
+ months: periods(value?.months, /^\d{4}-(?:0[1-9]|1[0-2])$/, MAX_SPENDING_MONTHS)
1561
+ };
1562
+ }
1467
1563
  function formatUsd(value) {
1468
1564
  return typeof value === "number" && Number.isFinite(value) ? `$${value.toFixed(4)}` : "\u2014";
1469
1565
  }
@@ -1491,32 +1587,88 @@ function applyQualityBiases(routes, biases) {
1491
1587
  });
1492
1588
  }
1493
1589
 
1494
- // .dsh-plugin/client/catalog.mjs
1590
+ // .dsh-plugin/shared/adaptive-feedback.mjs
1591
+ var finite2 = (value) => typeof value === "number" && Number.isFinite(value);
1495
1592
  var clean3 = (value) => typeof value === "string" ? value.trim() : "";
1593
+ var routeKey3 = (provider, model) => `${provider}\0${model}`;
1594
+ function applyFeedbackProfile(routes, profile) {
1595
+ if (!Array.isArray(routes) || profile?.enabled !== true || !profile.adjustments || typeof profile.adjustments !== "object" || Array.isArray(profile.adjustments)) return routes;
1596
+ return routes.map((route) => {
1597
+ if (!route || typeof route !== "object") return route;
1598
+ const key = routeKey3(clean3(route.provider), clean3(route.model));
1599
+ if (!Object.hasOwn(profile.adjustments, key)) return route;
1600
+ const value = profile.adjustments[key];
1601
+ if (!value || typeof value !== "object" || Array.isArray(value)) return route;
1602
+ const adjustments = Object.fromEntries(Object.entries(value).filter(([, bias]) => finite2(bias) && Math.abs(bias) <= 0.1));
1603
+ if (!Object.keys(adjustments).length) return route;
1604
+ return {
1605
+ ...route,
1606
+ preferenceAdjustments: adjustments,
1607
+ preferenceAdjustmentMeta: {
1608
+ policyVersion: profile.policyVersion,
1609
+ revision: profile.revision,
1610
+ scope: profile.scope,
1611
+ feedbackCount: profile.feedbackCount,
1612
+ effectiveWeight: profile.effectiveWeight,
1613
+ updatedAt: profile.updatedAt,
1614
+ halfLifeDays: profile.halfLifeDays,
1615
+ maxAdjustment: profile.maxAdjustment,
1616
+ window: profile.window
1617
+ }
1618
+ };
1619
+ });
1620
+ }
1621
+
1622
+ // .dsh-plugin/shared/dynamic-data-view.mjs
1623
+ var exactRouteKey = (route) => `${String(route?.provider ?? "")}\0${String(route?.model ?? "")}`;
1624
+ function applyPricingSnapshot(routes, snapshot) {
1625
+ if (snapshot?.kind !== "pricing" || !snapshot.prices || typeof snapshot.prices !== "object") return routes;
1626
+ return (Array.isArray(routes) ? routes : []).map((route) => {
1627
+ if (route?.pricingSource === "user") return route;
1628
+ const entry = snapshot.prices[exactRouteKey(route)];
1629
+ if (!entry) return route;
1630
+ return {
1631
+ ...route,
1632
+ pricing: {
1633
+ input: entry.input,
1634
+ output: entry.output,
1635
+ currency: "USD",
1636
+ ...entry.cacheRead === void 0 ? {} : { cacheRead: entry.cacheRead },
1637
+ ...entry.cacheWrite === void 0 ? {} : { cacheWrite: entry.cacheWrite }
1638
+ },
1639
+ pricingSource: "dynamic",
1640
+ pricingVersion: snapshot.version,
1641
+ snapshotAsOf: entry.asOf
1642
+ };
1643
+ });
1644
+ }
1645
+
1646
+ // .dsh-plugin/client/catalog.mjs
1647
+ var clean4 = (value) => typeof value === "string" ? value.trim() : "";
1496
1648
  function routesFromModelCatalog(catalog) {
1497
1649
  const groups = Array.isArray(catalog?.groups) ? catalog.groups : [];
1498
1650
  const routable = new Set(Array.isArray(catalog?.routableProviders) ? catalog.routableProviders : []);
1499
1651
  const routes = [];
1500
1652
  const seen = /* @__PURE__ */ new Set();
1501
1653
  for (const group of groups) {
1502
- const provider = clean3(group?.id);
1654
+ const provider = clean4(group?.id);
1503
1655
  if (!provider || !routable.has(provider)) continue;
1504
1656
  for (const entry of Array.isArray(group.models) ? group.models : []) {
1505
- const model = clean3(entry?.id);
1657
+ const model = clean4(entry?.id);
1506
1658
  if (!model) continue;
1507
1659
  const key = `${provider}\0${model}`;
1508
1660
  if (seen.has(key)) continue;
1509
1661
  seen.add(key);
1510
1662
  const reasoning = entry?.reasoning;
1511
- const efforts = Array.isArray(reasoning?.efforts) ? [...new Set(reasoning.efforts.map((item) => clean3(item?.id ?? item)).filter(Boolean))] : [];
1663
+ const efforts = Array.isArray(reasoning?.efforts) ? [...new Set(reasoning.efforts.map((item) => clean4(item?.id ?? item)).filter(Boolean))] : [];
1512
1664
  routes.push({
1513
1665
  provider,
1514
- providerName: clean3(group.name) || provider,
1666
+ providerName: clean4(group.name) || provider,
1515
1667
  model,
1516
- name: clean3(entry.name) || model,
1668
+ name: clean4(entry.name) || model,
1517
1669
  reasoningKnown: reasoning !== void 0 && reasoning !== null,
1518
1670
  reasoningEfforts: efforts,
1519
- ...clean3(reasoning?.defaultEffort) ? { defaultReasoningEffort: clean3(reasoning.defaultEffort) } : {},
1671
+ ...clean4(reasoning?.defaultEffort) ? { defaultReasoningEffort: clean4(reasoning.defaultEffort) } : {},
1520
1672
  // modelCatalog deliberately omits modalities; unknown means the Host
1521
1673
  // must still validate image capability before a real request.
1522
1674
  inputModalities: []
@@ -1527,10 +1679,9 @@ function routesFromModelCatalog(catalog) {
1527
1679
  return routes;
1528
1680
  }
1529
1681
  function createWorkspacePlan(task, catalog, options = {}) {
1530
- const routes = applyQualityBiases(applyModelProfiles(
1531
- routesFromModelCatalog(catalog),
1532
- parseModelProfilesJson(options.modelProfilesJson ?? "[]")
1533
- ), options.qualityBiases ?? null);
1682
+ const profiled = applyModelProfiles(routesFromModelCatalog(catalog), parseModelProfilesJson(options.modelProfilesJson ?? "[]"));
1683
+ const priced = applyPricingSnapshot(profiled, options.pricingSnapshot ?? null);
1684
+ const routes = options.learning ? applyFeedbackProfile(priced, options.learning) : applyQualityBiases(priced, options.qualityBiases ?? null);
1534
1685
  return createPlanFromRoutes(task, routes, options);
1535
1686
  }
1536
1687
 
@@ -1557,6 +1708,7 @@ function profileDraft(profile) {
1557
1708
  cacheWrite: profile?.pricing?.cacheWrite === void 0 ? "" : String(profile.pricing.cacheWrite),
1558
1709
  specialties: Array.isArray(profile?.specialties) ? profile.specialties.join(", ") : "",
1559
1710
  cliModel: profile?.cliModel ?? "",
1711
+ benchmarkModel: profile?.benchmarkModel ?? "",
1560
1712
  execution: profile?.execution === "official" || profile?.execution === "api" ? profile.execution : "auto",
1561
1713
  billing: BILLING_MODES.includes(profile?.billing) ? profile.billing : DEFAULT_BILLING_MODE,
1562
1714
  subscription: ["plan-key", "cli-login", "none"].includes(profile?.subscription) ? profile.subscription : "auto",
@@ -1568,6 +1720,8 @@ function profileFromDraft(route, draft) {
1568
1720
  const model = field(route?.model);
1569
1721
  if (!provider || !model) throw new Error("\u8BF7\u5148\u4ECE\u5B98\u65B9\u6A21\u578B\u76EE\u5F55\u9009\u62E9\u4E00\u6761\u51C6\u786E\u7684\u6A21\u578B\u8DEF\u7EBF\u3002");
1570
1722
  const profile = { provider, model };
1723
+ const benchmarkModel = field(draft?.benchmarkModel);
1724
+ if (benchmarkModel) profile.benchmarkModel = benchmarkModel;
1571
1725
  const quality = nonnegativeField(draft?.quality, "\u8D28\u91CF\u8BC4\u5206", 100);
1572
1726
  if (quality !== null) profile.quality = quality;
1573
1727
  const input = nonnegativeField(draft?.input, "\u8F93\u5165\u5355\u4EF7");
@@ -1637,7 +1791,7 @@ function ModelProfileEditor({ routes, settingsScope, onSaved }) {
1637
1791
  const [notice, setNotice] = import_react.default.useState(null);
1638
1792
  import_react.default.useEffect(() => settingsScope.subscribe(() => setSnapshot(settingsScope.getSnapshot())), [settingsScope]);
1639
1793
  const route = routes.find((item) => profileRouteKey(item) === selected) ?? routes[0];
1640
- const routeKey3 = route ? profileRouteKey(route) : "";
1794
+ const routeKey4 = route ? profileRouteKey(route) : "";
1641
1795
  const rawJson = snapshot.value?.modelProfilesJson ?? "[]";
1642
1796
  let profiles = [];
1643
1797
  let loadError = "";
@@ -1646,16 +1800,16 @@ function ModelProfileEditor({ routes, settingsScope, onSaved }) {
1646
1800
  } catch (error) {
1647
1801
  loadError = messageOf(error);
1648
1802
  }
1649
- const saved = profiles.find((item) => profileRouteKey(item) === routeKey3);
1650
- const pending = drafts[routeKey3];
1803
+ const saved = profiles.find((item) => profileRouteKey(item) === routeKey4);
1804
+ const pending = drafts[routeKey4];
1651
1805
  const draft = pending?.fields ?? profileDraft(saved);
1652
1806
  const writable = snapshot.status === "ready" && snapshot.writable === true && !saving && !loadError;
1653
1807
  const unmatched = profiles.filter((item) => !routes.some((route2) => profileRouteKey(route2) === profileRouteKey(item))).length;
1654
1808
  const edit = (name, value) => {
1655
1809
  if (!route || !writable) return;
1656
1810
  setDrafts((previous) => {
1657
- const previousEntry = previous[routeKey3] ?? { fields: profileDraft(saved), baseRevision: snapshot.revision };
1658
- return { ...previous, [routeKey3]: { ...previousEntry, fields: { ...previousEntry.fields, [name]: value } } };
1811
+ const previousEntry = previous[routeKey4] ?? { fields: profileDraft(saved), baseRevision: snapshot.revision };
1812
+ return { ...previous, [routeKey4]: { ...previousEntry, fields: { ...previousEntry.fields, [name]: value } } };
1659
1813
  });
1660
1814
  setNotice(null);
1661
1815
  };
@@ -1680,7 +1834,7 @@ function ModelProfileEditor({ routes, settingsScope, onSaved }) {
1680
1834
  if (!accepted) throw new Error("\u8BBE\u7F6E\u672A\u88AB\u4FDD\u5B58\uFF0C\u53EF\u80FD\u88AB\u5176\u4ED6\u9875\u9762\u4FEE\u6539\u3002\u8F93\u5165\u5DF2\u4FDD\u7559\uFF0C\u8BF7\u91CD\u65B0\u52A0\u8F7D\u540E\u6838\u5BF9\u3002");
1681
1835
  setDrafts((previous) => {
1682
1836
  const next = { ...previous };
1683
- delete next[routeKey3];
1837
+ delete next[routeKey4];
1684
1838
  return next;
1685
1839
  });
1686
1840
  setNotice({ tone: "success", text: remove ? "\u5DF2\u5220\u9664\u8BE5\u6A21\u578B\u7684\u81EA\u62A5\u914D\u7F6E\u3002" : "\u8BE5\u6A21\u578B\u914D\u7F6E\u5DF2\u4FDD\u5B58\uFF1B\u91CD\u65B0\u751F\u6210\u5EFA\u8BAE\u5373\u53EF\u4F7F\u7528\u3002" });
@@ -1694,15 +1848,15 @@ function ModelProfileEditor({ routes, settingsScope, onSaved }) {
1694
1848
  const reload = () => {
1695
1849
  setDrafts((previous) => {
1696
1850
  const next = { ...previous };
1697
- delete next[routeKey3];
1851
+ delete next[routeKey4];
1698
1852
  return next;
1699
1853
  });
1700
1854
  setNotice(null);
1701
1855
  };
1702
- return /* @__PURE__ */ import_react.default.createElement("section", { className: "mr-card mr-profile-card", "aria-label": "\u9010\u6A21\u578B\u4EF7\u683C\u4E0E\u80FD\u529B\u914D\u7F6E" }, /* @__PURE__ */ import_react.default.createElement("div", { className: "mr-card-head" }, /* @__PURE__ */ import_react.default.createElement("div", null, /* @__PURE__ */ import_react.default.createElement("h2", { className: "mr-card-title" }, "\u9010\u6A21\u578B\u4EF7\u683C\u4E0E\u80FD\u529B"), /* @__PURE__ */ import_react.default.createElement("p", { className: "mr-card-copy" }, "\u9009\u62E9\u5B98\u65B9\u6A21\u578B\u76EE\u5F55\u4E2D\u7684\u51C6\u786E\u8DEF\u7EBF\uFF0C\u586B\u5199\u4F60\u638C\u63E1\u7684\u8D28\u91CF\u8BC4\u5206\u4E0E\u5355\u4EF7\u3002\u914D\u7F6E\u7531\u4F60\u63D0\u4F9B\uFF0C\u63D2\u4EF6\u4E0D\u4F1A\u8BFB\u53D6\u8D26\u53F7\u5BC6\u94A5\u3002"))), /* @__PURE__ */ import_react.default.createElement("div", { className: "mr-card-body" }, loadError && /* @__PURE__ */ import_react.default.createElement("p", { className: "mr-error", role: "alert" }, "\u5DF2\u6709\u914D\u7F6E\u65E0\u6CD5\u89E3\u6790\uFF1A", loadError, "\u3002\u8BF7\u5148\u5728\u63D2\u4EF6\u8BBE\u7F6E\u9875\u4FEE\u6B63 JSON\u3002"), snapshot.status !== "ready" && /* @__PURE__ */ import_react.default.createElement("p", { className: "mr-caption" }, "\u8BBE\u7F6E\u72B6\u6001\uFF1A", snapshot.status === "loading" ? "\u6B63\u5728\u52A0\u8F7D" : "\u5F53\u524D\u4E0D\u53EF\u7528"), snapshot.status === "ready" && !snapshot.writable && /* @__PURE__ */ import_react.default.createElement("p", { className: "mr-error", role: "status" }, "\u5F53\u524D\u8BBE\u7F6E\u4E3A\u53EA\u8BFB\uFF0C\u8BF7\u5728\u53EF\u5199\u7684\u672C\u673A\u73AF\u5883\u914D\u7F6E\u3002"), routes.length === 0 ? /* @__PURE__ */ import_react.default.createElement("p", { className: "mr-empty" }, "\u8BF7\u5148\u5728 DeepSeek Harness \u7684\u201C\u6A21\u578B\u201D\u9875\u6DFB\u52A0\u6A21\u578B\uFF0C\u518D\u8FD4\u56DE\u8FD9\u91CC\u586B\u5199\u4EF7\u683C\u4E0E\u80FD\u529B\u3002") : /* @__PURE__ */ import_react.default.createElement(import_react.default.Fragment, null, /* @__PURE__ */ import_react.default.createElement("label", { className: "mr-label", htmlFor: "mr-profile-route" }, "\u6A21\u578B\u8DEF\u7EBF"), /* @__PURE__ */ import_react.default.createElement("select", { className: "mr-input", id: "mr-profile-route", value: routeKey3, onChange: (event) => {
1856
+ return /* @__PURE__ */ import_react.default.createElement("section", { className: "mr-card mr-profile-card", "aria-label": "\u9010\u6A21\u578B\u4EF7\u683C\u4E0E\u80FD\u529B\u914D\u7F6E" }, /* @__PURE__ */ import_react.default.createElement("div", { className: "mr-card-head" }, /* @__PURE__ */ import_react.default.createElement("div", null, /* @__PURE__ */ import_react.default.createElement("h2", { className: "mr-card-title" }, "\u9010\u6A21\u578B\u4EF7\u683C\u4E0E\u80FD\u529B"), /* @__PURE__ */ import_react.default.createElement("p", { className: "mr-card-copy" }, "\u9009\u62E9\u5B98\u65B9\u6A21\u578B\u76EE\u5F55\u4E2D\u7684\u51C6\u786E\u8DEF\u7EBF\uFF0C\u586B\u5199\u4F60\u638C\u63E1\u7684\u8D28\u91CF\u8BC4\u5206\u4E0E\u5355\u4EF7\u3002\u914D\u7F6E\u7531\u4F60\u63D0\u4F9B\uFF0C\u63D2\u4EF6\u4E0D\u4F1A\u8BFB\u53D6\u8D26\u53F7\u5BC6\u94A5\u3002"))), /* @__PURE__ */ import_react.default.createElement("div", { className: "mr-card-body" }, loadError && /* @__PURE__ */ import_react.default.createElement("p", { className: "mr-error", role: "alert" }, "\u5DF2\u6709\u914D\u7F6E\u65E0\u6CD5\u89E3\u6790\uFF1A", loadError, "\u3002\u8BF7\u5148\u5728\u63D2\u4EF6\u8BBE\u7F6E\u9875\u4FEE\u6B63 JSON\u3002"), snapshot.status !== "ready" && /* @__PURE__ */ import_react.default.createElement("p", { className: "mr-caption" }, "\u8BBE\u7F6E\u72B6\u6001\uFF1A", snapshot.status === "loading" ? "\u6B63\u5728\u52A0\u8F7D" : "\u5F53\u524D\u4E0D\u53EF\u7528"), snapshot.status === "ready" && !snapshot.writable && /* @__PURE__ */ import_react.default.createElement("p", { className: "mr-error", role: "status" }, "\u5F53\u524D\u8BBE\u7F6E\u4E3A\u53EA\u8BFB\uFF0C\u8BF7\u5728\u53EF\u5199\u7684\u672C\u673A\u73AF\u5883\u914D\u7F6E\u3002"), routes.length === 0 ? /* @__PURE__ */ import_react.default.createElement("p", { className: "mr-empty" }, "\u8BF7\u5148\u5728 DeepSeek Harness \u7684\u201C\u6A21\u578B\u201D\u9875\u6DFB\u52A0\u6A21\u578B\uFF0C\u518D\u8FD4\u56DE\u8FD9\u91CC\u586B\u5199\u4EF7\u683C\u4E0E\u80FD\u529B\u3002") : /* @__PURE__ */ import_react.default.createElement(import_react.default.Fragment, null, /* @__PURE__ */ import_react.default.createElement("label", { className: "mr-label", htmlFor: "mr-profile-route" }, "\u6A21\u578B\u8DEF\u7EBF"), /* @__PURE__ */ import_react.default.createElement("select", { className: "mr-input", id: "mr-profile-route", value: routeKey4, onChange: (event) => {
1703
1857
  setSelected(event.target.value);
1704
1858
  setNotice(null);
1705
- } }, routes.map((item) => /* @__PURE__ */ import_react.default.createElement("option", { key: profileRouteKey(item), value: profileRouteKey(item) }, item.provider, "/", item.model))), /* @__PURE__ */ import_react.default.createElement("p", { className: "mr-caption mr-profile-state" }, saved ? `\u5DF2\u914D\u7F6E${saved.pricing ? "\u5355\u4EF7" : "\u80FD\u529B\uFF0C\u4EF7\u683C\u672A\u77E5"}` : "\u672A\u914D\u7F6E\uFF0C\u4EF7\u683C\u4E0E\u8D28\u91CF\u6765\u6E90\u672A\u77E5", pending ? " \xB7 \u5F53\u524D\u6709\u672A\u4FDD\u5B58\u8F93\u5165" : "", unmatched > 0 ? ` \xB7 \u53E6\u6709 ${unmatched} \u6761\u914D\u7F6E\u4E0D\u5728\u5F53\u524D\u6A21\u578B\u76EE\u5F55\u4E2D\uFF0C\u4FDD\u5B58\u65F6\u4F1A\u4FDD\u7559` : ""), /* @__PURE__ */ import_react.default.createElement("div", { className: "mr-profile-grid" }, /* @__PURE__ */ import_react.default.createElement("label", { className: "mr-profile-field" }, /* @__PURE__ */ import_react.default.createElement("span", null, "\u8D28\u91CF\u8BC4\u5206\uFF080\u2013100\uFF0C\u81EA\u62A5\uFF09"), /* @__PURE__ */ import_react.default.createElement("input", { className: "mr-input", type: "number", min: "0", max: "100", step: "any", value: draft.quality, disabled: !writable, onChange: (event) => edit("quality", event.target.value), placeholder: "\u4F8B\u5982 85\uFF1B\u7559\u7A7A\u8868\u793A\u672A\u77E5" })), /* @__PURE__ */ import_react.default.createElement("label", { className: "mr-profile-field" }, /* @__PURE__ */ import_react.default.createElement("span", null, "\u8F93\u5165\u5355\u4EF7\uFF08USD / \u767E\u4E07 token\uFF09"), /* @__PURE__ */ import_react.default.createElement("input", { className: "mr-input", type: "number", min: "0", step: "any", value: draft.input, disabled: !writable, onChange: (event) => edit("input", event.target.value), placeholder: "\u7559\u7A7A\u8868\u793A\u672A\u77E5" })), /* @__PURE__ */ import_react.default.createElement("label", { className: "mr-profile-field" }, /* @__PURE__ */ import_react.default.createElement("span", null, "\u8F93\u51FA\u5355\u4EF7\uFF08USD / \u767E\u4E07 token\uFF09"), /* @__PURE__ */ import_react.default.createElement("input", { className: "mr-input", type: "number", min: "0", step: "any", value: draft.output, disabled: !writable, onChange: (event) => edit("output", event.target.value), placeholder: "\u7559\u7A7A\u8868\u793A\u672A\u77E5" })), /* @__PURE__ */ import_react.default.createElement("label", { className: "mr-profile-field" }, /* @__PURE__ */ import_react.default.createElement("span", null, "\u64C5\u957F\u65B9\u5411\uFF08\u82F1\u6587\u6807\u7B7E\uFF0C\u9017\u53F7\u5206\u9694\uFF09"), /* @__PURE__ */ import_react.default.createElement("input", { className: "mr-input", type: "text", value: draft.specialties, disabled: !writable, onChange: (event) => edit("specialties", event.target.value), placeholder: PROFILE_SPECIALTY_HINT })), /* @__PURE__ */ import_react.default.createElement("label", { className: "mr-profile-field" }, /* @__PURE__ */ import_react.default.createElement("span", null, "\u5B98\u65B9 CLI \u6A21\u578B\u540D\uFF08\u53EF\u9009\uFF09"), /* @__PURE__ */ import_react.default.createElement("input", { className: "mr-input", type: "text", value: draft.cliModel, disabled: !writable, onChange: (event) => edit("cliModel", event.target.value), placeholder: "\u4EC5\u5728\u5382\u5546 CLI \u652F\u6301\u8BE5\u51C6\u786E\u540D\u79F0\u65F6\u586B\u5199" })), /* @__PURE__ */ import_react.default.createElement("label", { className: "mr-profile-field" }, /* @__PURE__ */ import_react.default.createElement("span", null, "\u6267\u884C\u65B9\u5F0F"), /* @__PURE__ */ import_react.default.createElement("select", { className: "mr-input", value: draft.execution || "auto", disabled: !writable, onChange: (event) => edit("execution", event.target.value) }, /* @__PURE__ */ import_react.default.createElement("option", { value: "auto" }, "\u81EA\u52A8\uFF1A\u5DF2\u5B89\u88C5\u5219\u7528\u5B98\u65B9\u5DE5\u5177\uFF0C\u5931\u8D25\u56DE\u9000 API"), /* @__PURE__ */ import_react.default.createElement("option", { value: "official" }, "\u5B98\u65B9\u5DE5\u5177\uFF1A\u5931\u8D25\u6216\u672A\u5B89\u88C5\u65F6\u56DE\u9000 API"), /* @__PURE__ */ import_react.default.createElement("option", { value: "api" }, "\u4EC5\u6A21\u578B\u76EE\u5F55 API"))), /* @__PURE__ */ import_react.default.createElement("label", { className: "mr-profile-field" }, /* @__PURE__ */ import_react.default.createElement("span", null, "\u8BA1\u8D39\u65B9\u5F0F"), /* @__PURE__ */ import_react.default.createElement("select", { className: "mr-input", value: draft.billing, disabled: !writable, onChange: (event) => edit("billing", event.target.value) }, /* @__PURE__ */ import_react.default.createElement("option", { value: "subscription-first" }, "\u8BA2\u9605\u4F18\u5148\uFF1A\u989D\u5EA6\u7528\u5C3D\u6216\u9650\u6D41\u65F6\u5207\u6362 API Key"), /* @__PURE__ */ import_react.default.createElement("option", { value: "api-only" }, "\u53EA\u7528 API Key"), /* @__PURE__ */ import_react.default.createElement("option", { value: "subscription-only" }, "\u53EA\u7528\u8BA2\u9605\uFF1A\u989D\u5EA6\u7528\u5C3D\u65F6\u4E0D\u5207\u6362"))), /* @__PURE__ */ import_react.default.createElement("label", { className: "mr-profile-field" }, /* @__PURE__ */ import_react.default.createElement("span", null, "\u8BA2\u9605\u6765\u6E90"), /* @__PURE__ */ import_react.default.createElement("select", { className: "mr-input", value: draft.subscription, disabled: !writable, onChange: (event) => edit("subscription", event.target.value) }, /* @__PURE__ */ import_react.default.createElement("option", { value: "auto" }, "\u81EA\u52A8\uFF1A\u6709\u5B98\u65B9 CLI \u65F6\u7528 CLI \u8D26\u53F7\u767B\u5F55"), /* @__PURE__ */ import_react.default.createElement("option", { value: "plan-key" }, "\u7F16\u7A0B\u5957\u9910 Key\uFF1A\u8BE5\u8DEF\u7EBF\u672C\u8EAB\u662F\u5957\u9910\u7AEF\u70B9"), /* @__PURE__ */ import_react.default.createElement("option", { value: "cli-login" }, "\u5B98\u65B9 CLI \u8D26\u53F7\u767B\u5F55"), /* @__PURE__ */ import_react.default.createElement("option", { value: "none" }, "\u65E0\u8BA2\u9605\uFF1A\u59CB\u7EC8\u6309 API \u8BA1\u8D39"))), draft.subscription === "plan-key" && /* @__PURE__ */ import_react.default.createElement("label", { className: "mr-profile-field" }, /* @__PURE__ */ import_react.default.createElement("span", null, "\u989D\u5EA6\u7528\u5C3D\u65F6\u56DE\u9000\u7684 API \u8DEF\u7EBF"), /* @__PURE__ */ import_react.default.createElement("select", { className: "mr-input", value: draft.apiRoute, disabled: !writable, onChange: (event) => edit("apiRoute", event.target.value) }, /* @__PURE__ */ import_react.default.createElement("option", { value: "" }, "\u4E0D\u56DE\u9000\uFF08\u672A\u914D\u7F6E API \u8DEF\u7EBF\uFF09"), routes.filter((item) => profileRouteKey(item) !== routeKey3).map((item) => /* @__PURE__ */ import_react.default.createElement("option", { key: profileRouteKey(item), value: profileRouteKey(item) }, item.provider, "/", item.model))))), /* @__PURE__ */ import_react.default.createElement("details", { className: "mr-profile-advanced" }, /* @__PURE__ */ import_react.default.createElement("summary", null, "\u7F13\u5B58\u5355\u4EF7\uFF08\u53EF\u9009\uFF09"), /* @__PURE__ */ import_react.default.createElement("div", { className: "mr-profile-grid" }, /* @__PURE__ */ import_react.default.createElement("label", { className: "mr-profile-field" }, /* @__PURE__ */ import_react.default.createElement("span", null, "\u7F13\u5B58\u8BFB\u53D6\uFF08USD / \u767E\u4E07 token\uFF09"), /* @__PURE__ */ import_react.default.createElement("input", { className: "mr-input", type: "number", min: "0", step: "any", value: draft.cacheRead, disabled: !writable, onChange: (event) => edit("cacheRead", event.target.value), placeholder: "\u7559\u7A7A\u6309\u666E\u901A\u8F93\u5165\u4EF7\u683C\u4F30\u7B97" })), /* @__PURE__ */ import_react.default.createElement("label", { className: "mr-profile-field" }, /* @__PURE__ */ import_react.default.createElement("span", null, "\u7F13\u5B58\u5199\u5165\uFF08USD / \u767E\u4E07 token\uFF09"), /* @__PURE__ */ import_react.default.createElement("input", { className: "mr-input", type: "number", min: "0", step: "any", value: draft.cacheWrite, disabled: !writable, onChange: (event) => edit("cacheWrite", event.target.value), placeholder: "\u7559\u7A7A\u6309\u666E\u901A\u8F93\u5165\u4EF7\u683C\u4F30\u7B97" })))), /* @__PURE__ */ import_react.default.createElement("div", { className: "mr-actions" }, /* @__PURE__ */ import_react.default.createElement("button", { className: "mr-button", type: "button", disabled: !writable || !pending, onClick: () => {
1859
+ } }, routes.map((item) => /* @__PURE__ */ import_react.default.createElement("option", { key: profileRouteKey(item), value: profileRouteKey(item) }, item.provider, "/", item.model))), /* @__PURE__ */ import_react.default.createElement("p", { className: "mr-caption mr-profile-state" }, saved ? `\u5DF2\u914D\u7F6E${saved.pricing ? "\u5355\u4EF7" : "\u80FD\u529B\uFF0C\u4EF7\u683C\u672A\u77E5"}` : "\u672A\u914D\u7F6E\uFF0C\u4EF7\u683C\u4E0E\u8D28\u91CF\u6765\u6E90\u672A\u77E5", pending ? " \xB7 \u5F53\u524D\u6709\u672A\u4FDD\u5B58\u8F93\u5165" : "", unmatched > 0 ? ` \xB7 \u53E6\u6709 ${unmatched} \u6761\u914D\u7F6E\u4E0D\u5728\u5F53\u524D\u6A21\u578B\u76EE\u5F55\u4E2D\uFF0C\u4FDD\u5B58\u65F6\u4F1A\u4FDD\u7559` : ""), /* @__PURE__ */ import_react.default.createElement("div", { className: "mr-profile-grid" }, /* @__PURE__ */ import_react.default.createElement("label", { className: "mr-profile-field" }, /* @__PURE__ */ import_react.default.createElement("span", null, "\u8D28\u91CF\u8BC4\u5206\uFF080\u2013100\uFF0C\u81EA\u62A5\uFF09"), /* @__PURE__ */ import_react.default.createElement("input", { className: "mr-input", type: "number", min: "0", max: "100", step: "any", value: draft.quality, disabled: !writable, onChange: (event) => edit("quality", event.target.value), placeholder: "\u4F8B\u5982 85\uFF1B\u7559\u7A7A\u8868\u793A\u672A\u77E5" })), /* @__PURE__ */ import_react.default.createElement("label", { className: "mr-profile-field" }, /* @__PURE__ */ import_react.default.createElement("span", null, "\u8F93\u5165\u5355\u4EF7\uFF08USD / \u767E\u4E07 token\uFF09"), /* @__PURE__ */ import_react.default.createElement("input", { className: "mr-input", type: "number", min: "0", step: "any", value: draft.input, disabled: !writable, onChange: (event) => edit("input", event.target.value), placeholder: "\u7559\u7A7A\u8868\u793A\u672A\u77E5" })), /* @__PURE__ */ import_react.default.createElement("label", { className: "mr-profile-field" }, /* @__PURE__ */ import_react.default.createElement("span", null, "\u8F93\u51FA\u5355\u4EF7\uFF08USD / \u767E\u4E07 token\uFF09"), /* @__PURE__ */ import_react.default.createElement("input", { className: "mr-input", type: "number", min: "0", step: "any", value: draft.output, disabled: !writable, onChange: (event) => edit("output", event.target.value), placeholder: "\u7559\u7A7A\u8868\u793A\u672A\u77E5" })), /* @__PURE__ */ import_react.default.createElement("label", { className: "mr-profile-field" }, /* @__PURE__ */ import_react.default.createElement("span", null, "\u64C5\u957F\u65B9\u5411\uFF08\u82F1\u6587\u6807\u7B7E\uFF0C\u9017\u53F7\u5206\u9694\uFF09"), /* @__PURE__ */ import_react.default.createElement("input", { className: "mr-input", type: "text", value: draft.specialties, disabled: !writable, onChange: (event) => edit("specialties", event.target.value), placeholder: PROFILE_SPECIALTY_HINT })), /* @__PURE__ */ import_react.default.createElement("label", { className: "mr-profile-field" }, /* @__PURE__ */ import_react.default.createElement("span", null, "\u5B98\u65B9 CLI \u6A21\u578B\u540D\uFF08\u53EF\u9009\uFF09"), /* @__PURE__ */ import_react.default.createElement("input", { className: "mr-input", type: "text", value: draft.cliModel, disabled: !writable, onChange: (event) => edit("cliModel", event.target.value), placeholder: "\u4EC5\u5728\u5382\u5546 CLI \u652F\u6301\u8BE5\u51C6\u786E\u540D\u79F0\u65F6\u586B\u5199" })), /* @__PURE__ */ import_react.default.createElement("label", { className: "mr-profile-field" }, /* @__PURE__ */ import_react.default.createElement("span", null, "LiveBench \u51C6\u786E\u6A21\u578B\u540D\u79F0\uFF08\u53EF\u9009\uFF09"), /* @__PURE__ */ import_react.default.createElement("input", { className: "mr-input", type: "text", value: draft.benchmarkModel ?? "", disabled: !writable, onChange: (event) => edit("benchmarkModel", event.target.value), placeholder: "\u786E\u8BA4\u7248\u672C\u4E0E\u63A8\u7406\u6863\u4F4D\u4E00\u81F4\uFF1B\u4E0D\u81EA\u52A8\u731C\u6D4B\u522B\u540D" })), /* @__PURE__ */ import_react.default.createElement("label", { className: "mr-profile-field" }, /* @__PURE__ */ import_react.default.createElement("span", null, "\u6267\u884C\u65B9\u5F0F"), /* @__PURE__ */ import_react.default.createElement("select", { className: "mr-input", value: draft.execution || "auto", disabled: !writable, onChange: (event) => edit("execution", event.target.value) }, /* @__PURE__ */ import_react.default.createElement("option", { value: "auto" }, "\u81EA\u52A8\uFF1A\u5DF2\u5B89\u88C5\u5219\u7528\u5B98\u65B9\u5DE5\u5177\uFF0C\u5931\u8D25\u56DE\u9000 API"), /* @__PURE__ */ import_react.default.createElement("option", { value: "official" }, "\u5B98\u65B9\u5DE5\u5177\uFF1A\u5931\u8D25\u6216\u672A\u5B89\u88C5\u65F6\u56DE\u9000 API"), /* @__PURE__ */ import_react.default.createElement("option", { value: "api" }, "\u4EC5\u6A21\u578B\u76EE\u5F55 API"))), /* @__PURE__ */ import_react.default.createElement("label", { className: "mr-profile-field" }, /* @__PURE__ */ import_react.default.createElement("span", null, "\u8BA1\u8D39\u65B9\u5F0F"), /* @__PURE__ */ import_react.default.createElement("select", { className: "mr-input", value: draft.billing, disabled: !writable, onChange: (event) => edit("billing", event.target.value) }, /* @__PURE__ */ import_react.default.createElement("option", { value: "subscription-first" }, "\u8BA2\u9605\u4F18\u5148\uFF1A\u989D\u5EA6\u7528\u5C3D\u6216\u9650\u6D41\u65F6\u5207\u6362 API Key"), /* @__PURE__ */ import_react.default.createElement("option", { value: "api-only" }, "\u53EA\u7528 API Key"), /* @__PURE__ */ import_react.default.createElement("option", { value: "subscription-only" }, "\u53EA\u7528\u8BA2\u9605\uFF1A\u989D\u5EA6\u7528\u5C3D\u65F6\u4E0D\u5207\u6362"))), /* @__PURE__ */ import_react.default.createElement("label", { className: "mr-profile-field" }, /* @__PURE__ */ import_react.default.createElement("span", null, "\u8BA2\u9605\u6765\u6E90"), /* @__PURE__ */ import_react.default.createElement("select", { className: "mr-input", value: draft.subscription, disabled: !writable, onChange: (event) => edit("subscription", event.target.value) }, /* @__PURE__ */ import_react.default.createElement("option", { value: "auto" }, "\u81EA\u52A8\uFF1A\u6709\u5B98\u65B9 CLI \u65F6\u7528 CLI \u8D26\u53F7\u767B\u5F55"), /* @__PURE__ */ import_react.default.createElement("option", { value: "plan-key" }, "\u7F16\u7A0B\u5957\u9910 Key\uFF1A\u8BE5\u8DEF\u7EBF\u672C\u8EAB\u662F\u5957\u9910\u7AEF\u70B9"), /* @__PURE__ */ import_react.default.createElement("option", { value: "cli-login" }, "\u5B98\u65B9 CLI \u8D26\u53F7\u767B\u5F55"), /* @__PURE__ */ import_react.default.createElement("option", { value: "none" }, "\u65E0\u8BA2\u9605\uFF1A\u59CB\u7EC8\u6309 API \u8BA1\u8D39"))), draft.subscription === "plan-key" && /* @__PURE__ */ import_react.default.createElement("label", { className: "mr-profile-field" }, /* @__PURE__ */ import_react.default.createElement("span", null, "\u989D\u5EA6\u7528\u5C3D\u65F6\u56DE\u9000\u7684 API \u8DEF\u7EBF"), /* @__PURE__ */ import_react.default.createElement("select", { className: "mr-input", value: draft.apiRoute, disabled: !writable, onChange: (event) => edit("apiRoute", event.target.value) }, /* @__PURE__ */ import_react.default.createElement("option", { value: "" }, "\u4E0D\u56DE\u9000\uFF08\u672A\u914D\u7F6E API \u8DEF\u7EBF\uFF09"), routes.filter((item) => profileRouteKey(item) !== routeKey4).map((item) => /* @__PURE__ */ import_react.default.createElement("option", { key: profileRouteKey(item), value: profileRouteKey(item) }, item.provider, "/", item.model))))), /* @__PURE__ */ import_react.default.createElement("details", { className: "mr-profile-advanced" }, /* @__PURE__ */ import_react.default.createElement("summary", null, "\u7F13\u5B58\u5355\u4EF7\uFF08\u53EF\u9009\uFF09"), /* @__PURE__ */ import_react.default.createElement("div", { className: "mr-profile-grid" }, /* @__PURE__ */ import_react.default.createElement("label", { className: "mr-profile-field" }, /* @__PURE__ */ import_react.default.createElement("span", null, "\u7F13\u5B58\u8BFB\u53D6\uFF08USD / \u767E\u4E07 token\uFF09"), /* @__PURE__ */ import_react.default.createElement("input", { className: "mr-input", type: "number", min: "0", step: "any", value: draft.cacheRead, disabled: !writable, onChange: (event) => edit("cacheRead", event.target.value), placeholder: "\u7559\u7A7A\u6309\u666E\u901A\u8F93\u5165\u4EF7\u683C\u4F30\u7B97" })), /* @__PURE__ */ import_react.default.createElement("label", { className: "mr-profile-field" }, /* @__PURE__ */ import_react.default.createElement("span", null, "\u7F13\u5B58\u5199\u5165\uFF08USD / \u767E\u4E07 token\uFF09"), /* @__PURE__ */ import_react.default.createElement("input", { className: "mr-input", type: "number", min: "0", step: "any", value: draft.cacheWrite, disabled: !writable, onChange: (event) => edit("cacheWrite", event.target.value), placeholder: "\u7559\u7A7A\u6309\u666E\u901A\u8F93\u5165\u4EF7\u683C\u4F30\u7B97" })))), /* @__PURE__ */ import_react.default.createElement("div", { className: "mr-actions" }, /* @__PURE__ */ import_react.default.createElement("button", { className: "mr-button", type: "button", disabled: !writable || !pending, onClick: () => {
1706
1860
  void write(false);
1707
1861
  } }, saving ? "\u4FDD\u5B58\u4E2D\u2026" : "\u4FDD\u5B58\u6B64\u6A21\u578B"), /* @__PURE__ */ import_react.default.createElement("button", { className: "mr-button mr-button-secondary", type: "button", disabled: !pending || saving, onClick: reload }, "\u91CD\u65B0\u52A0\u8F7D\u6B64\u8DEF\u7EBF"), saved && /* @__PURE__ */ import_react.default.createElement("button", { className: "mr-button mr-button-secondary", type: "button", disabled: !writable, onClick: () => {
1708
1862
  void write(true);
@@ -1846,11 +2000,23 @@ function packageCost(item) {
1846
2000
  }
1847
2001
  return { budget: item?.ran ? "\u8D39\u7528\u672A\u77E5" : "\u2014", reference: null };
1848
2002
  }
2003
+ function priorAttemptTotals(run) {
2004
+ const months = sanitizeArchivedSpending(run?.priorAttemptSpending).months;
2005
+ const totals = { budgetUsd: 0, referenceUsd: 0, unknownCalls: 0, subscriptionRuns: 0 };
2006
+ for (const period of Object.values(months)) {
2007
+ totals.budgetUsd += period.costUsd;
2008
+ totals.referenceUsd += period.subscriptionUsd;
2009
+ totals.unknownCalls += period.unknown;
2010
+ totals.subscriptionRuns += period.subscriptionRuns;
2011
+ }
2012
+ return totals;
2013
+ }
1849
2014
  function runTotals(run) {
1850
2015
  const items = [...run?.packages ?? [], ...run?.reviews ?? []];
1851
- let budgetUsd = 0;
1852
- let referenceUsd = 0;
1853
- let subscription = false;
2016
+ const prior = priorAttemptTotals(run);
2017
+ let budgetUsd = prior.budgetUsd;
2018
+ let referenceUsd = prior.referenceUsd;
2019
+ let subscription = prior.subscriptionRuns > 0;
1854
2020
  for (const item of items) {
1855
2021
  if (item.billing === "subscription") {
1856
2022
  subscription = true;
@@ -1948,6 +2114,92 @@ function rerunConfirmations({ run, item, override = null, choice = null, ledger
1948
2114
  return reasons;
1949
2115
  }
1950
2116
 
2117
+ // .dsh-plugin/client/adaptive-state.mjs
2118
+ var ADAPTIVE_DEFAULTS = Object.freeze({
2119
+ feedbackLearningEnabled: true,
2120
+ feedbackHalfLifeDays: 30,
2121
+ feedbackPriorWeight: 3,
2122
+ feedbackMaxAdjustment: 0.04,
2123
+ feedbackResetAt: 0,
2124
+ dynamicDataEnabled: false,
2125
+ liveBenchEndpoint: "https://livebench.ai",
2126
+ dynamicDataTtlMinutes: 1440,
2127
+ pricingSnapshotEndpoint: ""
2128
+ });
2129
+ var ADAPTIVE_NUMBER_FIELDS = Object.freeze([
2130
+ Object.freeze({ key: "feedbackHalfLifeDays", min: 1, max: 3650, step: 1 }),
2131
+ Object.freeze({ key: "feedbackPriorWeight", min: 1, max: 1e6, step: 1 }),
2132
+ Object.freeze({ key: "feedbackMaxAdjustment", min: 0, max: 0.1, step: 0.01 }),
2133
+ Object.freeze({ key: "dynamicDataTtlMinutes", min: 1, max: 10080, step: 1 })
2134
+ ]);
2135
+ function adaptiveSettingValue(settings, key) {
2136
+ return settings?.[key] ?? ADAPTIVE_DEFAULTS[key];
2137
+ }
2138
+ function parseAdaptiveNumber(key, draft) {
2139
+ const field2 = ADAPTIVE_NUMBER_FIELDS.find((item) => item.key === key);
2140
+ if (!field2) throw new TypeError("Unknown numeric setting");
2141
+ if (typeof draft !== "string" && typeof draft !== "number" || String(draft).trim() === "") throw new TypeError("Enter a number");
2142
+ const value = Number(draft);
2143
+ if (!Number.isFinite(value) || value < field2.min || value > field2.max) throw new RangeError(`Expected ${field2.min}..${field2.max}`);
2144
+ return value;
2145
+ }
2146
+ function parsePublicEndpoint(key, draft) {
2147
+ if (!["liveBenchEndpoint", "pricingSnapshotEndpoint"].includes(key)) throw new TypeError("Unknown endpoint setting");
2148
+ if (typeof draft !== "string") throw new TypeError("Enter a public HTTPS URL");
2149
+ const value = draft.trim();
2150
+ if (key === "pricingSnapshotEndpoint" && value === "") return "";
2151
+ if (!value || value.length > 2048) throw new TypeError("Enter a public HTTPS URL");
2152
+ let parsed;
2153
+ try {
2154
+ parsed = new URL(value);
2155
+ } catch {
2156
+ throw new TypeError("Enter a public HTTPS URL");
2157
+ }
2158
+ if (parsed.protocol !== "https:" || parsed.username || parsed.password || parsed.search || parsed.hash || parsed.port && parsed.port !== "443") {
2159
+ throw new TypeError("Use a public HTTPS URL without credentials, query or fragment");
2160
+ }
2161
+ if (!/^(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z]{2,}$/iu.test(parsed.hostname) || /(?:^|\.)(?:localhost|local|internal|lan|home|test|invalid)$/iu.test(parsed.hostname)) throw new TypeError("Use a public hostname");
2162
+ return value;
2163
+ }
2164
+ function publicEndpointDraft(key, value) {
2165
+ try {
2166
+ return parsePublicEndpoint(key, value);
2167
+ } catch {
2168
+ return "";
2169
+ }
2170
+ }
2171
+ function feedbackRatingArguments(run, item, direction) {
2172
+ if (!["up", "down"].includes(direction)) throw new TypeError("Unknown rating direction");
2173
+ const active = direction === "up" ? item?.rating === 1 : item?.rating === -1;
2174
+ return [run?.id, item?.id, active ? "clear" : direction, item?.finishedAt];
2175
+ }
2176
+ var nonnegative2 = (value) => Number.isFinite(value) && value >= 0 ? value : 0;
2177
+ function learningView(learning, settings = {}) {
2178
+ return {
2179
+ available: Boolean(learning && typeof learning === "object"),
2180
+ enabled: typeof learning?.enabled === "boolean" ? learning.enabled : adaptiveSettingValue(settings, "feedbackLearningEnabled") !== false,
2181
+ feedbackCount: nonnegative2(learning?.feedbackCount),
2182
+ ignoredCount: nonnegative2(learning?.ignoredCount),
2183
+ effectiveWeight: nonnegative2(learning?.effectiveWeight),
2184
+ policyVersion: typeof learning?.policyVersion === "string" ? learning.policyVersion.slice(0, 100) : null,
2185
+ resetAt: nonnegative2(adaptiveSettingValue(settings, "feedbackResetAt"))
2186
+ };
2187
+ }
2188
+ var STATUS_LABEL = Object.freeze({ disabled: "\u672A\u542F\u7528", missing: "\u5C1A\u65E0\u5FEB\u7167", fresh: "\u5FEB\u7167\u6709\u6548", stale: "\u5FEB\u7167\u8FC7\u671F", error: "\u66F4\u65B0\u5931\u8D25" });
2189
+ function dynamicSourceView(source) {
2190
+ const status = Object.hasOwn(STATUS_LABEL, source?.status ?? "") ? source.status : "missing";
2191
+ let publicSource = "";
2192
+ if (typeof source?.source === "string") publicSource = publicEndpointDraft("pricingSnapshotEndpoint", source.source);
2193
+ return {
2194
+ status,
2195
+ label: STATUS_LABEL[status],
2196
+ source: publicSource,
2197
+ version: typeof source?.version === "string" ? source.version.slice(0, 160) : null,
2198
+ verifiedAt: Number.isFinite(source?.verifiedAt) && source.verifiedAt > 0 ? source.verifiedAt : null,
2199
+ count: nonnegative2(source?.modelCount ?? source?.rowCount)
2200
+ };
2201
+ }
2202
+
1951
2203
  // .dsh-plugin/client/router-insights.jsx
1952
2204
  var text = (value) => typeof value === "string" ? value.trim() : "";
1953
2205
  var BAND = { simple: "\u7B80\u5355", balanced: "\u4E2D\u7B49", complex: "\u56F0\u96BE" };
@@ -1998,6 +2250,134 @@ function useSettingsWriter(settingsScope) {
1998
2250
  };
1999
2251
  return { value: snapshot.value ?? {}, writable, write, notice };
2000
2252
  }
2253
+ var ADAPTIVE_FIELD_LABEL = {
2254
+ feedbackHalfLifeDays: "\u53CD\u9988\u534A\u8870\u671F\uFF08\u5929\uFF09",
2255
+ feedbackPriorWeight: "\u6536\u7F29\u5F3A\u5EA6",
2256
+ feedbackMaxAdjustment: "\u6700\u5927\u504F\u597D\u6548\u7528\u8C03\u6574",
2257
+ dynamicDataTtlMinutes: "\u516C\u5171\u5FEB\u7167\u68C0\u67E5\u95F4\u9694\uFF08\u5206\u949F\uFF09"
2258
+ };
2259
+ function AdaptiveNumberControl({ field: field2, value, writable, onSave }) {
2260
+ const [draft, setDraft] = import_react2.default.useState("");
2261
+ const [notice, setNotice] = import_react2.default.useState("");
2262
+ const save = async () => {
2263
+ try {
2264
+ const next = parseAdaptiveNumber(field2.key, draft);
2265
+ setNotice("");
2266
+ if (await onSave(field2.key, next)) setDraft("");
2267
+ } catch {
2268
+ setNotice(`\u8BF7\u8F93\u5165 ${field2.min} \u5230 ${field2.max} \u7684\u6570\u5B57\u3002`);
2269
+ }
2270
+ };
2271
+ return /* @__PURE__ */ import_react2.default.createElement("div", { className: "mr-control-group" }, /* @__PURE__ */ import_react2.default.createElement("label", { className: "mr-control-label", htmlFor: `mr-${field2.key}` }, ADAPTIVE_FIELD_LABEL[field2.key]), /* @__PURE__ */ import_react2.default.createElement("div", { className: "mr-inline" }, /* @__PURE__ */ import_react2.default.createElement(
2272
+ "input",
2273
+ {
2274
+ className: "mr-input mr-budget",
2275
+ id: `mr-${field2.key}`,
2276
+ type: "number",
2277
+ min: field2.min,
2278
+ max: field2.max,
2279
+ step: field2.step,
2280
+ placeholder: String(value),
2281
+ value: draft,
2282
+ disabled: !writable,
2283
+ onChange: (event) => setDraft(event.target.value)
2284
+ }
2285
+ ), /* @__PURE__ */ import_react2.default.createElement("button", { className: "mr-button mr-button-secondary", type: "button", disabled: !writable || draft === "", onClick: () => {
2286
+ void save();
2287
+ } }, "\u4FDD\u5B58")), notice && /* @__PURE__ */ import_react2.default.createElement("span", { className: "mr-error", role: "alert" }, notice));
2288
+ }
2289
+ function PublicEndpointControl({ name, label, value, writable, onSave }) {
2290
+ const [draft, setDraft] = import_react2.default.useState(null);
2291
+ const [notice, setNotice] = import_react2.default.useState("");
2292
+ const current = publicEndpointDraft(name, value);
2293
+ const save = async () => {
2294
+ try {
2295
+ const next = parsePublicEndpoint(name, draft ?? current);
2296
+ setNotice("");
2297
+ if (await onSave(name, next)) setDraft(null);
2298
+ } catch {
2299
+ setNotice("\u8BF7\u8F93\u5165\u4E0D\u542B\u8BA4\u8BC1\u3001\u67E5\u8BE2\u53C2\u6570\u6216\u7247\u6BB5\u7684\u516C\u5F00 HTTPS \u5730\u5740\uFF1B\u4EF7\u683C\u5FEB\u7167\u53EF\u7559\u7A7A\u3002");
2300
+ }
2301
+ };
2302
+ return /* @__PURE__ */ import_react2.default.createElement("div", { className: "mr-control-group" }, /* @__PURE__ */ import_react2.default.createElement("label", { className: "mr-control-label", htmlFor: `mr-${name}` }, label), /* @__PURE__ */ import_react2.default.createElement(
2303
+ "input",
2304
+ {
2305
+ className: "mr-input",
2306
+ id: `mr-${name}`,
2307
+ type: "url",
2308
+ maxLength: 2048,
2309
+ value: draft ?? current,
2310
+ disabled: !writable,
2311
+ placeholder: name === "liveBenchEndpoint" ? "https://livebench.ai" : "\u7559\u7A7A\uFF1A\u4E0D\u8BFB\u53D6\u8FDC\u7A0B\u4EF7\u683C\u5FEB\u7167",
2312
+ onChange: (event) => setDraft(event.target.value)
2313
+ }
2314
+ ), /* @__PURE__ */ import_react2.default.createElement("button", { className: "mr-button mr-button-secondary", type: "button", disabled: !writable || draft === null, onClick: () => {
2315
+ void save();
2316
+ } }, "\u4FDD\u5B58\u5730\u5740"), notice && /* @__PURE__ */ import_react2.default.createElement("span", { className: "mr-error", role: "alert" }, notice));
2317
+ }
2318
+ function PublicSourceStatus({ label, source }) {
2319
+ const view = dynamicSourceView(source);
2320
+ return /* @__PURE__ */ import_react2.default.createElement("div", { className: "mr-control-group" }, /* @__PURE__ */ import_react2.default.createElement("span", { className: "mr-control-label" }, label, "\uFF1A", view.label), /* @__PURE__ */ import_react2.default.createElement("span", { className: "mr-caption" }, view.version ? `\u7248\u672C ${view.version} \xB7 ` : "", view.count, " \u6761\u8BB0\u5F55", view.verifiedAt ? ` \xB7 \u6700\u8FD1\u6821\u9A8C ${new Date(view.verifiedAt).toLocaleString()}` : ""), view.source && /* @__PURE__ */ import_react2.default.createElement("span", { className: "mr-caption" }, "\u516C\u5F00\u6765\u6E90\uFF1A", view.source), view.status === "error" && /* @__PURE__ */ import_react2.default.createElement("span", { className: "mr-caption" }, "\u66F4\u65B0\u5931\u8D25\uFF1B\u662F\u5426\u53EF\u7528\u7531 Host \u6821\u9A8C\uFF0C\u4E0D\u5C06\u7F3A\u5931\u6570\u636E\u5F53\u4F5C\u96F6\u6210\u672C\u6216\u6EE1\u5206\u3002"));
2321
+ }
2322
+ function AdaptiveControls({ ledger, settings, onChanged }) {
2323
+ const value = settings.value;
2324
+ const learning = learningView(ledger?.learning, value);
2325
+ const [resetBusy, setResetBusy] = import_react2.default.useState(false);
2326
+ const save = async (key, next) => {
2327
+ const accepted = await settings.write(key, next);
2328
+ if (accepted) onChanged?.();
2329
+ return accepted;
2330
+ };
2331
+ const reset = async () => {
2332
+ if (!window.confirm("\u4ECE\u73B0\u5728\u91CD\u65B0\u5B66\u4E60\u4F60\u7684\u504F\u597D\uFF1F\u6B64\u524D\u53CD\u9988\u5C06\u4E0D\u518D\u53C2\u4E0E\u8C03\u6574\uFF0C\u4F46\u6267\u884C\u8BB0\u5F55\u3001\u8D39\u7528\u5386\u53F2\u548C\u539F\u8BC4\u4EF7\u4E0D\u4F1A\u5220\u9664\u3002")) return;
2333
+ setResetBusy(true);
2334
+ try {
2335
+ await save("feedbackResetAt", Date.now());
2336
+ } finally {
2337
+ setResetBusy(false);
2338
+ }
2339
+ };
2340
+ return /* @__PURE__ */ import_react2.default.createElement(import_react2.default.Fragment, null, /* @__PURE__ */ import_react2.default.createElement("h3", { className: "mr-section-title" }, "\u6301\u7EED\u53CD\u9988\u4E0E\u672C\u5730\u504F\u597D"), /* @__PURE__ */ import_react2.default.createElement("p", { className: "mr-caption" }, "\u53EA\u4F7F\u7528\u4F60\u5BF9\u5DF2\u8BB0\u5F55\u7ED3\u679C\u7684\u70B9\u8D5E / \u4E0D\u597D / \u64A4\u56DE\uFF0C\u6309\u4EFB\u52A1\u7C7B\u578B\u548C\u65F6\u95F4\u8870\u51CF\u8C03\u6574\u504F\u597D\u6548\u7528\uFF1B\u4E0D\u62AC\u9AD8\u8D28\u91CF\u786C\u95E8\u69DB\u3002\u7CFB\u7EDF\u6267\u884C\u6210\u529F\u4E0D\u7B49\u4E8E\u4F60\u6EE1\u610F\uFF0C\u6A21\u578B\u590D\u6838\u4E5F\u4E0D\u4F5C\u4E3A\u4EBA\u5DE5\u8BC4\u5206\u3002\u4E0D\u4F1A\u4E3A\u4E86\u5B66\u4E60\u53D1\u8D77\u4ED8\u8D39\u63A2\u7D22\u3002"), /* @__PURE__ */ import_react2.default.createElement("p", { className: "mr-caption" }, "\u8303\u56F4\uFF1A\u672C\u5730 DSH_HOME \u5DE5\u4F5C\u5BA4\u5171\u4EAB\uFF0C\u4E0D\u662F\u6309\u8D26\u53F7\u9694\u79BB\uFF1B\u6700\u591A\u6700\u8FD1 200 \u6B21\u8FD0\u884C\u7684\u6ED1\u52A8\u7A97\u53E3\uFF0C\u4E0D\u4E0A\u4F20\u53CD\u9988\u6216\u4EFB\u52A1\u5185\u5BB9\u3002"), /* @__PURE__ */ import_react2.default.createElement("div", { className: "mr-controls" }, /* @__PURE__ */ import_react2.default.createElement("label", { className: "mr-check" }, /* @__PURE__ */ import_react2.default.createElement(
2341
+ "input",
2342
+ {
2343
+ type: "checkbox",
2344
+ checked: adaptiveSettingValue(value, "feedbackLearningEnabled") !== false,
2345
+ disabled: !settings.writable,
2346
+ onChange: (event) => {
2347
+ void save("feedbackLearningEnabled", event.target.checked);
2348
+ }
2349
+ }
2350
+ ), "\u542F\u7528\u7528\u6237\u53CD\u9988\u5B66\u4E60"), ADAPTIVE_NUMBER_FIELDS.filter((field2) => field2.key !== "dynamicDataTtlMinutes").map((field2) => /* @__PURE__ */ import_react2.default.createElement(
2351
+ AdaptiveNumberControl,
2352
+ {
2353
+ key: field2.key,
2354
+ field: field2,
2355
+ value: adaptiveSettingValue(value, field2.key),
2356
+ writable: settings.writable,
2357
+ onSave: save
2358
+ }
2359
+ ))), learning.available ? /* @__PURE__ */ import_react2.default.createElement("p", { className: "mr-caption", role: "status" }, learning.enabled ? "\u5B66\u4E60\u5DF2\u542F\u7528" : "\u5B66\u4E60\u5DF2\u505C\u7528", " \xB7 \u6709\u6548\u53CD\u9988 ", learning.feedbackCount, " \xB7 \u6709\u6548\u6743\u91CD ", learning.effectiveWeight.toFixed(2), " \xB7 \u5FFD\u7565 ", learning.ignoredCount, learning.policyVersion ? ` \xB7 \u7B56\u7565 ${learning.policyVersion}` : "") : /* @__PURE__ */ import_react2.default.createElement("p", { className: "mr-caption", role: "status" }, "\u5B66\u4E60\u6458\u8981\u5C1A\u672A\u8BFB\u53D6\uFF1B\u4FDD\u5B58\u540E\u5237\u65B0\u6267\u884C\u8BB0\u5F55\u67E5\u770B\u3002"), learning.resetAt > 0 && /* @__PURE__ */ import_react2.default.createElement("p", { className: "mr-caption" }, "\u5B66\u4E60\u8D77\u70B9\uFF1A", new Date(learning.resetAt).toLocaleString(), "\uFF0C\u6B64\u524D\u53CD\u9988\u4E0D\u518D\u53C2\u4E0E\u8C03\u6574\u3002"), /* @__PURE__ */ import_react2.default.createElement("button", { className: "mr-button mr-button-secondary", type: "button", disabled: !settings.writable || resetBusy, onClick: () => {
2360
+ void reset();
2361
+ } }, resetBusy ? "\u6B63\u5728\u8BBE\u7F6E\u2026" : "\u4ECE\u73B0\u5728\u91CD\u65B0\u5B66\u4E60"), /* @__PURE__ */ import_react2.default.createElement("h3", { className: "mr-section-title" }, "\u52A8\u6001\u516C\u5171\u6570\u636E"), /* @__PURE__ */ import_react2.default.createElement("p", { className: "mr-caption" }, "\u9ED8\u8BA4\u5173\u95ED\u3002\u660E\u786E\u542F\u7528\u540E\uFF0C\u5728\u6253\u5F00 / \u5237\u65B0\u8D26\u672C\u53CA\u6267\u884C\u524D\u6309\u68C0\u67E5\u95F4\u9694\u8BFB\u53D6\u516C\u5F00 LiveBench \u548C\u53EF\u9009\u4EF7\u683C\u5FEB\u7167\uFF1B\u4EF7\u683C\u4E0E\u80FD\u529B\u5148\u9A8C\u4FDD\u7559\u7248\u672C\uFF0C\u4E0D\u4EE3\u8868\u771F\u5B9E\u4EFB\u52A1\u6536\u76CA\u3002\u53EA\u6709\u6253\u5F00\u516C\u5171\u6E90\u5F00\u5173\u624D\u4F1A\u8BFB\u53D6\u8FDC\u7A0B\u6570\u636E\uFF0C\u4E0D\u53D1\u9001\u4EFB\u52A1\u6216\u53CD\u9988\u3002"), /* @__PURE__ */ import_react2.default.createElement("div", { className: "mr-controls" }, /* @__PURE__ */ import_react2.default.createElement("label", { className: "mr-check" }, /* @__PURE__ */ import_react2.default.createElement(
2362
+ "input",
2363
+ {
2364
+ type: "checkbox",
2365
+ checked: adaptiveSettingValue(value, "dynamicDataEnabled") === true,
2366
+ disabled: !settings.writable,
2367
+ onChange: (event) => {
2368
+ void save("dynamicDataEnabled", event.target.checked);
2369
+ }
2370
+ }
2371
+ ), "\u542F\u7528\u52A8\u6001\u516C\u5171\u6570\u636E"), /* @__PURE__ */ import_react2.default.createElement(
2372
+ AdaptiveNumberControl,
2373
+ {
2374
+ field: ADAPTIVE_NUMBER_FIELDS.find((field2) => field2.key === "dynamicDataTtlMinutes"),
2375
+ value: adaptiveSettingValue(value, "dynamicDataTtlMinutes"),
2376
+ writable: settings.writable,
2377
+ onSave: save
2378
+ }
2379
+ ), /* @__PURE__ */ import_react2.default.createElement(PublicEndpointControl, { name: "liveBenchEndpoint", label: "LiveBench \u516C\u5F00\u6E90", value: adaptiveSettingValue(value, "liveBenchEndpoint"), writable: settings.writable, onSave: save }), /* @__PURE__ */ import_react2.default.createElement(PublicEndpointControl, { name: "pricingSnapshotEndpoint", label: "\u4EF7\u683C\u5FEB\u7167\u516C\u5F00\u6E90\uFF08\u53EF\u9009\uFF09", value: adaptiveSettingValue(value, "pricingSnapshotEndpoint"), writable: settings.writable, onSave: save }), /* @__PURE__ */ import_react2.default.createElement(PublicSourceStatus, { label: "LiveBench", source: ledger?.dynamicData?.liveBench }), /* @__PURE__ */ import_react2.default.createElement(PublicSourceStatus, { label: "\u4EF7\u683C", source: ledger?.dynamicData?.pricing })));
2380
+ }
2001
2381
  function CostControlCard({ ledger, settingsScope, onChanged, error }) {
2002
2382
  const settings = useSettingsWriter(settingsScope);
2003
2383
  const [dailyDraft, setDailyDraft] = import_react2.default.useState("");
@@ -2036,7 +2416,7 @@ function CostControlCard({ ledger, settingsScope, onChanged, error }) {
2036
2416
  void set("allowManualReassign", event.target.checked);
2037
2417
  } }), "\u5141\u8BB8\u624B\u52A8\u6539\u6D3E\u5DE5\u4F5C\u5305"), /* @__PURE__ */ import_react2.default.createElement("label", { className: "mr-check" }, /* @__PURE__ */ import_react2.default.createElement("input", { type: "checkbox", checked: value.confirmUnsandboxedCli !== false, disabled: !settings.writable, onChange: (event) => {
2038
2418
  void set("confirmUnsandboxedCli", event.target.checked);
2039
- } }), "\u76F4\u63A5\u542F\u52A8\u65E0\u6C99\u7BB1 CLI \u524D\u5148\u786E\u8BA4")), settings.notice && /* @__PURE__ */ import_react2.default.createElement("p", { className: "mr-error", role: "alert" }, settings.notice)));
2419
+ } }), "\u76F4\u63A5\u542F\u52A8\u65E0\u6C99\u7BB1 CLI \u524D\u5148\u786E\u8BA4")), /* @__PURE__ */ import_react2.default.createElement(AdaptiveControls, { ledger, settings, onChanged }), settings.notice && /* @__PURE__ */ import_react2.default.createElement("p", { className: "mr-error", role: "alert" }, settings.notice)));
2040
2420
  }
2041
2421
  function DagView({ packages, renderNode, label = "\u5B50\u4EFB\u52A1\u4F9D\u8D56\u56FE" }) {
2042
2422
  const layers = dagLayers(packages);
@@ -2058,7 +2438,7 @@ function RunNode({ run, item, routes, allowReassign, busy, onRate, onRerun }) {
2058
2438
  const rerun = rerunSupport(run);
2059
2439
  const canRerun = rerun.supported && !item.ok && !busy;
2060
2440
  const others = routes.filter((route) => `${route.provider}/${route.model}` !== `${item.provider}/${item.model}`);
2061
- return /* @__PURE__ */ import_react2.default.createElement(import_react2.default.Fragment, null, /* @__PURE__ */ import_react2.default.createElement("p", { className: "mr-package-route" }, item.provider, "/", item.model, item.reassigned ? "\uFF08\u5DF2\u6539\u6D3E\uFF09" : ""), /* @__PURE__ */ import_react2.default.createElement("div", { className: "mr-channel-line" }, /* @__PURE__ */ import_react2.default.createElement(ChannelText, { item }), /* @__PURE__ */ import_react2.default.createElement("span", { className: "mr-caption" }, "\u9884\u4F30 ", money(item.estimatedCost), " \xB7 \u5B9E\u9645 ", cost.budget, item.difficulty ? ` \xB7 \u96BE\u5EA6 ${BAND[item.difficulty] ?? item.difficulty}` : "")), cost.reference && /* @__PURE__ */ import_react2.default.createElement("p", { className: "mr-package-copy" }, cost.reference), item.actualModel && /* @__PURE__ */ import_react2.default.createElement("p", { className: "mr-package-copy" }, "CLI \u56DE\u62A5\u6A21\u578B\uFF1A", item.actualModel), (item.billing || item.billingMode) && /* @__PURE__ */ import_react2.default.createElement("p", { className: "mr-package-copy" }, "\u8BA1\u8D39\uFF1A", BILLING_CHANNEL_LABEL[item.billing] ?? "\u2014", item.subscriptionRoute ? ` \xB7 \u5957\u9910\u8DEF\u7EBF ${item.subscriptionRoute.provider}/${item.subscriptionRoute.model}` : "", item.billingMode && item.billingMode !== "subscription-first" ? ` \xB7 ${BILLING_MODE_LABEL[item.billingMode] ?? item.billingMode}` : ""), billingSwitchText(item) && /* @__PURE__ */ import_react2.default.createElement("p", { className: "mr-package-copy mr-warn-text" }, "\u8BA1\u8D39\u5207\u6362\uFF1A", billingSwitchText(item)), item.fallback?.reason && item.fallback.reason !== billingSwitchText(item) && /* @__PURE__ */ import_react2.default.createElement("p", { className: "mr-package-copy" }, "\u56DE\u9000\u539F\u56E0\uFF1A", item.fallback.reason), item.fallback?.error && /* @__PURE__ */ import_react2.default.createElement("p", { className: "mr-package-copy mr-fallback-error" }, "CLI \u539F\u59CB\u9519\u8BEF\uFF1A", /* @__PURE__ */ import_react2.default.createElement("code", null, item.fallback.error)), !item.ok && item.error && /* @__PURE__ */ import_react2.default.createElement("p", { className: "mr-package-copy mr-fallback-error" }, item.error), item.review && /* @__PURE__ */ import_react2.default.createElement("p", { className: "mr-package-copy" }, "\u5F3A\u6A21\u578B\u62BD\u67E5\uFF08", item.review.provider, "/", item.review.model, "\uFF09\uFF1A", item.review.score ? `${item.review.score}/5` : "\u672A\u8BC4\u5206", " ", item.review.summary), item.answer && /* @__PURE__ */ import_react2.default.createElement("details", { className: "mr-tool-log" }, /* @__PURE__ */ import_react2.default.createElement("summary", null, "\u67E5\u770B\u7ED3\u679C"), /* @__PURE__ */ import_react2.default.createElement("pre", null, item.answer, item.answerTruncated ? "\n\u2026\uFF08\u5DF2\u622A\u65AD\uFF09" : "")), /* @__PURE__ */ import_react2.default.createElement("div", { className: "mr-node-actions" }, item.ok && /* @__PURE__ */ import_react2.default.createElement(import_react2.default.Fragment, null, /* @__PURE__ */ import_react2.default.createElement("button", { className: "mr-button mr-button-secondary mr-mini", type: "button", "aria-pressed": item.rating === 1, disabled: busy, onClick: () => onRate(run.id, item.id, item.rating === 1 ? "clear" : "up") }, "\u{1F44D} \u6709\u7528"), /* @__PURE__ */ import_react2.default.createElement("button", { className: "mr-button mr-button-secondary mr-mini", type: "button", "aria-pressed": item.rating === -1, disabled: busy, onClick: () => onRate(run.id, item.id, item.rating === -1 ? "clear" : "down") }, "\u{1F44E} \u4E0D\u597D")), canRerun && /* @__PURE__ */ import_react2.default.createElement("button", { className: "mr-button mr-mini", type: "button", title: rerun.confirm || void 0, onClick: () => onRerun(run.id, item.id, null) }, run.kind === "tool" ? "\u91CD\u65B0\u6267\u884C\u6B64\u8C03\u7528" : rerun.writes ? "\u5728\u65B0\u5DE5\u4F5C\u533A\u7EED\u8DD1" : "\u91CD\u8DD1\u6B64\u6B65"), !rerun.supported && !item.ok && item.ran && /* @__PURE__ */ import_react2.default.createElement("span", { className: "mr-caption" }, rerun.reason), rerun.supported && rerun.reassign && !(rerun.writes && item.ok) && allowReassign && others.length > 0 && !busy && /* @__PURE__ */ import_react2.default.createElement("span", { className: "mr-inline" }, /* @__PURE__ */ import_react2.default.createElement("select", { className: "mr-input mr-mini-select", "aria-label": "\u6539\u6D3E\u5230", value: target, onChange: (event) => setTarget(event.target.value) }, /* @__PURE__ */ import_react2.default.createElement("option", { value: "" }, "\u6539\u6D3E\u5230\u2026"), others.map((route) => /* @__PURE__ */ import_react2.default.createElement("option", { key: `${route.provider}/${route.model}`, value: `${route.provider}\0${route.model}` }, route.provider, "/", route.model))), /* @__PURE__ */ import_react2.default.createElement("button", { className: "mr-button mr-button-secondary mr-mini", type: "button", disabled: !target, onClick: () => {
2441
+ return /* @__PURE__ */ import_react2.default.createElement(import_react2.default.Fragment, null, /* @__PURE__ */ import_react2.default.createElement("p", { className: "mr-package-route" }, item.provider, "/", item.model, item.reassigned ? "\uFF08\u5DF2\u6539\u6D3E\uFF09" : ""), /* @__PURE__ */ import_react2.default.createElement("div", { className: "mr-channel-line" }, /* @__PURE__ */ import_react2.default.createElement(ChannelText, { item }), /* @__PURE__ */ import_react2.default.createElement("span", { className: "mr-caption" }, "\u9884\u4F30 ", money(item.estimatedCost), " \xB7 \u5B9E\u9645 ", cost.budget, item.difficulty ? ` \xB7 \u96BE\u5EA6 ${BAND[item.difficulty] ?? item.difficulty}` : "")), cost.reference && /* @__PURE__ */ import_react2.default.createElement("p", { className: "mr-package-copy" }, cost.reference), item.actualModel && /* @__PURE__ */ import_react2.default.createElement("p", { className: "mr-package-copy" }, "CLI \u56DE\u62A5\u6A21\u578B\uFF1A", item.actualModel), (item.billing || item.billingMode) && /* @__PURE__ */ import_react2.default.createElement("p", { className: "mr-package-copy" }, "\u8BA1\u8D39\uFF1A", BILLING_CHANNEL_LABEL[item.billing] ?? "\u2014", item.subscriptionRoute ? ` \xB7 \u5957\u9910\u8DEF\u7EBF ${item.subscriptionRoute.provider}/${item.subscriptionRoute.model}` : "", item.billingMode && item.billingMode !== "subscription-first" ? ` \xB7 ${BILLING_MODE_LABEL[item.billingMode] ?? item.billingMode}` : ""), billingSwitchText(item) && /* @__PURE__ */ import_react2.default.createElement("p", { className: "mr-package-copy mr-warn-text" }, "\u8BA1\u8D39\u5207\u6362\uFF1A", billingSwitchText(item)), item.fallback?.reason && item.fallback.reason !== billingSwitchText(item) && /* @__PURE__ */ import_react2.default.createElement("p", { className: "mr-package-copy" }, "\u56DE\u9000\u539F\u56E0\uFF1A", item.fallback.reason), item.fallback?.error && /* @__PURE__ */ import_react2.default.createElement("p", { className: "mr-package-copy mr-fallback-error" }, "CLI \u539F\u59CB\u9519\u8BEF\uFF1A", /* @__PURE__ */ import_react2.default.createElement("code", null, item.fallback.error)), !item.ok && item.error && /* @__PURE__ */ import_react2.default.createElement("p", { className: "mr-package-copy mr-fallback-error" }, item.error), item.review && /* @__PURE__ */ import_react2.default.createElement("p", { className: "mr-package-copy" }, "\u5F3A\u6A21\u578B\u62BD\u67E5\uFF08", item.review.provider, "/", item.review.model, "\uFF09\uFF1A", item.review.score ? `${item.review.score}/5` : "\u672A\u8BC4\u5206", " ", item.review.summary), item.answer && /* @__PURE__ */ import_react2.default.createElement("details", { className: "mr-tool-log" }, /* @__PURE__ */ import_react2.default.createElement("summary", null, "\u67E5\u770B\u7ED3\u679C"), /* @__PURE__ */ import_react2.default.createElement("pre", null, item.answer, item.answerTruncated ? "\n\u2026\uFF08\u5DF2\u622A\u65AD\uFF09" : "")), /* @__PURE__ */ import_react2.default.createElement("div", { className: "mr-node-actions" }, item.ok && /* @__PURE__ */ import_react2.default.createElement(import_react2.default.Fragment, null, /* @__PURE__ */ import_react2.default.createElement("button", { className: "mr-button mr-button-secondary mr-mini", type: "button", "aria-pressed": item.rating === 1, disabled: busy, onClick: () => onRate(...feedbackRatingArguments(run, item, "up")) }, "\u{1F44D} \u6709\u7528"), /* @__PURE__ */ import_react2.default.createElement("button", { className: "mr-button mr-button-secondary mr-mini", type: "button", "aria-pressed": item.rating === -1, disabled: busy, onClick: () => onRate(...feedbackRatingArguments(run, item, "down")) }, "\u{1F44E} \u4E0D\u597D")), canRerun && /* @__PURE__ */ import_react2.default.createElement("button", { className: "mr-button mr-mini", type: "button", title: rerun.confirm || void 0, onClick: () => onRerun(run.id, item.id, null) }, run.kind === "tool" ? "\u91CD\u65B0\u6267\u884C\u6B64\u8C03\u7528" : rerun.writes ? "\u5728\u65B0\u5DE5\u4F5C\u533A\u7EED\u8DD1" : "\u91CD\u8DD1\u6B64\u6B65"), !rerun.supported && !item.ok && item.ran && /* @__PURE__ */ import_react2.default.createElement("span", { className: "mr-caption" }, rerun.reason), rerun.supported && rerun.reassign && !(rerun.writes && item.ok) && allowReassign && others.length > 0 && !busy && /* @__PURE__ */ import_react2.default.createElement("span", { className: "mr-inline" }, /* @__PURE__ */ import_react2.default.createElement("select", { className: "mr-input mr-mini-select", "aria-label": "\u6539\u6D3E\u5230", value: target, onChange: (event) => setTarget(event.target.value) }, /* @__PURE__ */ import_react2.default.createElement("option", { value: "" }, "\u6539\u6D3E\u5230\u2026"), others.map((route) => /* @__PURE__ */ import_react2.default.createElement("option", { key: `${route.provider}/${route.model}`, value: `${route.provider}\0${route.model}` }, route.provider, "/", route.model))), /* @__PURE__ */ import_react2.default.createElement("button", { className: "mr-button mr-button-secondary mr-mini", type: "button", disabled: !target, onClick: () => {
2062
2442
  const [provider, model] = target.split("\0");
2063
2443
  onRerun(run.id, item.id, { provider, model });
2064
2444
  } }, "\u6539\u6D3E\u5E76\u91CD\u8DD1"))));
@@ -2081,7 +2461,10 @@ function RunHistoryCard({ ledger, routes, onRefresh, onRate, onRerun, busy, erro
2081
2461
  const runs = ledger?.runs ?? [];
2082
2462
  const [openId, setOpenId] = import_react2.default.useState(null);
2083
2463
  const current = runs.find((run) => run.id === openId) ?? runs[0];
2084
- return /* @__PURE__ */ import_react2.default.createElement("section", { className: "mr-card mr-results", "aria-label": "\u6267\u884C\u8BB0\u5F55" }, /* @__PURE__ */ import_react2.default.createElement("div", { className: "mr-card-head" }, /* @__PURE__ */ import_react2.default.createElement("div", null, /* @__PURE__ */ import_react2.default.createElement("h2", { className: "mr-card-title" }, "\u6267\u884C\u8BB0\u5F55\u4E0E\u5B50\u4EFB\u52A1"), /* @__PURE__ */ import_react2.default.createElement("p", { className: "mr-card-copy" }, "\u6765\u81EA\u4F1A\u8BDD\u4E2D\u7684 model_router_execute\u3001model_router_team_execute \u548C model_router_tool_run\u3002\u6BCF\u4E2A\u5DE5\u4F5C\u5305\u663E\u793A\u5206\u914D\u7684\u6A21\u578B\u3001\u539F\u56E0\u3001\u6E20\u9053\u3001\u8D39\u7528\uFF1B\u56DE\u9000\u65F6\u663E\u793A CLI \u539F\u59CB\u9519\u8BEF\u3002\u5931\u8D25\u7684\u6B65\u9AA4\u53EF\u5355\u72EC\u91CD\u8DD1\uFF0C\u4E0D\u4F1A\u91CD\u505A\u5DF2\u5B8C\u6210\u7684\u6B65\u9AA4\uFF1B\u53EF\u7F16\u8F91\u56E2\u961F\u8FD0\u884C\u4F1A\u5728\u65B0\u7684\u72EC\u7ACB\u5DE5\u4F5C\u533A\u5148\u5957\u7528\u4E4B\u524D\u7684\u6539\u52A8\u518D\u7EED\u8DD1\uFF0C\u5931\u8D25\u7684\u5355\u6B21\u8C03\u7528\u4F1A\u4F5C\u4E3A\u65B0\u8FD0\u884C\u91CD\u65B0\u6267\u884C\uFF0C\u4E8C\u8005\u90FD\u9700\u5148\u786E\u8BA4\u3002")), /* @__PURE__ */ import_react2.default.createElement("button", { className: "mr-button mr-button-secondary", type: "button", disabled: busy, onClick: onRefresh }, "\u5237\u65B0")), /* @__PURE__ */ import_react2.default.createElement("div", { className: "mr-card-body" }, error && /* @__PURE__ */ import_react2.default.createElement("p", { className: "mr-error", role: "alert" }, error), !ledger && !error && /* @__PURE__ */ import_react2.default.createElement("p", { className: "mr-empty", role: "status" }, "\u6B63\u5728\u8BFB\u53D6\u6267\u884C\u8BB0\u5F55\u2026"), ledger && runs.length === 0 && /* @__PURE__ */ import_react2.default.createElement("p", { className: "mr-empty" }, "\u8FD8\u6CA1\u6709\u6267\u884C\u8BB0\u5F55\u3002\u53EF\u5728\u4E0A\u65B9\u201C\u5728\u5DE5\u4F5C\u53F0\u6267\u884C\u201D\u4E2D\u9884\u89C8\u5E76\u6267\u884C\uFF0C\u6216\u5728\u5B98\u65B9\u4F1A\u8BDD\u4E2D\u8C03\u7528 model_router_execute\u3001model_router_team_execute\u3001model_router_tool_run\uFF0C\u8FD9\u91CC\u4F1A\u663E\u793A\u51B3\u7B56\u548C\u7ED3\u679C\u3002"), runs.length > 0 && /* @__PURE__ */ import_react2.default.createElement(import_react2.default.Fragment, null, /* @__PURE__ */ import_react2.default.createElement("label", { className: "mr-label", htmlFor: "mr-run-select" }, "\u9009\u62E9\u8BB0\u5F55"), /* @__PURE__ */ import_react2.default.createElement("select", { className: "mr-input", id: "mr-run-select", value: current?.id ?? "", onChange: (event) => setOpenId(event.target.value) }, runs.map((run) => /* @__PURE__ */ import_react2.default.createElement("option", { key: run.id, value: run.id }, new Date(run.createdAt).toLocaleString(), " \xB7 ", RUN_KIND_LABEL[run.kind ?? "assign"] ?? run.kind, " \xB7 ", RUN_STATUS_LABEL[run.status] ?? run.status, " \xB7 ", run.task.slice(0, 40)))), current && /* @__PURE__ */ import_react2.default.createElement("div", { className: "mr-run" }, /* @__PURE__ */ import_react2.default.createElement("div", { className: "mr-result-grid" }, /* @__PURE__ */ import_react2.default.createElement("div", { className: "mr-metric" }, /* @__PURE__ */ import_react2.default.createElement("div", { className: "mr-metric-label" }, "\u65B9\u6848"), /* @__PURE__ */ import_react2.default.createElement("div", { className: "mr-metric-value" }, ROUTING_PRESETS[current.preset]?.label ?? current.preset, current.budget?.downgraded ? "\uFF08\u8D85\u9884\u7B97\u81EA\u52A8\u964D\u7EA7\uFF09" : "")), /* @__PURE__ */ import_react2.default.createElement("div", { className: "mr-metric" }, /* @__PURE__ */ import_react2.default.createElement("div", { className: "mr-metric-label" }, "\u96BE\u5EA6"), /* @__PURE__ */ import_react2.default.createElement("div", { className: "mr-metric-value" }, BAND[current.decision?.complexity?.band] ?? "\u2014", current.decision?.complexity?.value !== null && current.decision?.complexity?.value !== void 0 ? ` \xB7 ${current.decision.complexity.value}` : "")), /* @__PURE__ */ import_react2.default.createElement("div", { className: "mr-metric" }, /* @__PURE__ */ import_react2.default.createElement("div", { className: "mr-metric-label" }, "\u9884\u4F30 / \u5B9E\u9645\uFF08\u8BA1\u5165\u9884\u7B97\uFF09"), /* @__PURE__ */ import_react2.default.createElement("div", { className: "mr-metric-value" }, money(current.decision?.estimatedCost), " / ", money(runTotals(current).budgetUsd))), /* @__PURE__ */ import_react2.default.createElement("div", { className: "mr-metric" }, /* @__PURE__ */ import_react2.default.createElement("div", { className: "mr-metric-label" }, "\u7C7B\u578B"), /* @__PURE__ */ import_react2.default.createElement("div", { className: "mr-metric-value" }, RUN_KIND_LABEL[current.kind ?? "assign"] ?? current.kind, current.kind === "team" || current.kind === "tool" ? ` \xB7 ${current.executionMode === "workspace-write" ? "\u53EF\u7F16\u8F91" : "\u53EA\u8BFB"}` : ""))), runTotals(current).subscription && /* @__PURE__ */ import_react2.default.createElement("p", { className: "mr-caption" }, "\u8BA2\u9605\u53C2\u8003\u8D39\u7528\uFF08\u6309 API \u4EF7\u6298\u7B97\uFF0C\u4E0D\u8BA1\u5165\u9884\u7B97\uFF09\uFF1A", money(runTotals(current).referenceUsd)), current.isolatedWorkspace && /* @__PURE__ */ import_react2.default.createElement("p", { className: "mr-caption" }, "\u72EC\u7ACB\u5DE5\u4F5C\u533A\uFF1A", /* @__PURE__ */ import_react2.default.createElement("code", null, current.isolatedWorkspace)), current.rerunOf && /* @__PURE__ */ import_react2.default.createElement("p", { className: "mr-caption" }, "\u91CD\u65B0\u6267\u884C\u81EA\u8FD0\u884C ", current.rerunOf.slice(0, 8), "\u3002"), current.decision?.reason && /* @__PURE__ */ import_react2.default.createElement("p", { className: "mr-caption" }, "\u8DEF\u7531\u539F\u56E0\uFF1A", current.decision.reason), /* @__PURE__ */ import_react2.default.createElement(DagView, { packages: current.packages, renderNode: (item) => /* @__PURE__ */ import_react2.default.createElement(RunNode, { run: current, item, routes, allowReassign: ledger?.settings?.allowManualReassign !== false, busy, onRate, onRerun }) })))));
2464
+ const totals = runTotals(current);
2465
+ const prior = priorAttemptTotals(current);
2466
+ const unknownCalls = prior.unknownCalls + [...current?.packages ?? [], ...current?.reviews ?? []].filter((item) => item.ran && item.billing !== "subscription" && !Number.isFinite(item.costUsd)).length;
2467
+ return /* @__PURE__ */ import_react2.default.createElement("section", { className: "mr-card mr-results", "aria-label": "\u6267\u884C\u8BB0\u5F55" }, /* @__PURE__ */ import_react2.default.createElement("div", { className: "mr-card-head" }, /* @__PURE__ */ import_react2.default.createElement("div", null, /* @__PURE__ */ import_react2.default.createElement("h2", { className: "mr-card-title" }, "\u6267\u884C\u8BB0\u5F55\u4E0E\u5B50\u4EFB\u52A1"), /* @__PURE__ */ import_react2.default.createElement("p", { className: "mr-card-copy" }, "\u67E5\u770B\u6A21\u578B\u5206\u914D\u3001\u9010\u6B65\u7ED3\u679C\u4E0E\u8D39\u7528\u3002\u5931\u8D25\u6B65\u9AA4\u53EF\u91CD\u8DD1\u6216\u6539\u6D3E\uFF1B\u5DF2\u5B8C\u6210\u7684\u4E0A\u6E38\u4FDD\u6301\u539F\u7ED3\u679C\u3002")), /* @__PURE__ */ import_react2.default.createElement("button", { className: "mr-button mr-button-secondary", type: "button", disabled: busy, onClick: onRefresh }, "\u5237\u65B0")), /* @__PURE__ */ import_react2.default.createElement("div", { className: "mr-card-body" }, error && /* @__PURE__ */ import_react2.default.createElement("p", { className: "mr-error", role: "alert" }, error), !ledger && !error && /* @__PURE__ */ import_react2.default.createElement("p", { className: "mr-empty", role: "status" }, "\u6B63\u5728\u8BFB\u53D6\u6267\u884C\u8BB0\u5F55\u2026"), ledger && runs.length === 0 && /* @__PURE__ */ import_react2.default.createElement("p", { className: "mr-empty" }, "\u8FD8\u6CA1\u6709\u6267\u884C\u8BB0\u5F55\u3002\u53EF\u5728\u4E0A\u65B9\u201C\u5728\u5DE5\u4F5C\u53F0\u6267\u884C\u201D\u4E2D\u9884\u89C8\u5E76\u6267\u884C\uFF0C\u6216\u5728\u5B98\u65B9\u4F1A\u8BDD\u4E2D\u8C03\u7528 model_router_execute\u3001model_router_team_execute\u3001model_router_tool_run\uFF0C\u8FD9\u91CC\u4F1A\u663E\u793A\u51B3\u7B56\u548C\u7ED3\u679C\u3002"), runs.length > 0 && /* @__PURE__ */ import_react2.default.createElement(import_react2.default.Fragment, null, /* @__PURE__ */ import_react2.default.createElement("label", { className: "mr-label", htmlFor: "mr-run-select" }, "\u9009\u62E9\u8BB0\u5F55"), /* @__PURE__ */ import_react2.default.createElement("select", { className: "mr-input", id: "mr-run-select", value: current?.id ?? "", onChange: (event) => setOpenId(event.target.value) }, runs.map((run) => /* @__PURE__ */ import_react2.default.createElement("option", { key: run.id, value: run.id }, new Date(run.createdAt).toLocaleString(), " \xB7 ", RUN_KIND_LABEL[run.kind ?? "assign"] ?? run.kind, " \xB7 ", RUN_STATUS_LABEL[run.status] ?? run.status, " \xB7 ", run.task.slice(0, 40)))), current && /* @__PURE__ */ import_react2.default.createElement("div", { className: "mr-run" }, /* @__PURE__ */ import_react2.default.createElement("div", { className: "mr-result-grid" }, /* @__PURE__ */ import_react2.default.createElement("div", { className: "mr-metric" }, /* @__PURE__ */ import_react2.default.createElement("div", { className: "mr-metric-label" }, "\u65B9\u6848"), /* @__PURE__ */ import_react2.default.createElement("div", { className: "mr-metric-value" }, ROUTING_PRESETS[current.preset]?.label ?? current.preset, current.budget?.downgraded ? "\uFF08\u8D85\u9884\u7B97\u81EA\u52A8\u964D\u7EA7\uFF09" : "")), /* @__PURE__ */ import_react2.default.createElement("div", { className: "mr-metric" }, /* @__PURE__ */ import_react2.default.createElement("div", { className: "mr-metric-label" }, "\u96BE\u5EA6"), /* @__PURE__ */ import_react2.default.createElement("div", { className: "mr-metric-value" }, BAND[current.decision?.complexity?.band] ?? "\u2014", current.decision?.complexity?.value !== null && current.decision?.complexity?.value !== void 0 ? ` \xB7 ${current.decision.complexity.value}` : "")), /* @__PURE__ */ import_react2.default.createElement("div", { className: "mr-metric" }, /* @__PURE__ */ import_react2.default.createElement("div", { className: "mr-metric-label" }, "\u9884\u4F30 / ", unknownCalls ? "\u5DF2\u77E5\u5B9E\u9645" : "\u5B9E\u9645", "\uFF08\u8BA1\u5165\u9884\u7B97\uFF09"), /* @__PURE__ */ import_react2.default.createElement("div", { className: "mr-metric-value" }, money(current.decision?.estimatedCost), " / ", money(totals.budgetUsd))), /* @__PURE__ */ import_react2.default.createElement("div", { className: "mr-metric" }, /* @__PURE__ */ import_react2.default.createElement("div", { className: "mr-metric-label" }, "\u7C7B\u578B"), /* @__PURE__ */ import_react2.default.createElement("div", { className: "mr-metric-value" }, RUN_KIND_LABEL[current.kind ?? "assign"] ?? current.kind, current.kind === "team" || current.kind === "tool" ? ` \xB7 ${current.executionMode === "workspace-write" ? "\u53EF\u7F16\u8F91" : "\u53EA\u8BFB"}` : ""))), totals.subscription && /* @__PURE__ */ import_react2.default.createElement("p", { className: "mr-caption" }, "\u8BA2\u9605\u53C2\u8003\u8D39\u7528\uFF08\u6309 API \u4EF7\u6298\u7B97\uFF0C\u4E0D\u8BA1\u5165\u9884\u7B97\uFF09\uFF1A", money(totals.referenceUsd)), unknownCalls > 0 && /* @__PURE__ */ import_react2.default.createElement("p", { className: "mr-caption" }, "\u53E6\u6709 ", unknownCalls, " \u6B21\u8C03\u7528\u8D39\u7528\u672A\u77E5\uFF0C\u672A\u8BA1\u5165\u4E0A\u65B9\u91D1\u989D\u3002"), (prior.budgetUsd > 0 || prior.subscriptionRuns > 0 || prior.unknownCalls > 0) && /* @__PURE__ */ import_react2.default.createElement("p", { className: "mr-caption" }, "\u7D2F\u8BA1\u5305\u542B\u6B64\u524D\u91CD\u8DD1\u5C1D\u8BD5\uFF1AAPI ", money(prior.budgetUsd), " \xB7 \u8BA2\u9605\u53C2\u8003 ", money(prior.referenceUsd), prior.unknownCalls > 0 ? ` \xB7 \u8D39\u7528\u672A\u77E5 ${prior.unknownCalls} \u6B21` : "", "\u3002\u4E0B\u65B9\u8282\u70B9\u663E\u793A\u6700\u8FD1\u4E00\u6B21\u7ED3\u679C\u3002"), current.isolatedWorkspace && /* @__PURE__ */ import_react2.default.createElement("p", { className: "mr-caption" }, "\u72EC\u7ACB\u5DE5\u4F5C\u533A\uFF1A", /* @__PURE__ */ import_react2.default.createElement("code", null, current.isolatedWorkspace)), current.rerunOf && /* @__PURE__ */ import_react2.default.createElement("p", { className: "mr-caption" }, "\u91CD\u65B0\u6267\u884C\u81EA\u8FD0\u884C ", current.rerunOf.slice(0, 8), "\u3002"), current.decision?.reason && /* @__PURE__ */ import_react2.default.createElement("p", { className: "mr-caption" }, "\u8DEF\u7531\u539F\u56E0\uFF1A", current.decision.reason), /* @__PURE__ */ import_react2.default.createElement(DagView, { packages: current.packages, renderNode: (item) => /* @__PURE__ */ import_react2.default.createElement(RunNode, { run: current, item, routes, allowReassign: ledger?.settings?.allowManualReassign !== false, busy, onRate, onRerun }) })))));
2085
2468
  }
2086
2469
  function BillingCard({ billing, error, onRefresh, refreshing }) {
2087
2470
  const rows = billingRows(billing);
@@ -2104,22 +2487,31 @@ var STATUS_TEXT = Object.freeze({
2104
2487
  "paused-budget": "\u5DF2\u56E0\u9884\u7B97\u6682\u505C\uFF0C\u672A\u542F\u52A8\u6A21\u578B",
2105
2488
  "paused-subscription-failure": "\u6709\u6B65\u9AA4\u56E0\u8BA2\u9605\u8C03\u7528\u5931\u8D25\u800C\u6682\u505C\uFF0C\u8BF7\u5728\u4E0B\u65B9\u6267\u884C\u8BB0\u5F55\u4E2D\u9009\u62E9\u5982\u4F55\u7EE7\u7EED"
2106
2489
  });
2107
- function RunLauncher({ task, mode, directRoute, budgetUsd, defaultPreset, ledger, previewRun, startRun, onStarted, disabledReason }) {
2490
+ function RunLauncher({ task, mode, directRoute, budgetUsd, defaultPreset, ledger, previewRun, startRun, onStarted, disabledReason, planningRevision }) {
2108
2491
  const [preset, setPreset] = import_react3.default.useState(defaultPreset || "balanced");
2109
2492
  const lastWorkspace = [...ledger?.runs ?? []].map((run) => run.workspace).find(Boolean) ?? "";
2110
2493
  const [workspace, setWorkspace] = import_react3.default.useState("");
2111
2494
  const [phase, setPhase] = import_react3.default.useState({ kind: "idle" });
2112
2495
  const mounted = import_react3.default.useRef(true);
2113
2496
  const confirmRef = import_react3.default.useRef(null);
2114
- import_react3.default.useEffect(() => () => {
2115
- mounted.current = false;
2497
+ const pendingRequest = import_react3.default.useRef(0);
2498
+ const inputSignature = JSON.stringify([task, mode, directRoute?.provider, directRoute?.model, budgetUsd, preset, workspace, lastWorkspace, planningRevision, disabledReason]);
2499
+ const latestSignature = import_react3.default.useRef(inputSignature);
2500
+ latestSignature.current = inputSignature;
2501
+ import_react3.default.useEffect(() => {
2502
+ mounted.current = true;
2503
+ return () => {
2504
+ mounted.current = false;
2505
+ pendingRequest.current += 1;
2506
+ };
2116
2507
  }, []);
2117
2508
  import_react3.default.useEffect(() => {
2118
2509
  setPreset(defaultPreset || "balanced");
2119
2510
  }, [defaultPreset]);
2120
2511
  import_react3.default.useEffect(() => {
2121
- setPhase((previous) => previous.kind === "preview" || previous.kind === "error" ? { kind: "idle" } : previous);
2122
- }, [task, mode, directRoute?.provider, directRoute?.model, budgetUsd, preset, workspace]);
2512
+ pendingRequest.current += 1;
2513
+ setPhase((previous) => ["previewing", "preview", "error"].includes(previous.kind) ? { kind: "idle" } : previous);
2514
+ }, [inputSignature]);
2123
2515
  import_react3.default.useEffect(() => {
2124
2516
  if (phase.kind === "preview") confirmRef.current?.focus();
2125
2517
  }, [phase.kind]);
@@ -2128,22 +2520,29 @@ function RunLauncher({ task, mode, directRoute, budgetUsd, defaultPreset, ledger
2128
2520
  const blocked = disabledReason || (unavailable ? "\u5DE5\u4F5C\u53F0\u6267\u884C\u670D\u52A1\u5C1A\u672A\u52A0\u8F7D\uFF0C\u8BF7\u66F4\u65B0\u63D2\u4EF6\u540E\u91CD\u8BD5\u3002" : !text2(task) ? "\u5148\u5728\u4E0A\u65B9\u201C\u4EFB\u52A1\u89C4\u5212\u201D\u4E2D\u63CF\u8FF0\u4EFB\u52A1\u3002" : "");
2129
2521
  const busy = phase.kind === "previewing" || phase.kind === "running";
2130
2522
  const preview = async () => {
2523
+ if (blocked || busy) return;
2524
+ const current = ++pendingRequest.current;
2525
+ const snapshot = request();
2526
+ const signature2 = inputSignature;
2131
2527
  setPhase({ kind: "previewing" });
2132
2528
  try {
2133
- const value = unwrapRemote(await previewRun(request()), "\u6267\u884C\u9884\u89C8\u5931\u8D25\u3002");
2134
- if (mounted.current) setPhase({ kind: "preview", value });
2529
+ const value = unwrapRemote(await previewRun(snapshot), "\u6267\u884C\u9884\u89C8\u5931\u8D25\u3002");
2530
+ if (mounted.current && current === pendingRequest.current && signature2 === latestSignature.current) setPhase({ kind: "preview", value, request: snapshot, signature: signature2 });
2135
2531
  } catch (error) {
2136
- if (mounted.current) setPhase({ kind: "error", message: text2(error?.message) || "\u6267\u884C\u9884\u89C8\u5931\u8D25\u3002" });
2532
+ if (mounted.current && current === pendingRequest.current && signature2 === latestSignature.current) setPhase({ kind: "error", message: text2(error?.message) || "\u6267\u884C\u9884\u89C8\u5931\u8D25\u3002" });
2137
2533
  }
2138
2534
  };
2139
2535
  const confirm2 = async () => {
2536
+ if (phase.kind !== "preview" || phase.signature !== latestSignature.current) return;
2140
2537
  const shown = phase.value;
2141
- setPhase({ kind: "running", value: shown });
2538
+ const snapshot = phase.request;
2539
+ const signature2 = phase.signature;
2540
+ setPhase({ kind: "running", value: shown, request: snapshot, signature: signature2 });
2142
2541
  try {
2143
- const value = unwrapRemote(await startRun({ ...request(), confirmedReasons: shown.reasons.map((item) => item.code) }), "\u6267\u884C\u5931\u8D25\u3002");
2542
+ const value = unwrapRemote(await startRun({ ...snapshot, confirmedReasons: (shown.reasons ?? []).map((item) => item.code) }), "\u6267\u884C\u5931\u8D25\u3002");
2144
2543
  if (!mounted.current) return;
2145
2544
  if (value.status === "needs-confirmation") {
2146
- setPhase({ kind: "preview", value, changed: true });
2545
+ setPhase(signature2 === latestSignature.current ? { kind: "preview", value, request: snapshot, signature: signature2, changed: true } : { kind: "idle" });
2147
2546
  return;
2148
2547
  }
2149
2548
  setPhase({ kind: "done", value });
@@ -2166,7 +2565,7 @@ function RunLauncher({ task, mode, directRoute, budgetUsd, defaultPreset, ledger
2166
2565
  },
2167
2566
  onCancel: () => setPhase({ kind: "idle" })
2168
2567
  }
2169
- ), phase.kind === "done" && /* @__PURE__ */ import_react3.default.createElement("div", { className: phase.value.status === "failed" || phase.value.status?.startsWith("paused") ? "mr-error" : "mr-empty", role: "status" }, STATUS_TEXT[phase.value.status] ?? `\u72B6\u6001\uFF1A${phase.value.status}`, phase.value.runId ? `\uFF1B\u7ED3\u679C\u5DF2\u8BB0\u5F55\uFF08\u8FD0\u884C ${phase.value.runId.slice(0, 8)}\uFF09\uFF0C\u89C1\u4E0B\u65B9\u201C\u6267\u884C\u8BB0\u5F55\u4E0E\u5B50\u4EFB\u52A1\u201D\u3002` : "\u3002", phase.value.budget?.message ? ` ${phase.value.budget.exceeded && phase.value.status !== "paused-budget" ? "\u5DF2\u6309\u4F60\u7684\u786E\u8BA4\u8D85\u9884\u7B97\u6267\u884C\uFF1A" : ""}${phase.value.budget.message}` : "")));
2568
+ ), phase.kind === "done" && /* @__PURE__ */ import_react3.default.createElement("div", { className: phase.value.status === "failed" || phase.value.status === "partial" || phase.value.status?.startsWith("paused") ? "mr-error" : "mr-empty", role: "status" }, STATUS_TEXT[phase.value.status] ?? `\u72B6\u6001\uFF1A${phase.value.status}`, phase.value.runId ? `\uFF1B\u7ED3\u679C\u5DF2\u8BB0\u5F55\uFF08\u8FD0\u884C ${phase.value.runId.slice(0, 8)}\uFF09\uFF0C\u89C1\u4E0B\u65B9\u201C\u6267\u884C\u8BB0\u5F55\u4E0E\u5B50\u4EFB\u52A1\u201D\u3002` : "\u3002", phase.value.budget?.message ? ` ${phase.value.budget.exceeded && phase.value.status !== "paused-budget" ? "\u5DF2\u6309\u4F60\u7684\u786E\u8BA4\u8D85\u9884\u7B97\u6267\u884C\uFF1A" : ""}${phase.value.budget.message}` : "")));
2170
2569
  }
2171
2570
  function LaunchPreview({ value, changed, running, confirmRef, onConfirm, onCancel }) {
2172
2571
  const packages = value.decision?.packages ?? [];
@@ -11604,7 +12003,7 @@ var xterm_default = `/**
11604
12003
  `;
11605
12004
 
11606
12005
  // .dsh-plugin/client/host-version.mjs
11607
- var ROUTER_CLIENT_VERSION = true ? "0.14.0" : "";
12006
+ var ROUTER_CLIENT_VERSION = true ? "0.16.0" : "";
11608
12007
  var STALE_HOST_MESSAGE = "\u63D2\u4EF6\u540E\u53F0\u7248\u672C\u8F83\u65E7\uFF0C\u8BF7\u5B8C\u5168\u9000\u51FA\u5E76\u91CD\u542F Harness\uFF08\u5305\u62EC\u6258\u76D8\u56FE\u6807\uFF09\u540E\u518D\u4F7F\u7528\u3002";
11609
12008
  function isMissingRemoteMethod(message) {
11610
12009
  const value = String(message ?? "");
@@ -12101,62 +12500,64 @@ function CliTerminalCard({ api, health }) {
12101
12500
 
12102
12501
  // .dsh-plugin/client/router-main.css
12103
12502
  var router_main_default = `.mr-workspace {
12104
- --mr-card: rgba(255, 255, 255, .94);
12105
- --mr-ink: #182232;
12106
- --mr-muted: #526174;
12107
- --mr-line: rgba(38, 55, 75, .13);
12108
- --mr-accent: #315cc8;
12503
+ --mr-card: #fff;
12504
+ --mr-ink: #1e2c3e;
12505
+ --mr-muted: #586b80;
12506
+ --mr-line: #dce4ed;
12507
+ --mr-accent: #2859c5;
12109
12508
  --mr-soft: #edf3ff;
12509
+ --mr-surface: #f3f6fa;
12510
+ --mr-button-ink: #fff;
12511
+ container: mr-workspace / inline-size;
12110
12512
  box-sizing: border-box;
12111
12513
  width: 100%;
12112
12514
  height: 100%;
12113
12515
  min-height: 0;
12114
12516
  overflow-y: auto;
12115
- background: rgba(246, 249, 253, .9);
12116
- backdrop-filter: blur(18px);
12517
+ background: var(--mr-surface);
12117
12518
  color: var(--mr-ink);
12118
12519
  font-family: inherit;
12119
12520
  }
12120
12521
  .mr-workspace *, .mr-workspace *::before, .mr-workspace *::after { box-sizing: border-box; }
12121
- .mr-shell { width: min(1160px, 100%); margin: 0 auto; padding: 36px 32px 64px; }
12122
- .mr-header { display: flex; flex-wrap: wrap; gap: 20px; align-items: end; justify-content: space-between; margin-bottom: 24px; }
12522
+ .mr-shell { width: min(1320px, 100%); margin: 0 auto; padding: 24px 32px 48px; }
12523
+ .mr-header { display: flex; flex-wrap: wrap; gap: 20px; align-items: center; justify-content: space-between; margin-bottom: 18px; }
12123
12524
  .mr-eyebrow { margin: 0 0 8px; color: var(--mr-accent); font-size: 11px; font-weight: 750; letter-spacing: .14em; text-transform: uppercase; }
12124
- .mr-title { margin: 0; font-size: clamp(25px, 3vw, 34px); letter-spacing: -.035em; line-height: 1.16; }
12525
+ .mr-title { margin: 0; font-size: clamp(25px, 3vw, 30px); letter-spacing: -.035em; line-height: 1.3; }
12125
12526
  .mr-subtitle { margin: 10px 0 0; color: var(--mr-muted); font-size: 14px; line-height: 1.65; }
12126
12527
  .mr-status { display: inline-flex; align-items: center; gap: 8px; padding: 8px 12px; border: 1px solid var(--mr-line); border-radius: 999px; background: var(--mr-card); color: var(--mr-muted); font-size: 12px; white-space: nowrap; }
12127
12528
  .mr-status-dot { width: 7px; height: 7px; border-radius: 50%; background: #2cba83; }
12128
12529
  .mr-status-dot.loading { background: #e9a640; }
12129
12530
  .mr-status-dot.error { background: #d95360; }
12130
- .mr-grid { display: grid; grid-template-columns: minmax(0, 1.35fr) minmax(280px, .85fr); gap: 18px; align-items: start; }
12131
- .mr-card { min-width: 0; border: 1px solid var(--mr-line); border-radius: 18px; background: var(--mr-card); box-shadow: 0 12px 42px rgba(25, 45, 76, .08); }
12531
+ .mr-grid { display: grid; grid-template-columns: minmax(0, 1.7fr) minmax(280px, .85fr); gap: 20px; align-items: start; }
12532
+ .mr-card { min-width: 0; border: 1px solid var(--mr-line); border-radius: 14px; background: var(--mr-card); box-shadow: 0 3px 12px rgba(25, 45, 76, .025); }
12132
12533
  .mr-card-head { display: flex; align-items: center; justify-content: space-between; gap: 12px; padding: 20px 22px 0; }
12133
- .mr-card-title { margin: 0; font-size: 16px; font-weight: 700; }
12534
+ .mr-card-title { margin: 0; font-size: 17px; font-weight: 700; line-height: 1.5; }
12134
12535
  .mr-card-copy { margin: 5px 0 0; color: var(--mr-muted); font-size: 12px; line-height: 1.55; }
12135
12536
  .mr-card-body { padding: 18px 22px 22px; }
12136
12537
  .mr-label { display: block; margin: 0 0 8px; font-size: 12px; font-weight: 700; }
12137
12538
  .mr-textarea, .mr-input { width: 100%; border: 1px solid var(--mr-line); border-radius: 11px; background: #fff; color: var(--mr-ink); font: inherit; outline: none; }
12138
- .mr-textarea { min-height: 154px; padding: 13px 14px; resize: vertical; line-height: 1.6; font-size: 14px; }
12539
+ .mr-textarea { min-height: 150px; padding: 13px 14px; resize: vertical; line-height: 1.7; font-size: 14px; }
12139
12540
  .mr-input { min-height: 38px; padding: 8px 11px; font-size: 13px; }
12140
12541
  .mr-textarea:focus, .mr-input:focus { border-color: var(--mr-accent); box-shadow: 0 0 0 3px rgba(49, 92, 200, .13); }
12141
12542
  .mr-controls { display: flex; flex-wrap: wrap; align-items: end; justify-content: space-between; gap: 14px; margin-top: 17px; }
12142
- .mr-control-group { display: flex; flex-direction: column; gap: 7px; }
12143
- .mr-control-label { color: var(--mr-muted); font-size: 11px; font-weight: 650; }
12543
+ .mr-control-group { display: flex; flex-direction: column; gap: 7px; min-width: 0; max-width: 100%; }
12544
+ .mr-control-label { color: var(--mr-muted); font-size: 12px; font-weight: 650; }
12144
12545
  .mr-segment { display: inline-flex; padding: 3px; border-radius: 10px; background: #edf1f7; }
12145
12546
  .mr-segment button { border: 0; border-radius: 8px; padding: 8px 12px; background: transparent; color: var(--mr-muted); font: inherit; font-size: 12px; cursor: pointer; }
12146
12547
  .mr-segment button[aria-pressed='true'] { background: #fff; color: var(--mr-ink); box-shadow: 0 2px 8px rgba(20, 35, 56, .1); font-weight: 700; }
12147
12548
  .mr-budget { width: 140px; }
12148
12549
  .mr-direct { min-width: min(100%, 280px); }
12149
12550
  .mr-actions { display: flex; flex-wrap: wrap; gap: 9px; align-items: center; margin-top: 18px; }
12150
- .mr-button { border: 1px solid transparent; border-radius: 10px; min-height: 38px; padding: 8px 14px; background: var(--mr-accent); color: #fff; font: inherit; font-size: 13px; font-weight: 700; cursor: pointer; }
12551
+ .mr-button { border: 1px solid transparent; border-radius: 9px; min-height: 38px; padding: 8px 14px; background: var(--mr-accent); color: var(--mr-button-ink); font: inherit; font-size: 13px; font-weight: 700; cursor: pointer; }
12151
12552
  .mr-button:hover:not(:disabled) { filter: brightness(.94); }
12152
12553
  .mr-button:disabled { cursor: not-allowed; opacity: .5; }
12153
12554
  .mr-button-secondary { border-color: var(--mr-line); background: #fff; color: var(--mr-ink); }
12154
- .mr-caption { color: var(--mr-muted); font-size: 11px; line-height: 1.5; }
12155
- .mr-search { margin-top: 14px; }
12555
+ .mr-caption { color: var(--mr-muted); font-size: 12px; line-height: 1.65; overflow-wrap: anywhere; }
12556
+ .mr-search { margin-top: 0; }
12156
12557
  .mr-list { display: grid; gap: 8px; margin-top: 13px; max-height: 395px; overflow-y: auto; }
12157
12558
  .mr-route { display: flex; justify-content: space-between; gap: 10px; padding: 10px 11px; border: 1px solid var(--mr-line); border-radius: 10px; background: #f9fbfe; }
12158
- .mr-route-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 12px; font-weight: 700; }
12159
- .mr-route-provider { margin-top: 2px; color: var(--mr-muted); font-size: 10px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
12559
+ .mr-route-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 13px; font-weight: 700; }
12560
+ .mr-route-provider { margin-top: 4px; color: var(--mr-muted); font-size: 11px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
12160
12561
  .mr-pill { align-self: start; flex: none; padding: 3px 7px; border-radius: 7px; background: var(--mr-soft); color: var(--mr-accent); font-size: 10px; font-weight: 700; }
12161
12562
  .mr-empty, .mr-error { padding: 14px; border-radius: 10px; background: #f4f6fa; color: var(--mr-muted); font-size: 12px; line-height: 1.6; }
12162
12563
  .mr-error { background: #fff0f1; color: #a52d3c; }
@@ -12171,12 +12572,12 @@ var router_main_default = `.mr-workspace {
12171
12572
  .mr-package-top { display: flex; flex-wrap: wrap; justify-content: space-between; gap: 8px; align-items: center; }
12172
12573
  .mr-package-name { font-size: 12px; font-weight: 750; }
12173
12574
  .mr-package-route { color: var(--mr-accent); font-size: 11px; font-weight: 700; }
12174
- .mr-package-copy { margin: 7px 0 0; color: var(--mr-muted); font-size: 11px; line-height: 1.6; }
12575
+ .mr-package-copy { margin: 7px 0 0; color: var(--mr-muted); font-size: 12px; line-height: 1.65; overflow-wrap: anywhere; }
12175
12576
  .mr-notice { margin-top: 18px; padding: 14px 16px; border: 1px solid rgba(49, 92, 200, .16); border-radius: 12px; background: #eff4ff; color: #354d7a; font-size: 11px; line-height: 1.65; }
12176
12577
  .mr-notice code { font-family: ui-monospace, SFMono-Regular, Consolas, monospace; font-size: 11px; }
12177
12578
  @media (max-width: 850px) { .mr-grid { grid-template-columns: 1fr; } .mr-shell { padding: 24px 18px 48px; } }
12178
12579
  @media (prefers-color-scheme: dark) {
12179
- .mr-workspace { --mr-card: rgba(30, 38, 51, .94); --mr-ink: #ecf2ff; --mr-muted: #aebbd0; --mr-line: rgba(210, 224, 245, .15); --mr-accent: #91adff; --mr-soft: rgba(97, 132, 222, .18); background: rgba(18, 23, 32, .91); }
12580
+ .mr-workspace { --mr-card: #1e2633; --mr-ink: #ecf2ff; --mr-muted: #aebbd0; --mr-line: #354154; --mr-accent: #a1baff; --mr-soft: #2b3959; --mr-surface: #141b26; --mr-button-ink: #17243b; color-scheme: dark; }
12180
12581
  .mr-textarea, .mr-input, .mr-segment button[aria-pressed='true'], .mr-button-secondary { background: #273245; color: var(--mr-ink); }
12181
12582
  .mr-segment, .mr-empty, .mr-metric { background: #222d3e; }
12182
12583
  .mr-route, .mr-package { background: #222d3e; }
@@ -12295,11 +12696,96 @@ var router_main_default = `.mr-workspace {
12295
12696
  .mr-term-history { margin-top: 14px; font-size: 12px; }
12296
12697
  .mr-term-table { width: 100%; border-collapse: collapse; margin-top: 6px; }
12297
12698
  .mr-term-table th, .mr-term-table td { padding: 4px 6px; border-bottom: 1px solid rgba(127, 127, 127, .25); text-align: left; vertical-align: top; max-width: 320px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
12699
+
12700
+ /* Workspace navigation keeps every panel mounted, including running terminals. */
12701
+ .mr-view[hidden] { display: none !important; }
12702
+ .mr-view { min-width: 0; }
12703
+ .mr-stack { display: grid; gap: 20px; }
12704
+ .mr-stack > .mr-card, .mr-model-grid > .mr-card { margin: 0; }
12705
+ .mr-overview { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); border: 1px solid var(--mr-line); background: var(--mr-card); border-radius: 14px; overflow: hidden; margin-bottom: 16px; }
12706
+ .mr-overview-item { display: grid; align-content: start; gap: 4px; min-width: 0; padding: 12px 22px; border: 0; text-align: left; background: transparent; color: var(--mr-ink); font: inherit; cursor: pointer; }
12707
+ .mr-overview-item + .mr-overview-item { border-left: 1px solid var(--mr-line); }
12708
+ .mr-overview-item:hover { background: var(--mr-soft); }
12709
+ .mr-overview-label { color: var(--mr-muted); font-size: 12px; }
12710
+ .mr-overview-item strong { font-size: 25px; font-weight: 650; line-height: 1.3; font-variant-numeric: tabular-nums; }
12711
+ .mr-overview-item small { color: var(--mr-muted); font-size: 14px; font-weight: 400; }
12712
+ .mr-overview-detail { color: var(--mr-muted); font-size: 11px; line-height: 1.5; }
12713
+ .mr-workspace-tabs { display: flex; gap: 6px; position: sticky; top: 0; z-index: 5; background: var(--mr-surface); padding: 10px 0; margin-bottom: 14px; border-bottom: 1px solid var(--mr-line); }
12714
+ .mr-workspace-tabs button { display: flex; align-items: center; justify-content: center; gap: 10px; min-height: 44px; padding: 10px 18px; border: 1px solid transparent; border-radius: 9px; color: var(--mr-muted); background: transparent; font: inherit; font-size: 13px; font-weight: 600; cursor: pointer; }
12715
+ .mr-workspace-tabs button:hover { background: var(--mr-card); color: var(--mr-ink); }
12716
+ .mr-workspace-tabs button[aria-selected='true'] { background: var(--mr-card); border-color: var(--mr-line); color: var(--mr-accent); box-shadow: 0 2px 4px rgba(25, 45, 76, .04); }
12717
+ .mr-tab-number { font-size: 10px; font-weight: 500; opacity: .7; font-variant-numeric: tabular-nums; }
12718
+ .mr-view-heading { margin: 4px 0 20px; }
12719
+ .mr-stack > .mr-view-heading { margin-bottom: 0; }
12720
+ .mr-view-heading h2 { margin: 0; font-size: 20px; }
12721
+ .mr-view-heading p { margin: 7px 0 0; color: var(--mr-muted); font-size: 13px; line-height: 1.6; }
12722
+ .mr-planning-grid { grid-template-columns: minmax(0, 1fr) 290px; }
12723
+ .mr-planning-guide { min-width: 0; padding: 20px 4px 4px 8px; }
12724
+ .mr-workflow { display: grid; gap: 24px; margin: 20px 0 24px; padding: 0; list-style: none; }
12725
+ .mr-workflow li { display: flex; align-items: start; gap: 12px; }
12726
+ .mr-workflow li > span { display: grid; place-items: center; flex: 0 0 30px; height: 30px; border: 1px solid var(--mr-line); border-radius: 50%; background: var(--mr-card); color: var(--mr-accent); font-size: 10px; font-weight: 650; }
12727
+ .mr-workflow strong { font-size: 13px; line-height: 30px; }
12728
+ .mr-workflow p { margin: 2px 0 0; color: var(--mr-muted); font-size: 12px; line-height: 1.65; }
12729
+ .mr-guide-links { display: grid; gap: 8px; }
12730
+ .mr-guide-links .mr-button { text-align: left; font-weight: 500; font-size: 12px; }
12731
+ .mr-task-hint { margin: 8px 0 0; }
12732
+ .mr-plan-explanation { margin: 12px 0; padding: 10px 12px; border: 1px solid var(--mr-line); border-radius: 9px; color: var(--mr-muted); font-size: 12px; line-height: 1.65; }
12733
+ .mr-plan-explanation summary, .mr-package-details summary { cursor: pointer; }
12734
+ .mr-package-details summary { line-height: 1.8; }
12735
+ .mr-package-details summary .mr-package-route { display: block; margin-left: 16px; overflow-wrap: anywhere; }
12736
+ .mr-package-details[open] { border-color: var(--mr-accent); }
12737
+ .mr-footer { margin-top: 28px; padding-top: 18px; border-top: 1px solid var(--mr-line); color: var(--mr-muted); font-size: 11px; line-height: 1.8; overflow-wrap: anywhere; }
12738
+ .mr-footer code { font-size: 11px; }
12739
+ .mr-tool-status { flex-wrap: wrap; line-height: 1.6; }
12740
+ .mr-table td { overflow-wrap: anywhere; }
12741
+ .mr-term-cwd { min-width: min(100%, 240px); }
12742
+
12743
+ /* Respond to the Harness panel width, even when a wide window has a sidebar. */
12744
+ @container mr-workspace (max-width: 960px) {
12745
+ .mr-shell { padding: 24px 22px 40px; }
12746
+ .mr-planning-grid { grid-template-columns: minmax(0, 1fr) 240px; }
12747
+ .mr-model-grid { grid-template-columns: 1fr; }
12748
+ .mr-planning-grid .mr-card-head { flex-wrap: wrap; }
12749
+ .mr-profile-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
12750
+ }
12751
+ @container mr-workspace (max-width: 680px) {
12752
+ .mr-shell { padding: 20px 14px 32px; }
12753
+ .mr-header { gap: 14px; margin-bottom: 18px; }
12754
+ .mr-subtitle { font-size: 13px; }
12755
+ .mr-overview { margin-bottom: 12px; }
12756
+ .mr-overview-item { padding: 13px 10px; gap: 6px; }
12757
+ .mr-overview-item strong { font-size: 20px; }
12758
+ .mr-overview-detail { font-size: 10px; }
12759
+ .mr-overview-item small { font-size: 11px; }
12760
+ .mr-workspace-tabs { gap: 2px; }
12761
+ .mr-workspace-tabs button { flex: 1; min-width: 0; padding: 9px 4px; font-size: 12px; }
12762
+ .mr-tab-number { display: none; }
12763
+ .mr-grid { grid-template-columns: 1fr; }
12764
+ .mr-planning-guide { padding: 12px 4px 0; }
12765
+ .mr-workflow { gap: 12px; margin: 14px 0; }
12766
+ .mr-guide-links { grid-template-columns: repeat(2, minmax(0, 1fr)); }
12767
+ .mr-guide-links .mr-button { font-size: 11px; }
12768
+ .mr-card-head { padding: 18px 16px 0; align-items: start; flex-wrap: wrap; }
12769
+ .mr-card-body { padding: 14px 16px 18px; }
12770
+ .mr-profile-grid { grid-template-columns: 1fr; }
12771
+ .mr-tool { align-items: stretch; flex-direction: column; gap: 10px; }
12772
+ .mr-tool-actions { justify-content: flex-start; }
12773
+ .mr-segment { flex-wrap: wrap; max-width: 100%; }
12774
+ .mr-launch-workspace { min-width: 0; }
12775
+ .mr-result-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
12776
+ .mr-meters { grid-template-columns: 1fr; }
12777
+ }
12778
+ @media (prefers-reduced-motion: reduce) { .mr-workspace { scroll-behavior: auto; } }
12298
12779
  `;
12299
12780
 
12300
12781
  // .dsh-plugin/client/router-main.jsx
12301
12782
  var money2 = (value) => value === null || value === void 0 ? "\u4EF7\u683C\u5F85\u914D\u7F6E" : `$${Number(value).toFixed(4)}`;
12302
12783
  var text5 = (value) => typeof value === "string" ? value.trim() : "";
12784
+ var routingSettingsSignature = (value) => JSON.stringify([
12785
+ value.modelProfilesJson,
12786
+ value.routingPreset,
12787
+ ...Object.keys(ADAPTIVE_DEFAULTS).map((key) => value[key] ?? ADAPTIVE_DEFAULTS[key])
12788
+ ]);
12303
12789
  function RouterPanelIcon({ size = 20, active = false }) {
12304
12790
  return /* @__PURE__ */ import_react5.default.createElement("svg", { width: size, height: size, viewBox: "0 0 24 24", fill: "none", "aria-hidden": "true" }, /* @__PURE__ */ import_react5.default.createElement("path", { d: "M7 6.5h7M7 17.5h7M15 6.5v11", stroke: "currentColor", strokeWidth: "1.8", strokeLinecap: "round" }), /* @__PURE__ */ import_react5.default.createElement("circle", { cx: "5", cy: "6.5", r: "2", fill: active ? "currentColor" : "none", stroke: "currentColor", strokeWidth: "1.6" }), /* @__PURE__ */ import_react5.default.createElement("circle", { cx: "5", cy: "17.5", r: "2", fill: active ? "currentColor" : "none", stroke: "currentColor", strokeWidth: "1.6" }), /* @__PURE__ */ import_react5.default.createElement("circle", { cx: "17", cy: "12", r: "3", fill: active ? "currentColor" : "none", stroke: "currentColor", strokeWidth: "1.7" }));
12305
12791
  }
@@ -12316,10 +12802,12 @@ function ChannelBadge({ item }) {
12316
12802
  const official = item.executionChannel === "official-cli";
12317
12803
  return /* @__PURE__ */ import_react5.default.createElement("span", { className: official ? "mr-pill mr-pill-channel-ok" : "mr-pill", title: item.channelDetail ?? "" }, official ? `\u5B98\u65B9 CLI \xB7 ${item.channelLabel ?? item.channelTool}` : "\u6A21\u578B\u76EE\u5F55 API");
12318
12804
  }
12319
- function PlanResults({ plan, ledger }) {
12805
+ function PlanResults({ plan, ledger, headingRef }) {
12320
12806
  const selected = plan.selected;
12321
12807
  const budget = planBudget(ledger, plan.estimatedCost);
12322
- return /* @__PURE__ */ import_react5.default.createElement("section", { className: "mr-card mr-results", "aria-label": "\u8DEF\u7531\u5EFA\u8BAE" }, /* @__PURE__ */ import_react5.default.createElement("div", { className: "mr-card-head" }, /* @__PURE__ */ import_react5.default.createElement("div", null, /* @__PURE__ */ import_react5.default.createElement("h2", { className: "mr-card-title" }, "\u8DEF\u7531\u5EFA\u8BAE"), /* @__PURE__ */ import_react5.default.createElement("p", { className: "mr-card-copy" }, "\u672C\u5730\u8BA1\u7B97\u5B8C\u6210\uFF0C\u672A\u5411\u6A21\u578B\u53D1\u9001\u4EFB\u52A1\u5185\u5BB9\u3002"))), /* @__PURE__ */ import_react5.default.createElement("div", { className: "mr-card-body" }, /* @__PURE__ */ import_react5.default.createElement("div", { className: "mr-result-grid" }, /* @__PURE__ */ import_react5.default.createElement("div", { className: "mr-metric" }, /* @__PURE__ */ import_react5.default.createElement("div", { className: "mr-metric-label" }, "\u63A8\u8350\u8DEF\u7EBF"), /* @__PURE__ */ import_react5.default.createElement("div", { className: "mr-metric-value" }, selected ? `${selected.provider}/${selected.model}` : "\u6682\u65E0\u8DEF\u7EBF")), /* @__PURE__ */ import_react5.default.createElement("div", { className: "mr-metric" }, /* @__PURE__ */ import_react5.default.createElement("div", { className: "mr-metric-label" }, "\u4EFB\u52A1\u590D\u6742\u5EA6 \xB7 \u96BE\u5EA6\u5206"), /* @__PURE__ */ import_react5.default.createElement("div", { className: "mr-metric-value" }, { simple: "\u7B80\u5355", balanced: "\u4E2D\u7B49", complex: "\u590D\u6742" }[plan.complexity.band] || plan.complexity.band, " \xB7 ", plan.complexity.value)), /* @__PURE__ */ import_react5.default.createElement("div", { className: "mr-metric" }, /* @__PURE__ */ import_react5.default.createElement("div", { className: "mr-metric-label" }, "\u4F30\u7B97\u603B\u6210\u672C"), /* @__PURE__ */ import_react5.default.createElement("div", { className: "mr-metric-value" }, money2(plan.estimatedCost))), /* @__PURE__ */ import_react5.default.createElement("div", { className: "mr-metric" }, /* @__PURE__ */ import_react5.default.createElement("div", { className: "mr-metric-label" }, "\u8DEF\u7531\u65B9\u6848"), /* @__PURE__ */ import_react5.default.createElement("div", { className: "mr-metric-value" }, ROUTING_PRESETS[plan.preset]?.label ?? "\u5747\u8861"))), budget?.exceeded && /* @__PURE__ */ import_react5.default.createElement("p", { className: "mr-error", role: "alert" }, "\u6267\u884C\u524D\u9884\u7B97\u68C0\u67E5\uFF1A", budget.message, " \u5B9E\u9645\u6267\u884C\u65F6\u5C06\u6309\u8BBE\u7F6E\u81EA\u52A8\u964D\u7EA7\u6216\u6682\u505C\u8BE2\u95EE\u3002"), budget?.limited && !budget.exceeded && budget.estimateKnown && /* @__PURE__ */ import_react5.default.createElement("p", { className: "mr-caption" }, "\u6267\u884C\u524D\u9884\u7B97\u68C0\u67E5\uFF1A\u672C\u6B21\u9884\u4F30 ", money2(plan.estimatedCost), "\uFF0C\u5269\u4F59\u989D\u5EA6 ", money2(budget.remainingUsd), "\u3002"), plan.loginRequired && /* @__PURE__ */ import_react5.default.createElement("p", { className: "mr-caption" }, "\u63A8\u8350\u6A21\u578B\u7684\u5B98\u65B9 CLI \u672A\u767B\u5F55\uFF0C\u6267\u884C\u65F6\u76F4\u63A5\u8D70\u6A21\u578B\u76EE\u5F55 API\uFF1B\u53EF\u5728\u201C\u5B98\u65B9\u5DE5\u5177\u201D\u5361\u7247\u70B9\u201C\u53BB\u767B\u5F55\u201D\u3002"), /* @__PURE__ */ import_react5.default.createElement("div", { className: "mr-channel-line" }, /* @__PURE__ */ import_react5.default.createElement("span", { className: "mr-control-label" }, "\u6267\u884C\u6E20\u9053"), /* @__PURE__ */ import_react5.default.createElement(ChannelBadge, { item: plan })), /* @__PURE__ */ import_react5.default.createElement("p", { className: "mr-caption" }, plan.reason), plan.optimization.budgetExceeded && /* @__PURE__ */ import_react5.default.createElement("p", { className: "mr-error" }, "\u6309\u5DF2\u63D0\u4F9B\u5355\u4EF7\u4F30\u7B97\uFF0C\u4EFB\u52A1\u53EF\u80FD\u8D85\u8FC7\u672C\u6B21\u9884\u7B97\u3002\u9884\u7B97\u53EA\u5F71\u54CD\u5EFA\u8BAE\uFF0C\u4E0D\u4F1A\u963B\u6B62\u5B9E\u9645\u6263\u8D39\u3002"), plan.mode === "team" && /* @__PURE__ */ import_react5.default.createElement(import_react5.default.Fragment, null, /* @__PURE__ */ import_react5.default.createElement("h3", { className: "mr-section-title" }, "\u56E2\u961F\u5DE5\u4F5C\u5305"), /* @__PURE__ */ import_react5.default.createElement("p", { className: "mr-caption" }, "\u4E0B\u65B9\u6A21\u578B\u662F\u89C4\u5212\u5EFA\u8BAE\uFF1B\u6258\u7BA1\u6267\u884C\u4F1A\u6309\u5382\u5546 CLI \u7684\u6A21\u578B\u540D\u89C4\u5219\u9009\u7528\uFF0C\u672A\u6838\u9A8C\u6620\u5C04\u65F6\u4F7F\u7528\u8BE5 CLI \u7684\u9ED8\u8BA4\u6A21\u578B\u3002"), plan.team.workPackages.length > 1 && /* @__PURE__ */ import_react5.default.createElement(DagView, { packages: plan.team.workPackages, label: "\u5DE5\u4F5C\u5305\u4F9D\u8D56\u56FE", renderNode: (item) => /* @__PURE__ */ import_react5.default.createElement("p", { className: "mr-package-route" }, item.recommendedProvider, "/", item.recommendedModel) }), plan.team.workPackages.length === 0 ? /* @__PURE__ */ import_react5.default.createElement("div", { className: "mr-empty" }, "\u5F53\u524D\u76EE\u5F55\u6CA1\u6709\u53EF\u5206\u914D\u7684\u6A21\u578B\u8DEF\u7EBF\u3002") : plan.team.workPackages.map((item, index) => /* @__PURE__ */ import_react5.default.createElement("article", { className: "mr-package", key: item.id }, /* @__PURE__ */ import_react5.default.createElement("div", { className: "mr-package-top" }, /* @__PURE__ */ import_react5.default.createElement("div", { className: "mr-package-name" }, index + 1, ". ", item.name), /* @__PURE__ */ import_react5.default.createElement("div", { className: "mr-package-route" }, item.recommendedProvider, "/", item.recommendedModel)), item.objective && /* @__PURE__ */ import_react5.default.createElement("p", { className: "mr-package-copy" }, "\u5177\u4F53\u76EE\u6807\uFF1A", item.objective), /* @__PURE__ */ import_react5.default.createElement("p", { className: "mr-package-copy" }, item.purpose, item.dependsOn.length > 0 ? ` \xB7 \u4F9D\u8D56\uFF1A${item.dependsOn.join("\u3001")}` : ""), /* @__PURE__ */ import_react5.default.createElement("p", { className: "mr-package-copy" }, "\u96BE\u5EA6\uFF1A", { simple: "\u7B80\u5355", balanced: "\u4E2D\u7B49", complex: "\u56F0\u96BE" }[item.difficulty] || item.difficulty || "\u5F85\u8BC4\u4F30", " \xB7 \u8D39\u7528\uFF1A", money2(item.estimatedCost)), /* @__PURE__ */ import_react5.default.createElement("p", { className: "mr-package-copy" }, "\u9A8C\u6536\uFF1A", item.verificationChecklist.join("\uFF1B")), /* @__PURE__ */ import_react5.default.createElement("div", { className: "mr-channel-line" }, /* @__PURE__ */ import_react5.default.createElement(ChannelBadge, { item }), item.loginRequired && /* @__PURE__ */ import_react5.default.createElement("span", { className: "mr-pill" }, "CLI \u672A\u767B\u5F55")), item.channelDetail && /* @__PURE__ */ import_react5.default.createElement("p", { className: "mr-package-copy" }, "\u6E20\u9053\u8BF4\u660E\uFF1A", item.channelDetail)))), plan.routingBypassed && /* @__PURE__ */ import_react5.default.createElement("p", { className: "mr-caption" }, "\u5DF2\u6307\u5B9A\u5355\u4E00\u6A21\u578B\uFF0C\u672A\u4E0E\u5176\u4ED6\u8DEF\u7EBF\u6BD4\u8F83\u3002\u5728\u5B98\u65B9\u4F1A\u8BDD\u4E2D\u8C03\u7528 ", /* @__PURE__ */ import_react5.default.createElement("code", null, "model_router_execute"), " \u5E76\u4F20\u5165\u8BE5 provider \u4E0E model \u5373\u53EF\u76F4\u63A5\u6267\u884C\uFF1B\u82E5\u8BE5\u6A21\u578B\u5141\u8BB8\u5B98\u65B9\u5DE5\u5177\uFF0C\u4F1A\u4F18\u5148\u4F7F\u7528\u5BF9\u5E94 CLI\u3002"), plan.mode === "team" && /* @__PURE__ */ import_react5.default.createElement("p", { className: "mr-caption" }, plan.team.handoff), /* @__PURE__ */ import_react5.default.createElement("div", { className: "mr-notice" }, plan.pricingNotice, " ", plan.qualityNotice, " ", plan.availabilityNotice, " ", plan.modalityNotice || "")));
12808
+ const packageNames = new Map((plan.team?.workPackages ?? []).map((item) => [item.id, item.name]));
12809
+ const purposeLabel = { analysis: "\u4EFB\u52A1\u5206\u6790", execution: "\u4EFB\u52A1\u5B9E\u65BD", verification: "\u72EC\u7ACB\u9A8C\u8BC1", synthesis: "\u7ED3\u679C\u6574\u5408" };
12810
+ return /* @__PURE__ */ import_react5.default.createElement("section", { className: "mr-card mr-results", "aria-label": "\u8DEF\u7531\u5EFA\u8BAE" }, /* @__PURE__ */ import_react5.default.createElement("div", { className: "mr-card-head" }, /* @__PURE__ */ import_react5.default.createElement("div", null, /* @__PURE__ */ import_react5.default.createElement("h2", { className: "mr-card-title", ref: headingRef, tabIndex: -1 }, "\u8DEF\u7531\u5EFA\u8BAE"), /* @__PURE__ */ import_react5.default.createElement("p", { className: "mr-card-copy" }, "\u672C\u5730\u8BA1\u7B97\u5B8C\u6210\uFF0C\u672A\u5411\u6A21\u578B\u53D1\u9001\u4EFB\u52A1\u5185\u5BB9\u3002"))), /* @__PURE__ */ import_react5.default.createElement("div", { className: "mr-card-body" }, /* @__PURE__ */ import_react5.default.createElement("div", { className: "mr-result-grid" }, /* @__PURE__ */ import_react5.default.createElement("div", { className: "mr-metric" }, /* @__PURE__ */ import_react5.default.createElement("div", { className: "mr-metric-label" }, "\u63A8\u8350\u8DEF\u7EBF"), /* @__PURE__ */ import_react5.default.createElement("div", { className: "mr-metric-value" }, selected ? `${selected.provider}/${selected.model}` : "\u6682\u65E0\u8DEF\u7EBF")), /* @__PURE__ */ import_react5.default.createElement("div", { className: "mr-metric" }, /* @__PURE__ */ import_react5.default.createElement("div", { className: "mr-metric-label" }, "\u4EFB\u52A1\u590D\u6742\u5EA6 \xB7 \u5206\u503C\uFF080\u20131\uFF09"), /* @__PURE__ */ import_react5.default.createElement("div", { className: "mr-metric-value" }, { simple: "\u7B80\u5355", balanced: "\u4E2D\u7B49", complex: "\u590D\u6742" }[plan.complexity.band] || plan.complexity.band, " \xB7 ", plan.complexity.value)), /* @__PURE__ */ import_react5.default.createElement("div", { className: "mr-metric" }, /* @__PURE__ */ import_react5.default.createElement("div", { className: "mr-metric-label" }, "\u4F30\u7B97\u603B\u6210\u672C"), /* @__PURE__ */ import_react5.default.createElement("div", { className: "mr-metric-value" }, money2(plan.estimatedCost))), /* @__PURE__ */ import_react5.default.createElement("div", { className: "mr-metric" }, /* @__PURE__ */ import_react5.default.createElement("div", { className: "mr-metric-label" }, "\u8DEF\u7531\u65B9\u6848"), /* @__PURE__ */ import_react5.default.createElement("div", { className: "mr-metric-value" }, ROUTING_PRESETS[plan.preset]?.label ?? "\u5747\u8861"))), budget?.exceeded && /* @__PURE__ */ import_react5.default.createElement("p", { className: "mr-error", role: "alert" }, "\u6267\u884C\u524D\u9884\u7B97\u68C0\u67E5\uFF1A", budget.message, " \u5B9E\u9645\u6267\u884C\u65F6\u5C06\u6309\u8BBE\u7F6E\u81EA\u52A8\u964D\u7EA7\u6216\u6682\u505C\u8BE2\u95EE\u3002"), budget?.limited && !budget.exceeded && budget.estimateKnown && /* @__PURE__ */ import_react5.default.createElement("p", { className: "mr-caption" }, "\u6267\u884C\u524D\u9884\u7B97\u68C0\u67E5\uFF1A\u672C\u6B21\u9884\u4F30 ", money2(plan.estimatedCost), "\uFF0C\u5269\u4F59\u989D\u5EA6 ", money2(budget.remainingUsd), "\u3002"), plan.loginRequired && /* @__PURE__ */ import_react5.default.createElement("p", { className: "mr-caption" }, "\u63A8\u8350\u6A21\u578B\u7684\u5B98\u65B9 CLI \u672A\u767B\u5F55\uFF0C\u6267\u884C\u65F6\u76F4\u63A5\u8D70\u6A21\u578B\u76EE\u5F55 API\uFF1B\u53EF\u5728\u201C\u5B98\u65B9\u5DE5\u5177\u201D\u5361\u7247\u70B9\u201C\u53BB\u767B\u5F55\u201D\u3002"), /* @__PURE__ */ import_react5.default.createElement("div", { className: "mr-channel-line" }, /* @__PURE__ */ import_react5.default.createElement("span", { className: "mr-control-label" }, "\u6267\u884C\u6E20\u9053"), /* @__PURE__ */ import_react5.default.createElement(ChannelBadge, { item: plan })), /* @__PURE__ */ import_react5.default.createElement("details", { className: "mr-plan-explanation" }, /* @__PURE__ */ import_react5.default.createElement("summary", null, "\u67E5\u770B\u89C4\u5212\u4F9D\u636E\u4E0E\u4F30\u7B97\u8BF4\u660E"), /* @__PURE__ */ import_react5.default.createElement("p", { className: "mr-caption" }, plan.reason), /* @__PURE__ */ import_react5.default.createElement("p", { className: "mr-caption" }, plan.pricingNotice, " ", plan.qualityNotice, " ", plan.availabilityNotice, " ", plan.modalityNotice || "")), plan.optimization.budgetExceeded && /* @__PURE__ */ import_react5.default.createElement("p", { className: "mr-error" }, "\u6309\u5DF2\u63D0\u4F9B\u5355\u4EF7\u4F30\u7B97\uFF0C\u4EFB\u52A1\u53EF\u80FD\u8D85\u8FC7\u672C\u6B21\u9884\u7B97\u3002\u9884\u7B97\u53EA\u5F71\u54CD\u5EFA\u8BAE\uFF0C\u4E0D\u4F1A\u963B\u6B62\u5B9E\u9645\u6263\u8D39\u3002"), plan.mode === "team" && /* @__PURE__ */ import_react5.default.createElement(import_react5.default.Fragment, null, /* @__PURE__ */ import_react5.default.createElement("h3", { className: "mr-section-title" }, "\u56E2\u961F\u5DE5\u4F5C\u5305"), /* @__PURE__ */ import_react5.default.createElement("p", { className: "mr-caption" }, "\u4E0B\u65B9\u6A21\u578B\u662F\u89C4\u5212\u5EFA\u8BAE\uFF1B\u6258\u7BA1\u6267\u884C\u4F1A\u6309\u5382\u5546 CLI \u7684\u6A21\u578B\u540D\u89C4\u5219\u9009\u7528\uFF0C\u672A\u6838\u9A8C\u6620\u5C04\u65F6\u4F7F\u7528\u8BE5 CLI \u7684\u9ED8\u8BA4\u6A21\u578B\u3002"), plan.team.workPackages.length > 1 && /* @__PURE__ */ import_react5.default.createElement(DagView, { packages: plan.team.workPackages, label: "\u5DE5\u4F5C\u5305\u4F9D\u8D56\u56FE", renderNode: (item) => /* @__PURE__ */ import_react5.default.createElement("p", { className: "mr-package-route" }, item.recommendedProvider, "/", item.recommendedModel) }), plan.team.workPackages.length === 0 ? /* @__PURE__ */ import_react5.default.createElement("div", { className: "mr-empty" }, "\u5F53\u524D\u76EE\u5F55\u6CA1\u6709\u53EF\u5206\u914D\u7684\u6A21\u578B\u8DEF\u7EBF\u3002") : plan.team.workPackages.map((item, index) => /* @__PURE__ */ import_react5.default.createElement("details", { className: "mr-package mr-package-details", key: item.id }, /* @__PURE__ */ import_react5.default.createElement("summary", null, /* @__PURE__ */ import_react5.default.createElement("span", { className: "mr-package-name" }, index + 1, ". ", item.name), /* @__PURE__ */ import_react5.default.createElement("span", { className: "mr-package-route" }, item.recommendedProvider, "/", item.recommendedModel)), item.objective && /* @__PURE__ */ import_react5.default.createElement("p", { className: "mr-package-copy" }, "\u5177\u4F53\u76EE\u6807\uFF1A", item.objective), /* @__PURE__ */ import_react5.default.createElement("p", { className: "mr-package-copy" }, purposeLabel[item.purpose] ?? item.purpose, item.dependsOn.length > 0 ? ` \xB7 \u4F9D\u8D56\uFF1A${item.dependsOn.map((id2) => packageNames.get(id2) ?? id2).join("\u3001")}` : ""), /* @__PURE__ */ import_react5.default.createElement("p", { className: "mr-package-copy" }, "\u96BE\u5EA6\uFF1A", { simple: "\u7B80\u5355", balanced: "\u4E2D\u7B49", complex: "\u56F0\u96BE" }[item.difficulty] || item.difficulty || "\u5F85\u8BC4\u4F30", " \xB7 \u8D39\u7528\uFF1A", money2(item.estimatedCost)), /* @__PURE__ */ import_react5.default.createElement("p", { className: "mr-package-copy" }, "\u9A8C\u6536\uFF1A", item.verificationChecklist.join("\uFF1B")), /* @__PURE__ */ import_react5.default.createElement("div", { className: "mr-channel-line" }, /* @__PURE__ */ import_react5.default.createElement(ChannelBadge, { item }), item.loginRequired && /* @__PURE__ */ import_react5.default.createElement("span", { className: "mr-pill" }, "CLI \u672A\u767B\u5F55")), item.channelDetail && /* @__PURE__ */ import_react5.default.createElement("p", { className: "mr-package-copy" }, "\u6E20\u9053\u8BF4\u660E\uFF1A", item.channelDetail)))), plan.routingBypassed && /* @__PURE__ */ import_react5.default.createElement("p", { className: "mr-caption" }, "\u5DF2\u6307\u5B9A\u5355\u4E00\u6A21\u578B\uFF0C\u672A\u4E0E\u5176\u4ED6\u8DEF\u7EBF\u6BD4\u8F83\u3002\u5728\u5B98\u65B9\u4F1A\u8BDD\u4E2D\u8C03\u7528 ", /* @__PURE__ */ import_react5.default.createElement("code", null, "model_router_execute"), " \u5E76\u4F20\u5165\u8BE5 provider \u4E0E model \u5373\u53EF\u76F4\u63A5\u6267\u884C\uFF1B\u82E5\u8BE5\u6A21\u578B\u5141\u8BB8\u5B98\u65B9\u5DE5\u5177\uFF0C\u4F1A\u4F18\u5148\u4F7F\u7528\u5BF9\u5E94 CLI\u3002"), plan.mode === "team" && /* @__PURE__ */ import_react5.default.createElement("p", { className: "mr-caption" }, plan.team.handoff)));
12323
12811
  }
12324
12812
  var remoteError = (response, fallback) => text5(response?.error?.message) || text5(response?.value?.error) || fallback;
12325
12813
  function probeLabel(probe) {
@@ -12466,12 +12954,19 @@ function OfficialToolsCard({ listOfficialTools, installOfficialTool, cancelOffic
12466
12954
  })), /* @__PURE__ */ import_react5.default.createElement("p", { className: "mr-caption", style: { marginTop: 12 } }, "\u5B89\u88C5\u7531 Host \u6309\u6CE8\u518C\u8868\u56FA\u5B9A\u6765\u6E90\u6267\u884C\uFF0C\u4E0D\u63A5\u53D7\u81EA\u5B9A\u4E49\u5305\u540D\uFF1B\u53EF\u70B9\u201C\u53D6\u6D88\u5B89\u88C5\u201D\u7EC8\u6B62\u4E0B\u8F7D\u4EFB\u52A1\uFF0C\u968F\u540E\u91CD\u65B0\u68C0\u6D4B\u5B9E\u9645\u7248\u672C\u3002ZCode \u5B89\u88C5\u5668\u542F\u52A8\u540E\u4ECD\u9700\u5728\u539F\u5382\u7A97\u53E3\u9009\u62E9\u76EE\u5F55\u5E76\u5B8C\u6210\u5B89\u88C5\u3002Agent \u4E5F\u53EF\u8C03\u7528 ", /* @__PURE__ */ import_react5.default.createElement("code", null, "model_router_tool_install"), "\uFF0C\u6216\u5728\u4F1A\u8BDD\u4F7F\u7528 ", /* @__PURE__ */ import_react5.default.createElement("code", null, "/tools"), "\u3002")));
12467
12955
  }
12468
12956
  var HEADLESS_TOOLS = /* @__PURE__ */ new Set(["claude-code", "codex", "gemini"]);
12957
+ var WORKSPACE_VIEWS = [
12958
+ { id: "plan", label: "\u4EFB\u52A1\u4E0E\u6267\u884C", number: "01" },
12959
+ { id: "models", label: "\u6A21\u578B\u914D\u7F6E", number: "02" },
12960
+ { id: "tools", label: "\u5B98\u65B9\u5DE5\u5177", number: "03" },
12961
+ { id: "controls", label: "\u9884\u7B97\u4E0E\u5B89\u5168", number: "04" }
12962
+ ];
12469
12963
  function useWorkbenchData({ toolHealth, completeOnboarding, loadLedger, rateResult, rerunStep, loadBoundaries }) {
12470
12964
  const [health, setHealth] = import_react5.default.useState({ report: null, error: "", refreshing: false });
12471
12965
  const [ledger, setLedger] = import_react5.default.useState({ value: null, error: "" });
12472
12966
  const [boundaries, setBoundaries] = import_react5.default.useState({ value: null, error: "" });
12473
12967
  const [busy, setBusy] = import_react5.default.useState(false);
12474
12968
  const mounted = import_react5.default.useRef(true);
12969
+ const ledgerRequest = import_react5.default.useRef(0);
12475
12970
  import_react5.default.useEffect(() => () => {
12476
12971
  mounted.current = false;
12477
12972
  }, []);
@@ -12489,11 +12984,15 @@ function useWorkbenchData({ toolHealth, completeOnboarding, loadLedger, rateResu
12489
12984
  }
12490
12985
  };
12491
12986
  const refreshLedger = async () => {
12987
+ const request = ++ledgerRequest.current;
12492
12988
  try {
12493
12989
  const value = await call(loadLedger, "\u6267\u884C\u8BB0\u5F55\u8BFB\u53D6\u5931\u8D25\u3002");
12494
- if (mounted.current) setLedger({ value, error: "" });
12990
+ if (mounted.current && request === ledgerRequest.current) setLedger({ value, error: "" });
12991
+ if (request !== ledgerRequest.current) return null;
12992
+ return value;
12495
12993
  } catch (error) {
12496
- if (mounted.current) setLedger((previous) => ({ ...previous, error: text5(error?.message) || "\u6267\u884C\u8BB0\u5F55\u8BFB\u53D6\u5931\u8D25\u3002" }));
12994
+ if (mounted.current && request === ledgerRequest.current) setLedger((previous) => ({ ...previous, error: text5(error?.message) || "\u6267\u884C\u8BB0\u5F55\u8BFB\u53D6\u5931\u8D25\u3002" }));
12995
+ return null;
12497
12996
  }
12498
12997
  };
12499
12998
  const refreshBoundaries = async () => {
@@ -12512,10 +13011,10 @@ function useWorkbenchData({ toolHealth, completeOnboarding, loadLedger, rateResu
12512
13011
  if (mounted.current) setHealth((previous) => ({ ...previous, error: text5(error?.message) || "\u65E0\u6CD5\u4FDD\u5B58\u4F53\u68C0\u72B6\u6001\u3002" }));
12513
13012
  }
12514
13013
  };
12515
- const rate = async (runId, packageId, rating) => {
13014
+ const rate = async (runId, packageId, rating, expectedFinishedAt) => {
12516
13015
  setBusy(true);
12517
13016
  try {
12518
- await call(() => rateResult({ runId, packageId, rating }), "\u8BC4\u4EF7\u4FDD\u5B58\u5931\u8D25\u3002");
13017
+ await call(() => rateResult({ runId, packageId, rating, ...expectedFinishedAt === void 0 ? {} : { expectedFinishedAt } }), "\u8BC4\u4EF7\u4FDD\u5B58\u5931\u8D25\u3002");
12519
13018
  await refreshLedger();
12520
13019
  } catch (error) {
12521
13020
  if (mounted.current) setLedger((previous) => ({ ...previous, error: text5(error?.message) || "\u8BC4\u4EF7\u4FDD\u5B58\u5931\u8D25\u3002" }));
@@ -12573,14 +13072,43 @@ function RouterMainPage({ loadCatalog, settingsScope, listOfficialTools, install
12573
13072
  const [plan, setPlan] = import_react5.default.useState(null);
12574
13073
  const [planError, setPlanError] = import_react5.default.useState("");
12575
13074
  const [toolProbes, setToolProbes] = import_react5.default.useState(null);
13075
+ const [routingSettings, setRoutingSettings] = import_react5.default.useState(() => {
13076
+ const value = settingsScope.getSnapshot().value ?? {};
13077
+ return routingSettingsSignature(value);
13078
+ });
13079
+ const [view, setView] = import_react5.default.useState("plan");
13080
+ const tabRefs = import_react5.default.useRef({});
13081
+ const resultHeading = import_react5.default.useRef(null);
12576
13082
  const budgetEdited = import_react5.default.useRef(false);
12577
13083
  const budgetValue = import_react5.default.useRef(budget);
12578
13084
  const mounted = import_react5.default.useRef(false);
12579
13085
  const catalogRequest = import_react5.default.useRef(0);
13086
+ const generationRequest = import_react5.default.useRef(0);
13087
+ const generationInputs = import_react5.default.useRef("");
13088
+ generationInputs.current = JSON.stringify([task, budget, mode, directKey, routingSettings, catalogState.catalog, toolProbes, workbench.health.report?.tools]);
13089
+ import_react5.default.useEffect(() => {
13090
+ if (plan) resultHeading.current?.focus({ preventScroll: true });
13091
+ }, [plan]);
13092
+ const selectView = (id2) => {
13093
+ setView(id2);
13094
+ tabRefs.current[id2]?.focus({ preventScroll: true });
13095
+ };
13096
+ const navigateTabs = (event, index) => {
13097
+ const next = event.key === "ArrowRight" ? (index + 1) % WORKSPACE_VIEWS.length : event.key === "ArrowLeft" ? (index + WORKSPACE_VIEWS.length - 1) % WORKSPACE_VIEWS.length : event.key === "Home" ? 0 : event.key === "End" ? WORKSPACE_VIEWS.length - 1 : null;
13098
+ if (next === null) return;
13099
+ event.preventDefault();
13100
+ selectView(WORKSPACE_VIEWS[next].id);
13101
+ };
12580
13102
  import_react5.default.useEffect(() => {
12581
13103
  const syncBudget = () => {
13104
+ const value = settingsScope.getSnapshot().value ?? {};
13105
+ const signature2 = routingSettingsSignature(value);
13106
+ setRoutingSettings((previous) => {
13107
+ if (previous === signature2) return previous;
13108
+ return signature2;
13109
+ });
12582
13110
  if (budgetEdited.current) return;
12583
- const next = String(settingsScope.getSnapshot().value?.budgetUsd ?? 0);
13111
+ const next = String(value.budgetUsd ?? 0);
12584
13112
  if (next !== budgetValue.current) {
12585
13113
  budgetValue.current = next;
12586
13114
  setBudget(next);
@@ -12591,6 +13119,18 @@ function RouterMainPage({ loadCatalog, settingsScope, listOfficialTools, install
12591
13119
  syncBudget();
12592
13120
  return settingsScope.subscribe(syncBudget);
12593
13121
  }, [settingsScope]);
13122
+ import_react5.default.useEffect(() => {
13123
+ setPlan(null);
13124
+ setPlanError("");
13125
+ }, [routingSettings]);
13126
+ const dataRevision = workbench.ledger.value?.dynamicData?.revision ?? "";
13127
+ const feedbackRevision = workbench.ledger.value?.learning?.revision ?? "";
13128
+ import_react5.default.useEffect(() => {
13129
+ if (plan && plan.workbenchRevision !== `${dataRevision}/${feedbackRevision}`) {
13130
+ setPlan(null);
13131
+ setPlanError("");
13132
+ }
13133
+ }, [dataRevision, feedbackRevision, plan]);
12594
13134
  import_react5.default.useEffect(() => {
12595
13135
  mounted.current = true;
12596
13136
  const request = ++catalogRequest.current;
@@ -12622,15 +13162,19 @@ function RouterMainPage({ loadCatalog, settingsScope, listOfficialTools, install
12622
13162
  }
12623
13163
  };
12624
13164
  const invalidatePlan = () => {
13165
+ generationRequest.current += 1;
12625
13166
  setPlan(null);
12626
13167
  setPlanError("");
12627
13168
  };
12628
13169
  const handleToolProbes = import_react5.default.useCallback((snapshot) => {
13170
+ generationRequest.current += 1;
12629
13171
  setToolProbes(snapshot);
12630
13172
  setPlan(null);
12631
13173
  setPlanError("");
12632
13174
  }, []);
12633
- const generate = () => {
13175
+ const generate = async () => {
13176
+ const request = ++generationRequest.current;
13177
+ const inputs = generationInputs.current;
12634
13178
  setPlanError("");
12635
13179
  try {
12636
13180
  if (!text5(task)) throw new Error("\u8BF7\u5148\u63CF\u8FF0\u4EFB\u52A1\u3002");
@@ -12639,7 +13183,14 @@ function RouterMainPage({ loadCatalog, settingsScope, listOfficialTools, install
12639
13183
  if (!Number.isFinite(parsedBudget) || parsedBudget < 0) throw new Error("\u9884\u7B97\u5FC5\u987B\u662F\u4E0D\u5C0F\u4E8E 0 \u7684\u6570\u5B57\u3002");
12640
13184
  const direct = mode === "direct" ? routes.find((route) => `${route.provider}/${route.model}` === directKey) ?? routes[0] : null;
12641
13185
  if (mode === "direct" && !direct) throw new Error("\u8BF7\u9009\u62E9\u8981\u76F4\u63A5\u4F7F\u7528\u7684\u6A21\u578B\u3002");
12642
- setPlan(createWorkspacePlan(task, catalogState.catalog, {
13186
+ const signature2 = routingSettingsSignature(settingsScope.getSnapshot().value ?? {});
13187
+ const ledger = await workbench.refreshLedger();
13188
+ if (request !== generationRequest.current || inputs !== generationInputs.current || !mounted.current) return;
13189
+ if (!ledger) throw new Error("\u8BF7\u5148\u6062\u590D\u6267\u884C\u8BB0\u5F55\u8FDE\u63A5\uFF1B\u65E0\u6CD5\u6838\u5BF9\u6700\u65B0\u6570\u636E\u4E0E\u5B66\u4E60\u72B6\u6001\u3002");
13190
+ if (signature2 !== routingSettingsSignature(settingsScope.getSnapshot().value ?? {})) throw new Error("\u89C4\u5212\u8BBE\u7F6E\u5DF2\u66F4\u65B0\uFF0C\u8BF7\u91CD\u65B0\u751F\u6210\u5EFA\u8BAE\u3002");
13191
+ const next = createWorkspacePlan(task, catalogState.catalog, {
13192
+ ...ledger.routingData,
13193
+ learning: ledger.learning,
12643
13194
  mode,
12644
13195
  ...direct ? { directProvider: direct.provider, directModel: direct.model } : {},
12645
13196
  budgetUsd: parsedBudget,
@@ -12647,42 +13198,22 @@ function RouterMainPage({ loadCatalog, settingsScope, listOfficialTools, install
12647
13198
  installedToolIds: (toolProbes?.probes ?? []).filter((probe) => probe.installed).map((probe) => probe.id),
12648
13199
  runnableToolIds: (toolProbes?.readiness ?? []).filter((item) => item.ready).map((item) => item.id),
12649
13200
  preset: settingsScope.getSnapshot().value?.routingPreset ?? "balanced",
12650
- qualityBiases: workbench.ledger.value?.biases ?? null,
12651
13201
  loggedOutToolIds: (workbench.health.report?.tools ?? []).filter((item) => item.installed && item.login?.state === "logged-out").map((item) => item.id)
12652
- }));
13202
+ });
13203
+ setPlan({ ...next, workbenchRevision: `${ledger.dynamicData?.revision ?? ""}/${ledger.learning?.revision ?? ""}` });
12653
13204
  } catch (error) {
13205
+ if (request !== generationRequest.current || inputs !== generationInputs.current || !mounted.current) return;
12654
13206
  setPlan(null);
12655
13207
  setPlanError(text5(error?.message) || "\u65E0\u6CD5\u751F\u6210\u8DEF\u7531\u5EFA\u8BAE\u3002");
12656
13208
  }
12657
13209
  };
12658
- return /* @__PURE__ */ import_react5.default.createElement("main", { className: "mr-workspace" }, /* @__PURE__ */ import_react5.default.createElement("style", null, router_main_default), /* @__PURE__ */ import_react5.default.createElement("div", { className: "mr-shell" }, /* @__PURE__ */ import_react5.default.createElement("header", { className: "mr-header" }, /* @__PURE__ */ import_react5.default.createElement("div", null, /* @__PURE__ */ import_react5.default.createElement("p", { className: "mr-eyebrow" }, "Model Router \xB7 DeepSeek Harness"), /* @__PURE__ */ import_react5.default.createElement("h1", { className: "mr-title" }, "\u6A21\u578B\u8DEF\u7531\u5DE5\u4F5C\u53F0"), /* @__PURE__ */ import_react5.default.createElement("p", { className: "mr-subtitle" }, "\u67E5\u770B\u5B98\u65B9\u6A21\u578B\u76EE\u5F55\uFF0C\u4E3A\u4EFB\u52A1\u751F\u6210\u8DEF\u7EBF\u5EFA\u8BAE\u4E0E\u56E2\u961F\u5DE5\u4F5C\u5305\u3002\u4E3B\u4F1A\u8BDD\u6A21\u578B\u4ECD\u7531\u5B98\u65B9\u9009\u62E9\u5668\u7BA1\u7406\u3002")), /* @__PURE__ */ import_react5.default.createElement("div", { className: "mr-status" }, /* @__PURE__ */ import_react5.default.createElement("span", { className: `mr-status-dot ${catalogState.status === "loading" ? "loading" : catalogState.status === "error" ? "error" : ""}` }), catalogState.status === "ready" ? `${providerCount} \u4E2A\u4F9B\u5E94\u5546 \xB7 ${routes.length} \u6761\u8DEF\u7EBF` : catalogState.status === "loading" ? "\u6B63\u5728\u8BFB\u53D6\u6A21\u578B\u76EE\u5F55" : "\u6A21\u578B\u76EE\u5F55\u8BFB\u53D6\u5931\u8D25")), staleHostNotice({ hostVersion: toolProbes?.hostVersion, loaded: Boolean(toolProbes?.probes?.length) }) && /* @__PURE__ */ import_react5.default.createElement("div", { className: "mr-error", role: "alert" }, staleHostNotice({ hostVersion: toolProbes?.hostVersion })), (workbench.health.report?.notices ?? []).map((notice) => /* @__PURE__ */ import_react5.default.createElement("div", { key: `${notice.kind}-${notice.at}`, className: "mr-error", role: "alert" }, notice.message)), workbench.health.report && !workbench.health.report.onboarding?.completedAt && /* @__PURE__ */ import_react5.default.createElement(
12659
- OnboardingBanner,
12660
- {
12661
- health: workbench.health.report,
12662
- error: workbench.health.error,
12663
- refreshing: workbench.health.refreshing,
12664
- onRefresh: () => {
12665
- void workbench.refreshHealth(true);
12666
- },
12667
- onDone: () => {
12668
- void workbench.finishOnboarding();
12669
- }
12670
- }
12671
- ), /* @__PURE__ */ import_react5.default.createElement(
12672
- CostControlCard,
12673
- {
12674
- ledger: workbench.ledger.value,
12675
- error: workbench.ledger.error && !workbench.ledger.value ? workbench.ledger.error : "",
12676
- settingsScope,
12677
- onChanged: () => {
12678
- invalidatePlan();
12679
- void workbench.refreshLedger();
12680
- }
12681
- }
12682
- ), /* @__PURE__ */ import_react5.default.createElement("div", { className: "mr-grid" }, /* @__PURE__ */ import_react5.default.createElement("section", { className: "mr-card", "aria-label": "\u4EFB\u52A1\u89C4\u5212" }, /* @__PURE__ */ import_react5.default.createElement("div", { className: "mr-card-head" }, /* @__PURE__ */ import_react5.default.createElement("div", null, /* @__PURE__ */ import_react5.default.createElement("h2", { className: "mr-card-title" }, "\u4EFB\u52A1\u89C4\u5212"), /* @__PURE__ */ import_react5.default.createElement("p", { className: "mr-card-copy" }, "\u201C\u751F\u6210\u8DEF\u7531\u5EFA\u8BAE\u201D\u5728\u672C\u673A\u5B8C\u6210\uFF0C\u4E0D\u4F1A\u542F\u52A8\u6A21\u578B\uFF1B\u8981\u5B9E\u9645\u6267\u884C\uFF0C\u8BF7\u5728\u4E0B\u65B9\u201C\u5728\u5DE5\u4F5C\u53F0\u6267\u884C\u201D\u4E2D\u9884\u89C8\u5E76\u786E\u8BA4\u3002"))), /* @__PURE__ */ import_react5.default.createElement("div", { className: "mr-card-body" }, /* @__PURE__ */ import_react5.default.createElement("label", { className: "mr-label", htmlFor: "mr-task" }, "\u4EFB\u52A1\u63CF\u8FF0"), /* @__PURE__ */ import_react5.default.createElement("textarea", { className: "mr-textarea", id: "mr-task", value: task, onChange: (event) => {
13210
+ const summary = healthSummary(workbench.health.report?.tools);
13211
+ return /* @__PURE__ */ import_react5.default.createElement("main", { className: "mr-workspace" }, /* @__PURE__ */ import_react5.default.createElement("style", null, router_main_default), /* @__PURE__ */ import_react5.default.createElement("div", { className: "mr-shell" }, /* @__PURE__ */ import_react5.default.createElement("header", { className: "mr-header" }, /* @__PURE__ */ import_react5.default.createElement("div", null, /* @__PURE__ */ import_react5.default.createElement("p", { className: "mr-eyebrow" }, "Model Router \xB7 DeepSeek Harness"), /* @__PURE__ */ import_react5.default.createElement("h1", { className: "mr-title" }, "\u6A21\u578B\u8DEF\u7531\u5DE5\u4F5C\u53F0"), /* @__PURE__ */ import_react5.default.createElement("p", { className: "mr-subtitle" }, "\u628A\u4EFB\u52A1\u4EA4\u7ED9\u5408\u9002\u7684\u6A21\u578B\u3002\u4ECE\u672C\u5730\u89C4\u5212\uFF0C\u5230\u53EF\u786E\u8BA4\u7684\u6267\u884C\u3002")), /* @__PURE__ */ import_react5.default.createElement("div", { className: "mr-status" }, /* @__PURE__ */ import_react5.default.createElement("span", { className: `mr-status-dot ${catalogState.status === "loading" ? "loading" : catalogState.status === "error" ? "error" : ""}` }), catalogState.status === "ready" ? `${providerCount} \u4E2A\u4F9B\u5E94\u5546 \xB7 ${routes.length} \u6761\u8DEF\u7EBF` : catalogState.status === "loading" ? "\u6B63\u5728\u8BFB\u53D6\u6A21\u578B\u76EE\u5F55" : "\u6A21\u578B\u76EE\u5F55\u8BFB\u53D6\u5931\u8D25")), /* @__PURE__ */ import_react5.default.createElement("div", { className: "mr-overview", "aria-label": "\u5DE5\u4F5C\u53F0\u6982\u89C8" }, /* @__PURE__ */ import_react5.default.createElement("button", { type: "button", className: "mr-overview-item", onClick: () => selectView("models") }, /* @__PURE__ */ import_react5.default.createElement("span", { className: "mr-overview-label" }, "\u6A21\u578B\u8DEF\u7EBF"), /* @__PURE__ */ import_react5.default.createElement("strong", null, catalogState.status === "ready" ? routes.length : "\u2014"), /* @__PURE__ */ import_react5.default.createElement("span", { className: "mr-overview-detail" }, catalogState.status === "ready" ? `${providerCount} \u4E2A\u4F9B\u5E94\u5546 \xB7 \u914D\u7F6E\u4EF7\u683C\u4E0E\u80FD\u529B \u2192` : "\u7B49\u5F85\u76EE\u5F55\u52A0\u8F7D")), /* @__PURE__ */ import_react5.default.createElement("button", { type: "button", className: "mr-overview-item", onClick: () => selectView("tools") }, /* @__PURE__ */ import_react5.default.createElement("span", { className: "mr-overview-label" }, "\u5B98\u65B9\u5DE5\u5177"), /* @__PURE__ */ import_react5.default.createElement("strong", null, workbench.health.report ? summary.installed : "\u2014", /* @__PURE__ */ import_react5.default.createElement("small", null, " / ", OFFICIAL_TOOLS.length)), /* @__PURE__ */ import_react5.default.createElement("span", { className: "mr-overview-detail" }, workbench.health.report ? `${summary.ready} \u4E2A\u5DF2\u767B\u5F55 \xB7 \u67E5\u770B\u4F53\u68C0 \u2192` : "\u67E5\u770B\u5B89\u88C5\u4E0E\u767B\u5F55\u72B6\u6001 \u2192")), /* @__PURE__ */ import_react5.default.createElement("button", { type: "button", className: "mr-overview-item", onClick: () => selectView("controls") }, /* @__PURE__ */ import_react5.default.createElement("span", { className: "mr-overview-label" }, "\u4ECA\u65E5 API \u8D39\u7528"), /* @__PURE__ */ import_react5.default.createElement("strong", null, workbench.ledger.value ? money2(workbench.ledger.value.spent?.today ?? 0) : "\u2014"), /* @__PURE__ */ import_react5.default.createElement("span", { className: "mr-overview-detail" }, "\u672C\u673A\u8BB0\u5F55\u4F30\u7B97 \xB7 \u67E5\u770B\u9884\u7B97 \u2192"))), /* @__PURE__ */ import_react5.default.createElement("div", { className: "mr-workspace-tabs", role: "tablist", "aria-label": "\u5DE5\u4F5C\u53F0\u529F\u80FD" }, WORKSPACE_VIEWS.map((item, index) => /* @__PURE__ */ import_react5.default.createElement("button", { key: item.id, ref: (element) => {
13212
+ tabRefs.current[item.id] = element;
13213
+ }, type: "button", role: "tab", id: `mr-tab-${item.id}`, "aria-selected": view === item.id, "aria-controls": `mr-panel-${item.id}`, tabIndex: view === item.id ? 0 : -1, onKeyDown: (event) => navigateTabs(event, index), onClick: () => setView(item.id) }, /* @__PURE__ */ import_react5.default.createElement("span", { className: "mr-tab-number", "aria-hidden": "true" }, item.number), item.label))), staleHostNotice({ hostVersion: toolProbes?.hostVersion, loaded: Boolean(toolProbes?.probes?.length) }) && /* @__PURE__ */ import_react5.default.createElement("div", { className: "mr-error", role: "alert" }, staleHostNotice({ hostVersion: toolProbes?.hostVersion })), (workbench.health.report?.notices ?? []).map((notice) => /* @__PURE__ */ import_react5.default.createElement("div", { key: `${notice.kind}-${notice.at}`, className: "mr-error", role: "alert" }, notice.message)), /* @__PURE__ */ import_react5.default.createElement("div", { className: "mr-view mr-stack", role: "tabpanel", id: "mr-panel-plan", "aria-labelledby": "mr-tab-plan", hidden: view !== "plan" }, /* @__PURE__ */ import_react5.default.createElement("div", { className: "mr-grid mr-planning-grid" }, /* @__PURE__ */ import_react5.default.createElement("section", { className: "mr-card", "aria-label": "\u4EFB\u52A1\u89C4\u5212" }, /* @__PURE__ */ import_react5.default.createElement("div", { className: "mr-card-head" }, /* @__PURE__ */ import_react5.default.createElement("div", null, /* @__PURE__ */ import_react5.default.createElement("h2", { className: "mr-card-title" }, "\u4EFB\u52A1\u89C4\u5212"), /* @__PURE__ */ import_react5.default.createElement("p", { className: "mr-card-copy" }, "\u5199\u6E05\u76EE\u6807\u4E0E\u9A8C\u6536\u6807\u51C6\uFF0C\u5148\u751F\u6210\u672C\u5730\u5EFA\u8BAE\uFF0C\u518D\u9884\u89C8\u6267\u884C\u3002")), /* @__PURE__ */ import_react5.default.createElement("span", { className: "mr-pill" }, "\u672C\u5730\u89C4\u5212 \xB7 \u4E0D\u6D88\u8017 token")), /* @__PURE__ */ import_react5.default.createElement("div", { className: "mr-card-body" }, /* @__PURE__ */ import_react5.default.createElement("label", { className: "mr-label", htmlFor: "mr-task" }, "\u4EFB\u52A1\u63CF\u8FF0"), /* @__PURE__ */ import_react5.default.createElement("textarea", { className: "mr-textarea", id: "mr-task", value: task, onChange: (event) => {
12683
13214
  setTask(event.target.value);
12684
13215
  invalidatePlan();
12685
- }, placeholder: "\u4F8B\u5982\uFF1A\u5206\u6790\u9879\u76EE\u67B6\u6784\uFF0C\u5206\u5DE5\u4FEE\u590D\u5173\u952E\u95EE\u9898\uFF0C\u5E76\u7ED9\u51FA\u9A8C\u6536\u6E05\u5355" }), /* @__PURE__ */ import_react5.default.createElement("div", { className: "mr-controls" }, /* @__PURE__ */ import_react5.default.createElement("div", { className: "mr-control-group" }, /* @__PURE__ */ import_react5.default.createElement("span", { className: "mr-control-label" }, "\u89C4\u5212\u6A21\u5F0F"), /* @__PURE__ */ import_react5.default.createElement("div", { className: "mr-segment", role: "group", "aria-label": "\u89C4\u5212\u6A21\u5F0F" }, /* @__PURE__ */ import_react5.default.createElement("button", { type: "button", "aria-pressed": mode === "single", onClick: () => {
13216
+ }, placeholder: "\u4F8B\u5982\uFF1A\u5206\u6790\u9879\u76EE\u67B6\u6784\uFF0C\u5206\u5DE5\u4FEE\u590D\u5173\u952E\u95EE\u9898\uFF0C\u5E76\u7ED9\u51FA\u9A8C\u6536\u6E05\u5355", "aria-describedby": "mr-task-hint" }), /* @__PURE__ */ import_react5.default.createElement("p", { className: "mr-caption mr-task-hint", id: "mr-task-hint" }, "\u56E2\u961F\u4EFB\u52A1\u53EF\u6309\u7F16\u53F7\u5199\u51FA\u6B65\u9AA4\u3001\u4EA4\u4ED8\u7269\u548C\u4F9D\u8D56\uFF1B\u89C4\u5212\u4E0D\u4F1A\u66F4\u6539\u4E3B\u4F1A\u8BDD\u6A21\u578B\u3002"), /* @__PURE__ */ import_react5.default.createElement("div", { className: "mr-controls" }, /* @__PURE__ */ import_react5.default.createElement("div", { className: "mr-control-group" }, /* @__PURE__ */ import_react5.default.createElement("span", { className: "mr-control-label" }, "\u89C4\u5212\u6A21\u5F0F"), /* @__PURE__ */ import_react5.default.createElement("div", { className: "mr-segment", role: "group", "aria-label": "\u89C4\u5212\u6A21\u5F0F" }, /* @__PURE__ */ import_react5.default.createElement("button", { type: "button", "aria-pressed": mode === "single", onClick: () => {
12686
13217
  setMode("single");
12687
13218
  invalidatePlan();
12688
13219
  } }, "\u5355\u4EFB\u52A1"), /* @__PURE__ */ import_react5.default.createElement("button", { type: "button", "aria-pressed": mode === "team", onClick: () => {
@@ -12699,7 +13230,7 @@ function RouterMainPage({ loadCatalog, settingsScope, listOfficialTools, install
12699
13230
  budgetValue.current = event.target.value;
12700
13231
  setBudget(event.target.value);
12701
13232
  invalidatePlan();
12702
- } }))), /* @__PURE__ */ import_react5.default.createElement("div", { className: "mr-actions" }, /* @__PURE__ */ import_react5.default.createElement("button", { className: "mr-button", type: "button", disabled: catalogState.status !== "ready" || routes.length === 0 || toolProbes === null, onClick: generate }, "\u751F\u6210\u8DEF\u7531\u5EFA\u8BAE"), /* @__PURE__ */ import_react5.default.createElement("span", { className: "mr-caption" }, toolProbes === null ? "\u6B63\u5728\u68C0\u6D4B\u5B98\u65B9\u5DE5\u5177\u2026" : "0 \u8868\u793A\u4E0D\u9650\u5236\u672C\u6B21\u5EFA\u8BAE\uFF1B\u4E0D\u4F1A\u8BBE\u7F6E\u771F\u5B9E\u652F\u51FA\u4E0A\u9650\u3002")), planError && /* @__PURE__ */ import_react5.default.createElement("p", { className: "mr-error", role: "alert" }, planError))), /* @__PURE__ */ import_react5.default.createElement("section", { className: "mr-card", "aria-label": "\u6A21\u578B\u76EE\u5F55" }, /* @__PURE__ */ import_react5.default.createElement("div", { className: "mr-card-head" }, /* @__PURE__ */ import_react5.default.createElement("div", null, /* @__PURE__ */ import_react5.default.createElement("h2", { className: "mr-card-title" }, "\u6A21\u578B\u76EE\u5F55"), /* @__PURE__ */ import_react5.default.createElement("p", { className: "mr-card-copy" }, "\u53EA\u663E\u793A\u5B98\u65B9\u5DF2\u767B\u8BB0\u7684 provider/model\uFF0C\u4E0D\u8BFB\u53D6 API Key\u3002")), /* @__PURE__ */ import_react5.default.createElement("button", { className: "mr-button mr-button-secondary", type: "button", onClick: refresh }, "\u5237\u65B0")), /* @__PURE__ */ import_react5.default.createElement("div", { className: "mr-card-body" }, catalogState.status === "error" && /* @__PURE__ */ import_react5.default.createElement("div", { className: "mr-error", role: "alert" }, catalogState.error), catalogState.status === "loading" && /* @__PURE__ */ import_react5.default.createElement("div", { className: "mr-empty" }, "\u6B63\u5728\u52A0\u8F7D\u5B98\u65B9\u6A21\u578B\u76EE\u5F55\u2026"), catalogState.status === "ready" && /* @__PURE__ */ import_react5.default.createElement(import_react5.default.Fragment, null, /* @__PURE__ */ import_react5.default.createElement("label", { className: "mr-label", htmlFor: "mr-model-search" }, "\u641C\u7D22\u8DEF\u7EBF"), /* @__PURE__ */ import_react5.default.createElement("input", { className: "mr-input mr-search", id: "mr-model-search", value: query, onChange: (event) => setQuery(event.target.value), placeholder: "\u6A21\u578B\u6216\u4F9B\u5E94\u5546" }), /* @__PURE__ */ import_react5.default.createElement(RouteList, { routes, query }), catalogState.catalog?.failures?.length > 0 && /* @__PURE__ */ import_react5.default.createElement("p", { className: "mr-caption" }, catalogState.catalog.failures.length, " \u4E2A\u4F9B\u5E94\u5546\u7684\u76EE\u5F55\u8BFB\u53D6\u5931\u8D25\uFF0C\u8BF7\u5728\u5B98\u65B9\u6A21\u578B\u9875\u68C0\u67E5\u914D\u7F6E\u3002")), /* @__PURE__ */ import_react5.default.createElement("p", { className: "mr-caption", style: { marginTop: 13 } }, "\u76EE\u5F55\u767B\u8BB0\u4E0D\u4EE3\u8868\u51ED\u636E\u6216\u7F51\u7EDC\u5F53\u524D\u53EF\u7528\uFF1B\u56FE\u50CF\u80FD\u529B\u9700\u8981\u5728\u5B9E\u9645\u4F7F\u7528\u524D\u6838\u5BF9\u3002")))), /* @__PURE__ */ import_react5.default.createElement(ModelProfileEditor, { routes, settingsScope, onSaved: invalidatePlan }), plan && /* @__PURE__ */ import_react5.default.createElement(PlanResults, { plan, ledger: workbench.ledger.value }), /* @__PURE__ */ import_react5.default.createElement(
13233
+ } }))), /* @__PURE__ */ import_react5.default.createElement("div", { className: "mr-actions" }, /* @__PURE__ */ import_react5.default.createElement("button", { className: "mr-button", type: "button", disabled: catalogState.status !== "ready" || routes.length === 0 || toolProbes === null, onClick: generate }, "\u751F\u6210\u8DEF\u7531\u5EFA\u8BAE"), /* @__PURE__ */ import_react5.default.createElement("span", { className: "mr-caption" }, catalogState.status === "loading" ? "\u6B63\u5728\u8BFB\u53D6\u6A21\u578B\u76EE\u5F55\u2026" : catalogState.status === "error" ? "\u76EE\u5F55\u8BFB\u53D6\u5931\u8D25\uFF0C\u8BF7\u5728\u201C\u6A21\u578B\u914D\u7F6E\u201D\u4E2D\u5237\u65B0\u3002" : routes.length === 0 ? "\u8BF7\u5148\u5728 Harness \u7684\u201C\u6A21\u578B\u201D\u9875\u6DFB\u52A0\u6A21\u578B\u3002" : toolProbes === null ? "\u6B63\u5728\u68C0\u6D4B\u5B98\u65B9\u5DE5\u5177\u2026" : "\u9884\u7B97 0 \u4E3A\u4E0D\u9650\uFF1B\u8D39\u7528\u4E3A\u4F30\u7B97\u3002")), planError && /* @__PURE__ */ import_react5.default.createElement("p", { className: "mr-error", role: "alert" }, planError))), /* @__PURE__ */ import_react5.default.createElement("aside", { className: "mr-planning-guide", "aria-label": "\u89C4\u5212\u4F7F\u7528\u63D0\u793A" }, /* @__PURE__ */ import_react5.default.createElement("p", { className: "mr-eyebrow" }, "\u5DE5\u4F5C\u6D41\u7A0B"), /* @__PURE__ */ import_react5.default.createElement("ol", { className: "mr-workflow" }, /* @__PURE__ */ import_react5.default.createElement("li", null, /* @__PURE__ */ import_react5.default.createElement("span", null, "01"), /* @__PURE__ */ import_react5.default.createElement("div", null, /* @__PURE__ */ import_react5.default.createElement("strong", null, "\u63CF\u8FF0\u4EFB\u52A1"), /* @__PURE__ */ import_react5.default.createElement("p", null, "\u9009\u62E9\u5355\u4EFB\u52A1\u3001\u56E2\u961F\u5206\u5DE5\u6216\u6307\u5B9A\u6A21\u578B\u3002"))), /* @__PURE__ */ import_react5.default.createElement("li", null, /* @__PURE__ */ import_react5.default.createElement("span", null, "02"), /* @__PURE__ */ import_react5.default.createElement("div", null, /* @__PURE__ */ import_react5.default.createElement("strong", null, "\u6838\u5BF9\u8DEF\u7531\u5EFA\u8BAE"), /* @__PURE__ */ import_react5.default.createElement("p", null, "\u68C0\u67E5\u6A21\u578B\u3001\u5DE5\u4F5C\u5305\u4F9D\u8D56\u548C\u4F30\u7B97\u8D39\u7528\u3002"))), /* @__PURE__ */ import_react5.default.createElement("li", null, /* @__PURE__ */ import_react5.default.createElement("span", null, "03"), /* @__PURE__ */ import_react5.default.createElement("div", null, /* @__PURE__ */ import_react5.default.createElement("strong", null, "\u9884\u89C8\u5E76\u786E\u8BA4\u6267\u884C"), /* @__PURE__ */ import_react5.default.createElement("p", null, "\u786E\u8BA4\u540E\u8C03\u7528\u6A21\u578B\uFF0C\u7ED3\u679C\u5199\u5165\u6267\u884C\u8BB0\u5F55\u3002")))), /* @__PURE__ */ import_react5.default.createElement("div", { className: "mr-guide-links" }, /* @__PURE__ */ import_react5.default.createElement("button", { className: "mr-button mr-button-secondary", type: "button", onClick: () => selectView("models") }, "\u914D\u7F6E\u6A21\u578B\u4EF7\u683C\u4E0E\u80FD\u529B \u2192"), /* @__PURE__ */ import_react5.default.createElement("button", { className: "mr-button mr-button-secondary", type: "button", onClick: () => selectView("tools") }, "\u68C0\u67E5\u5B98\u65B9\u5DE5\u5177\u4E0E\u767B\u5F55 \u2192")), /* @__PURE__ */ import_react5.default.createElement("p", { className: "mr-caption" }, "\u7F3A\u5C11\u4EF7\u683C\u65F6\u4F1A\u63D0\u793A\u201C\u4EF7\u683C\u5F85\u914D\u7F6E\u201D\u3002\u53EA\u8BFB\u6267\u884C\u53EF\u5728\u6B64\u5B8C\u6210\uFF1B\u4FEE\u6539\u6587\u4EF6\u7684\u4EFB\u52A1\u9700\u5728\u5B98\u65B9\u4F1A\u8BDD\u4E2D\u5BA1\u6279\u3002"))), plan && /* @__PURE__ */ import_react5.default.createElement(PlanResults, { plan, ledger: workbench.ledger.value, headingRef: resultHeading }), /* @__PURE__ */ import_react5.default.createElement(
12703
13234
  RunLauncher,
12704
13235
  {
12705
13236
  task,
@@ -12708,9 +13239,10 @@ function RouterMainPage({ loadCatalog, settingsScope, listOfficialTools, install
12708
13239
  ledger: workbench.ledger.value,
12709
13240
  previewRun,
12710
13241
  startRun,
13242
+ planningRevision: `${routingSettings}/${dataRevision}/${feedbackRevision}`,
12711
13243
  directRoute: mode === "direct" ? routes.find((route) => `${route.provider}/${route.model}` === directKey) ?? routes[0] ?? null : null,
12712
13244
  defaultPreset: settingsScope.getSnapshot().value?.routingPreset ?? "balanced",
12713
- disabledReason: catalogState.status === "loading" ? "\u6B63\u5728\u8BFB\u53D6\u6A21\u578B\u76EE\u5F55\u2026" : catalogState.status === "error" ? "\u6A21\u578B\u76EE\u5F55\u8BFB\u53D6\u5931\u8D25\uFF0C\u8BF7\u5728\u201C\u6A21\u578B\u76EE\u5F55\u201D\u5361\u7247\u70B9\u201C\u5237\u65B0\u201D\u3002" : routes.length === 0 ? "\u8BF7\u5148\u5728\u5B98\u65B9\u201C\u6A21\u578B\u201D\u9875\u914D\u7F6E\u81F3\u5C11\u4E00\u6761\u6A21\u578B\u8DEF\u7EBF\u3002" : "",
13245
+ disabledReason: catalogState.status === "loading" ? "\u6B63\u5728\u8BFB\u53D6\u6A21\u578B\u76EE\u5F55\u2026" : catalogState.status === "error" ? "\u6A21\u578B\u76EE\u5F55\u8BFB\u53D6\u5931\u8D25\uFF0C\u8BF7\u5728\u201C\u6A21\u578B\u914D\u7F6E\u201D\u4E2D\u5237\u65B0\u3002" : routes.length === 0 ? "\u8BF7\u5148\u5728\u5B98\u65B9\u201C\u6A21\u578B\u201D\u9875\u914D\u7F6E\u81F3\u5C11\u4E00\u6761\u6A21\u578B\u8DEF\u7EBF\u3002" : "",
12714
13246
  onStarted: () => {
12715
13247
  void workbench.refreshLedger();
12716
13248
  }
@@ -12725,13 +13257,26 @@ function RouterMainPage({ loadCatalog, settingsScope, listOfficialTools, install
12725
13257
  onRefresh: () => {
12726
13258
  void workbench.refreshLedger();
12727
13259
  },
12728
- onRate: (runId, packageId, rating) => {
12729
- void workbench.rate(runId, packageId, rating);
13260
+ onRate: (runId, packageId, rating, expectedFinishedAt) => {
13261
+ void workbench.rate(runId, packageId, rating, expectedFinishedAt);
12730
13262
  },
12731
13263
  onRerun: (runId, packageId, override, choice) => {
12732
13264
  void workbench.rerun(runId, packageId, override, choice);
12733
13265
  }
12734
13266
  }
13267
+ )), /* @__PURE__ */ import_react5.default.createElement("div", { className: "mr-view", role: "tabpanel", id: "mr-panel-models", "aria-labelledby": "mr-tab-models", hidden: view !== "models" }, /* @__PURE__ */ import_react5.default.createElement("div", { className: "mr-view-heading" }, /* @__PURE__ */ import_react5.default.createElement("h2", null, "\u6A21\u578B\u914D\u7F6E"), /* @__PURE__ */ import_react5.default.createElement("p", null, "\u4ECE\u5B98\u65B9\u76EE\u5F55\u9009\u62E9\u8DEF\u7EBF\uFF0C\u8865\u9F50\u6BD4\u8F83\u6240\u9700\u7684\u4EF7\u683C\u3001\u80FD\u529B\u4E0E\u6267\u884C\u65B9\u5F0F\u3002")), /* @__PURE__ */ import_react5.default.createElement("div", { className: "mr-grid mr-model-grid" }, /* @__PURE__ */ import_react5.default.createElement(ModelProfileEditor, { routes, settingsScope, onSaved: invalidatePlan }), /* @__PURE__ */ import_react5.default.createElement("section", { className: "mr-card", "aria-label": "\u6A21\u578B\u76EE\u5F55" }, /* @__PURE__ */ import_react5.default.createElement("div", { className: "mr-card-head" }, /* @__PURE__ */ import_react5.default.createElement("div", null, /* @__PURE__ */ import_react5.default.createElement("h2", { className: "mr-card-title" }, "\u6A21\u578B\u76EE\u5F55"), /* @__PURE__ */ import_react5.default.createElement("p", { className: "mr-card-copy" }, routes.length, " \u6761\u8DEF\u7EBF \xB7 \u53EA\u8BFB\u53D6\u5B98\u65B9\u76EE\u5F55\uFF0C\u4E0D\u8BFB\u53D6 API Key\u3002")), /* @__PURE__ */ import_react5.default.createElement("button", { className: "mr-button mr-button-secondary", type: "button", disabled: catalogState.status === "loading", onClick: refresh }, "\u5237\u65B0")), /* @__PURE__ */ import_react5.default.createElement("div", { className: "mr-card-body" }, catalogState.status === "error" && /* @__PURE__ */ import_react5.default.createElement("div", { className: "mr-error", role: "alert" }, catalogState.error), catalogState.status === "loading" && /* @__PURE__ */ import_react5.default.createElement("div", { className: "mr-empty" }, "\u6B63\u5728\u52A0\u8F7D\u5B98\u65B9\u6A21\u578B\u76EE\u5F55\u2026"), catalogState.status === "ready" && /* @__PURE__ */ import_react5.default.createElement(import_react5.default.Fragment, null, /* @__PURE__ */ import_react5.default.createElement("label", { className: "mr-label", htmlFor: "mr-model-search" }, "\u641C\u7D22\u8DEF\u7EBF"), /* @__PURE__ */ import_react5.default.createElement("input", { className: "mr-input mr-search", id: "mr-model-search", value: query, onChange: (event) => setQuery(event.target.value), placeholder: "\u6A21\u578B\u6216\u4F9B\u5E94\u5546" }), /* @__PURE__ */ import_react5.default.createElement(RouteList, { routes, query }), catalogState.catalog?.failures?.length > 0 && /* @__PURE__ */ import_react5.default.createElement("p", { className: "mr-caption" }, catalogState.catalog.failures.length, " \u4E2A\u4F9B\u5E94\u5546\u7684\u76EE\u5F55\u8BFB\u53D6\u5931\u8D25\uFF0C\u8BF7\u5728\u5B98\u65B9\u6A21\u578B\u9875\u68C0\u67E5\u914D\u7F6E\u3002")), /* @__PURE__ */ import_react5.default.createElement("p", { className: "mr-caption", style: { marginTop: 13 } }, "\u76EE\u5F55\u767B\u8BB0\u4E0D\u4EE3\u8868\u51ED\u636E\u6216\u7F51\u7EDC\u5F53\u524D\u53EF\u7528\uFF1B\u56FE\u50CF\u80FD\u529B\u9700\u8981\u5728\u5B9E\u9645\u4F7F\u7528\u524D\u6838\u5BF9\u3002"))))), /* @__PURE__ */ import_react5.default.createElement("div", { className: "mr-view mr-stack", role: "tabpanel", id: "mr-panel-tools", "aria-labelledby": "mr-tab-tools", hidden: view !== "tools" }, /* @__PURE__ */ import_react5.default.createElement("div", { className: "mr-view-heading" }, /* @__PURE__ */ import_react5.default.createElement("h2", null, "\u5B98\u65B9\u5DE5\u5177"), /* @__PURE__ */ import_react5.default.createElement("p", null, "\u7BA1\u7406\u672C\u673A CLI\u3001\u68C0\u67E5\u767B\u5F55\u72B6\u6001\uFF0C\u6216\u6253\u5F00\u4EA4\u4E92\u5F0F\u7EC8\u7AEF\u3002")), workbench.health.report && !workbench.health.report.onboarding?.completedAt && /* @__PURE__ */ import_react5.default.createElement(
13268
+ OnboardingBanner,
13269
+ {
13270
+ health: workbench.health.report,
13271
+ error: workbench.health.error,
13272
+ refreshing: workbench.health.refreshing,
13273
+ onRefresh: () => {
13274
+ void workbench.refreshHealth(true);
13275
+ },
13276
+ onDone: () => {
13277
+ void workbench.finishOnboarding();
13278
+ }
13279
+ }
12735
13280
  ), /* @__PURE__ */ import_react5.default.createElement(
12736
13281
  OfficialToolsCard,
12737
13282
  {
@@ -12745,7 +13290,18 @@ function RouterMainPage({ loadCatalog, settingsScope, listOfficialTools, install
12745
13290
  void workbench.refreshHealth(true);
12746
13291
  }
12747
13292
  }
12748
- ), terminalApi && /* @__PURE__ */ import_react5.default.createElement(CliTerminalCard, { api: terminalApi, health: workbench.health.report }), /* @__PURE__ */ import_react5.default.createElement(
13293
+ ), terminalApi && /* @__PURE__ */ import_react5.default.createElement(CliTerminalCard, { api: terminalApi, health: workbench.health.report })), /* @__PURE__ */ import_react5.default.createElement("div", { className: "mr-view mr-stack", role: "tabpanel", id: "mr-panel-controls", "aria-labelledby": "mr-tab-controls", hidden: view !== "controls" }, /* @__PURE__ */ import_react5.default.createElement("div", { className: "mr-view-heading" }, /* @__PURE__ */ import_react5.default.createElement("h2", null, "\u9884\u7B97\u4E0E\u5B89\u5168"), /* @__PURE__ */ import_react5.default.createElement("p", null, "\u8BBE\u7F6E\u6210\u672C\u4E0E\u8D28\u91CF\u7B56\u7565\uFF0C\u6838\u5BF9\u8BA2\u9605\u8BA1\u8D39\u548C\u6267\u884C\u8FB9\u754C\u3002")), /* @__PURE__ */ import_react5.default.createElement(
13294
+ CostControlCard,
13295
+ {
13296
+ ledger: workbench.ledger.value,
13297
+ error: workbench.ledger.error && !workbench.ledger.value ? workbench.ledger.error : "",
13298
+ settingsScope,
13299
+ onChanged: () => {
13300
+ invalidatePlan();
13301
+ void workbench.refreshLedger();
13302
+ }
13303
+ }
13304
+ ), /* @__PURE__ */ import_react5.default.createElement(
12749
13305
  BillingCard,
12750
13306
  {
12751
13307
  billing: workbench.health.report?.billing ?? null,
@@ -12757,7 +13313,7 @@ function RouterMainPage({ loadCatalog, settingsScope, listOfficialTools, install
12757
13313
  }
12758
13314
  ), /* @__PURE__ */ import_react5.default.createElement(SecurityCard, { data: workbench.boundaries.value, error: workbench.boundaries.error, onRefresh: () => {
12759
13315
  void workbench.refreshBoundaries();
12760
- } }), /* @__PURE__ */ import_react5.default.createElement("div", { className: "mr-notice" }, "\u53EA\u8BFB\u4EFB\u52A1\u53EF\u5728\u4E0A\u65B9\u201C\u5728\u5DE5\u4F5C\u53F0\u6267\u884C\u201D\u4E2D\u76F4\u63A5\u9884\u89C8\u5E76\u6267\u884C\uFF1B\u5728\u5B98\u65B9\u4F1A\u8BDD\u4E2D\u53EF\u4F7F\u7528 ", /* @__PURE__ */ import_react5.default.createElement("code", null, "model_router_execute"), "\uFF08\u6309\u8DEF\u7531\u6216\u6307\u5B9A\u6A21\u578B\u6267\u884C\uFF0C\u5B98\u65B9 CLI \u5931\u8D25\u5219\u56DE\u9000 API\uFF09\u3001", /* @__PURE__ */ import_react5.default.createElement("code", null, "model_router_consult"), "\u3001", /* @__PURE__ */ import_react5.default.createElement("code", null, "model_router_tool_run"), " \u6216 ", /* @__PURE__ */ import_react5.default.createElement("code", null, "model_router_team_execute"), "\u3002\u6307\u5B9A\u6A21\u578B\u4F1A\u8DF3\u8FC7\u8DEF\u7EBF\u6BD4\u8F83\u3002\u6258\u7BA1\u6267\u884C\u80FD\u529B\u548C\u5C31\u7EEA\u72B6\u6001\u89C1\u4E0A\u65B9\u5404\u5DE5\u5177\u5361\u7247\uFF1B\u5B9E\u9645\u4F7F\u7528\u7684\u6A21\u578B\u4EE5\u5382\u5546\u8BB0\u5F55\u4E3A\u51C6\u3002ZCode \u4F7F\u7528\u5176\u81EA\u8EAB\u914D\u7F6E\u7684\u9ED8\u8BA4\u6A21\u578B\u3002\u53EF\u7F16\u8F91\u56E2\u961F\u4EFB\u52A1\u8981\u6C42\u5E72\u51C0\u7684 Git \u4ED3\u5E93\uFF0C\u5E76\u7ECF\u5B98\u65B9\u5DE5\u5177\u5BA1\u6279\u3002\u8BBE\u7F6E\u4F4D\u4E8E\u201C\u63D2\u4EF6 \u2192 \u5DF2\u5B89\u88C5 \u2192 @ljwei-stak/model-router-galgame\u201D\u3002")));
13316
+ } })), /* @__PURE__ */ import_react5.default.createElement("footer", { className: "mr-footer" }, "\u4E3B\u4F1A\u8BDD\u6A21\u578B\u7531 Harness \u7BA1\u7406\u3002\u66F4\u591A\u8BBE\u7F6E\uFF1A\u63D2\u4EF6 \u2192 \u5DF2\u5B89\u88C5 \u2192 ", /* @__PURE__ */ import_react5.default.createElement("code", null, "@ljwei-stak/dsh-model-router"), "\u3002")));
12761
13317
  }
12762
13318
 
12763
13319
  // .dsh-plugin/shared/official-tools-remote.mjs
@@ -12814,7 +13370,13 @@ var optionalRouteText = (value, subject) => {
12814
13370
  var rateRequestCodec = strictCodec(`${OFFICIAL_TOOLS_REMOTE_PACKAGE}#RateRequest`, (value) => {
12815
13371
  const request = plainObject2(value, "rate request");
12816
13372
  if (!["up", "down", "clear"].includes(request.rating)) throw new TypeError("rating must be up, down or clear");
12817
- return { runId: idText(request.runId, "runId"), packageId: idText(request.packageId, "packageId"), rating: request.rating };
13373
+ if (request.expectedFinishedAt !== void 0 && (!Number.isFinite(request.expectedFinishedAt) || request.expectedFinishedAt < 0)) throw new TypeError("expectedFinishedAt must be a non-negative timestamp");
13374
+ return {
13375
+ runId: idText(request.runId, "runId"),
13376
+ packageId: idText(request.packageId, "packageId"),
13377
+ rating: request.rating,
13378
+ ...request.expectedFinishedAt === void 0 ? {} : { expectedFinishedAt: request.expectedFinishedAt }
13379
+ };
12818
13380
  });
12819
13381
  var rerunRequestCodec = strictCodec(`${OFFICIAL_TOOLS_REMOTE_PACKAGE}#RerunRequest`, (value) => {
12820
13382
  const request = plainObject2(value, "rerun request");