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.
- steerdev-0.4.27.dist-info/METADATA +224 -0
- steerdev-0.4.27.dist-info/RECORD +57 -0
- steerdev-0.4.27.dist-info/WHEEL +4 -0
- steerdev-0.4.27.dist-info/entry_points.txt +2 -0
- steerdev_agent/__init__.py +10 -0
- steerdev_agent/api/__init__.py +32 -0
- steerdev_agent/api/activity.py +278 -0
- steerdev_agent/api/agents.py +145 -0
- steerdev_agent/api/client.py +158 -0
- steerdev_agent/api/commands.py +399 -0
- steerdev_agent/api/configs.py +238 -0
- steerdev_agent/api/context.py +306 -0
- steerdev_agent/api/events.py +294 -0
- steerdev_agent/api/hooks.py +178 -0
- steerdev_agent/api/implementation_plan.py +408 -0
- steerdev_agent/api/messages.py +231 -0
- steerdev_agent/api/prd.py +281 -0
- steerdev_agent/api/runs.py +526 -0
- steerdev_agent/api/sessions.py +403 -0
- steerdev_agent/api/specs.py +321 -0
- steerdev_agent/api/tasks.py +659 -0
- steerdev_agent/api/workflow_runs.py +351 -0
- steerdev_agent/api/workflows.py +191 -0
- steerdev_agent/cli.py +2254 -0
- steerdev_agent/config/__init__.py +19 -0
- steerdev_agent/config/models.py +236 -0
- steerdev_agent/config/platform.py +272 -0
- steerdev_agent/config/settings.py +62 -0
- steerdev_agent/daemon.py +675 -0
- steerdev_agent/executor/__init__.py +64 -0
- steerdev_agent/executor/base.py +121 -0
- steerdev_agent/executor/claude.py +328 -0
- steerdev_agent/executor/stream.py +163 -0
- steerdev_agent/git/__init__.py +1 -0
- steerdev_agent/handlers/__init__.py +5 -0
- steerdev_agent/handlers/prd.py +533 -0
- steerdev_agent/integration.py +334 -0
- steerdev_agent/prompt/__init__.py +10 -0
- steerdev_agent/prompt/builder.py +263 -0
- steerdev_agent/prompt/templates.py +422 -0
- steerdev_agent/py.typed +0 -0
- steerdev_agent/runner.py +829 -0
- steerdev_agent/setup/__init__.py +5 -0
- steerdev_agent/setup/claude_setup.py +560 -0
- steerdev_agent/setup/templates/claude_md_section.md +140 -0
- steerdev_agent/setup/templates/settings.json +69 -0
- steerdev_agent/setup/templates/skills/activity/SKILL.md +160 -0
- steerdev_agent/setup/templates/skills/context/SKILL.md +122 -0
- steerdev_agent/setup/templates/skills/git-workflow/SKILL.md +218 -0
- steerdev_agent/setup/templates/skills/progress-logging/SKILL.md +211 -0
- steerdev_agent/setup/templates/skills/specs-management/SKILL.md +161 -0
- steerdev_agent/setup/templates/skills/task-management/SKILL.md +343 -0
- steerdev_agent/setup/templates/steerdev.yaml +51 -0
- steerdev_agent/version.py +149 -0
- steerdev_agent/workflow/__init__.py +10 -0
- steerdev_agent/workflow/executor.py +494 -0
- steerdev_agent/workflow/memory.py +185 -0
|
@@ -0,0 +1,281 @@
|
|
|
1
|
+
"""PRD API client for SteerDev Agent.
|
|
2
|
+
|
|
3
|
+
Provides methods for interacting with PRD documents and comments
|
|
4
|
+
during agent-driven PRD analysis and task generation.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from __future__ import annotations
|
|
8
|
+
|
|
9
|
+
from typing import Any
|
|
10
|
+
|
|
11
|
+
from loguru import logger
|
|
12
|
+
from pydantic import BaseModel
|
|
13
|
+
|
|
14
|
+
from steerdev_agent.api.client import SteerDevClient
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class PRDComment(BaseModel):
|
|
18
|
+
"""PRD comment model."""
|
|
19
|
+
|
|
20
|
+
id: str
|
|
21
|
+
prd_id: str
|
|
22
|
+
parent_id: str | None = None
|
|
23
|
+
content: str
|
|
24
|
+
comment_type: str # question, answer, note
|
|
25
|
+
context: str | None = None
|
|
26
|
+
category: str | None = None
|
|
27
|
+
author_type: str # agent, user
|
|
28
|
+
author_id: str
|
|
29
|
+
author_name: str | None = None
|
|
30
|
+
is_resolved: bool = False
|
|
31
|
+
created_at: str
|
|
32
|
+
updated_at: str
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
class PRDDocument(BaseModel):
|
|
36
|
+
"""PRD document model."""
|
|
37
|
+
|
|
38
|
+
id: str
|
|
39
|
+
project_id: str
|
|
40
|
+
title: str
|
|
41
|
+
content: str
|
|
42
|
+
source: str
|
|
43
|
+
source_file_name: str | None = None
|
|
44
|
+
status: str # draft, analyzing, clarifying, planning, ready, completed
|
|
45
|
+
implementation_plan: dict[str, Any] | None = None
|
|
46
|
+
run_id: str | None = None
|
|
47
|
+
created_by: str
|
|
48
|
+
created_at: str
|
|
49
|
+
updated_at: str
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
class PRDClient(SteerDevClient):
|
|
53
|
+
"""API client for PRD operations.
|
|
54
|
+
|
|
55
|
+
Used by the agent to:
|
|
56
|
+
- Get PRD document content
|
|
57
|
+
- Post analysis questions as comments
|
|
58
|
+
- Update PRD status
|
|
59
|
+
- Save implementation plans
|
|
60
|
+
"""
|
|
61
|
+
|
|
62
|
+
def get_prd(self, prd_id: str) -> PRDDocument | None:
|
|
63
|
+
"""Get a PRD document by ID.
|
|
64
|
+
|
|
65
|
+
Args:
|
|
66
|
+
prd_id: PRD document ID.
|
|
67
|
+
|
|
68
|
+
Returns:
|
|
69
|
+
PRD document or None if not found.
|
|
70
|
+
"""
|
|
71
|
+
try:
|
|
72
|
+
response = self.get(f"/prd/{prd_id}")
|
|
73
|
+
|
|
74
|
+
if response.status_code == 200:
|
|
75
|
+
data = response.json()
|
|
76
|
+
return PRDDocument(**data)
|
|
77
|
+
if response.status_code == 404:
|
|
78
|
+
return None
|
|
79
|
+
|
|
80
|
+
logger.error(f"Failed to get PRD: {response.status_code} - {response.text}")
|
|
81
|
+
return None
|
|
82
|
+
|
|
83
|
+
except Exception as e:
|
|
84
|
+
logger.error(f"Error getting PRD: {e}")
|
|
85
|
+
return None
|
|
86
|
+
|
|
87
|
+
def update_prd_status(self, prd_id: str, status: str) -> PRDDocument | None:
|
|
88
|
+
"""Update PRD status.
|
|
89
|
+
|
|
90
|
+
Args:
|
|
91
|
+
prd_id: PRD document ID.
|
|
92
|
+
status: New status value.
|
|
93
|
+
|
|
94
|
+
Returns:
|
|
95
|
+
Updated PRD document or None on failure.
|
|
96
|
+
"""
|
|
97
|
+
try:
|
|
98
|
+
response = self.patch(f"/prd/{prd_id}", json={"status": status})
|
|
99
|
+
|
|
100
|
+
if response.status_code == 200:
|
|
101
|
+
data = response.json()
|
|
102
|
+
return PRDDocument(**data)
|
|
103
|
+
|
|
104
|
+
logger.error(f"Failed to update PRD status: {response.status_code} - {response.text}")
|
|
105
|
+
return None
|
|
106
|
+
|
|
107
|
+
except Exception as e:
|
|
108
|
+
logger.error(f"Error updating PRD status: {e}")
|
|
109
|
+
return None
|
|
110
|
+
|
|
111
|
+
def save_implementation_plan(
|
|
112
|
+
self,
|
|
113
|
+
prd_id: str,
|
|
114
|
+
plan: dict[str, Any],
|
|
115
|
+
) -> PRDDocument | None:
|
|
116
|
+
"""Save implementation plan to PRD document.
|
|
117
|
+
|
|
118
|
+
Args:
|
|
119
|
+
prd_id: PRD document ID.
|
|
120
|
+
plan: Implementation plan dictionary.
|
|
121
|
+
|
|
122
|
+
Returns:
|
|
123
|
+
Updated PRD document or None on failure.
|
|
124
|
+
"""
|
|
125
|
+
try:
|
|
126
|
+
response = self.patch(
|
|
127
|
+
f"/prd/{prd_id}",
|
|
128
|
+
json={
|
|
129
|
+
"implementation_plan": plan,
|
|
130
|
+
"status": "ready",
|
|
131
|
+
},
|
|
132
|
+
)
|
|
133
|
+
|
|
134
|
+
if response.status_code == 200:
|
|
135
|
+
data = response.json()
|
|
136
|
+
return PRDDocument(**data)
|
|
137
|
+
|
|
138
|
+
logger.error(
|
|
139
|
+
f"Failed to save implementation plan: {response.status_code} - {response.text}"
|
|
140
|
+
)
|
|
141
|
+
return None
|
|
142
|
+
|
|
143
|
+
except Exception as e:
|
|
144
|
+
logger.error(f"Error saving implementation plan: {e}")
|
|
145
|
+
return None
|
|
146
|
+
|
|
147
|
+
def post_questions(
|
|
148
|
+
self,
|
|
149
|
+
prd_id: str,
|
|
150
|
+
questions: list[dict[str, str]],
|
|
151
|
+
agent_id: str,
|
|
152
|
+
agent_name: str = "SteerDev Agent",
|
|
153
|
+
) -> list[PRDComment]:
|
|
154
|
+
"""Post analysis questions as comments.
|
|
155
|
+
|
|
156
|
+
Args:
|
|
157
|
+
prd_id: PRD document ID.
|
|
158
|
+
questions: List of question dicts with keys: question, context, category.
|
|
159
|
+
agent_id: Agent ID posting the questions.
|
|
160
|
+
agent_name: Display name for the agent.
|
|
161
|
+
|
|
162
|
+
Returns:
|
|
163
|
+
List of created comments.
|
|
164
|
+
"""
|
|
165
|
+
try:
|
|
166
|
+
comments_data = [
|
|
167
|
+
{
|
|
168
|
+
"content": q.get("question", ""),
|
|
169
|
+
"comment_type": "question",
|
|
170
|
+
"context": q.get("context"),
|
|
171
|
+
"category": q.get("category"),
|
|
172
|
+
"author_type": "agent",
|
|
173
|
+
"author_id": agent_id,
|
|
174
|
+
"author_name": agent_name,
|
|
175
|
+
}
|
|
176
|
+
for q in questions
|
|
177
|
+
]
|
|
178
|
+
|
|
179
|
+
response = self.post(
|
|
180
|
+
f"/prd/{prd_id}/comments",
|
|
181
|
+
json={"comments": comments_data},
|
|
182
|
+
)
|
|
183
|
+
|
|
184
|
+
if response.status_code == 201:
|
|
185
|
+
data = response.json()
|
|
186
|
+
return [PRDComment(**c) for c in data.get("comments", [])]
|
|
187
|
+
|
|
188
|
+
logger.error(f"Failed to post questions: {response.status_code} - {response.text}")
|
|
189
|
+
return []
|
|
190
|
+
|
|
191
|
+
except Exception as e:
|
|
192
|
+
logger.error(f"Error posting questions: {e}")
|
|
193
|
+
return []
|
|
194
|
+
|
|
195
|
+
def get_comments(self, prd_id: str) -> list[PRDComment]:
|
|
196
|
+
"""Get all comments for a PRD.
|
|
197
|
+
|
|
198
|
+
Args:
|
|
199
|
+
prd_id: PRD document ID.
|
|
200
|
+
|
|
201
|
+
Returns:
|
|
202
|
+
List of comments.
|
|
203
|
+
"""
|
|
204
|
+
try:
|
|
205
|
+
response = self.get(f"/prd/{prd_id}/comments")
|
|
206
|
+
|
|
207
|
+
if response.status_code == 200:
|
|
208
|
+
data = response.json()
|
|
209
|
+
return [PRDComment(**c) for c in data.get("comments", [])]
|
|
210
|
+
|
|
211
|
+
logger.error(f"Failed to get comments: {response.status_code} - {response.text}")
|
|
212
|
+
return []
|
|
213
|
+
|
|
214
|
+
except Exception as e:
|
|
215
|
+
logger.error(f"Error getting comments: {e}")
|
|
216
|
+
return []
|
|
217
|
+
|
|
218
|
+
def resolve_comment(self, prd_id: str, comment_id: str) -> PRDComment | None:
|
|
219
|
+
"""Mark a question as resolved.
|
|
220
|
+
|
|
221
|
+
Args:
|
|
222
|
+
prd_id: PRD document ID.
|
|
223
|
+
comment_id: Comment ID to resolve.
|
|
224
|
+
|
|
225
|
+
Returns:
|
|
226
|
+
Updated comment or None on failure.
|
|
227
|
+
"""
|
|
228
|
+
try:
|
|
229
|
+
response = self.post(f"/prd/{prd_id}/comments/{comment_id}/resolve")
|
|
230
|
+
|
|
231
|
+
if response.status_code == 200:
|
|
232
|
+
data = response.json()
|
|
233
|
+
return PRDComment(**data)
|
|
234
|
+
|
|
235
|
+
logger.error(f"Failed to resolve comment: {response.status_code} - {response.text}")
|
|
236
|
+
return None
|
|
237
|
+
|
|
238
|
+
except Exception as e:
|
|
239
|
+
logger.error(f"Error resolving comment: {e}")
|
|
240
|
+
return None
|
|
241
|
+
|
|
242
|
+
def post_note(
|
|
243
|
+
self,
|
|
244
|
+
prd_id: str,
|
|
245
|
+
content: str,
|
|
246
|
+
agent_id: str,
|
|
247
|
+
agent_name: str = "SteerDev Agent",
|
|
248
|
+
) -> PRDComment | None:
|
|
249
|
+
"""Post a general note as a comment.
|
|
250
|
+
|
|
251
|
+
Args:
|
|
252
|
+
prd_id: PRD document ID.
|
|
253
|
+
content: Note content.
|
|
254
|
+
agent_id: Agent ID posting the note.
|
|
255
|
+
agent_name: Display name for the agent.
|
|
256
|
+
|
|
257
|
+
Returns:
|
|
258
|
+
Created comment or None on failure.
|
|
259
|
+
"""
|
|
260
|
+
try:
|
|
261
|
+
response = self.post(
|
|
262
|
+
f"/prd/{prd_id}/comments",
|
|
263
|
+
json={
|
|
264
|
+
"content": content,
|
|
265
|
+
"comment_type": "note",
|
|
266
|
+
"author_type": "agent",
|
|
267
|
+
"author_id": agent_id,
|
|
268
|
+
"author_name": agent_name,
|
|
269
|
+
},
|
|
270
|
+
)
|
|
271
|
+
|
|
272
|
+
if response.status_code == 201:
|
|
273
|
+
data = response.json()
|
|
274
|
+
return PRDComment(**data)
|
|
275
|
+
|
|
276
|
+
logger.error(f"Failed to post note: {response.status_code} - {response.text}")
|
|
277
|
+
return None
|
|
278
|
+
|
|
279
|
+
except Exception as e:
|
|
280
|
+
logger.error(f"Error posting note: {e}")
|
|
281
|
+
return None
|