SYMBOL INDEX (1058 symbols across 201 files) FILE: backend/app.py function set_sqlite_pragma (line 33) | def set_sqlite_pragma(dbapi_conn, connection_record): function create_app (line 52) | def create_app(): function _load_settings_to_config (line 192) | def _load_settings_to_config(app): function _compute_worktree_port (line 329) | def _compute_worktree_port(base_port: int) -> int: FILE: backend/config.py class Config (line 15) | class Config: class DevelopmentConfig (line 114) | class DevelopmentConfig(Config): class ProductionConfig (line 119) | class ProductionConfig(Config): function get_config (line 131) | def get_config(): FILE: backend/controllers/export_controller.py function export_pptx (line 27) | def export_pptx(project_id): function export_pdf (line 104) | def export_pdf(project_id): function export_images (line 178) | def export_images(project_id): function export_editable_pptx (line 246) | def export_editable_pptx(project_id): FILE: backend/controllers/file_controller.py function serve_file (line 15) | def serve_file(project_id, file_type, filename): function serve_user_template (line 52) | def serve_user_template(template_id, filename): function serve_global_material (line 85) | def serve_global_material(filename): function serve_mineru_file (line 117) | def serve_mineru_file(extract_id, filepath): FILE: backend/controllers/material_controller.py function _generate_image_caption (line 30) | def _generate_image_caption(filepath: str) -> str: function _build_material_query (line 102) | def _build_material_query(filter_project_id: str): function _get_materials_list (line 118) | def _get_materials_list(filter_project_id: str): function _handle_material_upload (line 133) | def _handle_material_upload(default_project_id: Optional[str] = None): function _resolve_target_project_id (line 166) | def _resolve_target_project_id(raw_project_id: Optional[str], allow_none... function _save_material_file (line 185) | def _save_material_file(file, target_project_id: Optional[str]): function generate_material_image (line 232) | def generate_material_image(project_id): function list_materials (line 362) | def list_materials(project_id): function upload_material (line 384) | def upload_material(project_id): function list_all_materials (line 399) | def list_all_materials(): function upload_material_global (line 428) | def upload_material_global(): function delete_material (line 443) | def delete_material(material_id): function associate_materials_to_project (line 474) | def associate_materials_to_project(): function download_materials_zip (line 526) | def download_materials_zip(): FILE: backend/controllers/page_controller.py function create_page (line 24) | def create_page(project_id): function delete_page (line 84) | def delete_page(project_id, page_id): function update_page (line 116) | def update_page(project_id, page_id): function update_page_outline (line 157) | def update_page_outline(project_id, page_id): function update_page_description (line 195) | def update_page_description(project_id, page_id): function generate_page_description (line 237) | def generate_page_description(project_id, page_id): function generate_page_image (line 325) | def generate_page_image(project_id, page_id): function edit_page_image (line 502) | def edit_page_image(project_id, page_id): function get_page_image_versions (line 676) | def get_page_image_versions(project_id, page_id): function set_current_image_version (line 698) | def set_current_image_version(project_id, page_id, version_id): function regenerate_renovation_page (line 742) | def regenerate_renovation_page(project_id, page_id): FILE: backend/controllers/project_controller.py function _get_project_reference_files_content (line 38) | def _get_project_reference_files_content(project_id: str) -> list: function _reconstruct_outline_from_pages (line 64) | def _reconstruct_outline_from_pages(pages: list) -> list: function _smart_merge_pages (line 123) | def _smart_merge_pages(project_id, pages_data): function list_projects (line 157) | def list_projects(): function create_project (line 197) | def create_project(): function get_project (line 267) | def get_project(project_id): function update_project (line 289) | def update_project(project_id): function delete_project (line 379) | def delete_project(project_id): function generate_outline (line 407) | def generate_outline(project_id): function generate_outline_stream (line 499) | def generate_outline_stream(project_id): function _sse_event (line 612) | def _sse_event(event: str, data: dict) -> str: function generate_from_description (line 618) | def generate_from_description(project_id): function generate_descriptions (line 735) | def generate_descriptions(project_id): function generate_descriptions_stream (line 828) | def generate_descriptions_stream(project_id): function generate_images (line 970) | def generate_images(project_id): function get_task_status (line 1090) | def get_task_status(project_id, task_id): function refine_outline (line 1108) | def refine_outline(project_id): function refine_descriptions (line 1205) | def refine_descriptions(project_id): function create_ppt_renovation_project (line 1329) | def create_ppt_renovation_project(): function extract_style (line 1565) | def extract_style(): FILE: backend/controllers/reference_file_controller.py function _allowed_file (line 25) | def _allowed_file(filename: str, allowed_extensions: set) -> bool: function _get_file_type (line 31) | def _get_file_type(filename: str) -> str: function _parse_file_async (line 38) | def _parse_file_async(file_id: str, file_path: str, filename: str, app): function upload_reference_file (line 107) | def upload_reference_file(): function get_reference_file (line 215) | def get_reference_file(file_id): function delete_reference_file (line 236) | def delete_reference_file(file_id): function list_project_reference_files (line 272) | def list_project_reference_files(project_id): function trigger_file_parse (line 310) | def trigger_file_parse(file_id): function associate_file_to_project (line 366) | def associate_file_to_project(file_id): function dissociate_file_from_project (line 409) | def dissociate_file_from_project(file_id): FILE: backend/controllers/settings_controller.py function temporary_settings_override (line 32) | def temporary_settings_override(settings_override: dict): function get_settings (line 151) | def get_settings(): function update_settings (line 168) | def update_settings(): function reset_settings (line 362) | def reset_settings(): function get_active_config (line 421) | def get_active_config(): function verify_api_key (line 436) | def verify_api_key(): function _sync_settings_to_config (line 537) | def _sync_settings_to_config(settings: Settings): function _get_test_image_path (line 691) | def _get_test_image_path() -> Path: function _get_baidu_credentials (line 698) | def _get_baidu_credentials(): function _create_file_parser (line 706) | def _create_file_parser(): function _test_baidu_ocr (line 761) | def _test_baidu_ocr(): function _test_text_model (line 778) | def _test_text_model(): function _test_caption_model (line 785) | def _test_caption_model(): function _test_baidu_inpaint (line 817) | def _test_baidu_inpaint(): function _test_image_model (line 845) | def _test_image_model(): function _test_mineru_pdf (line 864) | def _test_mineru_pdf(): function _run_test_async (line 922) | def _run_test_async(task_id: str, test_name: str, test_settings: dict, a... function run_settings_test (line 977) | def run_settings_test(test_name: str): function get_test_status (line 1082) | def get_test_status(task_id: str): FILE: backend/controllers/template_controller.py function upload_template (line 18) | def upload_template(project_id): function delete_template (line 64) | def delete_template(project_id): function get_system_templates (line 95) | def get_system_templates(): function upload_user_template (line 112) | def upload_user_template(): function list_user_templates (line 179) | def list_user_templates(): function delete_user_template (line 195) | def delete_user_template(template_id): FILE: backend/migrations/env.py function get_url (line 26) | def get_url() -> str: function run_migrations_offline (line 32) | def run_migrations_offline() -> None: function run_migrations_online (line 46) | def run_migrations_online() -> None: FILE: backend/migrations/versions/001_baseline_schema.py function upgrade (line 20) | def upgrade() -> None: function downgrade (line 127) | def downgrade() -> None: FILE: backend/migrations/versions/002_create_settings_table.py function upgrade (line 20) | def upgrade() -> None: function downgrade (line 48) | def downgrade() -> None: FILE: backend/migrations/versions/003_add_model_and_mineru_settings.py function _column_exists (line 20) | def _column_exists(table_name: str, column_name: str) -> bool: function upgrade (line 28) | def upgrade() -> None: function downgrade (line 51) | def downgrade() -> None: FILE: backend/migrations/versions/004_add_template_style_to_projects.py function upgrade (line 19) | def upgrade() -> None: function downgrade (line 28) | def downgrade() -> None: FILE: backend/migrations/versions/005_add_pdf_image_path.py function upgrade (line 22) | def upgrade() -> None: function downgrade (line 29) | def downgrade() -> None: FILE: backend/migrations/versions/006_add_export_settings_to_projects.py function upgrade (line 19) | def upgrade() -> None: function downgrade (line 32) | def downgrade() -> None: FILE: backend/migrations/versions/007_add_enable_reasoning_to_settings.py function _column_exists (line 20) | def _column_exists(table_name: str, column_name: str) -> bool: function upgrade (line 28) | def upgrade() -> None: function downgrade (line 42) | def downgrade() -> None: FILE: backend/migrations/versions/008_add_baidu_ocr_api_key_to_settings.py function _column_exists (line 20) | def _column_exists(table_name: str, column_name: str) -> bool: function upgrade (line 28) | def upgrade() -> None: function downgrade (line 41) | def downgrade() -> None: FILE: backend/migrations/versions/009_split_reasoning_config.py function _column_exists (line 20) | def _column_exists(table_name: str, column_name: str) -> bool: function upgrade (line 28) | def upgrade() -> None: function downgrade (line 64) | def downgrade() -> None: FILE: backend/migrations/versions/010_add_cached_image_path.py function upgrade (line 19) | def upgrade() -> None: function downgrade (line 23) | def downgrade() -> None: FILE: backend/migrations/versions/011_add_user_template_thumb.py function generate_user_template_thumbnails (line 18) | def generate_user_template_thumbnails(): function generate_page_thumbnails (line 104) | def generate_page_thumbnails(): function upgrade (line 193) | def upgrade(): function downgrade (line 204) | def downgrade(): FILE: backend/migrations/versions/012_add_export_allow_partial_to_projects.py function upgrade (line 19) | def upgrade(): function downgrade (line 26) | def downgrade(): FILE: backend/migrations/versions/013_add_lazyllm_source_fields.py function upgrade (line 19) | def upgrade(): function downgrade (line 26) | def downgrade(): FILE: backend/migrations/versions/014_add_per_model_provider_config.py function upgrade (line 19) | def upgrade(): function downgrade (line 28) | def downgrade(): FILE: backend/migrations/versions/015_rename_baidu_ocr_api_key.py function upgrade (line 18) | def upgrade(): function downgrade (line 23) | def downgrade(): FILE: backend/migrations/versions/38292967f3ca_add_output_language_to_settings_table.py function _column_exists (line 20) | def _column_exists(table_name: str, column_name: str) -> bool: function upgrade (line 28) | def upgrade() -> None: function downgrade (line 40) | def downgrade() -> None: FILE: backend/migrations/versions/64ecc9f34de0_add_description_generation_mode_to_.py function upgrade (line 19) | def upgrade() -> None: function downgrade (line 25) | def downgrade() -> None: FILE: backend/migrations/versions/7acf21d5e41d_make_settings_columns_nullable_for_env_.py function upgrade (line 19) | def upgrade() -> None: function downgrade (line 35) | def downgrade() -> None: FILE: backend/migrations/versions/88054bda1ece_add_outline_and_description_.py function upgrade (line 19) | def upgrade() -> None: function downgrade (line 26) | def downgrade() -> None: FILE: backend/migrations/versions/9439faddcdd5_add_description_extra_fields_to_settings.py function upgrade (line 19) | def upgrade() -> None: function downgrade (line 25) | def downgrade() -> None: FILE: backend/migrations/versions/9ad736fec43d_add_image_prompt_extra_fields_to_.py function upgrade (line 19) | def upgrade() -> None: function downgrade (line 25) | def downgrade() -> None: FILE: backend/migrations/versions/a912a64b7a86_add_mineru_token_to_settings_table.py function _column_exists (line 20) | def _column_exists(table_name: str, column_name: str) -> bool: function upgrade (line 28) | def upgrade() -> None: function downgrade (line 40) | def downgrade() -> None: FILE: backend/migrations/versions/ee22f1512027_add_image_aspect_ratio_to_project.py function upgrade (line 19) | def upgrade() -> None: function downgrade (line 23) | def downgrade() -> None: FILE: backend/models/material.py class Material (line 9) | class Material(db.Model): method to_dict (line 26) | def to_dict(self): method __repr__ (line 38) | def __repr__(self): FILE: backend/models/page.py class Page (line 11) | class Page(db.Model): method get_outline_content (line 35) | def get_outline_content(self): method set_outline_content (line 44) | def set_outline_content(self, data): method get_description_content (line 51) | def get_description_content(self): method set_description_content (line 60) | def set_description_content(self, data): method to_dict (line 67) | def to_dict(self, include_versions=False): method __repr__ (line 93) | def __repr__(self): FILE: backend/models/page_image_version.py class PageImageVersion (line 9) | class PageImageVersion(db.Model): method to_dict (line 25) | def to_dict(self): method __repr__ (line 44) | def __repr__(self): FILE: backend/models/project.py class Project (line 9) | class Project(db.Model): method to_dict (line 43) | def to_dict(self, include_pages=False): method __repr__ (line 80) | def __repr__(self): FILE: backend/models/reference_file.py class ReferenceFile (line 9) | class ReferenceFile(db.Model): method to_dict (line 31) | def to_dict(self, include_content=True, include_failed_count=False): method count_failed_image_captions (line 60) | def count_failed_image_captions(self) -> int: method __repr__ (line 79) | def __repr__(self): FILE: backend/models/settings.py class Settings (line 7) | class Settings(db.Model): method _val (line 63) | def _val(self, attr, defaults): method get_description_extra_fields (line 71) | def get_description_extra_fields(self): method get_image_prompt_extra_fields (line 82) | def get_image_prompt_extra_fields(self): method to_dict (line 93) | def to_dict(self): method _get_lazyllm_api_keys_info (line 139) | def _get_lazyllm_api_keys_info(self, raw=None): method get_lazyllm_api_keys_dict (line 150) | def get_lazyllm_api_keys_dict(self): method _get_config_defaults (line 160) | def _get_config_defaults(): method get_settings (line 198) | def get_settings(): method __repr__ (line 215) | def __repr__(self): FILE: backend/models/task.py class Task (line 10) | class Task(db.Model): method get_progress (line 28) | def get_progress(self): method set_progress (line 37) | def set_progress(self, data): method update_progress (line 44) | def update_progress(self, completed=None, failed=None): method to_dict (line 53) | def to_dict(self): method __repr__ (line 65) | def __repr__(self): FILE: backend/models/user_template.py class UserTemplate (line 9) | class UserTemplate(db.Model): method to_dict (line 23) | def to_dict(self): method __repr__ (line 40) | def __repr__(self): FILE: backend/services/ai_providers/__init__.py function get_provider_format (line 38) | def get_provider_format() -> str: function _resolve_setting (line 66) | def _resolve_setting(key: str, fallback: Optional[str] = None) -> Option... function _build_provider_config (line 97) | def _build_provider_config() -> Dict[str, Any]: function _get_model_type_provider_config (line 155) | def _get_model_type_provider_config(model_type: str) -> Dict[str, Any]: function get_image_caption_provider_config (line 213) | def get_image_caption_provider_config() -> Dict[str, Any]: function get_caption_provider (line 218) | def get_caption_provider(model: str = "gemini-3-flash-preview") -> TextP... function get_text_provider (line 241) | def get_text_provider(model: str = "gemini-3-flash-preview") -> TextProv... function get_image_provider (line 268) | def get_image_provider(model: str = "gemini-3-pro-image-preview") -> Ima... FILE: backend/services/ai_providers/genai_client.py function make_genai_client (line 11) | def make_genai_client( FILE: backend/services/ai_providers/image/baidu_inpainting_provider.py class BaiduInpaintingProvider (line 19) | class BaiduInpaintingProvider: method __init__ (line 31) | def __init__(self, api_key: str): method inpaint (line 52) | def inpaint( method inpaint_bboxes (line 187) | def inpaint_bboxes( function create_baidu_inpainting_provider (line 224) | def create_baidu_inpainting_provider( FILE: backend/services/ai_providers/image/base.py class ImageProvider (line 9) | class ImageProvider(ABC): method generate_image (line 13) | def generate_image( FILE: backend/services/ai_providers/image/gemini_inpainting_provider.py class GeminiInpaintingProvider (line 16) | class GeminiInpaintingProvider: method __init__ (line 33) | def __init__( method create_marked_image (line 62) | def create_marked_image(original_image: Image.Image, mask_image: Image... method inpaint_image (line 111) | def inpaint_image( FILE: backend/services/ai_providers/image/genai_provider.py class GenAIImageProvider (line 22) | class GenAIImageProvider(ImageProvider): method __init__ (line 25) | def __init__( method generate_image (line 48) | def generate_image( FILE: backend/services/ai_providers/image/lazyllm_provider.py function _calculate_image_dimensions (line 52) | def _calculate_image_dimensions( class LazyLLMImageProvider (line 134) | class LazyLLMImageProvider(ImageProvider): method __init__ (line 136) | def __init__(self, source: str = 'doubao', model: str = 'doubao-seedre... method generate_image (line 161) | def generate_image(self, prompt: str = None, FILE: backend/services/ai_providers/image/openai_provider.py class OpenAIImageProvider (line 26) | class OpenAIImageProvider(ImageProvider): method __init__ (line 38) | def __init__(self, api_key: str, api_base: str = None, model: str = "g... method _encode_image_to_base64 (line 56) | def _encode_image_to_base64(self, image: Image.Image) -> str: method _build_extra_body (line 73) | def _build_extra_body(self, aspect_ratio: str, resolution: str) -> dict: method generate_image (line 108) | def generate_image( FILE: backend/services/ai_providers/image/volcengine_inpainting_provider.py class VolcengineInpaintingProvider (line 18) | class VolcengineInpaintingProvider: method __init__ (line 25) | def __init__(self, access_key: str, secret_key: str, timeout: int = 60): method _encode_image_to_base64 (line 39) | def _encode_image_to_base64(self, image: Image.Image, is_mask: bool = ... method inpaint_image (line 76) | def inpaint_image( FILE: backend/services/ai_providers/lazyllm_env.py function collect_env_lazyllm_api_keys (line 11) | def collect_env_lazyllm_api_keys() -> str | None: function get_lazyllm_api_key (line 21) | def get_lazyllm_api_key(source: str, namespace: str = "BANANA") -> str: function ensure_lazyllm_namespace_key (line 33) | def ensure_lazyllm_namespace_key(source: str, namespace: str = "BANANA")... FILE: backend/services/ai_providers/ocr/baidu_accurate_ocr_provider.py class BaiduAccurateOCRProvider (line 49) | class BaiduAccurateOCRProvider: method __init__ (line 61) | def __init__(self, api_key: str): method recognize (line 82) | def recognize( method _location_to_bbox (line 290) | def _location_to_bbox(self, location: Dict[str, int]) -> List[int]: method get_full_text (line 310) | def get_full_text(self, result: Dict[str, Any], separator: str = '\n')... method get_text_with_positions (line 324) | def get_text_with_positions(self, result: Dict[str, Any]) -> List[Dict... function create_baidu_accurate_ocr_provider (line 344) | def create_baidu_accurate_ocr_provider( FILE: backend/services/ai_providers/ocr/baidu_table_ocr_provider.py class BaiduTableOCRProvider (line 19) | class BaiduTableOCRProvider: method __init__ (line 22) | def __init__(self, api_key: str): method recognize_table (line 43) | def recognize_table( method _location_to_bbox (line 204) | def _location_to_bbox(self, location: List[Dict[str, int]]) -> List[int]: method get_table_structure (line 222) | def get_table_structure(self, cells: List[Dict[str, Any]]) -> Dict[str... function create_baidu_table_ocr_provider (line 254) | def create_baidu_table_ocr_provider( FILE: backend/services/ai_providers/text/base.py function strip_think_tags (line 9) | def strip_think_tags(text: str) -> str: class TextProvider (line 16) | class TextProvider(ABC): method generate_text (line 20) | def generate_text(self, prompt: str, thinking_budget: int = 1000) -> str: method generate_text_stream (line 33) | def generate_text_stream(self, prompt: str, thinking_budget: int = 0) ... FILE: backend/services/ai_providers/text/genai_provider.py function _log_retry (line 20) | def _log_retry(retry_state): function _validate_response (line 28) | def _validate_response(response): class GenAITextProvider (line 41) | class GenAITextProvider(TextProvider): method __init__ (line 44) | def __init__( method generate_text (line 68) | def generate_text(self, prompt: str, thinking_budget: int = 0) -> str: method generate_with_image (line 97) | def generate_with_image(self, prompt: str, image_path: str, thinking_b... method generate_text_stream (line 129) | def generate_text_stream(self, prompt: str, thinking_budget: int = 0) ... FILE: backend/services/ai_providers/text/lazyllm_provider.py class LazyLLMTextProvider (line 16) | class LazyLLMTextProvider(TextProvider): method __init__ (line 18) | def __init__(self, source: str = 'deepseek', model: str = "deepseek-v3... method generate_text (line 46) | def generate_text(self, prompt, thinking_budget = 1000): method generate_with_image (line 50) | def generate_with_image(self, prompt: str, image_path: str, thinking_b... FILE: backend/services/ai_providers/text/openai_provider.py class OpenAITextProvider (line 14) | class OpenAITextProvider(TextProvider): method __init__ (line 17) | def __init__(self, api_key: str, api_base: str = None, model: str = "g... method generate_text (line 34) | def generate_text(self, prompt: str, thinking_budget: int = 0) -> str: method generate_text_stream (line 53) | def generate_text_stream(self, prompt: str, thinking_budget: int = 0) ... method generate_with_image (line 65) | def generate_with_image(self, prompt: str, image_path: str, thinking_b... FILE: backend/services/ai_service.py class ProjectContext (line 39) | class ProjectContext: method __init__ (line 42) | def __init__(self, project_or_dict, reference_files_content: Optional[... method to_dict (line 68) | def to_dict(self) -> Dict: class AIService (line 81) | class AIService: method __init__ (line 84) | def __init__(self, text_provider: TextProvider = None, image_provider:... method _get_text_thinking_budget (line 128) | def _get_text_thinking_budget(self) -> int: method _get_image_thinking_budget (line 137) | def _get_image_thinking_budget(self) -> int: method extract_image_urls_from_markdown (line 147) | def extract_image_urls_from_markdown(text: str) -> List[str]: method remove_markdown_images (line 174) | def remove_markdown_images(text: str) -> str: method generate_json (line 207) | def generate_json(self, prompt: str, thinking_budget: int = 1000) -> U... method generate_json_with_image (line 239) | def generate_json_with_image(self, prompt: str, image_path: str, think... method _convert_mineru_path_to_local (line 283) | def _convert_mineru_path_to_local(mineru_path: str) -> Optional[str]: method download_image_from_url (line 299) | def download_image_from_url(url: str) -> Optional[Image.Image]: method generate_outline (line 324) | def generate_outline(self, project_context: ProjectContext, language: ... method parse_markdown_outline (line 340) | def parse_markdown_outline(markdown: str) -> List[Dict]: method generate_outline_stream (line 382) | def generate_outline_stream(self, project_context: ProjectContext, lan... method parse_outline_text (line 465) | def parse_outline_text(self, project_context: ProjectContext, language... method flatten_outline (line 480) | def flatten_outline(self, outline: List[Dict]) -> List[Dict]: method _parse_extra_fields (line 499) | def _parse_extra_fields(text: str, field_names: list) -> tuple: method _get_extra_field_names (line 540) | def _get_extra_field_names() -> list: method generate_page_description (line 550) | def generate_page_description(self, project_context: ProjectContext, o... method generate_descriptions_stream (line 593) | def generate_descriptions_stream(self, project_context: ProjectContext, method _build_extra_field_pattern (line 716) | def _build_extra_field_pattern(field_names: list): method generate_outline_text (line 723) | def generate_outline_text(self, outline: List[Dict]) -> str: method generate_image_prompt (line 737) | def generate_image_prompt(self, outline: List[Dict], page: Dict, method generate_image (line 787) | def generate_image(self, prompt: str, ref_image_path: Optional[str] = ... method edit_image (line 883) | def edit_image(self, prompt: str, current_image_path: str, method parse_description_to_outline (line 909) | def parse_description_to_outline(self, project_context: ProjectContext... method parse_description_to_page_descriptions (line 923) | def parse_description_to_page_descriptions(self, project_context: Proj... method refine_outline (line 945) | def refine_outline(self, current_outline: List[Dict], user_requirement... method refine_descriptions (line 971) | def refine_descriptions(self, current_descriptions: List[Dict], user_r... method extract_page_content (line 1005) | def extract_page_content(self, markdown_text: str, language: str = 'zh... method _generate_text_from_image (line 1029) | def _generate_text_from_image(self, prompt: str, image_path: str) -> str: method generate_layout_caption (line 1051) | def generate_layout_caption(self, image_path: str) -> str: method extract_style_description (line 1055) | def extract_style_description(self, image_path: str) -> str: FILE: backend/services/ai_service_manager.py function _get_cached_text_provider (line 41) | def _get_cached_text_provider(model: str) -> TextProvider: function _get_cached_image_provider (line 60) | def _get_cached_image_provider(model: str) -> ImageProvider: function _get_cached_caption_provider (line 79) | def _get_cached_caption_provider(model: str) -> TextProvider: function get_ai_service (line 88) | def get_ai_service(force_new: bool = False) -> AIService: function clear_ai_service_cache (line 149) | def clear_ai_service_cache(): function get_provider_cache_info (line 175) | def get_provider_cache_info() -> dict: FILE: backend/services/export_service.py class ExportError (line 27) | class ExportError(Exception): method __init__ (line 34) | def __init__(self, message: str, error_type: str = 'unknown', details:... method _get_default_help_text (line 48) | def _get_default_help_text(self, error_type: str) -> str: method to_dict (line 60) | def to_dict(self) -> Dict[str, Any]: class ExportWarnings (line 71) | class ExportWarnings: method add_style_extraction_failed (line 92) | def add_style_extraction_failed(self, element_id: str, reason: str): method add_text_render_failed (line 99) | def add_text_render_failed(self, text: str, reason: str): method add_image_failed (line 106) | def add_image_failed(self, path: str, reason: str): method add_json_parse_failed (line 113) | def add_json_parse_failed(self, context: str, reason: str): method add_warning (line 120) | def add_warning(self, message: str): method has_warnings (line 124) | def has_warnings(self) -> bool: method to_summary (line 134) | def to_summary(self) -> List[str]: method to_dict (line 158) | def to_dict(self) -> Dict[str, Any]: function _get_page_size_inches (line 176) | def _get_page_size_inches(aspect_ratio: str = '16:9', base: float = 10.0... class ExportService (line 191) | class ExportService: method _build_style_extraction_error (line 200) | def _build_style_extraction_error( method create_pptx_from_images (line 235) | def create_pptx_from_images(image_paths: List[str], output_file: str =... method create_pdf_from_images (line 298) | def create_pdf_from_images(image_paths: List[str], output_file: str = ... method _add_pdf_metadata (line 346) | def _add_pdf_metadata(pdf_bytes: bytes) -> bytes: method create_pdf_from_images_pillow (line 391) | def create_pdf_from_images_pillow(image_paths: List[str], output_file:... method _add_mineru_text_to_slide (line 450) | def _add_mineru_text_to_slide(builder, slide, text_item: Dict[str, Any... method _add_table_cell_elements_to_slide (line 508) | def _add_table_cell_elements_to_slide( method _add_mineru_image_to_slide (line 570) | def _add_mineru_image_to_slide( method _collect_text_elements_for_extraction (line 687) | def _collect_text_elements_for_extraction( method _batch_extract_text_styles (line 724) | def _batch_extract_text_styles( method _collect_text_elements_for_batch_extraction (line 778) | def _collect_text_elements_for_batch_extraction( method _batch_extract_text_styles_with_full_image (line 821) | def _batch_extract_text_styles_with_full_image( method _batch_extract_text_styles_hybrid (line 919) | def _batch_extract_text_styles_hybrid( method create_editable_pptx_with_recursive_analysis (line 1146) | def create_editable_pptx_with_recursive_analysis( method _add_editable_elements_to_slide (line 1377) | def _add_editable_elements_to_slide( FILE: backend/services/file_parser_service.py function _get_ai_provider_format (line 23) | def _get_ai_provider_format(provider_format: str = None) -> str: class FileParserService (line 53) | class FileParserService: method __init__ (line 56) | def __init__(self, mineru_token: str, mineru_api_base: str = "https://... method _get_gemini_client (line 99) | def _get_gemini_client(self): method _get_openai_client (line 110) | def _get_openai_client(self): method _get_lazyllm_client (line 120) | def _get_lazyllm_client(self): method _can_generate_captions (line 135) | def _can_generate_captions(self) -> bool: method parse_file (line 145) | def parse_file(self, file_path: str, filename: str) -> tuple[Optional[... method _parse_text_file (line 219) | def _parse_text_file(self, file_path: str, filename: str) -> tuple[Opt... method _parse_spreadsheet_file (line 277) | def _parse_spreadsheet_file(self, file_path: str, filename: str) -> tu... method _get_upload_url (line 304) | def _get_upload_url(self, filename: str) -> tuple[Optional[str], Optio... method _upload_file (line 340) | def _upload_file(self, file_path: str, upload_url: str) -> Optional[str]: method _poll_result (line 362) | def _poll_result(self, batch_id: str, max_wait_time: int = 600) -> tup... method _download_markdown (line 412) | def _download_markdown(self, zip_url: str) -> tuple[Optional[str], Opt... method extract_header_footer_from_layout (line 488) | def extract_header_footer_from_layout(extract_id: str) -> str: method _replace_image_paths (line 534) | def _replace_image_paths(self, markdown_content: str, markdown_file_pa... method _enhance_markdown_with_captions (line 580) | def _enhance_markdown_with_captions(self, markdown_content: str) -> tu... method _generate_captions_parallel (line 639) | def _generate_captions_parallel(self, image_urls: List[str], max_worke... method _generate_single_caption (line 693) | def _generate_single_caption(self, image_url: str) -> str: FILE: backend/services/file_service.py function convert_image_to_rgb (line 14) | def convert_image_to_rgb(image: Image.Image) -> Image.Image: function resize_image_for_thumbnail (line 47) | def resize_image_for_thumbnail(image: Image.Image, max_width: int = 1920... class FileService (line 66) | class FileService: method __init__ (line 69) | def __init__(self, upload_folder: str): method _get_project_dir (line 74) | def _get_project_dir(self, project_id: str) -> Path: method _get_template_dir (line 80) | def _get_template_dir(self, project_id: str) -> Path: method _get_pages_dir (line 86) | def _get_pages_dir(self, project_id: str) -> Path: method _get_exports_dir (line 92) | def _get_exports_dir(self, project_id: str) -> Path: method _get_materials_dir (line 98) | def _get_materials_dir(self, project_id: str) -> Path: method save_template_image (line 104) | def save_template_image(self, file, project_id: str) -> str: method save_generated_image (line 128) | def save_generated_image(self, image: Image.Image, project_id: str, method get_cached_image_path (line 167) | def get_cached_image_path(self, project_id: str, page_id: str, version... method save_cached_image (line 185) | def save_cached_image(self, image: Image.Image, project_id: str, method save_material_image (line 221) | def save_material_image(self, image: Image.Image, project_id: Optional... method delete_page_image_version (line 257) | def delete_page_image_version(self, image_path: str) -> bool: method get_file_url (line 282) | def get_file_url(self, project_id: Optional[str], file_type: str, file... method get_absolute_path (line 299) | def get_absolute_path(self, relative_path: str) -> str: method delete_template (line 314) | def delete_template(self, project_id: str) -> bool: method delete_page_image (line 333) | def delete_page_image(self, project_id: str, page_id: str) -> bool: method delete_project_files (line 354) | def delete_project_files(self, project_id: str) -> bool: method file_exists (line 372) | def file_exists(self, relative_path: str) -> bool: method get_template_path (line 377) | def get_template_path(self, project_id: str) -> Optional[str]: method _get_user_templates_dir (line 412) | def _get_user_templates_dir(self) -> Path: method save_user_template (line 418) | def save_user_template(self, file, template_id: str) -> str: method delete_user_template (line 444) | def delete_user_template(self, template_id: str) -> bool: method save_user_template_thumbnail (line 463) | def save_user_template_thumbnail(self, template_id: str, original_path... FILE: backend/services/image_editability/coordinate_mapper.py class CoordinateMapper (line 8) | class CoordinateMapper: method local_to_global (line 12) | def local_to_global( method global_to_local (line 43) | def global_to_local( FILE: backend/services/image_editability/data_models.py class BBox (line 9) | class BBox: method width (line 17) | def width(self) -> float: method height (line 21) | def height(self) -> float: method area (line 25) | def area(self) -> float: method to_tuple (line 28) | def to_tuple(self) -> Tuple[float, float, float, float]: method to_dict (line 32) | def to_dict(self) -> Dict[str, float]: method scale (line 41) | def scale(self, scale_x: float, scale_y: float) -> 'BBox': method translate (line 50) | def translate(self, offset_x: float, offset_y: float) -> 'BBox': class EditableElement (line 61) | class EditableElement: method to_dict (line 79) | def to_dict(self) -> Dict[str, Any]: class EditableImage (line 96) | class EditableImage: method to_dict (line 118) | def to_dict(self) -> Dict[str, Any]: FILE: backend/services/image_editability/extractors.py class ExtractionContext (line 24) | class ExtractionContext: method __init__ (line 27) | def __init__( class ExtractionResult (line 41) | class ExtractionResult: method __init__ (line 44) | def __init__( method has_error (line 61) | def has_error(self) -> bool: class ElementExtractor (line 66) | class ElementExtractor(ABC): method extract (line 79) | def extract( method supports_type (line 106) | def supports_type(self, element_type: Optional[str]) -> bool: class MinerUElementExtractor (line 119) | class MinerUElementExtractor(ElementExtractor): method __init__ (line 127) | def __init__(self, parser_service, upload_folder: Path): method supports_type (line 138) | def supports_type(self, element_type: Optional[str]) -> bool: method extract (line 142) | def extract( method _find_cache (line 187) | def _find_cache(self, image_path: str) -> Optional[str]: method _parse_image (line 208) | def _parse_image(self, image_path: str, depth: int) -> Tuple[Optional[... method _extract_from_result (line 244) | def _extract_from_result( class BaiduOCRElementExtractor (line 451) | class BaiduOCRElementExtractor(ElementExtractor): method __init__ (line 459) | def __init__(self, baidu_table_ocr_provider): method supports_type (line 468) | def supports_type(self, element_type: Optional[str]) -> bool: method extract (line 472) | def extract( method _shrink_cells_to_avoid_overlap (line 547) | def _shrink_cells_to_avoid_overlap( class BaiduAccurateOCRElementExtractor (line 655) | class BaiduAccurateOCRElementExtractor(ElementExtractor): method __init__ (line 663) | def __init__(self, baidu_accurate_ocr_provider): method supports_type (line 672) | def supports_type(self, element_type: Optional[str]) -> bool: method extract (line 676) | def extract( class ExtractorRegistry (line 773) | class ExtractorRegistry: method __init__ (line 797) | def __init__(self): method register (line 802) | def register(self, element_type: str, extractor: ElementExtractor) -> ... method register_types (line 817) | def register_types(self, element_types: List[str], extractor: ElementE... method register_default (line 832) | def register_default(self, extractor: ElementExtractor) -> 'ExtractorR... method get_extractor (line 846) | def get_extractor(self, element_type: Optional[str]) -> Optional[Eleme... method get_all_extractors (line 866) | def get_all_extractors(self) -> List[ElementExtractor]: method create_default (line 879) | def create_default( FILE: backend/services/image_editability/factories.py class ExtractorFactory (line 28) | class ExtractorFactory: method create_default_extractors (line 32) | def create_default_extractors( method create_extractor_registry (line 75) | def create_extractor_registry( method create_baidu_accurate_ocr_extractor (line 134) | def create_baidu_accurate_ocr_extractor( method create_hybrid_extractor (line 160) | def create_hybrid_extractor( method create_hybrid_extractor_registry (line 212) | def create_hybrid_extractor_registry( class InpaintProviderFactory (line 286) | class InpaintProviderFactory: method create_default_provider (line 290) | def create_default_provider(inpainting_service: Optional[Any] = None) ... method create_generative_edit_provider (line 308) | def create_generative_edit_provider( method create_inpaint_registry (line 338) | def create_inpaint_registry( method create_baidu_inpaint_provider (line 390) | def create_baidu_inpaint_provider() -> Optional[BaiduInpaintProvider]: method create_hybrid_inpaint_provider (line 413) | def create_hybrid_inpaint_provider( class ServiceConfig (line 457) | class ServiceConfig: method __init__ (line 460) | def __init__( method from_defaults (line 488) | def from_defaults( class TextAttributeExtractorFactory (line 675) | class TextAttributeExtractorFactory: method create_caption_model_extractor (line 679) | def create_caption_model_extractor( method create_text_attribute_registry (line 707) | def create_text_attribute_registry( FILE: backend/services/image_editability/helpers.py function collect_bboxes_from_elements (line 16) | def collect_bboxes_from_elements(elements: List[EditableElement]) -> Lis... function crop_element_from_image (line 34) | def crop_element_from_image( function should_recurse_into_element (line 60) | def should_recurse_into_element( FILE: backend/services/image_editability/hybrid_extractor.py class BBoxUtils (line 27) | class BBoxUtils: method is_contained (line 31) | def is_contained(inner_bbox: List[float], outer_bbox: List[float], thr... method has_intersection (line 71) | def has_intersection(bbox1: List[float], bbox2: List[float], min_overl... method get_intersection_ratio (line 115) | def get_intersection_ratio(bbox1: List[float], bbox2: List[float]) -> ... class HybridElementExtractor (line 151) | class HybridElementExtractor(ElementExtractor): method __init__ (line 170) | def __init__( method supports_type (line 191) | def supports_type(self, element_type: Optional[str]) -> bool: method extract (line 195) | def extract( method _merge_results (line 306) | def _merge_results( function create_hybrid_extractor (line 432) | def create_hybrid_extractor( FILE: backend/services/image_editability/inpaint_providers.py class InpaintProvider (line 24) | class InpaintProvider(ABC): method inpaint_regions (line 36) | def inpaint_regions( class DefaultInpaintProvider (line 58) | class DefaultInpaintProvider(InpaintProvider): method __init__ (line 65) | def __init__(self, inpainting_service): method inpaint_regions (line 74) | def inpaint_regions( class GenerativeEditInpaintProvider (line 116) | class GenerativeEditInpaintProvider(InpaintProvider): method __init__ (line 135) | def __init__(self, ai_service, aspect_ratio: str = "16:9", resolution:... method inpaint_regions (line 148) | def inpaint_regions( class BaiduInpaintProvider (line 211) | class BaiduInpaintProvider(InpaintProvider): method __init__ (line 225) | def __init__(self, baidu_inpainting_provider): method inpaint_regions (line 234) | def inpaint_regions( class HybridInpaintProvider (line 273) | class HybridInpaintProvider(InpaintProvider): method __init__ (line 290) | def __init__( method inpaint_regions (line 308) | def inpaint_regions( method _enhance_image_quality (line 370) | def _enhance_image_quality( class InpaintProviderRegistry (line 456) | class InpaintProviderRegistry: method __init__ (line 481) | def __init__(self): method register (line 486) | def register(self, element_type: str, provider: InpaintProvider) -> 'I... method register_types (line 501) | def register_types(self, element_types: List[str], provider: InpaintPr... method register_default (line 516) | def register_default(self, provider: InpaintProvider) -> 'InpaintProvi... method get_provider (line 530) | def get_provider(self, element_type: Optional[str]) -> Optional[Inpain... method get_all_providers (line 550) | def get_all_providers(self) -> List[InpaintProvider]: method create_default (line 563) | def create_default( FILE: backend/services/image_editability/service.py class ImageEditabilityService (line 25) | class ImageEditabilityService: method __init__ (line 47) | def __init__(self, config: ServiceConfig): method make_image_editable (line 71) | def make_image_editable( method _extract_elements (line 186) | def _extract_elements( method _select_extractor (line 205) | def _select_extractor(self, element_type: Optional[str]) -> ElementExt... method _convert_to_editable_elements (line 212) | def _convert_to_editable_elements( method _generate_clean_background (line 298) | def _generate_clean_background( method _process_children (line 391) | def _process_children( FILE: backend/services/image_editability/text_attribute_extractors.py class ColoredSegment (line 21) | class ColoredSegment: method to_dict (line 31) | def to_dict(self) -> Dict[str, Any]: method from_dict (line 42) | def from_dict(cls, data: Dict[str, Any]) -> 'ColoredSegment': class TextStyleResult (line 66) | class TextStyleResult: method to_dict (line 101) | def to_dict(self) -> Dict[str, Any]: method from_dict (line 111) | def from_dict(cls, data: Dict[str, Any]) -> 'TextStyleResult': method get_hex_color (line 123) | def get_hex_color(self) -> str: method get_full_text (line 128) | def get_full_text(self) -> str: method has_multi_color (line 134) | def has_multi_color(self) -> bool: class TextAttributeExtractor (line 142) | class TextAttributeExtractor(ABC): method extract (line 152) | def extract( method supports_batch (line 172) | def supports_batch(self) -> bool: method extract_batch (line 181) | def extract_batch( class CaptionModelTextAttributeExtractor (line 211) | class CaptionModelTextAttributeExtractor(TextAttributeExtractor): method build_prompt (line 219) | def build_prompt(text_content: Optional[str] = None) -> str: method __init__ (line 230) | def __init__(self, ai_service, prompt_template: Optional[str] = None): method supports_batch (line 241) | def supports_batch(self) -> bool: method extract (line 245) | def extract( method _call_vision_model (line 296) | def _call_vision_model(self, image: Image.Image, prompt: str, thinking... method _hex_to_rgb (line 336) | def _hex_to_rgb(hex_color: str) -> Tuple[int, int, int]: method _parse_result (line 364) | def _parse_result(self, result_json: Dict[str, Any]) -> TextStyleResult: method extract_batch_with_full_image (line 428) | def extract_batch_with_full_image( method _parse_batch_result (line 524) | def _parse_batch_result( class TextAttributeExtractorRegistry (line 585) | class TextAttributeExtractorRegistry: method __init__ (line 608) | def __init__(self): method register (line 613) | def register(self, element_type: str, extractor: TextAttributeExtracto... method register_types (line 628) | def register_types(self, element_types: List[str], extractor: TextAttr... method register_default (line 643) | def register_default(self, extractor: TextAttributeExtractor) -> 'Text... method get_extractor (line 657) | def get_extractor(self, element_type: Optional[str]) -> Optional[TextA... method get_all_extractors (line 677) | def get_all_extractors(self) -> List[TextAttributeExtractor]: method create_default (line 690) | def create_default( FILE: backend/services/inpainting_service.py class InpaintingService (line 26) | class InpaintingService: method __init__ (line 40) | def __init__(self, provider=None, provider_type: str = "volcengine"): method remove_regions_by_bboxes (line 87) | def remove_regions_by_bboxes( method regenerate_background (line 174) | def regenerate_background( method create_mask_preview (line 222) | def create_mask_preview( method create_mask_image (line 245) | def create_mask_image( function get_inpainting_service (line 269) | def get_inpainting_service(provider_type: str = None) -> InpaintingService: function remove_regions (line 296) | def remove_regions( function regenerate_background (line 316) | def regenerate_background( FILE: backend/services/pdf_service.py function split_pdf_to_pages (line 12) | def split_pdf_to_pages(pdf_path: str, output_dir: str) -> List[str]: FILE: backend/services/prompts.py function _build_prompt (line 83) | def _build_prompt(prompt_text: str, reference_files_content=None, *, tag... function _get_original_input (line 92) | def _get_original_input(project_context: 'ProjectContext') -> str: function _get_original_input_labeled (line 103) | def _get_original_input_labeled(project_context: 'ProjectContext') -> str: function _get_previous_requirements_text (line 117) | def _get_previous_requirements_text(previous_requirements: Optional[List... function _format_extra_field_instructions (line 125) | def _format_extra_field_instructions(extra_fields: list | None) -> str: function _format_reference_files_xml (line 133) | def _format_reference_files_xml(reference_files_content: Optional[List[D... function _format_requirements (line 151) | def _format_requirements(requirements: str, context: str = "outline") ->... function get_default_output_language (line 180) | def get_default_output_language() -> str: function get_language_instruction (line 186) | def get_language_instruction(language: str = None) -> str: function get_ppt_language_instruction (line 193) | def get_ppt_language_instruction(language: str = None) -> str: function get_outline_generation_prompt (line 205) | def get_outline_generation_prompt(project_context: 'ProjectContext', lan... function get_outline_generation_prompt_markdown (line 227) | def get_outline_generation_prompt_markdown(project_context: 'ProjectCont... function get_outline_parsing_prompt (line 277) | def get_outline_parsing_prompt(project_context: 'ProjectContext', langua... function get_outline_parsing_prompt_markdown (line 311) | def get_outline_parsing_prompt_markdown(project_context: 'ProjectContext... function get_description_to_outline_prompt (line 338) | def get_description_to_outline_prompt(project_context: 'ProjectContext',... function get_description_to_outline_prompt_markdown (line 373) | def get_description_to_outline_prompt_markdown(project_context: 'Project... function get_outline_refinement_prompt (line 400) | def get_outline_refinement_prompt(current_outline: List[Dict], user_requ... function get_page_description_prompt (line 465) | def get_page_description_prompt(project_context: 'ProjectContext', outli... function get_all_descriptions_stream_prompt (line 509) | def get_all_descriptions_stream_prompt(project_context: 'ProjectContext', function get_description_split_prompt (line 568) | def get_description_split_prompt(project_context: 'ProjectContext', function get_descriptions_refinement_prompt (line 624) | def get_descriptions_refinement_prompt(current_descriptions: List[Dict],... function get_image_generation_prompt (line 703) | def get_image_generation_prompt(page_desc: str, outline_text: str, function get_image_edit_prompt (line 751) | def get_image_edit_prompt(edit_instruction: str, original_description: s... function get_clean_background_prompt (line 777) | def get_clean_background_prompt() -> str: function get_quality_enhancement_prompt (line 795) | def get_quality_enhancement_prompt(inpainted_regions: list = None) -> str: function get_text_attribute_extraction_prompt (line 846) | def get_text_attribute_extraction_prompt(content_hint: str = "") -> str: function get_batch_text_attribute_extraction_prompt (line 890) | def get_batch_text_attribute_extraction_prompt(text_elements_json: str) ... function get_ppt_page_content_extraction_prompt (line 949) | def get_ppt_page_content_extraction_prompt(markdown_text: str, language:... function get_layout_caption_prompt (line 991) | def get_layout_caption_prompt() -> str: function get_style_extraction_prompt (line 1016) | def get_style_extraction_prompt() -> str: FILE: backend/services/task_manager.py function _get_image_prompt_field_names (line 18) | def _get_image_prompt_field_names() -> set | None: function _append_extra_fields (line 30) | def _append_extra_fields(desc_text: str, desc_content: dict) -> str: class TaskManager (line 47) | class TaskManager: method __init__ (line 50) | def __init__(self, max_workers: int = 4): method submit_task (line 56) | def submit_task(self, task_id: str, func: Callable, *args, **kwargs): method _task_done_callback (line 66) | def _task_done_callback(self, task_id: str, future): method _cleanup_task (line 78) | def _cleanup_task(self, task_id: str): method is_task_active (line 84) | def is_task_active(self, task_id: str) -> bool: method shutdown (line 89) | def shutdown(self): function save_image_with_version (line 98) | def save_image_with_version(image, project_id: str, page_id: str, file_s... function generate_descriptions_task (line 167) | def generate_descriptions_task(task_id: str, project_id: str, ai_service, function generate_images_task (line 323) | def generate_images_task(task_id: str, project_id: str, ai_service, file... function generate_single_page_image_task (line 550) | def generate_single_page_image_task(task_id: str, project_id: str, page_... function edit_page_image_task (line 679) | def edit_page_image_task(task_id: str, project_id: str, page_id: str, function generate_material_image_task (line 786) | def generate_material_image_task(task_id: str, project_id: str, prompt: ... function process_ppt_renovation_task (line 883) | def process_ppt_renovation_task(task_id: str, project_id: str, ai_service, function export_editable_pptx_with_recursive_analysis_task (line 1130) | def export_editable_pptx_with_recursive_analysis_task( FILE: backend/tests/conftest.py function app (line 26) | def app(): function client (line 65) | def client(app): function db_session (line 80) | def db_session(app): function sample_project (line 91) | def sample_project(client): function mock_ai_service (line 104) | def mock_ai_service(): function temp_upload_dir (line 139) | def temp_upload_dir(): function sample_image_file (line 146) | def sample_image_file(): function assert_success_response (line 164) | def assert_success_response(response, status_code=200): function assert_error_response (line 173) | def assert_error_response(response, expected_status=None): FILE: backend/tests/integration/test_api_full_flow.py function wait_for_project_status (line 38) | def wait_for_project_status(project_id: str, expected_status: str, timeo... function wait_for_task_completion (line 90) | def wait_for_task_completion(project_id: str, task_id: str, timeout: int... function project_id (line 146) | def project_id(): class TestAPIFullFlow (line 164) | class TestAPIFullFlow: method test_api_full_flow_create_to_export (line 174) | def test_api_full_flow_create_to_export(self, project_id): method test_quick_api_flow_no_ai (line 350) | def test_quick_api_flow_no_ai(self): FILE: backend/tests/integration/test_full_workflow.py class TestFullWorkflow (line 12) | class TestFullWorkflow: method test_create_project_and_get_details (line 15) | def test_create_project_and_get_details(self, client): method test_template_upload_workflow (line 33) | def test_template_upload_workflow(self, client, sample_image_file): method test_project_lifecycle (line 54) | def test_project_lifecycle(self, client): class TestAPIErrorHandling (line 80) | class TestAPIErrorHandling: method test_invalid_json_body (line 83) | def test_invalid_json_body(self, client): method test_missing_required_fields (line 93) | def test_missing_required_fields(self, client): method test_method_not_allowed (line 99) | def test_method_not_allowed(self, client): class TestConcurrentRequests (line 107) | class TestConcurrentRequests: method test_multiple_project_creation (line 110) | def test_multiple_project_creation(self, client): FILE: backend/tests/unit/test_ai_mock.py class TestAIMock (line 11) | class TestAIMock: method test_ai_service_is_mocked (line 14) | def test_ai_service_is_mocked(self, mock_ai_service): method test_description_generation_mocked (line 26) | def test_description_generation_mocked(self, mock_ai_service): method test_image_generation_mocked (line 35) | def test_image_generation_mocked(self, mock_ai_service): method test_no_real_api_calls (line 43) | def test_no_real_api_calls(self, mock_ai_service): class TestEnvironmentFlags (line 55) | class TestEnvironmentFlags: method test_testing_flag_is_set (line 58) | def test_testing_flag_is_set(self): method test_mock_ai_flag_is_set (line 63) | def test_mock_ai_flag_is_set(self): FILE: backend/tests/unit/test_api_health.py class TestHealthEndpoint (line 8) | class TestHealthEndpoint: method test_health_check_returns_ok (line 11) | def test_health_check_returns_ok(self, client): method test_health_check_response_format (line 20) | def test_health_check_response_format(self, client): FILE: backend/tests/unit/test_api_material.py function _create_test_image (line 11) | def _create_test_image(): class TestMaterialUpload (line 21) | class TestMaterialUpload: method test_upload_material_without_caption (line 24) | def test_upload_material_without_caption(self, client): method test_upload_material_with_caption (line 37) | def test_upload_material_with_caption(self, mock_caption, client): method test_upload_material_caption_failure_still_succeeds (line 52) | def test_upload_material_caption_failure_still_succeeds(self, mock_cap... method test_upload_material_caption_false_param (line 66) | def test_upload_material_caption_false_param(self, mock_caption, client): method test_upload_material_invalid_file_type (line 78) | def test_upload_material_invalid_file_type(self, client): method test_upload_material_no_file (line 87) | def test_upload_material_no_file(self, client): class TestGenerateImageCaption (line 97) | class TestGenerateImageCaption: method test_caption_returns_empty_on_missing_gemini_key (line 100) | def test_caption_returns_empty_on_missing_gemini_key(self, app): method test_caption_returns_empty_on_missing_openai_key (line 119) | def test_caption_returns_empty_on_missing_openai_key(self, app): method test_caption_returns_empty_on_invalid_file (line 137) | def test_caption_returns_empty_on_invalid_file(self, app): method test_caption_gemini_success (line 147) | def test_caption_gemini_success(self, mock_client_class, app): FILE: backend/tests/unit/test_api_project.py class TestProjectCreate (line 9) | class TestProjectCreate: method test_create_project_idea_mode (line 12) | def test_create_project_idea_mode(self, client): method test_create_project_outline_mode (line 23) | def test_create_project_outline_mode(self, client): method test_create_project_missing_type (line 36) | def test_create_project_missing_type(self, client): method test_create_project_invalid_type (line 45) | def test_create_project_invalid_type(self, client): class TestProjectGet (line 55) | class TestProjectGet: method test_get_project_success (line 58) | def test_get_project_success(self, client, sample_project): method test_get_project_not_found (line 69) | def test_get_project_not_found(self, client): method test_get_project_invalid_id_format (line 75) | def test_get_project_invalid_id_format(self, client): class TestProjectUpdate (line 83) | class TestProjectUpdate: method test_update_project_status (line 86) | def test_update_project_status(self, client, sample_project): class TestProjectDelete (line 102) | class TestProjectDelete: method test_delete_project_success (line 105) | def test_delete_project_success(self, client, sample_project): method test_delete_project_not_found (line 119) | def test_delete_project_not_found(self, client): FILE: backend/tests/unit/test_api_settings_provider.py function _build_settings (line 13) | def _build_settings(**overrides): function test_update_settings_accepts_lazyllm_provider (line 30) | def test_update_settings_accepts_lazyllm_provider(): function test_verify_uses_configured_text_model (line 48) | def test_verify_uses_configured_text_model(): FILE: backend/tests/unit/test_editable_pptx_style_extraction.py class FailingExtractor (line 7) | class FailingExtractor: method extract_batch_with_full_image (line 8) | def extract_batch_with_full_image(self, full_image, text_elements, **k... method extract (line 11) | def extract(self, image, text_content=None, **kwargs): class EmptyGlobalExtractor (line 15) | class EmptyGlobalExtractor: method extract_batch_with_full_image (line 16) | def extract_batch_with_full_image(self, full_image, text_elements, **k... method extract (line 19) | def extract(self, image, text_content=None, **kwargs): class EditableImageStub (line 23) | class EditableImageStub: class BBox (line 24) | class BBox: method __init__ (line 25) | def __init__(self): class Element (line 31) | class Element: method __init__ (line 32) | def __init__(self, image_path: str): method __init__ (line 41) | def __init__(self, image_path: str): function _make_editable_images (line 46) | def _make_editable_images(tmp_path): function test_hybrid_style_extraction_fails_fast_when_provider_has_no_image_input (line 52) | def test_hybrid_style_extraction_fails_fast_when_provider_has_no_image_i... function test_hybrid_style_extraction_reports_missing_global_results_when_not_fail_fast (line 69) | def test_hybrid_style_extraction_reports_missing_global_results_when_not... FILE: backend/tests/unit/test_file_parser_service.py function _create_temp_image (line 15) | def _create_temp_image() -> str: function test_generate_single_caption_openai_uses_configured_model (line 21) | def test_generate_single_caption_openai_uses_configured_model(): function test_can_generate_captions_does_not_accept_legacy_prefixes (line 48) | def test_can_generate_captions_does_not_accept_legacy_prefixes(): function test_can_generate_captions_accepts_vendor_prefix_key (line 68) | def test_can_generate_captions_accepts_vendor_prefix_key(): FILE: backend/tests/unit/test_image_prompt_ratio.py class TestImagePromptAspectRatio (line 5) | class TestImagePromptAspectRatio: method test_default_ratio_is_16_9 (line 6) | def test_default_ratio_is_16_9(self): method test_custom_ratio_4_3 (line 14) | def test_custom_ratio_4_3(self): method test_custom_ratio_1_1 (line 24) | def test_custom_ratio_1_1(self): FILE: backend/tests/unit/test_lazyllm_image_content_type.py function _make_png_bytes (line 15) | def _make_png_bytes() -> bytes: function _inject_lazyllm_mock (line 22) | def _inject_lazyllm_mock(): class TestLazyLLMContentTypeFallback (line 37) | class TestLazyLLMContentTypeFallback: method setup_method (line 39) | def setup_method(self): method _make_provider (line 46) | def _make_provider(self): method test_fallback_on_content_type_error (line 54) | def test_fallback_on_content_type_error(self): method test_untrusted_host_is_not_fetched (line 80) | def test_untrusted_host_is_not_fetched(self): method test_non_content_type_error_is_reraised (line 96) | def test_non_content_type_error_is_reraised(self): FILE: backend/tests/unit/test_smart_merge.py function merge_app (line 15) | def merge_app(): function ctx (line 33) | def ctx(merge_app): function _make_project (line 43) | def _make_project(pid='test-proj'): function _make_page (line 51) | def _make_page(project_id, title, order, desc=None, image_path=None, sta... class TestPositionBasedMerge (line 64) | class TestPositionBasedMerge: method test_equal_pages_preserves_description_and_image (line 66) | def test_equal_pages_preserves_description_and_image(self, ctx): method test_more_pages_creates_new_ones (line 94) | def test_more_pages_creates_new_ones(self, ctx): method test_fewer_pages_deletes_trailing (line 114) | def test_fewer_pages_deletes_trailing(self, ctx): method test_no_old_pages_creates_all_new (line 135) | def test_no_old_pages_creates_all_new(self, ctx): method test_part_field_updated (line 151) | def test_part_field_updated(self, ctx): method test_order_index_updated (line 166) | def test_order_index_updated(self, ctx): FILE: backend/utils/image_utils.py function check_image_resolution (line 8) | def check_image_resolution(image: Image.Image, expected_resolution: str)... FILE: backend/utils/latex_utils.py function is_simple_latex (line 79) | def is_simple_latex(latex: str) -> bool: function latex_to_text (line 116) | def latex_to_text(latex: str) -> str: function latex_to_mathml (line 160) | def latex_to_mathml(latex: str) -> Optional[str]: function mathml_to_omml (line 179) | def mathml_to_omml(mathml: str) -> Optional[str]: function convert_latex_for_pptx (line 221) | def convert_latex_for_pptx(latex: str) -> Tuple[str, Optional[str]]: FILE: backend/utils/mask_utils.py function normalize_bbox (line 14) | def normalize_bbox(bbox: Union[Tuple, List, dict]) -> Tuple[int, int, in... function normalize_bboxes (line 38) | def normalize_bboxes(bboxes: List[Union[Tuple, List, dict]]) -> List[Tup... function merge_two_boxes (line 49) | def merge_two_boxes(box1: Tuple, box2: Tuple) -> Tuple[int, int, int, int]: function _iterative_merge (line 59) | def _iterative_merge( function create_mask_from_bboxes (line 109) | def create_mask_from_bboxes( function create_inverse_mask_from_bboxes (line 225) | def create_inverse_mask_from_bboxes( function create_mask_from_image_and_bboxes (line 251) | def create_mask_from_image_and_bboxes( function visualize_mask_overlay (line 274) | def visualize_mask_overlay( function merge_vertical_nearby_bboxes (line 331) | def merge_vertical_nearby_bboxes( function merge_overlapping_bboxes (line 422) | def merge_overlapping_bboxes( FILE: backend/utils/page_utils.py function parse_page_ids_from_query (line 8) | def parse_page_ids_from_query(request: Request) -> List[str]: function parse_page_ids_from_body (line 24) | def parse_page_ids_from_body(data: dict) -> List[str]: function get_filtered_pages (line 40) | def get_filtered_pages(project_id: str, page_ids: Optional[List[str]] = ... FILE: backend/utils/path_utils.py function convert_mineru_path_to_local (line 12) | def convert_mineru_path_to_local(mineru_path: str, project_root: Optiona... function find_mineru_file_with_prefix (line 46) | def find_mineru_file_with_prefix(mineru_path: str, project_root: Optiona... function find_file_with_prefix (line 75) | def find_file_with_prefix(file_path: Path) -> Optional[Path]: FILE: backend/utils/pptx_builder.py class HTMLTableParser (line 20) | class HTMLTableParser(HTMLParser): method __init__ (line 23) | def __init__(self): method handle_starttag (line 32) | def handle_starttag(self, tag, attrs): method handle_endtag (line 43) | def handle_endtag(self, tag): method handle_data (line 55) | def handle_data(self, data): method parse_html_table (line 60) | def parse_html_table(html: str) -> List[List[str]]: class PPTXBuilder (line 67) | class PPTXBuilder: method _get_font (line 95) | def _get_font(cls, size_pt: float) -> Optional[ImageFont.FreeTypeFont]: method _measure_text_width (line 110) | def _measure_text_width(cls, text: str, font_size_pt: float) -> Option... method __init__ (line 135) | def __init__(self, slide_width_inches: float = None, slide_height_inch... method create_presentation (line 148) | def create_presentation(self) -> Presentation: method _set_core_properties (line 157) | def _set_core_properties(prs: Presentation) -> None: method setup_presentation_size (line 170) | def setup_presentation_size(self, width_pixels: int, height_pixels: in... method add_blank_slide (line 226) | def add_blank_slide(self): method pixels_to_inches (line 236) | def pixels_to_inches(self, pixels: float, dpi: int = None) -> float: method calculate_font_size (line 250) | def calculate_font_size(self, bbox: List[int], text: str, text_level: ... method add_text_element (line 346) | def add_text_element( method add_image_element (line 502) | def add_image_element( method add_image_placeholder (line 540) | def add_image_placeholder( method add_table_element (line 571) | def add_table_element( method save (line 650) | def save(self, output_path: str): method get_presentation (line 669) | def get_presentation(self) -> Presentation: FILE: backend/utils/response.py function success_response (line 8) | def success_response(data: Any = None, message: str = "Success", status_... function error_response (line 31) | def error_response(error_code: str, message: str, status_code: int = 400): function bad_request (line 53) | def bad_request(message: str = "Invalid request"): function not_found (line 57) | def not_found(resource: str = "Resource"): function invalid_status (line 61) | def invalid_status(message: str = "Invalid status for this operation"): function ai_service_error (line 65) | def ai_service_error(message: str = "AI service error"): function rate_limit_error (line 69) | def rate_limit_error(message: str = "Rate limit exceeded"): FILE: backend/utils/validators.py function normalize_aspect_ratio (line 15) | def normalize_aspect_ratio(raw_value) -> str: function validate_project_status (line 90) | def validate_project_status(status: str) -> bool: function validate_page_status (line 95) | def validate_page_status(status: str) -> bool: function validate_task_status (line 100) | def validate_task_status(status: str) -> bool: function validate_task_type (line 105) | def validate_task_type(task_type: str) -> bool: function allowed_file (line 110) | def allowed_file(filename: str, allowed_extensions: Set[str]) -> bool: FILE: create-test-data.mjs constant BASE_URL (line 6) | const BASE_URL = process.env.BASE_URL || 'http://localhost:5401'; function createProject (line 9) | async function createProject(title) { function createTempFile (line 25) | function createTempFile(filename, content) { function uploadFile (line 36) | async function uploadFile(projectId, filename, content) { function main (line 53) | async function main() { FILE: frontend/e2e/aspect-ratio-lock-integration.spec.ts constant BASE (line 9) | const BASE = process.env.BASE_URL || 'http://localhost:3000' constant API (line 10) | const API = `http://localhost:${Number(new URL(BASE).port) + 2000}` FILE: frontend/e2e/aspect-ratio-lock.spec.ts constant PROJECT_ID (line 12) | const PROJECT_ID = 'mock-aspect-lock' function mockRoutes (line 41) | function mockRoutes(page: any, pages: any[]) { FILE: frontend/e2e/badge-status-after-generation.spec.ts constant PROJECT_ID (line 4) | const PROJECT_ID = 'badge-race-mock' constant PAGE_IDS (line 5) | const PAGE_IDS = ['p-1', 'p-2', 'p-3'] function makePage (line 7) | function makePage(id: string, idx: number, status: string, hasImage: boo... function projectJson (line 20) | function projectJson(pages: ReturnType[], projectStatus... function mockCommonRoutes (line 37) | async function mockCommonRoutes(page: Page) { FILE: frontend/e2e/desc-regeneration-skeleton.spec.ts constant PROJECT_ID (line 9) | const PROJECT_ID = 'mock-proj-regen-skeleton' function makePage (line 11) | function makePage(id: string, index: number, title: string, opts?: { des... constant OLD_DESC_1 (line 25) | const OLD_DESC_1 = 'Old description for page one' constant OLD_DESC_2 (line 26) | const OLD_DESC_2 = 'Old description for page two' constant NEW_DESC_1 (line 27) | const NEW_DESC_1 = 'Brand new description for page one' constant NEW_DESC_2 (line 28) | const NEW_DESC_2 = 'Brand new description for page two' FILE: frontend/e2e/description-detail-level.spec.ts constant PROJECT_ID (line 11) | const PROJECT_ID = 'mock-proj-detail-level' function makePage (line 13) | function makePage(id: string, index: number, title: string, description?... function setupMockRoutes (line 33) | async function setupMockRoutes(page: import('@playwright/test').Page) { FILE: frontend/e2e/description-no-flicker.spec.ts constant PROJECT_ID (line 10) | const PROJECT_ID = 'mock-proj-flicker' function makePage (line 12) | function makePage(id: string, index: number, title: string, description?... FILE: frontend/e2e/export-aspect-ratio.spec.ts constant BASE (line 13) | const BASE = process.env.BASE_URL || 'http://localhost:3000' constant API (line 15) | const API = `http://localhost:${Number(new URL(BASE).port) + 2000}` constant TINY_PNG (line 18) | const TINY_PNG = Buffer.from( constant WORKTREE_ROOT (line 26) | const WORKTREE_ROOT = path.resolve(__dirname, '..', '..') constant UPLOADS_DIR (line 27) | const UPLOADS_DIR = path.join(WORKTREE_ROOT, 'uploads') constant DB_PATH (line 28) | const DB_PATH = path.join(WORKTREE_ROOT, 'backend', 'instance', 'databas... constant UUID_RE (line 30) | const UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-... function assertUUID (line 32) | function assertUUID(val: string, label: string) { type ProjectData (line 36) | interface ProjectData { function setupProject (line 42) | async function setupProject( function cleanup (line 84) | function cleanup(projectId: string) { FILE: frontend/e2e/extract-style-caption.spec.ts constant BASE_URL (line 9) | const BASE_URL = process.env.BASE_URL || 'http://localhost:3000' constant TINY_PNG (line 11) | const TINY_PNG = Buffer.from( function triggerStyleExtract (line 17) | async function triggerStyleExtract(page: import('@playwright/test').Page) { FILE: frontend/e2e/failed-file-reselect.spec.ts constant FILE_FAILED (line 8) | const FILE_FAILED = 'file-failed-001' constant FILE_COMPLETED (line 9) | const FILE_COMPLETED = 'file-completed-002' FILE: frontend/e2e/file-preview-scrollbar.spec.ts constant LONG_MARKDOWN (line 12) | const LONG_MARKDOWN = '# Test Document\n\n' + 'Lorem ipsum dolor sit ame... constant PROJECT_ID (line 15) | const PROJECT_ID = 'mock-proj-001' constant FILE_ID (line 16) | const FILE_ID = 'mock-file-001' FILE: frontend/e2e/generation-fail.spec.ts function setupFailureMocks (line 3) | async function setupFailureMocks(page: Page, projectId: string, failUrl:... FILE: frontend/e2e/generation-requirements.spec.ts constant PROJECT_ID (line 3) | const PROJECT_ID = 'mock-gen-req-project' function clearAndType (line 43) | async function clearAndType(editor: import('@playwright/test').Locator, ... FILE: frontend/e2e/helpers/seed-project.ts constant FRONTEND_DIR (line 14) | const FRONTEND_DIR = cwd.endsWith('frontend') ? cwd : path.join(cwd, 'fr... constant PROJECT_ROOT (line 15) | const PROJECT_ROOT = path.resolve(FRONTEND_DIR, '..') constant DB_PATH (line 16) | const DB_PATH = path.join(PROJECT_ROOT, 'backend', 'instance', 'database... constant UPLOADS (line 17) | const UPLOADS = path.join(PROJECT_ROOT, 'uploads') constant FIXTURES (line 18) | const FIXTURES = path.join(FRONTEND_DIR, 'e2e', 'fixtures') function sql (line 20) | function sql(query: string) { function getFixtureImage (line 25) | function getFixtureImage(index: number): string { type SeededProject (line 30) | interface SeededProject { function seedProjectWithImages (line 39) | async function seedProjectWithImages( FILE: frontend/e2e/history-pagination.spec.ts constant PAGE_SIZE (line 12) | const PAGE_SIZE = 5 function makeProject (line 14) | function makeProject(index: number) { function setupMockRoutes (line 37) | async function setupMockRoutes( function createSimpleProject (line 199) | async function createSimpleProject(index: number): Promise { function deleteProject (line 209) | async function deleteProject(projectId: string) { FILE: frontend/e2e/image-prompt-ratio.spec.ts constant BASE (line 9) | const BASE = process.env.BASE_URL || 'http://localhost:3000' constant API (line 10) | const API = `http://localhost:${Number(new URL(BASE).port) + 2000}` FILE: frontend/e2e/image-queued-status.spec.ts constant PROJECT_ID (line 3) | const PROJECT_ID = 'queued-status-mock' constant PAGE_IDS (line 4) | const PAGE_IDS = ['p-1', 'p-2', 'p-3', 'p-4'] function makePage (line 6) | function makePage(id: string, idx: number, status: string, hasImage: boo... function projectJson (line 19) | function projectJson(pages: ReturnType[], projectStatus... function mockCommonRoutes (line 36) | async function mockCommonRoutes(page: Page) { FILE: frontend/e2e/import-markdown.spec.ts constant PROJECT_ID (line 10) | const PROJECT_ID = 'mock-import-proj' constant UNIFIED_MD (line 27) | const UNIFIED_MD = `# 项目 constant LEGACY_MD (line 57) | const LEGACY_MD = `# 大纲 constant EMPTY_MD (line 65) | const EMPTY_MD = `# 空文件 function writeTempFile (line 123) | function writeTempFile(name: string, content: string): string { FILE: frontend/e2e/lazyllm-image-content-type.spec.ts constant BASE (line 13) | const BASE = process.env.BASE_URL ?? 'http://localhost:3000' FILE: frontend/e2e/markdown-card-style.spec.ts constant BASE (line 3) | const BASE = process.env.BASE_URL || 'http://localhost:3000'; constant PROJECT_ID (line 4) | const PROJECT_ID = 'mock-style-test'; constant TINY_PNG (line 7) | const TINY_PNG = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAAB... function makePage (line 9) | function makePage(id: string, index: number, title: string, description:... function setupMocks (line 23) | function setupMocks(page: import('@playwright/test').Page, pages: Return... FILE: frontend/e2e/material-aspect-ratio.spec.ts function openMaterialGeneratorModal (line 23) | async function openMaterialGeneratorModal(page: Page) { FILE: frontend/e2e/outline-autosave-blur.spec.ts constant PROJECT_ID (line 3) | const PROJECT_ID = 'mock-autosave-project' FILE: frontend/e2e/outline-null-crash.spec.ts constant PROJECT_ID (line 3) | const PROJECT_ID = 'mock-null-outline' FILE: frontend/e2e/parsing-preview-toast.spec.ts constant PROJECT_ID (line 8) | const PROJECT_ID = 'mock-proj-parse' constant FILE_PARSING (line 9) | const FILE_PARSING = 'file-parsing-001' constant FILE_COMPLETED (line 10) | const FILE_COMPLETED = 'file-completed-002' FILE: frontend/e2e/per-model-startup-creds.spec.ts constant BACKEND_URL (line 21) | const BACKEND_URL = `http://localhost:${backendPort}` constant PROJECT_ROOT (line 22) | const PROJECT_ROOT = path.resolve(__dirname, '..', '..') constant LOG_FILE (line 23) | const LOG_FILE = path.join('/tmp', `startup-creds-backend-${process.pid}... function restartBackend (line 25) | function restartBackend() { FILE: frontend/e2e/preset-capsules.spec.ts constant PROJECT_ID (line 3) | const PROJECT_ID = 'mock-preset-project' function setupProjectMock (line 27) | async function setupProjectMock(page: import('@playwright/test').Page) { FILE: frontend/e2e/preview-text-style-template.spec.ts constant BASE_URL (line 10) | const BASE_URL = process.env.BASE_URL || 'http://localhost:3000' constant BACKEND_URL (line 11) | const BACKEND_URL = BASE_URL.replace(/:\d+$/, (m) => `:${parseInt(m.slic... function setupMocks (line 14) | async function setupMocks(page: import('@playwright/test').Page) { FILE: frontend/e2e/renovation-aspect-ratio.spec.ts constant BASE (line 12) | const BASE = process.env.BASE_URL || 'http://localhost:3000' constant API (line 13) | const API = `http://localhost:${Number(new URL(BASE).port) + 2000}` FILE: frontend/e2e/settings-backfill.spec.ts constant BASE_URL (line 10) | const BASE_URL = process.env.BASE_URL || 'http://localhost:3000' FILE: frontend/e2e/settings-env-fallback.spec.ts constant BASE_URL (line 11) | const BASE_URL = process.env.BASE_URL || 'http://localhost:3000' FILE: frontend/e2e/settings-per-model-provider-integration.spec.ts function getModelGroup (line 8) | function getModelGroup(page: Page, index: number) { FILE: frontend/e2e/settings-per-model-provider.spec.ts function getModelGroup (line 64) | function getModelGroup(page: Page, index: number) { FILE: frontend/e2e/settings-read-only.spec.ts constant BASE (line 6) | const BASE = process.env.BASE_URL ?? 'http://localhost:5173'; constant DB_PATH (line 7) | const DB_PATH = process.env.DB_PATH ?? function dbQuery (line 10) | function dbQuery(sql: string): string { FILE: frontend/e2e/settings-reset-fallback.spec.ts constant BASE (line 15) | const BASE = process.env.BASE_URL ?? 'http://localhost:5173' FILE: frontend/e2e/smart-merge.spec.ts constant BASE (line 9) | const BASE = process.env.BASE_URL || 'http://localhost:3000' constant PROJECT_ID (line 10) | const PROJECT_ID = 'mock-merge-proj' constant INITIAL_PAGES (line 12) | const INITIAL_PAGES = [ constant REFINED_FEWER_PAGES (line 43) | const REFINED_FEWER_PAGES = [ constant REFINED_MORE_PAGES (line 65) | const REFINED_MORE_PAGES = [ function setupMocks (line 104) | function setupMocks(page: import('@playwright/test').Page, pagesRef: { c... FILE: frontend/e2e/streaming-descriptions.spec.ts constant BASE_URL (line 3) | const BASE_URL = process.env.BASE_URL || 'http://localhost:3240'; function createProjectWithOutline (line 8) | async function createProjectWithOutline(page: import('@playwright/test')... FILE: frontend/e2e/streaming-outline.spec.ts constant BASE_URL (line 3) | const BASE_URL = process.env.BASE_URL || 'http://localhost:3240'; function createProjectAndNavigate (line 8) | async function createProjectAndNavigate(page: import('@playwright/test')... FILE: frontend/e2e/upload-folder-path.spec.ts constant FRONTEND_DIR (line 19) | const FRONTEND_DIR = process.cwd().endsWith('frontend') constant PROJECT_ROOT (line 22) | const PROJECT_ROOT = path.resolve(FRONTEND_DIR, '..') constant FIXTURES (line 23) | const FIXTURES = path.join(FRONTEND_DIR, 'e2e', 'fixtures') constant BACKEND_LOG (line 24) | const BACKEND_LOG = '/tmp/fix-upload-backend.log' FILE: frontend/e2e/ux-polish-i18n.spec.ts constant BASE (line 4) | const BASE = process.env.BASE_URL || 'http://localhost:3000'; FILE: frontend/src/App.tsx function App (line 13) | function App() { FILE: frontend/src/api/client.ts constant API_BASE_URL (line 5) | const API_BASE_URL = ''; FILE: frontend/src/api/endpoints.ts type OutlineStreamPage (line 134) | interface OutlineStreamPage { type OutlineStreamCallbacks (line 141) | interface OutlineStreamCallbacks { type DescriptionStreamEvent (line 247) | interface DescriptionStreamEvent { type DescriptionStreamCallbacks (line 254) | interface DescriptionStreamCallbacks { type Material (line 713) | interface Material { type UserTemplate (line 838) | interface UserTemplate { type ReferenceFile (line 887) | interface ReferenceFile { type OutputLanguage (line 1000) | type OutputLanguage = 'zh' | 'ja' | 'en' | 'auto'; type OutputLanguageOption (line 1002) | interface OutputLanguageOption { constant OUTPUT_LANGUAGE_OPTIONS (line 1007) | const OUTPUT_LANGUAGE_OPTIONS: OutputLanguageOption[] = [ type TestSettingsOverride (line 1087) | interface TestSettingsOverride { FILE: frontend/src/components/history/ProjectCard.tsx type ProjectCardProps (line 18) | interface ProjectCardProps { FILE: frontend/src/components/outline/OutlineCard.tsx type OutlineCardProps (line 33) | interface OutlineCardProps { FILE: frontend/src/components/preview/DescriptionCard.tsx type DescriptionCardProps (line 38) | interface DescriptionCardProps { FILE: frontend/src/components/preview/SlideCard.tsx type SlideCardProps (line 30) | interface SlideCardProps { FILE: frontend/src/components/shared/AccessCodeGuard.tsx constant STORAGE_KEY (line 7) | const STORAGE_KEY = 'banana-access-code'; function AccessCodeGuard (line 32) | function AccessCodeGuard({ children }: { children: ReactNode }) { FILE: frontend/src/components/shared/AiRefineInput.tsx type AiRefineInputProps (line 23) | interface AiRefineInputProps { FILE: frontend/src/components/shared/Button.tsx type ButtonProps (line 4) | interface ButtonProps extends React.ButtonHTMLAttributes { FILE: frontend/src/components/shared/ConfirmDialog.tsx type ConfirmDialogProps (line 6) | interface ConfirmDialogProps { FILE: frontend/src/components/shared/ContextualStatusBadge.tsx type ContextualStatusBadgeProps (line 6) | interface ContextualStatusBadgeProps { FILE: frontend/src/components/shared/ExportTasksPanel.tsx type ExportTasksPanelProps (line 362) | interface ExportTasksPanelProps { FILE: frontend/src/components/shared/FilePreviewModal.tsx type FilePreviewModalProps (line 22) | interface FilePreviewModalProps { FILE: frontend/src/components/shared/Footer.tsx constant GITHUB_REPO (line 4) | const GITHUB_REPO = 'Anionex/banana-slides'; constant GITHUB_URL (line 5) | const GITHUB_URL = `https://github.com/${GITHUB_REPO}`; FILE: frontend/src/components/shared/GithubBadge.tsx constant GITHUB_REPO (line 4) | const GITHUB_REPO = 'Anionex/banana-slides'; constant GITHUB_URL (line 5) | const GITHUB_URL = `https://github.com/${GITHUB_REPO}`; type GithubStats (line 7) | interface GithubStats { constant CACHE_KEY (line 12) | const CACHE_KEY = 'github-stats-cache-v2'; constant CACHE_DURATION (line 13) | const CACHE_DURATION = 3600 * 1000; FILE: frontend/src/components/shared/GithubRepoCard.tsx constant GITHUB_REPO (line 4) | const GITHUB_REPO = 'Anionex/banana-slides'; constant GITHUB_URL (line 5) | const GITHUB_URL = `https://github.com/${GITHUB_REPO}`; type RepoStats (line 7) | interface RepoStats { FILE: frontend/src/components/shared/HelpModal.tsx constant SHOWCASES (line 90) | const SHOWCASES = [ constant FEATURES (line 97) | const FEATURES: { key: string; icon: React.ReactNode }[] = [ function tList (line 108) | function tList(lang: 'zh' | 'en', path: string): string[] { type PageRenderer (line 121) | type PageRenderer = (ctx: { type PageDef (line 304) | interface PageDef { constant PAGES (line 310) | const PAGES: PageDef[] = [ type HelpModalProps (line 319) | interface HelpModalProps { FILE: frontend/src/components/shared/ImagePreviewList.tsx type ImagePreviewListProps (line 16) | interface ImagePreviewListProps { FILE: frontend/src/components/shared/Input.tsx type InputProps (line 4) | interface InputProps extends React.InputHTMLAttributes { FILE: frontend/src/components/shared/Loading.tsx type ProgressData (line 6) | interface ProgressData { type LoadingProps (line 14) | interface LoadingProps { FILE: frontend/src/components/shared/Markdown.tsx type MarkdownProps (line 11) | interface MarkdownProps { function preprocessMarkdown (line 20) | function preprocessMarkdown(content: string): string { FILE: frontend/src/components/shared/MarkdownTextarea.tsx constant IMAGE_REGEX (line 27) | const IMAGE_REGEX = /!\[([^\]]*)\]\(([^)]+)\)/g; constant CHIP_SELECTED_CLASS (line 28) | const CHIP_SELECTED_CLASS = 'md-chip-selected'; constant CHIP_CLASS (line 29) | const CHIP_CLASS = 'md-chip'; type MarkdownTextareaProps (line 31) | interface MarkdownTextareaProps { type MarkdownTextareaRef (line 55) | interface MarkdownTextareaRef { function escapeHtml (line 62) | function escapeHtml(text: string) { type Segment (line 66) | type Segment = function parseSegments (line 70) | function parseSegments(text: string): Segment[] { function serializeDOM (line 88) | function serializeDOM(element: HTMLElement): string { function getDisplayName (line 110) | function getDisplayName(alt: string, url: string): string { constant IMAGE_ICON (line 120) | const IMAGE_ICON = '> = { constant STORAGE_KEY_PREFIX (line 55) | const STORAGE_KEY_PREFIX = 'presetCapsules_'; function loadUserPresets (line 57) | function loadUserPresets(type: PresetType): Preset[] { function saveUserPresets (line 66) | function saveUserPresets(type: PresetType, presets: Preset[]) { type PresetCapsulesProps (line 71) | interface PresetCapsulesProps { function PresetCapsules (line 76) | function PresetCapsules({ type, onAppend }: PresetCapsulesProps) { FILE: frontend/src/components/shared/ProjectResourcesList.tsx type ProjectResourcesListProps (line 26) | interface ProjectResourcesListProps { FILE: frontend/src/components/shared/ProjectSettingsModal.tsx type ProjectSettingsModalProps (line 79) | interface ProjectSettingsModalProps { type SettingsTab (line 105) | type SettingsTab = 'project' | 'global' | 'export'; FILE: frontend/src/components/shared/ReferenceFileCard.tsx type ReferenceFileCardProps (line 26) | interface ReferenceFileCardProps { FILE: frontend/src/components/shared/ReferenceFileList.tsx type ReferenceFileListProps (line 12) | interface ReferenceFileListProps { FILE: frontend/src/components/shared/ReferenceFileSelector.tsx type ReferenceFileSelectorProps (line 68) | interface ReferenceFileSelectorProps { FILE: frontend/src/components/shared/ShimmerOverlay.tsx type ShimmerOverlayProps (line 3) | interface ShimmerOverlayProps { FILE: frontend/src/components/shared/StatusBadge.tsx type StatusBadgeProps (line 32) | interface StatusBadgeProps { FILE: frontend/src/components/shared/TemplateSelector.tsx type TemplateSelectorProps (line 44) | interface TemplateSelectorProps { FILE: frontend/src/components/shared/TextStyleSelector.tsx type TextStyleSelectorProps (line 32) | interface TextStyleSelectorProps { FILE: frontend/src/components/shared/Textarea.tsx type TextareaProps (line 4) | interface TextareaProps extends React.TextareaHTMLAttributes string):... function getStatusDescription (line 141) | function getStatusDescription(status: PageStatus, t: (key: string) => st... FILE: frontend/src/hooks/useT.ts type NestedRecord (line 3) | type NestedRecord = Record; type Translations (line 5) | type Translations = { function getNestedValue (line 14) | function getNestedValue(obj: NestedRecord, path: string): string | undef... function useT (line 60) | function useT(translations: T) { FILE: frontend/src/hooks/useTheme.ts type Theme (line 3) | type Theme = 'light' | 'dark' | 'system'; constant THEME_KEY (line 5) | const THEME_KEY = 'banana-slides-theme'; function getSystemTheme (line 7) | function getSystemTheme(): 'light' | 'dark' { function applyTheme (line 14) | function applyTheme(theme: Theme) { function useTheme (line 25) | function useTheme() { FILE: frontend/src/pages/DetailEditor.tsx constant PRESET_EXTRA_FIELDS (line 115) | const PRESET_EXTRA_FIELDS = new Set(['视觉元素', '视觉焦点', '排版布局', '演讲者备注']); FILE: frontend/src/pages/History.tsx constant DEFAULT_PAGE_SIZE (line 75) | const DEFAULT_PAGE_SIZE = 5; constant PAGE_SIZE_KEY (line 76) | const PAGE_SIZE_KEY = 'history_page_size'; FILE: frontend/src/pages/Home.tsx type CreationType (line 16) | type CreationType = 'idea' | 'outline' | 'description' | 'ppt_renovation'; FILE: frontend/src/pages/Settings.tsx type FieldType (line 216) | type FieldType = 'text' | 'password' | 'number' | 'select' | 'buttons' |... type FieldConfig (line 218) | interface FieldConfig { type SectionConfig (line 232) | interface SectionConfig { type TestStatus (line 238) | type TestStatus = 'idle' | 'loading' | 'success' | 'error'; type ServiceTestState (line 240) | interface ServiceTestState { constant LAZYLLM_SOURCES (line 247) | const LAZYLLM_SOURCES = [ constant ALL_PROVIDER_SOURCES (line 260) | const ALL_PROVIDER_SOURCES = [ constant API_KEY_PROVIDERS (line 267) | const API_KEY_PROVIDERS = new Set(['gemini', 'openai']); constant LAZYLLM_VENDOR_SET (line 270) | const LAZYLLM_VENDOR_SET = new Set(LAZYLLM_SOURCES.map(s => s.value)); constant SCROLL_SHOW_THRESHOLD (line 1302) | const SCROLL_SHOW_THRESHOLD = 300; FILE: frontend/src/store/useExportTasksStore.ts type ExportTaskStatus (line 14) | type ExportTaskStatus = 'PENDING' | 'PROCESSING' | 'RUNNING' | 'COMPLETE... type ExportTaskType (line 15) | type ExportTaskType = 'pptx' | 'pdf' | 'editable-pptx' | 'images'; type ExportTask (line 17) | interface ExportTask { type ExportTasksState (line 47) | interface ExportTasksState { FILE: frontend/src/store/useProjectStore.ts type ProjectState (line 76) | interface ProjectState { FILE: frontend/src/types/index.ts type PageStatus (line 2) | type PageStatus = 'DRAFT' | 'GENERATING_DESCRIPTION' | 'DESCRIPTION_GENE... type ProjectStatus (line 5) | type ProjectStatus = 'DRAFT' | 'OUTLINE_GENERATED' | 'DESCRIPTIONS_GENER... type OutlineContent (line 8) | interface OutlineContent { type DescriptionContent (line 14) | type DescriptionContent = type ImageVersion (line 30) | interface ImageVersion { type Page (line 41) | interface Page { type ExportExtractorMethod (line 57) | type ExportExtractorMethod = 'mineru' | 'hybrid'; type ExportInpaintMethod (line 60) | type ExportInpaintMethod = 'generative' | 'baidu' | 'hybrid'; type Project (line 63) | interface Project { type TaskStatus (line 88) | type TaskStatus = 'PENDING' | 'RUNNING' | 'COMPLETED' | 'FAILED'; type Task (line 91) | interface Task { type CreateProjectRequest (line 110) | interface CreateProjectRequest { type ApiResponse (line 120) | interface ApiResponse { type Settings (line 129) | interface Settings { FILE: frontend/src/utils/i18nHelper.ts type NestedRecord (line 3) | type NestedRecord = Record; type Translations (line 4) | type Translations = { zh: NestedRecord; en: NestedRecord }; function getNestedValue (line 6) | function getNestedValue(obj: NestedRecord, path: string): string | undef... function getT (line 22) | function getT(translations: T) { FILE: frontend/src/utils/index.ts function cn (line 8) | function cn(...inputs: ClassValue[]) { function normalizeProject (line 15) | function normalizeProject(data: any): Project { function normalizePage (line 27) | function normalizePage(data: any): Page { function debounce (line 38) | function debounce any>( function throttle (line 52) | function throttle any>( function downloadFile (line 69) | function downloadFile(blob: Blob, filename: string) { function formatDate (line 83) | function formatDate(dateString: string): string { function generateId (line 99) | function generateId(): string { function normalizeErrorMessage (line 106) | function normalizeErrorMessage(errorMessage: string | null | undefined):... FILE: frontend/src/utils/projectUtils.ts type StatusKey (line 103) | type StatusKey = 'notStarted' | 'completed' | 'pendingImages' | 'pending... type ExportOptions (line 176) | interface ExportOptions { type ParsedPage (line 239) | interface ParsedPage { constant EXTRA_FIELD_RE (line 255) | const EXTRA_FIELD_RE = /^([^\s::]{1,20})[::](.+)/; FILE: frontend/src/vite-env.d.ts type ImportMetaEnv (line 3) | interface ImportMetaEnv { type ImportMeta (line 6) | interface ImportMeta { FILE: frontend/vite.config.ts function computeWorktreePort (line 15) | function computeWorktreePort(basePort: number): number { FILE: scripts/export_editable_pptx.py function setup_flask_app (line 63) | def setup_flask_app(): function collect_image_paths (line 79) | def collect_image_paths(paths: List[str]) -> List[str]: function create_service_config (line 102) | def create_service_config( function export_editable_pptx (line 155) | def export_editable_pptx( function main (line 277) | def main(): FILE: scripts/translate_readme.py function translate_readme (line 26) | def translate_readme(source_file: str, target_file: str): function main (line 116) | def main(): FILE: scripts/translate_readme_incremental.py function split_by_headers (line 27) | def split_by_headers(content: str) -> List[Tuple[str, str, str]]: function get_git_diff_lines (line 68) | def get_git_diff_lines(file_path: str) -> set: function find_changed_blocks (line 108) | def find_changed_blocks(content: str, changed_lines: set) -> set: function translate_block (line 138) | def translate_block(content: str, text_provider) -> str: function incremental_translate (line 162) | def incremental_translate(source_file: str, target_file: str, force_full... function main (line 296) | def main(): FILE: v0_demo/demo.py function gen_outline (line 11) | def gen_outline(idea_prompt:str)->list[dict]: function flatten_outline (line 49) | def flatten_outline(outline: list[dict]) -> list[dict]: function gen_desc (line 65) | def gen_desc(idea_prompt, outline: list[Dict])->list[Dict] : function gen_outline_text (line 112) | def gen_outline_text(outline: list[Dict]) -> str: function gen_prompts (line 124) | def gen_prompts(outline: list[Dict], desc: list[str]) -> list[str]: function gen_images_parallel (line 154) | def gen_images_parallel(prompts: list[str], ref_image: str, output_dir: ... function create_pptx_from_images (line 192) | def create_pptx_from_images(input_dir: str = "output", output_file: str ... function gen_ppt (line 244) | def gen_ppt(idea_prompt, ref_image): FILE: v0_demo/gemini_genai.py function gen_image (line 19) | def gen_image(prompt: str, ref_image_path: str, aspect_ratio: str = DEFA... function gen_json_text (line 47) | def gen_json_text(prompt: str, model: str = "gemini-3-flash-preview") ->... function gen_text (line 61) | def gen_text(prompt: str, model: str = "gemini-3-flash-preview") -> str: FILE: v0_demo/lazyllm_genai.py function gen_text (line 56) | def gen_text(prompt: str, function gen_json_text (line 68) | def gen_json_text(prompt: str, function gen_image (line 79) | def gen_image(prompt: str, function describe_image (line 133) | def describe_image(image_path: str,