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.
Files changed (71) hide show
  1. {codee_agent-0.4.1 → codee_agent-0.4.2}/PKG-INFO +1 -1
  2. {codee_agent-0.4.1 → codee_agent-0.4.2}/pyproject.toml +1 -1
  3. {codee_agent-0.4.1 → codee_agent-0.4.2}/src/codee_agent_github_copilot/provider.py +27 -6
  4. {codee_agent-0.4.1 → codee_agent-0.4.2}/src/codee_agent_github_copilot/test.py +33 -1
  5. {codee_agent-0.4.1 → codee_agent-0.4.2}/LICENSE +0 -0
  6. {codee_agent-0.4.1 → codee_agent-0.4.2}/README.md +0 -0
  7. {codee_agent-0.4.1 → codee_agent-0.4.2}/src/codee/.gitignore +0 -0
  8. {codee_agent-0.4.1 → codee_agent-0.4.2}/src/codee/__init__.py +0 -0
  9. {codee_agent-0.4.1 → codee_agent-0.4.2}/src/codee/admin.py +0 -0
  10. {codee_agent-0.4.1 → codee_agent-0.4.2}/src/codee/admin_api.py +0 -0
  11. {codee_agent-0.4.1 → codee_agent-0.4.2}/src/codee/admin_cli.py +0 -0
  12. {codee_agent-0.4.1 → codee_agent-0.4.2}/src/codee/admin_service.py +0 -0
  13. {codee_agent-0.4.1 → codee_agent-0.4.2}/src/codee/executor.py +0 -0
  14. {codee_agent-0.4.1 → codee_agent-0.4.2}/src/codee/init_cli.py +0 -0
  15. {codee_agent-0.4.1 → codee_agent-0.4.2}/src/codee/lib/__init__.py +0 -0
  16. {codee_agent-0.4.1 → codee_agent-0.4.2}/src/codee/lib/cron_describe.py +0 -0
  17. {codee_agent-0.4.1 → codee_agent-0.4.2}/src/codee/lib/mcp_config.py +0 -0
  18. {codee_agent-0.4.1 → codee_agent-0.4.2}/src/codee/lib/runs_db.py +0 -0
  19. {codee_agent-0.4.1 → codee_agent-0.4.2}/src/codee/lib/test_mcp_config.py +0 -0
  20. {codee_agent-0.4.1 → codee_agent-0.4.2}/src/codee/lib/test_runs_db.py +0 -0
  21. {codee_agent-0.4.1 → codee_agent-0.4.2}/src/codee/lib/test_trigger_cron_skills.py +0 -0
  22. {codee_agent-0.4.1 → codee_agent-0.4.2}/src/codee/lib/test_trigger_issue_skills.py +0 -0
  23. {codee_agent-0.4.1 → codee_agent-0.4.2}/src/codee/lib/trigger_aws_sqs_skills.py +0 -0
  24. {codee_agent-0.4.1 → codee_agent-0.4.2}/src/codee/lib/trigger_cron_skills.py +0 -0
  25. {codee_agent-0.4.1 → codee_agent-0.4.2}/src/codee/lib/trigger_email_skills.py +0 -0
  26. {codee_agent-0.4.1 → codee_agent-0.4.2}/src/codee/lib/trigger_issue_skills.py +0 -0
  27. {codee_agent-0.4.1 → codee_agent-0.4.2}/src/codee/mail_server.py +0 -0
  28. {codee_agent-0.4.1 → codee_agent-0.4.2}/src/codee/start_cli.py +0 -0
  29. {codee_agent-0.4.1 → codee_agent-0.4.2}/src/codee/tasks_providers.py +0 -0
  30. {codee_agent-0.4.1 → codee_agent-0.4.2}/src/codee/templates/AGENTS.md +0 -0
  31. {codee_agent-0.4.1 → codee_agent-0.4.2}/src/codee/templates/CLAUDE.md +0 -0
  32. {codee_agent-0.4.1 → codee_agent-0.4.2}/src/codee/templates/skills/aws-sqs-alarm-response/SKILL.md +0 -0
  33. {codee_agent-0.4.1 → codee_agent-0.4.2}/src/codee/templates/skills/cron-research-5xx-errors/SKILL.md +0 -0
  34. {codee_agent-0.4.1 → codee_agent-0.4.2}/src/codee/templates/skills/story-code-reviewer/SKILL.md +0 -0
  35. {codee_agent-0.4.1 → codee_agent-0.4.2}/src/codee/templates/skills/story-developer/SKILL.md +0 -0
  36. {codee_agent-0.4.1 → codee_agent-0.4.2}/src/codee/templates/skills/story-planner/SKILL.md +0 -0
  37. {codee_agent-0.4.1 → codee_agent-0.4.2}/src/codee/templates/skills/story-planner/assets/readme-template.md +0 -0
  38. {codee_agent-0.4.1 → codee_agent-0.4.2}/src/codee/templates/skills/story-qa/SKILL.md +0 -0
  39. {codee_agent-0.4.1 → codee_agent-0.4.2}/src/codee/templates/skills/task-developer/SKILL.md +0 -0
  40. {codee_agent-0.4.1 → codee_agent-0.4.2}/src/codee/templates/skills/task-qa/SKILL.md +0 -0
  41. {codee_agent-0.4.1 → codee_agent-0.4.2}/src/codee/test_admin_api.py +0 -0
  42. {codee_agent-0.4.1 → codee_agent-0.4.2}/src/codee/test_admin_cli.py +0 -0
  43. {codee_agent-0.4.1 → codee_agent-0.4.2}/src/codee/test_admin_service.py +0 -0
  44. {codee_agent-0.4.1 → codee_agent-0.4.2}/src/codee/test_executor.py +0 -0
  45. {codee_agent-0.4.1 → codee_agent-0.4.2}/src/codee/test_init_cli.py +0 -0
  46. {codee_agent-0.4.1 → codee_agent-0.4.2}/src/codee/test_memory_index.py +0 -0
  47. {codee_agent-0.4.1 → codee_agent-0.4.2}/src/codee/test_start_cli.py +0 -0
  48. {codee_agent-0.4.1 → codee_agent-0.4.2}/src/codee/workflow_graph.py +0 -0
  49. {codee_agent-0.4.1 → codee_agent-0.4.2}/src/codee_admin/__init__.py +0 -0
  50. {codee_agent-0.4.1 → codee_agent-0.4.2}/src/codee_admin/codee_admin.py +0 -0
  51. {codee_agent-0.4.1 → codee_agent-0.4.2}/src/codee_agent_abstract/__init__.py +0 -0
  52. {codee_agent-0.4.1 → codee_agent-0.4.2}/src/codee_agent_abstract/provider.py +0 -0
  53. {codee_agent-0.4.1 → codee_agent-0.4.2}/src/codee_agent_claude_code/__init__.py +0 -0
  54. {codee_agent-0.4.1 → codee_agent-0.4.2}/src/codee_agent_claude_code/provider.py +0 -0
  55. {codee_agent-0.4.1 → codee_agent-0.4.2}/src/codee_agent_github_copilot/__init__.py +0 -0
  56. {codee_agent-0.4.1 → codee_agent-0.4.2}/src/codee_database/__init__.py +0 -0
  57. {codee_agent-0.4.1 → codee_agent-0.4.2}/src/codee_database/database.py +0 -0
  58. {codee_agent-0.4.1 → codee_agent-0.4.2}/src/codee_database/oauth_tokens.py +0 -0
  59. {codee_agent-0.4.1 → codee_agent-0.4.2}/src/codee_main_context/__init__.py +0 -0
  60. {codee_agent-0.4.1 → codee_agent-0.4.2}/src/codee_main_context/context.py +0 -0
  61. {codee_agent-0.4.1 → codee_agent-0.4.2}/src/codee_main_context/logging.py +0 -0
  62. {codee_agent-0.4.1 → codee_agent-0.4.2}/src/codee_main_context/test_logging.py +0 -0
  63. {codee_agent-0.4.1 → codee_agent-0.4.2}/src/codee_tasks_abstract/__init__.py +0 -0
  64. {codee_agent-0.4.1 → codee_agent-0.4.2}/src/codee_tasks_abstract/provider.py +0 -0
  65. {codee_agent-0.4.1 → codee_agent-0.4.2}/src/codee_tasks_azure_devops/__init__.py +0 -0
  66. {codee_agent-0.4.1 → codee_agent-0.4.2}/src/codee_tasks_azure_devops/oauth.py +0 -0
  67. {codee_agent-0.4.1 → codee_agent-0.4.2}/src/codee_tasks_azure_devops/provider.py +0 -0
  68. {codee_agent-0.4.1 → codee_agent-0.4.2}/src/codee_tasks_azure_devops/test.py +0 -0
  69. {codee_agent-0.4.1 → codee_agent-0.4.2}/src/codee_tasks_jira/__init__.py +0 -0
  70. {codee_agent-0.4.1 → codee_agent-0.4.2}/src/codee_tasks_jira/provider.py +0 -0
  71. {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.1
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,6 +1,6 @@
1
1
  [project]
2
2
  name = "codee-agent"
3
- version = "0.4.1"
3
+ version = "0.4.2"
4
4
  description = "A virtual co-worker that picks up Jira and Azure DevOps tasks and solves them with coding agents."
5
5
  readme = "README.md"
6
6
  license = "MIT"
@@ -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", self.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("copilot produced no result event; returning raw output")
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("errorType") or "unknown error"
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 GitHubCopilotAgent, _await_result
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