auto-coder 0.1.303__tar.gz → 0.1.305__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of auto-coder might be problematic. Click here for more details.

Files changed (214) hide show
  1. {auto_coder-0.1.303 → auto_coder-0.1.305}/PKG-INFO +1 -1
  2. {auto_coder-0.1.303 → auto_coder-0.1.305}/src/auto_coder.egg-info/PKG-INFO +1 -1
  3. {auto_coder-0.1.303 → auto_coder-0.1.305}/src/autocoder/auto_coder_runner.py +1 -1
  4. {auto_coder-0.1.303 → auto_coder-0.1.305}/src/autocoder/chat_auto_coder.py +1 -1
  5. {auto_coder-0.1.303 → auto_coder-0.1.305}/src/autocoder/commands/auto_command.py +1 -4
  6. {auto_coder-0.1.303 → auto_coder-0.1.305}/src/autocoder/commands/auto_web.py +1 -9
  7. {auto_coder-0.1.303 → auto_coder-0.1.305}/src/autocoder/common/auto_coder_lang.py +10 -1
  8. auto_coder-0.1.305/src/autocoder/common/global_cancel.py +82 -0
  9. {auto_coder-0.1.303 → auto_coder-0.1.305}/src/autocoder/dispacher/actions/action.py +8 -32
  10. {auto_coder-0.1.303 → auto_coder-0.1.305}/src/autocoder/dispacher/actions/plugins/action_regex_project.py +2 -6
  11. {auto_coder-0.1.303 → auto_coder-0.1.305}/src/autocoder/index/index.py +2 -4
  12. {auto_coder-0.1.303 → auto_coder-0.1.305}/src/autocoder/utils/auto_coder_utils/chat_stream_out.py +56 -11
  13. auto_coder-0.1.305/src/autocoder/utils/thread_utils.py +119 -0
  14. auto_coder-0.1.305/src/autocoder/version.py +1 -0
  15. auto_coder-0.1.303/src/autocoder/common/global_cancel.py +0 -21
  16. auto_coder-0.1.303/src/autocoder/utils/thread_utils.py +0 -210
  17. auto_coder-0.1.303/src/autocoder/version.py +0 -1
  18. {auto_coder-0.1.303 → auto_coder-0.1.305}/LICENSE +0 -0
  19. {auto_coder-0.1.303 → auto_coder-0.1.305}/README.md +0 -0
  20. {auto_coder-0.1.303 → auto_coder-0.1.305}/setup.cfg +0 -0
  21. {auto_coder-0.1.303 → auto_coder-0.1.305}/setup.py +0 -0
  22. {auto_coder-0.1.303 → auto_coder-0.1.305}/src/auto_coder.egg-info/SOURCES.txt +0 -0
  23. {auto_coder-0.1.303 → auto_coder-0.1.305}/src/auto_coder.egg-info/dependency_links.txt +0 -0
  24. {auto_coder-0.1.303 → auto_coder-0.1.305}/src/auto_coder.egg-info/entry_points.txt +0 -0
  25. {auto_coder-0.1.303 → auto_coder-0.1.305}/src/auto_coder.egg-info/requires.txt +0 -0
  26. {auto_coder-0.1.303 → auto_coder-0.1.305}/src/auto_coder.egg-info/top_level.txt +0 -0
  27. {auto_coder-0.1.303 → auto_coder-0.1.305}/src/autocoder/__init__.py +0 -0
  28. {auto_coder-0.1.303 → auto_coder-0.1.305}/src/autocoder/agent/__init__.py +0 -0
  29. {auto_coder-0.1.303 → auto_coder-0.1.305}/src/autocoder/agent/auto_demand_organizer.py +0 -0
  30. {auto_coder-0.1.303 → auto_coder-0.1.305}/src/autocoder/agent/auto_filegroup.py +0 -0
  31. {auto_coder-0.1.303 → auto_coder-0.1.305}/src/autocoder/agent/auto_guess_query.py +0 -0
  32. {auto_coder-0.1.303 → auto_coder-0.1.305}/src/autocoder/agent/auto_learn_from_commit.py +0 -0
  33. {auto_coder-0.1.303 → auto_coder-0.1.305}/src/autocoder/agent/auto_review_commit.py +0 -0
  34. {auto_coder-0.1.303 → auto_coder-0.1.305}/src/autocoder/agent/auto_tool.py +0 -0
  35. {auto_coder-0.1.303 → auto_coder-0.1.305}/src/autocoder/agent/coder.py +0 -0
  36. {auto_coder-0.1.303 → auto_coder-0.1.305}/src/autocoder/agent/designer.py +0 -0
  37. {auto_coder-0.1.303 → auto_coder-0.1.305}/src/autocoder/agent/planner.py +0 -0
  38. {auto_coder-0.1.303 → auto_coder-0.1.305}/src/autocoder/agent/project_reader.py +0 -0
  39. {auto_coder-0.1.303 → auto_coder-0.1.305}/src/autocoder/auto_coder.py +0 -0
  40. {auto_coder-0.1.303 → auto_coder-0.1.305}/src/autocoder/auto_coder_rag.py +0 -0
  41. {auto_coder-0.1.303 → auto_coder-0.1.305}/src/autocoder/auto_coder_server.py +0 -0
  42. {auto_coder-0.1.303 → auto_coder-0.1.305}/src/autocoder/benchmark.py +0 -0
  43. {auto_coder-0.1.303 → auto_coder-0.1.305}/src/autocoder/chat/__init__.py +0 -0
  44. {auto_coder-0.1.303 → auto_coder-0.1.305}/src/autocoder/chat_auto_coder_lang.py +0 -0
  45. {auto_coder-0.1.303 → auto_coder-0.1.305}/src/autocoder/command_args.py +0 -0
  46. {auto_coder-0.1.303 → auto_coder-0.1.305}/src/autocoder/command_parser.py +0 -0
  47. {auto_coder-0.1.303 → auto_coder-0.1.305}/src/autocoder/commands/__init__.py +0 -0
  48. {auto_coder-0.1.303 → auto_coder-0.1.305}/src/autocoder/commands/tools.py +0 -0
  49. {auto_coder-0.1.303 → auto_coder-0.1.305}/src/autocoder/common/JupyterClient.py +0 -0
  50. {auto_coder-0.1.303 → auto_coder-0.1.305}/src/autocoder/common/ShellClient.py +0 -0
  51. {auto_coder-0.1.303 → auto_coder-0.1.305}/src/autocoder/common/__init__.py +0 -0
  52. {auto_coder-0.1.303 → auto_coder-0.1.305}/src/autocoder/common/action_yml_file_manager.py +0 -0
  53. {auto_coder-0.1.303 → auto_coder-0.1.305}/src/autocoder/common/anything2images.py +0 -0
  54. {auto_coder-0.1.303 → auto_coder-0.1.305}/src/autocoder/common/anything2img.py +0 -0
  55. {auto_coder-0.1.303 → auto_coder-0.1.305}/src/autocoder/common/audio.py +0 -0
  56. {auto_coder-0.1.303 → auto_coder-0.1.305}/src/autocoder/common/auto_configure.py +0 -0
  57. {auto_coder-0.1.303 → auto_coder-0.1.305}/src/autocoder/common/buildin_tokenizer.py +0 -0
  58. {auto_coder-0.1.303 → auto_coder-0.1.305}/src/autocoder/common/chunk_validation.py +0 -0
  59. {auto_coder-0.1.303 → auto_coder-0.1.305}/src/autocoder/common/cleaner.py +0 -0
  60. {auto_coder-0.1.303 → auto_coder-0.1.305}/src/autocoder/common/code_auto_execute.py +0 -0
  61. {auto_coder-0.1.303 → auto_coder-0.1.305}/src/autocoder/common/code_auto_generate.py +0 -0
  62. {auto_coder-0.1.303 → auto_coder-0.1.305}/src/autocoder/common/code_auto_generate_diff.py +0 -0
  63. {auto_coder-0.1.303 → auto_coder-0.1.305}/src/autocoder/common/code_auto_generate_editblock.py +0 -0
  64. {auto_coder-0.1.303 → auto_coder-0.1.305}/src/autocoder/common/code_auto_generate_strict_diff.py +0 -0
  65. {auto_coder-0.1.303 → auto_coder-0.1.305}/src/autocoder/common/code_auto_merge.py +0 -0
  66. {auto_coder-0.1.303 → auto_coder-0.1.305}/src/autocoder/common/code_auto_merge_diff.py +0 -0
  67. {auto_coder-0.1.303 → auto_coder-0.1.305}/src/autocoder/common/code_auto_merge_editblock.py +0 -0
  68. {auto_coder-0.1.303 → auto_coder-0.1.305}/src/autocoder/common/code_auto_merge_strict_diff.py +0 -0
  69. {auto_coder-0.1.303 → auto_coder-0.1.305}/src/autocoder/common/code_modification_ranker.py +0 -0
  70. {auto_coder-0.1.303 → auto_coder-0.1.305}/src/autocoder/common/command_completer.py +0 -0
  71. {auto_coder-0.1.303 → auto_coder-0.1.305}/src/autocoder/common/command_generator.py +0 -0
  72. {auto_coder-0.1.303 → auto_coder-0.1.305}/src/autocoder/common/command_templates.py +0 -0
  73. {auto_coder-0.1.303 → auto_coder-0.1.305}/src/autocoder/common/computer_use.py +0 -0
  74. {auto_coder-0.1.303 → auto_coder-0.1.305}/src/autocoder/common/conf_import_export.py +0 -0
  75. {auto_coder-0.1.303 → auto_coder-0.1.305}/src/autocoder/common/conf_validator.py +0 -0
  76. {auto_coder-0.1.303 → auto_coder-0.1.305}/src/autocoder/common/const.py +0 -0
  77. {auto_coder-0.1.303 → auto_coder-0.1.305}/src/autocoder/common/context_pruner.py +0 -0
  78. {auto_coder-0.1.303 → auto_coder-0.1.305}/src/autocoder/common/conversation_pruner.py +0 -0
  79. {auto_coder-0.1.303 → auto_coder-0.1.305}/src/autocoder/common/files.py +0 -0
  80. {auto_coder-0.1.303 → auto_coder-0.1.305}/src/autocoder/common/git_utils.py +0 -0
  81. {auto_coder-0.1.303 → auto_coder-0.1.305}/src/autocoder/common/image_to_page.py +0 -0
  82. {auto_coder-0.1.303 → auto_coder-0.1.305}/src/autocoder/common/index_import_export.py +0 -0
  83. {auto_coder-0.1.303 → auto_coder-0.1.305}/src/autocoder/common/interpreter.py +0 -0
  84. {auto_coder-0.1.303 → auto_coder-0.1.305}/src/autocoder/common/llm_rerank.py +0 -0
  85. {auto_coder-0.1.303 → auto_coder-0.1.305}/src/autocoder/common/mcp_hub.py +0 -0
  86. {auto_coder-0.1.303 → auto_coder-0.1.305}/src/autocoder/common/mcp_server.py +0 -0
  87. {auto_coder-0.1.303 → auto_coder-0.1.305}/src/autocoder/common/mcp_servers/__init__.py +0 -0
  88. {auto_coder-0.1.303 → auto_coder-0.1.305}/src/autocoder/common/mcp_servers/mcp_server_gpt4o_mini_search.py +0 -0
  89. {auto_coder-0.1.303 → auto_coder-0.1.305}/src/autocoder/common/mcp_servers/mcp_server_perplexity.py +0 -0
  90. {auto_coder-0.1.303 → auto_coder-0.1.305}/src/autocoder/common/mcp_tools.py +0 -0
  91. {auto_coder-0.1.303 → auto_coder-0.1.305}/src/autocoder/common/memory_manager.py +0 -0
  92. {auto_coder-0.1.303 → auto_coder-0.1.305}/src/autocoder/common/model_speed_test.py +0 -0
  93. {auto_coder-0.1.303 → auto_coder-0.1.305}/src/autocoder/common/printer.py +0 -0
  94. {auto_coder-0.1.303 → auto_coder-0.1.305}/src/autocoder/common/recall_validation.py +0 -0
  95. {auto_coder-0.1.303 → auto_coder-0.1.305}/src/autocoder/common/result_manager.py +0 -0
  96. {auto_coder-0.1.303 → auto_coder-0.1.305}/src/autocoder/common/screenshots.py +0 -0
  97. {auto_coder-0.1.303 → auto_coder-0.1.305}/src/autocoder/common/search.py +0 -0
  98. {auto_coder-0.1.303 → auto_coder-0.1.305}/src/autocoder/common/search_replace.py +0 -0
  99. {auto_coder-0.1.303 → auto_coder-0.1.305}/src/autocoder/common/shells.py +0 -0
  100. {auto_coder-0.1.303 → auto_coder-0.1.305}/src/autocoder/common/stats_panel.py +0 -0
  101. {auto_coder-0.1.303 → auto_coder-0.1.305}/src/autocoder/common/stream_out_type.py +0 -0
  102. {auto_coder-0.1.303 → auto_coder-0.1.305}/src/autocoder/common/sys_prompt.py +0 -0
  103. {auto_coder-0.1.303 → auto_coder-0.1.305}/src/autocoder/common/text.py +0 -0
  104. {auto_coder-0.1.303 → auto_coder-0.1.305}/src/autocoder/common/types.py +0 -0
  105. {auto_coder-0.1.303 → auto_coder-0.1.305}/src/autocoder/common/utils_code_auto_generate.py +0 -0
  106. {auto_coder-0.1.303 → auto_coder-0.1.305}/src/autocoder/data/byzerllm.md +0 -0
  107. {auto_coder-0.1.303 → auto_coder-0.1.305}/src/autocoder/data/tokenizer.json +0 -0
  108. {auto_coder-0.1.303 → auto_coder-0.1.305}/src/autocoder/db/__init__.py +0 -0
  109. {auto_coder-0.1.303 → auto_coder-0.1.305}/src/autocoder/db/store.py +0 -0
  110. {auto_coder-0.1.303 → auto_coder-0.1.305}/src/autocoder/dispacher/__init__.py +0 -0
  111. {auto_coder-0.1.303 → auto_coder-0.1.305}/src/autocoder/dispacher/actions/__init__.py +0 -0
  112. {auto_coder-0.1.303 → auto_coder-0.1.305}/src/autocoder/dispacher/actions/copilot.py +0 -0
  113. {auto_coder-0.1.303 → auto_coder-0.1.305}/src/autocoder/dispacher/actions/plugins/__init__.py +0 -0
  114. {auto_coder-0.1.303 → auto_coder-0.1.305}/src/autocoder/dispacher/actions/plugins/action_translate.py +0 -0
  115. {auto_coder-0.1.303 → auto_coder-0.1.305}/src/autocoder/events/__init__.py +0 -0
  116. {auto_coder-0.1.303 → auto_coder-0.1.305}/src/autocoder/events/event_content.py +0 -0
  117. {auto_coder-0.1.303 → auto_coder-0.1.305}/src/autocoder/events/event_manager.py +0 -0
  118. {auto_coder-0.1.303 → auto_coder-0.1.305}/src/autocoder/events/event_manager_singleton.py +0 -0
  119. {auto_coder-0.1.303 → auto_coder-0.1.305}/src/autocoder/events/event_store.py +0 -0
  120. {auto_coder-0.1.303 → auto_coder-0.1.305}/src/autocoder/events/event_types.py +0 -0
  121. {auto_coder-0.1.303 → auto_coder-0.1.305}/src/autocoder/index/__init__.py +0 -0
  122. {auto_coder-0.1.303 → auto_coder-0.1.305}/src/autocoder/index/entry.py +0 -0
  123. {auto_coder-0.1.303 → auto_coder-0.1.305}/src/autocoder/index/filter/__init__.py +0 -0
  124. {auto_coder-0.1.303 → auto_coder-0.1.305}/src/autocoder/index/filter/normal_filter.py +0 -0
  125. {auto_coder-0.1.303 → auto_coder-0.1.305}/src/autocoder/index/filter/quick_filter.py +0 -0
  126. {auto_coder-0.1.303 → auto_coder-0.1.305}/src/autocoder/index/for_command.py +0 -0
  127. {auto_coder-0.1.303 → auto_coder-0.1.305}/src/autocoder/index/symbols_utils.py +0 -0
  128. {auto_coder-0.1.303 → auto_coder-0.1.305}/src/autocoder/index/types.py +0 -0
  129. {auto_coder-0.1.303 → auto_coder-0.1.305}/src/autocoder/lang.py +0 -0
  130. {auto_coder-0.1.303 → auto_coder-0.1.305}/src/autocoder/models.py +0 -0
  131. {auto_coder-0.1.303 → auto_coder-0.1.305}/src/autocoder/plugins/__init__.py +0 -0
  132. {auto_coder-0.1.303 → auto_coder-0.1.305}/src/autocoder/plugins/dynamic_completion_example.py +0 -0
  133. {auto_coder-0.1.303 → auto_coder-0.1.305}/src/autocoder/plugins/git_helper_plugin.py +0 -0
  134. {auto_coder-0.1.303 → auto_coder-0.1.305}/src/autocoder/plugins/sample_plugin.py +0 -0
  135. {auto_coder-0.1.303 → auto_coder-0.1.305}/src/autocoder/plugins/token_helper_plugin.py +0 -0
  136. {auto_coder-0.1.303 → auto_coder-0.1.305}/src/autocoder/plugins/utils.py +0 -0
  137. {auto_coder-0.1.303 → auto_coder-0.1.305}/src/autocoder/privacy/__init__.py +0 -0
  138. {auto_coder-0.1.303 → auto_coder-0.1.305}/src/autocoder/privacy/model_filter.py +0 -0
  139. {auto_coder-0.1.303 → auto_coder-0.1.305}/src/autocoder/pyproject/__init__.py +0 -0
  140. {auto_coder-0.1.303 → auto_coder-0.1.305}/src/autocoder/rag/__init__.py +0 -0
  141. {auto_coder-0.1.303 → auto_coder-0.1.305}/src/autocoder/rag/api_server.py +0 -0
  142. {auto_coder-0.1.303 → auto_coder-0.1.305}/src/autocoder/rag/cache/__init__.py +0 -0
  143. {auto_coder-0.1.303 → auto_coder-0.1.305}/src/autocoder/rag/cache/base_cache.py +0 -0
  144. {auto_coder-0.1.303 → auto_coder-0.1.305}/src/autocoder/rag/cache/byzer_storage_cache.py +0 -0
  145. {auto_coder-0.1.303 → auto_coder-0.1.305}/src/autocoder/rag/cache/cache_result_merge.py +0 -0
  146. {auto_coder-0.1.303 → auto_coder-0.1.305}/src/autocoder/rag/cache/file_monitor_cache.py +0 -0
  147. {auto_coder-0.1.303 → auto_coder-0.1.305}/src/autocoder/rag/cache/local_byzer_storage_cache.py +0 -0
  148. {auto_coder-0.1.303 → auto_coder-0.1.305}/src/autocoder/rag/cache/local_duckdb_storage_cache.py +0 -0
  149. {auto_coder-0.1.303 → auto_coder-0.1.305}/src/autocoder/rag/cache/rag_file_meta.py +0 -0
  150. {auto_coder-0.1.303 → auto_coder-0.1.305}/src/autocoder/rag/cache/simple_cache.py +0 -0
  151. {auto_coder-0.1.303 → auto_coder-0.1.305}/src/autocoder/rag/conversation_to_queries.py +0 -0
  152. {auto_coder-0.1.303 → auto_coder-0.1.305}/src/autocoder/rag/doc_filter.py +0 -0
  153. {auto_coder-0.1.303 → auto_coder-0.1.305}/src/autocoder/rag/document_retriever.py +0 -0
  154. {auto_coder-0.1.303 → auto_coder-0.1.305}/src/autocoder/rag/lang.py +0 -0
  155. {auto_coder-0.1.303 → auto_coder-0.1.305}/src/autocoder/rag/llm_wrapper.py +0 -0
  156. {auto_coder-0.1.303 → auto_coder-0.1.305}/src/autocoder/rag/loaders/__init__.py +0 -0
  157. {auto_coder-0.1.303 → auto_coder-0.1.305}/src/autocoder/rag/loaders/docx_loader.py +0 -0
  158. {auto_coder-0.1.303 → auto_coder-0.1.305}/src/autocoder/rag/loaders/excel_loader.py +0 -0
  159. {auto_coder-0.1.303 → auto_coder-0.1.305}/src/autocoder/rag/loaders/pdf_loader.py +0 -0
  160. {auto_coder-0.1.303 → auto_coder-0.1.305}/src/autocoder/rag/loaders/ppt_loader.py +0 -0
  161. {auto_coder-0.1.303 → auto_coder-0.1.305}/src/autocoder/rag/long_context_rag.py +0 -0
  162. {auto_coder-0.1.303 → auto_coder-0.1.305}/src/autocoder/rag/qa_conversation_strategy.py +0 -0
  163. {auto_coder-0.1.303 → auto_coder-0.1.305}/src/autocoder/rag/rag_config.py +0 -0
  164. {auto_coder-0.1.303 → auto_coder-0.1.305}/src/autocoder/rag/rag_entry.py +0 -0
  165. {auto_coder-0.1.303 → auto_coder-0.1.305}/src/autocoder/rag/raw_rag.py +0 -0
  166. {auto_coder-0.1.303 → auto_coder-0.1.305}/src/autocoder/rag/relevant_utils.py +0 -0
  167. {auto_coder-0.1.303 → auto_coder-0.1.305}/src/autocoder/rag/searchable.py +0 -0
  168. {auto_coder-0.1.303 → auto_coder-0.1.305}/src/autocoder/rag/simple_directory_reader.py +0 -0
  169. {auto_coder-0.1.303 → auto_coder-0.1.305}/src/autocoder/rag/simple_rag.py +0 -0
  170. {auto_coder-0.1.303 → auto_coder-0.1.305}/src/autocoder/rag/stream_event/__init__.py +0 -0
  171. {auto_coder-0.1.303 → auto_coder-0.1.305}/src/autocoder/rag/stream_event/event_writer.py +0 -0
  172. {auto_coder-0.1.303 → auto_coder-0.1.305}/src/autocoder/rag/stream_event/types.py +0 -0
  173. {auto_coder-0.1.303 → auto_coder-0.1.305}/src/autocoder/rag/token_checker.py +0 -0
  174. {auto_coder-0.1.303 → auto_coder-0.1.305}/src/autocoder/rag/token_counter.py +0 -0
  175. {auto_coder-0.1.303 → auto_coder-0.1.305}/src/autocoder/rag/token_limiter.py +0 -0
  176. {auto_coder-0.1.303 → auto_coder-0.1.305}/src/autocoder/rag/token_limiter_utils.py +0 -0
  177. {auto_coder-0.1.303 → auto_coder-0.1.305}/src/autocoder/rag/types.py +0 -0
  178. {auto_coder-0.1.303 → auto_coder-0.1.305}/src/autocoder/rag/utils.py +0 -0
  179. {auto_coder-0.1.303 → auto_coder-0.1.305}/src/autocoder/rag/variable_holder.py +0 -0
  180. {auto_coder-0.1.303 → auto_coder-0.1.305}/src/autocoder/regexproject/__init__.py +0 -0
  181. {auto_coder-0.1.303 → auto_coder-0.1.305}/src/autocoder/run_context.py +0 -0
  182. {auto_coder-0.1.303 → auto_coder-0.1.305}/src/autocoder/suffixproject/__init__.py +0 -0
  183. {auto_coder-0.1.303 → auto_coder-0.1.305}/src/autocoder/tsproject/__init__.py +0 -0
  184. {auto_coder-0.1.303 → auto_coder-0.1.305}/src/autocoder/utils/__init__.py +0 -0
  185. {auto_coder-0.1.303 → auto_coder-0.1.305}/src/autocoder/utils/_markitdown.py +0 -0
  186. {auto_coder-0.1.303 → auto_coder-0.1.305}/src/autocoder/utils/auto_coder_utils/__init__.py +0 -0
  187. {auto_coder-0.1.303 → auto_coder-0.1.305}/src/autocoder/utils/auto_project_type.py +0 -0
  188. {auto_coder-0.1.303 → auto_coder-0.1.305}/src/autocoder/utils/chat_auto_coder_utils/__init__.py +0 -0
  189. {auto_coder-0.1.303 → auto_coder-0.1.305}/src/autocoder/utils/conversation_store.py +0 -0
  190. {auto_coder-0.1.303 → auto_coder-0.1.305}/src/autocoder/utils/llm_client_interceptors.py +0 -0
  191. {auto_coder-0.1.303 → auto_coder-0.1.305}/src/autocoder/utils/llms.py +0 -0
  192. {auto_coder-0.1.303 → auto_coder-0.1.305}/src/autocoder/utils/log_capture.py +0 -0
  193. {auto_coder-0.1.303 → auto_coder-0.1.305}/src/autocoder/utils/model_provider_selector.py +0 -0
  194. {auto_coder-0.1.303 → auto_coder-0.1.305}/src/autocoder/utils/multi_turn.py +0 -0
  195. {auto_coder-0.1.303 → auto_coder-0.1.305}/src/autocoder/utils/operate_config_api.py +0 -0
  196. {auto_coder-0.1.303 → auto_coder-0.1.305}/src/autocoder/utils/print_table.py +0 -0
  197. {auto_coder-0.1.303 → auto_coder-0.1.305}/src/autocoder/utils/project_structure.py +0 -0
  198. {auto_coder-0.1.303 → auto_coder-0.1.305}/src/autocoder/utils/queue_communicate.py +0 -0
  199. {auto_coder-0.1.303 → auto_coder-0.1.305}/src/autocoder/utils/request_event_queue.py +0 -0
  200. {auto_coder-0.1.303 → auto_coder-0.1.305}/src/autocoder/utils/request_queue.py +0 -0
  201. {auto_coder-0.1.303 → auto_coder-0.1.305}/src/autocoder/utils/rest.py +0 -0
  202. {auto_coder-0.1.303 → auto_coder-0.1.305}/src/autocoder/utils/stream_thinking.py +0 -0
  203. {auto_coder-0.1.303 → auto_coder-0.1.305}/src/autocoder/utils/tests.py +0 -0
  204. {auto_coder-0.1.303 → auto_coder-0.1.305}/src/autocoder/utils/types.py +0 -0
  205. {auto_coder-0.1.303 → auto_coder-0.1.305}/tests/test_action_regex_project.py +0 -0
  206. {auto_coder-0.1.303 → auto_coder-0.1.305}/tests/test_action_yml_file_manager.py +0 -0
  207. {auto_coder-0.1.303 → auto_coder-0.1.305}/tests/test_chat_auto_coder.py +0 -0
  208. {auto_coder-0.1.303 → auto_coder-0.1.305}/tests/test_code_auto_merge_editblock.py +0 -0
  209. {auto_coder-0.1.303 → auto_coder-0.1.305}/tests/test_command_completer.py +0 -0
  210. {auto_coder-0.1.303 → auto_coder-0.1.305}/tests/test_planner.py +0 -0
  211. {auto_coder-0.1.303 → auto_coder-0.1.305}/tests/test_plugins.py +0 -0
  212. {auto_coder-0.1.303 → auto_coder-0.1.305}/tests/test_privacy.py +0 -0
  213. {auto_coder-0.1.303 → auto_coder-0.1.305}/tests/test_queue_communicate.py +0 -0
  214. {auto_coder-0.1.303 → auto_coder-0.1.305}/tests/test_symbols_utils.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: auto-coder
3
- Version: 0.1.303
3
+ Version: 0.1.305
4
4
  Summary: AutoCoder: AutoCoder
5
5
  Author: allwefantasy
6
6
  Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: auto-coder
3
- Version: 0.1.303
3
+ Version: 0.1.305
4
4
  Summary: AutoCoder: AutoCoder
5
5
  Author: allwefantasy
6
6
  Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
@@ -2594,7 +2594,7 @@ def conf_import(path: str):
2594
2594
  def auto_command(query: str,extra_args: Dict[str,Any]={}):
2595
2595
  """处理/auto指令"""
2596
2596
  from autocoder.commands.auto_command import CommandAutoTuner, AutoCommandRequest, CommandConfig, MemoryConfig
2597
- args = get_final_config()
2597
+ args = get_final_config()
2598
2598
 
2599
2599
  # 准备请求参数
2600
2600
  request = AutoCommandRequest(
@@ -623,7 +623,7 @@ def main():
623
623
 
624
624
  elif user_input.startswith("/auto"):
625
625
  query = user_input[len("/auto") :].strip()
626
- auto_command(ARGS, query)
626
+ auto_command(query)
627
627
  elif user_input.startswith("/debug"):
628
628
  code = user_input[len("/debug") :].strip()
629
629
  try:
@@ -500,10 +500,7 @@ class CommandAutoTuner:
500
500
  result_manager = ResultManager()
501
501
 
502
502
  while True:
503
- if global_cancel.requested:
504
- printer = Printer(console)
505
- printer.print_in_terminal("generation_cancelled")
506
- break
503
+ global_cancel.check_and_raise()
507
504
  # 执行命令
508
505
  command = response.suggestions[0].command
509
506
  parameters = response.suggestions[0].parameters
@@ -794,15 +794,7 @@ class AutoWebTuner:
794
794
  logger.info(f"开始执行迭代 {iterations}/{max_iterations}")
795
795
 
796
796
  # 检查是否需要取消操作
797
- if global_cancel.requested:
798
- logger.info("检测到取消请求,停止操作")
799
- self.printer.print_in_terminal(
800
- "operation_cancelled", style="yellow")
801
- return AutoWebResponse(
802
- explanation="操作已取消",
803
- overall_status="cancelled",
804
- actions=[]
805
- )
797
+ global_cancel.check_and_raise()
806
798
 
807
799
  # 如果没有更多操作,认为任务完成
808
800
  if not plan.actions:
@@ -66,6 +66,11 @@ MESSAGES = {
66
66
  "index_related_files_fail": "⚠️ Failed to find related files for chunk {{ chunk_count }}",
67
67
  "index_file_removed": "🗑️ Removed non-existent file index: {{ file_path }}",
68
68
  "index_file_saved": "💾 Saved index file, updated {{ updated_files }} files, removed {{ removed_files }} files, input_tokens: {{ input_tokens }}, output_tokens: {{ output_tokens }}, input_cost: {{ input_cost }}, output_cost: {{ output_cost }}",
69
+ "task_cancelled_by_user": "Task was cancelled by user",
70
+ "cancellation_requested": "Cancellation requested, waiting for thread to terminate...",
71
+ "force_terminating_thread": "Force terminating thread after timeout",
72
+ "force_raising_keyboard_interrupt": "Force raising KeyboardInterrupt after timeout",
73
+ "thread_terminated": "Thread terminated",
69
74
  "human_as_model_instructions": (
70
75
  "You are now in Human as Model mode. The content has been copied to your clipboard.\n"
71
76
  "The system is waiting for your input. When finished, enter 'EOF' on a new line to submit.\n"
@@ -156,7 +161,6 @@ MESSAGES = {
156
161
  "generated_shell_script": "Generated Shell Script",
157
162
  "confirm_execute_shell_script": "Do you want to execute this shell script?",
158
163
  "shell_script_not_executed": "Shell script was not executed",
159
- "conf_not_found": "Configuration file not found: {{path}}",
160
164
  "index_export_success": "Index exported successfully: {{path}}",
161
165
  "index_import_success": "Index imported successfully: {{path}}",
162
166
  "edits_title": "edits",
@@ -279,6 +283,11 @@ MESSAGES = {
279
283
  "index_related_files_fail": "⚠️ 无法为块 {{ chunk_count }} 找到相关文件",
280
284
  "index_file_removed": "🗑️ 已移除不存在的文件索引:{{ file_path }}",
281
285
  "index_file_saved": "💾 已保存索引文件,更新了 {{ updated_files }} 个文件,移除了 {{ removed_files }} 个文件,输入token数: {{ input_tokens }}, 输出token数: {{ output_tokens }}, 输入成本: {{ input_cost }}, 输出成本: {{ output_cost }}",
286
+ "task_cancelled_by_user": "任务被用户取消",
287
+ "cancellation_requested": "已请求取消,正在等待线程终止...",
288
+ "force_terminating_thread": "线程超时强制终止",
289
+ "force_raising_keyboard_interrupt": "超时强制抛出键盘中断异常",
290
+ "thread_terminated": "线程已终止",
282
291
  "human_as_model_instructions": (
283
292
  "您现在处于人类作为模型模式。内容已复制到您的剪贴板。\n"
284
293
  "系统正在等待您的输入。完成后,在新行输入'EOF'提交。\n"
@@ -0,0 +1,82 @@
1
+ import threading
2
+ from typing import Dict, Optional, Any
3
+
4
+ class CancelRequestedException(Exception):
5
+ """当取消请求被触发时抛出的异常"""
6
+ def __init__(self, token: Optional[str] = None, message: str = "Operation was cancelled"):
7
+ self.token = token
8
+ self.message = message
9
+ super().__init__(self.message)
10
+
11
+ class GlobalCancel:
12
+ def __init__(self):
13
+ self._global_flag = False
14
+ self._token_flags: Dict[str, bool] = {}
15
+ self._lock = threading.Lock()
16
+ self._context: Dict[str, Any] = {} # 存储与取消相关的上下文信息
17
+
18
+ @property
19
+ def requested(self) -> bool:
20
+ """检查是否请求了全局取消(向后兼容)"""
21
+ with self._lock:
22
+ return self._global_flag
23
+
24
+ def is_requested(self, token: Optional[str] = None) -> bool:
25
+ """检查是否请求了特定token或全局的取消"""
26
+ with self._lock:
27
+ # 全局标志总是优先
28
+ if self._global_flag:
29
+ return True
30
+ # 如果提供了token,检查该token的标志
31
+ if token is not None and token in self._token_flags:
32
+ return self._token_flags[token]
33
+ return False
34
+
35
+ def set(self, token: Optional[str] = None, context: Optional[Dict[str, Any]] = None) -> None:
36
+ """设置特定token或全局的取消标志"""
37
+ with self._lock:
38
+ if token is None:
39
+ self._global_flag = True
40
+ else:
41
+ self._token_flags[token] = True
42
+
43
+ # 存储上下文
44
+ if context:
45
+ if token is None:
46
+ self._context.update(context)
47
+ else:
48
+ if "tokens" not in self._context:
49
+ self._context["tokens"] = {}
50
+ self._context["tokens"][token] = context
51
+
52
+ def reset(self, token: Optional[str] = None) -> None:
53
+ """重置特定token或全局的取消标志"""
54
+ with self._lock:
55
+ if token is None:
56
+ # 全局重置
57
+ self._global_flag = False
58
+ self._token_flags.clear()
59
+ self._context.clear()
60
+ else:
61
+ # 特定token重置
62
+ if token in self._token_flags:
63
+ del self._token_flags[token]
64
+ if "tokens" in self._context and token in self._context["tokens"]:
65
+ del self._context["tokens"][token]
66
+
67
+ def get_context(self, token: Optional[str] = None) -> Dict[str, Any]:
68
+ """获取与取消相关的上下文信息"""
69
+ with self._lock:
70
+ if token is None:
71
+ return self._context.copy()
72
+ if "tokens" in self._context and token in self._context["tokens"]:
73
+ return self._context["tokens"][token].copy()
74
+ return {}
75
+
76
+ def check_and_raise(self, token: Optional[str] = None) -> None:
77
+ """检查是否请求了取消,如果是则抛出异常"""
78
+ if self.is_requested(token):
79
+ context = self.get_context(token)
80
+ raise CancelRequestedException(token, context.get("message", "Operation was cancelled"))
81
+
82
+ global_cancel = GlobalCancel()
@@ -112,10 +112,7 @@ class ActionTSProject(BaseAction):
112
112
  f"Content(send to model) is {content_length} tokens, which is larger than the maximum input length {self.args.model_max_input_length}"
113
113
  )
114
114
 
115
- if global_cancel.requested:
116
- printer = Printer()
117
- raise Exception(printer.get_message_from_key(
118
- "generation_cancelled"))
115
+ global_cancel.check_and_raise()
119
116
 
120
117
  if args.execute:
121
118
  self.printer.print_in_terminal("code_generation_start")
@@ -181,10 +178,7 @@ class ActionTSProject(BaseAction):
181
178
  action_file=self.args.file
182
179
  ).to_dict())
183
180
 
184
- if global_cancel.requested:
185
- printer = Printer()
186
- raise Exception(printer.get_message_from_key(
187
- "generation_cancelled"))
181
+ global_cancel.check_and_raise()
188
182
 
189
183
  merge_result = None
190
184
  if args.execute and args.auto_merge:
@@ -249,10 +243,7 @@ class ActionPyScriptProject(BaseAction):
249
243
 
250
244
  def process_content(self, source_code_list: SourceCodeList):
251
245
  args = self.args
252
- if global_cancel.requested:
253
- printer = Printer()
254
- raise Exception(printer.get_message_from_key(
255
- "generation_cancelled"))
246
+ global_cancel.check_and_raise()
256
247
 
257
248
  if args.execute:
258
249
  self.printer.print_in_terminal("code_generation_start")
@@ -318,10 +309,7 @@ class ActionPyScriptProject(BaseAction):
318
309
  action_file=self.args.file
319
310
  ).to_dict())
320
311
 
321
- if global_cancel.requested:
322
- printer = Printer()
323
- raise Exception(printer.get_message_from_key(
324
- "generation_cancelled"))
312
+ global_cancel.check_and_raise()
325
313
 
326
314
  merge_result = None
327
315
  if args.execute and args.auto_merge:
@@ -410,10 +398,7 @@ class ActionPyProject(BaseAction):
410
398
  max_length=self.args.model_max_input_length
411
399
  )
412
400
 
413
- if global_cancel.requested:
414
- printer = Printer()
415
- raise Exception(printer.get_message_from_key(
416
- "generation_cancelled"))
401
+ global_cancel.check_and_raise()
417
402
 
418
403
  if args.execute:
419
404
  self.printer.print_in_terminal("code_generation_start")
@@ -479,10 +464,7 @@ class ActionPyProject(BaseAction):
479
464
  action_file=self.args.file
480
465
  ).to_dict())
481
466
 
482
- if global_cancel.requested:
483
- printer = Printer()
484
- raise Exception(printer.get_message_from_key(
485
- "generation_cancelled"))
467
+ global_cancel.check_and_raise()
486
468
 
487
469
  merge_result = None
488
470
  if args.execute and args.auto_merge:
@@ -563,10 +545,7 @@ class ActionSuffixProject(BaseAction):
563
545
  f"Content(send to model) is {content_length} tokens, which is larger than the maximum input length {self.args.model_max_input_length}"
564
546
  )
565
547
 
566
- if global_cancel.requested:
567
- printer = Printer()
568
- raise Exception(printer.get_message_from_key(
569
- "generation_cancelled"))
548
+ global_cancel.check_and_raise()
570
549
 
571
550
  if args.execute:
572
551
  self.printer.print_in_terminal("code_generation_start")
@@ -631,10 +610,7 @@ class ActionSuffixProject(BaseAction):
631
610
  action_file=self.args.file
632
611
  ).to_dict())
633
612
 
634
- if global_cancel.requested:
635
- printer = Printer()
636
- raise Exception(printer.get_message_from_key(
637
- "generation_cancelled"))
613
+ global_cancel.check_and_raise()
638
614
 
639
615
  merge_result = None
640
616
  if args.execute and args.auto_merge:
@@ -66,9 +66,7 @@ class ActionRegexProject:
66
66
 
67
67
  start_time = time.time()
68
68
 
69
- if global_cancel.requested:
70
- printer = Printer()
71
- raise Exception(printer.get_message_from_key("generation_cancelled"))
69
+ global_cancel.check_and_raise()
72
70
 
73
71
  if args.execute:
74
72
  self.printer.print_in_terminal("code_generation_start")
@@ -128,9 +126,7 @@ class ActionRegexProject:
128
126
  action_file=self.args.file
129
127
  ).to_dict())
130
128
 
131
- if global_cancel.requested:
132
- printer = Printer()
133
- raise Exception(printer.get_message_from_key("generation_cancelled"))
129
+ global_cancel.check_and_raise()
134
130
 
135
131
  merge_result = None
136
132
  if args.execute and args.auto_merge:
@@ -296,8 +296,7 @@ class IndexManager:
296
296
  return False
297
297
 
298
298
  def build_index_for_single_source(self, source: SourceCode):
299
- if global_cancel.requested:
300
- return None
299
+ global_cancel.check_and_raise()
301
300
 
302
301
  file_path = source.module_name
303
302
  if not os.path.exists(file_path):
@@ -552,8 +551,7 @@ class IndexManager:
552
551
  for source in wait_to_build_files
553
552
  ]
554
553
  for future in as_completed(futures):
555
- if global_cancel.requested:
556
- break
554
+ global_cancel.check_and_raise()
557
555
  result = future.result()
558
556
  if result is not None:
559
557
  counter += 1
@@ -13,7 +13,7 @@ from autocoder.utils.request_queue import request_queue
13
13
  import time
14
14
  from byzerllm.utils.types import SingleOutputMeta
15
15
  from autocoder.common import AutoCoderArgs
16
- from autocoder.common.global_cancel import global_cancel
16
+ from autocoder.common.global_cancel import global_cancel, CancelRequestedException
17
17
  from autocoder.events.event_manager_singleton import get_event_manager
18
18
  from autocoder.events import event_content as EventContentCreator
19
19
  from autocoder.events.event_types import EventMetadata
@@ -68,23 +68,35 @@ class MultiStreamRenderer:
68
68
 
69
69
  def _process_stream(self,
70
70
  stream_idx: int,
71
- stream_generator: Generator[Tuple[str, Dict[str, Any]], None, None]):
71
+ stream_generator: Generator[Tuple[str, Dict[str, Any]], None, None],
72
+ cancel_token: Optional[str] = None):
72
73
  """Process a single stream in a separate thread"""
73
74
  stream = self.streams[stream_idx]
74
75
  try:
75
76
  for content, meta in stream_generator:
77
+ try:
78
+ # 使用新的异常机制检查取消请求
79
+ global_cancel.check_and_raise(cancel_token)
80
+ except CancelRequestedException:
81
+ break
82
+
76
83
  if content:
77
84
  stream.update(content)
85
+ except CancelRequestedException:
86
+ # 处理取消异常
87
+ stream.update("\n\n**Operation was cancelled**")
78
88
  finally:
79
89
  stream.complete()
80
90
 
81
91
  def render_streams(self,
82
- stream_generators: List[Generator[Tuple[str, Dict[str, Any]], None, None]]) -> List[str]:
92
+ stream_generators: List[Generator[Tuple[str, Dict[str, Any]], None, None]],
93
+ cancel_token: Optional[str] = None) -> List[str]:
83
94
  """
84
95
  Render multiple streams simultaneously
85
96
 
86
97
  Args:
87
98
  stream_generators: List of stream generators to render
99
+ cancel_token: Optional cancellation token
88
100
 
89
101
  Returns:
90
102
  List of final content from each stream
@@ -94,7 +106,7 @@ class MultiStreamRenderer:
94
106
  # Start processing threads
95
107
  threads = []
96
108
  for i, generator in enumerate(stream_generators):
97
- thread = Thread(target=self._process_stream, args=(i, generator))
109
+ thread = Thread(target=self._process_stream, args=(i, generator, cancel_token))
98
110
  thread.daemon = True
99
111
  thread.start()
100
112
  threads.append(thread)
@@ -102,6 +114,13 @@ class MultiStreamRenderer:
102
114
  try:
103
115
  with Live(self.layout, console=self.console, refresh_per_second=10) as live:
104
116
  while any(not stream.is_complete for stream in self.streams):
117
+ try:
118
+ # 使用新的异常机制检查取消请求
119
+ global_cancel.check_and_raise(cancel_token)
120
+ except CancelRequestedException:
121
+ print("\nCancelling streams...")
122
+ break
123
+
105
124
  # Update all panels
106
125
  for i, stream in enumerate(self.streams):
107
126
  panel = Panel(
@@ -116,7 +135,11 @@ class MultiStreamRenderer:
116
135
  time.sleep(0.1) # Prevent excessive CPU usage
117
136
 
118
137
  except KeyboardInterrupt:
138
+ # 键盘中断时设置取消标志
139
+ global_cancel.set(cancel_token, {"message": "Keyboard interrupt"})
119
140
  print("\nStopping streams...")
141
+ except CancelRequestedException:
142
+ print("\nCancelling streams...")
120
143
 
121
144
  # Wait for all threads to complete
122
145
  for thread in threads:
@@ -128,7 +151,8 @@ def multi_stream_out(
128
151
  stream_generators: List[Generator[Tuple[str, Dict[str, Any]], None, None]],
129
152
  titles: List[str],
130
153
  layout: str = "horizontal",
131
- console: Optional[Console] = None
154
+ console: Optional[Console] = None,
155
+ cancel_token: Optional[str] = None
132
156
  ) -> List[str]:
133
157
  """
134
158
  Render multiple streams with Rich
@@ -138,12 +162,13 @@ def multi_stream_out(
138
162
  titles: List of titles for each stream
139
163
  layout: "horizontal" or "vertical"
140
164
  console: Optional Rich console instance
165
+ cancel_token: Optional cancellation token
141
166
 
142
167
  Returns:
143
168
  List of final content from each stream
144
169
  """
145
170
  renderer = MultiStreamRenderer(titles, layout, console)
146
- return renderer.render_streams(stream_generators)
171
+ return renderer.render_streams(stream_generators, cancel_token)
147
172
 
148
173
 
149
174
  def stream_out(
@@ -155,7 +180,8 @@ def stream_out(
155
180
  final_title: Optional[str] = None,
156
181
  args: Optional[AutoCoderArgs] = None,
157
182
  display_func: Optional[Callable] = None,
158
- extra_meta: Dict[str, Any] = {}
183
+ extra_meta: Dict[str, Any] = {},
184
+ cancel_token: Optional[str] = None
159
185
  ) -> Tuple[str, Optional[SingleOutputMeta]]:
160
186
  """
161
187
  处理流式输出事件并在终端中展示
@@ -167,6 +193,9 @@ def stream_out(
167
193
  model_name: 模型名称
168
194
  title: 面板标题,如果没有提供则使用默认值
169
195
  args: AutoCoderArgs对象
196
+ display_func: 可选的显示函数
197
+ extra_meta: 额外的元数据
198
+ cancel_token: 可选的取消令牌
170
199
  Returns:
171
200
  Tuple[str, Dict[SingleOutputMeta]]: 返回完整的响应内容和最后的元数据
172
201
  """
@@ -197,10 +226,8 @@ def stream_out(
197
226
  console=console
198
227
  ) as live:
199
228
  for res in stream_generator:
200
- if global_cancel.requested:
201
- printer = Printer(console)
202
- printer.print_in_terminal("generation_cancelled")
203
- break
229
+ global_cancel.check_and_raise(cancel_token)
230
+
204
231
  last_meta = res[1]
205
232
  content = res[0]
206
233
 
@@ -312,6 +339,24 @@ def stream_out(
312
339
  )
313
340
  )
314
341
 
342
+ except CancelRequestedException as cancel_exc:
343
+ # 捕获取消异常,显示取消信息
344
+ console.print(Panel(
345
+ "Generation was cancelled",
346
+ title=f"Cancelled[ {panel_title} ]",
347
+ border_style="yellow"
348
+ ))
349
+
350
+ if request_id and request_queue:
351
+ request_queue.add_request(
352
+ request_id,
353
+ RequestValue(
354
+ value=StreamValue(value=["Operation was cancelled"]),
355
+ status=RequestOption.FAILED
356
+ ),
357
+ )
358
+ raise cancel_exc
359
+
315
360
  except Exception as e:
316
361
  console.print(Panel(
317
362
  f"Error: {str(e)}",
@@ -0,0 +1,119 @@
1
+ from functools import wraps
2
+ from typing import Any, Optional, Dict, Callable
3
+ import threading
4
+ import time
5
+ from autocoder.common.global_cancel import global_cancel, CancelRequestedException
6
+ from autocoder.common.printer import Printer
7
+ from autocoder.common.auto_coder_lang import get_message, get_message_with_format
8
+ from autocoder.events.event_manager_singleton import get_event_manager
9
+ from autocoder.events import event_content as EventContentCreator
10
+ from autocoder.events.event_types import EventMetadata
11
+
12
+ printer = Printer()
13
+
14
+ def run_in_raw_thread(token: Optional[str] = None, context: Optional[Dict[str, Any]] = None):
15
+ """A decorator that runs a function in a separate thread and handles exceptions.
16
+
17
+ Args:
18
+ token (Optional[str]): Optional cancellation token for this specific thread
19
+ context (Optional[Dict[str, Any]]): Optional context information for cancellation
20
+
21
+ Returns:
22
+ A wrapper function that executes the decorated function in a thread
23
+
24
+ The decorator will:
25
+ 1. Run the function in a separate thread
26
+ 2. Handle KeyboardInterrupt properly
27
+ 3. Propagate exceptions from the thread
28
+ 4. Support function arguments
29
+ 5. Preserve function metadata
30
+ 6. Support token-based cancellation
31
+ 7. Provide context information for cancellation
32
+ """
33
+ def decorator(func: Callable):
34
+
35
+ @wraps(func)
36
+ def wrapper(*args, **kwargs):
37
+ # Store thread results
38
+ result = []
39
+ exception_raised = [None] # 存储工作线程中的异常
40
+ thread_token = token
41
+ thread_context = context or {}
42
+ thread_terminated = threading.Event() # 用于标记线程是否已终止
43
+
44
+ def worker():
45
+ try:
46
+ # 执行用户函数
47
+ ret = func(*args, **kwargs)
48
+ result.append(ret)
49
+ except CancelRequestedException as e:
50
+ # 处理取消异常
51
+ printer.print_in_terminal("generation_cancelled")
52
+ exception_raised[0] = e
53
+ except Exception as e:
54
+ # 存储其他异常
55
+ exception_raised[0] = e
56
+ finally:
57
+ # 无论如何执行完毕后,重置取消标志并标记线程已终止
58
+ global_cancel.reset(thread_token)
59
+ thread_terminated.set()
60
+
61
+ # Create and start thread with a meaningful name
62
+ thread = threading.Thread(target=worker, name=f"{func.__name__}_thread")
63
+ thread.daemon = True # Make thread daemon so it doesn't prevent program exit
64
+
65
+ try:
66
+ thread.start()
67
+
68
+ # Poll thread status with timeout to allow for interruption
69
+ cancelled_by_keyboard = False
70
+ max_wait_time = 30 # 最大等待时间(秒)
71
+ wait_start_time = time.time()
72
+
73
+ while thread.is_alive():
74
+ # 每次等待较短时间,以便能够及时响应中断
75
+ thread.join(0.1)
76
+
77
+ # 检查是否已经超过最大等待时间(仅适用于已取消的情况)
78
+ elapsed_time = time.time() - wait_start_time
79
+ if cancelled_by_keyboard and elapsed_time > max_wait_time:
80
+ printer.print_in_terminal("force_terminating_thread")
81
+ break
82
+
83
+ # 检查线程间的取消请求
84
+ if global_cancel.is_requested(thread_token):
85
+ # 传播取消请求到工作线程
86
+ raise CancelRequestedException(thread_token)
87
+
88
+ # 如果工作线程出现了异常,在主线程中重新抛出
89
+ if exception_raised[0] is not None:
90
+ raise exception_raised[0]
91
+
92
+ # 返回结果
93
+ return result[0] if result else None
94
+
95
+ except KeyboardInterrupt:
96
+ # 设置取消标志
97
+ cancel_context = {"message": get_message("task_cancelled_by_user"), "source": "keyboard_interrupt"}
98
+ cancel_context.update(thread_context)
99
+ global_cancel.set(thread_token, cancel_context)
100
+ printer.print_in_terminal("cancellation_requested")
101
+
102
+ # 标记为键盘中断取消
103
+ cancelled_by_keyboard = True
104
+ wait_start_time = time.time()
105
+
106
+ # 等待线程终止或检测到取消
107
+ while thread.is_alive() and not thread_terminated.is_set():
108
+ thread.join(0.5)
109
+ elapsed_time = time.time() - wait_start_time
110
+ if elapsed_time > max_wait_time:
111
+ printer.print_in_terminal("force_raising_keyboard_interrupt")
112
+ break
113
+
114
+ # 如果线程已终止且有异常,优先抛出该异常
115
+ if exception_raised[0] is not None:
116
+ raise exception_raised[0]
117
+
118
+ return wrapper
119
+ return decorator
@@ -0,0 +1 @@
1
+ __version__ = "0.1.305"
@@ -1,21 +0,0 @@
1
- import threading
2
-
3
- class GlobalCancel:
4
- def __init__(self):
5
- self._flag = False
6
- self._lock = threading.Lock()
7
-
8
- @property
9
- def requested(self):
10
- with self._lock:
11
- return self._flag
12
-
13
- def set(self):
14
- with self._lock:
15
- self._flag = True
16
-
17
- def reset(self):
18
- with self._lock:
19
- self._flag = False
20
-
21
- global_cancel = GlobalCancel()