agentexec 0.2.0rc1__tar.gz → 0.2.0rc2__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 (146) hide show
  1. agentexec-0.2.0rc2/.python-version +1 -0
  2. {agentexec-0.2.0rc1 → agentexec-0.2.0rc2}/CHANGELOG.md +113 -0
  3. {agentexec-0.2.0rc1 → agentexec-0.2.0rc2}/PKG-INFO +2 -2
  4. agentexec-0.2.0rc2/RELEASE.md +91 -0
  5. agentexec-0.2.0rc2/examples/basic/debug_spawn.py +30 -0
  6. agentexec-0.2.0rc2/examples/basic/enqueue.py +26 -0
  7. agentexec-0.2.0rc2/examples/basic/entrypoint.sh +2 -0
  8. agentexec-0.2.0rc2/examples/basic/worker.py +50 -0
  9. {agentexec-0.2.0rc1 → agentexec-0.2.0rc2}/pyproject.toml +9 -5
  10. agentexec-0.2.0rc2/research/multiprocessing.md +778 -0
  11. {agentexec-0.2.0rc1 → agentexec-0.2.0rc2}/src/agentexec/activity/__init__.py +76 -57
  12. {agentexec-0.2.0rc1 → agentexec-0.2.0rc2}/src/agentexec/activity/events.py +9 -4
  13. {agentexec-0.2.0rc1 → agentexec-0.2.0rc2}/src/agentexec/activity/handlers.py +28 -37
  14. {agentexec-0.2.0rc1 → agentexec-0.2.0rc2}/src/agentexec/activity/models.py +106 -120
  15. {agentexec-0.2.0rc1 → agentexec-0.2.0rc2}/src/agentexec/activity/producer.py +15 -24
  16. agentexec-0.2.0rc2/src/agentexec/cli.py +156 -0
  17. agentexec-0.2.0rc2/src/agentexec/core/db.py +65 -0
  18. {agentexec-0.2.0rc1 → agentexec-0.2.0rc2}/src/agentexec/core/queue.py +3 -3
  19. {agentexec-0.2.0rc1 → agentexec-0.2.0rc2}/src/agentexec/core/results.py +2 -1
  20. {agentexec-0.2.0rc1 → agentexec-0.2.0rc2}/src/agentexec/core/task.py +1 -1
  21. {agentexec-0.2.0rc1 → agentexec-0.2.0rc2}/src/agentexec/schedule.py +3 -2
  22. {agentexec-0.2.0rc1 → agentexec-0.2.0rc2}/src/agentexec/state/base.py +2 -1
  23. {agentexec-0.2.0rc1 → agentexec-0.2.0rc2}/src/agentexec/state/kafka.py +8 -2
  24. {agentexec-0.2.0rc1 → agentexec-0.2.0rc2}/src/agentexec/state/redis.py +25 -17
  25. {agentexec-0.2.0rc1 → agentexec-0.2.0rc2}/src/agentexec/worker/pool.py +218 -169
  26. {agentexec-0.2.0rc1 → agentexec-0.2.0rc2}/tests/test_activity_tracking.py +80 -90
  27. {agentexec-0.2.0rc1 → agentexec-0.2.0rc2}/tests/test_db.py +10 -9
  28. {agentexec-0.2.0rc1 → agentexec-0.2.0rc2}/tests/test_public_api.py +2 -2
  29. {agentexec-0.2.0rc1 → agentexec-0.2.0rc2}/tests/test_queue_partitions.py +2 -1
  30. {agentexec-0.2.0rc1 → agentexec-0.2.0rc2}/tests/test_runners.py +10 -11
  31. {agentexec-0.2.0rc1 → agentexec-0.2.0rc2}/tests/test_schedule.py +4 -4
  32. {agentexec-0.2.0rc1 → agentexec-0.2.0rc2}/tests/test_task.py +2 -2
  33. {agentexec-0.2.0rc1 → agentexec-0.2.0rc2}/tests/test_task_locking.py +2 -2
  34. agentexec-0.2.0rc2/tests/test_worker_logging.py +439 -0
  35. {agentexec-0.2.0rc1 → agentexec-0.2.0rc2}/tests/test_worker_pool.py +47 -96
  36. agentexec-0.2.0rc1/src/agentexec/core/db.py +0 -52
  37. agentexec-0.2.0rc1/src/agentexec/core/logging.py +0 -27
  38. agentexec-0.2.0rc1/src/agentexec/worker/logging.py +0 -84
  39. agentexec-0.2.0rc1/tests/test_activity_tracking.py.bak +0 -427
  40. agentexec-0.2.0rc1/tests/test_worker_logging.py +0 -248
  41. {agentexec-0.2.0rc1 → agentexec-0.2.0rc2}/.claude/skills/prepare-release/SKILL.md +0 -0
  42. {agentexec-0.2.0rc1 → agentexec-0.2.0rc2}/.github/workflows/ci.yml +0 -0
  43. {agentexec-0.2.0rc1 → agentexec-0.2.0rc2}/.github/workflows/docker-publish.yml +0 -0
  44. {agentexec-0.2.0rc1 → agentexec-0.2.0rc2}/.github/workflows/npm-publish.yml +0 -0
  45. {agentexec-0.2.0rc1 → agentexec-0.2.0rc2}/.github/workflows/publish.yml +0 -0
  46. {agentexec-0.2.0rc1 → agentexec-0.2.0rc2}/.gitignore +0 -0
  47. {agentexec-0.2.0rc1 → agentexec-0.2.0rc2}/README.md +0 -0
  48. {agentexec-0.2.0rc1 → agentexec-0.2.0rc2}/docker/Dockerfile +0 -0
  49. {agentexec-0.2.0rc1 → agentexec-0.2.0rc2}/docker/README.md +0 -0
  50. {agentexec-0.2.0rc1 → agentexec-0.2.0rc2}/docker/entrypoint.py +0 -0
  51. {agentexec-0.2.0rc1 → agentexec-0.2.0rc2}/docker-compose.kafka.yml +0 -0
  52. {agentexec-0.2.0rc1 → agentexec-0.2.0rc2}/docs/api-reference/activity.md +0 -0
  53. {agentexec-0.2.0rc1 → agentexec-0.2.0rc2}/docs/api-reference/core.md +0 -0
  54. {agentexec-0.2.0rc1 → agentexec-0.2.0rc2}/docs/api-reference/pipeline.md +0 -0
  55. {agentexec-0.2.0rc1 → agentexec-0.2.0rc2}/docs/api-reference/runner.md +0 -0
  56. {agentexec-0.2.0rc1 → agentexec-0.2.0rc2}/docs/concepts/activity-tracking.md +0 -0
  57. {agentexec-0.2.0rc1 → agentexec-0.2.0rc2}/docs/concepts/architecture.md +0 -0
  58. {agentexec-0.2.0rc1 → agentexec-0.2.0rc2}/docs/concepts/task-lifecycle.md +0 -0
  59. {agentexec-0.2.0rc1 → agentexec-0.2.0rc2}/docs/concepts/worker-pool.md +0 -0
  60. {agentexec-0.2.0rc1 → agentexec-0.2.0rc2}/docs/contributing.md +0 -0
  61. {agentexec-0.2.0rc1 → agentexec-0.2.0rc2}/docs/deployment/docker.md +0 -0
  62. {agentexec-0.2.0rc1 → agentexec-0.2.0rc2}/docs/deployment/production.md +0 -0
  63. {agentexec-0.2.0rc1 → agentexec-0.2.0rc2}/docs/getting-started/configuration.md +0 -0
  64. {agentexec-0.2.0rc1 → agentexec-0.2.0rc2}/docs/getting-started/installation.md +0 -0
  65. {agentexec-0.2.0rc1 → agentexec-0.2.0rc2}/docs/getting-started/quickstart.md +0 -0
  66. {agentexec-0.2.0rc1 → agentexec-0.2.0rc2}/docs/guides/basic-usage.md +0 -0
  67. {agentexec-0.2.0rc1 → agentexec-0.2.0rc2}/docs/guides/custom-runners.md +0 -0
  68. {agentexec-0.2.0rc1 → agentexec-0.2.0rc2}/docs/guides/fastapi-integration.md +0 -0
  69. {agentexec-0.2.0rc1 → agentexec-0.2.0rc2}/docs/guides/openai-runner.md +0 -0
  70. {agentexec-0.2.0rc1 → agentexec-0.2.0rc2}/docs/guides/pipelines.md +0 -0
  71. {agentexec-0.2.0rc1 → agentexec-0.2.0rc2}/docs/index.md +0 -0
  72. {agentexec-0.2.0rc1 → agentexec-0.2.0rc2}/examples/multi-tenancy/README.md +0 -0
  73. {agentexec-0.2.0rc1 → agentexec-0.2.0rc2}/examples/multi-tenancy/example.py +0 -0
  74. {agentexec-0.2.0rc1 → agentexec-0.2.0rc2}/examples/openai-agents-fastapi/README.md +0 -0
  75. {agentexec-0.2.0rc1 → agentexec-0.2.0rc2}/examples/openai-agents-fastapi/alembic/README +0 -0
  76. {agentexec-0.2.0rc1 → agentexec-0.2.0rc2}/examples/openai-agents-fastapi/alembic/env.py +0 -0
  77. {agentexec-0.2.0rc1 → agentexec-0.2.0rc2}/examples/openai-agents-fastapi/alembic/script.py.mako +0 -0
  78. {agentexec-0.2.0rc1 → agentexec-0.2.0rc2}/examples/openai-agents-fastapi/alembic.ini +0 -0
  79. {agentexec-0.2.0rc1 → agentexec-0.2.0rc2}/examples/openai-agents-fastapi/compose.yml +0 -0
  80. {agentexec-0.2.0rc1 → agentexec-0.2.0rc2}/examples/openai-agents-fastapi/context.py +0 -0
  81. {agentexec-0.2.0rc1 → agentexec-0.2.0rc2}/examples/openai-agents-fastapi/db.py +0 -0
  82. {agentexec-0.2.0rc1 → agentexec-0.2.0rc2}/examples/openai-agents-fastapi/main.py +0 -0
  83. {agentexec-0.2.0rc1 → agentexec-0.2.0rc2}/examples/openai-agents-fastapi/models.py +0 -0
  84. {agentexec-0.2.0rc1 → agentexec-0.2.0rc2}/examples/openai-agents-fastapi/pipeline.py +0 -0
  85. {agentexec-0.2.0rc1 → agentexec-0.2.0rc2}/examples/openai-agents-fastapi/pyproject.toml +0 -0
  86. {agentexec-0.2.0rc1 → agentexec-0.2.0rc2}/examples/openai-agents-fastapi/tools.py +0 -0
  87. {agentexec-0.2.0rc1 → agentexec-0.2.0rc2}/examples/openai-agents-fastapi/ui/.gitignore +0 -0
  88. {agentexec-0.2.0rc1 → agentexec-0.2.0rc2}/examples/openai-agents-fastapi/ui/bun.lock +0 -0
  89. {agentexec-0.2.0rc1 → agentexec-0.2.0rc2}/examples/openai-agents-fastapi/ui/index.html +0 -0
  90. {agentexec-0.2.0rc1 → agentexec-0.2.0rc2}/examples/openai-agents-fastapi/ui/package.json +0 -0
  91. {agentexec-0.2.0rc1 → agentexec-0.2.0rc2}/examples/openai-agents-fastapi/ui/public/vite.svg +0 -0
  92. {agentexec-0.2.0rc1 → agentexec-0.2.0rc2}/examples/openai-agents-fastapi/ui/src/App.tsx +0 -0
  93. {agentexec-0.2.0rc1 → agentexec-0.2.0rc2}/examples/openai-agents-fastapi/ui/src/api/agents.ts +0 -0
  94. {agentexec-0.2.0rc1 → agentexec-0.2.0rc2}/examples/openai-agents-fastapi/ui/src/api/queries.ts +0 -0
  95. {agentexec-0.2.0rc1 → agentexec-0.2.0rc2}/examples/openai-agents-fastapi/ui/src/components/Layout.tsx +0 -0
  96. {agentexec-0.2.0rc1 → agentexec-0.2.0rc2}/examples/openai-agents-fastapi/ui/src/index.css +0 -0
  97. {agentexec-0.2.0rc1 → agentexec-0.2.0rc2}/examples/openai-agents-fastapi/ui/src/main.tsx +0 -0
  98. {agentexec-0.2.0rc1 → agentexec-0.2.0rc2}/examples/openai-agents-fastapi/ui/src/pages/AgentDetailPage.tsx +0 -0
  99. {agentexec-0.2.0rc1 → agentexec-0.2.0rc2}/examples/openai-agents-fastapi/ui/src/pages/AgentListPage.tsx +0 -0
  100. {agentexec-0.2.0rc1 → agentexec-0.2.0rc2}/examples/openai-agents-fastapi/ui/src/styles/github-dark.css +0 -0
  101. {agentexec-0.2.0rc1 → agentexec-0.2.0rc2}/examples/openai-agents-fastapi/ui/tsconfig.json +0 -0
  102. {agentexec-0.2.0rc1 → agentexec-0.2.0rc2}/examples/openai-agents-fastapi/ui/tsconfig.node.json +0 -0
  103. {agentexec-0.2.0rc1 → agentexec-0.2.0rc2}/examples/openai-agents-fastapi/ui/vite.config.ts +0 -0
  104. {agentexec-0.2.0rc1 → agentexec-0.2.0rc2}/examples/openai-agents-fastapi/views.py +0 -0
  105. {agentexec-0.2.0rc1 → agentexec-0.2.0rc2}/examples/openai-agents-fastapi/worker.py +0 -0
  106. {agentexec-0.2.0rc1 → agentexec-0.2.0rc2}/examples/queue-fairness/README.md +0 -0
  107. {agentexec-0.2.0rc1 → agentexec-0.2.0rc2}/examples/queue-fairness/run.py +0 -0
  108. {agentexec-0.2.0rc1 → agentexec-0.2.0rc2}/src/agentexec/__init__.py +0 -0
  109. {agentexec-0.2.0rc1 → agentexec-0.2.0rc2}/src/agentexec/activity/schemas.py +0 -0
  110. {agentexec-0.2.0rc1 → agentexec-0.2.0rc2}/src/agentexec/activity/status.py +0 -0
  111. {agentexec-0.2.0rc1 → agentexec-0.2.0rc2}/src/agentexec/config.py +0 -0
  112. {agentexec-0.2.0rc1 → agentexec-0.2.0rc2}/src/agentexec/core/__init__.py +0 -0
  113. {agentexec-0.2.0rc1 → agentexec-0.2.0rc2}/src/agentexec/pipeline.py +0 -0
  114. {agentexec-0.2.0rc1 → agentexec-0.2.0rc2}/src/agentexec/runners/__init__.py +0 -0
  115. {agentexec-0.2.0rc1 → agentexec-0.2.0rc2}/src/agentexec/runners/base.py +0 -0
  116. {agentexec-0.2.0rc1 → agentexec-0.2.0rc2}/src/agentexec/runners/openai.py +0 -0
  117. {agentexec-0.2.0rc1 → agentexec-0.2.0rc2}/src/agentexec/state/__init__.py +0 -0
  118. {agentexec-0.2.0rc1 → agentexec-0.2.0rc2}/src/agentexec/tracker.py +0 -0
  119. {agentexec-0.2.0rc1 → agentexec-0.2.0rc2}/src/agentexec/worker/__init__.py +0 -0
  120. {agentexec-0.2.0rc1 → agentexec-0.2.0rc2}/src/agentexec/worker/event.py +0 -0
  121. {agentexec-0.2.0rc1 → agentexec-0.2.0rc2}/tests/test_activity_schemas.py +0 -0
  122. {agentexec-0.2.0rc1 → agentexec-0.2.0rc2}/tests/test_config.py +0 -0
  123. {agentexec-0.2.0rc1 → agentexec-0.2.0rc2}/tests/test_kafka_integration.py +0 -0
  124. {agentexec-0.2.0rc1 → agentexec-0.2.0rc2}/tests/test_pipeline.py +0 -0
  125. {agentexec-0.2.0rc1 → agentexec-0.2.0rc2}/tests/test_pipeline_flow.py +0 -0
  126. {agentexec-0.2.0rc1 → agentexec-0.2.0rc2}/tests/test_queue.py +0 -0
  127. {agentexec-0.2.0rc1 → agentexec-0.2.0rc2}/tests/test_results.py +0 -0
  128. {agentexec-0.2.0rc1 → agentexec-0.2.0rc2}/tests/test_self_describing_results.py +0 -0
  129. {agentexec-0.2.0rc1 → agentexec-0.2.0rc2}/tests/test_state.py +0 -0
  130. {agentexec-0.2.0rc1 → agentexec-0.2.0rc2}/tests/test_state_backend.py +0 -0
  131. {agentexec-0.2.0rc1 → agentexec-0.2.0rc2}/tests/test_task_types.py +0 -0
  132. {agentexec-0.2.0rc1 → agentexec-0.2.0rc2}/tests/test_worker_event.py +0 -0
  133. {agentexec-0.2.0rc1 → agentexec-0.2.0rc2}/ui/.gitignore +0 -0
  134. {agentexec-0.2.0rc1 → agentexec-0.2.0rc2}/ui/README.md +0 -0
  135. {agentexec-0.2.0rc1 → agentexec-0.2.0rc2}/ui/bun.lock +0 -0
  136. {agentexec-0.2.0rc1 → agentexec-0.2.0rc2}/ui/package.json +0 -0
  137. {agentexec-0.2.0rc1 → agentexec-0.2.0rc2}/ui/src/components/ActiveAgentsBadge.tsx +0 -0
  138. {agentexec-0.2.0rc1 → agentexec-0.2.0rc2}/ui/src/components/ProgressBar.tsx +0 -0
  139. {agentexec-0.2.0rc1 → agentexec-0.2.0rc2}/ui/src/components/StatusBadge.tsx +0 -0
  140. {agentexec-0.2.0rc1 → agentexec-0.2.0rc2}/ui/src/components/TaskDetail.tsx +0 -0
  141. {agentexec-0.2.0rc1 → agentexec-0.2.0rc2}/ui/src/components/TaskList.tsx +0 -0
  142. {agentexec-0.2.0rc1 → agentexec-0.2.0rc2}/ui/src/components/index.ts +0 -0
  143. {agentexec-0.2.0rc1 → agentexec-0.2.0rc2}/ui/src/index.ts +0 -0
  144. {agentexec-0.2.0rc1 → agentexec-0.2.0rc2}/ui/src/types.ts +0 -0
  145. {agentexec-0.2.0rc1 → agentexec-0.2.0rc2}/ui/tsconfig.json +0 -0
  146. {agentexec-0.2.0rc1 → agentexec-0.2.0rc2}/ui/vite.config.ts +0 -0
@@ -0,0 +1 @@
1
+ 3.12
@@ -1,5 +1,118 @@
1
1
  # Changelog
2
2
 
3
+ ## v0.2.0rc2
4
+
5
+ Second release candidate for 0.2.0. Completes the async migration and
6
+ stabilizes the worker pool architecture.
7
+
8
+ ### Breaking Changes
9
+
10
+ **Fully async database layer**
11
+ - `configure_engine()` and `get_session()` now require an async SQLAlchemy engine (`AsyncEngine`) and return `AsyncSession`
12
+ - Database URLs must use async drivers (e.g. `sqlite+aiosqlite://`, `postgresql+asyncpg://`)
13
+ - `sqlalchemy[asyncio]` is now a core dependency; `aiosqlite` added as dev dependency
14
+
15
+ **Async activity query API**
16
+ - `activity.list()`, `activity.detail()`, and `activity.count_active()` are now async and accept `AsyncSession`
17
+ - Activity handlers are now async (`async def __call__`)
18
+
19
+ **Removed `session` parameter from activity mutations**
20
+ - `activity.create()`, `activity.update()`, `activity.complete()`, and `activity.error()` no longer accept a `session` parameter — the handler owns its own session lifecycle
21
+
22
+ **Queue priority parameter**
23
+ - `BaseQueueBackend.push()` signature changed from `high_priority: bool` to `priority: Priority | None`
24
+ - Affects Redis, Kafka, and any custom queue backend implementations
25
+
26
+ ### New Features
27
+
28
+ **CLI entrypoint**
29
+ - New `agentexec` CLI command via `[project.scripts]`
30
+
31
+ **Activity model `create()` classmethod**
32
+ - `Activity.create()` encapsulates record + initial log entry creation in one async call
33
+
34
+ **Async engine disposal**
35
+ - `dispose_engine()` ensures the async engine's background threads exit cleanly on shutdown
36
+
37
+ ### Architecture Changes
38
+
39
+ **Worker pool refactor**
40
+ - Workers now use the `spawn` multiprocessing start method with explicit context — no inherited state
41
+ - `StateEvent` replaced with stdlib `multiprocessing.Event` — removes dependency on the state backend for shutdown coordination
42
+ - Event handling and scheduling extracted into `_EventHandler` and `_Scheduler` classes
43
+ - Worker processes are now daemonic with `SIGINT` ignored — clean shutdown driven by the event
44
+ - `pool.start()` handles `CancelledError` directly for Ctrl+C shutdown
45
+
46
+ **Logging overhaul**
47
+ - Removed `worker/logging.py` and `core/logging.py` — all modules use stdlib `logging.getLogger(__name__)`
48
+ - Spawned workers bootstrap a `StreamHandler` on the root logger so logs reach stderr
49
+ - Pool messages use `logger.info`/`logger.error` instead of `print()`
50
+
51
+ ### Bug Fixes
52
+
53
+ - Fixed crash when worker receives a task for an unregistered task name (now logs error and skips)
54
+ - Failed tasks now log full tracebacks via `logger.exception` instead of `logger.error`
55
+ - Kafka consumer handles `None` message values without crashing
56
+ - `ActivityUpdated.status` is now `Status` enum instead of raw string
57
+ - `raise e` instead of bare `raise` in task execution for clearer tracebacks
58
+
59
+ ### Improvements
60
+
61
+ - Dependency groups use PEP 735 `[dependency-groups]` instead of `[tool.uv]`
62
+ - Ruff line-length increased to 110
63
+ - Removed verbose docstring examples and redundant comments throughout activity models
64
+ - `selectinload` for eager loading of activity logs in `get_by_agent_id`
65
+ - Redis backend adds `type: ignore` annotations for redis-py async stubs
66
+
67
+ ## v0.2.0rc1
68
+
69
+ First release candidate for 0.2.0. Major refactor of the backend, queue,
70
+ activity, and worker systems.
71
+
72
+ ### Breaking Changes
73
+
74
+ **Backend module restructure**
75
+ - `agentexec.state.redis_backend` renamed to `agentexec.state.redis` — update `AGENTEXEC_STATE_BACKEND` if set explicitly
76
+ - `AGENTEXEC_QUEUE_NAME` renamed to `AGENTEXEC_QUEUE_PREFIX` (old name still accepted as alias)
77
+
78
+ **Async activity API**
79
+ - Activity functions are now async: `await ax.activity.create(...)`, `await ax.activity.update(...)`, etc.
80
+
81
+ **Task context serialization**
82
+ - `Task.context` is now `Mapping[str, Any]` (raw dict), not a typed BaseModel — hydration happens at execution time
83
+ - `Task.create()` is now async
84
+
85
+ **Removed APIs**
86
+ - `set_global_session`/`get_global_session`/`remove_global_session` — use `configure_engine`/`get_session`
87
+ - `state.backend.publish`/`subscribe` (pubsub), `index_add`/`index_range`/`index_remove`, `clear`, `configure`
88
+
89
+ ### New Features
90
+
91
+ **Partitioned Redis queues**
92
+ - Tasks with `lock_key` route to dedicated partition queues with per-partition locking and SCAN-based fair dequeue
93
+
94
+ **Activity handler pattern**
95
+ - Pluggable persistence via `PostgresHandler` (default) and `IPCHandler` (worker processes)
96
+
97
+ **Task retry**
98
+ - Failed tasks requeue as high priority with `AGENTEXEC_MAX_TASK_RETRIES` (default 3)
99
+
100
+ **Kafka backend (experimental)**
101
+ - `pip install agentexec[kafka]` for queue and schedule via Kafka
102
+
103
+ **Typed worker IPC**
104
+ - `TaskFailed`, `LogEntry`, `ActivityUpdated` messages over `multiprocessing.Queue`
105
+
106
+ **Schedule composite keys**
107
+ - `{task_name}:{cron}:{context_hash}` for unique schedule identity
108
+
109
+ ### Improvements
110
+
111
+ - Class-based backend architecture with ABCs (`BaseStateBackend`, `BaseQueueBackend`, `BaseScheduleBackend`)
112
+ - `Task` is pure data, `TaskDefinition` owns behavior
113
+ - Session management via `configure_engine`/`get_session` (Pool owns the engine)
114
+ - Status enum extracted to `activity/status.py` (no SQLAlchemy dependency)
115
+
3
116
  ## v0.1.7
4
117
 
5
118
  ### New Features
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: agentexec
3
- Version: 0.2.0rc1
3
+ Version: 0.2.0rc2
4
4
  Summary: Production-ready orchestration for OpenAI Agents with Redis-backed coordination, activity tracking, and workflow management
5
5
  Project-URL: Homepage, https://github.com/Agent-CI/agentexec
6
6
  Project-URL: Documentation, https://github.com/Agent-CI/agentexec#readme
@@ -21,7 +21,7 @@ Requires-Dist: openai-agents>=0.1.0
21
21
  Requires-Dist: pydantic-settings>=2.5.0
22
22
  Requires-Dist: pydantic>=2.12.0
23
23
  Requires-Dist: redis>=7.0.1
24
- Requires-Dist: sqlalchemy>=2.0.44
24
+ Requires-Dist: sqlalchemy[asyncio]>=2.0.44
25
25
  Provides-Extra: kafka
26
26
  Requires-Dist: aiokafka>=0.11.0; extra == 'kafka'
27
27
  Description-Content-Type: text/markdown
@@ -0,0 +1,91 @@
1
+ # Release Process
2
+
3
+ This document describes how to publish a new release of agentexec.
4
+
5
+ ## Overview
6
+
7
+ Creating a **GitHub Release** triggers three publish workflows automatically:
8
+
9
+ | Workflow | Target | Secret Required |
10
+ |---|---|---|
11
+ | `publish.yml` | PyPI | `PYPI_API_TOKEN` |
12
+ | `docker-publish.yml` | ghcr.io (`agentexec-worker`) | `GITHUB_TOKEN` (built-in) |
13
+ | `npm-publish.yml` | npm (`agentexec-ui`) | `NPM_TOKEN` |
14
+
15
+ Docker and npm publishing can also be triggered manually via workflow dispatch.
16
+
17
+ ## Steps
18
+
19
+ ### 1. Ensure CI is green
20
+
21
+ Push all changes to `main` and verify the CI workflow passes (unit tests on
22
+ Python 3.12/3.13 and Kafka integration tests).
23
+
24
+ ### 2. Bump the version
25
+
26
+ Update the version in `pyproject.toml`:
27
+
28
+ ```toml
29
+ version = "X.Y.Z" # stable release
30
+ version = "X.Y.ZrcN" # release candidate
31
+ ```
32
+
33
+ For the UI package, also update `ui/package.json`.
34
+
35
+ Commit and push:
36
+
37
+ ```bash
38
+ git add pyproject.toml
39
+ git commit -m "Bump version to X.Y.Z"
40
+ git push
41
+ ```
42
+
43
+ ### 3. Update CHANGELOG.md
44
+
45
+ Add a new section at the top of `CHANGELOG.md` with release notes covering
46
+ breaking changes, new features, improvements, bug fixes, and testing updates.
47
+
48
+ ### 4. Tag the release
49
+
50
+ ```bash
51
+ git tag vX.Y.Z
52
+ git push origin vX.Y.Z
53
+ ```
54
+
55
+ ### 5. Create the GitHub Release
56
+
57
+ This is what triggers the publish workflows.
58
+
59
+ ```bash
60
+ gh release create vX.Y.Z --title "vX.Y.Z" --notes-file CHANGELOG.md
61
+ ```
62
+
63
+ For release candidates, mark as a pre-release:
64
+
65
+ ```bash
66
+ gh release create vX.Y.ZrcN --title "vX.Y.ZrcN" --generate-notes --prerelease
67
+ ```
68
+
69
+ ### 6. Verify
70
+
71
+ Check that all three publish workflows succeeded:
72
+
73
+ ```bash
74
+ gh run list --limit 5
75
+ ```
76
+
77
+ - **PyPI**: https://pypi.org/project/agentexec/
78
+ - **Docker**: https://ghcr.io/agent-ci/agentexec-worker
79
+ - **npm**: https://www.npmjs.com/package/agentexec-ui
80
+
81
+ ## Manual Publishing
82
+
83
+ Docker and npm workflows support manual dispatch for one-off builds:
84
+
85
+ ```bash
86
+ # Docker with a custom tag
87
+ gh workflow run docker-publish.yml -f tag=dev
88
+
89
+ # npm with a version override
90
+ gh workflow run npm-publish.yml -f version=0.2.0-beta.1
91
+ ```
@@ -0,0 +1,30 @@
1
+ """Debug: patch Worker to print tasks dict on startup, then run via Pool.run()."""
2
+ import sys
3
+ import os
4
+ import logging
5
+
6
+ sys.path.insert(0, os.getcwd())
7
+
8
+ logging.basicConfig(
9
+ level=logging.INFO,
10
+ format="[%(levelname)s/%(processName)s] %(name)s: %(message)s",
11
+ )
12
+
13
+ from worker import pool
14
+ from agentexec.worker.pool import Worker
15
+
16
+ _orig_init = Worker.__init__
17
+
18
+ def _debug_init(self, worker_id, context):
19
+ _orig_init(self, worker_id, context)
20
+ print(f"[DEBUG] Worker {worker_id} context.tasks = {list(context.tasks.keys())}", flush=True)
21
+ print(f"[DEBUG] Worker {worker_id} sys.path[:5] = {sys.path[:5]}", flush=True)
22
+
23
+ Worker.__init__ = _debug_init
24
+
25
+ from agentexec.config import CONF
26
+ CONF.num_workers = 1
27
+
28
+ if __name__ == "__main__":
29
+ print(f"[DEBUG] Parent tasks = {list(pool._context.tasks.keys())}")
30
+ pool.run()
@@ -0,0 +1,26 @@
1
+ """Enqueue tasks for the worker pool.
2
+
3
+ Simulates what an API server would do when a user submits work.
4
+
5
+ Usage:
6
+ uv run python enqueue.py
7
+ """
8
+
9
+ import asyncio
10
+
11
+ import agentexec as ax
12
+ from worker import ResearchContext, GreetContext, ErrorContext
13
+
14
+
15
+ async def main():
16
+ await ax.enqueue("research", ResearchContext(company="Anthropic"))
17
+ await ax.enqueue("research", ResearchContext(company="OpenAI"))
18
+ await ax.enqueue("greet", GreetContext(name="World"))
19
+ await ax.enqueue("error", ErrorContext())
20
+
21
+ print("Enqueued 4 tasks")
22
+ return
23
+
24
+
25
+ if __name__ == "__main__":
26
+ asyncio.run(main())
@@ -0,0 +1,2 @@
1
+ #!/bin/sh
2
+ agentexec run worker:pool --create-tables
@@ -0,0 +1,50 @@
1
+ """Task definitions for the basic example.
2
+
3
+ This module is imported by both the run script and the spawned worker
4
+ processes. Keep it free of side effects — no asyncio.run(), no table
5
+ creation, no enqueue calls.
6
+ """
7
+
8
+ import asyncio
9
+ import logging
10
+ from uuid import UUID
11
+
12
+ from pydantic import BaseModel
13
+ from sqlalchemy.ext.asyncio import create_async_engine
14
+
15
+ import agentexec as ax
16
+
17
+ logger = logging.getLogger(__name__)
18
+
19
+ engine = create_async_engine("sqlite+aiosqlite:///agents.db")
20
+ pool = ax.Pool(engine=engine)
21
+
22
+
23
+ class ResearchContext(BaseModel):
24
+ company: str
25
+
26
+
27
+ class GreetContext(BaseModel):
28
+ name: str
29
+
30
+
31
+ class ErrorContext(BaseModel):
32
+ pass
33
+
34
+
35
+ @pool.task("research")
36
+ async def research(agent_id: UUID, context: ResearchContext):
37
+ logger.info(f"Researching {context.company}...")
38
+ await asyncio.sleep(1)
39
+ logger.info(f"Done researching {context.company}")
40
+
41
+
42
+ @pool.task("greet")
43
+ async def greet(agent_id: UUID, context: GreetContext):
44
+ logger.info(f"Hello, {context.name}!")
45
+
46
+
47
+ @pool.task("error")
48
+ async def handle_error(agent_id: UUID, context: ErrorContext) -> None:
49
+ logger.info("This will throw an error")
50
+ raise Exception("Intentional error")
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "agentexec"
3
- version = "0.2.0rc1"
3
+ version = "0.2.0rc2"
4
4
  description = "Production-ready orchestration for OpenAI Agents with Redis-backed coordination, activity tracking, and workflow management"
5
5
  readme = "README.md"
6
6
  requires-python = ">=3.12"
@@ -23,7 +23,7 @@ dependencies = [
23
23
  "redis>=7.0.1",
24
24
  "pydantic>=2.12.0",
25
25
  "pydantic-settings>=2.5.0",
26
- "sqlalchemy>=2.0.44",
26
+ "sqlalchemy[asyncio]>=2.0.44",
27
27
  "openai-agents>=0.1.0",
28
28
  "croniter>=6.0.0",
29
29
  ]
@@ -34,6 +34,9 @@ kafka = [
34
34
  ]
35
35
 
36
36
 
37
+ [project.scripts]
38
+ agentexec = "agentexec.cli:main"
39
+
37
40
  [project.urls]
38
41
  Homepage = "https://github.com/Agent-CI/agentexec"
39
42
  Documentation = "https://github.com/Agent-CI/agentexec#readme"
@@ -47,8 +50,8 @@ build-backend = "hatchling.build"
47
50
  [tool.hatch.build.targets.wheel]
48
51
  packages = ["src/agentexec"]
49
52
 
50
- [tool.uv]
51
- dev-dependencies = [
53
+ [dependency-groups]
54
+ dev = [
52
55
  "pytest>=8.0.0",
53
56
  "pytest-asyncio>=0.23.0",
54
57
  "pytest-cov>=4.1.0",
@@ -56,10 +59,11 @@ dev-dependencies = [
56
59
  "ty>=0.0.1a7",
57
60
  "fakeredis>=2.32.1",
58
61
  "pytest-ty>=0.1.3",
62
+ "aiosqlite>=0.22.1",
59
63
  ]
60
64
 
61
65
  [tool.ruff]
62
- line-length = 100
66
+ line-length = 110
63
67
  target-version = "py312"
64
68
 
65
69
  [tool.ty.environment]