@genesislcap/ai-assistant 15.33.1 → 15.34.1
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/ai-assistant.api.json +1021 -6
- package/dist/ai-assistant.d.ts +209 -5
- package/dist/chat-driver.cjs +90 -0
- package/dist/chat-driver.cjs.map +3 -3
- package/dist/chat-driver.mjs +86 -0
- package/dist/chat-driver.mjs.map +3 -3
- package/dist/custom-elements.json +329 -3
- package/dist/dts/chat-driver-node.d.ts +2 -2
- package/dist/dts/chat-driver-node.d.ts.map +1 -1
- package/dist/dts/components/settings-modal/settings-modal.styles.d.ts.map +1 -1
- package/dist/dts/components/settings-modal/settings-modal.template.d.ts.map +1 -1
- package/dist/dts/index.d.ts +2 -0
- package/dist/dts/index.d.ts.map +1 -1
- package/dist/dts/main/budget-controller.d.ts +38 -6
- package/dist/dts/main/budget-controller.d.ts.map +1 -1
- package/dist/dts/main/main.d.ts +22 -4
- package/dist/dts/main/main.d.ts.map +1 -1
- package/dist/dts/main/main.types.d.ts +25 -0
- package/dist/dts/main/main.types.d.ts.map +1 -1
- package/dist/dts/provider/tiered-provider-switcher.d.ts +123 -0
- package/dist/dts/provider/tiered-provider-switcher.d.ts.map +1 -0
- package/dist/dts/state/ai-assistant-slice.d.ts +34 -0
- package/dist/dts/state/ai-assistant-slice.d.ts.map +1 -1
- package/dist/dts/state/session-store.d.ts.map +1 -1
- package/dist/esm/chat-driver-node.js +11 -1
- package/dist/esm/components/settings-modal/settings-modal.styles.js +75 -0
- package/dist/esm/components/settings-modal/settings-modal.template.js +56 -4
- package/dist/esm/index.js +1 -0
- package/dist/esm/main/budget-controller.js +178 -6
- package/dist/esm/main/main.js +20 -0
- package/dist/esm/provider/tiered-provider-switcher.js +142 -0
- package/dist/esm/state/ai-assistant-slice.js +17 -3
- package/docs/styling.md +24 -0
- package/package.json +18 -17
- package/sandbox/sandbox.ts +52 -0
- package/scripts/smoke-chat-driver-node.mjs +86 -0
package/dist/ai-assistant.d.ts
CHANGED
|
@@ -3,6 +3,9 @@ import type { AggregateUsage } from '@genesislcap/foundation-ai';
|
|
|
3
3
|
import { AIProviderRegistry } from '@genesislcap/foundation-ai';
|
|
4
4
|
import type { AIProviderRegistryStatusEntry } from '@genesislcap/foundation-ai';
|
|
5
5
|
import { AIProviderType } from '@genesislcap/foundation-ai';
|
|
6
|
+
import { AITierId } from '@genesislcap/foundation-ai';
|
|
7
|
+
import { AITiers } from '@genesislcap/foundation-ai';
|
|
8
|
+
import { AITierVendor } from '@genesislcap/foundation-ai';
|
|
6
9
|
import { BudgetExhaustedError } from '@genesislcap/foundation-ai';
|
|
7
10
|
import type { CachePolicy } from '@genesislcap/foundation-ai';
|
|
8
11
|
import type { ChatAttachment } from '@genesislcap/foundation-ai';
|
|
@@ -15,6 +18,7 @@ import type { ChatThinkingPolicy } from '@genesislcap/foundation-ai';
|
|
|
15
18
|
import type { ChatToolChoice } from '@genesislcap/foundation-ai';
|
|
16
19
|
import type { ChatToolDefinition } from '@genesislcap/foundation-ai';
|
|
17
20
|
import type { ChatToolHandlers } from '@genesislcap/foundation-ai';
|
|
21
|
+
import { Container } from '@genesislcap/web-core';
|
|
18
22
|
import { ElementStyles } from '@genesislcap/web-core';
|
|
19
23
|
import { GenesisElement } from '@genesislcap/web-core';
|
|
20
24
|
import type { InteractionRequestOptions } from '@genesislcap/foundation-ai';
|
|
@@ -3358,6 +3362,26 @@ export declare class FoundationAiAssistant extends GenesisElement {
|
|
|
3358
3362
|
* }
|
|
3359
3363
|
* ```
|
|
3360
3364
|
*
|
|
3365
|
+
* A host that meters its spend by source can pass an optional `segments` breakdown, and
|
|
3366
|
+
* the vendor's bar is drawn stacked with a legend naming each one (NEW-15):
|
|
3367
|
+
*
|
|
3368
|
+
* ```ts
|
|
3369
|
+
* assistantEl.setVendorBudget('anthropic', {
|
|
3370
|
+
* budgetUsd: 50,
|
|
3371
|
+
* spentUsd: 12.5,
|
|
3372
|
+
* segments: [
|
|
3373
|
+
* { id: 'app', label: 'App', spentUsd: 9 },
|
|
3374
|
+
* { id: 'batch', label: 'Batch jobs', spentUsd: 3.5 },
|
|
3375
|
+
* ],
|
|
3376
|
+
* });
|
|
3377
|
+
* ```
|
|
3378
|
+
*
|
|
3379
|
+
* The labels are yours — the assistant has no vocabulary for what a host spends money on.
|
|
3380
|
+
* Segments may add up to less than `spentUsd` (the remainder draws unlabelled) but never
|
|
3381
|
+
* to more; a breakdown that does, or that is otherwise malformed, is dropped with a debug
|
|
3382
|
+
* log and the single bar renders. Omit `segments` entirely and nothing about the meter
|
|
3383
|
+
* changes.
|
|
3384
|
+
*
|
|
3361
3385
|
* Re-run it on mount and after each turn. Scope and lifetime follow the rest
|
|
3362
3386
|
* of the session slice (per `stateKey`, survives pop-in/out and "Clear" /
|
|
3363
3387
|
* "New chat") — except that the figures are NOT persisted to the session
|
|
@@ -3366,10 +3390,7 @@ export declare class FoundationAiAssistant extends GenesisElement {
|
|
|
3366
3390
|
*
|
|
3367
3391
|
* @beta
|
|
3368
3392
|
*/
|
|
3369
|
-
setVendorBudget(vendor: string, figures:
|
|
3370
|
-
budgetUsd: number;
|
|
3371
|
-
spentUsd: number;
|
|
3372
|
-
} | null): boolean;
|
|
3393
|
+
setVendorBudget(vendor: string, figures: VendorBudgetFigures | null): boolean;
|
|
3373
3394
|
/**
|
|
3374
3395
|
* When budget figures last arrived — from the host's
|
|
3375
3396
|
* {@link FoundationAiAssistant.setVendorBudget} or the wall latch's own feed —
|
|
@@ -5232,6 +5253,22 @@ declare type ProviderRefusedDetail = NonNullable<Extract<ChatDriverResult, {
|
|
|
5232
5253
|
reason: 'done';
|
|
5233
5254
|
}>['providerRefused']>;
|
|
5234
5255
|
|
|
5256
|
+
/**
|
|
5257
|
+
* Build a {@link TieredAIProviderSwitcher} — which registers the tier-shaped provider
|
|
5258
|
+
* registry — and put it on the {@link (AIProviderSwitcher:variable)} token. Call once at app
|
|
5259
|
+
* bootstrap.
|
|
5260
|
+
*
|
|
5261
|
+
* @remarks
|
|
5262
|
+
* Everything here is synchronous and has to stay that way. `foundation-ai-assistant` resolves
|
|
5263
|
+
* the switcher and registry tokens as it connects, and an element that connects first caches
|
|
5264
|
+
* the no-op fallback — so an `await` above this call costs the whole page load its providers.
|
|
5265
|
+
* Load a stored vendor preference AFTER it, through
|
|
5266
|
+
* {@link TieredAIProviderSwitcher.adoptPersistedVendor}.
|
|
5267
|
+
*
|
|
5268
|
+
* @beta
|
|
5269
|
+
*/
|
|
5270
|
+
export declare function registerTieredAIProviders(container: Container, options: Omit<TieredAIProviderSwitcherOptions, 'container'>): TieredAIProviderSwitcher;
|
|
5271
|
+
|
|
5235
5272
|
/**
|
|
5236
5273
|
* Name reserved for the cross-agent handoff tool — injected by OrchestratingDriver.
|
|
5237
5274
|
*
|
|
@@ -5557,6 +5594,32 @@ export declare interface SettingsBudgetRow {
|
|
|
5557
5594
|
* `Math.min(100, …)`).
|
|
5558
5595
|
*/
|
|
5559
5596
|
barValue: number;
|
|
5597
|
+
/**
|
|
5598
|
+
* The stacked bar's pieces when the host broke this vendor's spend down, and `undefined`
|
|
5599
|
+
* when it did not — in which case the row renders the design system's single progress bar,
|
|
5600
|
+
* exactly as before (NEW-15).
|
|
5601
|
+
*/
|
|
5602
|
+
segments?: SettingsBudgetSegment[];
|
|
5603
|
+
}
|
|
5604
|
+
|
|
5605
|
+
/**
|
|
5606
|
+
* One piece of a stacked budget bar, pre-computed — see {@link SettingsBudgetRow.segments}.
|
|
5607
|
+
*
|
|
5608
|
+
* @beta
|
|
5609
|
+
*/
|
|
5610
|
+
export declare interface SettingsBudgetSegment {
|
|
5611
|
+
/** The host's segment id, or the platform's own id for the unattributed remainder. */
|
|
5612
|
+
id: string;
|
|
5613
|
+
/** The host's label. Empty for the remainder, which the legend does not list. */
|
|
5614
|
+
label: string;
|
|
5615
|
+
/** This piece's spend, e.g. `$12.34`. Empty for the remainder. */
|
|
5616
|
+
figures: string;
|
|
5617
|
+
/** Width as a percentage of the row's full track, already scaled to the clamped bar. */
|
|
5618
|
+
widthPercent: number;
|
|
5619
|
+
/** Alpha applied to the design system's accent, so the pieces read as one measure. */
|
|
5620
|
+
tone: number;
|
|
5621
|
+
/** Whether this piece appears in the legend — false for the unattributed remainder. */
|
|
5622
|
+
legend: boolean;
|
|
5560
5623
|
}
|
|
5561
5624
|
|
|
5562
5625
|
/**
|
|
@@ -5993,6 +6056,112 @@ export declare type TemperatureInput = number | ((ctx: SystemPromptContext) => n
|
|
|
5993
6056
|
*/
|
|
5994
6057
|
export declare type ThinkingPolicyInput = ChatThinkingPolicy | ((ctx: SystemPromptContext) => ChatThinkingPolicy | undefined | Promise<ChatThinkingPolicy | undefined>);
|
|
5995
6058
|
|
|
6059
|
+
/**
|
|
6060
|
+
* Which cloud vendor backs the tier-shaped provider registry, plus the means to move it at
|
|
6061
|
+
* runtime (GENC-1610).
|
|
6062
|
+
*
|
|
6063
|
+
* @remarks
|
|
6064
|
+
* Upstreamed from Genesis Create, which has run this shape in production: a registry keyed by
|
|
6065
|
+
* tier (`low` / `high` / `reasoning`), a vendor switch that rebuilds it in place, and the other
|
|
6066
|
+
* vendor kept alive as a standby entry. Agents keep resolving tier names, so a switch never
|
|
6067
|
+
* touches agent config.
|
|
6068
|
+
*
|
|
6069
|
+
* Register it on the {@link (AIProviderSwitcher:interface)} DI token — via
|
|
6070
|
+
* {@link registerTieredAIProviders} — and the settings modal's vendor UI (or an app's own
|
|
6071
|
+
* control) drives it.
|
|
6072
|
+
*
|
|
6073
|
+
* @beta
|
|
6074
|
+
*/
|
|
6075
|
+
export declare class TieredAIProviderSwitcher implements AIProviderSwitcher {
|
|
6076
|
+
readonly vendors: readonly AITierVendor[];
|
|
6077
|
+
private readonly options;
|
|
6078
|
+
private readonly defaultTier;
|
|
6079
|
+
private readonly registry;
|
|
6080
|
+
private readonly listeners;
|
|
6081
|
+
private _vendor;
|
|
6082
|
+
constructor(options: TieredAIProviderSwitcherOptions);
|
|
6083
|
+
get vendor(): AITierVendor;
|
|
6084
|
+
/**
|
|
6085
|
+
* A user-driven switch: move the registry, then tell the app so it can persist the choice.
|
|
6086
|
+
* An unknown vendor is ignored.
|
|
6087
|
+
*/
|
|
6088
|
+
switchTo(vendor: string): void;
|
|
6089
|
+
/**
|
|
6090
|
+
* Adopt a vendor the app read back from its own store — the same registry move as
|
|
6091
|
+
* {@link TieredAIProviderSwitcher.switchTo}, without the `onSwitch` callback, because this
|
|
6092
|
+
* value came FROM the store and writing it back would be a pointless round-trip on load.
|
|
6093
|
+
*
|
|
6094
|
+
* Exists because registration has to stay synchronous: an element that connects before the
|
|
6095
|
+
* token is registered caches the platform's no-op fallback, so an app cannot await its
|
|
6096
|
+
* stored preference before constructing this. It boots on `initialVendor` and adopts the
|
|
6097
|
+
* stored one a moment later, through a registry that is mutable and held by reference.
|
|
6098
|
+
*/
|
|
6099
|
+
adoptPersistedVendor(vendor: string): void;
|
|
6100
|
+
subscribe(listener: (vendor: string) => void): () => void;
|
|
6101
|
+
/** The registry move both entry points share, and nothing else. */
|
|
6102
|
+
private apply;
|
|
6103
|
+
private build;
|
|
6104
|
+
private isKnownVendor;
|
|
6105
|
+
}
|
|
6106
|
+
|
|
6107
|
+
/**
|
|
6108
|
+
* Options for {@link TieredAIProviderSwitcher}.
|
|
6109
|
+
*
|
|
6110
|
+
* @beta
|
|
6111
|
+
*/
|
|
6112
|
+
export declare interface TieredAIProviderSwitcherOptions {
|
|
6113
|
+
/** DI container the provider registry is registered on. */
|
|
6114
|
+
container: Container;
|
|
6115
|
+
/**
|
|
6116
|
+
* Where each vendor's tiers post, as a function of the vendor — for example one that
|
|
6117
|
+
* returns `/gwf/ai-service/<vendor>/chat`.
|
|
6118
|
+
*
|
|
6119
|
+
* A function and never a plain string, because the switcher builds MORE than one vendor:
|
|
6120
|
+
* the active one, a standby for each other vendor, and every tier again after a switch. A
|
|
6121
|
+
* single string would send all of them to the one vendor's proxy, so picking the other vendor
|
|
6122
|
+
* in settings would post Anthropic-shaped requests to a Gemini route — failing on every turn
|
|
6123
|
+
* rather than at bootstrap. An app that only ever reaches one vendor narrows `vendors` and
|
|
6124
|
+
* still passes a function; it just ignores its argument.
|
|
6125
|
+
*/
|
|
6126
|
+
serverEndpoint: (vendor: AITierVendor) => string;
|
|
6127
|
+
/**
|
|
6128
|
+
* The vendor to boot on. Required, and deliberately so: the platform has no opinion about
|
|
6129
|
+
* which cloud vendor an app should use, and a silent default would make one app's choice
|
|
6130
|
+
* look like a platform decision.
|
|
6131
|
+
*/
|
|
6132
|
+
initialVendor: AITierVendor;
|
|
6133
|
+
/**
|
|
6134
|
+
* The vendors this app can switch between. Defaults to every vendor in the table.
|
|
6135
|
+
*
|
|
6136
|
+
* Narrow it when the app's proxy can only reach one: the others would otherwise report a
|
|
6137
|
+
* status, and the assistant's partial-wall UX reads statuses — so a walled vendor would
|
|
6138
|
+
* offer "switch to the other one" about a vendor that has no key behind it.
|
|
6139
|
+
*/
|
|
6140
|
+
vendors?: readonly AITierVendor[];
|
|
6141
|
+
/**
|
|
6142
|
+
* Which tier the registry resolves for a caller that names no provider. Defaults to
|
|
6143
|
+
* `'high'`.
|
|
6144
|
+
*
|
|
6145
|
+
* High rather than the cheapest, because of what resolves through it: an orchestrated turn
|
|
6146
|
+
* classifies against the REGISTRY DEFAULT, so the classifier sees the session's accumulated
|
|
6147
|
+
* history on whatever model this names. On the smallest-window tier, a session grown to size
|
|
6148
|
+
* on a bigger model can hand the classifier a history that no longer fits — and the routing
|
|
6149
|
+
* turn fails at the moment it was supposed to hand off to a model that could have taken it.
|
|
6150
|
+
*/
|
|
6151
|
+
defaultTier?: AITierId;
|
|
6152
|
+
/** The tier table to build from. Defaults to the platform's. */
|
|
6153
|
+
tiers?: AITiers;
|
|
6154
|
+
/**
|
|
6155
|
+
* Called when {@link TieredAIProviderSwitcher.switchTo} accepts a vendor — the hook for an
|
|
6156
|
+
* app that persists the user's choice.
|
|
6157
|
+
*
|
|
6158
|
+
* Fires even when the chosen vendor is the one already active. That is not a redundant
|
|
6159
|
+
* call: during boot the registry shows this app's initial vendor while a stored preference
|
|
6160
|
+
* may still be loading, so "confirm what I can see" and "leave it alone" are different acts.
|
|
6161
|
+
*/
|
|
6162
|
+
onSwitch?: (vendor: AITierVendor) => void;
|
|
6163
|
+
}
|
|
6164
|
+
|
|
5996
6165
|
/**
|
|
5997
6166
|
* A chat message lifted into the debug-log timeline as a `kind: 'message'` entry.
|
|
5998
6167
|
*
|
|
@@ -6305,11 +6474,46 @@ export declare const userIconSvg = "<svg viewBox=\"0 0 24 24\" fill=\"none\" xml
|
|
|
6305
6474
|
*
|
|
6306
6475
|
* @beta
|
|
6307
6476
|
*/
|
|
6308
|
-
declare interface VendorBudgetFigures {
|
|
6477
|
+
export declare interface VendorBudgetFigures {
|
|
6309
6478
|
/** The vendor's budget cap in USD. Finite and `>= 0`. */
|
|
6310
6479
|
budgetUsd: number;
|
|
6311
6480
|
/** Metered spend against that cap in USD. Finite and `>= 0`; may exceed the cap. */
|
|
6312
6481
|
spentUsd: number;
|
|
6482
|
+
/**
|
|
6483
|
+
* Optional breakdown of {@link VendorBudgetFigures.spentUsd} by whatever the host meters
|
|
6484
|
+
* spend by — a surface, a team, an environment. Given, the vendor's bar is drawn stacked
|
|
6485
|
+
* with a legend; omitted, it is the single bar it has always been.
|
|
6486
|
+
*
|
|
6487
|
+
* Host-named, with no platform vocabulary: the assistant has no idea what a host's spend
|
|
6488
|
+
* sources are, and inventing labels for them is how a product word ends up in the platform.
|
|
6489
|
+
* Segments may cover less than the total (the remainder simply draws unlabelled); they may
|
|
6490
|
+
* not cover more, which would be a breakdown of a figure other than the one on screen.
|
|
6491
|
+
*
|
|
6492
|
+
* ORDER IS SIGNIFICANT: the bar and legend are drawn in array order, and the first segment
|
|
6493
|
+
* gets the strongest tone (full strength whenever the whole spend is attributed). Feed the
|
|
6494
|
+
* sources in a fixed, meaningful order — the one you want drawn first, first — and keep it
|
|
6495
|
+
* across re-feeds; a host that re-sorts its sources per response moves the strongest tone
|
|
6496
|
+
* between them with no change in the money.
|
|
6497
|
+
*/
|
|
6498
|
+
segments?: VendorBudgetSegment[];
|
|
6499
|
+
}
|
|
6500
|
+
|
|
6501
|
+
/**
|
|
6502
|
+
* One slice of a vendor's spend — see {@link VendorBudgetFigures.segments}.
|
|
6503
|
+
*
|
|
6504
|
+
* @beta
|
|
6505
|
+
*/
|
|
6506
|
+
export declare interface VendorBudgetSegment {
|
|
6507
|
+
/**
|
|
6508
|
+
* Identifies the source. Must be unique within a breakdown, and must not be
|
|
6509
|
+
* `__remainder__`, which the meter reserves for unattributed spend; a breakdown that breaks
|
|
6510
|
+
* either rule is dropped. It does not decide drawing order or tone — array order does.
|
|
6511
|
+
*/
|
|
6512
|
+
id: string;
|
|
6513
|
+
/** What the host calls this slice of the spend; rendered verbatim in the legend. */
|
|
6514
|
+
label: string;
|
|
6515
|
+
/** This slice's share of the spend in USD. Finite and `>= 0`. */
|
|
6516
|
+
spentUsd: number;
|
|
6313
6517
|
}
|
|
6314
6518
|
|
|
6315
6519
|
/**
|
package/dist/chat-driver.cjs
CHANGED
|
@@ -19,6 +19,8 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
19
19
|
// src/chat-driver-node.ts
|
|
20
20
|
var chat_driver_node_exports = {};
|
|
21
21
|
__export(chat_driver_node_exports, {
|
|
22
|
+
AI_TIER_IDS: () => AI_TIER_IDS,
|
|
23
|
+
AI_TIER_VENDORS: () => AI_TIER_VENDORS,
|
|
22
24
|
ANTHROPIC_CACHE_READ_MULTIPLIER: () => ANTHROPIC_CACHE_READ_MULTIPLIER,
|
|
23
25
|
ANTHROPIC_CACHE_WRITE_1H_MULTIPLIER: () => ANTHROPIC_CACHE_WRITE_1H_MULTIPLIER,
|
|
24
26
|
ANTHROPIC_CACHE_WRITE_5M_MULTIPLIER: () => ANTHROPIC_CACHE_WRITE_5M_MULTIPLIER,
|
|
@@ -26,6 +28,7 @@ __export(chat_driver_node_exports, {
|
|
|
26
28
|
AnthropicProvider: () => AnthropicProvider,
|
|
27
29
|
AnthropicTransport: () => AnthropicTransport,
|
|
28
30
|
ChatDriver: () => ChatDriver,
|
|
31
|
+
DEFAULT_AI_TIERS: () => DEFAULT_AI_TIERS,
|
|
29
32
|
DEFAULT_PROVIDER_REFUSED_MESSAGE: () => DEFAULT_PROVIDER_REFUSED_MESSAGE,
|
|
30
33
|
EMPTY_RESPONSE_NUDGE: () => EMPTY_RESPONSE_NUDGE,
|
|
31
34
|
GEMINI_CACHED_INPUT_MULTIPLIER: () => GEMINI_CACHED_INPUT_MULTIPLIER,
|
|
@@ -59,6 +62,7 @@ __export(chat_driver_node_exports, {
|
|
|
59
62
|
getMetaEvents: () => getMetaEvents,
|
|
60
63
|
isObservableAIProviderRegistry: () => isObservableAIProviderRegistry,
|
|
61
64
|
messageUsage: () => messageUsage,
|
|
65
|
+
resolveAITiers: () => resolveAITiers,
|
|
62
66
|
restoreMachine: () => restoreMachine,
|
|
63
67
|
strictFallbackAgent: () => strictFallbackAgent,
|
|
64
68
|
sumUsage: () => sumUsage,
|
|
@@ -1292,6 +1296,7 @@ function anthropicTokenCost(model, usage) {
|
|
|
1292
1296
|
}
|
|
1293
1297
|
var GEMINI_LONG_CONTEXT_THRESHOLD = 2e5;
|
|
1294
1298
|
var GEMINI_CACHED_INPUT_MULTIPLIER = 0.1;
|
|
1299
|
+
var GEMINI_3_8_FLASH_INTRO_RATE_ENDS = Date.parse("2027-01-01T00:00:00Z");
|
|
1295
1300
|
var GEMINI_PRICING = {
|
|
1296
1301
|
"gemini-2.5-flash-lite": {
|
|
1297
1302
|
kind: "flat",
|
|
@@ -3541,6 +3546,87 @@ var MutableAIProviderRegistry = class _MutableAIProviderRegistry {
|
|
|
3541
3546
|
}
|
|
3542
3547
|
};
|
|
3543
3548
|
|
|
3549
|
+
// ../../foundation-ai/dist/esm/tiers/ai-tiers.js
|
|
3550
|
+
var AI_TIER_IDS = ["low", "high", "reasoning"];
|
|
3551
|
+
var AI_TIER_VENDORS = ["anthropic", "gemini"];
|
|
3552
|
+
var AI_STALL_TIMEOUT_MS = 6e4;
|
|
3553
|
+
var AI_NO_RESPONSE_TIMEOUT_MS = 3e5;
|
|
3554
|
+
var DEFAULT_AI_TIERS = Object.freeze({
|
|
3555
|
+
anthropic: Object.freeze({
|
|
3556
|
+
low: Object.freeze({
|
|
3557
|
+
model: "claude-haiku-4-5-20251001",
|
|
3558
|
+
maxTokens: 16e3,
|
|
3559
|
+
stallTimeoutMs: AI_STALL_TIMEOUT_MS,
|
|
3560
|
+
timeoutMs: AI_NO_RESPONSE_TIMEOUT_MS
|
|
3561
|
+
}),
|
|
3562
|
+
// The heavy tier: whole-file writes, and adaptive thinking out of the same budget
|
|
3563
|
+
// wherever a caller leaves thinking on — hence Sonnet 5's full 128K ceiling rather
|
|
3564
|
+
// than a figure that only fits one of the two.
|
|
3565
|
+
high: Object.freeze({
|
|
3566
|
+
model: "claude-sonnet-5",
|
|
3567
|
+
maxTokens: 128e3,
|
|
3568
|
+
stallTimeoutMs: AI_STALL_TIMEOUT_MS,
|
|
3569
|
+
timeoutMs: AI_NO_RESPONSE_TIMEOUT_MS
|
|
3570
|
+
}),
|
|
3571
|
+
// One-shot judgement calls rather than tool loops, so a smaller ceiling is ample:
|
|
3572
|
+
// `max_tokens` is only a cap, and this tier never emits a whole file.
|
|
3573
|
+
//
|
|
3574
|
+
// Opus 4.8 rather than the 4.7 Create benched: the same price ($5 / $25) and the same 1M
|
|
3575
|
+
// window, but 4.8 supports native structured output where 4.7 takes the forced-tool
|
|
3576
|
+
// fallback — and structured judgement is what this tier is asked for most (review of #2540).
|
|
3577
|
+
reasoning: Object.freeze({
|
|
3578
|
+
model: "claude-opus-4-8",
|
|
3579
|
+
maxTokens: 32e3,
|
|
3580
|
+
stallTimeoutMs: AI_STALL_TIMEOUT_MS,
|
|
3581
|
+
timeoutMs: AI_NO_RESPONSE_TIMEOUT_MS
|
|
3582
|
+
})
|
|
3583
|
+
}),
|
|
3584
|
+
gemini: Object.freeze({
|
|
3585
|
+
low: Object.freeze({
|
|
3586
|
+
model: "gemini-3.1-flash-lite",
|
|
3587
|
+
stallTimeoutMs: AI_STALL_TIMEOUT_MS,
|
|
3588
|
+
timeoutMs: AI_NO_RESPONSE_TIMEOUT_MS
|
|
3589
|
+
}),
|
|
3590
|
+
// On an INTRODUCTORY rate that doubles to $1.50 / $7.50 on 2027-01-01, from which point it
|
|
3591
|
+
// is dearer on input than the gemini-3.5-flash it replaced. Chosen at the introductory rate
|
|
3592
|
+
// knowingly; `ai-tiers.test.ts` fails that day to force the re-bench.
|
|
3593
|
+
high: Object.freeze({
|
|
3594
|
+
model: "gemini-3.8-flash",
|
|
3595
|
+
stallTimeoutMs: AI_STALL_TIMEOUT_MS,
|
|
3596
|
+
timeoutMs: AI_NO_RESPONSE_TIMEOUT_MS
|
|
3597
|
+
}),
|
|
3598
|
+
// A PREVIEW model: no stability guarantee, and it may be withdrawn at short notice (its
|
|
3599
|
+
// transport warns on every construction). Accepted knowingly as the platform default because
|
|
3600
|
+
// no stable Gemini Pro was on offer when the tiers were benched; revisit as soon as Google
|
|
3601
|
+
// promotes, deprecates or withdraws it, since every app on this default inherits the risk.
|
|
3602
|
+
reasoning: Object.freeze({
|
|
3603
|
+
model: "gemini-3.1-pro-preview",
|
|
3604
|
+
stallTimeoutMs: AI_STALL_TIMEOUT_MS,
|
|
3605
|
+
timeoutMs: AI_NO_RESPONSE_TIMEOUT_MS
|
|
3606
|
+
})
|
|
3607
|
+
})
|
|
3608
|
+
});
|
|
3609
|
+
function resolveAITiers(overrides) {
|
|
3610
|
+
if (!(overrides === null || overrides === void 0 ? void 0 : overrides.anthropic) && !(overrides === null || overrides === void 0 ? void 0 : overrides.gemini))
|
|
3611
|
+
return DEFAULT_AI_TIERS;
|
|
3612
|
+
return Object.freeze({
|
|
3613
|
+
anthropic: mergeVendor(DEFAULT_AI_TIERS.anthropic, overrides.anthropic),
|
|
3614
|
+
gemini: mergeVendor(DEFAULT_AI_TIERS.gemini, overrides.gemini)
|
|
3615
|
+
});
|
|
3616
|
+
}
|
|
3617
|
+
function mergeVendor(defaults, overrides) {
|
|
3618
|
+
var _a;
|
|
3619
|
+
const merged = {};
|
|
3620
|
+
for (const tier of AI_TIER_IDS) {
|
|
3621
|
+
const defined = Object.fromEntries(Object.entries((_a = overrides === null || overrides === void 0 ? void 0 : overrides[tier]) !== null && _a !== void 0 ? _a : {}).filter(([, value]) => value !== void 0));
|
|
3622
|
+
const entry = Object.assign(Object.assign({}, defaults[tier]), defined);
|
|
3623
|
+
Object.freeze(entry);
|
|
3624
|
+
merged[tier] = entry;
|
|
3625
|
+
}
|
|
3626
|
+
Object.freeze(merged);
|
|
3627
|
+
return merged;
|
|
3628
|
+
}
|
|
3629
|
+
|
|
3544
3630
|
// src/channel/ai-activity-bus.ts
|
|
3545
3631
|
var NOOP_ACTIVITY_BUS = { publish: () => {
|
|
3546
3632
|
} };
|
|
@@ -8406,6 +8492,8 @@ function withFreshMetaSnapshot(stored, fresh) {
|
|
|
8406
8492
|
}
|
|
8407
8493
|
// Annotate the CommonJS export names for ESM import in node:
|
|
8408
8494
|
0 && (module.exports = {
|
|
8495
|
+
AI_TIER_IDS,
|
|
8496
|
+
AI_TIER_VENDORS,
|
|
8409
8497
|
ANTHROPIC_CACHE_READ_MULTIPLIER,
|
|
8410
8498
|
ANTHROPIC_CACHE_WRITE_1H_MULTIPLIER,
|
|
8411
8499
|
ANTHROPIC_CACHE_WRITE_5M_MULTIPLIER,
|
|
@@ -8413,6 +8501,7 @@ function withFreshMetaSnapshot(stored, fresh) {
|
|
|
8413
8501
|
AnthropicProvider,
|
|
8414
8502
|
AnthropicTransport,
|
|
8415
8503
|
ChatDriver,
|
|
8504
|
+
DEFAULT_AI_TIERS,
|
|
8416
8505
|
DEFAULT_PROVIDER_REFUSED_MESSAGE,
|
|
8417
8506
|
EMPTY_RESPONSE_NUDGE,
|
|
8418
8507
|
GEMINI_CACHED_INPUT_MULTIPLIER,
|
|
@@ -8446,6 +8535,7 @@ function withFreshMetaSnapshot(stored, fresh) {
|
|
|
8446
8535
|
getMetaEvents,
|
|
8447
8536
|
isObservableAIProviderRegistry,
|
|
8448
8537
|
messageUsage,
|
|
8538
|
+
resolveAITiers,
|
|
8449
8539
|
restoreMachine,
|
|
8450
8540
|
strictFallbackAgent,
|
|
8451
8541
|
sumUsage,
|