@molecule/app-ide-react 1.1.1 → 1.2.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.
- package/dist/components/ChatPanel.d.ts.map +1 -1
- package/dist/components/ChatPanel.js +89 -53
- package/dist/components/ChatPanel.js.map +1 -1
- package/dist/components/chat-model-mode-utilities.d.ts +29 -0
- package/dist/components/chat-model-mode-utilities.d.ts.map +1 -1
- package/dist/components/chat-model-mode-utilities.js +40 -0
- package/dist/components/chat-model-mode-utilities.js.map +1 -1
- package/dist/components/chat-models-utilities.d.ts +68 -8
- package/dist/components/chat-models-utilities.d.ts.map +1 -1
- package/dist/components/chat-models-utilities.js +116 -12
- package/dist/components/chat-models-utilities.js.map +1 -1
- package/package.json +3 -3
|
@@ -85,6 +85,35 @@ export declare function resolveModeModel(settings: PerModeModelSettings, mode: M
|
|
|
85
85
|
* @returns The clamped model id for the mode.
|
|
86
86
|
*/
|
|
87
87
|
export declare function freeTierModeModelId(models: readonly AppModelDefinition[], mode: ModelMode, fallback: string): string;
|
|
88
|
+
/**
|
|
89
|
+
* The model id that will ACTUALLY serve a conversation mode, for display.
|
|
90
|
+
*
|
|
91
|
+
* Mirrors the server's `selectModelForMode` candidate chain (minus the
|
|
92
|
+
* per-request override, which the UI never has): the project's per-mode model,
|
|
93
|
+
* then the project's SAVED legacy `chatModel`, each skipped when the free-tier
|
|
94
|
+
* clamp would reject it — then the server-sent per-mode default (which already
|
|
95
|
+
* folds in the owner's account-level settings and tier), then the catalog
|
|
96
|
+
* clamp as the last resort.
|
|
97
|
+
*
|
|
98
|
+
* `settings.chatModel` must be the PERSISTED value only — never a UI-seeded
|
|
99
|
+
* default. Seeding the catalog's single free-tier model (the executor) as
|
|
100
|
+
* "current" is exactly the bug this exists to fix: every plan-mode surface
|
|
101
|
+
* then labeled the planner as the executor model while the server planned
|
|
102
|
+
* with its own plan default (observed on prod 2026-08-13 — the UI said
|
|
103
|
+
* "DeepSeek V4 Flash" for a plan turn that DeepSeek V4 Pro served).
|
|
104
|
+
*
|
|
105
|
+
* @param mode - The conversation mode to resolve.
|
|
106
|
+
* @param settings - Persisted per-mode + legacy model settings (saved only).
|
|
107
|
+
* @param serverDefaults - Server-sent per-mode defaults (`GET /ai/models`).
|
|
108
|
+
* @param isFreeTier - Whether the current user is on the free/anon tier.
|
|
109
|
+
* @param models - The available models from the catalog.
|
|
110
|
+
* @param fallback - The free-tier model id to use when no clamp match exists.
|
|
111
|
+
* @returns The model id the mode resolves to.
|
|
112
|
+
*/
|
|
113
|
+
export declare function effectiveModeModelId(mode: 'plan' | 'execute', settings: PerModeModelSettings, serverDefaults: {
|
|
114
|
+
plan?: string;
|
|
115
|
+
execute?: string;
|
|
116
|
+
} | undefined, isFreeTier: boolean, models: readonly AppModelDefinition[], fallback: string): string;
|
|
88
117
|
/**
|
|
89
118
|
* Why a model is locked for a free-tier user in a given mode — `'paid'` for a
|
|
90
119
|
* genuinely paid model, `'mode'` for a model the free tier CAN use, just in a
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"chat-model-mode-utilities.d.ts","sourceRoot":"","sources":["../../src/components/chat-model-mode-utilities.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAEH,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAA;AAEjE,wEAAwE;AACxE,MAAM,MAAM,SAAS,GAAG,MAAM,GAAG,SAAS,GAAG,QAAQ,GAAG,SAAS,CAAA;AAEjE,6EAA6E;AAC7E,MAAM,WAAW,oBAAoB;IACnC,yFAAyF;IACzF,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,4FAA4F;IAC5F,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,iFAAiF;IACjF,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,+EAA+E;IAC/E,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,yEAAyE;IACzE,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB;AAED;;;;;;;;;GASG;AACH,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,MAAM,GAAG;IAAE,IAAI,EAAE,SAAS,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAI9F;AAED;;;;;GAKG;AACH,wBAAgB,cAAc,CAC5B,IAAI,EAAE,SAAS,GACd,WAAW,GAAG,cAAc,GAAG,aAAa,GAAG,cAAc,CAW/D;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,gBAAgB,CAC9B,QAAQ,EAAE,oBAAoB,EAC9B,IAAI,EAAE,SAAS,GACd,MAAM,GAAG,SAAS,CAWpB;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,mBAAmB,CACjC,MAAM,EAAE,SAAS,kBAAkB,EAAE,EACrC,IAAI,EAAE,SAAS,EACf,QAAQ,EAAE,MAAM,GACf,MAAM,CAgBR;AAED;;;;GAIG;AACH,MAAM,MAAM,kBAAkB,GAAG,MAAM,GAAG,MAAM,CAAA;AAKhD;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,kBAAkB,CAChC,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,SAAS,EACf,UAAU,EAAE,OAAO,EACnB,MAAM,EAAE,SAAS,kBAAkB,EAAE,EACrC,QAAQ,EAAE,MAAM,GACf,kBAAkB,GAAG,IAAI,CAe3B;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,kBAAkB,CAChC,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,SAAS,kBAAkB,EAAE,EACrC,QAAQ,EAAE,MAAM,GACf,SAAS,GAAG,IAAI,CAKlB;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,iBAAiB,CAC/B,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,SAAS,EACf,UAAU,EAAE,OAAO,EACnB,MAAM,EAAE,SAAS,kBAAkB,EAAE,EACrC,QAAQ,EAAE,MAAM,GACf,OAAO,CAET"}
|
|
1
|
+
{"version":3,"file":"chat-model-mode-utilities.d.ts","sourceRoot":"","sources":["../../src/components/chat-model-mode-utilities.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAEH,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAA;AAEjE,wEAAwE;AACxE,MAAM,MAAM,SAAS,GAAG,MAAM,GAAG,SAAS,GAAG,QAAQ,GAAG,SAAS,CAAA;AAEjE,6EAA6E;AAC7E,MAAM,WAAW,oBAAoB;IACnC,yFAAyF;IACzF,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,4FAA4F;IAC5F,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,iFAAiF;IACjF,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,+EAA+E;IAC/E,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,yEAAyE;IACzE,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB;AAED;;;;;;;;;GASG;AACH,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,MAAM,GAAG;IAAE,IAAI,EAAE,SAAS,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAI9F;AAED;;;;;GAKG;AACH,wBAAgB,cAAc,CAC5B,IAAI,EAAE,SAAS,GACd,WAAW,GAAG,cAAc,GAAG,aAAa,GAAG,cAAc,CAW/D;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,gBAAgB,CAC9B,QAAQ,EAAE,oBAAoB,EAC9B,IAAI,EAAE,SAAS,GACd,MAAM,GAAG,SAAS,CAWpB;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,mBAAmB,CACjC,MAAM,EAAE,SAAS,kBAAkB,EAAE,EACrC,IAAI,EAAE,SAAS,EACf,QAAQ,EAAE,MAAM,GACf,MAAM,CAgBR;AAED;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,wBAAgB,oBAAoB,CAClC,IAAI,EAAE,MAAM,GAAG,SAAS,EACxB,QAAQ,EAAE,oBAAoB,EAC9B,cAAc,EAAE;IAAE,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,SAAS,EAC/D,UAAU,EAAE,OAAO,EACnB,MAAM,EAAE,SAAS,kBAAkB,EAAE,EACrC,QAAQ,EAAE,MAAM,GACf,MAAM,CAcR;AAED;;;;GAIG;AACH,MAAM,MAAM,kBAAkB,GAAG,MAAM,GAAG,MAAM,CAAA;AAKhD;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,kBAAkB,CAChC,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,SAAS,EACf,UAAU,EAAE,OAAO,EACnB,MAAM,EAAE,SAAS,kBAAkB,EAAE,EACrC,QAAQ,EAAE,MAAM,GACf,kBAAkB,GAAG,IAAI,CAe3B;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,kBAAkB,CAChC,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,SAAS,kBAAkB,EAAE,EACrC,QAAQ,EAAE,MAAM,GACf,SAAS,GAAG,IAAI,CAKlB;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,iBAAiB,CAC/B,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,SAAS,EACf,UAAU,EAAE,OAAO,EACnB,MAAM,EAAE,SAAS,kBAAkB,EAAE,EACrC,QAAQ,EAAE,MAAM,GACf,OAAO,CAET"}
|
|
@@ -113,6 +113,46 @@ export function freeTierModeModelId(models, mode, fallback) {
|
|
|
113
113
|
const anyDeepseek = models.find((m) => m.provider === 'deepseek');
|
|
114
114
|
return anyDeepseek?.id ?? fallback;
|
|
115
115
|
}
|
|
116
|
+
/**
|
|
117
|
+
* The model id that will ACTUALLY serve a conversation mode, for display.
|
|
118
|
+
*
|
|
119
|
+
* Mirrors the server's `selectModelForMode` candidate chain (minus the
|
|
120
|
+
* per-request override, which the UI never has): the project's per-mode model,
|
|
121
|
+
* then the project's SAVED legacy `chatModel`, each skipped when the free-tier
|
|
122
|
+
* clamp would reject it — then the server-sent per-mode default (which already
|
|
123
|
+
* folds in the owner's account-level settings and tier), then the catalog
|
|
124
|
+
* clamp as the last resort.
|
|
125
|
+
*
|
|
126
|
+
* `settings.chatModel` must be the PERSISTED value only — never a UI-seeded
|
|
127
|
+
* default. Seeding the catalog's single free-tier model (the executor) as
|
|
128
|
+
* "current" is exactly the bug this exists to fix: every plan-mode surface
|
|
129
|
+
* then labeled the planner as the executor model while the server planned
|
|
130
|
+
* with its own plan default (observed on prod 2026-08-13 — the UI said
|
|
131
|
+
* "DeepSeek V4 Flash" for a plan turn that DeepSeek V4 Pro served).
|
|
132
|
+
*
|
|
133
|
+
* @param mode - The conversation mode to resolve.
|
|
134
|
+
* @param settings - Persisted per-mode + legacy model settings (saved only).
|
|
135
|
+
* @param serverDefaults - Server-sent per-mode defaults (`GET /ai/models`).
|
|
136
|
+
* @param isFreeTier - Whether the current user is on the free/anon tier.
|
|
137
|
+
* @param models - The available models from the catalog.
|
|
138
|
+
* @param fallback - The free-tier model id to use when no clamp match exists.
|
|
139
|
+
* @returns The model id the mode resolves to.
|
|
140
|
+
*/
|
|
141
|
+
export function effectiveModeModelId(mode, settings, serverDefaults, isFreeTier, models, fallback) {
|
|
142
|
+
const candidates = mode === 'plan'
|
|
143
|
+
? [settings.planModel, settings.chatModel]
|
|
144
|
+
: [settings.executeModel, settings.chatModel];
|
|
145
|
+
for (const candidate of candidates) {
|
|
146
|
+
if (!candidate)
|
|
147
|
+
continue;
|
|
148
|
+
// Mirror the server: a candidate the free-tier clamp rejects falls
|
|
149
|
+
// through to the next, it does not stick as the label.
|
|
150
|
+
if (freeTierLockReason(candidate, mode, isFreeTier, models, fallback) === null) {
|
|
151
|
+
return candidate;
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
return serverDefaults?.[mode] ?? freeTierModeModelId(models, mode, fallback);
|
|
155
|
+
}
|
|
116
156
|
/** Every mode a per-mode clamp exists for — used to test "free elsewhere". */
|
|
117
157
|
const MODEL_MODES = ['plan', 'execute', 'commit', 'compact'];
|
|
118
158
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"chat-model-mode-utilities.js","sourceRoot":"","sources":["../../src/components/chat-model-mode-utilities.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"chat-model-mode-utilities.js","sourceRoot":"","sources":["../../src/components/chat-model-mode-utilities.ts"],"names":[],"mappings":"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"}
|
|
@@ -40,34 +40,94 @@ export type ModelProcessingRegion = string;
|
|
|
40
40
|
*/
|
|
41
41
|
export declare function effectiveModelRegion(model: AppModelDefinition, requested?: string): ModelProcessingRegion;
|
|
42
42
|
/**
|
|
43
|
-
*
|
|
44
|
-
*
|
|
45
|
-
*
|
|
43
|
+
* The peak-hour multiplier in force for a model at an instant, in a region.
|
|
44
|
+
*
|
|
45
|
+
* Mirrors the server's `priceMultiplierAt`, including the rule that matters
|
|
46
|
+
* most: peak belongs to the NATIVE provider, so a region with a `regionPricing`
|
|
47
|
+
* override — a different host, billing its own flat card — never takes it.
|
|
48
|
+
* Showing a 2× on a re-host the user is actually routed to would be a lie in
|
|
49
|
+
* the expensive direction.
|
|
50
|
+
*
|
|
51
|
+
* @param model - The model metadata.
|
|
52
|
+
* @param region - The user's per-model region choice, if any.
|
|
53
|
+
* @param at - The instant to evaluate (defaults to now).
|
|
54
|
+
* @returns The multiplier, or `1` when no peak window applies.
|
|
55
|
+
*/
|
|
56
|
+
export declare function modelPeakMultiplier(model: AppModelDefinition, region?: string, at?: Date): number;
|
|
57
|
+
/**
|
|
58
|
+
* Whether a model can EVER cost more at some hours than others, in a region.
|
|
59
|
+
*
|
|
60
|
+
* Distinct from {@link modelPeakMultiplier}, which answers "right now". The
|
|
61
|
+
* picker needs both: one to price the current moment, one to decide whether the
|
|
62
|
+
* model deserves a "costs more at some hours" explanation at all — a model in
|
|
63
|
+
* its off-peak hours still surprises the user later if nothing says so.
|
|
64
|
+
*
|
|
65
|
+
* @param model - The model metadata.
|
|
66
|
+
* @param region - The user's per-model region choice, if any.
|
|
67
|
+
* @returns True when the model has peak windows that apply in this region.
|
|
68
|
+
*/
|
|
69
|
+
export declare function modelHasPeakPricing(model: AppModelDefinition, region?: string): boolean;
|
|
70
|
+
/**
|
|
71
|
+
* The peak windows as local-time `HH:MM–HH:MM` ranges, for display.
|
|
72
|
+
*
|
|
73
|
+
* Local, not UTC: a user reasons about "is it expensive right now" in their own
|
|
74
|
+
* clock, and the windows are only actionable if they can be compared to it.
|
|
75
|
+
*
|
|
76
|
+
* @param model - The model metadata.
|
|
77
|
+
* @returns Formatted local ranges, empty when the model has no peak windows.
|
|
78
|
+
*/
|
|
79
|
+
export declare function modelPeakWindowLabels(model: AppModelDefinition): string[];
|
|
80
|
+
/**
|
|
81
|
+
* What a representative agentic turn costs on a model, in USD — the single
|
|
82
|
+
* "cost" figure, at the rates of the model's effective region (`regionPricing`
|
|
83
|
+
* override when the region has one, else the base rates).
|
|
84
|
+
*
|
|
85
|
+
* This weighted `AGENTIC_TOKEN_MIX` replaced a plain `input + output` sum on
|
|
86
|
+
* 2026-08-14. That sum ignored cache reads, which is the term that actually
|
|
87
|
+
* dominates the bill, and the error was not small: it showed Claude Haiku at
|
|
88
|
+
* ×23 the cheapest model when the real figure is ×10, and gemini-3.7-flash at
|
|
89
|
+
* ×35 against a true ×15 — systematically scaring users off cache-friendly
|
|
90
|
+
* models while making a couple of others look cheaper than they bill. The sum
|
|
91
|
+
* was a fine proxy while every provider's cache read was a fixed fraction of
|
|
92
|
+
* input; it stopped being one once hosts started pricing cache reads
|
|
93
|
+
* independently (DeepSeek's absolute cache-hit rates, DeepInfra's 0.2x).
|
|
94
|
+
*
|
|
95
|
+
* Not currency: callers surface this only as a RELATIVE multiplier
|
|
96
|
+
* ({@link modelUsageRate}), never as a price.
|
|
46
97
|
*
|
|
47
98
|
* @param model - The model metadata.
|
|
48
99
|
* @param region - The user's per-model region choice, if any (omitted → the
|
|
49
100
|
* model's default region).
|
|
50
|
-
* @returns
|
|
101
|
+
* @returns The blended cost of one representative turn in USD.
|
|
51
102
|
*/
|
|
52
103
|
export declare function modelTotalCost(model: AppModelDefinition, region?: string): number;
|
|
53
104
|
/**
|
|
54
105
|
* Relative usage rate: how much faster this model consumes the user's AI
|
|
55
106
|
* allowance than the cheapest available model (a unitless `×N` multiplier,
|
|
56
|
-
* `1` for the cheapest). Derived from
|
|
57
|
-
* is the ONLY per-model "cost" figure user-facing surfaces show — AI
|
|
58
|
-
* never presented as currency.
|
|
107
|
+
* `1` for the cheapest). Derived from {@link modelTotalCost}, a blended agentic
|
|
108
|
+
* turn. This is the ONLY per-model "cost" figure user-facing surfaces show — AI
|
|
109
|
+
* usage is never presented as currency.
|
|
59
110
|
*
|
|
60
111
|
* The base is every model's DEFAULT-region cost (stable regardless of the
|
|
61
112
|
* user's per-model region choices); the rated model itself is priced at the
|
|
62
113
|
* given region so the figure tracks what a region switch actually changes.
|
|
63
114
|
*
|
|
115
|
+
* PEAK PRICING IS INCLUDED, at `at`. A model inside a provider's peak window
|
|
116
|
+
* genuinely drains the allowance at its multiplier, so the figure has to move
|
|
117
|
+
* with it — a single all-day number is wrong twice a day. Only the RATED model
|
|
118
|
+
* takes its multiplier: the base stays each model's off-peak default-region
|
|
119
|
+
* cost, so the anchor does not wobble as unrelated models enter their windows.
|
|
120
|
+
* Pair it with {@link modelHasPeakPricing} / {@link modelPeakWindowLabels} so a
|
|
121
|
+
* changing number reads as explained rather than erratic.
|
|
122
|
+
*
|
|
64
123
|
* @param model - The model to rate.
|
|
65
124
|
* @param models - The full available-model list (supplies the cheapest base).
|
|
66
125
|
* @param region - The rated model's region choice, if any (omitted → its
|
|
67
126
|
* default region).
|
|
127
|
+
* @param at - The instant to price at (defaults to now).
|
|
68
128
|
* @returns The multiplier, rounded to 1 decimal below 10 and whole above.
|
|
69
129
|
*/
|
|
70
|
-
export declare function modelUsageRate(model: AppModelDefinition, models: readonly AppModelDefinition[], region?: string): number;
|
|
130
|
+
export declare function modelUsageRate(model: AppModelDefinition, models: readonly AppModelDefinition[], region?: string, at?: Date): number;
|
|
71
131
|
/**
|
|
72
132
|
* Ascending comparator for two models by the given column. Returns a negative,
|
|
73
133
|
* zero, or positive number suitable for `Array.prototype.sort`. Ties fall back
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"chat-models-utilities.d.ts","sourceRoot":"","sources":["../../src/components/chat-models-utilities.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAA;AAEjE;;;;;;;;;GASG;AACH,MAAM,MAAM,eAAe,GAAG,MAAM,GAAG,SAAS,GAAG,MAAM,GAAG,QAAQ,GAAG,MAAM,GAAG,QAAQ,CAAA;AAExF,sBAAsB;AACtB,MAAM,MAAM,aAAa,GAAG,KAAK,GAAG,MAAM,CAAA;AAE1C;;;;GAIG;AACH,MAAM,MAAM,qBAAqB,GAAG,MAAM,CAAA;AAE1C;;;;;;;;;;GAUG;AACH,wBAAgB,oBAAoB,CAClC,KAAK,EAAE,kBAAkB,EACzB,SAAS,CAAC,EAAE,MAAM,GACjB,qBAAqB,CAGvB;AAED
|
|
1
|
+
{"version":3,"file":"chat-models-utilities.d.ts","sourceRoot":"","sources":["../../src/components/chat-models-utilities.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAA;AAEjE;;;;;;;;;GASG;AACH,MAAM,MAAM,eAAe,GAAG,MAAM,GAAG,SAAS,GAAG,MAAM,GAAG,QAAQ,GAAG,MAAM,GAAG,QAAQ,CAAA;AAExF,sBAAsB;AACtB,MAAM,MAAM,aAAa,GAAG,KAAK,GAAG,MAAM,CAAA;AAE1C;;;;GAIG;AACH,MAAM,MAAM,qBAAqB,GAAG,MAAM,CAAA;AAE1C;;;;;;;;;;GAUG;AACH,wBAAgB,oBAAoB,CAClC,KAAK,EAAE,kBAAkB,EACzB,SAAS,CAAC,EAAE,MAAM,GACjB,qBAAqB,CAGvB;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,mBAAmB,CACjC,KAAK,EAAE,kBAAkB,EACzB,MAAM,CAAC,EAAE,MAAM,EACf,EAAE,GAAE,IAAiB,GACpB,MAAM,CAaR;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,kBAAkB,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,OAAO,CAGvF;AAED;;;;;;;;GAQG;AACH,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,kBAAkB,GAAG,MAAM,EAAE,CAQzE;AAYD;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,kBAAkB,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,MAAM,CAejF;AAED;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,wBAAgB,cAAc,CAC5B,KAAK,EAAE,kBAAkB,EACzB,MAAM,EAAE,SAAS,kBAAkB,EAAE,EACrC,MAAM,CAAC,EAAE,MAAM,EACf,EAAE,GAAE,IAAiB,GACpB,MAAM,CAMR;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,aAAa,CAC3B,CAAC,EAAE,kBAAkB,EACrB,CAAC,EAAE,kBAAkB,EACrB,MAAM,EAAE,eAAe,EACvB,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,kBAAkB,KAAK,qBAAqB,GAC9D,MAAM,CAoCR;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,UAAU,CACxB,MAAM,EAAE,SAAS,kBAAkB,EAAE,EACrC,MAAM,EAAE,eAAe,EACvB,SAAS,EAAE,aAAa,EACxB,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,kBAAkB,KAAK,qBAAqB,GAC9D,kBAAkB,EAAE,CAQtB"}
|
|
@@ -23,44 +23,148 @@ export function effectiveModelRegion(model, requested) {
|
|
|
23
23
|
return requested && regions.includes(requested) ? requested : regions[0];
|
|
24
24
|
}
|
|
25
25
|
/**
|
|
26
|
-
*
|
|
27
|
-
*
|
|
28
|
-
*
|
|
26
|
+
* The peak-hour multiplier in force for a model at an instant, in a region.
|
|
27
|
+
*
|
|
28
|
+
* Mirrors the server's `priceMultiplierAt`, including the rule that matters
|
|
29
|
+
* most: peak belongs to the NATIVE provider, so a region with a `regionPricing`
|
|
30
|
+
* override — a different host, billing its own flat card — never takes it.
|
|
31
|
+
* Showing a 2× on a re-host the user is actually routed to would be a lie in
|
|
32
|
+
* the expensive direction.
|
|
33
|
+
*
|
|
34
|
+
* @param model - The model metadata.
|
|
35
|
+
* @param region - The user's per-model region choice, if any.
|
|
36
|
+
* @param at - The instant to evaluate (defaults to now).
|
|
37
|
+
* @returns The multiplier, or `1` when no peak window applies.
|
|
38
|
+
*/
|
|
39
|
+
export function modelPeakMultiplier(model, region, at = new Date()) {
|
|
40
|
+
if (model.regionPricing?.[effectiveModelRegion(model, region)])
|
|
41
|
+
return 1;
|
|
42
|
+
const peak = model.peakPricing;
|
|
43
|
+
if (!peak || peak.windows.length === 0)
|
|
44
|
+
return 1;
|
|
45
|
+
const minute = at.getUTCHours() * 60 + at.getUTCMinutes();
|
|
46
|
+
for (const w of peak.windows) {
|
|
47
|
+
const inWindow = w.startMinuteUtc <= w.endMinuteUtc
|
|
48
|
+
? minute >= w.startMinuteUtc && minute < w.endMinuteUtc
|
|
49
|
+
: minute >= w.startMinuteUtc || minute < w.endMinuteUtc;
|
|
50
|
+
if (inWindow)
|
|
51
|
+
return peak.multiplier;
|
|
52
|
+
}
|
|
53
|
+
return 1;
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Whether a model can EVER cost more at some hours than others, in a region.
|
|
57
|
+
*
|
|
58
|
+
* Distinct from {@link modelPeakMultiplier}, which answers "right now". The
|
|
59
|
+
* picker needs both: one to price the current moment, one to decide whether the
|
|
60
|
+
* model deserves a "costs more at some hours" explanation at all — a model in
|
|
61
|
+
* its off-peak hours still surprises the user later if nothing says so.
|
|
62
|
+
*
|
|
63
|
+
* @param model - The model metadata.
|
|
64
|
+
* @param region - The user's per-model region choice, if any.
|
|
65
|
+
* @returns True when the model has peak windows that apply in this region.
|
|
66
|
+
*/
|
|
67
|
+
export function modelHasPeakPricing(model, region) {
|
|
68
|
+
if (model.regionPricing?.[effectiveModelRegion(model, region)])
|
|
69
|
+
return false;
|
|
70
|
+
return (model.peakPricing?.windows.length ?? 0) > 0 && model.peakPricing.multiplier !== 1;
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* The peak windows as local-time `HH:MM–HH:MM` ranges, for display.
|
|
74
|
+
*
|
|
75
|
+
* Local, not UTC: a user reasons about "is it expensive right now" in their own
|
|
76
|
+
* clock, and the windows are only actionable if they can be compared to it.
|
|
77
|
+
*
|
|
78
|
+
* @param model - The model metadata.
|
|
79
|
+
* @returns Formatted local ranges, empty when the model has no peak windows.
|
|
80
|
+
*/
|
|
81
|
+
export function modelPeakWindowLabels(model) {
|
|
82
|
+
const windows = model.peakPricing?.windows ?? [];
|
|
83
|
+
const fmt = (minuteUtc) => {
|
|
84
|
+
const d = new Date();
|
|
85
|
+
d.setUTCHours(Math.floor(minuteUtc / 60), minuteUtc % 60, 0, 0);
|
|
86
|
+
return d.toLocaleTimeString(undefined, { hour: '2-digit', minute: '2-digit' });
|
|
87
|
+
};
|
|
88
|
+
return windows.map((w) => `${fmt(w.startMinuteUtc)}–${fmt(w.endMinuteUtc)}`);
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* The token mix a real agentic turn bills at, used to weight the cost figure.
|
|
92
|
+
*
|
|
93
|
+
* Agentic conversations re-send a growing prefix every turn, so prompt-cache
|
|
94
|
+
* HITS dominate: measured traffic runs ~94% cache reads (deepseek, 2026-08-01).
|
|
95
|
+
* Weighting matters more than the exact numbers — what breaks is ignoring cache
|
|
96
|
+
* reads entirely, not being a few points off the ratio.
|
|
97
|
+
*/
|
|
98
|
+
const AGENTIC_TOKEN_MIX = { cacheRead: 47_000, input: 3_000, output: 800 };
|
|
99
|
+
/**
|
|
100
|
+
* What a representative agentic turn costs on a model, in USD — the single
|
|
101
|
+
* "cost" figure, at the rates of the model's effective region (`regionPricing`
|
|
102
|
+
* override when the region has one, else the base rates).
|
|
103
|
+
*
|
|
104
|
+
* This weighted `AGENTIC_TOKEN_MIX` replaced a plain `input + output` sum on
|
|
105
|
+
* 2026-08-14. That sum ignored cache reads, which is the term that actually
|
|
106
|
+
* dominates the bill, and the error was not small: it showed Claude Haiku at
|
|
107
|
+
* ×23 the cheapest model when the real figure is ×10, and gemini-3.7-flash at
|
|
108
|
+
* ×35 against a true ×15 — systematically scaring users off cache-friendly
|
|
109
|
+
* models while making a couple of others look cheaper than they bill. The sum
|
|
110
|
+
* was a fine proxy while every provider's cache read was a fixed fraction of
|
|
111
|
+
* input; it stopped being one once hosts started pricing cache reads
|
|
112
|
+
* independently (DeepSeek's absolute cache-hit rates, DeepInfra's 0.2x).
|
|
113
|
+
*
|
|
114
|
+
* Not currency: callers surface this only as a RELATIVE multiplier
|
|
115
|
+
* ({@link modelUsageRate}), never as a price.
|
|
29
116
|
*
|
|
30
117
|
* @param model - The model metadata.
|
|
31
118
|
* @param region - The user's per-model region choice, if any (omitted → the
|
|
32
119
|
* model's default region).
|
|
33
|
-
* @returns
|
|
120
|
+
* @returns The blended cost of one representative turn in USD.
|
|
34
121
|
*/
|
|
35
122
|
export function modelTotalCost(model, region) {
|
|
36
123
|
const override = model.regionPricing?.[effectiveModelRegion(model, region)];
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
124
|
+
const input = override?.inputPricePerMTok ?? model.inputPricePerMTok;
|
|
125
|
+
const output = override?.outputPricePerMTok ?? model.outputPricePerMTok;
|
|
126
|
+
// An override with no cache fields bills cache reads at its input rate — the
|
|
127
|
+
// same fallback `modelRegionRates` applies server-side for metering.
|
|
128
|
+
const cacheRead = override
|
|
129
|
+
? (override.cacheReadPricePerMTok ?? override.inputPricePerMTok)
|
|
130
|
+
: model.cacheReadPricePerMTok;
|
|
131
|
+
return ((AGENTIC_TOKEN_MIX.cacheRead * cacheRead +
|
|
132
|
+
AGENTIC_TOKEN_MIX.input * input +
|
|
133
|
+
AGENTIC_TOKEN_MIX.output * output) /
|
|
134
|
+
1_000_000);
|
|
40
135
|
}
|
|
41
136
|
/**
|
|
42
137
|
* Relative usage rate: how much faster this model consumes the user's AI
|
|
43
138
|
* allowance than the cheapest available model (a unitless `×N` multiplier,
|
|
44
|
-
* `1` for the cheapest). Derived from
|
|
45
|
-
* is the ONLY per-model "cost" figure user-facing surfaces show — AI
|
|
46
|
-
* never presented as currency.
|
|
139
|
+
* `1` for the cheapest). Derived from {@link modelTotalCost}, a blended agentic
|
|
140
|
+
* turn. This is the ONLY per-model "cost" figure user-facing surfaces show — AI
|
|
141
|
+
* usage is never presented as currency.
|
|
47
142
|
*
|
|
48
143
|
* The base is every model's DEFAULT-region cost (stable regardless of the
|
|
49
144
|
* user's per-model region choices); the rated model itself is priced at the
|
|
50
145
|
* given region so the figure tracks what a region switch actually changes.
|
|
51
146
|
*
|
|
147
|
+
* PEAK PRICING IS INCLUDED, at `at`. A model inside a provider's peak window
|
|
148
|
+
* genuinely drains the allowance at its multiplier, so the figure has to move
|
|
149
|
+
* with it — a single all-day number is wrong twice a day. Only the RATED model
|
|
150
|
+
* takes its multiplier: the base stays each model's off-peak default-region
|
|
151
|
+
* cost, so the anchor does not wobble as unrelated models enter their windows.
|
|
152
|
+
* Pair it with {@link modelHasPeakPricing} / {@link modelPeakWindowLabels} so a
|
|
153
|
+
* changing number reads as explained rather than erratic.
|
|
154
|
+
*
|
|
52
155
|
* @param model - The model to rate.
|
|
53
156
|
* @param models - The full available-model list (supplies the cheapest base).
|
|
54
157
|
* @param region - The rated model's region choice, if any (omitted → its
|
|
55
158
|
* default region).
|
|
159
|
+
* @param at - The instant to price at (defaults to now).
|
|
56
160
|
* @returns The multiplier, rounded to 1 decimal below 10 and whole above.
|
|
57
161
|
*/
|
|
58
|
-
export function modelUsageRate(model, models, region) {
|
|
162
|
+
export function modelUsageRate(model, models, region, at = new Date()) {
|
|
59
163
|
const costs = models.map((m) => modelTotalCost(m)).filter((c) => c > 0);
|
|
60
164
|
const base = costs.length > 0 ? Math.min(...costs) : 0;
|
|
61
165
|
if (!Number.isFinite(base) || base <= 0)
|
|
62
166
|
return 1;
|
|
63
|
-
const rate = modelTotalCost(model, region) / base;
|
|
167
|
+
const rate = (modelTotalCost(model, region) * modelPeakMultiplier(model, region, at)) / base;
|
|
64
168
|
return rate >= 10 ? Math.round(rate) : Math.max(1, Math.round(rate * 10) / 10);
|
|
65
169
|
}
|
|
66
170
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"chat-models-utilities.js","sourceRoot":"","sources":["../../src/components/chat-models-utilities.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AA0BH;;;;;;;;;;GAUG;AACH,MAAM,UAAU,oBAAoB,CAClC,KAAyB,EACzB,SAAkB;IAElB,MAAM,OAAO,GAAG,KAAK,CAAC,OAAO,IAAI,CAAC,IAAI,CAAC,CAAA;IACvC,OAAO,SAAS,IAAI,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAA;AAC1E,CAAC;AAED
|
|
1
|
+
{"version":3,"file":"chat-models-utilities.js","sourceRoot":"","sources":["../../src/components/chat-models-utilities.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@molecule/app-ide-react",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.2.0",
|
|
4
4
|
"description": "React IDE components for molecule.dev workspace",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -56,13 +56,13 @@
|
|
|
56
56
|
"material-file-icons": "2.4.0"
|
|
57
57
|
},
|
|
58
58
|
"devDependencies": {
|
|
59
|
-
"@molecule/app-ai-models": "1.
|
|
59
|
+
"@molecule/app-ai-models": "1.2.0",
|
|
60
60
|
"@molecule/app-ai-voice": "1.0.1",
|
|
61
61
|
"@molecule/app-country-flags": "1.0.1",
|
|
62
62
|
"@molecule/app-i18n": "1.0.1",
|
|
63
63
|
"@molecule/app-icons": "1.0.1",
|
|
64
64
|
"@molecule/app-live-preview": "1.0.1",
|
|
65
|
-
"@molecule/app-locales-ide": "1.0
|
|
65
|
+
"@molecule/app-locales-ide": "1.1.0",
|
|
66
66
|
"@molecule/app-logger": "1.0.1",
|
|
67
67
|
"@molecule/app-react": "1.0.1",
|
|
68
68
|
"@molecule/app-storage": "1.0.1",
|