idun-agent-engine 0.4.1__py3-none-any.whl → 0.4.2__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 (43) hide show
  1. idun_agent_engine/_version.py +1 -1
  2. idun_agent_engine/agent/adk/adk.py +2 -2
  3. idun_agent_engine/agent/haystack/__init__.py +0 -2
  4. idun_agent_engine/agent/haystack/haystack.py +9 -5
  5. idun_agent_engine/agent/langgraph/langgraph.py +10 -13
  6. idun_agent_engine/core/config_builder.py +26 -13
  7. idun_agent_engine/guardrails/guardrails_hub/guardrails_hub.py +52 -9
  8. idun_agent_engine/mcp/__init__.py +2 -2
  9. idun_agent_engine/mcp/helpers.py +11 -15
  10. idun_agent_engine/mcp/registry.py +5 -5
  11. idun_agent_engine/observability/base.py +11 -2
  12. idun_agent_engine/observability/gcp_trace/gcp_trace_handler.py +3 -1
  13. idun_agent_engine/observability/langfuse/langfuse_handler.py +1 -3
  14. idun_agent_engine/server/dependencies.py +7 -2
  15. idun_agent_engine/server/lifespan.py +2 -7
  16. idun_agent_engine/server/routers/agent.py +2 -1
  17. idun_agent_engine/server/routers/base.py +7 -5
  18. idun_agent_engine/telemetry/__init__.py +0 -1
  19. idun_agent_engine/telemetry/config.py +0 -1
  20. idun_agent_engine/telemetry/telemetry.py +3 -4
  21. idun_agent_engine/templates/correction.py +4 -7
  22. idun_agent_engine/templates/deep_research.py +1 -0
  23. idun_agent_engine/templates/translation.py +4 -4
  24. {idun_agent_engine-0.4.1.dist-info → idun_agent_engine-0.4.2.dist-info}/METADATA +1 -1
  25. {idun_agent_engine-0.4.1.dist-info → idun_agent_engine-0.4.2.dist-info}/RECORD +40 -43
  26. idun_platform_cli/groups/agent/package.py +1 -1
  27. idun_platform_cli/telemetry.py +2 -1
  28. idun_platform_cli/tui/schemas/create_agent.py +8 -4
  29. idun_platform_cli/tui/screens/create_agent.py +38 -12
  30. idun_platform_cli/tui/utils/config.py +1 -1
  31. idun_platform_cli/tui/validators/guardrails.py +8 -6
  32. idun_platform_cli/tui/validators/mcps.py +9 -6
  33. idun_platform_cli/tui/widgets/chat_widget.py +3 -1
  34. idun_platform_cli/tui/widgets/guardrails_widget.py +4 -4
  35. idun_platform_cli/tui/widgets/mcps_widget.py +112 -24
  36. idun_platform_cli/tui/widgets/memory_widget.py +0 -1
  37. idun_platform_cli/tui/widgets/observability_widget.py +2 -2
  38. idun_platform_cli/tui/widgets/serve_widget.py +2 -3
  39. idun_agent_engine/agent/haystack/haystack_model.py +0 -13
  40. idun_agent_engine/guardrails/guardrails_hub/utils.py +0 -1
  41. idun_agent_engine/server/routers/agui.py +0 -47
  42. {idun_agent_engine-0.4.1.dist-info → idun_agent_engine-0.4.2.dist-info}/WHEEL +0 -0
  43. {idun_agent_engine-0.4.1.dist-info → idun_agent_engine-0.4.2.dist-info}/entry_points.txt +0 -0
@@ -2,11 +2,18 @@
2
2
 
3
3
  from textual.app import ComposeResult
4
4
  from textual.containers import Horizontal, Vertical
5
- from textual.widgets import Static, Input, Button, RadioSet, RadioButton, TextArea, OptionList
6
5
  from textual.widget import Widget
6
+ from textual.widgets import (
7
+ Button,
8
+ Input,
9
+ OptionList,
10
+ RadioButton,
11
+ RadioSet,
12
+ Static,
13
+ TextArea,
14
+ )
7
15
  from textual.widgets.option_list import Option
8
16
 
9
-
10
17
  MCP_TEMPLATES = {
11
18
  "time": {
12
19
  "name": "time-reference",
@@ -34,14 +41,24 @@ class MCPsWidget(Widget):
34
41
  templates_row = Horizontal(classes="templates-row")
35
42
  templates_row.compose_add_child(Static("Select template:", classes="mcp-label"))
36
43
  option_list = OptionList(id="template_selector", classes="template-selector")
37
- for template_name in MCP_TEMPLATES.keys():
44
+ for template_name in MCP_TEMPLATES:
38
45
  option_list.add_option(Option(template_name.title(), id=template_name))
39
46
  templates_row.compose_add_child(option_list)
40
- templates_row.compose_add_child(Button("Add from Template", id="add_from_template_button", classes="add-template-btn"))
47
+ templates_row.compose_add_child(
48
+ Button(
49
+ "Add from Template",
50
+ id="add_from_template_button",
51
+ classes="add-template-btn",
52
+ )
53
+ )
41
54
  templates_section.compose_add_child(templates_row)
42
55
  yield templates_section
43
56
 
44
- yield Button("+ Add Custom MCP Server", id="add_custom_mcp_button", classes="add-custom-btn")
57
+ yield Button(
58
+ "+ Add Custom MCP Server",
59
+ id="add_custom_mcp_button",
60
+ classes="add-custom-btn",
61
+ )
45
62
 
46
63
  yield Vertical(id="mcps_container", classes="mcps-container")
47
64
 
@@ -67,7 +84,9 @@ class MCPsWidget(Widget):
67
84
  def _add_from_template(self) -> None:
68
85
  template_selector = self.query_one("#template_selector", OptionList)
69
86
  if template_selector.highlighted is not None:
70
- option_id = template_selector.get_option_at_index(template_selector.highlighted).id
87
+ option_id = template_selector.get_option_at_index(
88
+ template_selector.highlighted
89
+ ).id
71
90
  if option_id and str(option_id) in MCP_TEMPLATES:
72
91
  template_data = MCP_TEMPLATES[str(option_id)].copy()
73
92
  self._add_mcp_server(template_data)
@@ -95,52 +114,109 @@ class MCPsWidget(Widget):
95
114
 
96
115
  header = Horizontal(classes="mcp-header")
97
116
  name_value = template_data.get("name", "") if template_data else ""
98
- header.compose_add_child(Static(name_value or f"Server {index + 1}", id=f"mcp_name_display_{index}", classes="mcp-name-display"))
99
- header.compose_add_child(Button("Remove", id=f"remove_mcp_{index}", classes="remove-mcp-btn"))
117
+ header.compose_add_child(
118
+ Static(
119
+ name_value or f"Server {index + 1}",
120
+ id=f"mcp_name_display_{index}",
121
+ classes="mcp-name-display",
122
+ )
123
+ )
124
+ header.compose_add_child(
125
+ Button("Remove", id=f"remove_mcp_{index}", classes="remove-mcp-btn")
126
+ )
100
127
  card.compose_add_child(header)
101
128
 
102
129
  name_row = Horizontal(classes="mcp-field-row")
103
130
  name_row.compose_add_child(Static("Name:", classes="mcp-label"))
104
- name_row.compose_add_child(Input(value=name_value, placeholder="server-name", id=f"mcp_name_{index}", classes="mcp-input"))
131
+ name_row.compose_add_child(
132
+ Input(
133
+ value=name_value,
134
+ placeholder="server-name",
135
+ id=f"mcp_name_{index}",
136
+ classes="mcp-input",
137
+ )
138
+ )
105
139
  card.compose_add_child(name_row)
106
140
 
107
141
  transport_row = Horizontal(classes="mcp-field-row")
108
142
  transport_row.compose_add_child(Static("Transport:", classes="mcp-label"))
109
143
  radio_set = RadioSet(id=f"mcp_transport_{index}")
110
144
 
111
- transport_value = template_data.get("transport", "streamable_http") if template_data else "streamable_http"
112
- radio_set.compose_add_child(RadioButton("stdio", id="stdio", value=(transport_value == "stdio")))
113
- radio_set.compose_add_child(RadioButton("sse", id="sse", value=(transport_value == "sse")))
114
- radio_set.compose_add_child(RadioButton("streamable_http", id="streamable_http", value=(transport_value == "streamable_http")))
115
- radio_set.compose_add_child(RadioButton("websocket", id="websocket", value=(transport_value == "websocket")))
145
+ transport_value = (
146
+ template_data.get("transport", "streamable_http")
147
+ if template_data
148
+ else "streamable_http"
149
+ )
150
+ radio_set.compose_add_child(
151
+ RadioButton("stdio", id="stdio", value=(transport_value == "stdio"))
152
+ )
153
+ radio_set.compose_add_child(
154
+ RadioButton("sse", id="sse", value=(transport_value == "sse"))
155
+ )
156
+ radio_set.compose_add_child(
157
+ RadioButton(
158
+ "streamable_http",
159
+ id="streamable_http",
160
+ value=(transport_value == "streamable_http"),
161
+ )
162
+ )
163
+ radio_set.compose_add_child(
164
+ RadioButton(
165
+ "websocket", id="websocket", value=(transport_value == "websocket")
166
+ )
167
+ )
116
168
  transport_row.compose_add_child(radio_set)
117
169
  card.compose_add_child(transport_row)
118
170
 
119
- http_fields = Vertical(id=f"mcp_http_fields_{index}", classes="http-fields-container")
171
+ http_fields = Vertical(
172
+ id=f"mcp_http_fields_{index}", classes="http-fields-container"
173
+ )
120
174
  http_fields.border_title = "HTTP Configuration"
121
175
 
122
176
  url_row = Horizontal(classes="mcp-field-row")
123
177
  url_row.compose_add_child(Static("URL:", classes="mcp-label"))
124
178
  url_value = template_data.get("url", "") if template_data else ""
125
- url_row.compose_add_child(Input(value=url_value, placeholder="https://api.example.com/mcp", id=f"mcp_url_{index}", classes="mcp-input"))
179
+ url_row.compose_add_child(
180
+ Input(
181
+ value=url_value,
182
+ placeholder="https://api.example.com/mcp",
183
+ id=f"mcp_url_{index}",
184
+ classes="mcp-input",
185
+ )
186
+ )
126
187
  http_fields.compose_add_child(url_row)
127
188
 
128
189
  headers_row = Horizontal(classes="mcp-field-row")
129
190
  headers_row.compose_add_child(Static("Headers (JSON):", classes="mcp-label"))
130
191
  headers_value = template_data.get("headers", "") if template_data else ""
131
- headers_row.compose_add_child(TextArea(text=str(headers_value) if headers_value else "", id=f"mcp_headers_{index}", classes="mcp-textarea"))
192
+ headers_row.compose_add_child(
193
+ TextArea(
194
+ text=str(headers_value) if headers_value else "",
195
+ id=f"mcp_headers_{index}",
196
+ classes="mcp-textarea",
197
+ )
198
+ )
132
199
  http_fields.compose_add_child(headers_row)
133
200
 
134
201
  http_fields.display = transport_value in ["sse", "streamable_http", "websocket"]
135
202
  card.compose_add_child(http_fields)
136
203
 
137
- stdio_fields = Vertical(id=f"mcp_stdio_fields_{index}", classes="stdio-fields-container")
204
+ stdio_fields = Vertical(
205
+ id=f"mcp_stdio_fields_{index}", classes="stdio-fields-container"
206
+ )
138
207
  stdio_fields.border_title = "Stdio Configuration"
139
208
 
140
209
  command_row = Horizontal(classes="mcp-field-row")
141
210
  command_row.compose_add_child(Static("Command:", classes="mcp-label"))
142
211
  command_value = template_data.get("command", "") if template_data else ""
143
- command_row.compose_add_child(Input(value=command_value, placeholder="npx", id=f"mcp_command_{index}", classes="mcp-input"))
212
+ command_row.compose_add_child(
213
+ Input(
214
+ value=command_value,
215
+ placeholder="npx",
216
+ id=f"mcp_command_{index}",
217
+ classes="mcp-input",
218
+ )
219
+ )
144
220
  stdio_fields.compose_add_child(command_row)
145
221
 
146
222
  args_row = Horizontal(classes="mcp-field-row")
@@ -150,7 +226,9 @@ class MCPsWidget(Widget):
150
226
  args_list = template_data["args"]
151
227
  if isinstance(args_list, list):
152
228
  args_value = "\n".join(args_list)
153
- args_textarea = TextArea(text=args_value, id=f"mcp_args_{index}", classes="mcp-textarea")
229
+ args_textarea = TextArea(
230
+ text=args_value, id=f"mcp_args_{index}", classes="mcp-textarea"
231
+ )
154
232
  args_textarea.placeholder = "run\n-i\n--rm"
155
233
  args_row.compose_add_child(args_textarea)
156
234
  stdio_fields.compose_add_child(args_row)
@@ -160,8 +238,11 @@ class MCPsWidget(Widget):
160
238
  env_value = ""
161
239
  if template_data and "env" in template_data:
162
240
  import json
241
+
163
242
  env_value = json.dumps(template_data["env"], indent=2)
164
- env_row.compose_add_child(TextArea(text=env_value, id=f"mcp_env_{index}", classes="mcp-textarea"))
243
+ env_row.compose_add_child(
244
+ TextArea(text=env_value, id=f"mcp_env_{index}", classes="mcp-textarea")
245
+ )
165
246
  stdio_fields.compose_add_child(env_row)
166
247
 
167
248
  stdio_fields.display = transport_value == "stdio"
@@ -189,7 +270,9 @@ class MCPsWidget(Widget):
189
270
  name = name_input.value
190
271
 
191
272
  if not name:
192
- self.app.notify(f"Server {server_id + 1}: Name is required", severity="error")
273
+ self.app.notify(
274
+ f"Server {server_id + 1}: Name is required", severity="error"
275
+ )
193
276
  return None
194
277
 
195
278
  radio_set = self.query_one(f"#mcp_transport_{server_id}", RadioSet)
@@ -206,7 +289,9 @@ class MCPsWidget(Widget):
206
289
  url_input = self.query_one(f"#mcp_url_{server_id}", Input)
207
290
  server_config["url"] = url_input.value
208
291
 
209
- headers_textarea = self.query_one(f"#mcp_headers_{server_id}", TextArea)
292
+ headers_textarea = self.query_one(
293
+ f"#mcp_headers_{server_id}", TextArea
294
+ )
210
295
  if headers_textarea.text.strip():
211
296
  server_config["headers"] = headers_textarea.text.strip()
212
297
 
@@ -224,7 +309,10 @@ class MCPsWidget(Widget):
224
309
  servers_data.append(server_config)
225
310
 
226
311
  except Exception:
227
- self.app.notify(f"Error reading MCP server {server_id + 1}: check your configuration.", severity="error")
312
+ self.app.notify(
313
+ f"Error reading MCP server {server_id + 1}: check your configuration.",
314
+ severity="error",
315
+ )
228
316
  return None
229
317
 
230
318
  return servers_data
@@ -92,7 +92,6 @@ class MemoryWidget(Widget):
92
92
 
93
93
  def get_data(self) -> CheckpointConfig | None:
94
94
  from idun_agent_schema.engine.langgraph import (
95
- CheckpointConfig,
96
95
  InMemoryCheckpointConfig,
97
96
  PostgresCheckpointConfig,
98
97
  SqliteCheckpointConfig,
@@ -4,9 +4,9 @@ from idun_agent_schema.engine.observability_v2 import (
4
4
  )
5
5
  from textual.app import ComposeResult
6
6
  from textual.containers import Horizontal, Vertical
7
- from textual.widgets import Static, Input, RadioSet, RadioButton, Switch
8
- from textual.widget import Widget
9
7
  from textual.reactive import reactive
8
+ from textual.widget import Widget
9
+ from textual.widgets import Input, RadioButton, RadioSet, Static, Switch
10
10
 
11
11
  from idun_platform_cli.tui.validators.observability import validate_observability
12
12
 
@@ -1,6 +1,5 @@
1
1
  """Serve configuration widget."""
2
2
 
3
- from typing import Any
4
3
 
5
4
  from rich.syntax import Syntax
6
5
  from textual.app import ComposeResult
@@ -57,7 +56,7 @@ class ServeWidget(Widget):
57
56
  self.config_data,
58
57
  default_flow_style=False,
59
58
  sort_keys=False,
60
- allow_unicode=True
59
+ allow_unicode=True,
61
60
  )
62
61
 
63
62
  syntax = Syntax(
@@ -67,7 +66,7 @@ class ServeWidget(Widget):
67
66
  line_numbers=True,
68
67
  word_wrap=False,
69
68
  indent_guides=True,
70
- background_color="default"
69
+ background_color="default",
71
70
  )
72
71
 
73
72
  self.query_one("#yaml_content", Static).update(syntax)
@@ -1,13 +0,0 @@
1
- """Configuration models for Haystack agents."""
2
-
3
- from typing import Literal
4
-
5
- from idun_agent_engine.core.engine_config import BaseAgentConfig
6
-
7
-
8
- class HaystackAgentConfig(BaseAgentConfig):
9
- """Configuration model for Haystack Agents."""
10
-
11
- type: Literal["haystack"] = "haystack"
12
- component_type: Literal["pipeline", "agent"]
13
- component_definition: str
@@ -1 +0,0 @@
1
- """Utils module."""
@@ -1,47 +0,0 @@
1
- # """AGUI routes for CopilotKit integration with LangGraph agents."""
2
-
3
- # import logging
4
- # from typing import Annotated
5
-
6
- # from ag_ui_langgraph import add_langgraph_fastapi_endpoint
7
- # from copilotkit import LangGraphAGUIAgent
8
- # from ag_ui_adk import ADKAgent as ADKAGUIAgent
9
- # from ag_ui_adk import add_adk_fastapi_endpoint
10
- # from fastapi import APIRouter, Depends, HTTPException, Request
11
-
12
- # from idun_agent_engine.agent.langgraph.langgraph import LanggraphAgent
13
- # from idun_agent_engine.agent.adk.adk import AdkAgent
14
- # from idun_agent_engine.server.dependencies import get_agent
15
-
16
- # logging.basicConfig(
17
- # format="%(asctime)s %(levelname)-8s %(message)s",
18
- # level=logging.INFO,
19
- # datefmt="%Y-%m-%d %H:%M:%S",
20
- # )
21
-
22
- # logger = logging.getLogger(__name__)
23
-
24
-
25
- # def setup_agui_router(app, agent: LanggraphAgent | AdkAgent) -> LangGraphAGUIAgent | ADKAGUIAgent:
26
- # """Set up AGUI routes for CopilotKit integration.
27
-
28
- # This function adds the LangGraph agent as a CopilotKit-compatible endpoint.
29
-
30
- # Args:
31
- # app: The FastAPI application instance
32
- # agent: The initialized LangGraph agent instance
33
- # """
34
- # try:
35
- # if isinstance(agent, LanggraphAgent):
36
- # # Create the AGUI agent wrapper
37
- # agui_agent = agent.copilotkit_agent_instance
38
- # elif isinstance(agent, AdkAgent):
39
- # # Create the AGUI agent wrapper
40
- # agui_agent = agent.copilotkit_agent_instance # TODO: duplicate in agent.adk.adk.py init
41
- # else:
42
- # raise ValueError(f"Unsupported agent type: {type(agent)}")
43
- # return agui_agent
44
- # logger.info(f"✅ AGUI endpoint configured at /agui for agent: {agent.name}")
45
- # except Exception as e:
46
- # logger.error(f"❌ Failed to setup AGUI router: {e}")
47
- # raise HTTPException(status_code=500, detail=f"Failed to setup AGUI router: {e}") from e