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.
- codebuff_agent-2.1.74.data/data/etc/jupyter/jupyter_server_config.d/codebuff_agent.json +7 -0
- codebuff_agent-2.1.74.data/data/share/jupyter/labextensions/codebuff/package.json +157 -0
- codebuff_agent-2.1.74.data/data/share/jupyter/labextensions/codebuff/static/104.2b8f20f9d1ac2c9db01b.js +1 -0
- codebuff_agent-2.1.74.data/data/share/jupyter/labextensions/codebuff/static/150.39fa98117cc8ca590465.js +1 -0
- codebuff_agent-2.1.74.data/data/share/jupyter/labextensions/codebuff/static/166.386ff9b2c37ac865fdee.js +1 -0
- codebuff_agent-2.1.74.data/data/share/jupyter/labextensions/codebuff/static/216.25cf81131bf7274dabf4.js +1 -0
- codebuff_agent-2.1.74.data/data/share/jupyter/labextensions/codebuff/static/353.581bd1cb00746399b62e.js +1 -0
- codebuff_agent-2.1.74.data/data/share/jupyter/labextensions/codebuff/static/367.575f9621b63c9a641aa9.js +1 -0
- codebuff_agent-2.1.74.data/data/share/jupyter/labextensions/codebuff/static/421.11dac223a2c2da1b09f5.js +1 -0
- codebuff_agent-2.1.74.data/data/share/jupyter/labextensions/codebuff/static/432.8513b4c6cc1d1232d165.js +2 -0
- codebuff_agent-2.1.74.data/data/share/jupyter/labextensions/codebuff/static/432.8513b4c6cc1d1232d165.js.LICENSE.txt +19 -0
- codebuff_agent-2.1.74.data/data/share/jupyter/labextensions/codebuff/static/439.ba5b5ef70ec6de214b8c.js +2 -0
- codebuff_agent-2.1.74.data/data/share/jupyter/labextensions/codebuff/static/439.ba5b5ef70ec6de214b8c.js.LICENSE.txt +8 -0
- codebuff_agent-2.1.74.data/data/share/jupyter/labextensions/codebuff/static/481.cc2dec9fa869d66f1407.js +1 -0
- codebuff_agent-2.1.74.data/data/share/jupyter/labextensions/codebuff/static/487.0796e931d6e651482c14.js +1 -0
- codebuff_agent-2.1.74.data/data/share/jupyter/labextensions/codebuff/static/49.d326f554b6f9ccde6580.js +1 -0
- codebuff_agent-2.1.74.data/data/share/jupyter/labextensions/codebuff/static/541.26897ea32845659e36be.js +1 -0
- codebuff_agent-2.1.74.data/data/share/jupyter/labextensions/codebuff/static/579.e569d3edd8391fd8fbb3.js +1 -0
- codebuff_agent-2.1.74.data/data/share/jupyter/labextensions/codebuff/static/58.eb7cc679f7535cc8a2f1.js +2 -0
- codebuff_agent-2.1.74.data/data/share/jupyter/labextensions/codebuff/static/58.eb7cc679f7535cc8a2f1.js.LICENSE.txt +8 -0
- codebuff_agent-2.1.74.data/data/share/jupyter/labextensions/codebuff/static/666.d9bfdb23f98489d0a188.js +1 -0
- codebuff_agent-2.1.74.data/data/share/jupyter/labextensions/codebuff/static/677.d266c39dbed33bc388b3.js +2 -0
- codebuff_agent-2.1.74.data/data/share/jupyter/labextensions/codebuff/static/677.d266c39dbed33bc388b3.js.LICENSE.txt +8 -0
- codebuff_agent-2.1.74.data/data/share/jupyter/labextensions/codebuff/static/68.26b6f59c8454adb17f20.js +204 -0
- codebuff_agent-2.1.74.data/data/share/jupyter/labextensions/codebuff/static/694.4ac443814260057e68f7.js +1 -0
- codebuff_agent-2.1.74.data/data/share/jupyter/labextensions/codebuff/static/791.61affb8d3480d3d60e0d.js +1 -0
- codebuff_agent-2.1.74.data/data/share/jupyter/labextensions/codebuff/static/848.4d2db09cfbb09374b299.js +2 -0
- codebuff_agent-2.1.74.data/data/share/jupyter/labextensions/codebuff/static/848.4d2db09cfbb09374b299.js.LICENSE.txt +9 -0
- codebuff_agent-2.1.74.data/data/share/jupyter/labextensions/codebuff/static/868.5cfe7e1a348ec5af1b8c.js +1 -0
- codebuff_agent-2.1.74.data/data/share/jupyter/labextensions/codebuff/static/97.ea559a5b8a9a09f17c6b.js +1 -0
- codebuff_agent-2.1.74.data/data/share/jupyter/labextensions/codebuff/static/remoteEntry.5292fc9c6df7e7920cc8.js +1 -0
- codebuff_agent-2.1.74.data/data/share/jupyter/labextensions/codebuff/static/style.js +4 -0
- codebuff_agent-2.1.74.data/data/share/jupyter/labextensions/codebuff/static/third-party-licenses.json +724 -0
- codebuff_agent-2.1.74.dist-info/METADATA +142 -0
- codebuff_agent-2.1.74.dist-info/RECORD +217 -0
- codebuff_agent-2.1.74.dist-info/WHEEL +4 -0
- codebuff_agent-2.1.74.dist-info/licenses/LICENSE +21 -0
- codebuff_core/__init__.py +153 -0
- codebuff_core/codebuff_config_defaults.json +64 -0
- codebuff_core/core/__init__.py +35 -0
- codebuff_core/core/code_validator.py +1238 -0
- codebuff_core/core/error_classifier.py +579 -0
- codebuff_core/core/exceptions.py +49 -0
- codebuff_core/data/tiktoken_cache/9b5ad71b2ce5302211f9c61530b329a4922fc6a4 +100256 -0
- codebuff_core/directory_policy.py +32 -0
- codebuff_core/factory.py +155 -0
- codebuff_core/interfaces.py +197 -0
- codebuff_core/knowledge/__init__.py +31 -0
- codebuff_core/knowledge/chunking.py +375 -0
- codebuff_core/knowledge/loader.py +339 -0
- codebuff_core/knowledge/watchdog_service.py +354 -0
- codebuff_core/legacy_paths.py +69 -0
- codebuff_core/llm/__init__.py +13 -0
- codebuff_core/llm/service.py +407 -0
- codebuff_core/managers/__init__.py +22 -0
- codebuff_core/managers/config_manager.py +690 -0
- codebuff_core/managers/remote_config.py +673 -0
- codebuff_core/managers/remote_skills.py +539 -0
- codebuff_core/managers/session_manager.py +255 -0
- codebuff_core/middleware/__init__.py +3 -0
- codebuff_core/middleware/error_recovery.py +394 -0
- codebuff_core/middleware/logging_utils.py +33 -0
- codebuff_core/models/__init__.py +111 -0
- codebuff_core/models/agent.py +306 -0
- codebuff_core/models/chat.py +57 -0
- codebuff_core/models/common.py +82 -0
- codebuff_core/models/rag.py +300 -0
- codebuff_core/platform_rules.py +127 -0
- codebuff_core/prompts/__init__.py +44 -0
- codebuff_core/prompts/auto_agent_prompts.py +1278 -0
- codebuff_core/services/__init__.py +30 -0
- codebuff_core/services/agent_service.py +345 -0
- codebuff_core/services/analytics_aggregate.py +837 -0
- codebuff_core/services/chat_service.py +898 -0
- codebuff_core/services/context_condenser.py +306 -0
- codebuff_core/services/pii_guardrail.py +393 -0
- codebuff_core/services/rag_chat_agent.py +2993 -0
- codebuff_core/services/rag_collections.py +2740 -0
- codebuff_core/services/rag_manager.py +890 -0
- codebuff_core/services/rag_service.py +145 -0
- codebuff_core/services/retriever.py +260 -0
- codebuff_core/services/vllm_embedding_service.py +290 -0
- codebuff_core/tests/__init__.py +1 -0
- codebuff_core/tests/conftest.py +81 -0
- codebuff_core/tests/test_error_recovery.py +647 -0
- codebuff_core/tests/test_factory.py +135 -0
- codebuff_core/tests/test_services.py +150 -0
- jupyter_ext/__init__.py +266 -0
- jupyter_ext/_version.py +4 -0
- jupyter_ext/agent/__init__.py +49 -0
- jupyter_ext/agent/agent_factory.py +2270 -0
- jupyter_ext/agent/ast_tools.py +451 -0
- jupyter_ext/agent/autofix_middleware.py +481 -0
- jupyter_ext/agent/background_procs.py +372 -0
- jupyter_ext/agent/code_history_middleware.py +211 -0
- jupyter_ext/agent/codex_autofix.py +160 -0
- jupyter_ext/agent/codex_bridge.py +3339 -0
- jupyter_ext/agent/codex_hooks.py +320 -0
- jupyter_ext/agent/codex_slash.py +685 -0
- jupyter_ext/agent/codex_threads.py +114 -0
- jupyter_ext/agent/content_injection.py +377 -0
- jupyter_ext/agent/continuation_middleware.py +548 -0
- jupyter_ext/agent/custom_skills.py +335 -0
- jupyter_ext/agent/file_diffs.py +99 -0
- jupyter_ext/agent/git_history.py +188 -0
- jupyter_ext/agent/guardrail_middleware.py +421 -0
- jupyter_ext/agent/json_repair_utils.py +54 -0
- jupyter_ext/agent/langchain_tools.py +2673 -0
- jupyter_ext/agent/mermaid_fixer.py +289 -0
- jupyter_ext/agent/mermaid_middleware.py +135 -0
- jupyter_ext/agent/middleware.py +359 -0
- jupyter_ext/agent/middleware_prompts.py +53 -0
- jupyter_ext/agent/observability.py +334 -0
- jupyter_ext/agent/patch_tool_calls.py +57 -0
- jupyter_ext/agent/prompts.py +112 -0
- jupyter_ext/agent/skill_middleware.py +257 -0
- jupyter_ext/agent/skills/airflow_dag_development.md +36 -0
- jupyter_ext/agent/skills/anomaly_detection.md +12 -0
- jupyter_ext/agent/skills/athena_sql.md +156 -0
- jupyter_ext/agent/skills/bdp_table_search.md +33 -0
- jupyter_ext/agent/skills/bigquery.md +65 -0
- jupyter_ext/agent/skills/bigquery_oracle.md +231 -0
- jupyter_ext/agent/skills/bigquery_tuning.md +307 -0
- jupyter_ext/agent/skills/classification_evaluation.md +11 -0
- jupyter_ext/agent/skills/clustering_analysis.md +12 -0
- jupyter_ext/agent/skills/comprehensive_eda.md +11 -0
- jupyter_ext/agent/skills/data_analysis.md +236 -0
- jupyter_ext/agent/skills/data_cleaning_pipeline.md +12 -0
- jupyter_ext/agent/skills/data_loading.md +158 -0
- jupyter_ext/agent/skills/data_quality_report.md +13 -0
- jupyter_ext/agent/skills/dimensionality_reduction.md +12 -0
- jupyter_ext/agent/skills/emr_script_development.md +17 -0
- jupyter_ext/agent/skills/experiment_tracking.md +13 -0
- jupyter_ext/agent/skills/feature_importance_analysis.md +10 -0
- jupyter_ext/agent/skills/hyperparameter_tuning.md +12 -0
- jupyter_ext/agent/skills/hypothesis_testing.md +12 -0
- jupyter_ext/agent/skills/imbalanced_data_handling.md +12 -0
- jupyter_ext/agent/skills/inference.md +392 -0
- jupyter_ext/agent/skills/lambda_function_development.md +19 -0
- jupyter_ext/agent/skills/model_comparison.md +11 -0
- jupyter_ext/agent/skills/model_explainability.md +12 -0
- jupyter_ext/agent/skills/model_training.md +318 -0
- jupyter_ext/agent/skills/pyspark.md +352 -0
- jupyter_ext/agent/skills/python_code_quality.md +35 -0
- jupyter_ext/agent/skills/regression_evaluation.md +12 -0
- jupyter_ext/agent/skills/spring_java_development.md +35 -0
- jupyter_ext/agent/skills/text_preprocessing.md +12 -0
- jupyter_ext/agent/skills/time_series_analysis.md +13 -0
- jupyter_ext/agent/skills/unit_testing.md +203 -0
- jupyter_ext/agent/todo_prompts.py +57 -0
- jupyter_ext/agent/tool_report.py +45 -0
- jupyter_ext/analytics_ingest.py +599 -0
- jupyter_ext/etc/jupyter/jupyter_server_config.d/codebuff_agent.json +7 -0
- jupyter_ext/handlers/__init__.py +8 -0
- jupyter_ext/handlers/analytics_handler.py +170 -0
- jupyter_ext/handlers/benchmark_handler.py +794 -0
- jupyter_ext/handlers/eda_benchmark_handler.py +1328 -0
- jupyter_ext/handlers/rag_admin_handler.py +689 -0
- jupyter_ext/handlers/websocket.py +497 -0
- jupyter_ext/http_handlers.py +8744 -0
- jupyter_ext/idle_monitor.py +346 -0
- jupyter_ext/labextension/package.json +157 -0
- jupyter_ext/labextension/static/104.2b8f20f9d1ac2c9db01b.js +1 -0
- jupyter_ext/labextension/static/150.39fa98117cc8ca590465.js +1 -0
- jupyter_ext/labextension/static/166.386ff9b2c37ac865fdee.js +1 -0
- jupyter_ext/labextension/static/216.25cf81131bf7274dabf4.js +1 -0
- jupyter_ext/labextension/static/353.581bd1cb00746399b62e.js +1 -0
- jupyter_ext/labextension/static/367.575f9621b63c9a641aa9.js +1 -0
- jupyter_ext/labextension/static/421.11dac223a2c2da1b09f5.js +1 -0
- jupyter_ext/labextension/static/432.8513b4c6cc1d1232d165.js +2 -0
- jupyter_ext/labextension/static/432.8513b4c6cc1d1232d165.js.LICENSE.txt +19 -0
- jupyter_ext/labextension/static/439.ba5b5ef70ec6de214b8c.js +2 -0
- jupyter_ext/labextension/static/439.ba5b5ef70ec6de214b8c.js.LICENSE.txt +8 -0
- jupyter_ext/labextension/static/481.cc2dec9fa869d66f1407.js +1 -0
- jupyter_ext/labextension/static/487.0796e931d6e651482c14.js +1 -0
- jupyter_ext/labextension/static/49.d326f554b6f9ccde6580.js +1 -0
- jupyter_ext/labextension/static/541.26897ea32845659e36be.js +1 -0
- jupyter_ext/labextension/static/579.e569d3edd8391fd8fbb3.js +1 -0
- jupyter_ext/labextension/static/58.eb7cc679f7535cc8a2f1.js +2 -0
- jupyter_ext/labextension/static/58.eb7cc679f7535cc8a2f1.js.LICENSE.txt +8 -0
- jupyter_ext/labextension/static/666.d9bfdb23f98489d0a188.js +1 -0
- jupyter_ext/labextension/static/677.d266c39dbed33bc388b3.js +2 -0
- jupyter_ext/labextension/static/677.d266c39dbed33bc388b3.js.LICENSE.txt +8 -0
- jupyter_ext/labextension/static/68.26b6f59c8454adb17f20.js +204 -0
- jupyter_ext/labextension/static/694.4ac443814260057e68f7.js +1 -0
- jupyter_ext/labextension/static/791.61affb8d3480d3d60e0d.js +1 -0
- jupyter_ext/labextension/static/848.4d2db09cfbb09374b299.js +2 -0
- jupyter_ext/labextension/static/848.4d2db09cfbb09374b299.js.LICENSE.txt +9 -0
- jupyter_ext/labextension/static/868.5cfe7e1a348ec5af1b8c.js +1 -0
- jupyter_ext/labextension/static/97.ea559a5b8a9a09f17c6b.js +1 -0
- jupyter_ext/labextension/static/remoteEntry.5292fc9c6df7e7920cc8.js +1 -0
- jupyter_ext/labextension/static/style.js +4 -0
- jupyter_ext/labextension/static/third-party-licenses.json +724 -0
- jupyter_ext/log_paths.py +113 -0
- jupyter_ext/resource_usage.py +519 -0
- jupyter_ext/secrets_bootstrap.py +116 -0
- jupyter_ext/team_access.py +105 -0
- jupyter_ext/tests/__init__.py +1 -0
- jupyter_ext/tests/test_context.py +234 -0
- jupyter_ext/tests/test_factory.py +563 -0
- jupyter_ext/tests/test_file_finder.py +139 -0
- jupyter_ext/tests/test_handlers.py +58 -0
- jupyter_ext/tests/test_mcp_selftest.py +204 -0
- jupyter_ext/tests/test_mermaid_fixer.py +272 -0
- jupyter_ext/tests/test_resource_tiers.py +298 -0
- jupyter_ext/tools/__init__.py +15 -0
- jupyter_ext/tools/base.py +90 -0
- jupyter_ext/tools/context.py +268 -0
- jupyter_ext/tools/dir_complete.py +86 -0
- jupyter_ext/tools/file_finder.py +303 -0
- jupyter_ext/tools/file_tools.py +244 -0
- jupyter_ext/tools/jupyter_tools.py +296 -0
- jupyter_ext/tools/registry.py +159 -0
- jupyter_ext/tools/search_tools.py +230 -0
- jupyter_ext/tools/security_tools.py +657 -0
- jupyter_ext/tools/shell_tools.py +109 -0
- 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
|
+
)
|