codebuff-agent 2.1.74__py3-none-any.whl

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.
Files changed (217) hide show
  1. codebuff_agent-2.1.74.data/data/etc/jupyter/jupyter_server_config.d/codebuff_agent.json +7 -0
  2. codebuff_agent-2.1.74.data/data/share/jupyter/labextensions/codebuff/package.json +157 -0
  3. codebuff_agent-2.1.74.data/data/share/jupyter/labextensions/codebuff/static/104.2b8f20f9d1ac2c9db01b.js +1 -0
  4. codebuff_agent-2.1.74.data/data/share/jupyter/labextensions/codebuff/static/150.39fa98117cc8ca590465.js +1 -0
  5. codebuff_agent-2.1.74.data/data/share/jupyter/labextensions/codebuff/static/166.386ff9b2c37ac865fdee.js +1 -0
  6. codebuff_agent-2.1.74.data/data/share/jupyter/labextensions/codebuff/static/216.25cf81131bf7274dabf4.js +1 -0
  7. codebuff_agent-2.1.74.data/data/share/jupyter/labextensions/codebuff/static/353.581bd1cb00746399b62e.js +1 -0
  8. codebuff_agent-2.1.74.data/data/share/jupyter/labextensions/codebuff/static/367.575f9621b63c9a641aa9.js +1 -0
  9. codebuff_agent-2.1.74.data/data/share/jupyter/labextensions/codebuff/static/421.11dac223a2c2da1b09f5.js +1 -0
  10. codebuff_agent-2.1.74.data/data/share/jupyter/labextensions/codebuff/static/432.8513b4c6cc1d1232d165.js +2 -0
  11. codebuff_agent-2.1.74.data/data/share/jupyter/labextensions/codebuff/static/432.8513b4c6cc1d1232d165.js.LICENSE.txt +19 -0
  12. codebuff_agent-2.1.74.data/data/share/jupyter/labextensions/codebuff/static/439.ba5b5ef70ec6de214b8c.js +2 -0
  13. codebuff_agent-2.1.74.data/data/share/jupyter/labextensions/codebuff/static/439.ba5b5ef70ec6de214b8c.js.LICENSE.txt +8 -0
  14. codebuff_agent-2.1.74.data/data/share/jupyter/labextensions/codebuff/static/481.cc2dec9fa869d66f1407.js +1 -0
  15. codebuff_agent-2.1.74.data/data/share/jupyter/labextensions/codebuff/static/487.0796e931d6e651482c14.js +1 -0
  16. codebuff_agent-2.1.74.data/data/share/jupyter/labextensions/codebuff/static/49.d326f554b6f9ccde6580.js +1 -0
  17. codebuff_agent-2.1.74.data/data/share/jupyter/labextensions/codebuff/static/541.26897ea32845659e36be.js +1 -0
  18. codebuff_agent-2.1.74.data/data/share/jupyter/labextensions/codebuff/static/579.e569d3edd8391fd8fbb3.js +1 -0
  19. codebuff_agent-2.1.74.data/data/share/jupyter/labextensions/codebuff/static/58.eb7cc679f7535cc8a2f1.js +2 -0
  20. codebuff_agent-2.1.74.data/data/share/jupyter/labextensions/codebuff/static/58.eb7cc679f7535cc8a2f1.js.LICENSE.txt +8 -0
  21. codebuff_agent-2.1.74.data/data/share/jupyter/labextensions/codebuff/static/666.d9bfdb23f98489d0a188.js +1 -0
  22. codebuff_agent-2.1.74.data/data/share/jupyter/labextensions/codebuff/static/677.d266c39dbed33bc388b3.js +2 -0
  23. codebuff_agent-2.1.74.data/data/share/jupyter/labextensions/codebuff/static/677.d266c39dbed33bc388b3.js.LICENSE.txt +8 -0
  24. codebuff_agent-2.1.74.data/data/share/jupyter/labextensions/codebuff/static/68.26b6f59c8454adb17f20.js +204 -0
  25. codebuff_agent-2.1.74.data/data/share/jupyter/labextensions/codebuff/static/694.4ac443814260057e68f7.js +1 -0
  26. codebuff_agent-2.1.74.data/data/share/jupyter/labextensions/codebuff/static/791.61affb8d3480d3d60e0d.js +1 -0
  27. codebuff_agent-2.1.74.data/data/share/jupyter/labextensions/codebuff/static/848.4d2db09cfbb09374b299.js +2 -0
  28. codebuff_agent-2.1.74.data/data/share/jupyter/labextensions/codebuff/static/848.4d2db09cfbb09374b299.js.LICENSE.txt +9 -0
  29. codebuff_agent-2.1.74.data/data/share/jupyter/labextensions/codebuff/static/868.5cfe7e1a348ec5af1b8c.js +1 -0
  30. codebuff_agent-2.1.74.data/data/share/jupyter/labextensions/codebuff/static/97.ea559a5b8a9a09f17c6b.js +1 -0
  31. codebuff_agent-2.1.74.data/data/share/jupyter/labextensions/codebuff/static/remoteEntry.5292fc9c6df7e7920cc8.js +1 -0
  32. codebuff_agent-2.1.74.data/data/share/jupyter/labextensions/codebuff/static/style.js +4 -0
  33. codebuff_agent-2.1.74.data/data/share/jupyter/labextensions/codebuff/static/third-party-licenses.json +724 -0
  34. codebuff_agent-2.1.74.dist-info/METADATA +142 -0
  35. codebuff_agent-2.1.74.dist-info/RECORD +217 -0
  36. codebuff_agent-2.1.74.dist-info/WHEEL +4 -0
  37. codebuff_agent-2.1.74.dist-info/licenses/LICENSE +21 -0
  38. codebuff_core/__init__.py +153 -0
  39. codebuff_core/codebuff_config_defaults.json +64 -0
  40. codebuff_core/core/__init__.py +35 -0
  41. codebuff_core/core/code_validator.py +1238 -0
  42. codebuff_core/core/error_classifier.py +579 -0
  43. codebuff_core/core/exceptions.py +49 -0
  44. codebuff_core/data/tiktoken_cache/9b5ad71b2ce5302211f9c61530b329a4922fc6a4 +100256 -0
  45. codebuff_core/directory_policy.py +32 -0
  46. codebuff_core/factory.py +155 -0
  47. codebuff_core/interfaces.py +197 -0
  48. codebuff_core/knowledge/__init__.py +31 -0
  49. codebuff_core/knowledge/chunking.py +375 -0
  50. codebuff_core/knowledge/loader.py +339 -0
  51. codebuff_core/knowledge/watchdog_service.py +354 -0
  52. codebuff_core/legacy_paths.py +69 -0
  53. codebuff_core/llm/__init__.py +13 -0
  54. codebuff_core/llm/service.py +407 -0
  55. codebuff_core/managers/__init__.py +22 -0
  56. codebuff_core/managers/config_manager.py +690 -0
  57. codebuff_core/managers/remote_config.py +673 -0
  58. codebuff_core/managers/remote_skills.py +539 -0
  59. codebuff_core/managers/session_manager.py +255 -0
  60. codebuff_core/middleware/__init__.py +3 -0
  61. codebuff_core/middleware/error_recovery.py +394 -0
  62. codebuff_core/middleware/logging_utils.py +33 -0
  63. codebuff_core/models/__init__.py +111 -0
  64. codebuff_core/models/agent.py +306 -0
  65. codebuff_core/models/chat.py +57 -0
  66. codebuff_core/models/common.py +82 -0
  67. codebuff_core/models/rag.py +300 -0
  68. codebuff_core/platform_rules.py +127 -0
  69. codebuff_core/prompts/__init__.py +44 -0
  70. codebuff_core/prompts/auto_agent_prompts.py +1278 -0
  71. codebuff_core/services/__init__.py +30 -0
  72. codebuff_core/services/agent_service.py +345 -0
  73. codebuff_core/services/analytics_aggregate.py +837 -0
  74. codebuff_core/services/chat_service.py +898 -0
  75. codebuff_core/services/context_condenser.py +306 -0
  76. codebuff_core/services/pii_guardrail.py +393 -0
  77. codebuff_core/services/rag_chat_agent.py +2993 -0
  78. codebuff_core/services/rag_collections.py +2740 -0
  79. codebuff_core/services/rag_manager.py +890 -0
  80. codebuff_core/services/rag_service.py +145 -0
  81. codebuff_core/services/retriever.py +260 -0
  82. codebuff_core/services/vllm_embedding_service.py +290 -0
  83. codebuff_core/tests/__init__.py +1 -0
  84. codebuff_core/tests/conftest.py +81 -0
  85. codebuff_core/tests/test_error_recovery.py +647 -0
  86. codebuff_core/tests/test_factory.py +135 -0
  87. codebuff_core/tests/test_services.py +150 -0
  88. jupyter_ext/__init__.py +266 -0
  89. jupyter_ext/_version.py +4 -0
  90. jupyter_ext/agent/__init__.py +49 -0
  91. jupyter_ext/agent/agent_factory.py +2270 -0
  92. jupyter_ext/agent/ast_tools.py +451 -0
  93. jupyter_ext/agent/autofix_middleware.py +481 -0
  94. jupyter_ext/agent/background_procs.py +372 -0
  95. jupyter_ext/agent/code_history_middleware.py +211 -0
  96. jupyter_ext/agent/codex_autofix.py +160 -0
  97. jupyter_ext/agent/codex_bridge.py +3339 -0
  98. jupyter_ext/agent/codex_hooks.py +320 -0
  99. jupyter_ext/agent/codex_slash.py +685 -0
  100. jupyter_ext/agent/codex_threads.py +114 -0
  101. jupyter_ext/agent/content_injection.py +377 -0
  102. jupyter_ext/agent/continuation_middleware.py +548 -0
  103. jupyter_ext/agent/custom_skills.py +335 -0
  104. jupyter_ext/agent/file_diffs.py +99 -0
  105. jupyter_ext/agent/git_history.py +188 -0
  106. jupyter_ext/agent/guardrail_middleware.py +421 -0
  107. jupyter_ext/agent/json_repair_utils.py +54 -0
  108. jupyter_ext/agent/langchain_tools.py +2673 -0
  109. jupyter_ext/agent/mermaid_fixer.py +289 -0
  110. jupyter_ext/agent/mermaid_middleware.py +135 -0
  111. jupyter_ext/agent/middleware.py +359 -0
  112. jupyter_ext/agent/middleware_prompts.py +53 -0
  113. jupyter_ext/agent/observability.py +334 -0
  114. jupyter_ext/agent/patch_tool_calls.py +57 -0
  115. jupyter_ext/agent/prompts.py +112 -0
  116. jupyter_ext/agent/skill_middleware.py +257 -0
  117. jupyter_ext/agent/skills/airflow_dag_development.md +36 -0
  118. jupyter_ext/agent/skills/anomaly_detection.md +12 -0
  119. jupyter_ext/agent/skills/athena_sql.md +156 -0
  120. jupyter_ext/agent/skills/bdp_table_search.md +33 -0
  121. jupyter_ext/agent/skills/bigquery.md +65 -0
  122. jupyter_ext/agent/skills/bigquery_oracle.md +231 -0
  123. jupyter_ext/agent/skills/bigquery_tuning.md +307 -0
  124. jupyter_ext/agent/skills/classification_evaluation.md +11 -0
  125. jupyter_ext/agent/skills/clustering_analysis.md +12 -0
  126. jupyter_ext/agent/skills/comprehensive_eda.md +11 -0
  127. jupyter_ext/agent/skills/data_analysis.md +236 -0
  128. jupyter_ext/agent/skills/data_cleaning_pipeline.md +12 -0
  129. jupyter_ext/agent/skills/data_loading.md +158 -0
  130. jupyter_ext/agent/skills/data_quality_report.md +13 -0
  131. jupyter_ext/agent/skills/dimensionality_reduction.md +12 -0
  132. jupyter_ext/agent/skills/emr_script_development.md +17 -0
  133. jupyter_ext/agent/skills/experiment_tracking.md +13 -0
  134. jupyter_ext/agent/skills/feature_importance_analysis.md +10 -0
  135. jupyter_ext/agent/skills/hyperparameter_tuning.md +12 -0
  136. jupyter_ext/agent/skills/hypothesis_testing.md +12 -0
  137. jupyter_ext/agent/skills/imbalanced_data_handling.md +12 -0
  138. jupyter_ext/agent/skills/inference.md +392 -0
  139. jupyter_ext/agent/skills/lambda_function_development.md +19 -0
  140. jupyter_ext/agent/skills/model_comparison.md +11 -0
  141. jupyter_ext/agent/skills/model_explainability.md +12 -0
  142. jupyter_ext/agent/skills/model_training.md +318 -0
  143. jupyter_ext/agent/skills/pyspark.md +352 -0
  144. jupyter_ext/agent/skills/python_code_quality.md +35 -0
  145. jupyter_ext/agent/skills/regression_evaluation.md +12 -0
  146. jupyter_ext/agent/skills/spring_java_development.md +35 -0
  147. jupyter_ext/agent/skills/text_preprocessing.md +12 -0
  148. jupyter_ext/agent/skills/time_series_analysis.md +13 -0
  149. jupyter_ext/agent/skills/unit_testing.md +203 -0
  150. jupyter_ext/agent/todo_prompts.py +57 -0
  151. jupyter_ext/agent/tool_report.py +45 -0
  152. jupyter_ext/analytics_ingest.py +599 -0
  153. jupyter_ext/etc/jupyter/jupyter_server_config.d/codebuff_agent.json +7 -0
  154. jupyter_ext/handlers/__init__.py +8 -0
  155. jupyter_ext/handlers/analytics_handler.py +170 -0
  156. jupyter_ext/handlers/benchmark_handler.py +794 -0
  157. jupyter_ext/handlers/eda_benchmark_handler.py +1328 -0
  158. jupyter_ext/handlers/rag_admin_handler.py +689 -0
  159. jupyter_ext/handlers/websocket.py +497 -0
  160. jupyter_ext/http_handlers.py +8744 -0
  161. jupyter_ext/idle_monitor.py +346 -0
  162. jupyter_ext/labextension/package.json +157 -0
  163. jupyter_ext/labextension/static/104.2b8f20f9d1ac2c9db01b.js +1 -0
  164. jupyter_ext/labextension/static/150.39fa98117cc8ca590465.js +1 -0
  165. jupyter_ext/labextension/static/166.386ff9b2c37ac865fdee.js +1 -0
  166. jupyter_ext/labextension/static/216.25cf81131bf7274dabf4.js +1 -0
  167. jupyter_ext/labextension/static/353.581bd1cb00746399b62e.js +1 -0
  168. jupyter_ext/labextension/static/367.575f9621b63c9a641aa9.js +1 -0
  169. jupyter_ext/labextension/static/421.11dac223a2c2da1b09f5.js +1 -0
  170. jupyter_ext/labextension/static/432.8513b4c6cc1d1232d165.js +2 -0
  171. jupyter_ext/labextension/static/432.8513b4c6cc1d1232d165.js.LICENSE.txt +19 -0
  172. jupyter_ext/labextension/static/439.ba5b5ef70ec6de214b8c.js +2 -0
  173. jupyter_ext/labextension/static/439.ba5b5ef70ec6de214b8c.js.LICENSE.txt +8 -0
  174. jupyter_ext/labextension/static/481.cc2dec9fa869d66f1407.js +1 -0
  175. jupyter_ext/labextension/static/487.0796e931d6e651482c14.js +1 -0
  176. jupyter_ext/labextension/static/49.d326f554b6f9ccde6580.js +1 -0
  177. jupyter_ext/labextension/static/541.26897ea32845659e36be.js +1 -0
  178. jupyter_ext/labextension/static/579.e569d3edd8391fd8fbb3.js +1 -0
  179. jupyter_ext/labextension/static/58.eb7cc679f7535cc8a2f1.js +2 -0
  180. jupyter_ext/labextension/static/58.eb7cc679f7535cc8a2f1.js.LICENSE.txt +8 -0
  181. jupyter_ext/labextension/static/666.d9bfdb23f98489d0a188.js +1 -0
  182. jupyter_ext/labextension/static/677.d266c39dbed33bc388b3.js +2 -0
  183. jupyter_ext/labextension/static/677.d266c39dbed33bc388b3.js.LICENSE.txt +8 -0
  184. jupyter_ext/labextension/static/68.26b6f59c8454adb17f20.js +204 -0
  185. jupyter_ext/labextension/static/694.4ac443814260057e68f7.js +1 -0
  186. jupyter_ext/labextension/static/791.61affb8d3480d3d60e0d.js +1 -0
  187. jupyter_ext/labextension/static/848.4d2db09cfbb09374b299.js +2 -0
  188. jupyter_ext/labextension/static/848.4d2db09cfbb09374b299.js.LICENSE.txt +9 -0
  189. jupyter_ext/labextension/static/868.5cfe7e1a348ec5af1b8c.js +1 -0
  190. jupyter_ext/labextension/static/97.ea559a5b8a9a09f17c6b.js +1 -0
  191. jupyter_ext/labextension/static/remoteEntry.5292fc9c6df7e7920cc8.js +1 -0
  192. jupyter_ext/labextension/static/style.js +4 -0
  193. jupyter_ext/labextension/static/third-party-licenses.json +724 -0
  194. jupyter_ext/log_paths.py +113 -0
  195. jupyter_ext/resource_usage.py +519 -0
  196. jupyter_ext/secrets_bootstrap.py +116 -0
  197. jupyter_ext/team_access.py +105 -0
  198. jupyter_ext/tests/__init__.py +1 -0
  199. jupyter_ext/tests/test_context.py +234 -0
  200. jupyter_ext/tests/test_factory.py +563 -0
  201. jupyter_ext/tests/test_file_finder.py +139 -0
  202. jupyter_ext/tests/test_handlers.py +58 -0
  203. jupyter_ext/tests/test_mcp_selftest.py +204 -0
  204. jupyter_ext/tests/test_mermaid_fixer.py +272 -0
  205. jupyter_ext/tests/test_resource_tiers.py +298 -0
  206. jupyter_ext/tools/__init__.py +15 -0
  207. jupyter_ext/tools/base.py +90 -0
  208. jupyter_ext/tools/context.py +268 -0
  209. jupyter_ext/tools/dir_complete.py +86 -0
  210. jupyter_ext/tools/file_finder.py +303 -0
  211. jupyter_ext/tools/file_tools.py +244 -0
  212. jupyter_ext/tools/jupyter_tools.py +296 -0
  213. jupyter_ext/tools/registry.py +159 -0
  214. jupyter_ext/tools/search_tools.py +230 -0
  215. jupyter_ext/tools/security_tools.py +657 -0
  216. jupyter_ext/tools/shell_tools.py +109 -0
  217. jupyter_ext/tools/user_tools.py +132 -0
@@ -0,0 +1,160 @@
1
+ """๋‚ด์žฅ PostToolUse hook โ€” ๊ณ ์นœ ํŒŒ์ผ์— ruff/biome autofix ๋ฅผ ๋Œ๋ฆฐ๋‹ค (์ด์Šˆ #145).
2
+
3
+ `codex_hooks.BUILTIN_HOOKS` ๊ฐ€ `python -m jupyter_ext.agent.codex_autofix` ๋กœ ๋ถ€๋ฅธ๋‹ค.
4
+ stdin ์€ codex `PostToolUse` ํŽ˜์ด๋กœ๋“œ์ด๊ณ , ์‚ฌ์šฉ์ž hooks.json ์˜ hook ๊ณผ ๊ฐ™์€ ๋Ÿฌ๋„ˆยท๊ฐ™์€
5
+ ๊ทœ๊ฒฉ์œผ๋กœ ๋ˆ๋‹ค. ํ‘œ์ค€ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋งŒ ์“ด๋‹ค โ€” hook ์€ ๋งค ํŽธ์ง‘๋งˆ๋‹ค ์ƒˆ ํ”„๋กœ์„ธ์Šค๋กœ ๋œฌ๋‹ค.
6
+
7
+ | ํŒŒ์ผ | ๋„๊ตฌ | ์กฐ๊ฑด |
8
+ |---|---|---|
9
+ | `.py` `.pyi` | `ruff check --fix --unfixable F401` โ†’ `ruff format` | ํ•ญ์ƒ (`ruff_command`) |
10
+ | JSยทTSยทJSONยทCSS | `biome check --write` | ํŒŒ์ผ๋ถ€ํ„ฐ ์›Œํฌ์ŠคํŽ˜์ด์Šค๊นŒ์ง€ `biome.json(c)` ์ด ์žˆ์„ ๋•Œ |
11
+
12
+ - ruff ๋Š” PATH ์˜ ๊ฒƒ์„ ๋จผ์ € ์“ฐ๊ณ , ์—†์œผ๋ฉด wheel ์ด ๊ฐ™์ด ๊น ๊ฒƒ(`python -m ruff`)์„ ์“ด๋‹ค.
13
+ ruff ๋Š” `codebuff-agent` ์˜ ๋Ÿฐํƒ€์ž„ ์˜์กด์„ฑ์ด๋‹ค (์ด์Šˆ #145) โ€” ์„œ๋ฒ„๋ฅผ venv ํ™œ์„ฑ ์—†์ด
14
+ ๋„์›Œ PATH ์— ์—†์–ด๋„ ๋ˆ๋‹ค.
15
+ - `write_file` ์˜ `.py` ๋Š” ๊ฑด๋„ˆ๋›ด๋‹ค. `langchain_tools` ๊ฐ€ ์ด๋ฏธ ruff ๋ฅผ ๋Œ๋ฆฐ๋‹ค.
16
+ - biome ์€ ์„ค์ • ๋””๋ ‰ํ„ฐ๋ฆฌ์˜ `node_modules/.bin/biome` ๋˜๋Š” PATH ์˜ ๊ฒƒ๋งŒ ์“ด๋‹ค.
17
+ `npx` ๋กœ ๋ฐ›์•„ ์˜ค์ง€ ์•Š๋Š”๋‹ค โ€” ํŽธ์ง‘ ํ•œ ๋ฒˆ์— ๋„คํŠธ์›Œํฌ๋ฅผ ํƒ€๋ฉด ์•ˆ ๋œ๋‹ค.
18
+ - ๋„๊ตฌ๊ฐ€ ์—†์œผ๋ฉด `systemMessage` ๋กœ ์•Œ๋ฆฐ๋‹ค (๋ธŒ๋ฆฌ์ง€๊ฐ€ ์„ธ์…˜๋‹น ํ•œ ๋ฒˆ๋งŒ ๋„์šด๋‹ค).
19
+ - ํ•ญ์ƒ exit 0 ์ด๋‹ค. ํฌ๋งท ์‹คํŒจ๊ฐ€ ํŽธ์ง‘์„ ๋ง‰์œผ๋ฉด ์•ˆ ๋œ๋‹ค.
20
+ """
21
+
22
+ from __future__ import annotations
23
+
24
+ import importlib.util
25
+ import json
26
+ import os
27
+ import re
28
+ import shutil
29
+ import subprocess
30
+ import sys
31
+ from pathlib import Path
32
+ from typing import Dict, List, Optional
33
+
34
+ PYTHON_SUFFIXES = {".py", ".pyi"}
35
+ BIOME_SUFFIXES = {
36
+ ".js",
37
+ ".jsx",
38
+ ".mjs",
39
+ ".cjs",
40
+ ".ts",
41
+ ".tsx",
42
+ ".json",
43
+ ".jsonc",
44
+ ".css",
45
+ }
46
+ BIOME_CONFIGS = ("biome.json", "biome.jsonc")
47
+ #: `ruff check` ์ธ์ž. F401(์•ˆ ์“ฐ์ธ import) ์€ ๊ณ ์น˜์ง€ ์•Š๋Š”๋‹ค โ€” ์—์ด์ „ํŠธ๋Š” import ๋ฅผ ๋จผ์ €
48
+ #: ์“ฐ๊ณ  ์“ฐ๋Š” ๊ณณ์„ ๋‹ค์Œ ํŽธ์ง‘์— ์“ฐ๋Š”๋ฐ, ๊ทธ ์‚ฌ์ด์— ์ง€์šฐ๋ฉด import ๊ฐ€ ์‚ฌ๋ผ์ง„๋‹ค. `--unfixable` ์€
49
+ #: ํ”„๋กœ์ ํŠธ ์„ค์ •์˜ unfixable ์— ๋”ํ•ด์ง€๋ฏ€๋กœ ์‚ฌ์šฉ์ž ์„ค์ •์„ ๋ฎ์ง€ ์•Š๋Š”๋‹ค
50
+ RUFF_FIX = ("check", "--fix", "--unfixable", "F401")
51
+ #: ํ•œ ๋ช…๋ น์˜ ํ•œ๋„. ๋‚ด์žฅ hook ์ „์ฒด ํ•œ๋„(`codex_hooks.BUILTIN_TIMEOUT`) ์•ˆ์— ๋‘˜์ด ๋“ค์–ด๊ฐ„๋‹ค
52
+ STEP_TIMEOUT = 25
53
+
54
+ _PATCH_HEADER = re.compile(r"^\*\*\* (?:Add|Update) File: (.+)$", re.MULTILINE)
55
+
56
+
57
+ def _target(payload: Dict, cwd: Path) -> Optional[Path]:
58
+ """๊ณ ์นœ ํŒŒ์ผ์˜ ์ ˆ๋Œ€๊ฒฝ๋กœ. ์›Œํฌ์ŠคํŽ˜์ด์Šค ๋ฐ–์ด๋ฉด None ์ด๋‹ค."""
59
+ tool_input = payload.get("tool_input") or {}
60
+ raw = tool_input.get("path")
61
+ if not raw:
62
+ m = _PATCH_HEADER.search(str(tool_input.get("command") or ""))
63
+ raw = m.group(1).strip() if m else ""
64
+ if not raw:
65
+ return None
66
+ path = (cwd / raw).resolve()
67
+ try:
68
+ path.relative_to(cwd)
69
+ except ValueError:
70
+ return None
71
+ return path if path.is_file() else None
72
+
73
+
74
+ def ruff_command() -> Optional[List[str]]:
75
+ """ruff ๋ฅผ ๋ถ€๋ฅด๋Š” ๋ช…๋ น ๋จธ๋ฆฌ. PATH โ†’ wheel ์ด ๊น ๊ฒƒ ์ˆœ์ด๊ณ , ๋‘˜ ๋‹ค ์—†์œผ๋ฉด None."""
76
+ found = shutil.which("ruff")
77
+ if found:
78
+ return [found]
79
+ if importlib.util.find_spec("ruff") is not None:
80
+ return [sys.executable, "-m", "ruff"]
81
+ return None
82
+
83
+
84
+ def _run(cmd: List[str], cwd: Path) -> None:
85
+ try:
86
+ subprocess.run(cmd, cwd=cwd, capture_output=True, timeout=STEP_TIMEOUT)
87
+ except (OSError, subprocess.TimeoutExpired):
88
+ pass
89
+
90
+
91
+ def _biome(path: Path, cwd: Path) -> Optional[str]:
92
+ """biome ์‹คํ–‰ ํŒŒ์ผ. ์„ค์ •์ด ์—†์œผ๋ฉด ๋นˆ ๋ฌธ์ž์—ด, ์„ค์ •์€ ์žˆ๋Š”๋ฐ ์‹คํ–‰ ํŒŒ์ผ์ด ์—†์œผ๋ฉด None."""
93
+ for d in [path.parent, *path.parent.parents]:
94
+ if any((d / name).is_file() for name in BIOME_CONFIGS):
95
+ local = d / "node_modules" / ".bin" / "biome"
96
+ if local.is_file() and os.access(local, os.X_OK):
97
+ return str(local)
98
+ return shutil.which("biome")
99
+ if d == cwd:
100
+ break
101
+ return ""
102
+
103
+
104
+ def autofix(payload: Dict) -> Dict:
105
+ cwd = Path(payload.get("cwd") or os.getcwd()).resolve()
106
+ path = _target(payload, cwd)
107
+ if path is None:
108
+ return {}
109
+ suffix = path.suffix.lower()
110
+ tool = (payload.get("tool_input") or {}).get("codebuff_tool")
111
+ if suffix in PYTHON_SUFFIXES:
112
+ if tool == "write_file" and suffix == ".py":
113
+ return {}
114
+ ruff = ruff_command()
115
+ if not ruff:
116
+ return {"systemMessage": "ruff ๊ฐ€ ์—†์–ด .py ์ž๋™ ํฌ๋งท์„ ๊ฑด๋„ˆ๋œ๋‹ˆ๋‹ค"}
117
+ cmds = [[*ruff, *RUFF_FIX, str(path)], [*ruff, "format", str(path)]]
118
+ name = "ruff"
119
+ elif suffix in BIOME_SUFFIXES:
120
+ biome = _biome(path, cwd)
121
+ if biome == "":
122
+ return {}
123
+ if biome is None:
124
+ return {
125
+ "systemMessage": "biome ์„ค์ •์€ ์žˆ๋Š”๋ฐ biome ์ด ์—†์–ด ์ž๋™ ํฌ๋งท์„ ๊ฑด๋„ˆ๋œ๋‹ˆ๋‹ค"
126
+ }
127
+ cmds = [[biome, "check", "--write", str(path)]]
128
+ name = "biome"
129
+ else:
130
+ return {}
131
+ before = path.read_bytes()
132
+ for cmd in cmds:
133
+ _run(cmd, cwd)
134
+ if path.read_bytes() == before:
135
+ return {}
136
+ rel = path.relative_to(cwd)
137
+ return {
138
+ "hookSpecificOutput": {
139
+ "hookEventName": "PostToolUse",
140
+ "additionalContext": (
141
+ f"autofix: {name} ๊ฐ€ {rel} ๋ฅผ ๊ณ ์ณค๋‹ค. ์ด ํŒŒ์ผ์„ ๋‹ค์‹œ edit_file ๋กœ "
142
+ "๊ณ ์น˜๊ธฐ ์ „์— read_file ๋กœ ์ƒˆ ๋‚ด์šฉ์„ ์ฝ๋Š”๋‹ค."
143
+ ),
144
+ }
145
+ }
146
+
147
+
148
+ def main() -> int:
149
+ try:
150
+ payload = json.loads(sys.stdin.read() or "{}")
151
+ out = autofix(payload) if isinstance(payload, dict) else {}
152
+ except Exception as e: # noqa: BLE001 โ€” ํฌ๋งท ์‹คํŒจ๊ฐ€ ํŽธ์ง‘์„ ๋ง‰์œผ๋ฉด ์•ˆ ๋œ๋‹ค
153
+ out = {"systemMessage": f"autofix ์‹คํŒจ: {e}"}
154
+ if out:
155
+ print(json.dumps(out, ensure_ascii=False))
156
+ return 0
157
+
158
+
159
+ if __name__ == "__main__":
160
+ sys.exit(main())