Compare commits

..
13 Commits
Author SHA1 Message Date
Baptiste DevessierandCharles Bochet 37200a1c3b [Workflows] Fix filtering on relative date (#16087)
https://github.com/user-attachments/assets/4079d59e-0550-401f-a29b-b235edd8ed48

Closes https://github.com/twentyhq/twenty/issues/16054
2025-11-26 18:04:52 +01:00
Charles BochetandCharles Bochet bc8c9eabeb Refactor error messages messaging (#16094)
We should try catch locally gmail errors when:
- fetching message list
- fetching messages
- refreshing aliases
- fetching folders
2025-11-26 18:04:43 +01:00
neo773andCharles Bochet c415660640 fix scheduling after folder actions are processed (#16097) 2025-11-26 18:04:35 +01:00
Paul Rastoinandprastoin ad75662919 Non composite and non morph or relation field update fix (#16091) 2025-11-26 12:57:44 +01:00
Paul Rastoinandprastoin aa7c5a778b Refactor upgrade devx to allow configuring workspaces status to pass over (#16066)
We need to be able to create custom workspace application on all
workspaces, even pending and ongoing etc
Right now the upgrade devx only allows and expect active or suspended
workspace to be passed to runOnWorkspace.

Created an intermediate class `WorkspacesMigrationRunner` that expect an
array `WorkspaceStatus` to be fetched for the current command to be run
on
The `ActiveOrSuspendedCommandRunner` statically passes both `SUSPENDED`
and `ACTIVE`, whereas the create workspace custom application passed all
the enum values

Workspace that are not fully init don't have a `workspace_schema` so
they don't have `dataSource`
Made a not very elegant check to see if current workspace we're about to
create dataSource on has one historically
Which means that dataSource is now optional, it had only one impact on
an existing command and the desired devx will become consuming existing
services that do not expect dataSource ( or at least yet )
2025-11-26 12:57:33 +01:00
Charles Bochet 8d43ed4515 Fix message import scheduled 2025-11-25 19:24:00 +01:00
Baptiste DevessierandCharles Bochet 3d1d3d9f04 [Side Panel V2] Bring back old container (#16065)
## Before

<img width="1446" height="780" alt="image"
src="https://github.com/user-attachments/assets/fa25f22d-b979-4a8f-9989-004d07f862d7"
/>

## After

<img width="3456" height="2160" alt="CleanShot 2025-11-25 at 17 35
59@2x"
src="https://github.com/user-attachments/assets/a87880c4-3faa-47c3-9215-34afc36270a3"
/>
2025-11-25 18:16:32 +01:00
EtienneandCharles Bochet b19dc703cc Security - disable gql introspection for non-auth user (#16047)
closes https://github.com/twentyhq/private-issues/issues/351
closes https://github.com/twentyhq/private-issues/issues/350

Before, introspection query works without token. After, fails.

```

query IntrospectionQuery {
  __schema {
    queryType {
      name
    }
    mutationType {
      name
    }
    subscriptionType {
      name
    }
    types {
      ...FullType
    }
    directives {
      name
      description
      locations
      args {
        ...InputValue
      }
    }
  }
}

fragment FullType on __Type {
  kind
  name
  description
  fields(includeDeprecated: true) {
    name
    description
    args {
      ...InputValue
    }
    type {
      ...TypeRef
    }
    isDeprecated
    deprecationReason
  }
  inputFields {
    ...InputValue
  }
  interfaces {
    ...TypeRef
  }
  enumValues(includeDeprecated: true) {
    name
    description
    isDeprecated
    deprecationReason
  }
  possibleTypes {
    ...TypeRef
  }
}

fragment InputValue on __InputValue {
  name
  description
  type {
    ...TypeRef
  }
  defaultValue
}

fragment TypeRef on __Type {
  kind
  name
  ofType {
    kind
    name
    ofType {
      kind
      name
      ofType {
        kind
        name
        ofType {
          kind
          name
          ofType {
            kind
            name
            ofType {
              kind
              name
              ofType {
                kind
                name
              }
            }
          }
        }
      }
    }
  }
}
```
2025-11-25 18:16:07 +01:00
neo773andCharles Bochet 9b668619c5 Update channel sync service to immediately enqueue jobs (#16064) 2025-11-25 18:15:57 +01:00
neo773andCharles Bochet e7c83dc04f move folder cron to message-list-fetch (#16062) 2025-11-25 18:15:49 +01:00
Charles BochetandCharles Bochet 693fe01fa4 Fix upgrade command messaging (#16067) 2025-11-25 18:15:42 +01:00
Charles BochetandCharles Bochet c616713435 Add import scheduled status to messaging sync (#16058)
We have introduced to new syncStage statuses:
`messageChannel.MESSAGES_IMPORT_SCHEDULED` and
`calendarChannel.CALENDAR_EVENTS_IMPORT_SCHEDULED`

We need to make sure all existing workspaces have it
2025-11-25 15:28:48 +01:00
Raphaël Bosiandprastoin 859c948d01 Fix page layout widget deletion (#16035)
With the new side panel, we are able to delete a widget with the side
panel still open. This caused the app to crash because we threw when the
widget id wasn't defined.

This PR fixes this by closing the side panel in the delete action and by
returning null instead of throwing.

## Before



https://github.com/user-attachments/assets/092bfe62-82dc-4d83-9967-1cc753ecf55e



## After


https://github.com/user-attachments/assets/8bed6cc5-961b-4112-8cf5-e587865d14da
2025-11-25 14:08:39 +01:00
1158 changed files with 22862 additions and 43733 deletions
+1 -1
View File
@@ -63,4 +63,4 @@ git push origin your-branch-name
## Reporting Issues
If you face any issues or have suggestions, please feel free to [create an issue on Twenty's GitHub repository](https://github.com/twentyhq/twenty/issues/new). Please provide as much detail as possible.
If you face any issues or have suggestions, please feel free to (create an issue on Twenty's GitHub repository)[https://github.com/twentyhq/twenty/issues/new]. Please provide as much detail as possible.
@@ -1,8 +1,4 @@
name: 'Test Docker Compose'
permissions:
contents: read
on:
pull_request:
+1 -3
View File
@@ -124,9 +124,7 @@ jobs:
exit 0
fi
git commit -m "chore: sync docs artifacts"
git push origin "HEAD:$HEAD_REF"
env:
HEAD_REF: ${{ github.head_ref }}
git push origin HEAD:${{ github.head_ref }}
- name: Check for changes and commit
if: github.event_name != 'pull_request'
+2
View File
@@ -9,6 +9,8 @@
"@linaria/core": "^6.2.0",
"@linaria/react": "^6.2.1",
"@radix-ui/colors": "^3.0.0",
"@sentry/profiling-node": "^9.26.0",
"@sentry/react": "^9.26.0",
"@sniptt/guards": "^0.2.0",
"@tabler/icons-react": "^3.31.0",
"@wyw-in-js/vite": "^0.7.0",
@@ -2056,8 +2056,8 @@ __metadata:
linkType: hard
"glob@npm:^10.2.2":
version: 10.5.0
resolution: "glob@npm:10.5.0"
version: 10.4.5
resolution: "glob@npm:10.4.5"
dependencies:
foreground-child: "npm:^3.1.0"
jackspeak: "npm:^3.1.2"
@@ -2067,7 +2067,7 @@ __metadata:
path-scurry: "npm:^1.11.1"
bin:
glob: dist/esm/bin.mjs
checksum: 10c0/100705eddbde6323e7b35e1d1ac28bcb58322095bd8e63a7d0bef1a2cdafe0d0f7922a981b2b48369a4f8c1b077be5c171804534c3509dfe950dde15fbe6d828
checksum: 10c0/19a9759ea77b8e3ca0a43c2f07ecddc2ad46216b786bb8f993c445aee80d345925a21e5280c7b7c6c59e860a0154b84e4b2b60321fea92cd3c56b4a7489f160e
languageName: node
linkType: hard
@@ -239,15 +239,6 @@ __metadata:
languageName: node
linkType: hard
"@types/node@npm:^24.7.2":
version: 24.10.1
resolution: "@types/node@npm:24.10.1"
dependencies:
undici-types: "npm:~7.16.0"
checksum: 10c0/d6bca7a78f550fbb376f236f92b405d676003a8a09a1b411f55920ef34286ee3ee51f566203920e835478784df52662b5b2af89159d9d319352e9ea21801c002
languageName: node
linkType: hard
"abbrev@npm:^3.0.0":
version: 3.0.1
resolution: "abbrev@npm:3.0.1"
@@ -581,8 +572,8 @@ __metadata:
linkType: hard
"glob@npm:^10.2.2":
version: 10.5.0
resolution: "glob@npm:10.5.0"
version: 10.4.5
resolution: "glob@npm:10.4.5"
dependencies:
foreground-child: "npm:^3.1.0"
jackspeak: "npm:^3.1.2"
@@ -592,7 +583,7 @@ __metadata:
path-scurry: "npm:^1.11.1"
bin:
glob: dist/esm/bin.mjs
checksum: 10c0/100705eddbde6323e7b35e1d1ac28bcb58322095bd8e63a7d0bef1a2cdafe0d0f7922a981b2b48369a4f8c1b077be5c171804534c3509dfe950dde15fbe6d828
checksum: 10c0/19a9759ea77b8e3ca0a43c2f07ecddc2ad46216b786bb8f993c445aee80d345925a21e5280c7b7c6c59e860a0154b84e4b2b60321fea92cd3c56b4a7489f160e
languageName: node
linkType: hard
@@ -916,10 +907,8 @@ __metadata:
version: 0.0.0-use.local
resolution: "rollup-engine@workspace:."
dependencies:
"@types/node": "npm:^24.7.2"
dotenv: "npm:^16.4.5"
tsx: "npm:^4.20.6"
twenty-sdk: "npm:0.0.3"
languageName: unknown
linkType: soft
@@ -1078,20 +1067,6 @@ __metadata:
languageName: node
linkType: hard
"twenty-sdk@npm:0.0.3":
version: 0.0.3
resolution: "twenty-sdk@npm:0.0.3"
checksum: 10c0/0a3c85c27edb22fb50f7eb0da4f9770e85729fce05e9e0118ad0cdfc36e42425c93340a6cd1c276daf30aeeaa612db0cd905831c0a8287a31bff3da5be9b0562
languageName: node
linkType: hard
"undici-types@npm:~7.16.0":
version: 7.16.0
resolution: "undici-types@npm:7.16.0"
checksum: 10c0/3033e2f2b5c9f1504bdc5934646cb54e37ecaca0f9249c983f7b1fc2e87c6d18399ebb05dc7fd5419e02b2e915f734d872a65da2e3eeed1813951c427d33cc9a
languageName: node
linkType: hard
"unique-filename@npm:^4.0.0":
version: 4.0.0
resolution: "unique-filename@npm:4.0.0"
@@ -50,7 +50,7 @@ const returnWorkspaceMemberObjectId = async (): Promise<string> => {
).id;
};
const createUpdatedByFieldMetadata = async (
const createUpdatedByField = async (
sourceObjectId: string,
workspaceMemberObjectId: string,
objectName: string,
@@ -124,7 +124,7 @@ const createUpdatedByFieldMetadata = async (
}
};
const updateUpdatedByFieldValue = async (
const updateUpdatedByField = async (
objectName: string,
workspaceMemberId: string,
recordId: string,
@@ -184,7 +184,7 @@ export const main = async (params: {
const workspaceMemberObjectId: string =
await returnWorkspaceMemberObjectId();
const isFieldCreated: boolean | undefined = await createUpdatedByFieldMetadata(
const isFieldCreated: boolean | undefined = await createUpdatedByField(
objectMetadata.id,
workspaceMemberObjectId,
objectMetadata.namePlural,
@@ -198,7 +198,7 @@ export const main = async (params: {
}
}
const isObjectUpdated: boolean | undefined = await updateUpdatedByFieldValue(
const isObjectUpdated: boolean | undefined = await updateUpdatedByField(
objectMetadata.namePlural,
workspaceMemberId,
recordId,
@@ -57,7 +57,7 @@ sectionInfo: أتمتة العمليات والاندماج مع الأدوات
**المشكلة**: الوصول إلى حد 100 سير عمل متزامن لكل مساحة عمل.
<Warning><Warning><Warning><Warning><Warning><Warning><Warning><Warning><Warning><Warning><Warning><Warning><Warning><Warning><Warning><Warning><Warning><Warning><Warning><Warning><Warning><Warning><Warning><Warning><Warning><Warning><Warning><Warning>لا يمكنك تشغيل أكثر من 100 سير عمل بالتوازي في أي وقت لكل مساحة عمل.</Warning></Warning>
<Warning><Warning><Warning><Warning><Warning><Warning><Warning><Warning><Warning><Warning><Warning><Warning><Warning><Warning><Warning>لا يمكنك تشغيل أكثر من 100 سير عمل بالتوازي في أي وقت لكل مساحة عمل.</Warning></Warning>
**حلول**:
@@ -18,7 +18,7 @@ Absolutamente. Puedes crear un nuevo espacio de trabajo haciendo clic en el men
<Accordion title="I accidentally created multiple workspaces but only need one. What should I do?"><Accordion title="How do I change my workspace appearance and regional settings?">Ve a `Configuración → Experiencia` para personalizar:
<Warning><Warning><Warning><Warning><Warning><Warning><Warning><Warning><Warning><Warning><Warning><Warning><Warning><Warning><Warning><Warning><Warning><Warning><Warning><Warning><Warning><Warning><Warning><Warning><Warning><Warning>No elimines tu cuenta (accesible en Configuración → Configuración de perfil): tu cuenta se comparte entre los diferentes espacios de trabajo.</Warning></Warning>
<Warning><Warning><Warning><Warning><Warning><Warning><Warning><Warning><Warning><Warning><Warning><Warning><Warning><Warning><Warning>No elimines tu cuenta (accesible en Configuración → Configuración de perfil): tu cuenta se comparte entre los diferentes espacios de trabajo.</Warning></Warning>
</Accordion>
<Accordion title="How can I disable my workspace?"><Accordion title="How can I disable my workspace?"><Accordion title="How can I disable my workspace?"><Accordion title="How can I disable my workspace?"><Accordion title="How can I disable my workspace?">Si solo deseas desactivar tu espacio de trabajo (no eliminarlo), ve a `Configuración → Facturación` y haz clic en `Cancelar plan`.</Accordion></Accordion>
@@ -57,7 +57,7 @@ Los formularios están diseñados actualmente solo para disparadores manuales. P
**Problema**: Se alcanza el límite de 100 flujos de trabajo concurrentes por espacio de trabajo.
<Warning><Warning><Warning><Warning><Warning><Warning><Warning><Warning><Warning><Warning><Warning><Warning><Warning><Warning><Warning><Warning><Warning><Warning><Warning><Warning><Warning><Warning><Warning><Warning><Warning><Warning><Warning><Warning><Warning><Warning>No puedes ejecutar más de 100 flujos de trabajo en paralelo en cualquier momento por espacio de trabajo.</Warning></Warning>
<Warning><Warning><Warning><Warning><Warning><Warning><Warning><Warning><Warning><Warning><Warning><Warning><Warning><Warning><Warning>No puedes ejecutar más de 100 flujos de trabajo en paralelo en cualquier momento por espacio de trabajo.</Warning></Warning>
**Soluciones**:
@@ -25,7 +25,7 @@ Vous pouvez **voir, modifier, supprimer des enregistrements** à partir de là a
- Utilisez la **barre de recherche** (appuyez sur `/` pour y accéder instantanément)
- Ouvrir la section **Paramètres**
<Warning><Warning><Warning><Warning><Warning><Warning><Warning><Warning><Warning><Warning><Warning><Warning><Warning><Warning><Warning><Warning><Warning><Warning><Warning><Warning><Warning><Warning><Warning><Warning><Warning><Warning><Warning>Veuillez noter que notre documentation API est accessible sous la section Paramètres et non dans le guide de l'utilisateur.</Warning></Warning>
<Warning><Warning><Warning><Warning><Warning><Warning><Warning><Warning><Warning><Warning><Warning><Warning><Warning><Warning><Warning>Veuillez noter que notre documentation API est accessible sous la section Paramètres et non dans le guide de l'utilisateur.</Warning></Warning>
- </Warning>
Ayez un accès direct à vos **vues favorites**. Les favoris sont uniques pour chaque utilisateur.
@@ -23,14 +23,6 @@ Figma は、デザイナーと開発者の間のコミュニケーションの
このガイドは、Figma を使って共同作業する方法を説明します。
このガイドは、Figma を使って共同作業する方法を説明します。
このガイドは、Figma を使って共同作業する方法を説明します。
このガイドは、Figma を使って共同作業する方法を説明します。
このガイドは、Figma を使って共同作業する方法を説明します。
このガイドは、Figma を使って共同作業する方法を説明します。
このガイドは、Figma を使って共同作業する方法を説明します。
このガイドは、Figma を使って共同作業する方法を説明します。
このガイドは、Figma を使って共同作業する方法を説明します。
このガイドは、Figma を使って共同作業する方法を説明します。
このガイドは、Figma を使って共同作業する方法を説明します。
## アクセス
@@ -92,21 +84,6 @@ Figma プラットフォームの学習に関するより包括的な詳細と
これは推奨拡張機能の一部です。
これは推奨拡張機能の一部です。
これは推奨拡張機能の一部です。
これは推奨拡張機能の一部です。
これは推奨拡張機能の一部です。
これは推奨拡張機能の一部です。
これは推奨拡張機能の一部です。
これは推奨拡張機能の一部です。
これは推奨拡張機能の一部です。
これは推奨拡張機能の一部です。
これは推奨拡張機能の一部です。
これは推奨拡張機能の一部です。
これは推奨拡張機能の一部です。
これは推奨拡張機能の一部です。
これは推奨拡張機能の一部です。
これは推奨拡張機能の一部です。
これは推奨拡張機能の一部です。
これは推奨拡張機能の一部です。
## コラボレーション
@@ -158,7 +158,7 @@ SSLHTTPS)は、特定のブラウザ機能が正しく動作するために
2. **.env ファイルを更新**
.env`ファイルを開き、`SERVER_URL\\\\\\\\\\\\\\\\\\\\\\\\\\\\\`を更新します:
.env`ファイルを開き、`SERVER_URL\\\\\\\\\\\\\\`を更新します:
```ini
SERVER_URL=http(s)://your-domain-or-ip:your-port
@@ -27,10 +27,10 @@ Twentyは、日常をサポートする最適なデータモデルを形成す
例:Stripeではオブジェクト`サブスクリプション`が、Airbnbではオブジェクト`旅行`が、スタートアップアクセラレーターではオブジェクト`バッチ`が必要でしょう。
**2. バリエーションにはフィールドを使い、新しいオブジェクトは使わないでください。**
既存のオブジェクトの特性に過ぎないもの(例:会社の「業種」や機会の「ステータス」)はフィールドにします。 カテゴリ、ラベル、属性にはフィールドが最適です。 カテゴリ、ラベル、属性にはフィールドが最適です。 カテゴリ、ラベル、属性にはフィールドが最適です。 カテゴリ、ラベル、属性にはフィールドが最適です。 カテゴリ、ラベル、属性にはフィールドが最適です。 カテゴリ、ラベル、属性にはフィールドが最適です。 カテゴリ、ラベル、属性にはフィールドが最適です。 カテゴリ、ラベル、属性にはフィールドが最適です。 カテゴリ、ラベル、属性にはフィールドが最適です。 カテゴリ、ラベル、属性にはフィールドが最適です。 カテゴリ、ラベル、属性にはフィールドが最適です。 カテゴリ、ラベル、属性にはフィールドが最適です。 カテゴリ、ラベル、属性にはフィールドが最適です。 カテゴリ、ラベル、属性にはフィールドが最適です。 カテゴリ、ラベル、属性にはフィールドが最適です。 カテゴリ、ラベル、属性にはフィールドが最適です。 カテゴリ、ラベル、属性にはフィールドが最適です。 カテゴリ、ラベル、属性にはフィールドが最適です。 カテゴリ、ラベル、属性にはフィールドが最適です。 カテゴリ、ラベル、属性にはフィールドが最適です。 カテゴリ、ラベル、属性にはフィールドが最適です。 カテゴリ、ラベル、属性にはフィールドが最適です。 カテゴリ、ラベル、属性にはフィールドが最適です。
既存のオブジェクトの特性に過ぎないもの(例:会社の「業種」や機会の「ステータス」)はフィールドにします。 カテゴリ、ラベル、属性にはフィールドが最適です。 カテゴリ、ラベル、属性にはフィールドが最適です。 カテゴリ、ラベル、属性にはフィールドが最適です。 カテゴリ、ラベル、属性にはフィールドが最適です。 カテゴリ、ラベル、属性にはフィールドが最適です。 カテゴリ、ラベル、属性にはフィールドが最適です。 カテゴリ、ラベル、属性にはフィールドが最適です。 カテゴリ、ラベル、属性にはフィールドが最適です。 カテゴリ、ラベル、属性にはフィールドが最適です。 カテゴリ、ラベル、属性にはフィールドが最適です。 カテゴリ、ラベル、属性にはフィールドが最適です。 カテゴリ、ラベル、属性にはフィールドが最適です。 カテゴリ、ラベル、属性にはフィールドが最適です。 カテゴリ、ラベル、属性にはフィールドが最適です。
**3. 単独で存在する場合には新しいオブジェクトを作成してください。**
概念が独自のライフサイクル、プロパティ、または関係を持つ場合、それは通常オブジェクトに値します。 例えば: 例えば: 例えば: 例えば: 例えば: 例えば: 例えば: 例えば: 例えば: 例えば: 例えば: 例えば: 例えば: 例えば: 例えば: 例えば: 例えば: 例えば: 例えば: 例えば: 例えば: 例えば: 例えば: 例えば: 例えば: 例えば: 例えば: 例えば: 例えば:
概念が独自のライフサイクル、プロパティ、または関係を持つ場合、それは通常オブジェクトに値します。 例えば: 例えば: 例えば: 例えば: 例えば: 例えば: 例えば: 例えば: 例えば: 例えば: 例えば: 例えば: 例えば: 例えば:
- **プロジェクト**:独自の期限、所有者、タスクを持つもの
- **サブスクリプション**:会社、製品、請求書を結ぶもの
@@ -50,7 +50,7 @@ CRMには基本的な2つの種類のレコードがあります:
## オブジェクト
オブジェクトは、CRMにおける特定のエンティティを表すデータ構造です(例:人々、会社、機会)。 オブジェクトは標準(ビルトイン)またはカスタム(あなたによって作成)することができます。 オブジェクトは標準(ビルトイン)またはカスタム(あなたによって作成)することができます。 オブジェクトは標準(ビルトイン)またはカスタム(あなたによって作成)することができます。 オブジェクトは標準(ビルトイン)またはカスタム(あなたによって作成)することができます。 オブジェクトは標準(ビルトイン)またはカスタム(あなたによって作成)することができます。 オブジェクトは標準(ビルトイン)またはカスタム(あなたによって作成)することができます。 オブジェクトは標準(ビルトイン)またはカスタム(あなたによって作成)することができます。 オブジェクトは標準(ビルトイン)またはカスタム(あなたによって作成)することができます。 オブジェクトは標準(ビルトイン)またはカスタム(あなたによって作成)することができます。 オブジェクトは標準(ビルトイン)またはカスタム(あなたによって作成)することができます。 オブジェクトは標準(ビルトイン)またはカスタム(あなたによって作成)することができます。 オブジェクトは標準(ビルトイン)またはカスタム(あなたによって作成)することができます。 オブジェクトは標準(ビルトイン)またはカスタム(あなたによって作成)することができます。 オブジェクトは標準(ビルトイン)またはカスタム(あなたによって作成)することができます。 オブジェクトは標準(ビルトイン)またはカスタム(あなたによって作成)することができます。 オブジェクトは標準(ビルトイン)またはカスタム(あなたによって作成)することができます。 オブジェクトは標準(ビルトイン)またはカスタム(あなたによって作成)することができます。
オブジェクトは、CRMにおける特定のエンティティを表すデータ構造です(例:人々、会社、機会)。 オブジェクトは標準(ビルトイン)またはカスタム(あなたによって作成)することができます。 オブジェクトは標準(ビルトイン)またはカスタム(あなたによって作成)することができます。 オブジェクトは標準(ビルトイン)またはカスタム(あなたによって作成)することができます。 オブジェクトは標準(ビルトイン)またはカスタム(あなたによって作成)することができます。 オブジェクトは標準(ビルトイン)またはカスタム(あなたによって作成)することができます。 オブジェクトは標準(ビルトイン)またはカスタム(あなたによって作成)することができます。 オブジェクトは標準(ビルトイン)またはカスタム(あなたによって作成)することができます。 オブジェクトは標準(ビルトイン)またはカスタム(あなたによって作成)することができます。 オブジェクトは標準(ビルトイン)またはカスタム(あなたによって作成)することができます。 オブジェクトは標準(ビルトイン)またはカスタム(あなたによって作成)することができます。 オブジェクトは標準(ビルトイン)またはカスタム(あなたによって作成)することができます。 オブジェクトは標準(ビルトイン)またはカスタム(あなたによって作成)することができます。 オブジェクトは標準(ビルトイン)またはカスタム(あなたによって作成)することができます。 オブジェクトは標準(ビルトイン)またはカスタム(あなたによって作成)することができます。
## 商談
@@ -17,7 +17,7 @@ image: /images/user-guide/notes/notes_header.png
### Coolify
使用 Coolify 部署 Twenty 到伺服器。 (官方 Coolify 映像即將推出) (官方 Coolify 映像即將推出) (官方 Coolify 映像即將推出) (官方 Coolify 映像即將推出) (官方 Coolify 映像即將推出) (官方 Coolify 映像即將推出) (官方 Coolify 映像即將推出) (官方 Coolify 映像即將推出) (官方 Coolify 映像即將推出) (官方 Coolify 映像即將推出) (官方 Coolify 映像即將推出) (官方 Coolify 映像即將推出) (官方 Coolify 映像即將推出) (官方 Coolify 映像即將推出) (官方 Coolify 映像即將推出)
使用 Coolify 部署 Twenty 到伺服器。 (官方 Coolify 映像即將推出) (官方 Coolify 映像即將推出) (官方 Coolify 映像即將推出) (官方 Coolify 映像即將推出) (官方 Coolify 映像即將推出) (官方 Coolify 映像即將推出) (官方 Coolify 映像即將推出) (官方 Coolify 映像即將推出) (官方 Coolify 映像即將推出) (官方 Coolify 映像即將推出) (官方 Coolify 映像即將推出) (官方 Coolify 映像即將推出) (官方 Coolify 映像即將推出) (官方 Coolify 映像即將推出)
[Coolify 文件](https://coolify.io/docs/get-started/introduction)
@@ -45,9 +45,8 @@ sectionInfo: 配置您的Twenty工作空间设置和偏好
刪除您的帳號將永久移除您對所有工作空間的訪問。
刪除您的帳號將永久移除您對所有工作空間的訪問。 此操作無法撤銷,您將失去所有工作空間權限,如您只想退出特定的團隊,應考慮退出個別的工作空間。 刪除您的帳號將永久移除您對所有工作空間的訪問。
刪除您的帳號將永久移除您對所有工作空間的訪問。 此操作無法撤銷,您將失去所有工作空間權限,如您只想退出特定的團隊,應考慮退出個別的工作空間。
</Warning> 刪除您的帳號將永久移除您對所有工作空間的訪問。
</Warning> 刪除您的帳號將永久移除您對所有工作空間的訪問。
刪除您的帳號將永久移除您對所有工作空間的訪問。 此操作無法撤銷,您將失去所有工作空間權限,如您只想退出特定的團隊,應考慮退出個別的工作空間。
</Warning>
要删除您的帐户:
-1
View File
@@ -55,7 +55,6 @@
"@react-email/components": "^0.5.3",
"@react-pdf/renderer": "^4.1.6",
"@scalar/api-reference-react": "^0.4.36",
"@sentry/react": "^10.27.0",
"@tiptap/core": "^3.4.2",
"@tiptap/extension-bold": "^3.4.2",
"@tiptap/extension-document": "^3.4.2",
File diff suppressed because one or more lines are too long
+71 -60
View File
@@ -53,7 +53,6 @@ export type Agent = {
applicationId?: Maybe<Scalars['UUID']>;
createdAt: Scalars['DateTime'];
description?: Maybe<Scalars['String']>;
evaluationInputs: Array<Scalars['String']>;
icon?: Maybe<Scalars['String']>;
id: Scalars['UUID'];
isCustom: Scalars['Boolean'];
@@ -68,32 +67,17 @@ export type Agent = {
updatedAt: Scalars['DateTime'];
};
export type AgentChatThread = {
__typename?: 'AgentChatThread';
export type AgentChatMessage = {
__typename?: 'AgentChatMessage';
createdAt: Scalars['DateTime'];
id: Scalars['UUID'];
title?: Maybe<Scalars['String']>;
updatedAt: Scalars['DateTime'];
};
export type AgentIdInput = {
/** The id of the agent. */
id: Scalars['UUID'];
};
export type AgentMessage = {
__typename?: 'AgentMessage';
agentId?: Maybe<Scalars['UUID']>;
createdAt: Scalars['DateTime'];
id: Scalars['UUID'];
parts: Array<AgentMessagePart>;
parts: Array<AgentChatMessagePart>;
role: Scalars['String'];
threadId: Scalars['UUID'];
turnId: Scalars['UUID'];
};
export type AgentMessagePart = {
__typename?: 'AgentMessagePart';
export type AgentChatMessagePart = {
__typename?: 'AgentChatMessagePart';
createdAt: Scalars['DateTime'];
errorDetails?: Maybe<Scalars['JSON']>;
errorMessage?: Maybe<Scalars['String']>;
@@ -121,23 +105,24 @@ export type AgentMessagePart = {
type: Scalars['String'];
};
export type AgentTurn = {
__typename?: 'AgentTurn';
agentId?: Maybe<Scalars['UUID']>;
export type AgentChatThread = {
__typename?: 'AgentChatThread';
createdAt: Scalars['DateTime'];
evaluations: Array<AgentTurnEvaluation>;
id: Scalars['UUID'];
messages: Array<AgentMessage>;
threadId: Scalars['UUID'];
title?: Maybe<Scalars['String']>;
updatedAt: Scalars['DateTime'];
};
export type AgentTurnEvaluation = {
__typename?: 'AgentTurnEvaluation';
comment?: Maybe<Scalars['String']>;
createdAt: Scalars['DateTime'];
export type AgentHandoff = {
__typename?: 'AgentHandoff';
description?: Maybe<Scalars['String']>;
id: Scalars['UUID'];
toAgent: Agent;
};
export type AgentIdInput = {
/** The id of the agent. */
id: Scalars['UUID'];
score: Scalars['Int'];
turnId: Scalars['UUID'];
};
export type AggregateChartConfiguration = {
@@ -343,7 +328,6 @@ export type BarChartConfiguration = {
color?: Maybe<Scalars['String']>;
description?: Maybe<Scalars['String']>;
displayDataLabel?: Maybe<Scalars['Boolean']>;
displayLegend?: Maybe<Scalars['Boolean']>;
filter?: Maybe<Scalars['JSON']>;
firstDayOfTheWeek?: Maybe<Scalars['Int']>;
graphType: GraphType;
@@ -771,9 +755,14 @@ export type CoreViewSort = {
workspaceId: Scalars['UUID'];
};
export type CreateAgentHandoffInput = {
description?: InputMaybe<Scalars['String']>;
fromAgentId: Scalars['UUID'];
toAgentId: Scalars['UUID'];
};
export type CreateAgentInput = {
description?: InputMaybe<Scalars['String']>;
evaluationInputs?: InputMaybe<Array<Scalars['String']>>;
icon?: InputMaybe<Scalars['String']>;
label: Scalars['String'];
modelConfiguration?: InputMaybe<Scalars['JSON']>;
@@ -1269,7 +1258,6 @@ export enum FeatureFlagKey {
IS_IMAP_SMTP_CALDAV_ENABLED = 'IS_IMAP_SMTP_CALDAV_ENABLED',
IS_JSON_FILTER_ENABLED = 'IS_JSON_FILTER_ENABLED',
IS_MESSAGE_FOLDER_CONTROL_ENABLED = 'IS_MESSAGE_FOLDER_CONTROL_ENABLED',
IS_NULL_EQUIVALENCE_ENABLED = 'IS_NULL_EQUIVALENCE_ENABLED',
IS_PAGE_LAYOUT_ENABLED = 'IS_PAGE_LAYOUT_ENABLED',
IS_POSTGRESQL_INTEGRATION_ENABLED = 'IS_POSTGRESQL_INTEGRATION_ENABLED',
IS_PUBLIC_DOMAIN_ENABLED = 'IS_PUBLIC_DOMAIN_ENABLED',
@@ -1671,7 +1659,6 @@ export type LineChartConfiguration = {
color?: Maybe<Scalars['String']>;
description?: Maybe<Scalars['String']>;
displayDataLabel?: Maybe<Scalars['Boolean']>;
displayLegend?: Maybe<Scalars['Boolean']>;
filter?: Maybe<Scalars['JSON']>;
firstDayOfTheWeek?: Maybe<Scalars['Int']>;
graphType: GraphType;
@@ -1742,8 +1729,10 @@ export type Mutation = {
checkPublicDomainValidRecords?: Maybe<DomainValidRecords>;
checkoutSession: BillingSessionOutput;
computeStepOutputSchema: Scalars['JSON'];
createAgentHandoff: Scalars['Boolean'];
createApiKey: ApiKey;
createApprovedAccessDomain: ApprovedAccessDomain;
createChatThread: AgentChatThread;
createCoreView: CoreView;
createCoreViewField: CoreViewField;
createCoreViewFilter: CoreViewFilter;
@@ -1837,6 +1826,7 @@ export type Mutation = {
initiateOTPProvisioning: InitiateTwoFactorAuthenticationProvisioningOutput;
initiateOTPProvisioningForAuthenticatedUser: InitiateTwoFactorAuthenticationProvisioningOutput;
publishServerlessFunction: ServerlessFunction;
removeAgentHandoff: Scalars['Boolean'];
removeRoleFromAgent: Scalars['Boolean'];
renewToken: AuthTokens;
resendEmailVerificationToken: ResendEmailVerificationTokenOutput;
@@ -1900,7 +1890,6 @@ export type Mutation = {
uploadImage: SignedFile;
uploadProfilePicture: SignedFile;
uploadWorkspaceLogo: SignedFile;
uploadWorkspaceMemberProfilePicture: SignedFile;
upsertFieldPermissions: Array<FieldPermission>;
upsertObjectPermissions: Array<ObjectPermission>;
upsertPermissionFlags: Array<PermissionFlag>;
@@ -1960,6 +1949,11 @@ export type MutationComputeStepOutputSchemaArgs = {
};
export type MutationCreateAgentHandoffArgs = {
input: CreateAgentHandoffInput;
};
export type MutationCreateApiKeyArgs = {
input: CreateApiKeyInput;
};
@@ -2415,6 +2409,11 @@ export type MutationPublishServerlessFunctionArgs = {
};
export type MutationRemoveAgentHandoffArgs = {
input: RemoveAgentHandoffInput;
};
export type MutationRemoveRoleFromAgentArgs = {
agentId: Scalars['UUID'];
};
@@ -2747,11 +2746,6 @@ export type MutationUploadWorkspaceLogoArgs = {
};
export type MutationUploadWorkspaceMemberProfilePictureArgs = {
file: Scalars['Upload'];
};
export type MutationUpsertFieldPermissionsArgs = {
upsertFieldPermissionsInput: UpsertFieldPermissionsInput;
};
@@ -2921,7 +2915,7 @@ export type ObjectRecordFilterInput = {
updatedAt?: InputMaybe<DateTimeFilter>;
};
/** Date granularity options (e.g. DAY, MONTH, QUARTER, YEAR, WEEK, DAY_OF_THE_WEEK, MONTH_OF_THE_YEAR, QUARTER_OF_THE_YEAR) */
/** Date granularity options (e.g. DAY, MONTH, QUARTER, YEAR, DAY_OF_THE_WEEK, MONTH_OF_THE_YEAR, QUARTER_OF_THE_YEAR) */
export enum ObjectRecordGroupByDateGranularity {
DAY = 'DAY',
DAY_OF_THE_WEEK = 'DAY_OF_THE_WEEK',
@@ -2930,7 +2924,6 @@ export enum ObjectRecordGroupByDateGranularity {
NONE = 'NONE',
QUARTER = 'QUARTER',
QUARTER_OF_THE_YEAR = 'QUARTER_OF_THE_YEAR',
WEEK = 'WEEK',
YEAR = 'YEAR'
}
@@ -3048,7 +3041,6 @@ export enum PermissionFlagType {
DATA_MODEL = 'DATA_MODEL',
DOWNLOAD_FILE = 'DOWNLOAD_FILE',
EXPORT_CSV = 'EXPORT_CSV',
HTTP_REQUEST_TOOL = 'HTTP_REQUEST_TOOL',
IMPERSONATE = 'IMPERSONATE',
IMPORT_CSV = 'IMPORT_CSV',
LAYOUTS = 'LAYOUTS',
@@ -3072,14 +3064,12 @@ export type PieChartConfiguration = {
dateGranularity?: Maybe<ObjectRecordGroupByDateGranularity>;
description?: Maybe<Scalars['String']>;
displayDataLabel?: Maybe<Scalars['Boolean']>;
displayLegend?: Maybe<Scalars['Boolean']>;
filter?: Maybe<Scalars['JSON']>;
firstDayOfTheWeek?: Maybe<Scalars['Int']>;
graphType: GraphType;
groupByFieldMetadataId: Scalars['UUID'];
groupBySubFieldName?: Maybe<Scalars['String']>;
orderBy?: Maybe<GraphOrderBy>;
showCenterMetric?: Maybe<Scalars['Boolean']>;
timezone?: Maybe<Scalars['String']>;
};
@@ -3141,12 +3131,17 @@ export type Query = {
apiKey?: Maybe<ApiKey>;
apiKeys: Array<ApiKey>;
billingPortalSession: BillingSessionOutput;
chatMessages: Array<AgentChatMessage>;
chatThread: AgentChatThread;
chatThreads: Array<AgentChatThread>;
checkUserExists: CheckUserExistOutput;
checkWorkspaceInviteHashIsValid: WorkspaceInviteHashValidOutput;
currentUser: User;
currentWorkspace: Workspace;
field: Field;
fields: FieldConnection;
findAgentHandoffTargets: Array<Agent>;
findAgentHandoffs: Array<AgentHandoff>;
findManyAgents: Array<Agent>;
findManyApplications: Array<Application>;
findManyCronTriggers: Array<CronTrigger>;
@@ -3227,6 +3222,16 @@ export type QueryBillingPortalSessionArgs = {
};
export type QueryChatMessagesArgs = {
threadId: Scalars['UUID'];
};
export type QueryChatThreadArgs = {
id: Scalars['UUID'];
};
export type QueryCheckUserExistsArgs = {
captchaToken?: InputMaybe<Scalars['String']>;
email: Scalars['String'];
@@ -3238,6 +3243,16 @@ export type QueryCheckWorkspaceInviteHashIsValidArgs = {
};
export type QueryFindAgentHandoffTargetsArgs = {
input: AgentIdInput;
};
export type QueryFindAgentHandoffsArgs = {
input: AgentIdInput;
};
export type QueryFindOneAgentArgs = {
input: AgentIdInput;
};
@@ -3587,6 +3602,11 @@ export enum RemoteTableStatus {
SYNCED = 'SYNCED'
}
export type RemoveAgentHandoffInput = {
fromAgentId: Scalars['UUID'];
toAgentId: Scalars['UUID'];
};
export type ResendEmailVerificationTokenOutput = {
__typename?: 'ResendEmailVerificationTokenOutput';
success: Scalars['Boolean'];
@@ -4012,7 +4032,6 @@ export type UuidFilterComparison = {
export type UpdateAgentInput = {
description?: InputMaybe<Scalars['String']>;
evaluationInputs?: InputMaybe<Array<Scalars['String']>>;
icon?: InputMaybe<Scalars['String']>;
id: Scalars['UUID'];
label?: InputMaybe<Scalars['String']>;
@@ -4064,7 +4083,6 @@ export type UpdateFieldInput = {
isUIReadOnly?: InputMaybe<Scalars['Boolean']>;
isUnique?: InputMaybe<Scalars['Boolean']>;
label?: InputMaybe<Scalars['String']>;
morphRelationsUpdatePayload?: InputMaybe<Array<Scalars['JSON']>>;
name?: InputMaybe<Scalars['String']>;
options?: InputMaybe<Scalars['JSON']>;
settings?: InputMaybe<Scalars['JSON']>;
@@ -4305,7 +4323,6 @@ export type UpdateWorkspaceInput = {
defaultRoleId?: InputMaybe<Scalars['UUID']>;
displayName?: InputMaybe<Scalars['String']>;
editableProfileFields?: InputMaybe<Array<Scalars['String']>>;
fastModel?: InputMaybe<Scalars['String']>;
inviteHash?: InputMaybe<Scalars['String']>;
isGoogleAuthBypassEnabled?: InputMaybe<Scalars['Boolean']>;
isGoogleAuthEnabled?: InputMaybe<Scalars['Boolean']>;
@@ -4316,7 +4333,7 @@ export type UpdateWorkspaceInput = {
isPublicInviteLinkEnabled?: InputMaybe<Scalars['Boolean']>;
isTwoFactorAuthenticationEnforced?: InputMaybe<Scalars['Boolean']>;
logo?: InputMaybe<Scalars['String']>;
smartModel?: InputMaybe<Scalars['String']>;
routerModel?: InputMaybe<Scalars['String']>;
subdomain?: InputMaybe<Scalars['String']>;
trashRetentionDays?: InputMaybe<Scalars['Float']>;
};
@@ -4643,7 +4660,6 @@ export type Workspace = {
deletedAt?: Maybe<Scalars['DateTime']>;
displayName?: Maybe<Scalars['String']>;
editableProfileFields?: Maybe<Array<Scalars['String']>>;
fastModel: Scalars['String'];
featureFlags?: Maybe<Array<FeatureFlagDto>>;
hasValidEnterpriseKey: Scalars['Boolean'];
id: Scalars['UUID'];
@@ -4660,7 +4676,6 @@ export type Workspace = {
logo?: Maybe<Scalars['String']>;
metadataVersion: Scalars['Float'];
routerModel: Scalars['String'];
smartModel: Scalars['String'];
subdomain: Scalars['String'];
trashRetentionDays: Scalars['Float'];
updatedAt: Scalars['DateTime'];
@@ -4788,7 +4803,7 @@ export type SearchQueryVariables = Exact<{
export type SearchQuery = { __typename?: 'Query', search: { __typename?: 'SearchResultConnection', edges: Array<{ __typename?: 'SearchResultEdge', cursor: string, node: { __typename?: 'SearchRecord', recordId: any, objectNameSingular: string, label: string, imageUrl?: string | null, tsRankCD: number, tsRank: number } }>, pageInfo: { __typename?: 'SearchResultPageInfo', hasNextPage: boolean, endCursor?: string | null } } };
export type PageLayoutWidgetFragmentFragment = { __typename?: 'PageLayoutWidget', id: any, title: string, type: WidgetType, objectMetadataId?: any | null, createdAt: string, updatedAt: string, deletedAt?: string | null, pageLayoutTabId: any, gridPosition: { __typename?: 'GridPosition', column: number, columnSpan: number, row: number, rowSpan: number }, configuration?: { __typename?: 'AggregateChartConfiguration', graphType: GraphType, aggregateFieldMetadataId: any, aggregateOperation: AggregateOperations, label?: string | null, displayDataLabel?: boolean | null, format?: string | null, description?: string | null, filter?: any | null, timezone?: string | null, firstDayOfTheWeek?: number | null } | { __typename?: 'BarChartConfiguration', graphType: GraphType, aggregateFieldMetadataId: any, aggregateOperation: AggregateOperations, primaryAxisGroupByFieldMetadataId: any, primaryAxisGroupBySubFieldName?: string | null, primaryAxisDateGranularity?: ObjectRecordGroupByDateGranularity | null, primaryAxisOrderBy?: GraphOrderBy | null, secondaryAxisGroupByFieldMetadataId?: any | null, secondaryAxisGroupBySubFieldName?: string | null, secondaryAxisGroupByDateGranularity?: ObjectRecordGroupByDateGranularity | null, secondaryAxisOrderBy?: GraphOrderBy | null, omitNullValues?: boolean | null, axisNameDisplay?: AxisNameDisplay | null, displayDataLabel?: boolean | null, displayLegend?: boolean | null, rangeMin?: number | null, rangeMax?: number | null, color?: string | null, description?: string | null, filter?: any | null, groupMode?: BarChartGroupMode | null, timezone?: string | null, firstDayOfTheWeek?: number | null } | { __typename?: 'GaugeChartConfiguration', graphType: GraphType, aggregateFieldMetadataId: any, aggregateOperation: AggregateOperations, displayDataLabel?: boolean | null, color?: string | null, description?: string | null, filter?: any | null, timezone?: string | null, firstDayOfTheWeek?: number | null } | { __typename?: 'IframeConfiguration', url?: string | null } | { __typename?: 'LineChartConfiguration', graphType: GraphType, aggregateFieldMetadataId: any, aggregateOperation: AggregateOperations, primaryAxisGroupByFieldMetadataId: any, primaryAxisGroupBySubFieldName?: string | null, primaryAxisDateGranularity?: ObjectRecordGroupByDateGranularity | null, primaryAxisOrderBy?: GraphOrderBy | null, secondaryAxisGroupByFieldMetadataId?: any | null, secondaryAxisGroupBySubFieldName?: string | null, secondaryAxisGroupByDateGranularity?: ObjectRecordGroupByDateGranularity | null, secondaryAxisOrderBy?: GraphOrderBy | null, omitNullValues?: boolean | null, axisNameDisplay?: AxisNameDisplay | null, displayDataLabel?: boolean | null, displayLegend?: boolean | null, rangeMin?: number | null, rangeMax?: number | null, color?: string | null, description?: string | null, filter?: any | null, isStacked?: boolean | null, timezone?: string | null, firstDayOfTheWeek?: number | null } | { __typename?: 'PieChartConfiguration', graphType: GraphType, groupByFieldMetadataId: any, aggregateFieldMetadataId: any, aggregateOperation: AggregateOperations, groupBySubFieldName?: string | null, dateGranularity?: ObjectRecordGroupByDateGranularity | null, orderBy?: GraphOrderBy | null, displayDataLabel?: boolean | null, showCenterMetric?: boolean | null, displayLegend?: boolean | null, color?: string | null, description?: string | null, filter?: any | null, timezone?: string | null, firstDayOfTheWeek?: number | null } | null };
export type PageLayoutWidgetFragmentFragment = { __typename?: 'PageLayoutWidget', id: any, title: string, type: WidgetType, objectMetadataId?: any | null, createdAt: string, updatedAt: string, deletedAt?: string | null, pageLayoutTabId: any, gridPosition: { __typename?: 'GridPosition', column: number, columnSpan: number, row: number, rowSpan: number }, configuration?: { __typename?: 'AggregateChartConfiguration', graphType: GraphType, aggregateFieldMetadataId: any, aggregateOperation: AggregateOperations, label?: string | null, displayDataLabel?: boolean | null, format?: string | null, description?: string | null, filter?: any | null, timezone?: string | null, firstDayOfTheWeek?: number | null } | { __typename?: 'BarChartConfiguration', graphType: GraphType, aggregateFieldMetadataId: any, aggregateOperation: AggregateOperations, primaryAxisGroupByFieldMetadataId: any, primaryAxisGroupBySubFieldName?: string | null, primaryAxisDateGranularity?: ObjectRecordGroupByDateGranularity | null, primaryAxisOrderBy?: GraphOrderBy | null, secondaryAxisGroupByFieldMetadataId?: any | null, secondaryAxisGroupBySubFieldName?: string | null, secondaryAxisGroupByDateGranularity?: ObjectRecordGroupByDateGranularity | null, secondaryAxisOrderBy?: GraphOrderBy | null, omitNullValues?: boolean | null, axisNameDisplay?: AxisNameDisplay | null, displayDataLabel?: boolean | null, rangeMin?: number | null, rangeMax?: number | null, color?: string | null, description?: string | null, filter?: any | null, groupMode?: BarChartGroupMode | null, timezone?: string | null, firstDayOfTheWeek?: number | null } | { __typename?: 'GaugeChartConfiguration', graphType: GraphType, aggregateFieldMetadataId: any, aggregateOperation: AggregateOperations, displayDataLabel?: boolean | null, color?: string | null, description?: string | null, filter?: any | null, timezone?: string | null, firstDayOfTheWeek?: number | null } | { __typename?: 'IframeConfiguration', url?: string | null } | { __typename?: 'LineChartConfiguration', graphType: GraphType, aggregateFieldMetadataId: any, aggregateOperation: AggregateOperations, primaryAxisGroupByFieldMetadataId: any, primaryAxisGroupBySubFieldName?: string | null, primaryAxisDateGranularity?: ObjectRecordGroupByDateGranularity | null, primaryAxisOrderBy?: GraphOrderBy | null, secondaryAxisGroupByFieldMetadataId?: any | null, secondaryAxisGroupBySubFieldName?: string | null, secondaryAxisGroupByDateGranularity?: ObjectRecordGroupByDateGranularity | null, secondaryAxisOrderBy?: GraphOrderBy | null, omitNullValues?: boolean | null, axisNameDisplay?: AxisNameDisplay | null, displayDataLabel?: boolean | null, rangeMin?: number | null, rangeMax?: number | null, color?: string | null, description?: string | null, filter?: any | null, isStacked?: boolean | null, timezone?: string | null, firstDayOfTheWeek?: number | null } | { __typename?: 'PieChartConfiguration', graphType: GraphType, groupByFieldMetadataId: any, aggregateFieldMetadataId: any, aggregateOperation: AggregateOperations, groupBySubFieldName?: string | null, dateGranularity?: ObjectRecordGroupByDateGranularity | null, orderBy?: GraphOrderBy | null, displayDataLabel?: boolean | null, color?: string | null, description?: string | null, filter?: any | null, timezone?: string | null, firstDayOfTheWeek?: number | null } | null };
export type UpdatePageLayoutWithTabsAndWidgetsMutationVariables = Exact<{
id: Scalars['String'];
@@ -4796,7 +4811,7 @@ export type UpdatePageLayoutWithTabsAndWidgetsMutationVariables = Exact<{
}>;
export type UpdatePageLayoutWithTabsAndWidgetsMutation = { __typename?: 'Mutation', updatePageLayoutWithTabsAndWidgets: { __typename?: 'PageLayout', id: any, name: string, type: PageLayoutType, objectMetadataId?: any | null, createdAt: string, updatedAt: string, deletedAt?: string | null, tabs?: Array<{ __typename?: 'PageLayoutTab', id: any, title: string, position: number, pageLayoutId: any, createdAt: string, updatedAt: string, widgets?: Array<{ __typename?: 'PageLayoutWidget', id: any, title: string, type: WidgetType, objectMetadataId?: any | null, createdAt: string, updatedAt: string, deletedAt?: string | null, pageLayoutTabId: any, gridPosition: { __typename?: 'GridPosition', column: number, columnSpan: number, row: number, rowSpan: number }, configuration?: { __typename?: 'AggregateChartConfiguration', graphType: GraphType, aggregateFieldMetadataId: any, aggregateOperation: AggregateOperations, label?: string | null, displayDataLabel?: boolean | null, format?: string | null, description?: string | null, filter?: any | null, timezone?: string | null, firstDayOfTheWeek?: number | null } | { __typename?: 'BarChartConfiguration', graphType: GraphType, aggregateFieldMetadataId: any, aggregateOperation: AggregateOperations, primaryAxisGroupByFieldMetadataId: any, primaryAxisGroupBySubFieldName?: string | null, primaryAxisDateGranularity?: ObjectRecordGroupByDateGranularity | null, primaryAxisOrderBy?: GraphOrderBy | null, secondaryAxisGroupByFieldMetadataId?: any | null, secondaryAxisGroupBySubFieldName?: string | null, secondaryAxisGroupByDateGranularity?: ObjectRecordGroupByDateGranularity | null, secondaryAxisOrderBy?: GraphOrderBy | null, omitNullValues?: boolean | null, axisNameDisplay?: AxisNameDisplay | null, displayDataLabel?: boolean | null, displayLegend?: boolean | null, rangeMin?: number | null, rangeMax?: number | null, color?: string | null, description?: string | null, filter?: any | null, groupMode?: BarChartGroupMode | null, timezone?: string | null, firstDayOfTheWeek?: number | null } | { __typename?: 'GaugeChartConfiguration', graphType: GraphType, aggregateFieldMetadataId: any, aggregateOperation: AggregateOperations, displayDataLabel?: boolean | null, color?: string | null, description?: string | null, filter?: any | null, timezone?: string | null, firstDayOfTheWeek?: number | null } | { __typename?: 'IframeConfiguration', url?: string | null } | { __typename?: 'LineChartConfiguration', graphType: GraphType, aggregateFieldMetadataId: any, aggregateOperation: AggregateOperations, primaryAxisGroupByFieldMetadataId: any, primaryAxisGroupBySubFieldName?: string | null, primaryAxisDateGranularity?: ObjectRecordGroupByDateGranularity | null, primaryAxisOrderBy?: GraphOrderBy | null, secondaryAxisGroupByFieldMetadataId?: any | null, secondaryAxisGroupBySubFieldName?: string | null, secondaryAxisGroupByDateGranularity?: ObjectRecordGroupByDateGranularity | null, secondaryAxisOrderBy?: GraphOrderBy | null, omitNullValues?: boolean | null, axisNameDisplay?: AxisNameDisplay | null, displayDataLabel?: boolean | null, displayLegend?: boolean | null, rangeMin?: number | null, rangeMax?: number | null, color?: string | null, description?: string | null, filter?: any | null, isStacked?: boolean | null, timezone?: string | null, firstDayOfTheWeek?: number | null } | { __typename?: 'PieChartConfiguration', graphType: GraphType, groupByFieldMetadataId: any, aggregateFieldMetadataId: any, aggregateOperation: AggregateOperations, groupBySubFieldName?: string | null, dateGranularity?: ObjectRecordGroupByDateGranularity | null, orderBy?: GraphOrderBy | null, displayDataLabel?: boolean | null, showCenterMetric?: boolean | null, displayLegend?: boolean | null, color?: string | null, description?: string | null, filter?: any | null, timezone?: string | null, firstDayOfTheWeek?: number | null } | null }> | null }> | null } };
export type UpdatePageLayoutWithTabsAndWidgetsMutation = { __typename?: 'Mutation', updatePageLayoutWithTabsAndWidgets: { __typename?: 'PageLayout', id: any, name: string, type: PageLayoutType, objectMetadataId?: any | null, createdAt: string, updatedAt: string, deletedAt?: string | null, tabs?: Array<{ __typename?: 'PageLayoutTab', id: any, title: string, position: number, pageLayoutId: any, createdAt: string, updatedAt: string, widgets?: Array<{ __typename?: 'PageLayoutWidget', id: any, title: string, type: WidgetType, objectMetadataId?: any | null, createdAt: string, updatedAt: string, deletedAt?: string | null, pageLayoutTabId: any, gridPosition: { __typename?: 'GridPosition', column: number, columnSpan: number, row: number, rowSpan: number }, configuration?: { __typename?: 'AggregateChartConfiguration', graphType: GraphType, aggregateFieldMetadataId: any, aggregateOperation: AggregateOperations, label?: string | null, displayDataLabel?: boolean | null, format?: string | null, description?: string | null, filter?: any | null, timezone?: string | null, firstDayOfTheWeek?: number | null } | { __typename?: 'BarChartConfiguration', graphType: GraphType, aggregateFieldMetadataId: any, aggregateOperation: AggregateOperations, primaryAxisGroupByFieldMetadataId: any, primaryAxisGroupBySubFieldName?: string | null, primaryAxisDateGranularity?: ObjectRecordGroupByDateGranularity | null, primaryAxisOrderBy?: GraphOrderBy | null, secondaryAxisGroupByFieldMetadataId?: any | null, secondaryAxisGroupBySubFieldName?: string | null, secondaryAxisGroupByDateGranularity?: ObjectRecordGroupByDateGranularity | null, secondaryAxisOrderBy?: GraphOrderBy | null, omitNullValues?: boolean | null, axisNameDisplay?: AxisNameDisplay | null, displayDataLabel?: boolean | null, rangeMin?: number | null, rangeMax?: number | null, color?: string | null, description?: string | null, filter?: any | null, groupMode?: BarChartGroupMode | null, timezone?: string | null, firstDayOfTheWeek?: number | null } | { __typename?: 'GaugeChartConfiguration', graphType: GraphType, aggregateFieldMetadataId: any, aggregateOperation: AggregateOperations, displayDataLabel?: boolean | null, color?: string | null, description?: string | null, filter?: any | null, timezone?: string | null, firstDayOfTheWeek?: number | null } | { __typename?: 'IframeConfiguration', url?: string | null } | { __typename?: 'LineChartConfiguration', graphType: GraphType, aggregateFieldMetadataId: any, aggregateOperation: AggregateOperations, primaryAxisGroupByFieldMetadataId: any, primaryAxisGroupBySubFieldName?: string | null, primaryAxisDateGranularity?: ObjectRecordGroupByDateGranularity | null, primaryAxisOrderBy?: GraphOrderBy | null, secondaryAxisGroupByFieldMetadataId?: any | null, secondaryAxisGroupBySubFieldName?: string | null, secondaryAxisGroupByDateGranularity?: ObjectRecordGroupByDateGranularity | null, secondaryAxisOrderBy?: GraphOrderBy | null, omitNullValues?: boolean | null, axisNameDisplay?: AxisNameDisplay | null, displayDataLabel?: boolean | null, rangeMin?: number | null, rangeMax?: number | null, color?: string | null, description?: string | null, filter?: any | null, isStacked?: boolean | null, timezone?: string | null, firstDayOfTheWeek?: number | null } | { __typename?: 'PieChartConfiguration', graphType: GraphType, groupByFieldMetadataId: any, aggregateFieldMetadataId: any, aggregateOperation: AggregateOperations, groupBySubFieldName?: string | null, dateGranularity?: ObjectRecordGroupByDateGranularity | null, orderBy?: GraphOrderBy | null, displayDataLabel?: boolean | null, color?: string | null, description?: string | null, filter?: any | null, timezone?: string | null, firstDayOfTheWeek?: number | null } | null }> | null }> | null } };
export type OnDbEventSubscriptionVariables = Exact<{
input: OnDbEventInput;
@@ -5122,7 +5137,6 @@ export const PageLayoutWidgetFragmentFragmentDoc = gql`
omitNullValues
axisNameDisplay
displayDataLabel
displayLegend
rangeMin
rangeMax
color
@@ -5147,7 +5161,6 @@ export const PageLayoutWidgetFragmentFragmentDoc = gql`
omitNullValues
axisNameDisplay
displayDataLabel
displayLegend
rangeMin
rangeMax
color
@@ -5166,8 +5179,6 @@ export const PageLayoutWidgetFragmentFragmentDoc = gql`
dateGranularity
orderBy
displayDataLabel
showCenterMetric
displayLegend
color
description
filter
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
Binary file not shown.
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
@@ -17,7 +17,7 @@ const StyledCard = styled.div<{ isSingleNote: boolean }>`
flex-direction: column;
height: 300px;
justify-content: space-between;
width: 100%;
max-width: ${({ isSingleNote }) => (isSingleNote ? '300px' : 'unset')};
`;
const StyledCardDetailsContainer = styled.div`
@@ -4,7 +4,7 @@ import { useRecoilValue } from 'recoil';
import { Avatar, IconSparkles } from 'twenty-ui/display';
import { AgentChatFilePreview } from '@/ai/components/internal/AgentChatFilePreview';
import { AgentMessageRole } from '@/ai/constants/AgentMessageRole';
import { AgentChatMessageRole } from '@/ai/constants/AgentChatMessageRole';
import { AIChatAssistantMessageRenderer } from '@/ai/components/AIChatAssistantMessageRenderer';
import { AIChatErrorMessage } from '@/ai/components/AIChatErrorMessage';
@@ -161,17 +161,17 @@ export const AIChatMessage = ({
);
const showError =
isDefined(error) && message.role === AgentMessageRole.ASSISTANT;
isDefined(error) && message.role === AgentChatMessageRole.ASSISTANT;
const fileParts = message.parts.filter((part) => part.type === 'file');
return (
<StyledMessageBubble
key={message.id}
isUser={message.role === AgentMessageRole.USER}
isUser={message.role === AgentChatMessageRole.USER}
>
<StyledMessageRow>
{message.role === AgentMessageRole.ASSISTANT && (
{message.role === AgentChatMessageRole.ASSISTANT && (
<StyledAvatarContainer>
<Avatar
size="sm"
@@ -181,13 +181,15 @@ export const AIChatMessage = ({
/>
</StyledAvatarContainer>
)}
{message.role === AgentMessageRole.USER && (
{message.role === AgentChatMessageRole.USER && (
<StyledAvatarContainer isUser>
<Avatar size="sm" placeholder="U" type="rounded" />
</StyledAvatarContainer>
)}
<StyledMessageContainer>
<StyledMessageText isUser={message.role === AgentMessageRole.USER}>
<StyledMessageText
isUser={message.role === AgentChatMessageRole.USER}
>
<AIChatAssistantMessageRenderer
isLastMessageStreaming={isLastMessageStreaming}
messageParts={message.parts}
@@ -246,8 +246,7 @@ const DetailsTab = ({ debug, copyToClipboard }: DetailsTabProps) => {
id: debug.selectedAgentId,
label: debug.selectedAgentLabel,
},
fastModel: debug.fastModel,
smartModel: debug.smartModel,
routerModel: debug.routerModel,
agentModel: debug.agentModel,
availableAgents: debug.availableAgents,
};
@@ -1,57 +1,47 @@
import { RoutingDebugDisplay } from '@/ai/components/RoutingDebugDisplay';
import { ShimmeringText } from '@/ai/components/ShimmeringText';
import { useTheme } from '@emotion/react';
import styled from '@emotion/styled';
import { useState } from 'react';
import { type DataMessagePart } from 'twenty-shared/ai';
import { IconChevronDown, IconChevronUp, IconCpu } from 'twenty-ui/display';
import { AnimatedExpandableContainer } from 'twenty-ui/layout';
import { IconCpu, IconSparkles } from 'twenty-ui/display';
const StyledContainer = styled.div`
const StyledRoutingContainer = styled.div`
align-items: center;
background: ${({ theme }) => theme.background.transparent.lighter};
border: ${({ theme }) => `1px dashed ${theme.border.color.medium}`};
border-radius: ${({ theme }) => theme.border.radius.md};
display: flex;
font-size: ${({ theme }) => theme.font.size.sm};
gap: ${({ theme }) => theme.spacing(2)};
margin-bottom: ${({ theme }) => theme.spacing(2)};
padding: ${({ theme }) => theme.spacing(2, 3)};
width: fit-content;
`;
const StyledIconContainer = styled.div<{ isLoading: boolean }>`
align-items: center;
animation: ${({ isLoading }) =>
isLoading ? 'pulseAnimation 2s ease-in-out infinite' : 'none'};
color: ${({ theme }) => theme.color.blue};
display: flex;
@keyframes pulseAnimation {
0%,
100% {
opacity: 1;
}
50% {
opacity: 0.5;
}
}
`;
const StyledText = styled.div`
color: ${({ theme }) => theme.font.color.tertiary};
`;
const StyledWrapper = styled.div`
display: flex;
flex-direction: column;
gap: ${({ theme }) => theme.spacing(2)};
`;
const StyledToggleButton = styled.div<{ isExpandable: boolean }>`
align-items: center;
background: none;
border: none;
cursor: ${({ isExpandable }) => (isExpandable ? 'pointer' : 'auto')};
display: flex;
color: ${({ theme }) => theme.font.color.tertiary};
gap: ${({ theme }) => theme.spacing(1)};
padding: ${({ theme }) => theme.spacing(1)} 0;
transition: color ${({ theme }) => theme.animation.duration.normal}s;
&:hover {
color: ${({ isExpandable, theme }) =>
isExpandable ? theme.font.color.secondary : theme.font.color.tertiary};
}
`;
const StyledDisplayMessage = styled.span`
color: ${({ theme }) => theme.font.color.tertiary};
font-size: ${({ theme }) => theme.font.size.md};
font-weight: ${({ theme }) => theme.font.weight.medium};
`;
const StyledIconTextContainer = styled.div`
display: flex;
align-items: center;
gap: ${({ theme }) => theme.spacing(1)};
svg {
min-width: ${({ theme }) => theme.icon.size.sm}px;
}
`;
const StyledContentContainer = styled.div`
background: ${({ theme }) => theme.background.transparent.lighter};
border: 1px solid ${({ theme }) => theme.border.color.light};
border-radius: ${({ theme }) => theme.border.radius.sm};
min-width: 0;
padding: ${({ theme }) => theme.spacing(3)};
`;
export const RoutingStatusDisplay = ({
@@ -59,54 +49,28 @@ export const RoutingStatusDisplay = ({
}: {
data: DataMessagePart['routing-status'];
}) => {
const theme = useTheme();
const [isExpanded, setIsExpanded] = useState(false);
const isLoading = data.state === 'loading';
const isDebugMode = process.env.IS_DEBUG_MODE === 'true';
const isExpandable = isDebugMode && data.state === 'routed' && data.debug;
if (data.state === 'error') {
return null;
}
if (isLoading) {
return (
<StyledContainer>
<StyledIconTextContainer>
<IconCpu size={theme.icon.size.sm} />
<ShimmeringText>
<StyledDisplayMessage>{data.text}</StyledDisplayMessage>
</ShimmeringText>
</StyledIconTextContainer>
</StyledContainer>
);
}
return (
<StyledContainer>
<StyledToggleButton
onClick={() => isExpandable && setIsExpanded(!isExpanded)}
isExpandable={!!isExpandable}
>
<StyledIconTextContainer>
<IconCpu size={theme.icon.size.sm} />
<StyledDisplayMessage>{data.text}</StyledDisplayMessage>
</StyledIconTextContainer>
{isExpandable &&
(isExpanded ? (
<IconChevronUp size={theme.icon.size.sm} />
) : (
<IconChevronDown size={theme.icon.size.sm} />
))}
</StyledToggleButton>
{isExpandable && (
<AnimatedExpandableContainer isExpanded={isExpanded} mode="fit-content">
<StyledContentContainer>
<RoutingDebugDisplay debug={data.debug!} />
</StyledContentContainer>
</AnimatedExpandableContainer>
<StyledWrapper>
<StyledRoutingContainer>
<StyledIconContainer isLoading={isLoading}>
{isLoading ? <IconSparkles size={16} /> : <IconCpu size={16} />}
</StyledIconContainer>
{isLoading ? (
<ShimmeringText>{data.text}</ShimmeringText>
) : (
<StyledText>{data.text}</StyledText>
)}
</StyledRoutingContainer>
{isDebugMode && data.state === 'routed' && data.debug && (
<RoutingDebugDisplay debug={data.debug} />
)}
</StyledContainer>
</StyledWrapper>
);
};
@@ -0,0 +1,4 @@
export enum AgentChatMessageRole {
USER = 'user',
ASSISTANT = 'assistant',
}
@@ -1,5 +0,0 @@
export enum AgentMessageRole {
SYSTEM = 'system',
USER = 'user',
ASSISTANT = 'assistant',
}
@@ -1 +0,0 @@
export const DEFAULT_FAST_MODEL = 'default-fast-model' as const;
@@ -1 +0,0 @@
export const DEFAULT_SMART_MODEL = 'default-smart-model' as const;
@@ -13,7 +13,6 @@ export const AGENT_FRAGMENT = gql`
roleId
isCustom
modelConfiguration
evaluationInputs
applicationId
createdAt
updatedAt
@@ -0,0 +1,7 @@
import { gql } from '@apollo/client';
export const CREATE_AGENT_HANDOFF = gql`
mutation CreateAgentHandoff($input: CreateAgentHandoffInput!) {
createAgentHandoff(input: $input)
}
`;
@@ -1,13 +0,0 @@
import { gql } from '@apollo/client';
export const EVALUATE_AGENT_TURN = gql`
mutation EvaluateAgentTurn($turnId: UUID!) {
evaluateAgentTurn(turnId: $turnId) {
id
turnId
score
comment
createdAt
}
}
`;
@@ -0,0 +1,7 @@
import { gql } from '@apollo/client';
export const REMOVE_AGENT_HANDOFF = gql`
mutation RemoveAgentHandoff($input: RemoveAgentHandoffInput!) {
removeAgentHandoff(input: $input)
}
`;
@@ -1,18 +0,0 @@
import { gql } from '@apollo/client';
export const RUN_EVALUATION_INPUT = gql`
mutation RunEvaluationInput($agentId: UUID!, $input: String!) {
runEvaluationInput(agentId: $agentId, input: $input) {
id
threadId
agentId
createdAt
evaluations {
id
score
comment
createdAt
}
}
}
`;
@@ -0,0 +1,18 @@
import { gql } from '@apollo/client';
export const FIND_AGENT_HANDOFF_TARGETS = gql`
query FindAgentHandoffTargets($input: AgentIdInput!) {
findAgentHandoffTargets(input: $input) {
id
name
label
description
icon
modelId
prompt
isCustom
createdAt
updatedAt
}
}
`;
@@ -0,0 +1,22 @@
import { gql } from '@apollo/client';
export const FIND_AGENT_HANDOFFS = gql`
query FindAgentHandoffs($input: AgentIdInput!) {
findAgentHandoffs(input: $input) {
id
description
toAgent {
id
name
label
description
icon
modelId
prompt
isCustom
createdAt
updatedAt
}
}
}
`;
@@ -1,47 +0,0 @@
import { gql } from '@apollo/client';
export const GET_AGENT_TURNS = gql`
query GetAgentTurns($agentId: UUID!) {
agentTurns(agentId: $agentId) {
id
threadId
agentId
createdAt
evaluations {
id
score
comment
createdAt
}
messages {
id
role
createdAt
parts {
id
type
textContent
reasoningContent
toolName
toolCallId
toolInput
toolOutput
errorMessage
state
errorDetails
sourceUrlSourceId
sourceUrlUrl
sourceUrlTitle
sourceDocumentSourceId
sourceDocumentMediaType
sourceDocumentTitle
sourceDocumentFilename
fileMediaType
fileFilename
fileUrl
providerMetadata
}
}
}
}
`;
@@ -5,7 +5,6 @@ export const GET_CHAT_MESSAGES = gql`
chatMessages(threadId: $threadId) {
id
threadId
turnId
role
createdAt
parts {
@@ -2,20 +2,13 @@ import { aiModelsState } from '@/client-config/states/aiModelsState';
import { useRecoilValue } from 'recoil';
import { type SelectOption } from 'twenty-ui/input';
import { DEFAULT_FAST_MODEL } from '@/ai/constants/DefaultFastModel';
import { DEFAULT_SMART_MODEL } from '@/ai/constants/DefaultSmartModel';
export const useAiModelOptions = (): SelectOption<string>[] => {
const aiModels = useRecoilValue(aiModelsState);
return aiModels
.map((model) => ({
value: model.modelId,
label:
model.modelId === DEFAULT_FAST_MODEL ||
model.modelId === DEFAULT_SMART_MODEL
? model.label
: `${model.label} (${model.provider})`,
label: `${model.label} (${model.provider})`,
}))
.sort((a, b) => a.label.localeCompare(b.label));
};

Some files were not shown because too many files have changed in this diff Show More