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
This commit is contained in:
@@ -1743,7 +1743,7 @@ type NativeModelCapabilities {
|
||||
twitterSearch: Boolean
|
||||
}
|
||||
|
||||
type ClientAIModelConfig {
|
||||
type ClientAiModelConfig {
|
||||
modelId: String!
|
||||
label: String!
|
||||
modelFamily: ModelFamily
|
||||
@@ -1769,7 +1769,7 @@ enum ModelFamily {
|
||||
GROK
|
||||
}
|
||||
|
||||
type AdminAIModelConfig {
|
||||
type AdminAiModelConfig {
|
||||
modelId: String!
|
||||
label: String!
|
||||
modelFamily: ModelFamily
|
||||
@@ -1789,8 +1789,8 @@ type AdminAIModelConfig {
|
||||
dataResidency: String
|
||||
}
|
||||
|
||||
type AdminAIModels {
|
||||
models: [AdminAIModelConfig!]!
|
||||
type AdminAiModels {
|
||||
models: [AdminAiModelConfig!]!
|
||||
defaultSmartModelId: String
|
||||
defaultFastModelId: String
|
||||
}
|
||||
@@ -1852,7 +1852,7 @@ type ClientConfig {
|
||||
appVersion: String
|
||||
authProviders: AuthProviders!
|
||||
billing: Billing!
|
||||
aiModels: [ClientAIModelConfig!]!
|
||||
aiModels: [ClientAiModelConfig!]!
|
||||
signInPrefilled: Boolean!
|
||||
isMultiWorkspaceEnabled: Boolean!
|
||||
isEmailVerificationRequired: Boolean!
|
||||
@@ -2957,14 +2957,14 @@ type AgentMessage {
|
||||
createdAt: DateTime!
|
||||
}
|
||||
|
||||
type AISystemPromptSection {
|
||||
type AiSystemPromptSection {
|
||||
title: String!
|
||||
content: String!
|
||||
estimatedTokenCount: Int!
|
||||
}
|
||||
|
||||
type AISystemPromptPreview {
|
||||
sections: [AISystemPromptSection!]!
|
||||
type AiSystemPromptPreview {
|
||||
sections: [AiSystemPromptSection!]!
|
||||
estimatedTokenCount: Int!
|
||||
}
|
||||
|
||||
@@ -3319,7 +3319,7 @@ type Query {
|
||||
chatThread(id: UUID!): AgentChatThread!
|
||||
chatMessages(threadId: UUID!): [AgentMessage!]!
|
||||
chatStreamCatchupChunks(threadId: UUID!): ChatStreamCatchupChunks!
|
||||
getAISystemPromptPreview: AISystemPromptPreview!
|
||||
getAiSystemPromptPreview: AiSystemPromptPreview!
|
||||
skills: [Skill!]!
|
||||
skill(id: UUID!): Skill
|
||||
chatThreads(
|
||||
@@ -3364,7 +3364,7 @@ type Query {
|
||||
getIndicatorHealthStatus(indicatorId: HealthIndicatorId!): AdminPanelHealthServiceData!
|
||||
getQueueMetrics(queueName: String!, timeRange: QueueMetricsTimeRange = OneHour): QueueMetricsData!
|
||||
versionInfo: VersionInfo!
|
||||
getAdminAiModels: AdminAIModels!
|
||||
getAdminAiModels: AdminAiModels!
|
||||
getDatabaseConfigVariable(key: String!): ConfigVariable!
|
||||
getQueueJobs(queueName: String!, state: JobState!, limit: Int = 50, offset: Int = 0): QueueJobsResponse!
|
||||
findAllApplicationRegistrations: [ApplicationRegistration!]!
|
||||
@@ -3519,7 +3519,7 @@ type Mutation {
|
||||
deleteManyNavigationMenuItems(ids: [UUID!]!): [NavigationMenuItem!]!
|
||||
deleteNavigationMenuItem(id: UUID!): NavigationMenuItem!
|
||||
uploadEmailAttachmentFile(file: Upload!): FileWithSignedUrl!
|
||||
uploadAIChatFile(file: Upload!): FileWithSignedUrl!
|
||||
uploadAiChatFile(file: Upload!): FileWithSignedUrl!
|
||||
uploadWorkflowFile(file: Upload!): FileWithSignedUrl!
|
||||
uploadWorkspaceLogo(file: Upload!): FileWithSignedUrl!
|
||||
uploadWorkspaceMemberProfilePicture(file: Upload!): FileWithSignedUrl!
|
||||
|
||||
@@ -1444,7 +1444,7 @@ export interface NativeModelCapabilities {
|
||||
__typename: 'NativeModelCapabilities'
|
||||
}
|
||||
|
||||
export interface ClientAIModelConfig {
|
||||
export interface ClientAiModelConfig {
|
||||
modelId: Scalars['String']
|
||||
label: Scalars['String']
|
||||
modelFamily?: ModelFamily
|
||||
@@ -1460,12 +1460,12 @@ export interface ClientAIModelConfig {
|
||||
contextWindowTokens?: Scalars['Float']
|
||||
maxOutputTokens?: Scalars['Float']
|
||||
dataResidency?: Scalars['String']
|
||||
__typename: 'ClientAIModelConfig'
|
||||
__typename: 'ClientAiModelConfig'
|
||||
}
|
||||
|
||||
export type ModelFamily = 'GPT' | 'CLAUDE' | 'GEMINI' | 'MISTRAL' | 'GROK'
|
||||
|
||||
export interface AdminAIModelConfig {
|
||||
export interface AdminAiModelConfig {
|
||||
modelId: Scalars['String']
|
||||
label: Scalars['String']
|
||||
modelFamily?: ModelFamily
|
||||
@@ -1483,14 +1483,14 @@ export interface AdminAIModelConfig {
|
||||
providerLabel?: Scalars['String']
|
||||
name?: Scalars['String']
|
||||
dataResidency?: Scalars['String']
|
||||
__typename: 'AdminAIModelConfig'
|
||||
__typename: 'AdminAiModelConfig'
|
||||
}
|
||||
|
||||
export interface AdminAIModels {
|
||||
models: AdminAIModelConfig[]
|
||||
export interface AdminAiModels {
|
||||
models: AdminAiModelConfig[]
|
||||
defaultSmartModelId?: Scalars['String']
|
||||
defaultFastModelId?: Scalars['String']
|
||||
__typename: 'AdminAIModels'
|
||||
__typename: 'AdminAiModels'
|
||||
}
|
||||
|
||||
export interface Billing {
|
||||
@@ -1552,7 +1552,7 @@ export interface ClientConfig {
|
||||
appVersion?: Scalars['String']
|
||||
authProviders: AuthProviders
|
||||
billing: Billing
|
||||
aiModels: ClientAIModelConfig[]
|
||||
aiModels: ClientAiModelConfig[]
|
||||
signInPrefilled: Scalars['Boolean']
|
||||
isMultiWorkspaceEnabled: Scalars['Boolean']
|
||||
isEmailVerificationRequired: Scalars['Boolean']
|
||||
@@ -2628,17 +2628,17 @@ export interface AgentMessage {
|
||||
__typename: 'AgentMessage'
|
||||
}
|
||||
|
||||
export interface AISystemPromptSection {
|
||||
export interface AiSystemPromptSection {
|
||||
title: Scalars['String']
|
||||
content: Scalars['String']
|
||||
estimatedTokenCount: Scalars['Int']
|
||||
__typename: 'AISystemPromptSection'
|
||||
__typename: 'AiSystemPromptSection'
|
||||
}
|
||||
|
||||
export interface AISystemPromptPreview {
|
||||
sections: AISystemPromptSection[]
|
||||
export interface AiSystemPromptPreview {
|
||||
sections: AiSystemPromptSection[]
|
||||
estimatedTokenCount: Scalars['Int']
|
||||
__typename: 'AISystemPromptPreview'
|
||||
__typename: 'AiSystemPromptPreview'
|
||||
}
|
||||
|
||||
export interface ChatStreamCatchupChunks {
|
||||
@@ -2891,7 +2891,7 @@ export interface Query {
|
||||
chatThread: AgentChatThread
|
||||
chatMessages: AgentMessage[]
|
||||
chatStreamCatchupChunks: ChatStreamCatchupChunks
|
||||
getAISystemPromptPreview: AISystemPromptPreview
|
||||
getAiSystemPromptPreview: AiSystemPromptPreview
|
||||
skills: Skill[]
|
||||
skill?: Skill
|
||||
chatThreads: AgentChatThreadConnection
|
||||
@@ -2927,7 +2927,7 @@ export interface Query {
|
||||
getIndicatorHealthStatus: AdminPanelHealthServiceData
|
||||
getQueueMetrics: QueueMetricsData
|
||||
versionInfo: VersionInfo
|
||||
getAdminAiModels: AdminAIModels
|
||||
getAdminAiModels: AdminAiModels
|
||||
getDatabaseConfigVariable: ConfigVariable
|
||||
getQueueJobs: QueueJobsResponse
|
||||
findAllApplicationRegistrations: ApplicationRegistration[]
|
||||
@@ -2975,7 +2975,7 @@ export interface Mutation {
|
||||
deleteManyNavigationMenuItems: NavigationMenuItem[]
|
||||
deleteNavigationMenuItem: NavigationMenuItem
|
||||
uploadEmailAttachmentFile: FileWithSignedUrl
|
||||
uploadAIChatFile: FileWithSignedUrl
|
||||
uploadAiChatFile: FileWithSignedUrl
|
||||
uploadWorkflowFile: FileWithSignedUrl
|
||||
uploadWorkspaceLogo: FileWithSignedUrl
|
||||
uploadWorkspaceMemberProfilePicture: FileWithSignedUrl
|
||||
@@ -4706,7 +4706,7 @@ export interface NativeModelCapabilitiesGenqlSelection{
|
||||
__scalar?: boolean | number
|
||||
}
|
||||
|
||||
export interface ClientAIModelConfigGenqlSelection{
|
||||
export interface ClientAiModelConfigGenqlSelection{
|
||||
modelId?: boolean | number
|
||||
label?: boolean | number
|
||||
modelFamily?: boolean | number
|
||||
@@ -4726,7 +4726,7 @@ export interface ClientAIModelConfigGenqlSelection{
|
||||
__scalar?: boolean | number
|
||||
}
|
||||
|
||||
export interface AdminAIModelConfigGenqlSelection{
|
||||
export interface AdminAiModelConfigGenqlSelection{
|
||||
modelId?: boolean | number
|
||||
label?: boolean | number
|
||||
modelFamily?: boolean | number
|
||||
@@ -4748,8 +4748,8 @@ export interface AdminAIModelConfigGenqlSelection{
|
||||
__scalar?: boolean | number
|
||||
}
|
||||
|
||||
export interface AdminAIModelsGenqlSelection{
|
||||
models?: AdminAIModelConfigGenqlSelection
|
||||
export interface AdminAiModelsGenqlSelection{
|
||||
models?: AdminAiModelConfigGenqlSelection
|
||||
defaultSmartModelId?: boolean | number
|
||||
defaultFastModelId?: boolean | number
|
||||
__typename?: boolean | number
|
||||
@@ -4819,7 +4819,7 @@ export interface ClientConfigGenqlSelection{
|
||||
appVersion?: boolean | number
|
||||
authProviders?: AuthProvidersGenqlSelection
|
||||
billing?: BillingGenqlSelection
|
||||
aiModels?: ClientAIModelConfigGenqlSelection
|
||||
aiModels?: ClientAiModelConfigGenqlSelection
|
||||
signInPrefilled?: boolean | number
|
||||
isMultiWorkspaceEnabled?: boolean | number
|
||||
isEmailVerificationRequired?: boolean | number
|
||||
@@ -5993,7 +5993,7 @@ export interface AgentMessageGenqlSelection{
|
||||
__scalar?: boolean | number
|
||||
}
|
||||
|
||||
export interface AISystemPromptSectionGenqlSelection{
|
||||
export interface AiSystemPromptSectionGenqlSelection{
|
||||
title?: boolean | number
|
||||
content?: boolean | number
|
||||
estimatedTokenCount?: boolean | number
|
||||
@@ -6001,8 +6001,8 @@ export interface AISystemPromptSectionGenqlSelection{
|
||||
__scalar?: boolean | number
|
||||
}
|
||||
|
||||
export interface AISystemPromptPreviewGenqlSelection{
|
||||
sections?: AISystemPromptSectionGenqlSelection
|
||||
export interface AiSystemPromptPreviewGenqlSelection{
|
||||
sections?: AiSystemPromptSectionGenqlSelection
|
||||
estimatedTokenCount?: boolean | number
|
||||
__typename?: boolean | number
|
||||
__scalar?: boolean | number
|
||||
@@ -6265,7 +6265,7 @@ export interface QueryGenqlSelection{
|
||||
chatThread?: (AgentChatThreadGenqlSelection & { __args: {id: Scalars['UUID']} })
|
||||
chatMessages?: (AgentMessageGenqlSelection & { __args: {threadId: Scalars['UUID']} })
|
||||
chatStreamCatchupChunks?: (ChatStreamCatchupChunksGenqlSelection & { __args: {threadId: Scalars['UUID']} })
|
||||
getAISystemPromptPreview?: AISystemPromptPreviewGenqlSelection
|
||||
getAiSystemPromptPreview?: AiSystemPromptPreviewGenqlSelection
|
||||
skills?: SkillGenqlSelection
|
||||
skill?: (SkillGenqlSelection & { __args: {id: Scalars['UUID']} })
|
||||
chatThreads?: (AgentChatThreadConnectionGenqlSelection & { __args: {
|
||||
@@ -6307,7 +6307,7 @@ export interface QueryGenqlSelection{
|
||||
getIndicatorHealthStatus?: (AdminPanelHealthServiceDataGenqlSelection & { __args: {indicatorId: HealthIndicatorId} })
|
||||
getQueueMetrics?: (QueueMetricsDataGenqlSelection & { __args: {queueName: Scalars['String'], timeRange?: (QueueMetricsTimeRange | null)} })
|
||||
versionInfo?: VersionInfoGenqlSelection
|
||||
getAdminAiModels?: AdminAIModelsGenqlSelection
|
||||
getAdminAiModels?: AdminAiModelsGenqlSelection
|
||||
getDatabaseConfigVariable?: (ConfigVariableGenqlSelection & { __args: {key: Scalars['String']} })
|
||||
getQueueJobs?: (QueueJobsResponseGenqlSelection & { __args: {queueName: Scalars['String'], state: JobState, limit?: (Scalars['Int'] | null), offset?: (Scalars['Int'] | null)} })
|
||||
findAllApplicationRegistrations?: ApplicationRegistrationGenqlSelection
|
||||
@@ -6374,7 +6374,7 @@ export interface MutationGenqlSelection{
|
||||
deleteManyNavigationMenuItems?: (NavigationMenuItemGenqlSelection & { __args: {ids: Scalars['UUID'][]} })
|
||||
deleteNavigationMenuItem?: (NavigationMenuItemGenqlSelection & { __args: {id: Scalars['UUID']} })
|
||||
uploadEmailAttachmentFile?: (FileWithSignedUrlGenqlSelection & { __args: {file: Scalars['Upload']} })
|
||||
uploadAIChatFile?: (FileWithSignedUrlGenqlSelection & { __args: {file: Scalars['Upload']} })
|
||||
uploadAiChatFile?: (FileWithSignedUrlGenqlSelection & { __args: {file: Scalars['Upload']} })
|
||||
uploadWorkflowFile?: (FileWithSignedUrlGenqlSelection & { __args: {file: Scalars['Upload']} })
|
||||
uploadWorkspaceLogo?: (FileWithSignedUrlGenqlSelection & { __args: {file: Scalars['Upload']} })
|
||||
uploadWorkspaceMemberProfilePicture?: (FileWithSignedUrlGenqlSelection & { __args: {file: Scalars['Upload']} })
|
||||
@@ -7887,26 +7887,26 @@ export interface LogicFunctionLogsInput {applicationId?: (Scalars['UUID'] | null
|
||||
|
||||
|
||||
|
||||
const ClientAIModelConfig_possibleTypes: string[] = ['ClientAIModelConfig']
|
||||
export const isClientAIModelConfig = (obj?: { __typename?: any } | null): obj is ClientAIModelConfig => {
|
||||
if (!obj?.__typename) throw new Error('__typename is missing in "isClientAIModelConfig"')
|
||||
return ClientAIModelConfig_possibleTypes.includes(obj.__typename)
|
||||
const ClientAiModelConfig_possibleTypes: string[] = ['ClientAiModelConfig']
|
||||
export const isClientAiModelConfig = (obj?: { __typename?: any } | null): obj is ClientAiModelConfig => {
|
||||
if (!obj?.__typename) throw new Error('__typename is missing in "isClientAiModelConfig"')
|
||||
return ClientAiModelConfig_possibleTypes.includes(obj.__typename)
|
||||
}
|
||||
|
||||
|
||||
|
||||
const AdminAIModelConfig_possibleTypes: string[] = ['AdminAIModelConfig']
|
||||
export const isAdminAIModelConfig = (obj?: { __typename?: any } | null): obj is AdminAIModelConfig => {
|
||||
if (!obj?.__typename) throw new Error('__typename is missing in "isAdminAIModelConfig"')
|
||||
return AdminAIModelConfig_possibleTypes.includes(obj.__typename)
|
||||
const AdminAiModelConfig_possibleTypes: string[] = ['AdminAiModelConfig']
|
||||
export const isAdminAiModelConfig = (obj?: { __typename?: any } | null): obj is AdminAiModelConfig => {
|
||||
if (!obj?.__typename) throw new Error('__typename is missing in "isAdminAiModelConfig"')
|
||||
return AdminAiModelConfig_possibleTypes.includes(obj.__typename)
|
||||
}
|
||||
|
||||
|
||||
|
||||
const AdminAIModels_possibleTypes: string[] = ['AdminAIModels']
|
||||
export const isAdminAIModels = (obj?: { __typename?: any } | null): obj is AdminAIModels => {
|
||||
if (!obj?.__typename) throw new Error('__typename is missing in "isAdminAIModels"')
|
||||
return AdminAIModels_possibleTypes.includes(obj.__typename)
|
||||
const AdminAiModels_possibleTypes: string[] = ['AdminAiModels']
|
||||
export const isAdminAiModels = (obj?: { __typename?: any } | null): obj is AdminAiModels => {
|
||||
if (!obj?.__typename) throw new Error('__typename is missing in "isAdminAiModels"')
|
||||
return AdminAiModels_possibleTypes.includes(obj.__typename)
|
||||
}
|
||||
|
||||
|
||||
@@ -8975,18 +8975,18 @@ export interface LogicFunctionLogsInput {applicationId?: (Scalars['UUID'] | null
|
||||
|
||||
|
||||
|
||||
const AISystemPromptSection_possibleTypes: string[] = ['AISystemPromptSection']
|
||||
export const isAISystemPromptSection = (obj?: { __typename?: any } | null): obj is AISystemPromptSection => {
|
||||
if (!obj?.__typename) throw new Error('__typename is missing in "isAISystemPromptSection"')
|
||||
return AISystemPromptSection_possibleTypes.includes(obj.__typename)
|
||||
const AiSystemPromptSection_possibleTypes: string[] = ['AiSystemPromptSection']
|
||||
export const isAiSystemPromptSection = (obj?: { __typename?: any } | null): obj is AiSystemPromptSection => {
|
||||
if (!obj?.__typename) throw new Error('__typename is missing in "isAiSystemPromptSection"')
|
||||
return AiSystemPromptSection_possibleTypes.includes(obj.__typename)
|
||||
}
|
||||
|
||||
|
||||
|
||||
const AISystemPromptPreview_possibleTypes: string[] = ['AISystemPromptPreview']
|
||||
export const isAISystemPromptPreview = (obj?: { __typename?: any } | null): obj is AISystemPromptPreview => {
|
||||
if (!obj?.__typename) throw new Error('__typename is missing in "isAISystemPromptPreview"')
|
||||
return AISystemPromptPreview_possibleTypes.includes(obj.__typename)
|
||||
const AiSystemPromptPreview_possibleTypes: string[] = ['AiSystemPromptPreview']
|
||||
export const isAiSystemPromptPreview = (obj?: { __typename?: any } | null): obj is AiSystemPromptPreview => {
|
||||
if (!obj?.__typename) throw new Error('__typename is missing in "isAiSystemPromptPreview"')
|
||||
return AiSystemPromptPreview_possibleTypes.includes(obj.__typename)
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -3506,7 +3506,7 @@ export default {
|
||||
1
|
||||
]
|
||||
},
|
||||
"ClientAIModelConfig": {
|
||||
"ClientAiModelConfig": {
|
||||
"modelId": [
|
||||
1
|
||||
],
|
||||
@@ -3557,7 +3557,7 @@ export default {
|
||||
]
|
||||
},
|
||||
"ModelFamily": {},
|
||||
"AdminAIModelConfig": {
|
||||
"AdminAiModelConfig": {
|
||||
"modelId": [
|
||||
1
|
||||
],
|
||||
@@ -3613,7 +3613,7 @@ export default {
|
||||
1
|
||||
]
|
||||
},
|
||||
"AdminAIModels": {
|
||||
"AdminAiModels": {
|
||||
"models": [
|
||||
181
|
||||
],
|
||||
@@ -5936,7 +5936,7 @@ export default {
|
||||
1
|
||||
]
|
||||
},
|
||||
"AISystemPromptSection": {
|
||||
"AiSystemPromptSection": {
|
||||
"title": [
|
||||
1
|
||||
],
|
||||
@@ -5950,7 +5950,7 @@ export default {
|
||||
1
|
||||
]
|
||||
},
|
||||
"AISystemPromptPreview": {
|
||||
"AiSystemPromptPreview": {
|
||||
"sections": [
|
||||
331
|
||||
],
|
||||
@@ -6810,7 +6810,7 @@ export default {
|
||||
]
|
||||
}
|
||||
],
|
||||
"getAISystemPromptPreview": [
|
||||
"getAiSystemPromptPreview": [
|
||||
332
|
||||
],
|
||||
"skills": [
|
||||
@@ -7544,7 +7544,7 @@ export default {
|
||||
]
|
||||
}
|
||||
],
|
||||
"uploadAIChatFile": [
|
||||
"uploadAiChatFile": [
|
||||
118,
|
||||
{
|
||||
"file": [
|
||||
|
||||
@@ -19,19 +19,6 @@ export type Scalars = {
|
||||
Upload: any;
|
||||
};
|
||||
|
||||
export type AiSystemPromptPreview = {
|
||||
__typename?: 'AISystemPromptPreview';
|
||||
estimatedTokenCount: Scalars['Int'];
|
||||
sections: Array<AiSystemPromptSection>;
|
||||
};
|
||||
|
||||
export type AiSystemPromptSection = {
|
||||
__typename?: 'AISystemPromptSection';
|
||||
content: Scalars['String'];
|
||||
estimatedTokenCount: Scalars['Int'];
|
||||
title: Scalars['String'];
|
||||
};
|
||||
|
||||
export type ActivateWorkspaceInput = {
|
||||
displayName?: InputMaybe<Scalars['String']>;
|
||||
};
|
||||
@@ -43,7 +30,7 @@ export type AddQuerySubscriptionInput = {
|
||||
};
|
||||
|
||||
export type AdminAiModelConfig = {
|
||||
__typename?: 'AdminAIModelConfig';
|
||||
__typename?: 'AdminAiModelConfig';
|
||||
contextWindowTokens?: Maybe<Scalars['Float']>;
|
||||
dataResidency?: Maybe<Scalars['String']>;
|
||||
inputCostPerMillionTokens?: Maybe<Scalars['Float']>;
|
||||
@@ -64,7 +51,7 @@ export type AdminAiModelConfig = {
|
||||
};
|
||||
|
||||
export type AdminAiModels = {
|
||||
__typename?: 'AdminAIModels';
|
||||
__typename?: 'AdminAiModels';
|
||||
defaultFastModelId?: Maybe<Scalars['String']>;
|
||||
defaultSmartModelId?: Maybe<Scalars['String']>;
|
||||
models: Array<AdminAiModelConfig>;
|
||||
@@ -328,6 +315,19 @@ export enum AiModelRole {
|
||||
SMART = 'SMART'
|
||||
}
|
||||
|
||||
export type AiSystemPromptPreview = {
|
||||
__typename?: 'AiSystemPromptPreview';
|
||||
estimatedTokenCount: Scalars['Int'];
|
||||
sections: Array<AiSystemPromptSection>;
|
||||
};
|
||||
|
||||
export type AiSystemPromptSection = {
|
||||
__typename?: 'AiSystemPromptSection';
|
||||
content: Scalars['String'];
|
||||
estimatedTokenCount: Scalars['Int'];
|
||||
title: Scalars['String'];
|
||||
};
|
||||
|
||||
export enum AllMetadataName {
|
||||
agent = 'agent',
|
||||
commandMenuItem = 'commandMenuItem',
|
||||
@@ -924,7 +924,7 @@ export type CheckUserExist = {
|
||||
};
|
||||
|
||||
export type ClientAiModelConfig = {
|
||||
__typename?: 'ClientAIModelConfig';
|
||||
__typename?: 'ClientAiModelConfig';
|
||||
contextWindowTokens?: Maybe<Scalars['Float']>;
|
||||
dataResidency?: Maybe<Scalars['String']>;
|
||||
inputCostPerMillionTokens?: Maybe<Scalars['Float']>;
|
||||
@@ -2792,7 +2792,7 @@ export type Mutation = {
|
||||
updateWorkspaceMemberRole: WorkspaceMember;
|
||||
updateWorkspaceMemberSettings: Scalars['Boolean'];
|
||||
upgradeApplication: Scalars['Boolean'];
|
||||
uploadAIChatFile: FileWithSignedUrl;
|
||||
uploadAiChatFile: FileWithSignedUrl;
|
||||
uploadAppTarball: ApplicationRegistration;
|
||||
uploadApplicationFile: File;
|
||||
uploadEmailAttachmentFile: FileWithSignedUrl;
|
||||
@@ -4441,13 +4441,13 @@ export type Query = {
|
||||
findWorkspaceInvitations: Array<WorkspaceInvitation>;
|
||||
frontComponent?: Maybe<FrontComponent>;
|
||||
frontComponents: Array<FrontComponent>;
|
||||
getAISystemPromptPreview: AiSystemPromptPreview;
|
||||
getAddressDetails: PlaceDetailsResult;
|
||||
getAdminAiModels: AdminAiModels;
|
||||
getAdminAiUsageByWorkspace: Array<UsageBreakdownItem>;
|
||||
getAdminChatThreadMessages: AdminChatThreadMessages;
|
||||
getAdminWorkspaceChatThreads: Array<AdminWorkspaceChatThread>;
|
||||
getAiProviders: Scalars['JSON'];
|
||||
getAiSystemPromptPreview: AiSystemPromptPreview;
|
||||
getApprovedAccessDomains: Array<ApprovedAccessDomain>;
|
||||
getAutoCompleteAddress: Array<AutocompleteResult>;
|
||||
getAvailablePackages: Scalars['JSON'];
|
||||
@@ -6636,7 +6636,7 @@ export type UploadAiChatFileMutationVariables = Exact<{
|
||||
}>;
|
||||
|
||||
|
||||
export type UploadAiChatFileMutation = { __typename?: 'Mutation', uploadAIChatFile: { __typename?: 'FileWithSignedUrl', id: string, path: string, size: number, createdAt: string, url: string } };
|
||||
export type UploadAiChatFileMutation = { __typename?: 'Mutation', uploadAiChatFile: { __typename?: 'FileWithSignedUrl', id: string, path: string, size: number, createdAt: string, url: string } };
|
||||
|
||||
export type FindManyAgentsQueryVariables = Exact<{ [key: string]: never; }>;
|
||||
|
||||
@@ -7462,7 +7462,7 @@ export type SetAdminDefaultAiModelMutation = { __typename?: 'Mutation', setAdmin
|
||||
export type GetAdminAiModelsQueryVariables = Exact<{ [key: string]: never; }>;
|
||||
|
||||
|
||||
export type GetAdminAiModelsQuery = { __typename?: 'Query', getAdminAiModels: { __typename?: 'AdminAIModels', defaultSmartModelId?: string | null, defaultFastModelId?: string | null, models: Array<{ __typename?: 'AdminAIModelConfig', modelId: string, label: string, modelFamily?: ModelFamily | null, sdkPackage?: string | null, isAvailable: boolean, isAdminEnabled: boolean, isDeprecated?: boolean | null, isRecommended?: boolean | null, contextWindowTokens?: number | null, maxOutputTokens?: number | null, inputCostPerMillionTokens?: number | null, outputCostPerMillionTokens?: number | null, providerName?: string | null, providerLabel?: string | null, name?: string | null, dataResidency?: string | null }> } };
|
||||
export type GetAdminAiModelsQuery = { __typename?: 'Query', getAdminAiModels: { __typename?: 'AdminAiModels', defaultSmartModelId?: string | null, defaultFastModelId?: string | null, models: Array<{ __typename?: 'AdminAiModelConfig', modelId: string, label: string, modelFamily?: ModelFamily | null, sdkPackage?: string | null, isAvailable: boolean, isAdminEnabled: boolean, isDeprecated?: boolean | null, isRecommended?: boolean | null, contextWindowTokens?: number | null, maxOutputTokens?: number | null, inputCostPerMillionTokens?: number | null, outputCostPerMillionTokens?: number | null, providerName?: string | null, providerLabel?: string | null, name?: string | null, dataResidency?: string | null }> } };
|
||||
|
||||
export type GetAdminAiUsageByWorkspaceQueryVariables = Exact<{
|
||||
periodStart?: InputMaybe<Scalars['DateTime']>;
|
||||
@@ -8589,7 +8589,7 @@ export type CheckCustomDomainValidRecordsMutation = { __typename?: 'Mutation', c
|
||||
export type GetAiSystemPromptPreviewQueryVariables = Exact<{ [key: string]: never; }>;
|
||||
|
||||
|
||||
export type GetAiSystemPromptPreviewQuery = { __typename?: 'Query', getAISystemPromptPreview: { __typename?: 'AISystemPromptPreview', estimatedTokenCount: number, sections: Array<{ __typename?: 'AISystemPromptSection', title: string, content: string, estimatedTokenCount: number }> } };
|
||||
export type GetAiSystemPromptPreviewQuery = { __typename?: 'Query', getAiSystemPromptPreview: { __typename?: 'AiSystemPromptPreview', estimatedTokenCount: number, sections: Array<{ __typename?: 'AiSystemPromptSection', title: string, content: string, estimatedTokenCount: number }> } };
|
||||
|
||||
export type GetPublicWorkspaceDataByIdQueryVariables = Exact<{
|
||||
id: Scalars['UUID'];
|
||||
@@ -8670,7 +8670,7 @@ export const SendChatMessageDocument = {"kind":"Document","definitions":[{"kind"
|
||||
export const StopAgentChatStreamDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"StopAgentChatStream"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"threadId"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"UUID"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"stopAgentChatStream"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"threadId"},"value":{"kind":"Variable","name":{"kind":"Name","value":"threadId"}}}]}]}}]} as unknown as DocumentNode<StopAgentChatStreamMutation, StopAgentChatStreamMutationVariables>;
|
||||
export const UpdateOneAgentDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"UpdateOneAgent"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"input"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"UpdateAgentInput"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"updateOneAgent"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"input"},"value":{"kind":"Variable","name":{"kind":"Name","value":"input"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"AgentFields"}}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"AgentFields"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Agent"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"label"}},{"kind":"Field","name":{"kind":"Name","value":"description"}},{"kind":"Field","name":{"kind":"Name","value":"icon"}},{"kind":"Field","name":{"kind":"Name","value":"prompt"}},{"kind":"Field","name":{"kind":"Name","value":"modelId"}},{"kind":"Field","name":{"kind":"Name","value":"responseFormat"}},{"kind":"Field","name":{"kind":"Name","value":"roleId"}},{"kind":"Field","name":{"kind":"Name","value":"isCustom"}},{"kind":"Field","name":{"kind":"Name","value":"modelConfiguration"}},{"kind":"Field","name":{"kind":"Name","value":"evaluationInputs"}},{"kind":"Field","name":{"kind":"Name","value":"applicationId"}},{"kind":"Field","name":{"kind":"Name","value":"createdAt"}},{"kind":"Field","name":{"kind":"Name","value":"updatedAt"}}]}}]} as unknown as DocumentNode<UpdateOneAgentMutation, UpdateOneAgentMutationVariables>;
|
||||
export const UpdateSkillDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"UpdateSkill"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"input"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"UpdateSkillInput"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"updateSkill"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"input"},"value":{"kind":"Variable","name":{"kind":"Name","value":"input"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"SkillFields"}}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"SkillFields"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Skill"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"label"}},{"kind":"Field","name":{"kind":"Name","value":"description"}},{"kind":"Field","name":{"kind":"Name","value":"icon"}},{"kind":"Field","name":{"kind":"Name","value":"content"}},{"kind":"Field","name":{"kind":"Name","value":"isCustom"}},{"kind":"Field","name":{"kind":"Name","value":"isActive"}},{"kind":"Field","name":{"kind":"Name","value":"createdAt"}},{"kind":"Field","name":{"kind":"Name","value":"updatedAt"}}]}}]} as unknown as DocumentNode<UpdateSkillMutation, UpdateSkillMutationVariables>;
|
||||
export const UploadAiChatFileDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"uploadAIChatFile"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"file"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"Upload"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"uploadAIChatFile"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"file"},"value":{"kind":"Variable","name":{"kind":"Name","value":"file"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"path"}},{"kind":"Field","name":{"kind":"Name","value":"size"}},{"kind":"Field","name":{"kind":"Name","value":"createdAt"}},{"kind":"Field","name":{"kind":"Name","value":"url"}}]}}]}}]} as unknown as DocumentNode<UploadAiChatFileMutation, UploadAiChatFileMutationVariables>;
|
||||
export const UploadAiChatFileDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"uploadAiChatFile"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"file"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"Upload"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"uploadAiChatFile"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"file"},"value":{"kind":"Variable","name":{"kind":"Name","value":"file"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"path"}},{"kind":"Field","name":{"kind":"Name","value":"size"}},{"kind":"Field","name":{"kind":"Name","value":"createdAt"}},{"kind":"Field","name":{"kind":"Name","value":"url"}}]}}]}}]} as unknown as DocumentNode<UploadAiChatFileMutation, UploadAiChatFileMutationVariables>;
|
||||
export const FindManyAgentsDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"FindManyAgents"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"findManyAgents"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"AgentFields"}}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"AgentFields"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Agent"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"label"}},{"kind":"Field","name":{"kind":"Name","value":"description"}},{"kind":"Field","name":{"kind":"Name","value":"icon"}},{"kind":"Field","name":{"kind":"Name","value":"prompt"}},{"kind":"Field","name":{"kind":"Name","value":"modelId"}},{"kind":"Field","name":{"kind":"Name","value":"responseFormat"}},{"kind":"Field","name":{"kind":"Name","value":"roleId"}},{"kind":"Field","name":{"kind":"Name","value":"isCustom"}},{"kind":"Field","name":{"kind":"Name","value":"modelConfiguration"}},{"kind":"Field","name":{"kind":"Name","value":"evaluationInputs"}},{"kind":"Field","name":{"kind":"Name","value":"applicationId"}},{"kind":"Field","name":{"kind":"Name","value":"createdAt"}},{"kind":"Field","name":{"kind":"Name","value":"updatedAt"}}]}}]} as unknown as DocumentNode<FindManyAgentsQuery, FindManyAgentsQueryVariables>;
|
||||
export const FindManySkillsDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"FindManySkills"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"skills"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"SkillFields"}}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"SkillFields"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Skill"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"label"}},{"kind":"Field","name":{"kind":"Name","value":"description"}},{"kind":"Field","name":{"kind":"Name","value":"icon"}},{"kind":"Field","name":{"kind":"Name","value":"content"}},{"kind":"Field","name":{"kind":"Name","value":"isCustom"}},{"kind":"Field","name":{"kind":"Name","value":"isActive"}},{"kind":"Field","name":{"kind":"Name","value":"createdAt"}},{"kind":"Field","name":{"kind":"Name","value":"updatedAt"}}]}}]} as unknown as DocumentNode<FindManySkillsQuery, FindManySkillsQueryVariables>;
|
||||
export const FindOneAgentDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"FindOneAgent"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"id"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"UUID"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"findOneAgent"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"input"},"value":{"kind":"ObjectValue","fields":[{"kind":"ObjectField","name":{"kind":"Name","value":"id"},"value":{"kind":"Variable","name":{"kind":"Name","value":"id"}}}]}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"AgentFields"}}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"AgentFields"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Agent"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"label"}},{"kind":"Field","name":{"kind":"Name","value":"description"}},{"kind":"Field","name":{"kind":"Name","value":"icon"}},{"kind":"Field","name":{"kind":"Name","value":"prompt"}},{"kind":"Field","name":{"kind":"Name","value":"modelId"}},{"kind":"Field","name":{"kind":"Name","value":"responseFormat"}},{"kind":"Field","name":{"kind":"Name","value":"roleId"}},{"kind":"Field","name":{"kind":"Name","value":"isCustom"}},{"kind":"Field","name":{"kind":"Name","value":"modelConfiguration"}},{"kind":"Field","name":{"kind":"Name","value":"evaluationInputs"}},{"kind":"Field","name":{"kind":"Name","value":"applicationId"}},{"kind":"Field","name":{"kind":"Name","value":"createdAt"}},{"kind":"Field","name":{"kind":"Name","value":"updatedAt"}}]}}]} as unknown as DocumentNode<FindOneAgentQuery, FindOneAgentQueryVariables>;
|
||||
@@ -8939,6 +8939,6 @@ export const DeleteCurrentWorkspaceDocument = {"kind":"Document","definitions":[
|
||||
export const UpdateWorkspaceDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"UpdateWorkspace"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"input"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"UpdateWorkspaceInput"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"updateWorkspace"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"data"},"value":{"kind":"Variable","name":{"kind":"Name","value":"input"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"customDomain"}},{"kind":"Field","name":{"kind":"Name","value":"subdomain"}},{"kind":"Field","name":{"kind":"Name","value":"displayName"}},{"kind":"Field","name":{"kind":"Name","value":"logo"}},{"kind":"Field","name":{"kind":"Name","value":"allowImpersonation"}},{"kind":"Field","name":{"kind":"Name","value":"isPublicInviteLinkEnabled"}},{"kind":"Field","name":{"kind":"Name","value":"isGoogleAuthEnabled"}},{"kind":"Field","name":{"kind":"Name","value":"isMicrosoftAuthEnabled"}},{"kind":"Field","name":{"kind":"Name","value":"isPasswordAuthEnabled"}},{"kind":"Field","name":{"kind":"Name","value":"isTwoFactorAuthenticationEnforced"}},{"kind":"Field","name":{"kind":"Name","value":"defaultRole"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"RoleFragment"}}]}}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"RoleFragment"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Role"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"label"}},{"kind":"Field","name":{"kind":"Name","value":"description"}},{"kind":"Field","name":{"kind":"Name","value":"icon"}},{"kind":"Field","name":{"kind":"Name","value":"canUpdateAllSettings"}},{"kind":"Field","name":{"kind":"Name","value":"canAccessAllTools"}},{"kind":"Field","name":{"kind":"Name","value":"isEditable"}},{"kind":"Field","name":{"kind":"Name","value":"canReadAllObjectRecords"}},{"kind":"Field","name":{"kind":"Name","value":"canUpdateAllObjectRecords"}},{"kind":"Field","name":{"kind":"Name","value":"canSoftDeleteAllObjectRecords"}},{"kind":"Field","name":{"kind":"Name","value":"canDestroyAllObjectRecords"}},{"kind":"Field","name":{"kind":"Name","value":"canBeAssignedToUsers"}},{"kind":"Field","name":{"kind":"Name","value":"canBeAssignedToAgents"}},{"kind":"Field","name":{"kind":"Name","value":"canBeAssignedToApiKeys"}}]}}]} as unknown as DocumentNode<UpdateWorkspaceMutation, UpdateWorkspaceMutationVariables>;
|
||||
export const UploadWorkspaceLogoDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"UploadWorkspaceLogo"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"file"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"Upload"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"uploadWorkspaceLogo"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"file"},"value":{"kind":"Variable","name":{"kind":"Name","value":"file"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"url"}}]}}]}}]} as unknown as DocumentNode<UploadWorkspaceLogoMutation, UploadWorkspaceLogoMutationVariables>;
|
||||
export const CheckCustomDomainValidRecordsDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"CheckCustomDomainValidRecords"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"checkCustomDomainValidRecords"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"domain"}},{"kind":"Field","name":{"kind":"Name","value":"records"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"type"}},{"kind":"Field","name":{"kind":"Name","value":"key"}},{"kind":"Field","name":{"kind":"Name","value":"value"}},{"kind":"Field","name":{"kind":"Name","value":"validationType"}},{"kind":"Field","name":{"kind":"Name","value":"status"}}]}}]}}]}}]} as unknown as DocumentNode<CheckCustomDomainValidRecordsMutation, CheckCustomDomainValidRecordsMutationVariables>;
|
||||
export const GetAiSystemPromptPreviewDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"GetAISystemPromptPreview"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"getAISystemPromptPreview"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"sections"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"title"}},{"kind":"Field","name":{"kind":"Name","value":"content"}},{"kind":"Field","name":{"kind":"Name","value":"estimatedTokenCount"}}]}},{"kind":"Field","name":{"kind":"Name","value":"estimatedTokenCount"}}]}}]}}]} as unknown as DocumentNode<GetAiSystemPromptPreviewQuery, GetAiSystemPromptPreviewQueryVariables>;
|
||||
export const GetAiSystemPromptPreviewDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"GetAiSystemPromptPreview"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"getAiSystemPromptPreview"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"sections"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"title"}},{"kind":"Field","name":{"kind":"Name","value":"content"}},{"kind":"Field","name":{"kind":"Name","value":"estimatedTokenCount"}}]}},{"kind":"Field","name":{"kind":"Name","value":"estimatedTokenCount"}}]}}]}}]} as unknown as DocumentNode<GetAiSystemPromptPreviewQuery, GetAiSystemPromptPreviewQueryVariables>;
|
||||
export const GetPublicWorkspaceDataByIdDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"GetPublicWorkspaceDataById"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"id"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"UUID"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"getPublicWorkspaceDataById"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"id"},"value":{"kind":"Variable","name":{"kind":"Name","value":"id"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"displayName"}},{"kind":"Field","name":{"kind":"Name","value":"logo"}}]}}]}}]} as unknown as DocumentNode<GetPublicWorkspaceDataByIdQuery, GetPublicWorkspaceDataByIdQueryVariables>;
|
||||
export const GetWorkspaceFromInviteHashDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"GetWorkspaceFromInviteHash"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"inviteHash"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"findWorkspaceFromInviteHash"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"inviteHash"},"value":{"kind":"Variable","name":{"kind":"Name","value":"inviteHash"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"displayName"}},{"kind":"Field","name":{"kind":"Name","value":"logo"}},{"kind":"Field","name":{"kind":"Name","value":"allowImpersonation"}}]}}]}}]} as unknown as DocumentNode<GetWorkspaceFromInviteHashQuery, GetWorkspaceFromInviteHashQueryVariables>;
|
||||
@@ -1,22 +0,0 @@
|
||||
import { AIChatApiKeyNotConfiguredMessage } from '@/ai/components/AIChatApiKeyNotConfiguredMessage';
|
||||
import { AIChatCreditsExhaustedMessage } from '@/ai/components/AIChatCreditsExhaustedMessage';
|
||||
import { AIChatErrorMessage } from '@/ai/components/AIChatErrorMessage';
|
||||
import { type AIChatError } from '@/ai/types/AIChatError';
|
||||
import { AIChatErrorCode } from '@/ai/utils/aiChatErrorCode';
|
||||
import { isGraphqlErrorOfType } from '~/utils/is-graphql-error-of-type.util';
|
||||
|
||||
type AIChatErrorRendererProps = {
|
||||
error: AIChatError;
|
||||
};
|
||||
|
||||
export const AIChatErrorRenderer = ({ error }: AIChatErrorRendererProps) => {
|
||||
if (isGraphqlErrorOfType(error, AIChatErrorCode.BILLING_CREDITS_EXHAUSTED)) {
|
||||
return <AIChatCreditsExhaustedMessage />;
|
||||
}
|
||||
|
||||
if (isGraphqlErrorOfType(error, AIChatErrorCode.API_KEY_NOT_CONFIGURED)) {
|
||||
return <AIChatApiKeyNotConfiguredMessage />;
|
||||
}
|
||||
|
||||
return <AIChatErrorMessage error={error} />;
|
||||
};
|
||||
@@ -10,7 +10,7 @@ import { AGENT_CHAT_NEW_THREAD_DRAFT_KEY } from '@/ai/states/agentChatDraftsByTh
|
||||
import { agentChatFetchedMessagesComponentFamilyState } from '@/ai/states/agentChatFetchedMessagesComponentFamilyState';
|
||||
import { agentChatMessagesLoadingState } from '@/ai/states/agentChatMessagesLoadingState';
|
||||
import { agentChatQueuedMessagesComponentFamilyState } from '@/ai/states/agentChatQueuedMessagesComponentFamilyState';
|
||||
import { currentAIChatThreadState } from '@/ai/states/currentAIChatThreadState';
|
||||
import { currentAiChatThreadState } from '@/ai/states/currentAiChatThreadState';
|
||||
import { skipMessagesSkeletonUntilLoadedState } from '@/ai/states/skipMessagesSkeletonUntilLoadedState';
|
||||
import { mapDBMessagesToUIMessages } from '@/ai/utils/mapDBMessagesToUIMessages';
|
||||
import { useQueryWithCallbacks } from '@/apollo/hooks/useQueryWithCallbacks';
|
||||
@@ -26,13 +26,13 @@ import {
|
||||
|
||||
export const AgentChatMessagesFetchEffect = () => {
|
||||
const store = useStore();
|
||||
const currentAIChatThread = useAtomStateValue(currentAIChatThreadState);
|
||||
const currentAiChatThread = useAtomStateValue(currentAiChatThreadState);
|
||||
|
||||
const isNewThread = useMemo(
|
||||
() =>
|
||||
currentAIChatThread === null ||
|
||||
currentAIChatThread === AGENT_CHAT_NEW_THREAD_DRAFT_KEY,
|
||||
[currentAIChatThread],
|
||||
currentAiChatThread === null ||
|
||||
currentAiChatThread === AGENT_CHAT_NEW_THREAD_DRAFT_KEY,
|
||||
[currentAiChatThread],
|
||||
);
|
||||
|
||||
const setAgentChatMessagesLoading = useSetAtomState(
|
||||
@@ -45,12 +45,12 @@ export const AgentChatMessagesFetchEffect = () => {
|
||||
|
||||
const setAgentChatFetchedMessages = useSetAtomComponentFamilyState(
|
||||
agentChatFetchedMessagesComponentFamilyState,
|
||||
{ threadId: currentAIChatThread },
|
||||
{ threadId: currentAiChatThread },
|
||||
);
|
||||
|
||||
const setAgentChatQueuedMessages = useSetAtomComponentFamilyState(
|
||||
agentChatQueuedMessagesComponentFamilyState,
|
||||
{ threadId: currentAIChatThread },
|
||||
{ threadId: currentAiChatThread },
|
||||
);
|
||||
|
||||
const handleEventCallbackFamilyCallback =
|
||||
@@ -84,7 +84,7 @@ export const AgentChatMessagesFetchEffect = () => {
|
||||
return;
|
||||
}
|
||||
|
||||
const threadId = store.get(currentAIChatThreadState.atom);
|
||||
const threadId = store.get(currentAiChatThreadState.atom);
|
||||
|
||||
if (!isDefined(threadId)) {
|
||||
return;
|
||||
@@ -135,8 +135,8 @@ export const AgentChatMessagesFetchEffect = () => {
|
||||
const { refetch: refetchAgentChatMessages } = useQueryWithCallbacks(
|
||||
GetChatMessagesDocument,
|
||||
{
|
||||
variables: { threadId: currentAIChatThread ?? '' },
|
||||
skip: !isDefined(currentAIChatThread) || isNewThread,
|
||||
variables: { threadId: currentAiChatThread ?? '' },
|
||||
skip: !isDefined(currentAiChatThread) || isNewThread,
|
||||
onFirstLoad: handleFirstLoad,
|
||||
onDataLoaded: handleDataLoaded,
|
||||
onLoadingChange: handleLoadingChange,
|
||||
|
||||
+3
-3
@@ -1,6 +1,6 @@
|
||||
import { AI_CHAT_SCROLL_WRAPPER_ID } from '@/ai/constants/AiChatScrollWrapperId';
|
||||
import { agentChatIsInitialScrollPendingOnThreadChangeState } from '@/ai/states/agentChatIsInitialScrollPendingOnThreadChangeState';
|
||||
import { scrollAIChatToBottom } from '@/ai/utils/scrollAIChatToBottom';
|
||||
import { scrollAiChatToBottom } from '@/ai/utils/scrollAiChatToBottom';
|
||||
import { useAtomStateValue } from '@/ui/utilities/state/jotai/hooks/useAtomStateValue';
|
||||
import { useSetAtomState } from '@/ui/utilities/state/jotai/hooks/useSetAtomState';
|
||||
import { useEffect } from 'react';
|
||||
@@ -37,10 +37,10 @@ export const AgentChatScrollToBottomOnDisplayedThreadChangeLayoutEffect =
|
||||
clearTimeout(settleTimeoutId);
|
||||
}
|
||||
|
||||
scrollAIChatToBottom();
|
||||
scrollAiChatToBottom();
|
||||
|
||||
settleTimeoutId = setTimeout(() => {
|
||||
scrollAIChatToBottom();
|
||||
scrollAiChatToBottom();
|
||||
setAgentChatIsInitialScrollPendingOnThreadChange(false);
|
||||
mutationObserver.disconnect();
|
||||
}, SCROLL_SETTLE_DELAY_MS);
|
||||
|
||||
+10
-10
@@ -15,7 +15,7 @@ import { agentChatIsStreamingComponentFamilyState } from '@/ai/states/agentChatI
|
||||
import { agentChatMessagesComponentFamilyState } from '@/ai/states/agentChatMessagesComponentFamilyState';
|
||||
import { agentChatMessagesLoadingState } from '@/ai/states/agentChatMessagesLoadingState';
|
||||
import { agentChatThreadsLoadingState } from '@/ai/states/agentChatThreadsLoadingState';
|
||||
import { currentAIChatThreadState } from '@/ai/states/currentAIChatThreadState';
|
||||
import { currentAiChatThreadState } from '@/ai/states/currentAiChatThreadState';
|
||||
import { useListenToBrowserEvent } from '@/browser-event/hooks/useListenToBrowserEvent';
|
||||
import { useAtomComponentFamilyStateValue } from '@/ui/utilities/state/jotai/hooks/useAtomComponentFamilyStateValue';
|
||||
import { useAtomStateValue } from '@/ui/utilities/state/jotai/hooks/useAtomStateValue';
|
||||
@@ -23,7 +23,7 @@ import { useSetAtomComponentFamilyState } from '@/ui/utilities/state/jotai/hooks
|
||||
import { useSetAtomState } from '@/ui/utilities/state/jotai/hooks/useSetAtomState';
|
||||
|
||||
export const AgentChatStreamSubscriptionEffect = () => {
|
||||
const currentAIChatThread = useAtomStateValue(currentAIChatThreadState);
|
||||
const currentAiChatThread = useAtomStateValue(currentAiChatThreadState);
|
||||
|
||||
const { createChatThread } = useCreateAgentChatThread();
|
||||
|
||||
@@ -41,25 +41,25 @@ export const AgentChatStreamSubscriptionEffect = () => {
|
||||
useAgentChat(ensureThreadIdForSend);
|
||||
|
||||
const subscriptionThreadId =
|
||||
currentAIChatThread !== null && isValidUuid(currentAIChatThread)
|
||||
? currentAIChatThread
|
||||
currentAiChatThread !== null && isValidUuid(currentAiChatThread)
|
||||
? currentAiChatThread
|
||||
: null;
|
||||
|
||||
useAgentChatSubscription(subscriptionThreadId);
|
||||
|
||||
const agentChatFetchedMessages = useAtomComponentFamilyStateValue(
|
||||
agentChatFetchedMessagesComponentFamilyState,
|
||||
{ threadId: currentAIChatThread },
|
||||
{ threadId: currentAiChatThread },
|
||||
);
|
||||
|
||||
const setAgentChatMessages = useSetAtomComponentFamilyState(
|
||||
agentChatMessagesComponentFamilyState,
|
||||
{ threadId: currentAIChatThread },
|
||||
{ threadId: currentAiChatThread },
|
||||
);
|
||||
|
||||
const agentChatIsStreaming = useAtomComponentFamilyStateValue(
|
||||
agentChatIsStreamingComponentFamilyState,
|
||||
{ threadId: currentAIChatThread },
|
||||
{ threadId: currentAiChatThread },
|
||||
);
|
||||
|
||||
const agentChatDisplayedThread = useAtomStateValue(
|
||||
@@ -81,17 +81,17 @@ export const AgentChatStreamSubscriptionEffect = () => {
|
||||
|
||||
setAgentChatMessages(agentChatFetchedMessages);
|
||||
|
||||
if (currentAIChatThread !== agentChatDisplayedThread) {
|
||||
if (currentAiChatThread !== agentChatDisplayedThread) {
|
||||
if (agentChatFetchedMessages.length > 0) {
|
||||
setAgentChatIsInitialScrollPendingOnThreadChange(true);
|
||||
}
|
||||
setAgentChatDisplayedThread(currentAIChatThread);
|
||||
setAgentChatDisplayedThread(currentAiChatThread);
|
||||
}
|
||||
}, [
|
||||
agentChatFetchedMessages,
|
||||
agentChatIsStreaming,
|
||||
setAgentChatMessages,
|
||||
currentAIChatThread,
|
||||
currentAiChatThread,
|
||||
agentChatDisplayedThread,
|
||||
setAgentChatDisplayedThread,
|
||||
setAgentChatIsInitialScrollPendingOnThreadChange,
|
||||
|
||||
+5
-5
@@ -1,17 +1,17 @@
|
||||
import { agentChatIsScrolledToBottomSelector } from '@/ai/states/agentChatIsScrolledToBottomSelector';
|
||||
import { agentChatMessagesComponentFamilyState } from '@/ai/states/agentChatMessagesComponentFamilyState';
|
||||
import { currentAIChatThreadState } from '@/ai/states/currentAIChatThreadState';
|
||||
import { scrollAIChatToBottom } from '@/ai/utils/scrollAIChatToBottom';
|
||||
import { currentAiChatThreadState } from '@/ai/states/currentAiChatThreadState';
|
||||
import { scrollAiChatToBottom } from '@/ai/utils/scrollAiChatToBottom';
|
||||
import { useAtomComponentFamilyStateValue } from '@/ui/utilities/state/jotai/hooks/useAtomComponentFamilyStateValue';
|
||||
import { useAtomStateValue } from '@/ui/utilities/state/jotai/hooks/useAtomStateValue';
|
||||
import { useEffect } from 'react';
|
||||
|
||||
export const AgentChatStreamingAutoScrollEffect = () => {
|
||||
const currentAIChatThread = useAtomStateValue(currentAIChatThreadState);
|
||||
const currentAiChatThread = useAtomStateValue(currentAiChatThreadState);
|
||||
|
||||
const agentChatMessages = useAtomComponentFamilyStateValue(
|
||||
agentChatMessagesComponentFamilyState,
|
||||
{ threadId: currentAIChatThread },
|
||||
{ threadId: currentAiChatThread },
|
||||
);
|
||||
|
||||
const agentChatIsScrolledToBottom = useAtomStateValue(
|
||||
@@ -24,7 +24,7 @@ export const AgentChatStreamingAutoScrollEffect = () => {
|
||||
}
|
||||
|
||||
if (agentChatIsScrolledToBottom) {
|
||||
scrollAIChatToBottom();
|
||||
scrollAiChatToBottom();
|
||||
}
|
||||
}, [agentChatMessages, agentChatIsScrolledToBottom]);
|
||||
|
||||
|
||||
+5
-5
@@ -1,18 +1,18 @@
|
||||
import { useUpdateStreamingPartsWithDiff } from '@/ai/hooks/useUpdateStreamingPartsWithDiff';
|
||||
import { agentChatLastDiffSyncedThreadState } from '@/ai/states/agentChatLastDiffSyncedThreadState';
|
||||
import { agentChatMessagesComponentFamilyState } from '@/ai/states/agentChatMessagesComponentFamilyState';
|
||||
import { currentAIChatThreadState } from '@/ai/states/currentAIChatThreadState';
|
||||
import { currentAiChatThreadState } from '@/ai/states/currentAiChatThreadState';
|
||||
import { useAtomComponentFamilyStateValue } from '@/ui/utilities/state/jotai/hooks/useAtomComponentFamilyStateValue';
|
||||
import { useAtomStateValue } from '@/ui/utilities/state/jotai/hooks/useAtomStateValue';
|
||||
import { useSetAtomState } from '@/ui/utilities/state/jotai/hooks/useSetAtomState';
|
||||
import { useEffect } from 'react';
|
||||
|
||||
export const AgentChatStreamingPartsDiffSyncEffect = () => {
|
||||
const currentAIChatThread = useAtomStateValue(currentAIChatThreadState);
|
||||
const currentAiChatThread = useAtomStateValue(currentAiChatThreadState);
|
||||
|
||||
const agentChatMessages = useAtomComponentFamilyStateValue(
|
||||
agentChatMessagesComponentFamilyState,
|
||||
{ threadId: currentAIChatThread },
|
||||
{ threadId: currentAiChatThread },
|
||||
);
|
||||
|
||||
const { updateStreamingPartsWithDiff } = useUpdateStreamingPartsWithDiff();
|
||||
@@ -27,11 +27,11 @@ export const AgentChatStreamingPartsDiffSyncEffect = () => {
|
||||
}
|
||||
|
||||
updateStreamingPartsWithDiff(agentChatMessages);
|
||||
setAgentChatLastDiffSyncedThread(currentAIChatThread);
|
||||
setAgentChatLastDiffSyncedThread(currentAiChatThread);
|
||||
}, [
|
||||
agentChatMessages,
|
||||
updateStreamingPartsWithDiff,
|
||||
currentAIChatThread,
|
||||
currentAiChatThread,
|
||||
setAgentChatLastDiffSyncedThread,
|
||||
]);
|
||||
|
||||
|
||||
+10
-10
@@ -10,8 +10,8 @@ import { agentChatInputState } from '@/ai/states/agentChatInputState';
|
||||
import { agentChatThreadsLoadingState } from '@/ai/states/agentChatThreadsLoadingState';
|
||||
import { agentChatThreadsSelector } from '@/ai/states/agentChatThreadsSelector';
|
||||
import { agentChatUsageComponentFamilyState } from '@/ai/states/agentChatUsageComponentFamilyState';
|
||||
import { currentAIChatThreadState } from '@/ai/states/currentAIChatThreadState';
|
||||
import { currentAIChatThreadTitleComponentFamilyState } from '@/ai/states/currentAIChatThreadTitleComponentFamilyState';
|
||||
import { currentAiChatThreadState } from '@/ai/states/currentAiChatThreadState';
|
||||
import { currentAiChatThreadTitleComponentFamilyState } from '@/ai/states/currentAiChatThreadTitleComponentFamilyState';
|
||||
import { hasInitializedAgentChatThreadsState } from '@/ai/states/hasInitializedAgentChatThreadsState';
|
||||
import { hasTriggeredCreateForDraftState } from '@/ai/states/hasTriggeredCreateForDraftState';
|
||||
import { useUpdateMetadataStoreDraft } from '@/metadata-store/hooks/useUpdateMetadataStoreDraft';
|
||||
@@ -35,14 +35,14 @@ export const AgentChatThreadInitializationEffect = () => {
|
||||
PermissionFlagType.AI_SETTINGS,
|
||||
);
|
||||
|
||||
const currentAIChatThread = useAtomStateValue(currentAIChatThreadState);
|
||||
const setCurrentAIChatThread = useSetAtomState(currentAIChatThreadState);
|
||||
const currentAiChatThread = useAtomStateValue(currentAiChatThreadState);
|
||||
const setCurrentAiChatThread = useSetAtomState(currentAiChatThreadState);
|
||||
const setAgentChatInput = useSetAtomState(agentChatInputState);
|
||||
const setAgentChatThreadsLoading = useSetAtomState(
|
||||
agentChatThreadsLoadingState,
|
||||
);
|
||||
const threadTitleFamilyCallback = useAtomComponentFamilyStateCallbackState(
|
||||
currentAIChatThreadTitleComponentFamilyState,
|
||||
currentAiChatThreadTitleComponentFamilyState,
|
||||
);
|
||||
const agentChatUsageFamilyCallback = useAtomComponentFamilyStateCallbackState(
|
||||
agentChatUsageComponentFamilyState,
|
||||
@@ -93,7 +93,7 @@ export const AgentChatThreadInitializationEffect = () => {
|
||||
useEffect(() => {
|
||||
if (
|
||||
hasInitializedAgentChatThreads ||
|
||||
(currentAIChatThread !== null && isValidUuid(currentAIChatThread))
|
||||
(currentAiChatThread !== null && isValidUuid(currentAiChatThread))
|
||||
) {
|
||||
return;
|
||||
}
|
||||
@@ -114,7 +114,7 @@ export const AgentChatThreadInitializationEffect = () => {
|
||||
const draftForThread =
|
||||
store.get(agentChatDraftsByThreadIdState.atom)[firstThread.id] ?? '';
|
||||
|
||||
setCurrentAIChatThread(firstThread.id);
|
||||
setCurrentAiChatThread(firstThread.id);
|
||||
setAgentChatInput(draftForThread);
|
||||
|
||||
const firstThreadFamilyKey = { threadId: firstThread.id };
|
||||
@@ -144,7 +144,7 @@ export const AgentChatThreadInitializationEffect = () => {
|
||||
);
|
||||
} else {
|
||||
store.set(hasTriggeredCreateForDraftState.atom, false);
|
||||
setCurrentAIChatThread(AGENT_CHAT_NEW_THREAD_DRAFT_KEY);
|
||||
setCurrentAiChatThread(AGENT_CHAT_NEW_THREAD_DRAFT_KEY);
|
||||
setAgentChatInput(
|
||||
store.get(agentChatDraftsByThreadIdState.atom)[
|
||||
AGENT_CHAT_NEW_THREAD_DRAFT_KEY
|
||||
@@ -153,12 +153,12 @@ export const AgentChatThreadInitializationEffect = () => {
|
||||
}
|
||||
}, [
|
||||
agentChatThreads,
|
||||
currentAIChatThread,
|
||||
currentAiChatThread,
|
||||
hasAiSettingsPermission,
|
||||
hasInitializedAgentChatThreads,
|
||||
setHasInitializedAgentChatThreads,
|
||||
storeEntry.status,
|
||||
setCurrentAIChatThread,
|
||||
setCurrentAiChatThread,
|
||||
setAgentChatInput,
|
||||
store,
|
||||
threadTitleFamilyCallback,
|
||||
|
||||
+3
-3
@@ -1,17 +1,17 @@
|
||||
import { AIChatBanner } from '@/ai/components/AIChatBanner';
|
||||
import { AiChatBanner } from '@/ai/components/AiChatBanner';
|
||||
import { t } from '@lingui/core/macro';
|
||||
import { IconExternalLink } from 'twenty-ui/display';
|
||||
|
||||
const DOCS_URL =
|
||||
'https://twenty.com/developers/section/self-hosting/self-hosting-var#ai-features';
|
||||
|
||||
export const AIChatApiKeyNotConfiguredMessage = () => {
|
||||
export const AiChatApiKeyNotConfiguredMessage = () => {
|
||||
const handleDocsClick = () => {
|
||||
window.open(DOCS_URL, '_blank', 'noopener,noreferrer');
|
||||
};
|
||||
|
||||
return (
|
||||
<AIChatBanner
|
||||
<AiChatBanner
|
||||
message={t`AI not configured. Set OPENAI_API_KEY, ANTHROPIC_API_KEY, or XAI_API_KEY in your environment.`}
|
||||
variant="warning"
|
||||
buttonTitle={t`View Docs`}
|
||||
+3
-3
@@ -1,4 +1,4 @@
|
||||
import { AIChatCompactionIndicator } from '@/ai/components/AIChatCompactionIndicator';
|
||||
import { AiChatCompactionIndicator } from '@/ai/components/AiChatCompactionIndicator';
|
||||
import { CodeExecutionDisplay } from '@/ai/components/CodeExecutionDisplay';
|
||||
import { RoutingStatusDisplay } from '@/ai/components/RoutingStatusDisplay';
|
||||
import { ThinkingStepsDisplay } from '@/ai/components/ThinkingStepsDisplay';
|
||||
@@ -60,7 +60,7 @@ const MessagePartRenderer = ({
|
||||
case 'data-routing-status':
|
||||
return <RoutingStatusDisplay data={part.data} />;
|
||||
case 'data-compaction':
|
||||
return <AIChatCompactionIndicator />;
|
||||
return <AiChatCompactionIndicator />;
|
||||
case 'data-code-execution':
|
||||
return (
|
||||
<CodeExecutionDisplay
|
||||
@@ -87,7 +87,7 @@ const MessagePartRenderer = ({
|
||||
}
|
||||
};
|
||||
|
||||
export const AIChatAssistantMessageRenderer = ({
|
||||
export const AiChatAssistantMessageRenderer = ({
|
||||
messageParts,
|
||||
isLastMessageStreaming,
|
||||
hasError,
|
||||
+8
-8
@@ -9,9 +9,9 @@ import {
|
||||
import { Button } from 'twenty-ui/input';
|
||||
import { themeCssVariables } from 'twenty-ui/theme-constants';
|
||||
|
||||
type AIChatBannerVariant = 'default' | 'warning';
|
||||
type AiChatBannerVariant = 'default' | 'warning';
|
||||
|
||||
const StyledBanner = styled.div<{ variant: AIChatBannerVariant }>`
|
||||
const StyledBanner = styled.div<{ variant: AiChatBannerVariant }>`
|
||||
align-items: center;
|
||||
background-color: ${({ variant }) =>
|
||||
variant === 'warning'
|
||||
@@ -25,7 +25,7 @@ const StyledBanner = styled.div<{ variant: AIChatBannerVariant }>`
|
||||
width: 100%;
|
||||
`;
|
||||
|
||||
const StyledIconContainer = styled.div<{ variant: AIChatBannerVariant }>`
|
||||
const StyledIconContainer = styled.div<{ variant: AiChatBannerVariant }>`
|
||||
align-items: center;
|
||||
color: ${({ variant }) =>
|
||||
variant === 'warning'
|
||||
@@ -38,7 +38,7 @@ const StyledIconContainer = styled.div<{ variant: AIChatBannerVariant }>`
|
||||
width: 16px;
|
||||
`;
|
||||
|
||||
const StyledMessage = styled.p<{ variant: AIChatBannerVariant }>`
|
||||
const StyledMessage = styled.p<{ variant: AiChatBannerVariant }>`
|
||||
color: ${({ variant }) =>
|
||||
variant === 'warning'
|
||||
? themeCssVariables.color.orange
|
||||
@@ -53,9 +53,9 @@ const StyledMessage = styled.p<{ variant: AIChatBannerVariant }>`
|
||||
min-width: 0;
|
||||
`;
|
||||
|
||||
export type AIChatBannerProps = {
|
||||
export type AiChatBannerProps = {
|
||||
message: string;
|
||||
variant?: AIChatBannerVariant;
|
||||
variant?: AiChatBannerVariant;
|
||||
tooltipMessage?: string;
|
||||
buttonTitle?: string;
|
||||
buttonIcon?: IconComponent;
|
||||
@@ -64,7 +64,7 @@ export type AIChatBannerProps = {
|
||||
isButtonLoading?: boolean;
|
||||
};
|
||||
|
||||
export const AIChatBanner = ({
|
||||
export const AiChatBanner = ({
|
||||
message,
|
||||
variant = 'default',
|
||||
tooltipMessage,
|
||||
@@ -73,7 +73,7 @@ export const AIChatBanner = ({
|
||||
buttonOnClick,
|
||||
isButtonDisabled = false,
|
||||
isButtonLoading = false,
|
||||
}: AIChatBannerProps) => {
|
||||
}: AiChatBannerProps) => {
|
||||
const tooltipId = 'ai-chat-banner-tooltip';
|
||||
|
||||
return (
|
||||
+1
-1
@@ -16,7 +16,7 @@ const StyledIconTextContainer = styled.div`
|
||||
gap: ${themeCssVariables.spacing[1]};
|
||||
`;
|
||||
|
||||
export const AIChatCompactionIndicator = () => {
|
||||
export const AiChatCompactionIndicator = () => {
|
||||
const { theme } = useContext(ThemeContext);
|
||||
|
||||
return (
|
||||
+3
-3
@@ -1,4 +1,4 @@
|
||||
import { AIChatBanner } from '@/ai/components/AIChatBanner';
|
||||
import { AiChatBanner } from '@/ai/components/AiChatBanner';
|
||||
import { usePermissionFlagMap } from '@/settings/roles/hooks/usePermissionFlagMap';
|
||||
import { useSubscriptionStatus } from '@/workspace/hooks/useSubscriptionStatus';
|
||||
import { t } from '@lingui/core/macro';
|
||||
@@ -10,7 +10,7 @@ import {
|
||||
} from '~/generated-metadata/graphql';
|
||||
import { useNavigateSettings } from '~/hooks/useNavigateSettings';
|
||||
|
||||
export const AIChatCreditsExhaustedMessage = () => {
|
||||
export const AiChatCreditsExhaustedMessage = () => {
|
||||
const navigateSettings = useNavigateSettings();
|
||||
const subscriptionStatus = useSubscriptionStatus();
|
||||
|
||||
@@ -32,7 +32,7 @@ export const AIChatCreditsExhaustedMessage = () => {
|
||||
const buttonTitle = isTrialing ? t`Subscribe Now` : t`Upgrade Plan`;
|
||||
|
||||
return (
|
||||
<AIChatBanner
|
||||
<AiChatBanner
|
||||
message={message}
|
||||
variant="warning"
|
||||
buttonTitle={hasPermissionToManageBilling ? buttonTitle : undefined}
|
||||
+13
-13
@@ -2,15 +2,15 @@ import { styled } from '@linaria/react';
|
||||
import { EditorContent } from '@tiptap/react';
|
||||
import { themeCssVariables } from 'twenty-ui/theme-constants';
|
||||
|
||||
import { AIChatEmptyState } from '@/ai/components/AIChatEmptyState';
|
||||
import { AIChatStandaloneError } from '@/ai/components/AIChatStandaloneError';
|
||||
import { AiChatEmptyState } from '@/ai/components/AiChatEmptyState';
|
||||
import { AiChatStandaloneError } from '@/ai/components/AiChatStandaloneError';
|
||||
import { AgentChatContextPreview } from '@/ai/components/internal/AgentChatContextPreview';
|
||||
import { AgentChatFileUploadButton } from '@/ai/components/internal/AgentChatFileUploadButton';
|
||||
import { AIChatContextUsageButton } from '@/ai/components/internal/AIChatContextUsageButton';
|
||||
import { AIChatEditorFocusEffect } from '@/ai/components/internal/AIChatEditorFocusEffect';
|
||||
import { AIChatSkeletonLoader } from '@/ai/components/internal/AIChatSkeletonLoader';
|
||||
import { AiChatContextUsageButton } from '@/ai/components/internal/AiChatContextUsageButton';
|
||||
import { AiChatEditorFocusEffect } from '@/ai/components/internal/AiChatEditorFocusEffect';
|
||||
import { AiChatSkeletonLoader } from '@/ai/components/internal/AiChatSkeletonLoader';
|
||||
import { SendMessageButton } from '@/ai/components/internal/SendMessageButton';
|
||||
import { useAIChatEditor } from '@/ai/hooks/useAIChatEditor';
|
||||
import { useAiChatEditor } from '@/ai/hooks/useAiChatEditor';
|
||||
import { useAiModelOptions } from '@/ai/hooks/useAiModelOptions';
|
||||
import { useAgentChatModelId } from '@/ai/hooks/useAgentChatModelId';
|
||||
import { agentChatUserSelectedModelState } from '@/ai/states/agentChatUserSelectedModelState';
|
||||
@@ -104,7 +104,7 @@ const StyledRightButtonsContainer = styled.div`
|
||||
gap: ${themeCssVariables.spacing[1]};
|
||||
`;
|
||||
|
||||
export const AIChatEditorSection = () => {
|
||||
export const AiChatEditorSection = () => {
|
||||
const isMobile = useIsMobile();
|
||||
const { options, pinnedOption } = useAiModelOptions({
|
||||
variant: 'pinned-default',
|
||||
@@ -123,14 +123,14 @@ export const AIChatEditorSection = () => {
|
||||
);
|
||||
const { selectedModelId } = useAgentChatModelId();
|
||||
|
||||
const { editor, handleSendAndClear } = useAIChatEditor();
|
||||
const { editor, handleSendAndClear } = useAiChatEditor();
|
||||
|
||||
return (
|
||||
<>
|
||||
<AIChatEditorFocusEffect editor={editor} />
|
||||
<AIChatEmptyState editor={editor} />
|
||||
<AIChatStandaloneError />
|
||||
<AIChatSkeletonLoader />
|
||||
<AiChatEditorFocusEffect editor={editor} />
|
||||
<AiChatEmptyState editor={editor} />
|
||||
<AiChatStandaloneError />
|
||||
<AiChatSkeletonLoader />
|
||||
|
||||
<StyledInputArea isMobile={isMobile}>
|
||||
<AgentChatContextPreview />
|
||||
@@ -141,7 +141,7 @@ export const AIChatEditorSection = () => {
|
||||
<StyledButtonsContainer>
|
||||
<StyledLeftButtonsContainer>
|
||||
<AgentChatFileUploadButton />
|
||||
<AIChatContextUsageButton />
|
||||
<AiChatContextUsageButton />
|
||||
</StyledLeftButtonsContainer>
|
||||
<StyledRightButtonsContainer>
|
||||
<Select
|
||||
+8
-8
@@ -2,13 +2,13 @@ import { styled } from '@linaria/react';
|
||||
import { type Editor } from '@tiptap/react';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
import { AIChatSuggestedPrompts } from '@/ai/components/suggested-prompts/AIChatSuggestedPrompts';
|
||||
import { AiChatSuggestedPrompts } from '@/ai/components/suggested-prompts/AiChatSuggestedPrompts';
|
||||
import { AGENT_CHAT_NEW_THREAD_DRAFT_KEY } from '@/ai/states/agentChatDraftsByThreadIdState';
|
||||
import { agentChatErrorComponentFamilyState } from '@/ai/states/agentChatErrorComponentFamilyState';
|
||||
import { agentChatHasMessageComponentSelector } from '@/ai/states/agentChatHasMessageComponentSelector';
|
||||
import { agentChatMessagesLoadingState } from '@/ai/states/agentChatMessagesLoadingState';
|
||||
import { agentChatThreadsLoadingState } from '@/ai/states/agentChatThreadsLoadingState';
|
||||
import { currentAIChatThreadState } from '@/ai/states/currentAIChatThreadState';
|
||||
import { currentAiChatThreadState } from '@/ai/states/currentAiChatThreadState';
|
||||
import { skipMessagesSkeletonUntilLoadedState } from '@/ai/states/skipMessagesSkeletonUntilLoadedState';
|
||||
import { useAtomComponentFamilyStateValue } from '@/ui/utilities/state/jotai/hooks/useAtomComponentFamilyStateValue';
|
||||
import { useAtomComponentSelectorValue } from '@/ui/utilities/state/jotai/hooks/useAtomComponentSelectorValue';
|
||||
@@ -22,15 +22,15 @@ const StyledEmptyState = styled.div`
|
||||
justify-content: flex-end;
|
||||
`;
|
||||
|
||||
type AIChatEmptyStateProps = {
|
||||
type AiChatEmptyStateProps = {
|
||||
editor: Editor | null;
|
||||
};
|
||||
|
||||
export const AIChatEmptyState = ({ editor }: AIChatEmptyStateProps) => {
|
||||
const currentAIChatThread = useAtomStateValue(currentAIChatThreadState);
|
||||
export const AiChatEmptyState = ({ editor }: AiChatEmptyStateProps) => {
|
||||
const currentAiChatThread = useAtomStateValue(currentAiChatThreadState);
|
||||
const agentChatError = useAtomComponentFamilyStateValue(
|
||||
agentChatErrorComponentFamilyState,
|
||||
{ threadId: currentAIChatThread },
|
||||
{ threadId: currentAiChatThread },
|
||||
);
|
||||
const agentChatThreadsLoading = useAtomStateValue(
|
||||
agentChatThreadsLoadingState,
|
||||
@@ -47,7 +47,7 @@ export const AIChatEmptyState = ({ editor }: AIChatEmptyStateProps) => {
|
||||
);
|
||||
|
||||
const isOnNewChatSlot =
|
||||
currentAIChatThread === AGENT_CHAT_NEW_THREAD_DRAFT_KEY;
|
||||
currentAiChatThread === AGENT_CHAT_NEW_THREAD_DRAFT_KEY;
|
||||
const skeletonShowing =
|
||||
(agentChatThreadsLoading && isOnNewChatSlot) ||
|
||||
(agentChatMessagesLoading && !skipMessagesSkeletonUntilLoaded);
|
||||
@@ -60,7 +60,7 @@ export const AIChatEmptyState = ({ editor }: AIChatEmptyStateProps) => {
|
||||
|
||||
return (
|
||||
<StyledEmptyState>
|
||||
<AIChatSuggestedPrompts editor={editor} />
|
||||
<AiChatSuggestedPrompts editor={editor} />
|
||||
</StyledEmptyState>
|
||||
);
|
||||
};
|
||||
+4
-4
@@ -4,7 +4,7 @@ import { t } from '@lingui/core/macro';
|
||||
import { IconAlertCircle } from 'twenty-ui/display';
|
||||
import { useContext } from 'react';
|
||||
|
||||
import { type AIChatError } from '@/ai/types/AIChatError';
|
||||
import { type AiChatError } from '@/ai/types/AiChatError';
|
||||
import { ThemeContext, themeCssVariables } from 'twenty-ui/theme-constants';
|
||||
import { getErrorMessageFromApolloError } from '~/utils/get-error-message-from-apollo-error.util';
|
||||
|
||||
@@ -43,11 +43,11 @@ const StyledErrorMessage = styled.div`
|
||||
word-break: break-word;
|
||||
`;
|
||||
|
||||
type AIChatErrorMessageProps = {
|
||||
error: AIChatError;
|
||||
type AiChatErrorMessageProps = {
|
||||
error: AiChatError;
|
||||
};
|
||||
|
||||
export const AIChatErrorMessage = ({ error }: AIChatErrorMessageProps) => {
|
||||
export const AiChatErrorMessage = ({ error }: AiChatErrorMessageProps) => {
|
||||
const { theme } = useContext(ThemeContext);
|
||||
const errorMessage = CombinedGraphQLErrors.is(error)
|
||||
? getErrorMessageFromApolloError(error)
|
||||
@@ -0,0 +1,22 @@
|
||||
import { AiChatApiKeyNotConfiguredMessage } from '@/ai/components/AiChatApiKeyNotConfiguredMessage';
|
||||
import { AiChatCreditsExhaustedMessage } from '@/ai/components/AiChatCreditsExhaustedMessage';
|
||||
import { AiChatErrorMessage } from '@/ai/components/AiChatErrorMessage';
|
||||
import { type AiChatError } from '@/ai/types/AiChatError';
|
||||
import { AiChatErrorCode } from '@/ai/utils/aiChatErrorCode';
|
||||
import { isGraphqlErrorOfType } from '~/utils/is-graphql-error-of-type.util';
|
||||
|
||||
type AiChatErrorRendererProps = {
|
||||
error: AiChatError;
|
||||
};
|
||||
|
||||
export const AiChatErrorRenderer = ({ error }: AiChatErrorRendererProps) => {
|
||||
if (isGraphqlErrorOfType(error, AiChatErrorCode.BILLING_CREDITS_EXHAUSTED)) {
|
||||
return <AiChatCreditsExhaustedMessage />;
|
||||
}
|
||||
|
||||
if (isGraphqlErrorOfType(error, AiChatErrorCode.API_KEY_NOT_CONFIGURED)) {
|
||||
return <AiChatApiKeyNotConfiguredMessage />;
|
||||
}
|
||||
|
||||
return <AiChatErrorMessage error={error} />;
|
||||
};
|
||||
+3
-3
@@ -1,4 +1,4 @@
|
||||
import { AIChatErrorRenderer } from '@/ai/components/AIChatErrorRenderer';
|
||||
import { AiChatErrorRenderer } from '@/ai/components/AiChatErrorRenderer';
|
||||
import { AgentMessageRole } from '@/ai/constants/AgentMessageRole';
|
||||
import { agentChatDisplayedThreadState } from '@/ai/states/agentChatDisplayedThreadState';
|
||||
import { agentChatErrorComponentFamilyState } from '@/ai/states/agentChatErrorComponentFamilyState';
|
||||
@@ -16,7 +16,7 @@ const StyledErrorWrapper = styled.div`
|
||||
padding-top: ${themeCssVariables.spacing[3]};
|
||||
`;
|
||||
|
||||
export const AIChatErrorUnderMessageList = () => {
|
||||
export const AiChatErrorUnderMessageList = () => {
|
||||
const agentChatDisplayedThread = useAtomStateValue(
|
||||
agentChatDisplayedThreadState,
|
||||
);
|
||||
@@ -50,7 +50,7 @@ export const AIChatErrorUnderMessageList = () => {
|
||||
|
||||
return (
|
||||
<StyledErrorWrapper>
|
||||
<AIChatErrorRenderer error={agentChatError} />
|
||||
<AiChatErrorRenderer error={agentChatError} />
|
||||
</StyledErrorWrapper>
|
||||
);
|
||||
};
|
||||
+3
-3
@@ -1,4 +1,4 @@
|
||||
import { AIChatMessage } from '@/ai/components/AIChatMessage';
|
||||
import { AiChatMessage } from '@/ai/components/AiChatMessage';
|
||||
import { agentChatDisplayedThreadState } from '@/ai/states/agentChatDisplayedThreadState';
|
||||
import { agentChatErrorComponentFamilyState } from '@/ai/states/agentChatErrorComponentFamilyState';
|
||||
import { agentChatIsStreamingComponentFamilyState } from '@/ai/states/agentChatIsStreamingComponentFamilyState';
|
||||
@@ -8,7 +8,7 @@ import { useAtomComponentSelectorValue } from '@/ui/utilities/state/jotai/hooks/
|
||||
import { useAtomStateValue } from '@/ui/utilities/state/jotai/hooks/useAtomStateValue';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
export const AIChatLastMessageWithStreamingState = () => {
|
||||
export const AiChatLastMessageWithStreamingState = () => {
|
||||
const lastMessageId = useAtomComponentSelectorValue(
|
||||
agentChatLastMessageIdComponentSelector,
|
||||
);
|
||||
@@ -30,7 +30,7 @@ export const AIChatLastMessageWithStreamingState = () => {
|
||||
}
|
||||
|
||||
return (
|
||||
<AIChatMessage
|
||||
<AiChatMessage
|
||||
messageId={lastMessageId}
|
||||
isLastMessageStreaming={agentChatIsStreaming}
|
||||
error={agentChatError ?? undefined}
|
||||
+9
-9
@@ -3,10 +3,10 @@ import { styled } from '@linaria/react';
|
||||
import { AgentChatFilePreview } from '@/ai/components/internal/AgentChatFilePreview';
|
||||
import { AgentMessageRole } from '@/ai/constants/AgentMessageRole';
|
||||
|
||||
import { AIChatAssistantMessageRenderer } from '@/ai/components/AIChatAssistantMessageRenderer';
|
||||
import { AIChatErrorRenderer } from '@/ai/components/AIChatErrorRenderer';
|
||||
import { AiChatAssistantMessageRenderer } from '@/ai/components/AiChatAssistantMessageRenderer';
|
||||
import { AiChatErrorRenderer } from '@/ai/components/AiChatErrorRenderer';
|
||||
import { agentChatMessageComponentFamilySelector } from '@/ai/states/agentChatMessageComponentFamilySelector';
|
||||
import { type AIChatError } from '@/ai/types/AIChatError';
|
||||
import { type AiChatError } from '@/ai/types/AiChatError';
|
||||
import { LightCopyIconButton } from '@/object-record/record-field/ui/components/LightCopyIconButton';
|
||||
import { useAtomComponentFamilySelectorValue } from '@/ui/utilities/state/jotai/hooks/useAtomComponentFamilySelectorValue';
|
||||
import { useAtomStateValue } from '@/ui/utilities/state/jotai/hooks/useAtomStateValue';
|
||||
@@ -140,17 +140,17 @@ const StyledFilesContainer = styled.div`
|
||||
margin-top: ${themeCssVariables.spacing[2]};
|
||||
`;
|
||||
|
||||
type AIChatMessageProps = {
|
||||
type AiChatMessageProps = {
|
||||
messageId: string;
|
||||
isLastMessageStreaming?: boolean;
|
||||
error?: AIChatError | undefined;
|
||||
error?: AiChatError | undefined;
|
||||
};
|
||||
|
||||
export const AIChatMessage = ({
|
||||
export const AiChatMessage = ({
|
||||
messageId,
|
||||
isLastMessageStreaming = false,
|
||||
error,
|
||||
}: AIChatMessageProps) => {
|
||||
}: AiChatMessageProps) => {
|
||||
const agentChatMessage = useAtomComponentFamilySelectorValue(
|
||||
agentChatMessageComponentFamilySelector,
|
||||
{ messageId },
|
||||
@@ -173,7 +173,7 @@ export const AIChatMessage = ({
|
||||
<StyledMessageBubble isUser={isUser}>
|
||||
<StyledMessageContainer isUser={isUser}>
|
||||
<StyledMessageText isUser={isUser}>
|
||||
<AIChatAssistantMessageRenderer
|
||||
<AiChatAssistantMessageRenderer
|
||||
isLastMessageStreaming={isLastMessageStreaming}
|
||||
messageParts={agentChatMessage.parts}
|
||||
hasError={shouldShowError}
|
||||
@@ -187,7 +187,7 @@ export const AIChatMessage = ({
|
||||
</StyledFilesContainer>
|
||||
)}
|
||||
{shouldShowError && isDefined(error) && (
|
||||
<AIChatErrorRenderer error={error} />
|
||||
<AiChatErrorRenderer error={error} />
|
||||
)}
|
||||
</StyledMessageContainer>
|
||||
{agentChatMessage.parts.length > 0 && (
|
||||
+3
-3
@@ -1,13 +1,13 @@
|
||||
import { AIChatMessage } from '@/ai/components/AIChatMessage';
|
||||
import { AiChatMessage } from '@/ai/components/AiChatMessage';
|
||||
import { agentChatNonLastMessageIdsComponentSelector } from '@/ai/states/agentChatNonLastMessageIdsComponentSelector';
|
||||
import { useAtomComponentSelectorValue } from '@/ui/utilities/state/jotai/hooks/useAtomComponentSelectorValue';
|
||||
|
||||
export const AIChatNonLastMessageIdsList = () => {
|
||||
export const AiChatNonLastMessageIdsList = () => {
|
||||
const agentChatNonLastMessageIds = useAtomComponentSelectorValue(
|
||||
agentChatNonLastMessageIdsComponentSelector,
|
||||
);
|
||||
|
||||
return agentChatNonLastMessageIds.map((messageId) => (
|
||||
<AIChatMessage key={messageId} messageId={messageId} />
|
||||
<AiChatMessage key={messageId} messageId={messageId} />
|
||||
));
|
||||
};
|
||||
+5
-5
@@ -1,7 +1,7 @@
|
||||
import { styled } from '@linaria/react';
|
||||
|
||||
import { agentChatQueuedMessagesComponentFamilyState } from '@/ai/states/agentChatQueuedMessagesComponentFamilyState';
|
||||
import { currentAIChatThreadState } from '@/ai/states/currentAIChatThreadState';
|
||||
import { currentAiChatThreadState } from '@/ai/states/currentAiChatThreadState';
|
||||
import { useDeleteQueuedMessage } from '@/ai/hooks/useDeleteQueuedMessage';
|
||||
import { useAtomComponentFamilyStateValue } from '@/ui/utilities/state/jotai/hooks/useAtomComponentFamilyStateValue';
|
||||
import { useAtomStateValue } from '@/ui/utilities/state/jotai/hooks/useAtomStateValue';
|
||||
@@ -41,15 +41,15 @@ const StyledQueuedText = styled.span`
|
||||
white-space: nowrap;
|
||||
`;
|
||||
|
||||
export const AIChatQueuedMessages = () => {
|
||||
const currentAIChatThread = useAtomStateValue(currentAIChatThreadState);
|
||||
export const AiChatQueuedMessages = () => {
|
||||
const currentAiChatThread = useAtomStateValue(currentAiChatThreadState);
|
||||
const agentChatQueuedMessages = useAtomComponentFamilyStateValue(
|
||||
agentChatQueuedMessagesComponentFamilyState,
|
||||
{ threadId: currentAIChatThread },
|
||||
{ threadId: currentAiChatThread },
|
||||
);
|
||||
const { deleteQueuedMessage } = useDeleteQueuedMessage();
|
||||
|
||||
if (!isDefined(currentAIChatThread) || agentChatQueuedMessages.length === 0) {
|
||||
if (!isDefined(currentAiChatThread) || agentChatQueuedMessages.length === 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
+3
-3
@@ -1,5 +1,5 @@
|
||||
import { agentChatIsScrolledToBottomSelector } from '@/ai/states/agentChatIsScrolledToBottomSelector';
|
||||
import { scrollAIChatToBottom } from '@/ai/utils/scrollAIChatToBottom';
|
||||
import { scrollAiChatToBottom } from '@/ai/utils/scrollAiChatToBottom';
|
||||
import { useAtomStateValue } from '@/ui/utilities/state/jotai/hooks/useAtomStateValue';
|
||||
import { styled } from '@linaria/react';
|
||||
import { IconArrowDown } from 'twenty-ui/display';
|
||||
@@ -33,7 +33,7 @@ const StyledScrollToBottomButton = styled.button<{ isVisible: boolean }>`
|
||||
}
|
||||
`;
|
||||
|
||||
export const AIChatScrollToBottomButton = () => {
|
||||
export const AiChatScrollToBottomButton = () => {
|
||||
const agentChatIsScrolledToBottom = useAtomStateValue(
|
||||
agentChatIsScrolledToBottomSelector,
|
||||
);
|
||||
@@ -41,7 +41,7 @@ export const AIChatScrollToBottomButton = () => {
|
||||
return (
|
||||
<StyledScrollToBottomButton
|
||||
isVisible={!agentChatIsScrolledToBottom}
|
||||
onClick={scrollAIChatToBottom}
|
||||
onClick={scrollAiChatToBottom}
|
||||
>
|
||||
<IconArrowDown size={16} />
|
||||
</StyledScrollToBottomButton>
|
||||
+6
-6
@@ -1,11 +1,11 @@
|
||||
import { styled } from '@linaria/react';
|
||||
import { themeCssVariables } from 'twenty-ui/theme-constants';
|
||||
|
||||
import { AIChatErrorRenderer } from '@/ai/components/AIChatErrorRenderer';
|
||||
import { AiChatErrorRenderer } from '@/ai/components/AiChatErrorRenderer';
|
||||
import { agentChatErrorComponentFamilyState } from '@/ai/states/agentChatErrorComponentFamilyState';
|
||||
import { agentChatHasMessageComponentSelector } from '@/ai/states/agentChatHasMessageComponentSelector';
|
||||
import { agentChatIsLoadingState } from '@/ai/states/agentChatIsLoadingState';
|
||||
import { currentAIChatThreadState } from '@/ai/states/currentAIChatThreadState';
|
||||
import { currentAiChatThreadState } from '@/ai/states/currentAiChatThreadState';
|
||||
import { useAtomComponentFamilyStateValue } from '@/ui/utilities/state/jotai/hooks/useAtomComponentFamilyStateValue';
|
||||
import { useAtomComponentSelectorValue } from '@/ui/utilities/state/jotai/hooks/useAtomComponentSelectorValue';
|
||||
import { useAtomStateValue } from '@/ui/utilities/state/jotai/hooks/useAtomStateValue';
|
||||
@@ -20,13 +20,13 @@ const StyledErrorContainer = styled.div`
|
||||
width: 100%;
|
||||
`;
|
||||
|
||||
export const AIChatStandaloneError = () => {
|
||||
export const AiChatStandaloneError = () => {
|
||||
const agentChatIsLoading = useAtomStateValue(agentChatIsLoadingState);
|
||||
|
||||
const currentAIChatThread = useAtomStateValue(currentAIChatThreadState);
|
||||
const currentAiChatThread = useAtomStateValue(currentAiChatThreadState);
|
||||
const agentChatError = useAtomComponentFamilyStateValue(
|
||||
agentChatErrorComponentFamilyState,
|
||||
{ threadId: currentAIChatThread },
|
||||
{ threadId: currentAiChatThread },
|
||||
);
|
||||
|
||||
const hasMessages = useAtomComponentSelectorValue(
|
||||
@@ -42,7 +42,7 @@ export const AIChatStandaloneError = () => {
|
||||
|
||||
return (
|
||||
<StyledErrorContainer>
|
||||
<AIChatErrorRenderer error={agentChatError} />
|
||||
<AiChatErrorRenderer error={agentChatError} />
|
||||
</StyledErrorContainer>
|
||||
);
|
||||
};
|
||||
+12
-12
@@ -3,15 +3,15 @@ import { useState } from 'react';
|
||||
import { themeCssVariables } from 'twenty-ui/theme-constants';
|
||||
|
||||
import { DropZone } from '@/activities/files/components/DropZone';
|
||||
import { AIChatEditorSection } from '@/ai/components/AIChatEditorSection';
|
||||
import { useAIChatFileUpload } from '@/ai/hooks/useAIChatFileUpload';
|
||||
import { AiChatEditorSection } from '@/ai/components/AiChatEditorSection';
|
||||
import { useAiChatFileUpload } from '@/ai/hooks/useAiChatFileUpload';
|
||||
import { AGENT_CHAT_NEW_THREAD_DRAFT_KEY } from '@/ai/states/agentChatDraftsByThreadIdState';
|
||||
import { currentAIChatThreadState } from '@/ai/states/currentAIChatThreadState';
|
||||
import { currentAiChatThreadState } from '@/ai/states/currentAiChatThreadState';
|
||||
import { threadIdCreatedFromDraftState } from '@/ai/states/threadIdCreatedFromDraftState';
|
||||
import { useAtomStateValue } from '@/ui/utilities/state/jotai/hooks/useAtomStateValue';
|
||||
|
||||
import { AIChatQueuedMessages } from '@/ai/components/AIChatQueuedMessages';
|
||||
import { AIChatTabMessageList } from '@/ai/components/AIChatTabMessageList';
|
||||
import { AiChatQueuedMessages } from '@/ai/components/AiChatQueuedMessages';
|
||||
import { AiChatTabMessageList } from '@/ai/components/AiChatTabMessageList';
|
||||
|
||||
const StyledContainer = styled.div<{ isDraggingFile: boolean }>`
|
||||
background: ${themeCssVariables.background.primary};
|
||||
@@ -23,20 +23,20 @@ const StyledContainer = styled.div<{ isDraggingFile: boolean }>`
|
||||
isDraggingFile ? themeCssVariables.spacing[3] : '0'};
|
||||
`;
|
||||
|
||||
export const AIChatTab = () => {
|
||||
export const AiChatTab = () => {
|
||||
const [isDraggingFile, setIsDraggingFile] = useState(false);
|
||||
const currentAIChatThread = useAtomStateValue(currentAIChatThreadState);
|
||||
const currentAiChatThread = useAtomStateValue(currentAiChatThreadState);
|
||||
const threadIdCreatedFromDraft = useAtomStateValue(
|
||||
threadIdCreatedFromDraftState,
|
||||
);
|
||||
const draftKey = currentAIChatThread ?? AGENT_CHAT_NEW_THREAD_DRAFT_KEY;
|
||||
const draftKey = currentAiChatThread ?? AGENT_CHAT_NEW_THREAD_DRAFT_KEY;
|
||||
const editorSectionKey =
|
||||
draftKey !== AGENT_CHAT_NEW_THREAD_DRAFT_KEY &&
|
||||
draftKey === threadIdCreatedFromDraft
|
||||
? AGENT_CHAT_NEW_THREAD_DRAFT_KEY
|
||||
: draftKey;
|
||||
|
||||
const { uploadFiles } = useAIChatFileUpload();
|
||||
const { uploadFiles } = useAiChatFileUpload();
|
||||
|
||||
return (
|
||||
<StyledContainer
|
||||
@@ -52,9 +52,9 @@ export const AIChatTab = () => {
|
||||
)}
|
||||
{!isDraggingFile && (
|
||||
<>
|
||||
<AIChatTabMessageList />
|
||||
<AIChatQueuedMessages />
|
||||
<AIChatEditorSection key={editorSectionKey} />
|
||||
<AiChatTabMessageList />
|
||||
<AiChatQueuedMessages />
|
||||
<AiChatEditorSection key={editorSectionKey} />
|
||||
</>
|
||||
)}
|
||||
</StyledContainer>
|
||||
+9
-9
@@ -1,7 +1,7 @@
|
||||
import { AIChatErrorUnderMessageList } from '@/ai/components/AIChatErrorUnderMessageList';
|
||||
import { AIChatLastMessageWithStreamingState } from '@/ai/components/AIChatLastMessageWithStreamingState';
|
||||
import { AIChatNonLastMessageIdsList } from '@/ai/components/AIChatNonLastMessageIdsList';
|
||||
import { AIChatScrollToBottomButton } from '@/ai/components/AIChatScrollToBottomButton';
|
||||
import { AiChatErrorUnderMessageList } from '@/ai/components/AiChatErrorUnderMessageList';
|
||||
import { AiChatLastMessageWithStreamingState } from '@/ai/components/AiChatLastMessageWithStreamingState';
|
||||
import { AiChatNonLastMessageIdsList } from '@/ai/components/AiChatNonLastMessageIdsList';
|
||||
import { AiChatScrollToBottomButton } from '@/ai/components/AiChatScrollToBottomButton';
|
||||
import { AgentChatScrollToBottomOnDisplayedThreadChangeLayoutEffect } from '@/ai/components/AgentChatScrollToBottomOnDisplayedThreadChangeLayoutEffect';
|
||||
import { AI_CHAT_SCROLL_WRAPPER_ID } from '@/ai/constants/AiChatScrollWrapperId';
|
||||
import { agentChatHasMessageComponentSelector } from '@/ai/states/agentChatHasMessageComponentSelector';
|
||||
@@ -23,7 +23,7 @@ const StyledScrollWrapperContainer = styled.div`
|
||||
width: calc(100% - 24px);
|
||||
`;
|
||||
|
||||
export const AIChatTabMessageList = () => {
|
||||
export const AiChatTabMessageList = () => {
|
||||
const agentChatHasMessage = useAtomComponentSelectorValue(
|
||||
agentChatHasMessageComponentSelector,
|
||||
);
|
||||
@@ -45,12 +45,12 @@ export const AIChatTabMessageList = () => {
|
||||
}}
|
||||
>
|
||||
<ScrollWrapper componentInstanceId={AI_CHAT_SCROLL_WRAPPER_ID}>
|
||||
<AIChatNonLastMessageIdsList />
|
||||
<AIChatLastMessageWithStreamingState />
|
||||
<AIChatErrorUnderMessageList />
|
||||
<AiChatNonLastMessageIdsList />
|
||||
<AiChatLastMessageWithStreamingState />
|
||||
<AiChatErrorUnderMessageList />
|
||||
<AgentChatScrollToBottomOnDisplayedThreadChangeLayoutEffect />
|
||||
</ScrollWrapper>
|
||||
<AIChatScrollToBottomButton />
|
||||
<AiChatScrollToBottomButton />
|
||||
</StyledScrollWrapperContainer>
|
||||
);
|
||||
};
|
||||
+3
-3
@@ -1,4 +1,4 @@
|
||||
import { useAIChatThreadClick } from '@/ai/hooks/useAIChatThreadClick';
|
||||
import { useAiChatThreadClick } from '@/ai/hooks/useAiChatThreadClick';
|
||||
import { styled } from '@linaria/react';
|
||||
import { useLingui } from '@lingui/react/macro';
|
||||
import { useContext } from 'react';
|
||||
@@ -65,7 +65,7 @@ const StyledThreadTitle = styled.div`
|
||||
white-space: nowrap;
|
||||
`;
|
||||
|
||||
export const AIChatThreadGroup = ({
|
||||
export const AiChatThreadGroup = ({
|
||||
threads,
|
||||
title,
|
||||
}: {
|
||||
@@ -74,7 +74,7 @@ export const AIChatThreadGroup = ({
|
||||
}) => {
|
||||
const { theme } = useContext(ThemeContext);
|
||||
const { t } = useLingui();
|
||||
const { handleThreadClick } = useAIChatThreadClick();
|
||||
const { handleThreadClick } = useAiChatThreadClick();
|
||||
|
||||
if (threads.length === 0) {
|
||||
return null;
|
||||
+9
-9
@@ -1,10 +1,10 @@
|
||||
import { styled } from '@linaria/react';
|
||||
|
||||
import { AIChatThreadGroup } from '@/ai/components/AIChatThreadGroup';
|
||||
import { AIChatThreadsListFocusEffect } from '@/ai/components/AIChatThreadsListFocusEffect';
|
||||
import { AIChatSkeletonLoader } from '@/ai/components/internal/AIChatSkeletonLoader';
|
||||
import { AiChatThreadGroup } from '@/ai/components/AiChatThreadGroup';
|
||||
import { AiChatThreadsListFocusEffect } from '@/ai/components/AiChatThreadsListFocusEffect';
|
||||
import { AiChatSkeletonLoader } from '@/ai/components/internal/AiChatSkeletonLoader';
|
||||
import { useChatThreads } from '@/ai/hooks/useChatThreads';
|
||||
import { useSwitchToNewAIChat } from '@/ai/hooks/useSwitchToNewAIChat';
|
||||
import { useSwitchToNewAiChat } from '@/ai/hooks/useSwitchToNewAiChat';
|
||||
import { groupThreadsByDate } from '@/ai/utils/groupThreadsByDate';
|
||||
import { useHotkeysOnFocusedElement } from '@/ui/utilities/hotkey/hooks/useHotkeysOnFocusedElement';
|
||||
import { t } from '@lingui/core/macro';
|
||||
@@ -35,8 +35,8 @@ const StyledButtonsContainer = styled.div`
|
||||
padding: ${themeCssVariables.spacing[2]} 10px;
|
||||
`;
|
||||
|
||||
export const AIChatThreadsList = () => {
|
||||
const { switchToNewChat } = useSwitchToNewAIChat();
|
||||
export const AiChatThreadsList = () => {
|
||||
const { switchToNewChat } = useSwitchToNewAiChat();
|
||||
|
||||
const focusId = 'threads-list';
|
||||
|
||||
@@ -52,16 +52,16 @@ export const AIChatThreadsList = () => {
|
||||
const groupedThreads = groupThreadsByDate(threads);
|
||||
|
||||
if (loading && threads.length === 0) {
|
||||
return <AIChatSkeletonLoader />;
|
||||
return <AiChatSkeletonLoader />;
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<AIChatThreadsListFocusEffect focusId={focusId} />
|
||||
<AiChatThreadsListFocusEffect focusId={focusId} />
|
||||
<StyledContainer>
|
||||
<StyledThreadsContainer>
|
||||
{Object.entries(groupedThreads).map(([title, threadsInGroup]) => (
|
||||
<AIChatThreadGroup
|
||||
<AiChatThreadGroup
|
||||
key={title}
|
||||
title={capitalize(title)}
|
||||
threads={threadsInGroup}
|
||||
+1
-1
@@ -3,7 +3,7 @@ import { useRemoveFocusItemFromFocusStackById } from '@/ui/utilities/focus/hooks
|
||||
import { FocusComponentType } from '@/ui/utilities/focus/types/FocusComponentType';
|
||||
import { useEffect } from 'react';
|
||||
|
||||
export const AIChatThreadsListFocusEffect = ({
|
||||
export const AiChatThreadsListFocusEffect = ({
|
||||
focusId,
|
||||
}: {
|
||||
focusId: string;
|
||||
+10
-10
@@ -2,11 +2,11 @@ import { styled } from '@linaria/react';
|
||||
import { useLingui } from '@lingui/react/macro';
|
||||
import { themeCssVariables } from 'twenty-ui/theme-constants';
|
||||
|
||||
import { AIChatSkeletonLoader } from '@/ai/components/internal/AIChatSkeletonLoader';
|
||||
import { NavigationDrawerAIChatThreadDateSection } from '@/ai/components/NavigationDrawerAIChatThreadDateSection';
|
||||
import { useAIChatThreadClick } from '@/ai/hooks/useAIChatThreadClick';
|
||||
import { AiChatSkeletonLoader } from '@/ai/components/internal/AiChatSkeletonLoader';
|
||||
import { NavigationDrawerAiChatThreadDateSection } from '@/ai/components/NavigationDrawerAiChatThreadDateSection';
|
||||
import { useAiChatThreadClick } from '@/ai/hooks/useAiChatThreadClick';
|
||||
import { useChatThreads } from '@/ai/hooks/useChatThreads';
|
||||
import { currentAIChatThreadState } from '@/ai/states/currentAIChatThreadState';
|
||||
import { currentAiChatThreadState } from '@/ai/states/currentAiChatThreadState';
|
||||
import { type DateGroupKey } from '@/ai/utils/dateGroupKey';
|
||||
import { DATE_GROUP_KEYS } from '@/ai/utils/dateGroupKeys';
|
||||
import { getDateGroupTitle } from '@/ai/utils/getDateGroupTitle';
|
||||
@@ -42,11 +42,11 @@ const StyledFetchMoreTrigger = styled.div`
|
||||
width: 100%;
|
||||
`;
|
||||
|
||||
export const NavigationDrawerAIChatContent = () => {
|
||||
export const NavigationDrawerAiChatContent = () => {
|
||||
const { t } = useLingui();
|
||||
|
||||
const currentAIChatThread = useAtomStateValue(currentAIChatThreadState);
|
||||
const { handleThreadClick } = useAIChatThreadClick({
|
||||
const currentAiChatThread = useAtomStateValue(currentAiChatThreadState);
|
||||
const { handleThreadClick } = useAiChatThreadClick({
|
||||
resetNavigationStack: true,
|
||||
});
|
||||
|
||||
@@ -57,7 +57,7 @@ export const NavigationDrawerAIChatContent = () => {
|
||||
if (loading && threads.length === 0) {
|
||||
return (
|
||||
<StyledContainer>
|
||||
<AIChatSkeletonLoader />
|
||||
<AiChatSkeletonLoader />
|
||||
</StyledContainer>
|
||||
);
|
||||
}
|
||||
@@ -78,11 +78,11 @@ export const NavigationDrawerAIChatContent = () => {
|
||||
if (threadsInGroup.length === 0) return null;
|
||||
|
||||
return (
|
||||
<NavigationDrawerAIChatThreadDateSection
|
||||
<NavigationDrawerAiChatThreadDateSection
|
||||
key={key}
|
||||
title={getDateGroupTitle(key)}
|
||||
threads={threadsInGroup}
|
||||
currentThreadId={currentAIChatThread}
|
||||
currentThreadId={currentAiChatThread}
|
||||
onThreadClick={handleThreadClick}
|
||||
/>
|
||||
);
|
||||
+3
-3
@@ -32,19 +32,19 @@ const StyledThreadTimestamp = styled.span`
|
||||
padding-right: ${themeCssVariables.spacing['0.5']};
|
||||
`;
|
||||
|
||||
export type NavigationDrawerAIChatThreadDateSectionProps = {
|
||||
export type NavigationDrawerAiChatThreadDateSectionProps = {
|
||||
title: string;
|
||||
threads: AgentChatThread[];
|
||||
currentThreadId: string | null;
|
||||
onThreadClick: (thread: AgentChatThread) => void;
|
||||
};
|
||||
|
||||
export const NavigationDrawerAIChatThreadDateSection = ({
|
||||
export const NavigationDrawerAiChatThreadDateSection = ({
|
||||
title,
|
||||
threads,
|
||||
currentThreadId,
|
||||
onThreadClick,
|
||||
}: NavigationDrawerAIChatThreadDateSectionProps) => {
|
||||
}: NavigationDrawerAiChatThreadDateSectionProps) => {
|
||||
const { t } = useLingui();
|
||||
|
||||
return (
|
||||
+17
-17
@@ -8,13 +8,13 @@ import { userEvent, within } from 'storybook/test';
|
||||
import { type ExtendedUIMessage } from 'twenty-shared/ai';
|
||||
import { ComponentDecorator } from 'twenty-ui/testing';
|
||||
|
||||
import { AIChatMessage } from '@/ai/components/AIChatMessage';
|
||||
import { AiChatMessage } from '@/ai/components/AiChatMessage';
|
||||
|
||||
import { AgentChatComponentInstanceContext } from '@/ai/states/AgentChatComponentInstanceContext';
|
||||
import { agentChatDisplayedThreadState } from '@/ai/states/agentChatDisplayedThreadState';
|
||||
import { agentChatMessageComponentFamilyState } from '@/ai/states/agentChatMessageComponentFamilyState';
|
||||
import { agentChatMessagesComponentFamilyState } from '@/ai/states/agentChatMessagesComponentFamilyState';
|
||||
import { currentAIChatThreadState } from '@/ai/states/currentAIChatThreadState';
|
||||
import { currentAiChatThreadState } from '@/ai/states/currentAiChatThreadState';
|
||||
|
||||
import { styled } from '@linaria/react';
|
||||
import { useStore } from 'jotai';
|
||||
@@ -258,7 +258,7 @@ const AgentChatMessagesSetterEffect = ({
|
||||
const store = useStore();
|
||||
|
||||
useEffect(() => {
|
||||
const currentThreadId = store.get(currentAIChatThreadState.atom);
|
||||
const currentThreadId = store.get(currentAiChatThreadState.atom);
|
||||
|
||||
store.set(agentChatDisplayedThreadState.atom, currentThreadId);
|
||||
|
||||
@@ -293,9 +293,9 @@ const AgentChatInstanceDecorator: Decorator = (Story) => (
|
||||
</AgentChatComponentInstanceContext.Provider>
|
||||
);
|
||||
|
||||
const meta: Meta<typeof AIChatMessage> = {
|
||||
title: 'Modules/AI/AIChatMessage',
|
||||
component: AIChatMessage,
|
||||
const meta: Meta<typeof AiChatMessage> = {
|
||||
title: 'Modules/AI/AiChatMessage',
|
||||
component: AiChatMessage,
|
||||
decorators: [
|
||||
ComponentDecorator,
|
||||
RootDecorator,
|
||||
@@ -308,48 +308,48 @@ const meta: Meta<typeof AIChatMessage> = {
|
||||
};
|
||||
|
||||
export default meta;
|
||||
type Story = StoryObj<typeof AIChatMessage>;
|
||||
type Story = StoryObj<typeof AiChatMessage>;
|
||||
|
||||
// Conversation showcase - demonstrates a full AI chat flow
|
||||
export const ConversationWithCodeExecution: Story = {
|
||||
render: () => (
|
||||
<StyledConversationContainer>
|
||||
<AIChatMessage messageId={mockUserMessage.id} />
|
||||
<AIChatMessage messageId={mockAssistantWithCodeExecution.id} />
|
||||
<AiChatMessage messageId={mockUserMessage.id} />
|
||||
<AiChatMessage messageId={mockAssistantWithCodeExecution.id} />
|
||||
</StyledConversationContainer>
|
||||
),
|
||||
};
|
||||
|
||||
export const UserMessage: Story = {
|
||||
render: () => <AIChatMessage messageId={mockUserMessage.id} />,
|
||||
render: () => <AiChatMessage messageId={mockUserMessage.id} />,
|
||||
};
|
||||
|
||||
export const AssistantTextResponse: Story = {
|
||||
render: () => <AIChatMessage messageId={mockSimpleTextResponse.id} />,
|
||||
render: () => <AiChatMessage messageId={mockSimpleTextResponse.id} />,
|
||||
};
|
||||
|
||||
export const AssistantStreaming: Story = {
|
||||
render: () => <AIChatMessage messageId={mockStreamingMessage.id} />,
|
||||
render: () => <AiChatMessage messageId={mockStreamingMessage.id} />,
|
||||
};
|
||||
|
||||
export const CodeExecutionRunning: Story = {
|
||||
render: () => <AIChatMessage messageId={mockCodeExecutionRunning.id} />,
|
||||
render: () => <AiChatMessage messageId={mockCodeExecutionRunning.id} />,
|
||||
};
|
||||
|
||||
export const CodeExecutionWithError: Story = {
|
||||
render: () => <AIChatMessage messageId={mockCodeExecutionError.id} />,
|
||||
render: () => <AiChatMessage messageId={mockCodeExecutionError.id} />,
|
||||
};
|
||||
|
||||
export const ThinkingStepsThinkingState: Story = {
|
||||
render: () => <AIChatMessage messageId={mockThinkingStepsStreaming.id} />,
|
||||
render: () => <AiChatMessage messageId={mockThinkingStepsStreaming.id} />,
|
||||
};
|
||||
|
||||
export const ThinkingStepsDoneCollapsed: Story = {
|
||||
render: () => <AIChatMessage messageId={mockThinkingStepsDone.id} />,
|
||||
render: () => <AiChatMessage messageId={mockThinkingStepsDone.id} />,
|
||||
};
|
||||
|
||||
export const ThinkingStepsDoneExpanded: Story = {
|
||||
render: () => <AIChatMessage messageId={mockThinkingStepsDone.id} />,
|
||||
render: () => <AiChatMessage messageId={mockThinkingStepsDone.id} />,
|
||||
play: async ({ canvasElement }) => {
|
||||
const canvas = within(canvasElement);
|
||||
const summaryButton = await canvas.findByRole('button', {
|
||||
+3
-3
@@ -2,7 +2,7 @@ import { render, screen } from '@testing-library/react';
|
||||
import { ThemeProvider } from 'twenty-ui/theme-constants';
|
||||
import { type ExtendedUIMessagePart } from 'twenty-shared/ai';
|
||||
|
||||
import { AIChatAssistantMessageRenderer } from '@/ai/components/AIChatAssistantMessageRenderer';
|
||||
import { AiChatAssistantMessageRenderer } from '@/ai/components/AiChatAssistantMessageRenderer';
|
||||
|
||||
jest.mock('@/ai/components/ThinkingStepsDisplay', () => ({
|
||||
ThinkingStepsDisplay: ({
|
||||
@@ -43,7 +43,7 @@ jest.mock('@/ai/components/CodeExecutionDisplay', () => ({
|
||||
const renderAssistantRenderer = (messageParts: ExtendedUIMessagePart[]) => {
|
||||
return render(
|
||||
<ThemeProvider colorScheme="light">
|
||||
<AIChatAssistantMessageRenderer
|
||||
<AiChatAssistantMessageRenderer
|
||||
messageParts={messageParts}
|
||||
isLastMessageStreaming={false}
|
||||
/>
|
||||
@@ -51,7 +51,7 @@ const renderAssistantRenderer = (messageParts: ExtendedUIMessagePart[]) => {
|
||||
);
|
||||
};
|
||||
|
||||
describe('AIChatAssistantMessageRenderer', () => {
|
||||
describe('AiChatAssistantMessageRenderer', () => {
|
||||
it('should group reasoning and tool steps into ThinkingStepsDisplay', () => {
|
||||
const messageParts = [
|
||||
{
|
||||
+2
-2
@@ -1,4 +1,4 @@
|
||||
import { useAIChatFileUpload } from '@/ai/hooks/useAIChatFileUpload';
|
||||
import { useAiChatFileUpload } from '@/ai/hooks/useAiChatFileUpload';
|
||||
import { agentChatSelectedFilesState } from '@/ai/states/agentChatSelectedFilesState';
|
||||
import { useSetAtomState } from '@/ui/utilities/state/jotai/hooks/useSetAtomState';
|
||||
import { styled } from '@linaria/react';
|
||||
@@ -23,7 +23,7 @@ export const AgentChatFileUploadButton = () => {
|
||||
agentChatSelectedFilesState,
|
||||
);
|
||||
const fileInputRef = useRef<HTMLInputElement>(null);
|
||||
const { uploadFiles } = useAIChatFileUpload();
|
||||
const { uploadFiles } = useAiChatFileUpload();
|
||||
|
||||
const handleFileInputChange = (
|
||||
event: React.ChangeEvent<HTMLInputElement>,
|
||||
|
||||
+4
-4
@@ -13,7 +13,7 @@ import {
|
||||
agentChatUsageComponentFamilyState,
|
||||
type AgentChatLastMessageUsage,
|
||||
} from '@/ai/states/agentChatUsageComponentFamilyState';
|
||||
import { currentAIChatThreadState } from '@/ai/states/currentAIChatThreadState';
|
||||
import { currentAiChatThreadState } from '@/ai/states/currentAiChatThreadState';
|
||||
import { SettingsBillingLabelValueItem } from '@/settings/billing/components/internal/SettingsBillingLabelValueItem';
|
||||
import { billingState } from '@/client-config/states/billingState';
|
||||
import { useAtomComponentFamilyStateValue } from '@/ui/utilities/state/jotai/hooks/useAtomComponentFamilyStateValue';
|
||||
@@ -93,13 +93,13 @@ const getCachedLabel = (lastMessage: AgentChatLastMessageUsage): string => {
|
||||
return ` (${t`${cachedPercent}% cached`})`;
|
||||
};
|
||||
|
||||
export const AIChatContextUsageButton = () => {
|
||||
export const AiChatContextUsageButton = () => {
|
||||
const { t } = useLingui();
|
||||
const [isHovered, setIsHovered] = useState(false);
|
||||
const currentAIChatThread = useAtomStateValue(currentAIChatThreadState);
|
||||
const currentAiChatThread = useAtomStateValue(currentAiChatThreadState);
|
||||
const agentChatUsage = useAtomComponentFamilyStateValue(
|
||||
agentChatUsageComponentFamilyState,
|
||||
{ threadId: currentAIChatThread },
|
||||
{ threadId: currentAiChatThread },
|
||||
);
|
||||
const billing = useAtomStateValue(billingState);
|
||||
const isBillingEnabled = billing?.isBillingEnabled ?? false;
|
||||
+3
-3
@@ -4,13 +4,13 @@ import { useEffect } from 'react';
|
||||
import { shouldFocusChatEditorState } from '@/ai/states/shouldFocusChatEditorState';
|
||||
import { useAtomState } from '@/ui/utilities/state/jotai/hooks/useAtomState';
|
||||
|
||||
type AIChatEditorFocusEffectProps = {
|
||||
type AiChatEditorFocusEffectProps = {
|
||||
editor: Editor | null;
|
||||
};
|
||||
|
||||
export const AIChatEditorFocusEffect = ({
|
||||
export const AiChatEditorFocusEffect = ({
|
||||
editor,
|
||||
}: AIChatEditorFocusEffectProps) => {
|
||||
}: AiChatEditorFocusEffectProps) => {
|
||||
const [shouldFocusChatEditor, setShouldFocusChatEditor] = useAtomState(
|
||||
shouldFocusChatEditorState,
|
||||
);
|
||||
+4
-4
@@ -7,7 +7,7 @@ import { AGENT_CHAT_NEW_THREAD_DRAFT_KEY } from '@/ai/states/agentChatDraftsByTh
|
||||
import { agentChatMessagesLoadingState } from '@/ai/states/agentChatMessagesLoadingState';
|
||||
import { agentChatThreadsLoadingState } from '@/ai/states/agentChatThreadsLoadingState';
|
||||
import { agentChatHasMessageComponentSelector } from '@/ai/states/agentChatHasMessageComponentSelector';
|
||||
import { currentAIChatThreadState } from '@/ai/states/currentAIChatThreadState';
|
||||
import { currentAiChatThreadState } from '@/ai/states/currentAiChatThreadState';
|
||||
import { skipMessagesSkeletonUntilLoadedState } from '@/ai/states/skipMessagesSkeletonUntilLoadedState';
|
||||
import { useAtomComponentSelectorValue } from '@/ui/utilities/state/jotai/hooks/useAtomComponentSelectorValue';
|
||||
import { useAtomStateValue } from '@/ui/utilities/state/jotai/hooks/useAtomStateValue';
|
||||
@@ -32,7 +32,7 @@ const StyledMessageSkeleton = styled.div`
|
||||
|
||||
const NUMBER_OF_SKELETONS = 6;
|
||||
|
||||
export const AIChatSkeletonLoader = () => {
|
||||
export const AiChatSkeletonLoader = () => {
|
||||
const { theme } = useContext(ThemeContext);
|
||||
const agentChatThreadsLoading = useAtomStateValue(
|
||||
agentChatThreadsLoadingState,
|
||||
@@ -43,14 +43,14 @@ export const AIChatSkeletonLoader = () => {
|
||||
const skipMessagesSkeletonUntilLoaded = useAtomStateValue(
|
||||
skipMessagesSkeletonUntilLoadedState,
|
||||
);
|
||||
const currentAIChatThread = useAtomStateValue(currentAIChatThreadState);
|
||||
const currentAiChatThread = useAtomStateValue(currentAiChatThreadState);
|
||||
|
||||
const hasMessages = useAtomComponentSelectorValue(
|
||||
agentChatHasMessageComponentSelector,
|
||||
);
|
||||
|
||||
const isOnNewChatSlot =
|
||||
currentAIChatThread === AGENT_CHAT_NEW_THREAD_DRAFT_KEY;
|
||||
currentAiChatThread === AGENT_CHAT_NEW_THREAD_DRAFT_KEY;
|
||||
const showForMessagesLoading =
|
||||
agentChatMessagesLoading && !skipMessagesSkeletonUntilLoaded;
|
||||
const shouldRender =
|
||||
@@ -2,7 +2,7 @@ import { AGENT_CHAT_STOP_EVENT_NAME } from '@/ai/constants/AgentChatStopEventNam
|
||||
import { agentChatInputIsEmptySelector } from '@/ai/states/agentChatInputIsEmptySelector';
|
||||
import { agentChatIsLoadingState } from '@/ai/states/agentChatIsLoadingState';
|
||||
import { agentChatIsStreamingComponentFamilyState } from '@/ai/states/agentChatIsStreamingComponentFamilyState';
|
||||
import { currentAIChatThreadState } from '@/ai/states/currentAIChatThreadState';
|
||||
import { currentAiChatThreadState } from '@/ai/states/currentAiChatThreadState';
|
||||
import { dispatchBrowserEvent } from '@/browser-event/utils/dispatchBrowserEvent';
|
||||
import { useAtomComponentFamilyStateValue } from '@/ui/utilities/state/jotai/hooks/useAtomComponentFamilyStateValue';
|
||||
import { useAtomStateValue } from '@/ui/utilities/state/jotai/hooks/useAtomStateValue';
|
||||
@@ -20,10 +20,10 @@ export const SendMessageButton = ({ onSend }: SendMessageButtonProps) => {
|
||||
|
||||
const agentChatIsLoading = useAtomStateValue(agentChatIsLoadingState);
|
||||
|
||||
const currentAIChatThread = useAtomStateValue(currentAIChatThreadState);
|
||||
const currentAiChatThread = useAtomStateValue(currentAiChatThreadState);
|
||||
const agentChatIsStreaming = useAtomComponentFamilyStateValue(
|
||||
agentChatIsStreamingComponentFamilyState,
|
||||
{ threadId: currentAIChatThread },
|
||||
{ threadId: currentAiChatThread },
|
||||
);
|
||||
|
||||
const handleStopClick = () => {
|
||||
|
||||
+3
-3
@@ -36,13 +36,13 @@ const StyledSuggestedPromptButtonContainer = styled.div`
|
||||
const pickRandom = <T,>(items: T[]): T =>
|
||||
items[Math.floor(Math.random() * items.length)];
|
||||
|
||||
type AIChatSuggestedPromptsProps = {
|
||||
type AiChatSuggestedPromptsProps = {
|
||||
editor: Editor | null;
|
||||
};
|
||||
|
||||
export const AIChatSuggestedPrompts = ({
|
||||
export const AiChatSuggestedPrompts = ({
|
||||
editor,
|
||||
}: AIChatSuggestedPromptsProps) => {
|
||||
}: AiChatSuggestedPromptsProps) => {
|
||||
const { t: resolveMessage } = useLingui();
|
||||
const setAgentChatInput = useSetAtomState(agentChatInputState);
|
||||
|
||||
+2
-2
@@ -1,8 +1,8 @@
|
||||
import { gql } from '@apollo/client';
|
||||
|
||||
export const UPLOAD_AI_CHAT_FILE = gql`
|
||||
mutation uploadAIChatFile($file: Upload!) {
|
||||
uploadAIChatFile(file: $file) {
|
||||
mutation uploadAiChatFile($file: Upload!) {
|
||||
uploadAiChatFile(file: $file) {
|
||||
id
|
||||
path
|
||||
size
|
||||
@@ -22,7 +22,7 @@ import { agentChatInputState } from '@/ai/states/agentChatInputState';
|
||||
import { agentChatSelectedFilesState } from '@/ai/states/agentChatSelectedFilesState';
|
||||
import { agentChatUploadedFilesState } from '@/ai/states/agentChatUploadedFilesState';
|
||||
import { agentChatMessagesComponentFamilyState } from '@/ai/states/agentChatMessagesComponentFamilyState';
|
||||
import { currentAIChatThreadState } from '@/ai/states/currentAIChatThreadState';
|
||||
import { currentAiChatThreadState } from '@/ai/states/currentAiChatThreadState';
|
||||
import { useGetBrowsingContext } from '@/ai/hooks/useBrowsingContext';
|
||||
import { useAgentChatModelId } from '@/ai/hooks/useAgentChatModelId';
|
||||
import { useListenToBrowserEvent } from '@/browser-event/hooks/useListenToBrowserEvent';
|
||||
@@ -37,7 +37,7 @@ export const useAgentChat = (
|
||||
const { modelIdForRequest } = useAgentChatModelId();
|
||||
const { getBrowsingContext } = useGetBrowsingContext();
|
||||
const apolloClient = useApolloClient();
|
||||
const setCurrentAIChatThread = useSetAtomState(currentAIChatThreadState);
|
||||
const setCurrentAiChatThread = useSetAtomState(currentAiChatThreadState);
|
||||
const store = useStore();
|
||||
|
||||
const agentChatSelectedFiles = useAtomStateValue(agentChatSelectedFilesState);
|
||||
@@ -55,7 +55,7 @@ export const useAgentChat = (
|
||||
|
||||
const handleSendMessage = useCallback(async () => {
|
||||
const draftKey =
|
||||
store.get(currentAIChatThreadState.atom) ??
|
||||
store.get(currentAiChatThreadState.atom) ??
|
||||
AGENT_CHAT_NEW_THREAD_DRAFT_KEY;
|
||||
const contentToSend =
|
||||
draftKey === AGENT_CHAT_NEW_THREAD_DRAFT_KEY
|
||||
@@ -158,7 +158,7 @@ export const useAgentChat = (
|
||||
|
||||
setPendingThreadIdAfterFirstSend((pendingId) => {
|
||||
if (isDefined(pendingId)) {
|
||||
setCurrentAIChatThread(pendingId);
|
||||
setCurrentAiChatThread(pendingId);
|
||||
}
|
||||
|
||||
return null;
|
||||
@@ -195,7 +195,7 @@ export const useAgentChat = (
|
||||
});
|
||||
|
||||
if (draftKey === AGENT_CHAT_NEW_THREAD_DRAFT_KEY) {
|
||||
setCurrentAIChatThread(threadId);
|
||||
setCurrentAiChatThread(threadId);
|
||||
}
|
||||
|
||||
setPendingThreadIdAfterFirstSend(null);
|
||||
@@ -211,7 +211,7 @@ export const useAgentChat = (
|
||||
setAgentChatUploadedFiles,
|
||||
setAgentChatDraftsByThreadId,
|
||||
modelIdForRequest,
|
||||
setCurrentAIChatThread,
|
||||
setCurrentAiChatThread,
|
||||
apolloClient,
|
||||
]);
|
||||
|
||||
@@ -221,7 +221,7 @@ export const useAgentChat = (
|
||||
});
|
||||
|
||||
const handleStop = useCallback(async () => {
|
||||
const threadId = store.get(currentAIChatThreadState.atom);
|
||||
const threadId = store.get(currentAiChatThreadState.atom);
|
||||
|
||||
if (!isDefined(threadId) || !isValidUuid(threadId)) {
|
||||
return;
|
||||
|
||||
@@ -18,7 +18,7 @@ import { agentChatHandleEventCallbackComponentFamilyState } from '@/ai/states/ag
|
||||
import { agentChatIsStreamingComponentFamilyState } from '@/ai/states/agentChatIsStreamingComponentFamilyState';
|
||||
import { agentChatMessagesComponentFamilyState } from '@/ai/states/agentChatMessagesComponentFamilyState';
|
||||
import { agentChatUsageComponentFamilyState } from '@/ai/states/agentChatUsageComponentFamilyState';
|
||||
import { currentAIChatThreadTitleComponentFamilyState } from '@/ai/states/currentAIChatThreadTitleComponentFamilyState';
|
||||
import { currentAiChatThreadTitleComponentFamilyState } from '@/ai/states/currentAiChatThreadTitleComponentFamilyState';
|
||||
import { dispatchBrowserEvent } from '@/browser-event/utils/dispatchBrowserEvent';
|
||||
import { useAtomComponentFamilyStateCallbackState } from '@/ui/utilities/state/jotai/hooks/useAtomComponentFamilyStateCallbackState';
|
||||
import { useAtomStateValue } from '@/ui/utilities/state/jotai/hooks/useAtomStateValue';
|
||||
@@ -116,7 +116,7 @@ export const useAgentChatSubscription = (threadId: string | null) => {
|
||||
agentChatUsageComponentFamilyState,
|
||||
);
|
||||
const threadTitleFamilyCallback = useAtomComponentFamilyStateCallbackState(
|
||||
currentAIChatThreadTitleComponentFamilyState,
|
||||
currentAiChatThreadTitleComponentFamilyState,
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
|
||||
+4
-4
@@ -15,7 +15,7 @@ import {
|
||||
agentChatDraftsByThreadIdState,
|
||||
} from '@/ai/states/agentChatDraftsByThreadIdState';
|
||||
import { agentChatInputState } from '@/ai/states/agentChatInputState';
|
||||
import { currentAIChatThreadState } from '@/ai/states/currentAIChatThreadState';
|
||||
import { currentAiChatThreadState } from '@/ai/states/currentAiChatThreadState';
|
||||
import { dispatchAgentChatEnsureThreadForDraftEvent } from '@/ai/utils/dispatchAgentChatEnsureThreadForDraftEvent';
|
||||
import { dispatchAgentChatSendMessageEvent } from '@/ai/utils/dispatchAgentChatSendMessageEvent';
|
||||
import { MENTION_SUGGESTION_PLUGIN_KEY } from '@/mention/constants/MentionSuggestionPluginKey';
|
||||
@@ -41,9 +41,9 @@ const textToTiptapContent = (text: string) => ({
|
||||
],
|
||||
});
|
||||
|
||||
export const useAIChatEditor = () => {
|
||||
export const useAiChatEditor = () => {
|
||||
const setAgentChatInput = useSetAtomState(agentChatInputState);
|
||||
const currentAIChatThread = useAtomStateValue(currentAIChatThreadState);
|
||||
const currentAiChatThread = useAtomStateValue(currentAiChatThreadState);
|
||||
const [agentChatDraftsByThreadId, setAgentChatDraftsByThreadId] =
|
||||
useAtomState(agentChatDraftsByThreadIdState);
|
||||
const { searchMentionRecords } = useMentionSearch();
|
||||
@@ -51,7 +51,7 @@ export const useAIChatEditor = () => {
|
||||
const { removeFocusItemFromFocusStackById } =
|
||||
useRemoveFocusItemFromFocusStackById();
|
||||
|
||||
const draftKey = currentAIChatThread ?? AGENT_CHAT_NEW_THREAD_DRAFT_KEY;
|
||||
const draftKey = currentAiChatThread ?? AGENT_CHAT_NEW_THREAD_DRAFT_KEY;
|
||||
const initialDraft = agentChatDraftsByThreadId[draftKey] ?? '';
|
||||
const initialContent = textToTiptapContent(initialDraft);
|
||||
|
||||
+2
-2
@@ -9,7 +9,7 @@ import { isDefined } from 'twenty-shared/utils';
|
||||
import { type AgentChatFileUIPart } from '@/ai/types/agent-chat-file-ui-part.type';
|
||||
import { UploadAiChatFileDocument } from '~/generated-metadata/graphql';
|
||||
|
||||
export const useAIChatFileUpload = () => {
|
||||
export const useAiChatFileUpload = () => {
|
||||
const apolloClient = useApolloClient();
|
||||
const [uploadAiChatFile] = useMutation(UploadAiChatFileDocument, {
|
||||
client: apolloClient,
|
||||
@@ -31,7 +31,7 @@ export const useAIChatFileUpload = () => {
|
||||
},
|
||||
});
|
||||
|
||||
const response = result?.data?.uploadAIChatFile;
|
||||
const response = result?.data?.uploadAiChatFile;
|
||||
|
||||
if (!isDefined(response)) {
|
||||
throw new Error(t`Couldn't upload the file.`);
|
||||
+15
-15
@@ -1,10 +1,10 @@
|
||||
import { agentChatDraftsByThreadIdState } from '@/ai/states/agentChatDraftsByThreadIdState';
|
||||
import { agentChatInputState } from '@/ai/states/agentChatInputState';
|
||||
import { agentChatUsageComponentFamilyState } from '@/ai/states/agentChatUsageComponentFamilyState';
|
||||
import { currentAIChatThreadState } from '@/ai/states/currentAIChatThreadState';
|
||||
import { currentAIChatThreadTitleComponentFamilyState } from '@/ai/states/currentAIChatThreadTitleComponentFamilyState';
|
||||
import { currentAiChatThreadState } from '@/ai/states/currentAiChatThreadState';
|
||||
import { currentAiChatThreadTitleComponentFamilyState } from '@/ai/states/currentAiChatThreadTitleComponentFamilyState';
|
||||
import { threadIdCreatedFromDraftState } from '@/ai/states/threadIdCreatedFromDraftState';
|
||||
import { useOpenAskAIPageInSidePanel } from '@/side-panel/hooks/useOpenAskAIPageInSidePanel';
|
||||
import { useOpenAskAiPageInSidePanel } from '@/side-panel/hooks/useOpenAskAiPageInSidePanel';
|
||||
import { useAtomComponentFamilyStateCallbackState } from '@/ui/utilities/state/jotai/hooks/useAtomComponentFamilyStateCallbackState';
|
||||
import { useAtomState } from '@/ui/utilities/state/jotai/hooks/useAtomState';
|
||||
import { useSetAtomState } from '@/ui/utilities/state/jotai/hooks/useSetAtomState';
|
||||
@@ -12,44 +12,44 @@ import { useStore } from 'jotai';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
import { type AgentChatThread } from '~/generated-metadata/graphql';
|
||||
|
||||
export type UseAIChatThreadClickOptions = {
|
||||
export type UseAiChatThreadClickOptions = {
|
||||
resetNavigationStack?: boolean;
|
||||
};
|
||||
|
||||
export const useAIChatThreadClick = (
|
||||
options: UseAIChatThreadClickOptions = {},
|
||||
export const useAiChatThreadClick = (
|
||||
options: UseAiChatThreadClickOptions = {},
|
||||
) => {
|
||||
const { resetNavigationStack = false } = options;
|
||||
const setThreadIdCreatedFromDraft = useSetAtomState(
|
||||
threadIdCreatedFromDraftState,
|
||||
);
|
||||
const [currentAIChatThread, setCurrentAIChatThread] = useAtomState(
|
||||
currentAIChatThreadState,
|
||||
const [currentAiChatThread, setCurrentAiChatThread] = useAtomState(
|
||||
currentAiChatThreadState,
|
||||
);
|
||||
const setAgentChatInput = useSetAtomState(agentChatInputState);
|
||||
const setAgentChatDraftsByThreadId = useSetAtomState(
|
||||
agentChatDraftsByThreadIdState,
|
||||
);
|
||||
const threadTitleFamilyCallback = useAtomComponentFamilyStateCallbackState(
|
||||
currentAIChatThreadTitleComponentFamilyState,
|
||||
currentAiChatThreadTitleComponentFamilyState,
|
||||
);
|
||||
const agentChatUsageFamilyCallback = useAtomComponentFamilyStateCallbackState(
|
||||
agentChatUsageComponentFamilyState,
|
||||
);
|
||||
const store = useStore();
|
||||
const { openAskAIPage } = useOpenAskAIPageInSidePanel();
|
||||
const { openAskAiPage } = useOpenAskAiPageInSidePanel();
|
||||
|
||||
const handleThreadClick = (thread: AgentChatThread) => {
|
||||
setThreadIdCreatedFromDraft(null);
|
||||
const isSameThread = thread.id === currentAIChatThread;
|
||||
const isSameThread = thread.id === currentAiChatThread;
|
||||
|
||||
if (currentAIChatThread !== null) {
|
||||
if (currentAiChatThread !== null) {
|
||||
setAgentChatDraftsByThreadId((prev) => ({
|
||||
...prev,
|
||||
[currentAIChatThread]: store.get(agentChatInputState.atom),
|
||||
[currentAiChatThread]: store.get(agentChatInputState.atom),
|
||||
}));
|
||||
}
|
||||
setCurrentAIChatThread(thread.id);
|
||||
setCurrentAiChatThread(thread.id);
|
||||
|
||||
if (!isSameThread) {
|
||||
const newDraft =
|
||||
@@ -82,7 +82,7 @@ export const useAIChatThreadClick = (
|
||||
: null,
|
||||
);
|
||||
|
||||
openAskAIPage({
|
||||
openAskAiPage({
|
||||
resetNavigationStack,
|
||||
});
|
||||
};
|
||||
@@ -5,7 +5,7 @@ import {
|
||||
agentChatDraftsByThreadIdState,
|
||||
} from '@/ai/states/agentChatDraftsByThreadIdState';
|
||||
import { agentChatInputState } from '@/ai/states/agentChatInputState';
|
||||
import { currentAIChatThreadState } from '@/ai/states/currentAIChatThreadState';
|
||||
import { currentAiChatThreadState } from '@/ai/states/currentAiChatThreadState';
|
||||
import { shouldFocusChatEditorState } from '@/ai/states/shouldFocusChatEditorState';
|
||||
import { hasTriggeredCreateForDraftState } from '@/ai/states/hasTriggeredCreateForDraftState';
|
||||
import { isCreatingChatThreadState } from '@/ai/states/isCreatingChatThreadState';
|
||||
@@ -20,7 +20,7 @@ import { useMutation } from '@apollo/client/react';
|
||||
import { CreateChatThreadDocument } from '~/generated-metadata/graphql';
|
||||
|
||||
export const useCreateAgentChatThread = () => {
|
||||
const setCurrentAIChatThread = useSetAtomState(currentAIChatThreadState);
|
||||
const setCurrentAiChatThread = useSetAtomState(currentAiChatThreadState);
|
||||
const setAgentChatInput = useSetAtomState(agentChatInputState);
|
||||
const setIsCreatingChatThread = useSetAtomState(isCreatingChatThreadState);
|
||||
const setAgentChatDraftsByThreadId = useSetAtomState(
|
||||
@@ -55,7 +55,7 @@ export const useCreateAgentChatThread = () => {
|
||||
|
||||
const newThreadId = data.createChatThread.id;
|
||||
const previousDraftKey =
|
||||
store.get(currentAIChatThreadState.atom) ??
|
||||
store.get(currentAiChatThreadState.atom) ??
|
||||
AGENT_CHAT_NEW_THREAD_DRAFT_KEY;
|
||||
const draftsSnapshot = store.get(agentChatDraftsByThreadIdState.atom);
|
||||
const newDraft = draftsSnapshot[AGENT_CHAT_NEW_THREAD_DRAFT_KEY] ?? '';
|
||||
@@ -79,7 +79,7 @@ export const useCreateAgentChatThread = () => {
|
||||
}));
|
||||
}
|
||||
|
||||
setCurrentAIChatThread(newThreadId);
|
||||
setCurrentAiChatThread(newThreadId);
|
||||
setAgentChatInput(newDraft);
|
||||
},
|
||||
onError: () => {
|
||||
|
||||
+2
-2
@@ -5,7 +5,7 @@ import {
|
||||
AGENT_CHAT_NEW_THREAD_DRAFT_KEY,
|
||||
agentChatDraftsByThreadIdState,
|
||||
} from '@/ai/states/agentChatDraftsByThreadIdState';
|
||||
import { currentAIChatThreadState } from '@/ai/states/currentAIChatThreadState';
|
||||
import { currentAiChatThreadState } from '@/ai/states/currentAiChatThreadState';
|
||||
import { hasTriggeredCreateForDraftState } from '@/ai/states/hasTriggeredCreateForDraftState';
|
||||
import { isCreatingChatThreadState } from '@/ai/states/isCreatingChatThreadState';
|
||||
import { pendingCreateFromDraftPromiseState } from '@/ai/states/pendingCreateFromDraftPromiseState';
|
||||
@@ -21,7 +21,7 @@ export const useEnsureAgentChatThreadExistsForDraft = (
|
||||
const store = useStore();
|
||||
|
||||
const ensureThreadExistsForDraft = useCallback(() => {
|
||||
const currentThreadId = store.get(currentAIChatThreadState.atom);
|
||||
const currentThreadId = store.get(currentAiChatThreadState.atom);
|
||||
|
||||
if (currentThreadId !== AGENT_CHAT_NEW_THREAD_DRAFT_KEY) {
|
||||
return;
|
||||
|
||||
@@ -3,7 +3,7 @@ import { useCallback } from 'react';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
import { AGENT_CHAT_NEW_THREAD_DRAFT_KEY } from '@/ai/states/agentChatDraftsByThreadIdState';
|
||||
import { currentAIChatThreadState } from '@/ai/states/currentAIChatThreadState';
|
||||
import { currentAiChatThreadState } from '@/ai/states/currentAiChatThreadState';
|
||||
import { isCreatingChatThreadState } from '@/ai/states/isCreatingChatThreadState';
|
||||
import { isCreatingForFirstSendState } from '@/ai/states/isCreatingForFirstSendState';
|
||||
import { pendingCreateFromDraftPromiseState } from '@/ai/states/pendingCreateFromDraftPromiseState';
|
||||
@@ -18,7 +18,7 @@ export const useEnsureAgentChatThreadIdForSend = (
|
||||
const ensureThreadIdForSend = useCallback(async (): Promise<
|
||||
string | null
|
||||
> => {
|
||||
const currentThreadId = store.get(currentAIChatThreadState.atom);
|
||||
const currentThreadId = store.get(currentAiChatThreadState.atom);
|
||||
|
||||
if (
|
||||
currentThreadId !== null &&
|
||||
|
||||
+10
-10
@@ -5,27 +5,27 @@ import {
|
||||
agentChatDraftsByThreadIdState,
|
||||
} from '@/ai/states/agentChatDraftsByThreadIdState';
|
||||
import { agentChatInputState } from '@/ai/states/agentChatInputState';
|
||||
import { currentAIChatThreadState } from '@/ai/states/currentAIChatThreadState';
|
||||
import { currentAiChatThreadState } from '@/ai/states/currentAiChatThreadState';
|
||||
import { shouldFocusChatEditorState } from '@/ai/states/shouldFocusChatEditorState';
|
||||
import { hasTriggeredCreateForDraftState } from '@/ai/states/hasTriggeredCreateForDraftState';
|
||||
import { threadIdCreatedFromDraftState } from '@/ai/states/threadIdCreatedFromDraftState';
|
||||
import { useOpenAskAIPageInSidePanel } from '@/side-panel/hooks/useOpenAskAIPageInSidePanel';
|
||||
import { useOpenAskAiPageInSidePanel } from '@/side-panel/hooks/useOpenAskAiPageInSidePanel';
|
||||
import { useAtomState } from '@/ui/utilities/state/jotai/hooks/useAtomState';
|
||||
import { useSetAtomState } from '@/ui/utilities/state/jotai/hooks/useSetAtomState';
|
||||
|
||||
export const useSwitchToNewAIChat = () => {
|
||||
export const useSwitchToNewAiChat = () => {
|
||||
const setThreadIdCreatedFromDraft = useSetAtomState(
|
||||
threadIdCreatedFromDraftState,
|
||||
);
|
||||
const [currentAIChatThread, setCurrentAIChatThread] = useAtomState(
|
||||
currentAIChatThreadState,
|
||||
const [currentAiChatThread, setCurrentAiChatThread] = useAtomState(
|
||||
currentAiChatThreadState,
|
||||
);
|
||||
const setAgentChatInput = useSetAtomState(agentChatInputState);
|
||||
const setAgentChatDraftsByThreadId = useSetAtomState(
|
||||
agentChatDraftsByThreadIdState,
|
||||
);
|
||||
const store = useStore();
|
||||
const { openAskAIPage } = useOpenAskAIPageInSidePanel();
|
||||
const { openAskAiPage } = useOpenAskAiPageInSidePanel();
|
||||
|
||||
const switchToNewChat = () => {
|
||||
setThreadIdCreatedFromDraft(null);
|
||||
@@ -33,16 +33,16 @@ export const useSwitchToNewAIChat = () => {
|
||||
store.get(agentChatDraftsByThreadIdState.atom)[
|
||||
AGENT_CHAT_NEW_THREAD_DRAFT_KEY
|
||||
] ?? '';
|
||||
if (currentAIChatThread !== null) {
|
||||
if (currentAiChatThread !== null) {
|
||||
setAgentChatDraftsByThreadId((prev) => ({
|
||||
...prev,
|
||||
[currentAIChatThread]: store.get(agentChatInputState.atom),
|
||||
[currentAiChatThread]: store.get(agentChatInputState.atom),
|
||||
}));
|
||||
}
|
||||
store.set(hasTriggeredCreateForDraftState.atom, false);
|
||||
setCurrentAIChatThread(AGENT_CHAT_NEW_THREAD_DRAFT_KEY);
|
||||
setCurrentAiChatThread(AGENT_CHAT_NEW_THREAD_DRAFT_KEY);
|
||||
setAgentChatInput(newChatDraft);
|
||||
openAskAIPage();
|
||||
openAskAiPage();
|
||||
store.set(shouldFocusChatEditorState.atom, true);
|
||||
};
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import { AgentChatComponentInstanceContext } from '@/ai/states/AgentChatComponentInstanceContext';
|
||||
import { type AIChatError } from '@/ai/types/AIChatError';
|
||||
import { type AiChatError } from '@/ai/types/AiChatError';
|
||||
import { createAtomComponentFamilyState } from '@/ui/utilities/state/jotai/utils/createAtomComponentFamilyState';
|
||||
|
||||
export const agentChatErrorComponentFamilyState =
|
||||
createAtomComponentFamilyState<
|
||||
AIChatError | null,
|
||||
AiChatError | null,
|
||||
{ threadId: string | null }
|
||||
>({
|
||||
key: 'agentChatErrorComponentFamilyState',
|
||||
|
||||
+2
-2
@@ -1,6 +1,6 @@
|
||||
import { createAtomState } from '@/ui/utilities/state/jotai/utils/createAtomState';
|
||||
|
||||
export const currentAIChatThreadState = createAtomState<string | null>({
|
||||
key: 'ai/currentAIChatThreadState',
|
||||
export const currentAiChatThreadState = createAtomState<string | null>({
|
||||
key: 'ai/currentAiChatThreadState',
|
||||
defaultValue: null,
|
||||
});
|
||||
+2
-2
@@ -1,9 +1,9 @@
|
||||
import { AgentChatComponentInstanceContext } from '@/ai/states/AgentChatComponentInstanceContext';
|
||||
import { createAtomComponentFamilyState } from '@/ui/utilities/state/jotai/utils/createAtomComponentFamilyState';
|
||||
|
||||
export const currentAIChatThreadTitleComponentFamilyState =
|
||||
export const currentAiChatThreadTitleComponentFamilyState =
|
||||
createAtomComponentFamilyState<string | null, { threadId: string | null }>({
|
||||
key: 'currentAIChatThreadTitleComponentFamilyState',
|
||||
key: 'currentAiChatThreadTitleComponentFamilyState',
|
||||
defaultValue: null,
|
||||
componentInstanceContext: AgentChatComponentInstanceContext,
|
||||
});
|
||||
+1
-1
@@ -1,3 +1,3 @@
|
||||
import { type CombinedGraphQLErrors } from '@apollo/client/errors';
|
||||
|
||||
export type AIChatError = Error | CombinedGraphQLErrors;
|
||||
export type AiChatError = Error | CombinedGraphQLErrors;
|
||||
@@ -1,5 +1,5 @@
|
||||
// Error codes matching backend AgentExceptionCode and BillingExceptionCode
|
||||
export const AIChatErrorCode = {
|
||||
export const AiChatErrorCode = {
|
||||
BILLING_CREDITS_EXHAUSTED: 'BILLING_CREDITS_EXHAUSTED',
|
||||
API_KEY_NOT_CONFIGURED: 'API_KEY_NOT_CONFIGURED',
|
||||
} as const;
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
import { AI_CHAT_SCROLL_WRAPPER_ID } from '@/ai/constants/AiChatScrollWrapperId';
|
||||
|
||||
export const scrollAIChatToBottom = () => {
|
||||
export const scrollAiChatToBottom = () => {
|
||||
const scrollWrapperElement = document.getElementById(
|
||||
`scroll-wrapper-${AI_CHAT_SCROLL_WRAPPER_ID}`,
|
||||
);
|
||||
@@ -152,9 +152,9 @@ const SettingsAI = lazy(() =>
|
||||
})),
|
||||
);
|
||||
|
||||
const SettingsAIUsageUserDetail = lazy(() =>
|
||||
import('~/pages/settings/ai/SettingsAIUsageUserDetail').then((module) => ({
|
||||
default: module.SettingsAIUsageUserDetail,
|
||||
const SettingsAiUsageUserDetail = lazy(() =>
|
||||
import('~/pages/settings/ai/SettingsAiUsageUserDetail').then((module) => ({
|
||||
default: module.SettingsAiUsageUserDetail,
|
||||
})),
|
||||
);
|
||||
|
||||
@@ -230,9 +230,9 @@ const SettingsSkillForm = lazy(() =>
|
||||
})),
|
||||
);
|
||||
|
||||
const SettingsAIPrompts = lazy(() =>
|
||||
import('~/pages/settings/ai/SettingsAIPrompts').then((module) => ({
|
||||
default: module.SettingsAIPrompts,
|
||||
const SettingsAiPrompts = lazy(() =>
|
||||
import('~/pages/settings/ai/SettingsAiPrompts').then((module) => ({
|
||||
default: module.SettingsAiPrompts,
|
||||
})),
|
||||
);
|
||||
|
||||
@@ -564,33 +564,33 @@ export const SettingsRoutes = ({ isAdminPageEnabled }: SettingsRoutesProps) => (
|
||||
element={<SettingsApiWebhooks />}
|
||||
/>
|
||||
<Route path={SettingsPath.AI} element={<SettingsAI />} />
|
||||
<Route path={SettingsPath.AIPrompts} element={<SettingsAIPrompts />} />
|
||||
<Route path={SettingsPath.AiPrompts} element={<SettingsAiPrompts />} />
|
||||
<Route
|
||||
path={SettingsPath.AINewAgent}
|
||||
path={SettingsPath.AiNewAgent}
|
||||
element={<SettingsAgentForm mode="create" />}
|
||||
/>
|
||||
<Route
|
||||
path={SettingsPath.AIAgentDetail}
|
||||
path={SettingsPath.AiAgentDetail}
|
||||
element={<SettingsAgentForm mode="edit" />}
|
||||
/>
|
||||
<Route
|
||||
path={SettingsPath.AIAgentTurnDetail}
|
||||
path={SettingsPath.AiAgentTurnDetail}
|
||||
element={<SettingsAgentTurnDetail />}
|
||||
/>
|
||||
<Route
|
||||
path={SettingsPath.AINewSkill}
|
||||
path={SettingsPath.AiNewSkill}
|
||||
element={<SettingsSkillForm mode="create" />}
|
||||
/>
|
||||
<Route
|
||||
path={SettingsPath.AISkillDetail}
|
||||
path={SettingsPath.AiSkillDetail}
|
||||
element={<SettingsSkillForm mode="edit" />}
|
||||
/>
|
||||
<Route
|
||||
path={SettingsPath.AIUsageUserDetail}
|
||||
element={<SettingsAIUsageUserDetail />}
|
||||
path={SettingsPath.AiUsageUserDetail}
|
||||
element={<SettingsAiUsageUserDetail />}
|
||||
/>
|
||||
<Route
|
||||
path={SettingsPath.AIToolDetail}
|
||||
path={SettingsPath.AiToolDetail}
|
||||
element={<SettingsToolDetail />}
|
||||
/>
|
||||
<Route
|
||||
|
||||
+1
-1
@@ -208,7 +208,7 @@ export const ENGINE_COMPONENT_KEY_COMPONENT_MAP: Record<
|
||||
),
|
||||
[EngineComponentKey.VIEW_PREVIOUS_AI_CHATS]: (
|
||||
<HeadlessOpenSidePanelPageEngineCommand
|
||||
page={SidePanelPages.ViewPreviousAIChats}
|
||||
page={SidePanelPages.ViewPreviousAiChats}
|
||||
pageTitle={msg`View Previous AI Chats`}
|
||||
pageIcon={IconHistory}
|
||||
/>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { useKeyboardShortcutMenu } from '@/keyboard-shortcut-menu/hooks/useKeyboardShortcutMenu';
|
||||
import { SIDE_PANEL_FOCUS_ID } from '@/side-panel/constants/SidePanelFocusId';
|
||||
import { useOpenAskAIPageInSidePanel } from '@/side-panel/hooks/useOpenAskAIPageInSidePanel';
|
||||
import { useOpenAskAiPageInSidePanel } from '@/side-panel/hooks/useOpenAskAiPageInSidePanel';
|
||||
import { useOpenRecordsSearchPageInSidePanel } from '@/side-panel/hooks/useOpenRecordsSearchPageInSidePanel';
|
||||
import { useSidePanelHistory } from '@/side-panel/hooks/useSidePanelHistory';
|
||||
import { useSidePanelMenu } from '@/side-panel/hooks/useSidePanelMenu';
|
||||
@@ -20,7 +20,7 @@ export const useCommandMenuHotKeys = () => {
|
||||
|
||||
const { openRecordsSearchPage } = useOpenRecordsSearchPageInSidePanel();
|
||||
|
||||
const { openAskAIPage } = useOpenAskAIPageInSidePanel();
|
||||
const { openAskAiPage } = useOpenAskAiPageInSidePanel();
|
||||
|
||||
const { goBackFromSidePanel, goBackOneSubPageOrMainPage } =
|
||||
useSidePanelHistory();
|
||||
@@ -59,11 +59,11 @@ export const useCommandMenuHotKeys = () => {
|
||||
keys: ['@'],
|
||||
callback: () => {
|
||||
if (isAiEnabled) {
|
||||
openAskAIPage({ resetNavigationStack: true });
|
||||
openAskAiPage({ resetNavigationStack: true });
|
||||
}
|
||||
},
|
||||
containsModifier: false,
|
||||
dependencies: [openAskAIPage, isAiEnabled],
|
||||
dependencies: [openAskAiPage, isAiEnabled],
|
||||
options: {
|
||||
ignoreModifiers: true,
|
||||
},
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { currentWorkspaceState } from '@/auth/states/currentWorkspaceState';
|
||||
import { NavigationDrawerAIChatContent } from '@/ai/components/NavigationDrawerAIChatContent';
|
||||
import { NavigationDrawerAiChatContent } from '@/ai/components/NavigationDrawerAiChatContent';
|
||||
import { MainNavigationDrawerNavigationContent } from '@/navigation/components/MainNavigationDrawerNavigationContent';
|
||||
import { MainNavigationDrawerTabsRow } from '@/navigation/components/MainNavigationDrawerTabsRow';
|
||||
import { NavigationDrawer } from '@/ui/navigation/navigation-drawer/components/NavigationDrawer';
|
||||
@@ -27,7 +27,7 @@ export const MainNavigationDrawer = ({ className }: { className?: string }) => {
|
||||
<NavigationDrawerScrollableContent>
|
||||
{navigationDrawerActiveTab ===
|
||||
NAVIGATION_DRAWER_TABS.AI_CHAT_HISTORY ? (
|
||||
<NavigationDrawerAIChatContent />
|
||||
<NavigationDrawerAiChatContent />
|
||||
) : (
|
||||
<MainNavigationDrawerNavigationContent />
|
||||
)}
|
||||
|
||||
+2
-2
@@ -11,7 +11,7 @@ import { useIsMobile } from 'twenty-ui/utilities';
|
||||
|
||||
import { useContext } from 'react';
|
||||
|
||||
import { useSwitchToNewAIChat } from '@/ai/hooks/useSwitchToNewAIChat';
|
||||
import { useSwitchToNewAiChat } from '@/ai/hooks/useSwitchToNewAiChat';
|
||||
import { NavigationDrawerAnimatedCollapseWrapper } from '@/ui/navigation/navigation-drawer/components/NavigationDrawerAnimatedCollapseWrapper';
|
||||
import { isNavigationDrawerExpandedState } from '@/ui/navigation/states/isNavigationDrawerExpanded';
|
||||
import { navigationDrawerActiveTabState } from '@/ui/navigation/states/navigationDrawerActiveTabState';
|
||||
@@ -140,7 +140,7 @@ export const MainNavigationDrawerTabsRow = () => {
|
||||
);
|
||||
const [navigationDrawerActiveTab, setNavigationDrawerActiveTab] =
|
||||
useAtomState(navigationDrawerActiveTabState);
|
||||
const { switchToNewChat } = useSwitchToNewAIChat();
|
||||
const { switchToNewChat } = useSwitchToNewAiChat();
|
||||
const isAiEnabled = useIsFeatureEnabled(FeatureFlagKey.IS_AI_ENABLED);
|
||||
const setIsNavigationDrawerExpanded = useSetAtomState(
|
||||
isNavigationDrawerExpandedState,
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { useSwitchToNewAIChat } from '@/ai/hooks/useSwitchToNewAIChat';
|
||||
import { useSwitchToNewAiChat } from '@/ai/hooks/useSwitchToNewAiChat';
|
||||
import { MAIN_CONTEXT_STORE_INSTANCE_ID } from '@/context-store/constants/MainContextStoreInstanceId';
|
||||
import { contextStoreCurrentObjectMetadataItemIdComponentState } from '@/context-store/states/contextStoreCurrentObjectMetadataItemIdComponentState';
|
||||
import { useDefaultHomePagePath } from '@/navigation/hooks/useDefaultHomePagePath';
|
||||
@@ -23,7 +23,7 @@ import {
|
||||
import { NavigationBar } from 'twenty-ui/navigation';
|
||||
import { FeatureFlagKey } from '~/generated-metadata/graphql';
|
||||
|
||||
type NavigationBarItemName = 'main' | 'search' | 'newAIChat';
|
||||
type NavigationBarItemName = 'main' | 'search' | 'newAiChat';
|
||||
|
||||
export const MobileNavigationBar = () => {
|
||||
const navigate = useNavigate();
|
||||
@@ -36,7 +36,7 @@ export const MobileNavigationBar = () => {
|
||||
useAtomState(isNavigationDrawerExpandedState);
|
||||
const [currentMobileNavigationDrawer, setCurrentMobileNavigationDrawer] =
|
||||
useAtomState(currentMobileNavigationDrawerState);
|
||||
const { switchToNewChat } = useSwitchToNewAIChat();
|
||||
const { switchToNewChat } = useSwitchToNewAiChat();
|
||||
const isAiEnabled = useIsFeatureEnabled(FeatureFlagKey.IS_AI_ENABLED);
|
||||
const { alphaSortedActiveNonSystemObjectMetadataItems } =
|
||||
useFilteredObjectMetadataItems();
|
||||
@@ -95,7 +95,7 @@ export const MobileNavigationBar = () => {
|
||||
...(isAiEnabled
|
||||
? [
|
||||
{
|
||||
name: 'newAIChat' as const,
|
||||
name: 'newAiChat' as const,
|
||||
Icon: IconMessageCirclePlus,
|
||||
onClick: () => {
|
||||
setIsNavigationDrawerExpanded(false);
|
||||
|
||||
@@ -74,7 +74,7 @@ const useSettingsNavigationItems = (): SettingsNavigationSection[] => {
|
||||
const isAdminEnabled =
|
||||
(currentUser?.canImpersonate || currentUser?.canAccessFullAdminPanel) ??
|
||||
false;
|
||||
const isAIEnabled = useIsFeatureEnabled(FeatureFlagKey.IS_AI_ENABLED);
|
||||
const isAiEnabled = useIsFeatureEnabled(FeatureFlagKey.IS_AI_ENABLED);
|
||||
const isSupportChatConfigured =
|
||||
supportChat?.supportDriver === 'FRONT' &&
|
||||
isNonEmptyString(supportChat.supportFrontChatId);
|
||||
@@ -183,7 +183,7 @@ const useSettingsNavigationItems = (): SettingsNavigationSection[] => {
|
||||
path: SettingsPath.AI,
|
||||
Icon: IconSparkles,
|
||||
isHidden:
|
||||
!isAIEnabled || !permissionMap[PermissionFlagType.WORKSPACE],
|
||||
!isAiEnabled || !permissionMap[PermissionFlagType.WORKSPACE],
|
||||
modifier: 'new',
|
||||
},
|
||||
{
|
||||
|
||||
+2
-2
@@ -82,7 +82,7 @@ export const SettingsRolePermissionsObjectLevelObjectForm = ({
|
||||
},
|
||||
{
|
||||
children: agent.label,
|
||||
href: getSettingsPath(SettingsPath.AIAgentDetail, {
|
||||
href: getSettingsPath(SettingsPath.AiAgentDetail, {
|
||||
agentId: agent.id,
|
||||
}),
|
||||
},
|
||||
@@ -112,7 +112,7 @@ export const SettingsRolePermissionsObjectLevelObjectForm = ({
|
||||
|
||||
const finishButtonPath =
|
||||
fromAgentId && isDefined(agent)
|
||||
? getSettingsPath(SettingsPath.AIAgentDetail, { agentId: agent.id })
|
||||
? getSettingsPath(SettingsPath.AiAgentDetail, { agentId: agent.id })
|
||||
: getSettingsPath(SettingsPath.RoleDetail, { roleId });
|
||||
|
||||
const objectPredicates =
|
||||
|
||||
+3
-3
@@ -30,7 +30,7 @@ type UseActionRolePermissionFlagConfigParams = {
|
||||
export const useActionRolePermissionFlagConfig = ({
|
||||
assignmentCapabilities,
|
||||
}: UseActionRolePermissionFlagConfigParams = {}): SettingsRolePermissionsSettingPermission[] => {
|
||||
const isAIEnabled = useIsFeatureEnabled(FeatureFlagKey.IS_AI_ENABLED);
|
||||
const isAiEnabled = useIsFeatureEnabled(FeatureFlagKey.IS_AI_ENABLED);
|
||||
|
||||
const {
|
||||
canBeAssignedToAgents = false,
|
||||
@@ -154,7 +154,7 @@ export const useActionRolePermissionFlagConfig = ({
|
||||
canBeAssignedToUsers && !canBeAssignedToAgents && !canBeAssignedToApiKeys;
|
||||
|
||||
return allPermissions.filter((permission) => {
|
||||
if (permission.key === PermissionFlagType.AI && !isAIEnabled) {
|
||||
if (permission.key === PermissionFlagType.AI && !isAiEnabled) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -179,6 +179,6 @@ export const useActionRolePermissionFlagConfig = ({
|
||||
canBeAssignedToAgents,
|
||||
canBeAssignedToUsers,
|
||||
canBeAssignedToApiKeys,
|
||||
isAIEnabled,
|
||||
isAiEnabled,
|
||||
]);
|
||||
};
|
||||
|
||||
+3
-3
@@ -33,7 +33,7 @@ type UseSettingsRolePermissionFlagConfigParams = {
|
||||
export const useSettingsRolePermissionFlagConfig = ({
|
||||
assignmentCapabilities,
|
||||
}: UseSettingsRolePermissionFlagConfigParams = {}): SettingsRolePermissionsSettingPermission[] => {
|
||||
const isAIEnabled = useIsFeatureEnabled(FeatureFlagKey.IS_AI_ENABLED);
|
||||
const isAiEnabled = useIsFeatureEnabled(FeatureFlagKey.IS_AI_ENABLED);
|
||||
|
||||
const {
|
||||
canBeAssignedToAgents = false,
|
||||
@@ -174,7 +174,7 @@ export const useSettingsRolePermissionFlagConfig = ({
|
||||
canBeAssignedToUsers && !canBeAssignedToAgents && !canBeAssignedToApiKeys;
|
||||
|
||||
return allPermissions.filter((permission) => {
|
||||
if (permission.key === PermissionFlagType.AI_SETTINGS && !isAIEnabled) {
|
||||
if (permission.key === PermissionFlagType.AI_SETTINGS && !isAiEnabled) {
|
||||
return false;
|
||||
}
|
||||
if (hasAssignmentCapabilities) {
|
||||
@@ -198,6 +198,6 @@ export const useSettingsRolePermissionFlagConfig = ({
|
||||
canBeAssignedToAgents,
|
||||
canBeAssignedToUsers,
|
||||
canBeAssignedToApiKeys,
|
||||
isAIEnabled,
|
||||
isAiEnabled,
|
||||
]);
|
||||
};
|
||||
|
||||
+8
-8
@@ -1,5 +1,5 @@
|
||||
import { currentAIChatThreadState } from '@/ai/states/currentAIChatThreadState';
|
||||
import { currentAIChatThreadTitleComponentFamilyState } from '@/ai/states/currentAIChatThreadTitleComponentFamilyState';
|
||||
import { currentAiChatThreadState } from '@/ai/states/currentAiChatThreadState';
|
||||
import { currentAiChatThreadTitleComponentFamilyState } from '@/ai/states/currentAiChatThreadTitleComponentFamilyState';
|
||||
import { useAtomComponentFamilyStateValue } from '@/ui/utilities/state/jotai/hooks/useAtomComponentFamilyStateValue';
|
||||
import { useAtomStateValue } from '@/ui/utilities/state/jotai/hooks/useAtomStateValue';
|
||||
import { styled } from '@linaria/react';
|
||||
@@ -13,17 +13,17 @@ const StyledPageTitle = styled.div`
|
||||
font-weight: ${themeCssVariables.font.weight.semiBold};
|
||||
`;
|
||||
|
||||
export const SidePanelAskAIInfo = () => {
|
||||
const currentAIChatThread = useAtomStateValue(currentAIChatThreadState);
|
||||
const currentAIChatThreadTitle = useAtomComponentFamilyStateValue(
|
||||
currentAIChatThreadTitleComponentFamilyState,
|
||||
{ threadId: currentAIChatThread },
|
||||
export const SidePanelAskAiInfo = () => {
|
||||
const currentAiChatThread = useAtomStateValue(currentAiChatThreadState);
|
||||
const currentAiChatThreadTitle = useAtomComponentFamilyStateValue(
|
||||
currentAiChatThreadTitleComponentFamilyState,
|
||||
{ threadId: currentAiChatThread },
|
||||
);
|
||||
|
||||
return (
|
||||
<StyledPageTitle>
|
||||
<OverflowingTextWithTooltip
|
||||
text={currentAIChatThreadTitle ?? t`Ask AI`}
|
||||
text={currentAiChatThreadTitle ?? t`Ask AI`}
|
||||
/>
|
||||
</StyledPageTitle>
|
||||
);
|
||||
@@ -7,7 +7,7 @@ import {
|
||||
|
||||
import { selectedNavigationMenuItemIdInEditModeState } from '@/navigation-menu-item/common/states/selectedNavigationMenuItemIdInEditModeState';
|
||||
import { useNavigationMenuItemSectionItems } from '@/navigation-menu-item/display/hooks/useNavigationMenuItemSectionItems';
|
||||
import { SidePanelAskAIInfo } from '@/side-panel/components/SidePanelAskAIInfo';
|
||||
import { SidePanelAskAiInfo } from '@/side-panel/components/SidePanelAskAiInfo';
|
||||
import { SidePanelFolderInfo } from '@/side-panel/components/SidePanelFolderInfo';
|
||||
import { SidePanelLinkInfo } from '@/side-panel/components/SidePanelLinkInfo';
|
||||
import { SidePanelMultipleRecordsInfo } from '@/side-panel/components/SidePanelMultipleRecordsInfo';
|
||||
@@ -114,10 +114,10 @@ export const SidePanelPageInfo = ({ pageChip }: SidePanelPageInfoProps) => {
|
||||
);
|
||||
}
|
||||
|
||||
const isAskAIPage = pageChip.page?.page === SidePanelPages.AskAI;
|
||||
const isAskAiPage = pageChip.page?.page === SidePanelPages.AskAI;
|
||||
|
||||
if (isAskAIPage) {
|
||||
return <SidePanelAskAIInfo />;
|
||||
if (isAskAiPage) {
|
||||
return <SidePanelAskAiInfo />;
|
||||
}
|
||||
|
||||
if (pageChip.page?.page === SidePanelPages.NavigationMenuAddItem) {
|
||||
|
||||
+5
-5
@@ -1,4 +1,4 @@
|
||||
import { useSwitchToNewAIChat } from '@/ai/hooks/useSwitchToNewAIChat';
|
||||
import { useSwitchToNewAiChat } from '@/ai/hooks/useSwitchToNewAiChat';
|
||||
import { SidePanelObjectFilterDropdown } from '@/side-panel/components/SidePanelObjectFilterDropdown';
|
||||
import { sidePanelPageState } from '@/side-panel/states/sidePanelPageState';
|
||||
import { sidePanelSearchObjectFilterState } from '@/side-panel/states/sidePanelSearchObjectFilterState';
|
||||
@@ -22,7 +22,7 @@ export const SidePanelTopBarRightCornerIcon = () => {
|
||||
const isMobile = useIsMobile();
|
||||
const isAiEnabled = useIsFeatureEnabled(FeatureFlagKey.IS_AI_ENABLED);
|
||||
const sidePanelPage = useAtomStateValue(sidePanelPageState);
|
||||
const { switchToNewChat } = useSwitchToNewAIChat();
|
||||
const { switchToNewChat } = useSwitchToNewAiChat();
|
||||
const [sidePanelSearchObjectFilter, setSidePanelSearchObjectFilter] =
|
||||
useAtomState(sidePanelSearchObjectFilterState);
|
||||
|
||||
@@ -37,12 +37,12 @@ export const SidePanelTopBarRightCornerIcon = () => {
|
||||
);
|
||||
}
|
||||
|
||||
const isOnAskAIPage = [
|
||||
const isOnAskAiPage = [
|
||||
SidePanelPages.AskAI,
|
||||
SidePanelPages.ViewPreviousAIChats,
|
||||
SidePanelPages.ViewPreviousAiChats,
|
||||
].includes(sidePanelPage);
|
||||
|
||||
if (isMobile || !isAiEnabled || !isOnAskAIPage) {
|
||||
if (isMobile || !isAiEnabled || !isOnAskAiPage) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
@@ -2,8 +2,8 @@ import { SidePanelCommandMenuItemDisplayPage } from '@/command-menu-item/display
|
||||
import { SidePanelCommandMenuItemEditPage } from '@/command-menu-item/edit/components/SidePanelCommandMenuItemEditPage';
|
||||
import { SidePanelNavigationMenuItemEditPage } from '@/navigation-menu-item/edit/side-panel/components/SidePanelNavigationMenuItemEditPage';
|
||||
import { SidePanelNewSidebarItemPage } from '@/navigation-menu-item/edit/side-panel/components/SidePanelNewSidebarItemPage';
|
||||
import { SidePanelAIChatThreadsPage } from '@/side-panel/pages/ai-chat-threads/components/SidePanelAIChatThreadsPage';
|
||||
import { SidePanelAskAIPage } from '@/side-panel/pages/ask-ai/components/SidePanelAskAIPage';
|
||||
import { SidePanelAiChatThreadsPage } from '@/side-panel/pages/ai-chat-threads/components/SidePanelAiChatThreadsPage';
|
||||
import { SidePanelAskAiPage } from '@/side-panel/pages/ask-ai/components/SidePanelAskAiPage';
|
||||
import { SidePanelCalendarEventPage } from '@/side-panel/pages/calendar-event/components/SidePanelCalendarEventPage';
|
||||
import { SidePanelComposeEmailPage } from '@/side-panel/pages/compose-email/components/SidePanelComposeEmailPage';
|
||||
import { SidePanelFrontComponentPage } from '@/side-panel/pages/front-component/components/SidePanelFrontComponentPage';
|
||||
@@ -49,8 +49,8 @@ export const SIDE_PANEL_PAGES_CONFIG = new Map<SidePanelPages, React.ReactNode>(
|
||||
[SidePanelPages.WorkflowStepView, <SidePanelWorkflowViewStep />],
|
||||
[SidePanelPages.WorkflowRunStepView, <SidePanelWorkflowRunViewStep />],
|
||||
[SidePanelPages.SearchRecords, <SidePanelSearchRecordsPage />],
|
||||
[SidePanelPages.AskAI, <SidePanelAskAIPage />],
|
||||
[SidePanelPages.ViewPreviousAIChats, <SidePanelAIChatThreadsPage />],
|
||||
[SidePanelPages.AskAI, <SidePanelAskAiPage />],
|
||||
[SidePanelPages.ViewPreviousAiChats, <SidePanelAiChatThreadsPage />],
|
||||
[
|
||||
SidePanelPages.PageLayoutDashboardWidgetTypeSelect,
|
||||
<SidePanelPageLayoutDashboardWidgetTypeSelect />,
|
||||
|
||||
+8
-8
@@ -2,7 +2,7 @@ import { act, renderHook } from '@testing-library/react';
|
||||
import { Provider as JotaiProvider } from 'jotai';
|
||||
import { type ReactNode } from 'react';
|
||||
|
||||
import { useOpenAskAIPageInSidePanel } from '@/side-panel/hooks/useOpenAskAIPageInSidePanel';
|
||||
import { useOpenAskAiPageInSidePanel } from '@/side-panel/hooks/useOpenAskAiPageInSidePanel';
|
||||
import { isSidePanelOpenedState } from '@/side-panel/states/isSidePanelOpenedState';
|
||||
import { jotaiStore } from '@/ui/utilities/state/jotai/jotaiStore';
|
||||
import { SidePanelPages } from 'twenty-shared/types';
|
||||
@@ -23,19 +23,19 @@ const Wrapper = ({ children }: { children: ReactNode }) => (
|
||||
<JotaiProvider store={jotaiStore}>{children}</JotaiProvider>
|
||||
);
|
||||
|
||||
describe('useOpenAskAIPageInSidePanel', () => {
|
||||
describe('useOpenAskAiPageInSidePanel', () => {
|
||||
beforeEach(() => {
|
||||
jest.clearAllMocks();
|
||||
jotaiStore.set(isSidePanelOpenedState.atom, false);
|
||||
});
|
||||
|
||||
it('should navigate to AskAI page with correct defaults', () => {
|
||||
const { result } = renderHook(() => useOpenAskAIPageInSidePanel(), {
|
||||
const { result } = renderHook(() => useOpenAskAiPageInSidePanel(), {
|
||||
wrapper: Wrapper,
|
||||
});
|
||||
|
||||
act(() => {
|
||||
result.current.openAskAIPage();
|
||||
result.current.openAskAiPage();
|
||||
});
|
||||
|
||||
expect(navigateSidePanelMenuMock).toHaveBeenCalledWith(
|
||||
@@ -50,12 +50,12 @@ describe('useOpenAskAIPageInSidePanel', () => {
|
||||
it('should use resetNavigationStack from argument when provided', () => {
|
||||
jotaiStore.set(isSidePanelOpenedState.atom, true);
|
||||
|
||||
const { result } = renderHook(() => useOpenAskAIPageInSidePanel(), {
|
||||
const { result } = renderHook(() => useOpenAskAiPageInSidePanel(), {
|
||||
wrapper: Wrapper,
|
||||
});
|
||||
|
||||
act(() => {
|
||||
result.current.openAskAIPage({ resetNavigationStack: false });
|
||||
result.current.openAskAiPage({ resetNavigationStack: false });
|
||||
});
|
||||
|
||||
expect(navigateSidePanelMenuMock).toHaveBeenCalledWith(
|
||||
@@ -68,12 +68,12 @@ describe('useOpenAskAIPageInSidePanel', () => {
|
||||
it('should default resetNavigationStack to isSidePanelOpened', () => {
|
||||
jotaiStore.set(isSidePanelOpenedState.atom, true);
|
||||
|
||||
const { result } = renderHook(() => useOpenAskAIPageInSidePanel(), {
|
||||
const { result } = renderHook(() => useOpenAskAiPageInSidePanel(), {
|
||||
wrapper: Wrapper,
|
||||
});
|
||||
|
||||
act(() => {
|
||||
result.current.openAskAIPage();
|
||||
result.current.openAskAiPage();
|
||||
});
|
||||
|
||||
expect(navigateSidePanelMenuMock).toHaveBeenCalledWith(
|
||||
+3
-3
@@ -7,11 +7,11 @@ import { SidePanelPages } from 'twenty-shared/types';
|
||||
import { IconSparkles } from 'twenty-ui/display';
|
||||
import { v4 } from 'uuid';
|
||||
|
||||
export const useOpenAskAIPageInSidePanel = () => {
|
||||
export const useOpenAskAiPageInSidePanel = () => {
|
||||
const { navigateSidePanelMenu } = useSidePanelMenu();
|
||||
const isSidePanelOpened = useAtomStateValue(isSidePanelOpenedState);
|
||||
|
||||
const openAskAIPage = useCallback(
|
||||
const openAskAiPage = useCallback(
|
||||
({
|
||||
resetNavigationStack,
|
||||
}: {
|
||||
@@ -34,6 +34,6 @@ export const useOpenAskAIPageInSidePanel = () => {
|
||||
);
|
||||
|
||||
return {
|
||||
openAskAIPage,
|
||||
openAskAiPage,
|
||||
};
|
||||
};
|
||||
+3
-3
@@ -1,4 +1,4 @@
|
||||
import { AIChatThreadsList } from '@/ai/components/AIChatThreadsList';
|
||||
import { AiChatThreadsList } from '@/ai/components/AiChatThreadsList';
|
||||
import { styled } from '@linaria/react';
|
||||
|
||||
const StyledContainer = styled.div`
|
||||
@@ -6,10 +6,10 @@ const StyledContainer = styled.div`
|
||||
width: 100%;
|
||||
`;
|
||||
|
||||
export const SidePanelAIChatThreadsPage = () => {
|
||||
export const SidePanelAiChatThreadsPage = () => {
|
||||
return (
|
||||
<StyledContainer>
|
||||
<AIChatThreadsList />
|
||||
<AiChatThreadsList />
|
||||
</StyledContainer>
|
||||
);
|
||||
};
|
||||
+3
-3
@@ -1,15 +1,15 @@
|
||||
import { styled } from '@linaria/react';
|
||||
import { AIChatTab } from '@/ai/components/AIChatTab';
|
||||
import { AiChatTab } from '@/ai/components/AiChatTab';
|
||||
|
||||
const StyledContainer = styled.div`
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
`;
|
||||
|
||||
export const SidePanelAskAIPage = () => {
|
||||
export const SidePanelAskAiPage = () => {
|
||||
return (
|
||||
<StyledContainer>
|
||||
<AIChatTab />
|
||||
<AiChatTab />
|
||||
</StyledContainer>
|
||||
);
|
||||
};
|
||||
+1
-1
@@ -85,7 +85,7 @@ export const WorkflowStepFooter = ({
|
||||
const handleViewAgent = () => {
|
||||
closeDropdown(dropdownId);
|
||||
if (isDefined(agentId)) {
|
||||
navigateSettings(SettingsPath.AIAgentDetail, { agentId });
|
||||
navigateSettings(SettingsPath.AiAgentDetail, { agentId });
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
+2
-2
@@ -1,8 +1,8 @@
|
||||
import { gql } from '@apollo/client';
|
||||
|
||||
export const GET_AI_SYSTEM_PROMPT_PREVIEW = gql`
|
||||
query GetAISystemPromptPreview {
|
||||
getAISystemPromptPreview {
|
||||
query GetAiSystemPromptPreview {
|
||||
getAiSystemPromptPreview {
|
||||
sections {
|
||||
title
|
||||
content
|
||||
@@ -93,10 +93,10 @@ export const SettingsAdminNewAiProvider = () => {
|
||||
const hasSelected = selectedModelsDevId !== null || isCustomMode;
|
||||
const npmPackage = form.watch('npm');
|
||||
const isBedrock = npmPackage === '@ai-sdk/amazon-bedrock';
|
||||
const isOpenAICompatible = npmPackage === '@ai-sdk/openai-compatible';
|
||||
const isOpenAiCompatible = npmPackage === '@ai-sdk/openai-compatible';
|
||||
const needsApiKey = !isBedrock;
|
||||
const isModelsDevWithoutNativeSdk =
|
||||
selectedModelsDevId !== null && isOpenAICompatible;
|
||||
selectedModelsDevId !== null && isOpenAiCompatible;
|
||||
|
||||
const handleProviderSelected = (providerId: string) => {
|
||||
setSelectedModelsDevId(providerId);
|
||||
@@ -150,7 +150,7 @@ export const SettingsAdminNewAiProvider = () => {
|
||||
values.apiKey.trim() && {
|
||||
apiKey: values.apiKey.trim(),
|
||||
}),
|
||||
...(isOpenAICompatible &&
|
||||
...(isOpenAiCompatible &&
|
||||
values.baseUrl.trim() && {
|
||||
baseUrl: values.baseUrl.trim(),
|
||||
}),
|
||||
@@ -178,7 +178,7 @@ export const SettingsAdminNewAiProvider = () => {
|
||||
}
|
||||
}
|
||||
|
||||
if (!isBedrock && !isOpenAICompatible && !values.apiKey.trim()) {
|
||||
if (!isBedrock && !isOpenAiCompatible && !values.apiKey.trim()) {
|
||||
form.setError('apiKey', {
|
||||
type: 'manual',
|
||||
message: t`API key is required`,
|
||||
@@ -187,7 +187,7 @@ export const SettingsAdminNewAiProvider = () => {
|
||||
return;
|
||||
}
|
||||
|
||||
if (isOpenAICompatible && !values.baseUrl.trim()) {
|
||||
if (isOpenAiCompatible && !values.baseUrl.trim()) {
|
||||
form.setError('baseUrl', {
|
||||
type: 'manual',
|
||||
message: t`Base URL is required`,
|
||||
@@ -325,7 +325,7 @@ export const SettingsAdminNewAiProvider = () => {
|
||||
</Section>
|
||||
)}
|
||||
|
||||
{isOpenAICompatible && (
|
||||
{isOpenAiCompatible && (
|
||||
<Section>
|
||||
<H2Title
|
||||
title={t`Base URL`}
|
||||
|
||||
@@ -22,10 +22,10 @@ import {
|
||||
} from 'twenty-ui/display';
|
||||
import { Button } from 'twenty-ui/input';
|
||||
import { UndecoratedLink } from 'twenty-ui/navigation';
|
||||
import { SettingsAIMoreTab } from '~/pages/settings/ai/components/SettingsAIMoreTab';
|
||||
import { SettingsAiMoreTab } from '~/pages/settings/ai/components/SettingsAiMoreTab';
|
||||
import { SettingsAgentToolsTab } from '~/pages/settings/ai/components/SettingsAgentToolsTab';
|
||||
import { SettingsAIModelsTab } from './components/SettingsAIModelsTab';
|
||||
import { SettingsAIUsageTab } from './components/SettingsAIUsageTab';
|
||||
import { SettingsAiModelsTab } from './components/SettingsAiModelsTab';
|
||||
import { SettingsAiUsageTab } from './components/SettingsAiUsageTab';
|
||||
import { SettingsAgentSkills } from './components/SettingsAgentSkills';
|
||||
import { SETTINGS_AI_TABS } from './constants/SettingsAiTabs';
|
||||
|
||||
@@ -117,7 +117,7 @@ export const SettingsAI = () => {
|
||||
title={t`AI`}
|
||||
actionButton={
|
||||
isSkillsTab ? (
|
||||
<UndecoratedLink to={getSettingsPath(SettingsPath.AINewSkill)}>
|
||||
<UndecoratedLink to={getSettingsPath(SettingsPath.AiNewSkill)}>
|
||||
<Button
|
||||
Icon={IconPlus}
|
||||
title={t`New Skill`}
|
||||
@@ -149,11 +149,11 @@ export const SettingsAI = () => {
|
||||
tabs={tabs}
|
||||
componentInstanceId={SETTINGS_AI_TABS.COMPONENT_INSTANCE_ID}
|
||||
/>
|
||||
{isModelsTab && <SettingsAIModelsTab />}
|
||||
{isModelsTab && <SettingsAiModelsTab />}
|
||||
{isSkillsTab && <SettingsAgentSkills />}
|
||||
{isToolsTab && <SettingsAgentToolsTab />}
|
||||
{isUsageTab && <SettingsAIUsageTab />}
|
||||
{isMoreTab && <SettingsAIMoreTab />}
|
||||
{isUsageTab && <SettingsAiUsageTab />}
|
||||
{isMoreTab && <SettingsAiMoreTab />}
|
||||
</SettingsPageContainer>
|
||||
</SubMenuTopBarContainer>
|
||||
);
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { AIChatAssistantMessageRenderer } from '@/ai/components/AIChatAssistantMessageRenderer';
|
||||
import { AiChatAssistantMessageRenderer } from '@/ai/components/AiChatAssistantMessageRenderer';
|
||||
import { mapDBMessagesToUIMessages } from '@/ai/utils/mapDBMessagesToUIMessages';
|
||||
import { SettingsPageContainer } from '@/settings/components/SettingsPageContainer';
|
||||
import { SubMenuTopBarContainer } from '@/ui/layout/page/components/SubMenuTopBarContainer';
|
||||
@@ -84,7 +84,7 @@ export const SettingsAgentTurnDetail = () => {
|
||||
{ children: t`AI`, href: getSettingsPath(SettingsPath.AI) },
|
||||
{
|
||||
children: t`Agent`,
|
||||
href: getSettingsPath(SettingsPath.AIAgentDetail).replace(
|
||||
href: getSettingsPath(SettingsPath.AiAgentDetail).replace(
|
||||
':agentId',
|
||||
agentId || '',
|
||||
),
|
||||
@@ -130,7 +130,7 @@ export const SettingsAgentTurnDetail = () => {
|
||||
{ children: t`AI`, href: getSettingsPath(SettingsPath.AI) },
|
||||
{
|
||||
children: t`Agent`,
|
||||
href: getSettingsPath(SettingsPath.AIAgentDetail).replace(
|
||||
href: getSettingsPath(SettingsPath.AiAgentDetail).replace(
|
||||
':agentId',
|
||||
agentId || '',
|
||||
),
|
||||
@@ -171,7 +171,7 @@ export const SettingsAgentTurnDetail = () => {
|
||||
<StyledMessageBubble key={message.id}>
|
||||
<StyledMessageRole>{roleLabel}</StyledMessageRole>
|
||||
<StyledMessageContent>
|
||||
<AIChatAssistantMessageRenderer
|
||||
<AiChatAssistantMessageRenderer
|
||||
messageParts={message.parts}
|
||||
isLastMessageStreaming={false}
|
||||
/>
|
||||
|
||||
+2
-2
@@ -28,14 +28,14 @@ const StyledTitleContainer = styled.div`
|
||||
margin-top: ${themeCssVariables.spacing[2]};
|
||||
`;
|
||||
|
||||
export const SettingsAIPrompts = () => {
|
||||
export const SettingsAiPrompts = () => {
|
||||
const currentWorkspaceMember = useAtomStateValue(currentWorkspaceMemberState);
|
||||
|
||||
const { data: previewData, loading: previewLoading } = useQuery(
|
||||
GetAiSystemPromptPreviewDocument,
|
||||
);
|
||||
|
||||
const preview = previewData?.getAISystemPromptPreview;
|
||||
const preview = previewData?.getAiSystemPromptPreview;
|
||||
const sections = preview?.sections ?? [];
|
||||
|
||||
const buildUserContextPreview = (): string => {
|
||||
+1
-1
@@ -14,7 +14,7 @@ import { SettingsPath } from 'twenty-shared/types';
|
||||
import { getSettingsPath } from 'twenty-shared/utils';
|
||||
import { Section } from 'twenty-ui/layout';
|
||||
|
||||
export const SettingsAIUsageUserDetail = () => {
|
||||
export const SettingsAiUsageUserDetail = () => {
|
||||
const { t: tLingui } = useLingui();
|
||||
const { userWorkspaceId } = useParams<{ userWorkspaceId: string }>();
|
||||
|
||||
@@ -239,7 +239,7 @@ export const SettingsAgentLogsTab = ({
|
||||
>
|
||||
{latestEvaluation && (
|
||||
<UndecoratedLink
|
||||
to={getSettingsPath(SettingsPath.AIAgentTurnDetail)
|
||||
to={getSettingsPath(SettingsPath.AiAgentTurnDetail)
|
||||
.replace(':agentId', agentId)
|
||||
.replace(':turnId', turn.id)}
|
||||
>
|
||||
|
||||
@@ -20,7 +20,7 @@ import {
|
||||
CreateOneRoleDocument,
|
||||
GetRolesDocument,
|
||||
} from '~/generated-metadata/graphql';
|
||||
import { type SettingsAIAgentFormValues } from '~/pages/settings/ai/hooks/useSettingsAgentFormState';
|
||||
import { type SettingsAiAgentFormValues } from '~/pages/settings/ai/hooks/useSettingsAgentFormState';
|
||||
|
||||
const StyledWarningText = styled.div`
|
||||
color: ${themeCssVariables.font.color.tertiary};
|
||||
@@ -29,10 +29,10 @@ const StyledWarningText = styled.div`
|
||||
`;
|
||||
|
||||
type SettingsAgentRoleTabProps = {
|
||||
formValues: SettingsAIAgentFormValues;
|
||||
formValues: SettingsAiAgentFormValues;
|
||||
onFieldChange: (
|
||||
field: keyof SettingsAIAgentFormValues,
|
||||
value: SettingsAIAgentFormValues[keyof SettingsAIAgentFormValues],
|
||||
field: keyof SettingsAiAgentFormValues,
|
||||
value: SettingsAiAgentFormValues[keyof SettingsAiAgentFormValues],
|
||||
) => void;
|
||||
disabled: boolean;
|
||||
agentId?: string;
|
||||
|
||||
@@ -21,7 +21,7 @@ import { type Agent } from '~/generated-metadata/graphql';
|
||||
import { SettingsAgentDeleteConfirmationModal } from '~/pages/settings/ai/components/SettingsAgentDeleteConfirmationModal';
|
||||
import { SettingsAgentResponseFormat } from '~/pages/settings/ai/components/SettingsAgentResponseFormat';
|
||||
import { computeMetadataNameFromLabel } from '~/pages/settings/data-model/utils/computeMetadataNameFromLabel';
|
||||
import { type SettingsAIAgentFormValues } from '~/pages/settings/ai/hooks/useSettingsAgentFormState';
|
||||
import { type SettingsAiAgentFormValues } from '~/pages/settings/ai/hooks/useSettingsAgentFormState';
|
||||
import { useAtomStateValue } from '@/ui/utilities/state/jotai/hooks/useAtomStateValue';
|
||||
|
||||
const StyledFormContainer = styled.div`
|
||||
@@ -49,10 +49,10 @@ const StyledErrorMessage = styled.div`
|
||||
const DELETE_AGENT_MODAL_ID = 'delete-agent-modal';
|
||||
|
||||
type SettingsAgentSettingsTabProps = {
|
||||
formValues: SettingsAIAgentFormValues;
|
||||
formValues: SettingsAiAgentFormValues;
|
||||
onFieldChange: (
|
||||
field: keyof SettingsAIAgentFormValues,
|
||||
value: SettingsAIAgentFormValues[keyof SettingsAIAgentFormValues],
|
||||
field: keyof SettingsAiAgentFormValues,
|
||||
value: SettingsAiAgentFormValues[keyof SettingsAiAgentFormValues],
|
||||
) => void;
|
||||
disabled: boolean;
|
||||
agent?: Agent;
|
||||
|
||||
@@ -85,7 +85,7 @@ export const SettingsAgentSkillsTable = ({
|
||||
}
|
||||
link={
|
||||
skill.isActive
|
||||
? getSettingsPath(SettingsPath.AISkillDetail, {
|
||||
? getSettingsPath(SettingsPath.AiSkillDetail, {
|
||||
skillId: skill.id,
|
||||
})
|
||||
: undefined
|
||||
|
||||
+3
-3
@@ -8,7 +8,7 @@ import { OverflowingTextWithTooltip, useIcons } from 'twenty-ui/display';
|
||||
import { ThemeContext, themeCssVariables } from 'twenty-ui/theme-constants';
|
||||
import { type Agent } from '~/generated-metadata/graphql';
|
||||
|
||||
export type SettingsAIAgentTableRowProps = {
|
||||
export type SettingsAiAgentTableRowProps = {
|
||||
action: ReactNode;
|
||||
agent: Agent;
|
||||
link?: string;
|
||||
@@ -21,11 +21,11 @@ const StyledIconContainer = styled.div`
|
||||
height: ${themeCssVariables.spacing[4]};
|
||||
`;
|
||||
|
||||
export const SettingsAIAgentTableRow = ({
|
||||
export const SettingsAiAgentTableRow = ({
|
||||
action,
|
||||
agent,
|
||||
link,
|
||||
}: SettingsAIAgentTableRowProps) => {
|
||||
}: SettingsAiAgentTableRowProps) => {
|
||||
const { theme } = useContext(ThemeContext);
|
||||
const { getIcon } = useIcons();
|
||||
const Icon = getIcon(agent.icon || 'IconRobot');
|
||||
+10
-10
@@ -24,8 +24,8 @@ import { FindManyAgentsDocument } from '~/generated-metadata/graphql';
|
||||
import { TableRow } from '@/ui/layout/table/components/TableRow';
|
||||
import {
|
||||
AI_AGENT_TABLE_ROW_GRID_TEMPLATE_COLUMNS,
|
||||
SettingsAIAgentTableRow,
|
||||
} from './SettingsAIAgentTableRow';
|
||||
SettingsAiAgentTableRow,
|
||||
} from './SettingsAiAgentTableRow';
|
||||
|
||||
const StyledSearchContainer = styled.div`
|
||||
margin-bottom: ${themeCssVariables.spacing[2]};
|
||||
@@ -39,7 +39,7 @@ const StyledTableHeaderRowContainer = styled.div`
|
||||
margin-bottom: ${themeCssVariables.spacing[2]};
|
||||
`;
|
||||
|
||||
export const SettingsAIAgentsTable = () => {
|
||||
export const SettingsAiAgentsTable = () => {
|
||||
const { theme } = useContext(ThemeContext);
|
||||
const { data, loading } = useQuery(FindManyAgentsDocument);
|
||||
|
||||
@@ -104,13 +104,13 @@ export const SettingsAIAgentsTable = () => {
|
||||
gridTemplateColumns={AI_AGENT_TABLE_ROW_GRID_TEMPLATE_COLUMNS}
|
||||
>
|
||||
{SETTINGS_AI_AGENT_TABLE_METADATA.fields.map(
|
||||
(settingsAIAgentTableMetadataField) => (
|
||||
(settingsAiAgentTableMetadataField) => (
|
||||
<SortableTableHeader
|
||||
key={settingsAIAgentTableMetadataField.fieldName}
|
||||
fieldName={settingsAIAgentTableMetadataField.fieldName}
|
||||
label={t(settingsAIAgentTableMetadataField.fieldLabel)}
|
||||
key={settingsAiAgentTableMetadataField.fieldName}
|
||||
fieldName={settingsAiAgentTableMetadataField.fieldName}
|
||||
label={t(settingsAiAgentTableMetadataField.fieldLabel)}
|
||||
tableId={SETTINGS_AI_AGENT_TABLE_METADATA.tableId}
|
||||
align={settingsAIAgentTableMetadataField.align}
|
||||
align={settingsAiAgentTableMetadataField.align}
|
||||
initialSort={SETTINGS_AI_AGENT_TABLE_METADATA.initialSort}
|
||||
/>
|
||||
),
|
||||
@@ -123,7 +123,7 @@ export const SettingsAIAgentsTable = () => {
|
||||
<Skeleton height={32} borderRadius={4} key={index} />
|
||||
))}
|
||||
{filteredAgents.map((agent) => (
|
||||
<SettingsAIAgentTableRow
|
||||
<SettingsAiAgentTableRow
|
||||
key={agent.id}
|
||||
agent={agent}
|
||||
action={
|
||||
@@ -132,7 +132,7 @@ export const SettingsAIAgentsTable = () => {
|
||||
stroke={theme.icon.stroke.sm}
|
||||
/>
|
||||
}
|
||||
link={getSettingsPath(SettingsPath.AIAgentDetail, {
|
||||
link={getSettingsPath(SettingsPath.AiAgentDetail, {
|
||||
agentId: agent.id,
|
||||
})}
|
||||
/>
|
||||
+1
-1
@@ -51,7 +51,7 @@ const StyledEditorContainer = styled.div`
|
||||
|
||||
type McpAuthMethod = 'oauth' | 'api-key';
|
||||
|
||||
export const SettingsAIMCP = () => {
|
||||
export const SettingsAiMCP = () => {
|
||||
const { t } = useLingui();
|
||||
const { copyToClipboard } = useCopyToClipboard();
|
||||
const [authMethod, setAuthMethod] = useState<McpAuthMethod>('oauth');
|
||||
+1
-1
@@ -34,7 +34,7 @@ const StyledCustomModelsContainer = styled.div`
|
||||
padding-top: ${themeCssVariables.spacing[4]};
|
||||
`;
|
||||
|
||||
export const SettingsAIModelsTab = () => {
|
||||
export const SettingsAiModelsTab = () => {
|
||||
const { enqueueErrorSnackBar } = useSnackBar();
|
||||
const [currentWorkspace, setCurrentWorkspace] = useAtomState(
|
||||
currentWorkspaceState,
|
||||
+5
-5
@@ -19,7 +19,7 @@ import {
|
||||
GetAiSystemPromptPreviewDocument,
|
||||
UpdateWorkspaceDocument,
|
||||
} from '~/generated-metadata/graphql';
|
||||
import { SettingsAIMCP } from '~/pages/settings/ai/components/SettingsAIMCP';
|
||||
import { SettingsAiMCP } from '~/pages/settings/ai/components/SettingsAiMCP';
|
||||
import { formatNumber } from '~/utils/format/formatNumber';
|
||||
|
||||
const StyledFormContainer = styled.div`
|
||||
@@ -28,7 +28,7 @@ const StyledFormContainer = styled.div`
|
||||
gap: ${themeCssVariables.spacing[4]};
|
||||
`;
|
||||
|
||||
export const SettingsAIMoreTab = () => {
|
||||
export const SettingsAiMoreTab = () => {
|
||||
const { theme } = useContext(ThemeContext);
|
||||
const { enqueueErrorSnackBar } = useSnackBar();
|
||||
const [currentWorkspace, setCurrentWorkspace] = useAtomState(
|
||||
@@ -87,7 +87,7 @@ export const SettingsAIMoreTab = () => {
|
||||
};
|
||||
|
||||
const systemPromptTokenCount =
|
||||
previewData?.getAISystemPromptPreview.estimatedTokenCount;
|
||||
previewData?.getAiSystemPromptPreview.estimatedTokenCount;
|
||||
const systemPromptDescription = isDefined(systemPromptTokenCount)
|
||||
? t`Read the system prompts to understand how the AI works (~${formatNumber(
|
||||
systemPromptTokenCount,
|
||||
@@ -128,7 +128,7 @@ export const SettingsAIMoreTab = () => {
|
||||
/>
|
||||
</StyledFormContainer>
|
||||
</Section>
|
||||
<SettingsAIMCP />
|
||||
<SettingsAiMCP />
|
||||
|
||||
<Section>
|
||||
<H2Title
|
||||
@@ -136,7 +136,7 @@ export const SettingsAIMoreTab = () => {
|
||||
description={systemPromptDescription}
|
||||
/>
|
||||
|
||||
<UndecoratedLink to={getSettingsPath(SettingsPath.AIPrompts)}>
|
||||
<UndecoratedLink to={getSettingsPath(SettingsPath.AiPrompts)}>
|
||||
<SettingsCard
|
||||
Icon={<IconPrompt size={theme.icon.size.md} />}
|
||||
title={t`Read system prompts`}
|
||||
+2
-2
@@ -18,7 +18,7 @@ import { Tag } from 'twenty-ui/components';
|
||||
import { H2Title, IconLock } from 'twenty-ui/display';
|
||||
import { Section } from 'twenty-ui/layout';
|
||||
|
||||
export const SettingsAIUsageTab = () => {
|
||||
export const SettingsAiUsageTab = () => {
|
||||
const currentWorkspace = useAtomStateValue(currentWorkspaceState);
|
||||
const billing = useAtomStateValue(billingState);
|
||||
const isBillingEnabled = billing?.isBillingEnabled ?? false;
|
||||
@@ -130,7 +130,7 @@ export const SettingsAIUsageTab = () => {
|
||||
description={t`Click a user to see their daily breakdown.`}
|
||||
operationTypes={AI_OPERATION_TYPES}
|
||||
getDetailPath={(userWorkspaceId) =>
|
||||
getSettingsPath(SettingsPath.AIUsageUserDetail, {
|
||||
getSettingsPath(SettingsPath.AiUsageUserDetail, {
|
||||
userWorkspaceId,
|
||||
})
|
||||
}
|
||||
@@ -115,7 +115,7 @@ export const SettingsToolsTable = () => {
|
||||
const isCustom = (item: ToolItem) => isDefined(item.applicationId);
|
||||
|
||||
const getToolLink = (item: ToolItem) =>
|
||||
getSettingsPath(SettingsPath.AIToolDetail, {
|
||||
getSettingsPath(SettingsPath.AiToolDetail, {
|
||||
toolIdentifier: item.identifier,
|
||||
});
|
||||
|
||||
|
||||
+1
-1
@@ -3,7 +3,7 @@ import { msg } from '@lingui/core/macro';
|
||||
import { type Agent } from '~/generated-metadata/graphql';
|
||||
|
||||
export const SETTINGS_AI_AGENT_TABLE_METADATA: TableMetadata<Agent> = {
|
||||
tableId: 'settingsAIAgent',
|
||||
tableId: 'settingsAiAgent',
|
||||
fields: [
|
||||
{
|
||||
fieldLabel: msg`Name`,
|
||||
|
||||
+7
-7
@@ -10,7 +10,7 @@ import { TextArea } from '@/ui/input/components/TextArea';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
import { themeCssVariables } from 'twenty-ui/theme-constants';
|
||||
import { computeMetadataNameFromLabel } from '~/pages/settings/data-model/utils/computeMetadataNameFromLabel';
|
||||
import { type SettingsAIAgentFormValues } from '~/pages/settings/ai/hooks/useSettingsAgentFormState';
|
||||
import { type SettingsAiAgentFormValues } from '~/pages/settings/ai/hooks/useSettingsAgentFormState';
|
||||
|
||||
const StyledFormContainer = styled.div`
|
||||
display: flex;
|
||||
@@ -34,20 +34,20 @@ const StyledErrorMessage = styled.div`
|
||||
margin-top: ${themeCssVariables.spacing[1]};
|
||||
`;
|
||||
|
||||
type SettingsAIAgentFormProps = {
|
||||
formValues: SettingsAIAgentFormValues;
|
||||
type SettingsAiAgentFormProps = {
|
||||
formValues: SettingsAiAgentFormValues;
|
||||
onFieldChange: (
|
||||
field: keyof SettingsAIAgentFormValues,
|
||||
value: SettingsAIAgentFormValues[keyof SettingsAIAgentFormValues],
|
||||
field: keyof SettingsAiAgentFormValues,
|
||||
value: SettingsAiAgentFormValues[keyof SettingsAiAgentFormValues],
|
||||
) => void;
|
||||
disabled: boolean;
|
||||
};
|
||||
|
||||
export const SettingsAIAgentForm = ({
|
||||
export const SettingsAiAgentForm = ({
|
||||
formValues,
|
||||
onFieldChange,
|
||||
disabled,
|
||||
}: SettingsAIAgentFormProps) => {
|
||||
}: SettingsAiAgentFormProps) => {
|
||||
const { t } = useLingui();
|
||||
|
||||
const { options: modelOptions } = useAiModelOptions();
|
||||
@@ -1,14 +1,14 @@
|
||||
import { useState } from 'react';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
import { type z } from 'zod';
|
||||
import { settingsAIAgentFormSchema } from '~/pages/settings/ai/validation-schemas/settingsAIAgentFormSchema';
|
||||
import { settingsAiAgentFormSchema } from '~/pages/settings/ai/validation-schemas/settingsAiAgentFormSchema';
|
||||
|
||||
export type SettingsAIAgentFormValues = z.infer<
|
||||
typeof settingsAIAgentFormSchema
|
||||
export type SettingsAiAgentFormValues = z.infer<
|
||||
typeof settingsAiAgentFormSchema
|
||||
>;
|
||||
|
||||
export const useSettingsAgentFormState = (mode: 'create' | 'edit') => {
|
||||
const [formValues, setFormValues] = useState<SettingsAIAgentFormValues>({
|
||||
const [formValues, setFormValues] = useState<SettingsAiAgentFormValues>({
|
||||
name: '',
|
||||
label: '',
|
||||
description: '',
|
||||
@@ -29,7 +29,7 @@ export const useSettingsAgentFormState = (mode: 'create' | 'edit') => {
|
||||
|
||||
const validateForm = (): boolean => {
|
||||
try {
|
||||
settingsAIAgentFormSchema.parse(formValues);
|
||||
settingsAiAgentFormSchema.parse(formValues);
|
||||
return true;
|
||||
} catch {
|
||||
return false;
|
||||
@@ -37,13 +37,13 @@ export const useSettingsAgentFormState = (mode: 'create' | 'edit') => {
|
||||
};
|
||||
|
||||
const handleFieldChange = (
|
||||
field: keyof SettingsAIAgentFormValues,
|
||||
value: SettingsAIAgentFormValues[keyof SettingsAIAgentFormValues],
|
||||
field: keyof SettingsAiAgentFormValues,
|
||||
value: SettingsAiAgentFormValues[keyof SettingsAiAgentFormValues],
|
||||
) => {
|
||||
setFormValues((prev) => ({ ...prev, [field]: value }));
|
||||
};
|
||||
|
||||
const resetForm = (values?: Partial<SettingsAIAgentFormValues>) => {
|
||||
const resetForm = (values?: Partial<SettingsAiAgentFormValues>) => {
|
||||
if (isDefined(values)) {
|
||||
setFormValues((prev) => ({ ...prev, ...values }));
|
||||
} else {
|
||||
|
||||
+3
-3
@@ -2,7 +2,7 @@ import { type AgentResponseSchema } from 'twenty-shared/ai';
|
||||
import { z } from 'zod';
|
||||
import { zodNonEmptyString } from '~/types/ZodNonEmptyString';
|
||||
|
||||
export const settingsAIAgentFormSchema = z.object({
|
||||
export const settingsAiAgentFormSchema = z.object({
|
||||
name: z.string().optional(),
|
||||
label: zodNonEmptyString,
|
||||
description: z.string().nullish(),
|
||||
@@ -36,6 +36,6 @@ export const settingsAIAgentFormSchema = z.object({
|
||||
evaluationInputs: z.array(z.string()).default([]),
|
||||
});
|
||||
|
||||
export type SettingsAIAgentFormValues = z.infer<
|
||||
typeof settingsAIAgentFormSchema
|
||||
export type SettingsAiAgentFormValues = z.infer<
|
||||
typeof settingsAiAgentFormSchema
|
||||
>;
|
||||
+2
-2
@@ -9,7 +9,7 @@ import { getSettingsPath, isDefined } from 'twenty-shared/utils';
|
||||
import { H2Title } from 'twenty-ui/display';
|
||||
import { Section } from 'twenty-ui/layout';
|
||||
import { type Application } from '~/generated-metadata/graphql';
|
||||
import { SettingsAIAgentsTable } from '~/pages/settings/ai/components/SettingsAIAgentsTable';
|
||||
import { SettingsAiAgentsTable } from '~/pages/settings/ai/components/SettingsAiAgentsTable';
|
||||
import {
|
||||
SettingsApplicationDataTable,
|
||||
type ApplicationDataTableRow,
|
||||
@@ -139,7 +139,7 @@ export const SettingsApplicationDetailContentTab = ({
|
||||
title={t`Agents`}
|
||||
description={t`Agents powering this app`}
|
||||
/>
|
||||
<SettingsAIAgentsTable />
|
||||
<SettingsAiAgentsTable />
|
||||
</Section>
|
||||
)}
|
||||
</>
|
||||
|
||||
@@ -45,7 +45,7 @@ export const SettingsRoleAddObjectLevel = () => {
|
||||
},
|
||||
{
|
||||
children: agent.label,
|
||||
href: getSettingsPath(SettingsPath.AIAgentDetail, {
|
||||
href: getSettingsPath(SettingsPath.AiAgentDetail, {
|
||||
agentId: agent.id,
|
||||
}),
|
||||
},
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user