codee-agent 0.4.1__tar.gz → 0.4.2__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.
- {codee_agent-0.4.1 → codee_agent-0.4.2}/PKG-INFO +1 -1
- {codee_agent-0.4.1 → codee_agent-0.4.2}/pyproject.toml +1 -1
- {codee_agent-0.4.1 → codee_agent-0.4.2}/src/codee_agent_github_copilot/provider.py +27 -6
- {codee_agent-0.4.1 → codee_agent-0.4.2}/src/codee_agent_github_copilot/test.py +33 -1
- {codee_agent-0.4.1 → codee_agent-0.4.2}/LICENSE +0 -0
- {codee_agent-0.4.1 → codee_agent-0.4.2}/README.md +0 -0
- {codee_agent-0.4.1 → codee_agent-0.4.2}/src/codee/.gitignore +0 -0
- {codee_agent-0.4.1 → codee_agent-0.4.2}/src/codee/__init__.py +0 -0
- {codee_agent-0.4.1 → codee_agent-0.4.2}/src/codee/admin.py +0 -0
- {codee_agent-0.4.1 → codee_agent-0.4.2}/src/codee/admin_api.py +0 -0
- {codee_agent-0.4.1 → codee_agent-0.4.2}/src/codee/admin_cli.py +0 -0
- {codee_agent-0.4.1 → codee_agent-0.4.2}/src/codee/admin_service.py +0 -0
- {codee_agent-0.4.1 → codee_agent-0.4.2}/src/codee/executor.py +0 -0
- {codee_agent-0.4.1 → codee_agent-0.4.2}/src/codee/init_cli.py +0 -0
- {codee_agent-0.4.1 → codee_agent-0.4.2}/src/codee/lib/__init__.py +0 -0
- {codee_agent-0.4.1 → codee_agent-0.4.2}/src/codee/lib/cron_describe.py +0 -0
- {codee_agent-0.4.1 → codee_agent-0.4.2}/src/codee/lib/mcp_config.py +0 -0
- {codee_agent-0.4.1 → codee_agent-0.4.2}/src/codee/lib/runs_db.py +0 -0
- {codee_agent-0.4.1 → codee_agent-0.4.2}/src/codee/lib/test_mcp_config.py +0 -0
- {codee_agent-0.4.1 → codee_agent-0.4.2}/src/codee/lib/test_runs_db.py +0 -0
- {codee_agent-0.4.1 → codee_agent-0.4.2}/src/codee/lib/test_trigger_cron_skills.py +0 -0
- {codee_agent-0.4.1 → codee_agent-0.4.2}/src/codee/lib/test_trigger_issue_skills.py +0 -0
- {codee_agent-0.4.1 → codee_agent-0.4.2}/src/codee/lib/trigger_aws_sqs_skills.py +0 -0
- {codee_agent-0.4.1 → codee_agent-0.4.2}/src/codee/lib/trigger_cron_skills.py +0 -0
- {codee_agent-0.4.1 → codee_agent-0.4.2}/src/codee/lib/trigger_email_skills.py +0 -0
- {codee_agent-0.4.1 → codee_agent-0.4.2}/src/codee/lib/trigger_issue_skills.py +0 -0
- {codee_agent-0.4.1 → codee_agent-0.4.2}/src/codee/mail_server.py +0 -0
- {codee_agent-0.4.1 → codee_agent-0.4.2}/src/codee/start_cli.py +0 -0
- {codee_agent-0.4.1 → codee_agent-0.4.2}/src/codee/tasks_providers.py +0 -0
- {codee_agent-0.4.1 → codee_agent-0.4.2}/src/codee/templates/AGENTS.md +0 -0
- {codee_agent-0.4.1 → codee_agent-0.4.2}/src/codee/templates/CLAUDE.md +0 -0
- {codee_agent-0.4.1 → codee_agent-0.4.2}/src/codee/templates/skills/aws-sqs-alarm-response/SKILL.md +0 -0
- {codee_agent-0.4.1 → codee_agent-0.4.2}/src/codee/templates/skills/cron-research-5xx-errors/SKILL.md +0 -0
- {codee_agent-0.4.1 → codee_agent-0.4.2}/src/codee/templates/skills/story-code-reviewer/SKILL.md +0 -0
- {codee_agent-0.4.1 → codee_agent-0.4.2}/src/codee/templates/skills/story-developer/SKILL.md +0 -0
- {codee_agent-0.4.1 → codee_agent-0.4.2}/src/codee/templates/skills/story-planner/SKILL.md +0 -0
- {codee_agent-0.4.1 → codee_agent-0.4.2}/src/codee/templates/skills/story-planner/assets/readme-template.md +0 -0
- {codee_agent-0.4.1 → codee_agent-0.4.2}/src/codee/templates/skills/story-qa/SKILL.md +0 -0
- {codee_agent-0.4.1 → codee_agent-0.4.2}/src/codee/templates/skills/task-developer/SKILL.md +0 -0
- {codee_agent-0.4.1 → codee_agent-0.4.2}/src/codee/templates/skills/task-qa/SKILL.md +0 -0
- {codee_agent-0.4.1 → codee_agent-0.4.2}/src/codee/test_admin_api.py +0 -0
- {codee_agent-0.4.1 → codee_agent-0.4.2}/src/codee/test_admin_cli.py +0 -0
- {codee_agent-0.4.1 → codee_agent-0.4.2}/src/codee/test_admin_service.py +0 -0
- {codee_agent-0.4.1 → codee_agent-0.4.2}/src/codee/test_executor.py +0 -0
- {codee_agent-0.4.1 → codee_agent-0.4.2}/src/codee/test_init_cli.py +0 -0
- {codee_agent-0.4.1 → codee_agent-0.4.2}/src/codee/test_memory_index.py +0 -0
- {codee_agent-0.4.1 → codee_agent-0.4.2}/src/codee/test_start_cli.py +0 -0
- {codee_agent-0.4.1 → codee_agent-0.4.2}/src/codee/workflow_graph.py +0 -0
- {codee_agent-0.4.1 → codee_agent-0.4.2}/src/codee_admin/__init__.py +0 -0
- {codee_agent-0.4.1 → codee_agent-0.4.2}/src/codee_admin/codee_admin.py +0 -0
- {codee_agent-0.4.1 → codee_agent-0.4.2}/src/codee_agent_abstract/__init__.py +0 -0
- {codee_agent-0.4.1 → codee_agent-0.4.2}/src/codee_agent_abstract/provider.py +0 -0
- {codee_agent-0.4.1 → codee_agent-0.4.2}/src/codee_agent_claude_code/__init__.py +0 -0
- {codee_agent-0.4.1 → codee_agent-0.4.2}/src/codee_agent_claude_code/provider.py +0 -0
- {codee_agent-0.4.1 → codee_agent-0.4.2}/src/codee_agent_github_copilot/__init__.py +0 -0
- {codee_agent-0.4.1 → codee_agent-0.4.2}/src/codee_database/__init__.py +0 -0
- {codee_agent-0.4.1 → codee_agent-0.4.2}/src/codee_database/database.py +0 -0
- {codee_agent-0.4.1 → codee_agent-0.4.2}/src/codee_database/oauth_tokens.py +0 -0
- {codee_agent-0.4.1 → codee_agent-0.4.2}/src/codee_main_context/__init__.py +0 -0
- {codee_agent-0.4.1 → codee_agent-0.4.2}/src/codee_main_context/context.py +0 -0
- {codee_agent-0.4.1 → codee_agent-0.4.2}/src/codee_main_context/logging.py +0 -0
- {codee_agent-0.4.1 → codee_agent-0.4.2}/src/codee_main_context/test_logging.py +0 -0
- {codee_agent-0.4.1 → codee_agent-0.4.2}/src/codee_tasks_abstract/__init__.py +0 -0
- {codee_agent-0.4.1 → codee_agent-0.4.2}/src/codee_tasks_abstract/provider.py +0 -0
- {codee_agent-0.4.1 → codee_agent-0.4.2}/src/codee_tasks_azure_devops/__init__.py +0 -0
- {codee_agent-0.4.1 → codee_agent-0.4.2}/src/codee_tasks_azure_devops/oauth.py +0 -0
- {codee_agent-0.4.1 → codee_agent-0.4.2}/src/codee_tasks_azure_devops/provider.py +0 -0
- {codee_agent-0.4.1 → codee_agent-0.4.2}/src/codee_tasks_azure_devops/test.py +0 -0
- {codee_agent-0.4.1 → codee_agent-0.4.2}/src/codee_tasks_jira/__init__.py +0 -0
- {codee_agent-0.4.1 → codee_agent-0.4.2}/src/codee_tasks_jira/provider.py +0 -0
- {codee_agent-0.4.1 → codee_agent-0.4.2}/src/codee_tasks_jira/test.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: codee-agent
|
|
3
|
-
Version: 0.4.
|
|
3
|
+
Version: 0.4.2
|
|
4
4
|
Summary: A virtual co-worker that picks up Jira and Azure DevOps tasks and solves them with coding agents.
|
|
5
5
|
Keywords: ai,agent,jira,azure-devops,claude-code,github-copilot,automation
|
|
6
6
|
Author: Denis Kibalko
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import json
|
|
2
|
+
import os
|
|
2
3
|
import queue
|
|
3
4
|
import subprocess
|
|
4
5
|
import threading
|
|
@@ -25,13 +26,31 @@ ACP_TIMEOUT_SECONDS = 60
|
|
|
25
26
|
_INITIALIZE_ID = 1
|
|
26
27
|
_SESSION_NEW_ID = 2
|
|
27
28
|
|
|
29
|
+
# Ceiling on what one run may spend. AI credits bill at $0.04 each, so the
|
|
30
|
+
# default is the same $20 cap the Claude Code agent puts on a run.
|
|
31
|
+
MAX_AI_CREDITS_ENV_VAR = "CODEE_COPILOT_MAX_AI_CREDITS"
|
|
32
|
+
DEFAULT_MAX_AI_CREDITS = 1000
|
|
33
|
+
# The CLI rejects anything lower outright, which reads as a broken agent rather
|
|
34
|
+
# than a misconfigured cap, so a smaller override is raised to it instead.
|
|
35
|
+
MIN_AI_CREDITS = 30
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
def _max_ai_credits() -> str:
|
|
39
|
+
"""The per-run credit cap, read fresh so a changed env applies to the next run."""
|
|
40
|
+
raw = os.environ.get(MAX_AI_CREDITS_ENV_VAR, "").strip()
|
|
41
|
+
if not raw:
|
|
42
|
+
return str(DEFAULT_MAX_AI_CREDITS)
|
|
43
|
+
try:
|
|
44
|
+
return str(max(MIN_AI_CREDITS, int(raw)))
|
|
45
|
+
except ValueError:
|
|
46
|
+
log.warning("%s=%r is not a number, using %d",
|
|
47
|
+
MAX_AI_CREDITS_ENV_VAR, raw, DEFAULT_MAX_AI_CREDITS)
|
|
48
|
+
return str(DEFAULT_MAX_AI_CREDITS)
|
|
49
|
+
|
|
28
50
|
|
|
29
51
|
class GitHubCopilotAgent(AbstractCodingAgent):
|
|
30
52
|
"""Runs the ``copilot`` CLI in a fresh session, under the id the caller supplies."""
|
|
31
53
|
|
|
32
|
-
# Ceiling on what one run may spend. AI credits bill at $0.04 each, so this
|
|
33
|
-
# is the same $20 cap the Claude Code agent puts on a run. Minimum is 30.
|
|
34
|
-
MAX_AI_CREDITS = "500"
|
|
35
54
|
TIMEOUT_SECONDS = 7200 # 2 hours
|
|
36
55
|
|
|
37
56
|
def __init__(self, settings: Settings, cwd: Path):
|
|
@@ -52,7 +71,7 @@ class GitHubCopilotAgent(AbstractCodingAgent):
|
|
|
52
71
|
"copilot",
|
|
53
72
|
"-p", user_message,
|
|
54
73
|
"--session-id", session_id,
|
|
55
|
-
"--max-ai-credits",
|
|
74
|
+
"--max-ai-credits", _max_ai_credits(),
|
|
56
75
|
"--output-format", "json",
|
|
57
76
|
# Tools, paths and URLs: the equivalent of claude's bypassPermissions.
|
|
58
77
|
"--allow-all",
|
|
@@ -95,7 +114,8 @@ class GitHubCopilotAgent(AbstractCodingAgent):
|
|
|
95
114
|
if outcome is None:
|
|
96
115
|
# Not the JSONL we know how to read — hand back whatever it printed
|
|
97
116
|
# rather than failing a run that the CLI itself called successful.
|
|
98
|
-
log.warning(
|
|
117
|
+
log.warning(
|
|
118
|
+
"copilot produced no result event; returning raw output")
|
|
99
119
|
return result.stdout
|
|
100
120
|
if outcome.get("exitCode"):
|
|
101
121
|
raise RuntimeError(
|
|
@@ -240,7 +260,8 @@ def _parse_events(stdout: str) -> tuple[str, dict | None, list[str]]:
|
|
|
240
260
|
reply = content.strip()
|
|
241
261
|
elif kind == SESSION_ERROR:
|
|
242
262
|
data = event.get("data") or {}
|
|
243
|
-
message = data.get("message") or data.get(
|
|
263
|
+
message = data.get("message") or data.get(
|
|
264
|
+
"errorType") or "unknown error"
|
|
244
265
|
errors.append(str(message))
|
|
245
266
|
elif kind == RESULT:
|
|
246
267
|
outcome = event
|
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
import json
|
|
2
|
+
import os
|
|
2
3
|
import queue
|
|
3
4
|
import subprocess
|
|
4
5
|
import unittest
|
|
5
6
|
from pathlib import Path
|
|
6
7
|
from unittest.mock import Mock, patch
|
|
7
8
|
|
|
8
|
-
from codee_agent_github_copilot.provider import
|
|
9
|
+
from codee_agent_github_copilot.provider import (
|
|
10
|
+
MAX_AI_CREDITS_ENV_VAR, GitHubCopilotAgent, _await_result)
|
|
9
11
|
from codee_main_context.context import Settings
|
|
10
12
|
|
|
11
13
|
SESSION = "82232f47-df60-4cb3-8c3a-de12074c9205"
|
|
@@ -123,6 +125,36 @@ class CopilotRunTest(unittest.TestCase):
|
|
|
123
125
|
self.agent.run("/do-it CORE-1", SESSION)
|
|
124
126
|
|
|
125
127
|
|
|
128
|
+
class CopilotCreditCapTest(unittest.TestCase):
|
|
129
|
+
def _credits(self, value: str | None) -> str:
|
|
130
|
+
stdout = _stream(_event("assistant.message", {"content": "ok"}),
|
|
131
|
+
_event("result", exitCode=0))
|
|
132
|
+
with patch.dict(os.environ, {}, clear=False):
|
|
133
|
+
if value is None:
|
|
134
|
+
os.environ.pop(MAX_AI_CREDITS_ENV_VAR, None)
|
|
135
|
+
else:
|
|
136
|
+
os.environ[MAX_AI_CREDITS_ENV_VAR] = value
|
|
137
|
+
with patch("subprocess.run", return_value=_completed(stdout)) as run:
|
|
138
|
+
GitHubCopilotAgent(Settings(), Path("/repo")).run("/do-it", SESSION)
|
|
139
|
+
cmd = run.call_args.args[0]
|
|
140
|
+
return cmd[cmd.index("--max-ai-credits") + 1]
|
|
141
|
+
|
|
142
|
+
def test_an_unset_env_var_keeps_the_default_cap(self) -> None:
|
|
143
|
+
self.assertEqual(self._credits(None), "1000")
|
|
144
|
+
|
|
145
|
+
def test_the_env_var_sets_the_cap(self) -> None:
|
|
146
|
+
self.assertEqual(self._credits("250"), "250")
|
|
147
|
+
|
|
148
|
+
def test_a_blank_env_var_keeps_the_default_cap(self) -> None:
|
|
149
|
+
self.assertEqual(self._credits(" "), "1000")
|
|
150
|
+
|
|
151
|
+
def test_a_cap_under_the_cli_minimum_is_raised_to_it(self) -> None:
|
|
152
|
+
self.assertEqual(self._credits("5"), "30")
|
|
153
|
+
|
|
154
|
+
def test_a_non_numeric_cap_falls_back_to_the_default(self) -> None:
|
|
155
|
+
self.assertEqual(self._credits("lots"), "1000")
|
|
156
|
+
|
|
157
|
+
|
|
126
158
|
class CopilotModelCatalogTest(unittest.TestCase):
|
|
127
159
|
def _queue(self, *lines: str) -> "queue.Queue[str]":
|
|
128
160
|
lines_queue: queue.Queue[str] = queue.Queue()
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{codee_agent-0.4.1 → codee_agent-0.4.2}/src/codee/templates/skills/aws-sqs-alarm-response/SKILL.md
RENAMED
|
File without changes
|
{codee_agent-0.4.1 → codee_agent-0.4.2}/src/codee/templates/skills/cron-research-5xx-errors/SKILL.md
RENAMED
|
File without changes
|
{codee_agent-0.4.1 → codee_agent-0.4.2}/src/codee/templates/skills/story-code-reviewer/SKILL.md
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|