Add AI model pricing, Bedrock provider, and InferenceProvider/ModelFamily split (#18155)

## Summary

- **Model pricing overhaul**: All model constants updated with accurate
pricing in dollars per 1M tokens, including cached input rates, cache
creation rates, and tiered >200k context pricing
- **New providers**: Added Google (Gemini 3.x), Mistral, and AWS Bedrock
as inference providers. Bedrock serves Claude Opus 4.6 and Sonnet 4.6
via AWS, with proper credential handling following the existing S3/SES
pattern
- **InferenceProvider/ModelFamily split**: Refactored `ModelProvider`
into two orthogonal enums — `InferenceProvider` (who serves the model:
auth, SDK, metadata format) and `ModelFamily` (who created it: token
counting semantics). This eliminates growing `||` chains for token
normalization checks like `excludesCachedTokens`
- **Billing improvements**: Reasoning tokens charged at output rate,
cache token discounts applied accurately, real errors thrown to Sentry
on billing failures

## Test plan

- [x] All existing unit tests updated and passing (23 tests across 3
test files)
- [x] Lint passes for both twenty-server and twenty-front
- [ ] CI checks pass


Made with [Cursor](https://cursor.com)

---------

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Félix Malfait
2026-02-22 14:39:04 +01:00
committed by GitHub
parent a900b4a4b4
commit 41f09c5a4c
37 changed files with 1462 additions and 383 deletions
@@ -679,12 +679,13 @@ export type CheckUserExistOutput = {
export type ClientAiModelConfig = {
__typename?: 'ClientAIModelConfig';
deprecated?: Maybe<Scalars['Boolean']>;
inputCostPer1kTokensInCredits: Scalars['Float'];
inferenceProvider: InferenceProvider;
inputCostPerMillionTokensInCredits: Scalars['Float'];
label: Scalars['String'];
modelFamily?: Maybe<ModelFamily>;
modelId: Scalars['String'];
nativeCapabilities?: Maybe<NativeModelCapabilities>;
outputCostPer1kTokensInCredits: Scalars['Float'];
provider: ModelProvider;
outputCostPerMillionTokensInCredits: Scalars['Float'];
};
export type ClientConfig = {
@@ -1883,6 +1884,18 @@ export enum IndexType {
GIN = 'GIN'
}
export enum InferenceProvider {
ANTHROPIC = 'ANTHROPIC',
BEDROCK = 'BEDROCK',
GOOGLE = 'GOOGLE',
GROQ = 'GROQ',
MISTRAL = 'MISTRAL',
NONE = 'NONE',
OPENAI = 'OPENAI',
OPENAI_COMPATIBLE = 'OPENAI_COMPATIBLE',
XAI = 'XAI'
}
export type InitiateTwoFactorAuthenticationProvisioningOutput = {
__typename?: 'InitiateTwoFactorAuthenticationProvisioningOutput';
uri: Scalars['String'];
@@ -2155,12 +2168,11 @@ export type MetadataEventWithQueryIds = {
queryIds: Array<Scalars['String']>;
};
export enum ModelProvider {
export enum ModelFamily {
ANTHROPIC = 'ANTHROPIC',
GROQ = 'GROQ',
NONE = 'NONE',
GOOGLE = 'GOOGLE',
MISTRAL = 'MISTRAL',
OPENAI = 'OPENAI',
OPENAI_COMPATIBLE = 'OPENAI_COMPATIBLE',
XAI = 'XAI'
}