hdsp-jupyter-extension 2.0.6__py3-none-any.whl → 2.0.7__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 (90) hide show
  1. agent_server/core/reflection_engine.py +0 -1
  2. agent_server/knowledge/watchdog_service.py +1 -1
  3. agent_server/langchain/ARCHITECTURE.md +1193 -0
  4. agent_server/langchain/agent.py +74 -588
  5. agent_server/langchain/custom_middleware.py +636 -0
  6. agent_server/langchain/executors/__init__.py +2 -7
  7. agent_server/langchain/executors/notebook_searcher.py +46 -38
  8. agent_server/langchain/hitl_config.py +66 -0
  9. agent_server/langchain/llm_factory.py +166 -0
  10. agent_server/langchain/logging_utils.py +184 -0
  11. agent_server/langchain/prompts.py +119 -0
  12. agent_server/langchain/state.py +16 -6
  13. agent_server/langchain/tools/__init__.py +6 -0
  14. agent_server/langchain/tools/file_tools.py +91 -129
  15. agent_server/langchain/tools/jupyter_tools.py +18 -18
  16. agent_server/langchain/tools/resource_tools.py +161 -0
  17. agent_server/langchain/tools/search_tools.py +198 -216
  18. agent_server/langchain/tools/shell_tools.py +54 -0
  19. agent_server/main.py +4 -1
  20. agent_server/routers/health.py +1 -1
  21. agent_server/routers/langchain_agent.py +940 -285
  22. hdsp_agent_core/prompts/auto_agent_prompts.py +3 -3
  23. {hdsp_jupyter_extension-2.0.6.data → hdsp_jupyter_extension-2.0.7.data}/data/share/jupyter/labextensions/hdsp-agent/build_log.json +1 -1
  24. {hdsp_jupyter_extension-2.0.6.data → hdsp_jupyter_extension-2.0.7.data}/data/share/jupyter/labextensions/hdsp-agent/package.json +2 -2
  25. hdsp_jupyter_extension-2.0.6.data/data/share/jupyter/labextensions/hdsp-agent/static/frontend_styles_index_js.02d346171474a0fb2dc1.js → hdsp_jupyter_extension-2.0.7.data/data/share/jupyter/labextensions/hdsp-agent/static/frontend_styles_index_js.4770ec0fb2d173b6deb4.js +312 -6
  26. hdsp_jupyter_extension-2.0.7.data/data/share/jupyter/labextensions/hdsp-agent/static/frontend_styles_index_js.4770ec0fb2d173b6deb4.js.map +1 -0
  27. hdsp_jupyter_extension-2.0.6.data/data/share/jupyter/labextensions/hdsp-agent/static/lib_index_js.a223ea20056954479ae9.js → hdsp_jupyter_extension-2.0.7.data/data/share/jupyter/labextensions/hdsp-agent/static/lib_index_js.29cf4312af19e86f82af.js +1547 -330
  28. hdsp_jupyter_extension-2.0.7.data/data/share/jupyter/labextensions/hdsp-agent/static/lib_index_js.29cf4312af19e86f82af.js.map +1 -0
  29. hdsp_jupyter_extension-2.0.6.data/data/share/jupyter/labextensions/hdsp-agent/static/remoteEntry.addf2fa038fa60304aa2.js → hdsp_jupyter_extension-2.0.7.data/data/share/jupyter/labextensions/hdsp-agent/static/remoteEntry.61343eb4cf0577e74b50.js +8 -8
  30. hdsp_jupyter_extension-2.0.7.data/data/share/jupyter/labextensions/hdsp-agent/static/remoteEntry.61343eb4cf0577e74b50.js.map +1 -0
  31. hdsp_jupyter_extension-2.0.6.data/data/share/jupyter/labextensions/hdsp-agent/static/vendors-node_modules_emotion_cache_dist_emotion-cache_browser_development_esm_js.24edcc52a1c014a8a5f0.js → hdsp_jupyter_extension-2.0.7.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 +209 -2
  32. hdsp_jupyter_extension-2.0.7.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 +1 -0
  33. jupyter_ext/labextension/static/vendors-node_modules_emotion_react_dist_emotion-react_browser_development_esm_js.19ecf6babe00caff6b8a.js → hdsp_jupyter_extension-2.0.7.data/data/share/jupyter/labextensions/hdsp-agent/static/vendors-node_modules_emotion_react_dist_emotion-react_browser_development_esm_js.36b49c71871f98d4f549.js +2 -209
  34. hdsp_jupyter_extension-2.0.7.data/data/share/jupyter/labextensions/hdsp-agent/static/vendors-node_modules_emotion_react_dist_emotion-react_browser_development_esm_js.36b49c71871f98d4f549.js.map +1 -0
  35. hdsp_jupyter_extension-2.0.6.data/data/share/jupyter/labextensions/hdsp-agent/static/vendors-node_modules_mui_material_utils_createSvgIcon_js.1f5038488cdfd8b3a85d.js → hdsp_jupyter_extension-2.0.7.data/data/share/jupyter/labextensions/hdsp-agent/static/vendors-node_modules_mui_material_utils_createSvgIcon_js.2e13df4ea61496e95d45.js +3 -212
  36. hdsp_jupyter_extension-2.0.7.data/data/share/jupyter/labextensions/hdsp-agent/static/vendors-node_modules_mui_material_utils_createSvgIcon_js.2e13df4ea61496e95d45.js.map +1 -0
  37. {hdsp_jupyter_extension-2.0.6.dist-info → hdsp_jupyter_extension-2.0.7.dist-info}/METADATA +2 -1
  38. {hdsp_jupyter_extension-2.0.6.dist-info → hdsp_jupyter_extension-2.0.7.dist-info}/RECORD +71 -68
  39. jupyter_ext/_version.py +1 -1
  40. jupyter_ext/handlers.py +1176 -58
  41. jupyter_ext/labextension/build_log.json +1 -1
  42. jupyter_ext/labextension/package.json +2 -2
  43. jupyter_ext/labextension/static/{frontend_styles_index_js.02d346171474a0fb2dc1.js → frontend_styles_index_js.4770ec0fb2d173b6deb4.js} +312 -6
  44. jupyter_ext/labextension/static/frontend_styles_index_js.4770ec0fb2d173b6deb4.js.map +1 -0
  45. jupyter_ext/labextension/static/{lib_index_js.a223ea20056954479ae9.js → lib_index_js.29cf4312af19e86f82af.js} +1547 -330
  46. jupyter_ext/labextension/static/lib_index_js.29cf4312af19e86f82af.js.map +1 -0
  47. jupyter_ext/labextension/static/{remoteEntry.addf2fa038fa60304aa2.js → remoteEntry.61343eb4cf0577e74b50.js} +8 -8
  48. jupyter_ext/labextension/static/remoteEntry.61343eb4cf0577e74b50.js.map +1 -0
  49. jupyter_ext/labextension/static/{vendors-node_modules_emotion_cache_dist_emotion-cache_browser_development_esm_js.24edcc52a1c014a8a5f0.js → vendors-node_modules_emotion_cache_dist_emotion-cache_browser_development_esm_js-node_modules-782ee5.d9ed8645ef1d311657d8.js} +209 -2
  50. jupyter_ext/labextension/static/vendors-node_modules_emotion_cache_dist_emotion-cache_browser_development_esm_js-node_modules-782ee5.d9ed8645ef1d311657d8.js.map +1 -0
  51. hdsp_jupyter_extension-2.0.6.data/data/share/jupyter/labextensions/hdsp-agent/static/vendors-node_modules_emotion_react_dist_emotion-react_browser_development_esm_js.19ecf6babe00caff6b8a.js → jupyter_ext/labextension/static/vendors-node_modules_emotion_react_dist_emotion-react_browser_development_esm_js.36b49c71871f98d4f549.js +2 -209
  52. jupyter_ext/labextension/static/vendors-node_modules_emotion_react_dist_emotion-react_browser_development_esm_js.36b49c71871f98d4f549.js.map +1 -0
  53. jupyter_ext/labextension/static/{vendors-node_modules_mui_material_utils_createSvgIcon_js.1f5038488cdfd8b3a85d.js → vendors-node_modules_mui_material_utils_createSvgIcon_js.2e13df4ea61496e95d45.js} +3 -212
  54. jupyter_ext/labextension/static/vendors-node_modules_mui_material_utils_createSvgIcon_js.2e13df4ea61496e95d45.js.map +1 -0
  55. jupyter_ext/resource_usage.py +180 -0
  56. jupyter_ext/tests/test_handlers.py +58 -0
  57. agent_server/langchain/executors/jupyter_executor.py +0 -429
  58. agent_server/langchain/middleware/__init__.py +0 -36
  59. agent_server/langchain/middleware/code_search_middleware.py +0 -278
  60. agent_server/langchain/middleware/error_handling_middleware.py +0 -338
  61. agent_server/langchain/middleware/jupyter_execution_middleware.py +0 -301
  62. agent_server/langchain/middleware/rag_middleware.py +0 -227
  63. agent_server/langchain/middleware/validation_middleware.py +0 -240
  64. hdsp_jupyter_extension-2.0.6.data/data/share/jupyter/labextensions/hdsp-agent/static/frontend_styles_index_js.02d346171474a0fb2dc1.js.map +0 -1
  65. hdsp_jupyter_extension-2.0.6.data/data/share/jupyter/labextensions/hdsp-agent/static/lib_index_js.a223ea20056954479ae9.js.map +0 -1
  66. hdsp_jupyter_extension-2.0.6.data/data/share/jupyter/labextensions/hdsp-agent/static/remoteEntry.addf2fa038fa60304aa2.js.map +0 -1
  67. hdsp_jupyter_extension-2.0.6.data/data/share/jupyter/labextensions/hdsp-agent/static/vendors-node_modules_emotion_cache_dist_emotion-cache_browser_development_esm_js.24edcc52a1c014a8a5f0.js.map +0 -1
  68. hdsp_jupyter_extension-2.0.6.data/data/share/jupyter/labextensions/hdsp-agent/static/vendors-node_modules_emotion_react_dist_emotion-react_browser_development_esm_js.19ecf6babe00caff6b8a.js.map +0 -1
  69. hdsp_jupyter_extension-2.0.6.data/data/share/jupyter/labextensions/hdsp-agent/static/vendors-node_modules_mui_material_utils_createSvgIcon_js.1f5038488cdfd8b3a85d.js.map +0 -1
  70. jupyter_ext/labextension/static/frontend_styles_index_js.02d346171474a0fb2dc1.js.map +0 -1
  71. jupyter_ext/labextension/static/lib_index_js.a223ea20056954479ae9.js.map +0 -1
  72. jupyter_ext/labextension/static/remoteEntry.addf2fa038fa60304aa2.js.map +0 -1
  73. jupyter_ext/labextension/static/vendors-node_modules_emotion_cache_dist_emotion-cache_browser_development_esm_js.24edcc52a1c014a8a5f0.js.map +0 -1
  74. jupyter_ext/labextension/static/vendors-node_modules_emotion_react_dist_emotion-react_browser_development_esm_js.19ecf6babe00caff6b8a.js.map +0 -1
  75. jupyter_ext/labextension/static/vendors-node_modules_mui_material_utils_createSvgIcon_js.1f5038488cdfd8b3a85d.js.map +0 -1
  76. {hdsp_jupyter_extension-2.0.6.data → hdsp_jupyter_extension-2.0.7.data}/data/etc/jupyter/jupyter_server_config.d/hdsp_jupyter_extension.json +0 -0
  77. {hdsp_jupyter_extension-2.0.6.data → hdsp_jupyter_extension-2.0.7.data}/data/share/jupyter/labextensions/hdsp-agent/install.json +0 -0
  78. {hdsp_jupyter_extension-2.0.6.data → hdsp_jupyter_extension-2.0.7.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
  79. {hdsp_jupyter_extension-2.0.6.data → hdsp_jupyter_extension-2.0.7.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
  80. {hdsp_jupyter_extension-2.0.6.data → hdsp_jupyter_extension-2.0.7.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
  81. {hdsp_jupyter_extension-2.0.6.data → hdsp_jupyter_extension-2.0.7.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
  82. {hdsp_jupyter_extension-2.0.6.data → hdsp_jupyter_extension-2.0.7.data}/data/share/jupyter/labextensions/hdsp-agent/static/style.js +0 -0
  83. {hdsp_jupyter_extension-2.0.6.data → hdsp_jupyter_extension-2.0.7.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
  84. {hdsp_jupyter_extension-2.0.6.data → hdsp_jupyter_extension-2.0.7.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
  85. {hdsp_jupyter_extension-2.0.6.data → hdsp_jupyter_extension-2.0.7.data}/data/share/jupyter/labextensions/hdsp-agent/static/vendors-node_modules_emotion_styled_dist_emotion-styled_browser_development_esm_js.661fb5836f4978a7c6e1.js +0 -0
  86. {hdsp_jupyter_extension-2.0.6.data → hdsp_jupyter_extension-2.0.7.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
  87. {hdsp_jupyter_extension-2.0.6.data → hdsp_jupyter_extension-2.0.7.data}/data/share/jupyter/labextensions/hdsp-agent/static/vendors-node_modules_mui_material_index_js.985697e0162d8d088ca2.js +0 -0
  88. {hdsp_jupyter_extension-2.0.6.data → hdsp_jupyter_extension-2.0.7.data}/data/share/jupyter/labextensions/hdsp-agent/static/vendors-node_modules_mui_material_index_js.985697e0162d8d088ca2.js.map +0 -0
  89. {hdsp_jupyter_extension-2.0.6.dist-info → hdsp_jupyter_extension-2.0.7.dist-info}/WHEEL +0 -0
  90. {hdsp_jupyter_extension-2.0.6.dist-info → hdsp_jupyter_extension-2.0.7.dist-info}/licenses/LICENSE +0 -0
@@ -1,301 +0,0 @@
1
- """
2
- Jupyter Execution Middleware
3
-
4
- Handles actual execution of code in Jupyter kernel.
5
- Wraps jupyter_cell tool calls to execute code and return results.
6
- """
7
-
8
- import asyncio
9
- import logging
10
- from typing import Any, Callable, Dict, Optional
11
-
12
- from agent_server.langchain.executors.jupyter_executor import (
13
- JupyterExecutor,
14
- get_jupyter_executor,
15
- )
16
- from agent_server.langchain.state import AgentRuntime, AgentState
17
-
18
- logger = logging.getLogger(__name__)
19
-
20
-
21
- class JupyterExecutionMiddleware:
22
- """
23
- Middleware that executes code in Jupyter kernel.
24
-
25
- This middleware:
26
- 1. Wraps jupyter_cell and markdown tool calls
27
- 2. Executes code using JupyterExecutor
28
- 3. Returns execution results to the agent
29
- 4. Handles execution errors and timeouts
30
-
31
- Uses @wrap_tool_call hook pattern from LangChain middleware.
32
- """
33
-
34
- def __init__(
35
- self,
36
- executor: Optional[JupyterExecutor] = None,
37
- timeout: float = 60.0,
38
- add_to_notebook: bool = True,
39
- enabled: bool = True,
40
- ):
41
- """
42
- Initialize Jupyter execution middleware.
43
-
44
- Args:
45
- executor: JupyterExecutor instance
46
- timeout: Execution timeout in seconds
47
- add_to_notebook: Whether to add cells to notebook
48
- enabled: Whether execution is enabled
49
- """
50
- self._executor = executor
51
- self._timeout = timeout
52
- self._add_to_notebook = add_to_notebook
53
- self._enabled = enabled
54
-
55
- @property
56
- def name(self) -> str:
57
- return "JupyterExecutionMiddleware"
58
-
59
- def _get_executor(self, runtime: AgentRuntime) -> JupyterExecutor:
60
- """Get executor from runtime or create default"""
61
- if runtime and runtime.jupyter_executor:
62
- return runtime.jupyter_executor
63
- if self._executor:
64
- return self._executor
65
- return get_jupyter_executor()
66
-
67
- async def wrap_tool_call(
68
- self,
69
- tool_name: str,
70
- tool_input: Dict[str, Any],
71
- next_call: Callable,
72
- state: AgentState,
73
- runtime: AgentRuntime,
74
- ) -> Dict[str, Any]:
75
- """
76
- Wrap tool calls to handle Jupyter execution.
77
-
78
- For jupyter_cell tools, executes code in kernel.
79
- For other tools, passes through to next handler.
80
-
81
- Args:
82
- tool_name: Name of the tool
83
- tool_input: Tool input parameters
84
- next_call: Next handler in chain
85
- state: Current agent state
86
- runtime: Agent runtime context
87
-
88
- Returns:
89
- Tool execution result
90
- """
91
- if not self._enabled:
92
- return await next_call(tool_name, tool_input)
93
-
94
- # Handle jupyter_cell execution
95
- if tool_name == "jupyter_cell_tool":
96
- return await self._execute_jupyter_cell(
97
- tool_input, state, runtime
98
- )
99
-
100
- # Handle markdown cell
101
- if tool_name == "markdown_tool":
102
- return await self._add_markdown_cell(
103
- tool_input, state, runtime
104
- )
105
-
106
- # Handle final_answer
107
- if tool_name == "final_answer_tool":
108
- return await self._handle_final_answer(
109
- tool_input, state, runtime
110
- )
111
-
112
- # Pass through for other tools
113
- return await next_call(tool_name, tool_input)
114
-
115
- async def _execute_jupyter_cell(
116
- self,
117
- tool_input: Dict[str, Any],
118
- state: AgentState,
119
- runtime: AgentRuntime,
120
- ) -> Dict[str, Any]:
121
- """Execute code in Jupyter cell"""
122
- code = tool_input.get("code", "")
123
- if not code:
124
- return {
125
- "success": False,
126
- "error": "No code provided",
127
- }
128
-
129
- # Check for validation failure
130
- if tool_input.get("validation_failed"):
131
- errors = tool_input.get("validation_errors", [])
132
- return {
133
- "success": False,
134
- "error_type": "ValidationError",
135
- "error": "Code validation failed",
136
- "validation_errors": errors,
137
- "message": "Please fix validation errors and try again",
138
- }
139
-
140
- executor = self._get_executor(runtime)
141
-
142
- # Initialize executor if needed
143
- if not executor.is_initialized:
144
- notebook_context = state.get("notebook_context", {})
145
- kernel_id = notebook_context.get("kernel_id")
146
- notebook_path = notebook_context.get("notebook_path")
147
-
148
- if kernel_id and notebook_path:
149
- await executor.initialize(kernel_id, notebook_path)
150
- else:
151
- logger.warning("Kernel/notebook not available, using mock execution")
152
-
153
- try:
154
- result = await asyncio.wait_for(
155
- executor.execute_code(
156
- code,
157
- timeout=self._timeout,
158
- add_to_notebook=self._add_to_notebook,
159
- ),
160
- timeout=self._timeout + 5,
161
- )
162
-
163
- # Update execution history in state
164
- execution_history = state.get("execution_history", [])
165
- execution_history.append(result.to_dict())
166
- state["execution_history"] = execution_history
167
-
168
- if result.success:
169
- return {
170
- "success": True,
171
- "output": result.output,
172
- "execution_count": result.execution_count,
173
- "cell_index": result.cell_index,
174
- "display_data": result.display_data,
175
- }
176
- else:
177
- # Update error state
178
- state["error_count"] = state.get("error_count", 0) + 1
179
- state["last_error"] = {
180
- "error_type": result.error_type,
181
- "error_message": result.error_message,
182
- "traceback": result.traceback,
183
- }
184
-
185
- return {
186
- "success": False,
187
- "error_type": result.error_type,
188
- "error": result.error_message,
189
- "traceback": result.traceback,
190
- "output": result.output,
191
- }
192
-
193
- except asyncio.TimeoutError:
194
- logger.error(f"Execution timeout after {self._timeout}s")
195
- state["error_count"] = state.get("error_count", 0) + 1
196
- state["last_error"] = {
197
- "error_type": "TimeoutError",
198
- "error_message": f"Execution timed out after {self._timeout} seconds",
199
- }
200
-
201
- return {
202
- "success": False,
203
- "error_type": "TimeoutError",
204
- "error": f"Execution timed out after {self._timeout} seconds",
205
- }
206
- except Exception as e:
207
- logger.error(f"Execution failed: {e}")
208
- state["error_count"] = state.get("error_count", 0) + 1
209
- state["last_error"] = {
210
- "error_type": type(e).__name__,
211
- "error_message": str(e),
212
- }
213
-
214
- return {
215
- "success": False,
216
- "error_type": type(e).__name__,
217
- "error": str(e),
218
- }
219
-
220
- async def _add_markdown_cell(
221
- self,
222
- tool_input: Dict[str, Any],
223
- state: AgentState,
224
- runtime: AgentRuntime,
225
- ) -> Dict[str, Any]:
226
- """Add markdown cell to notebook"""
227
- content = tool_input.get("content", "")
228
- if not content:
229
- return {
230
- "success": False,
231
- "error": "No content provided",
232
- }
233
-
234
- executor = self._get_executor(runtime)
235
-
236
- if not executor.is_initialized:
237
- return {
238
- "success": True,
239
- "message": "[Mock] Markdown cell would be added",
240
- "content": content[:100],
241
- }
242
-
243
- try:
244
- cell_index = await executor.add_markdown_cell(content)
245
-
246
- return {
247
- "success": True,
248
- "cell_index": cell_index,
249
- "message": "Markdown cell added successfully",
250
- }
251
- except Exception as e:
252
- logger.error(f"Failed to add markdown cell: {e}")
253
- return {
254
- "success": False,
255
- "error": str(e),
256
- }
257
-
258
- async def _handle_final_answer(
259
- self,
260
- tool_input: Dict[str, Any],
261
- state: AgentState,
262
- runtime: AgentRuntime,
263
- ) -> Dict[str, Any]:
264
- """Handle final answer tool"""
265
- answer = tool_input.get("answer", "")
266
- summary = tool_input.get("summary", "")
267
-
268
- # Update state
269
- state["final_answer"] = answer
270
- state["is_complete"] = True
271
-
272
- return {
273
- "success": True,
274
- "answer": answer,
275
- "summary": summary,
276
- "message": "Task completed",
277
- "is_complete": True,
278
- }
279
-
280
-
281
- def create_jupyter_execution_middleware(
282
- timeout: float = 60.0,
283
- add_to_notebook: bool = True,
284
- enabled: bool = True,
285
- ) -> JupyterExecutionMiddleware:
286
- """
287
- Factory function to create Jupyter execution middleware.
288
-
289
- Args:
290
- timeout: Execution timeout in seconds
291
- add_to_notebook: Add cells to notebook
292
- enabled: Whether to enable execution
293
-
294
- Returns:
295
- Configured JupyterExecutionMiddleware instance
296
- """
297
- return JupyterExecutionMiddleware(
298
- timeout=timeout,
299
- add_to_notebook=add_to_notebook,
300
- enabled=enabled,
301
- )
@@ -1,227 +0,0 @@
1
- """
2
- RAG Middleware
3
-
4
- Injects relevant context from the RAG system before model calls.
5
- Uses the existing RAG manager to retrieve relevant documentation
6
- and code examples based on the user's request.
7
- """
8
-
9
- import logging
10
- from typing import Any, Dict, List, Optional
11
-
12
- from agent_server.langchain.state import AgentRuntime, AgentState
13
-
14
- logger = logging.getLogger(__name__)
15
-
16
-
17
- class RAGMiddleware:
18
- """
19
- Middleware that injects RAG context before model calls.
20
-
21
- This middleware:
22
- 1. Detects required libraries from the user request
23
- 2. Queries the RAG system for relevant documentation
24
- 3. Injects the context into the agent state
25
-
26
- Uses @before_model hook pattern from LangChain middleware.
27
- """
28
-
29
- def __init__(
30
- self,
31
- rag_manager: Any = None,
32
- library_detector: Any = None,
33
- max_context_length: int = 4000,
34
- enabled: bool = True,
35
- ):
36
- """
37
- Initialize RAG middleware.
38
-
39
- Args:
40
- rag_manager: RAGManager instance for context retrieval
41
- library_detector: LibraryDetector for detecting required libraries
42
- max_context_length: Maximum context length to inject
43
- enabled: Whether RAG injection is enabled
44
- """
45
- self._rag_manager = rag_manager
46
- self._library_detector = library_detector
47
- self._max_context_length = max_context_length
48
- self._enabled = enabled
49
-
50
- @property
51
- def name(self) -> str:
52
- return "RAGMiddleware"
53
-
54
- def _get_rag_manager(self):
55
- """Lazy load RAG manager if not provided"""
56
- if self._rag_manager is None:
57
- try:
58
- from agent_server.core.rag_manager import get_rag_manager
59
- self._rag_manager = get_rag_manager()
60
- except ImportError:
61
- logger.warning("RAG manager not available")
62
- return None
63
- return self._rag_manager
64
-
65
- def _get_library_detector(self):
66
- """Lazy load library detector if not provided"""
67
- if self._library_detector is None:
68
- try:
69
- from hdsp_agent_core.knowledge.loader import get_library_detector
70
- self._library_detector = get_library_detector()
71
- except ImportError:
72
- logger.warning("Library detector not available")
73
- return None
74
- return self._library_detector
75
-
76
- def _detect_libraries(
77
- self,
78
- request: str,
79
- imported_libraries: List[str],
80
- ) -> List[str]:
81
- """Detect required libraries from the request"""
82
- detector = self._get_library_detector()
83
- if detector is None:
84
- return []
85
-
86
- try:
87
- from hdsp_agent_core.knowledge.loader import get_knowledge_base
88
- knowledge_base = get_knowledge_base()
89
- available = knowledge_base.list_available_libraries()
90
-
91
- if not available:
92
- return []
93
-
94
- detected = detector.detect(
95
- request=request,
96
- available_libraries=available,
97
- imported_libraries=imported_libraries,
98
- )
99
-
100
- return detected
101
- except Exception as e:
102
- logger.warning(f"Library detection failed: {e}")
103
- return []
104
-
105
- async def _get_rag_context(
106
- self,
107
- query: str,
108
- detected_libraries: List[str],
109
- ) -> Optional[str]:
110
- """Get RAG context for the query"""
111
- rag_manager = self._get_rag_manager()
112
- if rag_manager is None or not rag_manager.is_ready:
113
- return None
114
-
115
- try:
116
- context = await rag_manager.get_context_for_query(
117
- query=query,
118
- detected_libraries=detected_libraries,
119
- )
120
-
121
- if context and len(context) > self._max_context_length:
122
- context = context[:self._max_context_length] + "\n... (truncated)"
123
-
124
- return context
125
- except Exception as e:
126
- logger.warning(f"RAG context retrieval failed: {e}")
127
- return None
128
-
129
- async def before_model(
130
- self,
131
- state: AgentState,
132
- runtime: AgentRuntime,
133
- ) -> Optional[Dict[str, Any]]:
134
- """
135
- Hook called before each model invocation.
136
-
137
- Injects RAG context into the state if available.
138
-
139
- Args:
140
- state: Current agent state
141
- runtime: Agent runtime context
142
-
143
- Returns:
144
- Updated state fields or None
145
- """
146
- if not self._enabled:
147
- return None
148
-
149
- # Skip if context already injected
150
- if state.get("rag_context"):
151
- return None
152
-
153
- user_request = state.get("user_request", "")
154
- if not user_request:
155
- return None
156
-
157
- # Detect libraries
158
- notebook_context = state.get("notebook_context", {})
159
- imported_libs = notebook_context.get("imported_libraries", [])
160
-
161
- detected_libraries = self._detect_libraries(user_request, imported_libs)
162
-
163
- if detected_libraries:
164
- logger.info(f"Detected libraries: {detected_libraries}")
165
-
166
- # Get RAG context
167
- rag_context = await self._get_rag_context(user_request, detected_libraries)
168
-
169
- if rag_context:
170
- logger.info(f"RAG context injected: {len(rag_context)} chars")
171
- return {
172
- "rag_context": rag_context,
173
- "detected_libraries": detected_libraries,
174
- }
175
-
176
- return {"detected_libraries": detected_libraries}
177
-
178
- def format_context_for_prompt(
179
- self,
180
- rag_context: Optional[str],
181
- detected_libraries: List[str],
182
- ) -> str:
183
- """
184
- Format RAG context for inclusion in the prompt.
185
-
186
- Args:
187
- rag_context: Retrieved RAG context
188
- detected_libraries: List of detected libraries
189
-
190
- Returns:
191
- Formatted context string
192
- """
193
- if not rag_context:
194
- return ""
195
-
196
- parts = []
197
-
198
- if detected_libraries:
199
- parts.append(f"## Detected Libraries: {', '.join(detected_libraries)}")
200
-
201
- parts.append("## Relevant Documentation")
202
- parts.append(rag_context)
203
-
204
- return "\n\n".join(parts)
205
-
206
-
207
- def create_rag_middleware(
208
- rag_manager: Any = None,
209
- max_context_length: int = 4000,
210
- enabled: bool = True,
211
- ) -> RAGMiddleware:
212
- """
213
- Factory function to create RAG middleware.
214
-
215
- Args:
216
- rag_manager: Optional RAGManager instance
217
- max_context_length: Maximum context length
218
- enabled: Whether to enable RAG
219
-
220
- Returns:
221
- Configured RAGMiddleware instance
222
- """
223
- return RAGMiddleware(
224
- rag_manager=rag_manager,
225
- max_context_length=max_context_length,
226
- enabled=enabled,
227
- )