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.
- idun_agent_engine/_version.py +1 -1
- idun_agent_engine/agent/adk/adk.py +5 -2
- idun_agent_engine/core/config_builder.py +7 -0
- idun_agent_engine/mcp/helpers.py +44 -2
- {idun_agent_engine-0.4.0.dist-info → idun_agent_engine-0.4.1.dist-info}/METADATA +2 -2
- {idun_agent_engine-0.4.0.dist-info → idun_agent_engine-0.4.1.dist-info}/RECORD +26 -23
- idun_platform_cli/groups/agent/package.py +3 -0
- idun_platform_cli/groups/agent/serve.py +2 -0
- idun_platform_cli/groups/init.py +2 -0
- idun_platform_cli/telemetry.py +54 -0
- idun_platform_cli/tui/css/create_agent.py +137 -14
- idun_platform_cli/tui/css/main.py +7 -10
- idun_platform_cli/tui/main.py +3 -3
- idun_platform_cli/tui/screens/create_agent.py +158 -18
- idun_platform_cli/tui/utils/config.py +22 -1
- idun_platform_cli/tui/validators/guardrails.py +15 -3
- idun_platform_cli/tui/widgets/__init__.py +8 -4
- idun_platform_cli/tui/widgets/chat_widget.py +153 -0
- idun_platform_cli/tui/widgets/guardrails_widget.py +9 -1
- idun_platform_cli/tui/widgets/identity_widget.py +28 -10
- idun_platform_cli/tui/widgets/mcps_widget.py +2 -2
- idun_platform_cli/tui/widgets/memory_widget.py +195 -0
- idun_platform_cli/tui/widgets/observability_widget.py +11 -13
- idun_platform_cli/tui/widgets/serve_widget.py +51 -47
- {idun_agent_engine-0.4.0.dist-info → idun_agent_engine-0.4.1.dist-info}/WHEEL +0 -0
- {idun_agent_engine-0.4.0.dist-info → idun_agent_engine-0.4.1.dist-info}/entry_points.txt +0 -0
|
@@ -25,6 +25,7 @@ class IdentityWidget(Widget):
|
|
|
25
25
|
def __init__(self, *args, **kwargs):
|
|
26
26
|
super().__init__(*args, **kwargs)
|
|
27
27
|
self.selected_file_path = ""
|
|
28
|
+
self.selected_variable = ""
|
|
28
29
|
|
|
29
30
|
def compose(self) -> ComposeResult:
|
|
30
31
|
agent_info_section = Horizontal(
|
|
@@ -115,7 +116,7 @@ class IdentityWidget(Widget):
|
|
|
115
116
|
import ast
|
|
116
117
|
|
|
117
118
|
try:
|
|
118
|
-
with open(file_path
|
|
119
|
+
with open(file_path) as f:
|
|
119
120
|
tree = ast.parse(f.read())
|
|
120
121
|
|
|
121
122
|
variables = []
|
|
@@ -127,21 +128,28 @@ class IdentityWidget(Widget):
|
|
|
127
128
|
|
|
128
129
|
var_list = self.query_one("#variable_list", OptionList)
|
|
129
130
|
var_list.clear_options()
|
|
131
|
+
self.selected_variable = ""
|
|
130
132
|
|
|
131
133
|
if variables:
|
|
132
134
|
for var in variables:
|
|
133
135
|
var_list.add_option(Option(var, id=var))
|
|
134
|
-
var_list.highlighted = 0
|
|
135
136
|
else:
|
|
136
137
|
var_list.add_option(Option("No variables found", id="none"))
|
|
137
138
|
|
|
138
|
-
except Exception
|
|
139
|
-
self.app.notify(
|
|
139
|
+
except Exception:
|
|
140
|
+
self.app.notify(
|
|
141
|
+
"Error parsing file. Make sure it's a valid Python file.",
|
|
142
|
+
severity="error",
|
|
143
|
+
)
|
|
140
144
|
|
|
141
145
|
def on_option_list_option_highlighted(
|
|
142
146
|
self, event: OptionList.OptionHighlighted
|
|
143
147
|
) -> None:
|
|
144
148
|
if event.option_list.id == "variable_list":
|
|
149
|
+
var_list = self.query_one("#variable_list", OptionList)
|
|
150
|
+
if var_list.highlighted is not None:
|
|
151
|
+
variable_option = var_list.get_option_at_index(var_list.highlighted)
|
|
152
|
+
self.selected_variable = str(variable_option.id)
|
|
145
153
|
self._update_full_definition()
|
|
146
154
|
elif event.option_list.id == "framework_select":
|
|
147
155
|
self._update_section_labels()
|
|
@@ -149,7 +157,9 @@ class IdentityWidget(Widget):
|
|
|
149
157
|
def _update_section_labels(self) -> None:
|
|
150
158
|
framework_select = self.query_one("#framework_select", OptionList)
|
|
151
159
|
if framework_select.highlighted is not None:
|
|
152
|
-
framework_option = framework_select.get_option_at_index(
|
|
160
|
+
framework_option = framework_select.get_option_at_index(
|
|
161
|
+
framework_select.highlighted
|
|
162
|
+
)
|
|
153
163
|
framework = str(framework_option.id)
|
|
154
164
|
|
|
155
165
|
graph_section = self.query_one(".graph-definition-section", Vertical)
|
|
@@ -192,14 +202,22 @@ class IdentityWidget(Widget):
|
|
|
192
202
|
self.app.notify("Agent name and port are required!", severity="error")
|
|
193
203
|
return False
|
|
194
204
|
|
|
195
|
-
|
|
196
|
-
|
|
205
|
+
if not self.selected_file_path:
|
|
206
|
+
self.query_one("#identity_error", Static).update(
|
|
207
|
+
"Please select a Python file"
|
|
208
|
+
)
|
|
209
|
+
self.app.notify(
|
|
210
|
+
"Graph definition incomplete! Select a file.", severity="error"
|
|
211
|
+
)
|
|
212
|
+
return False
|
|
197
213
|
|
|
198
|
-
if not self.
|
|
214
|
+
if not self.selected_variable or self.selected_variable == "none":
|
|
199
215
|
self.query_one("#identity_error", Static).update(
|
|
200
|
-
"Please select a
|
|
216
|
+
"Please select a variable from the list"
|
|
217
|
+
)
|
|
218
|
+
self.app.notify(
|
|
219
|
+
"Graph definition incomplete! Select a variable.", severity="error"
|
|
201
220
|
)
|
|
202
|
-
self.app.notify("Graph definition incomplete!", severity="error")
|
|
203
221
|
return False
|
|
204
222
|
|
|
205
223
|
return True
|
|
@@ -223,8 +223,8 @@ class MCPsWidget(Widget):
|
|
|
223
223
|
|
|
224
224
|
servers_data.append(server_config)
|
|
225
225
|
|
|
226
|
-
except Exception
|
|
227
|
-
self.app.notify(f"Error reading server {server_id + 1}:
|
|
226
|
+
except Exception:
|
|
227
|
+
self.app.notify(f"Error reading MCP server {server_id + 1}: check your configuration.", severity="error")
|
|
228
228
|
return None
|
|
229
229
|
|
|
230
230
|
return servers_data
|
|
@@ -0,0 +1,195 @@
|
|
|
1
|
+
"""Memory and checkpoint configuration widget."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from typing import TYPE_CHECKING
|
|
6
|
+
|
|
7
|
+
from pydantic import ValidationError
|
|
8
|
+
from textual.app import ComposeResult
|
|
9
|
+
from textual.containers import Horizontal, Vertical
|
|
10
|
+
from textual.css.query import NoMatches
|
|
11
|
+
from textual.reactive import reactive
|
|
12
|
+
from textual.widget import Widget
|
|
13
|
+
from textual.widgets import Input, RadioButton, RadioSet, Static
|
|
14
|
+
|
|
15
|
+
if TYPE_CHECKING:
|
|
16
|
+
from idun_agent_schema.engine.langgraph import CheckpointConfig
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
class MemoryWidget(Widget):
|
|
20
|
+
selected_type = reactive("memory")
|
|
21
|
+
|
|
22
|
+
def compose(self) -> ComposeResult:
|
|
23
|
+
main_section = Vertical(classes="memory-main")
|
|
24
|
+
main_section.border_title = "Checkpoint Configuration"
|
|
25
|
+
|
|
26
|
+
with main_section, Horizontal(classes="field-row framework-row"):
|
|
27
|
+
yield Static("Type:", classes="field-label")
|
|
28
|
+
with RadioSet(id="checkpoint_type_select"):
|
|
29
|
+
yield RadioButton("In-Memory", id="memory", value=True)
|
|
30
|
+
yield RadioButton("SQLite", id="sqlite")
|
|
31
|
+
yield RadioButton("PostgreSQL", id="postgres")
|
|
32
|
+
|
|
33
|
+
config_container = Vertical(
|
|
34
|
+
classes="checkpoint-config-container",
|
|
35
|
+
id="checkpoint_config",
|
|
36
|
+
)
|
|
37
|
+
yield config_container
|
|
38
|
+
|
|
39
|
+
def on_mount(self) -> None:
|
|
40
|
+
self._update_checkpoint_config()
|
|
41
|
+
|
|
42
|
+
def on_radio_set_changed(self, event: RadioSet.Changed) -> None:
|
|
43
|
+
if event.radio_set.id == "checkpoint_type_select":
|
|
44
|
+
self.selected_type = str(event.pressed.id)
|
|
45
|
+
self._update_checkpoint_config()
|
|
46
|
+
|
|
47
|
+
def _update_checkpoint_config(self) -> None:
|
|
48
|
+
try:
|
|
49
|
+
config_container = self.query_one("#checkpoint_config", Vertical)
|
|
50
|
+
config_container.remove_children()
|
|
51
|
+
|
|
52
|
+
if self.selected_type == "memory":
|
|
53
|
+
pass
|
|
54
|
+
elif self.selected_type == "sqlite":
|
|
55
|
+
self._render_sqlite_config(config_container)
|
|
56
|
+
elif self.selected_type == "postgres":
|
|
57
|
+
self._render_postgres_config(config_container)
|
|
58
|
+
except Exception:
|
|
59
|
+
pass
|
|
60
|
+
|
|
61
|
+
def _render_sqlite_config(self, container: Vertical) -> None:
|
|
62
|
+
config_section = Vertical(
|
|
63
|
+
Horizontal(
|
|
64
|
+
Static("DB URL:", classes="field-label"),
|
|
65
|
+
Input(
|
|
66
|
+
placeholder="sqlite:///./checkpoints.db",
|
|
67
|
+
id="sqlite_db_url",
|
|
68
|
+
classes="field-input",
|
|
69
|
+
),
|
|
70
|
+
classes="field-row",
|
|
71
|
+
),
|
|
72
|
+
classes="checkpoint-fields-section",
|
|
73
|
+
)
|
|
74
|
+
config_section.border_title = "SQLite Configuration"
|
|
75
|
+
container.mount(config_section)
|
|
76
|
+
|
|
77
|
+
def _render_postgres_config(self, container: Vertical) -> None:
|
|
78
|
+
config_section = Vertical(
|
|
79
|
+
Horizontal(
|
|
80
|
+
Static("DB URL:", classes="field-label"),
|
|
81
|
+
Input(
|
|
82
|
+
placeholder="postgresql://user:pass@localhost:5432/db",
|
|
83
|
+
id="postgres_db_url",
|
|
84
|
+
classes="field-input",
|
|
85
|
+
),
|
|
86
|
+
classes="field-row",
|
|
87
|
+
),
|
|
88
|
+
classes="checkpoint-fields-section",
|
|
89
|
+
)
|
|
90
|
+
config_section.border_title = "PostgreSQL Configuration"
|
|
91
|
+
container.mount(config_section)
|
|
92
|
+
|
|
93
|
+
def get_data(self) -> CheckpointConfig | None:
|
|
94
|
+
from idun_agent_schema.engine.langgraph import (
|
|
95
|
+
CheckpointConfig,
|
|
96
|
+
InMemoryCheckpointConfig,
|
|
97
|
+
PostgresCheckpointConfig,
|
|
98
|
+
SqliteCheckpointConfig,
|
|
99
|
+
)
|
|
100
|
+
|
|
101
|
+
try:
|
|
102
|
+
radio_set = self.query_one("#checkpoint_type_select", RadioSet)
|
|
103
|
+
|
|
104
|
+
checkpoint_type = "memory"
|
|
105
|
+
if radio_set.pressed_button:
|
|
106
|
+
checkpoint_type = str(radio_set.pressed_button.id)
|
|
107
|
+
|
|
108
|
+
if checkpoint_type == "memory":
|
|
109
|
+
return InMemoryCheckpointConfig(type="memory")
|
|
110
|
+
|
|
111
|
+
elif checkpoint_type == "sqlite":
|
|
112
|
+
try:
|
|
113
|
+
db_url_input = self.query_one("#sqlite_db_url", Input)
|
|
114
|
+
db_url = db_url_input.value.strip()
|
|
115
|
+
except NoMatches:
|
|
116
|
+
self.app.notify(
|
|
117
|
+
"Configuration error. Please reselect checkpoint type.",
|
|
118
|
+
severity="error",
|
|
119
|
+
)
|
|
120
|
+
return None
|
|
121
|
+
|
|
122
|
+
if not db_url:
|
|
123
|
+
self.app.notify(
|
|
124
|
+
"SQLite DB URL is required",
|
|
125
|
+
severity="error",
|
|
126
|
+
)
|
|
127
|
+
return None
|
|
128
|
+
|
|
129
|
+
if not db_url.startswith("sqlite:///"):
|
|
130
|
+
self.app.notify(
|
|
131
|
+
"SQLite URL must start with 'sqlite:///'",
|
|
132
|
+
severity="error",
|
|
133
|
+
)
|
|
134
|
+
return None
|
|
135
|
+
|
|
136
|
+
try:
|
|
137
|
+
return SqliteCheckpointConfig(type="sqlite", db_url=db_url)
|
|
138
|
+
except ValidationError:
|
|
139
|
+
self.app.notify(
|
|
140
|
+
"Invalid SQLite configuration. Check your URL format.",
|
|
141
|
+
severity="error",
|
|
142
|
+
)
|
|
143
|
+
return None
|
|
144
|
+
|
|
145
|
+
elif checkpoint_type == "postgres":
|
|
146
|
+
try:
|
|
147
|
+
db_url_input = self.query_one("#postgres_db_url", Input)
|
|
148
|
+
db_url = db_url_input.value.strip()
|
|
149
|
+
except NoMatches:
|
|
150
|
+
self.app.notify(
|
|
151
|
+
"Configuration error. Please reselect checkpoint type.",
|
|
152
|
+
severity="error",
|
|
153
|
+
)
|
|
154
|
+
return None
|
|
155
|
+
|
|
156
|
+
if not db_url:
|
|
157
|
+
self.app.notify(
|
|
158
|
+
"PostgreSQL DB URL is required",
|
|
159
|
+
severity="error",
|
|
160
|
+
)
|
|
161
|
+
return None
|
|
162
|
+
|
|
163
|
+
if not (
|
|
164
|
+
db_url.startswith("postgresql://")
|
|
165
|
+
or db_url.startswith("postgres://")
|
|
166
|
+
):
|
|
167
|
+
self.app.notify(
|
|
168
|
+
"PostgreSQL URL must start with 'postgresql://' or 'postgres://'",
|
|
169
|
+
severity="error",
|
|
170
|
+
)
|
|
171
|
+
return None
|
|
172
|
+
|
|
173
|
+
try:
|
|
174
|
+
return PostgresCheckpointConfig(type="postgres", db_url=db_url)
|
|
175
|
+
except ValidationError:
|
|
176
|
+
self.app.notify(
|
|
177
|
+
"Invalid PostgreSQL configuration. Check your URL format.",
|
|
178
|
+
severity="error",
|
|
179
|
+
)
|
|
180
|
+
return None
|
|
181
|
+
|
|
182
|
+
except NoMatches:
|
|
183
|
+
self.app.notify(
|
|
184
|
+
"Error reading checkpoint configuration",
|
|
185
|
+
severity="error",
|
|
186
|
+
)
|
|
187
|
+
return None
|
|
188
|
+
except Exception:
|
|
189
|
+
self.app.notify(
|
|
190
|
+
"Error validating checkpoint configuration",
|
|
191
|
+
severity="error",
|
|
192
|
+
)
|
|
193
|
+
return None
|
|
194
|
+
|
|
195
|
+
return None
|
|
@@ -4,7 +4,7 @@ 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,
|
|
7
|
+
from textual.widgets import Static, Input, RadioSet, RadioButton, Switch
|
|
8
8
|
from textual.widget import Widget
|
|
9
9
|
from textual.reactive import reactive
|
|
10
10
|
|
|
@@ -12,21 +12,18 @@ from idun_platform_cli.tui.validators.observability import validate_observabilit
|
|
|
12
12
|
|
|
13
13
|
|
|
14
14
|
class ObservabilityWidget(Widget):
|
|
15
|
-
selected_provider = reactive("
|
|
15
|
+
selected_provider = reactive("OFF")
|
|
16
16
|
|
|
17
17
|
def compose(self) -> ComposeResult:
|
|
18
18
|
main_section = Vertical(classes="observability-main")
|
|
19
19
|
main_section.border_title = "Observability"
|
|
20
20
|
|
|
21
21
|
with main_section:
|
|
22
|
-
with Horizontal(classes="field-row"):
|
|
23
|
-
yield Static("Enabled:", classes="field-label")
|
|
24
|
-
yield Switch(value=True, id="enabled_toggle")
|
|
25
|
-
|
|
26
22
|
with Horizontal(classes="field-row framework-row"):
|
|
27
23
|
yield Static("Provider:", classes="field-label")
|
|
28
24
|
with RadioSet(id="provider_select"):
|
|
29
|
-
yield RadioButton("
|
|
25
|
+
yield RadioButton("Off", id="OFF", value=True)
|
|
26
|
+
yield RadioButton("LANGFUSE", id="LANGFUSE")
|
|
30
27
|
yield RadioButton("PHOENIX", id="PHOENIX")
|
|
31
28
|
yield RadioButton("GCP LOGGING", id="GCP_LOGGING")
|
|
32
29
|
yield RadioButton("GCP TRACE", id="GCP_TRACE")
|
|
@@ -49,7 +46,9 @@ class ObservabilityWidget(Widget):
|
|
|
49
46
|
config_container = self.query_one("#provider_config", Vertical)
|
|
50
47
|
config_container.remove_children()
|
|
51
48
|
|
|
52
|
-
if self.selected_provider == "
|
|
49
|
+
if self.selected_provider == "OFF":
|
|
50
|
+
pass
|
|
51
|
+
elif self.selected_provider == "LANGFUSE":
|
|
53
52
|
self._render_langfuse_config(config_container)
|
|
54
53
|
elif self.selected_provider == "PHOENIX":
|
|
55
54
|
self._render_phoenix_config(config_container)
|
|
@@ -305,16 +304,15 @@ class ObservabilityWidget(Widget):
|
|
|
305
304
|
def get_data(self) -> ObservabilityConfig | None:
|
|
306
305
|
radio_set = self.query_one("#provider_select", RadioSet)
|
|
307
306
|
|
|
308
|
-
provider =
|
|
307
|
+
provider = "OFF"
|
|
309
308
|
if radio_set.pressed_button:
|
|
310
309
|
provider = str(radio_set.pressed_button.id)
|
|
311
310
|
|
|
312
|
-
|
|
313
|
-
config = {}
|
|
314
|
-
|
|
315
|
-
if not enabled:
|
|
311
|
+
if provider == "OFF":
|
|
316
312
|
return None
|
|
317
313
|
|
|
314
|
+
config = {}
|
|
315
|
+
|
|
318
316
|
match provider:
|
|
319
317
|
case "LANGFUSE":
|
|
320
318
|
config = {
|
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
"""Serve configuration widget."""
|
|
2
2
|
|
|
3
|
+
from typing import Any
|
|
4
|
+
|
|
5
|
+
from rich.syntax import Syntax
|
|
3
6
|
from textual.app import ComposeResult
|
|
4
|
-
from textual.containers import Vertical
|
|
7
|
+
from textual.containers import Horizontal, Vertical
|
|
5
8
|
from textual.widget import Widget
|
|
6
9
|
from textual.widgets import Button, RichLog, Static
|
|
7
10
|
|
|
@@ -14,23 +17,20 @@ class ServeWidget(Widget):
|
|
|
14
17
|
self.shell_id = None
|
|
15
18
|
|
|
16
19
|
def compose(self) -> ComposeResult:
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
with summary_container:
|
|
21
|
-
agent_box = Vertical(classes="summary-box", id="agent_summary")
|
|
22
|
-
agent_box.border_title = "Agent"
|
|
23
|
-
with agent_box:
|
|
24
|
-
yield Static("Loading...", id="agent_summary_text")
|
|
20
|
+
yaml_container = Vertical(classes="serve-yaml-display")
|
|
21
|
+
yaml_container.border_title = "Agent Configuration"
|
|
25
22
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
with obs_box:
|
|
29
|
-
yield Static("Loading...", id="obs_summary_text")
|
|
23
|
+
with yaml_container:
|
|
24
|
+
yield Static("Loading configuration...", id="yaml_content")
|
|
30
25
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
26
|
+
button_container = Horizontal(classes="serve-button-container")
|
|
27
|
+
with button_container:
|
|
28
|
+
yield Button(
|
|
29
|
+
"Save and Exit", id="save_exit_button", classes="validate-run-btn"
|
|
30
|
+
)
|
|
31
|
+
yield Button(
|
|
32
|
+
"Save and Run", id="save_run_button", classes="validate-run-btn"
|
|
33
|
+
)
|
|
34
34
|
|
|
35
35
|
logs_container = Vertical(classes="serve-logs", id="logs_container")
|
|
36
36
|
logs_container.border_title = "Server Logs"
|
|
@@ -40,37 +40,41 @@ class ServeWidget(Widget):
|
|
|
40
40
|
|
|
41
41
|
def load_config(self, config: dict) -> None:
|
|
42
42
|
self.config_data = config
|
|
43
|
-
self.
|
|
44
|
-
|
|
45
|
-
def
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
43
|
+
self._update_yaml_display()
|
|
44
|
+
|
|
45
|
+
def _update_yaml_display(self) -> None:
|
|
46
|
+
import yaml
|
|
47
|
+
|
|
48
|
+
if not self.config_data:
|
|
49
|
+
self.query_one("#yaml_content", Static).update(
|
|
50
|
+
"[yellow]No configuration loaded yet.[/yellow]\n"
|
|
51
|
+
"[dim]Complete the previous sections to generate configuration.[/dim]"
|
|
52
|
+
)
|
|
53
|
+
return
|
|
54
|
+
|
|
55
|
+
try:
|
|
56
|
+
yaml_string = yaml.dump(
|
|
57
|
+
self.config_data,
|
|
58
|
+
default_flow_style=False,
|
|
59
|
+
sort_keys=False,
|
|
60
|
+
allow_unicode=True
|
|
61
|
+
)
|
|
62
|
+
|
|
63
|
+
syntax = Syntax(
|
|
64
|
+
yaml_string,
|
|
65
|
+
"yaml",
|
|
66
|
+
theme="monokai",
|
|
67
|
+
line_numbers=True,
|
|
68
|
+
word_wrap=False,
|
|
69
|
+
indent_guides=True,
|
|
70
|
+
background_color="default"
|
|
71
|
+
)
|
|
72
|
+
|
|
73
|
+
self.query_one("#yaml_content", Static).update(syntax)
|
|
74
|
+
|
|
75
|
+
except Exception as e:
|
|
76
|
+
error_msg = f"[red]Error displaying configuration:[/red]\n{str(e)}"
|
|
77
|
+
self.query_one("#yaml_content", Static).update(error_msg)
|
|
74
78
|
|
|
75
79
|
def get_agent_name(self) -> str:
|
|
76
80
|
agent_info = self.config_data.get("agent", {})
|
|
File without changes
|
|
File without changes
|