steerdev 0.4.27__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 (57) hide show
  1. steerdev-0.4.27.dist-info/METADATA +224 -0
  2. steerdev-0.4.27.dist-info/RECORD +57 -0
  3. steerdev-0.4.27.dist-info/WHEEL +4 -0
  4. steerdev-0.4.27.dist-info/entry_points.txt +2 -0
  5. steerdev_agent/__init__.py +10 -0
  6. steerdev_agent/api/__init__.py +32 -0
  7. steerdev_agent/api/activity.py +278 -0
  8. steerdev_agent/api/agents.py +145 -0
  9. steerdev_agent/api/client.py +158 -0
  10. steerdev_agent/api/commands.py +399 -0
  11. steerdev_agent/api/configs.py +238 -0
  12. steerdev_agent/api/context.py +306 -0
  13. steerdev_agent/api/events.py +294 -0
  14. steerdev_agent/api/hooks.py +178 -0
  15. steerdev_agent/api/implementation_plan.py +408 -0
  16. steerdev_agent/api/messages.py +231 -0
  17. steerdev_agent/api/prd.py +281 -0
  18. steerdev_agent/api/runs.py +526 -0
  19. steerdev_agent/api/sessions.py +403 -0
  20. steerdev_agent/api/specs.py +321 -0
  21. steerdev_agent/api/tasks.py +659 -0
  22. steerdev_agent/api/workflow_runs.py +351 -0
  23. steerdev_agent/api/workflows.py +191 -0
  24. steerdev_agent/cli.py +2254 -0
  25. steerdev_agent/config/__init__.py +19 -0
  26. steerdev_agent/config/models.py +236 -0
  27. steerdev_agent/config/platform.py +272 -0
  28. steerdev_agent/config/settings.py +62 -0
  29. steerdev_agent/daemon.py +675 -0
  30. steerdev_agent/executor/__init__.py +64 -0
  31. steerdev_agent/executor/base.py +121 -0
  32. steerdev_agent/executor/claude.py +328 -0
  33. steerdev_agent/executor/stream.py +163 -0
  34. steerdev_agent/git/__init__.py +1 -0
  35. steerdev_agent/handlers/__init__.py +5 -0
  36. steerdev_agent/handlers/prd.py +533 -0
  37. steerdev_agent/integration.py +334 -0
  38. steerdev_agent/prompt/__init__.py +10 -0
  39. steerdev_agent/prompt/builder.py +263 -0
  40. steerdev_agent/prompt/templates.py +422 -0
  41. steerdev_agent/py.typed +0 -0
  42. steerdev_agent/runner.py +829 -0
  43. steerdev_agent/setup/__init__.py +5 -0
  44. steerdev_agent/setup/claude_setup.py +560 -0
  45. steerdev_agent/setup/templates/claude_md_section.md +140 -0
  46. steerdev_agent/setup/templates/settings.json +69 -0
  47. steerdev_agent/setup/templates/skills/activity/SKILL.md +160 -0
  48. steerdev_agent/setup/templates/skills/context/SKILL.md +122 -0
  49. steerdev_agent/setup/templates/skills/git-workflow/SKILL.md +218 -0
  50. steerdev_agent/setup/templates/skills/progress-logging/SKILL.md +211 -0
  51. steerdev_agent/setup/templates/skills/specs-management/SKILL.md +161 -0
  52. steerdev_agent/setup/templates/skills/task-management/SKILL.md +343 -0
  53. steerdev_agent/setup/templates/steerdev.yaml +51 -0
  54. steerdev_agent/version.py +149 -0
  55. steerdev_agent/workflow/__init__.py +10 -0
  56. steerdev_agent/workflow/executor.py +494 -0
  57. steerdev_agent/workflow/memory.py +185 -0
@@ -0,0 +1,224 @@
1
+ Metadata-Version: 2.4
2
+ Name: steerdev
3
+ Version: 0.4.27
4
+ Summary: Backend task runner for steerdev.com - orchestrates CLI coding agents with activity reporting
5
+ Project-URL: Homepage, https://github.com/pentoai/steerdev-agent
6
+ Project-URL: Repository, https://github.com/pentoai/steerdev-agent
7
+ Project-URL: Documentation, https://github.com/pentoai/steerdev-agent#readme
8
+ Author-email: Leonardo Piñeyro <leopiney@gmail.com>
9
+ License: MIT
10
+ Keywords: agent,ai,automation,cli,terminal
11
+ Classifier: Development Status :: 3 - Alpha
12
+ Classifier: Intended Audience :: Developers
13
+ Classifier: License :: OSI Approved :: MIT License
14
+ Classifier: Programming Language :: Python :: 3
15
+ Classifier: Programming Language :: Python :: 3.12
16
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
17
+ Classifier: Topic :: Terminals
18
+ Requires-Python: >=3.12
19
+ Requires-Dist: httpx>=0.27.0
20
+ Requires-Dist: loguru>=0.7.3
21
+ Requires-Dist: pydantic-settings>=2.0.0
22
+ Requires-Dist: pydantic>=2.0.0
23
+ Requires-Dist: python-dotenv>=1.2.1
24
+ Requires-Dist: pyyaml>=6.0.0
25
+ Requires-Dist: rich>=13.0.0
26
+ Requires-Dist: typer>=0.12.0
27
+ Provides-Extra: dev
28
+ Requires-Dist: basedpyright>=1.21.0; extra == 'dev'
29
+ Requires-Dist: ipdb>=0.13.13; extra == 'dev'
30
+ Requires-Dist: pre-commit>=4.0.0; extra == 'dev'
31
+ Requires-Dist: pytest-asyncio>=0.24.0; extra == 'dev'
32
+ Requires-Dist: pytest-cov>=4.1.0; extra == 'dev'
33
+ Requires-Dist: pytest>=8.0.0; extra == 'dev'
34
+ Requires-Dist: ruff>=0.8.0; extra == 'dev'
35
+ Description-Content-Type: text/markdown
36
+
37
+ # SteerDev Agent
38
+
39
+ Task runner for [steerdev.com](https://steerdev.com) — orchestrates AI coding agents via subprocess execution while streaming events to the SteerDev platform.
40
+
41
+ ## What It Does
42
+
43
+ SteerDev Agent connects your AI coding agent (Claude Code, Codex, Aider) to the steerdev.com platform:
44
+
45
+ 1. **Fetches tasks** from your SteerDev project
46
+ 2. **Builds prompts** with project context, task details, and workflow instructions
47
+ 3. **Launches the agent** as a subprocess with JSON streaming
48
+ 4. **Streams events** back to the API for real-time monitoring
49
+ 5. **Manages sessions** for tracking and resuming conversations
50
+
51
+ ## Installation
52
+
53
+ ```bash
54
+ # Install with uv (recommended)
55
+ uv tool install steerdev-agent
56
+
57
+ # Or from source
58
+ git clone https://github.com/pentoai/steerdev-agent.git
59
+ cd steerdev-agent
60
+ uv tool install .
61
+ ```
62
+
63
+ ## Quick Start
64
+
65
+ ### 1. Set Up Your Project
66
+
67
+ ```bash
68
+ # Configure the agent for your project
69
+ steerdev-agent setup --project-id YOUR_PROJECT_ID --api-key YOUR_API_KEY
70
+ ```
71
+
72
+ ### 2. Set Environment Variables
73
+
74
+ ```bash
75
+ export STEERDEV_API_KEY="your-api-key"
76
+
77
+ # Ensure your CLI agent is logged in (e.g., `claude login` for Claude Code)
78
+ ```
79
+
80
+ ### 3. Run the Agent
81
+
82
+ ```bash
83
+ # Run the next task in your project
84
+ steerdev-agent run --project-id YOUR_PROJECT_ID
85
+
86
+ # Run a specific task
87
+ steerdev-agent run --project-id YOUR_PROJECT_ID --task-id TASK_ID
88
+
89
+ # Resume an existing session
90
+ steerdev-agent resume --session-id SESSION_ID --message "Continue working..."
91
+ ```
92
+
93
+ ## CLI Commands
94
+
95
+ ### `steerdev-agent run`
96
+
97
+ Run the agent against a project or specific task.
98
+
99
+ ```bash
100
+ steerdev-agent run --project-id PROJECT_ID
101
+ steerdev-agent run --project-id PROJECT_ID --task-id TASK_ID
102
+ steerdev-agent run -c agent.yaml --prompt "Fix the failing tests"
103
+ ```
104
+
105
+ ### `steerdev-agent tasks`
106
+
107
+ Manage tasks from your SteerDev project.
108
+
109
+ ```bash
110
+ steerdev-agent tasks next # Get the next task to work on
111
+ steerdev-agent tasks list # List all tasks
112
+ steerdev-agent tasks get TASK_ID # Get task details
113
+ steerdev-agent tasks update TASK_ID --status in-progress
114
+ ```
115
+
116
+ ### `steerdev-agent setup`
117
+
118
+ Configure your project for use with the agent.
119
+
120
+ ```bash
121
+ steerdev-agent setup --project-id YOUR_PROJECT_ID --api-key YOUR_API_KEY
122
+ ```
123
+
124
+ ### `steerdev-agent config`
125
+
126
+ Manage YAML configuration files.
127
+
128
+ ```bash
129
+ steerdev-agent config init --output agent.yaml # Generate config
130
+ steerdev-agent config validate agent.yaml # Validate config
131
+ steerdev-agent config show agent.yaml # Show config
132
+ ```
133
+
134
+ ## Configuration
135
+
136
+ ### YAML Config File
137
+
138
+ ```yaml
139
+ agent:
140
+ model: null # Model override
141
+ max_turns: null # Max agent turns per task
142
+ timeout_seconds: 3600 # Max execution time
143
+ workflow_id: null # Workflow ID for multi-phase execution
144
+
145
+ api:
146
+ api_endpoint: "https://steerdev.com/api/v1"
147
+ api_key_env: STEERDEV_API_KEY
148
+ project_id_env: STEERDEV_PROJECT_ID
149
+
150
+ executor:
151
+ type: claude # claude, codex, aider
152
+ permission_mode: default
153
+ allowed_tools: []
154
+ disallowed_tools: []
155
+ mcp_config: null
156
+
157
+ worktrees:
158
+ enabled: false
159
+ ```
160
+
161
+ ### Environment Variables
162
+
163
+ | Variable | Description |
164
+ | --- | --- |
165
+ | `STEERDEV_API_KEY` | API key for steerdev.com |
166
+ | `STEERDEV_PROJECT_ID` | Default project ID |
167
+
168
+ > **Note:** CLI agents (Claude Code, Codex, etc.) must be logged in independently before running steerdev-agent. No LLM API keys are needed here.
169
+
170
+ ## Architecture
171
+
172
+ ```
173
+ steerdev-agent run
174
+
175
+ ├── Fetch task from steerdev.com API
176
+ ├── Build prompt (project context + task + workflow)
177
+ ├── Create session
178
+ ├── Launch agent subprocess (Claude Code)
179
+ │ └── Stream JSON events
180
+ │ ├── Parse (assistant, tool_use, tool_result)
181
+ │ └── Batch & send to steerdev.com API
182
+ └── Complete session
183
+ ```
184
+
185
+ ### Key Modules
186
+
187
+ | Module | Purpose |
188
+ | --- | --- |
189
+ | `cli.py` | Typer CLI entry point |
190
+ | `runner.py` | Main orchestrator |
191
+ | `executor/` | Agent subprocess management |
192
+ | `api/` | SteerDev API clients |
193
+ | `prompt/` | Prompt building and templates |
194
+ | `workflow/` | Multi-phase workflow execution |
195
+ | `config/` | Configuration models and settings |
196
+ | `setup/` | Project setup utilities |
197
+
198
+ ## Development
199
+
200
+ ```bash
201
+ # Install dependencies
202
+ uv sync --extra dev
203
+
204
+ # Run tests
205
+ uv run pytest
206
+
207
+ # Lint & format
208
+ uv run ruff check .
209
+ uv run ruff format .
210
+
211
+ # Type check
212
+ uv run basedpyright
213
+ ```
214
+
215
+ ## Requirements
216
+
217
+ - Python 3.12+
218
+ - [uv](https://docs.astral.sh/uv/) package manager
219
+ - An AI coding agent CLI (e.g., `claude` for Claude Code)
220
+ - SteerDev API key
221
+
222
+ ## License
223
+
224
+ MIT — see [LICENSE](LICENSE) for details.
@@ -0,0 +1,57 @@
1
+ steerdev_agent/__init__.py,sha256=8jg_dquRV68EKaIG4kpxdsNOjtCxeddw_k8ZmdgqGnM,325
2
+ steerdev_agent/cli.py,sha256=_Q3iNw5kJAh094ud4lPOJvJrZFHkfGaBcMk37mOTxX0,73199
3
+ steerdev_agent/daemon.py,sha256=5n1YNgctXPoSoAzTffsFDBN6v7Al8jIMdbg5g6WU5tA,25616
4
+ steerdev_agent/integration.py,sha256=idur-0K1O0cMLVKTOT4ChxYBGImc4xSb24SQEhsNIFI,9182
5
+ steerdev_agent/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
6
+ steerdev_agent/runner.py,sha256=C5m1dNl5PxyIDHmDWbCnX1SVvD3QD2xldncYWROR0cA,30525
7
+ steerdev_agent/version.py,sha256=kcCna8u-Gkuii21sGvDLoPaIDGyFzZziuELn_Ks3ubY,4202
8
+ steerdev_agent/api/__init__.py,sha256=g3Nrb6T-QTPbTjBTIpuhc5nGoC9PaCmzBgE2lKfCUW0,917
9
+ steerdev_agent/api/activity.py,sha256=fv-VD5sJkbky4LMh4kahepoYxky_slzrLppY_f4gshI,8095
10
+ steerdev_agent/api/agents.py,sha256=ETkTslpNJ5RyAcdHIinDWYm8IDX_mdoSOkjYNY_n6fI,4641
11
+ steerdev_agent/api/client.py,sha256=Om5yGyJne6L1LIRFiXRgz5K202SJigfa3ehwqp7lWqI,4115
12
+ steerdev_agent/api/commands.py,sha256=OkXB4gFNZ_eyWK68giQRr01SCW-huRIqvHFoRdAuDsg,12486
13
+ steerdev_agent/api/configs.py,sha256=ybneChpd2ImkIgG-z5hQh2yUMa51BiJP1AJPM0V5mrY,8080
14
+ steerdev_agent/api/context.py,sha256=iCc-msk6NY248K10OJqWvOqE-Lf4yQ9fSDldB3x3pzU,10623
15
+ steerdev_agent/api/events.py,sha256=9Uta4eIUZ4uKVj9b-NFwnnHEiwU_VNGdWhLJUYmewRk,9300
16
+ steerdev_agent/api/hooks.py,sha256=lhkqFgD0Rs0MQdG2WqOvDJ2HCO5CWmgEemwdCz-7Gis,5135
17
+ steerdev_agent/api/implementation_plan.py,sha256=9Nw27nrH95_f-Chg02myEobaTV0SnvJdFw0sn3ZUTzs,13796
18
+ steerdev_agent/api/messages.py,sha256=0jxXOD0Gfj3rR6nAHdNuUah8dwgDpD6Dl5qrcEKymjg,7232
19
+ steerdev_agent/api/prd.py,sha256=KZBIg0Jw7qNIHy5Uf5cMMjo3F70d9dOp3aEzWztTjJg,8016
20
+ steerdev_agent/api/runs.py,sha256=J4bTKz7u4f4cduo2ooVtxzv3902sGUjXcynHBV4UdaM,17253
21
+ steerdev_agent/api/sessions.py,sha256=gfLHoMVLugZxty-XTn3fkNrEXji8kDWX4voyiQrgEF0,12956
22
+ steerdev_agent/api/specs.py,sha256=rovPapRXb2iDmXE8804e3HLZpKd8JyCvpaR6E3mqsiw,9419
23
+ steerdev_agent/api/tasks.py,sha256=hx9pMa06JTxRv4kAYOQaijI5u7t-Jr3LB-7CdlZqp7k,21768
24
+ steerdev_agent/api/workflow_runs.py,sha256=CamYaWzvZgFoC6Wbj75x3NRJ5HcNYO4_JNxElsOiD2A,11460
25
+ steerdev_agent/api/workflows.py,sha256=ULSQB6qYW0SEc5sqkLhPpdWylkIWr7Tf9dqRI9Pgtro,5850
26
+ steerdev_agent/config/__init__.py,sha256=NgQosi2oRWhszULHe_wP6APTMUzwg-IpJZ6eCtVhGd0,360
27
+ steerdev_agent/config/models.py,sha256=RkwvZaIhYWUWWEgH_0zp4kd_c5fY_nX4nNA7euKnIFg,6503
28
+ steerdev_agent/config/platform.py,sha256=cZ2S7agD268GwJgewnhWSb5GryHKD10ZeFyE-gosu70,9912
29
+ steerdev_agent/config/settings.py,sha256=JQ6lq2Pzr0J8-aG11L2gRxrMaj2Gxdzkxz98NL6ojyE,1656
30
+ steerdev_agent/executor/__init__.py,sha256=SQDHWsstoL9gGj5ou5S7Pm3fgy-a0YAUs3pJKBuev3I,2050
31
+ steerdev_agent/executor/base.py,sha256=09Ms9jHcYBFbaYb5acIEFAbwALpVGadVlapttdfy1F8,3094
32
+ steerdev_agent/executor/claude.py,sha256=iUGoHSTl1RFkN4xHwZgyxmUWmckIjSC9ESIZ3gY-4j4,10920
33
+ steerdev_agent/executor/stream.py,sha256=ZSUHs2osb5VrNV7PD3SpXtIxjR-_L3VFE9rwvwZKM28,4937
34
+ steerdev_agent/git/__init__.py,sha256=p6kqpae8Q58FzaLUnTCAjOPl688a7N3vXPNct5UCix8,31
35
+ steerdev_agent/handlers/__init__.py,sha256=UD12PAJC-BYIVa_KwRhe5dl9v4XXNIwmrHl-lbWy6X8,115
36
+ steerdev_agent/handlers/prd.py,sha256=C9buyN3jh4_TkgDfQVTaB2publojUxdJX7t7EEKvUj4,18398
37
+ steerdev_agent/prompt/__init__.py,sha256=MR8fwQZ1e2wnslfg0LPNt2HdQi4OxUn5dzETLGcNHi0,242
38
+ steerdev_agent/prompt/builder.py,sha256=Mi9df_CPg-SxxZAU-vLjRPfDGpTUetqoA6vMePMBwkk,9166
39
+ steerdev_agent/prompt/templates.py,sha256=HUiFTxyh6EF4lGlPlPsmzsw38uVrO4xSpyzro1tnimQ,12427
40
+ steerdev_agent/setup/__init__.py,sha256=klinupTkTfYo7url0JtV-e9rxDWnKijPuvOdnpVaouU,146
41
+ steerdev_agent/setup/claude_setup.py,sha256=QK9dE40E5H2rtUY2Cj8S35HIZh04gI47pYH4Tbx-vho,19249
42
+ steerdev_agent/setup/templates/claude_md_section.md,sha256=fVmfI5_Ka5MJNGciVhbffx8jwrfs2pAlblmn1g8AyRw,3925
43
+ steerdev_agent/setup/templates/settings.json,sha256=44UM3QsqSxvvFQDXU5km2GMAWr6orYVmOAxzcIxXDOU,1386
44
+ steerdev_agent/setup/templates/steerdev.yaml,sha256=QRAInaVNZW2hZLnaY4QjUf_gKJiDzAzlLG6PQ37xJSQ,1102
45
+ steerdev_agent/setup/templates/skills/activity/SKILL.md,sha256=nm5Rbj9wCPLB9-_-7Qzb8Ww9nsVLsSmWMuVvhX7BI80,4913
46
+ steerdev_agent/setup/templates/skills/context/SKILL.md,sha256=ID5Gl5TY6D3przAthF8quFSeD0HyEmv1Pp027EitaxY,3086
47
+ steerdev_agent/setup/templates/skills/git-workflow/SKILL.md,sha256=o3H2la6ldcA_u8Tpjr6VXpnOgi4Os2o_nml2RqEAZ6U,5547
48
+ steerdev_agent/setup/templates/skills/progress-logging/SKILL.md,sha256=Qq0L6DqBDC1K2Rz-Evm9Jdk7fGRUHKXh_WNAggRkH2g,6813
49
+ steerdev_agent/setup/templates/skills/specs-management/SKILL.md,sha256=2KCm42QWXlBp8CJOjtSPEAEESg4wjx6qjtCyIOYBtHk,3715
50
+ steerdev_agent/setup/templates/skills/task-management/SKILL.md,sha256=ed9nXxEBjAwDrInvWvhL5LkEJDp0CAjeJJT6XdkWkB0,9372
51
+ steerdev_agent/workflow/__init__.py,sha256=0pyLL9d9Em9e6yVsCQ4DNOpWwxjjfihUpfv99FiPqjU,296
52
+ steerdev_agent/workflow/executor.py,sha256=xCjTQnHacf6GF4euD9qMa0VnFPMluZ7Ru2kOiBioNWg,18552
53
+ steerdev_agent/workflow/memory.py,sha256=7dFyhKi_90ix58zoKNGWdfCQWOzXW8TzO9QEo184OfA,5845
54
+ steerdev-0.4.27.dist-info/METADATA,sha256=hx6DLCSx_8JtONFB-I7LdgEeXTpCQ1T46kGPGD92Pmg,6113
55
+ steerdev-0.4.27.dist-info/WHEEL,sha256=QccIxa26bgl1E6uMy58deGWi-0aeIkkangHcxk2kWfw,87
56
+ steerdev-0.4.27.dist-info/entry_points.txt,sha256=js2hCJbrnJF1-GQLY70Ls-nd03C7LBnqMKjQdLFi0-E,52
57
+ steerdev-0.4.27.dist-info/RECORD,,
@@ -0,0 +1,4 @@
1
+ Wheel-Version: 1.0
2
+ Generator: hatchling 1.29.0
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
@@ -0,0 +1,2 @@
1
+ [console_scripts]
2
+ steerdev = steerdev_agent.cli:app
@@ -0,0 +1,10 @@
1
+ """SteerDev Agent - Backend task runner for steerdev.com.
2
+
3
+ Orchestrates TUI coding agents (Claude Code, Gemini CLI, Codex) using tui-operator,
4
+ with activity reporting to steerdev.com API and notification integrations.
5
+ """
6
+
7
+ from steerdev_agent.version import get_version
8
+
9
+ __version__ = get_version()
10
+ __all__ = ["__version__"]
@@ -0,0 +1,32 @@
1
+ """SteerDev API client module."""
2
+
3
+ from steerdev_agent.api.client import SteerDevClient, get_api_key, get_project_id
4
+ from steerdev_agent.api.configs import ConfigsClient
5
+ from steerdev_agent.api.events import EventData, EventsClient
6
+ from steerdev_agent.api.hooks import HooksClient
7
+ from steerdev_agent.api.runs import RunCreateRequest, RunResponse, RunsClient
8
+ from steerdev_agent.api.sessions import (
9
+ SessionCreateRequest,
10
+ SessionResponse,
11
+ SessionsClient,
12
+ )
13
+ from steerdev_agent.api.tasks import TasksClient
14
+ from steerdev_agent.api.workflow_runs import WorkflowRunsClient
15
+
16
+ __all__ = [
17
+ "ConfigsClient",
18
+ "EventData",
19
+ "EventsClient",
20
+ "HooksClient",
21
+ "RunCreateRequest",
22
+ "RunResponse",
23
+ "RunsClient",
24
+ "SessionCreateRequest",
25
+ "SessionResponse",
26
+ "SessionsClient",
27
+ "SteerDevClient",
28
+ "TasksClient",
29
+ "WorkflowRunsClient",
30
+ "get_api_key",
31
+ "get_project_id",
32
+ ]
@@ -0,0 +1,278 @@
1
+ """Activity API client for SteerDev Agent.
2
+
3
+ Provides methods for self-reporting progress/blockers and
4
+ querying activity history.
5
+ """
6
+
7
+ from __future__ import annotations
8
+
9
+ from datetime import UTC, datetime
10
+ from typing import Any
11
+
12
+ from pydantic import BaseModel, Field
13
+ from rich.console import Console
14
+ from rich.panel import Panel
15
+ from rich.table import Table
16
+
17
+ from steerdev_agent.api.client import (
18
+ SteerDevClient,
19
+ get_agent_id,
20
+ get_agent_name,
21
+ )
22
+
23
+ console = Console()
24
+
25
+
26
+ # Valid activity event types for self-reporting
27
+ VALID_EVENT_TYPES = [
28
+ "progress", # Progress update
29
+ "blocker", # Blocked on something
30
+ "question", # Need clarification
31
+ "milestone", # Reached a milestone
32
+ "error", # Encountered an error
33
+ "warning", # Warning/heads-up
34
+ "info", # General information
35
+ ]
36
+
37
+
38
+ class ActivityEvent(BaseModel):
39
+ """Activity event model."""
40
+
41
+ id: str
42
+ event_type: str
43
+ message: str
44
+ timestamp: str
45
+ run_id: str | None = None
46
+ session_name: str | None = None
47
+ agent_id: str | None = None
48
+ agent_name: str | None = None
49
+ metadata: dict[str, Any] = Field(default_factory=dict)
50
+
51
+
52
+ class ActivityListResponse(BaseModel):
53
+ """Response model for activity list."""
54
+
55
+ events: list[ActivityEvent]
56
+ total: int
57
+ limit: int
58
+ offset: int
59
+
60
+
61
+ class ActivityClient(SteerDevClient):
62
+ """Client for activity reporting and querying.
63
+
64
+ Provides methods for agents to self-report progress,
65
+ blockers, and other activity events.
66
+ """
67
+
68
+ def report(
69
+ self,
70
+ event_type: str,
71
+ message: str,
72
+ metadata: dict[str, Any] | None = None,
73
+ run_id: str | None = None,
74
+ session_name: str | None = None,
75
+ ) -> bool:
76
+ """Report an activity event.
77
+
78
+ Args:
79
+ event_type: Type of event (progress, blocker, question, etc.).
80
+ message: Human-readable message describing the event.
81
+ metadata: Additional metadata for the event.
82
+ run_id: Optional run ID to associate with.
83
+ session_name: Optional session name.
84
+
85
+ Returns:
86
+ True if the event was reported successfully.
87
+ """
88
+ agent_id = get_agent_id()
89
+ agent_name = get_agent_name() or "SteerDev Agent"
90
+
91
+ event = {
92
+ "event_type": event_type,
93
+ "message": message,
94
+ "timestamp": datetime.now(UTC).isoformat(),
95
+ "metadata": metadata or {},
96
+ }
97
+
98
+ if run_id:
99
+ event["run_id"] = run_id
100
+ if session_name:
101
+ event["session_name"] = session_name
102
+ if agent_id:
103
+ event["agent_id"] = agent_id
104
+
105
+ request_body = {
106
+ "agent_name": agent_name,
107
+ "application": "claude_code",
108
+ "events": [event],
109
+ }
110
+
111
+ console.print(f"Reporting activity to {self.api_base}/activity/report")
112
+ response = self.post("/activity/report", json=request_body)
113
+
114
+ if response.status_code not in (200, 201, 202):
115
+ console.print(f"[red]API Error: {response.status_code} - {response.text}[/red]")
116
+ return False
117
+
118
+ return True
119
+
120
+ def query(
121
+ self,
122
+ run_id: str | None = None,
123
+ event_type: str | None = None,
124
+ limit: int = 20,
125
+ offset: int = 0,
126
+ ) -> list[dict[str, Any]]:
127
+ """Query activity history.
128
+
129
+ Args:
130
+ run_id: Filter by run ID.
131
+ event_type: Filter by event type.
132
+ limit: Maximum number of events to return.
133
+ offset: Offset for pagination.
134
+
135
+ Returns:
136
+ List of activity event dicts.
137
+ """
138
+ params: dict[str, str | int] = {"limit": limit, "offset": offset}
139
+ if run_id:
140
+ params["run_id"] = run_id
141
+ if event_type:
142
+ params["event_type"] = event_type
143
+
144
+ console.print(f"Querying activity from {self.api_base}/activity")
145
+ response = self.get("/activity", params=params)
146
+
147
+ if response.status_code != 200:
148
+ console.print(f"[red]API Error: {response.status_code} - {response.text}[/red]")
149
+ return []
150
+
151
+ data = response.json()
152
+ return data.get("events", []) if isinstance(data, dict) else data
153
+
154
+
155
+ def get_event_type_style(event_type: str) -> str:
156
+ """Get Rich style for an event type.
157
+
158
+ Args:
159
+ event_type: Activity event type.
160
+
161
+ Returns:
162
+ Rich style string.
163
+ """
164
+ return {
165
+ "progress": "green",
166
+ "blocker": "red",
167
+ "question": "yellow",
168
+ "milestone": "bold green",
169
+ "error": "bold red",
170
+ "warning": "yellow",
171
+ "info": "blue",
172
+ "session_start": "cyan",
173
+ "session_end": "dim cyan",
174
+ "agent_stopped": "dim",
175
+ "subagent_stopped": "dim",
176
+ }.get(event_type, "white")
177
+
178
+
179
+ def display_activity_event(event: dict[str, Any]) -> None:
180
+ """Display an activity event in a formatted panel.
181
+
182
+ Args:
183
+ event: Activity event dict.
184
+ """
185
+ event_type = event.get("event_type", "unknown")
186
+ type_style = get_event_type_style(event_type)
187
+
188
+ info = (
189
+ f"[bold cyan]Type:[/bold cyan] [{type_style}]{event_type}[/{type_style}]\n"
190
+ f"[bold cyan]Message:[/bold cyan] {event.get('message', 'N/A')}\n"
191
+ f"[bold cyan]Timestamp:[/bold cyan] {event.get('timestamp', 'N/A')}"
192
+ )
193
+
194
+ if event.get("run_id"):
195
+ info += f"\n[bold cyan]Run ID:[/bold cyan] {event['run_id']}"
196
+
197
+ if event.get("session_name"):
198
+ info += f"\n[bold cyan]Session:[/bold cyan] {event['session_name']}"
199
+
200
+ if event.get("agent_name"):
201
+ info += f"\n[bold cyan]Agent:[/bold cyan] {event['agent_name']}"
202
+
203
+ metadata = event.get("metadata", {})
204
+ if metadata:
205
+ info += "\n\n[bold cyan]Metadata:[/bold cyan]"
206
+ for key, value in metadata.items():
207
+ info += f"\n • {key}: {value}"
208
+
209
+ console.print(Panel(info, title="Activity Event", border_style="blue"))
210
+
211
+
212
+ def display_activity_list(events: list[dict[str, Any]]) -> None:
213
+ """Display a list of activity events in a formatted table.
214
+
215
+ Args:
216
+ events: List of activity event dicts.
217
+ """
218
+ if not events:
219
+ console.print("[yellow]No activity events found[/yellow]")
220
+ return
221
+
222
+ table = Table(title="Activity History")
223
+ table.add_column("Type", style="magenta", no_wrap=True)
224
+ table.add_column("Message", style="white")
225
+ table.add_column("Timestamp", style="dim")
226
+ table.add_column("Run ID", style="dim")
227
+
228
+ for event in events:
229
+ event_type = event.get("event_type", "unknown")
230
+ type_style = get_event_type_style(event_type)
231
+ run_id = event.get("run_id", "")
232
+ if run_id and len(run_id) > 8:
233
+ run_id = run_id[:8] + "..."
234
+
235
+ # Truncate message for table display
236
+ message = event.get("message", "")
237
+ if len(message) > 60:
238
+ message = message[:60] + "..."
239
+
240
+ # Format timestamp
241
+ timestamp = event.get("timestamp", "")
242
+ if timestamp:
243
+ # Parse and format for display
244
+ try:
245
+ dt = datetime.fromisoformat(timestamp.replace("Z", "+00:00"))
246
+ timestamp = dt.strftime("%Y-%m-%d %H:%M")
247
+ except (ValueError, AttributeError):
248
+ pass
249
+
250
+ table.add_row(
251
+ f"[{type_style}]{event_type}[/{type_style}]",
252
+ message,
253
+ timestamp,
254
+ run_id,
255
+ )
256
+
257
+ console.print(table)
258
+ console.print(f"\n[dim]Total: {len(events)} events[/dim]")
259
+
260
+
261
+ def display_report_success(event_type: str, message: str) -> None:
262
+ """Display activity report success message.
263
+
264
+ Args:
265
+ event_type: Type of event that was reported.
266
+ message: Message that was reported.
267
+ """
268
+ type_style = get_event_type_style(event_type)
269
+
270
+ console.print(
271
+ Panel(
272
+ f"[bold green]Activity reported successfully[/bold green]\n\n"
273
+ f"Type: [{type_style}]{event_type}[/{type_style}]\n"
274
+ f"Message: {message[:100]}{'...' if len(message) > 100 else ''}",
275
+ title="Success",
276
+ border_style="green",
277
+ )
278
+ )