idun-agent-engine 0.3.9__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.
- idun_agent_engine/_version.py +1 -1
- idun_agent_engine/agent/adk/adk.py +5 -2
- idun_agent_engine/agent/langgraph/langgraph.py +1 -1
- idun_agent_engine/core/app_factory.py +1 -1
- idun_agent_engine/core/config_builder.py +11 -5
- idun_agent_engine/guardrails/guardrails_hub/__init__.py +2 -2
- idun_agent_engine/mcp/__init__.py +18 -2
- idun_agent_engine/mcp/helpers.py +135 -43
- idun_agent_engine/mcp/registry.py +7 -1
- idun_agent_engine/server/lifespan.py +22 -0
- idun_agent_engine/telemetry/__init__.py +19 -0
- idun_agent_engine/telemetry/config.py +29 -0
- idun_agent_engine/telemetry/telemetry.py +248 -0
- {idun_agent_engine-0.3.9.dist-info → idun_agent_engine-0.4.1.dist-info}/METADATA +12 -8
- {idun_agent_engine-0.3.9.dist-info → idun_agent_engine-0.4.1.dist-info}/RECORD +45 -17
- idun_platform_cli/groups/agent/package.py +3 -0
- idun_platform_cli/groups/agent/serve.py +2 -0
- idun_platform_cli/groups/init.py +25 -0
- idun_platform_cli/main.py +3 -0
- idun_platform_cli/telemetry.py +54 -0
- idun_platform_cli/tui/__init__.py +0 -0
- idun_platform_cli/tui/css/__init__.py +0 -0
- idun_platform_cli/tui/css/create_agent.py +912 -0
- idun_platform_cli/tui/css/main.py +89 -0
- idun_platform_cli/tui/main.py +87 -0
- idun_platform_cli/tui/schemas/__init__.py +0 -0
- idun_platform_cli/tui/schemas/create_agent.py +60 -0
- idun_platform_cli/tui/screens/__init__.py +0 -0
- idun_platform_cli/tui/screens/create_agent.py +622 -0
- idun_platform_cli/tui/utils/__init__.py +0 -0
- idun_platform_cli/tui/utils/config.py +182 -0
- idun_platform_cli/tui/validators/__init__.py +0 -0
- idun_platform_cli/tui/validators/guardrails.py +88 -0
- idun_platform_cli/tui/validators/mcps.py +84 -0
- idun_platform_cli/tui/validators/observability.py +65 -0
- idun_platform_cli/tui/widgets/__init__.py +19 -0
- idun_platform_cli/tui/widgets/chat_widget.py +153 -0
- idun_platform_cli/tui/widgets/guardrails_widget.py +356 -0
- idun_platform_cli/tui/widgets/identity_widget.py +252 -0
- idun_platform_cli/tui/widgets/mcps_widget.py +230 -0
- idun_platform_cli/tui/widgets/memory_widget.py +195 -0
- idun_platform_cli/tui/widgets/observability_widget.py +382 -0
- idun_platform_cli/tui/widgets/serve_widget.py +82 -0
- {idun_agent_engine-0.3.9.dist-info → idun_agent_engine-0.4.1.dist-info}/WHEEL +0 -0
- {idun_agent_engine-0.3.9.dist-info → idun_agent_engine-0.4.1.dist-info}/entry_points.txt +0 -0
|
@@ -0,0 +1,248 @@
|
|
|
1
|
+
"""Non-blocking telemetry for Idun Agent Engine.
|
|
2
|
+
|
|
3
|
+
Telemetry is ON by default and can be disabled with `IDUN_TELEMETRY_ENABLED=false`.
|
|
4
|
+
|
|
5
|
+
We persist a stable `distinct_id` in the OS cache directory at:
|
|
6
|
+
`<cache_dir>/idun/telemetry_user_id`
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
from __future__ import annotations
|
|
10
|
+
|
|
11
|
+
import os
|
|
12
|
+
import platform
|
|
13
|
+
import re
|
|
14
|
+
import sys
|
|
15
|
+
import threading
|
|
16
|
+
import uuid
|
|
17
|
+
from concurrent.futures import Future, ThreadPoolExecutor
|
|
18
|
+
from dataclasses import dataclass, field
|
|
19
|
+
from pathlib import Path
|
|
20
|
+
from typing import Any
|
|
21
|
+
|
|
22
|
+
from platformdirs import user_cache_dir
|
|
23
|
+
|
|
24
|
+
from .config import telemetry_enabled
|
|
25
|
+
|
|
26
|
+
_POSTHOG_HOST = "https://us.i.posthog.com"
|
|
27
|
+
_POSTHOG_PROJECT_API_KEY = "phc_mpAplkH6w5zK1aSkkG0IL5Ys55m6X34BFvGozB2NqPw"
|
|
28
|
+
_DISTINCT_ID_ENV = "IDUN_TELEMETRY_DISTINCT_ID"
|
|
29
|
+
_CACHE_APP_NAME = "idun"
|
|
30
|
+
_CACHE_DISTINCT_ID_FILE = "telemetry_user_id"
|
|
31
|
+
_MAX_VALUE_LENGTH = 200
|
|
32
|
+
_SENSITIVE_KEY_FRAGMENTS = (
|
|
33
|
+
"api_key",
|
|
34
|
+
"apikey",
|
|
35
|
+
"access_key",
|
|
36
|
+
"accesskey",
|
|
37
|
+
"private_key",
|
|
38
|
+
"privatekey",
|
|
39
|
+
"secret",
|
|
40
|
+
"token",
|
|
41
|
+
"password",
|
|
42
|
+
"passphrase",
|
|
43
|
+
"client_secret",
|
|
44
|
+
"clientsecret",
|
|
45
|
+
"bearer",
|
|
46
|
+
"authorization",
|
|
47
|
+
)
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
def _is_sensitive_key(key: str) -> bool:
|
|
51
|
+
normalized = re.sub(r"[^a-z0-9]+", "_", key.lower())
|
|
52
|
+
return any(fragment in normalized for fragment in _SENSITIVE_KEY_FRAGMENTS)
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
def _is_private_key_value(value: str) -> bool:
|
|
56
|
+
upper_value = value.upper()
|
|
57
|
+
return "PRIVATE KEY" in upper_value or "BEGIN OPENSSH PRIVATE KEY" in upper_value
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
def _truncate_value(value: str) -> str:
|
|
61
|
+
if len(value) <= _MAX_VALUE_LENGTH:
|
|
62
|
+
return value
|
|
63
|
+
return value[:_MAX_VALUE_LENGTH]
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
def sanitize_telemetry_config(value: Any) -> Any:
|
|
67
|
+
"""Return a telemetry-safe copy of config objects."""
|
|
68
|
+
if hasattr(value, "model_dump") and callable(value.model_dump):
|
|
69
|
+
value = value.model_dump() # type: ignore[assignment]
|
|
70
|
+
elif hasattr(value, "dict") and callable(value.dict):
|
|
71
|
+
value = value.dict() # type: ignore[assignment]
|
|
72
|
+
|
|
73
|
+
if isinstance(value, dict):
|
|
74
|
+
sanitized: dict[str, Any] = {}
|
|
75
|
+
for key, item in value.items():
|
|
76
|
+
if isinstance(key, str) and _is_sensitive_key(key):
|
|
77
|
+
sanitized[key] = "[redacted]"
|
|
78
|
+
else:
|
|
79
|
+
sanitized[key] = sanitize_telemetry_config(item)
|
|
80
|
+
return sanitized
|
|
81
|
+
|
|
82
|
+
if isinstance(value, (list, tuple, set)):
|
|
83
|
+
return [sanitize_telemetry_config(item) for item in value]
|
|
84
|
+
|
|
85
|
+
if isinstance(value, str):
|
|
86
|
+
if _is_private_key_value(value):
|
|
87
|
+
return "[redacted]"
|
|
88
|
+
return _truncate_value(value)
|
|
89
|
+
|
|
90
|
+
return value
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
def _safe_read_text(path: Path) -> str | None:
|
|
94
|
+
try:
|
|
95
|
+
return path.read_text(encoding="utf-8").strip()
|
|
96
|
+
except Exception:
|
|
97
|
+
return None
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
def _safe_write_text(path: Path, text: str) -> None:
|
|
101
|
+
try:
|
|
102
|
+
path.parent.mkdir(parents=True, exist_ok=True)
|
|
103
|
+
path.write_text(text, encoding="utf-8")
|
|
104
|
+
except Exception:
|
|
105
|
+
# Best-effort only.
|
|
106
|
+
return
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
def _get_or_create_distinct_id() -> str | None:
|
|
110
|
+
"""Return a stable distinct id.
|
|
111
|
+
|
|
112
|
+
Preference order:
|
|
113
|
+
- `IDUN_TELEMETRY_DISTINCT_ID` (if set)
|
|
114
|
+
- A UUID persisted to `<cache_dir>/idun/telemetry_user_id`
|
|
115
|
+
"""
|
|
116
|
+
|
|
117
|
+
raw = os.environ.get(_DISTINCT_ID_ENV)
|
|
118
|
+
if raw and raw.strip():
|
|
119
|
+
return raw.strip()
|
|
120
|
+
|
|
121
|
+
cache_dir = Path(user_cache_dir(_CACHE_APP_NAME))
|
|
122
|
+
id_path = cache_dir / _CACHE_DISTINCT_ID_FILE
|
|
123
|
+
|
|
124
|
+
existing = _safe_read_text(id_path)
|
|
125
|
+
if existing:
|
|
126
|
+
return existing
|
|
127
|
+
|
|
128
|
+
new_id = str(uuid.uuid4())
|
|
129
|
+
_safe_write_text(id_path, new_id)
|
|
130
|
+
return new_id
|
|
131
|
+
|
|
132
|
+
|
|
133
|
+
def _common_properties() -> dict[str, Any]:
|
|
134
|
+
from .._version import __version__
|
|
135
|
+
|
|
136
|
+
return {
|
|
137
|
+
"library": "idun-agent-engine",
|
|
138
|
+
"library_version": __version__,
|
|
139
|
+
"python_version": platform.python_version(),
|
|
140
|
+
"python_implementation": platform.python_implementation(),
|
|
141
|
+
"platform": sys.platform,
|
|
142
|
+
"os": platform.system(),
|
|
143
|
+
"os_version": platform.release(),
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
|
|
147
|
+
@dataclass(slots=True)
|
|
148
|
+
class IdunTelemetry:
|
|
149
|
+
"""Non-blocking telemetry client."""
|
|
150
|
+
|
|
151
|
+
enabled: bool = field(default_factory=telemetry_enabled)
|
|
152
|
+
_executor: ThreadPoolExecutor | None = field(default=None, init=False, repr=False)
|
|
153
|
+
_client: Any | None = field(default=None, init=False, repr=False)
|
|
154
|
+
_client_lock: threading.Lock = field(
|
|
155
|
+
default_factory=threading.Lock, init=False, repr=False
|
|
156
|
+
)
|
|
157
|
+
_distinct_id: str | None = field(default=None, init=False, repr=False)
|
|
158
|
+
|
|
159
|
+
def _ensure_executor(self) -> ThreadPoolExecutor:
|
|
160
|
+
if self._executor is None:
|
|
161
|
+
self._executor = ThreadPoolExecutor(
|
|
162
|
+
max_workers=1, thread_name_prefix="idun-telemetry"
|
|
163
|
+
)
|
|
164
|
+
return self._executor
|
|
165
|
+
|
|
166
|
+
def _get_client(self) -> Any | None:
|
|
167
|
+
if not self.enabled:
|
|
168
|
+
return None
|
|
169
|
+
if self._client is not None:
|
|
170
|
+
return self._client
|
|
171
|
+
|
|
172
|
+
with self._client_lock:
|
|
173
|
+
if self._client is not None:
|
|
174
|
+
return self._client
|
|
175
|
+
try:
|
|
176
|
+
from posthog import Posthog
|
|
177
|
+
except Exception:
|
|
178
|
+
# Dependency missing or import failure should not break runtime.
|
|
179
|
+
return None
|
|
180
|
+
|
|
181
|
+
client = Posthog(_POSTHOG_PROJECT_API_KEY, host=_POSTHOG_HOST)
|
|
182
|
+
self._client = client
|
|
183
|
+
self._distinct_id = _get_or_create_distinct_id()
|
|
184
|
+
return self._client
|
|
185
|
+
|
|
186
|
+
def capture(self, event: str, properties: dict[str, Any] | None = None) -> Future[None] | None:
|
|
187
|
+
"""Capture an event asynchronously (best-effort)."""
|
|
188
|
+
|
|
189
|
+
if not self.enabled:
|
|
190
|
+
return None
|
|
191
|
+
|
|
192
|
+
executor = self._ensure_executor()
|
|
193
|
+
|
|
194
|
+
def _send() -> None:
|
|
195
|
+
client = self._get_client()
|
|
196
|
+
if client is None:
|
|
197
|
+
return
|
|
198
|
+
|
|
199
|
+
merged: dict[str, Any] = _common_properties()
|
|
200
|
+
if properties:
|
|
201
|
+
merged.update(properties)
|
|
202
|
+
|
|
203
|
+
try:
|
|
204
|
+
if self._distinct_id:
|
|
205
|
+
client.capture(
|
|
206
|
+
event=event,
|
|
207
|
+
distinct_id=self._distinct_id,
|
|
208
|
+
properties=merged,
|
|
209
|
+
)
|
|
210
|
+
else:
|
|
211
|
+
client.capture(event=event, properties=merged)
|
|
212
|
+
except Exception:
|
|
213
|
+
# Never fail user code because of telemetry.
|
|
214
|
+
return
|
|
215
|
+
|
|
216
|
+
try:
|
|
217
|
+
return executor.submit(_send)
|
|
218
|
+
except Exception:
|
|
219
|
+
return None
|
|
220
|
+
|
|
221
|
+
def shutdown(self, timeout_seconds: float = 1.0) -> None:
|
|
222
|
+
"""Best-effort flush/shutdown without blocking application shutdown."""
|
|
223
|
+
|
|
224
|
+
executor = self._executor
|
|
225
|
+
client = self._client
|
|
226
|
+
|
|
227
|
+
if executor is None:
|
|
228
|
+
return
|
|
229
|
+
|
|
230
|
+
def _shutdown_client() -> None:
|
|
231
|
+
try:
|
|
232
|
+
if client is not None:
|
|
233
|
+
shutdown_fn = getattr(client, "shutdown", None)
|
|
234
|
+
if callable(shutdown_fn):
|
|
235
|
+
shutdown_fn()
|
|
236
|
+
except Exception:
|
|
237
|
+
return
|
|
238
|
+
|
|
239
|
+
try:
|
|
240
|
+
fut = executor.submit(_shutdown_client)
|
|
241
|
+
fut.result(timeout=timeout_seconds)
|
|
242
|
+
except Exception:
|
|
243
|
+
pass
|
|
244
|
+
finally:
|
|
245
|
+
try:
|
|
246
|
+
executor.shutdown(wait=False, cancel_futures=False)
|
|
247
|
+
except Exception:
|
|
248
|
+
pass
|
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: idun-agent-engine
|
|
3
|
-
Version: 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
|
|
7
7
|
Project-URL: Documentation, https://github.com/geoffreyharrazi/idun-agent-platform/tree/main/libs/idun_agent_engine
|
|
8
8
|
Project-URL: Issues, https://github.com/geoffreyharrazi/idun-agent-platform/issues
|
|
9
9
|
Author-email: Geoffrey HARRAZI <geoffreyharrazi@gmail.com>
|
|
10
|
-
License-Expression:
|
|
10
|
+
License-Expression: GPL-3.0-only
|
|
11
11
|
Keywords: agents,fastapi,langgraph,llm,observability,sdk
|
|
12
12
|
Classifier: Framework :: FastAPI
|
|
13
13
|
Classifier: Intended Audience :: Developers
|
|
14
|
-
Classifier: License :: OSI Approved ::
|
|
14
|
+
Classifier: License :: OSI Approved :: GNU General Public License v3 (GPLv3)
|
|
15
15
|
Classifier: Programming Language :: Python :: 3
|
|
16
16
|
Classifier: Programming Language :: Python :: 3 :: Only
|
|
17
17
|
Classifier: Programming Language :: Python :: 3.12
|
|
@@ -31,12 +31,12 @@ 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.
|
|
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
|
|
38
38
|
Requires-Dist: langchain-google-vertexai<4.0.0,>=2.0.27
|
|
39
|
-
Requires-Dist: langchain-mcp-adapters<0.
|
|
39
|
+
Requires-Dist: langchain-mcp-adapters<0.3.0,>=0.2.0
|
|
40
40
|
Requires-Dist: langchain<2.0.0,>=1.0.0
|
|
41
41
|
Requires-Dist: langfuse-haystack>=2.3.0
|
|
42
42
|
Requires-Dist: langfuse<4.0.0,>=2.60.8
|
|
@@ -51,12 +51,16 @@ Requires-Dist: openinference-instrumentation-mcp<2.0.0,>=1.0.0
|
|
|
51
51
|
Requires-Dist: openinference-instrumentation-vertexai<1.0.0,>=0.1.0
|
|
52
52
|
Requires-Dist: opentelemetry-exporter-gcp-trace<2.0.0,>=1.6.0
|
|
53
53
|
Requires-Dist: opentelemetry-exporter-otlp-proto-http<2.0.0,>=1.22.0
|
|
54
|
+
Requires-Dist: platformdirs<5.0.0,>=4.0.0
|
|
55
|
+
Requires-Dist: posthog<8.0.0,>=7.0.0
|
|
54
56
|
Requires-Dist: psycopg-binary<4.0.0,>=3.3.0
|
|
55
57
|
Requires-Dist: pydantic<3.0.0,>=2.11.7
|
|
56
58
|
Requires-Dist: python-dotenv>=1.1.1
|
|
59
|
+
Requires-Dist: pyyaml<7.0.0,>=6.0.0
|
|
57
60
|
Requires-Dist: sqlalchemy<3.0.0,>=2.0.36
|
|
58
61
|
Requires-Dist: streamlit<2.0.0,>=1.47.1
|
|
59
62
|
Requires-Dist: tavily-python<0.8.0,>=0.7.9
|
|
63
|
+
Requires-Dist: textual<7.4.0,>=7.3.0
|
|
60
64
|
Requires-Dist: uvicorn<0.36.0,>=0.35.0
|
|
61
65
|
Description-Content-Type: text/markdown
|
|
62
66
|
|
|
@@ -72,7 +76,7 @@ Idun Agent Engine is a lightweight runtime and SDK that wraps your agent with a
|
|
|
72
76
|
pip install idun-agent-engine
|
|
73
77
|
```
|
|
74
78
|
|
|
75
|
-
- Requires Python 3.
|
|
79
|
+
- Requires Python 3.12+
|
|
76
80
|
- Ships with FastAPI, Uvicorn, LangGraph, SQLite checkpointing, and optional observability hooks
|
|
77
81
|
|
|
78
82
|
## Quickstart
|
|
@@ -319,9 +323,9 @@ from idun_agent_engine import (
|
|
|
319
323
|
|
|
320
324
|
Issues and PRs are welcome. See the repository:
|
|
321
325
|
|
|
322
|
-
- Repo: `https://github.com/
|
|
326
|
+
- Repo: `https://github.com/Idun-Group/idun-agent-platform`
|
|
323
327
|
- Package path: `libs/idun_agent_engine`
|
|
324
|
-
- Open an issue: `https://github.com/
|
|
328
|
+
- Open an issue: `https://github.com/Idun-Group/idun-agent-platform/issues`
|
|
325
329
|
|
|
326
330
|
Run locally:
|
|
327
331
|
|
|
@@ -1,29 +1,29 @@
|
|
|
1
1
|
idun_agent_engine/__init__.py,sha256=PhOL6foq5V0eXaoXw7xKUeCWXIWrOHrAFB8OuJnBqyM,550
|
|
2
|
-
idun_agent_engine/_version.py,sha256=
|
|
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=
|
|
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
|
|
11
11
|
idun_agent_engine/agent/haystack/utils.py,sha256=sKRoPhzZWFw1NPsYwCockafzMBCCq3lGOrndbNE_C3M,609
|
|
12
12
|
idun_agent_engine/agent/langgraph/__init__.py,sha256=CoBdkp9P4livdy5B0bvj9o7ftoqKmXEr9cZv4TZLncs,107
|
|
13
|
-
idun_agent_engine/agent/langgraph/langgraph.py,sha256=
|
|
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
|
-
idun_agent_engine/core/app_factory.py,sha256=
|
|
16
|
-
idun_agent_engine/core/config_builder.py,sha256=
|
|
15
|
+
idun_agent_engine/core/app_factory.py,sha256=2w4o7wV8FQCZdBTk3W7cS0vnmpUM_TdAmphFKHbL31w,2597
|
|
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
|
|
20
20
|
idun_agent_engine/guardrails/base.py,sha256=rvi7gcuKK8-3GtGicWzMWYsKKv0g3LjGBI-FycxgKVU,814
|
|
21
|
-
idun_agent_engine/guardrails/guardrails_hub/__init__.py,sha256=
|
|
21
|
+
idun_agent_engine/guardrails/guardrails_hub/__init__.py,sha256=MwWdgrM1dNzKwuS9ZEFw5Cin91JXh2PYlMma8yZFO7o,123
|
|
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
|
-
idun_agent_engine/mcp/__init__.py,sha256=
|
|
25
|
-
idun_agent_engine/mcp/helpers.py,sha256=
|
|
26
|
-
idun_agent_engine/mcp/registry.py,sha256=
|
|
24
|
+
idun_agent_engine/mcp/__init__.py,sha256=ygChpEQ4MzMpEifW3szi5kNiLIMhOhJEtqxy0nmewDU,501
|
|
25
|
+
idun_agent_engine/mcp/helpers.py,sha256=b345RHXgeZ15a4gfg8sUJ3Ke7Iwke6FR1RqDRfRUB0c,6589
|
|
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
|
|
29
29
|
idun_agent_engine/observability/gcp_logging/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
@@ -38,24 +38,52 @@ idun_agent_engine/observability/phoenix_local/__init__.py,sha256=m9dIw1GWGKAW4wP
|
|
|
38
38
|
idun_agent_engine/observability/phoenix_local/phoenix_local_handler.py,sha256=wjOZuMpAxdD5D33rzxycNEzFMunETpPnYjiHjbjz5GA,4252
|
|
39
39
|
idun_agent_engine/server/__init__.py,sha256=WaFektUsy37bNg2niAUy_TykzStukgWPnxC-t49CEwo,177
|
|
40
40
|
idun_agent_engine/server/dependencies.py,sha256=MVH8STOQ8wu-iYE_28y5dvw5FGT5PX0uQl0ldkpxw6Y,2080
|
|
41
|
-
idun_agent_engine/server/lifespan.py,sha256=
|
|
41
|
+
idun_agent_engine/server/lifespan.py,sha256=pTPZ36R4jlx1jq249kpj4DEe-opIGYiRNUHncKlnuGs,4670
|
|
42
42
|
idun_agent_engine/server/server_config.py,sha256=RYA7Y0c5aRw_WXaX8svFUIEtTPqzn3o-WQRm2p52C6g,213
|
|
43
43
|
idun_agent_engine/server/routers/__init__.py,sha256=BgNzSVvHtGPGn5zhXhomwpKlDYBkeFi7xCbdcWVOgc8,102
|
|
44
44
|
idun_agent_engine/server/routers/agent.py,sha256=qLaVRKgMIu-YfOi-tPEzLNRZKZ4DaZEQ8KQ-4HrWbbY,9194
|
|
45
45
|
idun_agent_engine/server/routers/agui.py,sha256=Z1G4fuo57MazQWfp7ao8QZ1or2H9BXLS_JB1nFPXAkE,1891
|
|
46
46
|
idun_agent_engine/server/routers/base.py,sha256=wICOXCokCIRjmHuDPDTWqeXqOVPes1CtDtiR_HvtsF0,3756
|
|
47
|
+
idun_agent_engine/telemetry/__init__.py,sha256=oYmmgUYvuwM-eV1qBeTgy6HoG6H3LC_S4fMH04QiMWY,519
|
|
48
|
+
idun_agent_engine/telemetry/config.py,sha256=APSmZWocwSqB1xSxoZkJrSTZnWlBiQdif4whdXi8uBE,845
|
|
49
|
+
idun_agent_engine/telemetry/telemetry.py,sha256=g14ouZnSIV85A58HeAH5IlJ_IDKO_uYo7kFbWRo5PpI,7319
|
|
47
50
|
idun_agent_engine/templates/__init__.py,sha256=xxbJZXaX6VEm_UrqzAOQcuujpEji5yqYzwQfwiqig8o,31
|
|
48
51
|
idun_agent_engine/templates/correction.py,sha256=qApH4W99K31maxNrGf0hPVe_Wd4xjYjJrEKlu7PbRpw,1823
|
|
49
52
|
idun_agent_engine/templates/deep_research.py,sha256=j4WypBkBz7V3EG-U8vawfNXDNhcCf2QiEK0veI4M68s,1077
|
|
50
53
|
idun_agent_engine/templates/translation.py,sha256=vjp1yEyhDMFO4nEbq5WG7LAA7nLrhVAjznOkV7ob_Ss,2149
|
|
51
54
|
idun_platform_cli/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
52
|
-
idun_platform_cli/main.py,sha256=
|
|
55
|
+
idun_platform_cli/main.py,sha256=B7b1x0kgfuiAWGmSCFJeu_zkWiodJjOGu0nWuNAWM-k,299
|
|
56
|
+
idun_platform_cli/telemetry.py,sha256=mLTO8717ckmglm_oSl1xFxomk-eqwqrCU9Nl1uq27Dg,1711
|
|
53
57
|
idun_platform_cli/groups/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
58
|
+
idun_platform_cli/groups/init.py,sha256=gBWU7tQ0v9aaPNSQXorKWrOkUc5YgJU06pzDC-qG97U,769
|
|
54
59
|
idun_platform_cli/groups/agent/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
55
60
|
idun_platform_cli/groups/agent/main.py,sha256=QMGQi3JZ76SeFI3miIjVWpMt0L-hGz5FwxtTPQX4-Uw,301
|
|
56
|
-
idun_platform_cli/groups/agent/package.py,sha256=
|
|
57
|
-
idun_platform_cli/groups/agent/serve.py,sha256=
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
61
|
+
idun_platform_cli/groups/agent/package.py,sha256=JeoQBZ_egkeKhQhB-FuGGrY1T1VG4f4ixuhjt0mDygE,2615
|
|
62
|
+
idun_platform_cli/groups/agent/serve.py,sha256=ujCmJ3JsrjHkXvNwyB7V4poAaTxMQAPcIbRPDVybRQo,3947
|
|
63
|
+
idun_platform_cli/tui/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
64
|
+
idun_platform_cli/tui/main.py,sha256=1gFEdbynBfiBLrZrKvNJN16Uc_3DOJl1spexRz38Q-E,3080
|
|
65
|
+
idun_platform_cli/tui/css/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
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
|
|
68
|
+
idun_platform_cli/tui/schemas/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
69
|
+
idun_platform_cli/tui/schemas/create_agent.py,sha256=2jsZ5v1sZLKmypgimdVoeVjd-wOylTE3IUYPw63eb8Y,1512
|
|
70
|
+
idun_platform_cli/tui/screens/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
71
|
+
idun_platform_cli/tui/screens/create_agent.py,sha256=3Yav2gvJhh0el4BTLuYzYELrHWuKDBnNnNHlRIBUEJE,23881
|
|
72
|
+
idun_platform_cli/tui/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
73
|
+
idun_platform_cli/tui/utils/config.py,sha256=AEgjgnNkCtQwuGxI8lclteunKZXvn_TMx0eBx7uJWto,7286
|
|
74
|
+
idun_platform_cli/tui/validators/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
75
|
+
idun_platform_cli/tui/validators/guardrails.py,sha256=l6TJKxjpr8Nktwndh6C7Juz4oY-bqpg295jtYTKHuQ8,3537
|
|
76
|
+
idun_platform_cli/tui/validators/mcps.py,sha256=oDxbxt7qOzsW8yjd_fwBnlDPOSxPqCXqbF5q8eEYRVQ,2852
|
|
77
|
+
idun_platform_cli/tui/validators/observability.py,sha256=IWNuJg42eZUxjV-7v12kms7DpJsAs3FSSD5zLU5eKUc,2436
|
|
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
|
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import sys
|
|
2
|
+
|
|
3
|
+
import click
|
|
4
|
+
|
|
5
|
+
from idun_platform_cli.telemetry import track_command
|
|
6
|
+
from idun_platform_cli.tui.main import IdunApp
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
@click.command("init")
|
|
10
|
+
@track_command("init")
|
|
11
|
+
def init_command() -> None:
|
|
12
|
+
"""Starts a terminal user interface that guides you through configuring and managing Idun agents."""
|
|
13
|
+
try:
|
|
14
|
+
app = IdunApp()
|
|
15
|
+
app.run()
|
|
16
|
+
except ImportError as e:
|
|
17
|
+
print(f"[ERROR]: Missing required dependency for TUI: {e}")
|
|
18
|
+
print("[INFO]: Make sure 'textual' is installed in your environment")
|
|
19
|
+
sys.exit(1)
|
|
20
|
+
except KeyboardInterrupt:
|
|
21
|
+
print("\n[INFO]: Initialization cancelled by user")
|
|
22
|
+
sys.exit(0)
|
|
23
|
+
except Exception as e:
|
|
24
|
+
print(f"[ERROR]: Failed to launch the Idun TUI: {e}")
|
|
25
|
+
sys.exit(1)
|
idun_platform_cli/main.py
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import click
|
|
2
|
+
|
|
2
3
|
from idun_platform_cli.groups.agent.main import agent
|
|
4
|
+
from idun_platform_cli.groups.init import init_command
|
|
3
5
|
|
|
4
6
|
|
|
5
7
|
@click.group()
|
|
@@ -9,6 +11,7 @@ def cli():
|
|
|
9
11
|
|
|
10
12
|
|
|
11
13
|
cli.add_command(agent)
|
|
14
|
+
cli.add_command(init_command, name="init")
|
|
12
15
|
|
|
13
16
|
if __name__ == "__main__":
|
|
14
17
|
cli()
|
|
@@ -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
|
|
File without changes
|
|
File without changes
|