hdsp-jupyter-extension 2.0.6__py3-none-any.whl → 2.0.8__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 (88) hide show
  1. agent_server/core/embedding_service.py +67 -46
  2. agent_server/core/rag_manager.py +31 -17
  3. agent_server/core/reflection_engine.py +0 -1
  4. agent_server/core/retriever.py +13 -8
  5. agent_server/core/vllm_embedding_service.py +243 -0
  6. agent_server/knowledge/watchdog_service.py +1 -1
  7. agent_server/langchain/ARCHITECTURE.md +1193 -0
  8. agent_server/langchain/agent.py +82 -588
  9. agent_server/langchain/custom_middleware.py +663 -0
  10. agent_server/langchain/executors/__init__.py +2 -7
  11. agent_server/langchain/executors/notebook_searcher.py +46 -38
  12. agent_server/langchain/hitl_config.py +71 -0
  13. agent_server/langchain/llm_factory.py +166 -0
  14. agent_server/langchain/logging_utils.py +223 -0
  15. agent_server/langchain/prompts.py +150 -0
  16. agent_server/langchain/state.py +16 -6
  17. agent_server/langchain/tools/__init__.py +19 -0
  18. agent_server/langchain/tools/file_tools.py +354 -114
  19. agent_server/langchain/tools/file_utils.py +334 -0
  20. agent_server/langchain/tools/jupyter_tools.py +18 -18
  21. agent_server/langchain/tools/lsp_tools.py +264 -0
  22. agent_server/langchain/tools/resource_tools.py +161 -0
  23. agent_server/langchain/tools/search_tools.py +198 -216
  24. agent_server/langchain/tools/shell_tools.py +54 -0
  25. agent_server/main.py +11 -1
  26. agent_server/routers/health.py +1 -1
  27. agent_server/routers/langchain_agent.py +1040 -289
  28. agent_server/routers/rag.py +8 -3
  29. hdsp_agent_core/models/rag.py +15 -1
  30. hdsp_agent_core/prompts/auto_agent_prompts.py +3 -3
  31. hdsp_agent_core/services/rag_service.py +6 -1
  32. {hdsp_jupyter_extension-2.0.6.data → hdsp_jupyter_extension-2.0.8.data}/data/share/jupyter/labextensions/hdsp-agent/build_log.json +1 -1
  33. {hdsp_jupyter_extension-2.0.6.data → hdsp_jupyter_extension-2.0.8.data}/data/share/jupyter/labextensions/hdsp-agent/package.json +3 -2
  34. 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.8.data/data/share/jupyter/labextensions/hdsp-agent/static/frontend_styles_index_js.8740a527757068814573.js +470 -7
  35. hdsp_jupyter_extension-2.0.8.data/data/share/jupyter/labextensions/hdsp-agent/static/frontend_styles_index_js.8740a527757068814573.js.map +1 -0
  36. hdsp_jupyter_extension-2.0.6.data/data/share/jupyter/labextensions/hdsp-agent/static/lib_index_js.a223ea20056954479ae9.js → hdsp_jupyter_extension-2.0.8.data/data/share/jupyter/labextensions/hdsp-agent/static/lib_index_js.e4ff4b5779b5e049f84c.js +3196 -441
  37. hdsp_jupyter_extension-2.0.8.data/data/share/jupyter/labextensions/hdsp-agent/static/lib_index_js.e4ff4b5779b5e049f84c.js.map +1 -0
  38. hdsp_jupyter_extension-2.0.6.data/data/share/jupyter/labextensions/hdsp-agent/static/remoteEntry.addf2fa038fa60304aa2.js → hdsp_jupyter_extension-2.0.8.data/data/share/jupyter/labextensions/hdsp-agent/static/remoteEntry.020cdb0b864cfaa4e41e.js +9 -7
  39. hdsp_jupyter_extension-2.0.8.data/data/share/jupyter/labextensions/hdsp-agent/static/remoteEntry.020cdb0b864cfaa4e41e.js.map +1 -0
  40. {hdsp_jupyter_extension-2.0.6.dist-info → hdsp_jupyter_extension-2.0.8.dist-info}/METADATA +2 -1
  41. {hdsp_jupyter_extension-2.0.6.dist-info → hdsp_jupyter_extension-2.0.8.dist-info}/RECORD +75 -69
  42. jupyter_ext/__init__.py +18 -0
  43. jupyter_ext/_version.py +1 -1
  44. jupyter_ext/handlers.py +1351 -58
  45. jupyter_ext/labextension/build_log.json +1 -1
  46. jupyter_ext/labextension/package.json +3 -2
  47. jupyter_ext/labextension/static/{frontend_styles_index_js.02d346171474a0fb2dc1.js → frontend_styles_index_js.8740a527757068814573.js} +470 -7
  48. jupyter_ext/labextension/static/frontend_styles_index_js.8740a527757068814573.js.map +1 -0
  49. jupyter_ext/labextension/static/{lib_index_js.a223ea20056954479ae9.js → lib_index_js.e4ff4b5779b5e049f84c.js} +3196 -441
  50. jupyter_ext/labextension/static/lib_index_js.e4ff4b5779b5e049f84c.js.map +1 -0
  51. jupyter_ext/labextension/static/{remoteEntry.addf2fa038fa60304aa2.js → remoteEntry.020cdb0b864cfaa4e41e.js} +9 -7
  52. jupyter_ext/labextension/static/remoteEntry.020cdb0b864cfaa4e41e.js.map +1 -0
  53. jupyter_ext/resource_usage.py +180 -0
  54. jupyter_ext/tests/test_handlers.py +58 -0
  55. agent_server/langchain/executors/jupyter_executor.py +0 -429
  56. agent_server/langchain/middleware/__init__.py +0 -36
  57. agent_server/langchain/middleware/code_search_middleware.py +0 -278
  58. agent_server/langchain/middleware/error_handling_middleware.py +0 -338
  59. agent_server/langchain/middleware/jupyter_execution_middleware.py +0 -301
  60. agent_server/langchain/middleware/rag_middleware.py +0 -227
  61. agent_server/langchain/middleware/validation_middleware.py +0 -240
  62. hdsp_jupyter_extension-2.0.6.data/data/share/jupyter/labextensions/hdsp-agent/static/frontend_styles_index_js.02d346171474a0fb2dc1.js.map +0 -1
  63. hdsp_jupyter_extension-2.0.6.data/data/share/jupyter/labextensions/hdsp-agent/static/lib_index_js.a223ea20056954479ae9.js.map +0 -1
  64. hdsp_jupyter_extension-2.0.6.data/data/share/jupyter/labextensions/hdsp-agent/static/remoteEntry.addf2fa038fa60304aa2.js.map +0 -1
  65. jupyter_ext/labextension/static/frontend_styles_index_js.02d346171474a0fb2dc1.js.map +0 -1
  66. jupyter_ext/labextension/static/lib_index_js.a223ea20056954479ae9.js.map +0 -1
  67. jupyter_ext/labextension/static/remoteEntry.addf2fa038fa60304aa2.js.map +0 -1
  68. {hdsp_jupyter_extension-2.0.6.data → hdsp_jupyter_extension-2.0.8.data}/data/etc/jupyter/jupyter_server_config.d/hdsp_jupyter_extension.json +0 -0
  69. {hdsp_jupyter_extension-2.0.6.data → hdsp_jupyter_extension-2.0.8.data}/data/share/jupyter/labextensions/hdsp-agent/install.json +0 -0
  70. {hdsp_jupyter_extension-2.0.6.data → hdsp_jupyter_extension-2.0.8.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
  71. {hdsp_jupyter_extension-2.0.6.data → hdsp_jupyter_extension-2.0.8.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
  72. {hdsp_jupyter_extension-2.0.6.data → hdsp_jupyter_extension-2.0.8.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
  73. {hdsp_jupyter_extension-2.0.6.data → hdsp_jupyter_extension-2.0.8.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
  74. {hdsp_jupyter_extension-2.0.6.data → hdsp_jupyter_extension-2.0.8.data}/data/share/jupyter/labextensions/hdsp-agent/static/style.js +0 -0
  75. {hdsp_jupyter_extension-2.0.6.data → hdsp_jupyter_extension-2.0.8.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
  76. {hdsp_jupyter_extension-2.0.6.data → hdsp_jupyter_extension-2.0.8.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
  77. {hdsp_jupyter_extension-2.0.6.data → hdsp_jupyter_extension-2.0.8.data}/data/share/jupyter/labextensions/hdsp-agent/static/vendors-node_modules_emotion_cache_dist_emotion-cache_browser_development_esm_js.24edcc52a1c014a8a5f0.js +0 -0
  78. {hdsp_jupyter_extension-2.0.6.data → hdsp_jupyter_extension-2.0.8.data}/data/share/jupyter/labextensions/hdsp-agent/static/vendors-node_modules_emotion_cache_dist_emotion-cache_browser_development_esm_js.24edcc52a1c014a8a5f0.js.map +0 -0
  79. {hdsp_jupyter_extension-2.0.6.data → hdsp_jupyter_extension-2.0.8.data}/data/share/jupyter/labextensions/hdsp-agent/static/vendors-node_modules_emotion_react_dist_emotion-react_browser_development_esm_js.19ecf6babe00caff6b8a.js +0 -0
  80. {hdsp_jupyter_extension-2.0.6.data → hdsp_jupyter_extension-2.0.8.data}/data/share/jupyter/labextensions/hdsp-agent/static/vendors-node_modules_emotion_react_dist_emotion-react_browser_development_esm_js.19ecf6babe00caff6b8a.js.map +0 -0
  81. {hdsp_jupyter_extension-2.0.6.data → hdsp_jupyter_extension-2.0.8.data}/data/share/jupyter/labextensions/hdsp-agent/static/vendors-node_modules_emotion_styled_dist_emotion-styled_browser_development_esm_js.661fb5836f4978a7c6e1.js +0 -0
  82. {hdsp_jupyter_extension-2.0.6.data → hdsp_jupyter_extension-2.0.8.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
  83. {hdsp_jupyter_extension-2.0.6.data → hdsp_jupyter_extension-2.0.8.data}/data/share/jupyter/labextensions/hdsp-agent/static/vendors-node_modules_mui_material_index_js.985697e0162d8d088ca2.js +0 -0
  84. {hdsp_jupyter_extension-2.0.6.data → hdsp_jupyter_extension-2.0.8.data}/data/share/jupyter/labextensions/hdsp-agent/static/vendors-node_modules_mui_material_index_js.985697e0162d8d088ca2.js.map +0 -0
  85. {hdsp_jupyter_extension-2.0.6.data → hdsp_jupyter_extension-2.0.8.data}/data/share/jupyter/labextensions/hdsp-agent/static/vendors-node_modules_mui_material_utils_createSvgIcon_js.1f5038488cdfd8b3a85d.js +0 -0
  86. {hdsp_jupyter_extension-2.0.6.data → hdsp_jupyter_extension-2.0.8.data}/data/share/jupyter/labextensions/hdsp-agent/static/vendors-node_modules_mui_material_utils_createSvgIcon_js.1f5038488cdfd8b3a85d.js.map +0 -0
  87. {hdsp_jupyter_extension-2.0.6.dist-info → hdsp_jupyter_extension-2.0.8.dist-info}/WHEEL +0 -0
  88. {hdsp_jupyter_extension-2.0.6.dist-info → hdsp_jupyter_extension-2.0.8.dist-info}/licenses/LICENSE +0 -0
@@ -1,429 +0,0 @@
1
- """
2
- Jupyter Executor (Embedded Mode)
3
-
4
- Provides direct access to Jupyter kernel for code execution
5
- when running inside JupyterLab server.
6
-
7
- This executor uses the Jupyter server's kernel manager to:
8
- - Execute code in the current notebook's kernel
9
- - Add cells to the notebook
10
- - Retrieve execution results
11
- """
12
-
13
- import asyncio
14
- import logging
15
- from dataclasses import dataclass, field
16
- from typing import Any, Dict, List, Optional
17
-
18
- logger = logging.getLogger(__name__)
19
-
20
-
21
- @dataclass
22
- class ExecutionResult:
23
- """Result of code execution in Jupyter kernel"""
24
- success: bool
25
- output: str = ""
26
- error_type: Optional[str] = None
27
- error_message: Optional[str] = None
28
- traceback: Optional[List[str]] = None
29
- execution_count: int = 0
30
- cell_index: int = -1
31
- display_data: List[Dict[str, Any]] = field(default_factory=list)
32
-
33
- def to_dict(self) -> Dict[str, Any]:
34
- return {
35
- "success": self.success,
36
- "output": self.output,
37
- "error_type": self.error_type,
38
- "error_message": self.error_message,
39
- "traceback": self.traceback,
40
- "execution_count": self.execution_count,
41
- "cell_index": self.cell_index,
42
- "display_data": self.display_data,
43
- }
44
-
45
-
46
- class JupyterExecutor:
47
- """
48
- Executes code in Jupyter kernel (Embedded Mode).
49
-
50
- In Embedded Mode, this class directly accesses the Jupyter server's
51
- kernel manager and contents manager to execute code and modify notebooks.
52
-
53
- Usage:
54
- executor = JupyterExecutor()
55
- await executor.initialize(kernel_id, notebook_path)
56
- result = await executor.execute_code("print('hello')")
57
- """
58
-
59
- def __init__(self):
60
- self._kernel_manager = None
61
- self._contents_manager = None
62
- self._kernel_id: Optional[str] = None
63
- self._notebook_path: Optional[str] = None
64
- self._kernel_client = None
65
- self._initialized = False
66
-
67
- @property
68
- def is_initialized(self) -> bool:
69
- return self._initialized
70
-
71
- async def initialize(
72
- self,
73
- kernel_id: str,
74
- notebook_path: str,
75
- kernel_manager: Any = None,
76
- contents_manager: Any = None,
77
- ) -> bool:
78
- """
79
- Initialize the executor with kernel and notebook information.
80
-
81
- Args:
82
- kernel_id: ID of the kernel to use
83
- notebook_path: Path to the notebook file
84
- kernel_manager: Jupyter's MappingKernelManager (optional, auto-detect)
85
- contents_manager: Jupyter's ContentsManager (optional, auto-detect)
86
-
87
- Returns:
88
- True if initialization successful
89
- """
90
- self._kernel_id = kernel_id
91
- self._notebook_path = notebook_path
92
-
93
- # Try to get kernel manager from Jupyter server if not provided
94
- if kernel_manager is None:
95
- kernel_manager = self._get_kernel_manager()
96
-
97
- if contents_manager is None:
98
- contents_manager = self._get_contents_manager()
99
-
100
- self._kernel_manager = kernel_manager
101
- self._contents_manager = contents_manager
102
-
103
- if self._kernel_manager is None:
104
- logger.warning("Kernel manager not available. Running in mock mode.")
105
- self._initialized = True
106
- return True
107
-
108
- # Get kernel client
109
- try:
110
- self._kernel_client = self._kernel_manager.get_kernel(kernel_id)
111
- self._initialized = True
112
- logger.info(f"JupyterExecutor initialized with kernel {kernel_id}")
113
- return True
114
- except Exception as e:
115
- logger.error(f"Failed to get kernel client: {e}")
116
- self._initialized = False
117
- return False
118
-
119
- def _get_kernel_manager(self) -> Optional[Any]:
120
- """Try to get kernel manager from Jupyter server app"""
121
- try:
122
- from jupyter_server.serverapp import ServerApp
123
- app = ServerApp.instance()
124
- return app.kernel_manager
125
- except Exception:
126
- try:
127
- # Fallback for older versions
128
- from notebook.notebookapp import NotebookApp
129
- app = NotebookApp.instance()
130
- return app.kernel_manager
131
- except Exception:
132
- return None
133
-
134
- def _get_contents_manager(self) -> Optional[Any]:
135
- """Try to get contents manager from Jupyter server app"""
136
- try:
137
- from jupyter_server.serverapp import ServerApp
138
- app = ServerApp.instance()
139
- return app.contents_manager
140
- except Exception:
141
- try:
142
- from notebook.notebookapp import NotebookApp
143
- app = NotebookApp.instance()
144
- return app.contents_manager
145
- except Exception:
146
- return None
147
-
148
- async def execute_code(
149
- self,
150
- code: str,
151
- timeout: float = 60.0,
152
- add_to_notebook: bool = True,
153
- ) -> ExecutionResult:
154
- """
155
- Execute Python code in the Jupyter kernel.
156
-
157
- Args:
158
- code: Python code to execute
159
- timeout: Execution timeout in seconds
160
- add_to_notebook: Whether to add the code as a new cell
161
-
162
- Returns:
163
- ExecutionResult with output or error
164
- """
165
- if not self._initialized:
166
- return ExecutionResult(
167
- success=False,
168
- error_type="NotInitialized",
169
- error_message="Executor not initialized. Call initialize() first."
170
- )
171
-
172
- # If no kernel manager, use mock execution
173
- if self._kernel_manager is None:
174
- return await self._mock_execute(code)
175
-
176
- try:
177
- # Add cell to notebook if requested
178
- cell_index = -1
179
- if add_to_notebook and self._contents_manager:
180
- cell_index = await self._add_cell_to_notebook(code)
181
-
182
- # Execute code in kernel
183
- result = await self._execute_in_kernel(code, timeout)
184
- result.cell_index = cell_index
185
-
186
- return result
187
-
188
- except asyncio.TimeoutError:
189
- return ExecutionResult(
190
- success=False,
191
- error_type="TimeoutError",
192
- error_message=f"Execution timed out after {timeout} seconds"
193
- )
194
- except Exception as e:
195
- logger.error(f"Execution failed: {e}")
196
- return ExecutionResult(
197
- success=False,
198
- error_type=type(e).__name__,
199
- error_message=str(e)
200
- )
201
-
202
- async def _execute_in_kernel(
203
- self,
204
- code: str,
205
- timeout: float
206
- ) -> ExecutionResult:
207
- """Execute code using kernel client"""
208
- # This is a simplified implementation
209
- # In production, you would use jupyter_client's async API
210
-
211
- try:
212
- from jupyter_client import KernelClient
213
-
214
- # Get connection info from kernel manager
215
- km = self._kernel_manager
216
- kernel = km.get_kernel(self._kernel_id)
217
-
218
- # Create a client and execute
219
- client = kernel.client()
220
- client.start_channels()
221
-
222
- try:
223
- # Send execute request
224
- msg_id = client.execute(code)
225
-
226
- # Wait for results
227
- output_parts = []
228
- error_info = None
229
- execution_count = 0
230
- display_data = []
231
-
232
- deadline = asyncio.get_event_loop().time() + timeout
233
-
234
- while True:
235
- remaining = deadline - asyncio.get_event_loop().time()
236
- if remaining <= 0:
237
- raise asyncio.TimeoutError()
238
-
239
- try:
240
- msg = client.get_iopub_msg(timeout=min(remaining, 1.0))
241
- except Exception:
242
- continue
243
-
244
- if msg["parent_header"].get("msg_id") != msg_id:
245
- continue
246
-
247
- msg_type = msg["msg_type"]
248
- content = msg["content"]
249
-
250
- if msg_type == "stream":
251
- output_parts.append(content.get("text", ""))
252
- elif msg_type == "execute_result":
253
- output_parts.append(str(content.get("data", {}).get("text/plain", "")))
254
- execution_count = content.get("execution_count", 0)
255
- elif msg_type == "display_data":
256
- display_data.append(content.get("data", {}))
257
- elif msg_type == "error":
258
- error_info = {
259
- "ename": content.get("ename", "Error"),
260
- "evalue": content.get("evalue", ""),
261
- "traceback": content.get("traceback", []),
262
- }
263
- elif msg_type == "status" and content.get("execution_state") == "idle":
264
- break
265
-
266
- if error_info:
267
- return ExecutionResult(
268
- success=False,
269
- output="".join(output_parts),
270
- error_type=error_info["ename"],
271
- error_message=error_info["evalue"],
272
- traceback=error_info["traceback"],
273
- execution_count=execution_count,
274
- display_data=display_data,
275
- )
276
-
277
- return ExecutionResult(
278
- success=True,
279
- output="".join(output_parts),
280
- execution_count=execution_count,
281
- display_data=display_data,
282
- )
283
-
284
- finally:
285
- client.stop_channels()
286
-
287
- except ImportError:
288
- logger.warning("jupyter_client not available, using mock execution")
289
- return await self._mock_execute(code)
290
- except Exception as e:
291
- return ExecutionResult(
292
- success=False,
293
- error_type=type(e).__name__,
294
- error_message=str(e),
295
- )
296
-
297
- async def _add_cell_to_notebook(self, code: str) -> int:
298
- """Add a new code cell to the notebook"""
299
- if not self._contents_manager or not self._notebook_path:
300
- return -1
301
-
302
- try:
303
- # Read current notebook
304
- model = self._contents_manager.get(self._notebook_path, content=True)
305
- notebook = model["content"]
306
-
307
- # Create new cell
308
- new_cell = {
309
- "cell_type": "code",
310
- "execution_count": None,
311
- "metadata": {},
312
- "outputs": [],
313
- "source": code,
314
- }
315
-
316
- # Add cell
317
- notebook["cells"].append(new_cell)
318
- cell_index = len(notebook["cells"]) - 1
319
-
320
- # Save notebook
321
- self._contents_manager.save(model, self._notebook_path)
322
-
323
- return cell_index
324
-
325
- except Exception as e:
326
- logger.error(f"Failed to add cell to notebook: {e}")
327
- return -1
328
-
329
- async def add_markdown_cell(self, content: str) -> int:
330
- """Add a markdown cell to the notebook"""
331
- if not self._contents_manager or not self._notebook_path:
332
- return -1
333
-
334
- try:
335
- model = self._contents_manager.get(self._notebook_path, content=True)
336
- notebook = model["content"]
337
-
338
- new_cell = {
339
- "cell_type": "markdown",
340
- "metadata": {},
341
- "source": content,
342
- }
343
-
344
- notebook["cells"].append(new_cell)
345
- cell_index = len(notebook["cells"]) - 1
346
-
347
- self._contents_manager.save(model, self._notebook_path)
348
-
349
- return cell_index
350
-
351
- except Exception as e:
352
- logger.error(f"Failed to add markdown cell: {e}")
353
- return -1
354
-
355
- async def _mock_execute(self, code: str) -> ExecutionResult:
356
- """Mock execution for testing or when kernel is not available"""
357
- logger.info(f"Mock executing code: {code[:100]}...")
358
-
359
- # Simple mock that just returns success
360
- return ExecutionResult(
361
- success=True,
362
- output=f"[Mock] Code executed successfully:\n{code[:200]}",
363
- execution_count=1,
364
- )
365
-
366
- async def get_notebook_state(self) -> Dict[str, Any]:
367
- """Get current notebook state"""
368
- if not self._contents_manager or not self._notebook_path:
369
- return {
370
- "cell_count": 0,
371
- "imported_libraries": [],
372
- "defined_variables": [],
373
- }
374
-
375
- try:
376
- model = self._contents_manager.get(self._notebook_path, content=True)
377
- notebook = model["content"]
378
- cells = notebook.get("cells", [])
379
-
380
- # Extract imports and variables from code cells
381
- imported_libraries = set()
382
- defined_variables = set()
383
-
384
- import re
385
- import_pattern = re.compile(r'^(?:import|from)\s+([\w.]+)', re.MULTILINE)
386
- var_pattern = re.compile(r'^(\w+)\s*=', re.MULTILINE)
387
-
388
- for cell in cells:
389
- if cell.get("cell_type") != "code":
390
- continue
391
-
392
- source = cell.get("source", "")
393
- if isinstance(source, list):
394
- source = "".join(source)
395
-
396
- # Find imports
397
- for match in import_pattern.finditer(source):
398
- lib = match.group(1).split(".")[0]
399
- imported_libraries.add(lib)
400
-
401
- # Find variable definitions
402
- for match in var_pattern.finditer(source):
403
- defined_variables.add(match.group(1))
404
-
405
- return {
406
- "cell_count": len(cells),
407
- "imported_libraries": list(imported_libraries),
408
- "defined_variables": list(defined_variables),
409
- }
410
-
411
- except Exception as e:
412
- logger.error(f"Failed to get notebook state: {e}")
413
- return {
414
- "cell_count": 0,
415
- "imported_libraries": [],
416
- "defined_variables": [],
417
- }
418
-
419
-
420
- # Singleton instance
421
- _executor_instance: Optional[JupyterExecutor] = None
422
-
423
-
424
- def get_jupyter_executor() -> JupyterExecutor:
425
- """Get or create the JupyterExecutor singleton"""
426
- global _executor_instance
427
- if _executor_instance is None:
428
- _executor_instance = JupyterExecutor()
429
- return _executor_instance
@@ -1,36 +0,0 @@
1
- """
2
- LangChain Middleware for Jupyter Agent
3
-
4
- Middleware stack (execution order):
5
- 1. RAGMiddleware: Inject RAG context before model calls
6
- 2. CodeSearchMiddleware: Search workspace/notebook for relevant code
7
- 3. ValidationMiddleware: Validate code before execution
8
- 4. JupyterExecutionMiddleware: Execute code in Jupyter kernel
9
- 5. ErrorHandlingMiddleware: Classify errors and decide recovery strategy
10
-
11
- Built-in middleware used:
12
- - SummarizationMiddleware: Compress long conversations
13
- - ModelRetryMiddleware: Retry on rate limits
14
- - ToolRetryMiddleware: Retry failed tool calls
15
- - ModelCallLimitMiddleware: Prevent infinite loops
16
- """
17
-
18
- from agent_server.langchain.middleware.code_search_middleware import (
19
- CodeSearchMiddleware,
20
- )
21
- from agent_server.langchain.middleware.error_handling_middleware import (
22
- ErrorHandlingMiddleware,
23
- )
24
- from agent_server.langchain.middleware.jupyter_execution_middleware import (
25
- JupyterExecutionMiddleware,
26
- )
27
- from agent_server.langchain.middleware.rag_middleware import RAGMiddleware
28
- from agent_server.langchain.middleware.validation_middleware import ValidationMiddleware
29
-
30
- __all__ = [
31
- "RAGMiddleware",
32
- "CodeSearchMiddleware",
33
- "ValidationMiddleware",
34
- "JupyterExecutionMiddleware",
35
- "ErrorHandlingMiddleware",
36
- ]