hdsp-jupyter-extension 2.0.26__py3-none-any.whl → 2.0.28__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 (71) hide show
  1. agent_server/context_providers/__init__.py +4 -2
  2. agent_server/context_providers/actions.py +73 -7
  3. agent_server/context_providers/file.py +23 -23
  4. agent_server/langchain/__init__.py +2 -2
  5. agent_server/langchain/agent.py +18 -251
  6. agent_server/langchain/agent_factory.py +26 -4
  7. agent_server/langchain/agent_prompts/planner_prompt.py +22 -35
  8. agent_server/langchain/custom_middleware.py +278 -43
  9. agent_server/langchain/llm_factory.py +102 -54
  10. agent_server/langchain/logging_utils.py +1 -1
  11. agent_server/langchain/middleware/__init__.py +5 -0
  12. agent_server/langchain/middleware/code_history_middleware.py +126 -37
  13. agent_server/langchain/middleware/content_injection_middleware.py +110 -0
  14. agent_server/langchain/middleware/subagent_events.py +88 -9
  15. agent_server/langchain/middleware/subagent_middleware.py +518 -240
  16. agent_server/langchain/prompts.py +5 -22
  17. agent_server/langchain/state_schema.py +44 -0
  18. agent_server/langchain/tools/jupyter_tools.py +4 -5
  19. agent_server/langchain/tools/tool_registry.py +6 -0
  20. agent_server/routers/chat.py +305 -2
  21. agent_server/routers/config.py +193 -8
  22. agent_server/routers/config_schema.py +254 -0
  23. agent_server/routers/context.py +31 -8
  24. agent_server/routers/langchain_agent.py +310 -153
  25. hdsp_agent_core/managers/config_manager.py +100 -1
  26. {hdsp_jupyter_extension-2.0.26.data → hdsp_jupyter_extension-2.0.28.data}/data/share/jupyter/labextensions/hdsp-agent/build_log.json +1 -1
  27. {hdsp_jupyter_extension-2.0.26.data → hdsp_jupyter_extension-2.0.28.data}/data/share/jupyter/labextensions/hdsp-agent/package.json +2 -2
  28. hdsp_jupyter_extension-2.0.26.data/data/share/jupyter/labextensions/hdsp-agent/static/frontend_styles_index_js.b5e4416b4e07ec087aad.js → hdsp_jupyter_extension-2.0.28.data/data/share/jupyter/labextensions/hdsp-agent/static/frontend_styles_index_js.55727265b00191e68d9a.js +479 -15
  29. hdsp_jupyter_extension-2.0.28.data/data/share/jupyter/labextensions/hdsp-agent/static/frontend_styles_index_js.55727265b00191e68d9a.js.map +1 -0
  30. jupyter_ext/labextension/static/lib_index_js.67505497667f9c0a763d.js → hdsp_jupyter_extension-2.0.28.data/data/share/jupyter/labextensions/hdsp-agent/static/lib_index_js.df05d90f366bfd5fa023.js +1287 -190
  31. hdsp_jupyter_extension-2.0.28.data/data/share/jupyter/labextensions/hdsp-agent/static/lib_index_js.df05d90f366bfd5fa023.js.map +1 -0
  32. hdsp_jupyter_extension-2.0.26.data/data/share/jupyter/labextensions/hdsp-agent/static/remoteEntry.0fe2dcbbd176ee0efceb.js → hdsp_jupyter_extension-2.0.28.data/data/share/jupyter/labextensions/hdsp-agent/static/remoteEntry.08fce819ee32e9d25175.js +3 -3
  33. jupyter_ext/labextension/static/remoteEntry.0fe2dcbbd176ee0efceb.js.map → hdsp_jupyter_extension-2.0.28.data/data/share/jupyter/labextensions/hdsp-agent/static/remoteEntry.08fce819ee32e9d25175.js.map +1 -1
  34. {hdsp_jupyter_extension-2.0.26.dist-info → hdsp_jupyter_extension-2.0.28.dist-info}/METADATA +1 -1
  35. {hdsp_jupyter_extension-2.0.26.dist-info → hdsp_jupyter_extension-2.0.28.dist-info}/RECORD +66 -64
  36. jupyter_ext/_version.py +1 -1
  37. jupyter_ext/handlers.py +41 -0
  38. jupyter_ext/labextension/build_log.json +1 -1
  39. jupyter_ext/labextension/package.json +2 -2
  40. jupyter_ext/labextension/static/{frontend_styles_index_js.b5e4416b4e07ec087aad.js → frontend_styles_index_js.55727265b00191e68d9a.js} +479 -15
  41. jupyter_ext/labextension/static/frontend_styles_index_js.55727265b00191e68d9a.js.map +1 -0
  42. hdsp_jupyter_extension-2.0.26.data/data/share/jupyter/labextensions/hdsp-agent/static/lib_index_js.67505497667f9c0a763d.js → jupyter_ext/labextension/static/lib_index_js.df05d90f366bfd5fa023.js +1287 -190
  43. jupyter_ext/labextension/static/lib_index_js.df05d90f366bfd5fa023.js.map +1 -0
  44. jupyter_ext/labextension/static/{remoteEntry.0fe2dcbbd176ee0efceb.js → remoteEntry.08fce819ee32e9d25175.js} +3 -3
  45. hdsp_jupyter_extension-2.0.26.data/data/share/jupyter/labextensions/hdsp-agent/static/remoteEntry.0fe2dcbbd176ee0efceb.js.map → jupyter_ext/labextension/static/remoteEntry.08fce819ee32e9d25175.js.map +1 -1
  46. agent_server/langchain/middleware/description_injector.py +0 -150
  47. hdsp_jupyter_extension-2.0.26.data/data/share/jupyter/labextensions/hdsp-agent/static/frontend_styles_index_js.b5e4416b4e07ec087aad.js.map +0 -1
  48. hdsp_jupyter_extension-2.0.26.data/data/share/jupyter/labextensions/hdsp-agent/static/lib_index_js.67505497667f9c0a763d.js.map +0 -1
  49. jupyter_ext/labextension/static/frontend_styles_index_js.b5e4416b4e07ec087aad.js.map +0 -1
  50. jupyter_ext/labextension/static/lib_index_js.67505497667f9c0a763d.js.map +0 -1
  51. {hdsp_jupyter_extension-2.0.26.data → hdsp_jupyter_extension-2.0.28.data}/data/etc/jupyter/jupyter_server_config.d/hdsp_jupyter_extension.json +0 -0
  52. {hdsp_jupyter_extension-2.0.26.data → hdsp_jupyter_extension-2.0.28.data}/data/share/jupyter/labextensions/hdsp-agent/install.json +0 -0
  53. {hdsp_jupyter_extension-2.0.26.data → hdsp_jupyter_extension-2.0.28.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
  54. {hdsp_jupyter_extension-2.0.26.data → hdsp_jupyter_extension-2.0.28.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
  55. {hdsp_jupyter_extension-2.0.26.data → hdsp_jupyter_extension-2.0.28.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
  56. {hdsp_jupyter_extension-2.0.26.data → hdsp_jupyter_extension-2.0.28.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
  57. {hdsp_jupyter_extension-2.0.26.data → hdsp_jupyter_extension-2.0.28.data}/data/share/jupyter/labextensions/hdsp-agent/static/style.js +0 -0
  58. {hdsp_jupyter_extension-2.0.26.data → hdsp_jupyter_extension-2.0.28.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
  59. {hdsp_jupyter_extension-2.0.26.data → hdsp_jupyter_extension-2.0.28.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
  60. {hdsp_jupyter_extension-2.0.26.data → hdsp_jupyter_extension-2.0.28.data}/data/share/jupyter/labextensions/hdsp-agent/static/vendors-node_modules_emotion_cache_dist_emotion-cache_browser_development_esm_js.24edcc52a1c014a8a5f0.js +0 -0
  61. {hdsp_jupyter_extension-2.0.26.data → hdsp_jupyter_extension-2.0.28.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
  62. {hdsp_jupyter_extension-2.0.26.data → hdsp_jupyter_extension-2.0.28.data}/data/share/jupyter/labextensions/hdsp-agent/static/vendors-node_modules_emotion_react_dist_emotion-react_browser_development_esm_js.19ecf6babe00caff6b8a.js +0 -0
  63. {hdsp_jupyter_extension-2.0.26.data → hdsp_jupyter_extension-2.0.28.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
  64. {hdsp_jupyter_extension-2.0.26.data → hdsp_jupyter_extension-2.0.28.data}/data/share/jupyter/labextensions/hdsp-agent/static/vendors-node_modules_emotion_styled_dist_emotion-styled_browser_development_esm_js.661fb5836f4978a7c6e1.js +0 -0
  65. {hdsp_jupyter_extension-2.0.26.data → hdsp_jupyter_extension-2.0.28.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
  66. {hdsp_jupyter_extension-2.0.26.data → hdsp_jupyter_extension-2.0.28.data}/data/share/jupyter/labextensions/hdsp-agent/static/vendors-node_modules_mui_material_index_js.985697e0162d8d088ca2.js +0 -0
  67. {hdsp_jupyter_extension-2.0.26.data → hdsp_jupyter_extension-2.0.28.data}/data/share/jupyter/labextensions/hdsp-agent/static/vendors-node_modules_mui_material_index_js.985697e0162d8d088ca2.js.map +0 -0
  68. {hdsp_jupyter_extension-2.0.26.data → hdsp_jupyter_extension-2.0.28.data}/data/share/jupyter/labextensions/hdsp-agent/static/vendors-node_modules_mui_material_utils_createSvgIcon_js.1f5038488cdfd8b3a85d.js +0 -0
  69. {hdsp_jupyter_extension-2.0.26.data → hdsp_jupyter_extension-2.0.28.data}/data/share/jupyter/labextensions/hdsp-agent/static/vendors-node_modules_mui_material_utils_createSvgIcon_js.1f5038488cdfd8b3a85d.js.map +0 -0
  70. {hdsp_jupyter_extension-2.0.26.dist-info → hdsp_jupyter_extension-2.0.28.dist-info}/WHEEL +0 -0
  71. {hdsp_jupyter_extension-2.0.26.dist-info → hdsp_jupyter_extension-2.0.28.dist-info}/licenses/LICENSE +0 -0
@@ -42,35 +42,38 @@ class SubagentEvent:
42
42
  """Convert to debug message for UI display (legacy, for logging)."""
43
43
  if self.event_type == "subagent_start":
44
44
  desc_preview = self.description[:80] + "..." if self.description and len(self.description) > 80 else self.description
45
- return f"Subagent - {self.subagent_name} - 작업 시작: {desc_preview}"
45
+ return f"Subagent-{self.subagent_name} 작업 시작: {desc_preview}"
46
46
  elif self.event_type == "subagent_tool_call":
47
- return f"Subagent - {self.subagent_name} - Tool 실행: {self.tool_name}"
47
+ return f"Subagent-{self.subagent_name} Tool 실행: {self.tool_name}"
48
48
  elif self.event_type == "subagent_complete":
49
- return f"Subagent - {self.subagent_name} - 완료"
49
+ return f"Subagent-{self.subagent_name} 완료"
50
50
  else:
51
- return f"Subagent - {self.subagent_name} - {self.event_type}"
51
+ return f"Subagent-{self.subagent_name} {self.event_type}"
52
52
 
53
53
  def to_status_dict(self) -> Dict[str, Any]:
54
54
  """Convert to status dict with icon for SSE streaming."""
55
55
  if self.event_type == "subagent_start":
56
56
  desc_preview = self.description[:80] + "..." if self.description and len(self.description) > 80 else self.description
57
+ full_status = f"Subagent-{self.subagent_name} 작업 시작: {self.description}"
57
58
  return {
58
- "status": f"Subagent - {self.subagent_name} - 작업 시작: {desc_preview}",
59
- "icon": "subagentStart"
59
+ "status": f"Subagent-{self.subagent_name} 작업 시작: {desc_preview}",
60
+ "icon": "subagentStart",
61
+ "expandable": bool(self.description and len(self.description) > 80),
62
+ "full_text": full_status,
60
63
  }
61
64
  elif self.event_type == "subagent_tool_call":
62
65
  return {
63
- "status": f"Subagent - {self.subagent_name} - Tool 실행: {self.tool_name}",
66
+ "status": f"Subagent-{self.subagent_name} Tool 실행: {self.tool_name}",
64
67
  "icon": "tool"
65
68
  }
66
69
  elif self.event_type == "subagent_complete":
67
70
  return {
68
- "status": f"Subagent - {self.subagent_name} - 완료",
71
+ "status": f"Subagent-{self.subagent_name} 완료",
69
72
  "icon": "subagentComplete"
70
73
  }
71
74
  else:
72
75
  return {
73
- "status": f"Subagent - {self.subagent_name} - {self.event_type}",
76
+ "status": f"Subagent-{self.subagent_name} {self.event_type}",
74
77
  "icon": "info"
75
78
  }
76
79
 
@@ -169,3 +172,79 @@ def drain_subagent_events() -> List[SubagentEvent]:
169
172
  def get_pending_event_count() -> int:
170
173
  """Get the number of pending events in the queue."""
171
174
  return _event_queue.qsize()
175
+
176
+
177
+ # ═══════════════════════════════════════════════════════════════════════════
178
+ # Summarization Events - For context compression status display
179
+ # ═══════════════════════════════════════════════════════════════════════════
180
+
181
+ @dataclass
182
+ class SummarizationEvent:
183
+ """Represents a summarization event for UI display."""
184
+
185
+ event_type: str # summarization_start, summarization_complete
186
+ message_count_before: Optional[int] = None
187
+ message_count_after: Optional[int] = None
188
+ timestamp: datetime = field(default_factory=datetime.now)
189
+
190
+ def to_status_dict(self) -> Dict[str, Any]:
191
+ """Convert to status dict with icon for SSE streaming."""
192
+ if self.event_type == "summarization_start":
193
+ return {
194
+ "status": "대화 컨텍스트 요약 중...",
195
+ "icon": "thinking"
196
+ }
197
+ elif self.event_type == "summarization_complete":
198
+ if self.message_count_before and self.message_count_after:
199
+ return {
200
+ "status": f"대화가 자동으로 압축되었습니다. ({self.message_count_before} → {self.message_count_after} 메시지)",
201
+ "icon": "check"
202
+ }
203
+ return {
204
+ "status": "대화가 자동으로 압축되었습니다.",
205
+ "icon": "check"
206
+ }
207
+ else:
208
+ return {
209
+ "status": f"Summarization {self.event_type}",
210
+ "icon": "info"
211
+ }
212
+
213
+
214
+ # Separate queue for summarization events (to avoid mixing with subagent events)
215
+ _summarization_queue: Queue = Queue()
216
+
217
+
218
+ def emit_summarization_start() -> None:
219
+ """Emit a summarization start event."""
220
+ event = SummarizationEvent(event_type="summarization_start")
221
+ _summarization_queue.put(event)
222
+ logger.info("Summarization event: starting context compression")
223
+
224
+
225
+ def emit_summarization_complete(before_count: int = 0, after_count: int = 0) -> None:
226
+ """Emit a summarization complete event."""
227
+ event = SummarizationEvent(
228
+ event_type="summarization_complete",
229
+ message_count_before=before_count,
230
+ message_count_after=after_count,
231
+ )
232
+ _summarization_queue.put(event)
233
+ logger.info(f"Summarization event: complete ({before_count} → {after_count} messages)")
234
+
235
+
236
+ def drain_summarization_events() -> List[SummarizationEvent]:
237
+ """
238
+ Drain all pending summarization events from the queue.
239
+
240
+ Returns:
241
+ List of SummarizationEvent objects
242
+ """
243
+ events = []
244
+ while True:
245
+ try:
246
+ event = _summarization_queue.get_nowait()
247
+ events.append(event)
248
+ except Empty:
249
+ break
250
+ return events