diff --git a/changai/changai/api/v2/ai_translate.py b/changai/changai/api/v2/ai_translate.py index 6ae020a..e1d2ca3 100644 --- a/changai/changai/api/v2/ai_translate.py +++ b/changai/changai/api/v2/ai_translate.py @@ -1,4 +1,5 @@ import os +import anthropic import frappe from frappe import _ from anthropic import Anthropic @@ -7,11 +8,12 @@ def get_meta(doc:str): return frappe.get_meta(doc) def get_doctype(doc:str,docname: str): return frappe.get_doc(doc, docname) -def get_settings(doc:str): +def get_settings(): return frappe.get_single("ChangAI Settings") @frappe.whitelist(allow_guest=False) -def translate_and_store(docname: str, doctype: str, from_field: str, to_field: str, text: str, to_language: str): """ +def translate_and_store(docname: str, doctype: str, from_field: str, to_field: str, text: str, to_language: str): + """ Translates text and stores it in a dynamically created field """ meta = get_meta(doctype) @@ -23,7 +25,7 @@ def translate_and_store(docname: str, doctype: str, from_field: str, to_field: s ) if not text: frappe.throw(_("No text to translate")) - settings = get_settings(doctype) + settings = get_settings() try: api_key = settings.claude_api_key except Exception: @@ -43,11 +45,11 @@ def translate_and_store(docname: str, doctype: str, from_field: str, to_field: s try: client = Anthropic(api_key=api_key) prompt = f""" -Translate the following text into {to_language}. -Return ONLY the translated text. -Text: -{text} -""" + Translate the following text into {to_language}. + Return ONLY the translated text. + Text: + {text} + """ response = client.messages.create( model="claude-3-haiku-20240307", max_tokens=1024, diff --git a/changai/changai/api/v2/auto_gen_api.py b/changai/changai/api/v2/auto_gen_api.py index 5d3b92c..e31caf3 100644 --- a/changai/changai/api/v2/auto_gen_api.py +++ b/changai/changai/api/v2/auto_gen_api.py @@ -210,6 +210,7 @@ def update_masterdata(): "message":"Master Data update running in RQ Job" } + def sync_master_data_smart() -> Dict[str, Any]: file_name = "master_data.yaml" payload = _read_filedoctype(file_name, RAG_FOLDER) diff --git a/changai/changai/api/v2/schema_utils.py b/changai/changai/api/v2/schema_utils.py index aae8797..d5a069d 100644 --- a/changai/changai/api/v2/schema_utils.py +++ b/changai/changai/api/v2/schema_utils.py @@ -10,7 +10,6 @@ import yaml from pathlib import Path - def _safe_join(base: Path, rel: str) -> Path: """ Prevent path traversal. Only allow reading inside base directory. @@ -116,6 +115,23 @@ def validate_sql_schema(sql: str, dialect: str = "mysql") -> dict: except sqlglot.errors.ParseError as e: return {"ok": False, "error": str(e)} +from frappe.utils import add_to_date, today, date_diff, days_diff + +@frappe.whitelist(allow_guest=False) +def checkmaster_updates(): + file_name = "master_data.yaml" + payload = _read_filedoctype(file_name, RAG_FOLDER) + if not payload: + return {"update": False, "data": False} + if not payload.get("data") or not payload.get("_meta"): + return {"data": False} + meta = payload.get("_meta") or {} + lastdate = meta["last_sync"] + docs = frappe.get_all("DocType",filters={"modified":[">",lastdate]}) + if len(docs)>0: + return {"update": False,"data":True,"days": days_diff(today(),lastdate)} + return {"update": True,"data":True} + @frappe.whitelist() def convert_yaml_schema_to_sqlglot_meta() -> dict: @@ -147,4 +163,10 @@ def convert_yaml_schema_to_sqlglot_meta() -> dict: "ok": False, "message": str(e) } - \ No newline at end of file + +from frappe import _ +@frappe.whitelist(allow_guest=False) +def test(): + res=checkmaster_updates() + if not res.get("update"): + frappe.throw(_("Please update master data for entity recognition to work. Click on Update Master Data button in Training tab in ChangAI Settings.
Check Quick Start Guide Here πŸ‘‡")) diff --git a/changai/changai/api/v2/text2sql_pipeline_v2.py b/changai/changai/api/v2/text2sql_pipeline_v2.py index 7991b58..528045a 100644 --- a/changai/changai/api/v2/text2sql_pipeline_v2.py +++ b/changai/changai/api/v2/text2sql_pipeline_v2.py @@ -19,8 +19,9 @@ from langchain_huggingface import HuggingFaceEmbeddings from google import genai from google.genai import types -from changai.changai.api.v2.schema_utils import validate_sql_schema,_load_mapping_data +from changai.changai.api.v2.schema_utils import validate_sql_schema,_load_mapping_data,checkmaster_updates from google.oauth2 import service_account + from werkzeug.wrappers import Response from changai.changai.api.v2.helpdesk_api import( create_helpdesk_ticket, @@ -157,7 +158,6 @@ def read_asset(file_name: str, base: str = "assets") -> Any: FILTER_TABLES = read_asset("filter_tables.txt", base="prompts") filter_fields = read_asset("filter_fields.txt", base="prompts") - @frappe.whitelist(allow_guest=False) def download_model(): frappe.enqueue( @@ -1167,11 +1167,6 @@ def generate_sql(state:SQLState) -> SQLState: else: prompt=fill_sql_prompt(formatted_q,state["context"]) try: - # publish_pipeline_update( - # request_id, - # "sql_generation", - # "Generating SQL query" - # ) response=call_model(prompt) if not response: return {**state, "error": "Empty response from LLM", "sql_prompt": prompt} @@ -1347,18 +1342,27 @@ def repair_sqlquery(state: SQLState) -> SQLState: def detect_specific_entities(state: SQLState) -> SQLState: if not state.get("contains_values"): return {**state, "entity_cards": [], "entity_raw": None} - + q = (state.get("formatted_q") or "").strip() if not q: return {**state, "entity_cards": [], "entity_raw": None} try: + res=checkmaster_updates() + if not res.get("data"): + frappe.throw(_("Master Data do not exist. Bcs of that result may not come accurate. For better accuracy please update by clicking on Update Master Data button in Training tab in ChangAI Settings.
Check Quick Start Guide Here πŸ‘‡:\n" + "Click here").format(res.get("days"), CHANGAI_GUIDE_LINK)) + if not res.get("update") and res.get("days")>0: + frappe.throw(_("Your master data is {0} days old. Bcs of that result may not come accurate. For better accuracy please update by clicking on Update Master Data button in Training tab in ChangAI Settings.
Check Quick Start Guide Here πŸ‘‡:\n" + "Click here").format(res.get("days"), CHANGAI_GUIDE_LINK)) out = call_entity_retriever(q) return { **state, "entity_cards": out.get("cards") or [], "entity_raw": out.get("raw"), } + except frappe.exceptions.ValidationError: + raise except Exception as e: frappe.log_error(f"Entity retriever failed: {e}", "ChangAI Entity Gate") return {**state, "entity_cards": [], "entity_raw": {"error": str(e)}} diff --git a/changai/changai/api/v2/train_data_api.py b/changai/changai/api/v2/train_data_api.py index da84d24..a9169d3 100644 --- a/changai/changai/api/v2/train_data_api.py +++ b/changai/changai/api/v2/train_data_api.py @@ -26,6 +26,7 @@ LINK_TAG = "[LINK]" CHANGAI_SETTINGS = "ChangAI Settings" VALID_OUTPUT_MESSAGE = "You must output ONLY a valid JSON array." +GEMINI_JSON_PARSE_FAIL = "Gemini JSON parse failed" SYSTEM_FIELDS = { "name", "owner", "creation", "modified", "modified_by", @@ -177,7 +178,6 @@ def _validate_table(doctype: str) -> bool: _table_cache[doctype] = bool(frappe.db.exists("DocType", doctype)) return _table_cache[doctype] - def _get_fieldnames_set(doctype: str) -> set: if doctype in _field_cache: return _field_cache[doctype] @@ -353,10 +353,21 @@ def _call_claude_batch_once(client, messages: List[dict]) -> str: frappe.log_error(str(e), "Claude Unexpected Error") raise +from typing import Optional -def _call_claude_batch_with_retry(client, module_name, module_description) -> str: +def _call_claude_batch_with_retry( + client, + input_raw: Optional[str] = None, + module_name: Optional[str] = None, + module_description: Optional[str] = None, +) -> str: raw = None - messages = _build_claude_messages(module_name, module_description) + + if input_raw and not module_name and module_description: + messages = _build_claude_correction_messages(input_raw) + else: + messages = _build_claude_messages(module_name, module_description) + for attempt in range(MAX_RETRIES): try: @@ -367,11 +378,12 @@ def _call_claude_batch_with_retry(client, module_name, module_description) -> st break - except anthropic.AuthenticationError: + except anthropic.AuthenticationError as e: + frappe.log_error(str(e), "Claude authentication failed") return "" except Exception as e: - frappe.log_error(str(e)[:100], "Claude call failed (retrying)") + frappe.log_error(str(e), "Claude call failed (retrying)") _sleep_backoff(attempt) return raw or "" @@ -438,7 +450,7 @@ def _generate_batch_claude( arr = _parse_json_array(raw, "Claude") return _extract_unique_records(arr, seen_anchors) -def _build_openai_messages(module_name, module_description, wrong_examples=None) -> List[dict]: +def _build_claude_correction_messages(input_raw) -> List[dict]: return [ { "role": "system", @@ -450,11 +462,8 @@ def _build_openai_messages(module_name, module_description, wrong_examples=None) }, { "role": "user", - "content": _training_prompt( - module_name, - module_description, - BATCH_SIZE, - wrong_examples, + "content": __correction_prompt( + input_raw ), }, ] @@ -494,9 +503,16 @@ def _call_openai_batch_once(client, messages: List[dict]) -> str: raise -def _call_openai_batch_with_retry(client, module_name, module_description, wrong_examples=None) -> str: +def _call_openai_batch_with_retry(client,input_raw:None, module_name:None, module_description:None) -> str: raw = None - messages = _build_openai_messages(module_name, module_description, wrong_examples) + messages = None + if input_raw: + messages = _build_claude_correction_messages(input_raw) + elif module_name and module_description: + messages = _build_claude_messages(module_name, module_description) + else: + frappe.log_error("No valid input to build messages", "Claude batch skipped") + return "" for attempt in range(MAX_RETRIES): try: @@ -507,13 +523,14 @@ def _call_openai_batch_with_retry(client, module_name, module_description, wrong break - except openai.AuthenticationError: + except anthropic.AuthenticationError: return "" except Exception as e: - frappe.log_error(str(e)[:300], "OpenAI call failed (retrying)") + frappe.log_error(str(e)[:2000], "Claude call failed (retrying)") _sleep_backoff(attempt) - + if not raw: + frappe.log_error("All retries exhausted", "Claude batch failed") return raw or "" @@ -563,30 +580,6 @@ def _extract_unique_training_records(arr: List[dict], seen_anchors) -> List[dict records.append({"anchor": anchor, "positives": positives}) return records - - -def _generate_batch( - client, - module_name, - seen_anchors, - module_description, - total_count, - wrong_examples=None, -) -> List[dict]: - raw = _call_openai_batch_with_retry( - client=client, - module_name=module_name, - module_description=module_description, - wrong_examples=wrong_examples, - ) - - if not raw: - frappe.log_error("All retries failed", "OpenAI generate_batch failed") - return [] - - arr = _parse_openai_json_array(raw) - return _extract_unique_training_records(arr, seen_anchors) - def _get_gemini_client(): settings = frappe.get_single(CHANGAI_SETTINGS) json_content = (settings.get("gemini_json_content") or "").strip() @@ -684,8 +677,6 @@ def _get_generation_backend(use_claude: bool, use_gemini: bool): return _get_claude_client(), _generate_batch_claude if use_gemini: return _get_gemini_client(), _generate_batch_gemini - return _get_openai_client(), _generate_batch - def _normalize_modules(modules): if isinstance(modules, str): @@ -740,13 +731,14 @@ def _generate_and_store_module_records( ) if not raw_records: continue + + # validated_records, removed = _validate_records(raw_records) + # if not validated_records: + # continue - validated_records, removed = _validate_records(raw_records) - if not validated_records: - continue try: - final_records = _assign_qids(validated_records, module_name, existing_count) + final_records = _assign_qids(raw_records, module_name, existing_count) except Exception as e: return {"ok": False, "message": f"Error assigning QIDs: {str(e)}"} @@ -845,7 +837,7 @@ def start_train(modules: str, total_count: int): timeout=14400, modules=modules, total_count=total_count, - path="Home/Training Data/Batch 5", + path="Home/Training Data/Batch 7", use_claude=False, use_gemini=True ) @@ -855,7 +847,7 @@ def start_train(modules: str, total_count: int): timeout=14400, modules=modules, total_count=val_count, - path="Home/Validation Data/Batch 5", + path="Home/Validation Data/Batch 7", use_claude=True, # <-- Claude ) return {"ok": True, "message": "Training and validation jobs queued."} @@ -893,7 +885,7 @@ def _call_gemini_with_retry(client, model_id: str, contents: List[dict], system_ try: cfg = types.GenerateContentConfig( temperature=0.9, - max_output_tokens=4096, + max_output_tokens=8192, system_instruction=system_instruction, ) @@ -949,10 +941,10 @@ def _parse_gemini_json_array(raw: str) -> List[dict]: try: arr = json.loads(cleaned) except Exception: - frappe.log_error(title="Gemini JSON parse failed", message=raw[:3000]) + frappe.log_error(title=GEMINI_JSON_PARSE_FAIL, message=raw[:3000]) return [] except Exception: - frappe.log_error(title="Gemini JSON parse failed", message=raw[:3000]) + frappe.log_error(title=GEMINI_JSON_PARSE_FAIL, message=raw[:3000]) return [] return arr if isinstance(arr, list) else [] @@ -979,6 +971,45 @@ def _extract_valid_records(arr: List[dict], seen_anchors: set) -> List[dict]: return records +def _call_openai_correction(raw:str): + try: + cleaned_res = json.loads(raw) + except Exception as e: + frappe.log_error(title="Cleaning failed", message=frappe.get_traceback()) + return [] + + try: + openai_client=_get_openai_client() + + # validate records first + for i, record in enumerate(cleaned_res): + if not isinstance(record, dict): + raise ValueError(f"Record {i} is not a dict") + if not record.get("anchor") or not record.get("positives"): + raise ValueError(f"Record {i} missing anchor or positives") + + corrected_all = [] + + # process in batches of 5 + for i in range(0, len(cleaned_res), 5): + batch = cleaned_res[i:i+5] + corrected_raw = _call_openai_batch_with_retry(openai_client, input_raw=batch,module_name=None, module_description=None) + + # if OpenAI returns JSONs string + corrected_batch = json.loads(corrected_raw) + + if not isinstance(corrected_batch, list): + raise ValueError(f"Corrected batch starting at index {i} is not a list") + + corrected_all.extend(corrected_batch) + + except Exception as e: + frappe.log_error(title="Correction failed", message=frappe.get_traceback()[:4000]) + return [] + + return corrected_all + +import json def _generate_batch_gemini( client, @@ -987,7 +1018,7 @@ def _generate_batch_gemini( module_description, total_count, wrong_examples, -) -> List[dict]: +) -> list[dict]: model_id = "gemini-2.5-flash-lite" system_instruction = _build_gemini_system_instruction() @@ -1008,55 +1039,251 @@ def _generate_batch_gemini( if not raw: return [] - arr = _parse_gemini_json_array(raw) - return _extract_valid_records(arr, seen_anchors) + # Step 1: parse Gemini output into valid array + try: + arr = raw if isinstance(raw, list) else _parse_gemini_json_array(raw) + except Exception as e: + frappe.log_error( + title=GEMINI_JSON_PARSE_FAIL, + message=f"{e}\n\nRaw output:\n{str(raw)[:5000]}" + ) + return [] + if not isinstance(arr, list): + frappe.log_error( + title="Gemini output is not a list", + message=str(arr)[:5000] + ) + return [] + + # Step 2: content correction only after valid JSON exists + try: + corrected_raw = _call_openai_correction( + json.dumps(arr, ensure_ascii=False) + ) + if corrected_raw: + corrected_arr = ( + corrected_raw + if isinstance(corrected_raw, list) + else _parse_gemini_json_array(corrected_raw) + ) + if isinstance(corrected_arr, list): + arr = corrected_arr + except Exception as e: + frappe.log_error( + title="OpenAI content correction failed", + message=str(e) + ) + # keep original arr + + return _extract_valid_records(arr, seen_anchors) def _training_prompt(module_name: str, module_description: str, batch_size: int, wrong_examples: list = None) -> str: hard_n = (batch_size * 3) // 10 std_n = batch_size - hard_n - - err_data = "" - if wrong_examples: - wrong_examples = json.loads(wrong_examples) if isinstance(wrong_examples, str) else wrong_examples - err_list = "\n".join( - [f"Fail: {e['anchor']} | Wrong: {e.get('top5',['?'])[0]}" for e in wrong_examples[:4]] - ) - err_data = f""" - FIX FAILED PATTERNS: - {err_list} - RULE: - - If failed patterns are provided above, generate targeted corrected anchors or similar anchors that retrieve the correct tables/fields. - """ - else: - err_data = """ - NOTE: - - No failed patterns are provided. - - Generate normal high-quality training examples for this module. - """ return f""" -Act: ERP Architect. Task: Generate {batch_size} training records (JSON). -Module: {module_name} ({module_description}) -{err_data} -if the Error -ANCHOR RULES: -- Queries for: SEE, FIND, LIST, CHECK, COUNT. -- Style: Fast/Urgent, Casual, Typos. No SQL/Technical phrasing. -- Mix: {std_n} Standard, {hard_n} Targeted (Hard/Tricky). 1 distractor from other module. +Act as an ERPNext ERP Architect and Text2SQL dataset designer. + +Task: +Generate {batch_size} high-quality training records as a RAW JSON ARRAY only. + +Module: +{module_name} ({module_description}) + +Goal: +Create production-grade Text2SQL training data where each record contains: +- qid +- anchor +- positives + +Anchor generation rules: +- Generate only business-style natural language queries. +- Query intent must be one of: SEE, FIND, LIST, CHECK, COUNT. +- Use natural end-user phrasing only. +- Style mix must include: + - urgent / fast phrasing + - casual phrasing + - typo / messy phrasing +- Do not use SQL terms, database terms, schema terms, or technical wording. +- Mix: + - {std_n} standard queries + - {hard_n} targeted hard/tricky queries +- Include 1 distractor inspired by another module, but keep the main answer grounded in the current module where logically valid. + +Schema rules: +- Use standard ERPNext schema. +- Use parent-child tables whenever required by the query. +- Use only tables and fields that would genuinely be required to generate correct SQL. +- Do not invent tables, fields, joins, or doctypes. +- If a query logically requires a child table, linked table, lookup table, date field, grouping field, filter field, aggregation field, sorting field, or join-relevant field, it must be included in positives. +- If a table or field is not required for correct SQL generation, do not include it. + +Critical positives rules: +- positives must be a flat, single-level list of strings only. +- Do not use objects, dictionaries, nested lists, tuples, arrays inside arrays, or any structured item inside positives. +- Every item inside positives must be a string. +- Missing even one critical table or field makes the sample invalid. +- Positives must include every table and field genuinely needed to answer the anchor and generate the SQL correctly. +- This includes, when applicable: + - root transaction tables + - child tables + - lookup/master tables + - identifier fields + - output/display fields + - filter fields + - date/time fields + - amount/value fields + - grouping fields + - aggregation fields + - sorting/ranking fields +- Prefer completeness and schema correctness over shortness. + +Field/table selection policy: +- Think like a production Text2SQL system, not like a casual annotator. +- For every anchor, determine: + 1. the main entity/table, + 2. all fields needed in SELECT, + 3. all fields needed in WHERE, + 4. all fields needed in GROUP BY, + 5. all fields needed in ORDER BY, + 6. all fields needed for aggregation, + 7. all tables/fields needed for joins. +- Then include all of them in positives. +- Do not omit child tables if the business meaning depends on line items, ledger rows, account rows, stock rows, or detail rows. +- Do not rely on only a parent table when SQL would require a child/detail table. +- Do not return weak positives with only one table unless that is truly sufficient. +CRITICAL SQL REASONING STEP (MANDATORY): + +Before constructing positives, explicitly derive the SQL requirements from the anchor: + +1. Identify SELECT fields (what needs to be shown). +2. Identify WHERE conditions (filters such as dates, status, names, etc.). +3. Identify GROUP BY fields (if query includes "per", "each", "by"). +4. Identify ORDER BY fields (if query includes "top", "highest", "lowest"). +5. Identify AGGREGATION fields: + - "total", "sum", "amount" β†’ numeric fields (e.g., grand_total, paid_amount, debit, credit, amount) + - "count" β†’ identifier field (e.g., name) + - "balance" β†’ debit/credit fields from ledger tables (NOT master tables) +6. Identify JOIN requirements: + - If query references related entity (customer, item, account, warehouse), include linking fields and related tables. +7. Identify TIME filters: + - "today", "yesterday", "last month", "this year" β†’ λ°˜λ“œμ‹œ include correct date field (posting_date, transaction_date, etc.) + +MANDATORY RULE: +If any of the above are required by the query, the corresponding fields MUST be included in positives. + +Samples missing: +- aggregation field +- grouping field +- numeric field for totals +- ledger fields for balance +- correct date field for time filtering + +are INVALID and must be corrected before output. +Validation pass (mandatory before final output): +For each generated record, perform an internal validation pass and correct the sample before returning it. +Check: +- Can correct SQL be generated from these positives alone? +- Is any required table missing? +- Is any required field missing? +- If the query uses time logic, is the correct date field included? +- If the query uses ranking/comparison, is the numeric/sort field included? +- If the query uses grouping like β€œper customer”, is the grouping field included? +- If the query needs joins, are the linked tables and join-relevant fields included? +- If the query refers to line-level business meaning, is the child table included? +If any answer is no, fix the record before output. + +CRITICAL OUTPUT CONSTRAINT: +- Output MUST be a raw JSON array (UTF-8 text). +- DO NOT wrap in ``` or ```json. +- DO NOT include any explanation, notes, or extra text. +- DO NOT include trailing commas. +- DO NOT include comments. +- The first character must be '[' and the last character must be ']'. +- If the format is violated, the response will be discarded. +- Return exactly {batch_size} records. + +Each record must follow this structure: +{{ + "qid": "_", + "anchor": "", + "positives": [ + "", + "" + ] +}} +Do not include Generic fields like creation, modified, owner, parenttype,parentfield, parent, idx, name, docstatus. +Important MUST!!! - Positive string format rules: +- Use only these string formats: + - "[TABLE] tabDoctype | desc: ..." + - "[FIELD] fieldname | [TABLE] tabDoctype | desc: ..." +- Keep descriptions short, precise, and business-relevant. +- Descriptions must support retrieval quality, but must not replace required fields/tables. +- Use only tables and fields that eixst in ERPNext" RULES: -- Use standard ERPNext schema (incl. Parent-Child). - Format: RAW JSON ARRAY ONLY. No markdown/prose. -EXAMPLE: -[{{ +Example: +[ + {{ + "qid": "PR_001", "anchor": "who authorized the extra items received in the Dammam warehouse yesterday?", "positives": [ - "[TABLE] tabPurchase Receipt | desc: Root transaction for physical goods arrival; holds authorization metadata.", - "[TABLE] tabUser | desc: Master table for system users to map 'owner' IDs to full names/emails.", - "[FIELD] owner | [TABLE] tabPurchase Receipt | desc: The User ID of the specific employee who 'Submitted' (authorized) this receipt.", - "[FIELD] set_warehouse | [TABLE] tabPurchase Receipt | desc: Header-level field to filter by location, like 'Dammam'.", - "[LINK] tabPurchase Receipt -> tabUser ON owner | desc: Join: Connects the document creator to their profile to identify the 'who'." + "[TABLE] tabPurchase Receipt | desc: Root transaction for received goods.", + "[FIELD] owner | [TABLE] tabPurchase Receipt | desc: User who created or submitted the receipt.", + "[FIELD] set_warehouse | [TABLE] tabPurchase Receipt | desc: Header warehouse used to filter location.", + "[FIELD] posting_date | [TABLE] tabPurchase Receipt | desc: Date used for filtering yesterday.", + "[TABLE] tabUser | desc: User master used to resolve owner details.", + "[FIELD] name | [TABLE] tabUser | desc: User identifier used for joining.", ] -}}] -Make sure positives' must be a SINGLE-LEVEL list of strings.DO NOT use objects, nested lists, or dictionaries inside 'positives'. + }} +] +RULES: +- Use standard ERPNext schema (incl. Parent-Child).do not use custom tables or fields not in ERPNext. +- Format: RAW JSON ARRAY ONLY. No markdown/prose. OUTPUT: RAW JSON ARRAY [{batch_size} records]. Start '[' end ']'. +Important !!! Format: RAW JSON ARRAY ONLY. No markdown/prose. +Make sure positives' must be a SINGLE-LEVEL list of strings.DO NOT use objects, nested lists, or dictionaries inside 'positives'. +""".strip() + + +def __correction_prompt(input_raw) -> str: + return f""" +Act as an ERPNext data validation expert. + +Task: +{input_raw} + +Review the training records provided above. +For each record, carefully inspect: +1. the anchor +2. the positives list + +Your goal is to improve the quality of the dataset for embedding-model training, where the model must retrieve the correct ERPNext tables and fields needed for SQL generation. + +Instructions: +- Check whether all required tables and fields needed to answer the anchor are present in positives. +- Add any missing required tables or fields that are semantically necessary to answer the query. +- Remove any wrong, irrelevant, duplicate, or unnecessary tables or fields. +- Keep only the minimum necessary positives required to answer the anchor correctly. +- Do NOT include generic system fields such as: name, docstatus, status, creation, modified, owner, idx β€” these will be injected automatically later. +- Do NOT include optional or convenience fields unless they are strictly required for the SQL logic. +- Only use standard ERPNext tables and fields that actually exist in standard ERPNext modules. +- Do not invent custom tables or fields. +- Prefer standard ERPNext field names (e.g., use territory instead of region, transaction_date instead of posting_date where appropriate). +- Ensure the final corrected records are high-quality, precise, and minimal for retrieval training. +ADDITIONAL PRODUCTION RULES (STRICT): +* Every query MUST include: entity + metric + filter (time/status/condition). +* Mandatory fields must always be included based on query intent (e.g., sales β†’ amount field, time β†’ date field). +* Remove all noise/irrelevant fields (non-business or system fields). +* Queries must include messy, real-world, and typo variations. +* Cover edge cases: zero/no data, highest/lowest, time ranges, status conditions. +* Ensure records are validation-ready (complete, correct, and usable for SQL generation). +- if the positives are not in this below format.Make it in this below fomat also: +[TABLE] | desc: +[FIELD] | [TABLE] | desc: +Output rules: +- Return the corrected records only. +- Preserve the same JSONL structure (one JSON object per line). +- Do not add explanations, notes, markdown, or extra text. +- Output raw JSON only. """.strip() \ No newline at end of file diff --git a/changai/changai/replicate_model_files/changai_qwen3/predict.py b/changai/changai/replicate_model_files/changai_qwen3/predict.py index 47affc7..4e11031 100644 --- a/changai/changai/replicate_model_files/changai_qwen3/predict.py +++ b/changai/changai/replicate_model_files/changai_qwen3/predict.py @@ -166,7 +166,7 @@ def _db_formatter_prompt(self, question: str, db_result: Any) -> str: # ---------------- Predict ---------------- - def _handle_llm_task(self, user_input: str) -> Any: +def _handle_llm_task(self, user_input: str) -> Any: if not user_input: return "Error: user_input is required when task='llm'." return self._run_main_llm(user_input=user_input) diff --git a/changai/public/dist/changai-chatbot.js b/changai/public/dist/changai-chatbot.js index 50f4378..64ae320 100644 --- a/changai/public/dist/changai-chatbot.js +++ b/changai/public/dist/changai-chatbot.js @@ -17,4 +17,4 @@ * @vue/runtime-dom v3.5.18 * (c) 2018-present Yuxi (Evan) You and Vue contributors * @license MIT -**/let us;const Ii=typeof window!="undefined"&&window.trustedTypes;if(Ii)try{us=Ii.createPolicy("vue",{createHTML:e=>e})}catch{}const Oi=us?e=>us.createHTML(e):e=>e,sl="http://www.w3.org/2000/svg",il="http://www.w3.org/1998/Math/MathML",Xe=typeof document!="undefined"?document:null,Li=Xe&&Xe.createElement("template"),rl={insert:(e,t,n)=>{t.insertBefore(e,n||null)},remove:e=>{const t=e.parentNode;t&&t.removeChild(e)},createElement:(e,t,n,s)=>{const i=t==="svg"?Xe.createElementNS(sl,e):t==="mathml"?Xe.createElementNS(il,e):n?Xe.createElement(e,{is:n}):Xe.createElement(e);return e==="select"&&s&&s.multiple!=null&&i.setAttribute("multiple",s.multiple),i},createText:e=>Xe.createTextNode(e),createComment:e=>Xe.createComment(e),setText:(e,t)=>{e.nodeValue=t},setElementText:(e,t)=>{e.textContent=t},parentNode:e=>e.parentNode,nextSibling:e=>e.nextSibling,querySelector:e=>Xe.querySelector(e),setScopeId(e,t){e.setAttribute(t,"")},insertStaticContent(e,t,n,s,i,r){const o=n?n.previousSibling:t.lastChild;if(i&&(i===r||i.nextSibling))for(;t.insertBefore(i.cloneNode(!0),n),!(i===r||!(i=i.nextSibling)););else{Li.innerHTML=Oi(s==="svg"?`${e}`:s==="mathml"?`${e}`:e);const l=Li.content;if(s==="svg"||s==="mathml"){const a=l.firstChild;for(;a.firstChild;)l.appendChild(a.firstChild);l.removeChild(a)}t.insertBefore(l,n)}return[o?o.nextSibling:t.firstChild,n?n.previousSibling:t.lastChild]}},ut="transition",Wt="animation",Jt=Symbol("_vtc"),Bi={name:String,type:String,css:{type:Boolean,default:!0},duration:[String,Number,Object],enterFromClass:String,enterActiveClass:String,enterToClass:String,appearFromClass:String,appearActiveClass:String,appearToClass:String,leaveFromClass:String,leaveActiveClass:String,leaveToClass:String},ol=Oe({},ni,Bi),ll=(e=>(e.displayName="Transition",e.props=ol,e))((e,{slots:t})=>tl(co,al(e),t)),xt=(e,t=[])=>{H(e)?e.forEach(n=>n(...t)):e&&e(...t)},Di=e=>e?H(e)?e.some(t=>t.length>1):e.length>1:!1;function al(e){const t={};for(const v in e)v in Bi||(t[v]=e[v]);if(e.css===!1)return t;const{name:n="v",type:s,duration:i,enterFromClass:r=`${n}-enter-from`,enterActiveClass:o=`${n}-enter-active`,enterToClass:l=`${n}-enter-to`,appearFromClass:a=r,appearActiveClass:p=o,appearToClass:c=l,leaveFromClass:d=`${n}-leave-from`,leaveActiveClass:h=`${n}-leave-active`,leaveToClass:y=`${n}-leave-to`}=e,I=ul(i),P=I&&I[0],q=I&&I[1],{onBeforeEnter:D,onEnter:N,onEnterCancelled:K,onLeave:w,onLeaveCancelled:T,onBeforeAppear:z=D,onAppear:G=N,onAppearCancelled:oe=K}=t,V=(v,A,j,Y)=>{v._enterCancelled=Y,yt(v,A?c:l),yt(v,A?p:o),j&&j()},Z=(v,A)=>{v._isLeaving=!1,yt(v,d),yt(v,y),yt(v,h),A&&A()},ie=v=>(A,j)=>{const Y=v?G:N,k=()=>V(A,v,j);xt(Y,[A,k]),Fi(()=>{yt(A,v?a:r),Qe(A,v?c:l),Di(Y)||Ni(A,s,P,k)})};return Oe(t,{onBeforeEnter(v){xt(D,[v]),Qe(v,r),Qe(v,o)},onBeforeAppear(v){xt(z,[v]),Qe(v,a),Qe(v,p)},onEnter:ie(!1),onAppear:ie(!0),onLeave(v,A){v._isLeaving=!0;const j=()=>Z(v,A);Qe(v,d),v._enterCancelled?(Qe(v,h),ji()):(ji(),Qe(v,h)),Fi(()=>{v._isLeaving&&(yt(v,d),Qe(v,y),Di(w)||Ni(v,s,q,j))}),xt(w,[v,j])},onEnterCancelled(v){V(v,!1,void 0,!0),xt(K,[v])},onAppearCancelled(v){V(v,!0,void 0,!0),xt(oe,[v])},onLeaveCancelled(v){Z(v),xt(T,[v])}})}function ul(e){if(e==null)return null;if(ue(e))return[cs(e.enter),cs(e.leave)];{const t=cs(e);return[t,t]}}function cs(e){return mr(e)}function Qe(e,t){t.split(/\s+/).forEach(n=>n&&e.classList.add(n)),(e[Jt]||(e[Jt]=new Set)).add(t)}function yt(e,t){t.split(/\s+/).forEach(s=>s&&e.classList.remove(s));const n=e[Jt];n&&(n.delete(t),n.size||(e[Jt]=void 0))}function Fi(e){requestAnimationFrame(()=>{requestAnimationFrame(e)})}let cl=0;function Ni(e,t,n,s){const i=e._endId=++cl,r=()=>{i===e._endId&&s()};if(n!=null)return setTimeout(r,n);const{type:o,timeout:l,propCount:a}=fl(e,t);if(!o)return s();const p=o+"end";let c=0;const d=()=>{e.removeEventListener(p,h),r()},h=y=>{y.target===e&&++c>=a&&d()};setTimeout(()=>{c(n[I]||"").split(", "),i=s(`${ut}Delay`),r=s(`${ut}Duration`),o=Vi(i,r),l=s(`${Wt}Delay`),a=s(`${Wt}Duration`),p=Vi(l,a);let c=null,d=0,h=0;t===ut?o>0&&(c=ut,d=o,h=r.length):t===Wt?p>0&&(c=Wt,d=p,h=a.length):(d=Math.max(o,p),c=d>0?o>p?ut:Wt:null,h=c?c===ut?r.length:a.length:0);const y=c===ut&&/\b(transform|all)(,|$)/.test(s(`${ut}Property`).toString());return{type:c,timeout:d,propCount:h,hasTransform:y}}function Vi(e,t){for(;e.lengthHi(n)+Hi(e[s])))}function Hi(e){return e==="auto"?0:Number(e.slice(0,-1).replace(",","."))*1e3}function ji(){return document.body.offsetHeight}function dl(e,t,n){const s=e[Jt];s&&(t=(t?[t,...s]:[...s]).join(" ")),t==null?e.removeAttribute("class"):n?e.setAttribute("class",t):e.className=t}const Ui=Symbol("_vod"),pl=Symbol("_vsh"),hl=Symbol(""),gl=/(^|;)\s*display\s*:/;function bl(e,t,n){const s=e.style,i=ce(n);let r=!1;if(n&&!i){if(t)if(ce(t))for(const o of t.split(";")){const l=o.slice(0,o.indexOf(":")).trim();n[l]==null&&Tn(s,l,"")}else for(const o in t)n[o]==null&&Tn(s,o,"");for(const o in n)o==="display"&&(r=!0),Tn(s,o,n[o])}else if(i){if(t!==n){const o=s[hl];o&&(n+=";"+o),s.cssText=n,r=gl.test(n)}}else t&&e.removeAttribute("style");Ui in e&&(e[Ui]=r?s.display:"",e[pl]&&(s.display="none"))}const qi=/\s*!important$/;function Tn(e,t,n){if(H(n))n.forEach(s=>Tn(e,t,s));else if(n==null&&(n=""),t.startsWith("--"))e.setProperty(t,n);else{const s=ml(e,t);qi.test(n)?e.setProperty(pt(s),n.replace(qi,""),"important"):e[s]=n}}const Ki=["Webkit","Moz","ms"],fs={};function ml(e,t){const n=fs[t];if(n)return n;let s=tt(t);if(s!=="filter"&&s in e)return fs[t]=s;s=_s(s);for(let i=0;ids||(wl.then(()=>ds=0),ds=Date.now());function Cl(e,t){const n=s=>{if(!s._vts)s._vts=Date.now();else if(s._vts<=n.attached)return;De(Sl(s,n.value),t,5,[s])};return n.value=e,n.attached=_l(),n}function Sl(e,t){if(H(t)){const n=e.stopImmediatePropagation;return e.stopImmediatePropagation=()=>{n.call(e),e._stopped=!0},t.map(s=>i=>!i._stopped&&s&&s(i))}else return t}const Zi=e=>e.charCodeAt(0)===111&&e.charCodeAt(1)===110&&e.charCodeAt(2)>96&&e.charCodeAt(2)<123,Tl=(e,t,n,s,i,r)=>{const o=i==="svg";t==="class"?dl(e,s,o):t==="style"?bl(e,n,s):Zt(t)?Rn(t)||xl(e,t,n,s,r):(t[0]==="."?(t=t.slice(1),!0):t[0]==="^"?(t=t.slice(1),!1):El(e,t,s,o))?(Ji(e,t,s),!e.tagName.includes("-")&&(t==="value"||t==="checked"||t==="selected")&&Wi(e,t,s,o,r,t!=="value")):e._isVueCE&&(/[A-Z]/.test(t)||!ce(s))?Ji(e,tt(t),s,r,t):(t==="true-value"?e._trueValue=s:t==="false-value"&&(e._falseValue=s),Wi(e,t,s,o))};function El(e,t,n,s){if(s)return!!(t==="innerHTML"||t==="textContent"||t in e&&Zi(t)&&Q(n));if(t==="spellcheck"||t==="draggable"||t==="translate"||t==="autocorrect"||t==="form"||t==="list"&&e.tagName==="INPUT"||t==="type"&&e.tagName==="TEXTAREA")return!1;if(t==="width"||t==="height"){const i=e.tagName;if(i==="IMG"||i==="VIDEO"||i==="CANVAS"||i==="SOURCE")return!1}return Zi(t)&&ce(n)?!1:t in e}const Xi=e=>{const t=e.props["onUpdate:modelValue"]||!1;return H(t)?n=>en(t,n):t};function Al(e){e.target.composing=!0}function Qi(e){const t=e.target;t.composing&&(t.composing=!1,t.dispatchEvent(new Event("input")))}const ps=Symbol("_assign"),Rl={created(e,{modifiers:{lazy:t,trim:n,number:s}},i){e[ps]=Xi(i);const r=s||i.props&&i.props.type==="number";Mt(e,t?"change":"input",o=>{if(o.target.composing)return;let l=e.value;n&&(l=l.trim()),r&&(l=kn(l)),e[ps](l)}),n&&Mt(e,"change",()=>{e.value=e.value.trim()}),t||(Mt(e,"compositionstart",Al),Mt(e,"compositionend",Qi),Mt(e,"change",Qi))},mounted(e,{value:t}){e.value=t==null?"":t},beforeUpdate(e,{value:t,oldValue:n,modifiers:{lazy:s,trim:i,number:r}},o){if(e[ps]=Xi(o),e.composing)return;const l=(r||e.type==="number")&&!/^0\d/.test(e.value)?kn(e.value):e.value,a=t==null?"":t;l!==a&&(document.activeElement===e&&e.type!=="range"&&(s&&t===n||i&&e.value.trim()===a)||(e.value=a))}},$l=["ctrl","shift","alt","meta"],Pl={stop:e=>e.stopPropagation(),prevent:e=>e.preventDefault(),self:e=>e.target!==e.currentTarget,ctrl:e=>!e.ctrlKey,shift:e=>!e.shiftKey,alt:e=>!e.altKey,meta:e=>!e.metaKey,left:e=>"button"in e&&e.button!==0,middle:e=>"button"in e&&e.button!==1,right:e=>"button"in e&&e.button!==2,exact:(e,t)=>$l.some(n=>e[`${n}Key`]&&!t.includes(n))},ke=(e,t)=>{const n=e._withMods||(e._withMods={}),s=t.join(".");return n[s]||(n[s]=(i,...r)=>{for(let o=0;o{const t=kl().createApp(...e),{mount:n}=t;return t.mount=s=>{const i=Ll(s);if(!i)return;const r=t._component;!Q(r)&&!r.render&&!r.template&&(r.template=i.innerHTML),i.nodeType===1&&(i.textContent="");const o=n(i,!1,Ol(i));return i instanceof Element&&(i.removeAttribute("v-cloak"),i.setAttribute("data-v-app","")),o},t};function Ol(e){if(e instanceof SVGElement)return"svg";if(typeof MathMLElement=="function"&&e instanceof MathMLElement)return"mathml"}function Ll(e){return ce(e)?document.querySelector(e):e}const Bl=["aria-pressed"],Dl={key:0,viewBox:"0 0 24 24",width:"20",height:"20","aria-hidden":"true"},Fl={key:1,viewBox:"0 0 24 24",width:"18",height:"18","aria-hidden":"true",fill:"none"},Nl={__name:"ChatbotToggler",props:{isOpen:{type:Boolean,required:!0}},emits:["toggle"],setup(e){return(t,n)=>(M(),B("button",{class:"fixed bottom-5 right-5 z-9999 grid h-12 w-12 appearance-none place-items-center rounded-full border border-white/20 bg-gradient-to-br from-brand-500 to-brand-600 text-white shadow-[0_20px_36px_-20px_rgba(109,79,194,0.85)] transition-all duration-250 hover:-translate-y-0.5 hover:from-brand-600 hover:to-violet-700 hover:shadow-[0_22px_40px_-22px_rgba(109,79,194,1)] focus:outline-none max-[600px]:bottom-3 max-[600px]:right-3 max-[600px]:h-13 max-[600px]:w-13",style:{"border-radius":"9999px"},"aria-pressed":e.isOpen?"true":"false",onClick:n[0]||(n[0]=s=>t.$emit("toggle"))},[e.isOpen?(M(),B("svg",Fl,n[2]||(n[2]=[m("path",{d:"M6 6l12 12M18 6L6 18",stroke:"currentColor","stroke-width":"2","stroke-linecap":"round"},null,-1)]))):(M(),B("svg",Dl,n[1]||(n[1]=[m("path",{d:"M4 4h16a2 2 0 0 1 2 2v9a2 2 0 0 1-2 2H8l-4 4v-4H4a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2z",fill:"currentColor",stroke:"currentColor","stroke-width":"2","stroke-linecap":"miter","stroke-linejoin":"miter"},null,-1)])))],8,Bl))}},Vl={class:"chat-header relative flex min-h-14 items-center justify-between px-4 pb-2.5 pt-3 text-white sm:px-5"},Hl={class:"flex min-w-0 flex-1 items-center gap-2 sm:gap-2.5"},jl={xmlns:"http://www.w3.org/2000/svg",width:"35",height:"35",viewBox:"0 0 1024 1024",class:"h-8 w-8 shrink-0 rounded-full bg-white p-1.5 shadow-md motion-safe:animate-soft-float",style:{fill:"#6d4fc2"}},Ul={class:"ml-2 flex items-center gap-1.5"},ql=["title"],Kl=["title","aria-label"],zl={key:0,viewBox:"0 0 24 24",width:"14",height:"14",fill:"none",stroke:"currentColor","stroke-width":"2","aria-hidden":"true"},Wl={key:1,viewBox:"0 0 24 24",width:"14",height:"14",fill:"none",stroke:"currentColor","stroke-width":"2","aria-hidden":"true"},Jl=["title","aria-label"],Gl={key:0,xmlns:"http://www.w3.org/2000/svg",width:"16",height:"16",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor","stroke-width":"2","aria-hidden":"true"},Yl={key:1,xmlns:"http://www.w3.org/2000/svg",width:"16",height:"16",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor","stroke-width":"2","aria-hidden":"true"},Zl={key:2,xmlns:"http://www.w3.org/2000/svg",width:"16",height:"16",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor","stroke-width":"2","aria-hidden":"true"},Xl={__name:"ChatHeader",props:{windowMode:{type:String,required:!0},autoReadEnabled:{type:Boolean,required:!0},activeTtsProvider:{type:String,required:!0}},emits:["close","cycleResize","toggleAutoRead"],setup(e){const t=e,n={default:"Compact",half:"Half Screen",full:"Full Screen"},s=de(()=>n[t.windowMode]||"Compact"),i=de(()=>t.windowMode==="default"?"Half Screen":t.windowMode==="half"?"Full Screen":"Compact"),r=de(()=>t.activeTtsProvider==="polly"?"TTS: Polly":t.activeTtsProvider==="browser"?"TTS: Browser":"TTS: Off"),o=de(()=>t.activeTtsProvider==="polly"?"bg-emerald-500/45":t.activeTtsProvider==="browser"?"bg-amber-500/45":"bg-slate-500/35");return(l,a)=>(M(),B("div",Vl,[m("div",Hl,[(M(),B("svg",jl,a[3]||(a[3]=[m("path",{d:"M738.3 287.6H285.7c-59 0-106.8 47.8-106.8 106.8v303.1c0 59 47.8 106.8 106.8 106.8h81.5v111.1c0 .7.8 1.1 1.4.7l166.9-110.6 41.8-.8h117.4l43.6-.4c59 0 106.8-47.8 106.8-106.8V394.5c0-59-47.8-106.9-106.8-106.9zM351.7 448.2c0-29.5 23.9-53.5 53.5-53.5s53.5 23.9 53.5 53.5-23.9 53.5-53.5 53.5-53.5-23.9-53.5-53.5zm157.9 267.1c-67.8 0-123.8-47.5-132.3-109h264.6c-8.6 61.5-64.5 109-132.3 109zm110-213.7c-29.5 0-53.5-23.9-53.5-53.5s23.9-53.5 53.5-53.5 53.5 23.9 53.5 53.5-23.9 53.5-53.5 53.5zM867.2 644.5V453.1h26.5c19.4 0 35.1 15.7 35.1 35.1v121.1c0 19.4-15.7 35.1-35.1 35.1h-26.5zM95.2 609.4V488.2c0-19.4 15.7-35.1 35.1-35.1h26.5v191.3h-26.5c-19.4 0-35.1-15.7-35.1-35.1zM561.5 149.6c0 23.4-15.6 43.3-36.9 49.7v44.9h-30v-44.9c-21.4-6.5-36.9-26.3-36.9-49.7 0-28.6 23.3-51.9 51.9-51.9s51.9 23.3 51.9 51.9z"},null,-1)]))),a[4]||(a[4]=m("h2",{class:"truncate text-xs font-semibold tracking-[0.01em] sm:text-base text-white/95"},"ChangAI from ERPGulf",-1))]),m("div",Ul,[m("span",{class:re(["hidden rounded-full border border-white/25 px-2 py-1 text-[10px] font-semibold uppercase tracking-wide text-white/95 shadow-sm backdrop-blur-sm sm:inline",o.value]),title:`TTS provider: ${r.value}`},we(r.value),11,ql),m("button",{class:re(["h-8 min-w-8 appearance-none items-center justify-center rounded-md border border-white/20 px-2 text-xs font-semibold text-white/90 transition-all duration-200 focus:outline-none sm:flex",e.autoReadEnabled?"bg-white/24 shadow-sm":"hover:bg-white/15"]),style:{"border-radius":"0.375rem"},title:e.autoReadEnabled?"Auto speech on":"Auto speech off","aria-label":e.autoReadEnabled?"Turn off auto speech":"Turn on auto speech",onClick:a[0]||(a[0]=p=>l.$emit("toggleAutoRead"))},[e.autoReadEnabled?(M(),B("svg",zl,a[5]||(a[5]=[m("path",{d:"M11 5L6 9H3v6h3l5 4V5z"},null,-1),m("path",{d:"M15 9a4 4 0 0 1 0 6"},null,-1),m("path",{d:"M18 7a7 7 0 0 1 0 10"},null,-1)]))):(M(),B("svg",Wl,a[6]||(a[6]=[m("path",{d:"M11 5L6 9H3v6h3l5 4V5z"},null,-1),m("path",{d:"M22 9l-6 6"},null,-1),m("path",{d:"M16 9l6 6"},null,-1)])))],10,Kl),m("button",{class:re(["flex h-8 min-w-8 appearance-none items-center justify-center rounded-md border border-white/20 px-2 text-xs font-semibold text-white/90 transition-all duration-200 focus:outline-none","bg-white/20 shadow-sm hover:bg-white/25"]),style:{"border-radius":"0.375rem"},title:`Resize mode: ${s.value} (click to ${i.value})`,"aria-label":`Resize mode ${s.value}. Click to switch to ${i.value}`,onClick:a[1]||(a[1]=p=>l.$emit("cycleResize"))},[e.windowMode==="default"?(M(),B("svg",Gl,a[7]||(a[7]=[m("rect",{x:"7",y:"8",width:"10",height:"8",rx:"2"},null,-1)]))):e.windowMode==="half"?(M(),B("svg",Yl,a[8]||(a[8]=[m("rect",{x:"4",y:"5",width:"16",height:"14",rx:"2"},null,-1),m("path",{d:"M12 5v14"},null,-1)]))):(M(),B("svg",Zl,a[9]||(a[9]=[m("rect",{x:"4",y:"5",width:"16",height:"14",rx:"2"},null,-1),m("path",{d:"M8 8H6v2M16 8h2v2M8 16H6v-2M16 16h2v-2"},null,-1)])))],8,Jl),m("button",{class:"grid h-8 w-8 shrink-0 appearance-none place-items-center rounded-full border border-white/20 text-white transition-all duration-200 hover:scale-105 hover:bg-white/20 focus:outline-none focus-visible:ring-2 focus-visible:ring-white/70",style:{"border-radius":"9999px"},"aria-label":"Close chatbot",onClick:a[2]||(a[2]=p=>l.$emit("close"))},a[10]||(a[10]=[m("svg",{xmlns:"http://www.w3.org/2000/svg",height:"24",width:"24",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor","stroke-width":"2"},[m("path",{d:"M6 9l6 6 6-6"})],-1)]))])]))}},Ql={class:"flex gap-1.5 border-b border-slate-200/80 px-2.5 pb-2.5 pt-1"},ea=["onClick"],ta={class:"inline-flex items-center gap-1.5"},na={__name:"TabBar",props:{modelValue:{type:String,required:!0},debugEnabled:{type:Boolean,default:!1}},emits:["update:modelValue"],setup(e){const t=e,n=de(()=>{const s=[{id:"chat",label:"Chats"},{id:"debug",label:"Debug"},{id:"support",label:"Support"},{id:"settings",label:"Settings"}];return t.debugEnabled?s:s.filter(i=>i.id!=="debug")});return(s,i)=>(M(),B("div",Ql,[(M(!0),B(he,null,vn(n.value,r=>(M(),B("button",{key:r.id,class:re(["group min-w-0 flex-1 h-9 appearance-none rounded-lg border border-transparent bg-transparent px-2 text-xs font-semibold transition-all duration-200 focus:outline-none",e.modelValue===r.id?"border-white/30 bg-linear-to-r from-violet-300/36 via-indigo-300/30 to-sky-300/28 text-white shadow-[0_4px_10px_rgba(20,24,40,0.22)]":"text-white/80 hover:border-white/25 hover:bg-white/12 hover:text-white"]),onClick:o=>s.$emit("update:modelValue",r.id)},[m("span",ta,[m("span",{class:re(["h-1.5 w-1.5 rounded-full transition-colors duration-200",e.modelValue===r.id?"bg-white":"bg-white/40 group-hover:bg-white/70"])},null,2),rs(" "+we(r.label),1)])],10,ea))),128))]))}},sa=(e,t)=>{const n=e.__vccOpts||e;for(const[s,i]of t)n[s]=i;return n},ia={},ra={xmlns:"http://www.w3.org/2000/svg",width:"50",height:"50",viewBox:"0 0 1024 1024",class:"h-7.5 w-7.5 shrink-0 self-end rounded-full bg-gradient-to-br from-brand-500 to-brand-600 p-1.5 fill-white shadow-[0_10px_18px_-12px_rgba(109,79,194,0.85)]"};function oa(e,t){return M(),B("svg",ra,t[0]||(t[0]=[m("path",{d:"M738.3 287.6H285.7c-59 0-106.8 47.8-106.8 106.8v303.1c0 59 47.8 106.8 106.8 106.8h81.5v111.1c0 .7.8 1.1 1.4.7l166.9-110.6 41.8-.8h117.4l43.6-.4c59 0 106.8-47.8 106.8-106.8V394.5c0-59-47.8-106.9-106.8-106.9zM351.7 448.2c0-29.5 23.9-53.5 53.5-53.5s53.5 23.9 53.5 53.5-23.9 53.5-53.5 53.5-53.5-23.9-53.5-53.5zm157.9 267.1c-67.8 0-123.8-47.5-132.3-109h264.6c-8.6 61.5-64.5 109-132.3 109zm110-213.7c-29.5 0-53.5-23.9-53.5-53.5s23.9-53.5 53.5-53.5 53.5 23.9 53.5 53.5-23.9 53.5-53.5 53.5zM867.2 644.5V453.1h26.5c19.4 0 35.1 15.7 35.1 35.1v121.1c0 19.4-15.7 35.1-35.1 35.1h-26.5zM95.2 609.4V488.2c0-19.4 15.7-35.1 35.1-35.1h26.5v191.3h-26.5c-19.4 0-35.1-15.7-35.1-35.1zM561.5 149.6c0 23.4-15.6 43.3-36.9 49.7v44.9h-30v-44.9c-21.4-6.5-36.9-26.3-36.9-49.7 0-28.6 23.3-51.9 51.9-51.9s51.9 23.3 51.9 51.9z"},null,-1)]))}const tr=sa(ia,[["render",oa]]),En={PIPELINE:"changai.changai.api.v2.text2sql_pipeline_v2.run_text2sql_pipeline",SUPPORT:"changai.changai.api.v2.text2sql_pipeline_v2.support_bot",SETTINGS:"changai.changai.api.v2.text2sql_pipeline_v2.get_frontend_settings",TTS:"changai.changai.api.v2.text2sql_pipeline_v2.synthesize_tts"};function hs(e,t={},n="actual"){return n==="test"?Promise.resolve({Bot:`[TEST MODE] ${JSON.stringify(t)}`}):!window.frappe||!window.frappe.call?Promise.reject(new Error("Frappe API is unavailable in actual mode.")):new Promise((s,i)=>{window.frappe.call({method:e,args:t,callback(r){s(r.message)},error(r){i(r)}})})}function la(e,t,n="actual",s=null){if(n==="test")return{promise:Promise.resolve({Bot:`[TEST MODE] ${JSON.stringify({user_question:e,chat_id:t,request_id:s})}`}),cancel:()=>!1};if(!window.frappe||!window.frappe.call)return{promise:Promise.reject(new Error("Frappe API is unavailable in actual mode.")),cancel:()=>!1};let i=null,r=!1;return{promise:new Promise((a,p)=>{i=window.frappe.call({method:En.PIPELINE,args:{user_question:e,chat_id:t,request_id:s},callback(c){r=!0,a(c.message)},error(c){r=!0,p(c)}})}),cancel:()=>r||!i||typeof i.abort!="function"?!1:(i.abort(),r=!0,!0)}}function aa(e,t="actual"){return hs(En.SUPPORT,{message:e},t)}function ua(e="actual"){return hs(En.SETTINGS,{},e)}function ca(e,t="Joanna",n="actual"){return hs(En.TTS,{text:e,voice_id:t},n)}const fa={key:1,class:"flex min-w-0 max-w-[calc(100%-2.5rem)] flex-1 flex-col max-[600px]:max-w-[calc(100%-2.25rem)]"},da={key:0,class:"flex w-fit flex-col items-start gap-1"},pa=["aria-label"],ha={class:"inline-flex items-center gap-1.5"},ga={class:"text-[8px] font-semibold tracking-[0.12em] uppercase text-[#3a67c9]"},ba={key:1,class:"flex w-fit max-w-full flex-col items-start gap-2"},ma={class:"chat-card relative w-fit max-w-full whitespace-pre-line rounded-[10px_10px_10px_3px] px-4 py-3 text-xs leading-relaxed wrap-anywhere text-slate-900"},va=["innerHTML"],xa={key:0,class:"pointer-events-none absolute inset-x-0 bottom-0 h-14 rounded-b-[10px] bg-linear-to-t from-white via-white/92 to-white/0","aria-hidden":"true"},ya={key:0,class:"flex flex-wrap items-center gap-2"},wa=["title","aria-label"],_a=["title","aria-label"],Ca={viewBox:"0 0 24 24",width:"16",height:"16",fill:"none",stroke:"currentColor","stroke-width":"2","aria-hidden":"true"},Sa={key:2,class:"w-fit max-w-[85%] whitespace-pre-line rounded-[13px_13px_3px_13px] bg-linear-to-br from-brand-500 to-brand-600 px-4 py-3 text-[11px] leading-relaxed wrap-anywhere text-white shadow-[0_14px_30px_-18px_rgba(109,79,194,0.85)] max-[600px]:max-w-[88%]"},nr={__name:"ChatMessage",props:{message:{type:Object,required:!0},autoReadEnabled:{type:Boolean,default:!1},ttsConfig:{type:Object,default:()=>({enableVoiceChat:!1,pollyAvailable:!1,usePolly:!0,voiceId:"Joanna"})}},setup(e){const t=e,n=U(!1),s=U(null),i=U(!1),r=U(!1),o=de(()=>typeof window!="undefined"&&"speechSynthesis"in window&&"SpeechSynthesisUtterance"in window);function l(w){typeof window!="undefined"&&window.dispatchEvent(new CustomEvent("changai-tts-provider",{detail:{provider:w}}))}function a(w){return typeof w!="string"?"":w.includes("<")?(new DOMParser().parseFromString(w,"text/html").body.textContent||"").replace(/\s+/g," ").trim():w.trim()}function p(){o.value&&window.speechSynthesis.cancel(),s.value&&(s.value.pause(),s.value.src="",s.value=null),n.value=!1}function c(){var w,T,z;if(r.value=!r.value,r.value)p();else{const G=P.value;if(!t.autoReadEnabled||!((w=t.ttsConfig)!=null&&w.enableVoiceChat)||!G||I())return;if((T=t.ttsConfig)!=null&&T.pollyAvailable&&((z=t.ttsConfig)!=null&&z.usePolly)){h(G).catch(oe=>{d(G)});return}d(G)}}function d(w){if(!o.value||!w)return;window.dispatchEvent(new CustomEvent("changai-tts-stop")),window.speechSynthesis.cancel();const T=new SpeechSynthesisUtterance(w);T.rate=1,T.pitch=1,T.onend=()=>{n.value=!1},T.onerror=()=>{n.value=!1},n.value=!0,l("browser"),window.speechSynthesis.speak(T)}async function h(w){var V;const T=await ca(w,((V=t.ttsConfig)==null?void 0:V.voiceId)||"Joanna");if(!(T!=null&&T.ok)||!(T!=null&&T.audio_base64))throw new Error((T==null?void 0:T.error)||"Polly synthesis failed");window.dispatchEvent(new CustomEvent("changai-tts-stop")),p();const z=(T==null?void 0:T.mime_type)||"audio/mpeg",G=new Audio(`data:${z};base64,${T.audio_base64}`);s.value=G,n.value=!0;let oe=!1;G.onplay=()=>{oe=!0,l("polly")},G.onended=()=>{s.value===G&&(s.value=null),n.value=!1},G.onerror=()=>{s.value===G&&(s.value=null),n.value=!1},await G.play(),oe||l("polly")}function y(){n.value=!1}function I(){var w;return!!((w=t.message)!=null&&w.isStatus)}const P=de(()=>{var w;return a(((w=t.message)==null?void 0:w.text)||"")}),q=de(()=>{var w;return((w=t.message)==null?void 0:w.role)!=="user"&&I()}),D=de(()=>{var w;return(w=t.message)!=null&&w.isStatus?t.message.statusType==="support"?"Sending to support":P.value||"Thinking":""}),N=de(()=>{var z;if(((z=t.message)==null?void 0:z.role)==="user"||q.value)return!1;const w=P.value,T=w.split(/\n+/).filter(Boolean).length;return w.length>520||T>8}),K=de(()=>{var w,T;return N.value&&((w=t.message)==null?void 0:w.role)!=="user"&&!q.value&&((T=t.ttsConfig)==null?void 0:T.enableVoiceChat)});return Pt(()=>t.message.text,async(w,T)=>{var oe,V,Z;if(!t.autoReadEnabled||t.message.role==="user"||r.value)return;if(!((oe=t.ttsConfig)!=null&&oe.enableVoiceChat)){l("off");return}const z=a(w);if(!z||I())return;const G=a(T||"");if(z!==G){if((V=t.ttsConfig)!=null&&V.pollyAvailable&&((Z=t.ttsConfig)!=null&&Z.usePolly))try{await h(z);return}catch{}d(z)}}),Pt(()=>t.message.text,()=>{i.value=!1,r.value=!1}),bn(()=>{typeof window!="undefined"&&window.addEventListener("changai-tts-stop",y)}),mn(()=>{typeof window!="undefined"&&window.removeEventListener("changai-tts-stop",y),n.value&&p()}),(w,T)=>(M(),B("div",{class:re(["motion-safe:animate-fade-rise flex w-full gap-1.5",e.message.role==="user"?"flex-col items-end":"items-start"])},[e.message.role!=="user"?(M(),Ze(tr,{key:0})):ye("",!0),e.message.role!=="user"?(M(),B("div",fa,[q.value?(M(),B("div",da,[m("div",{class:"chat-card inline-flex w-fit rounded-[10px_10px_10px_3px] px-3 py-2",role:"status","aria-live":"polite","aria-label":D.value},[m("div",ha,[T[1]||(T[1]=m("span",{class:"relative inline-flex h-4 w-4 shrink-0 items-center justify-center"},[m("span",{class:"absolute inset-0 rounded-full border border-transparent border-t-[#4b89ff] border-r-[#4b89ff]/70 animate-gemini-arc"}),m("svg",{viewBox:"0 0 24 24",class:"relative h-3 w-3 text-[#4b89ff] animate-gemini-spark","aria-hidden":"true"},[m("path",{fill:"currentColor",d:"M12 2.8c.52 3.22 1.6 5.66 3.22 7.28 1.62 1.62 4.06 2.7 7.28 3.22-3.22.52-5.66 1.6-7.28 3.22-1.62 1.62-2.7 4.06-3.22 7.28-.52-3.22-1.6-5.66-3.22-7.28-1.62-1.62-4.06-2.7-7.28-3.22 3.22-.52 5.66-1.6 7.28-3.22 1.62-1.62 2.7-4.06 3.22-7.28Z"})])],-1)),m("span",ga,we(D.value),1)])],8,pa)])):(M(),B("div",ba,[m("div",ma,[m("div",{class:re(["overflow-x-auto",N.value&&!i.value?"max-h-48 overflow-y-hidden":""]),innerHTML:e.message.text},null,10,va),N.value&&!i.value?(M(),B("div",xa)):ye("",!0)]),N.value||K.value?(M(),B("div",ya,[N.value?(M(),B("button",{key:0,type:"button",class:"inline-flex items-center rounded-full border border-slate-200 bg-white px-2.5 py-1 text-[10px] font-semibold uppercase tracking-[0.08em] text-slate-600 transition-colors duration-200 hover:border-brand-200 hover:text-brand-600",title:i.value?"Collapse response":"Expand response","aria-label":i.value?"Collapse response":"Expand response",onClick:T[0]||(T[0]=z=>i.value=!i.value)},we(i.value?"Collapse":"Expand"),9,wa)):ye("",!0),K.value?(M(),B("button",{key:1,type:"button",class:re(["inline-flex h-8 w-8 items-center justify-center rounded-full border transition-colors duration-200",r.value?"border-red-200 bg-red-50 text-red-600 hover:border-red-300 hover:bg-red-100":"border-green-200 bg-green-50 text-green-600 hover:border-green-300 hover:bg-green-100"]),title:r.value?"TTS muted":"TTS enabled","aria-label":r.value?"TTS muted":"TTS enabled",onClick:c},[(M(),B("svg",Ca,[T[6]||(T[6]=m("path",{d:"M11 5L6 9H3v6h3l5 4V5Z"},null,-1)),r.value?(M(),B(he,{key:0},[T[2]||(T[2]=m("path",{d:"M15 9l4 6"},null,-1)),T[3]||(T[3]=m("path",{d:"M19 9l-4 6"},null,-1))],64)):(M(),B(he,{key:1},[T[4]||(T[4]=m("path",{d:"M15 10a3 3 0 0 1 0 4"},null,-1)),T[5]||(T[5]=m("path",{d:"M17.5 7.5a6 6 0 0 1 0 9"},null,-1))],64))]))],10,_a)):ye("",!0)])):ye("",!0)]))])):(M(),B("p",Sa,we(e.message.text),1))],2))}},Ta={class:"flex flex-col gap-4 sm:gap-5"},Ea={class:"motion-safe:animate-fade-rise flex w-full items-start gap-1.5"},Aa={__name:"ChatTab",props:{messages:{type:Array,required:!0},autoReadEnabled:{type:Boolean,default:!1},ttsConfig:{type:Object,required:!0}},setup(e){return(t,n)=>(M(),B("div",Ta,[m("div",Ea,[fe(tr),n[0]||(n[0]=m("p",{class:"w-fit max-w-[calc(100%-2.5rem)] whitespace-pre-line rounded-[10px_10px_10px_3px] bg-brand-50 px-4 py-3 text-xs leading-relaxed wrap-anywhere text-slate-900 max-[600px]:max-w-[calc(100%-2.25rem)]"},[rs(" Hello there πŸ‘‹ I am ChangAI from ERPGulf.com , your ERP assistant."),m("br"),m("a",{target:"_blank",href:"https://app.erpgulf.com/en/articles/chang-ai-quick-start-guide",rel:"noopener noreferrer",style:{color:"#1e90ff"}},"ChangAI Quick Start Guide - Click here.")],-1))]),(M(!0),B(he,null,vn(e.messages,(s,i)=>(M(),Ze(nr,{key:i,message:s,autoReadEnabled:e.autoReadEnabled,ttsConfig:e.ttsConfig},null,8,["message","autoReadEnabled","ttsConfig"]))),128))]))}};function sr(e){try{return JSON.stringify(e,null,2)}catch{return String(e)}}function ir(e){var t,n;return(e==null?void 0:e.message)||((t=e==null?void 0:e.responseJSON)==null?void 0:t.exception)||((n=e==null?void 0:e.responseJSON)==null?void 0:n.message)||(e==null?void 0:e.responseText)||String(e)}function Ra(e){return typeof e=="string"?e:e&&typeof e=="object"?e.error?`⚠️ ${e.error}`:e.answer||e.text||"":""}const $a={key:0,class:"rounded-lg bg-brand-50 px-4 py-3 text-xs text-black"},Pa={class:"whitespace-pre-wrap wrap-anywhere text-[11px] leading-relaxed text-black"},Ma={key:1,class:"mb-3 min-w-0 overflow-x-auto rounded-lg bg-brand-50 p-2 text-[11px]"},ka={class:"whitespace-pre-wrap wrap-anywhere text-[11px] leading-relaxed text-black"},Ia={__name:"DebugTab",props:{logs:{type:Array,required:!0},currentDebug:{type:Object,default:null}},setup(e){const t=new Set(["gemini_json_content","private_key","private_key_id","client_secret","client_id","aws_access_key","aws_secret_key","api_key","token","access_token","refresh_token","password","secret","authorization","embed_version_id","llm_version_id","entity_retriever","retriever","deploy_url","support_api_url","get_ticket_details_url"]);function n(i,r=0){if(r>10||i===null||i===void 0||typeof i=="string"||typeof i=="number"||typeof i=="boolean")return i;if(Array.isArray(i))return i.map(o=>n(o,r+1));if(typeof i=="object"){const o={};for(const[l,a]of Object.entries(i))t.has(l.toLowerCase())||(o[l]=n(a,r+1));return o}return i}function s(i){return sr(n(i))}return(i,r)=>(M(),B("div",null,[e.logs.length===0?(M(),B("p",$a,"No debug data yet.")):ye("",!0),(M(!0),B(he,null,vn(e.logs,(o,l)=>(M(),B("div",{key:l,class:"mb-3 min-w-0 overflow-x-auto rounded-lg bg-gray-100 p-2 text-[11px]"},[m("pre",Pa,we(s(o)),1)]))),128)),e.currentDebug?(M(),B("div",Ma,[m("pre",ka,we(s(e.currentDebug)),1)])):ye("",!0)]))}},Oa={class:"flex flex-col gap-4 sm:gap-5"},La={key:0,class:"chat-card motion-safe:animate-fade-rise rounded-lg px-4 py-3 text-xs text-slate-900"},Ba={__name:"SupportTab",props:{messages:{type:Array,required:!0},autoReadEnabled:{type:Boolean,default:!1},ttsConfig:{type:Object,required:!0}},setup(e){return(t,n)=>(M(),B("div",Oa,[e.messages.length===0?(M(),B("p",La,"Send a message to Support.")):ye("",!0),(M(!0),B(he,null,vn(e.messages,(s,i)=>(M(),Ze(nr,{key:i,message:s,autoReadEnabled:e.autoReadEnabled,ttsConfig:e.ttsConfig},null,8,["message","autoReadEnabled","ttsConfig"]))),128))]))}},Da={class:"flex flex-col gap-4"},Fa={class:"chat-card motion-safe:animate-fade-rise rounded-xl p-4"},Na={class:"flex items-start justify-between gap-4"},Va=["aria-pressed","title"],Ha={class:"chat-card motion-safe:animate-fade-rise rounded-xl p-4"},ja={class:"flex items-start justify-between gap-4"},Ua={class:"mt-2 text-[11px] text-slate-500"},qa={key:0,class:"mt-1 text-[11px] text-slate-500"},Ka={key:1,class:"mt-1 text-[11px] text-slate-500"},za=["aria-pressed","disabled"],Wa={key:0,class:"mt-3 rounded-md bg-amber-50 px-2.5 py-2 text-xs text-amber-700"},Ja={key:1,class:"mt-3 rounded-md bg-amber-50 px-2.5 py-2 text-xs text-amber-700"},Ga={class:"chat-card motion-safe:animate-fade-rise rounded-xl p-4"},Ya={class:"flex items-start justify-between gap-4"},Za=["aria-pressed","title"],Xa={__name:"SettingsTab",props:{autoReadEnabled:{type:Boolean,required:!0},ttsConfig:{type:Object,required:!0},settings:{type:Object,default:null},debugEnabled:{type:Boolean,default:!1}},emits:["toggleAutoRead","togglePollyPreference","toggleDebug"],setup(e){const t=e,n=de(()=>{var s,i;return(s=t.ttsConfig)!=null&&s.enableVoiceChat?(i=t.ttsConfig)!=null&&i.pollyAvailable?"Available":"Unavailable":"Voice disabled on server"});return(s,i)=>{var r,o,l,a,p,c,d,h,y,I,P,q,D,N,K;return M(),B("div",Da,[i[8]||(i[8]=m("div",{class:"chat-card motion-safe:animate-fade-rise rounded-xl p-4 text-slate-900"},[m("h3",{class:"text-sm font-semibold tracking-[0.01em]"},"Speech Settings"),m("p",{class:"mt-1 text-xs leading-relaxed text-slate-600"},"These controls apply only inside this chatbot box for the current browser session.")],-1)),m("div",Fa,[m("div",Na,[i[3]||(i[3]=m("div",null,[m("p",{class:"text-sm font-semibold text-slate-900"},"Auto Read Replies"),m("p",{class:"mt-1 text-xs text-slate-600"},"Automatically read bot replies aloud.")],-1)),m("button",{class:re(["group relative h-7 w-12 shrink-0 rounded-full border border-slate-200 transition-all duration-200",e.autoReadEnabled?"bg-emerald-500/95":"bg-slate-300"]),"aria-pressed":e.autoReadEnabled?"true":"false",title:e.autoReadEnabled?"Disable auto read":"Enable auto read",onClick:i[0]||(i[0]=w=>s.$emit("toggleAutoRead"))},[m("span",{class:re(["absolute top-0.5 h-5.5 w-5.5 rounded-full bg-white shadow-sm transition-all duration-200",e.autoReadEnabled?"left-[1.45rem]":"left-0.5"])},null,2)],10,Va)]),m("p",{class:re(["mt-3 text-[11px] font-medium",e.autoReadEnabled?"text-emerald-700":"text-slate-500"])},we(e.autoReadEnabled?"Auto read is active.":"Auto read is currently off."),3)]),m("div",Ha,[m("div",ja,[m("div",null,[i[4]||(i[4]=m("p",{class:"text-sm font-semibold text-slate-900"},"Use Amazon Polly",-1)),i[5]||(i[5]=m("p",{class:"mt-1 text-xs text-slate-600"},"Use Polly when available; otherwise browser speech is used automatically.",-1)),m("p",Ua,"Availability: "+we(n.value),1),(r=e.settings)!=null&&r.aws_region?(M(),B("p",qa,"Region: "+we(e.settings.aws_region),1)):ye("",!0),(o=e.ttsConfig)!=null&&o.voiceId?(M(),B("p",Ka,"Voice: "+we(e.ttsConfig.voiceId),1)):ye("",!0)]),m("button",{class:re(["relative h-7 w-12 shrink-0 rounded-full border border-slate-200 transition-all duration-200 disabled:cursor-not-allowed disabled:opacity-55",(l=e.ttsConfig)!=null&&l.usePolly&&((a=e.ttsConfig)!=null&&a.enableVoiceChat)&&((p=e.ttsConfig)!=null&&p.pollyAvailable)?"bg-emerald-500/95":"bg-slate-300"]),"aria-pressed":(c=e.ttsConfig)!=null&&c.usePolly&&((d=e.ttsConfig)!=null&&d.enableVoiceChat)&&((h=e.ttsConfig)!=null&&h.pollyAvailable)?"true":"false",disabled:!((y=e.ttsConfig)!=null&&y.pollyAvailable)||!((I=e.ttsConfig)!=null&&I.enableVoiceChat),onClick:i[1]||(i[1]=w=>s.$emit("togglePollyPreference"))},[m("span",{class:re(["absolute top-0.5 h-5.5 w-5.5 rounded-full bg-white shadow-sm transition-all duration-200",(P=e.ttsConfig)!=null&&P.usePolly&&((q=e.ttsConfig)!=null&&q.enableVoiceChat)&&((D=e.ttsConfig)!=null&&D.pollyAvailable)?"left-[1.45rem]":"left-0.5"])},null,2)],10,za)]),(N=e.ttsConfig)!=null&&N.enableVoiceChat?(K=e.ttsConfig)!=null&&K.pollyAvailable?ye("",!0):(M(),B("p",Ja,"Polly is not available for this site. Browser speech will be used.")):(M(),B("p",Wa,"Voice chat is disabled in ChangAI Settings."))]),m("div",Ga,[m("div",Ya,[m("div",null,[i[6]||(i[6]=m("p",{class:"text-sm font-semibold text-slate-900"},"Enable Debug Tab",-1)),i[7]||(i[7]=m("p",{class:"mt-1 text-xs text-slate-600"}," Show or hide the Debug tab inside this chatbot. ",-1)),m("p",{class:re(["mt-2 text-[11px] font-medium",e.debugEnabled?"text-emerald-700":"text-slate-500"])},we(e.debugEnabled?"Debug tab is active.":"Debug tab is currently off."),3)]),m("button",{type:"button",class:re(["relative h-7 w-12 shrink-0 rounded-full border border-slate-200 transition-all duration-200",e.debugEnabled?"bg-emerald-500/95":"bg-slate-300"]),"aria-pressed":e.debugEnabled?"true":"false",title:e.debugEnabled?"Disable debug tab":"Enable debug tab",onClick:i[2]||(i[2]=w=>s.$emit("toggleDebug"))},[m("span",{class:re(["absolute top-0.5 h-5.5 w-5.5 rounded-full bg-white shadow-sm transition-all duration-200",e.debugEnabled?"left-[1.45rem]":"left-0.5"])},null,2)],10,Za)])])])}}},Qa={key:0,class:"pointer-events-none absolute -top-14 left-0 right-0 z-20 flex justify-center px-2",role:"status","aria-live":"polite"},eu={__name:"StatusToast",props:{visible:{type:Boolean,required:!0},message:{type:String,default:""},type:{type:String,default:"info"},dismissible:{type:Boolean,default:!0}},emits:["close"],setup(e){const t=e,n=de(()=>t.type==="error"?"bg-red-50 text-red-700 ring-red-200":(t.type==="listening","bg-blue-50 text-blue-700 ring-blue-200")),s=de(()=>t.type==="error"?"bg-red-500":t.type==="listening"?"bg-blue-500 animate-pulse":"bg-blue-500");return(i,r)=>(M(),Ze(ll,{"enter-active-class":"transition duration-200 ease-out","enter-from-class":"translate-y-1 opacity-0","enter-to-class":"translate-y-0 opacity-100","leave-active-class":"transition duration-150 ease-in","leave-from-class":"translate-y-0 opacity-100","leave-to-class":"translate-y-1 opacity-0"},{default:ei(()=>[e.visible?(M(),B("div",Qa,[m("div",{class:re(["pointer-events-auto flex max-w-[92%] items-start gap-2 rounded-lg px-3 py-2 text-xs shadow-lg ring-1",n.value])},[m("span",{class:re(["mt-0.5 h-2 w-2 shrink-0 rounded-full",s.value])},null,2),m("span",null,we(e.message),1),e.dismissible?(M(),B("button",{key:0,type:"button",class:"ml-1 appearance-none border-0 text-current/80 transition hover:text-current focus:outline-none","aria-label":"Dismiss notification",onClick:r[0]||(r[0]=o=>i.$emit("close"))}," Γ— ")):ye("",!0)],2)])):ye("",!0)]),_:1}))}},tu={class:"relative w-full"},nu=["placeholder","disabled"],su=["title","aria-label","disabled"],iu={key:0,viewBox:"0 0 24 24",width:"16",height:"16",fill:"currentColor","aria-hidden":"true"},ru={key:1,viewBox:"0 0 24 24",width:"16",height:"16",fill:"none",stroke:"currentColor","stroke-width":"2","aria-hidden":"true"},ou={key:2,viewBox:"0 0 24 24",width:"16",height:"16",fill:"none",stroke:"currentColor","stroke-width":"2","aria-hidden":"true",class:"animate-spin"},lu=["title","aria-label","disabled"],au={key:0,viewBox:"0 0 24 24",width:"18",height:"18",fill:"none","aria-hidden":"true",class:"text-rose-600 motion-safe:animate-stop-button-pulse"},uu={key:1,viewBox:"0 0 24 24",width:"16",height:"16",fill:"currentColor","aria-hidden":"true"},cu={__name:"ChatForm",props:{placeholder:{type:String,default:"Message..."},disabled:{type:Boolean,default:!1},isAwaitingResponse:{type:Boolean,default:!1}},emits:["submit","cancel"],setup(e,{expose:t,emit:n}){const s=e,i=n,r=U(""),o=U(null),l=U(!1),a=U(!1),p=U(!1),c=U(!1),d=U(!1),h=U(""),y=U("info"),I=U("Voice input is unavailable in this browser/context.");let P=null,q=null;const D=U(""),N=U(!1),K=de(()=>p.value?"Requesting microphone permission...":a.value?l.value?"Stop voice input":"Start voice input":"Voice input is unavailable in this browser/context"),w=de(()=>s.isAwaitingResponse?"Stop response":"Send"),T=de(()=>s.isAwaitingResponse?!1:s.disabled||!r.value.trim()),z=de(()=>s.isAwaitingResponse?"bg-white border border-rose-100 shadow-[0_8px_20px_-12px_rgba(159,18,57,0.35)] hover:bg-rose-50":"bg-linear-to-br from-brand-500 to-brand-600 text-white shadow-[0_10px_24px_-16px_rgba(109,79,194,0.85)] hover:from-brand-600 hover:to-violet-700");function G(){return typeof window=="undefined"?null:window.SpeechRecognition||window.webkitSpeechRecognition||null}function oe(){var Ce;const Y=G(),k=typeof window!="undefined"?window.isSecureContext:!1,ge=typeof navigator!="undefined"&&!!((Ce=navigator.mediaDevices)!=null&&Ce.getUserMedia);a.value=!!(Y&&k&&ge),k?(!ge||!Y)&&(I.value="Voice input is not supported in this browser."):I.value="Voice input requires HTTPS (or localhost).",Y&&a.value&&(P=new Y,P.continuous=!0,P.interimResults=!0,P.lang=typeof navigator!="undefined"&&navigator.language||"en-US",P.onstart=()=>{l.value=!0,v("Listening... Tap mic to stop","listening",{persistent:!0,key:"listening"})},P.onend=()=>{l.value=!1,D.value==="listening"&&A(),N.value&&(N.value=!1,j())},P.onerror=le=>{if(l.value=!1,N.value=!1,(le==null?void 0:le.error)==="not-allowed"||(le==null?void 0:le.error)==="service-not-allowed"){v("Microphone permission denied. Please allow microphone access in browser settings.","error");return}if((le==null?void 0:le.error)==="audio-capture"){v("No microphone detected. Please connect a microphone and try again.","error");return}if((le==null?void 0:le.error)==="no-speech"){v("No speech detected. Try speaking a bit louder.","info");return}v("Voice input failed. Please try again.","error")},P.onresult=le=>{let Ie="";for(let He=le.resultIndex;Hege.stop()),c.value=!0,!0}catch(k){return(k==null?void 0:k.name)==="NotAllowedError"||(k==null?void 0:k.name)==="SecurityError"?v("Microphone permission denied. Please allow it and try again.","error"):(k==null?void 0:k.name)==="NotFoundError"?v("No microphone found on this device.","error"):v("Unable to access microphone. Please check browser permissions.","error"),!1}finally{p.value=!1,D.value==="requesting"&&A()}}async function ie(){var k;!await Z()||!P||(N.value=!1,(k=o.value)==null||k.focus(),P.start())}function v(Y,k="info",ge={}){const{duration:Ce=4200,persistent:le=!1,key:Ie=""}=ge;h.value=Y,y.value=k,D.value=Ie,d.value=!0,q&&clearTimeout(q),le||(q=setTimeout(()=>{d.value=!1,D.value=""},Ce))}function A(){d.value=!1,D.value="",q&&(clearTimeout(q),q=null)}function j(){if(s.isAwaitingResponse){i("cancel");return}const Y=r.value.trim();Y&&(l.value&&P&&P.stop(),i("submit",Y),r.value="")}return t({focus:()=>{var Y;return(Y=o.value)==null?void 0:Y.focus()}}),bn(()=>{oe()}),mn(()=>{P&&l.value&&(N.value=!1,P.stop()),A()}),(Y,k)=>(M(),B("div",tu,[m("form",{class:"group flex min-h-11 items-center gap-2 rounded-full border border-slate-200/90 bg-white/95 px-3 shadow-[0_12px_26px_-20px_rgba(15,23,42,0.7)] transition-all duration-250 focus-within:-translate-y-0.5 focus-within:border-brand-200 focus-within:shadow-[0_18px_30px_-20px_rgba(13,110,253,0.5)] focus-within:ring-2 focus-within:ring-brand-500/25",style:{"border-radius":"9999px"},autocomplete:"off",onSubmit:ke(j,["prevent"]),onClick:k[5]||(k[5]=ke(()=>{},["stop"])),onMousedown:k[6]||(k[6]=ke(()=>{},["stop"])),onKeydown:k[7]||(k[7]=ke(()=>{},["stop"])),onKeyup:k[8]||(k[8]=ke(()=>{},["stop"]))},[oo(m("input",{ref_key:"inputRef",ref:o,type:"text","onUpdate:modelValue":k[0]||(k[0]=ge=>r.value=ge),class:"h-11 w-full border-none bg-transparent text-sm font-medium text-slate-800 placeholder:text-slate-400 focus:outline-none disabled:cursor-not-allowed disabled:opacity-50",placeholder:e.disabled?"Waiting for response...":e.placeholder,disabled:e.disabled,required:"",onKeydown:k[1]||(k[1]=ke(()=>{},["stop"])),onKeyup:k[2]||(k[2]=ke(()=>{},["stop"])),onKeypress:k[3]||(k[3]=ke(()=>{},["stop"])),onInput:k[4]||(k[4]=ke(()=>{},["stop"]))},null,40,nu),[[Rl,r.value]]),m("button",{type:"button",class:re(["grid h-8 w-8 shrink-0 appearance-none place-items-center rounded-full border border-transparent text-slate-600 transition-all duration-200 hover:-translate-y-0.5 hover:border-slate-200 hover:bg-slate-100 hover:text-slate-900 focus:outline-none disabled:cursor-not-allowed disabled:opacity-40",l.value?"border-red-200 bg-red-100 text-red-600 shadow-[0_10px_20px_-18px_rgba(220,38,38,0.9)] hover:bg-red-100 hover:text-red-600":""]),style:{"border-radius":"9999px"},title:K.value,"aria-label":K.value,disabled:e.disabled||!a.value||p.value,onClick:V},[l.value&&!p.value?(M(),B("svg",iu,k[9]||(k[9]=[m("rect",{x:"6",y:"6",width:"12",height:"12",rx:"2"},null,-1)]))):p.value?(M(),B("svg",ou,k[11]||(k[11]=[m("circle",{cx:"12",cy:"12",r:"9",opacity:"0.3"},null,-1),m("path",{d:"M21 12a9 9 0 0 1-9 9"},null,-1)]))):(M(),B("svg",ru,k[10]||(k[10]=[m("path",{d:"M12 3a3 3 0 0 0-3 3v6a3 3 0 0 0 6 0V6a3 3 0 0 0-3-3z"},null,-1),m("path",{d:"M19 10v2a7 7 0 0 1-14 0v-2"},null,-1),m("path",{d:"M12 19v3"},null,-1)])))],10,su),m("button",{type:"submit",title:w.value,"aria-label":w.value,class:re(["grid h-8 w-8 shrink-0 appearance-none place-items-center rounded-full border-0 transition-all duration-200 hover:-translate-y-0.5 focus:outline-none disabled:cursor-not-allowed disabled:opacity-40",z.value]),style:{"border-radius":"9999px"},disabled:T.value},[e.isAwaitingResponse?(M(),B("svg",au,k[12]||(k[12]=[m("circle",{cx:"12",cy:"12",r:"8",stroke:"currentColor","stroke-width":"2.1",class:"opacity-95"},null,-1),m("rect",{x:"9",y:"9",width:"6",height:"6",rx:"1.35",fill:"currentColor"},null,-1)]))):(M(),B("svg",uu,k[13]||(k[13]=[m("path",{d:"M4 12l1.41 1.41L11 7.83V20h2V7.83l5.59 5.58L20 12l-8-8-8 8z"},null,-1)])))],10,lu)],32),fe(eu,{visible:d.value,message:h.value,type:y.value,dismissible:y.value!=="listening",onClose:A},null,8,["visible","message","type","dismissible"])]))}},fu={class:"relative overflow-hidden bg-linear-to-br from-brand-600 via-brand-500 to-violet-400"},du={class:"min-w-0"},pu={key:0,class:"border-t border-slate-200/80 bg-white/90 px-3 py-3 pb-[calc(12px+env(safe-area-inset-bottom))] backdrop-blur-sm sm:px-4 sm:py-4"},hu={__name:"ChatbotPopup",props:{isOpen:{type:Boolean,required:!0},activeTab:{type:String,required:!0},debugEnabled:{type:Boolean,default:!1},chatHistory:{type:Array,required:!0},debugLogs:{type:Array,required:!0},currentDebug:{type:Object,default:null},supportHistory:{type:Array,required:!0},autoReadEnabled:{type:Boolean,required:!0},ttsConfig:{type:Object,required:!0},activeTtsProvider:{type:String,required:!0},settings:{type:Object,default:null},isAwaitingResponse:{type:Boolean,default:!1}},emits:["close","submit","cancelResponse","update:activeTab","toggleAutoRead","togglePollyPreference","toggleDebug"],setup(e,{expose:t,emit:n}){const s=e,i=n,r=U(null),o=U(null),l=U(s.activeTab),a=U("default");function p(){if(a.value==="default"){a.value="half";return}if(a.value==="half"){a.value="full";return}a.value="default"}const c=de(()=>{const d="chat-shell fixed z-[9999] flex min-h-0 flex-col overflow-hidden border border-slate-200/80 shadow-[0_32px_80px_-44px_rgba(2,6,23,0.7),0_18px_40px_-24px_rgba(15,23,42,0.45)] transition-all duration-300 ease-out origin-bottom-right motion-safe:animate-surface-in",h=s.isOpen?"pointer-events-auto opacity-100 translate-x-0 translate-y-0 scale-100":"pointer-events-none opacity-0 translate-x-1/5 translate-y-8 scale-95";return a.value==="full"?[d,h,"inset-0 h-screen w-screen max-h-screen max-w-screen rounded-none origin-center"]:a.value==="half"?[d,h,"bottom-[74px] right-5 h-[min(86vh,860px)] w-[min(50vw,860px)] rounded-2xl","max-[900px]:bottom-[78px] max-[900px]:right-3 max-[900px]:h-[min(86vh,760px)] max-[900px]:w-[min(70vw,760px)] max-[900px]:rounded-[14px]","max-[600px]:inset-0 max-[600px]:h-screen max-[600px]:w-screen max-[600px]:max-h-screen max-[600px]:max-w-screen max-[600px]:rounded-none max-[600px]:pb-[env(safe-area-inset-bottom)]"]:[d,h,"bottom-[74px] right-5 h-[min(560px,72vh)] w-[min(360px,calc(100vw-40px))] rounded-2xl","max-[900px]:bottom-[78px] max-[900px]:right-3 max-[900px]:h-[min(70vh,540px)] max-[900px]:w-[min(360px,calc(100vw-24px))] max-[900px]:rounded-[14px]","max-[600px]:inset-0 max-[600px]:h-screen max-[600px]:w-screen max-[600px]:max-h-screen max-[600px]:max-w-screen max-[600px]:rounded-none max-[600px]:pb-[env(safe-area-inset-bottom)]"]});return Pt(()=>s.activeTab,d=>{l.value=d}),Pt(()=>s.isOpen,d=>{d&&l.value!=="settings"&&Ye(()=>{var h;return(h=o.value)==null?void 0:h.focus()})}),Pt(l,d=>{i("update:activeTab",d)}),Pt(()=>s.debugEnabled,d=>{!d&&l.value==="debug"&&(l.value="chat")}),t({scrollToBottom(){Ye(()=>{const d=r.value;d&&d.scrollTo({top:d.scrollHeight,behavior:"smooth"})})}}),(d,h)=>(M(),B("div",{class:re(c.value),onKeydown:h[8]||(h[8]=ke(()=>{},["stop"])),onKeyup:h[9]||(h[9]=ke(()=>{},["stop"])),onKeypress:h[10]||(h[10]=ke(()=>{},["stop"]))},[h[12]||(h[12]=m("div",{class:"pointer-events-none absolute -right-14 -top-14 h-36 w-36 rounded-full bg-brand-500/15 blur-2xl"},null,-1)),h[13]||(h[13]=m("div",{class:"pointer-events-none absolute -bottom-14 -left-12 h-32 w-32 rounded-full bg-violet-400/15 blur-2xl"},null,-1)),m("div",fu,[h[11]||(h[11]=m("div",{class:"pointer-events-none absolute inset-0 opacity-45",style:{background:"linear-gradient(120deg, rgba(255,255,255,0.16) 0%, rgba(255,255,255,0.02) 52%, rgba(255,255,255,0.12) 100%)"}},null,-1)),fe(Xl,{windowMode:a.value,autoReadEnabled:e.autoReadEnabled,activeTtsProvider:e.activeTtsProvider,onClose:h[0]||(h[0]=y=>d.$emit("close")),onCycleResize:p,onToggleAutoRead:h[1]||(h[1]=y=>d.$emit("toggleAutoRead"))},null,8,["windowMode","autoReadEnabled","activeTtsProvider"]),fe(na,{modelValue:l.value,"onUpdate:modelValue":h[2]||(h[2]=y=>l.value=y),debugEnabled:e.debugEnabled},null,8,["modelValue","debugEnabled"])]),m("div",{class:"chat-scrollbar min-h-0 flex-1 overflow-x-hidden overflow-y-auto bg-slate-50/60 px-4 py-4 max-[900px]:px-3.5 max-[900px]:py-3.5 max-[600px]:px-3 max-[600px]:py-3",ref_key:"chatBodyRef",ref:r},[m("div",du,[l.value==="chat"?(M(),Ze(Aa,{key:0,messages:e.chatHistory,autoReadEnabled:e.autoReadEnabled,ttsConfig:e.ttsConfig},null,8,["messages","autoReadEnabled","ttsConfig"])):l.value==="debug"&&e.debugEnabled?(M(),Ze(Ia,{key:1,logs:e.debugLogs,currentDebug:e.currentDebug},null,8,["logs","currentDebug"])):l.value==="support"?(M(),Ze(Ba,{key:2,messages:e.supportHistory,autoReadEnabled:e.autoReadEnabled,ttsConfig:e.ttsConfig},null,8,["messages","autoReadEnabled","ttsConfig"])):l.value==="settings"?(M(),Ze(Xa,{key:3,autoReadEnabled:e.autoReadEnabled,ttsConfig:e.ttsConfig,settings:e.settings,debugEnabled:e.debugEnabled,onToggleAutoRead:h[3]||(h[3]=y=>d.$emit("toggleAutoRead")),onTogglePollyPreference:h[4]||(h[4]=y=>d.$emit("togglePollyPreference")),onToggleDebug:h[5]||(h[5]=y=>d.$emit("toggleDebug"))},null,8,["autoReadEnabled","ttsConfig","settings","debugEnabled"])):ye("",!0)])],512),l.value!=="settings"?(M(),B("div",pu,[fe(cu,{ref_key:"chatFormRef",ref:o,placeholder:l.value==="support"?"Message Support...":"Message...",disabled:l.value==="chat"&&e.isAwaitingResponse,isAwaitingResponse:l.value==="chat"&&e.isAwaitingResponse,onSubmit:h[6]||(h[6]=y=>d.$emit("submit",y)),onCancel:h[7]||(h[7]=y=>d.$emit("cancelResponse"))},null,8,["placeholder","disabled","isAwaitingResponse"])])):ye("",!0)],34))}},rr="changai_chat_id",or="changai_polly_enabled";function gu(){let e=sessionStorage.getItem(rr);return e||(e=`session_${Date.now()}_${crypto.randomUUID()}`,sessionStorage.setItem(rr,e)),e}function bu(){const e=localStorage.getItem(or);return e===null?!0:e==="true"}function mu(e){localStorage.setItem(or,String(!!e))}const vu={__name:"App",setup(e){const t=U(!1),n=U("chat"),s=U([]),i=U([]),r=U(!1),o=U([]),l=U(null),a=U("actual"),p=U(!0),c=U(null),d=U(!1),h=U(null),y=U({enableVoiceChat:!1,pollyAvailable:!1,usePolly:!0,voiceId:"Joanna"}),I=U("off"),P=U(null),q=de(()=>P.value!==null);function D(){if(!y.value.enableVoiceChat){I.value="off";return}I.value=y.value.usePolly?"polly":"browser"}function N(v){var j;const A=(j=v==null?void 0:v.detail)==null?void 0:j.provider;(A==="polly"||A==="browser"||A==="off")&&(I.value=A)}async function K(){var v,A,j,Y;if(!(d.value||c.value)){d.value=!0;try{c.value=await ua(a.value),y.value={enableVoiceChat:!!((v=c.value)!=null&&v.enable_voice_chat),pollyAvailable:!!((A=c.value)!=null&&A.polly_enabled),usePolly:!!((j=c.value)!=null&&j.polly_enabled)&&bu(),voiceId:((Y=c.value)==null?void 0:Y.polly_voice_id)||"Joanna"},D(),i.value.push({type:"settings",settings:c.value})}catch(k){const ge=ir(k);i.value.push({type:"settings",error:ge})}finally{d.value=!1}}}function w(){t.value=!t.value}function T(){var v;(v=l.value)==null||v.scrollToBottom()}function z(){p.value=!p.value}function G(){const v=!y.value.usePolly;y.value={...y.value,usePolly:v&&y.value.pollyAvailable},mu(y.value.usePolly),D()}async function oe(v){n.value==="support"?await ie(v):await V(v)}async function V(v){var Be;h.value=null,a.value==="actual"&&await K(),s.value.push({role:"user",text:v}),await Ye(),T();const A=ln({role:"model",text:"Thinking...",cancelable:!0,isStatus:!0,statusType:"thinking"});s.value.push(A),await Ye(),T();let j=!1;const Y=gu(),k=`${Y}_${Date.now()}`,ge=la(v,Y,a.value,k),Ce=`debug_${k}`;let le=Date.now();const Ie=[],He=ae=>{var wt;const ct=Date.now(),gs=((ct-le)/1e3).toFixed(2);le=ct;const ft=`${ae.message} (${gs}s)`;if(ae.message&&(Ie.push(ft),h.value=ft),!ae.done&&ae.message&&(A.text=ae.message,A.statusType="pipeline"),ae.done){A.cancelable=!1,A.isStatus=!1,A.statusType=null,ae.error?(A.text=`⚠️ ${ae.message||"Something failed"}`,A.isStatus=!1,A.statusType=null):(wt=ae.data)!=null&&wt.answer?(A.text=ae.data.answer,A.isStatus=!1,A.statusType=null):ae.message&&(A.text=ae.message),frappe.realtime.off(Ce),h.value=null;return}};frappe.realtime.on(Ce,He),P.value=()=>{j||(j=!0,ge.cancel(),frappe.realtime.off(Ce),A.isStatus=!1,A.statusType=null,A.text="Cancelled by user.",i.value.push({type:"cancelled",user:v,steps:[...Ie]}),h.value=null,A.cancelable=!1,P.value=null)};try{const ae=await ge.promise;if(j)return;A.cancelable=!1;const ct=((Be=Ra(ae==null?void 0:ae.Bot))==null?void 0:Be.trim())||"No response.";A.isStatus=!1,A.statusType=null,A.text=ct,i.value.push({type:"success",user:v,steps:[...Ie],final_response:ae}),h.value=null}catch(ae){if(j)return;frappe.realtime.off(Ce),A.cancelable=!1,A.isStatus=!1,A.statusType=null;const ct=ir(ae);h.value=null,i.value.push({type:"failed",user:v,steps:[...Ie],error:ct}),A.isStatus=!1,A.statusType=null,A.text="⚠️ Something went wrong. Please try again."}finally{frappe.realtime.off(Ce),j||(P.value=null)}await Ye(),T()}function Z(){var v;(v=P.value)==null||v.call(P)}async function ie(v){o.value.push({role:"user",text:v}),await Ye(),T();const A=ln({role:"model",text:"Sending to support...",isStatus:!0,statusType:"support"});o.value.push(A),await Ye(),T();try{const j=await aa(v,a.value);A.text=j?sr(j):"Support request sent successfully."}catch{A.text="⚠️ Failed to reach support. Please try again."}await Ye(),T()}return bn(()=>{typeof window!="undefined"&&window.addEventListener("changai-tts-provider",N),a.value==="actual"&&K()}),mn(()=>{typeof window!="undefined"&&window.removeEventListener("changai-tts-provider",N)}),(v,A)=>(M(),B(he,null,[fe(Nl,{isOpen:t.value,onToggle:w},null,8,["isOpen"]),fe(hu,{ref_key:"popupRef",ref:l,isOpen:t.value,activeTab:n.value,"onUpdate:activeTab":A[0]||(A[0]=j=>n.value=j),chatHistory:s.value,debugLogs:i.value,currentDebug:h.value,supportHistory:o.value,autoReadEnabled:p.value,ttsConfig:y.value,activeTtsProvider:I.value,settings:c.value,isAwaitingResponse:q.value,debugEnabled:r.value,onToggleDebug:A[1]||(A[1]=j=>r.value=!r.value),onClose:A[2]||(A[2]=j=>t.value=!1),onSubmit:oe,onCancelResponse:Z,onToggleAutoRead:z,onTogglePollyPreference:G},null,8,["isOpen","activeTab","chatHistory","debugLogs","currentDebug","supportHistory","autoReadEnabled","ttsConfig","activeTtsProvider","settings","isAwaitingResponse","debugEnabled"])],64))}};function xu(){const e=document.querySelector('link[href*="/assets/changai/dist/changai-chatbot.css"]');if(e!=null&&e.href)return e.href;const t=Array.from(document.scripts).find(n=>{var s;return(s=n.src)==null?void 0:s.includes("/assets/changai/dist/changai-chatbot.js")});return t!=null&&t.src?t.src.replace(/changai-chatbot\.js(\?.*)?$/,"changai-chatbot.css$1"):null}function yu(e){const t=xu();if(!t){const n=Array.from(document.querySelectorAll("style[data-vite-dev-id]"));return n.length&&n.forEach(s=>{const i=document.createElement("style");i.dataset.changaiShadowDevStyle="1",i.textContent=s.textContent||"",e.appendChild(i)}),Promise.resolve()}return e.querySelector('link[data-changai-shadow-style="1"]')?Promise.resolve():new Promise(n=>{const s=document.createElement("link");s.rel="stylesheet",s.href=t,s.dataset.changaiShadowStyle="1",s.onload=()=>n(),s.onerror=()=>n(),e.appendChild(s),setTimeout(n,1200)})}async function lr(){if(document.getElementById("changai-chatbot-host"))return;const e=document.createElement("div");e.id="changai-chatbot-host",document.body.appendChild(e);const t=e.attachShadow({mode:"open"});await yu(t);const n=document.createElement("div");n.id="changai-chatbot-root",t.appendChild(n),Il(vu).mount(n);function s(i){i.stopPropagation()}n.addEventListener("keydown",s),n.addEventListener("keyup",s),n.addEventListener("keypress",s)}document.readyState==="loading"?document.addEventListener("DOMContentLoaded",lr):lr()})(); +**/let us;const Ii=typeof window!="undefined"&&window.trustedTypes;if(Ii)try{us=Ii.createPolicy("vue",{createHTML:e=>e})}catch{}const Oi=us?e=>us.createHTML(e):e=>e,sl="http://www.w3.org/2000/svg",il="http://www.w3.org/1998/Math/MathML",Xe=typeof document!="undefined"?document:null,Li=Xe&&Xe.createElement("template"),rl={insert:(e,t,n)=>{t.insertBefore(e,n||null)},remove:e=>{const t=e.parentNode;t&&t.removeChild(e)},createElement:(e,t,n,s)=>{const i=t==="svg"?Xe.createElementNS(sl,e):t==="mathml"?Xe.createElementNS(il,e):n?Xe.createElement(e,{is:n}):Xe.createElement(e);return e==="select"&&s&&s.multiple!=null&&i.setAttribute("multiple",s.multiple),i},createText:e=>Xe.createTextNode(e),createComment:e=>Xe.createComment(e),setText:(e,t)=>{e.nodeValue=t},setElementText:(e,t)=>{e.textContent=t},parentNode:e=>e.parentNode,nextSibling:e=>e.nextSibling,querySelector:e=>Xe.querySelector(e),setScopeId(e,t){e.setAttribute(t,"")},insertStaticContent(e,t,n,s,i,r){const o=n?n.previousSibling:t.lastChild;if(i&&(i===r||i.nextSibling))for(;t.insertBefore(i.cloneNode(!0),n),!(i===r||!(i=i.nextSibling)););else{Li.innerHTML=Oi(s==="svg"?`${e}`:s==="mathml"?`${e}`:e);const l=Li.content;if(s==="svg"||s==="mathml"){const a=l.firstChild;for(;a.firstChild;)l.appendChild(a.firstChild);l.removeChild(a)}t.insertBefore(l,n)}return[o?o.nextSibling:t.firstChild,n?n.previousSibling:t.lastChild]}},ut="transition",Wt="animation",Jt=Symbol("_vtc"),Bi={name:String,type:String,css:{type:Boolean,default:!0},duration:[String,Number,Object],enterFromClass:String,enterActiveClass:String,enterToClass:String,appearFromClass:String,appearActiveClass:String,appearToClass:String,leaveFromClass:String,leaveActiveClass:String,leaveToClass:String},ol=Oe({},ni,Bi),ll=(e=>(e.displayName="Transition",e.props=ol,e))((e,{slots:t})=>tl(co,al(e),t)),xt=(e,t=[])=>{H(e)?e.forEach(n=>n(...t)):e&&e(...t)},Di=e=>e?H(e)?e.some(t=>t.length>1):e.length>1:!1;function al(e){const t={};for(const v in e)v in Bi||(t[v]=e[v]);if(e.css===!1)return t;const{name:n="v",type:s,duration:i,enterFromClass:r=`${n}-enter-from`,enterActiveClass:o=`${n}-enter-active`,enterToClass:l=`${n}-enter-to`,appearFromClass:a=r,appearActiveClass:p=o,appearToClass:c=l,leaveFromClass:d=`${n}-leave-from`,leaveActiveClass:h=`${n}-leave-active`,leaveToClass:y=`${n}-leave-to`}=e,I=ul(i),P=I&&I[0],q=I&&I[1],{onBeforeEnter:D,onEnter:N,onEnterCancelled:K,onLeave:w,onLeaveCancelled:T,onBeforeAppear:z=D,onAppear:G=N,onAppearCancelled:oe=K}=t,V=(v,A,j,Y)=>{v._enterCancelled=Y,yt(v,A?c:l),yt(v,A?p:o),j&&j()},Z=(v,A)=>{v._isLeaving=!1,yt(v,d),yt(v,y),yt(v,h),A&&A()},ie=v=>(A,j)=>{const Y=v?G:N,k=()=>V(A,v,j);xt(Y,[A,k]),Fi(()=>{yt(A,v?a:r),Qe(A,v?c:l),Di(Y)||Ni(A,s,P,k)})};return Oe(t,{onBeforeEnter(v){xt(D,[v]),Qe(v,r),Qe(v,o)},onBeforeAppear(v){xt(z,[v]),Qe(v,a),Qe(v,p)},onEnter:ie(!1),onAppear:ie(!0),onLeave(v,A){v._isLeaving=!0;const j=()=>Z(v,A);Qe(v,d),v._enterCancelled?(Qe(v,h),ji()):(ji(),Qe(v,h)),Fi(()=>{v._isLeaving&&(yt(v,d),Qe(v,y),Di(w)||Ni(v,s,q,j))}),xt(w,[v,j])},onEnterCancelled(v){V(v,!1,void 0,!0),xt(K,[v])},onAppearCancelled(v){V(v,!0,void 0,!0),xt(oe,[v])},onLeaveCancelled(v){Z(v),xt(T,[v])}})}function ul(e){if(e==null)return null;if(ue(e))return[cs(e.enter),cs(e.leave)];{const t=cs(e);return[t,t]}}function cs(e){return mr(e)}function Qe(e,t){t.split(/\s+/).forEach(n=>n&&e.classList.add(n)),(e[Jt]||(e[Jt]=new Set)).add(t)}function yt(e,t){t.split(/\s+/).forEach(s=>s&&e.classList.remove(s));const n=e[Jt];n&&(n.delete(t),n.size||(e[Jt]=void 0))}function Fi(e){requestAnimationFrame(()=>{requestAnimationFrame(e)})}let cl=0;function Ni(e,t,n,s){const i=e._endId=++cl,r=()=>{i===e._endId&&s()};if(n!=null)return setTimeout(r,n);const{type:o,timeout:l,propCount:a}=fl(e,t);if(!o)return s();const p=o+"end";let c=0;const d=()=>{e.removeEventListener(p,h),r()},h=y=>{y.target===e&&++c>=a&&d()};setTimeout(()=>{c(n[I]||"").split(", "),i=s(`${ut}Delay`),r=s(`${ut}Duration`),o=Vi(i,r),l=s(`${Wt}Delay`),a=s(`${Wt}Duration`),p=Vi(l,a);let c=null,d=0,h=0;t===ut?o>0&&(c=ut,d=o,h=r.length):t===Wt?p>0&&(c=Wt,d=p,h=a.length):(d=Math.max(o,p),c=d>0?o>p?ut:Wt:null,h=c?c===ut?r.length:a.length:0);const y=c===ut&&/\b(transform|all)(,|$)/.test(s(`${ut}Property`).toString());return{type:c,timeout:d,propCount:h,hasTransform:y}}function Vi(e,t){for(;e.lengthHi(n)+Hi(e[s])))}function Hi(e){return e==="auto"?0:Number(e.slice(0,-1).replace(",","."))*1e3}function ji(){return document.body.offsetHeight}function dl(e,t,n){const s=e[Jt];s&&(t=(t?[t,...s]:[...s]).join(" ")),t==null?e.removeAttribute("class"):n?e.setAttribute("class",t):e.className=t}const Ui=Symbol("_vod"),pl=Symbol("_vsh"),hl=Symbol(""),gl=/(^|;)\s*display\s*:/;function bl(e,t,n){const s=e.style,i=ce(n);let r=!1;if(n&&!i){if(t)if(ce(t))for(const o of t.split(";")){const l=o.slice(0,o.indexOf(":")).trim();n[l]==null&&Tn(s,l,"")}else for(const o in t)n[o]==null&&Tn(s,o,"");for(const o in n)o==="display"&&(r=!0),Tn(s,o,n[o])}else if(i){if(t!==n){const o=s[hl];o&&(n+=";"+o),s.cssText=n,r=gl.test(n)}}else t&&e.removeAttribute("style");Ui in e&&(e[Ui]=r?s.display:"",e[pl]&&(s.display="none"))}const qi=/\s*!important$/;function Tn(e,t,n){if(H(n))n.forEach(s=>Tn(e,t,s));else if(n==null&&(n=""),t.startsWith("--"))e.setProperty(t,n);else{const s=ml(e,t);qi.test(n)?e.setProperty(pt(s),n.replace(qi,""),"important"):e[s]=n}}const Ki=["Webkit","Moz","ms"],fs={};function ml(e,t){const n=fs[t];if(n)return n;let s=tt(t);if(s!=="filter"&&s in e)return fs[t]=s;s=_s(s);for(let i=0;ids||(wl.then(()=>ds=0),ds=Date.now());function Cl(e,t){const n=s=>{if(!s._vts)s._vts=Date.now();else if(s._vts<=n.attached)return;De(Sl(s,n.value),t,5,[s])};return n.value=e,n.attached=_l(),n}function Sl(e,t){if(H(t)){const n=e.stopImmediatePropagation;return e.stopImmediatePropagation=()=>{n.call(e),e._stopped=!0},t.map(s=>i=>!i._stopped&&s&&s(i))}else return t}const Zi=e=>e.charCodeAt(0)===111&&e.charCodeAt(1)===110&&e.charCodeAt(2)>96&&e.charCodeAt(2)<123,Tl=(e,t,n,s,i,r)=>{const o=i==="svg";t==="class"?dl(e,s,o):t==="style"?bl(e,n,s):Zt(t)?Rn(t)||xl(e,t,n,s,r):(t[0]==="."?(t=t.slice(1),!0):t[0]==="^"?(t=t.slice(1),!1):El(e,t,s,o))?(Ji(e,t,s),!e.tagName.includes("-")&&(t==="value"||t==="checked"||t==="selected")&&Wi(e,t,s,o,r,t!=="value")):e._isVueCE&&(/[A-Z]/.test(t)||!ce(s))?Ji(e,tt(t),s,r,t):(t==="true-value"?e._trueValue=s:t==="false-value"&&(e._falseValue=s),Wi(e,t,s,o))};function El(e,t,n,s){if(s)return!!(t==="innerHTML"||t==="textContent"||t in e&&Zi(t)&&Q(n));if(t==="spellcheck"||t==="draggable"||t==="translate"||t==="autocorrect"||t==="form"||t==="list"&&e.tagName==="INPUT"||t==="type"&&e.tagName==="TEXTAREA")return!1;if(t==="width"||t==="height"){const i=e.tagName;if(i==="IMG"||i==="VIDEO"||i==="CANVAS"||i==="SOURCE")return!1}return Zi(t)&&ce(n)?!1:t in e}const Xi=e=>{const t=e.props["onUpdate:modelValue"]||!1;return H(t)?n=>en(t,n):t};function Al(e){e.target.composing=!0}function Qi(e){const t=e.target;t.composing&&(t.composing=!1,t.dispatchEvent(new Event("input")))}const ps=Symbol("_assign"),Rl={created(e,{modifiers:{lazy:t,trim:n,number:s}},i){e[ps]=Xi(i);const r=s||i.props&&i.props.type==="number";Mt(e,t?"change":"input",o=>{if(o.target.composing)return;let l=e.value;n&&(l=l.trim()),r&&(l=kn(l)),e[ps](l)}),n&&Mt(e,"change",()=>{e.value=e.value.trim()}),t||(Mt(e,"compositionstart",Al),Mt(e,"compositionend",Qi),Mt(e,"change",Qi))},mounted(e,{value:t}){e.value=t==null?"":t},beforeUpdate(e,{value:t,oldValue:n,modifiers:{lazy:s,trim:i,number:r}},o){if(e[ps]=Xi(o),e.composing)return;const l=(r||e.type==="number")&&!/^0\d/.test(e.value)?kn(e.value):e.value,a=t==null?"":t;l!==a&&(document.activeElement===e&&e.type!=="range"&&(s&&t===n||i&&e.value.trim()===a)||(e.value=a))}},$l=["ctrl","shift","alt","meta"],Pl={stop:e=>e.stopPropagation(),prevent:e=>e.preventDefault(),self:e=>e.target!==e.currentTarget,ctrl:e=>!e.ctrlKey,shift:e=>!e.shiftKey,alt:e=>!e.altKey,meta:e=>!e.metaKey,left:e=>"button"in e&&e.button!==0,middle:e=>"button"in e&&e.button!==1,right:e=>"button"in e&&e.button!==2,exact:(e,t)=>$l.some(n=>e[`${n}Key`]&&!t.includes(n))},ke=(e,t)=>{const n=e._withMods||(e._withMods={}),s=t.join(".");return n[s]||(n[s]=(i,...r)=>{for(let o=0;o{const t=kl().createApp(...e),{mount:n}=t;return t.mount=s=>{const i=Ll(s);if(!i)return;const r=t._component;!Q(r)&&!r.render&&!r.template&&(r.template=i.innerHTML),i.nodeType===1&&(i.textContent="");const o=n(i,!1,Ol(i));return i instanceof Element&&(i.removeAttribute("v-cloak"),i.setAttribute("data-v-app","")),o},t};function Ol(e){if(e instanceof SVGElement)return"svg";if(typeof MathMLElement=="function"&&e instanceof MathMLElement)return"mathml"}function Ll(e){return ce(e)?document.querySelector(e):e}const Bl=["aria-pressed"],Dl={key:0,viewBox:"0 0 24 24",width:"20",height:"20","aria-hidden":"true"},Fl={key:1,viewBox:"0 0 24 24",width:"18",height:"18","aria-hidden":"true",fill:"none"},Nl={__name:"ChatbotToggler",props:{isOpen:{type:Boolean,required:!0}},emits:["toggle"],setup(e){return(t,n)=>(M(),B("button",{class:"fixed bottom-5 right-5 z-9999 grid h-12 w-12 appearance-none place-items-center rounded-full border border-white/20 bg-gradient-to-br from-brand-500 to-brand-600 text-white shadow-[0_20px_36px_-20px_rgba(109,79,194,0.85)] transition-all duration-250 hover:-translate-y-0.5 hover:from-brand-600 hover:to-violet-700 hover:shadow-[0_22px_40px_-22px_rgba(109,79,194,1)] focus:outline-none max-[600px]:bottom-3 max-[600px]:right-3 max-[600px]:h-13 max-[600px]:w-13",style:{"border-radius":"9999px"},"aria-pressed":e.isOpen?"true":"false",onClick:n[0]||(n[0]=s=>t.$emit("toggle"))},[e.isOpen?(M(),B("svg",Fl,n[2]||(n[2]=[m("path",{d:"M6 6l12 12M18 6L6 18",stroke:"currentColor","stroke-width":"2","stroke-linecap":"round"},null,-1)]))):(M(),B("svg",Dl,n[1]||(n[1]=[m("path",{d:"M4 4h16a2 2 0 0 1 2 2v9a2 2 0 0 1-2 2H8l-4 4v-4H4a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2z",fill:"currentColor",stroke:"currentColor","stroke-width":"2","stroke-linecap":"miter","stroke-linejoin":"miter"},null,-1)])))],8,Bl))}},Vl={class:"chat-header relative flex min-h-14 items-center justify-between px-4 pb-2.5 pt-3 text-white sm:px-5"},Hl={class:"flex min-w-0 flex-1 items-center gap-2 sm:gap-2.5"},jl={xmlns:"http://www.w3.org/2000/svg",width:"35",height:"35",viewBox:"0 0 1024 1024",class:"h-8 w-8 shrink-0 rounded-full bg-white p-1.5 shadow-md motion-safe:animate-soft-float",style:{fill:"#6d4fc2"}},Ul={class:"ml-2 flex items-center gap-1.5"},ql=["title"],Kl=["title","aria-label"],zl={key:0,viewBox:"0 0 24 24",width:"14",height:"14",fill:"none",stroke:"currentColor","stroke-width":"2","aria-hidden":"true"},Wl={key:1,viewBox:"0 0 24 24",width:"14",height:"14",fill:"none",stroke:"currentColor","stroke-width":"2","aria-hidden":"true"},Jl=["title","aria-label"],Gl={key:0,xmlns:"http://www.w3.org/2000/svg",width:"16",height:"16",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor","stroke-width":"2","aria-hidden":"true"},Yl={key:1,xmlns:"http://www.w3.org/2000/svg",width:"16",height:"16",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor","stroke-width":"2","aria-hidden":"true"},Zl={key:2,xmlns:"http://www.w3.org/2000/svg",width:"16",height:"16",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor","stroke-width":"2","aria-hidden":"true"},Xl={__name:"ChatHeader",props:{windowMode:{type:String,required:!0},autoReadEnabled:{type:Boolean,required:!0},activeTtsProvider:{type:String,required:!0}},emits:["close","cycleResize","toggleAutoRead"],setup(e){const t=e,n={default:"Compact",half:"Half Screen",full:"Full Screen"},s=de(()=>n[t.windowMode]||"Compact"),i=de(()=>t.windowMode==="default"?"Half Screen":t.windowMode==="half"?"Full Screen":"Compact"),r=de(()=>t.activeTtsProvider==="polly"?"TTS: Polly":t.activeTtsProvider==="browser"?"TTS: Browser":"TTS: Off"),o=de(()=>t.activeTtsProvider==="polly"?"bg-emerald-500/45":t.activeTtsProvider==="browser"?"bg-amber-500/45":"bg-slate-500/35");return(l,a)=>(M(),B("div",Vl,[m("div",Hl,[(M(),B("svg",jl,a[3]||(a[3]=[m("path",{d:"M738.3 287.6H285.7c-59 0-106.8 47.8-106.8 106.8v303.1c0 59 47.8 106.8 106.8 106.8h81.5v111.1c0 .7.8 1.1 1.4.7l166.9-110.6 41.8-.8h117.4l43.6-.4c59 0 106.8-47.8 106.8-106.8V394.5c0-59-47.8-106.9-106.8-106.9zM351.7 448.2c0-29.5 23.9-53.5 53.5-53.5s53.5 23.9 53.5 53.5-23.9 53.5-53.5 53.5-53.5-23.9-53.5-53.5zm157.9 267.1c-67.8 0-123.8-47.5-132.3-109h264.6c-8.6 61.5-64.5 109-132.3 109zm110-213.7c-29.5 0-53.5-23.9-53.5-53.5s23.9-53.5 53.5-53.5 53.5 23.9 53.5 53.5-23.9 53.5-53.5 53.5zM867.2 644.5V453.1h26.5c19.4 0 35.1 15.7 35.1 35.1v121.1c0 19.4-15.7 35.1-35.1 35.1h-26.5zM95.2 609.4V488.2c0-19.4 15.7-35.1 35.1-35.1h26.5v191.3h-26.5c-19.4 0-35.1-15.7-35.1-35.1zM561.5 149.6c0 23.4-15.6 43.3-36.9 49.7v44.9h-30v-44.9c-21.4-6.5-36.9-26.3-36.9-49.7 0-28.6 23.3-51.9 51.9-51.9s51.9 23.3 51.9 51.9z"},null,-1)]))),a[4]||(a[4]=m("h2",{class:"truncate text-xs font-semibold tracking-[0.01em] sm:text-base text-white/95"},"ChangAI from ERPGulf",-1))]),m("div",Ul,[m("span",{class:re(["hidden rounded-full border border-white/25 px-2 py-1 text-[10px] font-semibold uppercase tracking-wide text-white/95 shadow-sm backdrop-blur-sm sm:inline",o.value]),title:`TTS provider: ${r.value}`},we(r.value),11,ql),m("button",{class:re(["h-8 min-w-8 appearance-none items-center justify-center rounded-md border border-white/20 px-2 text-xs font-semibold text-white/90 transition-all duration-200 focus:outline-none sm:flex",e.autoReadEnabled?"bg-white/24 shadow-sm":"hover:bg-white/15"]),style:{"border-radius":"0.375rem"},title:e.autoReadEnabled?"Auto speech on":"Auto speech off","aria-label":e.autoReadEnabled?"Turn off auto speech":"Turn on auto speech",onClick:a[0]||(a[0]=p=>l.$emit("toggleAutoRead"))},[e.autoReadEnabled?(M(),B("svg",zl,a[5]||(a[5]=[m("path",{d:"M11 5L6 9H3v6h3l5 4V5z"},null,-1),m("path",{d:"M15 9a4 4 0 0 1 0 6"},null,-1),m("path",{d:"M18 7a7 7 0 0 1 0 10"},null,-1)]))):(M(),B("svg",Wl,a[6]||(a[6]=[m("path",{d:"M11 5L6 9H3v6h3l5 4V5z"},null,-1),m("path",{d:"M22 9l-6 6"},null,-1),m("path",{d:"M16 9l6 6"},null,-1)])))],10,Kl),m("button",{class:re(["flex h-8 min-w-8 appearance-none items-center justify-center rounded-md border border-white/20 px-2 text-xs font-semibold text-white/90 transition-all duration-200 focus:outline-none","bg-white/20 shadow-sm hover:bg-white/25"]),style:{"border-radius":"0.375rem"},title:`Resize mode: ${s.value} (click to ${i.value})`,"aria-label":`Resize mode ${s.value}. Click to switch to ${i.value}`,onClick:a[1]||(a[1]=p=>l.$emit("cycleResize"))},[e.windowMode==="default"?(M(),B("svg",Gl,a[7]||(a[7]=[m("rect",{x:"7",y:"8",width:"10",height:"8",rx:"2"},null,-1)]))):e.windowMode==="half"?(M(),B("svg",Yl,a[8]||(a[8]=[m("rect",{x:"4",y:"5",width:"16",height:"14",rx:"2"},null,-1),m("path",{d:"M12 5v14"},null,-1)]))):(M(),B("svg",Zl,a[9]||(a[9]=[m("rect",{x:"4",y:"5",width:"16",height:"14",rx:"2"},null,-1),m("path",{d:"M8 8H6v2M16 8h2v2M8 16H6v-2M16 16h2v-2"},null,-1)])))],8,Jl),m("button",{class:"grid h-8 w-8 shrink-0 appearance-none place-items-center rounded-full border border-white/20 text-white transition-all duration-200 hover:scale-105 hover:bg-white/20 focus:outline-none focus-visible:ring-2 focus-visible:ring-white/70",style:{"border-radius":"9999px"},"aria-label":"Close chatbot",onClick:a[2]||(a[2]=p=>l.$emit("close"))},a[10]||(a[10]=[m("svg",{xmlns:"http://www.w3.org/2000/svg",height:"24",width:"24",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor","stroke-width":"2"},[m("path",{d:"M6 9l6 6 6-6"})],-1)]))])]))}},Ql={class:"flex gap-1.5 border-b border-slate-200/80 px-2.5 pb-2.5 pt-1"},ea=["onClick"],ta={class:"inline-flex items-center gap-1.5"},na={__name:"TabBar",props:{modelValue:{type:String,required:!0},debugEnabled:{type:Boolean,default:!1}},emits:["update:modelValue"],setup(e){const t=e,n=de(()=>{const s=[{id:"chat",label:"Chats"},{id:"debug",label:"Debug"},{id:"support",label:"Support"},{id:"settings",label:"Settings"}];return t.debugEnabled?s:s.filter(i=>i.id!=="debug")});return(s,i)=>(M(),B("div",Ql,[(M(!0),B(he,null,vn(n.value,r=>(M(),B("button",{key:r.id,class:re(["group min-w-0 flex-1 h-9 appearance-none rounded-lg border border-transparent bg-transparent px-2 text-xs font-semibold transition-all duration-200 focus:outline-none",e.modelValue===r.id?"border-white/30 bg-linear-to-r from-violet-300/36 via-indigo-300/30 to-sky-300/28 text-white shadow-[0_4px_10px_rgba(20,24,40,0.22)]":"text-white/80 hover:border-white/25 hover:bg-white/12 hover:text-white"]),onClick:o=>s.$emit("update:modelValue",r.id)},[m("span",ta,[m("span",{class:re(["h-1.5 w-1.5 rounded-full transition-colors duration-200",e.modelValue===r.id?"bg-white":"bg-white/40 group-hover:bg-white/70"])},null,2),rs(" "+we(r.label),1)])],10,ea))),128))]))}},sa=(e,t)=>{const n=e.__vccOpts||e;for(const[s,i]of t)n[s]=i;return n},ia={},ra={xmlns:"http://www.w3.org/2000/svg",width:"50",height:"50",viewBox:"0 0 1024 1024",class:"h-7.5 w-7.5 shrink-0 self-end rounded-full bg-gradient-to-br from-brand-500 to-brand-600 p-1.5 fill-white shadow-[0_10px_18px_-12px_rgba(109,79,194,0.85)]"};function oa(e,t){return M(),B("svg",ra,t[0]||(t[0]=[m("path",{d:"M738.3 287.6H285.7c-59 0-106.8 47.8-106.8 106.8v303.1c0 59 47.8 106.8 106.8 106.8h81.5v111.1c0 .7.8 1.1 1.4.7l166.9-110.6 41.8-.8h117.4l43.6-.4c59 0 106.8-47.8 106.8-106.8V394.5c0-59-47.8-106.9-106.8-106.9zM351.7 448.2c0-29.5 23.9-53.5 53.5-53.5s53.5 23.9 53.5 53.5-23.9 53.5-53.5 53.5-53.5-23.9-53.5-53.5zm157.9 267.1c-67.8 0-123.8-47.5-132.3-109h264.6c-8.6 61.5-64.5 109-132.3 109zm110-213.7c-29.5 0-53.5-23.9-53.5-53.5s23.9-53.5 53.5-53.5 53.5 23.9 53.5 53.5-23.9 53.5-53.5 53.5zM867.2 644.5V453.1h26.5c19.4 0 35.1 15.7 35.1 35.1v121.1c0 19.4-15.7 35.1-35.1 35.1h-26.5zM95.2 609.4V488.2c0-19.4 15.7-35.1 35.1-35.1h26.5v191.3h-26.5c-19.4 0-35.1-15.7-35.1-35.1zM561.5 149.6c0 23.4-15.6 43.3-36.9 49.7v44.9h-30v-44.9c-21.4-6.5-36.9-26.3-36.9-49.7 0-28.6 23.3-51.9 51.9-51.9s51.9 23.3 51.9 51.9z"},null,-1)]))}const tr=sa(ia,[["render",oa]]),En={PIPELINE:"changai.changai.api.v2.text2sql_pipeline_v2.run_text2sql_pipeline",SUPPORT:"changai.changai.api.v2.text2sql_pipeline_v2.support_bot",SETTINGS:"changai.changai.api.v2.text2sql_pipeline_v2.get_frontend_settings",TTS:"changai.changai.api.v2.text2sql_pipeline_v2.synthesize_tts"};function hs(e,t={},n="actual"){return n==="test"?Promise.resolve({Bot:`[TEST MODE] ${JSON.stringify(t)}`}):!window.frappe||!window.frappe.call?Promise.reject(new Error("Frappe API is unavailable in actual mode.")):new Promise((s,i)=>{window.frappe.call({method:e,args:t,callback(r){s(r.message)},error(r){i(r)}})})}function la(e,t,n="actual",s=null){if(n==="test")return{promise:Promise.resolve({Bot:`[TEST MODE] ${JSON.stringify({user_question:e,chat_id:t,request_id:s})}`}),cancel:()=>!1};if(!window.frappe||!window.frappe.call)return{promise:Promise.reject(new Error("Frappe API is unavailable in actual mode.")),cancel:()=>!1};let i=null,r=!1;return{promise:new Promise((a,p)=>{i=window.frappe.call({method:En.PIPELINE,args:{user_question:e,chat_id:t,request_id:s},callback(c){r=!0,a(c.message)},error(c){r=!0,p(c)}})}),cancel:()=>r||!i||typeof i.abort!="function"?!1:(i.abort(),r=!0,!0)}}function aa(e,t="actual"){return hs(En.SUPPORT,{message:e},t)}function ua(e="actual"){return hs(En.SETTINGS,{},e)}function ca(e,t="Joanna",n="actual"){return hs(En.TTS,{text:e,voice_id:t},n)}const fa={key:1,class:"flex min-w-0 max-w-[calc(100%-2.5rem)] flex-1 flex-col max-[600px]:max-w-[calc(100%-2.25rem)]"},da={key:0,class:"flex w-fit flex-col items-start gap-1"},pa=["aria-label"],ha={class:"inline-flex items-center gap-1.5"},ga={class:"text-[8px] font-semibold tracking-[0.12em] uppercase text-[#3a67c9]"},ba={key:1,class:"flex w-fit max-w-full flex-col items-start gap-2"},ma={class:"chat-card relative w-fit max-w-full whitespace-pre-line rounded-[10px_10px_10px_3px] px-4 py-3 text-xs leading-relaxed wrap-anywhere text-slate-900"},va=["innerHTML"],xa={key:0,class:"pointer-events-none absolute inset-x-0 bottom-0 h-14 rounded-b-[10px] bg-linear-to-t from-white via-white/92 to-white/0","aria-hidden":"true"},ya={key:0,class:"flex flex-wrap items-center gap-2"},wa=["title","aria-label"],_a=["title","aria-label"],Ca={viewBox:"0 0 24 24",width:"16",height:"16",fill:"none",stroke:"currentColor","stroke-width":"2","aria-hidden":"true"},Sa={key:2,class:"w-fit max-w-[85%] whitespace-pre-line rounded-[13px_13px_3px_13px] bg-linear-to-br from-brand-500 to-brand-600 px-4 py-3 text-[11px] leading-relaxed wrap-anywhere text-white shadow-[0_14px_30px_-18px_rgba(109,79,194,0.85)] max-[600px]:max-w-[88%]"},nr={__name:"ChatMessage",props:{message:{type:Object,required:!0},autoReadEnabled:{type:Boolean,default:!1},ttsConfig:{type:Object,default:()=>({enableVoiceChat:!1,pollyAvailable:!1,usePolly:!0,voiceId:"Joanna"})}},setup(e){const t=e,n=U(!1),s=U(null),i=U(!1),r=U(!1),o=de(()=>typeof window!="undefined"&&"speechSynthesis"in window&&"SpeechSynthesisUtterance"in window);function l(w){typeof window!="undefined"&&window.dispatchEvent(new CustomEvent("changai-tts-provider",{detail:{provider:w}}))}function a(w){return typeof w!="string"?"":w.includes("<")?(new DOMParser().parseFromString(w,"text/html").body.textContent||"").replace(/\s+/g," ").trim():w.trim()}function p(){o.value&&window.speechSynthesis.cancel(),s.value&&(s.value.pause(),s.value.src="",s.value=null),n.value=!1}function c(){var w,T,z;if(r.value=!r.value,r.value)p();else{const G=P.value;if(!t.autoReadEnabled||!((w=t.ttsConfig)!=null&&w.enableVoiceChat)||!G||I())return;if((T=t.ttsConfig)!=null&&T.pollyAvailable&&((z=t.ttsConfig)!=null&&z.usePolly)){h(G).catch(oe=>{d(G)});return}d(G)}}function d(w){if(!o.value||!w)return;window.dispatchEvent(new CustomEvent("changai-tts-stop")),window.speechSynthesis.cancel();const T=new SpeechSynthesisUtterance(w);T.rate=1,T.pitch=1,T.onend=()=>{n.value=!1},T.onerror=()=>{n.value=!1},n.value=!0,l("browser"),window.speechSynthesis.speak(T)}async function h(w){var V;const T=await ca(w,((V=t.ttsConfig)==null?void 0:V.voiceId)||"Joanna");if(!(T!=null&&T.ok)||!(T!=null&&T.audio_base64))throw new Error((T==null?void 0:T.error)||"Polly synthesis failed");window.dispatchEvent(new CustomEvent("changai-tts-stop")),p();const z=(T==null?void 0:T.mime_type)||"audio/mpeg",G=new Audio(`data:${z};base64,${T.audio_base64}`);s.value=G,n.value=!0;let oe=!1;G.onplay=()=>{oe=!0,l("polly")},G.onended=()=>{s.value===G&&(s.value=null),n.value=!1},G.onerror=()=>{s.value===G&&(s.value=null),n.value=!1},await G.play(),oe||l("polly")}function y(){n.value=!1}function I(){var w;return!!((w=t.message)!=null&&w.isStatus)}const P=de(()=>{var w;return a(((w=t.message)==null?void 0:w.text)||"")}),q=de(()=>{var w;return((w=t.message)==null?void 0:w.role)!=="user"&&I()}),D=de(()=>{var w;return(w=t.message)!=null&&w.isStatus?t.message.statusType==="support"?"Sending to support":P.value||"Thinking":""}),N=de(()=>{var z;if(((z=t.message)==null?void 0:z.role)==="user"||q.value)return!1;const w=P.value,T=w.split(/\n+/).filter(Boolean).length;return w.length>520||T>8}),K=de(()=>{var w,T;return N.value&&((w=t.message)==null?void 0:w.role)!=="user"&&!q.value&&((T=t.ttsConfig)==null?void 0:T.enableVoiceChat)});return Pt(()=>t.message.text,async(w,T)=>{var oe,V,Z;if(!t.autoReadEnabled||t.message.role==="user"||r.value)return;if(!((oe=t.ttsConfig)!=null&&oe.enableVoiceChat)){l("off");return}const z=a(w);if(!z||I())return;const G=a(T||"");if(z!==G){if((V=t.ttsConfig)!=null&&V.pollyAvailable&&((Z=t.ttsConfig)!=null&&Z.usePolly))try{await h(z);return}catch{}d(z)}}),Pt(()=>t.message.text,()=>{i.value=!1,r.value=!1}),bn(()=>{typeof window!="undefined"&&window.addEventListener("changai-tts-stop",y)}),mn(()=>{typeof window!="undefined"&&window.removeEventListener("changai-tts-stop",y),n.value&&p()}),(w,T)=>(M(),B("div",{class:re(["motion-safe:animate-fade-rise flex w-full gap-1.5",e.message.role==="user"?"flex-col items-end":"items-start"])},[e.message.role!=="user"?(M(),Ze(tr,{key:0})):ye("",!0),e.message.role!=="user"?(M(),B("div",fa,[q.value?(M(),B("div",da,[m("div",{class:"chat-card inline-flex w-fit rounded-[10px_10px_10px_3px] px-3 py-2",role:"status","aria-live":"polite","aria-label":D.value},[m("div",ha,[T[1]||(T[1]=m("span",{class:"relative inline-flex h-4 w-4 shrink-0 items-center justify-center"},[m("span",{class:"absolute inset-0 rounded-full border border-transparent border-t-[#4b89ff] border-r-[#4b89ff]/70 animate-gemini-arc"}),m("svg",{viewBox:"0 0 24 24",class:"relative h-3 w-3 text-[#4b89ff] animate-gemini-spark","aria-hidden":"true"},[m("path",{fill:"currentColor",d:"M12 2.8c.52 3.22 1.6 5.66 3.22 7.28 1.62 1.62 4.06 2.7 7.28 3.22-3.22.52-5.66 1.6-7.28 3.22-1.62 1.62-2.7 4.06-3.22 7.28-.52-3.22-1.6-5.66-3.22-7.28-1.62-1.62-4.06-2.7-7.28-3.22 3.22-.52 5.66-1.6 7.28-3.22 1.62-1.62 2.7-4.06 3.22-7.28Z"})])],-1)),m("span",ga,we(D.value),1)])],8,pa)])):(M(),B("div",ba,[m("div",ma,[m("div",{class:re(["overflow-x-auto",N.value&&!i.value?"max-h-48 overflow-y-hidden":""]),innerHTML:e.message.text},null,10,va),N.value&&!i.value?(M(),B("div",xa)):ye("",!0)]),N.value||K.value?(M(),B("div",ya,[N.value?(M(),B("button",{key:0,type:"button",class:"inline-flex items-center rounded-full border border-slate-200 bg-white px-2.5 py-1 text-[10px] font-semibold uppercase tracking-[0.08em] text-slate-600 transition-colors duration-200 hover:border-brand-200 hover:text-brand-600",title:i.value?"Collapse response":"Expand response","aria-label":i.value?"Collapse response":"Expand response",onClick:T[0]||(T[0]=z=>i.value=!i.value)},we(i.value?"Collapse":"Expand"),9,wa)):ye("",!0),K.value?(M(),B("button",{key:1,type:"button",class:re(["inline-flex h-8 w-8 items-center justify-center rounded-full border transition-colors duration-200",r.value?"border-red-200 bg-red-50 text-red-600 hover:border-red-300 hover:bg-red-100":"border-green-200 bg-green-50 text-green-600 hover:border-green-300 hover:bg-green-100"]),title:r.value?"TTS muted":"TTS enabled","aria-label":r.value?"TTS muted":"TTS enabled",onClick:c},[(M(),B("svg",Ca,[T[6]||(T[6]=m("path",{d:"M11 5L6 9H3v6h3l5 4V5Z"},null,-1)),r.value?(M(),B(he,{key:0},[T[2]||(T[2]=m("path",{d:"M15 9l4 6"},null,-1)),T[3]||(T[3]=m("path",{d:"M19 9l-4 6"},null,-1))],64)):(M(),B(he,{key:1},[T[4]||(T[4]=m("path",{d:"M15 10a3 3 0 0 1 0 4"},null,-1)),T[5]||(T[5]=m("path",{d:"M17.5 7.5a6 6 0 0 1 0 9"},null,-1))],64))]))],10,_a)):ye("",!0)])):ye("",!0)]))])):(M(),B("p",Sa,we(e.message.text),1))],2))}},Ta={class:"flex flex-col gap-4 sm:gap-5"},Ea={class:"motion-safe:animate-fade-rise flex w-full items-start gap-1.5"},Aa={__name:"ChatTab",props:{messages:{type:Array,required:!0},autoReadEnabled:{type:Boolean,default:!1},ttsConfig:{type:Object,required:!0}},setup(e){return(t,n)=>(M(),B("div",Ta,[m("div",Ea,[fe(tr),n[0]||(n[0]=m("p",{class:"w-fit max-w-[calc(100%-2.5rem)] whitespace-pre-line rounded-[10px_10px_10px_3px] bg-brand-50 px-4 py-3 text-xs leading-relaxed wrap-anywhere text-slate-900 max-[600px]:max-w-[calc(100%-2.25rem)]"},[rs(" Hello there πŸ‘‹ I am ChangAI from ERPGulf.com , your ERP assistant."),m("br"),m("a",{target:"_blank",href:"https://app.erpgulf.com/en/articles/chang-ai-quick-start-guide",rel:"noopener noreferrer",style:{color:"#1e90ff"}},"ChangAI Quick Start Guide - Click here.")],-1))]),(M(!0),B(he,null,vn(e.messages,(s,i)=>(M(),Ze(nr,{key:i,message:s,autoReadEnabled:e.autoReadEnabled,ttsConfig:e.ttsConfig},null,8,["message","autoReadEnabled","ttsConfig"]))),128))]))}};function sr(e){try{return JSON.stringify(e,null,2)}catch{return String(e)}}function ir(e){var t,n;return(e==null?void 0:e.message)||((t=e==null?void 0:e.responseJSON)==null?void 0:t.exception)||((n=e==null?void 0:e.responseJSON)==null?void 0:n.message)||(e==null?void 0:e.responseText)||String(e)}function Ra(e){return typeof e=="string"?e:e&&typeof e=="object"?e.error?`⚠️ ${e.error}`:e.answer||e.text||"":""}const $a={key:0,class:"rounded-lg bg-brand-50 px-4 py-3 text-xs text-black"},Pa={class:"whitespace-pre-wrap wrap-anywhere text-[11px] leading-relaxed text-black"},Ma={key:1,class:"mb-3 min-w-0 overflow-x-auto rounded-lg bg-brand-50 p-2 text-[11px]"},ka={class:"whitespace-pre-wrap wrap-anywhere text-[11px] leading-relaxed text-black"},Ia={__name:"DebugTab",props:{logs:{type:Array,required:!0},currentDebug:{type:Object,default:null}},setup(e){const t=new Set(["gemini_json_content","private_key","private_key_id","client_secret","client_id","aws_access_key","aws_secret_key","api_key","token","access_token","refresh_token","password","secret","authorization","embed_version_id","llm_version_id","entity_retriever","retriever","deploy_url","support_api_url","get_ticket_details_url"]);function n(i,r=0){if(r>10||i===null||i===void 0||typeof i=="string"||typeof i=="number"||typeof i=="boolean")return i;if(Array.isArray(i))return i.map(o=>n(o,r+1));if(typeof i=="object"){const o={};for(const[l,a]of Object.entries(i))t.has(l.toLowerCase())||(o[l]=n(a,r+1));return o}return i}function s(i){return sr(n(i))}return(i,r)=>(M(),B("div",null,[e.logs.length===0?(M(),B("p",$a,"No debug data yet.")):ye("",!0),(M(!0),B(he,null,vn(e.logs,(o,l)=>(M(),B("div",{key:l,class:"mb-3 min-w-0 overflow-x-auto rounded-lg bg-gray-100 p-2 text-[11px]"},[m("pre",Pa,we(s(o)),1)]))),128)),e.currentDebug?(M(),B("div",Ma,[m("pre",ka,we(s(e.currentDebug)),1)])):ye("",!0)]))}},Oa={class:"flex flex-col gap-4 sm:gap-5"},La={key:0,class:"chat-card motion-safe:animate-fade-rise rounded-lg px-4 py-3 text-xs text-slate-900"},Ba={__name:"SupportTab",props:{messages:{type:Array,required:!0},autoReadEnabled:{type:Boolean,default:!1},ttsConfig:{type:Object,required:!0}},setup(e){return(t,n)=>(M(),B("div",Oa,[e.messages.length===0?(M(),B("p",La,"Send a message to Support.")):ye("",!0),(M(!0),B(he,null,vn(e.messages,(s,i)=>(M(),Ze(nr,{key:i,message:s,autoReadEnabled:e.autoReadEnabled,ttsConfig:e.ttsConfig},null,8,["message","autoReadEnabled","ttsConfig"]))),128))]))}},Da={class:"flex flex-col gap-4"},Fa={class:"chat-card motion-safe:animate-fade-rise rounded-xl p-4"},Na={class:"flex items-start justify-between gap-4"},Va=["aria-pressed","title"],Ha={class:"chat-card motion-safe:animate-fade-rise rounded-xl p-4"},ja={class:"flex items-start justify-between gap-4"},Ua={class:"mt-2 text-[11px] text-slate-500"},qa={key:0,class:"mt-1 text-[11px] text-slate-500"},Ka={key:1,class:"mt-1 text-[11px] text-slate-500"},za=["aria-pressed","disabled"],Wa={key:0,class:"mt-3 rounded-md bg-amber-50 px-2.5 py-2 text-xs text-amber-700"},Ja={key:1,class:"mt-3 rounded-md bg-amber-50 px-2.5 py-2 text-xs text-amber-700"},Ga={class:"chat-card motion-safe:animate-fade-rise rounded-xl p-4"},Ya={class:"flex items-start justify-between gap-4"},Za=["aria-pressed","title"],Xa={__name:"SettingsTab",props:{autoReadEnabled:{type:Boolean,required:!0},ttsConfig:{type:Object,required:!0},settings:{type:Object,default:null},debugEnabled:{type:Boolean,default:!1}},emits:["toggleAutoRead","togglePollyPreference","toggleDebug"],setup(e){const t=e,n=de(()=>{var s,i;return(s=t.ttsConfig)!=null&&s.enableVoiceChat?(i=t.ttsConfig)!=null&&i.pollyAvailable?"Available":"Unavailable":"Voice disabled on server"});return(s,i)=>{var r,o,l,a,p,c,d,h,y,I,P,q,D,N,K;return M(),B("div",Da,[i[8]||(i[8]=m("div",{class:"chat-card motion-safe:animate-fade-rise rounded-xl p-4 text-slate-900"},[m("h3",{class:"text-sm font-semibold tracking-[0.01em]"},"Speech Settings"),m("p",{class:"mt-1 text-xs leading-relaxed text-slate-600"},"These controls apply only inside this chatbot box for the current browser session.")],-1)),m("div",Fa,[m("div",Na,[i[3]||(i[3]=m("div",null,[m("p",{class:"text-sm font-semibold text-slate-900"},"Auto Read Replies"),m("p",{class:"mt-1 text-xs text-slate-600"},"Automatically read bot replies aloud.")],-1)),m("button",{class:re(["group relative h-7 w-12 shrink-0 rounded-full border border-slate-200 transition-all duration-200",e.autoReadEnabled?"bg-emerald-500/95":"bg-slate-300"]),"aria-pressed":e.autoReadEnabled?"true":"false",title:e.autoReadEnabled?"Disable auto read":"Enable auto read",onClick:i[0]||(i[0]=w=>s.$emit("toggleAutoRead"))},[m("span",{class:re(["absolute top-0.5 h-5.5 w-5.5 rounded-full bg-white shadow-sm transition-all duration-200",e.autoReadEnabled?"left-[1.45rem]":"left-0.5"])},null,2)],10,Va)]),m("p",{class:re(["mt-3 text-[11px] font-medium",e.autoReadEnabled?"text-emerald-700":"text-slate-500"])},we(e.autoReadEnabled?"Auto read is active.":"Auto read is currently off."),3)]),m("div",Ha,[m("div",ja,[m("div",null,[i[4]||(i[4]=m("p",{class:"text-sm font-semibold text-slate-900"},"Use Amazon Polly",-1)),i[5]||(i[5]=m("p",{class:"mt-1 text-xs text-slate-600"},"Use Polly when available; otherwise browser speech is used automatically.",-1)),m("p",Ua,"Availability: "+we(n.value),1),(r=e.settings)!=null&&r.aws_region?(M(),B("p",qa,"Region: "+we(e.settings.aws_region),1)):ye("",!0),(o=e.ttsConfig)!=null&&o.voiceId?(M(),B("p",Ka,"Voice: "+we(e.ttsConfig.voiceId),1)):ye("",!0)]),m("button",{class:re(["relative h-7 w-12 shrink-0 rounded-full border border-slate-200 transition-all duration-200 disabled:cursor-not-allowed disabled:opacity-55",(l=e.ttsConfig)!=null&&l.usePolly&&((a=e.ttsConfig)!=null&&a.enableVoiceChat)&&((p=e.ttsConfig)!=null&&p.pollyAvailable)?"bg-emerald-500/95":"bg-slate-300"]),"aria-pressed":(c=e.ttsConfig)!=null&&c.usePolly&&((d=e.ttsConfig)!=null&&d.enableVoiceChat)&&((h=e.ttsConfig)!=null&&h.pollyAvailable)?"true":"false",disabled:!((y=e.ttsConfig)!=null&&y.pollyAvailable)||!((I=e.ttsConfig)!=null&&I.enableVoiceChat),onClick:i[1]||(i[1]=w=>s.$emit("togglePollyPreference"))},[m("span",{class:re(["absolute top-0.5 h-5.5 w-5.5 rounded-full bg-white shadow-sm transition-all duration-200",(P=e.ttsConfig)!=null&&P.usePolly&&((q=e.ttsConfig)!=null&&q.enableVoiceChat)&&((D=e.ttsConfig)!=null&&D.pollyAvailable)?"left-[1.45rem]":"left-0.5"])},null,2)],10,za)]),(N=e.ttsConfig)!=null&&N.enableVoiceChat?(K=e.ttsConfig)!=null&&K.pollyAvailable?ye("",!0):(M(),B("p",Ja,"Polly is not available for this site. Browser speech will be used.")):(M(),B("p",Wa,"Voice chat is disabled in ChangAI Settings."))]),m("div",Ga,[m("div",Ya,[m("div",null,[i[6]||(i[6]=m("p",{class:"text-sm font-semibold text-slate-900"},"Enable Debug Tab",-1)),i[7]||(i[7]=m("p",{class:"mt-1 text-xs text-slate-600"}," Show or hide the Debug tab inside this chatbot. ",-1)),m("p",{class:re(["mt-2 text-[11px] font-medium",e.debugEnabled?"text-emerald-700":"text-slate-500"])},we(e.debugEnabled?"Debug tab is active.":"Debug tab is currently off."),3)]),m("button",{type:"button",class:re(["relative h-7 w-12 shrink-0 rounded-full border border-slate-200 transition-all duration-200",e.debugEnabled?"bg-emerald-500/95":"bg-slate-300"]),"aria-pressed":e.debugEnabled?"true":"false",title:e.debugEnabled?"Disable debug tab":"Enable debug tab",onClick:i[2]||(i[2]=w=>s.$emit("toggleDebug"))},[m("span",{class:re(["absolute top-0.5 h-5.5 w-5.5 rounded-full bg-white shadow-sm transition-all duration-200",e.debugEnabled?"left-[1.45rem]":"left-0.5"])},null,2)],10,Za)])])])}}},Qa={key:0,class:"pointer-events-none absolute -top-14 left-0 right-0 z-20 flex justify-center px-2",role:"status","aria-live":"polite"},eu={__name:"StatusToast",props:{visible:{type:Boolean,required:!0},message:{type:String,default:""},type:{type:String,default:"info"},dismissible:{type:Boolean,default:!0}},emits:["close"],setup(e){const t=e,n=de(()=>t.type==="error"?"bg-red-50 text-red-700 ring-red-200":(t.type==="listening","bg-blue-50 text-blue-700 ring-blue-200")),s=de(()=>t.type==="error"?"bg-red-500":t.type==="listening"?"bg-blue-500 animate-pulse":"bg-blue-500");return(i,r)=>(M(),Ze(ll,{"enter-active-class":"transition duration-200 ease-out","enter-from-class":"translate-y-1 opacity-0","enter-to-class":"translate-y-0 opacity-100","leave-active-class":"transition duration-150 ease-in","leave-from-class":"translate-y-0 opacity-100","leave-to-class":"translate-y-1 opacity-0"},{default:ei(()=>[e.visible?(M(),B("div",Qa,[m("div",{class:re(["pointer-events-auto flex max-w-[92%] items-start gap-2 rounded-lg px-3 py-2 text-xs shadow-lg ring-1",n.value])},[m("span",{class:re(["mt-0.5 h-2 w-2 shrink-0 rounded-full",s.value])},null,2),m("span",null,we(e.message),1),e.dismissible?(M(),B("button",{key:0,type:"button",class:"ml-1 appearance-none border-0 text-current/80 transition hover:text-current focus:outline-none","aria-label":"Dismiss notification",onClick:r[0]||(r[0]=o=>i.$emit("close"))}," Γ— ")):ye("",!0)],2)])):ye("",!0)]),_:1}))}},tu={class:"relative w-full"},nu=["placeholder","disabled"],su=["title","aria-label","disabled"],iu={key:0,viewBox:"0 0 24 24",width:"16",height:"16",fill:"currentColor","aria-hidden":"true"},ru={key:1,viewBox:"0 0 24 24",width:"16",height:"16",fill:"none",stroke:"currentColor","stroke-width":"2","aria-hidden":"true"},ou={key:2,viewBox:"0 0 24 24",width:"16",height:"16",fill:"none",stroke:"currentColor","stroke-width":"2","aria-hidden":"true",class:"animate-spin"},lu=["title","aria-label","disabled"],au={key:0,viewBox:"0 0 24 24",width:"18",height:"18",fill:"none","aria-hidden":"true",class:"text-rose-600 motion-safe:animate-stop-button-pulse"},uu={key:1,viewBox:"0 0 24 24",width:"16",height:"16",fill:"currentColor","aria-hidden":"true"},cu={__name:"ChatForm",props:{placeholder:{type:String,default:"Message..."},disabled:{type:Boolean,default:!1},isAwaitingResponse:{type:Boolean,default:!1}},emits:["submit","cancel"],setup(e,{expose:t,emit:n}){const s=e,i=n,r=U(""),o=U(null),l=U(!1),a=U(!1),p=U(!1),c=U(!1),d=U(!1),h=U(""),y=U("info"),I=U("Voice input is unavailable in this browser/context.");let P=null,q=null;const D=U(""),N=U(!1),K=de(()=>p.value?"Requesting microphone permission...":a.value?l.value?"Stop voice input":"Start voice input":"Voice input is unavailable in this browser/context"),w=de(()=>s.isAwaitingResponse?"Stop response":"Send"),T=de(()=>s.isAwaitingResponse?!1:s.disabled||!r.value.trim()),z=de(()=>s.isAwaitingResponse?"bg-white border border-rose-100 shadow-[0_8px_20px_-12px_rgba(159,18,57,0.35)] hover:bg-rose-50":"bg-linear-to-br from-brand-500 to-brand-600 text-white shadow-[0_10px_24px_-16px_rgba(109,79,194,0.85)] hover:from-brand-600 hover:to-violet-700");function G(){return typeof window=="undefined"?null:window.SpeechRecognition||window.webkitSpeechRecognition||null}function oe(){var Ce;const Y=G(),k=typeof window!="undefined"?window.isSecureContext:!1,ge=typeof navigator!="undefined"&&!!((Ce=navigator.mediaDevices)!=null&&Ce.getUserMedia);a.value=!!(Y&&k&&ge),k?(!ge||!Y)&&(I.value="Voice input is not supported in this browser."):I.value="Voice input requires HTTPS (or localhost).",Y&&a.value&&(P=new Y,P.continuous=!0,P.interimResults=!0,P.lang=typeof navigator!="undefined"&&navigator.language||"en-US",P.onstart=()=>{l.value=!0,v("Listening... Tap mic to stop","listening",{persistent:!0,key:"listening"})},P.onend=()=>{l.value=!1,D.value==="listening"&&A(),N.value&&(N.value=!1,j())},P.onerror=le=>{if(l.value=!1,N.value=!1,(le==null?void 0:le.error)==="not-allowed"||(le==null?void 0:le.error)==="service-not-allowed"){v("Microphone permission denied. Please allow microphone access in browser settings.","error");return}if((le==null?void 0:le.error)==="audio-capture"){v("No microphone detected. Please connect a microphone and try again.","error");return}if((le==null?void 0:le.error)==="no-speech"){v("No speech detected. Try speaking a bit louder.","info");return}v("Voice input failed. Please try again.","error")},P.onresult=le=>{let Ie="";for(let He=le.resultIndex;Hege.stop()),c.value=!0,!0}catch(k){return(k==null?void 0:k.name)==="NotAllowedError"||(k==null?void 0:k.name)==="SecurityError"?v("Microphone permission denied. Please allow it and try again.","error"):(k==null?void 0:k.name)==="NotFoundError"?v("No microphone found on this device.","error"):v("Unable to access microphone. Please check browser permissions.","error"),!1}finally{p.value=!1,D.value==="requesting"&&A()}}async function ie(){var k;!await Z()||!P||(N.value=!1,(k=o.value)==null||k.focus(),P.start())}function v(Y,k="info",ge={}){const{duration:Ce=4200,persistent:le=!1,key:Ie=""}=ge;h.value=Y,y.value=k,D.value=Ie,d.value=!0,q&&clearTimeout(q),le||(q=setTimeout(()=>{d.value=!1,D.value=""},Ce))}function A(){d.value=!1,D.value="",q&&(clearTimeout(q),q=null)}function j(){if(s.isAwaitingResponse){i("cancel");return}const Y=r.value.trim();Y&&(l.value&&P&&P.stop(),i("submit",Y),r.value="")}return t({focus:()=>{var Y;return(Y=o.value)==null?void 0:Y.focus()}}),bn(()=>{oe()}),mn(()=>{P&&l.value&&(N.value=!1,P.stop()),A()}),(Y,k)=>(M(),B("div",tu,[m("form",{class:"group flex min-h-11 items-center gap-2 rounded-full border border-slate-200/90 bg-white/95 px-3 shadow-[0_12px_26px_-20px_rgba(15,23,42,0.7)] transition-all duration-250 focus-within:-translate-y-0.5 focus-within:border-brand-200 focus-within:shadow-[0_18px_30px_-20px_rgba(13,110,253,0.5)] focus-within:ring-2 focus-within:ring-brand-500/25",style:{"border-radius":"9999px"},autocomplete:"off",onSubmit:ke(j,["prevent"]),onClick:k[5]||(k[5]=ke(()=>{},["stop"])),onMousedown:k[6]||(k[6]=ke(()=>{},["stop"])),onKeydown:k[7]||(k[7]=ke(()=>{},["stop"])),onKeyup:k[8]||(k[8]=ke(()=>{},["stop"]))},[oo(m("input",{ref_key:"inputRef",ref:o,type:"text","onUpdate:modelValue":k[0]||(k[0]=ge=>r.value=ge),class:"h-11 w-full border-none bg-transparent text-sm font-medium text-slate-800 placeholder:text-slate-400 focus:outline-none disabled:cursor-not-allowed disabled:opacity-50",placeholder:e.disabled?"Waiting for response...":e.placeholder,disabled:e.disabled,required:"",onKeydown:k[1]||(k[1]=ke(()=>{},["stop"])),onKeyup:k[2]||(k[2]=ke(()=>{},["stop"])),onKeypress:k[3]||(k[3]=ke(()=>{},["stop"])),onInput:k[4]||(k[4]=ke(()=>{},["stop"]))},null,40,nu),[[Rl,r.value]]),m("button",{type:"button",class:re(["grid h-8 w-8 shrink-0 appearance-none place-items-center rounded-full border border-transparent text-slate-600 transition-all duration-200 hover:-translate-y-0.5 hover:border-slate-200 hover:bg-slate-100 hover:text-slate-900 focus:outline-none disabled:cursor-not-allowed disabled:opacity-40",l.value?"border-red-200 bg-red-100 text-red-600 shadow-[0_10px_20px_-18px_rgba(220,38,38,0.9)] hover:bg-red-100 hover:text-red-600":""]),style:{"border-radius":"9999px"},title:K.value,"aria-label":K.value,disabled:e.disabled||!a.value||p.value,onClick:V},[l.value&&!p.value?(M(),B("svg",iu,k[9]||(k[9]=[m("rect",{x:"6",y:"6",width:"12",height:"12",rx:"2"},null,-1)]))):p.value?(M(),B("svg",ou,k[11]||(k[11]=[m("circle",{cx:"12",cy:"12",r:"9",opacity:"0.3"},null,-1),m("path",{d:"M21 12a9 9 0 0 1-9 9"},null,-1)]))):(M(),B("svg",ru,k[10]||(k[10]=[m("path",{d:"M12 3a3 3 0 0 0-3 3v6a3 3 0 0 0 6 0V6a3 3 0 0 0-3-3z"},null,-1),m("path",{d:"M19 10v2a7 7 0 0 1-14 0v-2"},null,-1),m("path",{d:"M12 19v3"},null,-1)])))],10,su),m("button",{type:"submit",title:w.value,"aria-label":w.value,class:re(["grid h-8 w-8 shrink-0 appearance-none place-items-center rounded-full border-0 transition-all duration-200 hover:-translate-y-0.5 focus:outline-none disabled:cursor-not-allowed disabled:opacity-40",z.value]),style:{"border-radius":"9999px"},disabled:T.value},[e.isAwaitingResponse?(M(),B("svg",au,k[12]||(k[12]=[m("circle",{cx:"12",cy:"12",r:"8",stroke:"currentColor","stroke-width":"2.1",class:"opacity-95"},null,-1),m("rect",{x:"9",y:"9",width:"6",height:"6",rx:"1.35",fill:"currentColor"},null,-1)]))):(M(),B("svg",uu,k[13]||(k[13]=[m("path",{d:"M4 12l1.41 1.41L11 7.83V20h2V7.83l5.59 5.58L20 12l-8-8-8 8z"},null,-1)])))],10,lu)],32),fe(eu,{visible:d.value,message:h.value,type:y.value,dismissible:y.value!=="listening",onClose:A},null,8,["visible","message","type","dismissible"])]))}},fu={class:"relative overflow-hidden bg-linear-to-br from-brand-600 via-brand-500 to-violet-400"},du={class:"min-w-0"},pu={key:0,class:"border-t border-slate-200/80 bg-white/90 px-3 py-3 pb-[calc(12px+env(safe-area-inset-bottom))] backdrop-blur-sm sm:px-4 sm:py-4"},hu={__name:"ChatbotPopup",props:{isOpen:{type:Boolean,required:!0},activeTab:{type:String,required:!0},debugEnabled:{type:Boolean,default:!1},chatHistory:{type:Array,required:!0},debugLogs:{type:Array,required:!0},currentDebug:{type:Object,default:null},supportHistory:{type:Array,required:!0},autoReadEnabled:{type:Boolean,required:!0},ttsConfig:{type:Object,required:!0},activeTtsProvider:{type:String,required:!0},settings:{type:Object,default:null},isAwaitingResponse:{type:Boolean,default:!1}},emits:["close","submit","cancelResponse","update:activeTab","toggleAutoRead","togglePollyPreference","toggleDebug"],setup(e,{expose:t,emit:n}){const s=e,i=n,r=U(null),o=U(null),l=U(s.activeTab),a=U("default");function p(){if(a.value==="default"){a.value="half";return}if(a.value==="half"){a.value="full";return}a.value="default"}const c=de(()=>{const d="chat-shell fixed z-[9999] flex min-h-0 flex-col overflow-hidden border border-slate-200/80 shadow-[0_32px_80px_-44px_rgba(2,6,23,0.7),0_18px_40px_-24px_rgba(15,23,42,0.45)] transition-all duration-300 ease-out origin-bottom-right",h=s.isOpen?"pointer-events-auto opacity-100 translate-x-0 translate-y-0 scale-100 motion-safe:animate-surface-in":"pointer-events-none opacity-0 translate-x-1/5 translate-y-8 scale-95";return a.value==="full"?[d,h,"inset-0 h-screen w-screen max-h-screen max-w-screen rounded-none origin-center"]:a.value==="half"?[d,h,"bottom-[74px] right-5 h-[min(86vh,860px)] w-[min(50vw,860px)] rounded-2xl","max-[900px]:bottom-[78px] max-[900px]:right-3 max-[900px]:h-[min(86vh,760px)] max-[900px]:w-[min(70vw,760px)] max-[900px]:rounded-[14px]","max-[600px]:inset-0 max-[600px]:h-screen max-[600px]:w-screen max-[600px]:max-h-screen max-[600px]:max-w-screen max-[600px]:rounded-none max-[600px]:pb-[env(safe-area-inset-bottom)]"]:[d,h,"bottom-[74px] right-5 h-[min(560px,72vh)] w-[min(360px,calc(100vw-40px))] rounded-2xl","max-[900px]:bottom-[78px] max-[900px]:right-3 max-[900px]:h-[min(70vh,540px)] max-[900px]:w-[min(360px,calc(100vw-24px))] max-[900px]:rounded-[14px]","max-[600px]:inset-0 max-[600px]:h-screen max-[600px]:w-screen max-[600px]:max-h-screen max-[600px]:max-w-screen max-[600px]:rounded-none max-[600px]:pb-[env(safe-area-inset-bottom)]"]});return Pt(()=>s.activeTab,d=>{l.value=d}),Pt(()=>s.isOpen,d=>{d&&l.value!=="settings"&&Ye(()=>{var h;return(h=o.value)==null?void 0:h.focus()})}),Pt(l,d=>{i("update:activeTab",d)}),Pt(()=>s.debugEnabled,d=>{!d&&l.value==="debug"&&(l.value="chat")}),t({scrollToBottom(){Ye(()=>{const d=r.value;d&&d.scrollTo({top:d.scrollHeight,behavior:"smooth"})})}}),(d,h)=>(M(),B("div",{class:re(c.value),onKeydown:h[8]||(h[8]=ke(()=>{},["stop"])),onKeyup:h[9]||(h[9]=ke(()=>{},["stop"])),onKeypress:h[10]||(h[10]=ke(()=>{},["stop"]))},[h[12]||(h[12]=m("div",{class:"pointer-events-none absolute -right-14 -top-14 h-36 w-36 rounded-full bg-brand-500/15 blur-2xl"},null,-1)),h[13]||(h[13]=m("div",{class:"pointer-events-none absolute -bottom-14 -left-12 h-32 w-32 rounded-full bg-violet-400/15 blur-2xl"},null,-1)),m("div",fu,[h[11]||(h[11]=m("div",{class:"pointer-events-none absolute inset-0 opacity-45",style:{background:"linear-gradient(120deg, rgba(255,255,255,0.16) 0%, rgba(255,255,255,0.02) 52%, rgba(255,255,255,0.12) 100%)"}},null,-1)),fe(Xl,{windowMode:a.value,autoReadEnabled:e.autoReadEnabled,activeTtsProvider:e.activeTtsProvider,onClose:h[0]||(h[0]=y=>d.$emit("close")),onCycleResize:p,onToggleAutoRead:h[1]||(h[1]=y=>d.$emit("toggleAutoRead"))},null,8,["windowMode","autoReadEnabled","activeTtsProvider"]),fe(na,{modelValue:l.value,"onUpdate:modelValue":h[2]||(h[2]=y=>l.value=y),debugEnabled:e.debugEnabled},null,8,["modelValue","debugEnabled"])]),m("div",{class:"chat-scrollbar min-h-0 flex-1 overflow-x-hidden overflow-y-auto bg-slate-50/60 px-4 py-4 max-[900px]:px-3.5 max-[900px]:py-3.5 max-[600px]:px-3 max-[600px]:py-3",ref_key:"chatBodyRef",ref:r},[m("div",du,[l.value==="chat"?(M(),Ze(Aa,{key:0,messages:e.chatHistory,autoReadEnabled:e.autoReadEnabled,ttsConfig:e.ttsConfig},null,8,["messages","autoReadEnabled","ttsConfig"])):l.value==="debug"&&e.debugEnabled?(M(),Ze(Ia,{key:1,logs:e.debugLogs,currentDebug:e.currentDebug},null,8,["logs","currentDebug"])):l.value==="support"?(M(),Ze(Ba,{key:2,messages:e.supportHistory,autoReadEnabled:e.autoReadEnabled,ttsConfig:e.ttsConfig},null,8,["messages","autoReadEnabled","ttsConfig"])):l.value==="settings"?(M(),Ze(Xa,{key:3,autoReadEnabled:e.autoReadEnabled,ttsConfig:e.ttsConfig,settings:e.settings,debugEnabled:e.debugEnabled,onToggleAutoRead:h[3]||(h[3]=y=>d.$emit("toggleAutoRead")),onTogglePollyPreference:h[4]||(h[4]=y=>d.$emit("togglePollyPreference")),onToggleDebug:h[5]||(h[5]=y=>d.$emit("toggleDebug"))},null,8,["autoReadEnabled","ttsConfig","settings","debugEnabled"])):ye("",!0)])],512),l.value!=="settings"?(M(),B("div",pu,[fe(cu,{ref_key:"chatFormRef",ref:o,placeholder:l.value==="support"?"Message Support...":"Message...",disabled:l.value==="chat"&&e.isAwaitingResponse,isAwaitingResponse:l.value==="chat"&&e.isAwaitingResponse,onSubmit:h[6]||(h[6]=y=>d.$emit("submit",y)),onCancel:h[7]||(h[7]=y=>d.$emit("cancelResponse"))},null,8,["placeholder","disabled","isAwaitingResponse"])])):ye("",!0)],34))}},rr="changai_chat_id",or="changai_polly_enabled";function gu(){let e=sessionStorage.getItem(rr);return e||(e=`session_${Date.now()}_${crypto.randomUUID()}`,sessionStorage.setItem(rr,e)),e}function bu(){const e=localStorage.getItem(or);return e===null?!0:e==="true"}function mu(e){localStorage.setItem(or,String(!!e))}const vu={__name:"App",setup(e){const t=U(!1),n=U("chat"),s=U([]),i=U([]),r=U(!1),o=U([]),l=U(null),a=U("actual"),p=U(!0),c=U(null),d=U(!1),h=U(null),y=U({enableVoiceChat:!1,pollyAvailable:!1,usePolly:!0,voiceId:"Joanna"}),I=U("off"),P=U(null),q=de(()=>P.value!==null);function D(){if(!y.value.enableVoiceChat){I.value="off";return}I.value=y.value.usePolly?"polly":"browser"}function N(v){var j;const A=(j=v==null?void 0:v.detail)==null?void 0:j.provider;(A==="polly"||A==="browser"||A==="off")&&(I.value=A)}async function K(){var v,A,j,Y;if(!(d.value||c.value)){d.value=!0;try{c.value=await ua(a.value),y.value={enableVoiceChat:!!((v=c.value)!=null&&v.enable_voice_chat),pollyAvailable:!!((A=c.value)!=null&&A.polly_enabled),usePolly:!!((j=c.value)!=null&&j.polly_enabled)&&bu(),voiceId:((Y=c.value)==null?void 0:Y.polly_voice_id)||"Joanna"},D(),i.value.push({type:"settings",settings:c.value})}catch(k){const ge=ir(k);i.value.push({type:"settings",error:ge})}finally{d.value=!1}}}function w(){t.value=!t.value}function T(){var v;(v=l.value)==null||v.scrollToBottom()}function z(){p.value=!p.value}function G(){const v=!y.value.usePolly;y.value={...y.value,usePolly:v&&y.value.pollyAvailable},mu(y.value.usePolly),D()}async function oe(v){n.value==="support"?await ie(v):await V(v)}async function V(v){var Be;h.value=null,a.value==="actual"&&await K(),s.value.push({role:"user",text:v}),await Ye(),T();const A=ln({role:"model",text:"Thinking...",cancelable:!0,isStatus:!0,statusType:"thinking"});s.value.push(A),await Ye(),T();let j=!1;const Y=gu(),k=`${Y}_${Date.now()}`,ge=la(v,Y,a.value,k),Ce=`debug_${k}`;let le=Date.now();const Ie=[],He=ae=>{var wt;const ct=Date.now(),gs=((ct-le)/1e3).toFixed(2);le=ct;const ft=`${ae.message} (${gs}s)`;if(ae.message&&(Ie.push(ft),h.value=ft),!ae.done&&ae.message&&(A.text=ae.message,A.statusType="pipeline"),ae.done){A.cancelable=!1,A.isStatus=!1,A.statusType=null,ae.error?(A.text=`⚠️ ${ae.message||"Something failed"}`,A.isStatus=!1,A.statusType=null):(wt=ae.data)!=null&&wt.answer?(A.text=ae.data.answer,A.isStatus=!1,A.statusType=null):ae.message&&(A.text=ae.message),frappe.realtime.off(Ce),h.value=null;return}};frappe.realtime.on(Ce,He),P.value=()=>{j||(j=!0,ge.cancel(),frappe.realtime.off(Ce),A.isStatus=!1,A.statusType=null,A.text="Cancelled by user.",i.value.push({type:"cancelled",user:v,steps:[...Ie]}),h.value=null,A.cancelable=!1,P.value=null)};try{const ae=await ge.promise;if(j)return;A.cancelable=!1;const ct=((Be=Ra(ae==null?void 0:ae.Bot))==null?void 0:Be.trim())||"No response.";A.isStatus=!1,A.statusType=null,A.text=ct,i.value.push({type:"success",user:v,steps:[...Ie],final_response:ae}),h.value=null}catch(ae){if(j)return;frappe.realtime.off(Ce),A.cancelable=!1,A.isStatus=!1,A.statusType=null;const ct=ir(ae);h.value=null,i.value.push({type:"failed",user:v,steps:[...Ie],error:ct}),A.isStatus=!1,A.statusType=null,A.text="⚠️ Something went wrong. Please try again."}finally{frappe.realtime.off(Ce),j||(P.value=null)}await Ye(),T()}function Z(){var v;(v=P.value)==null||v.call(P)}async function ie(v){o.value.push({role:"user",text:v}),await Ye(),T();const A=ln({role:"model",text:"Sending to support...",isStatus:!0,statusType:"support"});o.value.push(A),await Ye(),T();try{const j=await aa(v,a.value);A.text=j?sr(j):"Support request sent successfully."}catch{A.text="⚠️ Failed to reach support. Please try again."}await Ye(),T()}return bn(()=>{typeof window!="undefined"&&window.addEventListener("changai-tts-provider",N),a.value==="actual"&&K()}),mn(()=>{typeof window!="undefined"&&window.removeEventListener("changai-tts-provider",N)}),(v,A)=>(M(),B(he,null,[fe(Nl,{isOpen:t.value,onToggle:w},null,8,["isOpen"]),fe(hu,{ref_key:"popupRef",ref:l,isOpen:t.value,activeTab:n.value,"onUpdate:activeTab":A[0]||(A[0]=j=>n.value=j),chatHistory:s.value,debugLogs:i.value,currentDebug:h.value,supportHistory:o.value,autoReadEnabled:p.value,ttsConfig:y.value,activeTtsProvider:I.value,settings:c.value,isAwaitingResponse:q.value,debugEnabled:r.value,onToggleDebug:A[1]||(A[1]=j=>r.value=!r.value),onClose:A[2]||(A[2]=j=>t.value=!1),onSubmit:oe,onCancelResponse:Z,onToggleAutoRead:z,onTogglePollyPreference:G},null,8,["isOpen","activeTab","chatHistory","debugLogs","currentDebug","supportHistory","autoReadEnabled","ttsConfig","activeTtsProvider","settings","isAwaitingResponse","debugEnabled"])],64))}};function xu(){const e=document.querySelector('link[href*="/assets/changai/dist/changai-chatbot.css"]');if(e!=null&&e.href)return e.href;const t=Array.from(document.scripts).find(n=>{var s;return(s=n.src)==null?void 0:s.includes("/assets/changai/dist/changai-chatbot.js")});return t!=null&&t.src?t.src.replace(/changai-chatbot\.js(\?.*)?$/,"changai-chatbot.css$1"):null}function yu(e){const t=xu();if(!t){const n=Array.from(document.querySelectorAll("style[data-vite-dev-id]"));return n.length&&n.forEach(s=>{const i=document.createElement("style");i.dataset.changaiShadowDevStyle="1",i.textContent=s.textContent||"",e.appendChild(i)}),Promise.resolve()}return e.querySelector('link[data-changai-shadow-style="1"]')?Promise.resolve():new Promise(n=>{const s=document.createElement("link");s.rel="stylesheet",s.href=t,s.dataset.changaiShadowStyle="1",s.onload=()=>n(),s.onerror=()=>n(),e.appendChild(s),setTimeout(n,1200)})}async function lr(){if(document.getElementById("changai-chatbot-host"))return;const e=document.createElement("div");e.id="changai-chatbot-host",document.body.appendChild(e);const t=e.attachShadow({mode:"open"});await yu(t);const n=document.createElement("div");n.id="changai-chatbot-root",t.appendChild(n),Il(vu).mount(n);function s(i){i.stopPropagation()}n.addEventListener("keydown",s),n.addEventListener("keyup",s),n.addEventListener("keypress",s)}document.readyState==="loading"?document.addEventListener("DOMContentLoaded",lr):lr()})(); diff --git a/frontend/src/components/ChatbotPopup.vue b/frontend/src/components/ChatbotPopup.vue index 51bb355..3bbd863 100644 --- a/frontend/src/components/ChatbotPopup.vue +++ b/frontend/src/components/ChatbotPopup.vue @@ -107,9 +107,9 @@ function cycleWindowMode() { } const popupClasses = computed(() => { - const base = 'chat-shell fixed z-[9999] flex min-h-0 flex-col overflow-hidden border border-slate-200/80 shadow-[0_32px_80px_-44px_rgba(2,6,23,0.7),0_18px_40px_-24px_rgba(15,23,42,0.45)] transition-all duration-300 ease-out origin-bottom-right motion-safe:animate-surface-in' + const base = 'chat-shell fixed z-[9999] flex min-h-0 flex-col overflow-hidden border border-slate-200/80 shadow-[0_32px_80px_-44px_rgba(2,6,23,0.7),0_18px_40px_-24px_rgba(15,23,42,0.45)] transition-all duration-300 ease-out origin-bottom-right' const state = props.isOpen - ? 'pointer-events-auto opacity-100 translate-x-0 translate-y-0 scale-100' + ? 'pointer-events-auto opacity-100 translate-x-0 translate-y-0 scale-100 motion-safe:animate-surface-in' : 'pointer-events-none opacity-0 translate-x-1/5 translate-y-8 scale-95' if (windowMode.value === 'full') {