From 54b949b392344ede2a42add56a842e1ebbb27f07 Mon Sep 17 00:00:00 2001 From: admin Date: Mon, 26 Oct 2026 00:50:43 +0800 Subject: [PATCH] chore(brand): rename the product to ReplyPier The upstream project name is gone from code, assets, docs and build output: brand strings, domains (replypier.site and its app/api/docs/help subdomains), env prefixes, image and network names, the widget's public JS API (window.ReplyPier, replypierId/BaseUrl/Config/Token), CSS tokens (--rp-*), file and directory names, and the WordPress plugin package. - widget loader is now webclient/replypier.min.js; both bundles rebuilt from source (backend/assets/widget.{js,css}, frontend/public/webclient) - NOTICE, llms.txt, CONTRIBUTING, HELP_CENTER_INFRA and config.dev.js rewritten rather than string-swapped; the demo config no longer ships the previous vendor's Firebase/Razorpay/Google keys - new migration replypier_ai_model_001 adds REPLYPIER to the managed AIModelType and rewrites pre-rename rows - local compose project, database, role and volume renamed; LOCAL_DEPLOY documents carrying the old local data over --- .claude/skills/write-e2e-test/SKILL.md | 4 +- .gitignore | 8 +- AGENT_HANDOFF.md | 2 +- CONTRIBUTING.md | 4 +- Dockerfile.frontend.prod | 4 +- Dockerfile.postgres | 2 +- HELP_CENTER_INFRA.md | 57 +- LOCAL_DEPLOY.md | 15 +- NOTICE | 13 +- backend/.env.example | 4 +- backend/__init__.py | 2 +- backend/alembic/env.py | 2 +- ...4e15242_add_priority_to_knowledge_queue.py | 2 +- ...ee_merge_guardrails_and_chat_initiation.py | 2 +- ...f5fa1db0cb_add_teamid_to_agent_sessions.py | 2 +- ...9e_removed_message_node_specific_fields.py | 2 +- .../1493b8279a2f_added_shopify_models.py | 2 +- .../186c65ae9406_added_rating_table.py | 2 +- .../2037204bbebf_add_guardrails_node_type.py | 2 +- .../2381319791e8_merge_multiple_heads.py | 2 +- ...fd826882d08_add_workflow_history_column.py | 2 +- .../versions/30caca239191_add_jira_config.py | 2 +- ... 520df92643e3_added_replypier_ai_model.py} | 6 +- ...a829bb8_make_user_org_and_role_nullable.py | 2 +- .../537f2b7d4a7c_added_end_chat_support.py | 2 +- ...6cd9e4_role_remove_name_alone_as_unique.py | 2 +- .../621095beb234_add_mcp_tools_tables.py | 2 +- ...widget_position_to_agent_customizations.py | 2 +- ...b4fc00d8_added_wlecome_header_and_title.py | 2 +- ...add_oauth_state_fields_to_shopify_shops.py | 2 +- .../7fd0447b3d45_workflow_tables_added.py | 2 +- .../versions/85364d188f15_merge_heads.py | 2 +- ...8aa4_change_datetime_to_timestamp_with_.py | 2 +- ...b_make_knowledge_queue_user_id_nullable.py | 2 +- ...726029_add_extra_data_to_agent_sessions.py | 2 +- ...3b2_add_agent_shopify_config_with_shop_.py | 2 +- ...ew_node_type_user_input.py 14-13-41-620.py | 2 +- ...b2c3d4e5f6_add_chat_initiation_messages.py | 2 +- ...a8_merge_crm_and_chat_session_idx_heads.py | 2 +- ...abc123456789_add_file_attachments_table.py | 2 +- .../add_agent_ai_replies_toggle_001.py | 2 +- .../add_agent_guardrail_prompt_001.py | 2 +- .../add_agent_ticketing_toggle_001.py | 2 +- .../versions/add_ai_disclaimer_toggle_001.py | 2 +- .../versions/add_allow_attachments_001.py | 2 +- .../versions/add_allow_new_chat_001.py | 2 +- .../add_allowed_attachment_types_001.py | 2 +- .../versions/add_channel_tables_001.py | 2 +- .../versions/add_chat_session_idx_001.py | 2 +- .../versions/add_crm_customer_syncs_001.py | 2 +- .../add_crm_tables_001_add_crm_tables.py | 2 +- ...d_customer_phone_001_add_customer_phone.py | 2 +- .../versions/add_guardrails_layer_001.py | 2 +- ...dd_hc_faq_feedback_001_add_faq_feedback.py | 2 +- .../add_hc_job_meter_001_add_job_metering.py | 2 +- .../add_invest_glassbox_001_add_glassbox.py | 2 +- .../add_investigation_runs_001_add_runs.py | 2 +- .../versions/add_mcp_usage_guidance_001.py | 2 +- ...if_prefs_001_user_notification_settings.py | 2 +- .../add_openai_compat_ai_model_001.py | 2 +- .../versions/add_require_token_auth_001.py | 2 +- .../versions/add_run_connector_status_001.py | 2 +- .../versions/add_sentiment_analysis_001.py | 2 +- .../versions/add_slack_integration_001.py | 2 +- ...ticketing_core_001_add_native_ticketing.py | 2 +- .../versions/add_tkt_db_ssh_001_add_ssh.py | 2 +- .../versions/add_tkt_phase4_001_add_phase4.py | 2 +- .../alembic/versions/add_widget_apps_001.py | 2 +- .../b2c3d4e5f6a7_add_customer_meta_data.py | 2 +- .../versions/b365b8447598_initial_version.py | 2 +- ..._add_agent_queue_and_people_permissions.py | 2 +- ...aa7a5d6109_removed_node_specific_fields.py | 2 +- ..._premium_chat_styles_and_show_citations.py | 2 +- .../versions/c3d4e5f6a7b8_add_lead_capture.py | 2 +- ...crm_sync_varchar_001_crm_target_varchar.py | 2 +- ...f4a5b6c7_add_contact_collection_columns.py | 2 +- .../d9a4b9902f80_add_attempts_to_otp_table.py | 2 +- ...dd_progress_tracking_to_knowledge_queue.py | 2 +- .../dd0e5ceefe4b_added_new_node_type.py | 2 +- .../alembic/versions/drop_slack_tables_001.py | 2 +- .../e252efacd083_agent_createddate_added.py | 2 +- .../e3f4a5b6c7d8_add_aurora_chat_style.py | 2 +- .../e65e1b8e7e3c_add_jira_agent_config.py | 2 +- ...add_rate_limiting_fields_to_agent_model.py | 2 +- ...8e9_add_sunrise_style_and_quick_actions.py | 2 +- .../f7a1c2d3e4b5_add_faq_help_center.py | 4 +- ...4f644fc0c_added_user_id_in_rating_table.py | 2 +- .../versions/fcm_tokens_per_device_001.py | 2 +- ...48f854bcbf_add_ticket_fields_to_session.py | 2 +- .../alembic/versions/merge_hc_url_path_001.py | 2 +- .../alembic/versions/merge_tkt_csat_001.py | 2 +- .../alembic/versions/merge_tkt_phone_001.py | 2 +- .../versions/normalise_upload_prefix_001.py | 2 +- .../versions/purge_mangled_crawl_pages_001.py | 2 +- .../versions/repair_agent_role_seed_001.py | 2 +- ..._ai_model_001_carry_managed_model_label.py | 67 + backend/app/__init__.py | 2 +- backend/app/agents/chat_agent.py | 2 +- backend/app/agents/choice_prompt.py | 2 +- backend/app/agents/encrypted_storage.py | 2 +- backend/app/agents/faq_generator.py | 2 +- backend/app/agents/guardrail_policy.py | 2 +- backend/app/agents/history_memory.py | 2 +- backend/app/agents/structured_output.py | 2 +- backend/app/agents/ticket_investigator.py | 2 +- backend/app/agents/transfer_agent.py | 2 +- backend/app/api/__init__.py | 2 +- backend/app/api/agent.py | 14 +- backend/app/api/ai_setup.py | 46 +- backend/app/api/analytics.py | 2 +- backend/app/api/channels/__init__.py | 2 +- backend/app/api/channels/accounts.py | 2 +- backend/app/api/channels/agent_config.py | 2 +- backend/app/api/channels/email.py | 2 +- backend/app/api/channels/line.py | 2 +- backend/app/api/channels/meta.py | 6 +- backend/app/api/channels/slack.py | 2 +- backend/app/api/channels/sms.py | 2 +- backend/app/api/channels/telegram.py | 2 +- .../app/api/channels/whatsapp_messaging.py | 2 +- backend/app/api/chat.py | 2 +- backend/app/api/crm.py | 2 +- backend/app/api/file_upload.py | 2 +- backend/app/api/help_center/__init__.py | 2 +- backend/app/api/help_center/branding.py | 8 +- backend/app/api/help_center/domain.py | 2 +- backend/app/api/help_center/faqs.py | 2 +- backend/app/api/help_center/generation.py | 2 +- backend/app/api/help_center_images.py | 2 +- backend/app/api/help_center_public.py | 10 +- backend/app/api/jira.py | 2 +- backend/app/api/knowledge.py | 2 +- backend/app/api/lead_capture.py | 2 +- backend/app/api/mcp_tool.py | 2 +- backend/app/api/notification.py | 4 +- backend/app/api/organizations.py | 2 +- backend/app/api/people.py | 2 +- backend/app/api/roles.py | 2 +- backend/app/api/session_to_agent.py | 2 +- backend/app/api/shopify.py | 2 +- backend/app/api/ticket_db_connectors.py | 2 +- backend/app/api/ticket_webhooks.py | 2 +- backend/app/api/tickets.py | 4 +- backend/app/api/token.py | 2 +- backend/app/api/user_groups.py | 2 +- backend/app/api/users.py | 2 +- backend/app/api/webhooks/__init__.py | 2 +- backend/app/api/webhooks/common.py | 2 +- backend/app/api/webhooks/email.py | 2 +- backend/app/api/webhooks/line.py | 2 +- backend/app/api/webhooks/meta.py | 2 +- backend/app/api/webhooks/slack.py | 2 +- backend/app/api/webhooks/sms.py | 2 +- backend/app/api/webhooks/telegram.py | 2 +- backend/app/api/widget.py | 4 +- backend/app/api/widget_apps.py | 2 +- backend/app/api/widget_chat.py | 4 +- backend/app/api/workflow.py | 2 +- backend/app/api/workflow_node.py | 2 +- backend/app/channels/__init__.py | 2 +- backend/app/channels/app_hooks.py | 2 +- backend/app/channels/base.py | 2 +- backend/app/channels/constants.py | 2 +- backend/app/channels/email.py | 2 +- backend/app/channels/instagram.py | 2 +- backend/app/channels/interactive.py | 2 +- backend/app/channels/interactive_limits.py | 2 +- backend/app/channels/line.py | 2 +- backend/app/channels/messenger.py | 2 +- backend/app/channels/meta_base.py | 2 +- backend/app/channels/registry.py | 2 +- backend/app/channels/sent_choices.py | 2 +- backend/app/channels/slack.py | 14 +- backend/app/channels/sms/__init__.py | 2 +- backend/app/channels/sms/adapter.py | 2 +- backend/app/channels/sms/base.py | 2 +- backend/app/channels/sms/brevo.py | 2 +- backend/app/channels/sms/messagebird.py | 2 +- backend/app/channels/sms/plivo.py | 2 +- backend/app/channels/sms/sns.py | 2 +- backend/app/channels/sms/twilio.py | 2 +- backend/app/channels/sms/vonage.py | 2 +- backend/app/channels/telegram.py | 2 +- backend/app/channels/whatsapp.py | 2 +- backend/app/core/agno_telemetry.py | 4 +- backend/app/core/application.py | 4 +- backend/app/core/auth.py | 2 +- backend/app/core/auth_utils.py | 2 +- backend/app/core/config.py | 20 +- backend/app/core/cors.py | 2 +- backend/app/core/crawler_policy.py | 2 +- backend/app/core/default_templates.py | 2 +- backend/app/core/edition.py | 2 +- backend/app/core/encryption.py | 2 +- backend/app/core/error_handlers.py | 2 +- backend/app/core/exceptions.py | 2 +- backend/app/core/external_urls.py | 2 +- backend/app/core/file_validation.py | 2 +- backend/app/core/help_center_host.py | 2 +- backend/app/core/local_file_urls.py | 4 +- backend/app/core/logger.py | 2 +- backend/app/core/model_catalog.py | 4 +- backend/app/core/oauth_state.py | 2 +- backend/app/core/outbound_http.py | 2 +- backend/app/core/outbound_policy.py | 2 +- backend/app/core/params.py | 2 +- backend/app/core/processor/__init__.py | 2 +- backend/app/core/processor/status.py | 2 +- backend/app/core/redis.py | 2 +- backend/app/core/s3.py | 2 +- backend/app/core/security.py | 2 +- backend/app/core/socketio.py | 4 +- backend/app/crm/__init__.py | 2 +- backend/app/crm/base.py | 2 +- backend/app/crm/hubspot.py | 2 +- backend/app/crm/mapping.py | 4 +- backend/app/crm/pipedrive.py | 4 +- backend/app/crm/registry.py | 2 +- backend/app/database.py | 2 +- backend/app/knowledge/README.md | 2 +- backend/app/knowledge/chunking.py | 2 +- backend/app/knowledge/content_summarizer.py | 2 +- backend/app/knowledge/crawl4ai_fallback.py | 2 +- backend/app/knowledge/crawl_scope.py | 2 +- backend/app/knowledge/crawler_identity.py | 4 +- backend/app/knowledge/deadline.py | 2 +- backend/app/knowledge/domains.py | 2 +- backend/app/knowledge/embedder.py | 2 +- backend/app/knowledge/enhanced_pdf_kb.py | 2 +- backend/app/knowledge/enhanced_website_kb.py | 2 +- .../app/knowledge/enhanced_website_reader.py | 2 +- backend/app/knowledge/failure_advice.py | 2 +- backend/app/knowledge/knowledge_base.py | 2 +- backend/app/knowledge/main_content.py | 2 +- backend/app/knowledge/optimized_pgvector.py | 2 +- backend/app/knowledge/page_editor.py | 2 +- backend/app/knowledge/page_fetch.py | 2 +- backend/app/knowledge/pdf_download.py | 2 +- backend/app/knowledge/pdf_limits.py | 2 +- backend/app/knowledge/sitemap_parser.py | 2 +- backend/app/knowledge/sitemap_reader.py | 2 +- backend/app/knowledge/url_safety.py | 2 +- backend/app/main.py | 6 +- backend/app/models/__init__.py | 2 +- backend/app/models/agent.py | 2 +- backend/app/models/ai_config.py | 4 +- backend/app/models/auth_session.py | 2 +- backend/app/models/channels/__init__.py | 2 +- .../models/channels/agent_channel_config.py | 2 +- .../app/models/channels/channel_account.py | 2 +- .../models/channels/channel_conversation.py | 4 +- backend/app/models/chat_history.py | 2 +- backend/app/models/crm.py | 2 +- backend/app/models/customer.py | 2 +- backend/app/models/faq.py | 2 +- backend/app/models/faq_generation_job.py | 2 +- backend/app/models/fcm_token.py | 2 +- backend/app/models/file_attachment.py | 2 +- backend/app/models/guardrail_event.py | 2 +- backend/app/models/help_center.py | 2 +- backend/app/models/investigation.py | 4 +- backend/app/models/jira.py | 2 +- backend/app/models/knowledge.py | 2 +- backend/app/models/knowledge_queue.py | 2 +- backend/app/models/knowledge_to_agent.py | 2 +- backend/app/models/lead_capture.py | 2 +- backend/app/models/mcp_tool.py | 2 +- backend/app/models/notification.py | 2 +- backend/app/models/notification_settings.py | 2 +- backend/app/models/organization.py | 2 +- backend/app/models/permission.py | 2 +- backend/app/models/rating.py | 2 +- backend/app/models/role.py | 2 +- backend/app/models/schemas/__init__.py | 2 +- backend/app/models/schemas/agent.py | 2 +- .../app/models/schemas/agent_customization.py | 4 +- backend/app/models/schemas/ai_config.py | 2 +- backend/app/models/schemas/channel.py | 2 +- backend/app/models/schemas/chat.py | 2 +- backend/app/models/schemas/crm.py | 2 +- backend/app/models/schemas/faq.py | 2 +- backend/app/models/schemas/help_center.py | 2 +- backend/app/models/schemas/investigation.py | 2 +- backend/app/models/schemas/jira.py | 2 +- backend/app/models/schemas/lead_capture.py | 2 +- backend/app/models/schemas/mcp_tool.py | 2 +- backend/app/models/schemas/notification.py | 2 +- backend/app/models/schemas/organization.py | 2 +- backend/app/models/schemas/pagination.py | 2 +- backend/app/models/schemas/people.py | 2 +- backend/app/models/schemas/role.py | 2 +- .../app/models/schemas/shopify/__init__.py | 2 +- .../schemas/shopify/agent_shopify_config.py | 2 +- .../models/schemas/shopify/shopify_shop.py | 2 +- backend/app/models/schemas/ticket.py | 2 +- .../app/models/schemas/ticket_db_connector.py | 2 +- backend/app/models/schemas/user.py | 2 +- backend/app/models/schemas/user_group.py | 2 +- backend/app/models/schemas/widget.py | 2 +- backend/app/models/schemas/widget_app.py | 2 +- backend/app/models/schemas/workflow.py | 2 +- backend/app/models/session_to_agent.py | 2 +- backend/app/models/shopify/__init__.py | 2 +- .../models/shopify/agent_shopify_config.py | 2 +- backend/app/models/shopify/shopify_shop.py | 2 +- backend/app/models/ticket.py | 2 +- backend/app/models/ticket_activity.py | 2 +- backend/app/models/ticket_db_connector.py | 4 +- backend/app/models/ticket_settings.py | 2 +- backend/app/models/user.py | 2 +- backend/app/models/widget.py | 2 +- backend/app/models/widget_app.py | 2 +- backend/app/models/workflow.py | 2 +- backend/app/models/workflow_connection.py | 2 +- backend/app/models/workflow_node.py | 2 +- backend/app/repositories/__init__.py | 2 +- backend/app/repositories/agent.py | 2 +- .../agent_shopify_config_repository.py | 2 +- backend/app/repositories/ai_config.py | 2 +- backend/app/repositories/channels/__init__.py | 2 +- backend/app/repositories/channels/accounts.py | 2 +- .../app/repositories/channels/agent_config.py | 2 +- .../repositories/channels/conversations.py | 2 +- backend/app/repositories/chat.py | 2 +- backend/app/repositories/crm.py | 2 +- backend/app/repositories/customer.py | 2 +- backend/app/repositories/faq.py | 2 +- .../app/repositories/faq_generation_job.py | 2 +- backend/app/repositories/fcm_token.py | 2 +- backend/app/repositories/file_attachment.py | 2 +- backend/app/repositories/group.py | 2 +- backend/app/repositories/guardrail_event.py | 2 +- backend/app/repositories/help_center.py | 2 +- backend/app/repositories/jira.py | 2 +- backend/app/repositories/knowledge.py | 2 +- backend/app/repositories/knowledge_queue.py | 2 +- .../app/repositories/knowledge_to_agent.py | 2 +- backend/app/repositories/lead_capture.py | 2 +- backend/app/repositories/mcp_tool.py | 2 +- .../app/repositories/notification_settings.py | 2 +- backend/app/repositories/organization.py | 2 +- backend/app/repositories/people.py | 2 +- backend/app/repositories/rating.py | 2 +- backend/app/repositories/role.py | 2 +- backend/app/repositories/session_to_agent.py | 2 +- .../repositories/shopify_shop_repository.py | 2 +- backend/app/repositories/ticket.py | 2 +- backend/app/repositories/user.py | 2 +- backend/app/repositories/user_group.py | 2 +- backend/app/repositories/widget.py | 2 +- backend/app/repositories/widget_app.py | 2 +- backend/app/repositories/workflow.py | 2 +- backend/app/repositories/workflow_node.py | 2 +- backend/app/services/agent_rooms.py | 2 +- backend/app/services/app_first_routing.py | 2 +- backend/app/services/auth_sessions.py | 2 +- backend/app/services/business_message.py | 2 +- backend/app/services/channel_chat.py | 4 +- backend/app/services/channel_replies.py | 2 +- backend/app/services/channel_status.py | 4 +- backend/app/services/chat_notifications.py | 2 +- backend/app/services/chat_scope_roles.py | 2 +- backend/app/services/contact_capture.py | 2 +- backend/app/services/conversation_token.py | 2 +- backend/app/services/crm_sync.py | 2 +- backend/app/services/crm_tokens.py | 2 +- backend/app/services/db_connector_service.py | 2 +- backend/app/services/domain_verification.py | 8 +- backend/app/services/faq_article_import.py | 4 +- backend/app/services/faq_generation.py | 2 +- backend/app/services/faq_import.py | 4 +- backend/app/services/faq_usage.py | 2 +- backend/app/services/feature_gate.py | 2 +- backend/app/services/file_storage.py | 2 +- backend/app/services/file_upload_service.py | 2 +- backend/app/services/firebase.py | 2 +- backend/app/services/help_center_access.py | 2 +- backend/app/services/help_center_content.py | 2 +- backend/app/services/help_center_images.py | 2 +- backend/app/services/help_center_public.py | 2 +- backend/app/services/help_center_seo.py | 2 +- backend/app/services/help_center_settings.py | 2 +- backend/app/services/human_routing.py | 2 +- backend/app/services/image_security.py | 2 +- backend/app/services/jira.py | 2 +- .../app/services/knowledge_vector_links.py | 2 +- backend/app/services/lead_capture.py | 2 +- backend/app/services/message_delivery.py | 2 +- backend/app/services/meta_own_app.py | 6 +- backend/app/services/notifications.py | 2 +- backend/app/services/public_rate_limit.py | 2 +- backend/app/services/sentiment.py | 2 +- backend/app/services/shopify.py | 16 +- backend/app/services/shopify_auth_service.py | 2 +- .../app/services/shopify_helper_service.py | 2 +- backend/app/services/shopify_session.py | 2 +- backend/app/services/shopify_urls.py | 2 +- backend/app/services/slack_events.py | 4 +- backend/app/services/socket_rate_limit.py | 2 +- backend/app/services/sql_guardrails.py | 2 +- backend/app/services/telegram_webhooks.py | 4 +- backend/app/services/ticket.py | 2 +- backend/app/services/ticket_access.py | 2 +- backend/app/services/ticket_csat.py | 2 +- backend/app/services/ticket_email.py | 4 +- backend/app/services/ticket_email_reply.py | 2 +- backend/app/services/ticket_events.py | 2 +- backend/app/services/ticket_investigation.py | 2 +- backend/app/services/ticket_jira.py | 6 +- backend/app/services/ticket_privacy.py | 2 +- backend/app/services/usage_metering.py | 4 +- backend/app/services/user.py | 2 +- backend/app/services/whatsapp_outbound.py | 2 +- backend/app/services/widget_identity.py | 2 +- backend/app/services/workflow.py | 2 +- backend/app/services/workflow_chat.py | 2 +- backend/app/services/workflow_conditions.py | 2 +- backend/app/services/workflow_execution.py | 2 +- backend/app/services/workflow_node.py | 2 +- .../app/templates/help_center/article.html | 2 +- backend/app/templates/help_center/base.html | 22 +- backend/app/templates/help_center/index.html | 2 +- backend/app/tools/faq_search.py | 2 +- backend/app/tools/guardrailed_db_toolkit.py | 2 +- backend/app/tools/jira_toolkit.py | 2 +- backend/app/tools/knowledge_search_byagent.py | 2 +- backend/app/tools/mcp_connection.py | 2 +- backend/app/tools/mcp_manager.py | 2 +- backend/app/tools/mcp_outbound.py | 2 +- backend/app/tools/shopify_order_access.py | 2 +- backend/app/tools/shopify_toolkit.py | 2 +- backend/app/tools/ticket_toolkit.py | 2 +- backend/app/utils/agno_eval_guard.py | 2 +- backend/app/utils/agno_patches.py | 6 +- backend/app/utils/agno_utils.py | 4 +- backend/app/utils/backoff.py | 2 +- backend/app/utils/business_hours.py | 2 +- backend/app/utils/client_ip.py | 2 +- backend/app/utils/domain_check.py | 2 +- backend/app/utils/guardrail_runtime.py | 2 +- backend/app/utils/guardrails.py | 2 +- backend/app/utils/model_context.py | 4 +- backend/app/utils/phone.py | 2 +- backend/app/utils/rate_limit.py | 2 +- backend/app/utils/response_parser.py | 2 +- backend/app/utils/sanitize.py | 2 +- backend/app/utils/urls.py | 2 +- backend/app/utils/uuids.py | 2 +- backend/app/workers/chat_auto_closer.py | 2 +- backend/app/workers/crm_sync.py | 2 +- backend/app/workers/faq_processor.py | 2 +- backend/app/workers/knowledge_processor.py | 2 +- .../app/workers/run_knowledge_processor.py | 2 +- backend/app/workers/ticket_investigator.py | 2 +- backend/assets/widget.css | 2 +- backend/assets/widget.js | 7663 +++++++++-------- backend/scripts/encrypt_chat_at_rest.py | 2 +- backend/scripts/preload_models.py | 2 +- backend/scripts/prune_offsite_pages.py | 2 +- backend/scripts/rechunk_knowledge.py | 2 +- backend/scripts/test_lead_capture_prompt.py | 2 +- backend/tests/__init__.py | 2 +- backend/tests/agent/test_chat_agent.py | 2 +- .../tests/agent/test_chat_agent_guardrails.py | 2 +- backend/tests/agent/test_transfer_agent.py | 2 +- .../tests/agents/test_chat_agent_end_chat.py | 2 +- .../test_chat_agent_lead_capture_prompt.py | 2 +- .../agents/test_chat_agent_overflow_retry.py | 2 +- .../agents/test_chat_agent_transfer_prompt.py | 2 +- .../tests/agents/test_encrypted_storage.py | 2 +- backend/tests/agents/test_faq_generator.py | 2 +- backend/tests/agents/test_guardrail_policy.py | 4 +- backend/tests/agents/test_history_memory.py | 2 +- backend/tests/agents/test_quick_replies.py | 2 +- .../agents/test_ticket_investigator_agent.py | 4 +- backend/tests/api/conftest.py | 2 +- backend/tests/api/test_agent.py | 2 +- backend/tests/api/test_agent_photo_upload.py | 2 +- backend/tests/api/test_agent_workflow.py | 2 +- backend/tests/api/test_ai_setup.py | 74 +- backend/tests/api/test_analytics.py | 2 +- backend/tests/api/test_auth_sessions_api.py | 2 +- backend/tests/api/test_channels_api.py | 2 +- backend/tests/api/test_chat.py | 2 +- backend/tests/api/test_chat_scope_roles.py | 2 +- backend/tests/api/test_crm_api.py | 2 +- backend/tests/api/test_file_upload.py | 2 +- backend/tests/api/test_help_center_api.py | 6 +- backend/tests/api/test_help_center_images.py | 2 +- backend/tests/api/test_help_center_public.py | 30 +- backend/tests/api/test_help_center_tls_ask.py | 6 +- backend/tests/api/test_jira.py | 2 +- backend/tests/api/test_knowledge.py | 2 +- backend/tests/api/test_lead_capture_api.py | 2 +- backend/tests/api/test_mcp_tool.py | 4 +- backend/tests/api/test_meta_channels_api.py | 4 +- backend/tests/api/test_meta_own_app.py | 16 +- backend/tests/api/test_notification.py | 2 +- backend/tests/api/test_org_scoping_guards.py | 2 +- backend/tests/api/test_organizations.py | 2 +- backend/tests/api/test_people_crm_api.py | 2 +- backend/tests/api/test_people_permissions.py | 2 +- backend/tests/api/test_roles.py | 2 +- backend/tests/api/test_session_to_agent.py | 2 +- .../tests/api/test_shopify_agent_config.py | 2 +- backend/tests/api/test_shopify_api.py | 2 +- .../tests/api/test_shopify_gdpr_webhooks.py | 2 +- backend/tests/api/test_signed_local_files.py | 2 +- backend/tests/api/test_static_mounts.py | 2 +- .../tests/api/test_ticket_db_connectors.py | 2 +- .../tests/api/test_ticket_email_webhook.py | 2 +- backend/tests/api/test_token.py | 2 +- backend/tests/api/test_user_groups.py | 2 +- backend/tests/api/test_users.py | 2 +- backend/tests/api/test_webhook_form_limits.py | 2 +- backend/tests/api/test_widget.py | 2 +- backend/tests/api/test_widget_chat.py | 2 +- .../tests/api/test_widget_chat_enhanced.py | 2 +- .../tests/api/test_widget_chat_identity.py | 2 +- .../tests/api/test_widget_chat_workflow.py | 2 +- .../tests/api/test_widget_display_schema.py | 2 +- backend/tests/api/test_widget_end_chat.py | 2 +- backend/tests/api/test_widget_identity.py | 2 +- backend/tests/api/test_widget_takeover.py | 2 +- backend/tests/api/test_widget_workflow.py | 2 +- backend/tests/api/test_workflow.py | 2 +- .../tests/api/test_workflow_node_single.py | 2 +- backend/tests/channels/test_app_hooks.py | 2 +- .../channels/test_channel_quick_replies.py | 2 +- .../channels/test_email_sms_line_adapters.py | 2 +- backend/tests/channels/test_interactive.py | 2 +- backend/tests/channels/test_meta_adapters.py | 2 +- backend/tests/channels/test_slack_adapter.py | 4 +- backend/tests/channels/test_sms_providers.py | 2 +- backend/tests/channels/test_smtp_config.py | 2 +- .../tests/channels/test_telegram_adapter.py | 2 +- backend/tests/conftest.py | 2 +- backend/tests/core/__init__.py | 2 +- backend/tests/core/test_agno_telemetry.py | 2 +- backend/tests/core/test_auth.py | 2 +- backend/tests/core/test_auth_utils.py | 2 +- backend/tests/core/test_config.py | 2 +- backend/tests/core/test_cors_credentials.py | 2 +- .../tests/core/test_cors_middleware_update.py | 2 +- backend/tests/core/test_cors_org_origins.py | 2 +- backend/tests/core/test_crawler_policy.py | 2 +- backend/tests/core/test_database_fork.py | 2 +- backend/tests/core/test_edition.py | 2 +- backend/tests/core/test_encryption.py | 2 +- backend/tests/core/test_error_handlers.py | 2 +- backend/tests/core/test_external_urls.py | 2 +- backend/tests/core/test_file_validation.py | 2 +- backend/tests/core/test_knowledge_base.py | 2 +- backend/tests/core/test_oauth_state.py | 2 +- backend/tests/core/test_outbound_http.py | 2 +- backend/tests/core/test_outbound_policy.py | 2 +- backend/tests/core/test_params.py | 2 +- backend/tests/core/test_redis.py | 2 +- backend/tests/core/test_s3.py | 2 +- backend/tests/core/test_socketio.py | 6 +- backend/tests/core/test_socketio_redis_tls.py | 2 +- backend/tests/core/test_sql_bind_params.py | 2 +- backend/tests/core/test_widget_channels.py | 2 +- backend/tests/crm/test_crm_hubspot.py | 2 +- backend/tests/crm/test_crm_mapping.py | 4 +- backend/tests/crm/test_crm_pipedrive.py | 2 +- backend/tests/knowledge/test_chunking.py | 2 +- .../knowledge/test_content_summarizer.py | 2 +- .../tests/knowledge/test_crawl4ai_fallback.py | 2 +- backend/tests/knowledge/test_crawl_scope.py | 2 +- .../tests/knowledge/test_crawler_identity.py | 6 +- backend/tests/knowledge/test_domains.py | 2 +- .../tests/knowledge/test_enhanced_pdf_kb.py | 2 +- .../knowledge/test_enhanced_website_kb.py | 2 +- .../knowledge/test_enhanced_website_reader.py | 4 +- .../tests/knowledge/test_failure_advice.py | 2 +- backend/tests/knowledge/test_main_content.py | 2 +- .../knowledge/test_optimized_pgvector.py | 2 +- backend/tests/knowledge/test_page_fetch.py | 2 +- backend/tests/knowledge/test_pdf_download.py | 2 +- backend/tests/knowledge/test_pdf_limits.py | 2 +- .../tests/knowledge/test_rechunk_knowledge.py | 2 +- .../test_rechunk_knowledge_transaction.py | 2 +- .../tests/knowledge/test_sitemap_parser.py | 2 +- .../tests/knowledge/test_sitemap_reader.py | 2 +- backend/tests/knowledge/test_url_safety.py | 2 +- backend/tests/repo/test_agentrepo.py | 2 +- backend/tests/repo/test_ai_configrepo.py | 2 +- backend/tests/repo/test_chat_repo.py | 2 +- backend/tests/repo/test_crm_repo.py | 2 +- backend/tests/repo/test_customer_repo.py | 2 +- .../tests/repo/test_file_attachment_repo.py | 2 +- backend/tests/repo/test_group_repo.py | 2 +- .../tests/repo/test_knowledge_queue_repo.py | 2 +- backend/tests/repo/test_knowledge_repo.py | 2 +- .../repo/test_knowledge_to_agent_repo.py | 2 +- backend/tests/repo/test_lead_capture_repo.py | 2 +- backend/tests/repo/test_organization_repo.py | 2 +- backend/tests/repo/test_people_repo.py | 2 +- backend/tests/repo/test_role_repo.py | 2 +- .../tests/repo/test_session_to_agent_repo.py | 2 +- backend/tests/repo/test_user_group_repo.py | 2 +- backend/tests/repo/test_user_repo.py | 2 +- backend/tests/repo/test_widget_repo.py | 2 +- .../test_agent_shopify_config_repository.py | 2 +- .../test_channel_account_auth_failure.py | 2 +- .../tests/repositories/test_chat_sentiment.py | 2 +- .../repositories/test_chat_visibility.py | 2 +- .../repositories/test_customer_identify.py | 2 +- backend/tests/repositories/test_fcm_token.py | 2 +- .../repositories/test_guardrail_event.py | 2 +- .../repositories/test_jira_repository.py | 2 +- .../test_knowledge_source_limit.py | 2 +- .../repositories/test_mcp_tool_repository.py | 2 +- .../test_session_to_agent_repository.py | 2 +- .../test_shopify_shop_repository.py | 2 +- .../test_widget_app_repository.py | 2 +- backend/tests/service/__init__.py | 2 +- backend/tests/service/test_crm_sync.py | 6 +- backend/tests/service/test_crm_tokens.py | 2 +- backend/tests/service/test_firebase.py | 2 +- backend/tests/service/test_jira.py | 2 +- .../service/test_lead_capture_service.py | 2 +- .../tests/service/test_socket_rate_limit.py | 2 +- backend/tests/service/test_widget_identity.py | 2 +- backend/tests/services/test_agent_rooms.py | 2 +- .../tests/services/test_app_first_routing.py | 2 +- backend/tests/services/test_auth_sessions.py | 2 +- .../tests/services/test_business_message.py | 2 +- backend/tests/services/test_channel_chat.py | 2 +- .../services/test_channel_interactions.py | 2 +- .../tests/services/test_channel_replies.py | 2 +- backend/tests/services/test_channel_status.py | 4 +- .../tests/services/test_chat_notifications.py | 2 +- .../tests/services/test_contact_capture.py | 2 +- .../tests/services/test_conversation_token.py | 2 +- .../services/test_db_connector_service.py | 2 +- .../services/test_domain_verification.py | 8 +- .../tests/services/test_faq_article_import.py | 4 +- backend/tests/services/test_faq_generation.py | 2 +- backend/tests/services/test_faq_import.py | 2 +- .../services/test_file_upload_service.py | 2 +- .../services/test_help_center_content.py | 2 +- .../tests/services/test_help_center_seo.py | 2 +- .../services/test_help_center_settings.py | 6 +- backend/tests/services/test_human_routing.py | 2 +- backend/tests/services/test_image_security.py | 2 +- .../services/test_knowledge_vector_links.py | 2 +- .../tests/services/test_message_delivery.py | 2 +- backend/tests/services/test_sentiment.py | 2 +- .../tests/services/test_shopify_service.py | 2 +- .../tests/services/test_shopify_session.py | 2 +- backend/tests/services/test_sql_guardrails.py | 10 +- .../tests/services/test_surface_guardrails.py | 2 +- .../tests/services/test_telegram_webhooks.py | 4 +- backend/tests/services/test_ticket_csat.py | 2 +- .../services/test_ticket_email_threading.py | 2 +- .../services/test_ticket_investigation.py | 2 +- .../tests/services/test_ticket_metering.py | 2 +- backend/tests/services/test_ticket_phase4.py | 2 +- backend/tests/services/test_ticket_privacy.py | 6 +- backend/tests/services/test_ticket_service.py | 2 +- backend/tests/services/test_upload_paths.py | 2 +- backend/tests/services/test_user.py | 2 +- backend/tests/services/test_workflow_chat.py | 2 +- .../services/test_workflow_chat_end_chat.py | 2 +- .../services/test_workflow_conditions.py | 2 +- .../tests/services/test_workflow_execution.py | 2 +- .../test_workflow_execution_end_chat.py | 2 +- backend/tests/services/test_workflow_node.py | 2 +- .../tests/services/test_workflow_service.py | 2 +- backend/tests/test_lifespan.py | 2 +- backend/tests/test_migrations.py | 2 +- backend/tests/test_personal_access_token.py | 2 +- backend/tests/tools/__init__.py | 2 +- .../tools/test_guardrailed_db_toolkit.py | 4 +- backend/tests/tools/test_jira_toolkit.py | 2 +- .../tools/test_knowledge_search_byagent.py | 2 +- .../tools/test_knowledge_search_chunks.py | 2 +- backend/tests/tools/test_mcp_manager.py | 4 +- .../tests/tools/test_shopify_order_access.py | 2 +- backend/tests/tools/test_shopify_toolkit.py | 2 +- backend/tests/tools/test_ticket_toolkit.py | 8 +- backend/tests/utils/test_agno_eval_guard.py | 2 +- .../utils/test_agno_eval_guard_integration.py | 4 +- backend/tests/utils/test_agno_patches.py | 2 +- backend/tests/utils/test_agno_utils.py | 12 +- backend/tests/utils/test_backoff.py | 2 +- backend/tests/utils/test_business_hours.py | 2 +- backend/tests/utils/test_domain_check.py | 2 +- backend/tests/utils/test_guardrail_runtime.py | 2 +- .../tests/utils/test_guardrails_jailbreak.py | 2 +- backend/tests/utils/test_model_context.py | 2 +- backend/tests/utils/test_offtopic_exercise.py | 8 +- backend/tests/utils/test_phone.py | 2 +- backend/tests/utils/test_rate_limit.py | 2 +- backend/tests/utils/test_response_parser.py | 2 +- backend/tests/utils/test_sanitize.py | 2 +- .../tests/workers/test_knowledge_processor.py | 2 +- .../test_knowledge_processor_abandoned.py | 2 +- .../test_knowledge_processor_notifications.py | 2 +- backend/tests_live/conftest.py | 2 +- backend/tests_live/test_behaviours_live.py | 2 +- backend/tests_live/test_guardrails_live.py | 2 +- .../tests_live/test_vulnerabilities_live.py | 4 +- deploy/local/compose.yaml | 8 +- deploy/local/demo.template.html | 8 +- deploy/local/init_env.py | 2 +- deploy/local/local.sh | 8 +- deploy/server/README.md | 2 +- deploy/server/config.example.json | 6 +- deploy/server/updater/deployment.py | 6 +- design/brand-refresh/README.md | 4 +- docker-compose.prod.yml | 28 +- docker-compose.yml | 2 +- e2e/.env.e2e | 4 +- e2e/AUTHORING.md | 6 +- e2e/FEATURES.md | 2 +- e2e/package-lock.json | 4 +- e2e/package.json | 4 +- e2e/scripts/stack.sh | 16 +- e2e/scripts/upgrade-check.sh | 4 +- e2e/services/customer-site/server.ts | 22 +- e2e/services/fake-externals/server.ts | 8 +- e2e/services/fake-llm/server.ts | 4 +- e2e/specs/a11y/a11y.spec.ts | 4 +- e2e/specs/channels/own-meta-app.spec.ts | 2 +- e2e/specs/crm/pipedrive.org.spec.ts | 4 +- e2e/specs/perf/budgets.spec.ts | 2 +- e2e/specs/widget/js-api.spec.ts | 2 +- e2e/src/api/ai.ts | 6 +- e2e/src/api/schema.d.ts | 2 +- e2e/src/components/chat-widget.ts | 22 +- e2e/src/env.ts | 2 +- e2e/src/org-setup.ts | 2 +- e2e/src/pages/ai-config.page.ts | 2 +- e2e/src/pages/setup.page.ts | 2 +- frontend/index.html | 2 +- frontend/nginx.conf | 2 +- frontend/public/config.dev.js | 37 +- frontend/public/webclient/chattermate.min.js | 889 -- frontend/public/webclient/replypier.min.js | 889 ++ frontend/scripts/build-webclient-dev.ts | 16 +- frontend/scripts/build-webclient-prod.ts | 14 +- frontend/scripts/generate-prod-env.ts | 6 +- frontend/src/App.vue | 2 +- frontend/src/__tests__/App.spec.ts | 2 +- .../__tests__/components/BaseModal.spec.ts | 2 +- .../__tests__/components/HandlerBadge.spec.ts | 2 +- .../components/MessageStatusTicks.spec.ts | 2 +- .../components/QuickReplyChips.spec.ts | 2 +- .../__tests__/components/StepLaunch.spec.ts | 4 +- .../components/StepTeach.recovery.spec.ts | 18 +- .../components/UserForm.chatScope.spec.ts | 2 +- .../components/WhatsAppTemplateSelect.spec.ts | 2 +- .../AgentInstructionsTab.replyButtons.spec.ts | 2 +- .../aiagent/AIAgentOnboarding.resume.spec.ts | 2 +- .../components/aiagent/ChatMessage.spec.ts | 2 +- .../common/GuidanceTextarea.spec.ts | 2 +- .../__tests__/components/faq/FaqCard.spec.ts | 2 +- .../components/faq/FaqGenerateBar.spec.ts | 2 +- .../faq/FaqGenerationProgress.spec.ts | 2 +- .../components/faq/FaqImportModal.spec.ts | 2 +- .../components/faq/FaqSeoFields.spec.ts | 2 +- .../components/integrations/CopyField.spec.ts | 2 +- .../integrations/MessengerPagePicker.spec.ts | 2 +- .../MetaChannelConnect.appSecret.spec.ts | 2 +- .../integrations/MetaChannelConnect.spec.ts | 2 +- .../integrations/MetaOwnAppWebhook.spec.ts | 2 +- .../KnowledgeAddSourceModal.scope.spec.ts | 2 +- .../components/layout/BottomNav.spec.ts | 2 +- .../components/layout/navItems.spec.ts | 2 +- .../notifications/EnablePushPrompt.spec.ts | 8 +- .../tickets/InvestigationNoteForm.spec.ts | 2 +- .../tickets/TicketConnectorsSection.spec.ts | 2 +- .../tickets/TicketInvestigationPanel.spec.ts | 2 +- .../tickets/TicketSidePanel.spec.ts | 2 +- .../composables/useBreakpoint.spec.ts | 2 +- .../composables/useConversationToken.spec.ts | 8 +- .../__tests__/composables/useCurrency.spec.ts | 2 +- .../useFaqWorkspace.category.spec.ts | 2 +- .../__tests__/composables/useMCPTools.spec.ts | 2 +- .../useNotificationSettings.spec.ts | 2 +- .../composables/useOrgInboxRoom.spec.ts | 2 +- .../useOrganizationSettings.spec.ts | 2 +- .../useUsers.resetPassword.spec.ts | 2 +- .../useWidgetCustomization.spec.ts | 2 +- .../useWidgetSocket.reconnect.spec.ts | 2 +- .../src/__tests__/fixtures/permissions.ts | 2 +- .../src/__tests__/fixtures/widget-snippet.txt | 6 +- .../__tests__/layouts/DashboardLayout.spec.ts | 2 +- frontend/src/__tests__/pwa/register.spec.ts | 2 +- .../__tests__/router/routePermissions.spec.ts | 2 +- frontend/src/__tests__/services/api.spec.ts | 2 +- .../services/firebase-unregister.spec.ts | 2 +- .../__tests__/services/installUrls.spec.ts | 2 +- frontend/src/__tests__/stores/counter.spec.ts | 2 +- frontend/src/__tests__/stubs/pwa-register.ts | 2 +- .../src/__tests__/utils/aiDisclaimer.spec.ts | 2 +- .../__tests__/utils/channelAccounts.spec.ts | 2 +- .../src/__tests__/utils/chatActions.spec.ts | 2 +- .../src/__tests__/utils/chatState.spec.ts | 2 +- frontend/src/__tests__/utils/color.spec.ts | 2 +- frontend/src/__tests__/utils/endChat.spec.ts | 2 +- .../__tests__/utils/knowledgePages.spec.ts | 2 +- frontend/src/__tests__/utils/mcp.spec.ts | 2 +- .../src/__tests__/utils/messageMatch.spec.ts | 2 +- frontend/src/__tests__/utils/metaSdk.spec.ts | 2 +- .../src/__tests__/utils/permissions.spec.ts | 2 +- .../src/__tests__/utils/planLimits.spec.ts | 2 +- frontend/src/__tests__/utils/sanitize.spec.ts | 2 +- .../__tests__/utils/swOauthCallback.spec.ts | 4 +- frontend/src/__tests__/utils/text.spec.ts | 2 +- .../src/__tests__/utils/timezones.spec.ts | 2 +- .../src/__tests__/utils/uploadUrl.spec.ts | 2 +- .../src/__tests__/utils/validators.spec.ts | 2 +- .../__tests__/utils/whatsappLanguages.spec.ts | 2 +- .../__tests__/utils/whatsappTemplates.spec.ts | 2 +- .../src/__tests__/utils/widgetEmbed.spec.ts | 20 +- .../__tests__/utils/widgetPresence.spec.ts | 2 +- .../src/__tests__/utils/widgetTheme.spec.ts | 22 +- frontend/src/__tests__/views/403.spec.ts | 2 +- .../__tests__/views/ConversationsView.spec.ts | 2 +- .../__tests__/views/HumanAgentView.spec.ts | 2 +- .../src/__tests__/views/LoginView.spec.ts | 2 +- .../src/__tests__/views/SetupView.spec.ts | 4 +- .../views/settings/AIConfigSettings.spec.ts | 2 +- .../settings/OrganizationSettings.spec.ts | 2 +- .../__tests__/webclient/hostBridge.spec.ts | 6 +- ...tity.spec.ts => replypierIdentity.spec.ts} | 78 +- ...cle.spec.ts => replypierLifecycle.spec.ts} | 106 +- .../webclient/widgetComposer.spec.ts | 2 +- .../webclient/widgetStartupRefusal.spec.ts | 2 +- frontend/src/assets/base.css | 10 +- frontend/src/assets/styles/components.css | 118 +- .../src/components/agent/AgentAdvancedTab.vue | 2 +- .../agent/AgentChatPreviewPanel.vue | 68 +- .../agent/AgentCustomizationView.vue | 6 +- frontend/src/components/agent/AgentDetail.vue | 2 +- .../components/agent/AgentInstructionsTab.vue | 2 +- .../components/agent/AgentIntegrationsTab.vue | 2 +- .../components/agent/AgentLeadCaptureTab.vue | 2 +- frontend/src/components/agent/AgentList.vue | 2 +- .../src/components/agent/AgentMCPToolsTab.vue | 2 +- .../src/components/agent/AgentWidgetTab.vue | 32 +- .../src/components/agent/AgentWorkflowTab.vue | 2 +- .../src/components/agent/CreateAgentModal.vue | 2 +- .../src/components/agent/KnowledgeGrid.vue | 4 +- frontend/src/components/ai/AISetup.vue | 50 +- .../src/components/aiagent/AIAgentSetup.vue | 2 +- .../src/components/aiagent/ChatMessage.vue | 2 +- .../aiagent/onboarding/AIAgentOnboarding.vue | 2 +- .../aiagent/onboarding/steps/StepCreate.vue | 14 +- .../aiagent/onboarding/steps/StepLaunch.vue | 6 +- .../aiagent/onboarding/steps/StepTeach.vue | 4 +- .../aiagent/onboarding/steps/StepTest.vue | 2 +- .../onboarding/steps/TeachTextFallback.vue | 2 +- .../onboarding/steps/step-controls.css | 2 +- .../components/analytics/AgentPerformance.vue | 2 +- .../analytics/AnalyticsDashboard.vue | 2 +- .../analytics/CustomerAnalytics.vue | 2 +- .../analytics/SentimentAnalytics.vue | 2 +- frontend/src/components/common/BaseModal.vue | 2 +- .../src/components/common/ChannelBadge.vue | 2 +- frontend/src/components/common/FileUpload.vue | 2 +- .../components/common/GuidanceTextarea.vue | 2 +- frontend/src/components/common/Modal.vue | 2 +- .../common/PasswordStrengthMeter.vue | 2 +- .../conversations/ChatInfoPanel.vue | 2 +- .../conversations/ConversationChat.vue | 4 +- .../conversations/ConversationFilters.vue | 2 +- .../conversations/ConversationsList.vue | 2 +- .../components/conversations/HandlerBadge.vue | 2 +- .../conversations/MessageStatusTicks.vue | 2 +- .../components/conversations/MessageTag.vue | 2 +- .../conversations/NewWhatsAppConversation.vue | 2 +- .../conversations/QuickReplyChips.vue | 2 +- .../conversations/WhatsAppTemplatePicker.vue | 2 +- .../conversations/WhatsAppTemplateSelect.vue | 2 +- frontend/src/components/faq/FaqCard.vue | 2 +- .../src/components/faq/FaqCategoryGroup.vue | 2 +- frontend/src/components/faq/FaqEmptyState.vue | 4 +- .../src/components/faq/FaqGenerateBar.vue | 2 +- .../components/faq/FaqGenerationProgress.vue | 2 +- .../src/components/faq/FaqImportModal.vue | 8 +- frontend/src/components/faq/FaqOrb.vue | 2 +- .../src/components/faq/FaqProLockOverlay.vue | 4 +- frontend/src/components/faq/FaqSeoFields.vue | 2 +- .../src/components/faq/FaqSourcePicker.vue | 2 +- frontend/src/components/faq/FaqWorkspace.vue | 2 +- .../components/faq/HelpCenterAppearance.vue | 2 +- .../components/faq/HelpCenterDomainPanel.vue | 4 +- .../components/faq/HelpCenterLogoField.vue | 2 +- .../src/components/faq/HelpCenterPreview.vue | 2 +- .../src/components/faq/HelpCenterPublic.vue | 2 +- .../src/components/faq/MarkdownEditor.vue | 2 +- .../src/components/human-agent/GroupForm.vue | 2 +- .../src/components/human-agent/GroupList.vue | 2 +- .../human-agent/ResetPasswordForm.vue | 2 +- .../src/components/human-agent/RoleForm.vue | 2 +- .../src/components/human-agent/RoleList.vue | 2 +- .../src/components/human-agent/UserForm.vue | 2 +- .../components/human-agent/UserGroupForm.vue | 2 +- .../src/components/human-agent/UserList.vue | 2 +- .../integrations/ChannelConnectModal.vue | 2 +- .../src/components/integrations/CopyField.vue | 2 +- .../integrations/MessengerPagePicker.vue | 2 +- .../integrations/MetaChannelConnect.vue | 4 +- .../integrations/MetaOwnAppWebhook.vue | 6 +- .../integrations/TelegramConnectModal.vue | 2 +- .../integrations/WhatsAppTemplateManager.vue | 2 +- .../src/components/jira/JiraTicketModal.vue | 2 +- .../knowledge/KnowledgeAddSourceModal.vue | 2 +- .../knowledge/KnowledgeExplorer.vue | 2 +- .../knowledge/KnowledgeLinkModal.vue | 2 +- .../knowledge/KnowledgePageDetail.vue | 2 +- .../knowledge/KnowledgePageEditor.vue | 2 +- .../knowledge/KnowledgePlanMeters.vue | 2 +- .../knowledge/KnowledgeSourceTree.vue | 2 +- frontend/src/components/layout/AppSidebar.vue | 2 +- frontend/src/components/layout/BottomNav.vue | 2 +- frontend/src/components/layout/MoreSheet.vue | 2 +- .../src/components/layout/SidebarToggle.vue | 2 +- frontend/src/components/layout/navIcons.ts | 2 +- frontend/src/components/layout/navItems.ts | 2 +- .../notifications/EnablePushPrompt.vue | 6 +- .../notifications/NotificationList.vue | 2 +- .../notifications/notificationIcons.ts | 2 +- .../components/organization/Organizations.vue | 6 +- .../components/people/PersonDetailDrawer.vue | 2 +- frontend/src/components/pwa/InstallPrompt.vue | 4 +- .../tickets/EvidenceCitationRow.vue | 2 +- .../src/components/tickets/HypothesisCard.vue | 2 +- .../tickets/InvestigationNoteForm.vue | 2 +- .../components/tickets/LinkedTicketCard.vue | 2 +- .../components/tickets/TicketActivityFeed.vue | 4 +- .../components/tickets/TicketAiStateChip.vue | 2 +- .../tickets/TicketApprovalBanner.vue | 6 +- .../tickets/TicketConnectorsSection.vue | 2 +- .../components/tickets/TicketCreateModal.vue | 2 +- .../tickets/TicketDbConnectorsSection.vue | 4 +- .../components/tickets/TicketEmptyState.vue | 2 +- .../components/tickets/TicketFilterBar.vue | 2 +- .../tickets/TicketInvestigationPanel.vue | 2 +- .../tickets/TicketPriorityBadge.vue | 2 +- .../src/components/tickets/TicketRcaDoc.vue | 4 +- .../components/tickets/TicketSidePanel.vue | 6 +- .../components/tickets/TicketStatusBadge.vue | 2 +- frontend/src/components/tickets/ticketMeta.ts | 2 +- frontend/src/components/user/UserSettings.vue | 2 +- .../src/components/widget-app/ApiKeyModal.vue | 2 +- .../components/widget-app/WidgetAppForm.vue | 2 +- .../components/widget-app/WidgetAppList.vue | 2 +- .../components/workflow/NodeConfigPanel.vue | 2 +- .../components/workflow/PropertiesPanel.vue | 2 +- .../components/workflow/WorkflowBuilder.vue | 2 +- .../components/workflow/nodes/ActionNode.vue | 2 +- .../workflow/nodes/ActionNodeConfig.vue | 2 +- .../workflow/nodes/ConditionNode.vue | 2 +- .../workflow/nodes/ConditionNodeConfig.vue | 2 +- .../src/components/workflow/nodes/EndNode.vue | 2 +- .../workflow/nodes/EndNodeConfig.vue | 2 +- .../components/workflow/nodes/FormNode.vue | 2 +- .../workflow/nodes/FormNodeConfig.vue | 2 +- .../workflow/nodes/GuardrailsNodeConfig.vue | 2 +- .../workflow/nodes/HumanTransferNode.vue | 2 +- .../nodes/HumanTransferNodeConfig.vue | 2 +- .../src/components/workflow/nodes/LLMNode.vue | 2 +- .../workflow/nodes/LLMNodeConfig.vue | 2 +- .../workflow/nodes/LandingPageNodeConfig.vue | 2 +- .../components/workflow/nodes/MessageNode.vue | 2 +- .../workflow/nodes/MessageNodeConfig.vue | 2 +- .../workflow/nodes/UserInputNodeConfig.vue | 2 +- .../components/workflow/nodes/WaitNode.vue | 2 +- .../workflow/nodes/WaitNodeConfig.vue | 2 +- .../src/components/workflow/nodes/index.ts | 2 +- frontend/src/composables/useAISetup.ts | 2 +- frontend/src/composables/useAgentAdvanced.ts | 2 +- frontend/src/composables/useAgentChat.ts | 2 +- frontend/src/composables/useAgentCreate.ts | 2 +- frontend/src/composables/useAgentDetail.ts | 2 +- frontend/src/composables/useAgentEdit.ts | 2 +- frontend/src/composables/useAgentWorkflow.ts | 2 +- frontend/src/composables/useAuth.ts | 2 +- frontend/src/composables/useBreakpoint.ts | 2 +- .../src/composables/useConversationChat.ts | 2 +- .../src/composables/useConversationFiles.ts | 2 +- .../src/composables/useConversationToken.ts | 4 +- .../src/composables/useConversationsList.ts | 2 +- frontend/src/composables/useCrawlCheck.ts | 2 +- frontend/src/composables/useCurrency.ts | 2 +- .../src/composables/useEnterpriseFeatures.ts | 2 +- frontend/src/composables/useFaqWorkspace.ts | 2 +- frontend/src/composables/useForgotPassword.ts | 2 +- frontend/src/composables/useGroups.ts | 2 +- .../src/composables/useHelpCenterSettings.ts | 2 +- .../src/composables/useJiraIntegration.ts | 2 +- frontend/src/composables/useJiraTicket.ts | 2 +- .../src/composables/useKnowledgeExplorer.ts | 2 +- .../src/composables/useKnowledgeManagement.ts | 2 +- frontend/src/composables/useMCPTools.ts | 2 +- frontend/src/composables/useMetaSignup.ts | 2 +- .../composables/useNotificationSettings.ts | 2 +- frontend/src/composables/useNotifications.ts | 2 +- .../src/composables/useOnboardingState.ts | 4 +- .../src/composables/useOnboardingTestChat.ts | 6 +- frontend/src/composables/useOrgInboxRoom.ts | 2 +- .../composables/useOrganizationSettings.ts | 2 +- frontend/src/composables/usePWAInstall.ts | 2 +- frontend/src/composables/useRoles.ts | 2 +- .../src/composables/useStagedSourceCap.ts | 2 +- frontend/src/composables/useTheme.ts | 4 +- frontend/src/composables/useTicketDetail.ts | 2 +- frontend/src/composables/useTicketSocket.ts | 2 +- .../src/composables/useTicketingSettings.ts | 2 +- .../src/composables/useTicketsWorkspace.ts | 2 +- frontend/src/composables/useTypewriter.ts | 2 +- frontend/src/composables/useUnreadBadge.ts | 2 +- frontend/src/composables/useUsers.ts | 2 +- frontend/src/composables/useVisualViewport.ts | 2 +- frontend/src/composables/useWidgetApps.ts | 2 +- .../src/composables/useWidgetCustomization.ts | 2 +- frontend/src/composables/useWidgetFiles.ts | 2 +- frontend/src/composables/useWidgetSocket.ts | 6 +- frontend/src/composables/useWidgetStyles.ts | 20 +- .../src/composables/useWorkflowManagement.ts | 2 +- .../src/composables/useWorkflowValidation.ts | 2 +- frontend/src/config/api.ts | 2 +- frontend/src/config/docs.ts | 4 +- frontend/src/config/themeColors.ts | 2 +- frontend/src/layouts/DashboardLayout.vue | 6 +- frontend/src/main.ts | 4 +- frontend/src/pwa/navigationDenylist.ts | 2 +- frontend/src/pwa/pushContract.ts | 2 +- frontend/src/pwa/register.ts | 4 +- frontend/src/router/index.ts | 2 +- frontend/src/router/landing.ts | 2 +- frontend/src/router/routePermissions.ts | 2 +- frontend/src/services/agent.ts | 2 +- frontend/src/services/ai.ts | 2 +- frontend/src/services/api.ts | 2 +- frontend/src/services/auth.ts | 2 +- frontend/src/services/channels.ts | 4 +- frontend/src/services/chat.ts | 2 +- frontend/src/services/crm.ts | 2 +- frontend/src/services/faq.ts | 2 +- frontend/src/services/firebase.ts | 2 +- frontend/src/services/groups.ts | 2 +- frontend/src/services/jira.ts | 2 +- frontend/src/services/knowledge.ts | 2 +- frontend/src/services/leadCapture.ts | 2 +- frontend/src/services/mcp.ts | 2 +- frontend/src/services/notification.ts | 2 +- frontend/src/services/organization.ts | 2 +- frontend/src/services/people.ts | 2 +- frontend/src/services/roles.ts | 2 +- frontend/src/services/sessionToAgent.ts | 2 +- frontend/src/services/shopify.ts | 2 +- frontend/src/services/socket.ts | 2 +- frontend/src/services/tickets.ts | 2 +- frontend/src/services/user.ts | 2 +- frontend/src/services/users.ts | 2 +- frontend/src/services/widget-app.ts | 2 +- frontend/src/services/widget.ts | 2 +- frontend/src/services/workflow.ts | 2 +- frontend/src/services/workflowNode.ts | 2 +- frontend/src/stores/counter.ts | 2 +- frontend/src/sw.ts | 4 +- frontend/src/types/agent.ts | 2 +- frontend/src/types/ai.ts | 2 +- frontend/src/types/chat.ts | 2 +- frontend/src/types/faq.ts | 2 +- frontend/src/types/global.d.ts | 2 +- frontend/src/types/knowledge.ts | 2 +- frontend/src/types/leadCapture.ts | 2 +- frontend/src/types/mcp.ts | 2 +- frontend/src/types/organization.ts | 2 +- frontend/src/types/people.ts | 2 +- frontend/src/types/ticket.ts | 2 +- frontend/src/types/timezone-select-js.d.ts | 2 +- frontend/src/types/user.ts | 2 +- frontend/src/types/widget-app.ts | 2 +- frontend/src/types/widget.ts | 2 +- frontend/src/types/window.d.ts | 2 +- frontend/src/types/workflow.ts | 2 +- frontend/src/utils/aiDisclaimer.ts | 2 +- frontend/src/utils/apiError.ts | 2 +- frontend/src/utils/avatars.ts | 2 +- frontend/src/utils/channelAccounts.ts | 2 +- frontend/src/utils/chatActions.ts | 2 +- frontend/src/utils/chatState.ts | 2 +- frontend/src/utils/color.ts | 2 +- frontend/src/utils/emitter.ts | 2 +- frontend/src/utils/endChat.ts | 2 +- frontend/src/utils/knowledgePages.ts | 2 +- frontend/src/utils/mcp.ts | 2 +- frontend/src/utils/messageMatch.ts | 2 +- frontend/src/utils/metaSdk.ts | 2 +- frontend/src/utils/orb.ts | 2 +- frontend/src/utils/permissionGroups.ts | 2 +- frontend/src/utils/permissions.ts | 2 +- frontend/src/utils/planLimitToast.ts | 2 +- frontend/src/utils/sanitize.ts | 2 +- frontend/src/utils/setupEvents.ts | 4 +- frontend/src/utils/storage.ts | 2 +- frontend/src/utils/text.ts | 2 +- frontend/src/utils/timezones.ts | 2 +- frontend/src/utils/validators.ts | 2 +- frontend/src/utils/whatsappLanguages.ts | 2 +- frontend/src/utils/whatsappTemplates.ts | 2 +- frontend/src/utils/widgetEmbed.ts | 26 +- frontend/src/utils/widgetPresence.ts | 2 +- frontend/src/views/403.vue | 2 +- frontend/src/views/AIAgentView.vue | 2 +- frontend/src/views/AnalyticsView.vue | 2 +- frontend/src/views/ConversationsView.vue | 2 +- frontend/src/views/FaqView.vue | 2 +- frontend/src/views/HumanAgentView.vue | 6 +- frontend/src/views/KnowledgeView.vue | 2 +- frontend/src/views/LoginView.vue | 2 +- frontend/src/views/PeopleView.vue | 2 +- frontend/src/views/SetupView.vue | 4 +- frontend/src/views/TicketDetailView.vue | 2 +- frontend/src/views/TicketsView.vue | 4 +- frontend/src/views/UserSettingsView.vue | 2 +- .../src/views/settings/AIConfigSettings.vue | 2 +- .../views/settings/IntegrationsSettings.vue | 18 +- .../views/settings/OrganizationSettings.vue | 2 +- .../src/views/settings/TicketingSettings.vue | 6 +- .../src/views/settings/WidgetAppsSettings.vue | 2 +- frontend/src/webclient/AskAiPanel.vue | 80 +- frontend/src/webclient/NewChatConfirm.vue | 20 +- frontend/src/webclient/WidgetBuilder.vue | 288 +- frontend/src/webclient/host-bridge.ts | 2 +- frontend/src/webclient/markdown.ts | 2 +- frontend/src/webclient/new-chat.ts | 2 +- .../{chattermate.js => replypier.js} | 316 +- frontend/src/webclient/widget-env.ts | 6 +- frontend/src/webclient/widget-surface.css | 196 +- frontend/src/webclient/widget-theme.ts | 38 +- frontend/src/webclient/widget.css | 8 +- frontend/src/webclient/widget.ts | 2 +- frontend/vite.config.ts | 8 +- frontend/vite.widget.config.ts | 2 +- frontend/vite.widget.docker.config.ts | 2 +- llms.txt | 77 +- relicense_headers.py | 2 +- .../README.md | 18 +- .../index.html | 124 +- .../package-lock.json | 4 +- .../package.json | 2 +- .../server.js | 2 +- .../ui-options.html | 16 +- .../ui-test.html | 46 +- wordpress/chattermate-chat.zip | Bin 13853 -> 0 bytes wordpress/replypier-chat.zip | Bin 0 -> 13824 bytes 1156 files changed, 7292 insertions(+), 7147 deletions(-) rename backend/alembic/versions/{520df92643e3_added_chattermate_ai_model.py => 520df92643e3_added_replypier_ai_model.py} (95%) create mode 100644 backend/alembic/versions/replypier_ai_model_001_carry_managed_model_label.py delete mode 100644 frontend/public/webclient/chattermate.min.js create mode 100644 frontend/public/webclient/replypier.min.js rename frontend/src/__tests__/webclient/{chattermateIdentity.spec.ts => replypierIdentity.spec.ts} (77%) rename frontend/src/__tests__/webclient/{chattermateLifecycle.spec.ts => replypierLifecycle.spec.ts} (69%) rename frontend/src/webclient/{chattermate.js => replypier.js} (90%) rename {chattermate-test => replypier-test}/README.md (79%) rename {chattermate-test => replypier-test}/index.html (86%) rename {chattermate-test => replypier-test}/package-lock.json (99%) rename {chattermate-test => replypier-test}/package.json (84%) rename {chattermate-test => replypier-test}/server.js (98%) rename {chattermate-test => replypier-test}/ui-options.html (93%) rename {chattermate-test => replypier-test}/ui-test.html (85%) delete mode 100644 wordpress/chattermate-chat.zip create mode 100644 wordpress/replypier-chat.zip diff --git a/.claude/skills/write-e2e-test/SKILL.md b/.claude/skills/write-e2e-test/SKILL.md index d20437c..8285c40 100644 --- a/.claude/skills/write-e2e-test/SKILL.md +++ b/.claude/skills/write-e2e-test/SKILL.md @@ -1,9 +1,9 @@ --- name: write-e2e-test -description: Write or change a ChatterMate Playwright end-to-end test (e2e/). Use when adding e2e coverage for a feature, fixing a failing e2e spec, or adding a page object, fixture or fake-LLM script. +description: Write or change a ReplyPier Playwright end-to-end test (e2e/). Use when adding e2e coverage for a feature, fixing a failing e2e spec, or adding a page object, fixture or fake-LLM script. --- -# Writing a ChatterMate e2e test +# Writing a ReplyPier e2e test The suite lives in `e2e/`. Read `e2e/AUTHORING.md` first — it is the source of truth for layout and rules. The essentials: diff --git a/.gitignore b/.gitignore index 89300ef..1d81073 100644 --- a/.gitignore +++ b/.gitignore @@ -25,13 +25,13 @@ uploads/ *.csr.crt /shopify/ -# WordPress plugin source lives in its own repo (chattermate-wordpress-plugin); +# WordPress plugin source lives in its own repo (replypier-wordpress-plugin); # only the built, installable zip is tracked here for manual download. /wordpress/* -!/wordpress/chattermate-chat.zip +!/wordpress/replypier-chat.zip # Firebase service account key (contains sensitive credentials) -chattermate-13e0a-firebase-adminsdk-7dqo6-57f3de88cb.json +*-firebase-adminsdk-*.json test.db *.db @@ -71,7 +71,7 @@ config/ frontend/.env.*.bak* # Stale loader copies — server.js serves the current build from frontend/public/webclient -chattermate-test/chattermate.min.js +replypier-test/replypier.min.js # Only the :dev webclient build emits a sourcemap, and the committed loader is # the :prod one, which does not reference it. Keeps a stray dev artifact out. diff --git a/AGENT_HANDOFF.md b/AGENT_HANDOFF.md index 2ca16d1..83b5181 100644 --- a/AGENT_HANDOFF.md +++ b/AGENT_HANDOFF.md @@ -30,7 +30,7 @@ | PostgreSQL 16 + pgvector | `127.0.0.1:15432` | | Redis | `127.0.0.1:16380` | -Docker context 为 `colima-bytedesk`,Compose 项目名为 `chattermate-local`,数据库卷为 `chattermate-local_postgres_data`。它们是运行配置,不能为整理名称而改动或删除。Colima 虚拟机承载数据库与缓存,不要单独关闭。 +Docker context 为 `colima-bytedesk`,Compose 项目名为 `replypier-local`,数据库卷为 `replypier-local_postgres_data`。它们是运行配置,不能为整理名称而改动或删除。Colima 虚拟机承载数据库与缓存,不要单独关闭。 ## 配置与数据保护 diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 541567c..d67ae5b 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,11 +1,11 @@ -# Contributing to ChatterMate +# Contributing to ReplyPier Thanks for your interest in contributing! This document explains how to get your changes accepted. ## License -The ChatterMate open-source core is licensed under the +The ReplyPier open-source core is licensed under the [Apache License 2.0](LICENSE). By contributing, you agree that your contributions will be licensed under Apache-2.0. diff --git a/Dockerfile.frontend.prod b/Dockerfile.frontend.prod index e35b476..9435dd6 100644 --- a/Dockerfile.frontend.prod +++ b/Dockerfile.frontend.prod @@ -22,12 +22,12 @@ RUN npm install # Build the application, widget, and webclient. Use the :prod webclient build so # the shipped loader bakes the production fallback URL (the real backend URL is -# resolved at runtime via window.chattermateBaseUrl / APP_CONFIG regardless). +# resolved at runtime via window.replypierBaseUrl / APP_CONFIG regardless). RUN npm run build-only && \ npm run build:widgetdocker && \ npm run build:webclient:prod && \ if [ ! -f dist/index.html ]; then \ - echo "ChatterMate
" > dist/index.html; \ + echo "ReplyPier
" > dist/index.html; \ fi # Production stage diff --git a/Dockerfile.postgres b/Dockerfile.postgres index 6b30212..8daf739 100644 --- a/Dockerfile.postgres +++ b/Dockerfile.postgres @@ -18,7 +18,7 @@ RUN git clone https://github.com/pgvector/pgvector.git && \ COPY ./backend/scripts/init-vector.sql /docker-entrypoint-initdb.d/ # Set environment variables -ENV POSTGRES_DB=chattermate +ENV POSTGRES_DB=replypier ENV POSTGRES_USER=postgres ENV POSTGRES_PASSWORD=postgres diff --git a/HELP_CENTER_INFRA.md b/HELP_CENTER_INFRA.md index 7931c95..808f975 100644 --- a/HELP_CENTER_INFRA.md +++ b/HELP_CENTER_INFRA.md @@ -6,11 +6,10 @@ deploy-time pieces that live **outside** the repo: DNS, TLS and the host nginx on the production VPS. `frontend/nginx.conf` and the docker-compose files need **no changes**. -> **As deployed on the ChatterMate cloud VPS (2026-07-14):** the base domain is -> **`help.chattermate.chat`** (orgs serve at `{slug}.help.chattermate.chat`), not -> the `chattermate.help` this doc originally planned — that domain was never -> registered, and the org only owns `chattermate.chat`. DNS is **Route53**, so the -> wildcard cert is issued and auto-renewed with the `dns-route53` plugin. +> **As deployed on the ReplyPier VPS (2026-07-14):** the base domain is +> **`help.replypier.site`** (orgs serve at `{slug}.help.replypier.site`). DNS is +> **Route53**, so the wildcard cert is issued and auto-renewed with the +> `dns-route53` plugin. > Placeholders (``, ``, …) stand in for the live values; the > real ones live on the VPS and in ops notes, not in this public repo. @@ -18,9 +17,9 @@ files need **no changes**. ### DNS (Route53) Point a wildcard under the domain you own at the VPS. On the cloud box this is -the `chattermate.chat` hosted zone (``): -- `*.help.chattermate.chat. A ` -- `*.help.chattermate.chat. AAAA ` +the `replypier.site` hosted zone (``): +- `*.help.replypier.site. A ` +- `*.help.replypier.site. AAAA ` One wildcard record covers every org — no per-org DNS. Create them via the API: ```bash @@ -30,7 +29,7 @@ aws route53 change-resource-record-sets --hosted-zone-id \ Backend env (`backend.env` on the VPS): ``` -HELP_CENTER_BASE_DOMAIN=help.chattermate.chat +HELP_CENTER_BASE_DOMAIN=help.replypier.site HELP_CENTER_TARGET_IPS=[""] # JSON array — see gotcha below ``` > **Gotcha:** `HELP_CENTER_TARGET_IPS` is a `frozenset` setting, so @@ -46,11 +45,11 @@ Route53 policy (`route53:ListHostedZones` + `GetChange` on `*`, (mode 600) on the box. Issue once: ```bash docker run --rm \ - -v ~/chattermate/certbot/conf:/etc/letsencrypt \ + -v ~/replypier/certbot/conf:/etc/letsencrypt \ -v ~/.aws:/root/.aws:ro \ certbot/dns-route53 certonly --dns-route53 \ - -d '*.help.chattermate.chat' -d 'help.chattermate.chat' \ - --cert-name help.chattermate.chat \ + -d '*.help.replypier.site' -d 'help.replypier.site' \ + --cert-name help.replypier.site \ --non-interactive --agree-tos -m ``` @@ -63,7 +62,7 @@ docker compose -f docker-compose.hostinger.yml \ # ...then, if the flag file appeared: rm it && docker compose exec -T nginx nginx -s reload ``` It uses the `certbot/dns-route53` image and mounts -`/home/chattermate/.aws:/root/.aws:ro`, so the wildcard renews unattended (the +`/home/replypier/.aws:/root/.aws:ro`, so the wildcard renews unattended (the renewal conf remembers `authenticator = dns-route53`). Existing HTTP-01 webroot certs still renew — the dns-route53 image is a superset of `certbot/certbot`. `renew` covers every cert in the shared `certbot/conf`, not just the wildcard. @@ -95,19 +94,19 @@ certs still renew — the dns-route53 image is a superset of `certbot/certbot`. > ``` ### Host nginx server block -Lives at `~/chattermate/nginx/conf.d/help-center.conf` (mounted read-only into -the `chattermate-nginx-1` container). `proxy_set_header Host $host` is what +Lives at `~/replypier/nginx/conf.d/help-center.conf` (mounted read-only into +the `replypier-nginx-1` container). `proxy_set_header Host $host` is what makes backend host-dispatch resolve the org. Upstream is the compose service -name `backend:8000` (nginx shares the `chattermate-network`), not a published +name `backend:8000` (nginx shares the `replypier-network`), not a published host port. ```nginx -# {slug}.help.chattermate.chat +# {slug}.help.replypier.site server { listen 443 ssl http2; - server_name *.help.chattermate.chat help.chattermate.chat; - ssl_certificate /etc/letsencrypt/live/help.chattermate.chat/fullchain.pem; - ssl_certificate_key /etc/letsencrypt/live/help.chattermate.chat/privkey.pem; + server_name *.help.replypier.site help.replypier.site; + ssl_certificate /etc/letsencrypt/live/help.replypier.site/fullchain.pem; + ssl_certificate_key /etc/letsencrypt/live/help.replypier.site/privkey.pem; include /etc/nginx/conf.d/ssl-params.conf; location / { @@ -121,7 +120,7 @@ server { server { listen 80; - server_name *.help.chattermate.chat help.chattermate.chat; + server_name *.help.replypier.site help.replypier.site; location /.well-known/acme-challenge/ { root /var/www/certbot; } location / { return 301 https://$host$request_uri; } } @@ -130,11 +129,11 @@ server { ## 2. Per-customer custom domain (runbook step per domain) Customers add two records (shown in their FAQ admin UI). On the cloud box the -CNAME target `cname.chattermate.chat` is **not** provisioned, so verification +CNAME target `cname.replypier.site` is **not** provisioned, so verification falls back to an A record pointing at `HELP_CENTER_TARGET_IPS` — either form works: -- `CNAME help.customer.com → cname.chattermate.chat` *(or)* `A help.customer.com → ` -- `TXT _chattermate.help.customer.com → cm-verify=` +- `CNAME help.customer.com → cname.replypier.site` *(or)* `A help.customer.com → ` +- `TXT _replypier.customer.com → rp-verify=` After they click **Verify domain** (DNS checks pass, `ssl_status` becomes `pending`), issue the certificate on the VPS — HTTP-01 works because the @@ -161,10 +160,10 @@ admin endpoint for verified-but-unprovisioned domains and runs whole VPS. ## 3. Verification checklist after deploy -1. `curl -sS -o /dev/null -w '%{http_code}\n' https://.help.chattermate.chat/` → `200` (and `http://` → `301`). -2. `https://.help.chattermate.chat` in a browser → published FAQs render, widget loads; an article at `/a/` returns `200`. -3. `docker exec chattermate-backend-1 printenv HELP_CENTER_BASE_DOMAIN` → `help.chattermate.chat` (and the backend is `healthy`, not crash-looping on `HELP_CENTER_TARGET_IPS`). -4. API unaffected: `https://app.chattermate.chat` / `https://api.chattermate.chat/api/v1/...` still route normally. +1. `curl -sS -o /dev/null -w '%{http_code}\n' https://.help.replypier.site/` → `200` (and `http://` → `301`). +2. `https://.help.replypier.site` in a browser → published FAQs render, widget loads; an article at `/a/` returns `200`. +3. `docker exec replypier-backend-1 printenv HELP_CENTER_BASE_DOMAIN` → `help.replypier.site` (and the backend is `healthy`, not crash-looping on `HELP_CENTER_TARGET_IPS`). +4. API unaffected: `https://app.replypier.site` / `https://api.replypier.site/api/v1/...` still route normally. 5. `POST /ask` from the page returns an answer and appears in `help_center_queries`. 6. `docker ps -a --filter name=certbot` → **empty**. `compose up -d` must not start a certbot container; one that sticks around means the long-running loop entrypoint is @@ -180,7 +179,7 @@ The feature is gated by the `help_center` plan flag, which lives in the - backfill existing plan rows' `features` JSON with the same values; - extend the message-limit check to add the org's period `help_center_queries` count (`HelpCenterQueryRepository.count_for_period`) - to the bot-message count when the org runs on the ChatterMate-hosted model. + to the bot-message count when the org runs on the ReplyPier-hosted model. Until that PR deploys, cloud orgs see the upgrade lock (`plan_allowed: false`); self-hosted/OSS installs are unrestricted immediately. diff --git a/LOCAL_DEPLOY.md b/LOCAL_DEPLOY.md index 947ac77..467032c 100644 --- a/LOCAL_DEPLOY.md +++ b/LOCAL_DEPLOY.md @@ -63,8 +63,8 @@ Python 后端、知识库 worker、前端预览服务在宿主机运行;Postgr | Redis | `127.0.0.1:16380` | - Docker context:`colima-bytedesk`。 -- Compose 项目名:`chattermate-local`。 -- 数据库卷:`chattermate-local_postgres_data`。 +- Compose 项目名:`replypier-local`。 +- 数据库卷:`replypier-local_postgres_data`。 - 配置:`backend/.env`、`frontend/.env`、`deploy/local/.env`。 - 运行文件、日志、构建产物、嵌入模型缓存:`deploy/local/.state/`。 - Widget 与演示配置:[test-environment.json](deploy/local/.state/test-environment.json)。 @@ -72,6 +72,17 @@ Python 后端、知识库 worker、前端预览服务在宿主机运行;Postgr 启动脚本使用上述 context、项目名和卷。不要随意改名、删除数据卷或关闭承载数据库的 Colima 虚拟机。 +### 改名后的旧数据(一次性,未执行) + +2026-10-26 品牌统一时,Compose 项目名、数据卷名、库名与库用户从旧名改成 `replypier-local` / `replypier-local_postgres_data` / `replypier` / `replypier`。旧卷里的本机数据不会自动挂到新卷,需要时再搬;全新环境无需处理。 + +当时 Colima 未运行,这一步没有执行、也没有验证。要做时先 `./deploy/local/local.sh stop`,再二选一: + +1. 保留旧数据:从旧卷 `pg_dumpall -U <旧用户>` 导出,起新栈后还原到 `replypier` 库,然后把 `backend/.env` 的 `DATABASE_URL` 指向新库。加密字段依赖同一个 `backend/.env` 密钥,换密钥会导致旧密文读不出来。 +2. 不复用:直接 `local.sh up` 得到空库,重新建管理员与 AI 客服配置。 + +不要用复制 PGDATA 的方式搬库:库名和角色名都变了,还需要在数据目录里额外改名。 + 恢复数据时须同时保留数据库和 `backend/.env` 中的加密配置,否则加密保存的模型配置及消息可能无法读取。不要覆盖密钥、重置管理员,或将私有环境文件提交和对外分享。 ## 会话权限检查 diff --git a/NOTICE b/NOTICE index e005d0a..d5723e6 100644 --- a/NOTICE +++ b/NOTICE @@ -1,8 +1,9 @@ -ChatterMate -Copyright 2024-2026 ChatterMate +ReplyPier +Copyright 2024-2026 ReplyPier -This product includes software developed by ChatterMate -(https://chattermate.chat). +This product is the ReplyPier AI customer-support platform: an AI agent answers +first from your own knowledge base, a human takes over in the same conversation, +and the visitor can rate the service at the end. -Licensed under the Apache License, Version 2.0. See the LICENSE file for -the full license text. +Licensed under the Apache License, Version 2.0. See the LICENSE file for the +full license text. Contribution terms are in CONTRIBUTING.md. diff --git a/backend/.env.example b/backend/.env.example index 2001803..1132e5d 100644 --- a/backend/.env.example +++ b/backend/.env.example @@ -1,5 +1,5 @@ # Database Configuration -DATABASE_URL=postgresql+psycopg://postgres:postgres@db:5432/chattermate +DATABASE_URL=postgresql+psycopg://postgres:postgres@db:5432/replypier # CORS Configuration add backend url to allow cors from frontend CORS_ORIGINS=["http://localhost:3000","http://localhost:8000"] @@ -61,7 +61,7 @@ ENVIRONMENT=development # S3 Configuration S3_FILE_STORAGE=false -S3_BUCKET=chattermate-uploads +S3_BUCKET=replypier-uploads S3_REGION=us-east-1 # Leave both blank on EC2/ECS/EKS to use the attached IAM role — boto3 then # resolves credentials from its default chain. Set them only for static keys; diff --git a/backend/__init__.py b/backend/__init__.py index a2b5f42..11ab711 100644 --- a/backend/__init__.py +++ b/backend/__init__.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/alembic/env.py b/backend/alembic/env.py index 76b1de4..652aea4 100644 --- a/backend/alembic/env.py +++ b/backend/alembic/env.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/alembic/versions/013174e15242_add_priority_to_knowledge_queue.py b/backend/alembic/versions/013174e15242_add_priority_to_knowledge_queue.py index d618cd7..5fbf9c0 100644 --- a/backend/alembic/versions/013174e15242_add_priority_to_knowledge_queue.py +++ b/backend/alembic/versions/013174e15242_add_priority_to_knowledge_queue.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/alembic/versions/0cf34ff05aee_merge_guardrails_and_chat_initiation.py b/backend/alembic/versions/0cf34ff05aee_merge_guardrails_and_chat_initiation.py index bd0ef7a..6135766 100644 --- a/backend/alembic/versions/0cf34ff05aee_merge_guardrails_and_chat_initiation.py +++ b/backend/alembic/versions/0cf34ff05aee_merge_guardrails_and_chat_initiation.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/alembic/versions/0cf5fa1db0cb_add_teamid_to_agent_sessions.py b/backend/alembic/versions/0cf5fa1db0cb_add_teamid_to_agent_sessions.py index e7ba66f..6d4fc00 100644 --- a/backend/alembic/versions/0cf5fa1db0cb_add_teamid_to_agent_sessions.py +++ b/backend/alembic/versions/0cf5fa1db0cb_add_teamid_to_agent_sessions.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/alembic/versions/0ee9dbc73d9e_removed_message_node_specific_fields.py b/backend/alembic/versions/0ee9dbc73d9e_removed_message_node_specific_fields.py index 882c184..2d414dd 100644 --- a/backend/alembic/versions/0ee9dbc73d9e_removed_message_node_specific_fields.py +++ b/backend/alembic/versions/0ee9dbc73d9e_removed_message_node_specific_fields.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/alembic/versions/1493b8279a2f_added_shopify_models.py b/backend/alembic/versions/1493b8279a2f_added_shopify_models.py index dfa093d..2f2947d 100644 --- a/backend/alembic/versions/1493b8279a2f_added_shopify_models.py +++ b/backend/alembic/versions/1493b8279a2f_added_shopify_models.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/alembic/versions/186c65ae9406_added_rating_table.py b/backend/alembic/versions/186c65ae9406_added_rating_table.py index 085c0c1..f95cc22 100644 --- a/backend/alembic/versions/186c65ae9406_added_rating_table.py +++ b/backend/alembic/versions/186c65ae9406_added_rating_table.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/alembic/versions/2037204bbebf_add_guardrails_node_type.py b/backend/alembic/versions/2037204bbebf_add_guardrails_node_type.py index fe5a785..d628523 100644 --- a/backend/alembic/versions/2037204bbebf_add_guardrails_node_type.py +++ b/backend/alembic/versions/2037204bbebf_add_guardrails_node_type.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/alembic/versions/2381319791e8_merge_multiple_heads.py b/backend/alembic/versions/2381319791e8_merge_multiple_heads.py index 2881371..3017663 100644 --- a/backend/alembic/versions/2381319791e8_merge_multiple_heads.py +++ b/backend/alembic/versions/2381319791e8_merge_multiple_heads.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/alembic/versions/2fd826882d08_add_workflow_history_column.py b/backend/alembic/versions/2fd826882d08_add_workflow_history_column.py index 0c1a05b..181e10d 100644 --- a/backend/alembic/versions/2fd826882d08_add_workflow_history_column.py +++ b/backend/alembic/versions/2fd826882d08_add_workflow_history_column.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/alembic/versions/30caca239191_add_jira_config.py b/backend/alembic/versions/30caca239191_add_jira_config.py index 201e96b..90dadf6 100644 --- a/backend/alembic/versions/30caca239191_add_jira_config.py +++ b/backend/alembic/versions/30caca239191_add_jira_config.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/alembic/versions/520df92643e3_added_chattermate_ai_model.py b/backend/alembic/versions/520df92643e3_added_replypier_ai_model.py similarity index 95% rename from backend/alembic/versions/520df92643e3_added_chattermate_ai_model.py rename to backend/alembic/versions/520df92643e3_added_replypier_ai_model.py index 295fab1..51560c5 100644 --- a/backend/alembic/versions/520df92643e3_added_chattermate_ai_model.py +++ b/backend/alembic/versions/520df92643e3_added_replypier_ai_model.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. """ -"""Added chattermate AI model +"""Added replypier AI model Revision ID: 520df92643e3 Revises: 85364d188f15 @@ -35,7 +35,7 @@ depends_on: Union[str, Sequence[str], None] = None def upgrade() -> None: # ### commands auto generated by Alembic - please adjust! ### # Create a new temporary type with the new value - op.execute("ALTER TYPE aimodeltype ADD VALUE IF NOT EXISTS 'CHATTERMATE'") + op.execute("ALTER TYPE aimodeltype ADD VALUE IF NOT EXISTS 'REPLYPIER'") # ### end Alembic commands ### def downgrade() -> None: diff --git a/backend/alembic/versions/52e6ca829bb8_make_user_org_and_role_nullable.py b/backend/alembic/versions/52e6ca829bb8_make_user_org_and_role_nullable.py index 67b2b42..ff9c5b6 100644 --- a/backend/alembic/versions/52e6ca829bb8_make_user_org_and_role_nullable.py +++ b/backend/alembic/versions/52e6ca829bb8_make_user_org_and_role_nullable.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/alembic/versions/537f2b7d4a7c_added_end_chat_support.py b/backend/alembic/versions/537f2b7d4a7c_added_end_chat_support.py index 72b61a3..671a9a9 100644 --- a/backend/alembic/versions/537f2b7d4a7c_added_end_chat_support.py +++ b/backend/alembic/versions/537f2b7d4a7c_added_end_chat_support.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/alembic/versions/5b5f936cd9e4_role_remove_name_alone_as_unique.py b/backend/alembic/versions/5b5f936cd9e4_role_remove_name_alone_as_unique.py index 608b25b..dfcf9fc 100644 --- a/backend/alembic/versions/5b5f936cd9e4_role_remove_name_alone_as_unique.py +++ b/backend/alembic/versions/5b5f936cd9e4_role_remove_name_alone_as_unique.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/alembic/versions/621095beb234_add_mcp_tools_tables.py b/backend/alembic/versions/621095beb234_add_mcp_tools_tables.py index c33bcdf..2c4c82c 100644 --- a/backend/alembic/versions/621095beb234_add_mcp_tools_tables.py +++ b/backend/alembic/versions/621095beb234_add_mcp_tools_tables.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/alembic/versions/6885c9f36712_add_chat_style_and_widget_position_to_agent_customizations.py b/backend/alembic/versions/6885c9f36712_add_chat_style_and_widget_position_to_agent_customizations.py index 0a3f6ae..aa1bcae 100644 --- a/backend/alembic/versions/6885c9f36712_add_chat_style_and_widget_position_to_agent_customizations.py +++ b/backend/alembic/versions/6885c9f36712_add_chat_style_and_widget_position_to_agent_customizations.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/alembic/versions/7991b4fc00d8_added_wlecome_header_and_title.py b/backend/alembic/versions/7991b4fc00d8_added_wlecome_header_and_title.py index 7954ddf..850cb56 100644 --- a/backend/alembic/versions/7991b4fc00d8_added_wlecome_header_and_title.py +++ b/backend/alembic/versions/7991b4fc00d8_added_wlecome_header_and_title.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/alembic/versions/7af9828611e7_add_oauth_state_fields_to_shopify_shops.py b/backend/alembic/versions/7af9828611e7_add_oauth_state_fields_to_shopify_shops.py index 4bbc458..546fea7 100644 --- a/backend/alembic/versions/7af9828611e7_add_oauth_state_fields_to_shopify_shops.py +++ b/backend/alembic/versions/7af9828611e7_add_oauth_state_fields_to_shopify_shops.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/alembic/versions/7fd0447b3d45_workflow_tables_added.py b/backend/alembic/versions/7fd0447b3d45_workflow_tables_added.py index b86d7f2..6ff4dad 100644 --- a/backend/alembic/versions/7fd0447b3d45_workflow_tables_added.py +++ b/backend/alembic/versions/7fd0447b3d45_workflow_tables_added.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/alembic/versions/85364d188f15_merge_heads.py b/backend/alembic/versions/85364d188f15_merge_heads.py index cf19171..cd86f6d 100644 --- a/backend/alembic/versions/85364d188f15_merge_heads.py +++ b/backend/alembic/versions/85364d188f15_merge_heads.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/alembic/versions/89a4f4898aa4_change_datetime_to_timestamp_with_.py b/backend/alembic/versions/89a4f4898aa4_change_datetime_to_timestamp_with_.py index af2a893..38b1970 100644 --- a/backend/alembic/versions/89a4f4898aa4_change_datetime_to_timestamp_with_.py +++ b/backend/alembic/versions/89a4f4898aa4_change_datetime_to_timestamp_with_.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/alembic/versions/910bfe03518b_make_knowledge_queue_user_id_nullable.py b/backend/alembic/versions/910bfe03518b_make_knowledge_queue_user_id_nullable.py index 46e4976..2be3f69 100644 --- a/backend/alembic/versions/910bfe03518b_make_knowledge_queue_user_id_nullable.py +++ b/backend/alembic/versions/910bfe03518b_make_knowledge_queue_user_id_nullable.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/alembic/versions/91a148726029_add_extra_data_to_agent_sessions.py b/backend/alembic/versions/91a148726029_add_extra_data_to_agent_sessions.py index 1bbe4a1..04942a2 100644 --- a/backend/alembic/versions/91a148726029_add_extra_data_to_agent_sessions.py +++ b/backend/alembic/versions/91a148726029_add_extra_data_to_agent_sessions.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/alembic/versions/9a01e6b653b2_add_agent_shopify_config_with_shop_.py b/backend/alembic/versions/9a01e6b653b2_add_agent_shopify_config_with_shop_.py index 844a313..7fc3f05 100644 --- a/backend/alembic/versions/9a01e6b653b2_add_agent_shopify_config_with_shop_.py +++ b/backend/alembic/versions/9a01e6b653b2_add_agent_shopify_config_with_shop_.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/alembic/versions/9ce623009955_added_new_node_type_user_input.py 14-13-41-620.py b/backend/alembic/versions/9ce623009955_added_new_node_type_user_input.py 14-13-41-620.py index 944c54c..6a57a2b 100644 --- a/backend/alembic/versions/9ce623009955_added_new_node_type_user_input.py 14-13-41-620.py +++ b/backend/alembic/versions/9ce623009955_added_new_node_type_user_input.py 14-13-41-620.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/alembic/versions/a1b2c3d4e5f6_add_chat_initiation_messages.py b/backend/alembic/versions/a1b2c3d4e5f6_add_chat_initiation_messages.py index 5d6e68e..deb593c 100644 --- a/backend/alembic/versions/a1b2c3d4e5f6_add_chat_initiation_messages.py +++ b/backend/alembic/versions/a1b2c3d4e5f6_add_chat_initiation_messages.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/alembic/versions/a8efc6b31aa8_merge_crm_and_chat_session_idx_heads.py b/backend/alembic/versions/a8efc6b31aa8_merge_crm_and_chat_session_idx_heads.py index a4448db..4b4db32 100644 --- a/backend/alembic/versions/a8efc6b31aa8_merge_crm_and_chat_session_idx_heads.py +++ b/backend/alembic/versions/a8efc6b31aa8_merge_crm_and_chat_session_idx_heads.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/alembic/versions/abc123456789_add_file_attachments_table.py b/backend/alembic/versions/abc123456789_add_file_attachments_table.py index d783c73..6d96a01 100644 --- a/backend/alembic/versions/abc123456789_add_file_attachments_table.py +++ b/backend/alembic/versions/abc123456789_add_file_attachments_table.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/alembic/versions/add_agent_ai_replies_toggle_001.py b/backend/alembic/versions/add_agent_ai_replies_toggle_001.py index 641e27b..9fdb61a 100644 --- a/backend/alembic/versions/add_agent_ai_replies_toggle_001.py +++ b/backend/alembic/versions/add_agent_ai_replies_toggle_001.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/alembic/versions/add_agent_guardrail_prompt_001.py b/backend/alembic/versions/add_agent_guardrail_prompt_001.py index 5579aca..d743830 100644 --- a/backend/alembic/versions/add_agent_guardrail_prompt_001.py +++ b/backend/alembic/versions/add_agent_guardrail_prompt_001.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/alembic/versions/add_agent_ticketing_toggle_001.py b/backend/alembic/versions/add_agent_ticketing_toggle_001.py index 8cfe5dc..f91695b 100644 --- a/backend/alembic/versions/add_agent_ticketing_toggle_001.py +++ b/backend/alembic/versions/add_agent_ticketing_toggle_001.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/alembic/versions/add_ai_disclaimer_toggle_001.py b/backend/alembic/versions/add_ai_disclaimer_toggle_001.py index 75eb913..7c8b11a 100644 --- a/backend/alembic/versions/add_ai_disclaimer_toggle_001.py +++ b/backend/alembic/versions/add_ai_disclaimer_toggle_001.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/alembic/versions/add_allow_attachments_001.py b/backend/alembic/versions/add_allow_attachments_001.py index f5dae0f..398d50f 100644 --- a/backend/alembic/versions/add_allow_attachments_001.py +++ b/backend/alembic/versions/add_allow_attachments_001.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/alembic/versions/add_allow_new_chat_001.py b/backend/alembic/versions/add_allow_new_chat_001.py index 236036b..da75b0d 100644 --- a/backend/alembic/versions/add_allow_new_chat_001.py +++ b/backend/alembic/versions/add_allow_new_chat_001.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/alembic/versions/add_allowed_attachment_types_001.py b/backend/alembic/versions/add_allowed_attachment_types_001.py index 91f8114..f365ad6 100644 --- a/backend/alembic/versions/add_allowed_attachment_types_001.py +++ b/backend/alembic/versions/add_allowed_attachment_types_001.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/alembic/versions/add_channel_tables_001.py b/backend/alembic/versions/add_channel_tables_001.py index 457b404..326f733 100644 --- a/backend/alembic/versions/add_channel_tables_001.py +++ b/backend/alembic/versions/add_channel_tables_001.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/alembic/versions/add_chat_session_idx_001.py b/backend/alembic/versions/add_chat_session_idx_001.py index 9ec498c..ff7270d 100644 --- a/backend/alembic/versions/add_chat_session_idx_001.py +++ b/backend/alembic/versions/add_chat_session_idx_001.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/alembic/versions/add_crm_customer_syncs_001.py b/backend/alembic/versions/add_crm_customer_syncs_001.py index b280395..b4cc775 100644 --- a/backend/alembic/versions/add_crm_customer_syncs_001.py +++ b/backend/alembic/versions/add_crm_customer_syncs_001.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/alembic/versions/add_crm_tables_001_add_crm_tables.py b/backend/alembic/versions/add_crm_tables_001_add_crm_tables.py index 266f9b3..b287cf9 100644 --- a/backend/alembic/versions/add_crm_tables_001_add_crm_tables.py +++ b/backend/alembic/versions/add_crm_tables_001_add_crm_tables.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/alembic/versions/add_customer_phone_001_add_customer_phone.py b/backend/alembic/versions/add_customer_phone_001_add_customer_phone.py index 95ad381..ea9328f 100644 --- a/backend/alembic/versions/add_customer_phone_001_add_customer_phone.py +++ b/backend/alembic/versions/add_customer_phone_001_add_customer_phone.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/alembic/versions/add_guardrails_layer_001.py b/backend/alembic/versions/add_guardrails_layer_001.py index c1257b5..b56d589 100644 --- a/backend/alembic/versions/add_guardrails_layer_001.py +++ b/backend/alembic/versions/add_guardrails_layer_001.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/alembic/versions/add_hc_faq_feedback_001_add_faq_feedback.py b/backend/alembic/versions/add_hc_faq_feedback_001_add_faq_feedback.py index 78a8572..076bb87 100644 --- a/backend/alembic/versions/add_hc_faq_feedback_001_add_faq_feedback.py +++ b/backend/alembic/versions/add_hc_faq_feedback_001_add_faq_feedback.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/alembic/versions/add_hc_job_meter_001_add_job_metering.py b/backend/alembic/versions/add_hc_job_meter_001_add_job_metering.py index e5f9299..96e205e 100644 --- a/backend/alembic/versions/add_hc_job_meter_001_add_job_metering.py +++ b/backend/alembic/versions/add_hc_job_meter_001_add_job_metering.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/alembic/versions/add_invest_glassbox_001_add_glassbox.py b/backend/alembic/versions/add_invest_glassbox_001_add_glassbox.py index 29f7a73..699ee3e 100644 --- a/backend/alembic/versions/add_invest_glassbox_001_add_glassbox.py +++ b/backend/alembic/versions/add_invest_glassbox_001_add_glassbox.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/alembic/versions/add_investigation_runs_001_add_runs.py b/backend/alembic/versions/add_investigation_runs_001_add_runs.py index 7b7518d..2de189f 100644 --- a/backend/alembic/versions/add_investigation_runs_001_add_runs.py +++ b/backend/alembic/versions/add_investigation_runs_001_add_runs.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/alembic/versions/add_mcp_usage_guidance_001.py b/backend/alembic/versions/add_mcp_usage_guidance_001.py index ee55bb0..fae6f1c 100644 --- a/backend/alembic/versions/add_mcp_usage_guidance_001.py +++ b/backend/alembic/versions/add_mcp_usage_guidance_001.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/alembic/versions/add_notif_prefs_001_user_notification_settings.py b/backend/alembic/versions/add_notif_prefs_001_user_notification_settings.py index 9ac359f..a62720d 100644 --- a/backend/alembic/versions/add_notif_prefs_001_user_notification_settings.py +++ b/backend/alembic/versions/add_notif_prefs_001_user_notification_settings.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/alembic/versions/add_openai_compat_ai_model_001.py b/backend/alembic/versions/add_openai_compat_ai_model_001.py index 7450dd9..6e9fb29 100644 --- a/backend/alembic/versions/add_openai_compat_ai_model_001.py +++ b/backend/alembic/versions/add_openai_compat_ai_model_001.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/alembic/versions/add_require_token_auth_001.py b/backend/alembic/versions/add_require_token_auth_001.py index aac161e..9d3a186 100644 --- a/backend/alembic/versions/add_require_token_auth_001.py +++ b/backend/alembic/versions/add_require_token_auth_001.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/alembic/versions/add_run_connector_status_001.py b/backend/alembic/versions/add_run_connector_status_001.py index 363077d..9650d50 100644 --- a/backend/alembic/versions/add_run_connector_status_001.py +++ b/backend/alembic/versions/add_run_connector_status_001.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/alembic/versions/add_sentiment_analysis_001.py b/backend/alembic/versions/add_sentiment_analysis_001.py index 458be61..0cea794 100644 --- a/backend/alembic/versions/add_sentiment_analysis_001.py +++ b/backend/alembic/versions/add_sentiment_analysis_001.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/alembic/versions/add_slack_integration_001.py b/backend/alembic/versions/add_slack_integration_001.py index 1e4c456..7ab8933 100644 --- a/backend/alembic/versions/add_slack_integration_001.py +++ b/backend/alembic/versions/add_slack_integration_001.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/alembic/versions/add_ticketing_core_001_add_native_ticketing.py b/backend/alembic/versions/add_ticketing_core_001_add_native_ticketing.py index e23a2a7..cdbf816 100644 --- a/backend/alembic/versions/add_ticketing_core_001_add_native_ticketing.py +++ b/backend/alembic/versions/add_ticketing_core_001_add_native_ticketing.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/alembic/versions/add_tkt_db_ssh_001_add_ssh.py b/backend/alembic/versions/add_tkt_db_ssh_001_add_ssh.py index 98acdd8..2139f7c 100644 --- a/backend/alembic/versions/add_tkt_db_ssh_001_add_ssh.py +++ b/backend/alembic/versions/add_tkt_db_ssh_001_add_ssh.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/alembic/versions/add_tkt_phase4_001_add_phase4.py b/backend/alembic/versions/add_tkt_phase4_001_add_phase4.py index bdd0734..9057344 100644 --- a/backend/alembic/versions/add_tkt_phase4_001_add_phase4.py +++ b/backend/alembic/versions/add_tkt_phase4_001_add_phase4.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/alembic/versions/add_widget_apps_001.py b/backend/alembic/versions/add_widget_apps_001.py index c75ab00..7f613a8 100644 --- a/backend/alembic/versions/add_widget_apps_001.py +++ b/backend/alembic/versions/add_widget_apps_001.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/alembic/versions/b2c3d4e5f6a7_add_customer_meta_data.py b/backend/alembic/versions/b2c3d4e5f6a7_add_customer_meta_data.py index bcf6ddb..3e78b21 100644 --- a/backend/alembic/versions/b2c3d4e5f6a7_add_customer_meta_data.py +++ b/backend/alembic/versions/b2c3d4e5f6a7_add_customer_meta_data.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/alembic/versions/b365b8447598_initial_version.py b/backend/alembic/versions/b365b8447598_initial_version.py index 7166fa2..4f212a7 100644 --- a/backend/alembic/versions/b365b8447598_initial_version.py +++ b/backend/alembic/versions/b365b8447598_initial_version.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/alembic/versions/b7c4e91a2d38_add_agent_queue_and_people_permissions.py b/backend/alembic/versions/b7c4e91a2d38_add_agent_queue_and_people_permissions.py index 13e3c64..dbe2da6 100644 --- a/backend/alembic/versions/b7c4e91a2d38_add_agent_queue_and_people_permissions.py +++ b/backend/alembic/versions/b7c4e91a2d38_add_agent_queue_and_people_permissions.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/alembic/versions/bdaa7a5d6109_removed_node_specific_fields.py b/backend/alembic/versions/bdaa7a5d6109_removed_node_specific_fields.py index effede0..fda661e 100644 --- a/backend/alembic/versions/bdaa7a5d6109_removed_node_specific_fields.py +++ b/backend/alembic/versions/bdaa7a5d6109_removed_node_specific_fields.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/alembic/versions/c1d2e3f4a5b6_add_premium_chat_styles_and_show_citations.py b/backend/alembic/versions/c1d2e3f4a5b6_add_premium_chat_styles_and_show_citations.py index db368cb..5918491 100644 --- a/backend/alembic/versions/c1d2e3f4a5b6_add_premium_chat_styles_and_show_citations.py +++ b/backend/alembic/versions/c1d2e3f4a5b6_add_premium_chat_styles_and_show_citations.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/alembic/versions/c3d4e5f6a7b8_add_lead_capture.py b/backend/alembic/versions/c3d4e5f6a7b8_add_lead_capture.py index 25c56c2..8b15aad 100644 --- a/backend/alembic/versions/c3d4e5f6a7b8_add_lead_capture.py +++ b/backend/alembic/versions/c3d4e5f6a7b8_add_lead_capture.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/alembic/versions/crm_sync_varchar_001_crm_target_varchar.py b/backend/alembic/versions/crm_sync_varchar_001_crm_target_varchar.py index b55921b..0587eac 100644 --- a/backend/alembic/versions/crm_sync_varchar_001_crm_target_varchar.py +++ b/backend/alembic/versions/crm_sync_varchar_001_crm_target_varchar.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/alembic/versions/d2e3f4a5b6c7_add_contact_collection_columns.py b/backend/alembic/versions/d2e3f4a5b6c7_add_contact_collection_columns.py index a70b177..8e3a551 100644 --- a/backend/alembic/versions/d2e3f4a5b6c7_add_contact_collection_columns.py +++ b/backend/alembic/versions/d2e3f4a5b6c7_add_contact_collection_columns.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/alembic/versions/d9a4b9902f80_add_attempts_to_otp_table.py b/backend/alembic/versions/d9a4b9902f80_add_attempts_to_otp_table.py index e61a317..ef0a854 100644 --- a/backend/alembic/versions/d9a4b9902f80_add_attempts_to_otp_table.py +++ b/backend/alembic/versions/d9a4b9902f80_add_attempts_to_otp_table.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/alembic/versions/dc827ab30bd4_add_progress_tracking_to_knowledge_queue.py b/backend/alembic/versions/dc827ab30bd4_add_progress_tracking_to_knowledge_queue.py index e1dc6bf..eb8842f 100644 --- a/backend/alembic/versions/dc827ab30bd4_add_progress_tracking_to_knowledge_queue.py +++ b/backend/alembic/versions/dc827ab30bd4_add_progress_tracking_to_knowledge_queue.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/alembic/versions/dd0e5ceefe4b_added_new_node_type.py b/backend/alembic/versions/dd0e5ceefe4b_added_new_node_type.py index c931e01..8958952 100644 --- a/backend/alembic/versions/dd0e5ceefe4b_added_new_node_type.py +++ b/backend/alembic/versions/dd0e5ceefe4b_added_new_node_type.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/alembic/versions/drop_slack_tables_001.py b/backend/alembic/versions/drop_slack_tables_001.py index fce7375..3b3e149 100644 --- a/backend/alembic/versions/drop_slack_tables_001.py +++ b/backend/alembic/versions/drop_slack_tables_001.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/alembic/versions/e252efacd083_agent_createddate_added.py b/backend/alembic/versions/e252efacd083_agent_createddate_added.py index 49830d3..6ea6eae 100644 --- a/backend/alembic/versions/e252efacd083_agent_createddate_added.py +++ b/backend/alembic/versions/e252efacd083_agent_createddate_added.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/alembic/versions/e3f4a5b6c7d8_add_aurora_chat_style.py b/backend/alembic/versions/e3f4a5b6c7d8_add_aurora_chat_style.py index b593052..6ba7196 100644 --- a/backend/alembic/versions/e3f4a5b6c7d8_add_aurora_chat_style.py +++ b/backend/alembic/versions/e3f4a5b6c7d8_add_aurora_chat_style.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/alembic/versions/e65e1b8e7e3c_add_jira_agent_config.py b/backend/alembic/versions/e65e1b8e7e3c_add_jira_agent_config.py index 561d4ae..91e17ec 100644 --- a/backend/alembic/versions/e65e1b8e7e3c_add_jira_agent_config.py +++ b/backend/alembic/versions/e65e1b8e7e3c_add_jira_agent_config.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/alembic/versions/f3dad24474e0_add_rate_limiting_fields_to_agent_model.py b/backend/alembic/versions/f3dad24474e0_add_rate_limiting_fields_to_agent_model.py index 627fb09..11450da 100644 --- a/backend/alembic/versions/f3dad24474e0_add_rate_limiting_fields_to_agent_model.py +++ b/backend/alembic/versions/f3dad24474e0_add_rate_limiting_fields_to_agent_model.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/alembic/versions/f4a5b6c7d8e9_add_sunrise_style_and_quick_actions.py b/backend/alembic/versions/f4a5b6c7d8e9_add_sunrise_style_and_quick_actions.py index 1ebc574..e13a4fa 100644 --- a/backend/alembic/versions/f4a5b6c7d8e9_add_sunrise_style_and_quick_actions.py +++ b/backend/alembic/versions/f4a5b6c7d8e9_add_sunrise_style_and_quick_actions.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/alembic/versions/f7a1c2d3e4b5_add_faq_help_center.py b/backend/alembic/versions/f7a1c2d3e4b5_add_faq_help_center.py index 653ad3e..35b3644 100644 --- a/backend/alembic/versions/f7a1c2d3e4b5_add_faq_help_center.py +++ b/backend/alembic/versions/f7a1c2d3e4b5_add_faq_help_center.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -21,7 +21,7 @@ Revises: drop_slack_tables_001 Create Date: 2026-07-12 New feature: AI-generated FAQs reviewed/published by the org and served as a -public help center on {slug}.chattermate.help or a verified custom domain. +public help center on {slug}.help.replypier.site or a verified custom domain. Tables: - faq_generation_jobs: async generate/import jobs (worker + UI polling) diff --git a/backend/alembic/versions/fa04f644fc0c_added_user_id_in_rating_table.py b/backend/alembic/versions/fa04f644fc0c_added_user_id_in_rating_table.py index cc75ccb..b3b338f 100644 --- a/backend/alembic/versions/fa04f644fc0c_added_user_id_in_rating_table.py +++ b/backend/alembic/versions/fa04f644fc0c_added_user_id_in_rating_table.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/alembic/versions/fcm_tokens_per_device_001.py b/backend/alembic/versions/fcm_tokens_per_device_001.py index 81a2ab6..b89b5fd 100644 --- a/backend/alembic/versions/fcm_tokens_per_device_001.py +++ b/backend/alembic/versions/fcm_tokens_per_device_001.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/alembic/versions/ff48f854bcbf_add_ticket_fields_to_session.py b/backend/alembic/versions/ff48f854bcbf_add_ticket_fields_to_session.py index ae866aa..0e56da0 100644 --- a/backend/alembic/versions/ff48f854bcbf_add_ticket_fields_to_session.py +++ b/backend/alembic/versions/ff48f854bcbf_add_ticket_fields_to_session.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/alembic/versions/merge_hc_url_path_001.py b/backend/alembic/versions/merge_hc_url_path_001.py index 26b73bb..64d3f9a 100644 --- a/backend/alembic/versions/merge_hc_url_path_001.py +++ b/backend/alembic/versions/merge_hc_url_path_001.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/alembic/versions/merge_tkt_csat_001.py b/backend/alembic/versions/merge_tkt_csat_001.py index a22fdd1..ee8978d 100644 --- a/backend/alembic/versions/merge_tkt_csat_001.py +++ b/backend/alembic/versions/merge_tkt_csat_001.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/alembic/versions/merge_tkt_phone_001.py b/backend/alembic/versions/merge_tkt_phone_001.py index a5820cd..dfc2961 100644 --- a/backend/alembic/versions/merge_tkt_phone_001.py +++ b/backend/alembic/versions/merge_tkt_phone_001.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/alembic/versions/normalise_upload_prefix_001.py b/backend/alembic/versions/normalise_upload_prefix_001.py index b89dec0..063ba53 100644 --- a/backend/alembic/versions/normalise_upload_prefix_001.py +++ b/backend/alembic/versions/normalise_upload_prefix_001.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/alembic/versions/purge_mangled_crawl_pages_001.py b/backend/alembic/versions/purge_mangled_crawl_pages_001.py index b2f1c40..f0c3e32 100644 --- a/backend/alembic/versions/purge_mangled_crawl_pages_001.py +++ b/backend/alembic/versions/purge_mangled_crawl_pages_001.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/alembic/versions/repair_agent_role_seed_001.py b/backend/alembic/versions/repair_agent_role_seed_001.py index 7206e13..7ed15c8 100644 --- a/backend/alembic/versions/repair_agent_role_seed_001.py +++ b/backend/alembic/versions/repair_agent_role_seed_001.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/alembic/versions/replypier_ai_model_001_carry_managed_model_label.py b/backend/alembic/versions/replypier_ai_model_001_carry_managed_model_label.py new file mode 100644 index 0000000..5f32a5e --- /dev/null +++ b/backend/alembic/versions/replypier_ai_model_001_carry_managed_model_label.py @@ -0,0 +1,67 @@ +""" +Copyright 2024-2026 ReplyPier + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +""" + +"""Carry the managed AI-model enum value onto its renamed label + +Revision ID: replypier_ai_model_001 +Revises: widget_key_lookup_001 +Create Date: 2026-10-26 00:00:00.000000 + +The brand rename changed ``AIModelType``'s managed-provider member. Databases +created before the rename carry the old label in the ``aimodeltype`` type and in +``ai_configs`` rows, so: + +1. add the new label to the type (a no-op on a database created after it), and +2. rewrite rows that still point at the old label. + +Fresh databases created from the rewritten ``520df92643e3`` migration never see +the old label; both statements are then no-ops. +""" +from typing import Sequence, Union + +from alembic import op + +# revision identifiers, used by Alembic. +revision: str = 'replypier_ai_model_001' +down_revision: Union[str, None] = 'widget_key_lookup_001' +branch_labels: Union[str, Sequence[str], None] = None +depends_on: Union[str, Sequence[str], None] = None + +# The managed-provider value this project used before the rename. Kept only so +# pre-rename rows can be found; nothing reads it at runtime. +LEGACY_MANAGED_VALUE = 'CHATTERMATE' +MANAGED_VALUE = 'REPLYPIER' + + +def upgrade() -> None: + # ADD VALUE cannot be used in the same transaction that references the new + # label, so it runs in its own autocommit block. + with op.get_context().autocommit_block(): + op.execute( + f"ALTER TYPE aimodeltype ADD VALUE IF NOT EXISTS '{MANAGED_VALUE}'" + ) + op.execute( + f"UPDATE ai_configs SET model_type = '{MANAGED_VALUE}' " + f"WHERE model_type::text = '{LEGACY_MANAGED_VALUE}'" + ) + + +def downgrade() -> None: + # PostgreSQL cannot drop an enum value; the data rewrite is reversible. + op.execute( + f"UPDATE ai_configs SET model_type = '{LEGACY_MANAGED_VALUE}' " + f"WHERE model_type::text = '{MANAGED_VALUE}'" + ) diff --git a/backend/app/__init__.py b/backend/app/__init__.py index 98c32de..f539b43 100644 --- a/backend/app/__init__.py +++ b/backend/app/__init__.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/app/agents/chat_agent.py b/backend/app/agents/chat_agent.py index 3c6017e..de1023f 100644 --- a/backend/app/agents/chat_agent.py +++ b/backend/app/agents/chat_agent.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/app/agents/choice_prompt.py b/backend/app/agents/choice_prompt.py index dcaa0ce..0160922 100644 --- a/backend/app/agents/choice_prompt.py +++ b/backend/app/agents/choice_prompt.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/app/agents/encrypted_storage.py b/backend/app/agents/encrypted_storage.py index beb5633..1d5a372 100644 --- a/backend/app/agents/encrypted_storage.py +++ b/backend/app/agents/encrypted_storage.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/app/agents/faq_generator.py b/backend/app/agents/faq_generator.py index 13b8bd7..3369073 100644 --- a/backend/app/agents/faq_generator.py +++ b/backend/app/agents/faq_generator.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/app/agents/guardrail_policy.py b/backend/app/agents/guardrail_policy.py index 0e64395..af83879 100644 --- a/backend/app/agents/guardrail_policy.py +++ b/backend/app/agents/guardrail_policy.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/app/agents/history_memory.py b/backend/app/agents/history_memory.py index 9a8e28f..b1b3fd6 100644 --- a/backend/app/agents/history_memory.py +++ b/backend/app/agents/history_memory.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/app/agents/structured_output.py b/backend/app/agents/structured_output.py index 3f508e9..c649f50 100644 --- a/backend/app/agents/structured_output.py +++ b/backend/app/agents/structured_output.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/app/agents/ticket_investigator.py b/backend/app/agents/ticket_investigator.py index 63e36ef..c9bcbce 100644 --- a/backend/app/agents/ticket_investigator.py +++ b/backend/app/agents/ticket_investigator.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/app/agents/transfer_agent.py b/backend/app/agents/transfer_agent.py index 749a6d8..daec73a 100644 --- a/backend/app/agents/transfer_agent.py +++ b/backend/app/agents/transfer_agent.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/app/api/__init__.py b/backend/app/api/__init__.py index e643879..563a34a 100644 --- a/backend/app/api/__init__.py +++ b/backend/app/api/__init__.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/app/api/agent.py b/backend/app/api/agent.py index 13d9982..45c5290 100644 --- a/backend/app/api/agent.py +++ b/backend/app/api/agent.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -723,23 +723,23 @@ async def generate_instructions( except ImportError: HAS_ENTERPRISE = False - # Get API key and model - first check for ChatterMate config if enterprise is available + # Get API key and model - first check for ReplyPier config if enterprise is available api_key = "" model_name = "" model_type = "" base_url = None if HAS_ENTERPRISE: - # Use Groq/OpenAI with keys from env for ChatterMate model + # Use Groq/OpenAI with keys from env for ReplyPier model model_type = 'OPENAI' - model_name = os.getenv('CHATTERMATE_MODEL_NAME', 'gpt-4o-mini') - api_key = os.getenv('CHATTERMATE_API_KEY', '') + model_name = os.getenv('REPLYPIER_MODEL_NAME', 'gpt-4o-mini') + api_key = os.getenv('REPLYPIER_API_KEY', '') if not api_key: - logger.error("ChatterMate API key not found in environment") + logger.error("ReplyPier API key not found in environment") raise HTTPException( status_code=500, - detail="ChatterMate API configuration missing" + detail="ReplyPier API configuration missing" ) else: # Get from organization's AI config diff --git a/backend/app/api/ai_setup.py b/backend/app/api/ai_setup.py index 08af17a..dfec029 100644 --- a/backend/app/api/ai_setup.py +++ b/backend/app/api/ai_setup.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -102,25 +102,25 @@ async def setup_ai( # Validate model selection based on provider validate_model_selection(config_data.model_type, config_data.model_name) - # Check if this is a custom model setup (not ChatterMate) - is_custom_model = not (config_data.model_type.lower() == 'chattermate' and config_data.model_name.lower() == 'chattermate') + # Check if this is a custom model setup (not ReplyPier) + is_custom_model = not (config_data.model_type.lower() == 'replypier' and config_data.model_name.lower() == 'replypier') # Check feature access for custom models if is_custom_model: check_custom_models_feature_access(current_user, db) - # Check if using ChatterMate model - if HAS_ENTERPRISE and config_data.model_type.lower() == 'chattermate' and config_data.model_name.lower() == 'chattermate': + # Check if using ReplyPier model + if HAS_ENTERPRISE and config_data.model_type.lower() == 'replypier' and config_data.model_name.lower() == 'replypier': # Use Groq as provider with keys from env - model_type = AIModelType.CHATTERMATE - model_name = os.getenv('CHATTERMATE_MODEL_NAME', 'gpt-4o-mini') - api_key = os.getenv('CHATTERMATE_API_KEY', '') + model_type = AIModelType.REPLYPIER + model_name = os.getenv('REPLYPIER_MODEL_NAME', 'gpt-4o-mini') + api_key = os.getenv('REPLYPIER_API_KEY', '') if not api_key: - logger.error("ChatterMate API key not found in environment") + logger.error("ReplyPier API key not found in environment") raise HTTPException( status_code=500, - detail="ChatterMate API configuration missing" + detail="ReplyPier API configuration missing" ) # Create AI configuration @@ -146,7 +146,7 @@ async def setup_ai( ) logger.debug( - f"ChatterMate AI setup completed for org {current_user.organization_id}") + f"ReplyPier AI setup completed for org {current_user.organization_id}") return response # Regular custom model setup @@ -281,8 +281,8 @@ async def update_ai_config( # Validate model selection based on provider validate_model_selection(config_data.model_type, config_data.model_name) - # Check if this is a custom model setup (not ChatterMate) - is_custom_model = not (config_data.model_type.lower() == 'chattermate' and config_data.model_name.lower() == 'chattermate') + # Check if this is a custom model setup (not ReplyPier) + is_custom_model = not (config_data.model_type.lower() == 'replypier' and config_data.model_name.lower() == 'replypier') # Check feature access for custom models if is_custom_model: @@ -298,18 +298,18 @@ async def update_ai_config( detail="No active AI configuration found to update" ) - # Check if using ChatterMate model - if HAS_ENTERPRISE and config_data.model_type.lower() == 'chattermate' and config_data.model_name.lower() == 'chattermate': + # Check if using ReplyPier model + if HAS_ENTERPRISE and config_data.model_type.lower() == 'replypier' and config_data.model_name.lower() == 'replypier': # Use Groq as provider with keys from env - model_type = AIModelType.CHATTERMATE - model_name = os.getenv('CHATTERMATE_MODEL_NAME', 'gpt-4o-mini') - api_key = os.getenv('CHATTERMATE_API_KEY', '') + model_type = AIModelType.REPLYPIER + model_name = os.getenv('REPLYPIER_MODEL_NAME', 'gpt-4o-mini') + api_key = os.getenv('REPLYPIER_API_KEY', '') if not api_key: - logger.error("ChatterMate API key not found in environment") + logger.error("ReplyPier API key not found in environment") raise HTTPException( status_code=500, - detail="ChatterMate API configuration missing" + detail="ReplyPier API configuration missing" ) # Update AI configuration @@ -320,7 +320,7 @@ async def update_ai_config( api_key=api_key ) - logger.info(f"ChatterMate AI config updated for org {current_user.organization_id}") + logger.info(f"ReplyPier AI config updated for org {current_user.organization_id}") else: # For custom model, validate API key and/or base_url first if either is # changing in this request. @@ -429,8 +429,8 @@ def validate_model_selection(model_type: str, model_name: str): is what actually rejects a bad model ID. """ - # ChatterMate is a special case handled separately - if model_type.upper() == "CHATTERMATE" and model_name.lower() == "chattermate": + # ReplyPier is a special case handled separately + if model_type.upper() == "REPLYPIER" and model_name.lower() == "replypier": return True if not is_known_provider(model_type): diff --git a/backend/app/api/analytics.py b/backend/app/api/analytics.py index 2904567..d9b0454 100644 --- a/backend/app/api/analytics.py +++ b/backend/app/api/analytics.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/app/api/channels/__init__.py b/backend/app/api/channels/__init__.py index f6190b6..5afb026 100644 --- a/backend/app/api/channels/__init__.py +++ b/backend/app/api/channels/__init__.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/app/api/channels/accounts.py b/backend/app/api/channels/accounts.py index f50f992..2d20fad 100644 --- a/backend/app/api/channels/accounts.py +++ b/backend/app/api/channels/accounts.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/app/api/channels/agent_config.py b/backend/app/api/channels/agent_config.py index 360f51e..f67ea8c 100644 --- a/backend/app/api/channels/agent_config.py +++ b/backend/app/api/channels/agent_config.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/app/api/channels/email.py b/backend/app/api/channels/email.py index 0e9ec91..6621147 100644 --- a/backend/app/api/channels/email.py +++ b/backend/app/api/channels/email.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/app/api/channels/line.py b/backend/app/api/channels/line.py index eb24e88..86e17aa 100644 --- a/backend/app/api/channels/line.py +++ b/backend/app/api/channels/line.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/app/api/channels/meta.py b/backend/app/api/channels/meta.py index c2dfda0..ddd0315 100644 --- a/backend/app/api/channels/meta.py +++ b/backend/app/api/channels/meta.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -302,7 +302,7 @@ def _upsert_account(db: Session, organization: Organization, channel_type: str, forget: tuple = ()): """Create the account or refresh credentials on reconnect (same org only). `forget` names stored credentials that no longer apply (an app secret, - once the account is connected through ChatterMate's own app).""" + once the account is connected through ReplyPier's own app).""" repo = ChannelAccountRepository(db) existing = repo.get_by_external_id(channel_type, external_account_id) if existing is not None: @@ -542,7 +542,7 @@ async def list_messenger_signup_pages( pages = await _list_manageable_pages(user_token, "id,name,access_token") if not pages: raise HTTPException(status_code=400, detail=( - "No Facebook Pages were shared with ChatterMate. Run the connect " + "No Facebook Pages were shared with ReplyPier. Run the connect " "again and tick the Page you want to use.")) return MessengerSignupPagesOut( diff --git a/backend/app/api/channels/slack.py b/backend/app/api/channels/slack.py index b2ff4f6..d5cd9fb 100644 --- a/backend/app/api/channels/slack.py +++ b/backend/app/api/channels/slack.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/app/api/channels/sms.py b/backend/app/api/channels/sms.py index 886eba4..ae6a477 100644 --- a/backend/app/api/channels/sms.py +++ b/backend/app/api/channels/sms.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/app/api/channels/telegram.py b/backend/app/api/channels/telegram.py index 6009978..ea1fb52 100644 --- a/backend/app/api/channels/telegram.py +++ b/backend/app/api/channels/telegram.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/app/api/channels/whatsapp_messaging.py b/backend/app/api/channels/whatsapp_messaging.py index 0397fe4..9ef2a85 100644 --- a/backend/app/api/channels/whatsapp_messaging.py +++ b/backend/app/api/channels/whatsapp_messaging.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/app/api/chat.py b/backend/app/api/chat.py index a37737e..34ca721 100644 --- a/backend/app/api/chat.py +++ b/backend/app/api/chat.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/app/api/crm.py b/backend/app/api/crm.py index a38b8b5..fa47192 100644 --- a/backend/app/api/crm.py +++ b/backend/app/api/crm.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/app/api/file_upload.py b/backend/app/api/file_upload.py index 74ed0be..817695c 100644 --- a/backend/app/api/file_upload.py +++ b/backend/app/api/file_upload.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/app/api/help_center/__init__.py b/backend/app/api/help_center/__init__.py index b73b8bc..b42f021 100644 --- a/backend/app/api/help_center/__init__.py +++ b/backend/app/api/help_center/__init__.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/app/api/help_center/branding.py b/backend/app/api/help_center/branding.py index ed01850..91bdd01 100644 --- a/backend/app/api/help_center/branding.py +++ b/backend/app/api/help_center/branding.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -75,8 +75,8 @@ def domain_status_response(row: HelpCenterSettings) -> DomainStatusResponse: ), DnsRecord( type="TXT", - host=f"_chattermate.{row.custom_domain}", - value=f"cm-verify={row.domain_verification_token}", + host=f"_replypier.{row.custom_domain}", + value=f"rp-verify={row.domain_verification_token}", verified=row.txt_record_verified, ), ] @@ -100,7 +100,7 @@ async def settings_response( .all() ) response = HelpCenterSettingsResponse.model_validate(row) - # Absolute (api-origin) URL: the admin runs on app.chattermate.chat, whose + # Absolute (api-origin) URL: the admin runs on app.replypier.site, whose # nginx serves any *.png path as a static asset — a host-relative # /api/v1/uploads/*.png would 404 there. Anchor to the backend origin. response.logo_url = ( diff --git a/backend/app/api/help_center/domain.py b/backend/app/api/help_center/domain.py index 10d6da4..e10c91b 100644 --- a/backend/app/api/help_center/domain.py +++ b/backend/app/api/help_center/domain.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/app/api/help_center/faqs.py b/backend/app/api/help_center/faqs.py index 155d9be..8995df2 100644 --- a/backend/app/api/help_center/faqs.py +++ b/backend/app/api/help_center/faqs.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/app/api/help_center/generation.py b/backend/app/api/help_center/generation.py index 5b30c47..413f37c 100644 --- a/backend/app/api/help_center/generation.py +++ b/backend/app/api/help_center/generation.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/app/api/help_center_images.py b/backend/app/api/help_center_images.py index e8032f7..fc96be2 100644 --- a/backend/app/api/help_center_images.py +++ b/backend/app/api/help_center_images.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/app/api/help_center_public.py b/backend/app/api/help_center_public.py index 1b056ac..5e769f2 100644 --- a/backend/app/api/help_center_public.py +++ b/backend/app/api/help_center_public.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -74,7 +74,7 @@ from app.services.help_center_seo import ( ) from app.services.public_rate_limit import allow_request -public_app = FastAPI(title="ChatterMate Help Center", docs_url=None, redoc_url=None, openapi_url=None) +public_app = FastAPI(title="ReplyPier Help Center", docs_url=None, redoc_url=None, openapi_url=None) install_error_handlers(public_app) # Serve ONLY help-center images on this app, so relative logo/article-image paths # resolve on a subdomain/custom-domain origin (host dispatch). Scoped to the @@ -154,11 +154,11 @@ async def _chrome_context(row: HelpCenterSettings, base_path: str = "") -> dict: "favicon_url": await resolve_public_url(row.favicon_url) if row.favicon_url else None, "header_links": row.header_links or [], "widget_id": widget_id_for(row), - # The widget LOADER (chattermate.min.js) is served by the frontend, while + # The widget LOADER (replypier.min.js) is served by the frontend, while # the widget APP it pulls in (/assets/widget.js) is served from # VITE_WIDGET_URL by the backend. In prod both resolve to the app domain. - "widget_script_url": f"{settings.FRONTEND_URL}/webclient/chattermate.min.js", - # This install's API root, handed to the loader as window.chattermateBaseUrl + "widget_script_url": f"{settings.FRONTEND_URL}/webclient/replypier.min.js", + # This install's API root, handed to the loader as window.replypierBaseUrl # (same contract as the dashboard's embed snippet). Without it the loader # uses its build-time default — the vendor cloud — which no self-hosted # deployment can talk to. diff --git a/backend/app/api/jira.py b/backend/app/api/jira.py index a9dab0b..7ce36bb 100644 --- a/backend/app/api/jira.py +++ b/backend/app/api/jira.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/app/api/knowledge.py b/backend/app/api/knowledge.py index 1282009..89fca15 100644 --- a/backend/app/api/knowledge.py +++ b/backend/app/api/knowledge.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/app/api/lead_capture.py b/backend/app/api/lead_capture.py index 8cccd81..60077ae 100644 --- a/backend/app/api/lead_capture.py +++ b/backend/app/api/lead_capture.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/app/api/mcp_tool.py b/backend/app/api/mcp_tool.py index 680c8dc..4c2852b 100644 --- a/backend/app/api/mcp_tool.py +++ b/backend/app/api/mcp_tool.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/app/api/notification.py b/backend/app/api/notification.py index d54b9ab..340e743 100644 --- a/backend/app/api/notification.py +++ b/backend/app/api/notification.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -262,7 +262,7 @@ async def send_test_notification( user_id=current_user.id, type="CHAT", title="Test Notification", - message="This is a test notification from ChatterMate", + message="This is a test notification from ReplyPier", notification_metadata={"test": True} ) db.add(notification) diff --git a/backend/app/api/organizations.py b/backend/app/api/organizations.py index 0c8388a..a04b07d 100644 --- a/backend/app/api/organizations.py +++ b/backend/app/api/organizations.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/app/api/people.py b/backend/app/api/people.py index 699b584..5d4c266 100644 --- a/backend/app/api/people.py +++ b/backend/app/api/people.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/app/api/roles.py b/backend/app/api/roles.py index ca9c767..cd24e6c 100644 --- a/backend/app/api/roles.py +++ b/backend/app/api/roles.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/app/api/session_to_agent.py b/backend/app/api/session_to_agent.py index 75090d2..72844ce 100644 --- a/backend/app/api/session_to_agent.py +++ b/backend/app/api/session_to_agent.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/app/api/shopify.py b/backend/app/api/shopify.py index e3adb28..e3901e7 100644 --- a/backend/app/api/shopify.py +++ b/backend/app/api/shopify.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/app/api/ticket_db_connectors.py b/backend/app/api/ticket_db_connectors.py index a6760c6..ba26e9c 100644 --- a/backend/app/api/ticket_db_connectors.py +++ b/backend/app/api/ticket_db_connectors.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/app/api/ticket_webhooks.py b/backend/app/api/ticket_webhooks.py index a271333..769ca3c 100644 --- a/backend/app/api/ticket_webhooks.py +++ b/backend/app/api/ticket_webhooks.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/app/api/tickets.py b/backend/app/api/tickets.py index ccfab3e..47614b9 100644 --- a/backend/app/api/tickets.py +++ b/backend/app/api/tickets.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -131,7 +131,7 @@ def _activity_out(activity) -> TicketActivityOut: if activity.actor_user is not None: out.actor_name = activity.actor_user.full_name elif str(activity.actor_type) == TicketActorType.AI.value: - out.actor_name = "ChatterMate AI" + out.actor_name = "ReplyPier AI" return out diff --git a/backend/app/api/token.py b/backend/app/api/token.py index 7fde044..f0a0ded 100644 --- a/backend/app/api/token.py +++ b/backend/app/api/token.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/app/api/user_groups.py b/backend/app/api/user_groups.py index e27a71a..58b69d4 100644 --- a/backend/app/api/user_groups.py +++ b/backend/app/api/user_groups.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/app/api/users.py b/backend/app/api/users.py index d92eb86..bca21c9 100644 --- a/backend/app/api/users.py +++ b/backend/app/api/users.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/app/api/webhooks/__init__.py b/backend/app/api/webhooks/__init__.py index 117b51e..537a374 100644 --- a/backend/app/api/webhooks/__init__.py +++ b/backend/app/api/webhooks/__init__.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/app/api/webhooks/common.py b/backend/app/api/webhooks/common.py index fbd550f..c207050 100644 --- a/backend/app/api/webhooks/common.py +++ b/backend/app/api/webhooks/common.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/app/api/webhooks/email.py b/backend/app/api/webhooks/email.py index 6a8e1e3..ac78718 100644 --- a/backend/app/api/webhooks/email.py +++ b/backend/app/api/webhooks/email.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/app/api/webhooks/line.py b/backend/app/api/webhooks/line.py index d8f912b..2bf3bbb 100644 --- a/backend/app/api/webhooks/line.py +++ b/backend/app/api/webhooks/line.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/app/api/webhooks/meta.py b/backend/app/api/webhooks/meta.py index f1e7a9d..8b08648 100644 --- a/backend/app/api/webhooks/meta.py +++ b/backend/app/api/webhooks/meta.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/app/api/webhooks/slack.py b/backend/app/api/webhooks/slack.py index e973f9f..552a8e1 100644 --- a/backend/app/api/webhooks/slack.py +++ b/backend/app/api/webhooks/slack.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/app/api/webhooks/sms.py b/backend/app/api/webhooks/sms.py index f6561be..4b6a4c0 100644 --- a/backend/app/api/webhooks/sms.py +++ b/backend/app/api/webhooks/sms.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/app/api/webhooks/telegram.py b/backend/app/api/webhooks/telegram.py index 8602f07..7483262 100644 --- a/backend/app/api/webhooks/telegram.py +++ b/backend/app/api/webhooks/telegram.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/app/api/widget.py b/backend/app/api/widget.py index 8641e95..5a1dd35 100644 --- a/backend/app/api/widget.py +++ b/backend/app/api/widget.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -154,7 +154,7 @@ def _widget_runtime_config(request: Optional[Request] = None) -> dict: Derived from ``BACKEND_URL`` so a self-hosted widget talks to the configured backend instead of the vendor cloud. On the hosted deployment BACKEND_URL is - ``https://api.chattermate.chat``, which yields exactly the widget's baked-in + ``https://api.replypier.site``, which yields exactly the widget's baked-in defaults, so injecting this is a no-op there. """ global _warned_about_loopback_backend_url diff --git a/backend/app/api/widget_apps.py b/backend/app/api/widget_apps.py index cf42271..333a1f1 100644 --- a/backend/app/api/widget_apps.py +++ b/backend/app/api/widget_apps.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/app/api/widget_chat.py b/backend/app/api/widget_chat.py index dc8762f..c3984ed 100644 --- a/backend/app/api/widget_chat.py +++ b/backend/app/api/widget_chat.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -262,7 +262,7 @@ async def widget_connect(sid, environ, auth): message_limit_reached = False # Check message limits if enterprise module is available - if HAS_ENTERPRISE and ai_config.model_type == AIModelType.CHATTERMATE: + if HAS_ENTERPRISE and ai_config.model_type == AIModelType.REPLYPIER: if not await check_message_limit(db, org_id, sid, sio): message_limit_reached = True diff --git a/backend/app/api/workflow.py b/backend/app/api/workflow.py index a23e32c..106adf5 100644 --- a/backend/app/api/workflow.py +++ b/backend/app/api/workflow.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/app/api/workflow_node.py b/backend/app/api/workflow_node.py index c9a7bd2..60a3013 100644 --- a/backend/app/api/workflow_node.py +++ b/backend/app/api/workflow_node.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/app/channels/__init__.py b/backend/app/channels/__init__.py index 993c983..40ca93f 100644 --- a/backend/app/channels/__init__.py +++ b/backend/app/channels/__init__.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/app/channels/app_hooks.py b/backend/app/channels/app_hooks.py index fb05db6..c6a6144 100644 --- a/backend/app/channels/app_hooks.py +++ b/backend/app/channels/app_hooks.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/app/channels/base.py b/backend/app/channels/base.py index 0fa0ff9..447a4c3 100644 --- a/backend/app/channels/base.py +++ b/backend/app/channels/base.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/app/channels/constants.py b/backend/app/channels/constants.py index d2f21df..243037f 100644 --- a/backend/app/channels/constants.py +++ b/backend/app/channels/constants.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/app/channels/email.py b/backend/app/channels/email.py index 02c6550..fa614dc 100644 --- a/backend/app/channels/email.py +++ b/backend/app/channels/email.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/app/channels/instagram.py b/backend/app/channels/instagram.py index 89c2231..0c839b0 100644 --- a/backend/app/channels/instagram.py +++ b/backend/app/channels/instagram.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/app/channels/interactive.py b/backend/app/channels/interactive.py index 5e1ec0f..cb23566 100644 --- a/backend/app/channels/interactive.py +++ b/backend/app/channels/interactive.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/app/channels/interactive_limits.py b/backend/app/channels/interactive_limits.py index 201faf9..77b774e 100644 --- a/backend/app/channels/interactive_limits.py +++ b/backend/app/channels/interactive_limits.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/app/channels/line.py b/backend/app/channels/line.py index 918a822..1554bcb 100644 --- a/backend/app/channels/line.py +++ b/backend/app/channels/line.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/app/channels/messenger.py b/backend/app/channels/messenger.py index 4fee889..ee36206 100644 --- a/backend/app/channels/messenger.py +++ b/backend/app/channels/messenger.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/app/channels/meta_base.py b/backend/app/channels/meta_base.py index 13782fe..e63c3be 100644 --- a/backend/app/channels/meta_base.py +++ b/backend/app/channels/meta_base.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/app/channels/registry.py b/backend/app/channels/registry.py index 03f8d45..42dace8 100644 --- a/backend/app/channels/registry.py +++ b/backend/app/channels/registry.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/app/channels/sent_choices.py b/backend/app/channels/sent_choices.py index 2a1d27b..1bd81aa 100644 --- a/backend/app/channels/sent_choices.py +++ b/backend/app/channels/sent_choices.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/app/channels/slack.py b/backend/app/channels/slack.py index 7ac2cbc..1b33243 100644 --- a/backend/app/channels/slack.py +++ b/backend/app/channels/slack.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -51,8 +51,8 @@ WELCOME_WITH_AGENT = ( "knowledge and can bring in a human when you need one." ) WELCOME_NO_AGENT = ( - "Hi! I'm ChatterMate. 👋\n\n" - "No agent is connected to this workspace yet. Set one up in ChatterMate and " + "Hi! I'm ReplyPier. 👋\n\n" + "No agent is connected to this workspace yet. Set one up in ReplyPier and " "I'll start answering here." ) SUGGESTED_PROMPTS_TITLE = "Try asking:" @@ -133,15 +133,15 @@ HOME_INTRO = ( ) HOME_HOW_TO = ( "*How to use me*\n" - "• @mention *ChatterMate* in any channel — I reply in the thread\n" + "• @mention *ReplyPier* in any channel — I reply in the thread\n" "• Send me a *direct message* for a private conversation\n" "• Open me from the *assistant* in the top bar for a side-by-side chat" ) HOME_NO_AGENT = ( "*No agent connected yet*\nConnect an agent to this workspace from the " - "ChatterMate dashboard and I'll start answering here." + "ReplyPier dashboard and I'll start answering here." ) -DASHBOARD_LINK_LABEL = "Open the ChatterMate dashboard →" +DASHBOARD_LINK_LABEL = "Open the ReplyPier dashboard →" def build_home_view(agent_card: Optional[dict], dashboard_url: str) -> dict: @@ -152,7 +152,7 @@ def build_home_view(agent_card: Optional[dict], dashboard_url: str) -> dict: "instruction", "photo_url" | None}. """ blocks: List[dict] = [ - {"type": "header", "text": {"type": "plain_text", "text": "ChatterMate", "emoji": True}}, + {"type": "header", "text": {"type": "plain_text", "text": "ReplyPier", "emoji": True}}, {"type": "section", "text": {"type": "mrkdwn", "text": HOME_INTRO}}, {"type": "divider"}, ] diff --git a/backend/app/channels/sms/__init__.py b/backend/app/channels/sms/__init__.py index 4273dae..7df4f1c 100644 --- a/backend/app/channels/sms/__init__.py +++ b/backend/app/channels/sms/__init__.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/app/channels/sms/adapter.py b/backend/app/channels/sms/adapter.py index 0add7fd..3767174 100644 --- a/backend/app/channels/sms/adapter.py +++ b/backend/app/channels/sms/adapter.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/app/channels/sms/base.py b/backend/app/channels/sms/base.py index 9a880f7..40d2fe8 100644 --- a/backend/app/channels/sms/base.py +++ b/backend/app/channels/sms/base.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/app/channels/sms/brevo.py b/backend/app/channels/sms/brevo.py index ba60b8f..5b3a76f 100644 --- a/backend/app/channels/sms/brevo.py +++ b/backend/app/channels/sms/brevo.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/app/channels/sms/messagebird.py b/backend/app/channels/sms/messagebird.py index b87ad48..72b04ea 100644 --- a/backend/app/channels/sms/messagebird.py +++ b/backend/app/channels/sms/messagebird.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/app/channels/sms/plivo.py b/backend/app/channels/sms/plivo.py index 2441c35..a59488a 100644 --- a/backend/app/channels/sms/plivo.py +++ b/backend/app/channels/sms/plivo.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/app/channels/sms/sns.py b/backend/app/channels/sms/sns.py index b2a214f..a5af43d 100644 --- a/backend/app/channels/sms/sns.py +++ b/backend/app/channels/sms/sns.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/app/channels/sms/twilio.py b/backend/app/channels/sms/twilio.py index 943bdd0..67df47d 100644 --- a/backend/app/channels/sms/twilio.py +++ b/backend/app/channels/sms/twilio.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/app/channels/sms/vonage.py b/backend/app/channels/sms/vonage.py index 4a6b863..40ef8dd 100644 --- a/backend/app/channels/sms/vonage.py +++ b/backend/app/channels/sms/vonage.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/app/channels/telegram.py b/backend/app/channels/telegram.py index 11b88c8..adc752d 100644 --- a/backend/app/channels/telegram.py +++ b/backend/app/channels/telegram.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/app/channels/whatsapp.py b/backend/app/channels/whatsapp.py index eb4d9b7..98dca13 100644 --- a/backend/app/channels/whatsapp.py +++ b/backend/app/channels/whatsapp.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/app/core/agno_telemetry.py b/backend/app/core/agno_telemetry.py index 7daace4..2b3db7a 100644 --- a/backend/app/core/agno_telemetry.py +++ b/backend/app/core/agno_telemetry.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -23,7 +23,7 @@ limitations under the License. # or backend/.env). agno reads these variables before each run report, so # setting them once per process covers every agent, wherever it is built. With # both off, AGNO_API_ENABLED=false also stops agno's other calls to its API -# (session logging, playground, evals), which ChatterMate never uses. +# (session logging, playground, evals), which ReplyPier never uses. # # Environment variables rather than Agent(telemetry=False) because agents are # built in many places (chat, transfer, tickets, FAQs, summaries, help center) diff --git a/backend/app/core/application.py b/backend/app/core/application.py index e03a946..aadc29e 100644 --- a/backend/app/core/application.py +++ b/backend/app/core/application.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -22,7 +22,7 @@ logger = get_logger(__name__) # Create FastAPI app instance app = FastAPI( - title="ChatterMate API", + title="ReplyPier API", description="AI-Powered Customer Support Platform", version="1.0.0" ) diff --git a/backend/app/core/auth.py b/backend/app/core/auth.py index e3bed45..b4b97a3 100644 --- a/backend/app/core/auth.py +++ b/backend/app/core/auth.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/app/core/auth_utils.py b/backend/app/core/auth_utils.py index 552aaea..4cc0d53 100644 --- a/backend/app/core/auth_utils.py +++ b/backend/app/core/auth_utils.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/app/core/config.py b/backend/app/core/config.py index 4865137..703996c 100644 --- a/backend/app/core/config.py +++ b/backend/app/core/config.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -32,16 +32,16 @@ BACKEND_DIR = Path(__file__).resolve().parent.parent.parent ENV_FILE = Path(os.getenv("ENV_FILE") or BACKEND_DIR / ".env") load_dotenv(ENV_FILE) -DEFAULT_CORS = ["https://chattermate.chat", "http://localhost:5173", "http://localhost:8000"] +DEFAULT_CORS = ["https://replypier.site", "http://localhost:5173", "http://localhost:8000"] class Settings(BaseSettings): - PROJECT_NAME: str = "ChatterMate" + PROJECT_NAME: str = "ReplyPier" VERSION: str = "0.1.0" API_V1_STR: str = "/api/v1" # Database DATABASE_URL: str = os.getenv( - "DATABASE_URL", "postgresql+psycopg://test:test@localhost:5432/chattermate") + "DATABASE_URL", "postgresql+psycopg://test:test@localhost:5432/replypier") # Redis REDIS_URL: str = os.getenv("REDIS_URL", "redis://localhost:6379/0") REDIS_ENABLED: bool = os.getenv("REDIS_ENABLED", "false").lower() == "true" @@ -85,8 +85,8 @@ class Settings(BaseSettings): SMTP_PORT: int = int(os.getenv("SMTP_PORT", "587")) SMTP_USERNAME: str = os.getenv("SMTP_USERNAME", "your-email@gmail.com") SMTP_PASSWORD: str = os.getenv("SMTP_PASSWORD", "your-password") - FROM_EMAIL: str = os.getenv("FROM_EMAIL", "noreply@chattermate.chat") - FROM_NAME: str = os.getenv("FROM_NAME", "ChatterMate") + FROM_EMAIL: str = os.getenv("FROM_EMAIL", "noreply@replypier.site") + FROM_NAME: str = os.getenv("FROM_NAME", "ReplyPier") # Shopify SHOPIFY_API_KEY: str = os.getenv("SHOPIFY_API_KEY", "") @@ -152,7 +152,7 @@ class Settings(BaseSettings): # S3 Configuration S3_FILE_STORAGE: bool = os.getenv("S3_FILE_STORAGE", "false").lower() == "true" - S3_BUCKET: str = os.getenv("S3_BUCKET", "chattermate-uploads") + S3_BUCKET: str = os.getenv("S3_BUCKET", "replypier-uploads") S3_REGION: str = os.getenv("S3_REGION", "us-east-1") # None, not "", when unset: boto3 only falls back to its default credential # chain (env → shared config → IAM instance/container role) if these are @@ -256,9 +256,9 @@ class Settings(BaseSettings): # to "path" mode. HELP_CENTER_PUBLIC_MODE: str = os.getenv("HELP_CENTER_PUBLIC_MODE", "path") # Base domain serving {slug}. help centers. - HELP_CENTER_BASE_DOMAIN: str = os.getenv("HELP_CENTER_BASE_DOMAIN", "chattermate.help") + HELP_CENTER_BASE_DOMAIN: str = os.getenv("HELP_CENTER_BASE_DOMAIN", "help.replypier.site") # CNAME target customers point their custom help-center domain at. - HELP_CENTER_CNAME_TARGET: str = os.getenv("HELP_CENTER_CNAME_TARGET", "cname.chattermate.chat") + HELP_CENTER_CNAME_TARGET: str = os.getenv("HELP_CENTER_CNAME_TARGET", "cname.replypier.site") # IPs the CNAME target resolves to — accepted when a provider flattens the # CNAME into A/AAAA records (comma-separated). HELP_CENTER_TARGET_IPS: frozenset = frozenset( @@ -273,7 +273,7 @@ class Settings(BaseSettings): # Force a context-window size (tokens) for exotic/self-hosted models; 0 = auto. FAQ_CONTEXT_TOKENS_OVERRIDE: int = int(os.getenv("FAQ_CONTEXT_TOKENS_OVERRIDE", "0")) # Meter FAQ generation credits even for orgs on their own API key - # (default: hosted CHATTERMATE model only). + # (default: hosted REPLYPIER model only). FAQ_METER_OWN_KEY: bool = os.getenv("FAQ_METER_OWN_KEY", "false").lower() == "true" FAQ_IMPORT_MAX_PAGE_CHARS: int = int(os.getenv("FAQ_IMPORT_MAX_PAGE_CHARS", "100000")) FAQ_IMPORT_FETCH_TIMEOUT: int = int(os.getenv("FAQ_IMPORT_FETCH_TIMEOUT", "30")) diff --git a/backend/app/core/cors.py b/backend/app/core/cors.py index 8780bba..5d4d5c3 100644 --- a/backend/app/core/cors.py +++ b/backend/app/core/cors.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/app/core/crawler_policy.py b/backend/app/core/crawler_policy.py index a7f3a7e..77370db 100644 --- a/backend/app/core/crawler_policy.py +++ b/backend/app/core/crawler_policy.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/app/core/default_templates.py b/backend/app/core/default_templates.py index 0e0e5ce..9edb966 100644 --- a/backend/app/core/default_templates.py +++ b/backend/app/core/default_templates.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/app/core/edition.py b/backend/app/core/edition.py index ff673a7..b8171c6 100644 --- a/backend/app/core/edition.py +++ b/backend/app/core/edition.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/app/core/encryption.py b/backend/app/core/encryption.py index 0ce8ec4..212f65a 100644 --- a/backend/app/core/encryption.py +++ b/backend/app/core/encryption.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/app/core/error_handlers.py b/backend/app/core/error_handlers.py index d3835bd..739284c 100644 --- a/backend/app/core/error_handlers.py +++ b/backend/app/core/error_handlers.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/app/core/exceptions.py b/backend/app/core/exceptions.py index 2ffbd48..686242e 100644 --- a/backend/app/core/exceptions.py +++ b/backend/app/core/exceptions.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/app/core/external_urls.py b/backend/app/core/external_urls.py index d80560b..552c172 100644 --- a/backend/app/core/external_urls.py +++ b/backend/app/core/external_urls.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/app/core/file_validation.py b/backend/app/core/file_validation.py index b1a9725..02cbd8a 100644 --- a/backend/app/core/file_validation.py +++ b/backend/app/core/file_validation.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/app/core/help_center_host.py b/backend/app/core/help_center_host.py index 9363aae..89167bf 100644 --- a/backend/app/core/help_center_host.py +++ b/backend/app/core/help_center_host.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/app/core/local_file_urls.py b/backend/app/core/local_file_urls.py index 296dc34..1beecb5 100644 --- a/backend/app/core/local_file_urls.py +++ b/backend/app/core/local_file_urls.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -34,7 +34,7 @@ LOCAL_FILE_ROUTE = f"{settings.API_V1_STR}/files/local" # SECRET_KEY also signs JWTs; the purpose prefix keeps the two from ever # validating each other. -_PURPOSE = b"chattermate:local-file-url:v1\n" +_PURPOSE = b"replypier:local-file-url:v1\n" def _signature(key: str, expires: int) -> str: diff --git a/backend/app/core/logger.py b/backend/app/core/logger.py index eafa214..469357a 100644 --- a/backend/app/core/logger.py +++ b/backend/app/core/logger.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/app/core/model_catalog.py b/backend/app/core/model_catalog.py index cc4fe7c..fb18cbc 100644 --- a/backend/app/core/model_catalog.py +++ b/backend/app/core/model_catalog.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -56,7 +56,7 @@ def _m(value: str, label: str) -> CatalogModel: return {"value": value, "label": label} -# Keyed by AIModelType value. CHATTERMATE (managed) is intentionally excluded — it +# Keyed by AIModelType value. REPLYPIER (managed) is intentionally excluded — it # is handled as a special case in the setup flow and is not user-selectable here. MODEL_CATALOG: Dict[str, CatalogProvider] = { "OPENAI": { diff --git a/backend/app/core/oauth_state.py b/backend/app/core/oauth_state.py index 6697cd8..3c1aeb3 100644 --- a/backend/app/core/oauth_state.py +++ b/backend/app/core/oauth_state.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/app/core/outbound_http.py b/backend/app/core/outbound_http.py index f1871b4..e50fa6a 100644 --- a/backend/app/core/outbound_http.py +++ b/backend/app/core/outbound_http.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/app/core/outbound_policy.py b/backend/app/core/outbound_policy.py index 15d91ec..0b61d87 100644 --- a/backend/app/core/outbound_policy.py +++ b/backend/app/core/outbound_policy.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/app/core/params.py b/backend/app/core/params.py index 1946782..717e267 100644 --- a/backend/app/core/params.py +++ b/backend/app/core/params.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/app/core/processor/__init__.py b/backend/app/core/processor/__init__.py index 7fb18df..f24cd5c 100644 --- a/backend/app/core/processor/__init__.py +++ b/backend/app/core/processor/__init__.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/app/core/processor/status.py b/backend/app/core/processor/status.py index ee2021f..31400f4 100644 --- a/backend/app/core/processor/status.py +++ b/backend/app/core/processor/status.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/app/core/redis.py b/backend/app/core/redis.py index 606a627..615c931 100644 --- a/backend/app/core/redis.py +++ b/backend/app/core/redis.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/app/core/s3.py b/backend/app/core/s3.py index 531be78..c09b19b 100644 --- a/backend/app/core/s3.py +++ b/backend/app/core/s3.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/app/core/security.py b/backend/app/core/security.py index f842f6e..1b24071 100644 --- a/backend/app/core/security.py +++ b/backend/app/core/security.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/app/core/socketio.py b/backend/app/core/socketio.py index 98b486b..749543f 100644 --- a/backend/app/core/socketio.py +++ b/backend/app/core/socketio.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -100,7 +100,7 @@ def configure_socketio(cors_origins=None): manager = socketio.AsyncRedisManager( redis_url, write_only=False, - channel='chattermate', + channel='replypier', redis_options=redis_options(redis_url), ) manager.set_server(sio) diff --git a/backend/app/crm/__init__.py b/backend/app/crm/__init__.py index 7772742..86605d7 100644 --- a/backend/app/crm/__init__.py +++ b/backend/app/crm/__init__.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/app/crm/base.py b/backend/app/crm/base.py index 353cd08..e0a915a 100644 --- a/backend/app/crm/base.py +++ b/backend/app/crm/base.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/app/crm/hubspot.py b/backend/app/crm/hubspot.py index 0a3c634..46caa99 100644 --- a/backend/app/crm/hubspot.py +++ b/backend/app/crm/hubspot.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/app/crm/mapping.py b/backend/app/crm/mapping.py index 10aceab..9e99ccc 100644 --- a/backend/app/crm/mapping.py +++ b/backend/app/crm/mapping.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -109,7 +109,7 @@ def build_note_body(payload: LeadPayload) -> str: render notes as HTML, so plain newlines would collapse and run the summary into the header. Labelled lines keep the AI summary unmistakable; dynamic values are escaped.""" - lines = ["Lead captured by ChatterMate"] + lines = ["Lead captured by ReplyPier"] if payload.summary: lines.append(f"AI summary: {html.escape(payload.summary)}") for label, value in (payload.custom_fields or {}).items(): diff --git a/backend/app/crm/pipedrive.py b/backend/app/crm/pipedrive.py index 58e62c1..4614e97 100644 --- a/backend/app/crm/pipedrive.py +++ b/backend/app/crm/pipedrive.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -239,7 +239,7 @@ class PipedriveAdapter(CrmAdapter): if listing.json().get("data") or []: return None, None # open lead exists — nothing to create - body = {"title": f"{payload.name or payload.email} — ChatterMate lead", + body = {"title": f"{payload.name or payload.email} — ReplyPier lead", "person_id": person_id} if org_id: body["organization_id"] = org_id diff --git a/backend/app/crm/registry.py b/backend/app/crm/registry.py index b9c5006..c2e75ab 100644 --- a/backend/app/crm/registry.py +++ b/backend/app/crm/registry.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/app/database.py b/backend/app/database.py index e7ad7a8..07f4a47 100644 --- a/backend/app/database.py +++ b/backend/app/database.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/app/knowledge/README.md b/backend/app/knowledge/README.md index 86eea7a..51f1785 100644 --- a/backend/app/knowledge/README.md +++ b/backend/app/knowledge/README.md @@ -1,4 +1,4 @@ -# ChatterMate Enhanced Website Knowledge Base +# ReplyPier Enhanced Website Knowledge Base This module provides an enhanced website knowledge extraction system that significantly improves content extraction from web pages compared to the default implementation. diff --git a/backend/app/knowledge/chunking.py b/backend/app/knowledge/chunking.py index 149ca90..e4c8f95 100644 --- a/backend/app/knowledge/chunking.py +++ b/backend/app/knowledge/chunking.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/app/knowledge/content_summarizer.py b/backend/app/knowledge/content_summarizer.py index 68c1005..cccc645 100644 --- a/backend/app/knowledge/content_summarizer.py +++ b/backend/app/knowledge/content_summarizer.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/app/knowledge/crawl4ai_fallback.py b/backend/app/knowledge/crawl4ai_fallback.py index 995c3ca..0156119 100644 --- a/backend/app/knowledge/crawl4ai_fallback.py +++ b/backend/app/knowledge/crawl4ai_fallback.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/app/knowledge/crawl_scope.py b/backend/app/knowledge/crawl_scope.py index b970e7e..16cb340 100644 --- a/backend/app/knowledge/crawl_scope.py +++ b/backend/app/knowledge/crawl_scope.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/app/knowledge/crawler_identity.py b/backend/app/knowledge/crawler_identity.py index 0ba9761..0930d7a 100644 --- a/backend/app/knowledge/crawler_identity.py +++ b/backend/app/knowledge/crawler_identity.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -19,4 +19,4 @@ scrapers commonly fake, while a named crawler is let through - and site owners can see (and allow or block) who is reading them. """ -CRAWLER_USER_AGENT = "Mozilla/5.0 (compatible; ChatterMateBot/1.0; +https://chattermate.chat)" +CRAWLER_USER_AGENT = "Mozilla/5.0 (compatible; ReplyPierBot/1.0; +https://replypier.site)" diff --git a/backend/app/knowledge/deadline.py b/backend/app/knowledge/deadline.py index 885a8e3..8eb2870 100644 --- a/backend/app/knowledge/deadline.py +++ b/backend/app/knowledge/deadline.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/app/knowledge/domains.py b/backend/app/knowledge/domains.py index 07bcd73..007abfe 100644 --- a/backend/app/knowledge/domains.py +++ b/backend/app/knowledge/domains.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/app/knowledge/embedder.py b/backend/app/knowledge/embedder.py index 2deb7b3..df62503 100644 --- a/backend/app/knowledge/embedder.py +++ b/backend/app/knowledge/embedder.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/app/knowledge/enhanced_pdf_kb.py b/backend/app/knowledge/enhanced_pdf_kb.py index e263cfc..6c580de 100644 --- a/backend/app/knowledge/enhanced_pdf_kb.py +++ b/backend/app/knowledge/enhanced_pdf_kb.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/app/knowledge/enhanced_website_kb.py b/backend/app/knowledge/enhanced_website_kb.py index ad7af01..1df1440 100644 --- a/backend/app/knowledge/enhanced_website_kb.py +++ b/backend/app/knowledge/enhanced_website_kb.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/app/knowledge/enhanced_website_reader.py b/backend/app/knowledge/enhanced_website_reader.py index da05a7c..60d0180 100644 --- a/backend/app/knowledge/enhanced_website_reader.py +++ b/backend/app/knowledge/enhanced_website_reader.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/app/knowledge/failure_advice.py b/backend/app/knowledge/failure_advice.py index f48185e..ad457ae 100644 --- a/backend/app/knowledge/failure_advice.py +++ b/backend/app/knowledge/failure_advice.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/app/knowledge/knowledge_base.py b/backend/app/knowledge/knowledge_base.py index 4b56aad..7b4c348 100644 --- a/backend/app/knowledge/knowledge_base.py +++ b/backend/app/knowledge/knowledge_base.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/app/knowledge/main_content.py b/backend/app/knowledge/main_content.py index aabfdc1..4c27d6f 100644 --- a/backend/app/knowledge/main_content.py +++ b/backend/app/knowledge/main_content.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/app/knowledge/optimized_pgvector.py b/backend/app/knowledge/optimized_pgvector.py index faa7709..2ad79bf 100644 --- a/backend/app/knowledge/optimized_pgvector.py +++ b/backend/app/knowledge/optimized_pgvector.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/app/knowledge/page_editor.py b/backend/app/knowledge/page_editor.py index 0280ae2..efa7546 100644 --- a/backend/app/knowledge/page_editor.py +++ b/backend/app/knowledge/page_editor.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/app/knowledge/page_fetch.py b/backend/app/knowledge/page_fetch.py index fdb8919..b93e7da 100644 --- a/backend/app/knowledge/page_fetch.py +++ b/backend/app/knowledge/page_fetch.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/app/knowledge/pdf_download.py b/backend/app/knowledge/pdf_download.py index 23b3286..17f524b 100644 --- a/backend/app/knowledge/pdf_download.py +++ b/backend/app/knowledge/pdf_download.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/app/knowledge/pdf_limits.py b/backend/app/knowledge/pdf_limits.py index 1681423..9a7d1a9 100644 --- a/backend/app/knowledge/pdf_limits.py +++ b/backend/app/knowledge/pdf_limits.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/app/knowledge/sitemap_parser.py b/backend/app/knowledge/sitemap_parser.py index 5c18630..e04eb4b 100644 --- a/backend/app/knowledge/sitemap_parser.py +++ b/backend/app/knowledge/sitemap_parser.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/app/knowledge/sitemap_reader.py b/backend/app/knowledge/sitemap_reader.py index dcd773d..9203f59 100644 --- a/backend/app/knowledge/sitemap_reader.py +++ b/backend/app/knowledge/sitemap_reader.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/app/knowledge/url_safety.py b/backend/app/knowledge/url_safety.py index 29ce344..d9c845b 100644 --- a/backend/app/knowledge/url_safety.py +++ b/backend/app/knowledge/url_safety.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/app/main.py b/backend/app/main.py index 25fcbc1..32e46f3 100644 --- a/backend/app/main.py +++ b/backend/app/main.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -83,7 +83,7 @@ logger.debug(f"CORS origins: {cors_origins}") app.router.lifespan_context = lifespan # Add CORS middleware to FastAPI app. The regex covers every help-center -# subdomain (*.chattermate.help) so a newly-created slug is allowed without a +# subdomain (*.help.replypier.site) so a newly-created slug is allowed without a # cache refresh; explicit origins still cover org domains + custom domains. # Only first-party origins (the dashboard) may send credentials. app.add_middleware( @@ -319,7 +319,7 @@ async def root(): return { "name": settings.PROJECT_NAME, "version": settings.VERSION, - "description": "Welcome to ChatterMate API" + "description": "Welcome to ReplyPier API" } @app.api_route("/health", methods=["GET"], operation_id="get_health_check") diff --git a/backend/app/models/__init__.py b/backend/app/models/__init__.py index 8a49f78..bcc7c70 100644 --- a/backend/app/models/__init__.py +++ b/backend/app/models/__init__.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/app/models/agent.py b/backend/app/models/agent.py index 786b91f..9cbdd6e 100644 --- a/backend/app/models/agent.py +++ b/backend/app/models/agent.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/app/models/ai_config.py b/backend/app/models/ai_config.py index ced7605..81be020 100644 --- a/backend/app/models/ai_config.py +++ b/backend/app/models/ai_config.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -32,7 +32,7 @@ class AIModelType(str, Enum): OLLAMA = "OLLAMA" XAI = "XAI" OPENAI_COMPATIBLE = "OPENAI_COMPATIBLE" - CHATTERMATE = "CHATTERMATE" # own model for enterprise customers + REPLYPIER = "REPLYPIER" # own model for enterprise customers DEFAULT_AI_SETTINGS = { "instructions": [ diff --git a/backend/app/models/auth_session.py b/backend/app/models/auth_session.py index 290d472..0a2a76d 100644 --- a/backend/app/models/auth_session.py +++ b/backend/app/models/auth_session.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/app/models/channels/__init__.py b/backend/app/models/channels/__init__.py index 4b45b91..3979731 100644 --- a/backend/app/models/channels/__init__.py +++ b/backend/app/models/channels/__init__.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/app/models/channels/agent_channel_config.py b/backend/app/models/channels/agent_channel_config.py index d69e8ef..2a6200c 100644 --- a/backend/app/models/channels/agent_channel_config.py +++ b/backend/app/models/channels/agent_channel_config.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/app/models/channels/channel_account.py b/backend/app/models/channels/channel_account.py index affe41f..35559ac 100644 --- a/backend/app/models/channels/channel_account.py +++ b/backend/app/models/channels/channel_account.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/app/models/channels/channel_conversation.py b/backend/app/models/channels/channel_conversation.py index db43b35..eef5c33 100644 --- a/backend/app/models/channels/channel_conversation.py +++ b/backend/app/models/channels/channel_conversation.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -25,7 +25,7 @@ from app.database import Base class ChannelConversation(Base): - """Maps an external channel conversation to a ChatterMate session. + """Maps an external channel conversation to a ReplyPier session. The generic analog of SlackConversation: one row per (connected account, platform conversation, session). A new session for diff --git a/backend/app/models/chat_history.py b/backend/app/models/chat_history.py index 6bc220f..b809385 100644 --- a/backend/app/models/chat_history.py +++ b/backend/app/models/chat_history.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/app/models/crm.py b/backend/app/models/crm.py index f29f266..2fffa74 100644 --- a/backend/app/models/crm.py +++ b/backend/app/models/crm.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/app/models/customer.py b/backend/app/models/customer.py index 82af4f8..6030cb5 100644 --- a/backend/app/models/customer.py +++ b/backend/app/models/customer.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/app/models/faq.py b/backend/app/models/faq.py index 69568d4..a36d353 100644 --- a/backend/app/models/faq.py +++ b/backend/app/models/faq.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/app/models/faq_generation_job.py b/backend/app/models/faq_generation_job.py index 3fe3661..b1da751 100644 --- a/backend/app/models/faq_generation_job.py +++ b/backend/app/models/faq_generation_job.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/app/models/fcm_token.py b/backend/app/models/fcm_token.py index 7321677..7ee96f2 100644 --- a/backend/app/models/fcm_token.py +++ b/backend/app/models/fcm_token.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/app/models/file_attachment.py b/backend/app/models/file_attachment.py index b14f53e..bff7c98 100644 --- a/backend/app/models/file_attachment.py +++ b/backend/app/models/file_attachment.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/app/models/guardrail_event.py b/backend/app/models/guardrail_event.py index ab78121..470e61f 100644 --- a/backend/app/models/guardrail_event.py +++ b/backend/app/models/guardrail_event.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/app/models/help_center.py b/backend/app/models/help_center.py index 9742eb5..288513b 100644 --- a/backend/app/models/help_center.py +++ b/backend/app/models/help_center.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/app/models/investigation.py b/backend/app/models/investigation.py index 969351f..6532e62 100644 --- a/backend/app/models/investigation.py +++ b/backend/app/models/investigation.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -236,7 +236,7 @@ class TicketProposal(Base): """Autonomy L2: a resolution the AI proposes and a human decides on. Approval resolves the ticket and notifies the customer; a rejection can feed a refined investigation run (the reason becomes its context_note). - ChatterMate never executes infrastructure changes — approval records the + ReplyPier never executes infrastructure changes — approval records the decision, humans/runbooks perform any mutation.""" __tablename__ = "ticket_proposals" diff --git a/backend/app/models/jira.py b/backend/app/models/jira.py index d4556c0..f57ae29 100644 --- a/backend/app/models/jira.py +++ b/backend/app/models/jira.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/app/models/knowledge.py b/backend/app/models/knowledge.py index e76f1b7..81d781a 100644 --- a/backend/app/models/knowledge.py +++ b/backend/app/models/knowledge.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/app/models/knowledge_queue.py b/backend/app/models/knowledge_queue.py index 734c4f2..a5575a5 100644 --- a/backend/app/models/knowledge_queue.py +++ b/backend/app/models/knowledge_queue.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/app/models/knowledge_to_agent.py b/backend/app/models/knowledge_to_agent.py index 822f374..d62b23c 100644 --- a/backend/app/models/knowledge_to_agent.py +++ b/backend/app/models/knowledge_to_agent.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/app/models/lead_capture.py b/backend/app/models/lead_capture.py index 95c9364..46cb9ce 100644 --- a/backend/app/models/lead_capture.py +++ b/backend/app/models/lead_capture.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/app/models/mcp_tool.py b/backend/app/models/mcp_tool.py index 34dcf75..fb9d81b 100644 --- a/backend/app/models/mcp_tool.py +++ b/backend/app/models/mcp_tool.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/app/models/notification.py b/backend/app/models/notification.py index e91f639..8e0f01a 100644 --- a/backend/app/models/notification.py +++ b/backend/app/models/notification.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/app/models/notification_settings.py b/backend/app/models/notification_settings.py index e02d7c9..9ec205e 100644 --- a/backend/app/models/notification_settings.py +++ b/backend/app/models/notification_settings.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/app/models/organization.py b/backend/app/models/organization.py index 5f75544..2889737 100644 --- a/backend/app/models/organization.py +++ b/backend/app/models/organization.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/app/models/permission.py b/backend/app/models/permission.py index 854b747..31e4b4e 100644 --- a/backend/app/models/permission.py +++ b/backend/app/models/permission.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/app/models/rating.py b/backend/app/models/rating.py index bd73413..0b40846 100644 --- a/backend/app/models/rating.py +++ b/backend/app/models/rating.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/app/models/role.py b/backend/app/models/role.py index 29b18a7..1791d98 100644 --- a/backend/app/models/role.py +++ b/backend/app/models/role.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/app/models/schemas/__init__.py b/backend/app/models/schemas/__init__.py index a6b511e..fdcfbc8 100644 --- a/backend/app/models/schemas/__init__.py +++ b/backend/app/models/schemas/__init__.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/app/models/schemas/agent.py b/backend/app/models/schemas/agent.py index fd01d8d..dbc22bc 100644 --- a/backend/app/models/schemas/agent.py +++ b/backend/app/models/schemas/agent.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/app/models/schemas/agent_customization.py b/backend/app/models/schemas/agent_customization.py index dcd8b76..d537654 100644 --- a/backend/app/models/schemas/agent_customization.py +++ b/backend/app/models/schemas/agent_customization.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -60,7 +60,7 @@ class WidgetDisplaySide(str, enum.Enum): class WidgetDisplayConfig(BaseModel): """Dashboard "Widget placement" defaults, stored in customization_metadata. - The embed loader (chattermate.js) merges these under any options the + The embed loader (replypier.js) merges these under any options the installing developer set on the page. Bounds keep saved values renderable on any reasonable screen; the loader clamps again client-side. """ diff --git a/backend/app/models/schemas/ai_config.py b/backend/app/models/schemas/ai_config.py index eee6923..c2f5dc1 100644 --- a/backend/app/models/schemas/ai_config.py +++ b/backend/app/models/schemas/ai_config.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/app/models/schemas/channel.py b/backend/app/models/schemas/channel.py index 491178f..ffd072a 100644 --- a/backend/app/models/schemas/channel.py +++ b/backend/app/models/schemas/channel.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/app/models/schemas/chat.py b/backend/app/models/schemas/chat.py index 18f3afc..2609b16 100644 --- a/backend/app/models/schemas/chat.py +++ b/backend/app/models/schemas/chat.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/app/models/schemas/crm.py b/backend/app/models/schemas/crm.py index d277a2c..1b908f7 100644 --- a/backend/app/models/schemas/crm.py +++ b/backend/app/models/schemas/crm.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/app/models/schemas/faq.py b/backend/app/models/schemas/faq.py index f183a50..06d5299 100644 --- a/backend/app/models/schemas/faq.py +++ b/backend/app/models/schemas/faq.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/app/models/schemas/help_center.py b/backend/app/models/schemas/help_center.py index d68c7a7..51f86f2 100644 --- a/backend/app/models/schemas/help_center.py +++ b/backend/app/models/schemas/help_center.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/app/models/schemas/investigation.py b/backend/app/models/schemas/investigation.py index b191b6f..cd16901 100644 --- a/backend/app/models/schemas/investigation.py +++ b/backend/app/models/schemas/investigation.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/app/models/schemas/jira.py b/backend/app/models/schemas/jira.py index 6580aa8..d3c12c9 100644 --- a/backend/app/models/schemas/jira.py +++ b/backend/app/models/schemas/jira.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/app/models/schemas/lead_capture.py b/backend/app/models/schemas/lead_capture.py index 7e46d20..a877d28 100644 --- a/backend/app/models/schemas/lead_capture.py +++ b/backend/app/models/schemas/lead_capture.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/app/models/schemas/mcp_tool.py b/backend/app/models/schemas/mcp_tool.py index 9d13991..d1bbbc6 100644 --- a/backend/app/models/schemas/mcp_tool.py +++ b/backend/app/models/schemas/mcp_tool.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/app/models/schemas/notification.py b/backend/app/models/schemas/notification.py index 8b18a57..da9701a 100644 --- a/backend/app/models/schemas/notification.py +++ b/backend/app/models/schemas/notification.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/app/models/schemas/organization.py b/backend/app/models/schemas/organization.py index 3896955..242bd8a 100644 --- a/backend/app/models/schemas/organization.py +++ b/backend/app/models/schemas/organization.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/app/models/schemas/pagination.py b/backend/app/models/schemas/pagination.py index 6a29827..d5021b1 100644 --- a/backend/app/models/schemas/pagination.py +++ b/backend/app/models/schemas/pagination.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/app/models/schemas/people.py b/backend/app/models/schemas/people.py index 7cd34be..662435d 100644 --- a/backend/app/models/schemas/people.py +++ b/backend/app/models/schemas/people.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/app/models/schemas/role.py b/backend/app/models/schemas/role.py index 99d67d5..ce0940e 100644 --- a/backend/app/models/schemas/role.py +++ b/backend/app/models/schemas/role.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/app/models/schemas/shopify/__init__.py b/backend/app/models/schemas/shopify/__init__.py index 57e0e6f..342659e 100644 --- a/backend/app/models/schemas/shopify/__init__.py +++ b/backend/app/models/schemas/shopify/__init__.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/app/models/schemas/shopify/agent_shopify_config.py b/backend/app/models/schemas/shopify/agent_shopify_config.py index fa7ee44..24af911 100644 --- a/backend/app/models/schemas/shopify/agent_shopify_config.py +++ b/backend/app/models/schemas/shopify/agent_shopify_config.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/app/models/schemas/shopify/shopify_shop.py b/backend/app/models/schemas/shopify/shopify_shop.py index 18757f4..070390e 100644 --- a/backend/app/models/schemas/shopify/shopify_shop.py +++ b/backend/app/models/schemas/shopify/shopify_shop.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/app/models/schemas/ticket.py b/backend/app/models/schemas/ticket.py index 3a9492e..744250a 100644 --- a/backend/app/models/schemas/ticket.py +++ b/backend/app/models/schemas/ticket.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/app/models/schemas/ticket_db_connector.py b/backend/app/models/schemas/ticket_db_connector.py index 225cfc5..af1a234 100644 --- a/backend/app/models/schemas/ticket_db_connector.py +++ b/backend/app/models/schemas/ticket_db_connector.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/app/models/schemas/user.py b/backend/app/models/schemas/user.py index 1bbbdb2..6857c4d 100644 --- a/backend/app/models/schemas/user.py +++ b/backend/app/models/schemas/user.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/app/models/schemas/user_group.py b/backend/app/models/schemas/user_group.py index 90586eb..13200f3 100644 --- a/backend/app/models/schemas/user_group.py +++ b/backend/app/models/schemas/user_group.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/app/models/schemas/widget.py b/backend/app/models/schemas/widget.py index ca9429a..85abbc6 100644 --- a/backend/app/models/schemas/widget.py +++ b/backend/app/models/schemas/widget.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/app/models/schemas/widget_app.py b/backend/app/models/schemas/widget_app.py index 0f6b135..fec11b0 100644 --- a/backend/app/models/schemas/widget_app.py +++ b/backend/app/models/schemas/widget_app.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/app/models/schemas/workflow.py b/backend/app/models/schemas/workflow.py index 566aee9..8fd99fe 100644 --- a/backend/app/models/schemas/workflow.py +++ b/backend/app/models/schemas/workflow.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/app/models/session_to_agent.py b/backend/app/models/session_to_agent.py index f772fad..7ee2a3b 100644 --- a/backend/app/models/session_to_agent.py +++ b/backend/app/models/session_to_agent.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/app/models/shopify/__init__.py b/backend/app/models/shopify/__init__.py index 7247428..1eb284c 100644 --- a/backend/app/models/shopify/__init__.py +++ b/backend/app/models/shopify/__init__.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/app/models/shopify/agent_shopify_config.py b/backend/app/models/shopify/agent_shopify_config.py index f57b0af..2f0f84e 100644 --- a/backend/app/models/shopify/agent_shopify_config.py +++ b/backend/app/models/shopify/agent_shopify_config.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/app/models/shopify/shopify_shop.py b/backend/app/models/shopify/shopify_shop.py index 0ec595a..86d6551 100644 --- a/backend/app/models/shopify/shopify_shop.py +++ b/backend/app/models/shopify/shopify_shop.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/app/models/ticket.py b/backend/app/models/ticket.py index 7012f20..3a40357 100644 --- a/backend/app/models/ticket.py +++ b/backend/app/models/ticket.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/app/models/ticket_activity.py b/backend/app/models/ticket_activity.py index 2883021..aea6c33 100644 --- a/backend/app/models/ticket_activity.py +++ b/backend/app/models/ticket_activity.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/app/models/ticket_db_connector.py b/backend/app/models/ticket_db_connector.py index 7cc1fe5..bdc5c93 100644 --- a/backend/app/models/ticket_db_connector.py +++ b/backend/app/models/ticket_db_connector.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -32,7 +32,7 @@ class DBConnectorEngine(_ValueStrEnum): # Which value of the ticket's customer is matched against the scope column. # Email is the default because it is the identifier a support database is most -# likely to share with ChatterMate; phone suits channel-first businesses. +# likely to share with ReplyPier; phone suits channel-first businesses. ROW_SCOPE_KEYS = ("email", "phone") diff --git a/backend/app/models/ticket_settings.py b/backend/app/models/ticket_settings.py index 3d6f0c0..4ea021f 100644 --- a/backend/app/models/ticket_settings.py +++ b/backend/app/models/ticket_settings.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/app/models/user.py b/backend/app/models/user.py index 9b6a76c..a1391db 100644 --- a/backend/app/models/user.py +++ b/backend/app/models/user.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/app/models/widget.py b/backend/app/models/widget.py index 44443b7..0fba76c 100644 --- a/backend/app/models/widget.py +++ b/backend/app/models/widget.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/app/models/widget_app.py b/backend/app/models/widget_app.py index 0d091f8..1758102 100644 --- a/backend/app/models/widget_app.py +++ b/backend/app/models/widget_app.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/app/models/workflow.py b/backend/app/models/workflow.py index e9217c9..7fd11da 100644 --- a/backend/app/models/workflow.py +++ b/backend/app/models/workflow.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/app/models/workflow_connection.py b/backend/app/models/workflow_connection.py index 7568e05..dec85e8 100644 --- a/backend/app/models/workflow_connection.py +++ b/backend/app/models/workflow_connection.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/app/models/workflow_node.py b/backend/app/models/workflow_node.py index 491fc95..0ba5c64 100644 --- a/backend/app/models/workflow_node.py +++ b/backend/app/models/workflow_node.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/app/repositories/__init__.py b/backend/app/repositories/__init__.py index 4bf993d..710e6fa 100644 --- a/backend/app/repositories/__init__.py +++ b/backend/app/repositories/__init__.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/app/repositories/agent.py b/backend/app/repositories/agent.py index 145340d..e2fe226 100644 --- a/backend/app/repositories/agent.py +++ b/backend/app/repositories/agent.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/app/repositories/agent_shopify_config_repository.py b/backend/app/repositories/agent_shopify_config_repository.py index d24f4bd..beabc3f 100644 --- a/backend/app/repositories/agent_shopify_config_repository.py +++ b/backend/app/repositories/agent_shopify_config_repository.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/app/repositories/ai_config.py b/backend/app/repositories/ai_config.py index f456b56..198e07b 100644 --- a/backend/app/repositories/ai_config.py +++ b/backend/app/repositories/ai_config.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/app/repositories/channels/__init__.py b/backend/app/repositories/channels/__init__.py index 371793d..0be7c66 100644 --- a/backend/app/repositories/channels/__init__.py +++ b/backend/app/repositories/channels/__init__.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/app/repositories/channels/accounts.py b/backend/app/repositories/channels/accounts.py index 6745cb4..cdcd1f1 100644 --- a/backend/app/repositories/channels/accounts.py +++ b/backend/app/repositories/channels/accounts.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/app/repositories/channels/agent_config.py b/backend/app/repositories/channels/agent_config.py index fba1c45..1b8dd97 100644 --- a/backend/app/repositories/channels/agent_config.py +++ b/backend/app/repositories/channels/agent_config.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/app/repositories/channels/conversations.py b/backend/app/repositories/channels/conversations.py index 7b53ef6..2bd28c0 100644 --- a/backend/app/repositories/channels/conversations.py +++ b/backend/app/repositories/channels/conversations.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/app/repositories/chat.py b/backend/app/repositories/chat.py index 32d00f1..5404b52 100644 --- a/backend/app/repositories/chat.py +++ b/backend/app/repositories/chat.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/app/repositories/crm.py b/backend/app/repositories/crm.py index fb28da6..c2c1793 100644 --- a/backend/app/repositories/crm.py +++ b/backend/app/repositories/crm.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/app/repositories/customer.py b/backend/app/repositories/customer.py index 8407765..5ba2d2c 100644 --- a/backend/app/repositories/customer.py +++ b/backend/app/repositories/customer.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/app/repositories/faq.py b/backend/app/repositories/faq.py index ed18dc9..1ac1f47 100644 --- a/backend/app/repositories/faq.py +++ b/backend/app/repositories/faq.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/app/repositories/faq_generation_job.py b/backend/app/repositories/faq_generation_job.py index eb149ea..b0993a6 100644 --- a/backend/app/repositories/faq_generation_job.py +++ b/backend/app/repositories/faq_generation_job.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/app/repositories/fcm_token.py b/backend/app/repositories/fcm_token.py index d9d7fa1..503aa70 100644 --- a/backend/app/repositories/fcm_token.py +++ b/backend/app/repositories/fcm_token.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/app/repositories/file_attachment.py b/backend/app/repositories/file_attachment.py index 50d793e..a4e42a1 100644 --- a/backend/app/repositories/file_attachment.py +++ b/backend/app/repositories/file_attachment.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/app/repositories/group.py b/backend/app/repositories/group.py index 7217ccf..7e02f67 100644 --- a/backend/app/repositories/group.py +++ b/backend/app/repositories/group.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/app/repositories/guardrail_event.py b/backend/app/repositories/guardrail_event.py index 93e2979..654a5d3 100644 --- a/backend/app/repositories/guardrail_event.py +++ b/backend/app/repositories/guardrail_event.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/app/repositories/help_center.py b/backend/app/repositories/help_center.py index 2c22841..ae1705f 100644 --- a/backend/app/repositories/help_center.py +++ b/backend/app/repositories/help_center.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/app/repositories/jira.py b/backend/app/repositories/jira.py index 30aa35d..df729a9 100644 --- a/backend/app/repositories/jira.py +++ b/backend/app/repositories/jira.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/app/repositories/knowledge.py b/backend/app/repositories/knowledge.py index f044c6e..fed4c37 100644 --- a/backend/app/repositories/knowledge.py +++ b/backend/app/repositories/knowledge.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/app/repositories/knowledge_queue.py b/backend/app/repositories/knowledge_queue.py index 34bef4f..a2bdcd7 100644 --- a/backend/app/repositories/knowledge_queue.py +++ b/backend/app/repositories/knowledge_queue.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/app/repositories/knowledge_to_agent.py b/backend/app/repositories/knowledge_to_agent.py index 42bd8c7..90bc3ed 100644 --- a/backend/app/repositories/knowledge_to_agent.py +++ b/backend/app/repositories/knowledge_to_agent.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/app/repositories/lead_capture.py b/backend/app/repositories/lead_capture.py index 598efd2..1561d73 100644 --- a/backend/app/repositories/lead_capture.py +++ b/backend/app/repositories/lead_capture.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/app/repositories/mcp_tool.py b/backend/app/repositories/mcp_tool.py index b67b672..568ef43 100644 --- a/backend/app/repositories/mcp_tool.py +++ b/backend/app/repositories/mcp_tool.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/app/repositories/notification_settings.py b/backend/app/repositories/notification_settings.py index eb9376a..19812b3 100644 --- a/backend/app/repositories/notification_settings.py +++ b/backend/app/repositories/notification_settings.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/app/repositories/organization.py b/backend/app/repositories/organization.py index d30d916..e0b1392 100644 --- a/backend/app/repositories/organization.py +++ b/backend/app/repositories/organization.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/app/repositories/people.py b/backend/app/repositories/people.py index d4c6e43..0afee7a 100644 --- a/backend/app/repositories/people.py +++ b/backend/app/repositories/people.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/app/repositories/rating.py b/backend/app/repositories/rating.py index 9a13176..3796369 100644 --- a/backend/app/repositories/rating.py +++ b/backend/app/repositories/rating.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/app/repositories/role.py b/backend/app/repositories/role.py index d403a8e..c30b271 100644 --- a/backend/app/repositories/role.py +++ b/backend/app/repositories/role.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/app/repositories/session_to_agent.py b/backend/app/repositories/session_to_agent.py index 9a5354f..c2a9861 100644 --- a/backend/app/repositories/session_to_agent.py +++ b/backend/app/repositories/session_to_agent.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/app/repositories/shopify_shop_repository.py b/backend/app/repositories/shopify_shop_repository.py index 1fcf841..e19a3de 100644 --- a/backend/app/repositories/shopify_shop_repository.py +++ b/backend/app/repositories/shopify_shop_repository.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/app/repositories/ticket.py b/backend/app/repositories/ticket.py index 34a56e4..daef687 100644 --- a/backend/app/repositories/ticket.py +++ b/backend/app/repositories/ticket.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/app/repositories/user.py b/backend/app/repositories/user.py index 7fe403e..240bc24 100644 --- a/backend/app/repositories/user.py +++ b/backend/app/repositories/user.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/app/repositories/user_group.py b/backend/app/repositories/user_group.py index b94823b..6c6f2b1 100644 --- a/backend/app/repositories/user_group.py +++ b/backend/app/repositories/user_group.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/app/repositories/widget.py b/backend/app/repositories/widget.py index 0798184..76d3299 100644 --- a/backend/app/repositories/widget.py +++ b/backend/app/repositories/widget.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/app/repositories/widget_app.py b/backend/app/repositories/widget_app.py index 17fdb4e..c0f6232 100644 --- a/backend/app/repositories/widget_app.py +++ b/backend/app/repositories/widget_app.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/app/repositories/workflow.py b/backend/app/repositories/workflow.py index b476e09..db7b694 100644 --- a/backend/app/repositories/workflow.py +++ b/backend/app/repositories/workflow.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/app/repositories/workflow_node.py b/backend/app/repositories/workflow_node.py index 847e812..7ab7383 100644 --- a/backend/app/repositories/workflow_node.py +++ b/backend/app/repositories/workflow_node.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/app/services/agent_rooms.py b/backend/app/services/agent_rooms.py index 98eaaf9..3bf7455 100644 --- a/backend/app/services/agent_rooms.py +++ b/backend/app/services/agent_rooms.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/app/services/app_first_routing.py b/backend/app/services/app_first_routing.py index da1e772..58ee29f 100644 --- a/backend/app/services/app_first_routing.py +++ b/backend/app/services/app_first_routing.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/app/services/auth_sessions.py b/backend/app/services/auth_sessions.py index 4c4d458..6177004 100644 --- a/backend/app/services/auth_sessions.py +++ b/backend/app/services/auth_sessions.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/app/services/business_message.py b/backend/app/services/business_message.py index b5de4b5..f1be9f8 100644 --- a/backend/app/services/business_message.py +++ b/backend/app/services/business_message.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/app/services/channel_chat.py b/backend/app/services/channel_chat.py index ddea7b9..51f0b7b 100644 --- a/backend/app/services/channel_chat.py +++ b/backend/app/services/channel_chat.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -454,7 +454,7 @@ def _store_customer_message(db: Session, inbound: InboundMessage, session_record async def _within_message_limit(db: Session, org_id: str, ai_config) -> bool: """Enterprise subscription limit; permissive on any failure so the community edition and enterprise errors never block conversations.""" - if not (HAS_ENTERPRISE and ai_config.model_type == AIModelType.CHATTERMATE): + if not (HAS_ENTERPRISE and ai_config.model_type == AIModelType.REPLYPIER): return True try: return await check_message_limit(db, org_id, None, None) diff --git a/backend/app/services/channel_replies.py b/backend/app/services/channel_replies.py index 6621504..db36a37 100644 --- a/backend/app/services/channel_replies.py +++ b/backend/app/services/channel_replies.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/app/services/channel_status.py b/backend/app/services/channel_status.py index 22e4bcc..bdc6743 100644 --- a/backend/app/services/channel_status.py +++ b/backend/app/services/channel_status.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -68,7 +68,7 @@ async def process_status_event(account_id: UUID, event: StatusEvent) -> None: if account is None: return # Announced before matching: extensions count every receipt, including - # ones for messages ChatterMate never stored. + # ones for messages ReplyPier never stored. await emit_channel_event(ChannelEvent( kind=EventKind.STATUS, event_id=status_event_id(account.id, event.external_message_id, event.status.value), diff --git a/backend/app/services/chat_notifications.py b/backend/app/services/chat_notifications.py index ab2e163..72ce3fb 100644 --- a/backend/app/services/chat_notifications.py +++ b/backend/app/services/chat_notifications.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/app/services/chat_scope_roles.py b/backend/app/services/chat_scope_roles.py index 0d8a3ac..f4949a6 100644 --- a/backend/app/services/chat_scope_roles.py +++ b/backend/app/services/chat_scope_roles.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/app/services/contact_capture.py b/backend/app/services/contact_capture.py index 4bb5961..0d7aedb 100644 --- a/backend/app/services/contact_capture.py +++ b/backend/app/services/contact_capture.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/app/services/conversation_token.py b/backend/app/services/conversation_token.py index dfde722..a95c3d1 100644 --- a/backend/app/services/conversation_token.py +++ b/backend/app/services/conversation_token.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/app/services/crm_sync.py b/backend/app/services/crm_sync.py index 15e7041..0d5f8f6 100644 --- a/backend/app/services/crm_sync.py +++ b/backend/app/services/crm_sync.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/app/services/crm_tokens.py b/backend/app/services/crm_tokens.py index d2f8ef1..67ddfc9 100644 --- a/backend/app/services/crm_tokens.py +++ b/backend/app/services/crm_tokens.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/app/services/db_connector_service.py b/backend/app/services/db_connector_service.py index 077cc25..8342a71 100644 --- a/backend/app/services/db_connector_service.py +++ b/backend/app/services/db_connector_service.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/app/services/domain_verification.py b/backend/app/services/domain_verification.py index 6450133..e30cb59 100644 --- a/backend/app/services/domain_verification.py +++ b/backend/app/services/domain_verification.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -16,7 +16,7 @@ limitations under the License. Custom-domain verification for the public help center. The customer proves control of the domain with a TXT record -(_chattermate. = cm-verify=) and routes traffic with a CNAME +(_replypier. = rp-verify=) and routes traffic with a CNAME to HELP_CENTER_CNAME_TARGET (A/AAAA records matching HELP_CENTER_TARGET_IPS are accepted for providers that flatten CNAMEs). Both must pass before the host dispatcher will ever serve the domain. SSL turns active once an HTTPS @@ -38,7 +38,7 @@ logger = get_logger(__name__) DNS_LIFETIME_SECONDS = 5.0 SSL_PROBE_TIMEOUT_SECONDS = 10.0 -TXT_RECORD_PREFIX = "_chattermate" +TXT_RECORD_PREFIX = "_replypier" # Public resolvers for verification lookups. The container's own resolver is # Docker's embedded DNS (127.0.0.11) for service discovery — it negatively # caches names that didn't exist when first queried (so a TXT added *after* the @@ -60,7 +60,7 @@ def txt_record_host(domain: str) -> str: def expected_txt_value(row: HelpCenterSettings) -> str: - return f"cm-verify={row.domain_verification_token}" + return f"rp-verify={row.domain_verification_token}" def _resolver(): diff --git a/backend/app/services/faq_article_import.py b/backend/app/services/faq_article_import.py index 6a655d3..a7fdc12 100644 --- a/backend/app/services/faq_article_import.py +++ b/backend/app/services/faq_article_import.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -93,7 +93,7 @@ _GENERIC_SECTIONS = frozenset({ # Internal scheme marking images collected during conversion, replaced with the # re-hosted URL afterwards (conversion is sync; storage is async). The trailing # ".img" delimits the index so "…//1.img" is never a prefix of "…//10.img". -_IMG_PLACEHOLDER = "cm-pending-image://{index}.img" +_IMG_PLACEHOLDER = "rp-pending-image://{index}.img" @dataclass diff --git a/backend/app/services/faq_generation.py b/backend/app/services/faq_generation.py index 7e39e11..eeb78db 100644 --- a/backend/app/services/faq_generation.py +++ b/backend/app/services/faq_generation.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/app/services/faq_import.py b/backend/app/services/faq_import.py index fdeeb98..2590f87 100644 --- a/backend/app/services/faq_import.py +++ b/backend/app/services/faq_import.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -55,7 +55,7 @@ _BLOCK_TAGS = ( ) _BOILERPLATE_TAGS = ("script", "style", "noscript", "nav", "footer", "header", "form") -_FETCH_HEADERS = {"User-Agent": "ChatterMate-FAQ-Import/1.0 (+https://chattermate.chat)"} +_FETCH_HEADERS = {"User-Agent": "ReplyPier-FAQ-Import/1.0 (+https://replypier.site)"} def _soup_to_text(soup: BeautifulSoup) -> str: diff --git a/backend/app/services/faq_usage.py b/backend/app/services/faq_usage.py index bf46b56..77d8f52 100644 --- a/backend/app/services/faq_usage.py +++ b/backend/app/services/faq_usage.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/app/services/feature_gate.py b/backend/app/services/feature_gate.py index a24a342..96db4eb 100644 --- a/backend/app/services/feature_gate.py +++ b/backend/app/services/feature_gate.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/app/services/file_storage.py b/backend/app/services/file_storage.py index 09e583f..126697d 100644 --- a/backend/app/services/file_storage.py +++ b/backend/app/services/file_storage.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/app/services/file_upload_service.py b/backend/app/services/file_upload_service.py index 0dd65bc..b75a07d 100644 --- a/backend/app/services/file_upload_service.py +++ b/backend/app/services/file_upload_service.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/app/services/firebase.py b/backend/app/services/firebase.py index 6635950..645fa38 100644 --- a/backend/app/services/firebase.py +++ b/backend/app/services/firebase.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/app/services/help_center_access.py b/backend/app/services/help_center_access.py index ff8a5e3..1be390d 100644 --- a/backend/app/services/help_center_access.py +++ b/backend/app/services/help_center_access.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/app/services/help_center_content.py b/backend/app/services/help_center_content.py index feffaa4..1df4040 100644 --- a/backend/app/services/help_center_content.py +++ b/backend/app/services/help_center_content.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/app/services/help_center_images.py b/backend/app/services/help_center_images.py index cf68203..0d04c5f 100644 --- a/backend/app/services/help_center_images.py +++ b/backend/app/services/help_center_images.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/app/services/help_center_public.py b/backend/app/services/help_center_public.py index 46e729f..8a11fc3 100644 --- a/backend/app/services/help_center_public.py +++ b/backend/app/services/help_center_public.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/app/services/help_center_seo.py b/backend/app/services/help_center_seo.py index 122b979..9d600e7 100644 --- a/backend/app/services/help_center_seo.py +++ b/backend/app/services/help_center_seo.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/app/services/help_center_settings.py b/backend/app/services/help_center_settings.py index c814136..6ffc74e 100644 --- a/backend/app/services/help_center_settings.py +++ b/backend/app/services/help_center_settings.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/app/services/human_routing.py b/backend/app/services/human_routing.py index 2ad02ec..2d7483e 100644 --- a/backend/app/services/human_routing.py +++ b/backend/app/services/human_routing.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/app/services/image_security.py b/backend/app/services/image_security.py index 1689516..ac205b2 100644 --- a/backend/app/services/image_security.py +++ b/backend/app/services/image_security.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/app/services/jira.py b/backend/app/services/jira.py index 9e9491b..9f7668e 100644 --- a/backend/app/services/jira.py +++ b/backend/app/services/jira.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/app/services/knowledge_vector_links.py b/backend/app/services/knowledge_vector_links.py index 31f5bc1..fb99659 100644 --- a/backend/app/services/knowledge_vector_links.py +++ b/backend/app/services/knowledge_vector_links.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/app/services/lead_capture.py b/backend/app/services/lead_capture.py index b743689..712cb27 100644 --- a/backend/app/services/lead_capture.py +++ b/backend/app/services/lead_capture.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/app/services/message_delivery.py b/backend/app/services/message_delivery.py index 092926b..ccde325 100644 --- a/backend/app/services/message_delivery.py +++ b/backend/app/services/message_delivery.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/app/services/meta_own_app.py b/backend/app/services/meta_own_app.py index 949fa97..a29b457 100644 --- a/backend/app/services/meta_own_app.py +++ b/backend/app/services/meta_own_app.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. WhatsApp numbers and Messenger Pages that live in the customer's own Meta -app (connected with manual credentials) rather than in ChatterMate's. +app (connected with manual credentials) rather than in ReplyPier's. Meta signs their webhooks with the customer's app secret, which the shared /webhooks/meta endpoint can't check. So each such account gets its own @@ -95,7 +95,7 @@ async def resolve_own_app(access_token: str, entered_secret: Optional[str], """The customer's own app behind this token, proven with its secret — the one entered, or else the one kept from the last connect (checked again: the new token may be from another app). None without a secret, or - for ChatterMate's own app, whose webhooks the shared address already gets. + for ReplyPier's own app, whose webhooks the shared address already gets. Raises AppSecretMismatch or AppCheckUnavailable.""" secret = entered_secret or (own_app_secret(previous) if previous is not None else None) diff --git a/backend/app/services/notifications.py b/backend/app/services/notifications.py index b29044b..4b46d85 100644 --- a/backend/app/services/notifications.py +++ b/backend/app/services/notifications.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/app/services/public_rate_limit.py b/backend/app/services/public_rate_limit.py index 2c86ad4..71e031f 100644 --- a/backend/app/services/public_rate_limit.py +++ b/backend/app/services/public_rate_limit.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/app/services/sentiment.py b/backend/app/services/sentiment.py index 6b1bf51..df45b22 100644 --- a/backend/app/services/sentiment.py +++ b/backend/app/services/sentiment.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/backend/app/services/shopify.py b/backend/app/services/shopify.py index ab57026..28cf551 100644 --- a/backend/app/services/shopify.py +++ b/backend/app/services/shopify.py @@ -1,5 +1,5 @@ """ -Copyright 2024-2026 ChatterMate +Copyright 2024-2026 ReplyPier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -1144,7 +1144,7 @@ class ShopifyService: async def inject_widget_script(self, shop: ShopifyShop, script_tag: str) -> None: """ - Creates a Shopify Script Tag to inject the ChatterMate widget using the scriptTagCreate GraphQL mutation. + Creates a Shopify Script Tag to inject the ReplyPier widget using the scriptTagCreate GraphQL mutation. Args: shop: The ShopifyShop object. @@ -1158,12 +1158,12 @@ class ShopifyService: # 1. Extract the script URL from the script_tag string # The script_tag is in format: - # + # # We need to extract the script_url import re script_url_match = re.search(r' {% endif %} - + - + diff --git a/deploy/local/init_env.py b/deploy/local/init_env.py index facdaec..7bf3a80 100644 --- a/deploy/local/init_env.py +++ b/deploy/local/init_env.py @@ -26,7 +26,7 @@ def main() -> None: password = compose_env.read_text().strip().split("=", 1)[1] fernet_key = base64.b64encode(base64.urlsafe_b64encode(secrets.token_bytes(32))).decode() settings = { - "DATABASE_URL": f"postgresql+psycopg://chattermate:{password}@127.0.0.1:15432/chattermate", + "DATABASE_URL": f"postgresql+psycopg://replypier:{password}@127.0.0.1:15432/replypier", "REDIS_ENABLED": "true", "REDIS_URL": "redis://127.0.0.1:16380/0", "ENVIRONMENT": "production", diff --git a/deploy/local/local.sh b/deploy/local/local.sh index 4be9aae..d621313 100755 --- a/deploy/local/local.sh +++ b/deploy/local/local.sh @@ -60,10 +60,10 @@ build_frontend() { if [[ ! -f "${STATE}/assets/widget.css" ]]; then cp "${STATE}"/assets/unused/*.css "${STATE}/assets/widget.css" fi - node_modules/.bin/esbuild src/webclient/chattermate.js --bundle --minify --format=iife \ + node_modules/.bin/esbuild src/webclient/replypier.js --bundle --minify --format=iife \ --target=es2015 --loader:.svg=text --define:process.env.NODE_ENV='"production"' \ - --define:__CHATTERMATE_API_URL__='"http://127.0.0.1:8018/api/v1"' \ - --outfile="${STATE}/dashboard/webclient/chattermate.min.js" + --define:__REPLYPIER_API_URL__='"http://127.0.0.1:8018/api/v1"' \ + --outfile="${STATE}/dashboard/webclient/replypier.min.js" cat > "${STATE}/dashboard/config.js" <<'JS' self.APP_CONFIG = { API_URL: "http://127.0.0.1:8018/api/v1", @@ -112,7 +112,7 @@ case "${1:-status}" in colima --profile bytedesk start --activate=false --ssh-config=false fi compose up -d --wait --wait-timeout 180 - compose exec -T db psql -U chattermate -d chattermate -c 'CREATE EXTENSION IF NOT EXISTS vector;' + compose exec -T db psql -U replypier -d replypier -c 'CREATE EXTENSION IF NOT EXISTS vector;' (cd "${ROOT}/backend" && "${PYTHON}" -m alembic upgrade head) start_process backend "${ROOT}/backend" "${PYTHON}" -m uvicorn app.main:app --host 127.0.0.1 --port 8018 start_process knowledge "${ROOT}/backend" "${PYTHON}" -m app.workers.run_knowledge_processor diff --git a/deploy/server/README.md b/deploy/server/README.md index 9d19691..968c5fc 100644 --- a/deploy/server/README.md +++ b/deploy/server/README.md @@ -9,7 +9,7 @@ 1. 为服务器创建专用 SSH 密钥,将**公钥**添加为 Gitea 仓库的只读部署密钥;私钥留在 `/etc/replypier-updater/id_ed25519`,权限 `600`。通过可信渠道核实 Gitea 主机公钥并保存为同目录的 `known_hosts`。更新过程不使用账号密码或浏览器登录态。 2. 按 `config.example.json` 准备私有配置,填写当前安装提交和部署管理员用户 UUID。只有名单中的用户且持有 `super_admin` 权限才能更新;其他组织的管理员无权更新整个服务器。配置和 SSH 私钥不入库。 3. 以 root 执行 `./deploy/server/install-updater.sh /path/to/config.json`,然后执行 `python3 /opt/replypier-updater/cli.py check`。安装不会重置应用环境或数据库。 -4. Caddy 对稳定文件名的入口返回 `Cache-Control: no-cache, no-store, must-revalidate`:`/sw.js`、`/manifest.webmanifest`、`/config.js`、`/assets/widget.js`、`/assets/widget.css`、`/webclient/chattermate.min.js`。首次设置后,清除 CDN 中这些 URL 的已有缓存;带内容版本号的构建资源可以正常缓存。不要缓存 HTML 入口。 +4. Caddy 对稳定文件名的入口返回 `Cache-Control: no-cache, no-store, must-revalidate`:`/sw.js`、`/manifest.webmanifest`、`/config.js`、`/assets/widget.js`、`/assets/widget.css`、`/webclient/replypier.min.js`。首次设置后,清除 CDN 中这些 URL 的已有缓存;带内容版本号的构建资源可以正常缓存。不要缓存 HTML 入口。 ## 更新时发生什么 diff --git a/deploy/server/config.example.json b/deploy/server/config.example.json index 2e0bb24..6d71fb6 100644 --- a/deploy/server/config.example.json +++ b/deploy/server/config.example.json @@ -9,7 +9,7 @@ "known_hosts": "/etc/replypier-updater/known_hosts", "owner_ids": ["REPLACE_WITH_DEPLOYMENT_OWNER_USER_ID"], "initial_revision": "REPLACE_WITH_INSTALLED_COMMIT", - "db_container": "chattermate-local-db-1", - "db_user": "chattermate", - "db_name": "chattermate" + "db_container": "replypier-local-db-1", + "db_user": "replypier", + "db_name": "replypier" } diff --git a/deploy/server/updater/deployment.py b/deploy/server/updater/deployment.py index 788951c..7bc5f88 100644 --- a/deploy/server/updater/deployment.py +++ b/deploy/server/updater/deployment.py @@ -100,12 +100,12 @@ class Deployment: if len(styles) != 1: raise RuntimeError('网站组件的样式构建结果不完整。') shutil.copy2(styles[0], stage / 'assets/widget.css') - loader = stage / 'dashboard/webclient/chattermate.min.js' + loader = stage / 'dashboard/webclient/replypier.min.js' loader.parent.mkdir(exist_ok=True) - self.run([str(front / 'node_modules/.bin/esbuild'), 'src/webclient/chattermate.js', + self.run([str(front / 'node_modules/.bin/esbuild'), 'src/webclient/replypier.js', '--bundle', '--minify', '--format=iife', '--target=es2015', '--loader:.svg=text', '--define:process.env.NODE_ENV="production"', - '--define:__CHATTERMATE_API_URL__=' + json.dumps(self.cfg['public_url'] + '/api/v1'), + '--define:__REPLYPIER_API_URL__=' + json.dumps(self.cfg['public_url'] + '/api/v1'), '--outfile=' + str(loader)], cwd=front) # Runtime configuration belongs to this installation, not to the repository. live_web = self.root / 'deploy/local/.state/dashboard' diff --git a/design/brand-refresh/README.md b/design/brand-refresh/README.md index e2cdf9f..803fc20 100644 --- a/design/brand-refresh/README.md +++ b/design/brand-refresh/README.md @@ -18,14 +18,14 @@ - Browser icon: `frontend/public/favicon.svg`; duplicate `frontend/public/assets/favicon.svg`; ICO fallbacks at both locations. - Brand mark: `frontend/src/assets/logo.svg`, `frontend/public/images/logo.svg`, `frontend/public/assets/images/logo.svg`, `logo_dark.svg`. -- Footer marks: shared `frontend/src/components/common/BrandMark.vue`; `frontend/src/webclient/chattermate.js` imports the same source SVG for its error footer. +- Footer marks: shared `frontend/src/components/common/BrandMark.vue`; `frontend/src/webclient/replypier.js` imports the same source SVG for its error footer. - Preset portraits: 12 PNGs in `frontend/src/assets/avatars/avatar-*.png`; selected through `AgentDetail.vue`. - Paper-craft avatars: ten SVGs under `frontend/src/assets/avatars/paper-*.svg`; loaded by `frontend/src/utils/orb.ts` under the original stored variant indexes. Old generated data URIs are refreshed from avatar metadata at render time. Uploaded photos remain unchanged. - Additional candidates: PWA/install icons, default user/robot and role avatars, login/signup illustration. Third-party integration logos should retain official identities. ## Design constraints -Use existing ink/porcelain foundation: paper #F4F1EB, ink #16171A, vermilion #B23A22, celadon #2E6A5C, brass #8A6326. Keep 16px brand marks simple and readable. No change to customer-uploaded images or unrelated UI. Visible product naming currently mixes ReplyPier and ChatterMate; do not infer a full rename from the asset request. +Use existing ink/porcelain foundation: paper #F4F1EB, ink #16171A, vermilion #B23A22, celadon #2E6A5C, brass #8A6326. Keep 16px brand marks simple and readable. No change to customer-uploaded images or unrelated UI. Product naming is ReplyPier throughout (UI, code identifiers, docs); the old upstream name was purged in one pass, so any remaining trace is a bug worth fixing. ## Concepts diff --git a/docker-compose.prod.yml b/docker-compose.prod.yml index bfc1dae..d2e4b87 100644 --- a/docker-compose.prod.yml +++ b/docker-compose.prod.yml @@ -2,7 +2,7 @@ version: '3.8' services: frontend: - image: chattermate/frontend:latest + image: replypier/frontend:latest ports: - "80:80" env_file: @@ -10,11 +10,11 @@ services: depends_on: - backend networks: - - chattermate-network + - replypier-network restart: unless-stopped backend: - image: chattermate/backend:latest + image: replypier/backend:latest ports: - "8000:8000" environment: @@ -41,7 +41,7 @@ services: redis: condition: service_healthy networks: - - chattermate-network + - replypier-network restart: unless-stopped volumes: - backend_data:/app/uploads @@ -57,7 +57,7 @@ services: start_period: 10s knowledge_processor: - image: chattermate/backend:latest + image: replypier/backend:latest command: python -m app.workers.knowledge_processor environment: - REDIS_ENABLED=true @@ -83,7 +83,7 @@ services: redis: condition: service_healthy networks: - - chattermate-network + - replypier-network restart: always volumes: - backend_data:/app/uploads @@ -98,7 +98,7 @@ services: max-file: "3" crm_sync: - image: chattermate/backend:latest + image: replypier/backend:latest command: python -m app.workers.crm_sync environment: - LOG_LEVEL=info @@ -109,7 +109,7 @@ services: db: condition: service_healthy networks: - - chattermate-network + - replypier-network restart: always logging: driver: "json-file" @@ -118,7 +118,7 @@ services: max-file: "3" ticket_investigator: - image: chattermate/backend:latest + image: replypier/backend:latest command: python -m app.workers.ticket_investigator environment: - REDIS_ENABLED=true @@ -137,7 +137,7 @@ services: redis: condition: service_healthy networks: - - chattermate-network + - replypier-network restart: always volumes: - huggingface_cache:/app/.cache/huggingface @@ -156,11 +156,11 @@ services: environment: - POSTGRES_USER=postgres - POSTGRES_PASSWORD=postgres - - POSTGRES_DB=chattermate + - POSTGRES_DB=replypier volumes: - postgres_data:/var/lib/postgresql/data networks: - - chattermate-network + - replypier-network restart: unless-stopped healthcheck: test: ["CMD-SHELL", "pg_isready -U postgres"] @@ -176,7 +176,7 @@ services: volumes: - redis_data:/data networks: - - chattermate-network + - replypier-network restart: unless-stopped healthcheck: test: ["CMD", "redis-cli", "ping"] @@ -187,7 +187,7 @@ services: command: redis-server --appendonly yes --maxmemory 512mb --maxmemory-policy allkeys-lru networks: - chattermate-network: + replypier-network: driver: bridge volumes: diff --git a/docker-compose.yml b/docker-compose.yml index f29ce5b..7a28e93 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -176,7 +176,7 @@ services: ports: - "5432:5432" environment: - - POSTGRES_DB=chattermate + - POSTGRES_DB=replypier - POSTGRES_USER=postgres - POSTGRES_PASSWORD=postgres volumes: diff --git a/e2e/.env.e2e b/e2e/.env.e2e index 7da81d9..c207bd6 100644 --- a/e2e/.env.e2e +++ b/e2e/.env.e2e @@ -4,7 +4,7 @@ # NO_ENTERPRISE and the real DATABASE_URL are exported by stack.sh (they depend on # the edition and the local Postgres). This placeholder points nowhere, so a backend # started without stack.sh fails fast instead of falling back to the dev database. -DATABASE_URL=postgresql+psycopg://set-by-stack-sh@127.0.0.1:1/chattermate_e2e +DATABASE_URL=postgresql+psycopg://set-by-stack-sh@127.0.0.1:1/replypier_e2e ENVIRONMENT=test JWT_SECRET_KEY=e2e-jwt-secret-not-for-production @@ -35,7 +35,7 @@ FIREBASE_CREDENTIALS=/nonexistent/firebase-config.json AWS_ACCESS_KEY_ID= AWS_SECRET_ACCESS_KEY= -# Providers that ignore the org's base_url (e.g. the CHATTERMATE default model) +# Providers that ignore the org's base_url (e.g. the REPLYPIER default model) # still land on the fake LLM through the openai SDK's env fallback. OPENAI_BASE_URL=http://127.0.0.1:14010/v1 OPENAI_API_KEY=e2e-fake-key diff --git a/e2e/AUTHORING.md b/e2e/AUTHORING.md index 2aad12e..f224744 100644 --- a/e2e/AUTHORING.md +++ b/e2e/AUTHORING.md @@ -1,4 +1,4 @@ -# ChatterMate end-to-end tests +# ReplyPier end-to-end tests Playwright tests that drive the real dashboard, the real widget and the real backend. @@ -43,7 +43,7 @@ npx playwright test # reuses the running stack ``` **Safety:** -- `stack.sh` only ever manages `chattermate_e2e` and its template `chattermate_e2e_tpl`. It refuses any database name that does not end in `_e2e`. +- `stack.sh` only ever manages `replypier_e2e` and its template `replypier_e2e_tpl`. It refuses any database name that does not end in `_e2e`. - The backend reads only `e2e/.env.e2e` (through `ENV_FILE`), never `backend/.env`. - The OSS edition runs with `NO_ENTERPRISE=1`, and the dashboard is built without `src/modules/enterprise`, so it behaves like a community install even in a checkout that has the submodules. @@ -168,4 +168,4 @@ A journey that should hold on every channel loops over `channels` (or `channelsW - **Port already in use:** something else is on 18000, 15173, 14010, 14020, 14030, 13000, 11025 or 18025. Run `./scripts/stack.sh down`, or stop the other process. - **The launcher never becomes clickable:** the suite runs with `reducedMotion: 'reduce'` because the launcher floats forever otherwise. Keep that option on any new browser context. - **The customer site must be a real server:** Chrome blocks a page faked with `page.route` from calling `127.0.0.1` (Local Network Access). -- **The widget and loader are built from source on every run.** `stack.sh` builds the widget bundle and `chattermate.min.js` from the current `frontend/src/webclient` into `e2e/.cache`, and points the backend at that build with `WIDGET_ASSETS_DIR`. The committed production bundles in `backend/assets` and `frontend/public/webclient` are never rebuilt or modified. +- **The widget and loader are built from source on every run.** `stack.sh` builds the widget bundle and `replypier.min.js` from the current `frontend/src/webclient` into `e2e/.cache`, and points the backend at that build with `WIDGET_ASSETS_DIR`. The committed production bundles in `backend/assets` and `frontend/public/webclient` are never rebuilt or modified. diff --git a/e2e/FEATURES.md b/e2e/FEATURES.md index 7284a6f..92afce8 100644 --- a/e2e/FEATURES.md +++ b/e2e/FEATURES.md @@ -21,7 +21,7 @@ One row per user journey. Every feature PR adds or updates its row and the spec | Widget chat | Email-first agent (gate → chat, person recorded), Ask anything panel, lead capture with no email asked — each also with the first authorization lost | `specs/widget/chat-styles.spec.ts` | P1 | ✅ | | Widget chat | Agent wraps up → customer rates the chat → rating stored against the agent | `specs/widget/rating.spec.ts` | P1 | ✅ | | Widget chat | A second browser that types a customer's email gets its own empty conversation (the owner keeps theirs), can't rename them or make them a lead, and an address claimed before its owner signs in yields none of their chats | `specs/widget/conversation-ownership.spec.ts` | P1 | ✅ | -| Widget chat | Scoping keeps a visitor's own conversation: a second tab joins it; a visitor the site signed in finds it in another browser, and after `ChatterMate.identify()` | `specs/widget/conversation-ownership.spec.ts` | P1 | ✅ | +| Widget chat | Scoping keeps a visitor's own conversation: a second tab joins it; a visitor the site signed in finds it in another browser, and after `ReplyPier.identify()` | `specs/widget/conversation-ownership.spec.ts` | P1 | ✅ | | Widget chat | Provider error, provider timeout and malformed reply each end in an apology; the next message works | `specs/widget/ai-failures.spec.ts` | P1 | ✅ | | Human handover | AI hands over → contact form → agent takes over → two-way messages → the AI stays silent | `specs/handover/handover.spec.ts` | P1 | ✅ | | Human handover | After hours, or nobody online: the chat waits in the team's queue with a reply that says so | `specs/handover/after-hours.org.spec.ts`, `nobody-online.spec.ts` | P1 | ✅ | diff --git a/e2e/package-lock.json b/e2e/package-lock.json index 699ab25..bf14a1f 100644 --- a/e2e/package-lock.json +++ b/e2e/package-lock.json @@ -1,10 +1,10 @@ { - "name": "chattermate-e2e", + "name": "replypier-e2e", "lockfileVersion": 3, "requires": true, "packages": { "": { - "name": "chattermate-e2e", + "name": "replypier-e2e", "devDependencies": { "@axe-core/playwright": "4.13.0", "@modelcontextprotocol/sdk": "1.30.1", diff --git a/e2e/package.json b/e2e/package.json index 2e97f3b..68c7e0e 100644 --- a/e2e/package.json +++ b/e2e/package.json @@ -1,8 +1,8 @@ { - "name": "chattermate-e2e", + "name": "replypier-e2e", "private": true, "type": "module", - "description": "End-to-end tests for ChatterMate (dashboard, widget, backend) — see AUTHORING.md", + "description": "End-to-end tests for ReplyPier (dashboard, widget, backend) — see AUTHORING.md", "engines": { "node": ">=22.18" }, diff --git a/e2e/scripts/stack.sh b/e2e/scripts/stack.sh index eed51e5..f8222ba 100755 --- a/e2e/scripts/stack.sh +++ b/e2e/scripts/stack.sh @@ -1,5 +1,5 @@ #!/usr/bin/env bash -# Runs the ChatterMate e2e stack natively (no Docker): a throwaway Postgres DB, +# Runs the ReplyPier e2e stack natively (no Docker): a throwaway Postgres DB, # the backend, a production build of the dashboard and the fake LLM — all on # 127.0.0.1 ports that never collide with a dev stack on localhost. # @@ -39,7 +39,7 @@ CACHE_DIR="$E2E_DIR/.cache" export FASTEMBED_CACHE_PATH="${FASTEMBED_CACHE_PATH:-$CACHE_DIR/fastembed}" EDITION="${E2E_EDITION:-oss}" -DB_NAME="chattermate_e2e" +DB_NAME="replypier_e2e" TPL_NAME="${DB_NAME}_tpl" PG_URL="${E2E_PG_URL:-postgresql://${USER}@127.0.0.1:5432}" PG_URL="${PG_URL%/}" @@ -172,7 +172,7 @@ sync_frontend_copy() { mkdir -p "$dest" # The loader bundle is generated inside the copy (build_loader), so keep rsync off it. local excludes=(--exclude node_modules --exclude 'dist*' --exclude '.env*' --exclude e2e --exclude coverage - --exclude public/webclient/chattermate.min.js) + --exclude public/webclient/replypier.min.js) if [[ "$EDITION" == oss ]]; then excludes+=(--exclude src/modules/enterprise); fi rsync -a --delete -i "${excludes[@]}" "$REPO_DIR/frontend/" "$dest/" ln -sfn "$NODE_MODULES" "$dest/node_modules" @@ -192,15 +192,15 @@ build_widget() { find "$out" -mindepth 1 -maxdepth 1 ! -name widget.js ! -name widget.css -exec rm -rf {} + } -# The embed loader (chattermate.min.js), built from source into the dashboard copy's +# The embed loader (replypier.min.js), built from source into the dashboard copy's # public/ so vite ships it in the build — what build-webclient-*.ts does. build_loader() { local src="$1" - (cd "$src" && node_modules/.bin/esbuild src/webclient/chattermate.js --bundle --minify --format=iife \ + (cd "$src" && node_modules/.bin/esbuild src/webclient/replypier.js --bundle --minify --format=iife \ --target=es2015 --loader:.svg=text --log-level=warning \ --define:process.env.NODE_ENV='"production"' \ - --define:__CHATTERMATE_API_URL__="\"http://127.0.0.1:$BACKEND_PORT/api/v1\"" \ - --outfile=public/webclient/chattermate.min.js) >&2 + --define:__REPLYPIER_API_URL__="\"http://127.0.0.1:$BACKEND_PORT/api/v1\"" \ + --outfile=public/webclient/replypier.min.js) >&2 } # One copy of frontend/ feeds all three builds: loader, widget, dashboard. @@ -250,7 +250,7 @@ run_customer_site() { cd "$E2E_DIR" exec node services/customer-site/server.ts --port "$CUSTOMER_SITE_PORT" \ --api "http://127.0.0.1:$BACKEND_PORT/api/v1" \ - --loader "http://127.0.0.1:$FRONTEND_PORT/webclient/chattermate.min.js" + --loader "http://127.0.0.1:$FRONTEND_PORT/webclient/replypier.min.js" } # SMTP capture (Mailpit): everything the backend emails — email-channel replies, diff --git a/e2e/scripts/upgrade-check.sh b/e2e/scripts/upgrade-check.sh index c86c7b5..a39bda7 100755 --- a/e2e/scripts/upgrade-check.sh +++ b/e2e/scripts/upgrade-check.sh @@ -13,8 +13,8 @@ set -euo pipefail E2E_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" REPO_DIR="$(cd "$E2E_DIR/.." && pwd)" PG_URL="${E2E_PG_URL:-postgresql://${USER}@127.0.0.1:5432}"; PG_URL="${PG_URL%/}" -DB_NAME="chattermate_upgrade_e2e" -FRESH_DB="chattermate_fresh_e2e" +DB_NAME="replypier_upgrade_e2e" +FRESH_DB="replypier_fresh_e2e" BASE_REF="${1:-$(git -C "$REPO_DIR" describe --tags --abbrev=0 --match 'v*')}" if [[ -z "${E2E_PYTHON:-}" ]]; then if [[ -x "$REPO_DIR/backend/venv/bin/python" ]]; then E2E_PYTHON="$REPO_DIR/backend/venv/bin/python"; else E2E_PYTHON="python3"; fi diff --git a/e2e/services/customer-site/server.ts b/e2e/services/customer-site/server.ts index 36b66c7..4c5d549 100644 --- a/e2e/services/customer-site/server.ts +++ b/e2e/services/customer-site/server.ts @@ -1,11 +1,11 @@ -// A pretend customer website with the ChatterMate widget embedded the way the +// A pretend customer website with the ReplyPier widget embedded the way the // dashboard's install snippet does it. Everything about the embed comes from the // query string: // // http://127.0.0.1:13000/?widget= -// &config= → window.chattermateConfig (launcher, position, trigger, …) -// &token= → window.chattermateToken (token-authenticated widgets) -// &trigger=1 → adds a page button with data-chattermate-open +// &config= → window.replypierConfig (launcher, position, trigger, …) +// &token= → window.replypierToken (token-authenticated widgets) +// &trigger=1 → adds a page button with data-replypier-open // &snippet=iframe → the dashboard's iframe snippet instead of the script // // It has to be a real server on 127.0.0.1: Chrome's Local Network Access check @@ -23,7 +23,7 @@ function arg(name: string, fallback: string): string { const port = Number(arg('port', '13000')) const apiUrl = arg('api', 'http://127.0.0.1:18000/api/v1') -const loaderUrl = arg('loader', 'http://127.0.0.1:15173/webclient/chattermate.min.js') +const loaderUrl = arg('loader', 'http://127.0.0.1:15173/webclient/replypier.min.js') interface Embed { widgetId: string @@ -36,7 +36,7 @@ interface Embed { /** The dashboard's iframe snippet (AgentWidgetTab), classed so the page object finds it. */ function iframeSnippet(widgetId: string): string { const src = `${apiUrl}/widgets/${encodeURIComponent(widgetId)}/data` - return `` + return `` } function page(embed: Embed): string { @@ -51,18 +51,18 @@ function page(embed: Embed): string { ` } const globals = [ - `window.chattermateId = ${JSON.stringify(embed.widgetId)};`, - `window.chattermateBaseUrl = ${JSON.stringify(apiUrl)};`, + `window.replypierId = ${JSON.stringify(embed.widgetId)};`, + `window.replypierBaseUrl = ${JSON.stringify(apiUrl)};`, // config arrives as JSON text; parse it here so a malformed value fails the request, not the page. - embed.config ? `window.chattermateConfig = ${JSON.stringify(JSON.parse(embed.config))};` : '', - embed.token ? `window.chattermateToken = ${JSON.stringify(embed.token)};` : '', + embed.config ? `window.replypierConfig = ${JSON.stringify(JSON.parse(embed.config))};` : '', + embed.token ? `window.replypierToken = ${JSON.stringify(embed.token)};` : '', ].filter(Boolean).join('\n ') return ` Acme Store

Acme Store

- ${embed.trigger ? '' : ''} + ${embed.trigger ? '' : ''} diff --git a/e2e/services/fake-externals/server.ts b/e2e/services/fake-externals/server.ts index d536a73..120baa1 100644 --- a/e2e/services/fake-externals/server.ts +++ b/e2e/services/fake-externals/server.ts @@ -23,7 +23,7 @@ // Meta tokens `…:app=.:…` were issued by the customer's own Meta // app: GET /app answers that id and checks // appsecret_proof against that secret (any -// other token is ChatterMate's app) +// other token is ReplyPier's app) // Meta POST / {webhook_configuration} verifies the override callback the way // Meta does — a GET with hub.verify_token // that must echo hub.challenge — before @@ -188,13 +188,13 @@ function graphError(message: string, code = 100): Answer { return { status: 400, body: { error: { message, type: 'OAuthException', code, fbtrace_id: 'e2e' } } } } -/** ChatterMate's own Meta app; its secret mirrors META_APP_SECRET in .env.e2e. */ -const CHATTERMATE_APP = { id: 'e2e-chattermate-app', secret: 'e2e-meta-app-secret' } +/** ReplyPier's own Meta app; its secret mirrors META_APP_SECRET in .env.e2e. */ +const REPLYPIER_APP = { id: 'e2e-replypier-app', secret: 'e2e-meta-app-secret' } /** The Meta app that issued a token. */ function appOf(token: string): { id: string; secret: string } { const match = /:app=([^.:]+)\.([^:]+)/.exec(token) - return match ? { id: match[1], secret: match[2] } : CHATTERMATE_APP + return match ? { id: match[1], secret: match[2] } : REPLYPIER_APP } /** Meta checks an override callback before taking it: the GET must echo the challenge. */ diff --git a/e2e/services/fake-llm/server.ts b/e2e/services/fake-llm/server.ts index bec21aa..fe74cfe 100644 --- a/e2e/services/fake-llm/server.ts +++ b/e2e/services/fake-llm/server.ts @@ -5,7 +5,7 @@ // replies keyed by a `[[e2e:]]` marker in its agent's instructions or by the // agent's unique name — so parallel tests in one org never see each other's script. // -// It speaks only what ChatterMate uses: non-streaming /v1/chat/completions, with or +// It speaks only what ReplyPier uses: non-streaming /v1/chat/completions, with or // without a strict json_schema response_format (ChatAgent's ChatResponse), and tool // calls. Anything else fails loudly instead of returning something plausible. // @@ -245,7 +245,7 @@ async function route(req: IncomingMessage, res: ServerResponse) { throw new HttpError(401, 'Incorrect API key provided.') } const body = (await readJson(req)) as ChatRequest - if (body.stream) throw new HttpError(400, 'the e2e fake LLM does not stream — ChatterMate never asks it to; if it does now, extend services/fake-llm') + if (body.stream) throw new HttpError(400, 'the e2e fake LLM does not stream — ReplyPier never asks it to; if it does now, extend services/fake-llm') if (!Array.isArray(body.messages)) throw new HttpError(400, 'messages[] is required') return send(res, 200, await answer(body, req.headers.authorization ?? '')) } diff --git a/e2e/specs/a11y/a11y.spec.ts b/e2e/specs/a11y/a11y.spec.ts index a564bb9..b1f860d 100644 --- a/e2e/specs/a11y/a11y.spec.ts +++ b/e2e/specs/a11y/a11y.spec.ts @@ -11,14 +11,14 @@ test.describe('accessibility', () => { await expectNoNewA11yViolations(anonymousPage, 'login') }) - // The dashboard is dark unless the user picks light (stored as cm-theme); both are checked. + // The dashboard is dark unless the user picks light (stored as rp-theme); both are checked. for (const scheme of ['dark', 'light'] as const) { const suffix = scheme === 'dark' ? '' : '-light' test(`dashboard screens, ${scheme} theme @a11y`, async ({ page, agent, agentsPage, aiConfigPage, ticketsPage, peoplePage }) => { // An agent of its own, so the agents screen is the list (with a card to check), not first-run setup. expect(agent.id).toBeTruthy() - await page.addInitScript((theme) => localStorage.setItem('cm-theme', theme), scheme) + await page.addInitScript((theme) => localStorage.setItem('rp-theme', theme), scheme) await new InboxPage(page).goto() expect(await page.evaluate(() => document.documentElement.dataset.theme)).toBe(scheme) await expectNoNewA11yViolations(page, `inbox${suffix}`) diff --git a/e2e/specs/channels/own-meta-app.spec.ts b/e2e/specs/channels/own-meta-app.spec.ts index 523c1ac..975be82 100644 --- a/e2e/specs/channels/own-meta-app.spec.ts +++ b/e2e/specs/channels/own-meta-app.spec.ts @@ -13,7 +13,7 @@ import { // by the dashboard's unit tests. test.describe('a number or Page from the customer\'s own Meta app', () => { - test('a WhatsApp number receives messages: its webhooks are pointed at ChatterMate on connect @channels', async ({ agent, llm, adminApi, request }) => { + test('a WhatsApp number receives messages: its webhooks are pointed at ReplyPier on connect @channels', async ({ agent, llm, adminApi, request }) => { await llm.script(agent, (s) => s .when(/opening hours/i).reply('We are open 9am to 5pm, Monday to Friday.') .otherwise().reply('Happy to help!')) diff --git a/e2e/specs/crm/pipedrive.org.spec.ts b/e2e/specs/crm/pipedrive.org.spec.ts index 3e00219..7e16a72 100644 --- a/e2e/specs/crm/pipedrive.org.spec.ts +++ b/e2e/specs/crm/pipedrive.org.spec.ts @@ -49,9 +49,9 @@ test.describe('Pipedrive', () => { const personId = (created.response as { data: { id: number } }).data.id const [lead] = (await externals.calls('pipedrive', 'leads', { contains: `"person_id":${personId}` })).filter((c) => c.method === 'POST') - expect(lead.body).toMatchObject({ title: `${name} — ChatterMate lead`, person_id: personId }) + expect(lead.body).toMatchObject({ title: `${name} — ReplyPier lead`, person_id: personId }) const leadId = (lead.response as { data: { id: string } }).data.id const [note] = await externals.calls('pipedrive', 'notes', { contains: leadId }) - expect(note.body).toMatchObject({ lead_id: leadId, content: expect.stringContaining('Lead captured by ChatterMate') }) + expect(note.body).toMatchObject({ lead_id: leadId, content: expect.stringContaining('Lead captured by ReplyPier') }) }) }) diff --git a/e2e/specs/perf/budgets.spec.ts b/e2e/specs/perf/budgets.spec.ts index 84c1fa1..168744e 100644 --- a/e2e/specs/perf/budgets.spec.ts +++ b/e2e/specs/perf/budgets.spec.ts @@ -6,7 +6,7 @@ import { test, expect, env, AI_REPLY } from '@e2e' const KB = 1024 const BUDGETS = [ - { file: 'embed loader (chattermate.min.js)', url: `${env.frontendUrl}/webclient/chattermate.min.js`, maxBytes: 60 * KB }, + { file: 'embed loader (replypier.min.js)', url: `${env.frontendUrl}/webclient/replypier.min.js`, maxBytes: 60 * KB }, { file: 'widget script (widget.js)', url: `${env.backendUrl}/assets/widget.js`, maxBytes: 500 * KB }, { file: 'widget styles (widget.css)', url: `${env.backendUrl}/assets/widget.css`, maxBytes: 135 * KB }, ] diff --git a/e2e/specs/widget/js-api.spec.ts b/e2e/specs/widget/js-api.spec.ts index e3799c2..351287f 100644 --- a/e2e/specs/widget/js-api.spec.ts +++ b/e2e/specs/widget/js-api.spec.ts @@ -1,7 +1,7 @@ import { test, expect } from '@e2e' test.describe('widget JS API', () => { - test('the host page opens and closes the chat with window.ChatterMate @widget', async ({ widget }) => { + test('the host page opens and closes the chat with window.ReplyPier @widget', async ({ widget }) => { await widget.embed() await widget.api('open') diff --git a/e2e/src/api/ai.ts b/e2e/src/api/ai.ts index 88099b0..d91830f 100644 --- a/e2e/src/api/ai.ts +++ b/e2e/src/api/ai.ts @@ -27,12 +27,12 @@ export async function currentAiConfig(api: ApiClient): Promise { /** * Puts the org back on the AI it had before a test changed it: the fake LLM, or - * (enterprise) the ChatterMate AI its signup created, which reaches the fake too. + * (enterprise) the ReplyPier AI its signup created, which reaches the fake too. */ export async function restoreAi(api: ApiClient, before: AiConfig): Promise { - if (before.model_type.toUpperCase() === 'CHATTERMATE') { + if (before.model_type.toUpperCase() === 'REPLYPIER') { // As the dashboard's onboarding sends it: the backend injects the key. - await api.post('/ai/setup', { data: { model_type: 'CHATTERMATE', model_name: 'chattermate', api_key: '' } }) + await api.post('/ai/setup', { data: { model_type: 'REPLYPIER', model_name: 'replypier', api_key: '' } }) } else { await useFakeLlm(api) } diff --git a/e2e/src/api/schema.d.ts b/e2e/src/api/schema.d.ts index 7e1d6d7..a83652e 100644 --- a/e2e/src/api/schema.d.ts +++ b/e2e/src/api/schema.d.ts @@ -4914,7 +4914,7 @@ export interface components { * AIModelType * @enum {string} */ - AIModelType: "OPENAI" | "ANTHROPIC" | "DEEPSEEK" | "GOOGLE" | "GOOGLEVERTEX" | "GROQ" | "MISTRAL" | "HUGGINGFACE" | "OLLAMA" | "XAI" | "OPENAI_COMPATIBLE" | "CHATTERMATE"; + AIModelType: "OPENAI" | "ANTHROPIC" | "DEEPSEEK" | "GOOGLE" | "GOOGLEVERTEX" | "GROQ" | "MISTRAL" | "HUGGINGFACE" | "OLLAMA" | "XAI" | "OPENAI_COMPATIBLE" | "REPLYPIER"; /** AISetupResponse */ AISetupResponse: { /** Message */ diff --git a/e2e/src/components/chat-widget.ts b/e2e/src/components/chat-widget.ts index 610fff4..2feeceb 100644 --- a/e2e/src/components/chat-widget.ts +++ b/e2e/src/components/chat-widget.ts @@ -4,11 +4,11 @@ import { unique } from '../support/ids' import { step } from '../support/step' export interface EmbedOptions { - /** window.chattermateConfig — launcher, displayMode, position, trigger, … */ + /** window.replypierConfig — launcher, displayMode, position, trigger, … */ config?: Record - /** window.chattermateToken, for agents that require token auth. */ + /** window.replypierToken, for agents that require token auth. */ token?: string - /** Put a `[data-chattermate-open]` button on the page. */ + /** Put a `[data-replypier-open]` button on the page. */ withTriggerButton?: boolean /** The dashboard's iframe snippet instead of the script: the chat is already open. */ snippet?: 'script' | 'iframe' @@ -20,7 +20,7 @@ type JsApiMethod = 'open' | 'close' | 'toggle' | 'isOpen' | 'showLauncher' | 'hi * The customer's view: a pretend website with the widget embedded exactly the way the * dashboard's install snippet does it, and the chat inside the widget's iframe. * - * Why CSS here: the loader's launcher (#chattermate-button) and the widget's message + * Why CSS here: the loader's launcher (#replypier-button) and the widget's message * bubbles have no accessible role or name yet. Keeping those selectors in this one * file means adding aria-labels later is a one-file change. */ @@ -37,7 +37,7 @@ export class ChatWidget { this.widgetId = widgetId const id = unique('customer') this.customer = customer ?? { name: `Customer ${id}`, email: `${id}@example.com` } - this.frame = page.frameLocator('iframe.chattermate-iframe') + this.frame = page.frameLocator('iframe.replypier-iframe') } /** @@ -161,11 +161,11 @@ export class ChatWidget { return new ChatWidget(await this.page.context().newPage(), this.widgetId, this.customer) } - /** Calls the public `window.ChatterMate` API the host page uses. */ + /** Calls the public `window.ReplyPier` API the host page uses. */ async api(method: JsApiMethod, ...args: unknown[]): Promise { - await this.page.waitForFunction(() => 'ChatterMate' in window) + await this.page.waitForFunction(() => 'ReplyPier' in window) return this.page.evaluate( - ({ method, args }) => (window as unknown as { ChatterMate: Record unknown> }).ChatterMate[method](...args), + ({ method, args }) => (window as unknown as { ReplyPier: Record unknown> }).ReplyPier[method](...args), { method, args }, ) } @@ -176,12 +176,12 @@ export class ChatWidget { } get launcher(): Locator { - return this.page.locator('#chattermate-button') + return this.page.locator('#replypier-button') } /** The chat panel; it carries `.active` while open. */ get panel(): Locator { - return this.page.locator('#chattermate-container') + return this.page.locator('#replypier-container') } /** Shown by the loader instead of a chat when the widget refuses to load (e.g. no token). */ @@ -233,7 +233,7 @@ export class ChatWidget { /** The agent's welcome message, shown when the chat opens. */ get welcomeMessage(): Locator { - return this.frame.locator('.cm-welcome-block .message-bubble') + return this.frame.locator('.rp-welcome-block .message-bubble') } get contactForm(): Locator { diff --git a/e2e/src/env.ts b/e2e/src/env.ts index da23977..f59460d 100644 --- a/e2e/src/env.ts +++ b/e2e/src/env.ts @@ -25,7 +25,7 @@ export const env = { /** The pretend customer website the widget is embedded on (services/customer-site). */ customerSiteUrl: 'http://127.0.0.1:13000', /** The throwaway database stack.sh manages (same E2E_PG_URL convention). */ - databaseUrl: `${(process.env.E2E_PG_URL ?? `postgresql://${process.env.USER}@127.0.0.1:5432`).replace(/\/$/, '')}/chattermate_e2e`, + databaseUrl: `${(process.env.E2E_PG_URL ?? `postgresql://${process.env.USER}@127.0.0.1:5432`).replace(/\/$/, '')}/replypier_e2e`, /** The private enterprise suite, present only where the enterprise_frontend submodule is checked out. */ enterpriseSpecDir: fileURLToPath(new URL('../../frontend/src/modules/enterprise/e2e/', import.meta.url)), /** stack.sh, for `stack.sh python …` one-off jobs against the running stack. */ diff --git a/e2e/src/org-setup.ts b/e2e/src/org-setup.ts index bc1e047..0781eb3 100644 --- a/e2e/src/org-setup.ts +++ b/e2e/src/org-setup.ts @@ -16,7 +16,7 @@ export interface PreparedOrg { adminStorageState: string /** * OSS points the org at the fake LLM itself. Enterprise orgs keep the - * ChatterMate AI their signup created, which reaches the fake through + * ReplyPier AI their signup created, which reaches the fake through * OPENAI_BASE_URL. */ configureAi: boolean diff --git a/e2e/src/pages/ai-config.page.ts b/e2e/src/pages/ai-config.page.ts index dcdb579..9791618 100644 --- a/e2e/src/pages/ai-config.page.ts +++ b/e2e/src/pages/ai-config.page.ts @@ -22,7 +22,7 @@ export class AiConfigPage { async useOpenAiCompatible(settings: ModelSettings): Promise { await step(`Save an OpenAI-compatible model (${settings.model})`, async () => { - // With the enterprise module the page can open on the "ChatterMate AI" tab. + // With the enterprise module the page can open on the "ReplyPier AI" tab. await this.page.getByRole('tab', { name: /Bring Your Own Model/ }).click() await this.page.getByRole('radio', { name: /OpenAI-compatible/ }).click() await this.page.getByLabel('Base URL').fill(settings.baseUrl) diff --git a/e2e/src/pages/setup.page.ts b/e2e/src/pages/setup.page.ts index 269a361..9b2de8f 100644 --- a/e2e/src/pages/setup.page.ts +++ b/e2e/src/pages/setup.page.ts @@ -19,7 +19,7 @@ export class SetupPage { async goto(): Promise { await this.page.goto('/setup') - await expect(this.page.getByRole('heading', { name: 'Welcome to ChatterMate' })).toBeVisible() + await expect(this.page.getByRole('heading', { name: 'Welcome to ReplyPier' })).toBeVisible() } async createOrganization(details: OrgDetails): Promise { diff --git a/frontend/index.html b/frontend/index.html index 8b2881f..b20dfd2 100644 --- a/frontend/index.html +++ b/frontend/index.html @@ -19,7 +19,7 @@ and src/config/themeColors.ts — a static document cannot import them. */ (function () { try { - var stored = localStorage.getItem('cm-theme') || 'light'; + var stored = localStorage.getItem('rp-theme') || 'light'; var resolved = stored === 'system' ? (window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light') : (stored === 'light' ? 'light' : 'dark'); diff --git a/frontend/nginx.conf b/frontend/nginx.conf index e5ed2f9..91646f0 100644 --- a/frontend/nginx.conf +++ b/frontend/nginx.conf @@ -11,7 +11,7 @@ server { # Enhanced Security headers. # This config only ever runs inside the frontend image, i.e. for self-hosted - # deployments - app.chattermate.chat serves the SPA from its own reverse proxy + # deployments - app.replypier.site serves the SPA from its own reverse proxy # and never routes here, so its CSP is set there and is unaffected by this file. # The CSP is repeated in every location block below because an add_header inside # a location cancels the inherited ones - change one, change all five. diff --git a/frontend/public/config.dev.js b/frontend/public/config.dev.js index ede932b..f67aabd 100644 --- a/frontend/public/config.dev.js +++ b/frontend/public/config.dev.js @@ -3,30 +3,27 @@ // in a page self === window, so window.APP_CONFIG still works. self.APP_CONFIG = { // API URLs - API_URL: "https://devapi.chattermate.chat/api/v1", - WS_URL: "wss://devapi.chattermate.chat", - WIDGET_URL: "https://devapp.chattermate.chat", - - // Firebase Configuration - FIREBASE_API_KEY: "AIzaSyDTwDgANnBItYx39qm-6shq4cUws6QY4wI", - FIREBASE_AUTH_DOMAIN: "chattermate-13e0a.firebaseapp.com", - FIREBASE_PROJECT_ID: "chattermate-13e0a", - FIREBASE_MESSAGING_SENDER_ID: "680125690355", - FIREBASE_APP_ID: "1:680125690355:web:466f50999a6c91935ae286", - FIREBASE_STORAGE_BUCKET: "chattermate-13e0a.firebasestorage.app", - FIREBASE_MEASUREMENT_ID: "G-7LGB58R2Q7", - FIREBASE_VAPID_KEY: "BJKnggErez2qK3AxBhHyEV-EoS9lfcWO1GDXhRwUKIHbT_PH23vhY_8HRIz_KyuC-0gbuViSrtSMiFp7zgyYY4g", - + API_URL: "http://localhost:8000/api/v1", + WS_URL: "ws://localhost:8000", + WIDGET_URL: "http://localhost:8000", + + // Firebase Configuration (fill in for your own project; empty disables it) + FIREBASE_API_KEY: "", + FIREBASE_AUTH_DOMAIN: "", + FIREBASE_PROJECT_ID: "", + FIREBASE_MESSAGING_SENDER_ID: "", + FIREBASE_APP_ID: "", + FIREBASE_STORAGE_BUCKET: "", + FIREBASE_MEASUREMENT_ID: "", + FIREBASE_VAPID_KEY: "", + // Razorpay Checkout - RAZORPAY_KEY_ID: "rzp_test_T92OR9gqPBht0N", - GTM_ID: "", + RAZORPAY_KEY_ID: "", // Google Fonts API - GOOGLE_FONTS_API_KEY: "AIzaSyCTQCSK_ybLEglabeusbyekQGEyvFr2C5o", - - DEMO_WIDGET_ID: "a6ee36e9-b70e-4b12-8f94-cc5a5b147f26", + GOOGLE_FONTS_API_KEY: "", + // Node Environment NODE_ENV: "development", HOST: "0.0.0.0" }; - \ No newline at end of file diff --git a/frontend/public/webclient/chattermate.min.js b/frontend/public/webclient/chattermate.min.js deleted file mode 100644 index 7f3dcd8..0000000 --- a/frontend/public/webclient/chattermate.min.js +++ /dev/null @@ -1,889 +0,0 @@ -(()=>{var wt=(nt,it,e)=>new Promise((M,d)=>{var Y=x=>{try{z(e.next(x))}catch(B){d(B)}},G=x=>{try{z(e.throw(x))}catch(B){d(B)}},z=x=>x.done?M(x.value):Promise.resolve(x.value).then(Y,G);z((e=e.apply(nt,it)).next())});var _t=` -`;window.chattermateId;window.chattermateBaseUrl;window.ChatterMate;window.chattermateConfig;(function(){function nt(t){return/^#[0-9A-F]{6}$/i.test(t)}function it(){return typeof window!="undefined"&&window.chattermateBaseUrl?window.chattermateBaseUrl:typeof window!="undefined"&&window.APP_CONFIG&&window.APP_CONFIG.API_URL?window.APP_CONFIG.API_URL:"https://api.chattermate.chat/api/v1"}let e={baseUrl:it(),containerId:"chattermate-container",backdropId:"chattermate-backdrop",buttonId:"chattermate-button",chatBubbleColor:"#f34611",loadingContainerId:"chattermate-loading",tokenKey:"ctid",tokenProvider:null,containerBottom:100,containerRight:20,containerWidth:400,containerHeight:560,launcherBottom:20,launcherRight:20,side:"right",displayMode:"floating",launcher:!0,sidebarWidth:420,searchBarWidth:320,searchPlaceholder:"\u6709\u95EE\u9898\u968F\u65F6\u95EE\u6211\u2026",zIndex:999999,trigger:null,hotkey:!0,surfaceIsPalette:null,chatStyle:null,chatInitiationMessages:[],initiationMessageId:"chattermate-initiation",initiationShownKey:"ctim_shown",unreadCount:0,hasOpened:!1},M={};function d(t,n){e[t]=n,M[t]=!0}let Y=["floating","sidebar-left","sidebar-right","search-bar"],G=["ASK_ANYTHING","AURORA"],z=680,x=620,B=140,A={width:!1,height:!1},N=0;function j(){return e.surfaceIsPalette===!1?!1:(G.indexOf(e.chatStyle)!==-1||e.displayMode==="search-bar")&&e.displayMode!=="sidebar-left"&&e.displayMode!=="sidebar-right"}function q(){let t=document.getElementById(e.containerId);if(!t)return;if(!j()||!N){t.style.height="";return}let n=Math.min(at().height,Math.round(window.innerHeight*.76));t.style.height=Math.max(B,Math.min(n,N))+"px"}function at(){return{width:A.width?e.containerWidth:z,height:A.height?e.containerHeight:x}}function Lt(t){if(!t||typeof t!="object")return;let n=function(i,o){M[i]||(e[i]=o)};Y.indexOf(t.mode)!==-1&&n("displayMode",t.mode),(t.side==="left"||t.side==="right")&&n("side",t.side),typeof t.launcher=="boolean"&&n("launcher",t.launcher),m(t.width)&&(n("containerWidth",Math.max(280,t.width)),M.containerWidth||(A.width=!0)),m(t.height)&&(n("containerHeight",Math.max(400,t.height)),M.containerHeight||(A.height=!0)),m(t.sidebar_width)&&n("sidebarWidth",Math.max(280,t.sidebar_width)),typeof t.search_placeholder=="string"&&t.search_placeholder&&n("searchPlaceholder",t.search_placeholder.slice(0,80)),m(t.offset_bottom)&&n("launcherBottom",Math.max(0,t.offset_bottom)),m(t.offset_side)&&n("launcherRight",Math.max(0,t.offset_side)),m(t.z_index)&&n("zIndex",Math.max(1,Math.floor(t.z_index)))}function It(){let t=j(),n=t?at():{width:e.containerWidth,height:e.containerHeight};return{type:"WIDGET_DISPLAY",mode:t?"ask-ai":e.displayMode,width:n.width,height:n.height,hotkey:e.hotkey!==!1}}let c=null,R=[],V=!1,g=null,T=null,y=!1;function Z(t){c?t():y||R.push(t)}let X={},ot=!1;function _(t,n){let i=X[t];!i||!i.length||i.slice().forEach(function(o){try{o(n)}catch(h){}})}function zt(t){let n=/^#?([0-9a-f]{6})$/i.exec((t||"").trim());if(!n)return"#0B0C10";let i=parseInt(n[1],16);return(.299*(i>>16&255)+.587*(i>>8&255)+.114*(i&255))/255>.6?"#0B0C10":"#FFFFFF"}let rt=!1,E=null,st=[];function P(){if(rt)return;rt=!0,E&&(clearTimeout(E),E=null);let t=document.getElementById(e.buttonId);t&&t.classList.remove("chattermate-pending"),st.splice(0).forEach(n=>{try{n()}catch(i){}})}function F(){let t=document.getElementById(e.buttonId);if(!t)return;let n=t.querySelector(".cm-badge");if(!n)return;let i=e.hasOpened?e.unreadCount:(e.chatInitiationMessages||[]).length;n.textContent=i>99?"99+":String(i),n.style.display=i>0&&!t.classList.contains("active")?"flex":"none"}function O(){let t=e.displayMode,n=t==="sidebar-left"||t==="sidebar-right",i=t==="sidebar-left"?"left":t==="sidebar-right"?"right":e.side,o=t==="search-bar"?48:64,h=G.indexOf(e.chatStyle)===-1,r=j(),l=at(),w=document.createElement("style");w.id="chattermate-styles",w.textContent=` - /* ===== Rounded-square launcher (design comp) ===== */ - #${e.buttonId} { - position: fixed; - bottom: ${e.launcherBottom}px; - ${i}: ${e.launcherRight}px; - width: 64px; - height: 64px; - border-radius: 20px 20px 20px 6px; - background: ${e.chatBubbleColor}; - color: ${zt(e.chatBubbleColor)}; - box-shadow: 0 16px 40px -8px ${e.chatBubbleColor}cc, inset 0 0 0 1px rgba(255,255,255,0.08); - cursor: pointer; - z-index: ${e.zIndex}; - display: flex; - align-items: center; - justify-content: center; - transition: transform 0.3s cubic-bezier(.34,1.3,.5,1), opacity 320ms ease; - animation: chattermate-float 4s ease-in-out infinite; - } - #${e.buttonId}.active { animation: none; } - /* Stay fully invisible until the org's real brand color is known (or the - widget errors out / times out) \u2014 avoids ever flashing the wrong color. */ - #${e.buttonId}.chattermate-pending { - opacity: 0; - pointer-events: none; - } - #${e.buttonId}:hover { transform: scale(1.06); } - - /* Expanding rings (closed state only) */ - #${e.buttonId} .cm-ring { - position: absolute; - inset: 0; - border-radius: 20px 20px 20px 6px; - border: 1.5px solid ${e.chatBubbleColor}; - animation: chattermate-ring 2.4s ease-out infinite; - pointer-events: none; - } - #${e.buttonId} .cm-ring.r2 { animation-delay: 1.2s; } - #${e.buttonId}.active .cm-ring { display: none; } - - /* Pulsing 3-dot mark (closed). Absolutely centered so it stays pinned to the - button's center regardless of the button's display mode (flex on desktop, - block when .mobile-closed) or viewport. */ - #${e.buttonId} .cm-dots { - display: flex; - gap: 5px; - position: absolute; - top: 50%; - left: 50%; - transform: translate(-50%, -50%); - } - #${e.buttonId} .cm-dot { - width: 7px; - height: 7px; - border-radius: 50%; - background: currentColor; - animation: chattermate-pulse 1.5s ease-in-out infinite; - } - #${e.buttonId} .cm-dot:nth-child(2) { animation-delay: .18s; } - #${e.buttonId} .cm-dot:nth-child(3) { animation-delay: .36s; } - #${e.buttonId}.active .cm-dots { display: none; } - - /* Chevron (open) \u2014 absolutely centered, pinned to the button center. */ - #${e.buttonId} .cm-chevron { - display: none; - position: absolute; - top: 50%; - left: 50%; - transform: translate(-50%, -50%); - font-size: 26px; - font-weight: 700; - line-height: 1; - color: currentColor; - } - #${e.buttonId}.active .cm-chevron { display: block; } - - /* Unread badge = number of nudges */ - #${e.buttonId} .cm-badge { - position: absolute; - top: -5px; - right: -5px; - min-width: 22px; - height: 22px; - padding: 0 6px; - border-radius: 999px; - background: #FF8A73; - color: #0B0C10; - font: 700 11.5px/1 -apple-system, BlinkMacSystemFont, system-ui, sans-serif; - align-items: center; - justify-content: center; - border: 2px solid #F5F3EE; - box-shadow: 0 4px 12px rgba(0,0,0,0.25); - display: none; - } - #${e.buttonId}.active .cm-badge { display: none; } - - #${e.buttonId}.loading .cm-dots, - #${e.buttonId}.loading .cm-chevron { visibility: hidden; } - #${e.buttonId}.loading:after { - content: ''; - position: absolute; - width: 16px; - height: 16px; - top: 50%; - left: 50%; - margin: -8px 0 0 -8px; - border: 2px solid rgba(255,255,255,0.3); - border-radius: 50%; - border-top-color: #fff; - animation: chattermate-spin 0.6s linear infinite; - } - - /* Search-bar trigger content: hidden unless search-bar mode (below) shows it. */ - #${e.buttonId} .cm-search { display: none; } - - ${t==="search-bar"?` - @media (min-width: 769px) { - /* ===== Search-bar mode: the launcher becomes a search-input-like bar. - Same element, same click/toggle/badge logic. Mobile keeps the bubble. ===== */ - #${e.buttonId} { - width: ${e.searchBarWidth}px; - height: 48px; - border-radius: 24px; - padding: 0 16px; - background: #ffffff; - color: #374151; - box-shadow: 0 8px 24px rgba(0, 0, 0, 0.14), inset 0 0 0 1.5px ${e.chatBubbleColor}55; - animation: none; - justify-content: flex-start; - box-sizing: border-box; - } - #${e.buttonId}:hover { transform: scale(1.02); } - #${e.buttonId} .cm-ring, - #${e.buttonId} .cm-dots, - #${e.buttonId} .cm-chevron, - #${e.buttonId}.active .cm-chevron { display: none; } - /* Dark spinner \u2014 the stock white one vanishes on the white bar. */ - #${e.buttonId}.loading .cm-search { visibility: hidden; } - #${e.buttonId}.loading:after { - border-color: rgba(0, 0, 0, 0.15); - border-top-color: ${e.chatBubbleColor}; - } - #${e.buttonId} .cm-search { - display: flex; - align-items: center; - gap: 10px; - min-width: 0; - width: 100%; - } - #${e.buttonId} .cm-search svg { - flex-shrink: 0; - color: ${e.chatBubbleColor}; - } - #${e.buttonId} .cm-search-placeholder { - font: 400 14px/1.2 -apple-system, BlinkMacSystemFont, system-ui, sans-serif; - color: #6b7280; - white-space: nowrap; - overflow: hidden; - text-overflow: ellipsis; - } - } - `:""} - - @keyframes chattermate-spin { to { transform: rotate(360deg); } } - @keyframes chattermate-float { 0%, 100% { transform: translateY(0); } 50% { transform: translateY(-5px); } } - @keyframes chattermate-ring { 0% { transform: scale(.85); opacity: .5; } 100% { transform: scale(1.6); opacity: 0; } } - @keyframes chattermate-pulse { 0%, 100% { opacity: .45; } 50% { opacity: 1; } } - - @media (prefers-reduced-motion: reduce) { - #${e.buttonId}, - #${e.buttonId} .cm-ring, - #${e.buttonId} .cm-dot, - .initiation-orb { animation: none !important; } - /* Open and close in place: no slide, scale or fade for people who asked for less motion. */ - #${e.buttonId}, - #${e.containerId}, - #${e.backdropId} { transition: none !important; } - } - - #${e.containerId} { - position: fixed; - /* The window sits above the launcher; when the launcher is moved (via - ChatterMate.init position / setPosition) the window shifts by the same - delta so the two stay together. Mobile is full-screen (media query below) - and is unaffected. */ - bottom: ${(e.containerBottom||100)+((e.launcherBottom||20)-20)}px; - ${i}: ${(e.containerRight||20)+((e.launcherRight||20)-20)}px; - width: ${e.containerWidth||384}px; - max-width: calc(100vw - 48px); - height: ${e.containerHeight}px; - max-height: calc(100vh - 132px); - background: transparent; - z-index: ${e.zIndex}; - overflow: hidden; - /* Animated open/close with slide + fade */ - opacity: 0; - visibility: hidden; - transform: translateY(16px) scale(0.98); - transition: opacity 360ms cubic-bezier(0.22, 1, 0.36, 1), transform 360ms cubic-bezier(0.22, 1, 0.36, 1), visibility 0s linear 360ms; - border: none; - padding: 0; - margin: 0; - pointer-events: none; - } - - #${e.containerId}.active { - opacity: 1; - visibility: visible; - transform: translateY(0) scale(1); - transition: opacity 420ms cubic-bezier(0.22, 1, 0.36, 1), transform 420ms cubic-bezier(0.22, 1, 0.36, 1); - pointer-events: auto; - } - - /* Backdrop element: always in the DOM, so keep it out of the host page's flow - even when it is not in use \u2014 an unstyled div in adds a phantom row to - a flex/grid body layout. */ - #${e.backdropId} { - position: fixed; - inset: 0; - display: none; - } - - ${r?` - /* ===== Ask AI: centered command palette (\u2318K), the pattern people expect from - an "Ask anything" surface \u2014 dimmed page, top-anchored so the eye lands on - the input rather than the middle of the screen. ===== */ - #${e.containerId} { - top: 12vh; - bottom: auto; - left: 50%; - right: auto; - width: min(${l.width}px, calc(100vw - 32px)); - max-width: none; - /* A cross-document iframe can't size its embedder, so this is a starting - height only: the palette measures its content and posts WIDGET_RESIZE, - which sets an inline height (clamped to this ceiling). height:100% against - an auto-height parent would collapse to the 150px replaced default. */ - height: min(${l.height}px, 76vh); - max-height: 76vh; - transform: translate(-50%, -8px) scale(0.98); - z-index: ${e.zIndex+1}; - transition: opacity 360ms cubic-bezier(0.22, 1, 0.36, 1), - transform 360ms cubic-bezier(0.22, 1, 0.36, 1), - height 200ms cubic-bezier(0.22, 1, 0.36, 1), - visibility 0s linear 360ms; - } - #${e.containerId}.active { - transform: translate(-50%, 0) scale(1); - transition: opacity 420ms cubic-bezier(0.22, 1, 0.36, 1), - transform 420ms cubic-bezier(0.22, 1, 0.36, 1), - height 200ms cubic-bezier(0.22, 1, 0.36, 1); - } - #${e.containerId} .chattermate-iframe { - border-radius: 16px; - } - #${e.backdropId} { - display: block; - background: rgba(9, 9, 14, 0.45); - backdrop-filter: blur(2px); - z-index: ${e.zIndex}; - opacity: 0; - visibility: hidden; - transition: opacity 220ms ease, visibility 0s linear 220ms; - } - #${e.backdropId}.active { - opacity: 1; - visibility: visible; - transition: opacity 220ms ease; - } - /* The palette dims the page and closes on backdrop click / Esc, so the launcher - would just be a stray button floating over the dim. */ - #${e.buttonId}.active { - display: none; - } - @media (max-width: 768px) { - /* Full-screen on phones like every other mode. The main mobile block below - pins the edges but never resets transform \u2014 without this the centering - translate would shove the panel half a screen to the left. */ - #${e.containerId}, - #${e.containerId}.active { transform: none !important; } - #${e.backdropId} { display: none; } - } - `:""} - - ${n?` - /* ===== Sidebar mode: full-height drawer hugging the ${i} edge ===== */ - #${e.containerId} { - top: 0; - bottom: auto; - ${i}: 0; - ${i==="left"?"right: auto;":"left: auto;"} - width: ${e.sidebarWidth}px; - max-width: 100vw; - height: 100dvh; - max-height: 100dvh; - transform: translateX(${i==="left"?"-100%":"100%"}); - box-shadow: ${i==="left"?"":"-"}12px 0 40px rgba(0, 0, 0, 0.12); - } - #${e.containerId}.active { - transform: translateX(0); - } - #${e.containerId} .chattermate-iframe { - border-radius: 0; - } - ${h?` - /* The drawer's own header chevron closes it, so keeping the launcher on screen - would just park a duplicate button beside the panel. Hide it while open. */ - #${e.buttonId}.active { - display: none; - } - `:` - /* ASK_ANYTHING / AURORA draw no in-panel chevron, and the drawer would paint over - the launcher (later sibling, equal z-index) \u2014 leaving nothing to click. Keep it - reachable: slide it out beside the drawer edge, one layer up. */ - #${e.buttonId} { - z-index: ${e.zIndex+1}; - transition: transform 0.3s cubic-bezier(.34,1.3,.5,1), opacity 320ms ease, - left 360ms cubic-bezier(0.22, 1, 0.36, 1), right 360ms cubic-bezier(0.22, 1, 0.36, 1); - } - #${e.buttonId}.active { - ${i}: ${e.sidebarWidth+20}px; - } - `} - `:""} - - /* Clean border around the widget container */ - /* The widget panel (inside the iframe) draws its own theme-aware border, so the - container no longer adds one \u2014 avoids a double border (and a white line on dark themes). */ - - .chattermate-iframe { - width: 100%; - height: 100%; - border: none; - padding: 0; - margin: 0; - display: block; - border-radius: 24px; - /* Rely on corner shadows from container */ - box-shadow: none; - } - - #chattermate-mobile-close { - display: none; - position: fixed; - top: 20px; - right: 20px; - width: 44px; - height: 44px; - background: transparent; - border: none; - align-items: center; - justify-content: center; - cursor: pointer; - z-index: ${e.zIndex+1}; - transition: all 0.3s ease; - } - - #chattermate-mobile-topbar { - display: none; - position: fixed; - top: 0; - left: 0; - right: 0; - height: 60px; - background: rgba(255, 255, 255, 0.95); - backdrop-filter: blur(10px); - border-bottom: 1px solid rgba(0, 0, 0, 0.1); - z-index: ${e.zIndex}; - align-items: center; - justify-content: space-between; - padding: 0 20px; - box-sizing: border-box; - } - - #chattermate-mobile-topbar.active { - display: flex; - } - - #chattermate-mobile-topbar .topbar-title { - font-size: 16px; - font-weight: 600; - color: #333; - margin: 0; - } - - /* Only ASK_ANYTHING (which has no in-panel header chevron) uses the floating - mobile-close; other styles close via the header chevron, so don't double up. */ - .ask-anything-mobile #chattermate-mobile-close.active { - display: flex; - } - - @media (max-width: 768px) { - #${e.containerId} { - width: 100vw !important; - height: 100vh !important; - height: 100dvh !important; /* Dynamic viewport height for mobile browsers */ - /* Reset the desktop max-width/height clamp \u2014 without this the desktop rule's - max-width: calc(100vw - 48px) / max-height: calc(100vh - 132px) keeps the - window a floating panel instead of going full-screen on mobile. */ - max-width: 100vw !important; - max-height: 100vh !important; - max-height: 100dvh !important; - top: 0 !important; - left: 0 !important; - bottom: 0 !important; - right: 0 !important; - border-radius: 0 !important; - position: fixed !important; - margin: 0 !important; - padding: 0 !important; - } - - #${e.containerId}.active { - bottom: 0 !important; - } - - .chattermate-iframe { - border-radius: 0 !important; - width: 100vw !important; - height: 100vh !important; - height: 100dvh !important; /* Dynamic viewport height for mobile browsers */ - position: absolute !important; - top: 0 !important; - left: 0 !important; - margin: 0 !important; - padding: 0 !important; - } - - #${e.buttonId} { - display: none; - } - - #${e.buttonId}.mobile-closed { - /* flex (not block) keeps the launcher's centering context; the dots/chevron - are absolutely centered regardless, but this keeps it consistent. */ - display: flex !important; - width: 56px !important; - height: 56px !important; - /* Respect the configured position on mobile too, so the closed launcher can - clear a fixed bottom nav bar (the main reason to move it up). */ - bottom: ${e.launcherBottom}px !important; - ${i}: ${e.launcherRight}px !important; - } - - .ask-anything-mobile #chattermate-mobile-close.active { - display: flex !important; - } - - #chattermate-mobile-close:hover { - opacity: 0.7; - } - - /* ASK_ANYTHING style specific mobile topbar */ - .ask-anything-mobile #chattermate-mobile-topbar.active { - display: flex !important; - } - - .ask-anything-mobile #chattermate-mobile-close.active { - top: 15px !important; - right: 15px !important; - z-index: ${e.zIndex+2} !important; - } - - /* When topbar is visible, push iframe down to avoid overlap */ - .ask-anything-mobile .chattermate-iframe { - top: 60px !important; - height: calc(100vh - 60px) !important; - height: calc(100dvh - 60px) !important; - } - } - - @media (min-width: 769px) { - #chattermate-mobile-close { - display: none !important; - } - } - - /* Chat Initiation Message Styles */ - #${e.initiationMessageId} { - position: fixed !important; - /* Sit above the launcher (+12px gap) and align to its edge on the active side, - so it never overlaps the icon regardless of the configured position/mode. */ - bottom: ${(e.launcherBottom||20)+o+12}px !important; - ${i}: ${e.launcherRight||20}px !important; - max-width: 260px !important; - background: white !important; - padding: 12px 36px 12px 14px !important; - border-radius: 14px !important; - box-shadow: 0 3px 16px rgba(0, 0, 0, 0.1) !important; - z-index: ${e.zIndex-1} !important; - cursor: pointer !important; - opacity: 0; - visibility: hidden; - transform: translateY(10px) scale(0.95); - transition: all 0.4s cubic-bezier(0.22, 1, 0.36, 1) !important; - font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif !important; - font-size: 14px !important; - box-sizing: border-box !important; - margin: 0 !important; - border: none !important; - display: block !important; - width: auto !important; - height: auto !important; - min-width: 0 !important; - min-height: 0 !important; - max-height: none !important; - line-height: 1.4 !important; - text-align: left !important; - vertical-align: baseline !important; - overflow: visible !important; - } - /* Clamp the nudge text to 4 lines with an ellipsis so a long welcome/initiation - message can never balloon the bubble over the page or into the launcher. - Applied to the text node only, so the orb (left:-34px) is never clipped. */ - #${e.initiationMessageId} .initiation-message-text { - margin: 0 !important; - display: -webkit-box !important; - -webkit-line-clamp: 4 !important; - -webkit-box-orient: vertical !important; - overflow: hidden !important; - } - - /* Siri-style orb avatar beside the nudge (design comp) */ - .initiation-orb { - position: absolute !important; - left: -34px !important; - bottom: 2px !important; - width: 26px !important; - height: 26px !important; - border-radius: 50% !important; - background: conic-gradient(from 0deg, #C9F24E, #9D8CFF, #5FE3D6, #FF8A73, #C9F24E) !important; - box-shadow: 0 4px 14px rgba(157, 140, 255, 0.4) !important; - animation: chattermate-orb-spin 6s linear infinite !important; - z-index: 1 !important; - } - @keyframes chattermate-orb-spin { to { transform: rotate(360deg); } } - ${i==="left"?` - /* On the left edge the orb (which protrudes 34px past the bubble) would clip - off-screen \u2014 mirror it to the bubble's page-facing side. */ - .initiation-orb { - left: auto !important; - right: -34px !important; - } - `:""} - - #${e.initiationMessageId}.show { - opacity: 1; - visibility: visible; - transform: translateY(0) scale(1); - animation: chattermate-bounce-in 0.6s cubic-bezier(0.68, -0.55, 0.265, 1.55); - } - - @keyframes chattermate-bounce-in { - 0% { - opacity: 0; - transform: translateY(20px) scale(0.8); - } - 50% { - transform: translateY(-5px) scale(1.02); - } - 100% { - opacity: 1; - transform: translateY(0) scale(1); - } - } - - #${e.initiationMessageId}:hover { - transform: translateY(-2px) scale(1.02); - box-shadow: 0 5px 20px rgba(0, 0, 0, 0.14); - } - - #${e.initiationMessageId}::after { - content: '' !important; - position: absolute !important; - bottom: -7px !important; - ${i}: 30px !important; - width: 14px !important; - height: 14px !important; - min-width: 14px !important; - min-height: 14px !important; - max-width: 14px !important; - max-height: 14px !important; - background: white !important; - transform: rotate(45deg) !important; - box-shadow: 3px 3px 5px rgba(0, 0, 0, 0.06) !important; - clip-path: polygon(0 0, 100% 0, 100% 100%) !important; - border: none !important; - margin: 0 !important; - padding: 0 !important; - box-sizing: border-box !important; - z-index: -1 !important; - } - - .initiation-message-text { - font-size: 13px !important; - line-height: 1.4 !important; - color: #374151 !important; - margin: 0 !important; - padding: 0 4px 0 0 !important; - position: relative !important; - z-index: 1 !important; - min-height: 18px !important; - box-sizing: border-box !important; - border: none !important; - background: transparent !important; - display: block !important; - width: 100% !important; - height: auto !important; - max-width: none !important; - max-height: none !important; - text-align: left !important; - vertical-align: baseline !important; - font-weight: normal !important; - font-style: normal !important; - text-decoration: none !important; - text-transform: none !important; - letter-spacing: normal !important; - word-spacing: normal !important; - white-space: normal !important; - overflow-wrap: break-word !important; - word-wrap: break-word !important; - } - - .initiation-message-text::after { - content: '|'; - animation: blink 1s step-end infinite; - margin-left: 2px; - color: ${e.chatBubbleColor}; - font-weight: 500; - } - - .initiation-message-text.typing-complete::after { - display: none; - } - - @keyframes blink { - 0%, 50% { opacity: 1; } - 51%, 100% { opacity: 0; } - } - - .initiation-close { - position: absolute !important; - top: 10px !important; - right: 10px !important; - width: 20px !important; - height: 20px !important; - min-width: 20px !important; - min-height: 20px !important; - max-width: 20px !important; - max-height: 20px !important; - background: rgba(0, 0, 0, 0.04) !important; - border: none !important; - border-radius: 5px !important; - cursor: pointer !important; - opacity: 0.5 !important; - transition: all 0.2s ease !important; - z-index: 2 !important; - display: flex !important; - align-items: center !important; - justify-content: center !important; - padding: 0 !important; - margin: 0 !important; - box-sizing: border-box !important; - outline: none !important; - box-shadow: none !important; - text-decoration: none !important; - font-size: 0 !important; - line-height: 0 !important; - overflow: hidden !important; - flex-shrink: 0 !important; - } - - .initiation-close:hover { - opacity: 1 !important; - background: rgba(0, 0, 0, 0.08) !important; - transform: scale(1.05) !important; - } - - .initiation-close::before, - .initiation-close::after { - content: '' !important; - position: absolute !important; - width: 9px !important; - height: 1.5px !important; - min-width: 9px !important; - min-height: 1.5px !important; - max-width: 9px !important; - max-height: 1.5px !important; - background: #4a5568 !important; - border-radius: 1px !important; - top: 50% !important; - left: 50% !important; - margin: -0.75px 0 0 -4.5px !important; - padding: 0 !important; - border: none !important; - box-sizing: border-box !important; - } - - .initiation-close::before { - transform: rotate(45deg) !important; - } - - .initiation-close::after { - transform: rotate(-45deg) !important; - } - - @media (max-width: 768px) { - #${e.initiationMessageId} { - display: none !important; - } - } - - /* Error UI Styles */ - .chattermate-error-ui { - width: 100%; - height: 100%; - display: flex; - flex-direction: column; - align-items: center; - justify-content: center; - background: linear-gradient(135deg, #f8fafc 0%, #f1f5f9 100%); - border-radius: 24px; - overflow: hidden; - position: relative; - } - - .chattermate-error-ui::before { - content: ''; - position: absolute; - top: 0; - left: 0; - right: 0; - bottom: 0; - background: - radial-gradient(circle at 20% 30%, rgba(99, 102, 241, 0.08) 0%, transparent 50%), - radial-gradient(circle at 80% 70%, rgba(168, 85, 247, 0.06) 0%, transparent 50%); - pointer-events: none; - } - - .chattermate-error-card { - display: flex; - flex-direction: column; - align-items: center; - justify-content: center; - padding: 32px 24px; - text-align: center; - position: relative; - z-index: 1; - max-width: 90%; - } - - .chattermate-error-close { - position: absolute; - top: 12px; - right: 12px; - z-index: 2; - width: 36px; - height: 36px; - display: flex; - align-items: center; - justify-content: center; - border: none; - border-radius: 50%; - background: rgba(120, 120, 140, 0.12); - color: #4b5563; - font-size: 22px; - line-height: 1; - cursor: pointer; - transition: background 0.15s ease; - } - .chattermate-error-close:hover { - background: rgba(120, 120, 140, 0.22); - } - - .chattermate-error-icon-wrapper { - display: flex; - align-items: center; - justify-content: center; - width: 72px; - height: 72px; - background: linear-gradient(135deg, #e0e7ff 0%, #c7d2fe 100%); - border-radius: 20px; - margin-bottom: 20px; - box-shadow: 0 8px 24px rgba(99, 102, 241, 0.15); - } - - .chattermate-error-icon { - width: 36px; - height: 36px; - color: #6366f1; - } - - .chattermate-error-title { - font-size: 20px; - font-weight: 600; - color: #1e293b; - margin: 0 0 12px 0; - letter-spacing: -0.01em; - font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif; - } - - .chattermate-error-message { - font-size: 14px; - line-height: 1.6; - color: #64748b; - margin: 0 0 24px 0; - max-width: 280px; - font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif; - } - - .chattermate-error-footer { - display: flex; - align-items: center; - justify-content: center; - gap: 6px; - font-size: 12px; - color: #94a3b8; - opacity: 0.8; - font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif; - } - .chattermate-error-footer-link { - color: inherit; - text-decoration: none; - cursor: pointer; - } - .chattermate-error-footer-link:hover { - text-decoration: underline; - } - - @media (max-width: 768px) { - .chattermate-error-ui { - border-radius: 0; - } - - .chattermate-error-card { - padding: 24px 20px; - } - - .chattermate-error-icon-wrapper { - width: 64px; - height: 64px; - border-radius: 16px; - } - - .chattermate-error-icon { - width: 32px; - height: 32px; - } - - .chattermate-error-title { - font-size: 18px; - } - - .chattermate-error-message { - font-size: 13px; - max-width: 260px; - } - } - - ${e.launcher?"":` - /* Launcher hidden by config \u2014 the site opens the chat with its own trigger or - the JS API. Last in the sheet so it also beats the mobile .mobile-closed - re-show (display: flex !important at equal specificity). */ - #${e.buttonId}, #${e.buttonId}.mobile-closed { display: none !important; } - `} - `;let f=document.getElementById("chattermate-styles");f&&f.remove(),document.head.appendChild(w),vt()}function vt(){let t=document.getElementById(e.buttonId);if(!t)return;let n=t.querySelector(".cm-search-placeholder");n&&n.textContent!==e.searchPlaceholder&&(n.textContent=e.searchPlaceholder)}function C(t){if(typeof t!="string")return null;let n=t.trim();return!n||n==="undefined"||n==="null"?null:n}function ct(){return C(window.chattermateToken)||C(localStorage.getItem(e.tokenKey))}function lt(t){let n=C(t);if(!n)return null;let i=n.split(".")[1];if(!i)return null;try{let o=JSON.parse(atob(i.replace(/-/g,"+").replace(/_/g,"/")));return o.sub||o.customer_id||null}catch(o){return null}}function J(t){t&&localStorage.setItem(e.tokenKey,t)}function W(){localStorage.removeItem(e.tokenKey)}function H(){return window.innerWidth<=768}function Bt(t){return t?t.replace(/\uFFFD/g,"").replace(/[��]/g,"").replace(/[\x00-\x1F\x7F-\x9F]/g,"").trim():""}function Nt(){if(!e.chatInitiationMessages||e.chatInitiationMessages.length===0)return null;let t=Math.floor(Math.random()*e.chatInitiationMessages.length),n=e.chatInitiationMessages[t];return n?Bt(n):null}function Rt(){return H()||!e.launcher||!e.chatInitiationMessages||e.chatInitiationMessages.length===0?!1:!sessionStorage.getItem(e.initiationShownKey)}function dt(){sessionStorage.setItem(e.initiationShownKey,"true")}function Pt(){let t=Nt();if(!t)return null;let n=document.createElement("div");return n.id=e.initiationMessageId,n.innerHTML=` - - -

- `,n.dataset.fullMessage=t,n}function Ft(t,n,i=50){let o=t.querySelector(".initiation-message-text");if(!o)return;let h=0,r=setInterval(()=>{h{t.classList.add("show"),setTimeout(()=>{let o=t.dataset.fullMessage;o&&Ft(t,o,40)},300)},1500),t.addEventListener("click",o=>{o.target.classList.contains("initiation-close")||(t.typeInterval&&clearInterval(t.typeInterval),ht(t),n(),dt())});let i=t.querySelector(".initiation-close");i&&i.addEventListener("click",o=>{o.stopPropagation(),t.typeInterval&&clearInterval(t.typeInterval),ht(t),dt()})}function ht(t){t&&(t.classList.remove("show"),setTimeout(()=>{t.parentNode&&t.parentNode.removeChild(t)},400))}function pt(){y=!1,O();let t=document.createElement("div");t.id=e.buttonId,t.classList.add("chattermate-pending"),t.innerHTML=` - - -
- ⌄ - - - - - - `,E=setTimeout(P,8e3);let n=document.createElement("div");n.id=e.containerId;let i=document.createElement("div");i.id="chattermate-mobile-close",i.innerHTML=` - - - - `;let o=document.createElement("div");o.id="chattermate-mobile-topbar",o.innerHTML=` -

\u804A\u5929

-
- `;let h=document.createElement("div");h.id=e.backdropId,document.body.appendChild(t),document.body.appendChild(h),document.body.appendChild(n),document.body.appendChild(i),document.body.appendChild(o),F(),vt();let r=!1,l=null,w=!1,f=null;function b(){r=!r,n.classList.toggle("active"),h.classList.toggle("active",r),t.classList.toggle("active"),i.classList.toggle("active"),r&&(e.hasOpened=!0,e.unreadCount=0),l&&l.contentWindow&&l.contentWindow.postMessage({type:"WIDGET_VISIBILITY",open:r},"*"),F(),r&&f&&(ht(f),f=null,dt()),H()?r?(t.classList.remove("mobile-closed"),t.style.animation=""):(t.classList.add("mobile-closed"),t.style.animation="chattermate-float 4s ease-in-out infinite",o.classList.remove("active"),document.body.classList.remove("ask-anything-mobile")):r&&i.classList.remove("active"),r&&l&&l.contentWindow.postMessage({type:"SCROLL_TO_BOTTOM"},"*"),_(r?"open":"close")}let U=null,ft=!1;function Gt(a){let s=String(a||"").slice(0,2e3);s&&(ft&&l&&l.contentWindow?l.contentWindow.postMessage({type:"PREFILL_MESSAGE",text:s},"*"):U=s)}let K=0;function Ct(){for(K++;n.firstChild;)n.removeChild(n.firstChild);l=null,g=null,T=null,ft=!1,ot=!1,U=null,w=!1,t.classList.remove("loading"),N=0,q()}function jt(){r&&b(),Ct(),e.unreadCount=0,e.hasOpened=!1,F(),Q()}function qt(){r&&b(),Ct(),window.removeEventListener("resize",Tt),window.removeEventListener("message",At),f&&(f.typeInterval&&clearInterval(f.typeInterval),mt(f),f=null),[t,h,n,i,o].forEach(mt),mt(document.getElementById("chattermate-styles")),document.body.classList.remove("ask-anything-mobile"),rt=!1,E&&(clearTimeout(E),E=null),st.length=0,e.unreadCount=0,e.hasOpened=!1,c=null,R.length=0,V=!1,y=!0}function St(a){let s=document.createElement("div");s.className="chattermate-error-ui";let I=document.createElement("div");I.className="chattermate-error-card";let v=document.createElement("button");v.type="button",v.className="chattermate-error-close",v.setAttribute("aria-label","\u5173\u95ED\u804A\u5929"),v.textContent="\xD7",v.addEventListener("click",function(){r&&b()}),s.appendChild(v);let u=document.createElement("div");u.className="chattermate-error-icon-wrapper";let p=document.createElementNS("http://www.w3.org/2000/svg","svg");p.setAttribute("class","chattermate-error-icon"),p.setAttribute("viewBox","0 0 24 24"),p.setAttribute("fill","none"),p.setAttribute("stroke","currentColor"),p.setAttribute("stroke-width","1.5");let k=document.createElementNS("http://www.w3.org/2000/svg","path");k.setAttribute("d","M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z");let $=document.createElementNS("http://www.w3.org/2000/svg","path");$.setAttribute("d","M9 12l2 2 4-4"),p.appendChild(k),p.appendChild($),u.appendChild(p);let S=document.createElement("h2");S.className="chattermate-error-title",S.textContent="\u5BA2\u670D\u6682\u4E0D\u53EF\u7528";let bt=document.createElement("p");bt.className="chattermate-error-message",bt.textContent=a;let et=document.createElement("div");et.className="chattermate-error-footer";let xt=document.createElement("span");xt.innerHTML=_t;let yt=xt.querySelector("svg");yt.setAttribute("width","20"),yt.setAttribute("height","16"),yt.setAttribute("aria-hidden","true");let L=document.createElement("a");return L.href="https://chattermate.chat",L.target="_blank",L.rel="noopener noreferrer",L.className="chattermate-error-footer-link",L.textContent="\u7531 ChatterMate \u63D0\u4F9B\u652F\u6301",et.appendChild(xt),et.appendChild(L),I.appendChild(u),I.appendChild(S),I.appendChild(bt),I.appendChild(et),s.appendChild(I),s}function Q(){return wt(this,null,function*(){if(w||l)return;let a=K;try{w=!0,t.classList.add("loading");let s=ct(),I=`${e.baseUrl}/widgets/${window.chattermateId}/data?widget_id=${window.chattermateId}`,v={method:"GET",mode:"cors",headers:s?{Authorization:`Bearer ${s}`}:{}};fetch(I,v).then(u=>wt(null,null,function*(){if(a!==K)return null;if(u.status===401)try{let k=(yield u.json()).detail;if(k&&k.code==="identity_expired")return t.classList.remove("loading"),_("identityExpired"),Vt(),null;let $=typeof k=="string"?k:"";if($.includes("generate-token")||$.includes("API key")||$.includes("Token must be obtained")){t.classList.remove("loading"),W();let S=St("\u6B64\u804A\u5929\u7EC4\u4EF6\u5C1A\u672A\u914D\u7F6E\u5B8C\u6210\uFF0C\u8BF7\u8054\u7CFB\u7F51\u7AD9\u7BA1\u7406\u5458\u5F00\u901A\u5728\u7EBF\u5BA2\u670D\u3002");return n.appendChild(S),P(),null}}catch(p){}if(!u.ok)throw new Error("HTTP error! status: "+u.status);return u.text()})).then(u=>{u!==null&&a===K&&(l=document.createElement("iframe"),l.className="chattermate-iframe",l.title="\u804A\u5929",l.srcdoc=u,l.addEventListener("load",function(){ft=!0,l.contentWindow.postMessage(It(),"*"),l.contentWindow.postMessage({type:"WIDGET_VISIBILITY",open:r},"*"),U&&(l.contentWindow.postMessage({type:"PREFILL_MESSAGE",text:U},"*"),U=null),ot=!0,D=!1,_("ready")}),n.appendChild(l),g=l.contentWindow,t.classList.remove("loading"),l.style.opacity="1")}).catch(u=>{if(a!==K)return;console.error("Failed to load widget:",u),t.classList.remove("loading");let p=window.location.hostname||"\u5F53\u524D\u57DF\u540D",$=/^(localhost|127\.0\.0\.1|0\.0\.0\.0|\[?::1\]?)$/i.test(p)||/\.local$/i.test(p)?"\u804A\u5929\u7A97\u53E3\u65E0\u6CD5\u5728\u201C"+p+"\u201D\u4E0A\u52A0\u8F7D\u3002\u672C\u5730\u6D4B\u8BD5\u65F6\uFF0C\u8BF7\u5728 ChatterMate \u540E\u53F0\uFF08\u7EC4\u7EC7\u8BBE\u7F6E\uFF09\u4E2D\u628A\u7EC4\u7EC7\u57DF\u540D\u8BBE\u4E3A\u201C"+p+"\u201D\u3002":"\u804A\u5929\u7A97\u53E3\u65E0\u6CD5\u5728\u201C"+p+"\u201D\u4E0A\u52A0\u8F7D\u3002\u8BF7\u5728 ChatterMate \u540E\u53F0\uFF08\u7EC4\u7EC7\u8BBE\u7F6E\uFF09\u4E2D\u5C06\u6B64\u57DF\u540D\u52A0\u5165\u7EC4\u7EC7\uFF0C\u5373\u53EF\u5728\u6B64\u542F\u7528\u804A\u5929\u3002",S=St($);n.appendChild(S),P()})}catch(s){console.error("Failed to load widget:",s),t.classList.remove("loading"),P()}finally{w=!1}})}function At(a){if(!(!a.data||typeof a.data.type!="string")&&!(!g||a.source!==g)){if(a.data.type==="UNREAD_COUNT"){e.unreadCount=Math.max(0,parseInt(a.data.count,10)||0),F(),_("unread",e.unreadCount);return}if(a.data.type==="TOKEN_UPDATE"){let s=C(a.data.token);if(!s)return;J(s),a.source.postMessage({type:"TOKEN_RECEIVED",token:s},"*");return}if(a.data.type==="CHAT_SESSION"){T=String(a.data.sessionId||"")||null,a.data.created&&_("chatCreated",{sessionId:T,authenticated:!!a.data.authenticated});return}a.data.type==="IDENTITY_EXPIRED"&&(_("identityExpired"),Zt())}}function Vt(){if(D||typeof e.tokenProvider!="function"){W(),window.chattermateToken=null,Q();return}D=!0,Promise.resolve().then(()=>e.tokenProvider()).then(a=>{let s=C(a);s?(window.chattermateToken=s,J(s)):(W(),window.chattermateToken=null)}).catch(a=>{console.error("ChatterMate: tokenProvider failed",a),W(),window.chattermateToken=null}).finally(()=>{Q()})}let gt=!1,D=!1;function Zt(){if(!gt){if(D||typeof e.tokenProvider!="function"){tt({type:"IDENTITY_UNAVAILABLE"});return}gt=!0,D=!0,Promise.resolve().then(()=>e.tokenProvider()).then(a=>{let s=C(a);if(!s){tt({type:"IDENTITY_UNAVAILABLE"});return}window.chattermateToken=s,J(s),tt({type:"TOKEN_REFRESH",token:s})}).catch(a=>{console.error("ChatterMate: tokenProvider failed",a),tt({type:"IDENTITY_UNAVAILABLE"})}).finally(()=>{gt=!1})}}function tt(a){g&&g.postMessage(a,"*")}window.addEventListener("message",At),Q(),st.push(()=>{setTimeout(()=>{y||!r&&e.chatInitiationMessages.length>0&&(f=Pt(),Ot(f,b))},2e3)}),t.addEventListener("click",b),i.addEventListener("click",b),h.addEventListener("click",function(){r&&b()}),H()&&!r&&(t.classList.add("mobile-closed"),t.style.animation="chattermate-float 4s ease-in-out infinite");function Tt(){let a=H();a&&!r?(t.classList.add("mobile-closed"),t.style.animation="chattermate-float 4s ease-in-out infinite",i.classList.remove("active")):a||(t.classList.remove("mobile-closed"),t.style.animation="",r&&i.classList.remove("active")),O(),q()}window.addEventListener("resize",Tt),c={isOpen:function(){return r},toggle:b,open:function(a){r||b(),a&&a.message&&Gt(a.message)},close:function(){r&&b()},reload:jt,destroy:qt},R.splice(0).forEach(function(a){try{a()}catch(s){}})}$t(window.chattermateConfig),document.readyState==="loading"?document.addEventListener("DOMContentLoaded",function(){y||pt()}):pt();let Wt=typeof navigator!="undefined"&&/Mac|iPod|iPhone|iPad/.test(navigator.platform||"");document.addEventListener("keydown",function(t){if(!c||!j())return;let n=Wt?t.metaKey&&!t.ctrlKey:t.ctrlKey&&!t.metaKey;if(e.hotkey&&n&&!t.altKey&&!t.repeat&&(t.key==="k"||t.key==="K")){t.preventDefault(),c.toggle();return}t.key==="Escape"&&c.isOpen()&&c.close()}),document.addEventListener("click",function(t){let n=t.target;if(!n||!n.closest)return;let i=n.closest("[data-chattermate-open]");if(!i&&e.trigger)try{i=n.closest(e.trigger)}catch(o){}i&&(i.tagName==="A"&&t.preventDefault(),c?c.toggle():!y&&!V&&(V=!0,R.push(function(){c.open()})))}),window.addEventListener("message",function(t){if(!(!t.data||typeof t.data.type!="string")&&!(!g||t.source!==g)){if(t.data.type==="WIDGET_RESIZE"){if(typeof t.data.height!="number"||!isFinite(t.data.height))return;N=Math.round(t.data.height),q();return}if(t.data.type==="WIDGET_SURFACE"){let n=!!t.data.palette;if(e.surfaceIsPalette===n)return;e.surfaceIsPalette=n,n||(N=0),O(),q();return}if(t.data.type==="WIDGET_MINIMIZE"){Z(function(){c.close()});return}if(t.data.type==="CUSTOMIZATION_UPDATE"){let n=t.data.data,i=n.chat_bubble_color;if(e.chatBubbleColor=nt(i)?i:e.chatBubbleColor,typeof n.chat_style=="string"&&(e.chatStyle=n.chat_style),n.chat_initiation_messages&&Array.isArray(n.chat_initiation_messages)&&(e.chatInitiationMessages=n.chat_initiation_messages),Lt(n.widget_display),!H())M.containerBottom||(e.containerBottom=n.chat_style==="ASK_ANYTHING"?90:100);else{let o=c?c.isOpen():!1,h=document.getElementById("chattermate-mobile-topbar");n.chat_style==="ASK_ANYTHING"&&o?(document.body.classList.add("ask-anything-mobile"),h&&h.classList.add("active")):(document.body.classList.remove("ask-anything-mobile"),h&&h.classList.remove("active"))}O(),F(),P(),t.source&&typeof t.source.postMessage=="function"&&t.source.postMessage(It(),"*")}}});function m(t){return typeof t=="number"&&isFinite(t)}function mt(t){t&&t.parentNode&&t.parentNode.removeChild(t)}function ut(){document.getElementById("chattermate-styles")&&O()}function kt(t,n){if(!t||typeof t!="object")return;(t.side==="left"||t.side==="right")&&d("side",t.side),m(t.bottom)&&d("launcherBottom",Math.max(0,t.bottom));let i=m(t.offset)?t.offset:t.right;m(i)&&d("launcherRight",Math.max(0,i)),n||ut()}function $t(t){!t||typeof t!="object"||(t.baseUrl&&(e.baseUrl=t.baseUrl),t.id&&(window.chattermateId=t.id),typeof t.tokenProvider=="function"&&(e.tokenProvider=t.tokenProvider),typeof t.launcher=="boolean"&&d("launcher",t.launcher),Y.indexOf(t.displayMode)!==-1&&d("displayMode",t.displayMode),m(t.width)&&(d("containerWidth",Math.max(280,t.width)),A.width=!0),m(t.height)&&(d("containerHeight",Math.max(400,t.height)),A.height=!0),typeof t.hotkey=="boolean"&&d("hotkey",t.hotkey),m(t.sidebarWidth)&&d("sidebarWidth",Math.max(280,t.sidebarWidth)),m(t.zIndex)&&d("zIndex",Math.max(1,Math.floor(t.zIndex))),typeof t.trigger=="string"&&t.trigger&&d("trigger",t.trigger),t.searchBar&&typeof t.searchBar=="object"&&(typeof t.searchBar.placeholder=="string"&&t.searchBar.placeholder&&d("searchPlaceholder",t.searchBar.placeholder.slice(0,80)),m(t.searchBar.width)&&d("searchBarWidth",Math.max(160,t.searchBar.width))),t.position&&kt(t.position,!0),ut())}function Ht(){c&&c.reload()}function Mt(t,n){if(t&&n){let i=`${e.baseUrl}/widgets/${window.chattermateId}/end-chat?session_id=${encodeURIComponent(n)}&reason=CUSTOMER_REQUEST`;try{fetch(i,{method:"POST",mode:"cors",keepalive:!0,headers:{Authorization:`Bearer ${t}`}}).catch(()=>{})}catch(o){}}T=null,Ht()}function Ut(){if(c){c.reload();return}y&&(y=!1,document.readyState!=="loading"&&pt())}function Kt(){if(c){c.destroy();return}y=!0,R.length=0,V=!1}function Dt(t){let n=C(t);if(!n)return;let i=ct();if(n===i)return;let o=i&<(n)&<(n)===lt(i);if(window.chattermateToken=n,J(n),o&&g){g.postMessage({type:"TOKEN_REFRESH",token:n},"*");return}Mt(i,T)}function Yt(){let t=ct(),n=T;window.chattermateToken=null,W(),Mt(t,n)}function Et(t){d("launcher",!!t),ut()}window.ChatterMate={init:$t,setPosition:function(t){kt(t)},open:function(t){Z(function(){c.open(t)})},close:function(){Z(function(){c.close()})},toggle:function(){Z(function(){c.toggle()})},isOpen:function(){return c?c.isOpen():!1},showLauncher:function(){Et(!0)},hideLauncher:function(){Et(!1)},identify:function(t){Dt(t)},logout:function(){Yt()},reload:function(){Ut()},destroy:function(){Kt()},on:function(t,n){if(!(typeof t!="string"||typeof n!="function")){if(t==="ready"&&ot){try{n()}catch(i){}return}(X[t]=X[t]||[]).push(n)}},off:function(t,n){let i=X[t];if(!i)return;let o=i.indexOf(n);o!==-1&&i.splice(o,1)}}})();})(); diff --git a/frontend/public/webclient/replypier.min.js b/frontend/public/webclient/replypier.min.js new file mode 100644 index 0000000..a791ae7 --- /dev/null +++ b/frontend/public/webclient/replypier.min.js @@ -0,0 +1,889 @@ +(()=>{var we=(ie,ne,t)=>new Promise((E,p)=>{var D=y=>{try{z(t.next(y))}catch(B){p(B)}},G=y=>{try{z(t.throw(y))}catch(B){p(B)}},z=y=>y.done?E(y.value):Promise.resolve(y.value).then(D,G);z((t=t.apply(ie,ne)).next())});var _e=` +`;window.replypierId;window.replypierBaseUrl;window.ReplyPier;window.replypierConfig;(function(){function ie(e){return/^#[0-9A-F]{6}$/i.test(e)}function ne(){return typeof window!="undefined"&&window.replypierBaseUrl?window.replypierBaseUrl:typeof window!="undefined"&&window.APP_CONFIG&&window.APP_CONFIG.API_URL?window.APP_CONFIG.API_URL:"https://api.replypier.site/api/v1"}let t={baseUrl:ne(),containerId:"replypier-container",backdropId:"replypier-backdrop",buttonId:"replypier-button",chatBubbleColor:"#f34611",loadingContainerId:"replypier-loading",tokenKey:"rpid",tokenProvider:null,containerBottom:100,containerRight:20,containerWidth:400,containerHeight:560,launcherBottom:20,launcherRight:20,side:"right",displayMode:"floating",launcher:!0,sidebarWidth:420,searchBarWidth:320,searchPlaceholder:"\u6709\u95EE\u9898\u968F\u65F6\u95EE\u6211\u2026",zIndex:999999,trigger:null,hotkey:!0,surfaceIsPalette:null,chatStyle:null,chatInitiationMessages:[],initiationMessageId:"replypier-initiation",initiationShownKey:"rpim_shown",unreadCount:0,hasOpened:!1},E={};function p(e,i){t[e]=i,E[e]=!0}let D=["floating","sidebar-left","sidebar-right","search-bar"],G=["ASK_ANYTHING","AURORA"],z=680,y=620,B=140,A={width:!1,height:!1},P=0;function j(){return t.surfaceIsPalette===!1?!1:(G.indexOf(t.chatStyle)!==-1||t.displayMode==="search-bar")&&t.displayMode!=="sidebar-left"&&t.displayMode!=="sidebar-right"}function q(){let e=document.getElementById(t.containerId);if(!e)return;if(!j()||!P){e.style.height="";return}let i=Math.min(oe().height,Math.round(window.innerHeight*.76));e.style.height=Math.max(B,Math.min(i,P))+"px"}function oe(){return{width:A.width?t.containerWidth:z,height:A.height?t.containerHeight:y}}function Te(e){if(!e||typeof e!="object")return;let i=function(n,r){E[n]||(t[n]=r)};D.indexOf(e.mode)!==-1&&i("displayMode",e.mode),(e.side==="left"||e.side==="right")&&i("side",e.side),typeof e.launcher=="boolean"&&i("launcher",e.launcher),m(e.width)&&(i("containerWidth",Math.max(280,e.width)),E.containerWidth||(A.width=!0)),m(e.height)&&(i("containerHeight",Math.max(400,e.height)),E.containerHeight||(A.height=!0)),m(e.sidebar_width)&&i("sidebarWidth",Math.max(280,e.sidebar_width)),typeof e.search_placeholder=="string"&&e.search_placeholder&&i("searchPlaceholder",e.search_placeholder.slice(0,80)),m(e.offset_bottom)&&i("launcherBottom",Math.max(0,e.offset_bottom)),m(e.offset_side)&&i("launcherRight",Math.max(0,e.offset_side)),m(e.z_index)&&i("zIndex",Math.max(1,Math.floor(e.z_index)))}function Ie(){let e=j(),i=e?oe():{width:t.containerWidth,height:t.containerHeight};return{type:"WIDGET_DISPLAY",mode:e?"ask-ai":t.displayMode,width:i.width,height:i.height,hotkey:t.hotkey!==!1}}let l=null,R=[],V=!1,g=null,L=null,x=!1;function Z(e){l?e():x||R.push(e)}let X={},re=!1;function _(e,i){let n=X[e];!n||!n.length||n.slice().forEach(function(r){try{r(i)}catch(c){}})}function ze(e){let i=/^#?([0-9a-f]{6})$/i.exec((e||"").trim());if(!i)return"#0B0C10";let n=parseInt(i[1],16);return(.299*(n>>16&255)+.587*(n>>8&255)+.114*(n&255))/255>.6?"#0B0C10":"#FFFFFF"}let ae=!1,M=null,se=[];function N(){if(ae)return;ae=!0,M&&(clearTimeout(M),M=null);let e=document.getElementById(t.buttonId);e&&e.classList.remove("replypier-pending"),se.splice(0).forEach(i=>{try{i()}catch(n){}})}function F(){let e=document.getElementById(t.buttonId);if(!e)return;let i=e.querySelector(".rp-badge");if(!i)return;let n=t.hasOpened?t.unreadCount:(t.chatInitiationMessages||[]).length;i.textContent=n>99?"99+":String(n),i.style.display=n>0&&!e.classList.contains("active")?"flex":"none"}function O(){let e=t.displayMode,i=e==="sidebar-left"||e==="sidebar-right",n=e==="sidebar-left"?"left":e==="sidebar-right"?"right":t.side,r=e==="search-bar"?48:64,c=G.indexOf(t.chatStyle)===-1,a=j(),d=oe(),w=document.createElement("style");w.id="replypier-styles",w.textContent=` + /* ===== Rounded-square launcher (design comp) ===== */ + #${t.buttonId} { + position: fixed; + bottom: ${t.launcherBottom}px; + ${n}: ${t.launcherRight}px; + width: 64px; + height: 64px; + border-radius: 20px 20px 20px 6px; + background: ${t.chatBubbleColor}; + color: ${ze(t.chatBubbleColor)}; + box-shadow: 0 16px 40px -8px ${t.chatBubbleColor}cc, inset 0 0 0 1px rgba(255,255,255,0.08); + cursor: pointer; + z-index: ${t.zIndex}; + display: flex; + align-items: center; + justify-content: center; + transition: transform 0.3s cubic-bezier(.34,1.3,.5,1), opacity 320ms ease; + animation: replypier-float 4s ease-in-out infinite; + } + #${t.buttonId}.active { animation: none; } + /* Stay fully invisible until the org's real brand color is known (or the + widget errors out / times out) \u2014 avoids ever flashing the wrong color. */ + #${t.buttonId}.replypier-pending { + opacity: 0; + pointer-events: none; + } + #${t.buttonId}:hover { transform: scale(1.06); } + + /* Expanding rings (closed state only) */ + #${t.buttonId} .rp-ring { + position: absolute; + inset: 0; + border-radius: 20px 20px 20px 6px; + border: 1.5px solid ${t.chatBubbleColor}; + animation: replypier-ring 2.4s ease-out infinite; + pointer-events: none; + } + #${t.buttonId} .rp-ring.r2 { animation-delay: 1.2s; } + #${t.buttonId}.active .rp-ring { display: none; } + + /* Pulsing 3-dot mark (closed). Absolutely centered so it stays pinned to the + button's center regardless of the button's display mode (flex on desktop, + block when .mobile-closed) or viewport. */ + #${t.buttonId} .rp-dots { + display: flex; + gap: 5px; + position: absolute; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); + } + #${t.buttonId} .rp-dot { + width: 7px; + height: 7px; + border-radius: 50%; + background: currentColor; + animation: replypier-pulse 1.5s ease-in-out infinite; + } + #${t.buttonId} .rp-dot:nth-child(2) { animation-delay: .18s; } + #${t.buttonId} .rp-dot:nth-child(3) { animation-delay: .36s; } + #${t.buttonId}.active .rp-dots { display: none; } + + /* Chevron (open) \u2014 absolutely centered, pinned to the button center. */ + #${t.buttonId} .rp-chevron { + display: none; + position: absolute; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); + font-size: 26px; + font-weight: 700; + line-height: 1; + color: currentColor; + } + #${t.buttonId}.active .rp-chevron { display: block; } + + /* Unread badge = number of nudges */ + #${t.buttonId} .rp-badge { + position: absolute; + top: -5px; + right: -5px; + min-width: 22px; + height: 22px; + padding: 0 6px; + border-radius: 999px; + background: #FF8A73; + color: #0B0C10; + font: 700 11.5px/1 -apple-system, BlinkMacSystemFont, system-ui, sans-serif; + align-items: center; + justify-content: center; + border: 2px solid #F5F3EE; + box-shadow: 0 4px 12px rgba(0,0,0,0.25); + display: none; + } + #${t.buttonId}.active .rp-badge { display: none; } + + #${t.buttonId}.loading .rp-dots, + #${t.buttonId}.loading .rp-chevron { visibility: hidden; } + #${t.buttonId}.loading:after { + content: ''; + position: absolute; + width: 16px; + height: 16px; + top: 50%; + left: 50%; + margin: -8px 0 0 -8px; + border: 2px solid rgba(255,255,255,0.3); + border-radius: 50%; + border-top-color: #fff; + animation: replypier-spin 0.6s linear infinite; + } + + /* Search-bar trigger content: hidden unless search-bar mode (below) shows it. */ + #${t.buttonId} .rp-search { display: none; } + + ${e==="search-bar"?` + @media (min-width: 769px) { + /* ===== Search-bar mode: the launcher becomes a search-input-like bar. + Same element, same click/toggle/badge logic. Mobile keeps the bubble. ===== */ + #${t.buttonId} { + width: ${t.searchBarWidth}px; + height: 48px; + border-radius: 24px; + padding: 0 16px; + background: #ffffff; + color: #374151; + box-shadow: 0 8px 24px rgba(0, 0, 0, 0.14), inset 0 0 0 1.5px ${t.chatBubbleColor}55; + animation: none; + justify-content: flex-start; + box-sizing: border-box; + } + #${t.buttonId}:hover { transform: scale(1.02); } + #${t.buttonId} .rp-ring, + #${t.buttonId} .rp-dots, + #${t.buttonId} .rp-chevron, + #${t.buttonId}.active .rp-chevron { display: none; } + /* Dark spinner \u2014 the stock white one vanishes on the white bar. */ + #${t.buttonId}.loading .rp-search { visibility: hidden; } + #${t.buttonId}.loading:after { + border-color: rgba(0, 0, 0, 0.15); + border-top-color: ${t.chatBubbleColor}; + } + #${t.buttonId} .rp-search { + display: flex; + align-items: center; + gap: 10px; + min-width: 0; + width: 100%; + } + #${t.buttonId} .rp-search svg { + flex-shrink: 0; + color: ${t.chatBubbleColor}; + } + #${t.buttonId} .rp-search-placeholder { + font: 400 14px/1.2 -apple-system, BlinkMacSystemFont, system-ui, sans-serif; + color: #6b7280; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + } + } + `:""} + + @keyframes replypier-spin { to { transform: rotate(360deg); } } + @keyframes replypier-float { 0%, 100% { transform: translateY(0); } 50% { transform: translateY(-5px); } } + @keyframes replypier-ring { 0% { transform: scale(.85); opacity: .5; } 100% { transform: scale(1.6); opacity: 0; } } + @keyframes replypier-pulse { 0%, 100% { opacity: .45; } 50% { opacity: 1; } } + + @media (prefers-reduced-motion: reduce) { + #${t.buttonId}, + #${t.buttonId} .rp-ring, + #${t.buttonId} .rp-dot, + .initiation-orb { animation: none !important; } + /* Open and close in place: no slide, scale or fade for people who asked for less motion. */ + #${t.buttonId}, + #${t.containerId}, + #${t.backdropId} { transition: none !important; } + } + + #${t.containerId} { + position: fixed; + /* The window sits above the launcher; when the launcher is moved (via + ReplyPier.init position / setPosition) the window shifts by the same + delta so the two stay together. Mobile is full-screen (media query below) + and is unaffected. */ + bottom: ${(t.containerBottom||100)+((t.launcherBottom||20)-20)}px; + ${n}: ${(t.containerRight||20)+((t.launcherRight||20)-20)}px; + width: ${t.containerWidth||384}px; + max-width: calc(100vw - 48px); + height: ${t.containerHeight}px; + max-height: calc(100vh - 132px); + background: transparent; + z-index: ${t.zIndex}; + overflow: hidden; + /* Animated open/close with slide + fade */ + opacity: 0; + visibility: hidden; + transform: translateY(16px) scale(0.98); + transition: opacity 360ms cubic-bezier(0.22, 1, 0.36, 1), transform 360ms cubic-bezier(0.22, 1, 0.36, 1), visibility 0s linear 360ms; + border: none; + padding: 0; + margin: 0; + pointer-events: none; + } + + #${t.containerId}.active { + opacity: 1; + visibility: visible; + transform: translateY(0) scale(1); + transition: opacity 420ms cubic-bezier(0.22, 1, 0.36, 1), transform 420ms cubic-bezier(0.22, 1, 0.36, 1); + pointer-events: auto; + } + + /* Backdrop element: always in the DOM, so keep it out of the host page's flow + even when it is not in use \u2014 an unstyled div in adds a phantom row to + a flex/grid body layout. */ + #${t.backdropId} { + position: fixed; + inset: 0; + display: none; + } + + ${a?` + /* ===== Ask AI: centered command palette (\u2318K), the pattern people expect from + an "Ask anything" surface \u2014 dimmed page, top-anchored so the eye lands on + the input rather than the middle of the screen. ===== */ + #${t.containerId} { + top: 12vh; + bottom: auto; + left: 50%; + right: auto; + width: min(${d.width}px, calc(100vw - 32px)); + max-width: none; + /* A cross-document iframe can't size its embedder, so this is a starting + height only: the palette measures its content and posts WIDGET_RESIZE, + which sets an inline height (clamped to this ceiling). height:100% against + an auto-height parent would collapse to the 150px replaced default. */ + height: min(${d.height}px, 76vh); + max-height: 76vh; + transform: translate(-50%, -8px) scale(0.98); + z-index: ${t.zIndex+1}; + transition: opacity 360ms cubic-bezier(0.22, 1, 0.36, 1), + transform 360ms cubic-bezier(0.22, 1, 0.36, 1), + height 200ms cubic-bezier(0.22, 1, 0.36, 1), + visibility 0s linear 360ms; + } + #${t.containerId}.active { + transform: translate(-50%, 0) scale(1); + transition: opacity 420ms cubic-bezier(0.22, 1, 0.36, 1), + transform 420ms cubic-bezier(0.22, 1, 0.36, 1), + height 200ms cubic-bezier(0.22, 1, 0.36, 1); + } + #${t.containerId} .replypier-iframe { + border-radius: 16px; + } + #${t.backdropId} { + display: block; + background: rgba(9, 9, 14, 0.45); + backdrop-filter: blur(2px); + z-index: ${t.zIndex}; + opacity: 0; + visibility: hidden; + transition: opacity 220ms ease, visibility 0s linear 220ms; + } + #${t.backdropId}.active { + opacity: 1; + visibility: visible; + transition: opacity 220ms ease; + } + /* The palette dims the page and closes on backdrop click / Esc, so the launcher + would just be a stray button floating over the dim. */ + #${t.buttonId}.active { + display: none; + } + @media (max-width: 768px) { + /* Full-screen on phones like every other mode. The main mobile block below + pins the edges but never resets transform \u2014 without this the centering + translate would shove the panel half a screen to the left. */ + #${t.containerId}, + #${t.containerId}.active { transform: none !important; } + #${t.backdropId} { display: none; } + } + `:""} + + ${i?` + /* ===== Sidebar mode: full-height drawer hugging the ${n} edge ===== */ + #${t.containerId} { + top: 0; + bottom: auto; + ${n}: 0; + ${n==="left"?"right: auto;":"left: auto;"} + width: ${t.sidebarWidth}px; + max-width: 100vw; + height: 100dvh; + max-height: 100dvh; + transform: translateX(${n==="left"?"-100%":"100%"}); + box-shadow: ${n==="left"?"":"-"}12px 0 40px rgba(0, 0, 0, 0.12); + } + #${t.containerId}.active { + transform: translateX(0); + } + #${t.containerId} .replypier-iframe { + border-radius: 0; + } + ${c?` + /* The drawer's own header chevron closes it, so keeping the launcher on screen + would just park a duplicate button beside the panel. Hide it while open. */ + #${t.buttonId}.active { + display: none; + } + `:` + /* ASK_ANYTHING / AURORA draw no in-panel chevron, and the drawer would paint over + the launcher (later sibling, equal z-index) \u2014 leaving nothing to click. Keep it + reachable: slide it out beside the drawer edge, one layer up. */ + #${t.buttonId} { + z-index: ${t.zIndex+1}; + transition: transform 0.3s cubic-bezier(.34,1.3,.5,1), opacity 320ms ease, + left 360ms cubic-bezier(0.22, 1, 0.36, 1), right 360ms cubic-bezier(0.22, 1, 0.36, 1); + } + #${t.buttonId}.active { + ${n}: ${t.sidebarWidth+20}px; + } + `} + `:""} + + /* Clean border around the widget container */ + /* The widget panel (inside the iframe) draws its own theme-aware border, so the + container no longer adds one \u2014 avoids a double border (and a white line on dark themes). */ + + .replypier-iframe { + width: 100%; + height: 100%; + border: none; + padding: 0; + margin: 0; + display: block; + border-radius: 24px; + /* Rely on corner shadows from container */ + box-shadow: none; + } + + #replypier-mobile-close { + display: none; + position: fixed; + top: 20px; + right: 20px; + width: 44px; + height: 44px; + background: transparent; + border: none; + align-items: center; + justify-content: center; + cursor: pointer; + z-index: ${t.zIndex+1}; + transition: all 0.3s ease; + } + + #replypier-mobile-topbar { + display: none; + position: fixed; + top: 0; + left: 0; + right: 0; + height: 60px; + background: rgba(255, 255, 255, 0.95); + backdrop-filter: blur(10px); + border-bottom: 1px solid rgba(0, 0, 0, 0.1); + z-index: ${t.zIndex}; + align-items: center; + justify-content: space-between; + padding: 0 20px; + box-sizing: border-box; + } + + #replypier-mobile-topbar.active { + display: flex; + } + + #replypier-mobile-topbar .topbar-title { + font-size: 16px; + font-weight: 600; + color: #333; + margin: 0; + } + + /* Only ASK_ANYTHING (which has no in-panel header chevron) uses the floating + mobile-close; other styles close via the header chevron, so don't double up. */ + .ask-anything-mobile #replypier-mobile-close.active { + display: flex; + } + + @media (max-width: 768px) { + #${t.containerId} { + width: 100vw !important; + height: 100vh !important; + height: 100dvh !important; /* Dynamic viewport height for mobile browsers */ + /* Reset the desktop max-width/height clamp \u2014 without this the desktop rule's + max-width: calc(100vw - 48px) / max-height: calc(100vh - 132px) keeps the + window a floating panel instead of going full-screen on mobile. */ + max-width: 100vw !important; + max-height: 100vh !important; + max-height: 100dvh !important; + top: 0 !important; + left: 0 !important; + bottom: 0 !important; + right: 0 !important; + border-radius: 0 !important; + position: fixed !important; + margin: 0 !important; + padding: 0 !important; + } + + #${t.containerId}.active { + bottom: 0 !important; + } + + .replypier-iframe { + border-radius: 0 !important; + width: 100vw !important; + height: 100vh !important; + height: 100dvh !important; /* Dynamic viewport height for mobile browsers */ + position: absolute !important; + top: 0 !important; + left: 0 !important; + margin: 0 !important; + padding: 0 !important; + } + + #${t.buttonId} { + display: none; + } + + #${t.buttonId}.mobile-closed { + /* flex (not block) keeps the launcher's centering context; the dots/chevron + are absolutely centered regardless, but this keeps it consistent. */ + display: flex !important; + width: 56px !important; + height: 56px !important; + /* Respect the configured position on mobile too, so the closed launcher can + clear a fixed bottom nav bar (the main reason to move it up). */ + bottom: ${t.launcherBottom}px !important; + ${n}: ${t.launcherRight}px !important; + } + + .ask-anything-mobile #replypier-mobile-close.active { + display: flex !important; + } + + #replypier-mobile-close:hover { + opacity: 0.7; + } + + /* ASK_ANYTHING style specific mobile topbar */ + .ask-anything-mobile #replypier-mobile-topbar.active { + display: flex !important; + } + + .ask-anything-mobile #replypier-mobile-close.active { + top: 15px !important; + right: 15px !important; + z-index: ${t.zIndex+2} !important; + } + + /* When topbar is visible, push iframe down to avoid overlap */ + .ask-anything-mobile .replypier-iframe { + top: 60px !important; + height: calc(100vh - 60px) !important; + height: calc(100dvh - 60px) !important; + } + } + + @media (min-width: 769px) { + #replypier-mobile-close { + display: none !important; + } + } + + /* Chat Initiation Message Styles */ + #${t.initiationMessageId} { + position: fixed !important; + /* Sit above the launcher (+12px gap) and align to its edge on the active side, + so it never overlaps the icon regardless of the configured position/mode. */ + bottom: ${(t.launcherBottom||20)+r+12}px !important; + ${n}: ${t.launcherRight||20}px !important; + max-width: 260px !important; + background: white !important; + padding: 12px 36px 12px 14px !important; + border-radius: 14px !important; + box-shadow: 0 3px 16px rgba(0, 0, 0, 0.1) !important; + z-index: ${t.zIndex-1} !important; + cursor: pointer !important; + opacity: 0; + visibility: hidden; + transform: translateY(10px) scale(0.95); + transition: all 0.4s cubic-bezier(0.22, 1, 0.36, 1) !important; + font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif !important; + font-size: 14px !important; + box-sizing: border-box !important; + margin: 0 !important; + border: none !important; + display: block !important; + width: auto !important; + height: auto !important; + min-width: 0 !important; + min-height: 0 !important; + max-height: none !important; + line-height: 1.4 !important; + text-align: left !important; + vertical-align: baseline !important; + overflow: visible !important; + } + /* Clamp the nudge text to 4 lines with an ellipsis so a long welcome/initiation + message can never balloon the bubble over the page or into the launcher. + Applied to the text node only, so the orb (left:-34px) is never clipped. */ + #${t.initiationMessageId} .initiation-message-text { + margin: 0 !important; + display: -webkit-box !important; + -webkit-line-clamp: 4 !important; + -webkit-box-orient: vertical !important; + overflow: hidden !important; + } + + /* Siri-style orb avatar beside the nudge (design comp) */ + .initiation-orb { + position: absolute !important; + left: -34px !important; + bottom: 2px !important; + width: 26px !important; + height: 26px !important; + border-radius: 50% !important; + background: conic-gradient(from 0deg, #C9F24E, #9D8CFF, #5FE3D6, #FF8A73, #C9F24E) !important; + box-shadow: 0 4px 14px rgba(157, 140, 255, 0.4) !important; + animation: replypier-orb-spin 6s linear infinite !important; + z-index: 1 !important; + } + @keyframes replypier-orb-spin { to { transform: rotate(360deg); } } + ${n==="left"?` + /* On the left edge the orb (which protrudes 34px past the bubble) would clip + off-screen \u2014 mirror it to the bubble's page-facing side. */ + .initiation-orb { + left: auto !important; + right: -34px !important; + } + `:""} + + #${t.initiationMessageId}.show { + opacity: 1; + visibility: visible; + transform: translateY(0) scale(1); + animation: replypier-bounce-in 0.6s cubic-bezier(0.68, -0.55, 0.265, 1.55); + } + + @keyframes replypier-bounce-in { + 0% { + opacity: 0; + transform: translateY(20px) scale(0.8); + } + 50% { + transform: translateY(-5px) scale(1.02); + } + 100% { + opacity: 1; + transform: translateY(0) scale(1); + } + } + + #${t.initiationMessageId}:hover { + transform: translateY(-2px) scale(1.02); + box-shadow: 0 5px 20px rgba(0, 0, 0, 0.14); + } + + #${t.initiationMessageId}::after { + content: '' !important; + position: absolute !important; + bottom: -7px !important; + ${n}: 30px !important; + width: 14px !important; + height: 14px !important; + min-width: 14px !important; + min-height: 14px !important; + max-width: 14px !important; + max-height: 14px !important; + background: white !important; + transform: rotate(45deg) !important; + box-shadow: 3px 3px 5px rgba(0, 0, 0, 0.06) !important; + clip-path: polygon(0 0, 100% 0, 100% 100%) !important; + border: none !important; + margin: 0 !important; + padding: 0 !important; + box-sizing: border-box !important; + z-index: -1 !important; + } + + .initiation-message-text { + font-size: 13px !important; + line-height: 1.4 !important; + color: #374151 !important; + margin: 0 !important; + padding: 0 4px 0 0 !important; + position: relative !important; + z-index: 1 !important; + min-height: 18px !important; + box-sizing: border-box !important; + border: none !important; + background: transparent !important; + display: block !important; + width: 100% !important; + height: auto !important; + max-width: none !important; + max-height: none !important; + text-align: left !important; + vertical-align: baseline !important; + font-weight: normal !important; + font-style: normal !important; + text-decoration: none !important; + text-transform: none !important; + letter-spacing: normal !important; + word-spacing: normal !important; + white-space: normal !important; + overflow-wrap: break-word !important; + word-wrap: break-word !important; + } + + .initiation-message-text::after { + content: '|'; + animation: blink 1s step-end infinite; + margin-left: 2px; + color: ${t.chatBubbleColor}; + font-weight: 500; + } + + .initiation-message-text.typing-complete::after { + display: none; + } + + @keyframes blink { + 0%, 50% { opacity: 1; } + 51%, 100% { opacity: 0; } + } + + .initiation-close { + position: absolute !important; + top: 10px !important; + right: 10px !important; + width: 20px !important; + height: 20px !important; + min-width: 20px !important; + min-height: 20px !important; + max-width: 20px !important; + max-height: 20px !important; + background: rgba(0, 0, 0, 0.04) !important; + border: none !important; + border-radius: 5px !important; + cursor: pointer !important; + opacity: 0.5 !important; + transition: all 0.2s ease !important; + z-index: 2 !important; + display: flex !important; + align-items: center !important; + justify-content: center !important; + padding: 0 !important; + margin: 0 !important; + box-sizing: border-box !important; + outline: none !important; + box-shadow: none !important; + text-decoration: none !important; + font-size: 0 !important; + line-height: 0 !important; + overflow: hidden !important; + flex-shrink: 0 !important; + } + + .initiation-close:hover { + opacity: 1 !important; + background: rgba(0, 0, 0, 0.08) !important; + transform: scale(1.05) !important; + } + + .initiation-close::before, + .initiation-close::after { + content: '' !important; + position: absolute !important; + width: 9px !important; + height: 1.5px !important; + min-width: 9px !important; + min-height: 1.5px !important; + max-width: 9px !important; + max-height: 1.5px !important; + background: #4a5568 !important; + border-radius: 1px !important; + top: 50% !important; + left: 50% !important; + margin: -0.75px 0 0 -4.5px !important; + padding: 0 !important; + border: none !important; + box-sizing: border-box !important; + } + + .initiation-close::before { + transform: rotate(45deg) !important; + } + + .initiation-close::after { + transform: rotate(-45deg) !important; + } + + @media (max-width: 768px) { + #${t.initiationMessageId} { + display: none !important; + } + } + + /* Error UI Styles */ + .replypier-error-ui { + width: 100%; + height: 100%; + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + background: linear-gradient(135deg, #f8fafc 0%, #f1f5f9 100%); + border-radius: 24px; + overflow: hidden; + position: relative; + } + + .replypier-error-ui::before { + content: ''; + position: absolute; + top: 0; + left: 0; + right: 0; + bottom: 0; + background: + radial-gradient(circle at 20% 30%, rgba(99, 102, 241, 0.08) 0%, transparent 50%), + radial-gradient(circle at 80% 70%, rgba(168, 85, 247, 0.06) 0%, transparent 50%); + pointer-events: none; + } + + .replypier-error-card { + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + padding: 32px 24px; + text-align: center; + position: relative; + z-index: 1; + max-width: 90%; + } + + .replypier-error-close { + position: absolute; + top: 12px; + right: 12px; + z-index: 2; + width: 36px; + height: 36px; + display: flex; + align-items: center; + justify-content: center; + border: none; + border-radius: 50%; + background: rgba(120, 120, 140, 0.12); + color: #4b5563; + font-size: 22px; + line-height: 1; + cursor: pointer; + transition: background 0.15s ease; + } + .replypier-error-close:hover { + background: rgba(120, 120, 140, 0.22); + } + + .replypier-error-icon-wrapper { + display: flex; + align-items: center; + justify-content: center; + width: 72px; + height: 72px; + background: linear-gradient(135deg, #e0e7ff 0%, #c7d2fe 100%); + border-radius: 20px; + margin-bottom: 20px; + box-shadow: 0 8px 24px rgba(99, 102, 241, 0.15); + } + + .replypier-error-icon { + width: 36px; + height: 36px; + color: #6366f1; + } + + .replypier-error-title { + font-size: 20px; + font-weight: 600; + color: #1e293b; + margin: 0 0 12px 0; + letter-spacing: -0.01em; + font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif; + } + + .replypier-error-message { + font-size: 14px; + line-height: 1.6; + color: #64748b; + margin: 0 0 24px 0; + max-width: 280px; + font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif; + } + + .replypier-error-footer { + display: flex; + align-items: center; + justify-content: center; + gap: 6px; + font-size: 12px; + color: #94a3b8; + opacity: 0.8; + font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif; + } + .replypier-error-footer-link { + color: inherit; + text-decoration: none; + cursor: pointer; + } + .replypier-error-footer-link:hover { + text-decoration: underline; + } + + @media (max-width: 768px) { + .replypier-error-ui { + border-radius: 0; + } + + .replypier-error-card { + padding: 24px 20px; + } + + .replypier-error-icon-wrapper { + width: 64px; + height: 64px; + border-radius: 16px; + } + + .replypier-error-icon { + width: 32px; + height: 32px; + } + + .replypier-error-title { + font-size: 18px; + } + + .replypier-error-message { + font-size: 13px; + max-width: 260px; + } + } + + ${t.launcher?"":` + /* Launcher hidden by config \u2014 the site opens the chat with its own trigger or + the JS API. Last in the sheet so it also beats the mobile .mobile-closed + re-show (display: flex !important at equal specificity). */ + #${t.buttonId}, #${t.buttonId}.mobile-closed { display: none !important; } + `} + `;let f=document.getElementById("replypier-styles");f&&f.remove(),document.head.appendChild(w),ve()}function ve(){let e=document.getElementById(t.buttonId);if(!e)return;let i=e.querySelector(".rp-search-placeholder");i&&i.textContent!==t.searchPlaceholder&&(i.textContent=t.searchPlaceholder)}function C(e){if(typeof e!="string")return null;let i=e.trim();return!i||i==="undefined"||i==="null"?null:i}function le(){return C(window.replypierToken)||C(localStorage.getItem(t.tokenKey))}function de(e){let i=C(e);if(!i)return null;let n=i.split(".")[1];if(!n)return null;try{let r=JSON.parse(atob(n.replace(/-/g,"+").replace(/_/g,"/")));return r.sub||r.customer_id||null}catch(r){return null}}function J(e){e&&localStorage.setItem(t.tokenKey,e)}function W(){localStorage.removeItem(t.tokenKey)}function H(){return window.innerWidth<=768}function Be(e){return e?e.replace(/\uFFFD/g,"").replace(/[��]/g,"").replace(/[\x00-\x1F\x7F-\x9F]/g,"").trim():""}function Pe(){if(!t.chatInitiationMessages||t.chatInitiationMessages.length===0)return null;let e=Math.floor(Math.random()*t.chatInitiationMessages.length),i=t.chatInitiationMessages[e];return i?Be(i):null}function Re(){return H()||!t.launcher||!t.chatInitiationMessages||t.chatInitiationMessages.length===0?!1:!sessionStorage.getItem(t.initiationShownKey)}function pe(){sessionStorage.setItem(t.initiationShownKey,"true")}function Ne(){let e=Pe();if(!e)return null;let i=document.createElement("div");return i.id=t.initiationMessageId,i.innerHTML=` + + +

+ `,i.dataset.fullMessage=e,i}function Fe(e,i,n=50){let r=e.querySelector(".initiation-message-text");if(!r)return;let c=0,a=setInterval(()=>{c{e.classList.add("show"),setTimeout(()=>{let r=e.dataset.fullMessage;r&&Fe(e,r,40)},300)},1500),e.addEventListener("click",r=>{r.target.classList.contains("initiation-close")||(e.typeInterval&&clearInterval(e.typeInterval),ce(e),i(),pe())});let n=e.querySelector(".initiation-close");n&&n.addEventListener("click",r=>{r.stopPropagation(),e.typeInterval&&clearInterval(e.typeInterval),ce(e),pe()})}function ce(e){e&&(e.classList.remove("show"),setTimeout(()=>{e.parentNode&&e.parentNode.removeChild(e)},400))}function he(){x=!1,O();let e=document.createElement("div");e.id=t.buttonId,e.classList.add("replypier-pending"),e.innerHTML=` + + +
+ ⌄ + + + + + + `,M=setTimeout(N,8e3);let i=document.createElement("div");i.id=t.containerId;let n=document.createElement("div");n.id="replypier-mobile-close",n.innerHTML=` + + + + `;let r=document.createElement("div");r.id="replypier-mobile-topbar",r.innerHTML=` +

\u804A\u5929

+
+ `;let c=document.createElement("div");c.id=t.backdropId,document.body.appendChild(e),document.body.appendChild(c),document.body.appendChild(i),document.body.appendChild(n),document.body.appendChild(r),F(),ve();let a=!1,d=null,w=!1,f=null;function b(){a=!a,i.classList.toggle("active"),c.classList.toggle("active",a),e.classList.toggle("active"),n.classList.toggle("active"),a&&(t.hasOpened=!0,t.unreadCount=0),d&&d.contentWindow&&d.contentWindow.postMessage({type:"WIDGET_VISIBILITY",open:a},"*"),F(),a&&f&&(ce(f),f=null,pe()),H()?a?(e.classList.remove("mobile-closed"),e.style.animation=""):(e.classList.add("mobile-closed"),e.style.animation="replypier-float 4s ease-in-out infinite",r.classList.remove("active"),document.body.classList.remove("ask-anything-mobile")):a&&n.classList.remove("active"),a&&d&&d.contentWindow.postMessage({type:"SCROLL_TO_BOTTOM"},"*"),_(a?"open":"close")}let U=null,fe=!1;function Ge(o){let s=String(o||"").slice(0,2e3);s&&(fe&&d&&d.contentWindow?d.contentWindow.postMessage({type:"PREFILL_MESSAGE",text:s},"*"):U=s)}let K=0;function Ce(){for(K++;i.firstChild;)i.removeChild(i.firstChild);d=null,g=null,L=null,fe=!1,re=!1,U=null,w=!1,e.classList.remove("loading"),P=0,q()}function je(){a&&b(),Ce(),t.unreadCount=0,t.hasOpened=!1,F(),Q()}function qe(){a&&b(),Ce(),window.removeEventListener("resize",Le),window.removeEventListener("message",Ae),f&&(f.typeInterval&&clearInterval(f.typeInterval),me(f),f=null),[e,c,i,n,r].forEach(me),me(document.getElementById("replypier-styles")),document.body.classList.remove("ask-anything-mobile"),ae=!1,M&&(clearTimeout(M),M=null),se.length=0,t.unreadCount=0,t.hasOpened=!1,l=null,R.length=0,V=!1,x=!0}function Se(o){let s=document.createElement("div");s.className="replypier-error-ui";let I=document.createElement("div");I.className="replypier-error-card";let v=document.createElement("button");v.type="button",v.className="replypier-error-close",v.setAttribute("aria-label","\u5173\u95ED\u804A\u5929"),v.textContent="\xD7",v.addEventListener("click",function(){a&&b()}),s.appendChild(v);let u=document.createElement("div");u.className="replypier-error-icon-wrapper";let h=document.createElementNS("http://www.w3.org/2000/svg","svg");h.setAttribute("class","replypier-error-icon"),h.setAttribute("viewBox","0 0 24 24"),h.setAttribute("fill","none"),h.setAttribute("stroke","currentColor"),h.setAttribute("stroke-width","1.5");let k=document.createElementNS("http://www.w3.org/2000/svg","path");k.setAttribute("d","M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z");let $=document.createElementNS("http://www.w3.org/2000/svg","path");$.setAttribute("d","M9 12l2 2 4-4"),h.appendChild(k),h.appendChild($),u.appendChild(h);let S=document.createElement("h2");S.className="replypier-error-title",S.textContent="\u5BA2\u670D\u6682\u4E0D\u53EF\u7528";let be=document.createElement("p");be.className="replypier-error-message",be.textContent=o;let te=document.createElement("div");te.className="replypier-error-footer";let ye=document.createElement("span");ye.innerHTML=_e;let xe=ye.querySelector("svg");xe.setAttribute("width","20"),xe.setAttribute("height","16"),xe.setAttribute("aria-hidden","true");let T=document.createElement("a");return T.href="https://replypier.site",T.target="_blank",T.rel="noopener noreferrer",T.className="replypier-error-footer-link",T.textContent="\u7531 ReplyPier \u63D0\u4F9B\u652F\u6301",te.appendChild(ye),te.appendChild(T),I.appendChild(u),I.appendChild(S),I.appendChild(be),I.appendChild(te),s.appendChild(I),s}function Q(){return we(this,null,function*(){if(w||d)return;let o=K;try{w=!0,e.classList.add("loading");let s=le(),I=`${t.baseUrl}/widgets/${window.replypierId}/data?widget_id=${window.replypierId}`,v={method:"GET",mode:"cors",headers:s?{Authorization:`Bearer ${s}`}:{}};fetch(I,v).then(u=>we(null,null,function*(){if(o!==K)return null;if(u.status===401)try{let k=(yield u.json()).detail;if(k&&k.code==="identity_expired")return e.classList.remove("loading"),_("identityExpired"),Ve(),null;let $=typeof k=="string"?k:"";if($.includes("generate-token")||$.includes("API key")||$.includes("Token must be obtained")){e.classList.remove("loading"),W();let S=Se("\u6B64\u804A\u5929\u7EC4\u4EF6\u5C1A\u672A\u914D\u7F6E\u5B8C\u6210\uFF0C\u8BF7\u8054\u7CFB\u7F51\u7AD9\u7BA1\u7406\u5458\u5F00\u901A\u5728\u7EBF\u5BA2\u670D\u3002");return i.appendChild(S),N(),null}}catch(h){}if(!u.ok)throw new Error("HTTP error! status: "+u.status);return u.text()})).then(u=>{u!==null&&o===K&&(d=document.createElement("iframe"),d.className="replypier-iframe",d.title="\u804A\u5929",d.srcdoc=u,d.addEventListener("load",function(){fe=!0,d.contentWindow.postMessage(Ie(),"*"),d.contentWindow.postMessage({type:"WIDGET_VISIBILITY",open:a},"*"),U&&(d.contentWindow.postMessage({type:"PREFILL_MESSAGE",text:U},"*"),U=null),re=!0,Y=!1,_("ready")}),i.appendChild(d),g=d.contentWindow,e.classList.remove("loading"),d.style.opacity="1")}).catch(u=>{if(o!==K)return;console.error("Failed to load widget:",u),e.classList.remove("loading");let h=window.location.hostname||"\u5F53\u524D\u57DF\u540D",$=/^(localhost|127\.0\.0\.1|0\.0\.0\.0|\[?::1\]?)$/i.test(h)||/\.local$/i.test(h)?"\u804A\u5929\u7A97\u53E3\u65E0\u6CD5\u5728\u201C"+h+"\u201D\u4E0A\u52A0\u8F7D\u3002\u672C\u5730\u6D4B\u8BD5\u65F6\uFF0C\u8BF7\u5728 ReplyPier \u540E\u53F0\uFF08\u7EC4\u7EC7\u8BBE\u7F6E\uFF09\u4E2D\u628A\u7EC4\u7EC7\u57DF\u540D\u8BBE\u4E3A\u201C"+h+"\u201D\u3002":"\u804A\u5929\u7A97\u53E3\u65E0\u6CD5\u5728\u201C"+h+"\u201D\u4E0A\u52A0\u8F7D\u3002\u8BF7\u5728 ReplyPier \u540E\u53F0\uFF08\u7EC4\u7EC7\u8BBE\u7F6E\uFF09\u4E2D\u5C06\u6B64\u57DF\u540D\u52A0\u5165\u7EC4\u7EC7\uFF0C\u5373\u53EF\u5728\u6B64\u542F\u7528\u804A\u5929\u3002",S=Se($);i.appendChild(S),N()})}catch(s){console.error("Failed to load widget:",s),e.classList.remove("loading"),N()}finally{w=!1}})}function Ae(o){if(!(!o.data||typeof o.data.type!="string")&&!(!g||o.source!==g)){if(o.data.type==="UNREAD_COUNT"){t.unreadCount=Math.max(0,parseInt(o.data.count,10)||0),F(),_("unread",t.unreadCount);return}if(o.data.type==="TOKEN_UPDATE"){let s=C(o.data.token);if(!s)return;J(s),o.source.postMessage({type:"TOKEN_RECEIVED",token:s},"*");return}if(o.data.type==="CHAT_SESSION"){L=String(o.data.sessionId||"")||null,o.data.created&&_("chatCreated",{sessionId:L,authenticated:!!o.data.authenticated});return}o.data.type==="IDENTITY_EXPIRED"&&(_("identityExpired"),Ze())}}function Ve(){if(Y||typeof t.tokenProvider!="function"){W(),window.replypierToken=null,Q();return}Y=!0,Promise.resolve().then(()=>t.tokenProvider()).then(o=>{let s=C(o);s?(window.replypierToken=s,J(s)):(W(),window.replypierToken=null)}).catch(o=>{console.error("ReplyPier: tokenProvider failed",o),W(),window.replypierToken=null}).finally(()=>{Q()})}let ge=!1,Y=!1;function Ze(){if(!ge){if(Y||typeof t.tokenProvider!="function"){ee({type:"IDENTITY_UNAVAILABLE"});return}ge=!0,Y=!0,Promise.resolve().then(()=>t.tokenProvider()).then(o=>{let s=C(o);if(!s){ee({type:"IDENTITY_UNAVAILABLE"});return}window.replypierToken=s,J(s),ee({type:"TOKEN_REFRESH",token:s})}).catch(o=>{console.error("ReplyPier: tokenProvider failed",o),ee({type:"IDENTITY_UNAVAILABLE"})}).finally(()=>{ge=!1})}}function ee(o){g&&g.postMessage(o,"*")}window.addEventListener("message",Ae),Q(),se.push(()=>{setTimeout(()=>{x||!a&&t.chatInitiationMessages.length>0&&(f=Ne(),Oe(f,b))},2e3)}),e.addEventListener("click",b),n.addEventListener("click",b),c.addEventListener("click",function(){a&&b()}),H()&&!a&&(e.classList.add("mobile-closed"),e.style.animation="replypier-float 4s ease-in-out infinite");function Le(){let o=H();o&&!a?(e.classList.add("mobile-closed"),e.style.animation="replypier-float 4s ease-in-out infinite",n.classList.remove("active")):o||(e.classList.remove("mobile-closed"),e.style.animation="",a&&n.classList.remove("active")),O(),q()}window.addEventListener("resize",Le),l={isOpen:function(){return a},toggle:b,open:function(o){a||b(),o&&o.message&&Ge(o.message)},close:function(){a&&b()},reload:je,destroy:qe},R.splice(0).forEach(function(o){try{o()}catch(s){}})}$e(window.replypierConfig),document.readyState==="loading"?document.addEventListener("DOMContentLoaded",function(){x||he()}):he();let We=typeof navigator!="undefined"&&/Mac|iPod|iPhone|iPad/.test(navigator.platform||"");document.addEventListener("keydown",function(e){if(!l||!j())return;let i=We?e.metaKey&&!e.ctrlKey:e.ctrlKey&&!e.metaKey;if(t.hotkey&&i&&!e.altKey&&!e.repeat&&(e.key==="k"||e.key==="K")){e.preventDefault(),l.toggle();return}e.key==="Escape"&&l.isOpen()&&l.close()}),document.addEventListener("click",function(e){let i=e.target;if(!i||!i.closest)return;let n=i.closest("[data-replypier-open]");if(!n&&t.trigger)try{n=i.closest(t.trigger)}catch(r){}n&&(n.tagName==="A"&&e.preventDefault(),l?l.toggle():!x&&!V&&(V=!0,R.push(function(){l.open()})))}),window.addEventListener("message",function(e){if(!(!e.data||typeof e.data.type!="string")&&!(!g||e.source!==g)){if(e.data.type==="WIDGET_RESIZE"){if(typeof e.data.height!="number"||!isFinite(e.data.height))return;P=Math.round(e.data.height),q();return}if(e.data.type==="WIDGET_SURFACE"){let i=!!e.data.palette;if(t.surfaceIsPalette===i)return;t.surfaceIsPalette=i,i||(P=0),O(),q();return}if(e.data.type==="WIDGET_MINIMIZE"){Z(function(){l.close()});return}if(e.data.type==="CUSTOMIZATION_UPDATE"){let i=e.data.data,n=i.chat_bubble_color;if(t.chatBubbleColor=ie(n)?n:t.chatBubbleColor,typeof i.chat_style=="string"&&(t.chatStyle=i.chat_style),i.chat_initiation_messages&&Array.isArray(i.chat_initiation_messages)&&(t.chatInitiationMessages=i.chat_initiation_messages),Te(i.widget_display),!H())E.containerBottom||(t.containerBottom=i.chat_style==="ASK_ANYTHING"?90:100);else{let r=l?l.isOpen():!1,c=document.getElementById("replypier-mobile-topbar");i.chat_style==="ASK_ANYTHING"&&r?(document.body.classList.add("ask-anything-mobile"),c&&c.classList.add("active")):(document.body.classList.remove("ask-anything-mobile"),c&&c.classList.remove("active"))}O(),F(),N(),e.source&&typeof e.source.postMessage=="function"&&e.source.postMessage(Ie(),"*")}}});function m(e){return typeof e=="number"&&isFinite(e)}function me(e){e&&e.parentNode&&e.parentNode.removeChild(e)}function ue(){document.getElementById("replypier-styles")&&O()}function ke(e,i){if(!e||typeof e!="object")return;(e.side==="left"||e.side==="right")&&p("side",e.side),m(e.bottom)&&p("launcherBottom",Math.max(0,e.bottom));let n=m(e.offset)?e.offset:e.right;m(n)&&p("launcherRight",Math.max(0,n)),i||ue()}function $e(e){!e||typeof e!="object"||(e.baseUrl&&(t.baseUrl=e.baseUrl),e.id&&(window.replypierId=e.id),typeof e.tokenProvider=="function"&&(t.tokenProvider=e.tokenProvider),typeof e.launcher=="boolean"&&p("launcher",e.launcher),D.indexOf(e.displayMode)!==-1&&p("displayMode",e.displayMode),m(e.width)&&(p("containerWidth",Math.max(280,e.width)),A.width=!0),m(e.height)&&(p("containerHeight",Math.max(400,e.height)),A.height=!0),typeof e.hotkey=="boolean"&&p("hotkey",e.hotkey),m(e.sidebarWidth)&&p("sidebarWidth",Math.max(280,e.sidebarWidth)),m(e.zIndex)&&p("zIndex",Math.max(1,Math.floor(e.zIndex))),typeof e.trigger=="string"&&e.trigger&&p("trigger",e.trigger),e.searchBar&&typeof e.searchBar=="object"&&(typeof e.searchBar.placeholder=="string"&&e.searchBar.placeholder&&p("searchPlaceholder",e.searchBar.placeholder.slice(0,80)),m(e.searchBar.width)&&p("searchBarWidth",Math.max(160,e.searchBar.width))),e.position&&ke(e.position,!0),ue())}function He(){l&&l.reload()}function Ee(e,i){if(e&&i){let n=`${t.baseUrl}/widgets/${window.replypierId}/end-chat?session_id=${encodeURIComponent(i)}&reason=CUSTOMER_REQUEST`;try{fetch(n,{method:"POST",mode:"cors",keepalive:!0,headers:{Authorization:`Bearer ${e}`}}).catch(()=>{})}catch(r){}}L=null,He()}function Ue(){if(l){l.reload();return}x&&(x=!1,document.readyState!=="loading"&&he())}function Ke(){if(l){l.destroy();return}x=!0,R.length=0,V=!1}function Ye(e){let i=C(e);if(!i)return;let n=le();if(i===n)return;let r=n&&de(i)&&de(i)===de(n);if(window.replypierToken=i,J(i),r&&g){g.postMessage({type:"TOKEN_REFRESH",token:i},"*");return}Ee(n,L)}function De(){let e=le(),i=L;window.replypierToken=null,W(),Ee(e,i)}function Me(e){p("launcher",!!e),ue()}window.ReplyPier={init:$e,setPosition:function(e){ke(e)},open:function(e){Z(function(){l.open(e)})},close:function(){Z(function(){l.close()})},toggle:function(){Z(function(){l.toggle()})},isOpen:function(){return l?l.isOpen():!1},showLauncher:function(){Me(!0)},hideLauncher:function(){Me(!1)},identify:function(e){Ye(e)},logout:function(){De()},reload:function(){Ue()},destroy:function(){Ke()},on:function(e,i){if(!(typeof e!="string"||typeof i!="function")){if(e==="ready"&&re){try{i()}catch(n){}return}(X[e]=X[e]||[]).push(i)}},off:function(e,i){let n=X[e];if(!n)return;let r=n.indexOf(i);r!==-1&&n.splice(r,1)}}})();})(); diff --git a/frontend/scripts/build-webclient-dev.ts b/frontend/scripts/build-webclient-dev.ts index 7e72703..3a609a1 100644 --- a/frontend/scripts/build-webclient-dev.ts +++ b/frontend/scripts/build-webclient-dev.ts @@ -23,18 +23,18 @@ async function buildWebClientDev() { process.env.NODE_ENV = 'development' // Baked DEFAULT base URL only; getBaseUrl() still resolves - // window.chattermateBaseUrl / window.APP_CONFIG at runtime, so no rebuild is + // window.replypierBaseUrl / window.APP_CONFIG at runtime, so no rebuild is // needed when a deployment's env changes. const apiUrl = process.env.VITE_API_URL || 'http://localhost:8000/api/v1' console.log('Using API URL:', apiUrl) - const sourceFile = resolve(dirname(__dirname), 'src/webclient/chattermate.js') + const sourceFile = resolve(dirname(__dirname), 'src/webclient/replypier.js') await build({ entryPoints: [sourceFile], bundle: true, minify: false, // Don't minify for development - outfile: resolve(dirname(__dirname), 'public/webclient/chattermate.min.js'), + outfile: resolve(dirname(__dirname), 'public/webclient/replypier.min.js'), format: 'iife', target: ['es2015'], loader: { @@ -42,17 +42,17 @@ async function buildWebClientDev() { }, define: { 'process.env.NODE_ENV': '"development"', - '__CHATTERMATE_API_URL__': JSON.stringify(apiUrl), + '__REPLYPIER_API_URL__': JSON.stringify(apiUrl), }, sourcemap: true, // Add sourcemap for development }) // Copy output to dist/webclient directory - const publicWebclientPath = resolve(dirname(__dirname), 'public/webclient/chattermate.min.js') - const publicSourcemapPath = resolve(dirname(__dirname), 'public/webclient/chattermate.min.js.map') + const publicWebclientPath = resolve(dirname(__dirname), 'public/webclient/replypier.min.js') + const publicSourcemapPath = resolve(dirname(__dirname), 'public/webclient/replypier.min.js.map') const distWebclientDir = resolve(dirname(__dirname), 'dist/webclient') - const distWebclientPath = resolve(distWebclientDir, 'chattermate.min.js') - const distSourcemapPath = resolve(distWebclientDir, 'chattermate.min.js.map') + const distWebclientPath = resolve(distWebclientDir, 'replypier.min.js') + const distSourcemapPath = resolve(distWebclientDir, 'replypier.min.js.map') // Ensure dist/webclient directory exists if (!fs.existsSync(distWebclientDir)) { diff --git a/frontend/scripts/build-webclient-prod.ts b/frontend/scripts/build-webclient-prod.ts index c4120b2..0b0ad04 100644 --- a/frontend/scripts/build-webclient-prod.ts +++ b/frontend/scripts/build-webclient-prod.ts @@ -22,18 +22,18 @@ async function buildWebClientProd() { process.env.NODE_ENV = 'production' // Baked DEFAULT base URL. This only sets the fallback; getBaseUrl() still - // resolves window.chattermateBaseUrl / window.APP_CONFIG at runtime, so an + // resolves window.replypierBaseUrl / window.APP_CONFIG at runtime, so an // env change on a deployment needs no rebuild of this artifact. - const apiUrl = process.env.VITE_API_URL || 'https://api.chattermate.chat/api/v1' + const apiUrl = process.env.VITE_API_URL || 'https://api.replypier.site/api/v1' console.log('Using API URL:', apiUrl) - const sourceFile = resolve(dirname(__dirname), 'src/webclient/chattermate.js') + const sourceFile = resolve(dirname(__dirname), 'src/webclient/replypier.js') await build({ entryPoints: [sourceFile], bundle: true, minify: true, - outfile: resolve(dirname(__dirname), 'public/webclient/chattermate.min.js'), + outfile: resolve(dirname(__dirname), 'public/webclient/replypier.min.js'), format: 'iife', target: ['es2015'], loader: { @@ -41,14 +41,14 @@ async function buildWebClientProd() { }, define: { 'process.env.NODE_ENV': '"production"', - '__CHATTERMATE_API_URL__': JSON.stringify(apiUrl), + '__REPLYPIER_API_URL__': JSON.stringify(apiUrl), }, }) // Copy output to dist/webclient directory - const publicWebclientPath = resolve(dirname(__dirname), 'public/webclient/chattermate.min.js') + const publicWebclientPath = resolve(dirname(__dirname), 'public/webclient/replypier.min.js') const distWebclientDir = resolve(dirname(__dirname), 'dist/webclient') - const distWebclientPath = resolve(distWebclientDir, 'chattermate.min.js') + const distWebclientPath = resolve(distWebclientDir, 'replypier.min.js') // Ensure dist/webclient directory exists if (!fs.existsSync(distWebclientDir)) { diff --git a/frontend/scripts/generate-prod-env.ts b/frontend/scripts/generate-prod-env.ts index 7406538..807b0e1 100644 --- a/frontend/scripts/generate-prod-env.ts +++ b/frontend/scripts/generate-prod-env.ts @@ -14,9 +14,9 @@ const configContent = `// Runtime configuration - this file gets replaced at con // it too; in a page self === window, so window.APP_CONFIG still works. self.APP_CONFIG = { // API URLs - API_URL: "${process.env.VITE_API_URL || 'https://api.chattermate.chat/api/v1'}", - WS_URL: "${process.env.VITE_WS_URL || 'wss://api.chattermate.chat'}", - WIDGET_URL: "${process.env.VITE_WIDGET_URL || 'https://api.chattermate.chat'}", + API_URL: "${process.env.VITE_API_URL || 'https://api.replypier.site/api/v1'}", + WS_URL: "${process.env.VITE_WS_URL || 'wss://api.replypier.site'}", + WIDGET_URL: "${process.env.VITE_WIDGET_URL || 'https://api.replypier.site'}", // Firebase Configuration FIREBASE_API_KEY: "${process.env.VITE_FIREBASE_API_KEY || ''}", diff --git a/frontend/src/App.vue b/frontend/src/App.vue index ccc513d..78ded83 100644 --- a/frontend/src/App.vue +++ b/frontend/src/App.vue @@ -1,5 +1,5 @@
{
@@ -594,8 +594,8 @@ const handleInitiationClick = () => {
-
@@ -611,7 +611,7 @@ const handleInitiationClick = () => {

{{ agentName }}

- {{ isActive ? '在线 · 即时回复' : '离线' }} + {{ isActive ? '在线 · 即时回复' : '离线' }}
@@ -631,9 +631,9 @@ const handleInitiationClick = () => {
-
-
- +
+
+
{
-
@@ -748,13 +748,13 @@ const handleInitiationClick = () => { transition: all 0.3s ease; } -.cm-toggle-dots { +.rp-toggle-dots { display: flex; gap: 5px; align-items: center; justify-content: center; } -.cm-toggle-dots span { +.rp-toggle-dots span { width: 7px; height: 7px; border-radius: 50%; @@ -1136,7 +1136,7 @@ const handleInitiationClick = () => { line-height: 1.3; /* The theme's muted colour, not opacity over the text colour: dimming by opacity fell below readable contrast on light themes. */ - color: var(--cm-muted); + color: var(--rp-muted); } .ai-disclaimer + .powered-by { padding-top: 0; } @@ -1150,15 +1150,15 @@ const handleInitiationClick = () => { font-size: 0.75rem; border-top: 1px solid var(--o08); } -.powered-by .chattermate-logo, -.powered-by-welcome .chattermate-logo { +.powered-by .replypier-logo, +.powered-by-welcome .replypier-logo { flex-shrink: 0; } -/* "Powered by" is muted; "ChatterMate" is emphasized (comp). Both inherit the footer's - own colour (white on dark themes) so ChatterMate stays visible — dimming is on the +/* "Powered by" is muted; "ReplyPier" is emphasized (comp). Both inherit the footer's + own colour (white on dark themes) so ReplyPier stays visible — dimming is on the prefix only, never a dark app token that would vanish on the dark panel. */ -.cm-powered-prefix { color: var(--cm-muted); } -.cm-brand { font-weight: 700; } +.rp-powered-prefix { color: var(--rp-muted); } +.rp-brand { font-weight: 700; } .message-input input:disabled { cursor: not-allowed; @@ -1179,9 +1179,9 @@ const handleInitiationClick = () => { /* ===== Message entrance animation ===== */ .chat-messages .message { - animation: cm-msg-in 0.34s cubic-bezier(0.2, 0.7, 0.2, 1) both; + animation: rp-msg-in 0.34s cubic-bezier(0.2, 0.7, 0.2, 1) both; } -@keyframes cm-msg-in { +@keyframes rp-msg-in { from { opacity: 0; transform: translateY(8px); } to { opacity: 1; transform: none; } } diff --git a/frontend/src/components/agent/AgentCustomizationView.vue b/frontend/src/components/agent/AgentCustomizationView.vue index bb89be3..3997b9f 100644 --- a/frontend/src/components/agent/AgentCustomizationView.vue +++ b/frontend/src/components/agent/AgentCustomizationView.vue @@ -1,5 +1,5 @@ @@ -172,7 +172,7 @@ const iframeEmbedCode = computed(() => {
生成 Token(服务端)

- 创建一个后端接口,调用 ChatterMate API 生成 Token: + 创建一个后端接口,调用 ReplyPier API 生成 Token:

// Your backend endpoint (e.g., /api/chat-token)
@@ -207,7 +207,7 @@ const { data } = await response.json();
                 
加入网站(客户端)

- 把这段代码加入 HTML,并将 /api/chattermate 换成你的后端接口: + 把这段代码加入 HTML,并将 /api/replypier 换成你的后端接口:

{{ embedCode }}
@@ -267,7 +267,7 @@ const { data } = await response.json();

位置、尺寸和启动器显隐在 自定义 标签页中设置。 - 如需在特定页面覆盖,请在加载脚本前设置 window.chattermateConfig: + 如需在特定页面覆盖,请在加载脚本前设置 window.replypierConfig:

{{ configExampleCode }}
diff --git a/frontend/src/components/agent/AgentWorkflowTab.vue b/frontend/src/components/agent/AgentWorkflowTab.vue index 34f5b9f..b374e96 100644 --- a/frontend/src/components/agent/AgentWorkflowTab.vue +++ b/frontend/src/components/agent/AgentWorkflowTab.vue @@ -1,5 +1,5 @@ -

ChatterMate UI options gallery

+

ReplyPier UI options gallery

One card per placement/behaviour. Stub mode fakes the widget (no backend needed — good for checking the loader UI alone). Real mode loads your @@ -43,7 +43,7 @@

8. Hidden launcher + own button

-

No built-in launcher. Open via the page’s buttons, the trigger selector, data-chattermate-open, or the JS API.

+

No built-in launcher. Open via the page’s buttons, the trigger selector, data-replypier-open, or the JS API.

9. Custom z-index

@@ -114,14 +114,14 @@