hdsp-jupyter-extension 2.0.1__py3-none-any.whl → 2.0.3__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.
- agent_server/langchain/__init__.py +18 -0
- agent_server/langchain/agent.py +694 -0
- agent_server/langchain/executors/__init__.py +15 -0
- agent_server/langchain/executors/jupyter_executor.py +429 -0
- agent_server/langchain/executors/notebook_searcher.py +477 -0
- agent_server/langchain/middleware/__init__.py +36 -0
- agent_server/langchain/middleware/code_search_middleware.py +278 -0
- agent_server/langchain/middleware/error_handling_middleware.py +338 -0
- agent_server/langchain/middleware/jupyter_execution_middleware.py +301 -0
- agent_server/langchain/middleware/rag_middleware.py +227 -0
- agent_server/langchain/middleware/validation_middleware.py +240 -0
- agent_server/langchain/state.py +159 -0
- agent_server/langchain/tools/__init__.py +39 -0
- agent_server/langchain/tools/file_tools.py +279 -0
- agent_server/langchain/tools/jupyter_tools.py +143 -0
- agent_server/langchain/tools/search_tools.py +309 -0
- agent_server/main.py +13 -0
- agent_server/routers/health.py +14 -0
- agent_server/routers/langchain_agent.py +1368 -0
- {hdsp_jupyter_extension-2.0.1.data → hdsp_jupyter_extension-2.0.3.data}/data/share/jupyter/labextensions/hdsp-agent/build_log.json +1 -1
- {hdsp_jupyter_extension-2.0.1.data → hdsp_jupyter_extension-2.0.3.data}/data/share/jupyter/labextensions/hdsp-agent/package.json +2 -2
- hdsp_jupyter_extension-2.0.1.data/data/share/jupyter/labextensions/hdsp-agent/static/frontend_styles_index_js.2607ff74c74acfa83158.js → hdsp_jupyter_extension-2.0.3.data/data/share/jupyter/labextensions/hdsp-agent/static/frontend_styles_index_js.634cf0ae0f3592d0882f.js +408 -4
- hdsp_jupyter_extension-2.0.3.data/data/share/jupyter/labextensions/hdsp-agent/static/frontend_styles_index_js.634cf0ae0f3592d0882f.js.map +1 -0
- hdsp_jupyter_extension-2.0.1.data/data/share/jupyter/labextensions/hdsp-agent/static/lib_index_js.622c1a5918b3aafb2315.js → hdsp_jupyter_extension-2.0.3.data/data/share/jupyter/labextensions/hdsp-agent/static/lib_index_js.1366019c413f1d68467f.js +753 -65
- hdsp_jupyter_extension-2.0.3.data/data/share/jupyter/labextensions/hdsp-agent/static/lib_index_js.1366019c413f1d68467f.js.map +1 -0
- hdsp_jupyter_extension-2.0.1.data/data/share/jupyter/labextensions/hdsp-agent/static/remoteEntry.729f933de01ad5620730.js → hdsp_jupyter_extension-2.0.3.data/data/share/jupyter/labextensions/hdsp-agent/static/remoteEntry.b6d91b150c0800bddfa4.js +8 -8
- hdsp_jupyter_extension-2.0.3.data/data/share/jupyter/labextensions/hdsp-agent/static/remoteEntry.b6d91b150c0800bddfa4.js.map +1 -0
- jupyter_ext/labextension/static/vendors-node_modules_emotion_cache_dist_emotion-cache_browser_development_esm_js-node_modules-782ee5.d9ed8645ef1d311657d8.js → hdsp_jupyter_extension-2.0.3.data/data/share/jupyter/labextensions/hdsp-agent/static/vendors-node_modules_emotion_cache_dist_emotion-cache_browser_development_esm_js.24edcc52a1c014a8a5f0.js +2 -209
- hdsp_jupyter_extension-2.0.3.data/data/share/jupyter/labextensions/hdsp-agent/static/vendors-node_modules_emotion_cache_dist_emotion-cache_browser_development_esm_js.24edcc52a1c014a8a5f0.js.map +1 -0
- jupyter_ext/labextension/static/vendors-node_modules_emotion_react_dist_emotion-react_browser_development_esm_js.36b49c71871f98d4f549.js → hdsp_jupyter_extension-2.0.3.data/data/share/jupyter/labextensions/hdsp-agent/static/vendors-node_modules_emotion_react_dist_emotion-react_browser_development_esm_js.19ecf6babe00caff6b8a.js +209 -2
- hdsp_jupyter_extension-2.0.3.data/data/share/jupyter/labextensions/hdsp-agent/static/vendors-node_modules_emotion_react_dist_emotion-react_browser_development_esm_js.19ecf6babe00caff6b8a.js.map +1 -0
- hdsp_jupyter_extension-2.0.1.data/data/share/jupyter/labextensions/hdsp-agent/static/vendors-node_modules_mui_material_utils_createSvgIcon_js.2e13df4ea61496e95d45.js → hdsp_jupyter_extension-2.0.3.data/data/share/jupyter/labextensions/hdsp-agent/static/vendors-node_modules_mui_material_utils_createSvgIcon_js.1f5038488cdfd8b3a85d.js +212 -3
- hdsp_jupyter_extension-2.0.3.data/data/share/jupyter/labextensions/hdsp-agent/static/vendors-node_modules_mui_material_utils_createSvgIcon_js.1f5038488cdfd8b3a85d.js.map +1 -0
- {hdsp_jupyter_extension-2.0.1.dist-info → hdsp_jupyter_extension-2.0.3.dist-info}/METADATA +6 -1
- {hdsp_jupyter_extension-2.0.1.dist-info → hdsp_jupyter_extension-2.0.3.dist-info}/RECORD +66 -49
- jupyter_ext/_version.py +1 -1
- jupyter_ext/handlers.py +126 -1
- jupyter_ext/labextension/build_log.json +1 -1
- jupyter_ext/labextension/package.json +2 -2
- jupyter_ext/labextension/static/{frontend_styles_index_js.2607ff74c74acfa83158.js → frontend_styles_index_js.634cf0ae0f3592d0882f.js} +408 -4
- jupyter_ext/labextension/static/frontend_styles_index_js.634cf0ae0f3592d0882f.js.map +1 -0
- jupyter_ext/labextension/static/{lib_index_js.622c1a5918b3aafb2315.js → lib_index_js.1366019c413f1d68467f.js} +753 -65
- jupyter_ext/labextension/static/lib_index_js.1366019c413f1d68467f.js.map +1 -0
- jupyter_ext/labextension/static/{remoteEntry.729f933de01ad5620730.js → remoteEntry.b6d91b150c0800bddfa4.js} +8 -8
- jupyter_ext/labextension/static/remoteEntry.b6d91b150c0800bddfa4.js.map +1 -0
- hdsp_jupyter_extension-2.0.1.data/data/share/jupyter/labextensions/hdsp-agent/static/vendors-node_modules_emotion_cache_dist_emotion-cache_browser_development_esm_js-node_modules-782ee5.d9ed8645ef1d311657d8.js → jupyter_ext/labextension/static/vendors-node_modules_emotion_cache_dist_emotion-cache_browser_development_esm_js.24edcc52a1c014a8a5f0.js +2 -209
- jupyter_ext/labextension/static/vendors-node_modules_emotion_cache_dist_emotion-cache_browser_development_esm_js.24edcc52a1c014a8a5f0.js.map +1 -0
- hdsp_jupyter_extension-2.0.1.data/data/share/jupyter/labextensions/hdsp-agent/static/vendors-node_modules_emotion_react_dist_emotion-react_browser_development_esm_js.36b49c71871f98d4f549.js → jupyter_ext/labextension/static/vendors-node_modules_emotion_react_dist_emotion-react_browser_development_esm_js.19ecf6babe00caff6b8a.js +209 -2
- jupyter_ext/labextension/static/vendors-node_modules_emotion_react_dist_emotion-react_browser_development_esm_js.19ecf6babe00caff6b8a.js.map +1 -0
- jupyter_ext/labextension/static/{vendors-node_modules_mui_material_utils_createSvgIcon_js.2e13df4ea61496e95d45.js → vendors-node_modules_mui_material_utils_createSvgIcon_js.1f5038488cdfd8b3a85d.js} +212 -3
- jupyter_ext/labextension/static/vendors-node_modules_mui_material_utils_createSvgIcon_js.1f5038488cdfd8b3a85d.js.map +1 -0
- hdsp_jupyter_extension-2.0.1.data/data/share/jupyter/labextensions/hdsp-agent/static/frontend_styles_index_js.2607ff74c74acfa83158.js.map +0 -1
- hdsp_jupyter_extension-2.0.1.data/data/share/jupyter/labextensions/hdsp-agent/static/lib_index_js.622c1a5918b3aafb2315.js.map +0 -1
- hdsp_jupyter_extension-2.0.1.data/data/share/jupyter/labextensions/hdsp-agent/static/remoteEntry.729f933de01ad5620730.js.map +0 -1
- hdsp_jupyter_extension-2.0.1.data/data/share/jupyter/labextensions/hdsp-agent/static/vendors-node_modules_emotion_cache_dist_emotion-cache_browser_development_esm_js-node_modules-782ee5.d9ed8645ef1d311657d8.js.map +0 -1
- hdsp_jupyter_extension-2.0.1.data/data/share/jupyter/labextensions/hdsp-agent/static/vendors-node_modules_emotion_react_dist_emotion-react_browser_development_esm_js.36b49c71871f98d4f549.js.map +0 -1
- hdsp_jupyter_extension-2.0.1.data/data/share/jupyter/labextensions/hdsp-agent/static/vendors-node_modules_mui_material_utils_createSvgIcon_js.2e13df4ea61496e95d45.js.map +0 -1
- jupyter_ext/labextension/static/frontend_styles_index_js.2607ff74c74acfa83158.js.map +0 -1
- jupyter_ext/labextension/static/lib_index_js.622c1a5918b3aafb2315.js.map +0 -1
- jupyter_ext/labextension/static/remoteEntry.729f933de01ad5620730.js.map +0 -1
- jupyter_ext/labextension/static/vendors-node_modules_emotion_cache_dist_emotion-cache_browser_development_esm_js-node_modules-782ee5.d9ed8645ef1d311657d8.js.map +0 -1
- jupyter_ext/labextension/static/vendors-node_modules_emotion_react_dist_emotion-react_browser_development_esm_js.36b49c71871f98d4f549.js.map +0 -1
- jupyter_ext/labextension/static/vendors-node_modules_mui_material_utils_createSvgIcon_js.2e13df4ea61496e95d45.js.map +0 -1
- {hdsp_jupyter_extension-2.0.1.data → hdsp_jupyter_extension-2.0.3.data}/data/etc/jupyter/jupyter_server_config.d/hdsp_jupyter_extension.json +0 -0
- {hdsp_jupyter_extension-2.0.1.data → hdsp_jupyter_extension-2.0.3.data}/data/share/jupyter/labextensions/hdsp-agent/install.json +0 -0
- {hdsp_jupyter_extension-2.0.1.data → hdsp_jupyter_extension-2.0.3.data}/data/share/jupyter/labextensions/hdsp-agent/static/node_modules_emotion_use-insertion-effect-with-fallbacks_dist_emotion-use-insertion-effect-wi-3ba6b80.c095373419d05e6f141a.js +0 -0
- {hdsp_jupyter_extension-2.0.1.data → hdsp_jupyter_extension-2.0.3.data}/data/share/jupyter/labextensions/hdsp-agent/static/node_modules_emotion_use-insertion-effect-with-fallbacks_dist_emotion-use-insertion-effect-wi-3ba6b80.c095373419d05e6f141a.js.map +0 -0
- {hdsp_jupyter_extension-2.0.1.data → hdsp_jupyter_extension-2.0.3.data}/data/share/jupyter/labextensions/hdsp-agent/static/node_modules_emotion_use-insertion-effect-with-fallbacks_dist_emotion-use-insertion-effect-wi-3ba6b81.61e75fb98ecff46cf836.js +0 -0
- {hdsp_jupyter_extension-2.0.1.data → hdsp_jupyter_extension-2.0.3.data}/data/share/jupyter/labextensions/hdsp-agent/static/node_modules_emotion_use-insertion-effect-with-fallbacks_dist_emotion-use-insertion-effect-wi-3ba6b81.61e75fb98ecff46cf836.js.map +0 -0
- {hdsp_jupyter_extension-2.0.1.data → hdsp_jupyter_extension-2.0.3.data}/data/share/jupyter/labextensions/hdsp-agent/static/style.js +0 -0
- {hdsp_jupyter_extension-2.0.1.data → hdsp_jupyter_extension-2.0.3.data}/data/share/jupyter/labextensions/hdsp-agent/static/vendors-node_modules_babel_runtime_helpers_esm_extends_js-node_modules_emotion_serialize_dist-051195.e2553aab0c3963b83dd7.js +0 -0
- {hdsp_jupyter_extension-2.0.1.data → hdsp_jupyter_extension-2.0.3.data}/data/share/jupyter/labextensions/hdsp-agent/static/vendors-node_modules_babel_runtime_helpers_esm_extends_js-node_modules_emotion_serialize_dist-051195.e2553aab0c3963b83dd7.js.map +0 -0
- {hdsp_jupyter_extension-2.0.1.data → hdsp_jupyter_extension-2.0.3.data}/data/share/jupyter/labextensions/hdsp-agent/static/vendors-node_modules_emotion_styled_dist_emotion-styled_browser_development_esm_js.661fb5836f4978a7c6e1.js +0 -0
- {hdsp_jupyter_extension-2.0.1.data → hdsp_jupyter_extension-2.0.3.data}/data/share/jupyter/labextensions/hdsp-agent/static/vendors-node_modules_emotion_styled_dist_emotion-styled_browser_development_esm_js.661fb5836f4978a7c6e1.js.map +0 -0
- {hdsp_jupyter_extension-2.0.1.data → hdsp_jupyter_extension-2.0.3.data}/data/share/jupyter/labextensions/hdsp-agent/static/vendors-node_modules_mui_material_index_js.985697e0162d8d088ca2.js +0 -0
- {hdsp_jupyter_extension-2.0.1.data → hdsp_jupyter_extension-2.0.3.data}/data/share/jupyter/labextensions/hdsp-agent/static/vendors-node_modules_mui_material_index_js.985697e0162d8d088ca2.js.map +0 -0
- {hdsp_jupyter_extension-2.0.1.dist-info → hdsp_jupyter_extension-2.0.3.dist-info}/WHEEL +0 -0
- {hdsp_jupyter_extension-2.0.1.dist-info → hdsp_jupyter_extension-2.0.3.dist-info}/licenses/LICENSE +0 -0
|
@@ -0,0 +1,240 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Validation Middleware
|
|
3
|
+
|
|
4
|
+
Validates code before execution in Jupyter cells.
|
|
5
|
+
Uses static analysis (AST, Ruff, Pyflakes) to detect issues.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
import logging
|
|
9
|
+
from typing import Any, Dict, Optional
|
|
10
|
+
|
|
11
|
+
from agent_server.langchain.state import AgentRuntime, AgentState
|
|
12
|
+
|
|
13
|
+
logger = logging.getLogger(__name__)
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class ValidationMiddleware:
|
|
17
|
+
"""
|
|
18
|
+
Middleware that validates code before tool execution.
|
|
19
|
+
|
|
20
|
+
This middleware:
|
|
21
|
+
1. Intercepts jupyter_cell tool calls
|
|
22
|
+
2. Validates the code using CodeValidator
|
|
23
|
+
3. Blocks execution if critical errors found
|
|
24
|
+
4. Provides fix suggestions when possible
|
|
25
|
+
|
|
26
|
+
Uses @before_tool_call hook pattern from LangChain middleware.
|
|
27
|
+
"""
|
|
28
|
+
|
|
29
|
+
def __init__(
|
|
30
|
+
self,
|
|
31
|
+
code_validator: Any = None,
|
|
32
|
+
block_on_errors: bool = True,
|
|
33
|
+
auto_fix: bool = False,
|
|
34
|
+
enabled: bool = True,
|
|
35
|
+
):
|
|
36
|
+
"""
|
|
37
|
+
Initialize validation middleware.
|
|
38
|
+
|
|
39
|
+
Args:
|
|
40
|
+
code_validator: CodeValidator instance
|
|
41
|
+
block_on_errors: Block execution if errors found
|
|
42
|
+
auto_fix: Attempt auto-fix for fixable issues
|
|
43
|
+
enabled: Whether validation is enabled
|
|
44
|
+
"""
|
|
45
|
+
self._validator = code_validator
|
|
46
|
+
self._block_on_errors = block_on_errors
|
|
47
|
+
self._auto_fix = auto_fix
|
|
48
|
+
self._enabled = enabled
|
|
49
|
+
|
|
50
|
+
@property
|
|
51
|
+
def name(self) -> str:
|
|
52
|
+
return "ValidationMiddleware"
|
|
53
|
+
|
|
54
|
+
def _get_validator(self):
|
|
55
|
+
"""Lazy load code validator"""
|
|
56
|
+
if self._validator is None:
|
|
57
|
+
try:
|
|
58
|
+
from agent_server.core.code_validator import CodeValidator
|
|
59
|
+
self._validator = CodeValidator()
|
|
60
|
+
except ImportError:
|
|
61
|
+
logger.warning("CodeValidator not available")
|
|
62
|
+
return None
|
|
63
|
+
return self._validator
|
|
64
|
+
|
|
65
|
+
def _extract_code_from_tool_call(
|
|
66
|
+
self,
|
|
67
|
+
tool_name: str,
|
|
68
|
+
tool_input: Dict[str, Any],
|
|
69
|
+
) -> Optional[str]:
|
|
70
|
+
"""Extract code from tool call if applicable"""
|
|
71
|
+
if tool_name != "jupyter_cell_tool":
|
|
72
|
+
return None
|
|
73
|
+
|
|
74
|
+
code = tool_input.get("code", "")
|
|
75
|
+
if not code:
|
|
76
|
+
return None
|
|
77
|
+
|
|
78
|
+
return code
|
|
79
|
+
|
|
80
|
+
def _validate_code(
|
|
81
|
+
self,
|
|
82
|
+
code: str,
|
|
83
|
+
notebook_context: Dict[str, Any],
|
|
84
|
+
) -> Dict[str, Any]:
|
|
85
|
+
"""Validate code using CodeValidator"""
|
|
86
|
+
validator = self._get_validator()
|
|
87
|
+
if validator is None:
|
|
88
|
+
return {
|
|
89
|
+
"valid": True,
|
|
90
|
+
"issues": [],
|
|
91
|
+
"summary": "Validation skipped (validator not available)",
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
try:
|
|
95
|
+
# Build context for validator
|
|
96
|
+
ctx = {
|
|
97
|
+
"definedVariables": notebook_context.get("defined_variables", []),
|
|
98
|
+
"importedLibraries": notebook_context.get("imported_libraries", []),
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
# Reinitialize validator with context
|
|
102
|
+
validator_with_ctx = type(validator)(notebook_context=ctx)
|
|
103
|
+
result = validator_with_ctx.full_validation(code)
|
|
104
|
+
|
|
105
|
+
return {
|
|
106
|
+
"valid": result.is_valid,
|
|
107
|
+
"issues": [issue.to_dict() for issue in result.issues],
|
|
108
|
+
"has_errors": result.has_errors,
|
|
109
|
+
"has_warnings": result.has_warnings,
|
|
110
|
+
"summary": result.summary,
|
|
111
|
+
"dependencies": result.dependencies.to_dict() if result.dependencies else None,
|
|
112
|
+
}
|
|
113
|
+
except Exception as e:
|
|
114
|
+
logger.error(f"Validation failed: {e}")
|
|
115
|
+
return {
|
|
116
|
+
"valid": True, # Don't block on validation errors
|
|
117
|
+
"issues": [],
|
|
118
|
+
"summary": f"Validation error: {str(e)}",
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
async def before_tool_call(
|
|
122
|
+
self,
|
|
123
|
+
tool_name: str,
|
|
124
|
+
tool_input: Dict[str, Any],
|
|
125
|
+
state: AgentState,
|
|
126
|
+
runtime: AgentRuntime,
|
|
127
|
+
) -> Optional[Dict[str, Any]]:
|
|
128
|
+
"""
|
|
129
|
+
Hook called before each tool execution.
|
|
130
|
+
|
|
131
|
+
Validates code for jupyter_cell tool calls.
|
|
132
|
+
|
|
133
|
+
Args:
|
|
134
|
+
tool_name: Name of the tool being called
|
|
135
|
+
tool_input: Tool input parameters
|
|
136
|
+
state: Current agent state
|
|
137
|
+
runtime: Agent runtime context
|
|
138
|
+
|
|
139
|
+
Returns:
|
|
140
|
+
Modified tool input, or raises exception to block
|
|
141
|
+
"""
|
|
142
|
+
if not self._enabled:
|
|
143
|
+
return None
|
|
144
|
+
|
|
145
|
+
code = self._extract_code_from_tool_call(tool_name, tool_input)
|
|
146
|
+
if code is None:
|
|
147
|
+
return None
|
|
148
|
+
|
|
149
|
+
notebook_context = state.get("notebook_context", {})
|
|
150
|
+
validation_result = self._validate_code(code, notebook_context)
|
|
151
|
+
|
|
152
|
+
# Store validation result in state
|
|
153
|
+
state["validation_result"] = validation_result
|
|
154
|
+
|
|
155
|
+
if not validation_result.get("valid", True) and self._block_on_errors:
|
|
156
|
+
# Get error details
|
|
157
|
+
errors = [
|
|
158
|
+
issue for issue in validation_result.get("issues", [])
|
|
159
|
+
if issue.get("severity") == "error"
|
|
160
|
+
]
|
|
161
|
+
|
|
162
|
+
if errors:
|
|
163
|
+
error_messages = [
|
|
164
|
+
f"- {e.get('category', 'error')}: {e.get('message', 'Unknown error')}"
|
|
165
|
+
for e in errors[:5] # Limit to 5 errors
|
|
166
|
+
]
|
|
167
|
+
|
|
168
|
+
logger.warning(f"Code validation failed: {len(errors)} errors")
|
|
169
|
+
|
|
170
|
+
# Return modified result that includes validation feedback
|
|
171
|
+
return {
|
|
172
|
+
"code": code,
|
|
173
|
+
"validation_failed": True,
|
|
174
|
+
"validation_errors": error_messages,
|
|
175
|
+
"original_input": tool_input,
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
# Log warnings but allow execution
|
|
179
|
+
warnings = [
|
|
180
|
+
issue for issue in validation_result.get("issues", [])
|
|
181
|
+
if issue.get("severity") == "warning"
|
|
182
|
+
]
|
|
183
|
+
if warnings:
|
|
184
|
+
logger.info(f"Code validation: {len(warnings)} warnings")
|
|
185
|
+
|
|
186
|
+
return None
|
|
187
|
+
|
|
188
|
+
def format_validation_feedback(
|
|
189
|
+
self,
|
|
190
|
+
validation_result: Dict[str, Any],
|
|
191
|
+
) -> str:
|
|
192
|
+
"""
|
|
193
|
+
Format validation result for feedback to the model.
|
|
194
|
+
|
|
195
|
+
Args:
|
|
196
|
+
validation_result: Validation result dict
|
|
197
|
+
|
|
198
|
+
Returns:
|
|
199
|
+
Formatted feedback string
|
|
200
|
+
"""
|
|
201
|
+
if validation_result.get("valid", True):
|
|
202
|
+
return ""
|
|
203
|
+
|
|
204
|
+
lines = ["## Code Validation Issues"]
|
|
205
|
+
|
|
206
|
+
for issue in validation_result.get("issues", [])[:10]:
|
|
207
|
+
severity = issue.get("severity", "info")
|
|
208
|
+
category = issue.get("category", "unknown")
|
|
209
|
+
message = issue.get("message", "")
|
|
210
|
+
line = issue.get("line")
|
|
211
|
+
|
|
212
|
+
location = f"L{line}" if line else ""
|
|
213
|
+
lines.append(f"- [{severity.upper()}] {category}{location}: {message}")
|
|
214
|
+
|
|
215
|
+
lines.append("\nPlease fix these issues before execution.")
|
|
216
|
+
|
|
217
|
+
return "\n".join(lines)
|
|
218
|
+
|
|
219
|
+
|
|
220
|
+
def create_validation_middleware(
|
|
221
|
+
block_on_errors: bool = True,
|
|
222
|
+
auto_fix: bool = False,
|
|
223
|
+
enabled: bool = True,
|
|
224
|
+
) -> ValidationMiddleware:
|
|
225
|
+
"""
|
|
226
|
+
Factory function to create validation middleware.
|
|
227
|
+
|
|
228
|
+
Args:
|
|
229
|
+
block_on_errors: Block execution on validation errors
|
|
230
|
+
auto_fix: Attempt auto-fix for issues
|
|
231
|
+
enabled: Whether to enable validation
|
|
232
|
+
|
|
233
|
+
Returns:
|
|
234
|
+
Configured ValidationMiddleware instance
|
|
235
|
+
"""
|
|
236
|
+
return ValidationMiddleware(
|
|
237
|
+
block_on_errors=block_on_errors,
|
|
238
|
+
auto_fix=auto_fix,
|
|
239
|
+
enabled=enabled,
|
|
240
|
+
)
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Agent State Management
|
|
3
|
+
|
|
4
|
+
Defines the state schema for the LangChain agent using TypedDict.
|
|
5
|
+
This state is passed through the agent execution and updated by middleware.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from dataclasses import dataclass
|
|
9
|
+
from typing import Annotated, Any, Dict, List, Optional, TypedDict
|
|
10
|
+
|
|
11
|
+
from langchain_core.messages import BaseMessage
|
|
12
|
+
from langgraph.graph.message import add_messages
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
class NotebookContext(TypedDict, total=False):
|
|
16
|
+
"""Current notebook context"""
|
|
17
|
+
notebook_path: str
|
|
18
|
+
cell_count: int
|
|
19
|
+
imported_libraries: List[str]
|
|
20
|
+
defined_variables: List[str]
|
|
21
|
+
recent_cells: List[Dict[str, Any]]
|
|
22
|
+
kernel_id: Optional[str]
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
class ExecutionResult(TypedDict, total=False):
|
|
26
|
+
"""Result of code execution"""
|
|
27
|
+
success: bool
|
|
28
|
+
output: str
|
|
29
|
+
error_type: Optional[str]
|
|
30
|
+
error_message: Optional[str]
|
|
31
|
+
traceback: Optional[List[str]]
|
|
32
|
+
execution_count: int
|
|
33
|
+
cell_index: int
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
class SearchResult(TypedDict, total=False):
|
|
37
|
+
"""Result of code search"""
|
|
38
|
+
file_path: str
|
|
39
|
+
cell_index: Optional[int]
|
|
40
|
+
line_number: Optional[int]
|
|
41
|
+
content: str
|
|
42
|
+
match_type: str # "file", "cell", "line"
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
class AgentState(TypedDict, total=False):
|
|
46
|
+
"""
|
|
47
|
+
Main agent state schema for LangGraph.
|
|
48
|
+
|
|
49
|
+
This state flows through the agent execution and is updated by:
|
|
50
|
+
- Middleware (RAG context, validation results, etc.)
|
|
51
|
+
- Tool executions (execution results, search results)
|
|
52
|
+
- Agent decisions (current step, plan updates)
|
|
53
|
+
"""
|
|
54
|
+
# Message history - uses add_messages reducer to accumulate messages
|
|
55
|
+
messages: Annotated[List[BaseMessage], add_messages]
|
|
56
|
+
|
|
57
|
+
# User request
|
|
58
|
+
user_request: str
|
|
59
|
+
|
|
60
|
+
# Notebook context
|
|
61
|
+
notebook_context: NotebookContext
|
|
62
|
+
|
|
63
|
+
# RAG context (injected by RAGMiddleware)
|
|
64
|
+
rag_context: Optional[str]
|
|
65
|
+
|
|
66
|
+
# Code search results (injected by CodeSearchMiddleware)
|
|
67
|
+
search_results: List[SearchResult]
|
|
68
|
+
|
|
69
|
+
# Current execution plan
|
|
70
|
+
plan: Optional[Dict[str, Any]]
|
|
71
|
+
current_step_index: int
|
|
72
|
+
|
|
73
|
+
# Execution history
|
|
74
|
+
execution_history: List[ExecutionResult]
|
|
75
|
+
|
|
76
|
+
# Validation results
|
|
77
|
+
validation_result: Optional[Dict[str, Any]]
|
|
78
|
+
|
|
79
|
+
# Error handling state
|
|
80
|
+
error_count: int
|
|
81
|
+
last_error: Optional[Dict[str, Any]]
|
|
82
|
+
recovery_strategy: Optional[str]
|
|
83
|
+
|
|
84
|
+
# LLM configuration
|
|
85
|
+
llm_config: Dict[str, Any]
|
|
86
|
+
|
|
87
|
+
# Detected libraries for knowledge injection
|
|
88
|
+
detected_libraries: List[str]
|
|
89
|
+
|
|
90
|
+
# Final answer
|
|
91
|
+
final_answer: Optional[str]
|
|
92
|
+
is_complete: bool
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
@dataclass
|
|
96
|
+
class AgentRuntime:
|
|
97
|
+
"""
|
|
98
|
+
Runtime context passed to middleware.
|
|
99
|
+
|
|
100
|
+
Contains references to executors and services needed by middleware.
|
|
101
|
+
"""
|
|
102
|
+
jupyter_executor: Any = None
|
|
103
|
+
notebook_searcher: Any = None
|
|
104
|
+
rag_manager: Any = None
|
|
105
|
+
code_validator: Any = None
|
|
106
|
+
error_classifier: Any = None
|
|
107
|
+
workspace_root: str = "."
|
|
108
|
+
|
|
109
|
+
# Execution mode
|
|
110
|
+
embedded_mode: bool = True
|
|
111
|
+
|
|
112
|
+
# Configuration
|
|
113
|
+
max_retries: int = 3
|
|
114
|
+
max_model_calls: int = 20
|
|
115
|
+
enable_rag: bool = True
|
|
116
|
+
enable_validation: bool = True
|
|
117
|
+
|
|
118
|
+
|
|
119
|
+
def create_initial_state(
|
|
120
|
+
user_request: str,
|
|
121
|
+
notebook_context: Optional[Dict[str, Any]] = None,
|
|
122
|
+
llm_config: Optional[Dict[str, Any]] = None,
|
|
123
|
+
) -> AgentState:
|
|
124
|
+
"""
|
|
125
|
+
Create initial agent state from user request.
|
|
126
|
+
|
|
127
|
+
Args:
|
|
128
|
+
user_request: Natural language request from user
|
|
129
|
+
notebook_context: Current notebook state
|
|
130
|
+
llm_config: LLM configuration
|
|
131
|
+
|
|
132
|
+
Returns:
|
|
133
|
+
Initialized AgentState
|
|
134
|
+
"""
|
|
135
|
+
return AgentState(
|
|
136
|
+
messages=[],
|
|
137
|
+
user_request=user_request,
|
|
138
|
+
notebook_context=notebook_context or NotebookContext(
|
|
139
|
+
notebook_path="",
|
|
140
|
+
cell_count=0,
|
|
141
|
+
imported_libraries=[],
|
|
142
|
+
defined_variables=[],
|
|
143
|
+
recent_cells=[],
|
|
144
|
+
kernel_id=None,
|
|
145
|
+
),
|
|
146
|
+
rag_context=None,
|
|
147
|
+
search_results=[],
|
|
148
|
+
plan=None,
|
|
149
|
+
current_step_index=0,
|
|
150
|
+
execution_history=[],
|
|
151
|
+
validation_result=None,
|
|
152
|
+
error_count=0,
|
|
153
|
+
last_error=None,
|
|
154
|
+
recovery_strategy=None,
|
|
155
|
+
llm_config=llm_config or {},
|
|
156
|
+
detected_libraries=[],
|
|
157
|
+
final_answer=None,
|
|
158
|
+
is_complete=False,
|
|
159
|
+
)
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
"""
|
|
2
|
+
LangChain Tools for Jupyter Agent
|
|
3
|
+
|
|
4
|
+
Tools available:
|
|
5
|
+
- jupyter_cell: Execute Python code in notebook
|
|
6
|
+
- markdown: Add markdown cell
|
|
7
|
+
- final_answer: Complete the task
|
|
8
|
+
- read_file: Read file content
|
|
9
|
+
- write_file: Write file content
|
|
10
|
+
- list_files: List directory contents
|
|
11
|
+
- search_workspace: Search files in workspace
|
|
12
|
+
- search_notebook_cells: Search cells in notebooks
|
|
13
|
+
"""
|
|
14
|
+
|
|
15
|
+
from agent_server.langchain.tools.file_tools import (
|
|
16
|
+
list_files_tool,
|
|
17
|
+
read_file_tool,
|
|
18
|
+
write_file_tool,
|
|
19
|
+
)
|
|
20
|
+
from agent_server.langchain.tools.jupyter_tools import (
|
|
21
|
+
final_answer_tool,
|
|
22
|
+
jupyter_cell_tool,
|
|
23
|
+
markdown_tool,
|
|
24
|
+
)
|
|
25
|
+
from agent_server.langchain.tools.search_tools import (
|
|
26
|
+
search_notebook_cells_tool,
|
|
27
|
+
search_workspace_tool,
|
|
28
|
+
)
|
|
29
|
+
|
|
30
|
+
__all__ = [
|
|
31
|
+
"jupyter_cell_tool",
|
|
32
|
+
"markdown_tool",
|
|
33
|
+
"final_answer_tool",
|
|
34
|
+
"read_file_tool",
|
|
35
|
+
"write_file_tool",
|
|
36
|
+
"list_files_tool",
|
|
37
|
+
"search_workspace_tool",
|
|
38
|
+
"search_notebook_cells_tool",
|
|
39
|
+
]
|