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,109 @@
1
+ """셸 실행 도구."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import asyncio
6
+ from typing import Any, Optional
7
+
8
+ from .base import BaseTool, ToolResult
9
+
10
+
11
+ class ShellExecuteTool(BaseTool):
12
+ """셸 명령 실행 도구."""
13
+
14
+ def __init__(self, working_dir: Optional[str] = None, timeout: int = 60):
15
+ self._working_dir = working_dir
16
+ self._timeout = timeout
17
+
18
+ @property
19
+ def name(self) -> str:
20
+ return "shell_execute"
21
+
22
+ @property
23
+ def description(self) -> str:
24
+ return """Execute a shell command and return the output.
25
+ Use this for running scripts, installing packages, git operations, etc.
26
+ WARNING: This tool can execute arbitrary commands. Use with caution."""
27
+
28
+ @property
29
+ def parameters(self) -> dict[str, Any]:
30
+ return {
31
+ "type": "object",
32
+ "properties": {
33
+ "command": {
34
+ "type": "string",
35
+ "description": "The shell command to execute",
36
+ },
37
+ "working_dir": {
38
+ "type": "string",
39
+ "description": "Working directory for the command",
40
+ },
41
+ "timeout": {
42
+ "type": "integer",
43
+ "description": "Timeout in seconds (default: 60)",
44
+ "default": 60,
45
+ },
46
+ },
47
+ "required": ["command"],
48
+ }
49
+
50
+ @property
51
+ def risk_level(self) -> str:
52
+ return "critical"
53
+
54
+ async def execute(self, **kwargs: Any) -> ToolResult:
55
+ """셸 명령을 실행합니다."""
56
+ command = kwargs.get("command", "")
57
+ working_dir = kwargs.get("working_dir", self._working_dir)
58
+ timeout = kwargs.get("timeout", self._timeout)
59
+
60
+ if not command:
61
+ return ToolResult(success=False, error="명령이 필요합니다")
62
+
63
+ try:
64
+ # 서브프로세스 생성
65
+ process = await asyncio.create_subprocess_shell(
66
+ command,
67
+ stdout=asyncio.subprocess.PIPE,
68
+ stderr=asyncio.subprocess.PIPE,
69
+ cwd=working_dir,
70
+ )
71
+
72
+ # 타임아웃과 함께 완료 대기
73
+ try:
74
+ stdout, stderr = await asyncio.wait_for(
75
+ process.communicate(),
76
+ timeout=timeout,
77
+ )
78
+ except asyncio.TimeoutError:
79
+ process.kill()
80
+ await process.wait()
81
+ return ToolResult(
82
+ success=False,
83
+ error=f"{timeout}초 후 명령 시간 초과",
84
+ metadata={"command": command, "timeout": True},
85
+ )
86
+
87
+ # 출력 디코딩
88
+ stdout_str = stdout.decode("utf-8", errors="replace") if stdout else ""
89
+ stderr_str = stderr.decode("utf-8", errors="replace") if stderr else ""
90
+
91
+ success = process.returncode == 0
92
+
93
+ return ToolResult(
94
+ success=success,
95
+ data={
96
+ "stdout": stdout_str,
97
+ "stderr": stderr_str,
98
+ "return_code": process.returncode,
99
+ },
100
+ error=stderr_str if not success and stderr_str else None,
101
+ metadata={"command": command},
102
+ )
103
+
104
+ except Exception as e:
105
+ return ToolResult(
106
+ success=False,
107
+ error=f"명령 실행 오류: {str(e)}",
108
+ metadata={"command": command},
109
+ )
@@ -0,0 +1,132 @@
1
+ """
2
+ User interaction tools for agent mode.
3
+
4
+ - ask_user_tool: Request user input via HITL interrupt
5
+ - final_summary_tool: Summarize completed work with next step suggestions
6
+ """
7
+
8
+ import json
9
+ from typing import Any, Dict, List, Optional
10
+
11
+ from langchain_core.tools import tool
12
+ from pydantic import BaseModel, Field
13
+
14
+
15
+ class AskUserInput(BaseModel):
16
+ """Input schema for ask_user tool"""
17
+
18
+ question: str = Field(description="사용자에게 보여줄 질문 또는 요청")
19
+ options: Optional[List[str]] = Field(
20
+ default=None, description="선택지 목록 (없으면 자유 입력)"
21
+ )
22
+ input_type: str = Field(
23
+ default="text",
24
+ description="입력 타입: text (텍스트 입력), file (파일 업로드), selection (선택지 중 선택)",
25
+ )
26
+ user_response: Optional[str] = Field(
27
+ default=None,
28
+ description="사용자 응답 (HITL edit decision으로 프론트엔드에서 전달)",
29
+ )
30
+
31
+
32
+ @tool(args_schema=AskUserInput)
33
+ def ask_user_tool(
34
+ question: str,
35
+ options: Optional[List[str]] = None,
36
+ input_type: str = "text",
37
+ user_response: Optional[str] = None,
38
+ ) -> Dict[str, Any]:
39
+ """
40
+ 사용자에게 질문하고 응답을 기다리는 도구.
41
+
42
+ 이 도구 호출 후 에이전트는 사용자 응답을 기다립니다.
43
+ 사용자가 응답하면 그 내용이 다음 메시지로 전달됩니다.
44
+
45
+ 사용 시점:
46
+ - 선택 요청: ask_user_tool(question="어떤 모델을 사용할까요?", options=["Logistic", "RandomForest"])
47
+ - 정보 요청: ask_user_tool(question="API 키를 입력해 주세요", input_type="text")
48
+
49
+ 주의: 정보 출력용으로는 jupyter_markdown을 사용하고, 사용자 응답이 필요하면 이 도구를 사용하세요.
50
+
51
+ Args:
52
+ question: 사용자에게 보여줄 질문
53
+ options: 선택지 목록 (선택적, input_type="selection"일 때 사용)
54
+ input_type: 입력 타입 - text(텍스트), file(파일 업로드), selection(선택)
55
+ user_response: 사용자 응답 (HITL에서 프론트엔드가 전달)
56
+
57
+ Returns:
58
+ Dict containing the user response or waiting status
59
+ """
60
+ if user_response is not None:
61
+ return {
62
+ "tool": "ask_user",
63
+ "parameters": {
64
+ "question": question,
65
+ "options": options,
66
+ "input_type": input_type,
67
+ },
68
+ "status": "completed",
69
+ "user_response": user_response,
70
+ "message": f"사용자 응답: {user_response}",
71
+ }
72
+
73
+ return {
74
+ "tool": "ask_user",
75
+ "parameters": {
76
+ "question": question,
77
+ "options": options,
78
+ "input_type": input_type,
79
+ },
80
+ "status": "waiting_for_user",
81
+ "message": "사용자 응답을 기다리는 중입니다...",
82
+ }
83
+
84
+
85
+ class FinalSummaryInput(BaseModel):
86
+ """Input schema for final_summary tool"""
87
+
88
+ summary: str = Field(description="완료된 작업에 대한 요약 (한국어)")
89
+ next_items: List[dict] = Field(
90
+ description="다음 단계 제안 목록 (각각 subject와 description 포함, 3개 이상)"
91
+ )
92
+
93
+
94
+ @tool(args_schema=FinalSummaryInput)
95
+ def final_summary_tool(
96
+ summary: str,
97
+ next_items: List[dict],
98
+ ) -> str:
99
+ """
100
+ 모든 todo가 completed 상태가 된 후 호출하는 마무리 도구.
101
+ 별도의 "요약" todo를 만들지 말고, 실제 작업 todo가 모두 완료되면 바로 이 도구를 호출하세요.
102
+
103
+ Args:
104
+ summary: 완료된 작업에 대한 요약 (한국어로 작성)
105
+ next_items: 후속 작업 제안 목록 (각각 subject와 description 포함, 3개 이상)
106
+
107
+ Returns:
108
+ JSON string containing the summary and next items for frontend display
109
+ """
110
+ serialized_items = []
111
+ for item in next_items:
112
+ if isinstance(item, dict):
113
+ serialized_items.append(item)
114
+ elif hasattr(item, "model_dump"):
115
+ serialized_items.append(item.model_dump())
116
+ else:
117
+ serialized_items.append(
118
+ {
119
+ "subject": str(getattr(item, "subject", "")),
120
+ "description": str(getattr(item, "description", "")),
121
+ }
122
+ )
123
+ return json.dumps(
124
+ {
125
+ "tool": "final_summary",
126
+ "summary": summary,
127
+ "next_items": serialized_items,
128
+ "status": "completed",
129
+ "message": "작업 요약이 완료되었습니다.",
130
+ },
131
+ ensure_ascii=False,
132
+ )