Skip to content

Commit b1506e6

Browse files
authored
Fix app workflows list (#458)
1 parent 0d1e9bf commit b1506e6

File tree

2 files changed

+47
-26
lines changed

2 files changed

+47
-26
lines changed

src/mcp_agent/cli/cloud/commands/app/workflows/main.py

Lines changed: 27 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,9 @@
55

66
import typer
77
from rich.console import Group
8-
from rich.padding import Padding
98
from rich.panel import Panel
109
from rich.prompt import Prompt
1110
from rich.syntax import Syntax
12-
from rich.table import Table
1311
from rich.text import Text
1412

1513
from mcp_agent.cli.auth import load_api_key_credentials
@@ -248,16 +246,12 @@ def get_start_time(run: WorkflowRun):
248246
reverse=True,
249247
)
250248

251-
table = Table(title="Workflow Runs", show_lines=False, border_style="blue")
252-
table.add_column("Name", style="white", overflow="fold")
253-
table.add_column("Workflow ID", style="bold cyan", no_wrap=True)
254-
table.add_column("Run ID", style="blue", overflow="fold")
255-
table.add_column("Status", overflow="fold")
256-
table.add_column("Start Time", style="magenta", overflow="fold")
257-
table.add_column("End Time", style="yellow", overflow="fold")
249+
console.print(f"\n[bold blue] Workflow Runs ({len(sorted_runs)})[/bold blue]")
250+
251+
for i, run in enumerate(sorted_runs):
252+
if i > 0:
253+
console.print()
258254

259-
for idx, run in enumerate(sorted_runs):
260-
is_last_row = idx == len(sorted_runs) - 1
261255
start = getattr(run.temporal, "start_time", None)
262256
start_str = (
263257
datetime.fromtimestamp(start).strftime("%Y-%m-%d %H:%M:%S")
@@ -274,22 +268,31 @@ def get_start_time(run: WorkflowRun):
274268

275269
status = run.status.lower()
276270
if status == "completed":
277-
status_text = f"[green]{status}[/green]"
278-
elif status == "error":
279-
status_text = f"[red]{status}[/red]"
271+
status_text = f"[green]🟢 {status}[/green]"
272+
elif status == "error" or status == "failed":
273+
status_text = f"[red]🔴 {status}[/red]"
274+
elif status == "running":
275+
status_text = f"[yellow]🔄 {status}[/yellow]"
280276
else:
281-
status_text = status
282-
283-
table.add_row(
284-
run.name or "-",
285-
run.temporal.workflow_id if run.temporal else "N/A",
286-
Padding(run.id, (0, 0, 0 if is_last_row else 1, 0)),
287-
status_text,
288-
start_str,
289-
end_str,
277+
status_text = f"❓ {status}"
278+
279+
console.print(
280+
f"[bold cyan]{run.name or 'Unnamed Workflow'}[/bold cyan] {status_text}"
290281
)
282+
console.print(f" Run ID: {run.id}")
283+
284+
if run.temporal and run.temporal.workflow_id:
285+
console.print(f" Workflow ID: {run.temporal.workflow_id}")
286+
287+
console.print(f" Started: {start_str}")
288+
if end_str != "N/A":
289+
console.print(f" Completed: {end_str}")
291290

292-
console.print(table)
291+
# Show execution time if available
292+
if hasattr(run.temporal, "execution_time") and run.temporal.execution_time:
293+
duration = end - start if (start and end) else None
294+
if duration:
295+
console.print(f" Duration: {duration:.2f}s")
293296

294297
except Exception as e:
295298
print_error(f"Error fetching workflow runs: {str(e)}")

src/mcp_agent/cli/mcp_app/mcp_client.py

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import ast
12
import asyncio
23
import json
34
from contextlib import asynccontextmanager
@@ -62,10 +63,13 @@ class WorkflowRunState(BaseModel):
6263
class WorkflowRunResult(BaseModel):
6364
"""The result of a workflow run."""
6465

66+
kind: str
67+
"""The kind/type of result returned by the workflow run."""
68+
6569
value: str
6670
"""The value returned by the workflow run, if any."""
6771

68-
metadata: dict
72+
metadata: Optional[dict[str, Any]] = None
6973
"""Metadata associated with the workflow run result."""
7074

7175
start_time: Optional[float] = None
@@ -99,6 +103,9 @@ class WorkflowRunTemporal(BaseModel):
99103
close_time: Optional[float] = None
100104
"""The time when the workflow run completed."""
101105

106+
execution_time: Optional[float] = None
107+
"""The total time taken for the workflow run."""
108+
102109

103110
class WorkflowRun(BaseModel):
104111
"""An execution instance of a workflow definition."""
@@ -187,9 +194,20 @@ async def list_workflow_runs(self) -> ListWorkflowRunsResult:
187194
# Assuming the content is a JSON string representing a WorkflowRun item dict
188195
try:
189196
run_data = json.loads(item.text)
197+
if "result" in run_data and isinstance(run_data["result"], str):
198+
try:
199+
# Could be stringified python dict instead of valid JSON
200+
run_data["result"] = ast.literal_eval(run_data["result"])
201+
except (ValueError, SyntaxError) as e:
202+
try:
203+
run_data["result"] = json.loads(run_data["result"])
204+
except json.JSONDecodeError:
205+
raise ValueError(
206+
f"Invalid workflow run result data: {e}"
207+
) from e
190208
runs.append(WorkflowRun(**run_data))
191209
except json.JSONDecodeError as e:
192-
raise ValueError(f"Invalid workflow run data: {e}")
210+
raise ValueError(f"Invalid workflow run data: {e}") from e
193211

194212
return ListWorkflowRunsResult(workflow_runs=runs)
195213

0 commit comments

Comments
 (0)