codee-agent 0.1.0__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.
- codee/.gitignore +2 -0
- codee/__init__.py +0 -0
- codee/admin.py +1672 -0
- codee/admin_api.py +61 -0
- codee/admin_cli.py +86 -0
- codee/admin_service.py +1005 -0
- codee/executor.py +381 -0
- codee/init_cli.py +82 -0
- codee/lib/__init__.py +0 -0
- codee/lib/cron_describe.py +33 -0
- codee/lib/runs_db.py +195 -0
- codee/lib/test_runs_db.py +199 -0
- codee/lib/test_trigger_cron_skills.py +485 -0
- codee/lib/test_trigger_issue_skills.py +93 -0
- codee/lib/trigger_aws_sqs_skills.py +224 -0
- codee/lib/trigger_cron_skills.py +364 -0
- codee/lib/trigger_email_skills.py +225 -0
- codee/lib/trigger_issue_skills.py +107 -0
- codee/mail_server.py +45 -0
- codee/start_cli.py +98 -0
- codee/templates/AGENTS.md +42 -0
- codee/templates/CLAUDE.md +1 -0
- codee/templates/skills/aws-sqs-alarm-response/SKILL.md +23 -0
- codee/templates/skills/cron-research-5xx-errors/SKILL.md +17 -0
- codee/templates/skills/story-code-reviewer/SKILL.md +29 -0
- codee/templates/skills/story-developer/SKILL.md +26 -0
- codee/templates/skills/story-planner/SKILL.md +35 -0
- codee/templates/skills/story-planner/assets/readme-template.md +43 -0
- codee/templates/skills/story-qa/SKILL.md +28 -0
- codee/templates/skills/task-developer/SKILL.md +25 -0
- codee/templates/skills/task-qa/SKILL.md +26 -0
- codee/test_admin_api.py +64 -0
- codee/test_admin_cli.py +63 -0
- codee/test_admin_service.py +897 -0
- codee/test_executor.py +190 -0
- codee/test_init_cli.py +131 -0
- codee/test_memory_index.py +31 -0
- codee/test_start_cli.py +164 -0
- codee/workflow_graph.py +83 -0
- codee_admin/__init__.py +1 -0
- codee_admin/codee_admin.py +4 -0
- codee_agent-0.1.0.dist-info/METADATA +66 -0
- codee_agent-0.1.0.dist-info/RECORD +69 -0
- codee_agent-0.1.0.dist-info/WHEEL +4 -0
- codee_agent-0.1.0.dist-info/entry_points.txt +6 -0
- codee_agent-0.1.0.dist-info/licenses/LICENSE +21 -0
- codee_agent_abstract/__init__.py +0 -0
- codee_agent_abstract/provider.py +56 -0
- codee_agent_claude_code/__init__.py +0 -0
- codee_agent_claude_code/provider.py +90 -0
- codee_agent_github_copilot/__init__.py +0 -0
- codee_agent_github_copilot/provider.py +253 -0
- codee_agent_github_copilot/test.py +176 -0
- codee_database/__init__.py +0 -0
- codee_database/database.py +13 -0
- codee_database/oauth_tokens.py +148 -0
- codee_main_context/__init__.py +0 -0
- codee_main_context/context.py +127 -0
- codee_main_context/logging.py +111 -0
- codee_main_context/test_logging.py +90 -0
- codee_tasks_abstract/__init__.py +0 -0
- codee_tasks_abstract/provider.py +58 -0
- codee_tasks_azure_devops/__init__.py +0 -0
- codee_tasks_azure_devops/oauth.py +346 -0
- codee_tasks_azure_devops/provider.py +207 -0
- codee_tasks_azure_devops/test.py +462 -0
- codee_tasks_jira/__init__.py +0 -0
- codee_tasks_jira/provider.py +162 -0
- codee_tasks_jira/test.py +75 -0
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
# {STORY_ID}: {STORY_TITLE}
|
|
2
|
+
|
|
3
|
+
**Issue Tracker:** {ISSUE_URL}
|
|
4
|
+
**Created:** {DATE}
|
|
5
|
+
|
|
6
|
+
## Background
|
|
7
|
+
|
|
8
|
+
{Describe the problem, its impact, and the expected outcome.}
|
|
9
|
+
|
|
10
|
+
## Technical Approach
|
|
11
|
+
|
|
12
|
+
{Describe the proposed approach and the affected projects.}
|
|
13
|
+
|
|
14
|
+
| Project | Changes |
|
|
15
|
+
|---------|---------|
|
|
16
|
+
| {project} | {brief description} |
|
|
17
|
+
|
|
18
|
+
## Subtasks
|
|
19
|
+
|
|
20
|
+
| # | ID | Title | Estimate | Dependencies |
|
|
21
|
+
|---|----|-------|----------|--------------|
|
|
22
|
+
| 1 | {ID} | {title} | {hours}h | None |
|
|
23
|
+
|
|
24
|
+
### 1. {Subtask Title}
|
|
25
|
+
|
|
26
|
+
**ID:** {SUBTASK_ID}
|
|
27
|
+
**Estimate:** {hours}h
|
|
28
|
+
|
|
29
|
+
{Describe the implementation scope and approach.}
|
|
30
|
+
|
|
31
|
+
**Acceptance Criteria:**
|
|
32
|
+
|
|
33
|
+
- [ ] {criterion}
|
|
34
|
+
|
|
35
|
+
## Coverage
|
|
36
|
+
|
|
37
|
+
| Story Acceptance Criterion | Covered By |
|
|
38
|
+
|----------------------------|------------|
|
|
39
|
+
| {criterion} | {subtask IDs} |
|
|
40
|
+
|
|
41
|
+
## Open Questions
|
|
42
|
+
|
|
43
|
+
- None
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: story-qa
|
|
3
|
+
description: Validate one subtask from an Issue Tracker story against its acceptance criteria.
|
|
4
|
+
disable-model-invocation: true
|
|
5
|
+
x-codee-trigger: issue
|
|
6
|
+
x-codee-issue-status: ['[AI] Ready for QA']
|
|
7
|
+
x-codee-issue-type: story
|
|
8
|
+
argument-hint: <STORY_ID>
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
# Story QA
|
|
12
|
+
|
|
13
|
+
Validate one subtask per invocation. QA is read-only: do not modify the implementation or merge its merge request.
|
|
14
|
+
|
|
15
|
+
## Workflow
|
|
16
|
+
|
|
17
|
+
1. Read the story, acceptance criteria, attachments, comments, subtasks, and `story-spec/{STORY_ID}/README.md` when present.
|
|
18
|
+
2. Select one delivered subtask that needs verification and locate its merge request and test environment.
|
|
19
|
+
3. Read project instructions and relevant implementation details.
|
|
20
|
+
4. Create a QA plan mapping every applicable acceptance criterion to a scenario, environment, method, and expected result.
|
|
21
|
+
5. Execute each scenario and record the actual result.
|
|
22
|
+
6. For UI work, test important paths, edge cases, responsive layout, keyboard behavior, and browser console output. Capture screenshots for static evidence and video for dynamic interactions.
|
|
23
|
+
7. For service work, test success, validation, authorization, and edge cases. Record requests, responses, HTTP codes, and relevant side effects.
|
|
24
|
+
8. Mark each criterion pass or fail and separate blocking defects from non-blocking observations.
|
|
25
|
+
9. Post a concise Issue Tracker report with the results, evidence, environment, and actionable reproduction steps for failures.
|
|
26
|
+
10. Update the story specification with a short QA summary when useful.
|
|
27
|
+
|
|
28
|
+
Create a separate Issue Tracker item for unrelated defects instead of expanding the subtask.
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: task-developer
|
|
3
|
+
description: Implement a standalone Issue Tracker task and submit a merge request.
|
|
4
|
+
disable-model-invocation: true
|
|
5
|
+
x-codee-trigger: issue
|
|
6
|
+
x-codee-issue-status: ['[AI] Ready for development', '[AI] In Progress', Reopened]
|
|
7
|
+
x-codee-issue-type: task
|
|
8
|
+
argument-hint: <TASK_ID> [continue]
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
# Task Developer
|
|
12
|
+
|
|
13
|
+
## Workflow
|
|
14
|
+
|
|
15
|
+
1. Read the task, acceptance criteria, attachments, and comments in the Issue Tracker. With `continue`, also read new merge request feedback.
|
|
16
|
+
2. Read the affected projects' `CLAUDE.md`, `AGENTS.md`, and relevant local skills.
|
|
17
|
+
3. For bugs and regressions, reproduce the problem and identify the root cause before editing code. Report evidence when the issue cannot be reproduced or the root cause remains unclear.
|
|
18
|
+
4. Create or reuse a dedicated worktree and branch according to repository conventions.
|
|
19
|
+
5. Install dependencies and implement the smallest complete change that satisfies the acceptance criteria.
|
|
20
|
+
6. Run focused tests, the project build, and browser validation for UI work.
|
|
21
|
+
7. Review the complete diff for correctness, security, regressions, and missing tests.
|
|
22
|
+
8. Commit, push, and create or update the merge request. Do not merge it unless explicitly requested.
|
|
23
|
+
9. Add a concise Issue Tracker comment describing the change, validation, merge request, and any remaining risk.
|
|
24
|
+
|
|
25
|
+
For UI work, include screenshots or video evidence when appropriate. On continued work, always refresh the Issue Tracker item and merge request before acting.
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: task-qa
|
|
3
|
+
description: Validate a standalone Issue Tracker task against its acceptance criteria.
|
|
4
|
+
disable-model-invocation: true
|
|
5
|
+
x-codee-trigger: issue
|
|
6
|
+
x-codee-issue-status: ['[AI] Ready for QA']
|
|
7
|
+
x-codee-issue-type: task
|
|
8
|
+
argument-hint: <TASK_ID>
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
# Task QA Engineer
|
|
12
|
+
|
|
13
|
+
QA is read-only: do not modify the implementation or merge its merge request.
|
|
14
|
+
|
|
15
|
+
## Workflow
|
|
16
|
+
|
|
17
|
+
1. Read the task, acceptance criteria, attachments, and comments in the Issue Tracker.
|
|
18
|
+
2. Locate the merge request and test environment, then read relevant project instructions and implementation details.
|
|
19
|
+
3. Create a QA plan mapping every acceptance criterion to a scenario, environment, method, and expected result.
|
|
20
|
+
4. Execute each scenario and record the actual result.
|
|
21
|
+
5. For UI work, test important paths, edge cases, responsive layout, keyboard behavior, and browser console output. Capture screenshots for static evidence and video for dynamic interactions.
|
|
22
|
+
6. For service work, test success, validation, authorization, and edge cases. Record requests, responses, HTTP codes, and relevant side effects.
|
|
23
|
+
7. Mark each criterion pass or fail and separate blocking defects from non-blocking observations.
|
|
24
|
+
8. Post a concise Issue Tracker report with the results, evidence, environment, and actionable reproduction steps for failures.
|
|
25
|
+
|
|
26
|
+
Create a separate Issue Tracker item for unrelated defects instead of expanding the task.
|
codee/test_admin_api.py
ADDED
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import unittest
|
|
2
|
+
from unittest.mock import patch
|
|
3
|
+
|
|
4
|
+
from starlette.testclient import TestClient
|
|
5
|
+
|
|
6
|
+
from codee import admin_api
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class AzureDevOpsCallbackTest(unittest.TestCase):
|
|
10
|
+
"""The OAuth callback route: never renders, always bounces back to /settings."""
|
|
11
|
+
|
|
12
|
+
def setUp(self) -> None:
|
|
13
|
+
# follow_redirects off: the 303 target is the thing under test.
|
|
14
|
+
self.client = TestClient(admin_api.api_app, follow_redirects=False)
|
|
15
|
+
|
|
16
|
+
def _location(self, response) -> str:
|
|
17
|
+
self.assertEqual(response.status_code, 303)
|
|
18
|
+
return response.headers["location"]
|
|
19
|
+
|
|
20
|
+
def test_successful_callback_redirects_with_the_outcome(self) -> None:
|
|
21
|
+
with patch.object(admin_api._service, "complete_azure_authorization",
|
|
22
|
+
return_value=(True, "Connected to Azure DevOps as dev@acme.com")) as complete:
|
|
23
|
+
response = self.client.get(
|
|
24
|
+
admin_api.CALLBACK_PATH, params={"code": "code-1", "state": "state-1"})
|
|
25
|
+
|
|
26
|
+
complete.assert_called_once_with("code-1", "state-1")
|
|
27
|
+
location = self._location(response)
|
|
28
|
+
self.assertTrue(location.startswith("/settings?"))
|
|
29
|
+
self.assertIn("azure=connected", location)
|
|
30
|
+
self.assertIn("dev%40acme.com", location)
|
|
31
|
+
|
|
32
|
+
def test_failed_exchange_redirects_as_an_error(self) -> None:
|
|
33
|
+
with patch.object(admin_api._service, "complete_azure_authorization",
|
|
34
|
+
return_value=(False, "Invalid client secret.")):
|
|
35
|
+
response = self.client.get(
|
|
36
|
+
admin_api.CALLBACK_PATH, params={"code": "code-1", "state": "state-1"})
|
|
37
|
+
|
|
38
|
+
self.assertIn("azure=error", self._location(response))
|
|
39
|
+
|
|
40
|
+
def test_refused_consent_reports_azures_own_message(self) -> None:
|
|
41
|
+
with patch.object(admin_api._service, "complete_azure_authorization") as complete:
|
|
42
|
+
response = self.client.get(admin_api.CALLBACK_PATH, params={
|
|
43
|
+
"error": "access_denied",
|
|
44
|
+
"error_description": "AADSTS65004: User declined.\r\nTrace ID: abc",
|
|
45
|
+
})
|
|
46
|
+
|
|
47
|
+
complete.assert_not_called()
|
|
48
|
+
location = self._location(response)
|
|
49
|
+
self.assertIn("azure=error", location)
|
|
50
|
+
self.assertIn("User+declined.", location)
|
|
51
|
+
# The trace id lines are noise in a toast.
|
|
52
|
+
self.assertNotIn("Trace", location)
|
|
53
|
+
|
|
54
|
+
def test_callback_without_a_code_is_rejected(self) -> None:
|
|
55
|
+
with patch.object(admin_api._service, "complete_azure_authorization") as complete:
|
|
56
|
+
response = self.client.get(
|
|
57
|
+
admin_api.CALLBACK_PATH, params={"state": "state-1"})
|
|
58
|
+
|
|
59
|
+
complete.assert_not_called()
|
|
60
|
+
self.assertIn("azure=error", self._location(response))
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
if __name__ == "__main__":
|
|
64
|
+
unittest.main()
|
codee/test_admin_cli.py
ADDED
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import os
|
|
2
|
+
import sys
|
|
3
|
+
import tempfile
|
|
4
|
+
import unittest
|
|
5
|
+
from pathlib import Path
|
|
6
|
+
from unittest.mock import patch
|
|
7
|
+
|
|
8
|
+
from codee.admin_cli import RXCONFIG, _runtime_directory, main
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class AdminCliTest(unittest.TestCase):
|
|
12
|
+
def test_runtime_directory_writes_reflex_config(self) -> None:
|
|
13
|
+
with tempfile.TemporaryDirectory() as temporary_directory:
|
|
14
|
+
root = Path(temporary_directory)
|
|
15
|
+
with patch("codee.admin_cli.data_dir", return_value=root / ".codee"):
|
|
16
|
+
runtime = _runtime_directory(root)
|
|
17
|
+
|
|
18
|
+
self.assertEqual(runtime, root / ".codee" / "reflex")
|
|
19
|
+
self.assertEqual((runtime / "rxconfig.py").read_text(), RXCONFIG)
|
|
20
|
+
|
|
21
|
+
def test_main_launches_single_port_reflex(self) -> None:
|
|
22
|
+
original_directory = Path.cwd()
|
|
23
|
+
with tempfile.TemporaryDirectory() as temporary_directory:
|
|
24
|
+
root = Path(temporary_directory)
|
|
25
|
+
try:
|
|
26
|
+
with (
|
|
27
|
+
patch("codee.admin_cli.project_root", return_value=root),
|
|
28
|
+
patch("codee.admin_cli.data_dir",
|
|
29
|
+
return_value=root / ".codee"),
|
|
30
|
+
patch("reflex.reflex.cli") as reflex_cli,
|
|
31
|
+
patch.object(
|
|
32
|
+
sys, "argv", ["codee-admin", "--port", "8502"]),
|
|
33
|
+
):
|
|
34
|
+
self.assertEqual(main(), 0)
|
|
35
|
+
launched_argv = sys.argv.copy()
|
|
36
|
+
|
|
37
|
+
reflex_cli.assert_called_once_with()
|
|
38
|
+
self.assertEqual(
|
|
39
|
+
launched_argv,
|
|
40
|
+
[
|
|
41
|
+
"reflex",
|
|
42
|
+
"run",
|
|
43
|
+
"--env",
|
|
44
|
+
"prod",
|
|
45
|
+
"--single-port",
|
|
46
|
+
"--frontend-port",
|
|
47
|
+
"8502",
|
|
48
|
+
],
|
|
49
|
+
)
|
|
50
|
+
self.assertEqual(Path.cwd().resolve(),
|
|
51
|
+
(root / ".codee" / "reflex").resolve())
|
|
52
|
+
self.assertEqual(
|
|
53
|
+
Path(os.environ["CODEE_PROJECT_ROOT"]
|
|
54
|
+
).resolve(), root.resolve()
|
|
55
|
+
)
|
|
56
|
+
self.assertEqual(
|
|
57
|
+
os.environ["REFLEX_API_URL"], "http://127.0.0.1:8502")
|
|
58
|
+
finally:
|
|
59
|
+
os.chdir(original_directory)
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
if __name__ == "__main__":
|
|
63
|
+
unittest.main()
|