idun-agent-engine 0.4.0__py3-none-any.whl → 0.4.1__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.
@@ -1,3 +1,3 @@
1
1
  """Version information for Idun Agent Engine."""
2
2
 
3
- __version__ = "0.4.0"
3
+ __version__ = "0.4.1"
@@ -123,7 +123,7 @@ class AdkAgent(agent_base.BaseAgent):
123
123
  # Observability (provider-agnostic)
124
124
  if observability_config:
125
125
  handlers, infos = observability.create_observability_handlers(
126
- observability_config # type: ignore[arg-type]
126
+ observability_config # type: ignore[arg-type]
127
127
  )
128
128
  self._obs_callbacks = []
129
129
  for handler in handlers:
@@ -153,6 +153,7 @@ class AdkAgent(agent_base.BaseAgent):
153
153
 
154
154
  if is_langfuse_enabled:
155
155
  import os
156
+
156
157
  langfuse_pk = os.environ.get("LANGFUSE_PUBLIC_KEY")
157
158
  langfuse_host = os.environ.get("LANGFUSE_BASE_URL")
158
159
  print(f"LANGFUSE_PUBLIC_KEY: {langfuse_pk}")
@@ -171,7 +172,9 @@ class AdkAgent(agent_base.BaseAgent):
171
172
  except Exception as e:
172
173
  print(f"Failed to instrument Google ADK: {e}")
173
174
  except Exception as e:
174
- print(f"Error checking observability config for ADK instrumentation: {e}")
175
+ print(
176
+ f"Error checking observability config for ADK instrumentation: {e}"
177
+ )
175
178
 
176
179
  # Initialize Session Service
177
180
  await self._initialize_session_service()
@@ -4,6 +4,7 @@ This module provides a fluent API for building configuration objects using Pydan
4
4
  This approach ensures type safety, validation, and consistency with the rest of the codebase.
5
5
  """
6
6
 
7
+ import os
7
8
  from pathlib import Path
8
9
  from typing import Any
9
10
 
@@ -517,6 +518,9 @@ class ConfigBuilder:
517
518
  def load_from_file(config_path: str = "config.yaml") -> EngineConfig:
518
519
  """Load configuration from a YAML file and return a validated EngineConfig.
519
520
 
521
+ Sets IDUN_CONFIG_PATH environment variable to enable MCP helper functions
522
+ (get_adk_tools, get_langchain_tools) to automatically discover the config file.
523
+
520
524
  Args:
521
525
  config_path: Path to the configuration YAML file
522
526
 
@@ -532,6 +536,9 @@ class ConfigBuilder:
532
536
  # Resolve relative to the current working directory
533
537
  path = Path.cwd() / path
534
538
 
539
+ # Set IDUN_CONFIG_PATH for MCP helpers to discover
540
+ os.environ["IDUN_CONFIG_PATH"] = str(path)
541
+
535
542
  with open(path) as f:
536
543
  config_data = yaml.safe_load(f)
537
544
 
@@ -6,6 +6,7 @@ import os
6
6
  from idun_agent_engine.mcp.registry import MCPClientRegistry
7
7
  from idun_agent_schema.engine.mcp_server import MCPServer
8
8
 
9
+
9
10
  def _extract_mcp_configs(config_data: dict[str, Any]) -> list[MCPServer]:
10
11
  """Parse MCP server configs from a config dictionary."""
11
12
  mcp_configs_data = config_data.get("mcp_servers") or config_data.get("mcpServers")
@@ -86,6 +87,7 @@ def _fetch_config_from_api() -> dict[str, Any]:
86
87
  except yaml.YAMLError as e:
87
88
  raise ValueError(f"Failed to parse config YAML: {e}") from e
88
89
 
90
+
89
91
  def get_adk_tools_from_file(config_path: str | Path) -> list[Any]:
90
92
  """
91
93
  Loads MCP configurations from a YAML file and returns a list of ADK toolsets.
@@ -99,6 +101,7 @@ def get_adk_tools_from_file(config_path: str | Path) -> list[Any]:
99
101
  config_data = _load_config_from_file(config_path)
100
102
  return _get_toolsets_from_data(config_data)
101
103
 
104
+
102
105
  def get_adk_tools_from_api() -> list[Any]:
103
106
  """
104
107
  Fetches configuration from the Idun Manager API and returns a list of ADK toolsets.
@@ -112,13 +115,31 @@ def get_adk_tools_from_api() -> list[Any]:
112
115
 
113
116
  def get_adk_tools(config_path: str | Path | None = None) -> list[Any]:
114
117
  """
115
- Returns ADK toolsets using config from file when provided, otherwise from API.
118
+ Returns ADK toolsets using config from file when provided, from IDUN_CONFIG_PATH env var, or from API.
119
+
120
+ The function resolves configuration in the following order:
121
+ 1. Uses the provided config_path if specified
122
+ 2. Uses IDUN_CONFIG_PATH environment variable if set
123
+ 3. Falls back to fetching from Idun Manager API
124
+
125
+ Args:
126
+ config_path: Optional path to configuration YAML file. If provided, takes precedence.
116
127
 
117
128
  Returns:
118
129
  List of initialized ADK McpToolset instances.
130
+
131
+ Raises:
132
+ ValueError: If no config source is available or API credentials are missing.
133
+ FileNotFoundError: If specified config file doesn't exist.
119
134
  """
120
135
  if config_path:
121
136
  return get_adk_tools_from_file(config_path)
137
+
138
+ # Check for IDUN_CONFIG_PATH environment variable
139
+ env_config_path = os.environ.get("IDUN_CONFIG_PATH")
140
+ if env_config_path:
141
+ return get_adk_tools_from_file(env_config_path)
142
+
122
143
  return get_adk_tools_from_api()
123
144
 
124
145
 
@@ -140,8 +161,29 @@ async def get_langchain_tools_from_api() -> list[Any]:
140
161
 
141
162
  async def get_langchain_tools(config_path: str | Path | None = None) -> list[Any]:
142
163
  """
143
- Returns LangChain tool instances using config from file when provided, otherwise from API.
164
+ Returns LangChain tool instances using config from file when provided, from IDUN_CONFIG_PATH env var, or from API.
165
+
166
+ The function resolves configuration in the following order:
167
+ 1. Uses the provided config_path if specified
168
+ 2. Uses IDUN_CONFIG_PATH environment variable if set
169
+ 3. Falls back to fetching from Idun Manager API
170
+
171
+ Args:
172
+ config_path: Optional path to configuration YAML file. If provided, takes precedence.
173
+
174
+ Returns:
175
+ List of initialized LangChain tool instances.
176
+
177
+ Raises:
178
+ ValueError: If no config source is available or API credentials are missing.
179
+ FileNotFoundError: If specified config file doesn't exist.
144
180
  """
145
181
  if config_path:
146
182
  return await get_langchain_tools_from_file(config_path)
183
+
184
+ # Check for IDUN_CONFIG_PATH environment variable
185
+ env_config_path = os.environ.get("IDUN_CONFIG_PATH")
186
+ if env_config_path:
187
+ return await get_langchain_tools_from_file(env_config_path)
188
+
147
189
  return await get_langchain_tools_from_api()
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: idun-agent-engine
3
- Version: 0.4.0
3
+ Version: 0.4.1
4
4
  Summary: Python SDK and runtime to serve AI agents with FastAPI, LangGraph, and observability.
5
5
  Project-URL: Homepage, https://github.com/geoffreyharrazi/idun-agent-platform
6
6
  Project-URL: Repository, https://github.com/geoffreyharrazi/idun-agent-platform
@@ -31,7 +31,7 @@ Requires-Dist: deepagents<1.0.0,>=0.2.8
31
31
  Requires-Dist: fastapi<0.116.0,>=0.115.0
32
32
  Requires-Dist: google-adk<2.0.0,>=1.19.0
33
33
  Requires-Dist: google-cloud-logging<4.0.0,>=3.10.0
34
- Requires-Dist: guardrails-ai<0.8.0,>=0.7.0
34
+ Requires-Dist: guardrails-ai<0.8.0,>=0.7.2
35
35
  Requires-Dist: httpx<0.29.0,>=0.28.1
36
36
  Requires-Dist: idun-agent-schema<1.0.0,>=0.3.8
37
37
  Requires-Dist: langchain-core<2.0.0,>=1.0.0
@@ -1,10 +1,10 @@
1
1
  idun_agent_engine/__init__.py,sha256=PhOL6foq5V0eXaoXw7xKUeCWXIWrOHrAFB8OuJnBqyM,550
2
- idun_agent_engine/_version.py,sha256=IhNtSwHLVf0OkJXf7kUXlUOI7HCuAsywgZymi_DTmac,72
2
+ idun_agent_engine/_version.py,sha256=46Sg_0NATQ79huYXlK2uZI6BAN4q9gzxYyxZAuU0Bh0,72
3
3
  idun_agent_engine/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
4
4
  idun_agent_engine/agent/__init__.py,sha256=foyOoRdI_04q1b6f2A5EXEpWSCKjZxpgWMWrKcsHNl8,220
5
5
  idun_agent_engine/agent/base.py,sha256=c-3gljSHQpm6aY0JNDmXkaPtcW55rXdsI8Cgv9l4bCs,3294
6
6
  idun_agent_engine/agent/adk/__init__.py,sha256=jLV2Z9qQGZtBpF_0pQI1FRCPJ_J1G3Z6cEAzHnQyuu4,83
7
- idun_agent_engine/agent/adk/adk.py,sha256=29YC5rgLjdod-CU3a2JqgAvzYcD5u2EY7pylozGNi9c,11375
7
+ idun_agent_engine/agent/adk/adk.py,sha256=0lfubR5ylfmfuSTOryULxnlJS3gAxpP3xtRaDypGqvE,11415
8
8
  idun_agent_engine/agent/haystack/__init__.py,sha256=y5ADrD8gWBeYIvV7tmu6OpPdJ8POHt-tyraIL7RkkWI,179
9
9
  idun_agent_engine/agent/haystack/haystack.py,sha256=k4NAx_zTBO9uiExM9NtuDAN94H1lrCWtHf1GEWEN16g,10966
10
10
  idun_agent_engine/agent/haystack/haystack_model.py,sha256=EtOYnsWRufcrQufTRMeB3V-rZVQqfnmwKwPsYGfZdCs,362
@@ -13,7 +13,7 @@ idun_agent_engine/agent/langgraph/__init__.py,sha256=CoBdkp9P4livdy5B0bvj9o7ftoq
13
13
  idun_agent_engine/agent/langgraph/langgraph.py,sha256=cbVrUs74a0p6omypMHWO3-1uqGLtJdiyAMrCheQHF5w,22966
14
14
  idun_agent_engine/core/__init__.py,sha256=F0DMDlWcSWS_1dvh3xMbrdcVvZRHVnoAFFgREuSJfBI,408
15
15
  idun_agent_engine/core/app_factory.py,sha256=2w4o7wV8FQCZdBTk3W7cS0vnmpUM_TdAmphFKHbL31w,2597
16
- idun_agent_engine/core/config_builder.py,sha256=oTWzdaYARZUGvVKVznMZT7pPRKKbCKQuXkCTno0Xn-8,25757
16
+ idun_agent_engine/core/config_builder.py,sha256=MosVcPjn7qXUAlmaYvnPquJ0jZ55pDOLfLv0i-D-A28,26049
17
17
  idun_agent_engine/core/engine_config.py,sha256=IR8WhbenDstNSL7ORrUW8AnzgS3exFQxtwip66pFhcM,545
18
18
  idun_agent_engine/core/server_runner.py,sha256=DwN5kHiKVvUJLw5iSkaxs2rKRaMgOwSUZmeUPSuDbf8,4899
19
19
  idun_agent_engine/guardrails/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -22,7 +22,7 @@ idun_agent_engine/guardrails/guardrails_hub/__init__.py,sha256=MwWdgrM1dNzKwuS9Z
22
22
  idun_agent_engine/guardrails/guardrails_hub/guardrails_hub.py,sha256=DgcUIDy9_bcVcpYVvDJowFe_QVlCpEkr8hntPRgRmS0,3456
23
23
  idun_agent_engine/guardrails/guardrails_hub/utils.py,sha256=bC6-MsCVF7xKTr48z7OzJJUeWvqAB7BiHeNTiKsme70,20
24
24
  idun_agent_engine/mcp/__init__.py,sha256=ygChpEQ4MzMpEifW3szi5kNiLIMhOhJEtqxy0nmewDU,501
25
- idun_agent_engine/mcp/helpers.py,sha256=KYYAi9VxX6mRvw70ZiN_6rUz2fMt_KMn3-vUFoa6GC0,5084
25
+ idun_agent_engine/mcp/helpers.py,sha256=b345RHXgeZ15a4gfg8sUJ3Ke7Iwke6FR1RqDRfRUB0c,6589
26
26
  idun_agent_engine/mcp/registry.py,sha256=8zt9o8MZmYKx55xb0E7n-qOCR_3m2-XGf7ToQEwHkTU,4229
27
27
  idun_agent_engine/observability/__init__.py,sha256=DCtK6b3xiX4dh0_8GBDOcSXQdcIJz2wTqqPa_ZFAES4,430
28
28
  idun_agent_engine/observability/base.py,sha256=C6mY_ZafDEHkMz8_ZeaEh--pyYuzJYEUqhoJ0sVP2wY,5570
@@ -53,34 +53,37 @@ idun_agent_engine/templates/deep_research.py,sha256=j4WypBkBz7V3EG-U8vawfNXDNhcC
53
53
  idun_agent_engine/templates/translation.py,sha256=vjp1yEyhDMFO4nEbq5WG7LAA7nLrhVAjznOkV7ob_Ss,2149
54
54
  idun_platform_cli/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
55
55
  idun_platform_cli/main.py,sha256=B7b1x0kgfuiAWGmSCFJeu_zkWiodJjOGu0nWuNAWM-k,299
56
+ idun_platform_cli/telemetry.py,sha256=mLTO8717ckmglm_oSl1xFxomk-eqwqrCU9Nl1uq27Dg,1711
56
57
  idun_platform_cli/groups/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
57
- idun_platform_cli/groups/init.py,sha256=gQo_khZf-arvsG51bdwFXQyfaKvIBFaK9v5KU21AeDo,692
58
+ idun_platform_cli/groups/init.py,sha256=gBWU7tQ0v9aaPNSQXorKWrOkUc5YgJU06pzDC-qG97U,769
58
59
  idun_platform_cli/groups/agent/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
59
60
  idun_platform_cli/groups/agent/main.py,sha256=QMGQi3JZ76SeFI3miIjVWpMt0L-hGz5FwxtTPQX4-Uw,301
60
- idun_platform_cli/groups/agent/package.py,sha256=LdIFAcfrlUcCssmSliYQIi0NFMuVkpx6t8WhMHATan8,2525
61
- idun_platform_cli/groups/agent/serve.py,sha256=2AbL0G1WqR33jlyiGaNvAoPZ3G1o52KYUptz_HaAjIg,3863
61
+ idun_platform_cli/groups/agent/package.py,sha256=JeoQBZ_egkeKhQhB-FuGGrY1T1VG4f4ixuhjt0mDygE,2615
62
+ idun_platform_cli/groups/agent/serve.py,sha256=ujCmJ3JsrjHkXvNwyB7V4poAaTxMQAPcIbRPDVybRQo,3947
62
63
  idun_platform_cli/tui/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
63
- idun_platform_cli/tui/main.py,sha256=QO63okOX7s91r5JDA5mVjvmHuDSY9IArO6GQRaDYxCk,3083
64
+ idun_platform_cli/tui/main.py,sha256=1gFEdbynBfiBLrZrKvNJN16Uc_3DOJl1spexRz38Q-E,3080
64
65
  idun_platform_cli/tui/css/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
65
- idun_platform_cli/tui/css/create_agent.py,sha256=SxqNhB-sEbBcq9B_X4fktyhi31DJgJj61ymR4s0i9PE,12264
66
- idun_platform_cli/tui/css/main.py,sha256=9ii_dobgiz2DNdFhOC6VZSRNrRybI1a6ZykXrVqn7A4,1185
66
+ idun_platform_cli/tui/css/create_agent.py,sha256=ZyFNv6-EUTUaJ_817wh0KUvdu8rtuuPj9jTbigLfOR8,14050
67
+ idun_platform_cli/tui/css/main.py,sha256=gJ_kNb2lC2l99lq8NqtYU2imXAjUpxfiOaf1mNJr-Po,1134
67
68
  idun_platform_cli/tui/schemas/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
68
69
  idun_platform_cli/tui/schemas/create_agent.py,sha256=2jsZ5v1sZLKmypgimdVoeVjd-wOylTE3IUYPw63eb8Y,1512
69
70
  idun_platform_cli/tui/screens/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
70
- idun_platform_cli/tui/screens/create_agent.py,sha256=mtuN7HtQvwloiDZVIp9olJnEA9qHBmQPy-6YdiFXkaE,18332
71
+ idun_platform_cli/tui/screens/create_agent.py,sha256=3Yav2gvJhh0el4BTLuYzYELrHWuKDBnNnNHlRIBUEJE,23881
71
72
  idun_platform_cli/tui/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
72
- idun_platform_cli/tui/utils/config.py,sha256=An-pfUiD-sYQ12QLiE_M0NHAcpBCYo4TnxUbAmqodIA,6316
73
+ idun_platform_cli/tui/utils/config.py,sha256=AEgjgnNkCtQwuGxI8lclteunKZXvn_TMx0eBx7uJWto,7286
73
74
  idun_platform_cli/tui/validators/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
74
- idun_platform_cli/tui/validators/guardrails.py,sha256=XIDzouBtNo63ppyGFMx9lcRHquxOvhY67ouJpF01u50,2894
75
+ idun_platform_cli/tui/validators/guardrails.py,sha256=l6TJKxjpr8Nktwndh6C7Juz4oY-bqpg295jtYTKHuQ8,3537
75
76
  idun_platform_cli/tui/validators/mcps.py,sha256=oDxbxt7qOzsW8yjd_fwBnlDPOSxPqCXqbF5q8eEYRVQ,2852
76
77
  idun_platform_cli/tui/validators/observability.py,sha256=IWNuJg42eZUxjV-7v12kms7DpJsAs3FSSD5zLU5eKUc,2436
77
- idun_platform_cli/tui/widgets/__init__.py,sha256=d0tv94kZiFO6u7Rm8qvAXp5njDZqeVa7WfdU3A1GRdo,407
78
- idun_platform_cli/tui/widgets/guardrails_widget.py,sha256=ZYnvdDiUkOcAAp8gcR8ThpL8wVeAlmQrhPj5j-gUdOw,14299
79
- idun_platform_cli/tui/widgets/identity_widget.py,sha256=JWwfE4Dedv7F6r40tGnscHh8oevUr-_a-k5hZlXKvVg,8840
80
- idun_platform_cli/tui/widgets/mcps_widget.py,sha256=x2IS0SKIX6sfM5yBXW2d_arxWnwuaTEKUfYMTK-hZHw,10958
81
- idun_platform_cli/tui/widgets/observability_widget.py,sha256=Q2_vP7oC5LXznFUjMpse_1dLorrfGtbL11rhpEQOY8c,15064
82
- idun_platform_cli/tui/widgets/serve_widget.py,sha256=B2wK16AHo8BP-igZ0MJWhdCzuILvTzT0zn8PSJ_Szvc,2950
83
- idun_agent_engine-0.4.0.dist-info/METADATA,sha256=8PJDB-q0o90J46WfpMOrp13U9W-uJOeOYga1z2ZBeKA,10870
84
- idun_agent_engine-0.4.0.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
85
- idun_agent_engine-0.4.0.dist-info/entry_points.txt,sha256=XG3oxlSOaCrYKT1oyhKa0Ag1iJPMZ-WF6gaV_mzIJW4,52
86
- idun_agent_engine-0.4.0.dist-info/RECORD,,
78
+ idun_platform_cli/tui/widgets/__init__.py,sha256=w8rQsUxqTtxuhpOPxCgl1pmv2vjCJseKNc1lhfMMkBM,521
79
+ idun_platform_cli/tui/widgets/chat_widget.py,sha256=8RCAY97asVxyy7VV7IJ4kEAX9edK46UGO90BJ0X4BL0,5731
80
+ idun_platform_cli/tui/widgets/guardrails_widget.py,sha256=3EDrfTKXyN7N8qMuWVy-BjK6ia3CZIE0EVm1sh6FhMw,14552
81
+ idun_platform_cli/tui/widgets/identity_widget.py,sha256=LjpX-mgIinxJ5FzKBFz1HYbImwX7khpbetl86LsPnfw,9508
82
+ idun_platform_cli/tui/widgets/mcps_widget.py,sha256=5AToZHU5PAUJEuq0HhL4Mi_VmWlFLyTeY5pohWY3rKw,10974
83
+ idun_platform_cli/tui/widgets/memory_widget.py,sha256=QHCH0et_lJa9pheTpcZdbzTDUzw95Do2koi6hEdmrOc,6996
84
+ idun_platform_cli/tui/widgets/observability_widget.py,sha256=9AO7-nqMEIx_9FCmqbtprxoBejq4w8bR9wOhxl2BbmA,14915
85
+ idun_platform_cli/tui/widgets/serve_widget.py,sha256=0FinYhkyA0LJnX1g4JDrkcD5df-l-qgMxjRjgF0CleQ,2749
86
+ idun_agent_engine-0.4.1.dist-info/METADATA,sha256=xGS6C3n58AGB9WezKja-6Oy2EigEcuO3v8M6JKnZFu0,10870
87
+ idun_agent_engine-0.4.1.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
88
+ idun_agent_engine-0.4.1.dist-info/entry_points.txt,sha256=XG3oxlSOaCrYKT1oyhKa0Ag1iJPMZ-WF6gaV_mzIJW4,52
89
+ idun_agent_engine-0.4.1.dist-info/RECORD,,
@@ -4,6 +4,8 @@ from pathlib import Path
4
4
 
5
5
  import click
6
6
 
7
+ from idun_platform_cli.telemetry import track_command
8
+
7
9
 
8
10
  class Dependency(StrEnum):
9
11
  """Dependency Enum."""
@@ -57,6 +59,7 @@ CMD ["idun", "agent", "serve", "--source=manager"]
57
59
  @click.command("package")
58
60
  @click.argument("path", default=".")
59
61
  @click.option("--target", required=False, default=".")
62
+ @track_command("agent package")
60
63
  def package_command(path: str, target: str):
61
64
  """Packages the agent and it's dependencies into a Dockerfile. You can specifiy the input path and the destination. Defaults to current directory."""
62
65
  dependency = get_dependencies(path)
@@ -8,6 +8,7 @@ from idun_agent_engine.core.app_factory import create_app
8
8
  from idun_agent_engine.core.config_builder import ConfigBuilder
9
9
  from idun_agent_engine.core.engine_config import EngineConfig
10
10
  from idun_agent_engine.core.server_runner import run_server
11
+ from idun_platform_cli.telemetry import track_command
11
12
 
12
13
 
13
14
  class ServerSource(StrEnum):
@@ -84,6 +85,7 @@ class Serve:
84
85
  @click.command("serve")
85
86
  @click.option("--source", required=True)
86
87
  @click.option("--path")
88
+ @track_command("agent serve")
87
89
  def serve_command(source: str, path: str | None):
88
90
  """Reads a config and exposes it's agent as an API. Config is either fetched from the manager, or from a path.
89
91
 
@@ -2,10 +2,12 @@ import sys
2
2
 
3
3
  import click
4
4
 
5
+ from idun_platform_cli.telemetry import track_command
5
6
  from idun_platform_cli.tui.main import IdunApp
6
7
 
7
8
 
8
9
  @click.command("init")
10
+ @track_command("init")
9
11
  def init_command() -> None:
10
12
  """Starts a terminal user interface that guides you through configuring and managing Idun agents."""
11
13
  try:
@@ -0,0 +1,54 @@
1
+ """Telemetry utilities for CLI command tracking."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import functools
6
+ import time
7
+ from typing import Any, Callable, TypeVar
8
+
9
+ from idun_agent_engine.telemetry import get_telemetry, sanitize_telemetry_config
10
+
11
+ F = TypeVar("F", bound=Callable[..., Any])
12
+
13
+
14
+ def track_command(command_name: str) -> Callable[[F], F]:
15
+ """Decorator to track CLI command invocations via telemetry.
16
+
17
+ Args:
18
+ command_name: The name of the command to track (e.g., "init", "agent serve").
19
+
20
+ Returns:
21
+ A decorator that wraps the command function with telemetry tracking.
22
+ """
23
+
24
+ def decorator(func: F) -> F:
25
+ @functools.wraps(func)
26
+ def wrapper(*args: Any, **kwargs: Any) -> Any:
27
+ telemetry = get_telemetry()
28
+ start_time = time.time()
29
+ success = True
30
+ error_message: str | None = None
31
+
32
+ try:
33
+ return func(*args, **kwargs)
34
+ except Exception as e:
35
+ success = False
36
+ error_message = str(e)
37
+ raise
38
+ finally:
39
+ duration_ms = (time.time() - start_time) * 1000
40
+ telemetry.capture(
41
+ "cli command invoked",
42
+ properties={
43
+ "command": command_name,
44
+ "arguments": sanitize_telemetry_config(kwargs),
45
+ "success": success,
46
+ "error": error_message,
47
+ "duration_ms": round(duration_ms, 2),
48
+ },
49
+ )
50
+ telemetry.shutdown(timeout_seconds=0.5)
51
+
52
+ return wrapper # type: ignore[return-value]
53
+
54
+ return decorator
@@ -467,35 +467,38 @@ Footer > .footer--description {
467
467
  padding: 2;
468
468
  }
469
469
 
470
- .serve-summary {
470
+ .serve-yaml-display {
471
471
  width: 100%;
472
+ height: auto;
473
+ max-height: 15;
472
474
  border: round white;
473
475
  border-title-color: yellow;
474
476
  border-title-style: bold;
475
- padding: 2;
477
+ padding: 1;
476
478
  margin-bottom: 2;
479
+ overflow-y: auto;
477
480
  }
478
481
 
479
- .summary-box {
482
+ #yaml_content {
480
483
  width: 100%;
481
- border: round cyan;
482
- border-title-color: cyan;
483
- border-title-style: bold;
484
- padding: 1;
485
- margin-bottom: 1;
484
+ height: auto;
485
+ color: white;
486
486
  }
487
487
 
488
- .summary-box:last-child {
489
- margin-bottom: 0;
488
+ .serve-button-container {
489
+ width: 100%;
490
+ height: auto;
491
+ align: center middle;
490
492
  }
491
493
 
492
494
  .validate-run-btn {
493
- width: 100%;
495
+ width: 1fr;
494
496
  height: 3;
495
497
  background: green;
496
498
  color: white;
497
499
  text-style: bold;
498
500
  border: round white;
501
+ margin: 0 1;
499
502
  }
500
503
 
501
504
  .validate-run-btn:hover {
@@ -509,16 +512,16 @@ Footer > .footer--description {
509
512
  border: round yellow;
510
513
  }
511
514
 
512
- Button#validate_run_button.kill-mode {
515
+ Button#save_run_button.kill-mode {
513
516
  background: red;
514
517
  }
515
518
 
516
- Button#validate_run_button.kill-mode:hover {
519
+ Button#save_run_button.kill-mode:hover {
517
520
  background: darkred;
518
521
  color: white;
519
522
  }
520
523
 
521
- Button#validate_run_button.kill-mode:focus {
524
+ Button#save_run_button.kill-mode:focus {
522
525
  background: darkred;
523
526
  color: white;
524
527
  border: round yellow;
@@ -786,4 +789,124 @@ Switch {
786
789
  text-align: center;
787
790
  text-style: bold;
788
791
  }
792
+
793
+ #widget-chat {
794
+ padding: 2;
795
+ }
796
+
797
+ .chat-history-container {
798
+ width: 100%;
799
+ height: 1fr;
800
+ border: round white;
801
+ border-title-color: yellow;
802
+ border-title-style: bold;
803
+ padding: 1;
804
+ margin-bottom: 2;
805
+ }
806
+
807
+ #chat_history {
808
+ width: 100%;
809
+ height: 100%;
810
+ background: black;
811
+ color: white;
812
+ }
813
+
814
+ .chat-thinking-container {
815
+ width: 100%;
816
+ height: 2;
817
+ align: left middle;
818
+ padding: 0 1;
819
+ }
820
+
821
+ #chat_spinner {
822
+ width: auto;
823
+ height: auto;
824
+ color: yellow;
825
+ }
826
+
827
+ #thinking_label {
828
+ width: auto;
829
+ height: auto;
830
+ color: yellow;
831
+ margin-left: 1;
832
+ text-style: italic;
833
+ }
834
+
835
+ .chat-input-container {
836
+ width: 100%;
837
+ height: 5;
838
+ align: left middle;
839
+ }
840
+
841
+ .chat-input {
842
+ width: 1fr;
843
+ height: 3;
844
+ color: white;
845
+ background: transparent;
846
+ border: round white;
847
+ padding: 0 1;
848
+ margin-right: 1;
849
+ }
850
+
851
+ .chat-input:focus {
852
+ border: round cyan;
853
+ }
854
+
855
+ .chat-input:disabled {
856
+ opacity: 0.5;
857
+ }
858
+
859
+ .send-btn {
860
+ width: 12;
861
+ height: 3;
862
+ background: green;
863
+ color: white;
864
+ text-style: bold;
865
+ border: round white;
866
+ }
867
+
868
+ .send-btn:hover {
869
+ background: cyan;
870
+ color: black;
871
+ }
872
+
873
+ .send-btn:focus {
874
+ background: cyan;
875
+ color: black;
876
+ border: round yellow;
877
+ }
878
+
879
+ .send-btn:disabled {
880
+ background: gray;
881
+ opacity: 0.5;
882
+ }
883
+
884
+ #widget-memory {
885
+ padding: 2;
886
+ }
887
+
888
+ .memory-main {
889
+ width: 100%;
890
+ height: auto;
891
+ border: round white;
892
+ border-title-color: yellow;
893
+ border-title-style: bold;
894
+ padding: 1;
895
+ margin-bottom: 1;
896
+ }
897
+
898
+ .checkpoint-config-container {
899
+ width: 100%;
900
+ height: auto;
901
+ margin-top: 1;
902
+ }
903
+
904
+ .checkpoint-fields-section {
905
+ width: 100%;
906
+ height: auto;
907
+ border: round white;
908
+ border-title-color: yellow;
909
+ border-title-style: bold;
910
+ padding: 1;
911
+ }
789
912
  """
@@ -30,10 +30,16 @@ Container {
30
30
  margin-top: 1;
31
31
  }
32
32
 
33
+ .features-subtle {
34
+ text-align: center;
35
+ color: $text-muted;
36
+ margin-top: 1;
37
+ }
38
+
33
39
  .built-by {
34
40
  text-align: center;
35
41
  color: gray;
36
- margin-top: 1;
42
+ margin-top: 2;
37
43
  }
38
44
 
39
45
  .version {
@@ -79,14 +85,5 @@ Container {
79
85
  text-style: bold;
80
86
  }
81
87
 
82
- .question_prompt {
83
- width: 100%;
84
- height: auto;
85
- text-align: center;
86
- text-style: bold;
87
- color: white;
88
- margin-top: 2;
89
- }
90
-
91
88
 
92
89
  """
@@ -59,14 +59,14 @@ class IdunApp(App):
59
59
  )
60
60
 
61
61
  yield Static("IDUN AGENT PLATFORM", classes="platform")
62
- yield Static("Deploy, guard and monitor any agent", classes="tagline")
63
- yield Static("Built with ❤️ by Idun Group", classes="built-by")
62
+ yield Static("Deploy, guard and monitor your agents.", classes="tagline")
63
+ yield Static("Built with 💜 by Idun Group", classes="built-by")
64
64
  yield Static(f"v{__version__}", classes="version")
65
65
  with Horizontal(classes="link-container"):
66
66
  yield Link("⭐️ Github", url=self.REPO, classes="links")
67
67
  yield Link("📚 Docs", url=self.DOCS, classes="links")
68
+ yield Link("🌐 Website", url=self.DOCS, classes="links")
68
69
 
69
- yield Static("What do you want to do?", classes="question_prompt")
70
70
  yield MainPageActions()
71
71
  yield Footer()
72
72