Improve build performance 2x (#18449)

## Summary

Front Before:
<img width="1199" height="670" alt="image"
src="https://github.com/user-attachments/assets/b978f67c-c0a6-49fc-bedd-a443f11c365d"
/>

Front After:
<img width="1199" height="670" alt="image"
src="https://github.com/user-attachments/assets/a4939dbb-a8b4-4c74-978c-daa7f27d00f3"
/>


Server Before:
<img width="1199" height="670" alt="image"
src="https://github.com/user-attachments/assets/da53e97f-ec65-4224-a656-ca41040aef6e"
/>


Server After:
<img width="1199" height="670" alt="image"
src="https://github.com/user-attachments/assets/8cdf3885-f515-4d6c-989f-a421a4e8206c"
/>


### CI Server Pipeline Restructuring
- Split monolithic `server-setup` job into three parallel jobs:
`server-build`, `server-lint-typecheck`, and `server-validation`
- `server-build` only handles build + Nx cache save (~1m vs old 3.5m),
unblocking downstream jobs faster
- `server-lint-typecheck` runs in parallel with no DB dependency
- `server-validation` handles DB setup, migration checks, and GraphQL
generation checks in parallel with tests
- Make `server-test` (unit tests) fully independent — no longer waits
for server-setup, builds its own artifacts
- Increase integration test shards from 8 to 10 for better parallelism
- Expected critical path reduction: ~10m → ~7m (~30% faster)

### CI Front Pipeline Improvements
- Use artifact upload/download for storybook build instead of rebuilding
in test shards
- Serve pre-built storybook via `http-server` in test jobs, with
`STORYBOOK_URL` env var
- Update `vitest.config.ts` to use `storybookUrl` when `STORYBOOK_URL`
is set
- Remove redundant `twenty-shared`, `twenty-ui`, `twenty-sdk` builds
from storybook test shards

### Vite Build Optimizations
- Conditionally enable `rollup-plugin-visualizer` behind `ANALYZE=true`
env var (not loaded by default)
- Broaden Istanbul coverage exclusions to skip test files, stories,
mocks, and decorators
- Remove `@tabler/icons-react` alias from twenty-front and storybook
configs
- Bundle `@tabler/icons-react` into twenty-ui instead of treating it as
an external dependency
- Add lazy loading with `React.lazy` + `Suspense` for all page-level
route components in `useCreateAppRouter`
This commit is contained in:
Charles Bochet
2026-03-06 11:02:26 +01:00
committed by GitHub
parent aa062644c8
commit 364c944ca6
10 changed files with 284 additions and 94 deletions
+24 -2
View File
@@ -62,6 +62,12 @@ jobs:
run: npx nx reset:env twenty-front
- name: Front / Build storybook
run: npx nx storybook:build twenty-front
- name: Upload storybook build
uses: actions/upload-artifact@v4
with:
name: storybook-static
path: packages/twenty-front/storybook-static
retention-days: 1
- name: Save storybook build cache
uses: ./.github/actions/save-cache
with:
@@ -78,6 +84,7 @@ jobs:
env:
SHARD_COUNTER: 4
REACT_APP_SERVER_BASE_URL: http://localhost:3000
STORYBOOK_URL: http://localhost:6006
steps:
- name: Fetch local actions
uses: actions/checkout@v4
@@ -85,19 +92,33 @@ jobs:
fetch-depth: 10
- name: Install dependencies
uses: ./.github/actions/yarn-install
- name: Restore storybook build cache
uses: ./.github/actions/restore-cache
with:
key: ${{ env.STORYBOOK_BUILD_CACHE_KEY_FOR_RESTORE_ACTION }}
- name: Clean stale storybook vitest cache
run: rm -rf packages/twenty-front/node_modules/.cache/storybook
- name: Build dependencies
run: |
npx nx build twenty-shared
npx nx build twenty-ui
npx nx build twenty-sdk
- name: Download storybook build
uses: actions/download-artifact@v4
with:
name: storybook-static
path: packages/twenty-front/storybook-static
- name: Install Playwright
run: |
cd packages/twenty-front
npx playwright install
- name: Front / Write .env
run: npx nx reset:env twenty-front
- name: Run storybook tests
run: npx nx storybook:test twenty-front --configuration=${{ matrix.storybook_scope }} --shard=${{ matrix.shard }}/${{ env.SHARD_COUNTER }}
- name: Serve storybook & run tests
run: |
npx http-server packages/twenty-front/storybook-static --port 6006 --silent &
timeout 30 bash -c 'until curl -sf http://localhost:6006 > /dev/null 2>&1; do sleep 1; done'
npx nx storybook:test twenty-front --configuration=${{ matrix.storybook_scope }} --shard=${{ matrix.shard }}/${{ env.SHARD_COUNTER }}
# - name: Rename coverage file
# run: |
# if [ -f "packages/twenty-front/coverage/storybook/coverage-final.json" ]; then
@@ -214,6 +235,7 @@ jobs:
runs-on: ubuntu-latest-8-cores
env:
NODE_OPTIONS: "--max-old-space-size=10240"
ANALYZE: "true"
steps:
- name: Cancel Previous Runs
uses: styfle/cancel-workflow-action@0.11.0
+73 -27
View File
@@ -13,7 +13,7 @@ concurrency:
cancel-in-progress: ${{ github.ref != 'refs/heads/main' }}
env:
SERVER_SETUP_CACHE_KEY: server-setup
SERVER_BUILD_CACHE_KEY: server-build
jobs:
changed-files-check:
@@ -27,11 +27,59 @@ jobs:
packages/twenty-front/src/generated-metadata/**
packages/twenty-emails/**
packages/twenty-shared/**
server-setup:
server-build:
needs: changed-files-check
if: needs.changed-files-check.outputs.any_changed == 'true'
timeout-minutes: 30
runs-on: ubuntu-latest-8-cores
steps:
- name: Fetch custom Github Actions and base branch history
uses: actions/checkout@v4
with:
fetch-depth: 10
- name: Install dependencies
uses: ./.github/actions/yarn-install
- name: Restore server build cache
id: restore-server-build-cache
uses: ./.github/actions/restore-cache
with:
key: ${{ env.SERVER_BUILD_CACHE_KEY }}
- name: Build twenty-shared
run: npx nx build twenty-shared
- name: Server / Write .env
run: npx nx reset:env twenty-server
- name: Server / Build
run: npx nx build twenty-server
- name: Save server build cache
uses: ./.github/actions/save-cache
with:
key: ${{ steps.restore-server-build-cache.outputs.cache-primary-key }}
server-lint-typecheck:
needs: changed-files-check
if: needs.changed-files-check.outputs.any_changed == 'true'
timeout-minutes: 30
runs-on: ubuntu-latest-8-cores
steps:
- name: Fetch custom Github Actions and base branch history
uses: actions/checkout@v4
with:
fetch-depth: 10
- name: Install dependencies
uses: ./.github/actions/yarn-install
- name: Build twenty-shared
run: npx nx build twenty-shared
- name: Server / Run lint & typecheck
uses: ./.github/actions/nx-affected
with:
tag: scope:backend
tasks: lint,typecheck
server-validation:
needs: server-build
timeout-minutes: 30
runs-on: ubuntu-latest-8-cores
services:
postgres:
image: twentycrm/twenty-postgres-spilo
@@ -58,18 +106,12 @@ jobs:
fetch-depth: 10
- name: Install dependencies
uses: ./.github/actions/yarn-install
- name: Restore server setup
id: restore-server-setup-cache
- name: Restore server build cache
uses: ./.github/actions/restore-cache
with:
key: ${{ env.SERVER_SETUP_CACHE_KEY }}
key: ${{ env.SERVER_BUILD_CACHE_KEY }}
- name: Build twenty-shared
run: npx nx build twenty-shared
- name: Server / Run lint & typecheck
uses: ./.github/actions/nx-affected
with:
tag: scope:backend
tasks: lint,typecheck
- name: Server / Write .env
run: npx nx reset:env twenty-server
- name: Server / Build
@@ -84,10 +126,8 @@ jobs:
run: |
timeout 30s npx nx run twenty-server:worker || exit_code=$?
if [ $exit_code -eq 124 ]; then
# If timeout was reached (exit code 124), consider it a success
exit 0
elif [ $exit_code -ne 0 ]; then
# If worker failed for other reasons, fail the build
exit $exit_code
fi
- name: Server / Start
@@ -120,11 +160,9 @@ jobs:
fi
- name: GraphQL / Check for Pending Generation
run: |
# Run GraphQL generation commands
npx nx run twenty-front:graphql:generate
npx nx run twenty-front:graphql:generate --configuration=metadata
# Check if GraphQL generated files were modified
if ! git diff --quiet -- packages/twenty-front/src/generated packages/twenty-front/src/generated-metadata; then
echo "::error::GraphQL schema changes detected. Please run 'npx nx run twenty-front:graphql:generate' and 'npx nx run twenty-front:graphql:generate --configuration=metadata' and commit the changes."
echo ""
@@ -137,14 +175,11 @@ jobs:
echo ""
exit 1
fi
- name: Save server setup
uses: ./.github/actions/save-cache
with:
key: ${{ steps.restore-server-setup-cache.outputs.cache-primary-key }}
server-test:
needs: server-build
timeout-minutes: 30
runs-on: ubuntu-latest-8-cores
needs: server-setup
steps:
- name: Fetch custom Github Actions and base branch history
uses: actions/checkout@v4
@@ -152,10 +187,12 @@ jobs:
fetch-depth: 10
- name: Install dependencies
uses: ./.github/actions/yarn-install
- name: Restore server setup
- name: Restore server build cache
uses: ./.github/actions/restore-cache
with:
key: ${{ env.SERVER_SETUP_CACHE_KEY }}
key: ${{ env.SERVER_BUILD_CACHE_KEY }}
- name: Build twenty-shared
run: npx nx build twenty-shared
- name: Server / Run Tests
uses: ./.github/actions/nx-affected
with:
@@ -165,11 +202,11 @@ jobs:
server-integration-test:
timeout-minutes: 30
runs-on: ubuntu-latest-8-cores
needs: server-setup
needs: server-build
strategy:
fail-fast: false
matrix:
shard: [1, 2, 3, 4, 5, 6, 7, 8]
shard: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
services:
postgres:
image: twentycrm/twenty-postgres-spilo
@@ -207,7 +244,7 @@ jobs:
ANALYTICS_ENABLED: true
CLICKHOUSE_URL: "http://default:clickhousePassword@localhost:8123/twenty"
CLICKHOUSE_PASSWORD: clickhousePassword
SHARD_COUNTER: 8
SHARD_COUNTER: 10
steps:
- name: Fetch custom Github Actions and base branch history
uses: actions/checkout@v4
@@ -223,10 +260,10 @@ jobs:
echo "BILLING_STRIPE_BASE_PLAN_PRODUCT_ID=test-base-plan-product-id" >> .env.test
echo "BILLING_STRIPE_WEBHOOK_SECRET=test-webhook-secret" >> .env.test
echo "BILLING_PLAN_REQUIRED_LINK=http://localhost:3001/stripe-redirection" >> .env.test
- name: Restore server setup
- name: Restore server build cache
uses: ./.github/actions/restore-cache
with:
key: ${{ env.SERVER_SETUP_CACHE_KEY }}
key: ${{ env.SERVER_BUILD_CACHE_KEY }}
- name: Server / Build
run: npx nx build twenty-server
- name: Build dependencies
@@ -247,11 +284,20 @@ jobs:
tasks: 'test:integration'
configuration: 'with-db-reset'
args: --shard=${{ matrix.shard }}/${{ env.SHARD_COUNTER }}
ci-server-status-check:
if: always() && !cancelled()
timeout-minutes: 5
runs-on: ubuntu-latest
needs: [changed-files-check, server-setup, server-test, server-integration-test]
needs:
[
changed-files-check,
server-build,
server-lint-typecheck,
server-validation,
server-test,
server-integration-test,
]
steps:
- name: Fail job if any needs failed
if: contains(needs.*.result, 'failure')
-5
View File
@@ -58,11 +58,6 @@ const config: StorybookConfig = {
return mergeConfig(viteConfig, {
logLevel: 'warn',
resolve: {
alias: {
'@tabler/icons-react': '@tabler/icons-react/dist/esm/icons/index.mjs',
},
},
});
},
@@ -0,0 +1,9 @@
import { type ReactNode, Suspense } from 'react';
type LazyRouteProps = {
children: ReactNode;
};
export const LazyRoute = ({ children }: LazyRouteProps) => (
<Suspense fallback={<></>}>{children}</Suspense>
);
@@ -1,4 +1,5 @@
import { AppRouterProviders } from '@/app/components/AppRouterProviders';
import { LazyRoute } from '@/app/components/LazyRoute';
import { SettingsRoutes } from '@/app/components/SettingsRoutes';
import { VerifyLoginTokenEffect } from '@/auth/components/VerifyLoginTokenEffect';
@@ -8,25 +9,96 @@ import { BlankLayout } from '@/ui/layout/page/components/BlankLayout';
import { DefaultLayout } from '@/ui/layout/page/components/DefaultLayout';
import { AppPath } from 'twenty-shared/types';
import { lazy } from 'react';
import {
createBrowserRouter,
createRoutesFromElements,
Route,
} from 'react-router-dom';
import { Authorize } from '~/pages/auth/Authorize';
import { PasswordReset } from '~/pages/auth/PasswordReset';
import { SignInUp } from '~/pages/auth/SignInUp';
import { NotFound } from '~/pages/not-found/NotFound';
import { RecordIndexPage } from '~/pages/object-record/RecordIndexPage';
import { RecordShowPage } from '~/pages/object-record/RecordShowPage';
import { BookCall } from '~/pages/onboarding/BookCall';
import { BookCallDecision } from '~/pages/onboarding/BookCallDecision';
import { ChooseYourPlan } from '~/pages/onboarding/ChooseYourPlan';
import { CreateProfile } from '~/pages/onboarding/CreateProfile';
import { CreateWorkspace } from '~/pages/onboarding/CreateWorkspace';
import { InviteTeam } from '~/pages/onboarding/InviteTeam';
import { PaymentSuccess } from '~/pages/onboarding/PaymentSuccess';
import { SyncEmails } from '~/pages/onboarding/SyncEmails';
const RecordIndexPage = lazy(() =>
import('~/pages/object-record/RecordIndexPage').then((module) => ({
default: module.RecordIndexPage,
})),
);
const RecordShowPage = lazy(() =>
import('~/pages/object-record/RecordShowPage').then((module) => ({
default: module.RecordShowPage,
})),
);
const SignInUp = lazy(() =>
import('~/pages/auth/SignInUp').then((module) => ({
default: module.SignInUp,
})),
);
const PasswordReset = lazy(() =>
import('~/pages/auth/PasswordReset').then((module) => ({
default: module.PasswordReset,
})),
);
const Authorize = lazy(() =>
import('~/pages/auth/Authorize').then((module) => ({
default: module.Authorize,
})),
);
const CreateWorkspace = lazy(() =>
import('~/pages/onboarding/CreateWorkspace').then((module) => ({
default: module.CreateWorkspace,
})),
);
const CreateProfile = lazy(() =>
import('~/pages/onboarding/CreateProfile').then((module) => ({
default: module.CreateProfile,
})),
);
const SyncEmails = lazy(() =>
import('~/pages/onboarding/SyncEmails').then((module) => ({
default: module.SyncEmails,
})),
);
const InviteTeam = lazy(() =>
import('~/pages/onboarding/InviteTeam').then((module) => ({
default: module.InviteTeam,
})),
);
const ChooseYourPlan = lazy(() =>
import('~/pages/onboarding/ChooseYourPlan').then((module) => ({
default: module.ChooseYourPlan,
})),
);
const PaymentSuccess = lazy(() =>
import('~/pages/onboarding/PaymentSuccess').then((module) => ({
default: module.PaymentSuccess,
})),
);
const BookCallDecision = lazy(() =>
import('~/pages/onboarding/BookCallDecision').then((module) => ({
default: module.BookCallDecision,
})),
);
const BookCall = lazy(() =>
import('~/pages/onboarding/BookCall').then((module) => ({
default: module.BookCall,
})),
);
const NotFound = lazy(() =>
import('~/pages/not-found/NotFound').then((module) => ({
default: module.NotFound,
})),
);
export const useCreateAppRouter = (
isFunctionSettingsEnabled?: boolean,
@@ -43,26 +115,59 @@ export const useCreateAppRouter = (
<Route element={<DefaultLayout />}>
<Route path={AppPath.Verify} element={<VerifyLoginTokenEffect />} />
<Route path={AppPath.VerifyEmail} element={<VerifyEmailEffect />} />
<Route path={AppPath.SignInUp} element={<SignInUp />} />
<Route path={AppPath.Invite} element={<SignInUp />} />
<Route path={AppPath.ResetPassword} element={<PasswordReset />} />
<Route path={AppPath.CreateWorkspace} element={<CreateWorkspace />} />
<Route path={AppPath.CreateProfile} element={<CreateProfile />} />
<Route path={AppPath.SyncEmails} element={<SyncEmails />} />
<Route path={AppPath.InviteTeam} element={<InviteTeam />} />
<Route path={AppPath.PlanRequired} element={<ChooseYourPlan />} />
<Route
path={AppPath.SignInUp}
element={<LazyRoute><SignInUp /></LazyRoute>}
/>
<Route
path={AppPath.Invite}
element={<LazyRoute><SignInUp /></LazyRoute>}
/>
<Route
path={AppPath.ResetPassword}
element={<LazyRoute><PasswordReset /></LazyRoute>}
/>
<Route
path={AppPath.CreateWorkspace}
element={<LazyRoute><CreateWorkspace /></LazyRoute>}
/>
<Route
path={AppPath.CreateProfile}
element={<LazyRoute><CreateProfile /></LazyRoute>}
/>
<Route
path={AppPath.SyncEmails}
element={<LazyRoute><SyncEmails /></LazyRoute>}
/>
<Route
path={AppPath.InviteTeam}
element={<LazyRoute><InviteTeam /></LazyRoute>}
/>
<Route
path={AppPath.PlanRequired}
element={<LazyRoute><ChooseYourPlan /></LazyRoute>}
/>
<Route
path={AppPath.PlanRequiredSuccess}
element={<PaymentSuccess />}
element={<LazyRoute><PaymentSuccess /></LazyRoute>}
/>
<Route
path={AppPath.BookCallDecision}
element={<BookCallDecision />}
element={<LazyRoute><BookCallDecision /></LazyRoute>}
/>
<Route
path={AppPath.BookCall}
element={<LazyRoute><BookCall /></LazyRoute>}
/>
<Route path={AppPath.BookCall} element={<BookCall />} />
<Route path={indexAppPath.getIndexAppPath()} element={<></>} />
<Route path={AppPath.RecordIndexPage} element={<RecordIndexPage />} />
<Route path={AppPath.RecordShowPage} element={<RecordShowPage />} />
<Route
path={AppPath.RecordIndexPage}
element={<LazyRoute><RecordIndexPage /></LazyRoute>}
/>
<Route
path={AppPath.RecordShowPage}
element={<LazyRoute><RecordShowPage /></LazyRoute>}
/>
<Route
path={AppPath.SettingsCatchAll}
element={
@@ -72,10 +177,16 @@ export const useCreateAppRouter = (
/>
}
/>
<Route path={AppPath.NotFoundWildcard} element={<NotFound />} />
<Route
path={AppPath.NotFoundWildcard}
element={<LazyRoute><NotFound /></LazyRoute>}
/>
</Route>
<Route element={<BlankLayout />}>
<Route path={AppPath.Authorize} element={<Authorize />} />
<Route
path={AppPath.Authorize}
element={<LazyRoute><Authorize /></LazyRoute>}
/>
</Route>
</Route>,
),
@@ -1,26 +1,19 @@
import { styled } from '@linaria/react';
import { type Meta, type StoryObj } from '@storybook/react-vite';
import { expect, userEvent, within } from 'storybook/test';
import { ExpandableList } from '@/ui/layout/expandable-list/components/ExpandableList';
import { isDefined } from 'twenty-shared/utils';
import { Tag } from 'twenty-ui/components';
import { ComponentDecorator } from 'twenty-ui/testing';
import { themeCssVariables } from 'twenty-ui/theme-constants';
import { MAIN_COLOR_NAMES } from 'twenty-ui/theme';
const StyledContainer = styled.div`
padding: ${themeCssVariables.spacing[1]};
width: 300px;
`;
const meta: Meta<typeof ExpandableList> = {
title: 'UI/Layout/ExpandableList/ExpandableList',
component: ExpandableList,
decorators: [
(Story) => (
<StyledContainer>
<div style={{ padding: 4, width: 300 }}>
<Story />
</StyledContainer>
</div>
),
ComponentDecorator,
],
@@ -50,19 +43,16 @@ export const WithChipCount: Story = {
export const WithExpandedList: Story = {
...WithChipCount,
play: async () => {
const root = document.getElementsByTagName('body')[0];
play: async ({ canvasElement }) => {
const canvas = within(canvasElement);
if (!isDefined(root)) {
throw new Error('Root element not found');
}
const rootCanvas = within(root);
const chipCount = await rootCanvas.findByText(/^\+\d+$/);
const chipCount = await canvas.findByText(/^\+\d+$/);
await userEvent.click(chipCount);
expect(await rootCanvas.findByText('Option 7')).toBeDefined();
const body = canvasElement.ownerDocument.body;
const bodyCanvas = within(body);
expect(await bodyCanvas.findByText('Option 7')).toBeDefined();
},
};
+16 -7
View File
@@ -89,8 +89,13 @@ export default defineConfig(({ mode }) => {
exclude: [
'**/generated-metadata/**',
'**/testing/mock-data/generated/**',
'**/testing/**',
'**/*.test.{ts,tsx}',
'**/*.spec.{ts,tsx}',
'**/*.stories.{ts,tsx}',
'**/__stories__/**',
'**/__tests__/**',
'**/__mocks__/**',
'**/types/**',
'**/constants/**',
'**/states/**',
@@ -105,6 +110,7 @@ export default defineConfig(({ mode }) => {
'**/mutations/**',
'**/fragments/**',
'**/graphql/**',
'**/decorators/**',
],
babelOptions: {
presets: ['@babel/preset-typescript', '@babel/preset-react'],
@@ -112,12 +118,16 @@ export default defineConfig(({ mode }) => {
},
}),
),
visualizer({
open: true,
gzipSize: true,
brotliSize: true,
filename: 'dist/stats.html',
}) as PluginOption, // https://github.com/btd/rollup-plugin-visualizer/issues/162#issuecomment-1538265997,
...(env.ANALYZE === 'true'
? [
visualizer({
open: !process.env.CI,
gzipSize: true,
brotliSize: true,
filename: 'dist/stats.html',
}) as PluginOption,
]
: []),
],
optimizeDeps: {
@@ -236,7 +246,6 @@ export default defineConfig(({ mode }) => {
resolve: {
alias: {
path: 'rollup-plugin-node-polyfills/polyfills/path',
'@tabler/icons-react': '@tabler/icons-react/dist/esm/icons/index.mjs',
},
},
};
+3 -1
View File
@@ -24,7 +24,9 @@ export default defineConfig({
plugins: [
storybookTest({
configDir: path.join(dirname, '.storybook'),
storybookScript: 'yarn storybook --no-open',
...(process.env.STORYBOOK_URL
? { storybookUrl: process.env.STORYBOOK_URL }
: { storybookScript: 'yarn storybook --no-open' }),
}),
],
test: {
@@ -2,17 +2,17 @@ import { Module } from '@nestjs/common';
import { TypeOrmModule } from '@nestjs/typeorm';
import { AiAgentExecutionModule } from 'src/engine/metadata-modules/ai/ai-agent-execution/ai-agent-execution.module';
import { AgentTurnEntity } from 'src/engine/metadata-modules/ai/ai-agent-execution/entities/agent-turn.entity';
import { AiAgentModule } from 'src/engine/metadata-modules/ai/ai-agent/ai-agent.module';
import { AgentEntity } from 'src/engine/metadata-modules/ai/ai-agent/entities/agent.entity';
import { AiChatModule } from 'src/engine/metadata-modules/ai/ai-chat/ai-chat.module';
import { AgentChatThreadEntity } from 'src/engine/metadata-modules/ai/ai-chat/entities/agent-chat-thread.entity';
import { AgentTurnEntity } from 'src/engine/metadata-modules/ai/ai-agent-execution/entities/agent-turn.entity';
import { AiModelsModule } from 'src/engine/metadata-modules/ai/ai-models/ai-models.module';
import { PermissionsModule } from 'src/engine/metadata-modules/permissions/permissions.module';
import { AgentTurnEvaluationEntity } from './entities/agent-turn-evaluation.entity';
import { EvaluateAgentTurnJob } from './jobs/evaluate-agent-turn.job';
import { RunEvaluationInputJob } from './jobs/run-evaluation-input.job';
import { AgentTurnEvaluationEntity } from './entities/agent-turn-evaluation.entity';
import { AgentTurnResolver } from './resolvers/agent-turn.resolver';
import { AgentTurnGraderService } from './services/agent-turn-grader.service';
@@ -21,8 +21,8 @@ import { AgentTurnGraderService } from './services/agent-turn-grader.service';
TypeOrmModule.forFeature([
AgentTurnEvaluationEntity,
AgentTurnEntity,
AgentEntity,
AgentChatThreadEntity,
AgentEntity,
]),
AiAgentModule,
AiAgentExecutionModule,
+7 -1
View File
@@ -56,11 +56,15 @@ export default defineConfig(({ command }) => {
tsconfigPath: tsConfigPath,
};
const BUNDLED_DEPS = ['@tabler/icons-react'];
return {
resolve: {
alias: {
'@ui/': path.resolve(__dirname, 'src') + '/',
'@assets/': path.resolve(__dirname, 'src/assets') + '/',
'@tabler/icons-react':
'@tabler/icons-react/dist/esm/icons/index.mjs',
},
},
css: {
@@ -122,7 +126,9 @@ export default defineConfig(({ command }) => {
name: 'twenty-ui',
},
rollupOptions: {
external: Object.keys(packageJson.dependencies || {}),
external: Object.keys(packageJson.dependencies || {}).filter(
(dep) => !BUNDLED_DEPS.includes(dep),
),
output: [
{
assetFileNames: 'style.css',