idun-agent-engine 0.4.0__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 (51) hide show
  1. idun_agent_engine/_version.py +1 -1
  2. idun_agent_engine/agent/adk/adk.py +7 -4
  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 +33 -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 +53 -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.0.dist-info → idun_agent_engine-0.4.2.dist-info}/METADATA +2 -2
  25. idun_agent_engine-0.4.2.dist-info/RECORD +86 -0
  26. idun_platform_cli/groups/agent/package.py +4 -1
  27. idun_platform_cli/groups/agent/serve.py +2 -0
  28. idun_platform_cli/groups/init.py +2 -0
  29. idun_platform_cli/telemetry.py +55 -0
  30. idun_platform_cli/tui/css/create_agent.py +137 -14
  31. idun_platform_cli/tui/css/main.py +7 -10
  32. idun_platform_cli/tui/main.py +3 -3
  33. idun_platform_cli/tui/schemas/create_agent.py +8 -4
  34. idun_platform_cli/tui/screens/create_agent.py +186 -20
  35. idun_platform_cli/tui/utils/config.py +23 -2
  36. idun_platform_cli/tui/validators/guardrails.py +20 -6
  37. idun_platform_cli/tui/validators/mcps.py +9 -6
  38. idun_platform_cli/tui/widgets/__init__.py +8 -4
  39. idun_platform_cli/tui/widgets/chat_widget.py +155 -0
  40. idun_platform_cli/tui/widgets/guardrails_widget.py +12 -4
  41. idun_platform_cli/tui/widgets/identity_widget.py +28 -10
  42. idun_platform_cli/tui/widgets/mcps_widget.py +113 -25
  43. idun_platform_cli/tui/widgets/memory_widget.py +194 -0
  44. idun_platform_cli/tui/widgets/observability_widget.py +12 -14
  45. idun_platform_cli/tui/widgets/serve_widget.py +50 -47
  46. idun_agent_engine/agent/haystack/haystack_model.py +0 -13
  47. idun_agent_engine/guardrails/guardrails_hub/utils.py +0 -1
  48. idun_agent_engine/server/routers/agui.py +0 -47
  49. idun_agent_engine-0.4.0.dist-info/RECORD +0 -86
  50. {idun_agent_engine-0.4.0.dist-info → idun_agent_engine-0.4.2.dist-info}/WHEEL +0 -0
  51. {idun_agent_engine-0.4.0.dist-info → idun_agent_engine-0.4.2.dist-info}/entry_points.txt +0 -0
@@ -8,19 +8,15 @@ from collections.abc import Sequence
8
8
  from contextlib import asynccontextmanager
9
9
 
10
10
  from fastapi import FastAPI
11
+ from idun_agent_schema.engine.guardrails import Guardrails
11
12
 
12
13
  from ..core.config_builder import ConfigBuilder
13
- from ..mcp import MCPClientRegistry
14
-
15
- from idun_agent_schema.engine.guardrails import Guardrails, Guardrail
16
-
17
14
  from ..guardrails.base import BaseGuardrail
18
15
  from ..telemetry import get_telemetry, sanitize_telemetry_config
19
16
 
20
17
 
21
18
  def _parse_guardrails(guardrails_obj: Guardrails) -> Sequence[BaseGuardrail]:
22
19
  """Adds the position of the guardrails (input/output) and returns the lift of updated guardrails."""
23
-
24
20
  from ..guardrails.guardrails_hub.guardrails_hub import GuardrailsHubGuard as GHGuard
25
21
 
26
22
  if not guardrails_obj:
@@ -70,8 +66,8 @@ async def configure_app(app: FastAPI, engine_config):
70
66
  print(f"✅ Agent '{agent_name}' initialized and ready to serve!")
71
67
 
72
68
  # Setup AGUI routes if the agent is a LangGraph agent
73
- from ..agent.langgraph.langgraph import LanggraphAgent
74
69
  from ..agent.adk.adk import AdkAgent
70
+ from ..agent.langgraph.langgraph import LanggraphAgent
75
71
  # from ..server.routers.agui import setup_agui_router
76
72
 
77
73
  if isinstance(agent_instance, (LanggraphAgent, AdkAgent)):
@@ -91,7 +87,6 @@ async def configure_app(app: FastAPI, engine_config):
91
87
  @asynccontextmanager
92
88
  async def lifespan(app: FastAPI):
93
89
  """FastAPI lifespan context to initialize and teardown the agent."""
94
-
95
90
  # Load config and initialize agent on startup
96
91
  print("Server starting up...")
97
92
  if not app.state.engine_config:
@@ -84,6 +84,8 @@ async def invoke(
84
84
  )
85
85
  return ChatResponse(session_id=message["session_id"], response=response_content)
86
86
 
87
+ except HTTPException:
88
+ raise
87
89
  except Exception as e: # noqa: BLE001
88
90
  raise HTTPException(status_code=500, detail=str(e)) from e
89
91
 
@@ -142,7 +144,6 @@ async def copilotkit_stream(
142
144
  try:
143
145
  # Get the accept header from the request
144
146
  accept_header = request.headers.get("accept")
145
- agent_id = request.url.path.lstrip("/")
146
147
 
147
148
  # Create an event encoder to properly format SSE events
148
149
  encoder = EventEncoder(accept=accept_header or "")
@@ -1,8 +1,8 @@
1
1
  """Base routes for service health and landing info."""
2
2
 
3
3
  import os
4
- from typing import Optional
5
- from fastapi import APIRouter, Request, HTTPException
4
+
5
+ from fastapi import APIRouter, HTTPException, Request
6
6
  from pydantic import BaseModel
7
7
 
8
8
  from ..._version import __version__
@@ -15,7 +15,7 @@ base_router = APIRouter()
15
15
  class ReloadRequest(BaseModel):
16
16
  """Request body for reload endpoint."""
17
17
 
18
- path: Optional[str] = None
18
+ path: str | None = None
19
19
 
20
20
 
21
21
  @base_router.get("/health")
@@ -25,9 +25,8 @@ def health_check():
25
25
 
26
26
 
27
27
  @base_router.post("/reload")
28
- async def reload_config(request: Request, body: Optional[ReloadRequest] = None):
28
+ async def reload_config(request: Request, body: ReloadRequest | None = None):
29
29
  """Reload the agent configuration from the manager or a file."""
30
-
31
30
  try:
32
31
  if body and body.path:
33
32
  print(f"🔄 Reloading configuration from file: {body.path}...")
@@ -60,6 +59,9 @@ async def reload_config(request: Request, body: Optional[ReloadRequest] = None):
60
59
  "message": "Agent configuration reloaded successfully",
61
60
  }
62
61
 
62
+ except HTTPException:
63
+ raise
64
+
63
65
  except Exception as e:
64
66
  print(f"❌ Error reloading configuration: {e}")
65
67
  raise HTTPException(
@@ -9,7 +9,6 @@ _telemetry_singleton: IdunTelemetry | None = None
9
9
 
10
10
  def get_telemetry() -> IdunTelemetry:
11
11
  """Return the process-wide telemetry singleton."""
12
-
13
12
  global _telemetry_singleton
14
13
  if _telemetry_singleton is None:
15
14
  _telemetry_singleton = IdunTelemetry()
@@ -13,7 +13,6 @@ def telemetry_enabled(environ: dict[str, str] | None = None) -> bool:
13
13
  Telemetry is ON by default. Users can disable it by setting the environment
14
14
  variable `IDUN_TELEMETRY_ENABLED` to a falsy value (e.g. "false", "0", "no").
15
15
  """
16
-
17
16
  env = os.environ if environ is None else environ
18
17
  raw = env.get(IDUN_TELEMETRY_ENABLED_ENV)
19
18
  if raw is None:
@@ -113,7 +113,6 @@ def _get_or_create_distinct_id() -> str | None:
113
113
  - `IDUN_TELEMETRY_DISTINCT_ID` (if set)
114
114
  - A UUID persisted to `<cache_dir>/idun/telemetry_user_id`
115
115
  """
116
-
117
116
  raw = os.environ.get(_DISTINCT_ID_ENV)
118
117
  if raw and raw.strip():
119
118
  return raw.strip()
@@ -183,9 +182,10 @@ class IdunTelemetry:
183
182
  self._distinct_id = _get_or_create_distinct_id()
184
183
  return self._client
185
184
 
186
- def capture(self, event: str, properties: dict[str, Any] | None = None) -> Future[None] | None:
185
+ def capture(
186
+ self, event: str, properties: dict[str, Any] | None = None
187
+ ) -> Future[None] | None:
187
188
  """Capture an event asynchronously (best-effort)."""
188
-
189
189
  if not self.enabled:
190
190
  return None
191
191
 
@@ -220,7 +220,6 @@ class IdunTelemetry:
220
220
 
221
221
  def shutdown(self, timeout_seconds: float = 1.0) -> None:
222
222
  """Best-effort flush/shutdown without blocking application shutdown."""
223
-
224
223
  executor = self._executor
225
224
  client = self._client
226
225
 
@@ -1,7 +1,7 @@
1
1
  """Correction Agent Template."""
2
2
 
3
3
  import os
4
- from typing import TypedDict, Annotated, List, Any
4
+ from typing import Annotated, Any, TypedDict
5
5
 
6
6
  try:
7
7
  from langchain.chat_models import init_chat_model
@@ -11,13 +11,13 @@ except ImportError:
11
11
  except ImportError:
12
12
  init_chat_model = None
13
13
 
14
- from langchain_core.messages import SystemMessage, BaseMessage
15
- from langgraph.graph import StateGraph, START, END
14
+ from langchain_core.messages import BaseMessage, SystemMessage
15
+ from langgraph.graph import END, START, StateGraph
16
16
  from langgraph.graph.message import add_messages
17
17
 
18
18
 
19
19
  class State(TypedDict):
20
- messages: Annotated[List[BaseMessage], add_messages]
20
+ messages: Annotated[list[BaseMessage], add_messages]
21
21
 
22
22
 
23
23
  MODEL_NAME = os.getenv("CORRECTION_MODEL", "gemini-2.5-flash")
@@ -33,18 +33,15 @@ else:
33
33
  print("Warning: init_chat_model not found in langchain.")
34
34
 
35
35
 
36
-
37
36
  async def correct_text(state: State):
38
37
  """Correct the spelling, syntax, and grammar of the text."""
39
38
  if not llm:
40
-
41
39
  return {
42
40
  "messages": [
43
41
  SystemMessage(content="Error: Model not initialized. Check logs.")
44
42
  ]
45
43
  }
46
44
 
47
-
48
45
  prompt = (
49
46
  f"You are a professional text corrector for {LANGUAGE}. "
50
47
  f"Correct the spelling, syntax, grammar, and conjugation of the following text. "
@@ -1,6 +1,7 @@
1
1
  """Deep Research Agent Template."""
2
2
 
3
3
  import os
4
+
4
5
  from deepagents import create_deep_agent
5
6
  from tavily import TavilyClient
6
7
 
@@ -1,7 +1,7 @@
1
1
  """Translation Agent Template."""
2
2
 
3
3
  import os
4
- from typing import TypedDict, Annotated, List
4
+ from typing import Annotated, TypedDict
5
5
 
6
6
  # Try importing init_chat_model, fallback if necessary
7
7
  try:
@@ -12,14 +12,14 @@ except ImportError:
12
12
  except ImportError:
13
13
  init_chat_model = None
14
14
 
15
- from langchain_core.messages import SystemMessage, BaseMessage
16
- from langgraph.graph import StateGraph, START, END
15
+ from langchain_core.messages import BaseMessage, SystemMessage
16
+ from langgraph.graph import END, START, StateGraph
17
17
  from langgraph.graph.message import add_messages
18
18
 
19
19
 
20
20
  # Define the state
21
21
  class State(TypedDict):
22
- messages: Annotated[List[BaseMessage], add_messages]
22
+ messages: Annotated[list[BaseMessage], add_messages]
23
23
 
24
24
 
25
25
  # Read configuration from environment variables
@@ -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.2
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
@@ -0,0 +1,86 @@
1
+ idun_agent_engine/__init__.py,sha256=PhOL6foq5V0eXaoXw7xKUeCWXIWrOHrAFB8OuJnBqyM,550
2
+ idun_agent_engine/_version.py,sha256=rHg5d6fgwIvzBZWjYtyruzXJK6jO7QljvyRBzdBlBBU,72
3
+ idun_agent_engine/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
4
+ idun_agent_engine/agent/__init__.py,sha256=foyOoRdI_04q1b6f2A5EXEpWSCKjZxpgWMWrKcsHNl8,220
5
+ idun_agent_engine/agent/base.py,sha256=c-3gljSHQpm6aY0JNDmXkaPtcW55rXdsI8Cgv9l4bCs,3294
6
+ idun_agent_engine/agent/adk/__init__.py,sha256=jLV2Z9qQGZtBpF_0pQI1FRCPJ_J1G3Z6cEAzHnQyuu4,83
7
+ idun_agent_engine/agent/adk/adk.py,sha256=hljK87MJ5pfQWudbPhN4OpZxHXOXbZGLQA3mKaJ6dx4,11415
8
+ idun_agent_engine/agent/haystack/__init__.py,sha256=mfYFciVPKRXBxPhnpIy5qPJ8mUSyywUAxiFXFPTzEV4,104
9
+ idun_agent_engine/agent/haystack/haystack.py,sha256=nh86oGy7Q2mBbNdbvMfSYrtKLnNdXCI53S3SnzYp-J4,11039
10
+ idun_agent_engine/agent/haystack/utils.py,sha256=sKRoPhzZWFw1NPsYwCockafzMBCCq3lGOrndbNE_C3M,609
11
+ idun_agent_engine/agent/langgraph/__init__.py,sha256=CoBdkp9P4livdy5B0bvj9o7ftoqKmXEr9cZv4TZLncs,107
12
+ idun_agent_engine/agent/langgraph/langgraph.py,sha256=s8mSm6exo69KBPIhCinRotS8v4DyMGQLG1nFL65rUbA,22871
13
+ idun_agent_engine/core/__init__.py,sha256=F0DMDlWcSWS_1dvh3xMbrdcVvZRHVnoAFFgREuSJfBI,408
14
+ idun_agent_engine/core/app_factory.py,sha256=2w4o7wV8FQCZdBTk3W7cS0vnmpUM_TdAmphFKHbL31w,2597
15
+ idun_agent_engine/core/config_builder.py,sha256=5wbFNKLomw7aWEnfZ6iyljTwpFO_rdgw4c3CUzwLsW4,26221
16
+ idun_agent_engine/core/engine_config.py,sha256=IR8WhbenDstNSL7ORrUW8AnzgS3exFQxtwip66pFhcM,545
17
+ idun_agent_engine/core/server_runner.py,sha256=DwN5kHiKVvUJLw5iSkaxs2rKRaMgOwSUZmeUPSuDbf8,4899
18
+ idun_agent_engine/guardrails/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
19
+ idun_agent_engine/guardrails/base.py,sha256=rvi7gcuKK8-3GtGicWzMWYsKKv0g3LjGBI-FycxgKVU,814
20
+ idun_agent_engine/guardrails/guardrails_hub/__init__.py,sha256=MwWdgrM1dNzKwuS9ZEFw5Cin91JXh2PYlMma8yZFO7o,123
21
+ idun_agent_engine/guardrails/guardrails_hub/guardrails_hub.py,sha256=3H3_1XLXfOB_hrv9cti6aX5CPUNBrV9eQPLwjGx8YN4,4918
22
+ idun_agent_engine/mcp/__init__.py,sha256=PsBUpfFvvgzJhCFeIH8215VrHiHLnBCrP4jfHGw1gmQ,501
23
+ idun_agent_engine/mcp/helpers.py,sha256=NMieZ6FSOaEpxeBLwUWvr-NYje1_AM3_h9LK7Sym6dk,6561
24
+ idun_agent_engine/mcp/registry.py,sha256=ncur1Zp_2bSZBdJRTI8wIq2Lt-fP0oyPHPJH4RnEaKs,4241
25
+ idun_agent_engine/observability/__init__.py,sha256=DCtK6b3xiX4dh0_8GBDOcSXQdcIJz2wTqqPa_ZFAES4,430
26
+ idun_agent_engine/observability/base.py,sha256=Hst5dAxoJwPpiKw9p3MH79-AVZSNTciZ0hlq8K0rSFg,5686
27
+ idun_agent_engine/observability/gcp_logging/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
28
+ idun_agent_engine/observability/gcp_logging/gcp_logging_handler.py,sha256=cMUKfukmSZhIdO2v5oWkqI2_c6umtYqlhzflnOeoq6A,1685
29
+ idun_agent_engine/observability/gcp_trace/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
30
+ idun_agent_engine/observability/gcp_trace/gcp_trace_handler.py,sha256=WMg8u161P-rIS1k8jZiNcRyxvxNE7MwEkktKqcOFWHQ,3920
31
+ idun_agent_engine/observability/langfuse/__init__.py,sha256=J8XcHV4aT1pF97k5EZiqrnYYPs9VjwfV5rUMihc5Pgk,128
32
+ idun_agent_engine/observability/langfuse/langfuse_handler.py,sha256=c9Rzu7SCiyWOPVDimqwMY1Swvp57rKf-RePtHs-zhkw,2765
33
+ idun_agent_engine/observability/phoenix/__init__.py,sha256=tEwJYijcvSGNhFW4QJmvBcTu1D0YVJkZRTmkNCGTteM,130
34
+ idun_agent_engine/observability/phoenix/phoenix_handler.py,sha256=lGqSq-L1vmoEhAr9rbWO3KlNX5HSgBhCKESHMdZ-AfY,2539
35
+ idun_agent_engine/observability/phoenix_local/__init__.py,sha256=m9dIw1GWGKAW4wP08jxA7j4yrOg0Nxq_08bwVh8YogE,146
36
+ idun_agent_engine/observability/phoenix_local/phoenix_local_handler.py,sha256=wjOZuMpAxdD5D33rzxycNEzFMunETpPnYjiHjbjz5GA,4252
37
+ idun_agent_engine/server/__init__.py,sha256=WaFektUsy37bNg2niAUy_TykzStukgWPnxC-t49CEwo,177
38
+ idun_agent_engine/server/dependencies.py,sha256=hRviN2YEf8tvTek2F7IUIp-JH7_V-ru-HKbCqLAox2o,2117
39
+ idun_agent_engine/server/lifespan.py,sha256=oXPDmCjNxCIQdrcZ_Q7bDx6mtndpLRI7VNeKEDIuQNw,4619
40
+ idun_agent_engine/server/server_config.py,sha256=RYA7Y0c5aRw_WXaX8svFUIEtTPqzn3o-WQRm2p52C6g,213
41
+ idun_agent_engine/server/routers/__init__.py,sha256=BgNzSVvHtGPGn5zhXhomwpKlDYBkeFi7xCbdcWVOgc8,102
42
+ idun_agent_engine/server/routers/agent.py,sha256=QDqlR8P19ghLQrIFSd2w-c7iODXAv_P6bQ2AIYCWd7A,9182
43
+ idun_agent_engine/server/routers/base.py,sha256=5kZtPE0QAUZGlvsry2ygzz95IqdjvE2cFqGepD9TA6I,3763
44
+ idun_agent_engine/telemetry/__init__.py,sha256=jeKw2GMqqwoSh1sOxljVmVgP2BHObFYnZeNIF2NPwD8,518
45
+ idun_agent_engine/telemetry/config.py,sha256=JJhw3hysT_0HdbdyuOevD9WeEo4Eu4x0Y3sH5NWZvEY,844
46
+ idun_agent_engine/telemetry/telemetry.py,sha256=yOEExjFwhxvj5J6QW9cMeqFk6J6S0b1XlEb2Kni195o,7330
47
+ idun_agent_engine/templates/__init__.py,sha256=xxbJZXaX6VEm_UrqzAOQcuujpEji5yqYzwQfwiqig8o,31
48
+ idun_agent_engine/templates/correction.py,sha256=_NdgXLENpUhjT81CQI-gzH_yhGwbxSmBAo_VRFmBgQ0,1814
49
+ idun_agent_engine/templates/deep_research.py,sha256=x9BJucpkHzocxmCQ3--HrxjU8A1-StwL-2SVPcslTTI,1078
50
+ idun_agent_engine/templates/translation.py,sha256=bUEhhJuCpoON7PPi0yGE6f3SlZgXhN9WNwj1F9IyN9o,2143
51
+ idun_platform_cli/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
52
+ idun_platform_cli/main.py,sha256=B7b1x0kgfuiAWGmSCFJeu_zkWiodJjOGu0nWuNAWM-k,299
53
+ idun_platform_cli/telemetry.py,sha256=pSjnOXMbT2LuvNVPNCvBdYXRQG4EJbfrfiiC20NSIqk,1738
54
+ idun_platform_cli/groups/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
55
+ idun_platform_cli/groups/init.py,sha256=gBWU7tQ0v9aaPNSQXorKWrOkUc5YgJU06pzDC-qG97U,769
56
+ idun_platform_cli/groups/agent/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
57
+ idun_platform_cli/groups/agent/main.py,sha256=QMGQi3JZ76SeFI3miIjVWpMt0L-hGz5FwxtTPQX4-Uw,301
58
+ idun_platform_cli/groups/agent/package.py,sha256=DjCUSEbPLnHbYkxpkumLb7jZytMWr5WuPDxgLCTcy-8,2614
59
+ idun_platform_cli/groups/agent/serve.py,sha256=ujCmJ3JsrjHkXvNwyB7V4poAaTxMQAPcIbRPDVybRQo,3947
60
+ idun_platform_cli/tui/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
61
+ idun_platform_cli/tui/main.py,sha256=1gFEdbynBfiBLrZrKvNJN16Uc_3DOJl1spexRz38Q-E,3080
62
+ idun_platform_cli/tui/css/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
63
+ idun_platform_cli/tui/css/create_agent.py,sha256=ZyFNv6-EUTUaJ_817wh0KUvdu8rtuuPj9jTbigLfOR8,14050
64
+ idun_platform_cli/tui/css/main.py,sha256=gJ_kNb2lC2l99lq8NqtYU2imXAjUpxfiOaf1mNJr-Po,1134
65
+ idun_platform_cli/tui/schemas/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
66
+ idun_platform_cli/tui/schemas/create_agent.py,sha256=7aXTyf8boBr5xyLAf1O8rXsPca5LUqHz1GqKhOYwPsY,1714
67
+ idun_platform_cli/tui/screens/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
68
+ idun_platform_cli/tui/screens/create_agent.py,sha256=0j-euLfosun7syXAjZYuoexoXmIzmlnZjNiKcoMWKvc,24473
69
+ idun_platform_cli/tui/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
70
+ idun_platform_cli/tui/utils/config.py,sha256=SIDJUfE7vzI3xGXnVPeD7CeTA1Bi6xtQStLvjDMwn50,7281
71
+ idun_platform_cli/tui/validators/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
72
+ idun_platform_cli/tui/validators/guardrails.py,sha256=E4KEVD0KV4gG9ZdlA591HA0seYY2xEDB3HeVPAxbH5E,3585
73
+ idun_platform_cli/tui/validators/mcps.py,sha256=r_YOxIWLPXVDXN9lwO1UvhvbTns7WrwmunO1zydttu4,2883
74
+ idun_platform_cli/tui/validators/observability.py,sha256=IWNuJg42eZUxjV-7v12kms7DpJsAs3FSSD5zLU5eKUc,2436
75
+ idun_platform_cli/tui/widgets/__init__.py,sha256=w8rQsUxqTtxuhpOPxCgl1pmv2vjCJseKNc1lhfMMkBM,521
76
+ idun_platform_cli/tui/widgets/chat_widget.py,sha256=hPWZSX2kwSGwFxWWW1TQ-HOvOa5Y3BjCJnj5WgOrVqY,5753
77
+ idun_platform_cli/tui/widgets/guardrails_widget.py,sha256=EzrZEaAyx7ViW7Vk-QLyu235b1jqauCoyvM9i3qsuGY,14553
78
+ idun_platform_cli/tui/widgets/identity_widget.py,sha256=LjpX-mgIinxJ5FzKBFz1HYbImwX7khpbetl86LsPnfw,9508
79
+ idun_platform_cli/tui/widgets/mcps_widget.py,sha256=fXZzGbK7I4_yDFolvI3UbsR5yeKmW-sNz8STGKYk0E8,12125
80
+ idun_platform_cli/tui/widgets/memory_widget.py,sha256=QCJF6bd21s-QWdQY-UqqPtWZSIl-9xil6ul-a2r6vL0,6966
81
+ idun_platform_cli/tui/widgets/observability_widget.py,sha256=9ioS_BwOkW6NPtzJJa-S-mNUDOqP3QYYgTePcAun18s,14915
82
+ idun_platform_cli/tui/widgets/serve_widget.py,sha256=fSr75DuOxiXr0KbbEDAl0t5iOlDqMQLRiHdMCrENZdI,2728
83
+ idun_agent_engine-0.4.2.dist-info/METADATA,sha256=HrghAw_locsILEAp1BDj6D5SIq8xfFslUv6NndiLzx8,10870
84
+ idun_agent_engine-0.4.2.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
85
+ idun_agent_engine-0.4.2.dist-info/entry_points.txt,sha256=XG3oxlSOaCrYKT1oyhKa0Ag1iJPMZ-WF6gaV_mzIJW4,52
86
+ idun_agent_engine-0.4.2.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."""
@@ -36,7 +38,7 @@ def generate_dockerfile(dependency: Dependency) -> str:
36
38
  return "" # Unreachable, but satisfies type checker
37
39
  if dependency == Dependency.REQUIREMENT:
38
40
  # TODO: use from file
39
- requirements_dockerfile = f"""FROM python:3.12-slim
41
+ requirements_dockerfile = """FROM python:3.12-slim
40
42
  RUN apt-get update && pip install uv
41
43
 
42
44
  RUN uv pip install idun-agent-schema==0.3.1 --system
@@ -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,55 @@
1
+ """Telemetry utilities for CLI command tracking."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import functools
6
+ import time
7
+ from collections.abc import Callable
8
+ from typing import Any, TypeVar
9
+
10
+ from idun_agent_engine.telemetry import get_telemetry, sanitize_telemetry_config
11
+
12
+ F = TypeVar("F", bound=Callable[..., Any])
13
+
14
+
15
+ def track_command(command_name: str) -> Callable[[F], F]:
16
+ """Decorator to track CLI command invocations via telemetry.
17
+
18
+ Args:
19
+ command_name: The name of the command to track (e.g., "init", "agent serve").
20
+
21
+ Returns:
22
+ A decorator that wraps the command function with telemetry tracking.
23
+ """
24
+
25
+ def decorator(func: F) -> F:
26
+ @functools.wraps(func)
27
+ def wrapper(*args: Any, **kwargs: Any) -> Any:
28
+ telemetry = get_telemetry()
29
+ start_time = time.time()
30
+ success = True
31
+ error_message: str | None = None
32
+
33
+ try:
34
+ return func(*args, **kwargs)
35
+ except Exception as e:
36
+ success = False
37
+ error_message = str(e)
38
+ raise
39
+ finally:
40
+ duration_ms = (time.time() - start_time) * 1000
41
+ telemetry.capture(
42
+ "cli command invoked",
43
+ properties={
44
+ "command": command_name,
45
+ "arguments": sanitize_telemetry_config(kwargs),
46
+ "success": success,
47
+ "error": error_message,
48
+ "duration_ms": round(duration_ms, 2),
49
+ },
50
+ )
51
+ telemetry.shutdown(timeout_seconds=0.5)
52
+
53
+ return wrapper # type: ignore[return-value]
54
+
55
+ 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
  """