diff --git a/.env.example b/.env.example
index cd20ca72a..fb9ee8398 100644
--- a/.env.example
+++ b/.env.example
@@ -216,6 +216,8 @@ ANDROID_SHA256_CERT_FINGERPRINT=AC:73:8E:DE:EB:56:EA:CC:10:87:02:A7:65:37:7B:38:
# ENABLE_RACK_ATTACK=true
# RACK_ATTACK_LIMIT=300
# ENABLE_RACK_ATTACK_WIDGET_API=true
+# Comma-separated list of trusted IPs that bypass Rack Attack throttling rules
+# RACK_ATTACK_ALLOWED_IPS=127.0.0.1,::1,192.168.0.10
## Running chatwoot as an API only server
## setting this value to true will disable the frontend dashboard endpoints
diff --git a/.gitignore b/.gitignore
index 53deb62a8..c64fb5c1b 100644
--- a/.gitignore
+++ b/.gitignore
@@ -71,9 +71,6 @@ test/cypress/videos/*
/config/master.key
/config/*.enc
-#ignore files under .vscode directory
-.vscode
-.cursor
# yalc for local testing
.yalc
@@ -92,5 +89,8 @@ yarn-debug.log*
# https://vitejs.dev/guide/env-and-mode.html#env-files
*.local
-# Claude.ai config file
-CLAUDE.md
+
+# TextEditors & AI Agents config files
+.vscode
+.claude/settings.local.json
+.cursor
diff --git a/.windsurf/rules/chatwoot.md b/.windsurf/rules/chatwoot.md
new file mode 120000
index 000000000..b7e6491d3
--- /dev/null
+++ b/.windsurf/rules/chatwoot.md
@@ -0,0 +1 @@
+../../AGENTS.md
\ No newline at end of file
diff --git a/AGENTS.md b/AGENTS.md
new file mode 100644
index 000000000..ad374799c
--- /dev/null
+++ b/AGENTS.md
@@ -0,0 +1,58 @@
+# Chatwoot Development Guidelines
+
+## Build / Test / Lint
+
+- **Setup**: `bundle install && pnpm install`
+- **Run Dev**: `pnpm dev` or `overmind start -f ./Procfile.dev`
+- **Lint JS/Vue**: `pnpm eslint` / `pnpm eslint:fix`
+- **Lint Ruby**: `bundle exec rubocop -a`
+- **Test JS**: `pnpm test` or `pnpm test:watch`
+- **Test Ruby**: `bundle exec rspec spec/path/to/file_spec.rb`
+- **Single Test**: `bundle exec rspec spec/path/to/file_spec.rb:LINE_NUMBER`
+- **Run Project**: `overmind start -f Procfile.dev`
+
+## Code Style
+
+- **Ruby**: Follow RuboCop rules (150 character max line length)
+- **Vue/JS**: Use ESLint (Airbnb base + Vue 3 recommended)
+- **Vue Components**: Use PascalCase
+- **Events**: Use camelCase
+- **I18n**: No bare strings in templates; use i18n
+- **Error Handling**: Use custom exceptions (`lib/custom_exceptions/`)
+- **Models**: Validate presence/uniqueness, add proper indexes
+- **Type Safety**: Use PropTypes in Vue, strong params in Rails
+- **Naming**: Use clear, descriptive names with consistent casing
+- **Vue API**: Always use Composition API with `
+
+
+
+
+
+
+
+
diff --git a/app/javascript/dashboard/components-next/captain/pageComponents/assistant/EditAssistantForm.vue b/app/javascript/dashboard/components-next/captain/pageComponents/assistant/EditAssistantForm.vue
index 249051878..362950802 100644
--- a/app/javascript/dashboard/components-next/captain/pageComponents/assistant/EditAssistantForm.vue
+++ b/app/javascript/dashboard/components-next/captain/pageComponents/assistant/EditAssistantForm.vue
@@ -100,7 +100,10 @@ const handleBasicInfoUpdate = async () => {
const payload = {
name: state.name,
description: state.description,
- product_name: state.productName,
+ config: {
+ ...props.assistant.config,
+ product_name: state.productName,
+ },
};
emit('submit', payload);
diff --git a/app/javascript/dashboard/components-next/dialog/Dialog.vue b/app/javascript/dashboard/components-next/dialog/Dialog.vue
index 6800b1254..78ca5206b 100644
--- a/app/javascript/dashboard/components-next/dialog/Dialog.vue
+++ b/app/javascript/dashboard/components-next/dialog/Dialog.vue
@@ -2,9 +2,9 @@
import { ref, computed } from 'vue';
import { OnClickOutside } from '@vueuse/components';
import { useI18n } from 'vue-i18n';
-import { useMapGetter } from 'dashboard/composables/store.js';
import Button from 'dashboard/components-next/button/Button.vue';
+import TeleportWithDirection from 'dashboard/components-next/TeleportWithDirection.vue';
const props = defineProps({
type: {
@@ -59,8 +59,6 @@ const emit = defineEmits(['confirm', 'close']);
const { t } = useI18n();
-const isRTL = useMapGetter('accounts/isRTL');
-
const dialogRef = ref(null);
const dialogContentRef = ref(null);
@@ -94,7 +92,7 @@ defineExpose({ open, close });
-
+
-
+