diff --git a/app/javascript/dashboard/api/captain/config.js b/app/javascript/dashboard/api/captain/config.js new file mode 100644 index 000000000..9a7d73c8f --- /dev/null +++ b/app/javascript/dashboard/api/captain/config.js @@ -0,0 +1,14 @@ +/* global axios */ +import ApiClient from '../ApiClient'; + +class CaptainConfig extends ApiClient { + constructor() { + super('captain/config', { accountScoped: true }); + } + + get() { + return axios.get(this.url); + } +} + +export default new CaptainConfig(); diff --git a/app/javascript/dashboard/components-next/sidebar/Sidebar.vue b/app/javascript/dashboard/components-next/sidebar/Sidebar.vue index cd4309e6e..6833dedec 100644 --- a/app/javascript/dashboard/components-next/sidebar/Sidebar.vue +++ b/app/javascript/dashboard/components-next/sidebar/Sidebar.vue @@ -577,6 +577,12 @@ const menuItems = computed(() => { icon: 'i-lucide-credit-card', to: accountScopedRoute('billing_settings_index'), }, + { + name: 'Settings Captain', + label: t('SIDEBAR.CAPTAIN_AI'), + icon: 'i-lucide-sparkles', + to: accountScopedRoute('captain_settings_index'), + }, ], }, ]; diff --git a/app/javascript/dashboard/i18n/locale/en/settings.json b/app/javascript/dashboard/i18n/locale/en/settings.json index 4e51ef37a..9ef8a5c4b 100644 --- a/app/javascript/dashboard/i18n/locale/en/settings.json +++ b/app/javascript/dashboard/i18n/locale/en/settings.json @@ -377,7 +377,52 @@ "INFO_SHORT": "Automatically mark offline when you aren't using the app." }, "DOCS": "Read docs", - "SECURITY": "Security" + "SECURITY": "Security", + "CAPTAIN_AI": "Captain" + }, + "CAPTAIN_SETTINGS": { + "TITLE": "Captain Settings", + "DESCRIPTION": "Configure your AI models and features for Captain in Chatwoot.", + "LOADING": "Loading Captain configuration...", + "NOT_ENABLED": "Captain is not enabled for your account. Please upgrade your plan to access Captain features.", + "MODEL_CONFIG": { + "TITLE": "Model Configuration", + "DESCRIPTION": "Select AI models for different features.", + "SELECT_MODEL": "Select model", + "CREDITS_PER_MESSAGE": "{credits} credit/message", + "EDITOR": { + "TITLE": "Editor Features", + "DESCRIPTION": "Powers smart compose, grammar corrections, tone adjustments, and content enhancement in your message editor." + }, + "ASSISTANT": { + "TITLE": "Assistant", + "DESCRIPTION": "Handles automated responses, conversation summaries, and intelligent reply suggestions for customer interactions." + }, + "COPILOT": { + "TITLE": "Co-pilot", + "DESCRIPTION": "Provides real-time contextual suggestions, knowledge base recommendations, and proactive insights during conversations." + } + }, + "FEATURES": { + "TITLE": "Features", + "DESCRIPTION": "Enable or disable AI-powered features.", + "AUDIO_TRANSCRIPTION": { + "TITLE": "Audio Transcription", + "DESCRIPTION": "Automatically convert voice messages and call recordings into searchable text transcripts." + }, + "HELP_CENTER_SEARCH": { + "TITLE": "Help Center Search Indexing", + "DESCRIPTION": "Enable AI to search and reference your help center articles for accurate, context-aware customer responses." + }, + "LABEL_SUGGESTION": { + "TITLE": "Label Suggestion", + "DESCRIPTION": "Automatically suggest relevant labels and tags for conversations based on content analysis and context." + } + }, + "API": { + "SUCCESS": "Captain settings updated successfully.", + "ERROR": "Failed to update Captain settings. Please try again." + } }, "BILLING_SETTINGS": { "TITLE": "Billing", diff --git a/app/javascript/dashboard/routes/dashboard/settings/captain/Index.vue b/app/javascript/dashboard/routes/dashboard/settings/captain/Index.vue new file mode 100644 index 000000000..f90ec233c --- /dev/null +++ b/app/javascript/dashboard/routes/dashboard/settings/captain/Index.vue @@ -0,0 +1,121 @@ + + + diff --git a/app/javascript/dashboard/routes/dashboard/settings/captain/captain.routes.js b/app/javascript/dashboard/routes/dashboard/settings/captain/captain.routes.js new file mode 100644 index 000000000..c84817872 --- /dev/null +++ b/app/javascript/dashboard/routes/dashboard/settings/captain/captain.routes.js @@ -0,0 +1,33 @@ +import { frontendURL } from '../../../../helper/URLHelper'; +import { FEATURE_FLAGS } from 'dashboard/featureFlags'; +import SettingsWrapper from '../SettingsWrapper.vue'; +import Index from './Index.vue'; + +export default { + routes: [ + { + path: frontendURL('accounts/:accountId/settings/captain'), + meta: { + permissions: ['administrator'], + featureFlag: FEATURE_FLAGS.CAPTAIN, + }, + component: SettingsWrapper, + props: { + headerTitle: 'CAPTAIN_SETTINGS.TITLE', + icon: 'i-lucide-bot', + showNewButton: false, + }, + children: [ + { + path: '', + name: 'captain_settings_index', + component: Index, + meta: { + permissions: ['administrator'], + featureFlag: FEATURE_FLAGS.CAPTAIN, + }, + }, + ], + }, + ], +}; diff --git a/app/javascript/dashboard/routes/dashboard/settings/captain/components/FeatureToggle.vue b/app/javascript/dashboard/routes/dashboard/settings/captain/components/FeatureToggle.vue new file mode 100644 index 000000000..3f84b8c69 --- /dev/null +++ b/app/javascript/dashboard/routes/dashboard/settings/captain/components/FeatureToggle.vue @@ -0,0 +1,56 @@ + + + diff --git a/app/javascript/dashboard/routes/dashboard/settings/captain/components/ModelSelector.vue b/app/javascript/dashboard/routes/dashboard/settings/captain/components/ModelSelector.vue new file mode 100644 index 000000000..f8d2cfbf0 --- /dev/null +++ b/app/javascript/dashboard/routes/dashboard/settings/captain/components/ModelSelector.vue @@ -0,0 +1,135 @@ + + + diff --git a/app/javascript/dashboard/routes/dashboard/settings/settings.routes.js b/app/javascript/dashboard/routes/dashboard/settings/settings.routes.js index 22173f66d..41c3498e1 100644 --- a/app/javascript/dashboard/routes/dashboard/settings/settings.routes.js +++ b/app/javascript/dashboard/routes/dashboard/settings/settings.routes.js @@ -24,6 +24,7 @@ import teams from './teams/teams.routes'; import customRoles from './customRoles/customRole.routes'; import profile from './profile/profile.routes'; import security from './security/security.routes'; +import captain from './captain/captain.routes'; export default { routes: [ @@ -63,5 +64,6 @@ export default { ...customRoles.routes, ...profile.routes, ...security.routes, + ...captain.routes, ], }; diff --git a/app/javascript/dashboard/store/captain/config.js b/app/javascript/dashboard/store/captain/config.js new file mode 100644 index 000000000..77e7c2400 --- /dev/null +++ b/app/javascript/dashboard/store/captain/config.js @@ -0,0 +1,62 @@ +import CaptainConfigAPI from 'dashboard/api/captain/config'; + +const state = { + providers: {}, + models: {}, + features: {}, + uiFlags: { + isFetching: false, + }, +}; + +const getters = { + getProviders: $state => $state.providers, + getModels: $state => $state.models, + getFeatures: $state => $state.features, + getUIFlags: $state => $state.uiFlags, + getModelsForFeature: $state => featureKey => { + const feature = $state.features[featureKey]; + if (!feature?.models) return []; + return feature.models.map(modelKey => ({ + key: modelKey, + ...$state.models[modelKey], + })); + }, + getDefaultModelForFeature: $state => featureKey => { + const feature = $state.features[featureKey]; + return feature?.default || null; + }, +}; + +const mutations = { + SET_UI_FLAG($state, data) { + $state.uiFlags = { ...$state.uiFlags, ...data }; + }, + SET_CONFIG($state, { providers, models, features }) { + $state.providers = providers || {}; + $state.models = models || {}; + $state.features = features || {}; + }, +}; + +const actions = { + async fetch({ commit }) { + commit('SET_UI_FLAG', { isFetching: true }); + try { + const response = await CaptainConfigAPI.get(); + commit('SET_CONFIG', response.data); + } catch (error) { + // Ignore error + } finally { + commit('SET_UI_FLAG', { isFetching: false }); + } + }, +}; + +export default { + namespaced: true, + state, + getters, + mutations, + actions, +}; diff --git a/app/javascript/dashboard/store/index.js b/app/javascript/dashboard/store/index.js index d56958eb5..d5bf224a0 100755 --- a/app/javascript/dashboard/store/index.js +++ b/app/javascript/dashboard/store/index.js @@ -58,6 +58,7 @@ import copilotMessages from './captain/copilotMessages'; import captainScenarios from './captain/scenarios'; import captainTools from './captain/tools'; import captainCustomTools from './captain/customTools'; +import captainConfig from './captain/config'; const plugins = []; @@ -121,6 +122,7 @@ export default createStore({ captainScenarios, captainTools, captainCustomTools, + captainConfig, }, plugins, });