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
codee/admin_api.py
ADDED
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
"""Plain HTTP endpoints served alongside the Reflex pages.
|
|
2
|
+
|
|
3
|
+
OAuth callbacks can't be Reflex pages: the authorization code would have to
|
|
4
|
+
travel through the browser and into a page's ``on_load`` before anything could
|
|
5
|
+
be done with it. Handling them as backend routes keeps the code and the client
|
|
6
|
+
secret server-side, and lets the browser be bounced straight back to /settings.
|
|
7
|
+
|
|
8
|
+
Reflex mounts its own ASGI app underneath this Starlette app (see
|
|
9
|
+
``api_transformer`` in :mod:`codee.admin`), so these routes are matched first
|
|
10
|
+
and everything else falls through to the UI.
|
|
11
|
+
"""
|
|
12
|
+
from urllib.parse import urlencode
|
|
13
|
+
|
|
14
|
+
from starlette.applications import Starlette
|
|
15
|
+
from starlette.requests import Request
|
|
16
|
+
from starlette.responses import RedirectResponse
|
|
17
|
+
from starlette.routing import Route
|
|
18
|
+
|
|
19
|
+
from codee.admin_service import AdminService
|
|
20
|
+
from codee_tasks_azure_devops.oauth import CALLBACK_PATH
|
|
21
|
+
|
|
22
|
+
SETTINGS_PATH = "/settings"
|
|
23
|
+
|
|
24
|
+
# Its own service instance: this route runs outside any Reflex session, and
|
|
25
|
+
# every handler re-reads settings from disk anyway.
|
|
26
|
+
_service = AdminService()
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
def _back_to_settings(connected: bool, message: str) -> RedirectResponse:
|
|
30
|
+
"""Return to the settings page carrying the outcome for the UI to toast."""
|
|
31
|
+
query = urlencode(
|
|
32
|
+
{"azure": "connected" if connected else "error", "message": message})
|
|
33
|
+
# 303: the callback is a GET, and the browser should land on /settings as a
|
|
34
|
+
# fresh GET rather than replaying anything.
|
|
35
|
+
return RedirectResponse(f"{SETTINGS_PATH}?{query}", status_code=303)
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
def azure_devops_callback(request: Request) -> RedirectResponse:
|
|
39
|
+
"""Entra ID redirects here with ?code&state, or with ?error on refusal.
|
|
40
|
+
|
|
41
|
+
Defined as a sync handler on purpose: the token exchange is a blocking HTTP
|
|
42
|
+
call, so Starlette runs it in a worker thread instead of stalling the event
|
|
43
|
+
loop that serves the rest of the admin UI.
|
|
44
|
+
"""
|
|
45
|
+
params = request.query_params
|
|
46
|
+
if params.get("error"):
|
|
47
|
+
description = params.get("error_description") or params["error"]
|
|
48
|
+
return _back_to_settings(False, description.splitlines()[0])
|
|
49
|
+
|
|
50
|
+
code, state = params.get("code"), params.get("state")
|
|
51
|
+
if not code or not state:
|
|
52
|
+
return _back_to_settings(
|
|
53
|
+
False, "Azure DevOps did not return an authorization code.")
|
|
54
|
+
|
|
55
|
+
connected, message = _service.complete_azure_authorization(code, state)
|
|
56
|
+
return _back_to_settings(connected, message)
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
api_app = Starlette(routes=[
|
|
60
|
+
Route(CALLBACK_PATH, azure_devops_callback, methods=["GET"]),
|
|
61
|
+
])
|
codee/admin_cli.py
ADDED
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
"""Console-script launcher for the Reflex admin UI."""
|
|
2
|
+
import argparse
|
|
3
|
+
import os
|
|
4
|
+
import sys
|
|
5
|
+
from pathlib import Path
|
|
6
|
+
|
|
7
|
+
from codee.admin_service import DEFAULT_ADMIN_PORT
|
|
8
|
+
from codee_main_context.context import data_dir, project_root
|
|
9
|
+
from codee_main_context.logging import (
|
|
10
|
+
configure_logging, enable_debug, get_logger, verbose_debug_enabled)
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
log = get_logger(__name__)
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
RXCONFIG = """import reflex as rx
|
|
17
|
+
|
|
18
|
+
config = rx.Config(
|
|
19
|
+
app_name="codee_admin",
|
|
20
|
+
telemetry_enabled=False,
|
|
21
|
+
show_built_with_reflex=False,
|
|
22
|
+
plugins=[
|
|
23
|
+
rx.plugins.RadixThemesPlugin(
|
|
24
|
+
theme=rx.theme(
|
|
25
|
+
accent_color="green",
|
|
26
|
+
gray_color="sage",
|
|
27
|
+
radius="small",
|
|
28
|
+
appearance="inherit",
|
|
29
|
+
)
|
|
30
|
+
),
|
|
31
|
+
],
|
|
32
|
+
disable_plugins=[rx.plugins.SitemapPlugin],
|
|
33
|
+
)
|
|
34
|
+
"""
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
def _runtime_directory(root: Path) -> Path:
|
|
38
|
+
runtime = data_dir(root) / "reflex"
|
|
39
|
+
runtime.mkdir(parents=True, exist_ok=True)
|
|
40
|
+
config_path = runtime / "rxconfig.py"
|
|
41
|
+
if not config_path.exists() or config_path.read_text() != RXCONFIG:
|
|
42
|
+
config_path.write_text(RXCONFIG)
|
|
43
|
+
return runtime
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
def main() -> int:
|
|
47
|
+
parser = argparse.ArgumentParser(prog="codee-admin")
|
|
48
|
+
parser.add_argument("--port", "--server.port",
|
|
49
|
+
dest="port", type=int, default=DEFAULT_ADMIN_PORT)
|
|
50
|
+
parser.add_argument("-d", "--debug", action="store_true",
|
|
51
|
+
help="log debug messages")
|
|
52
|
+
arguments, reflex_arguments = parser.parse_known_args()
|
|
53
|
+
|
|
54
|
+
if arguments.debug:
|
|
55
|
+
enable_debug()
|
|
56
|
+
configure_logging()
|
|
57
|
+
|
|
58
|
+
root = project_root().resolve()
|
|
59
|
+
codee_data = data_dir(root).resolve()
|
|
60
|
+
os.environ["CODEE_PROJECT_ROOT"] = str(root)
|
|
61
|
+
os.environ["CODEE_DATA_DIR"] = str(codee_data)
|
|
62
|
+
os.environ["REFLEX_API_URL"] = f"http://127.0.0.1:{arguments.port}"
|
|
63
|
+
os.chdir(_runtime_directory(root))
|
|
64
|
+
|
|
65
|
+
from reflex.reflex import cli
|
|
66
|
+
|
|
67
|
+
sys.argv = [
|
|
68
|
+
"reflex",
|
|
69
|
+
"run",
|
|
70
|
+
"--env",
|
|
71
|
+
"prod",
|
|
72
|
+
"--single-port",
|
|
73
|
+
"--frontend-port",
|
|
74
|
+
str(arguments.port),
|
|
75
|
+
# Reflex keeps its own logger; only CODEE_DEBUG=all turns it up, since
|
|
76
|
+
# its debug output is far noisier than ours.
|
|
77
|
+
*(["--loglevel", "debug"] if verbose_debug_enabled() else []),
|
|
78
|
+
*reflex_arguments,
|
|
79
|
+
]
|
|
80
|
+
log.debug("root=%s data=%s reflex argv=%s", root, codee_data, sys.argv)
|
|
81
|
+
cli()
|
|
82
|
+
return 0
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
if __name__ == "__main__":
|
|
86
|
+
sys.exit(main())
|