pyagent-studio 0.1.0__tar.gz
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.
- pyagent_studio-0.1.0/.gitignore +18 -0
- pyagent_studio-0.1.0/PKG-INFO +140 -0
- pyagent_studio-0.1.0/README.md +110 -0
- pyagent_studio-0.1.0/pyproject.toml +43 -0
- pyagent_studio-0.1.0/src/pyagent_studio/__init__.py +14 -0
- pyagent_studio-0.1.0/src/pyagent_studio/app.py +84 -0
- pyagent_studio-0.1.0/src/pyagent_studio/cli.py +30 -0
- pyagent_studio-0.1.0/src/pyagent_studio/py.typed +0 -0
- pyagent_studio-0.1.0/src/pyagent_studio/screens/__init__.py +22 -0
- pyagent_studio-0.1.0/src/pyagent_studio/screens/cost.py +33 -0
- pyagent_studio-0.1.0/src/pyagent_studio/screens/dashboard.py +55 -0
- pyagent_studio-0.1.0/src/pyagent_studio/screens/editor.py +64 -0
- pyagent_studio-0.1.0/src/pyagent_studio/screens/governance.py +77 -0
- pyagent_studio-0.1.0/src/pyagent_studio/screens/graph.py +42 -0
- pyagent_studio-0.1.0/src/pyagent_studio/screens/simulation.py +64 -0
- pyagent_studio-0.1.0/src/pyagent_studio/screens/traces.py +43 -0
- pyagent_studio-0.1.0/src/pyagent_studio/services/__init__.py +13 -0
- pyagent_studio-0.1.0/src/pyagent_studio/services/blueprint_service.py +115 -0
- pyagent_studio-0.1.0/src/pyagent_studio/services/governance_service.py +105 -0
- pyagent_studio-0.1.0/src/pyagent_studio/services/simulation_service.py +109 -0
- pyagent_studio-0.1.0/src/pyagent_studio/services/trace_service.py +115 -0
- pyagent_studio-0.1.0/src/pyagent_studio/widgets/__init__.py +23 -0
- pyagent_studio-0.1.0/src/pyagent_studio/widgets/agent_card.py +40 -0
- pyagent_studio-0.1.0/src/pyagent_studio/widgets/blueprint_tree.py +73 -0
- pyagent_studio-0.1.0/src/pyagent_studio/widgets/cost_chart.py +40 -0
- pyagent_studio-0.1.0/src/pyagent_studio/widgets/diff_view.py +50 -0
- pyagent_studio-0.1.0/src/pyagent_studio/widgets/trace_table.py +29 -0
- pyagent_studio-0.1.0/src/pyagent_studio/widgets/validation_log.py +28 -0
- pyagent_studio-0.1.0/tests/__init__.py +0 -0
- pyagent_studio-0.1.0/tests/test_services.py +160 -0
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: pyagent-studio
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Terminal-based interactive workbench for designing, simulating, and debugging agent systems
|
|
5
|
+
Project-URL: Homepage, https://pyagent.org
|
|
6
|
+
Project-URL: Repository, https://github.com/pyagent-core/pyagent
|
|
7
|
+
Project-URL: Documentation, https://pyagent.org
|
|
8
|
+
Author-email: PyAgent Team <team@pyagent.org>
|
|
9
|
+
License: MIT
|
|
10
|
+
Keywords: LLM,TUI,agents,studio,textual,workbench
|
|
11
|
+
Classifier: Development Status :: 3 - Alpha
|
|
12
|
+
Classifier: Intended Audience :: Developers
|
|
13
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
17
|
+
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
|
|
18
|
+
Classifier: Typing :: Typed
|
|
19
|
+
Requires-Python: >=3.11
|
|
20
|
+
Requires-Dist: click>=8.1
|
|
21
|
+
Requires-Dist: pyagent-blueprint>=0.1.0
|
|
22
|
+
Requires-Dist: pyagent-trace>=0.1.0
|
|
23
|
+
Provides-Extra: dev
|
|
24
|
+
Requires-Dist: pytest-asyncio>=0.23; extra == 'dev'
|
|
25
|
+
Requires-Dist: pytest>=8.0; extra == 'dev'
|
|
26
|
+
Requires-Dist: textual-dev>=1.0; extra == 'dev'
|
|
27
|
+
Provides-Extra: tui
|
|
28
|
+
Requires-Dist: textual>=3.0; extra == 'tui'
|
|
29
|
+
Description-Content-Type: text/markdown
|
|
30
|
+
|
|
31
|
+
# pyagent-studio
|
|
32
|
+
|
|
33
|
+
**Terminal-based interactive workbench** for designing, simulating, debugging, and governing multi-agent LLM systems. Built with [Textual](https://textual.textualize.io/) for a rich TUI experience.
|
|
34
|
+
|
|
35
|
+
[](../../LICENSE)
|
|
36
|
+
[](https://www.python.org/downloads/)
|
|
37
|
+
|
|
38
|
+
## Install
|
|
39
|
+
|
|
40
|
+
```bash
|
|
41
|
+
pip install pyagent-studio[tui] # Full TUI (requires textual)
|
|
42
|
+
pip install pyagent-studio # Services only (no TUI)
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
Depends on: `pyagent-blueprint`, `pyagent-trace`, `click`.
|
|
46
|
+
|
|
47
|
+
## Quick Start
|
|
48
|
+
|
|
49
|
+
```bash
|
|
50
|
+
# Launch with a blueprint
|
|
51
|
+
pyagent-studio blueprint.yaml
|
|
52
|
+
|
|
53
|
+
# Or launch and browse discovered blueprints
|
|
54
|
+
pyagent-studio
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
## Screens
|
|
58
|
+
|
|
59
|
+
### Dashboard
|
|
60
|
+
List discovered YAML blueprints, view validation status, agent/workflow counts.
|
|
61
|
+
|
|
62
|
+
```
|
|
63
|
+
┌─────────────────────────────────────────────────────────────┐
|
|
64
|
+
│ PyAgent Studio — Dashboard │
|
|
65
|
+
├─────────────────────────────────────────────────────────────┤
|
|
66
|
+
│ File │ Name │ Agents │ Status │
|
|
67
|
+
│ customer_support.yaml │ customer-support │ 3 │ ✓ Valid │
|
|
68
|
+
│ research_agent.yaml │ research-agent │ 2 │ ✓ Valid │
|
|
69
|
+
└─────────────────────────────────────────────────────────────┘
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
### Editor
|
|
73
|
+
YAML editing with live validation panel showing Pydantic errors as you type.
|
|
74
|
+
|
|
75
|
+
### Graph
|
|
76
|
+
ASCII-rendered workflow DAG showing agents as boxes and edges as pattern connections.
|
|
77
|
+
|
|
78
|
+
### Simulation
|
|
79
|
+
Run blueprints with MockLLM (no API keys needed), stream results with timing and token counts.
|
|
80
|
+
|
|
81
|
+
### Traces
|
|
82
|
+
Browse recorded trace spans from `pyagent-trace` Recorder JSONL files.
|
|
83
|
+
|
|
84
|
+
### Cost
|
|
85
|
+
Cost breakdown tables by pattern, agent, and model with bar chart visualization.
|
|
86
|
+
|
|
87
|
+
### Governance
|
|
88
|
+
Validation issues, compliance scoring (% of checks passing), and semantic diff between blueprint versions.
|
|
89
|
+
|
|
90
|
+
## Key Bindings
|
|
91
|
+
|
|
92
|
+
| Key | Action |
|
|
93
|
+
|-----|--------|
|
|
94
|
+
| `Tab` / `Shift+Tab` | Switch screens |
|
|
95
|
+
| `q` | Quit |
|
|
96
|
+
| `Ctrl+S` | Save blueprint |
|
|
97
|
+
| `Ctrl+V` | Validate |
|
|
98
|
+
| `Ctrl+R` | Render graph |
|
|
99
|
+
| `Ctrl+T` | Run simulation |
|
|
100
|
+
| `Ctrl+D` | Show diff |
|
|
101
|
+
|
|
102
|
+
## Services (Headless API)
|
|
103
|
+
|
|
104
|
+
Use the services layer without the TUI for scripting and CI:
|
|
105
|
+
|
|
106
|
+
```python
|
|
107
|
+
from pyagent_studio import BlueprintService, SimulationService, GovernanceService
|
|
108
|
+
|
|
109
|
+
# Load and validate
|
|
110
|
+
svc = BlueprintService()
|
|
111
|
+
spec = svc.load("blueprint.yaml")
|
|
112
|
+
issues = svc.validate()
|
|
113
|
+
print(svc.summary())
|
|
114
|
+
|
|
115
|
+
# Run simulation
|
|
116
|
+
import asyncio
|
|
117
|
+
sim = SimulationService()
|
|
118
|
+
result = asyncio.run(sim.run(spec, "support", "I can't see my invoice"))
|
|
119
|
+
print(result.output)
|
|
120
|
+
|
|
121
|
+
# Governance
|
|
122
|
+
gov = GovernanceService()
|
|
123
|
+
report = gov.check_compliance(spec)
|
|
124
|
+
print(gov.format_report(report))
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
### TraceService
|
|
128
|
+
|
|
129
|
+
```python
|
|
130
|
+
from pyagent_studio import TraceService
|
|
131
|
+
|
|
132
|
+
traces = TraceService()
|
|
133
|
+
spans = traces.load("traces.jsonl")
|
|
134
|
+
llm_calls = traces.query(event_type="llm_call")
|
|
135
|
+
print(traces.summary())
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
## Full Documentation
|
|
139
|
+
|
|
140
|
+
See [pyagent.dev](https://pyagent.dev) for full API reference and integration guides.
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
# pyagent-studio
|
|
2
|
+
|
|
3
|
+
**Terminal-based interactive workbench** for designing, simulating, debugging, and governing multi-agent LLM systems. Built with [Textual](https://textual.textualize.io/) for a rich TUI experience.
|
|
4
|
+
|
|
5
|
+
[](../../LICENSE)
|
|
6
|
+
[](https://www.python.org/downloads/)
|
|
7
|
+
|
|
8
|
+
## Install
|
|
9
|
+
|
|
10
|
+
```bash
|
|
11
|
+
pip install pyagent-studio[tui] # Full TUI (requires textual)
|
|
12
|
+
pip install pyagent-studio # Services only (no TUI)
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
Depends on: `pyagent-blueprint`, `pyagent-trace`, `click`.
|
|
16
|
+
|
|
17
|
+
## Quick Start
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
# Launch with a blueprint
|
|
21
|
+
pyagent-studio blueprint.yaml
|
|
22
|
+
|
|
23
|
+
# Or launch and browse discovered blueprints
|
|
24
|
+
pyagent-studio
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
## Screens
|
|
28
|
+
|
|
29
|
+
### Dashboard
|
|
30
|
+
List discovered YAML blueprints, view validation status, agent/workflow counts.
|
|
31
|
+
|
|
32
|
+
```
|
|
33
|
+
┌─────────────────────────────────────────────────────────────┐
|
|
34
|
+
│ PyAgent Studio — Dashboard │
|
|
35
|
+
├─────────────────────────────────────────────────────────────┤
|
|
36
|
+
│ File │ Name │ Agents │ Status │
|
|
37
|
+
│ customer_support.yaml │ customer-support │ 3 │ ✓ Valid │
|
|
38
|
+
│ research_agent.yaml │ research-agent │ 2 │ ✓ Valid │
|
|
39
|
+
└─────────────────────────────────────────────────────────────┘
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
### Editor
|
|
43
|
+
YAML editing with live validation panel showing Pydantic errors as you type.
|
|
44
|
+
|
|
45
|
+
### Graph
|
|
46
|
+
ASCII-rendered workflow DAG showing agents as boxes and edges as pattern connections.
|
|
47
|
+
|
|
48
|
+
### Simulation
|
|
49
|
+
Run blueprints with MockLLM (no API keys needed), stream results with timing and token counts.
|
|
50
|
+
|
|
51
|
+
### Traces
|
|
52
|
+
Browse recorded trace spans from `pyagent-trace` Recorder JSONL files.
|
|
53
|
+
|
|
54
|
+
### Cost
|
|
55
|
+
Cost breakdown tables by pattern, agent, and model with bar chart visualization.
|
|
56
|
+
|
|
57
|
+
### Governance
|
|
58
|
+
Validation issues, compliance scoring (% of checks passing), and semantic diff between blueprint versions.
|
|
59
|
+
|
|
60
|
+
## Key Bindings
|
|
61
|
+
|
|
62
|
+
| Key | Action |
|
|
63
|
+
|-----|--------|
|
|
64
|
+
| `Tab` / `Shift+Tab` | Switch screens |
|
|
65
|
+
| `q` | Quit |
|
|
66
|
+
| `Ctrl+S` | Save blueprint |
|
|
67
|
+
| `Ctrl+V` | Validate |
|
|
68
|
+
| `Ctrl+R` | Render graph |
|
|
69
|
+
| `Ctrl+T` | Run simulation |
|
|
70
|
+
| `Ctrl+D` | Show diff |
|
|
71
|
+
|
|
72
|
+
## Services (Headless API)
|
|
73
|
+
|
|
74
|
+
Use the services layer without the TUI for scripting and CI:
|
|
75
|
+
|
|
76
|
+
```python
|
|
77
|
+
from pyagent_studio import BlueprintService, SimulationService, GovernanceService
|
|
78
|
+
|
|
79
|
+
# Load and validate
|
|
80
|
+
svc = BlueprintService()
|
|
81
|
+
spec = svc.load("blueprint.yaml")
|
|
82
|
+
issues = svc.validate()
|
|
83
|
+
print(svc.summary())
|
|
84
|
+
|
|
85
|
+
# Run simulation
|
|
86
|
+
import asyncio
|
|
87
|
+
sim = SimulationService()
|
|
88
|
+
result = asyncio.run(sim.run(spec, "support", "I can't see my invoice"))
|
|
89
|
+
print(result.output)
|
|
90
|
+
|
|
91
|
+
# Governance
|
|
92
|
+
gov = GovernanceService()
|
|
93
|
+
report = gov.check_compliance(spec)
|
|
94
|
+
print(gov.format_report(report))
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
### TraceService
|
|
98
|
+
|
|
99
|
+
```python
|
|
100
|
+
from pyagent_studio import TraceService
|
|
101
|
+
|
|
102
|
+
traces = TraceService()
|
|
103
|
+
spans = traces.load("traces.jsonl")
|
|
104
|
+
llm_calls = traces.query(event_type="llm_call")
|
|
105
|
+
print(traces.summary())
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
## Full Documentation
|
|
109
|
+
|
|
110
|
+
See [pyagent.dev](https://pyagent.dev) for full API reference and integration guides.
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["hatchling"]
|
|
3
|
+
build-backend = "hatchling.build"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "pyagent-studio"
|
|
7
|
+
version = "0.1.0"
|
|
8
|
+
description = "Terminal-based interactive workbench for designing, simulating, and debugging agent systems"
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
requires-python = ">=3.11"
|
|
11
|
+
license = {text = "MIT"}
|
|
12
|
+
authors = [{name = "PyAgent Team", email = "team@pyagent.org"}]
|
|
13
|
+
keywords = ["agents", "TUI", "studio", "LLM", "textual", "workbench"]
|
|
14
|
+
classifiers = [
|
|
15
|
+
"Development Status :: 3 - Alpha",
|
|
16
|
+
"Intended Audience :: Developers",
|
|
17
|
+
"License :: OSI Approved :: MIT License",
|
|
18
|
+
"Programming Language :: Python :: 3.11",
|
|
19
|
+
"Programming Language :: Python :: 3.12",
|
|
20
|
+
"Programming Language :: Python :: 3.13",
|
|
21
|
+
"Topic :: Scientific/Engineering :: Artificial Intelligence",
|
|
22
|
+
"Typing :: Typed",
|
|
23
|
+
]
|
|
24
|
+
dependencies = [
|
|
25
|
+
"pyagent-blueprint>=0.1.0",
|
|
26
|
+
"pyagent-trace>=0.1.0",
|
|
27
|
+
"click>=8.1",
|
|
28
|
+
]
|
|
29
|
+
|
|
30
|
+
[project.urls]
|
|
31
|
+
Homepage = "https://pyagent.org"
|
|
32
|
+
Repository = "https://github.com/pyagent-core/pyagent"
|
|
33
|
+
Documentation = "https://pyagent.org"
|
|
34
|
+
|
|
35
|
+
[project.optional-dependencies]
|
|
36
|
+
tui = ["textual>=3.0"]
|
|
37
|
+
dev = ["pytest>=8.0", "pytest-asyncio>=0.23", "textual-dev>=1.0"]
|
|
38
|
+
|
|
39
|
+
[project.scripts]
|
|
40
|
+
pyagent-studio = "pyagent_studio.cli:main"
|
|
41
|
+
|
|
42
|
+
[tool.hatch.build.targets.wheel]
|
|
43
|
+
packages = ["src/pyagent_studio"]
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
"""PyAgent Studio — terminal-based interactive workbench for agent systems."""
|
|
2
|
+
|
|
3
|
+
from pyagent_studio.services.blueprint_service import BlueprintService
|
|
4
|
+
from pyagent_studio.services.governance_service import GovernanceService
|
|
5
|
+
from pyagent_studio.services.simulation_service import SimulationService
|
|
6
|
+
from pyagent_studio.services.trace_service import TraceService
|
|
7
|
+
|
|
8
|
+
__all__ = [
|
|
9
|
+
"BlueprintService",
|
|
10
|
+
"GovernanceService",
|
|
11
|
+
"SimulationService",
|
|
12
|
+
"TraceService",
|
|
13
|
+
]
|
|
14
|
+
__version__ = "0.1.0"
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
"""StudioApp: main Textual application with screen routing."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from textual.app import App, ComposeResult
|
|
6
|
+
from textual.widgets import Footer, Header, TabbedContent, TabPane
|
|
7
|
+
|
|
8
|
+
from pyagent_blueprint.schema import BlueprintSpec
|
|
9
|
+
from pyagent_studio.services.blueprint_service import BlueprintService
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class StudioApp(App):
|
|
13
|
+
"""PyAgent Studio — terminal-based interactive workbench.
|
|
14
|
+
|
|
15
|
+
Launch via: ``pyagent-studio [blueprint.yaml]``
|
|
16
|
+
"""
|
|
17
|
+
|
|
18
|
+
TITLE = "PyAgent Studio"
|
|
19
|
+
CSS = """
|
|
20
|
+
TabbedContent {
|
|
21
|
+
height: 1fr;
|
|
22
|
+
}
|
|
23
|
+
"""
|
|
24
|
+
BINDINGS = [
|
|
25
|
+
("q", "quit", "Quit"),
|
|
26
|
+
("ctrl+s", "save", "Save"),
|
|
27
|
+
("ctrl+v", "validate", "Validate"),
|
|
28
|
+
("ctrl+r", "render", "Render Graph"),
|
|
29
|
+
("ctrl+t", "simulate", "Simulate"),
|
|
30
|
+
("ctrl+d", "diff", "Diff"),
|
|
31
|
+
]
|
|
32
|
+
|
|
33
|
+
def __init__(self, blueprint_path: str | None = None, **kwargs) -> None:
|
|
34
|
+
super().__init__(**kwargs)
|
|
35
|
+
self._blueprint_path = blueprint_path
|
|
36
|
+
self._service = BlueprintService()
|
|
37
|
+
self._spec: BlueprintSpec | None = None
|
|
38
|
+
|
|
39
|
+
def compose(self) -> ComposeResult:
|
|
40
|
+
yield Header()
|
|
41
|
+
with TabbedContent():
|
|
42
|
+
with TabPane("Dashboard", id="tab-dashboard"):
|
|
43
|
+
from textual.widgets import Static
|
|
44
|
+
yield Static("[bold]Dashboard[/bold]\n\nLoad a blueprint to get started.")
|
|
45
|
+
with TabPane("Editor", id="tab-editor"):
|
|
46
|
+
from textual.widgets import Static
|
|
47
|
+
yield Static("Editor — use Ctrl+V to validate")
|
|
48
|
+
with TabPane("Graph", id="tab-graph"):
|
|
49
|
+
from textual.widgets import Static
|
|
50
|
+
yield Static("Graph — load a blueprint first")
|
|
51
|
+
with TabPane("Simulation", id="tab-sim"):
|
|
52
|
+
from textual.widgets import Static
|
|
53
|
+
yield Static("Simulation — load a blueprint first")
|
|
54
|
+
with TabPane("Traces", id="tab-traces"):
|
|
55
|
+
from textual.widgets import Static
|
|
56
|
+
yield Static("Traces — no trace file loaded")
|
|
57
|
+
with TabPane("Cost", id="tab-cost"):
|
|
58
|
+
from textual.widgets import Static
|
|
59
|
+
yield Static("Cost — no data available")
|
|
60
|
+
with TabPane("Governance", id="tab-gov"):
|
|
61
|
+
from textual.widgets import Static
|
|
62
|
+
yield Static("Governance — load a blueprint first")
|
|
63
|
+
yield Footer()
|
|
64
|
+
|
|
65
|
+
def on_mount(self) -> None:
|
|
66
|
+
if self._blueprint_path:
|
|
67
|
+
try:
|
|
68
|
+
self._spec = self._service.load(self._blueprint_path)
|
|
69
|
+
self.notify(f"Loaded: {self._spec.metadata.name}")
|
|
70
|
+
except Exception as exc:
|
|
71
|
+
self.notify(f"Load error: {exc}", severity="error")
|
|
72
|
+
|
|
73
|
+
def action_quit(self) -> None:
|
|
74
|
+
self.exit()
|
|
75
|
+
|
|
76
|
+
def action_validate(self) -> None:
|
|
77
|
+
if self._spec is None:
|
|
78
|
+
self.notify("No blueprint loaded", severity="warning")
|
|
79
|
+
return
|
|
80
|
+
issues = self._service.validate()
|
|
81
|
+
if issues:
|
|
82
|
+
self.notify(f"{len(issues)} validation issue(s) found", severity="warning")
|
|
83
|
+
else:
|
|
84
|
+
self.notify("Blueprint is valid ✓")
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
"""CLI entry point: pyagent-studio [blueprint.yaml]."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import click
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
@click.command()
|
|
9
|
+
@click.argument("blueprint", required=False, default=None, type=click.Path())
|
|
10
|
+
def main(blueprint: str | None) -> None:
|
|
11
|
+
"""Launch PyAgent Studio — interactive agent system workbench.
|
|
12
|
+
|
|
13
|
+
Optionally pass a blueprint YAML file to load on startup.
|
|
14
|
+
"""
|
|
15
|
+
try:
|
|
16
|
+
from pyagent_studio.app import StudioApp
|
|
17
|
+
except ImportError:
|
|
18
|
+
click.echo(
|
|
19
|
+
"Error: textual is not installed. "
|
|
20
|
+
"Install with: pip install pyagent-studio[tui]",
|
|
21
|
+
err=True,
|
|
22
|
+
)
|
|
23
|
+
raise SystemExit(1)
|
|
24
|
+
|
|
25
|
+
app = StudioApp(blueprint_path=blueprint)
|
|
26
|
+
app.run()
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
if __name__ == "__main__":
|
|
30
|
+
main()
|
|
File without changes
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
"""Studio screens — Textual Screen subclasses for each TUI view."""
|
|
2
|
+
|
|
3
|
+
try:
|
|
4
|
+
from pyagent_studio.screens.dashboard import DashboardScreen
|
|
5
|
+
from pyagent_studio.screens.editor import EditorScreen
|
|
6
|
+
from pyagent_studio.screens.graph import GraphScreen
|
|
7
|
+
from pyagent_studio.screens.simulation import SimulationScreen
|
|
8
|
+
from pyagent_studio.screens.traces import TracesScreen
|
|
9
|
+
from pyagent_studio.screens.cost import CostScreen
|
|
10
|
+
from pyagent_studio.screens.governance import GovernanceScreen
|
|
11
|
+
|
|
12
|
+
__all__ = [
|
|
13
|
+
"CostScreen",
|
|
14
|
+
"DashboardScreen",
|
|
15
|
+
"EditorScreen",
|
|
16
|
+
"GovernanceScreen",
|
|
17
|
+
"GraphScreen",
|
|
18
|
+
"SimulationScreen",
|
|
19
|
+
"TracesScreen",
|
|
20
|
+
]
|
|
21
|
+
except ImportError:
|
|
22
|
+
__all__ = []
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
"""CostScreen: cost breakdown tables by pattern/agent/model."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from textual.app import ComposeResult
|
|
6
|
+
from textual.screen import Screen
|
|
7
|
+
from textual.widgets import Footer, Header, Static
|
|
8
|
+
|
|
9
|
+
from pyagent_studio.widgets.cost_chart import CostChart
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class CostScreen(Screen):
|
|
13
|
+
"""Display cost breakdown for agent system runs."""
|
|
14
|
+
|
|
15
|
+
BINDINGS = [("q", "quit", "Quit")]
|
|
16
|
+
|
|
17
|
+
def __init__(self, costs: dict[str, float] | None = None, **kwargs) -> None:
|
|
18
|
+
super().__init__(**kwargs)
|
|
19
|
+
self._costs = costs
|
|
20
|
+
|
|
21
|
+
def compose(self) -> ComposeResult:
|
|
22
|
+
yield Header()
|
|
23
|
+
yield Static("[bold]Cost Analysis[/bold]", id="title")
|
|
24
|
+
yield CostChart(id="cost-chart")
|
|
25
|
+
yield Footer()
|
|
26
|
+
|
|
27
|
+
def on_mount(self) -> None:
|
|
28
|
+
if self._costs:
|
|
29
|
+
chart = self.query_one("#cost-chart", CostChart)
|
|
30
|
+
chart.load_data(self._costs)
|
|
31
|
+
|
|
32
|
+
def action_quit(self) -> None:
|
|
33
|
+
self.app.exit()
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
"""DashboardScreen: list blueprints, health summary, quick actions."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from textual.app import ComposeResult
|
|
6
|
+
from textual.screen import Screen
|
|
7
|
+
from textual.widgets import DataTable, Footer, Header, Static
|
|
8
|
+
|
|
9
|
+
from pyagent_studio.services.blueprint_service import BlueprintService
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class DashboardScreen(Screen):
|
|
13
|
+
"""Main dashboard showing discovered blueprints and their status."""
|
|
14
|
+
|
|
15
|
+
BINDINGS = [
|
|
16
|
+
("n", "new_blueprint", "New"),
|
|
17
|
+
("enter", "open_blueprint", "Open"),
|
|
18
|
+
("q", "quit", "Quit"),
|
|
19
|
+
]
|
|
20
|
+
|
|
21
|
+
def __init__(self, service: BlueprintService | None = None, **kwargs) -> None:
|
|
22
|
+
super().__init__(**kwargs)
|
|
23
|
+
self._service = service or BlueprintService()
|
|
24
|
+
|
|
25
|
+
def compose(self) -> ComposeResult:
|
|
26
|
+
yield Header()
|
|
27
|
+
yield Static("[bold]PyAgent Studio — Dashboard[/bold]", id="title")
|
|
28
|
+
yield DataTable(id="blueprint-list")
|
|
29
|
+
yield Footer()
|
|
30
|
+
|
|
31
|
+
def on_mount(self) -> None:
|
|
32
|
+
table = self.query_one("#blueprint-list", DataTable)
|
|
33
|
+
table.add_columns("File", "Name", "Agents", "Workflows", "Status")
|
|
34
|
+
self._refresh_list(table)
|
|
35
|
+
|
|
36
|
+
def _refresh_list(self, table: DataTable) -> None:
|
|
37
|
+
"""Discover and list blueprints."""
|
|
38
|
+
table.clear()
|
|
39
|
+
for path in self._service.discover_blueprints():
|
|
40
|
+
try:
|
|
41
|
+
spec = self._service.load(path)
|
|
42
|
+
issues = self._service.validate()
|
|
43
|
+
status = "✓ Valid" if not issues else f"✗ {len(issues)} issue(s)"
|
|
44
|
+
table.add_row(
|
|
45
|
+
str(path.name),
|
|
46
|
+
spec.metadata.name,
|
|
47
|
+
str(len(spec.agents)),
|
|
48
|
+
str(len(spec.workflows)),
|
|
49
|
+
status,
|
|
50
|
+
)
|
|
51
|
+
except Exception:
|
|
52
|
+
table.add_row(str(path.name), "?", "?", "?", "✗ Load error")
|
|
53
|
+
|
|
54
|
+
def action_quit(self) -> None:
|
|
55
|
+
self.app.exit()
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
"""EditorScreen: YAML editing with live validation panel."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from textual.app import ComposeResult
|
|
6
|
+
from textual.containers import Horizontal
|
|
7
|
+
from textual.screen import Screen
|
|
8
|
+
from textual.widgets import Footer, Header, TextArea
|
|
9
|
+
|
|
10
|
+
from pyagent_studio.widgets.validation_log import ValidationLog
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class EditorScreen(Screen):
|
|
14
|
+
"""YAML editor with live validation sidebar."""
|
|
15
|
+
|
|
16
|
+
BINDINGS = [
|
|
17
|
+
("ctrl+s", "save", "Save"),
|
|
18
|
+
("ctrl+v", "validate", "Validate"),
|
|
19
|
+
("q", "quit", "Quit"),
|
|
20
|
+
]
|
|
21
|
+
|
|
22
|
+
DEFAULT_CSS = """
|
|
23
|
+
EditorScreen Horizontal {
|
|
24
|
+
height: 1fr;
|
|
25
|
+
}
|
|
26
|
+
EditorScreen TextArea {
|
|
27
|
+
width: 2fr;
|
|
28
|
+
}
|
|
29
|
+
EditorScreen ValidationLog {
|
|
30
|
+
width: 1fr;
|
|
31
|
+
border-left: solid green;
|
|
32
|
+
}
|
|
33
|
+
"""
|
|
34
|
+
|
|
35
|
+
def __init__(self, content: str = "", **kwargs) -> None:
|
|
36
|
+
super().__init__(**kwargs)
|
|
37
|
+
self._content = content
|
|
38
|
+
|
|
39
|
+
def compose(self) -> ComposeResult:
|
|
40
|
+
yield Header()
|
|
41
|
+
with Horizontal():
|
|
42
|
+
yield TextArea(self._content, language="yaml", id="editor")
|
|
43
|
+
yield ValidationLog(id="validation-log")
|
|
44
|
+
yield Footer()
|
|
45
|
+
|
|
46
|
+
def action_validate(self) -> None:
|
|
47
|
+
"""Validate current editor content."""
|
|
48
|
+
from pyagent_blueprint import BlueprintValidator, load_blueprint_from_str
|
|
49
|
+
from pyagent_blueprint.loader import BlueprintLoadError
|
|
50
|
+
|
|
51
|
+
editor = self.query_one("#editor", TextArea)
|
|
52
|
+
log = self.query_one("#validation-log", ValidationLog)
|
|
53
|
+
|
|
54
|
+
try:
|
|
55
|
+
spec = load_blueprint_from_str(editor.text)
|
|
56
|
+
validator = BlueprintValidator()
|
|
57
|
+
issues = validator.validate(spec)
|
|
58
|
+
log.load_issues(issues)
|
|
59
|
+
except (BlueprintLoadError, Exception) as exc:
|
|
60
|
+
log.clear()
|
|
61
|
+
log.write(f"[red]Parse error: {exc}[/red]")
|
|
62
|
+
|
|
63
|
+
def action_quit(self) -> None:
|
|
64
|
+
self.app.exit()
|