Commit Graph

56 Commits

Author SHA1 Message Date
github-actions[bot] 9b05e7fff4 chore: sync AI model catalog from models.dev (#20830)
Automated daily sync of `ai-providers.json` from
[models.dev](https://models.dev).

This PR updates pricing, context windows, and model availability based
on the latest data.
New models meeting inclusion criteria (tool calling, pricing data,
context limits) are added automatically.
Deprecated models are detected based on cost-efficiency within the same
model family.

**Please review before merging** — verify no critical models were
incorrectly deprecated.

Co-authored-by: FelixMalfait <6399865+FelixMalfait@users.noreply.github.com>
2026-05-22 09:06:07 +02:00
github-actions[bot] 1ed347bc17 chore: sync AI model catalog from models.dev (#20791)
Automated daily sync of `ai-providers.json` from
[models.dev](https://models.dev).

This PR updates pricing, context windows, and model availability based
on the latest data.
New models meeting inclusion criteria (tool calling, pricing data,
context limits) are added automatically.
Deprecated models are detected based on cost-efficiency within the same
model family.

**Please review before merging** — verify no critical models were
incorrectly deprecated.

Co-authored-by: FelixMalfait <6399865+FelixMalfait@users.noreply.github.com>
2026-05-21 09:14:02 +02:00
Etienne 4c4dc4cb21 fix(ai-chat)-preference models import (#20776) 2026-05-20 15:20:09 +00:00
github-actions[bot] e494bc7006 chore: sync AI model catalog from models.dev (#20751)
Automated daily sync of `ai-providers.json` from
[models.dev](https://models.dev).

This PR updates pricing, context windows, and model availability based
on the latest data.
New models meeting inclusion criteria (tool calling, pricing data,
context limits) are added automatically.
Deprecated models are detected based on cost-efficiency within the same
model family.

**Please review before merging** — verify no critical models were
incorrectly deprecated.

Co-authored-by: FelixMalfait <6399865+FelixMalfait@users.noreply.github.com>
2026-05-20 09:06:14 +02:00
Etienne 827f24df2b fix(ai) - add ai model preferences fallback (#20704)
**Problem** 
AI_MODEL_PREFERENCES, JSON env var is not supported +
IS_CONFIG_VARIABLES_IN_DB_ENABLED=false in twenty cloud server
-> No option to set AI_MODEL_PREFERENCES

**Solution** 
AI_MODEL_PREFERENCES supports three override sources beyond the
hardcoded code defaults, in priority order:

- DB (IS_CONFIG_VARIABLES_IN_DB_ENABLED=true), the only writable source;
admin-panel mutations persist here
- ENV not usable in Twenty Cloud, which does not handle JSON-format env
vars
- **Introduced in this PR** --> File
(AI_MODEL_PREFERENCES_STORAGE_PATH), a read-only startup fallback, the
only viable override in Cloud/self-managed deployments where DB config
is disabled and JSON env vars are unsupported.
2026-05-19 13:19:24 +00:00
github-actions[bot] 62b347fc74 chore: sync AI model catalog from models.dev (#20620)
Automated daily sync of `ai-providers.json` from
[models.dev](https://models.dev).

This PR updates pricing, context windows, and model availability based
on the latest data.
New models meeting inclusion criteria (tool calling, pricing data,
context limits) are added automatically.
Deprecated models are detected based on cost-efficiency within the same
model family.

**Please review before merging** — verify no critical models were
incorrectly deprecated.

Co-authored-by: FelixMalfait <6399865+FelixMalfait@users.noreply.github.com>
2026-05-16 08:45:07 +02:00
github-actions[bot] dd9027680e chore: sync AI model catalog from models.dev (#20601)
Automated daily sync of `ai-providers.json` from
[models.dev](https://models.dev).

This PR updates pricing, context windows, and model availability based
on the latest data.
New models meeting inclusion criteria (tool calling, pricing data,
context limits) are added automatically.
Deprecated models are detected based on cost-efficiency within the same
model family.

**Please review before merging** — verify no critical models were
incorrectly deprecated.

Co-authored-by: FelixMalfait <6399865+FelixMalfait@users.noreply.github.com>
2026-05-15 09:00:29 +02:00
github-actions[bot] 38d9eacff8 chore: sync AI model catalog from models.dev (#20523)
Automated daily sync of `ai-providers.json` from
[models.dev](https://models.dev).

This PR updates pricing, context windows, and model availability based
on the latest data.
New models meeting inclusion criteria (tool calling, pricing data,
context limits) are added automatically.
Deprecated models are detected based on cost-efficiency within the same
model family.

**Please review before merging** — verify no critical models were
incorrectly deprecated.

Co-authored-by: FelixMalfait <6399865+FelixMalfait@users.noreply.github.com>
2026-05-13 08:56:41 +02:00
github-actions[bot] ee8004922e chore: sync AI model catalog from models.dev (#20392)
Automated daily sync of `ai-providers.json` from
[models.dev](https://models.dev).

This PR updates pricing, context windows, and model availability based
on the latest data.
New models meeting inclusion criteria (tool calling, pricing data,
context limits) are added automatically.
Deprecated models are detected based on cost-efficiency within the same
model family.

**Please review before merging** — verify no critical models were
incorrectly deprecated.

Co-authored-by: FelixMalfait <6399865+FelixMalfait@users.noreply.github.com>
2026-05-08 08:32:12 +02:00
Etienne 81f351c90c Ai provider - fix (#20318) 2026-05-07 10:02:54 +02:00
Etienne 91124a3cb8 AI - Add azure foundry provider (#20170)
[Merge this before](https://github.com/twentyhq/twenty-infra/pull/655)

Co-authored-by: Félix Malfait <felix.malfait@gmail.com>
2026-05-04 14:45:06 +00:00
github-actions[bot] 4fbd8b207d chore: sync AI model catalog from models.dev (#20178)
Automated daily sync of `ai-providers.json` from
[models.dev](https://models.dev).

This PR updates pricing, context windows, and model availability based
on the latest data.
New models meeting inclusion criteria (tool calling, pricing data,
context limits) are added automatically.
Deprecated models are detected based on cost-efficiency within the same
model family.

**Please review before merging** — verify no critical models were
incorrectly deprecated.

Co-authored-by: FelixMalfait <6399865+FelixMalfait@users.noreply.github.com>
2026-05-01 08:50:48 +02:00
Etienne fd6d5f895d Ai Chat - Caching optim (#20126)
EDIT : 
- solving auto-caching from Anthropic by updating ai-sdk/anthropic +
adding providerOption at stream level
- concerning Bedrock, it needs breakpoint


**1. Breakpoints were only on the system prompt**

The code already placed a cache marker on the system prompt (~10K
tokens). But the conversation history — which can grow to hundreds of
thousands of tokens — had no marker, so Anthropic re-read it at full
price on every turn.

The fix adds a prepareStep hook inside streamText that stamps the last
message with a cache breakpoint before every LLM call. Anthropic then
caches the entire conversation prefix, and subsequent turns read it at
$0.30/M instead of $3/M.

prepareStep is used rather than a one-shot pre-processing step because
an agentic turn makes multiple internal LLM calls as tool results
accumulate — the hook refreshes the breakpoint before each one.

**2. Bedrock was using the wrong field**

The system prompt marker for Bedrock was set as cacheControl: { type:
'ephemeral' } — which is the Anthropic wire format. The Bedrock Converse
API expects cachePoint: { type: 'default' }. The system prompt was
silently not being cached on Bedrock at all.

Both the system prompt and the new prepareStep now go through a shared
getCacheProviderOptions helper that returns the correct field per
provider.

**3. Persisted cached token usage to monitor cache strat. efficiency**
2026-04-29 14:42:12 +00:00
github-actions[bot] c476c6c80b chore: sync AI model catalog from models.dev (#20122)
Automated daily sync of `ai-providers.json` from
[models.dev](https://models.dev).

This PR updates pricing, context windows, and model availability based
on the latest data.
New models meeting inclusion criteria (tool calling, pricing data,
context limits) are added automatically.
Deprecated models are detected based on cost-efficiency within the same
model family.

**Please review before merging** — verify no critical models were
incorrectly deprecated.

Co-authored-by: FelixMalfait <6399865+FelixMalfait@users.noreply.github.com>
2026-04-29 08:45:09 +02:00
github-actions[bot] 1c06506256 chore: sync AI model catalog from models.dev (#20106)
Automated daily sync of `ai-providers.json` from
[models.dev](https://models.dev).

This PR updates pricing, context windows, and model availability based
on the latest data.
New models meeting inclusion criteria (tool calling, pricing data,
context limits) are added automatically.
Deprecated models are detected based on cost-efficiency within the same
model family.

**Please review before merging** — verify no critical models were
incorrectly deprecated.

Co-authored-by: FelixMalfait <6399865+FelixMalfait@users.noreply.github.com>
2026-04-28 08:49:33 +02:00
nitin bb5f294c5a [AI] Collapse NativeToolBinder to a single bind() entry (#20051)
The binder doesnt need an agent or full tool context -- just a model and
options.
Single `bind(model, options)` entry!


Builds on #20022.
2026-04-27 16:35:59 +02:00
github-actions[bot] 577312f121 chore: sync AI model catalog from models.dev (#20073)
Automated daily sync of `ai-providers.json` from
[models.dev](https://models.dev).

This PR updates pricing, context windows, and model availability based
on the latest data.
New models meeting inclusion criteria (tool calling, pricing data,
context limits) are added automatically.
Deprecated models are detected based on cost-efficiency within the same
model family.

**Please review before merging** — verify no critical models were
incorrectly deprecated.

Co-authored-by: FelixMalfait <6399865+FelixMalfait@users.noreply.github.com>
2026-04-27 08:46:56 +02:00
github-actions[bot] 570038ad65 chore: sync AI model catalog from models.dev (#20045)
Automated daily sync of `ai-providers.json` from
[models.dev](https://models.dev).

This PR updates pricing, context windows, and model availability based
on the latest data.
New models meeting inclusion criteria (tool calling, pricing data,
context limits) are added automatically.
Deprecated models are detected based on cost-efficiency within the same
model family.

**Please review before merging** — verify no critical models were
incorrectly deprecated.

Co-authored-by: FelixMalfait <6399865+FelixMalfait@users.noreply.github.com>
2026-04-25 08:26:54 +02:00
nitin 6c1c0737b0 Clarify registry tools vs native model tool binding (#20022)
## Intent

This is a small foundation cleanup for the tool architecture.

The main decision is: registry tools and native SDK/model tools are
different things.

- Registry tools have descriptors, schemas, catalog entries, and execute
through `ToolExecutorService`
- Native model tools are opaque AI SDK objects, bound directly into the
model `ToolSet`
- Surfaces still own their policy: chat, MCP, and workflow agents decide
what they expose

## What changed

- Removed `NATIVE_MODEL` from `ToolCategory`
- Kept `ToolRegistryService` focused on registry-backed tools only
- Moved native model tool binding through `NativeToolBinderService`
- Reused native binding from chat instead of duplicating
provider-specific web-search logic
- Kept MCP local execution exclusions in a dedicated constant
- Moved surface-specific constants into dedicated constant files

## What comes next

- Move hardcoded chat app preloads, like Exa web search, into
app/manifest metadata
- Decide a clearer policy for local runtime tools like code interpreter
and HTTP request
- Gradually document the three tool shapes: registry tools, native model
tools, and local runtime tools

---------

Co-authored-by: claude[bot] <41898282+claude[bot]@users.noreply.github.com>
Co-authored-by: Félix Malfait <FelixMalfait@users.noreply.github.com>
Co-authored-by: Félix Malfait <felix.malfait@gmail.com>
2026-04-24 17:18:19 +02:00
github-actions[bot] e8f58fd23a chore: sync AI model catalog from models.dev (#20018)
Automated daily sync of `ai-providers.json` from
[models.dev](https://models.dev).

This PR updates pricing, context windows, and model availability based
on the latest data.
New models meeting inclusion criteria (tool calling, pricing data,
context limits) are added automatically.
Deprecated models are detected based on cost-efficiency within the same
model family.

**Please review before merging** — verify no critical models were
incorrectly deprecated.

Co-authored-by: FelixMalfait <6399865+FelixMalfait@users.noreply.github.com>
2026-04-24 08:34:13 +02:00
Paul Rastoin b1838b3090 Retrieve ai catalog at bootstrap (#20005)
# Introduction
Migrating from build injection to a runtime bootstrap injection of the
ai catalog that are dynamic to the env we're deploying to
2026-04-23 17:00:35 +00:00
github-actions[bot] a8d4039629 chore: sync AI model catalog from models.dev (#19914)
Automated daily sync of `ai-providers.json` from
[models.dev](https://models.dev).

This PR updates pricing, context windows, and model availability based
on the latest data.
New models meeting inclusion criteria (tool calling, pricing data,
context limits) are added automatically.
Deprecated models are detected based on cost-efficiency within the same
model family.

**Please review before merging** — verify no critical models were
incorrectly deprecated.

Co-authored-by: FelixMalfait <6399865+FelixMalfait@users.noreply.github.com>
2026-04-21 08:32:40 +02:00
github-actions[bot] 46aedcf133 chore: sync AI model catalog from models.dev (#19866)
Automated daily sync of `ai-providers.json` from
[models.dev](https://models.dev).

This PR updates pricing, context windows, and model availability based
on the latest data.
New models meeting inclusion criteria (tool calling, pricing data,
context limits) are added automatically.
Deprecated models are detected based on cost-efficiency within the same
model family.

**Please review before merging** — verify no critical models were
incorrectly deprecated.

Co-authored-by: FelixMalfait <6399865+FelixMalfait@users.noreply.github.com>
2026-04-20 08:38:46 +02:00
Félix Malfait 6117a1d6c0 refactor: standardize AI acronym to Ai (PascalCase) across internal identifiers (#19837)
## Summary

The "AI" acronym was rendered inconsistently across the codebase. The
backend AI module had settled on PascalCase `Ai` (`AiAgentModule`,
`AiBillingService`, `AiChatModule`, `AiModelRegistryService`, etc.),
while frontend components, several DTOs, a few types, and shared
identifiers still used all-caps `AI` (`AIChatTab`,
`AISystemPromptPreviewDTO`, `SettingsPath.AIPrompts`, ...). CLAUDE.md
specifies PascalCase for classes; this PR normalizes everything internal
to `Ai`.

**This is a pure internal rename.** The GraphQL schema is untouched —
`@ObjectType` decorator string arguments, resolver method names (which
become Query/Mutation field names), gql template contents, and the
`generated-metadata/graphql.ts` file are preserved verbatim. The only
visible change is TypeScript identifiers and file names.

## Also folded in (adjacent cleanups)

- **`AgentModelConfigService` → `AiModelConfigService`**. Lives in
`ai-models/` and is used by multiple AI code paths, not just the Agent
entity. The "Agent" prefix was misleading.
- **`generate-text-input.dto.ts` → `generate-text.input.ts`**. The
`ai-agent/dtos/` folder already uses `<entity>.input.ts` convention for
Input classes (`create-agent.input.ts` etc.); the old path mixed
`.dto.ts` file extension with a class that has no DTO suffix. File
rename only; class stays `GenerateTextInput`.
- **Removed stale TODO** in `ai-model-config.type.ts` that asked for the
`AiModelConfig` rename that this PR performs.

## Rename methodology

Bulk rename via perl with anchored regex
`(?<!['"])(?<![A-Z.])AI([A-Z])(?=[a-z])/Ai$1/g`:

- **Lookbehind for non-uppercase** skips adjacent acronyms (`MOSAIC`,
`OIDCSSO`) and leaves `AIRBNB_ID` alone.
- **Lookbehind for non-quote** protects most string literals.
- **Lookahead for lowercase** restricts matches to PascalCase
identifiers (`AIChatTab`), leaving SCREAMING_SNAKE constants untouched.

Strict file-scope exclusions: `generated-metadata/**`, `generated/**`,
`locales/**`, `migrations/**`, `illustrations/**`, `halftone/**`, and
the two gql template files (`queries/getAISystemPromptPreview.ts`,
`mutations/uploadAIChatFile.ts`).

Post-rename reverts for identifiers where the regex was too eager:
- Backend resolver method names kept: `getAISystemPromptPreview`,
`uploadAIChatFile` (they are GraphQL field names).
- `@ObjectType('AdminAIModels')` / `('AISystemPromptPreview')` /
`('AISystemPromptSection')` kept as-is.
- Backend classes `ClientAIModelConfig` / `AdminAIModelConfig` kept
as-is (they use `@ObjectType()` with no argument, so the class name IS
the schema name).
- External-library symbols restored: `OpenAIProvider`,
`createOpenAICompatible`, `vercelAIIntegration`.

File renames use a two-step rename to work on macOS case-insensitive
filesystems: `git mv X.tsx X.tsx.tmp && git mv X.tsx.tmp renamed.tsx`.

## Diff audit

- 0 changes to migrations
- 0 changes to locale `.po` / `.ts` files
- 0 changes to `generated-metadata/graphql.ts`
- 0 changes to website illustration files (base64 blobs preserved)
- 0 renames inside user-facing translation strings (`t\`…\``,
`msg\`…\``, `<Trans>…</Trans>`)

## Test plan

- [x] `npx nx typecheck twenty-server` — PASS
- [x] `npx nx typecheck twenty-front` — PASS
- [x] `npx jest ai-model admin agent-role` — 79/79 PASS
- [x] `npx oxlint --type-aware` on 118 changed files — 0 errors
- [x] `npx prettier --check` on 118 changed files — clean
- [ ] CI
2026-04-19 13:29:35 +02:00
Félix Malfait c28c20143b refactor(server): rename Agent exception to Ai; add THREAD_NOT_FOUND / MESSAGE_NOT_FOUND codes (fixes 500s) (#19831)
## Summary

- The exception class under `ai-agent/` was serving every AI surface
(agent, chat, role, models, generate-text), so `Agent` was a misnomer.
Promoted to the `ai/` namespace; renamed `AgentException` →
`AiException`, `AgentExceptionCode` → `AiExceptionCode`, and related
interceptor / filter / handler / file names accordingly.
- Split the single `AGENT_NOT_FOUND` code into entity-specific codes.
Chat-thread lookups no longer reuse the agent identifier.
- **Fixes Sentry 500s on `GetChatMessages` / `chatThread`.** Every
"Thread not found" and "Queued message not found" throw site in ai-chat
was previously wired to `AGENT_EXECUTION_FAILED`, which maps to
`InternalServerError` (HTTP 500). They now use `THREAD_NOT_FOUND` /
`MESSAGE_NOT_FOUND`, both of which map to `NotFoundError` (HTTP 404) in
the GraphQL and REST handlers.

The underlying cause of *why* clients are asking for threads that no
longer resolve for them — per-user chat-thread create events being
broadcast workspace-wide — is addressed separately in a follow-up PR.

### Code map

- Added: `ai/ai.exception.ts`,
`ai/utils/ai-graphql-api-exception-handler.util.ts` (+ spec with new
THREAD/MESSAGE cases),
`ai/interceptors/ai-graphql-api-exception.interceptor.ts`,
`ai/filters/ai-api-exception.filter.ts`
- Deleted: `ai/ai-agent/agent.exception.ts`,
`ai/ai-agent/utils/agent-graphql-api-exception-handler.util.ts` (+
spec),
`ai/ai-agent/interceptors/agent-graphql-api-exception.interceptor.ts`,
`ai/ai-agent/filters/agent-api-exception.filter.ts`
- Updated: 21 call sites across ai-agent, ai-agent-execution,
ai-agent-role, ai-chat, ai-generate-text, ai-models, role, and
workspace-migration validators.

## Test plan

- [x] `npx nx typecheck twenty-server`
- [x] `npx jest ai-graphql-api-exception-handler` (3/3 including new
THREAD_NOT_FOUND and MESSAGE_NOT_FOUND cases)
- [x] `npx jest agent-role.service` (9/9)
- [x] `npx oxlint --type-aware` on all changed files (0 warnings/errors)
- [x] `npx prettier --check` on all changed files
- [ ] CI
2026-04-18 21:08:33 +02:00
github-actions[bot] 768469f2bd chore: sync AI model catalog from models.dev (#19828)
Automated daily sync of `ai-providers.json` from
[models.dev](https://models.dev).

This PR updates pricing, context windows, and model availability based
on the latest data.
New models meeting inclusion criteria (tool calling, pricing data,
context limits) are added automatically.
Deprecated models are detected based on cost-efficiency within the same
model family.

**Please review before merging** — verify no critical models were
incorrectly deprecated.

Co-authored-by: FelixMalfait <6399865+FelixMalfait@users.noreply.github.com>
2026-04-18 08:21:55 +02:00
github-actions[bot] d7453303b8 chore: sync AI model catalog from models.dev (#19782)
Automated daily sync of `ai-providers.json` from
[models.dev](https://models.dev).

This PR updates pricing, context windows, and model availability based
on the latest data.
New models meeting inclusion criteria (tool calling, pricing data,
context limits) are added automatically.
Deprecated models are detected based on cost-efficiency within the same
model family.

**Please review before merging** — verify no critical models were
incorrectly deprecated.

Co-authored-by: FelixMalfait <6399865+FelixMalfait@users.noreply.github.com>
2026-04-17 08:32:09 +02:00
github-actions[bot] 4fd721a3c9 chore: sync AI model catalog from models.dev (#19533)
Automated daily sync of `ai-providers.json` from
[models.dev](https://models.dev).

This PR updates pricing, context windows, and model availability based
on the latest data.
New models meeting inclusion criteria (tool calling, pricing data,
context limits) are added automatically.
Deprecated models are detected based on cost-efficiency within the same
model family.

**Please review before merging** — verify no critical models were
incorrectly deprecated.

Co-authored-by: FelixMalfait <6399865+FelixMalfait@users.noreply.github.com>
2026-04-10 08:31:48 +02:00
nitin 50c5a1a8de [AI] new model tab design (#19384)
closes
https://discord.com/channels/1130383047699738754/1480979892610007121

<img width="1839" height="1316" alt="CleanShot 2026-04-07 at 15 22 38"
src="https://github.com/user-attachments/assets/d8f6048c-4e0f-425f-b7ea-4913d116020e"
/>
2026-04-09 14:15:43 +00:00
github-actions[bot] c27e3cd1a0 chore: sync AI model catalog from models.dev (#19478)
Automated daily sync of `ai-providers.json` from
[models.dev](https://models.dev).

This PR updates pricing, context windows, and model availability based
on the latest data.
New models meeting inclusion criteria (tool calling, pricing data,
context limits) are added automatically.
Deprecated models are detected based on cost-efficiency within the same
model family.

**Please review before merging** — verify no critical models were
incorrectly deprecated.

Co-authored-by: FelixMalfait <6399865+FelixMalfait@users.noreply.github.com>
2026-04-09 08:28:33 +02:00
Félix Malfait ffb6029c2d fix(ai-models): use AWS provider chain for Bedrock IRSA auth (#19470)
## Summary
- `buildBedrockProvider` ignored `authType: "role"` and only honored
static `accessKeyId`/`secretAccessKey` pairs, so deployments relying on
IRSA (e.g. EKS pods with `AWS_WEB_IDENTITY_TOKEN_FILE` + `AWS_ROLE_ARN`)
had no way to authenticate — `@ai-sdk/amazon-bedrock` does not walk the
AWS default credential chain on its own.
- When `authType === 'role'`, wire `fromNodeProviderChain()` from
`@aws-sdk/credential-providers` (already a server dependency, used by
the S3 and logic-function drivers) into `createAmazonBedrock` so IRSA
and other ambient AWS credentials resolve correctly.
- The static-credentials path is unchanged for `authType !== 'role'`.

## Test plan
- [ ] Deploy a server pod with IRSA + an `ai-models-config` entry using
`"authType": "role"` and verify Bedrock calls succeed (no `Could not
load credentials from any providers` error).
- [ ] Verify static-credentials providers (`accessKeyId` +
`secretAccessKey`) still work as before.
- [ ] `npx nx lint:diff-with-main twenty-server` passes.
- [ ] `npx nx typecheck twenty-server` passes.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-08 22:54:35 +02:00
Félix Malfait 6073bb6706 Fix AI model registry staleness on self-hosted instances (#19427)
## Summary

Fixes #19422.

Self-hosted users hitting "No AI models are available" after configuring
API keys via the admin panel were victims of a stale
`AiModelRegistryService` cache. Only the four `addAiProvider` /
`removeAiProvider` / `addModelToProvider` / `removeModelFromProvider`
mutations called `refreshRegistry()` — setting an API key through
`set/update/deleteDatabaseConfigVariable` left the registry pointing at
the pre-mutation provider state.

Rather than patch each mutation site (and re-introduce the same class of
bug on the next one), the registry now invalidates lazily based on the
LLM config-group hash, mirroring the pattern `WebSearchDriverFactory`
already uses via `DriverFactoryBase`. Any mutation to an LLM-tagged
config variable is picked up automatically on the next read — callers
never have to remember to refresh.

- Extracted `getConfigGroupHash` into a shared util reused by both
`DriverFactoryBase` and `AiModelRegistryService` (and switched the hash
to `JSON.stringify` so object-typed config vars like `AI_PROVIDERS`
actually contribute meaningfully).
- `AiModelRegistryService` gates all internal `Map` access behind
private getters that call `ensureFresh()`, so future read paths can't
accidentally observe stale state. Build path uses underscored backing
fields directly to avoid recursing.
- Dropped the now-redundant `refreshRegistry()` public method and its
four call sites in `admin-panel.resolver.ts`.

## Test plan

- [x] `nx typecheck twenty-server` passes
- [x] Existing admin-panel + ai-models specs pass (79 tests)
- [ ] Manual: on a self-hosted instance, set `OPENAI_API_KEY` (or
another provider key) via the admin panel `setDatabaseConfigVariable`
mutation and confirm AI features work without a server restart
- [ ] Manual: existing flows (`addAiProvider`, `addModelToProvider`,
etc.) still pick up new providers on the next read

🤖 Generated with [Claude Code](https://claude.com/claude-code)

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-08 22:32:05 +02:00
BugIsGod 8a84e32cf6 fix(ai): use @ai-sdk/openai-compatible for third-party providers (#19438)
## Summary:

I found a bug: 404 call when I use third-party providers (I used
deepseek). I found the final request url is:
`https://api.deepseek.com/v1/responses' `if we use createOpenAI. But the
correct one should be `https://api.provider.com/v1/chat/completions` for
the thirty provider. So I replace createOpenAI with
createOpenAICompatible in the openai-compatible provider path.

**Reproduction**: Add DeepSeek as a new AI provider (deepseek-chat,
deepseek-reasoner)

Also check the source code in Open Code project, they also use
createOpenAICompatible for the @ai-sdk/openai-compatible scenario
<img width="703" height="369" alt="image"
src="https://github.com/user-attachments/assets/90c4f924-6f1a-4fe7-821b-f13ee86a7a39"
/>


official docs: https://ai-sdk.dev/providers/openai-compatible-providers
https://ai-sdk.dev/providers/ai-sdk-providers/openai

<img width="860" height="293" alt="image"
src="https://github.com/user-attachments/assets/283b9b91-f1d6-4b1c-bb91-16ddccdff8b4"
/>



## Before
<img width="473" height="750" alt="deepseek before"
src="https://github.com/user-attachments/assets/f6b89294-1fa7-4ddc-a6a8-d396070caaca"
/>

## After

<img width="468" height="753" alt="deepseek after"
src="https://github.com/user-attachments/assets/0d170b70-e829-4a4c-abad-38879427c2df"
/>

## Backend error log

```json
[1] [Nest] 50907  - 07/04/2026, 23:48:57     LOG [ChatExecutionService] Starting chat execution with model deepseek/deepseek-chat, 4 active tools
[1] APICallError [AI_APICallError]: Not Found
[1]     at /Users/abel/Documents/Code/twenty/node_modules/@ai-sdk/provider-utils/dist/index.js:2512:14
[1]     at process.processTicksAndRejections (node:internal/process/task_queues:105:5)
[1]     at async postToApi (/Users/abel/Documents/Code/twenty/node_modules/@ai-sdk/provider-utils/dist/index.js:2373:28)
[1]     at async OpenAIResponsesLanguageModel.doStream (/Users/abel/Documents/Code/twenty/node_modules/@ai-sdk/openai/dist/index.js:4925:50)
[1]     at async fn (/Users/abel/Documents/Code/twenty/node_modules/ai/dist/index.js:7106:27)
[1]     at async /Users/abel/Documents/Code/twenty/node_modules/ai/dist/index.js:2340:24
[1]     at async _retryWithExponentialBackoff (/Users/abel/Documents/Code/twenty/node_modules/ai/dist/index.js:2599:12)
[1]     at async streamStep (/Users/abel/Documents/Code/twenty/node_modules/ai/dist/index.js:7063:17)
[1]     at async fn (/Users/abel/Documents/Code/twenty/node_modules/ai/dist/index.js:7455:9)
[1]     at async /Users/abel/Documents/Code/twenty/node_modules/ai/dist/index.js:2340:24 {
[1]   cause: undefined,
[1]   url: 'https://api.deepseek.com/v1/responses',
[1]   requestBodyValues: {
[1]     model: 'deepseek-chat',
[1]     input: [ [Object], [Object] ],
[1]     temperature: undefined,
[1]     top_p: undefined,
[1]     max_output_tokens: undefined,
[1]     conversation: undefined,
[1]     max_tool_calls: undefined,
[1]     metadata: undefined,
[1]     parallel_tool_calls: undefined,
[1]     previous_response_id: undefined,
[1]     store: undefined,
[1]     user: undefined,
[1]     instructions: undefined,
[1]     service_tier: undefined,
[1]     include: undefined,
[1]     prompt_cache_key: undefined,
[1]     prompt_cache_retention: undefined,
[1]     safety_identifier: undefined,
[1]     top_logprobs: undefined,
[1]     truncation: undefined,
[1]     tools: [ [Object], [Object], [Object], [Object] ],
[1]     tool_choice: 'auto',
[1]     stream: true
[1]   },
[1]   statusCode: 404,
[1]   responseHeaders: {
[1]     'access-control-allow-credentials': 'true',
[1]     connection: 'keep-alive',
[1]     'content-length': '0',
[1]     date: 'Tue, 07 Apr 2026 22:48:57 GMT',
[1]     server: 'elb',
[1]     'strict-transport-security': 'max-age=31536000; includeSubDomains; preload',
[1]     vary: 'origin, access-control-request-method, access-control-request-headers',
[1]     via: '1.1 83867089cd39052cd05f9e04909bedde.cloudfront.net (CloudFront)',
[1]     'x-amz-cf-id': 'O4b0VTi9Q1VVmTmq6czGlEWst7IPnAQl544hB7uIvfnSphBvUKbZTw==',
[1]     'x-amz-cf-pop': 'DUB56-P3',
[1]     'x-cache': 'Error from cloudfront',
[1]     'x-content-type-options': 'nosniff',
[1]     'x-ds-trace-id': 'a90e91809d285170338ef077f67ae2be'
[1]   },
[1]   responseBody: '',
[1]   isRetryable: false,
[1]   data: undefined,
[1]   Symbol(vercel.ai.error): true,
[1]   Symbol(vercel.ai.error.AI_APICallError): true
[1] }
[1] Exception Captured
[1]   undefined
[1]   [
[1]     NoOutputGeneratedError [AI_NoOutputGeneratedError]: No output generated. Check the stream for errors.
[1]         at Object.flush (/Users/abel/Documents/Code/twenty/node_modules/ai/dist/index.js:6656:103)
[1]         at invokePromiseCallback (node:internal/webstreams/util:172:10)
[1]         at Object.<anonymous> (node:internal/webstreams/util:177:23)
[1]         at transformStreamDefaultSinkCloseAlgorithm (node:internal/webstreams/transformstream:621:43)
[1]         at node:internal/webstreams/transformstream:379:11
[1]         at writableStreamDefaultControllerProcessClose (node:internal/webstreams/writablestream:1162:28)
[1]         at writableStreamDefaultControllerAdvanceQueueIfNeeded (node:internal/webstreams/writablestream:1253:5)
[1]         at writableStreamDefaultControllerClose (node:internal/webstreams/writablestream:1220:3)
[1]         at writableStreamClose (node:internal/webstreams/writablestream:722:3)
[1]         at writableStreamDefaultWriterClose (node:internal/webstreams/writablestream:1091:10) {
[1]       cause: undefined,
[1]       Symbol(vercel.ai.error): true,
[1]       Symbol(vercel.ai.error.AI_NoOutputGeneratedError): true
[1]     }
[1]   ]
[1] [Nest] 50907  - 07/04/2026, 23:48:59     LOG [BullMQDriver] Job 24 with name StreamAgentChatJob processed on queue ai-stream-queue in 2756.63ms
2026-04-08 12:01:49 +00:00
github-actions[bot] 8026451220 chore: sync AI model catalog from models.dev (#19426)
Automated daily sync of `ai-providers.json` from
[models.dev](https://models.dev).

This PR updates pricing, context windows, and model availability based
on the latest data.
New models meeting inclusion criteria (tool calling, pricing data,
context limits) are added automatically.
Deprecated models are detected based on cost-efficiency within the same
model family.

**Please review before merging** — verify no critical models were
incorrectly deprecated.

Co-authored-by: FelixMalfait <6399865+FelixMalfait@users.noreply.github.com>
2026-04-08 08:27:14 +02:00
github-actions[bot] ed912ec548 chore: sync AI model catalog from models.dev (#19339)
Automated daily sync of `ai-providers.json` from
[models.dev](https://models.dev).

This PR updates pricing, context windows, and model availability based
on the latest data.
New models meeting inclusion criteria (tool calling, pricing data,
context limits) are added automatically.
Deprecated models are detected based on cost-efficiency within the same
model family.

**Please review before merging** — verify no critical models were
incorrectly deprecated.

Co-authored-by: FelixMalfait <6399865+FelixMalfait@users.noreply.github.com>
2026-04-05 08:22:58 +02:00
github-actions[bot] 12b031b67d chore: sync AI model catalog from models.dev (#19298)
Automated daily sync of `ai-providers.json` from
[models.dev](https://models.dev).

This PR updates pricing, context windows, and model availability based
on the latest data.
New models meeting inclusion criteria (tool calling, pricing data,
context limits) are added automatically.
Deprecated models are detected based on cost-efficiency within the same
model family.

**Please review before merging** — verify no critical models were
incorrectly deprecated.

Co-authored-by: FelixMalfait <6399865+FelixMalfait@users.noreply.github.com>
2026-04-03 08:21:46 +02:00
github-actions[bot] 58189e1c05 chore: sync AI model catalog from models.dev (#19100)
Automated daily sync of `ai-providers.json` from
[models.dev](https://models.dev).

This PR updates pricing, context windows, and model availability based
on the latest data.
New models meeting inclusion criteria (tool calling, pricing data,
context limits) are added automatically.
Deprecated models are detected based on cost-efficiency within the same
model family.

**Please review before merging** — verify no critical models were
incorrectly deprecated.

Co-authored-by: FelixMalfait <6399865+FelixMalfait@users.noreply.github.com>
2026-03-30 08:31:25 +02:00
github-actions[bot] f651413297 chore: sync AI model catalog from models.dev (#19078)
Automated daily sync of `ai-providers.json` from
[models.dev](https://models.dev).

This PR updates pricing, context windows, and model availability based
on the latest data.
New models meeting inclusion criteria (tool calling, pricing data,
context limits) are added automatically.
Deprecated models are detected based on cost-efficiency within the same
model family.

**Please review before merging** — verify no critical models were
incorrectly deprecated.

Co-authored-by: FelixMalfait <6399865+FelixMalfait@users.noreply.github.com>
2026-03-29 08:20:40 +02:00
github-actions[bot] 6360fb3bce chore: sync AI model catalog from models.dev (#19028)
Automated daily sync of `ai-providers.json` from
[models.dev](https://models.dev).

This PR updates pricing, context windows, and model availability based
on the latest data.
New models meeting inclusion criteria (tool calling, pricing data,
context limits) are added automatically.
Deprecated models are detected based on cost-efficiency within the same
model family.

**Please review before merging** — verify no critical models were
incorrectly deprecated.

Co-authored-by: FelixMalfait <6399865+FelixMalfait@users.noreply.github.com>
2026-03-27 07:22:18 +01:00
Félix Malfait 7a341c6475 feat: support authType on AI providers for IAM role authentication (#19016)
## Summary
- Adds an `authType` field (`'api_key' | 'access_key' | 'iam_role'`) to
AI provider config
- Providers like Amazon Bedrock that authenticate via IAM role (instance
profile) can now be registered without explicit API keys or access keys
- Backend: `isProviderConfigured()` checks `apiKey || accessKeyId ||
authType`
- Frontend admin panel: shows green "Configured" badge and "IAM role"
description for providers with `authType: "iam_role"`
- Provider detail page shows "IAM role (instance profile)" in the
credentials row

## Companion PR
- twentyhq/twenty-infra#528 — patches `authType: "iam_role"` into
dev/staging Bedrock catalogs

## Changed files
- **Backend**: new `AiProviderAuthType` type, `isProviderConfigured`
util, updated registry + resolver
- **Frontend**: new `AiProviderAuthType` type, updated provider list
card + detail page

## Test plan
- [ ] Deploy with a Bedrock catalog that includes `"authType":
"iam_role"` — verify Bedrock shows "Configured" in admin AI panel
- [ ] Verify OpenAI/Anthropic with `apiKey` still show "Configured"
- [ ] Verify a provider with no credentials and no `authType` still
shows "No credentials"

Made with [Cursor](https://cursor.com)
2026-03-26 16:43:09 +01:00
nitin 578d990b9c [AI] Match ai chat composer to figma (#18874)
https://www.figma.com/design/xt8O9mFeLl46C5InWwoMrN/Twenty?node-id=93653-368288&t=obTG32NRidXid4lN-0

closes
https://discord.com/channels/1130383047699738754/1480990726442582086

---------

Co-authored-by: Félix Malfait <felix.malfait@gmail.com>
Co-authored-by: Félix Malfait <felix@twenty.com>
2026-03-26 05:43:54 +00:00
neo773 e0b36c3931 fix: ai providers json formatting (#18910)
fixes CI
2026-03-24 12:53:34 +01:00
github-actions[bot] fd044ba9a2 chore: sync AI model catalog from models.dev (#18885)
Automated daily sync of `ai-providers.json` from
[models.dev](https://models.dev).

This PR updates pricing, context windows, and model availability based
on the latest data.
New models meeting inclusion criteria (tool calling, pricing data,
context limits) are added automatically.
Deprecated models are detected based on cost-efficiency within the same
model family.

**Please review before merging** — verify no critical models were
incorrectly deprecated.

Co-authored-by: FelixMalfait <6399865+FelixMalfait@users.noreply.github.com>
2026-03-24 07:19:06 +01:00
Félix Malfait 6f4f7a1198 fix: add security headers to file serving endpoints to prevent stored XSS (#18857)
## Summary

- File serving endpoints (`GET file/:fileFolder/:id` and `GET
public-assets/...`) were piping S3/local file streams directly to the
response without any HTTP headers, allowing a stored XSS attack via
uploaded HTML files rendered inline on the CRM origin.
- Adds `Content-Type`, `Content-Disposition`, and
`X-Content-Type-Options: nosniff` headers to all file serving responses.
Only known-safe MIME types (images, PDF, plain text, audio, video) are
served inline; everything else (HTML, SVG, XML, etc.) forces
`Content-Disposition: attachment` to trigger download instead of
rendering.
- New `setFileResponseHeaders` utility with an explicit allowlist of
inline-safe MIME types.

## Test plan

- [x] Unit tests pass (9 tests including 2 new ones: header assertions
and attachment-disposition for HTML)
- [x] Lint clean (`lint:diff-with-main`)
- [x] Typecheck clean (`nx typecheck twenty-server`)
- [ ] Manual: upload an HTML file via `uploadWorkflowFile`, access the
returned URL — should download instead of rendering
- [ ] Manual: upload a PNG image, access the URL — should render inline
with correct `Content-Type: image/png`
- [ ] Manual: verify `X-Content-Type-Options: nosniff` header is present
on all file responses


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

---------

Co-authored-by: claude[bot] <41898282+claude[bot]@users.noreply.github.com>
Co-authored-by: Etienne <etiennejouan@users.noreply.github.com>
Co-authored-by: Etienne <45695613+etiennejouan@users.noreply.github.com>
2026-03-23 16:19:16 +01:00
github-actions[bot] b813d64324 chore: sync AI model catalog from models.dev (#18854)
Automated daily sync of `ai-providers.json` from
[models.dev](https://models.dev).

This PR updates pricing, context windows, and model availability based
on the latest data.
New models meeting inclusion criteria (tool calling, pricing data,
context limits) are added automatically.
Deprecated models are detected based on cost-efficiency within the same
model family.

**Please review before merging** — verify no critical models were
incorrectly deprecated.

Co-authored-by: FelixMalfait <6399865+FelixMalfait@users.noreply.github.com>
2026-03-23 13:14:09 +01:00
Félix Malfait 908aefe7c1 feat: replace hardcoded AI model constants with JSON seed catalog (#18818)
## Summary

- Replaces per-provider TypeScript constant files
(`openai-models.const.ts`, `anthropic-models.const.ts`, etc.) with a
single `ai-providers.json` catalog as the source of truth
- Adds runtime model discovery via AI SDK for self-hosted providers,
with `models.dev` enrichment for pricing/capabilities
- Introduces composite model IDs (`provider/modelId`) for canonical,
conflict-free identification
- Simplifies provider configuration: API keys are injected from
environment variables (e.g., `OPENAI_API_KEY`)
- Adds admin panel UI for provider management (add/remove/test), model
discovery, recommended model configuration, and default fast/smart model
selection per workspace
- Removes deprecated config variables (`AI_DISABLED_MODEL_IDS`,
`AUTO_ENABLE_NEW_AI_MODELS`, etc.)
- Adds database migration for composite model ID format

## Test plan

- [ ] Server typecheck passes
- [ ] Frontend typecheck passes
- [ ] Server unit tests pass
- [ ] Frontend unit tests pass
- [ ] CI pipeline green
- [ ] Admin panel AI tab loads correctly
- [ ] Provider discovery works for configured providers
- [ ] Model recommendation toggles persist
- [ ] Default fast/smart model selection works


Made with [Cursor](https://cursor.com)
2026-03-21 16:03:58 +01:00
Pablo Morales 172bbd01bc Add Gemini 3.1 Flash Lite model to AI registry (#18597)
## Summary
- Adds `gemini-3.1-flash-lite-preview` to the Google AI models registry
- Ultra-low-cost Gemini model ($0.25/M input, $1.50/M output) — half the
price of Gemini 3 Flash
- 1M context window, 64K max output, supports dynamic thinking
- No service code changes needed — the existing `AiModelRegistryService`
auto-discovers models from constants

## Changes
- `ai-models-types.const.ts`: Added `gemini-3.1-flash-lite-preview` to
the `ModelId` type union
- `google-models.const.ts`: Added model configuration with pricing,
context window, and capabilities

## Test plan
- [ ] `npx nx typecheck twenty-server` passes
- [ ] `npx nx lint twenty-server` passes
- [ ] With `GOOGLE_API_KEY` set, model appears in available models list
- [ ] Existing Gemini models unaffected

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 13:22:08 +00:00
Abdullah. 9107f5bbc7 feat: upgrade ai package to version six and the corresponding @ai-sdk/* packages to compatible versions (#18172)
Used the migration guide to carry out this upgrade:
https://ai-sdk.dev/docs/migration-guides/migration-guide-6-0

I have not been able to test locally due to credits.

<img width="220" height="450" alt="image"
src="https://github.com/user-attachments/assets/050b34b9-3239-4010-8c47-b43d44571994"
/>

---------

Co-authored-by: Félix Malfait <felix.malfait@gmail.com>
2026-02-25 16:49:26 +01:00
Félix Malfait 9a3852bf04 feat: add two-layer AI model availability filtering (#18170)
## Summary

- **Admin-level filtering**: New AI tab in admin panel with server-wide
model availability controls (whitelist/blacklist via
`AI_AUTO_ENABLE_NEW_MODELS`, `AI_DISABLED_MODEL_IDS`,
`AI_ENABLED_MODEL_IDS` config variables). Dedicated
`setAdminAiModelEnabled` mutation replaces frontend config-variable
manipulation. Filter dropdown to show/hide unconfigured and deprecated
models.
- **Workspace-level filtering**: Per-workspace controls with "Use best
models only" mode (curated list backed by `isRecommended` flag), or
custom whitelist/blacklist. Separate Smart/Fast model selectors with
"Best (...)" virtual options.
- **Security enforcement**: Both layers enforced at every backend
execution point — workspace update, agent create/update, chat execution.
Model ID validated against known models before config mutation. All
admin endpoints protected by `AdminPanelGuard`.

## Changes

### Backend (`twenty-server`)
- New config variables for admin-level model filtering
- `AiModelRegistryService`: `getAllModelsWithStatus()`,
`setModelAdminEnabled()` with model ID validation,
`isModelAdminAllowed()`
- `AdminPanelResolver`: `getAdminAiModels` query,
`setAdminAiModelEnabled` mutation
- `WorkspaceEntity`: new fields (`autoEnableNewAiModels`,
`disabledAiModelIds`, `enabledAiModelIds`, `useRecommendedModels`)
- `WorkspaceService`: model validation on `smartModel`/`fastModel`
updates
- `AgentResolver`: model availability checks on create/update
- `isModelAllowedByWorkspace` centralized utility
- `isRecommended` flag on model definitions
- Two TypeORM migrations

### Frontend (`twenty-front`)
- New `SettingsAdminAI` component with search, filter dropdown
(unconfigured/deprecated), and model toggle cards
- AI tab added to admin panel navigation
- `useWorkspaceAiModelAvailability` hook for workspace-level filtering
- `SettingsAIModelsTab` redesigned: merged sections, "Use best models
only" toggle, conditional available models list
- `getModelIcon`/`getModelProviderLabel` shared utilities with GraphQL
enum casing normalization
- Updated generated GraphQL types and mock data

## Test plan
- [ ] Toggle models on/off in admin panel AI tab and verify they
appear/disappear in workspace settings
- [ ] Enable "Use best models only" in workspace settings and verify
only recommended models are selectable
- [ ] Disable recommended mode and verify whitelist/blacklist toggles
work correctly
- [ ] Verify deprecated models hidden by default, shown greyed out when
filter enabled
- [ ] Verify unconfigured models hidden by default, shown disabled when
filter enabled
- [ ] Try setting a disabled model as Smart/Fast model — should be
rejected
- [ ] Try creating an agent with a disabled model — should be rejected
- [ ] Verify admin panel AI tab requires admin access


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

---------

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-02-24 10:14:24 +01:00
Félix Malfait 41f09c5a4c 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>
2026-02-22 14:39:04 +01:00