codee-agent 0.7.1__tar.gz → 0.7.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 (96) hide show
  1. {codee_agent-0.7.1 → codee_agent-0.7.2}/PKG-INFO +1 -1
  2. {codee_agent-0.7.1 → codee_agent-0.7.2}/pyproject.toml +1 -1
  3. {codee_agent-0.7.1 → codee_agent-0.7.2}/src/codee/admin.py +15 -0
  4. {codee_agent-0.7.1 → codee_agent-0.7.2}/src/codee/admin_service.py +7 -0
  5. {codee_agent-0.7.1 → codee_agent-0.7.2}/src/codee/executor.py +8 -0
  6. codee_agent-0.7.2/src/codee/lib/runtime_control.py +21 -0
  7. {codee_agent-0.7.1 → codee_agent-0.7.2}/src/codee/test_admin_service.py +11 -0
  8. {codee_agent-0.7.1 → codee_agent-0.7.2}/src/codee/test_executor.py +21 -0
  9. {codee_agent-0.7.1 → codee_agent-0.7.2}/LICENSE +0 -0
  10. {codee_agent-0.7.1 → codee_agent-0.7.2}/README.md +0 -0
  11. {codee_agent-0.7.1 → codee_agent-0.7.2}/src/codee/.gitignore +0 -0
  12. {codee_agent-0.7.1 → codee_agent-0.7.2}/src/codee/__init__.py +0 -0
  13. {codee_agent-0.7.1 → codee_agent-0.7.2}/src/codee/admin_api.py +0 -0
  14. {codee_agent-0.7.1 → codee_agent-0.7.2}/src/codee/admin_cli.py +0 -0
  15. {codee_agent-0.7.1 → codee_agent-0.7.2}/src/codee/agent_cli.py +0 -0
  16. {codee_agent-0.7.1 → codee_agent-0.7.2}/src/codee/coding_agents.py +0 -0
  17. {codee_agent-0.7.1 → codee_agent-0.7.2}/src/codee/init_cli.py +0 -0
  18. {codee_agent-0.7.1 → codee_agent-0.7.2}/src/codee/lib/__init__.py +0 -0
  19. {codee_agent-0.7.1 → codee_agent-0.7.2}/src/codee/lib/claude_key_rotation.py +0 -0
  20. {codee_agent-0.7.1 → codee_agent-0.7.2}/src/codee/lib/cron_describe.py +0 -0
  21. {codee_agent-0.7.1 → codee_agent-0.7.2}/src/codee/lib/mcp_config.py +0 -0
  22. {codee_agent-0.7.1 → codee_agent-0.7.2}/src/codee/lib/runs_db.py +0 -0
  23. {codee_agent-0.7.1 → codee_agent-0.7.2}/src/codee/lib/test_claude_key_rotation.py +0 -0
  24. {codee_agent-0.7.1 → codee_agent-0.7.2}/src/codee/lib/test_mcp_config.py +0 -0
  25. {codee_agent-0.7.1 → codee_agent-0.7.2}/src/codee/lib/test_runs_db.py +0 -0
  26. {codee_agent-0.7.1 → codee_agent-0.7.2}/src/codee/lib/test_trigger_cron_skills.py +0 -0
  27. {codee_agent-0.7.1 → codee_agent-0.7.2}/src/codee/lib/test_trigger_issue_skills.py +0 -0
  28. {codee_agent-0.7.1 → codee_agent-0.7.2}/src/codee/lib/trigger_aws_sqs_skills.py +0 -0
  29. {codee_agent-0.7.1 → codee_agent-0.7.2}/src/codee/lib/trigger_cron_skills.py +0 -0
  30. {codee_agent-0.7.1 → codee_agent-0.7.2}/src/codee/lib/trigger_email_skills.py +0 -0
  31. {codee_agent-0.7.1 → codee_agent-0.7.2}/src/codee/lib/trigger_issue_skills.py +0 -0
  32. {codee_agent-0.7.1 → codee_agent-0.7.2}/src/codee/mail_server.py +0 -0
  33. {codee_agent-0.7.1 → codee_agent-0.7.2}/src/codee/setup_wizard.py +0 -0
  34. {codee_agent-0.7.1 → codee_agent-0.7.2}/src/codee/start_cli.py +0 -0
  35. {codee_agent-0.7.1 → codee_agent-0.7.2}/src/codee/tasks_providers.py +0 -0
  36. {codee_agent-0.7.1 → codee_agent-0.7.2}/src/codee/templates/AGENTS.md +0 -0
  37. {codee_agent-0.7.1 → codee_agent-0.7.2}/src/codee/templates/CLAUDE.md +0 -0
  38. {codee_agent-0.7.1 → codee_agent-0.7.2}/src/codee/templates/skills/aws-sqs-alarm-response/SKILL.md +0 -0
  39. {codee_agent-0.7.1 → codee_agent-0.7.2}/src/codee/templates/skills/cron-research-5xx-errors/SKILL.md +0 -0
  40. {codee_agent-0.7.1 → codee_agent-0.7.2}/src/codee/templates/skills/story-code-reviewer/SKILL.md +0 -0
  41. {codee_agent-0.7.1 → codee_agent-0.7.2}/src/codee/templates/skills/story-developer/SKILL.md +0 -0
  42. {codee_agent-0.7.1 → codee_agent-0.7.2}/src/codee/templates/skills/story-planner/SKILL.md +0 -0
  43. {codee_agent-0.7.1 → codee_agent-0.7.2}/src/codee/templates/skills/story-planner/assets/readme-template.md +0 -0
  44. {codee_agent-0.7.1 → codee_agent-0.7.2}/src/codee/templates/skills/story-qa/SKILL.md +0 -0
  45. {codee_agent-0.7.1 → codee_agent-0.7.2}/src/codee/templates/skills/story-security-reviewer/SKILL.md +0 -0
  46. {codee_agent-0.7.1 → codee_agent-0.7.2}/src/codee/templates/skills/task-code-reviewer/SKILL.md +0 -0
  47. {codee_agent-0.7.1 → codee_agent-0.7.2}/src/codee/templates/skills/task-developer/SKILL.md +0 -0
  48. {codee_agent-0.7.1 → codee_agent-0.7.2}/src/codee/templates/skills/task-qa/SKILL.md +0 -0
  49. {codee_agent-0.7.1 → codee_agent-0.7.2}/src/codee/templates/skills/task-security-reviewer/SKILL.md +0 -0
  50. {codee_agent-0.7.1 → codee_agent-0.7.2}/src/codee/test_admin_api.py +0 -0
  51. {codee_agent-0.7.1 → codee_agent-0.7.2}/src/codee/test_admin_cli.py +0 -0
  52. {codee_agent-0.7.1 → codee_agent-0.7.2}/src/codee/test_agent_cli.py +0 -0
  53. {codee_agent-0.7.1 → codee_agent-0.7.2}/src/codee/test_coding_agents.py +0 -0
  54. {codee_agent-0.7.1 → codee_agent-0.7.2}/src/codee/test_init_cli.py +0 -0
  55. {codee_agent-0.7.1 → codee_agent-0.7.2}/src/codee/test_memory_index.py +0 -0
  56. {codee_agent-0.7.1 → codee_agent-0.7.2}/src/codee/test_setup_wizard.py +0 -0
  57. {codee_agent-0.7.1 → codee_agent-0.7.2}/src/codee/test_start_cli.py +0 -0
  58. {codee_agent-0.7.1 → codee_agent-0.7.2}/src/codee/workflow_graph.py +0 -0
  59. {codee_agent-0.7.1 → codee_agent-0.7.2}/src/codee_admin/__init__.py +0 -0
  60. {codee_agent-0.7.1 → codee_agent-0.7.2}/src/codee_admin/codee_admin.py +0 -0
  61. {codee_agent-0.7.1 → codee_agent-0.7.2}/src/codee_agent_abstract/__init__.py +0 -0
  62. {codee_agent-0.7.1 → codee_agent-0.7.2}/src/codee_agent_abstract/provider.py +0 -0
  63. {codee_agent-0.7.1 → codee_agent-0.7.2}/src/codee_agent_claude_code/__init__.py +0 -0
  64. {codee_agent-0.7.1 → codee_agent-0.7.2}/src/codee_agent_claude_code/account.py +0 -0
  65. {codee_agent-0.7.1 → codee_agent-0.7.2}/src/codee_agent_claude_code/credentials.py +0 -0
  66. {codee_agent-0.7.1 → codee_agent-0.7.2}/src/codee_agent_claude_code/oauth.py +0 -0
  67. {codee_agent-0.7.1 → codee_agent-0.7.2}/src/codee_agent_claude_code/provider.py +0 -0
  68. {codee_agent-0.7.1 → codee_agent-0.7.2}/src/codee_agent_claude_code/test.py +0 -0
  69. {codee_agent-0.7.1 → codee_agent-0.7.2}/src/codee_agent_claude_code/usage.py +0 -0
  70. {codee_agent-0.7.1 → codee_agent-0.7.2}/src/codee_agent_codex/__init__.py +0 -0
  71. {codee_agent-0.7.1 → codee_agent-0.7.2}/src/codee_agent_codex/provider.py +0 -0
  72. {codee_agent-0.7.1 → codee_agent-0.7.2}/src/codee_agent_codex/test.py +0 -0
  73. {codee_agent-0.7.1 → codee_agent-0.7.2}/src/codee_agent_github_copilot/__init__.py +0 -0
  74. {codee_agent-0.7.1 → codee_agent-0.7.2}/src/codee_agent_github_copilot/provider.py +0 -0
  75. {codee_agent-0.7.1 → codee_agent-0.7.2}/src/codee_agent_github_copilot/test.py +0 -0
  76. {codee_agent-0.7.1 → codee_agent-0.7.2}/src/codee_agent_opencode/__init__.py +0 -0
  77. {codee_agent-0.7.1 → codee_agent-0.7.2}/src/codee_agent_opencode/provider.py +0 -0
  78. {codee_agent-0.7.1 → codee_agent-0.7.2}/src/codee_agent_opencode/test.py +0 -0
  79. {codee_agent-0.7.1 → codee_agent-0.7.2}/src/codee_database/__init__.py +0 -0
  80. {codee_agent-0.7.1 → codee_agent-0.7.2}/src/codee_database/claude_code_accounts.py +0 -0
  81. {codee_agent-0.7.1 → codee_agent-0.7.2}/src/codee_database/database.py +0 -0
  82. {codee_agent-0.7.1 → codee_agent-0.7.2}/src/codee_database/oauth_tokens.py +0 -0
  83. {codee_agent-0.7.1 → codee_agent-0.7.2}/src/codee_main_context/__init__.py +0 -0
  84. {codee_agent-0.7.1 → codee_agent-0.7.2}/src/codee_main_context/context.py +0 -0
  85. {codee_agent-0.7.1 → codee_agent-0.7.2}/src/codee_main_context/logging.py +0 -0
  86. {codee_agent-0.7.1 → codee_agent-0.7.2}/src/codee_main_context/test_context.py +0 -0
  87. {codee_agent-0.7.1 → codee_agent-0.7.2}/src/codee_main_context/test_logging.py +0 -0
  88. {codee_agent-0.7.1 → codee_agent-0.7.2}/src/codee_tasks_abstract/__init__.py +0 -0
  89. {codee_agent-0.7.1 → codee_agent-0.7.2}/src/codee_tasks_abstract/provider.py +0 -0
  90. {codee_agent-0.7.1 → codee_agent-0.7.2}/src/codee_tasks_azure_devops/__init__.py +0 -0
  91. {codee_agent-0.7.1 → codee_agent-0.7.2}/src/codee_tasks_azure_devops/oauth.py +0 -0
  92. {codee_agent-0.7.1 → codee_agent-0.7.2}/src/codee_tasks_azure_devops/provider.py +0 -0
  93. {codee_agent-0.7.1 → codee_agent-0.7.2}/src/codee_tasks_azure_devops/test.py +0 -0
  94. {codee_agent-0.7.1 → codee_agent-0.7.2}/src/codee_tasks_jira/__init__.py +0 -0
  95. {codee_agent-0.7.1 → codee_agent-0.7.2}/src/codee_tasks_jira/provider.py +0 -0
  96. {codee_agent-0.7.1 → codee_agent-0.7.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.7.1
3
+ Version: 0.7.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,codex,opencode,automation
6
6
  Author: Denis Kibalko
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "codee-agent"
3
- version = "0.7.1"
3
+ version = "0.7.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"
@@ -319,6 +319,7 @@ class AdminState(rx.State):
319
319
  adding_repository: bool = False
320
320
 
321
321
  active_jobs: list[ActiveJob] = []
322
+ paused: bool = False
322
323
  total_runs: int = 0
323
324
  last_24h_runs: int = 0
324
325
  hourly_runs: list[dict[str, Any]] = []
@@ -779,10 +780,14 @@ class AdminState(rx.State):
779
780
  def _refresh_dashboard(self) -> None:
780
781
  dashboard = SERVICE.dashboard()
781
782
  self.active_jobs = [_active_job(job) for job in dashboard["active"]]
783
+ self.paused = dashboard["paused"]
782
784
  self.total_runs = dashboard["counts"]["total"]
783
785
  self.last_24h_runs = dashboard["counts"]["last_24h"]
784
786
  self.hourly_runs = dashboard["hourly"]
785
787
 
788
+ def toggle_pause(self) -> None:
789
+ self.paused = SERVICE.set_paused(not self.paused)
790
+
786
791
  @rx.event(background=True)
787
792
  async def poll_dashboard(self) -> None:
788
793
  """Keep the dashboard live for as long as it is the page on screen.
@@ -1978,6 +1983,16 @@ def running_panel() -> rx.Component:
1978
1983
  font_family=MONO, class_name="codee-breathe",
1979
1984
  animation="codee-breathe 2.4s ease-in-out infinite"),
1980
1985
  ),
1986
+ rx.spacer(),
1987
+ rx.button(
1988
+ rx.cond(AdminState.paused,
1989
+ rx.icon("play", size=15),
1990
+ rx.icon("pause", size=15)),
1991
+ rx.cond(AdminState.paused, "Unpause", "Pause"),
1992
+ variant="outline",
1993
+ color_scheme=rx.cond(AdminState.paused, "green", "gray"),
1994
+ on_click=AdminState.toggle_pause,
1995
+ ),
1981
1996
  spacing="3",
1982
1997
  align="center",
1983
1998
  width="100%",
@@ -35,6 +35,7 @@ from codee.lib import runs_db
35
35
  from codee.lib.claude_key_rotation import ensure_fresh
36
36
  from codee.lib.cron_describe import describe_cron
37
37
  from codee.lib.mcp_config import find_mcp_server, write_mcp_server
38
+ from codee.lib.runtime_control import is_paused, set_paused
38
39
  from codee.lib.trigger_cron_skills import request_force_run
39
40
  from codee.lib.trigger_issue_skills import (
40
41
  IssueTriggeredSkill,
@@ -2049,8 +2050,14 @@ class AdminService:
2049
2050
  "active": active,
2050
2051
  "counts": runs_db.counts(main_context=self.context),
2051
2052
  "hourly": runs_db.runs_by_hour(main_context=self.context),
2053
+ "paused": is_paused(self.context),
2052
2054
  }
2053
2055
 
2056
+ def set_paused(self, paused: bool) -> bool:
2057
+ """Allow or prevent future automated agent runs."""
2058
+ set_paused(self.context, paused)
2059
+ return is_paused(self.context)
2060
+
2054
2061
  def _task_url(self) -> Callable[[str], str]:
2055
2062
  """How to link a work item key, per the configured tasks provider.
2056
2063
 
@@ -21,6 +21,7 @@ from codee_tasks_abstract.provider import AbstractTasksProvider
21
21
 
22
22
  from codee.coding_agents import resolve_agent_code
23
23
  from codee.lib import claude_key_rotation, runs_db
24
+ from codee.lib.runtime_control import is_paused
24
25
  from codee.lib.trigger_aws_sqs_skills import trigger_aws_sqs_skills
25
26
  from codee.lib.trigger_cron_skills import trigger_cron_skills
26
27
  from codee.lib.trigger_email_skills import trigger_email_skills
@@ -359,6 +360,9 @@ def _submit_task(task_id: str, message: str, session_id: str, skill_name: str,
359
360
  against the next tick.
360
361
  """
361
362
  with _inflight_lock:
363
+ if is_paused(context):
364
+ log.debug("New agent work was paused before %s could start.", task_id)
365
+ return False
362
366
  if task_id in _inflight:
363
367
  log.debug("%s already running; skipping duplicate launch.", task_id)
364
368
  return False
@@ -387,6 +391,10 @@ def run_once() -> None:
387
391
  if not _pull_latest_code():
388
392
  log.warning("Failed to pull from the repo, still continuing...")
389
393
 
394
+ if is_paused(context):
395
+ log.info("New agent work is paused; active agents continue running.")
396
+ return
397
+
390
398
  trigger_cron_skills(_run_agent, main_context=context)
391
399
  trigger_aws_sqs_skills(_run_agent, main_context=context)
392
400
  trigger_email_skills(_run_agent, main_context=context)
@@ -0,0 +1,21 @@
1
+ """Persistent controls shared by the admin UI and executor process."""
2
+ from pathlib import Path
3
+
4
+ from codee_main_context.context import CodeeMainContext
5
+
6
+ PAUSED_FILE = "paused"
7
+
8
+
9
+ def is_paused(context: CodeeMainContext) -> bool:
10
+ """Return whether new agent work is paused."""
11
+ return (context.data_dir / PAUSED_FILE).exists()
12
+
13
+
14
+ def set_paused(context: CodeeMainContext, paused: bool) -> None:
15
+ """Persist whether new agent work may start."""
16
+ path = context.data_dir / PAUSED_FILE
17
+ if paused:
18
+ path.parent.mkdir(parents=True, exist_ok=True)
19
+ path.touch(exist_ok=True)
20
+ else:
21
+ path.unlink(missing_ok=True)
@@ -62,6 +62,17 @@ def _write_issue_skill(root: Path) -> Path:
62
62
 
63
63
 
64
64
  class RecentRunsTest(unittest.TestCase):
65
+ def test_dashboard_pause_state_persists(self) -> None:
66
+ with tempfile.TemporaryDirectory() as directory:
67
+ service = AdminService.__new__(AdminService)
68
+ service.data_dir = Path(directory)
69
+ service.context = CodeeMainContext(data_dir=service.data_dir)
70
+
71
+ self.assertFalse(service.set_paused(False))
72
+ self.assertTrue(service.set_paused(True))
73
+ self.assertTrue(service.dashboard()["paused"])
74
+ self.assertFalse(service.set_paused(False))
75
+
65
76
  def test_formats_relative_age_in_minutes_hours_and_days(self) -> None:
66
77
  now = datetime(2026, 9, 24, 12, 0, tzinfo=timezone.utc)
67
78
  cases = [
@@ -533,6 +533,27 @@ class ParentWorkItemSkipTest(unittest.TestCase):
533
533
  executor.run_once()
534
534
  return [call.args[0] for call in submit.call_args_list]
535
535
 
536
+ def test_paused_executor_starts_no_trigger_or_issue_work(self) -> None:
537
+ with patch.object(executor, "is_paused", return_value=True), \
538
+ patch.object(executor, "trigger_cron_skills") as cron, \
539
+ patch.object(executor, "trigger_aws_sqs_skills") as sqs, \
540
+ patch.object(executor, "trigger_email_skills") as email:
541
+ executor.run_once()
542
+
543
+ cron.assert_not_called()
544
+ sqs.assert_not_called()
545
+ email.assert_not_called()
546
+ self.provider.get_tasks.assert_not_called()
547
+
548
+ def test_pause_while_polling_prevents_issue_launch(self) -> None:
549
+ with patch.object(executor, "is_paused", return_value=True), \
550
+ patch.object(executor, "_run_task") as run_task:
551
+ launched = executor._submit_task(
552
+ "NIM-4", "prompt", "session", "Task developer")
553
+
554
+ self.assertFalse(launched)
555
+ run_task.assert_not_called()
556
+
536
557
  def test_an_item_under_a_mapped_parent_is_left_to_that_parents_run(self) -> None:
537
558
  self.assertEqual(
538
559
  self._submitted(_polled_task("NIM-1", parent_type="Story")), [])
File without changes
File without changes