agentseek-api 0.2.0__tar.gz → 0.2.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 (248) hide show
  1. {agentseek_api-0.2.0 → agentseek_api-0.2.2}/.env.example +1 -0
  2. {agentseek_api-0.2.0 → agentseek_api-0.2.2}/.github/workflows/ci.yml +15 -2
  3. agentseek_api-0.2.2/CHANGELOG.md +88 -0
  4. agentseek_api-0.2.0/README.md → agentseek_api-0.2.2/PKG-INFO +64 -2
  5. agentseek_api-0.2.0/PKG-INFO → agentseek_api-0.2.2/README.md +32 -33
  6. {agentseek_api-0.2.0 → agentseek_api-0.2.2}/README.zh-CN.md +1 -1
  7. {agentseek_api-0.2.0 → agentseek_api-0.2.2}/pyproject.toml +7 -6
  8. {agentseek_api-0.2.0 → agentseek_api-0.2.2}/scripts/test-redis-runtime.sh +136 -7
  9. agentseek_api-0.2.2/scripts/test_minimum_cli_dependencies.py +109 -0
  10. agentseek_api-0.2.2/scripts/verify_worker_concurrency.py +528 -0
  11. agentseek_api-0.2.2/src/agentseek_api/__init__.py +1 -0
  12. {agentseek_api-0.2.0 → agentseek_api-0.2.2}/src/agentseek_api/api/assistants.py +48 -6
  13. {agentseek_api-0.2.0 → agentseek_api-0.2.2}/src/agentseek_api/api/runs.py +12 -0
  14. {agentseek_api-0.2.0 → agentseek_api-0.2.2}/src/agentseek_api/cli.py +148 -59
  15. agentseek_api-0.2.2/src/agentseek_api/constants.py +3 -0
  16. {agentseek_api-0.2.0 → agentseek_api-0.2.2}/src/agentseek_api/core/database.py +12 -1
  17. agentseek_api-0.2.2/src/agentseek_api/dotenv_adapter.py +69 -0
  18. agentseek_api-0.2.2/src/agentseek_api/process_supervisor.py +1531 -0
  19. agentseek_api-0.2.2/src/agentseek_api/runtime_entrypoint.py +59 -0
  20. {agentseek_api-0.2.0 → agentseek_api-0.2.2}/src/agentseek_api/services/redis_queue.py +18 -0
  21. {agentseek_api-0.2.0 → agentseek_api-0.2.2}/src/agentseek_api/services/run_executor.py +30 -1
  22. {agentseek_api-0.2.0 → agentseek_api-0.2.2}/src/agentseek_api/services/run_preparation.py +27 -0
  23. {agentseek_api-0.2.0 → agentseek_api-0.2.2}/src/agentseek_api/services/stream_persistence.py +20 -5
  24. {agentseek_api-0.2.0 → agentseek_api-0.2.2}/src/agentseek_api/settings.py +2 -1
  25. agentseek_api-0.2.2/src/agentseek_api/worker.py +347 -0
  26. {agentseek_api-0.2.0 → agentseek_api-0.2.2}/tests/e2e/test_langsmith_compat_live.py +3 -3
  27. agentseek_api-0.2.2/tests/fixtures/runtime_settings_probe/sitecustomize.py +69 -0
  28. agentseek_api-0.2.2/tests/fixtures/termination_tree.py +67 -0
  29. {agentseek_api-0.2.0 → agentseek_api-0.2.2}/tests/integration/test_assistants_compat.py +2 -2
  30. agentseek_api-0.2.2/tests/integration/test_assistants_config_context_sync.py +145 -0
  31. agentseek_api-0.2.2/tests/integration/test_cli_runtime_processes.py +812 -0
  32. {agentseek_api-0.2.0 → agentseek_api-0.2.2}/tests/integration/test_langsmith_compat_coverage.py +2 -2
  33. agentseek_api-0.2.2/tests/integration/test_live_redis_queue.py +69 -0
  34. agentseek_api-0.2.2/tests/integration/test_live_redis_stream_persistence.py +75 -0
  35. {agentseek_api-0.2.0 → agentseek_api-0.2.2}/tests/integration/test_metadata_db_config.py +23 -8
  36. agentseek_api-0.2.2/tests/integration/test_runs_streaming.py +301 -0
  37. {agentseek_api-0.2.0 → agentseek_api-0.2.2}/tests/integration/test_stream_persistence.py +85 -1
  38. {agentseek_api-0.2.0 → agentseek_api-0.2.2}/tests/unit/test_assistant_routes_unit.py +4 -4
  39. {agentseek_api-0.2.0 → agentseek_api-0.2.2}/tests/unit/test_cli.py +689 -80
  40. agentseek_api-0.2.2/tests/unit/test_dotenv_adapter.py +89 -0
  41. agentseek_api-0.2.2/tests/unit/test_process_supervisor.py +2860 -0
  42. {agentseek_api-0.2.0 → agentseek_api-0.2.2}/tests/unit/test_redis_queue.py +26 -0
  43. agentseek_api-0.2.2/tests/unit/test_redis_runtime_script.py +68 -0
  44. agentseek_api-0.2.2/tests/unit/test_run_controls_validation.py +27 -0
  45. {agentseek_api-0.2.0 → agentseek_api-0.2.2}/tests/unit/test_run_executor.py +267 -1
  46. {agentseek_api-0.2.0 → agentseek_api-0.2.2}/tests/unit/test_run_preparation.py +139 -0
  47. agentseek_api-0.2.2/tests/unit/test_runtime_entrypoint.py +171 -0
  48. agentseek_api-0.2.2/tests/unit/test_runtime_environment.py +603 -0
  49. agentseek_api-0.2.2/tests/unit/test_worker.py +650 -0
  50. agentseek_api-0.2.2/tests/unit/test_worker_concurrency_probe.py +581 -0
  51. {agentseek_api-0.2.0 → agentseek_api-0.2.2}/uv.lock +8 -6
  52. agentseek_api-0.2.0/CHANGELOG.md +0 -22
  53. agentseek_api-0.2.0/src/agentseek_api/__init__.py +0 -1
  54. agentseek_api-0.2.0/src/agentseek_api/worker.py +0 -103
  55. agentseek_api-0.2.0/tests/integration/test_runs_streaming.py +0 -142
  56. agentseek_api-0.2.0/tests/unit/test_worker.py +0 -155
  57. {agentseek_api-0.2.0 → agentseek_api-0.2.2}/.dockerignore +0 -0
  58. {agentseek_api-0.2.0 → agentseek_api-0.2.2}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
  59. {agentseek_api-0.2.0 → agentseek_api-0.2.2}/.github/workflows/live-provider-streaming.yml +0 -0
  60. {agentseek_api-0.2.0 → agentseek_api-0.2.2}/.github/workflows/release.yml +0 -0
  61. {agentseek_api-0.2.0 → agentseek_api-0.2.2}/.gitignore +0 -0
  62. {agentseek_api-0.2.0 → agentseek_api-0.2.2}/AGENTS.md +0 -0
  63. {agentseek_api-0.2.0 → agentseek_api-0.2.2}/CONTRIBUTING.md +0 -0
  64. {agentseek_api-0.2.0 → agentseek_api-0.2.2}/LICENSE +0 -0
  65. {agentseek_api-0.2.0 → agentseek_api-0.2.2}/Makefile +0 -0
  66. {agentseek_api-0.2.0 → agentseek_api-0.2.2}/examples/README.md +0 -0
  67. {agentseek_api-0.2.0 → agentseek_api-0.2.2}/examples/__init__.py +0 -0
  68. {agentseek_api-0.2.0 → agentseek_api-0.2.2}/examples/assistant_config/agentseek.json +0 -0
  69. {agentseek_api-0.2.0 → agentseek_api-0.2.2}/examples/assistant_config/graph.py +0 -0
  70. {agentseek_api-0.2.0 → agentseek_api-0.2.2}/examples/auth/api_key_auth.py +0 -0
  71. {agentseek_api-0.2.0 → agentseek_api-0.2.2}/examples/auth/bearer_token_auth.py +0 -0
  72. {agentseek_api-0.2.0 → agentseek_api-0.2.2}/examples/auth/custom_backend.py +0 -0
  73. {agentseek_api-0.2.0 → agentseek_api-0.2.2}/examples/auth/jwt.md +0 -0
  74. {agentseek_api-0.2.0 → agentseek_api-0.2.2}/examples/auth/jwt_auth.py +0 -0
  75. {agentseek_api-0.2.0 → agentseek_api-0.2.2}/examples/custom_routes/app.py +0 -0
  76. {agentseek_api-0.2.0 → agentseek_api-0.2.2}/examples/docker_ci_auth/auth_backend.py +0 -0
  77. {agentseek_api-0.2.0 → agentseek_api-0.2.2}/examples/docker_ci_auth/manifest.json +0 -0
  78. {agentseek_api-0.2.0 → agentseek_api-0.2.2}/examples/external_graph/__init__.py +0 -0
  79. {agentseek_api-0.2.0 → agentseek_api-0.2.2}/examples/external_graph/graph.py +0 -0
  80. {agentseek_api-0.2.0 → agentseek_api-0.2.2}/examples/external_graph/manifest.json +0 -0
  81. {agentseek_api-0.2.0 → agentseek_api-0.2.2}/examples/external_graph/run.py +0 -0
  82. {agentseek_api-0.2.0 → agentseek_api-0.2.2}/examples/graphs/__init__.py +0 -0
  83. {agentseek_api-0.2.0 → agentseek_api-0.2.2}/examples/graphs/react_agent/__init__.py +0 -0
  84. {agentseek_api-0.2.0 → agentseek_api-0.2.2}/examples/graphs/react_agent/graph.py +0 -0
  85. {agentseek_api-0.2.0 → agentseek_api-0.2.2}/examples/graphs/store_memory/graph.py +0 -0
  86. {agentseek_api-0.2.0 → agentseek_api-0.2.2}/examples/graphs/stress_test/__init__.py +0 -0
  87. {agentseek_api-0.2.0 → agentseek_api-0.2.2}/examples/graphs/stress_test/graph.py +0 -0
  88. {agentseek_api-0.2.0 → agentseek_api-0.2.2}/examples/graphs/stress_tool_agent/__init__.py +0 -0
  89. {agentseek_api-0.2.0 → agentseek_api-0.2.2}/examples/graphs/stress_tool_agent/graph.py +0 -0
  90. {agentseek_api-0.2.0 → agentseek_api-0.2.2}/examples/graphs/subgraph_agent/__init__.py +0 -0
  91. {agentseek_api-0.2.0 → agentseek_api-0.2.2}/examples/graphs/subgraph_agent/graph.py +0 -0
  92. {agentseek_api-0.2.0 → agentseek_api-0.2.2}/examples/graphs/subgraph_hitl_agent/__init__.py +0 -0
  93. {agentseek_api-0.2.0 → agentseek_api-0.2.2}/examples/graphs/subgraph_hitl_agent/graph.py +0 -0
  94. {agentseek_api-0.2.0 → agentseek_api-0.2.2}/examples/live_provider_graphs/__init__.py +0 -0
  95. {agentseek_api-0.2.0 → agentseek_api-0.2.2}/examples/live_provider_graphs/graph.py +0 -0
  96. {agentseek_api-0.2.0 → agentseek_api-0.2.2}/examples/live_provider_graphs/manifest.json +0 -0
  97. {agentseek_api-0.2.0 → agentseek_api-0.2.2}/examples/minimal_agentseek/agentseek.json +0 -0
  98. {agentseek_api-0.2.0 → agentseek_api-0.2.2}/examples/minimal_agentseek/graph.py +0 -0
  99. {agentseek_api-0.2.0 → agentseek_api-0.2.2}/examples/run_sample_graphs.py +0 -0
  100. {agentseek_api-0.2.0 → agentseek_api-0.2.2}/examples/sample_graphs_manifest.json +0 -0
  101. {agentseek_api-0.2.0 → agentseek_api-0.2.2}/scripts/build_live_provider_matrix.py +0 -0
  102. {agentseek_api-0.2.0 → agentseek_api-0.2.2}/scripts/seekdb_checkpoint_smoke.py +0 -0
  103. {agentseek_api-0.2.0 → agentseek_api-0.2.2}/scripts/seekdb_embed_launcher.py +0 -0
  104. {agentseek_api-0.2.0 → agentseek_api-0.2.2}/scripts/test-checkpoints.sh +0 -0
  105. {agentseek_api-0.2.0 → agentseek_api-0.2.2}/scripts/test-cli-dev-samples.sh +0 -0
  106. {agentseek_api-0.2.0 → agentseek_api-0.2.2}/scripts/test-cli-docker.sh +0 -0
  107. {agentseek_api-0.2.0 → agentseek_api-0.2.2}/scripts/test-live-provider.sh +0 -0
  108. {agentseek_api-0.2.0 → agentseek_api-0.2.2}/scripts/test-seekdb.sh +0 -0
  109. {agentseek_api-0.2.0 → agentseek_api-0.2.2}/scripts/test_cli_config_autodiscovery.py +0 -0
  110. {agentseek_api-0.2.0 → agentseek_api-0.2.2}/scripts/test_cli_dev_studio_smoke.py +0 -0
  111. {agentseek_api-0.2.0 → agentseek_api-0.2.2}/scripts/test_cli_embed_serve_smoke.py +0 -0
  112. {agentseek_api-0.2.0 → agentseek_api-0.2.2}/scripts/test_cli_serve_smoke.py +0 -0
  113. {agentseek_api-0.2.0 → agentseek_api-0.2.2}/scripts/verify_docker_api.py +0 -0
  114. {agentseek_api-0.2.0 → agentseek_api-0.2.2}/src/agentseek_api/a2a_server.py +0 -0
  115. {agentseek_api-0.2.0 → agentseek_api-0.2.2}/src/agentseek_api/api/__init__.py +0 -0
  116. {agentseek_api-0.2.0 → agentseek_api-0.2.2}/src/agentseek_api/api/crons.py +0 -0
  117. {agentseek_api-0.2.0 → agentseek_api-0.2.2}/src/agentseek_api/api/stateless_runs.py +0 -0
  118. {agentseek_api-0.2.0 → agentseek_api-0.2.2}/src/agentseek_api/api/store.py +0 -0
  119. {agentseek_api-0.2.0 → agentseek_api-0.2.2}/src/agentseek_api/api/streaming.py +0 -0
  120. {agentseek_api-0.2.0 → agentseek_api-0.2.2}/src/agentseek_api/api/threads.py +0 -0
  121. {agentseek_api-0.2.0 → agentseek_api-0.2.2}/src/agentseek_api/core/__init__.py +0 -0
  122. {agentseek_api-0.2.0 → agentseek_api-0.2.2}/src/agentseek_api/core/a2a_config.py +0 -0
  123. {agentseek_api-0.2.0 → agentseek_api-0.2.2}/src/agentseek_api/core/app_loader.py +0 -0
  124. {agentseek_api-0.2.0 → agentseek_api-0.2.2}/src/agentseek_api/core/auth_deps.py +0 -0
  125. {agentseek_api-0.2.0 → agentseek_api-0.2.2}/src/agentseek_api/core/auth_middleware.py +0 -0
  126. {agentseek_api-0.2.0 → agentseek_api-0.2.2}/src/agentseek_api/core/config_file.py +0 -0
  127. {agentseek_api-0.2.0 → agentseek_api-0.2.2}/src/agentseek_api/core/content_type_fix.py +0 -0
  128. {agentseek_api-0.2.0 → agentseek_api-0.2.2}/src/agentseek_api/core/cors_config.py +0 -0
  129. {agentseek_api-0.2.0 → agentseek_api-0.2.2}/src/agentseek_api/core/http_config.py +0 -0
  130. {agentseek_api-0.2.0 → agentseek_api-0.2.2}/src/agentseek_api/core/mcp_config.py +0 -0
  131. {agentseek_api-0.2.0 → agentseek_api-0.2.2}/src/agentseek_api/core/oceanbase_checkpointer.py +0 -0
  132. {agentseek_api-0.2.0 → agentseek_api-0.2.2}/src/agentseek_api/core/orm.py +0 -0
  133. {agentseek_api-0.2.0 → agentseek_api-0.2.2}/src/agentseek_api/core/runtime_store.py +0 -0
  134. {agentseek_api-0.2.0 → agentseek_api-0.2.2}/src/agentseek_api/core/store_config.py +0 -0
  135. {agentseek_api-0.2.0 → agentseek_api-0.2.2}/src/agentseek_api/main.py +0 -0
  136. {agentseek_api-0.2.0 → agentseek_api-0.2.2}/src/agentseek_api/mcp_server.py +0 -0
  137. {agentseek_api-0.2.0 → agentseek_api-0.2.2}/src/agentseek_api/models/__init__.py +0 -0
  138. {agentseek_api-0.2.0 → agentseek_api-0.2.2}/src/agentseek_api/models/api.py +0 -0
  139. {agentseek_api-0.2.0 → agentseek_api-0.2.2}/src/agentseek_api/models/auth.py +0 -0
  140. {agentseek_api-0.2.0 → agentseek_api-0.2.2}/src/agentseek_api/models/protocol.py +0 -0
  141. {agentseek_api-0.2.0 → agentseek_api-0.2.2}/src/agentseek_api/scheduler.py +0 -0
  142. {agentseek_api-0.2.0 → agentseek_api-0.2.2}/src/agentseek_api/services/__init__.py +0 -0
  143. {agentseek_api-0.2.0 → agentseek_api-0.2.2}/src/agentseek_api/services/cron_models.py +0 -0
  144. {agentseek_api-0.2.0 → agentseek_api-0.2.2}/src/agentseek_api/services/cron_rrule.py +0 -0
  145. {agentseek_api-0.2.0 → agentseek_api-0.2.2}/src/agentseek_api/services/cron_scheduler.py +0 -0
  146. {agentseek_api-0.2.0 → agentseek_api-0.2.2}/src/agentseek_api/services/cron_service.py +0 -0
  147. {agentseek_api-0.2.0 → agentseek_api-0.2.2}/src/agentseek_api/services/cron_webhooks.py +0 -0
  148. {agentseek_api-0.2.0 → agentseek_api-0.2.2}/src/agentseek_api/services/default_assistants.py +0 -0
  149. {agentseek_api-0.2.0 → agentseek_api-0.2.2}/src/agentseek_api/services/executor.py +0 -0
  150. {agentseek_api-0.2.0 → agentseek_api-0.2.2}/src/agentseek_api/services/langgraph_service.py +0 -0
  151. {agentseek_api-0.2.0 → agentseek_api-0.2.2}/src/agentseek_api/services/run_jobs.py +0 -0
  152. {agentseek_api-0.2.0 → agentseek_api-0.2.2}/src/agentseek_api/services/run_state.py +0 -0
  153. {agentseek_api-0.2.0 → agentseek_api-0.2.2}/src/agentseek_api/services/sample_graphs.py +0 -0
  154. {agentseek_api-0.2.0 → agentseek_api-0.2.2}/src/agentseek_api/services/sse.py +0 -0
  155. {agentseek_api-0.2.0 → agentseek_api-0.2.2}/src/agentseek_api/services/stream_modes.py +0 -0
  156. {agentseek_api-0.2.0 → agentseek_api-0.2.2}/src/agentseek_api/services/thread_checkpoint_store.py +0 -0
  157. {agentseek_api-0.2.0 → agentseek_api-0.2.2}/src/agentseek_api/services/thread_protocol.py +0 -0
  158. {agentseek_api-0.2.0 → agentseek_api-0.2.2}/src/agentseek_api/services/thread_service.py +0 -0
  159. {agentseek_api-0.2.0 → agentseek_api-0.2.2}/tests/__init__.py +0 -0
  160. {agentseek_api-0.2.0 → agentseek_api-0.2.2}/tests/conftest.py +0 -0
  161. {agentseek_api-0.2.0 → agentseek_api-0.2.2}/tests/e2e/__init__.py +0 -0
  162. {agentseek_api-0.2.0 → agentseek_api-0.2.2}/tests/e2e/conftest.py +0 -0
  163. {agentseek_api-0.2.0 → agentseek_api-0.2.2}/tests/e2e/e2e_inprocess_flow.py +0 -0
  164. {agentseek_api-0.2.0 → agentseek_api-0.2.2}/tests/e2e/e2e_live_http_flow.py +0 -0
  165. {agentseek_api-0.2.0 → agentseek_api-0.2.2}/tests/e2e/e2e_live_http_multi_graph.py +0 -0
  166. {agentseek_api-0.2.0 → agentseek_api-0.2.2}/tests/e2e/e2e_live_http_resume_flow.py +0 -0
  167. {agentseek_api-0.2.0 → agentseek_api-0.2.2}/tests/e2e/fixtures/langgraph.store-e2e.json +0 -0
  168. {agentseek_api-0.2.0 → agentseek_api-0.2.2}/tests/e2e/live_provider_helpers.py +0 -0
  169. {agentseek_api-0.2.0 → agentseek_api-0.2.2}/tests/e2e/test_a2a_live.py +0 -0
  170. {agentseek_api-0.2.0 → agentseek_api-0.2.2}/tests/e2e/test_cron_api_live.py +0 -0
  171. {agentseek_api-0.2.0 → agentseek_api-0.2.2}/tests/e2e/test_cron_scheduler_live.py +0 -0
  172. {agentseek_api-0.2.0 → agentseek_api-0.2.2}/tests/e2e/test_live_provider_api.py +0 -0
  173. {agentseek_api-0.2.0 → agentseek_api-0.2.2}/tests/e2e/test_live_provider_mcp.py +0 -0
  174. {agentseek_api-0.2.0 → agentseek_api-0.2.2}/tests/e2e/test_mcp_live.py +0 -0
  175. {agentseek_api-0.2.0 → agentseek_api-0.2.2}/tests/e2e/test_real_api_flow.py +0 -0
  176. {agentseek_api-0.2.0 → agentseek_api-0.2.2}/tests/integration/test_a2a_endpoint.py +0 -0
  177. {agentseek_api-0.2.0 → agentseek_api-0.2.2}/tests/integration/test_agent_card.py +0 -0
  178. {agentseek_api-0.2.0 → agentseek_api-0.2.2}/tests/integration/test_agents_aliases.py +0 -0
  179. {agentseek_api-0.2.0 → agentseek_api-0.2.2}/tests/integration/test_assistants_crud.py +0 -0
  180. {agentseek_api-0.2.0 → agentseek_api-0.2.2}/tests/integration/test_assistants_ordering.py +0 -0
  181. {agentseek_api-0.2.0 → agentseek_api-0.2.2}/tests/integration/test_auth_coverage_gaps.py +0 -0
  182. {agentseek_api-0.2.0 → agentseek_api-0.2.2}/tests/integration/test_auth_handlers.py +0 -0
  183. {agentseek_api-0.2.0 → agentseek_api-0.2.2}/tests/integration/test_auth_route_enforcement.py +0 -0
  184. {agentseek_api-0.2.0 → agentseek_api-0.2.2}/tests/integration/test_auth_scope_matrix.py +0 -0
  185. {agentseek_api-0.2.0 → agentseek_api-0.2.2}/tests/integration/test_core_api_flow.py +0 -0
  186. {agentseek_api-0.2.0 → agentseek_api-0.2.2}/tests/integration/test_cron_api.py +0 -0
  187. {agentseek_api-0.2.0 → agentseek_api-0.2.2}/tests/integration/test_langsmith_compat_extra.py +0 -0
  188. {agentseek_api-0.2.0 → agentseek_api-0.2.2}/tests/integration/test_live_provider_streaming.py +0 -0
  189. {agentseek_api-0.2.0 → agentseek_api-0.2.2}/tests/integration/test_mcp_endpoint.py +0 -0
  190. {agentseek_api-0.2.0 → agentseek_api-0.2.2}/tests/integration/test_protocol_v2_streaming.py +0 -0
  191. {agentseek_api-0.2.0 → agentseek_api-0.2.2}/tests/integration/test_run_cancellation_async.py +0 -0
  192. {agentseek_api-0.2.0 → agentseek_api-0.2.2}/tests/integration/test_runs_compat.py +0 -0
  193. {agentseek_api-0.2.0 → agentseek_api-0.2.2}/tests/integration/test_runs_crud.py +0 -0
  194. {agentseek_api-0.2.0 → agentseek_api-0.2.2}/tests/integration/test_runs_ordering.py +0 -0
  195. {agentseek_api-0.2.0 → agentseek_api-0.2.2}/tests/integration/test_runs_resume.py +0 -0
  196. {agentseek_api-0.2.0 → agentseek_api-0.2.2}/tests/integration/test_runs_streaming_errors.py +0 -0
  197. {agentseek_api-0.2.0 → agentseek_api-0.2.2}/tests/integration/test_runs_validation.py +0 -0
  198. {agentseek_api-0.2.0 → agentseek_api-0.2.2}/tests/integration/test_runs_wait_and_get.py +0 -0
  199. {agentseek_api-0.2.0 → agentseek_api-0.2.2}/tests/integration/test_runs_wait_timeout.py +0 -0
  200. {agentseek_api-0.2.0 → agentseek_api-0.2.2}/tests/integration/test_scheduler_runtime.py +0 -0
  201. {agentseek_api-0.2.0 → agentseek_api-0.2.2}/tests/integration/test_stateless_runs_crud.py +0 -0
  202. {agentseek_api-0.2.0 → agentseek_api-0.2.2}/tests/integration/test_store_api.py +0 -0
  203. {agentseek_api-0.2.0 → agentseek_api-0.2.2}/tests/integration/test_system_endpoints.py +0 -0
  204. {agentseek_api-0.2.0 → agentseek_api-0.2.2}/tests/integration/test_threads_compat.py +0 -0
  205. {agentseek_api-0.2.0 → agentseek_api-0.2.2}/tests/integration/test_threads_crud.py +0 -0
  206. {agentseek_api-0.2.0 → agentseek_api-0.2.2}/tests/integration/test_threads_ordering.py +0 -0
  207. {agentseek_api-0.2.0 → agentseek_api-0.2.2}/tests/unit/test_a2a_config.py +0 -0
  208. {agentseek_api-0.2.0 → agentseek_api-0.2.2}/tests/unit/test_a2a_server.py +0 -0
  209. {agentseek_api-0.2.0 → agentseek_api-0.2.2}/tests/unit/test_app_loader.py +0 -0
  210. {agentseek_api-0.2.0 → agentseek_api-0.2.2}/tests/unit/test_auth.py +0 -0
  211. {agentseek_api-0.2.0 → agentseek_api-0.2.2}/tests/unit/test_auth_deps.py +0 -0
  212. {agentseek_api-0.2.0 → agentseek_api-0.2.2}/tests/unit/test_auth_internals.py +0 -0
  213. {agentseek_api-0.2.0 → agentseek_api-0.2.2}/tests/unit/test_checkpoint_guards.py +0 -0
  214. {agentseek_api-0.2.0 → agentseek_api-0.2.2}/tests/unit/test_content_type_fix.py +0 -0
  215. {agentseek_api-0.2.0 → agentseek_api-0.2.2}/tests/unit/test_cron_rrule.py +0 -0
  216. {agentseek_api-0.2.0 → agentseek_api-0.2.2}/tests/unit/test_cron_service.py +0 -0
  217. {agentseek_api-0.2.0 → agentseek_api-0.2.2}/tests/unit/test_cron_webhooks.py +0 -0
  218. {agentseek_api-0.2.0 → agentseek_api-0.2.2}/tests/unit/test_custom_routers.py +0 -0
  219. {agentseek_api-0.2.0 → agentseek_api-0.2.2}/tests/unit/test_database_manager.py +0 -0
  220. {agentseek_api-0.2.0 → agentseek_api-0.2.2}/tests/unit/test_default_assistants.py +0 -0
  221. {agentseek_api-0.2.0 → agentseek_api-0.2.2}/tests/unit/test_examples.py +0 -0
  222. {agentseek_api-0.2.0 → agentseek_api-0.2.2}/tests/unit/test_executor.py +0 -0
  223. {agentseek_api-0.2.0 → agentseek_api-0.2.2}/tests/unit/test_graph_manifest.py +0 -0
  224. {agentseek_api-0.2.0 → agentseek_api-0.2.2}/tests/unit/test_http_config.py +0 -0
  225. {agentseek_api-0.2.0 → agentseek_api-0.2.2}/tests/unit/test_langgraph_service.py +0 -0
  226. {agentseek_api-0.2.0 → agentseek_api-0.2.2}/tests/unit/test_live_provider_e2e_config.py +0 -0
  227. {agentseek_api-0.2.0 → agentseek_api-0.2.2}/tests/unit/test_live_provider_graphs.py +0 -0
  228. {agentseek_api-0.2.0 → agentseek_api-0.2.2}/tests/unit/test_live_provider_matrix.py +0 -0
  229. {agentseek_api-0.2.0 → agentseek_api-0.2.2}/tests/unit/test_mcp_config.py +0 -0
  230. {agentseek_api-0.2.0 → agentseek_api-0.2.2}/tests/unit/test_mcp_server.py +0 -0
  231. {agentseek_api-0.2.0 → agentseek_api-0.2.2}/tests/unit/test_oceanbase_checkpointer.py +0 -0
  232. {agentseek_api-0.2.0 → agentseek_api-0.2.2}/tests/unit/test_openapi_auth_config.py +0 -0
  233. {agentseek_api-0.2.0 → agentseek_api-0.2.2}/tests/unit/test_run_jobs.py +0 -0
  234. {agentseek_api-0.2.0 → agentseek_api-0.2.2}/tests/unit/test_run_state.py +0 -0
  235. {agentseek_api-0.2.0 → agentseek_api-0.2.2}/tests/unit/test_runtime_store.py +0 -0
  236. {agentseek_api-0.2.0 → agentseek_api-0.2.2}/tests/unit/test_sample_graphs.py +0 -0
  237. {agentseek_api-0.2.0 → agentseek_api-0.2.2}/tests/unit/test_scheduler.py +0 -0
  238. {agentseek_api-0.2.0 → agentseek_api-0.2.2}/tests/unit/test_scheduler_process.py +0 -0
  239. {agentseek_api-0.2.0 → agentseek_api-0.2.2}/tests/unit/test_seekdb_checkpoint_smoke.py +0 -0
  240. {agentseek_api-0.2.0 → agentseek_api-0.2.2}/tests/unit/test_seekdb_embed_launcher.py +0 -0
  241. {agentseek_api-0.2.0 → agentseek_api-0.2.2}/tests/unit/test_sse_keepalive.py +0 -0
  242. {agentseek_api-0.2.0 → agentseek_api-0.2.2}/tests/unit/test_store_config.py +0 -0
  243. {agentseek_api-0.2.0 → agentseek_api-0.2.2}/tests/unit/test_stream_modes.py +0 -0
  244. {agentseek_api-0.2.0 → agentseek_api-0.2.2}/tests/unit/test_stream_persistence_helpers.py +0 -0
  245. {agentseek_api-0.2.0 → agentseek_api-0.2.2}/tests/unit/test_thread_checkpoint_store.py +0 -0
  246. {agentseek_api-0.2.0 → agentseek_api-0.2.2}/tests/unit/test_thread_protocol.py +0 -0
  247. {agentseek_api-0.2.0 → agentseek_api-0.2.2}/tests/unit/test_thread_routes_unit.py +0 -0
  248. {agentseek_api-0.2.0 → agentseek_api-0.2.2}/tests/unit/test_thread_service.py +0 -0
@@ -8,6 +8,7 @@ AGENTSEEK_GRAPHS=
8
8
  AUTH_MODULE_PATH=
9
9
 
10
10
  # Redis worker stream replay buffer.
11
+ # WORKER_CONCURRENT_JOBS=10
11
12
  # REDIS_STREAM_MAXLEN=10000
12
13
  # REDIS_STREAM_TTL_SECONDS=3600
13
14
 
@@ -82,6 +82,18 @@ jobs:
82
82
  uv run python -c
83
83
  "from pathlib import Path; import subprocess; out = Path('.tmp/agentseek.Dockerfile'); out.parent.mkdir(exist_ok=True); subprocess.run(['uv', 'run', 'agentseek-api', 'dockerfile', '--config', 'examples/external_graph/manifest.json', str(out)], check=True); text = out.read_text(encoding='utf-8'); assert 'ENV PYTHONPATH=/deps/agent' in text; assert 'ENV AGENTSEEK_GRAPHS=/deps/agent/examples/external_graph/manifest.json' in text"
84
84
 
85
+ - name: CLI config, host environment, and process tests
86
+ run: >-
87
+ uv run pytest
88
+ tests/unit/test_cli.py
89
+ tests/unit/test_graph_manifest.py
90
+ tests/unit/test_dotenv_adapter.py
91
+ tests/unit/test_runtime_environment.py
92
+ tests/unit/test_runtime_entrypoint.py
93
+ tests/unit/test_process_supervisor.py
94
+ tests/integration/test_cli_runtime_processes.py
95
+ -q
96
+
85
97
  - name: Sync embedded SeekDB extra for serve smoke
86
98
  if: runner.os == 'Linux' || (runner.os == 'macOS' && runner.arch == 'ARM64')
87
99
  run: uv sync --dev --extra embedded
@@ -90,8 +102,9 @@ jobs:
90
102
  if: runner.os == 'Linux' || (runner.os == 'macOS' && runner.arch == 'ARM64')
91
103
  run: uv run python scripts/test_cli_serve_smoke.py
92
104
 
93
- - name: CLI config and Docker planning tests
94
- run: uv run pytest tests/unit/test_cli.py tests/unit/test_graph_manifest.py -q
105
+ - name: Minimum direct dependency compatibility
106
+ if: runner.os == 'Linux'
107
+ run: uv run python scripts/test_minimum_cli_dependencies.py
95
108
 
96
109
  embedded-seekdb-smoke:
97
110
  name: Embedded SeekDB Smoke
@@ -0,0 +1,88 @@
1
+ # Changelog
2
+
3
+ Notable changes to AgentSeek API are documented in this file.
4
+
5
+ ## Unreleased
6
+
7
+ ## 0.2.2 - 2026-08-16
8
+
9
+ ### Highlights
10
+
11
+ - Added bounded parallel Redis job execution within a worker process. Set
12
+ `WORKER_CONCURRENT_JOBS` to control the limit; the default is `10`.
13
+ - Aligned assistant and run `config.configurable` / `context` handling with the
14
+ LangGraph API contract, including assistant defaults and legacy configurable
15
+ access for graphs without a context schema.
16
+ - Defined one deterministic environment-ownership contract for the `dev`,
17
+ `serve`, `worker`, and `scheduler` host runtimes.
18
+
19
+ ### Fixed
20
+
21
+ - Made Redis job acknowledgement conditional on ownership of the active worker
22
+ lease, and stopped scheduling safely when a job fails or the lease is lost.
23
+ - Rejected client requests that provide both non-empty `config.configurable` and
24
+ `context`, mirrored either input into the other representation, and merged
25
+ assistant configuration into run configuration without discarding nested
26
+ defaults.
27
+ - Made inherited host environment keys, including explicit empty strings,
28
+ authoritative over config and CLI dotenv sources.
29
+ - Parsed each dotenv source independently with strict malformed-file handling,
30
+ and distinguished valueless `KEY` from explicit empty `KEY=`.
31
+ - Started `worker` and `scheduler` in fresh child processes so their settings
32
+ are built after the resolved environment is installed.
33
+ - Added bounded signal forwarding and descendant-process cleanup for `serve`,
34
+ `worker`, and `scheduler` across supported platforms.
35
+ - Kept version, help, and Dockerfile rendering independent of runtime settings
36
+ validation.
37
+ - Fell back to an ASCII CLI banner when a legacy Windows console cannot encode
38
+ the Unicode banner.
39
+
40
+ ### Upgrade notes
41
+
42
+ - Redis workers now execute up to `10` jobs concurrently by default. Set
43
+ `WORKER_CONCURRENT_JOBS=1` to retain the previous serial behavior.
44
+ - Clients must not send both non-empty `config.configurable` and `context` in
45
+ one assistant or run request; such requests now return HTTP 400. Prefer
46
+ `context` for new integrations.
47
+ - For `dev`, `serve`, `worker`, and `scheduler`, dotenv interpolation is
48
+ supported only against the inherited environment and earlier bindings in the
49
+ same physical file.
50
+ - For those host runtime commands, missing, malformed, and non-UTF-8 dotenv
51
+ sources fail closed with status 2 before a runtime child starts.
52
+ - Dependency resolution now requires SQLAlchemy 2.0.12 or newer, LangGraph
53
+ 1.0.6 or newer, LangChain Core 1.2.5 or newer, and MCP 1.27.1 through the 1.x
54
+ series. `python-dotenv` 1.0 through 1.2 is now a direct dependency.
55
+
56
+ ## 0.2.1 - 2026-07-14
57
+
58
+ ### Fixed
59
+
60
+ - Preserved empty JSON arrays in Redis thread-stream events by avoiding a Lua
61
+ cjson decode/encode round trip, while keeping generated envelope fields
62
+ authoritative.
63
+ - Mirrored completed tool, human, and system messages to `messages-tuple` when
64
+ requested so LangGraph SDK clients receive tool results before final-answer
65
+ streaming completes.
66
+
67
+ ### Upgrade notes
68
+
69
+ - No schema or configuration migration is required from 0.2.0.
70
+
71
+ ## 0.2.0 - 2026-07-12
72
+
73
+ ### Highlights
74
+
75
+ - Expanded the Crons API to align its request, response, filtering, sorting,
76
+ selection, and lifecycle behavior with the LangGraph Platform contract.
77
+ - Moved Redis-worker run and protocol event persistence from SQL to bounded
78
+ Redis Streams, removing metadata-database writes from the streaming hot path.
79
+ - Preserved UTF-8 output across SSE, wait, and A2A JSON responses while keeping
80
+ active thread event retention bounded without dropping live events.
81
+ - Upgraded checkpoint integration to `langchain-oceanbase` 0.6.0.
82
+
83
+ ### Upgrade notes
84
+
85
+ - Drain active Redis-worker runs before upgrading. Stream-event rows written to
86
+ SQL by earlier versions are not imported into Redis Streams.
87
+ - Redis stream replay is bounded by `REDIS_STREAM_MAXLEN` and
88
+ `REDIS_STREAM_TTL_SECONDS`; review these settings for long-running workloads.
@@ -1,3 +1,35 @@
1
+ Metadata-Version: 2.5
2
+ Name: agentseek-api
3
+ Version: 0.2.2
4
+ Summary: AgentSeek API core runtime with OceanBase checkpoints.
5
+ License-File: LICENSE
6
+ Requires-Python: >=3.12
7
+ Requires-Dist: aiomysql>=0.2.0
8
+ Requires-Dist: aiosqlite>=0.20.0
9
+ Requires-Dist: asyncpg>=0.29.0
10
+ Requires-Dist: cryptography>=45.0.0
11
+ Requires-Dist: fastapi>=0.110.1
12
+ Requires-Dist: greenlet>=3.1.0
13
+ Requires-Dist: langchain-anthropic>=1.0.0
14
+ Requires-Dist: langchain-core>=1.2.5
15
+ Requires-Dist: langchain-oceanbase==0.6.0
16
+ Requires-Dist: langchain-openai>=1.0.0
17
+ Requires-Dist: langchain>=0.3.9
18
+ Requires-Dist: langgraph-sdk>=0.3.5
19
+ Requires-Dist: langgraph>=1.0.6
20
+ Requires-Dist: mcp<2,>=1.27.1
21
+ Requires-Dist: pydantic-settings>=2.4.0
22
+ Requires-Dist: pydantic>=2.8.0
23
+ Requires-Dist: pymysql>=1.1.0
24
+ Requires-Dist: python-dotenv<1.3,>=1.0
25
+ Requires-Dist: redis>=5.0.0
26
+ Requires-Dist: scalar-fastapi>=1.0.3
27
+ Requires-Dist: sqlalchemy>=2.0.12
28
+ Requires-Dist: uvicorn>=0.30.0
29
+ Provides-Extra: embedded
30
+ Requires-Dist: langchain-oceanbase[pyseekdb]==0.6.0; extra == 'embedded'
31
+ Description-Content-Type: text/markdown
32
+
1
33
  # AgentSeek API
2
34
 
3
35
  **English** | [中文](README.zh-CN.md)
@@ -185,7 +217,7 @@ When the server starts it prints the banner and local URLs:
185
217
  ╠═╣│ ┬├┤ │││ │ ╚═╗├┤ ├┤ ├┴┐
186
218
  ╩ ╩└─┘└─┘┘└┘ ┴ ╚═╝└─┘└─┘┴ ┴
187
219
 
188
- AgentSeek v0.2.0
220
+ AgentSeek v0.2.2
189
221
 
190
222
  - 🚀 API: http://localhost:2024
191
223
  - 📚 Docs: http://localhost:2024/docs
@@ -260,7 +292,35 @@ When running from this repository, use `uv run agentseek-api ...`.
260
292
 
261
293
  - `-c, --config PATH`: explicit `agentseek.json`, `langgraph.json`, or manifest
262
294
  path
263
- - `--env-file PATH`: dotenv-style file loaded into the runtime environment
295
+ - `--env-file PATH`: host-runtime dotenv source
296
+
297
+ ### Host runtime environment
298
+
299
+ For `dev`, `serve`, `worker`, and `scheduler`, direct assignments are applied in
300
+ this order:
301
+
302
+ 1. the dotenv path named by config `env`;
303
+ 2. the literal config `env` mapping and `auth.path`;
304
+ 3. the CLI `--env-file`;
305
+ 4. the environment inherited by `agentseek-api`.
306
+
307
+ The inherited environment is authoritative by key presence. This includes an
308
+ explicit empty value. A lower source can fill an absent key, but cannot replace
309
+ an inherited `KEY=`.
310
+
311
+ Each dotenv file is evaluated independently. It can reference the inherited
312
+ environment and earlier bindings in the same physical file; it cannot reference
313
+ a config mapping or another dotenv file. Later assignment does not recompute an
314
+ earlier interpolated value.
315
+
316
+ In dotenv syntax, a bare `KEY` is valid but contributes no assignment, while
317
+ `KEY=` contributes an explicit empty string. Missing files, invalid UTF-8, and
318
+ malformed syntax stop the command before a runtime child starts.
319
+
320
+ The CLI applies command-owned values after this merge: the selected config path
321
+ becomes `AGENTSEEK_GRAPHS`, and `dev` forces `STUDIO_AUTH_LOCAL_DEV=true`.
322
+ Host and port options are passed as child argv and do not rewrite environment
323
+ keys with similar names.
264
324
 
265
325
  ### Common usage
266
326
 
@@ -622,6 +682,8 @@ parent api build --config ./langgraph.json -t my-api:dev
622
682
  - `REDIS_URL=redis://127.0.0.1:6379/0`
623
683
  - `REDIS_RUN_QUEUE_KEY=agentseek:runs:pending`
624
684
  - `REDIS_RUN_PROCESSING_KEY=agentseek:runs:processing`
685
+ - `WORKER_CONCURRENT_JOBS=10` bounds concurrently executing jobs in one
686
+ worker process
625
687
  - `REDIS_WORKER_LOCK_KEY=agentseek:worker:active`
626
688
  - `REDIS_WORKER_LOCK_TTL_SECONDS=30`
627
689
  - `REDIS_STREAM_MAXLEN=10000`
@@ -1,34 +1,3 @@
1
- Metadata-Version: 2.4
2
- Name: agentseek-api
3
- Version: 0.2.0
4
- Summary: AgentSeek API core runtime with OceanBase checkpoints.
5
- License-File: LICENSE
6
- Requires-Python: >=3.12
7
- Requires-Dist: aiomysql>=0.2.0
8
- Requires-Dist: aiosqlite>=0.20.0
9
- Requires-Dist: asyncpg>=0.29.0
10
- Requires-Dist: cryptography>=45.0.0
11
- Requires-Dist: fastapi>=0.110.1
12
- Requires-Dist: greenlet>=3.1.0
13
- Requires-Dist: langchain-anthropic>=1.0.0
14
- Requires-Dist: langchain-core>=1.0.0
15
- Requires-Dist: langchain-oceanbase==0.6.0
16
- Requires-Dist: langchain-openai>=1.0.0
17
- Requires-Dist: langchain>=0.3.9
18
- Requires-Dist: langgraph-sdk>=0.3.5
19
- Requires-Dist: langgraph>=1.0.3
20
- Requires-Dist: mcp>=1.27.1
21
- Requires-Dist: pydantic-settings>=2.4.0
22
- Requires-Dist: pydantic>=2.8.0
23
- Requires-Dist: pymysql>=1.1.0
24
- Requires-Dist: redis>=5.0.0
25
- Requires-Dist: scalar-fastapi>=1.0.3
26
- Requires-Dist: sqlalchemy>=2.0.0
27
- Requires-Dist: uvicorn>=0.30.0
28
- Provides-Extra: embedded
29
- Requires-Dist: langchain-oceanbase[pyseekdb]==0.6.0; extra == 'embedded'
30
- Description-Content-Type: text/markdown
31
-
32
1
  # AgentSeek API
33
2
 
34
3
  **English** | [中文](README.zh-CN.md)
@@ -216,7 +185,7 @@ When the server starts it prints the banner and local URLs:
216
185
  ╠═╣│ ┬├┤ │││ │ ╚═╗├┤ ├┤ ├┴┐
217
186
  ╩ ╩└─┘└─┘┘└┘ ┴ ╚═╝└─┘└─┘┴ ┴
218
187
 
219
- AgentSeek v0.2.0
188
+ AgentSeek v0.2.2
220
189
 
221
190
  - 🚀 API: http://localhost:2024
222
191
  - 📚 Docs: http://localhost:2024/docs
@@ -291,7 +260,35 @@ When running from this repository, use `uv run agentseek-api ...`.
291
260
 
292
261
  - `-c, --config PATH`: explicit `agentseek.json`, `langgraph.json`, or manifest
293
262
  path
294
- - `--env-file PATH`: dotenv-style file loaded into the runtime environment
263
+ - `--env-file PATH`: host-runtime dotenv source
264
+
265
+ ### Host runtime environment
266
+
267
+ For `dev`, `serve`, `worker`, and `scheduler`, direct assignments are applied in
268
+ this order:
269
+
270
+ 1. the dotenv path named by config `env`;
271
+ 2. the literal config `env` mapping and `auth.path`;
272
+ 3. the CLI `--env-file`;
273
+ 4. the environment inherited by `agentseek-api`.
274
+
275
+ The inherited environment is authoritative by key presence. This includes an
276
+ explicit empty value. A lower source can fill an absent key, but cannot replace
277
+ an inherited `KEY=`.
278
+
279
+ Each dotenv file is evaluated independently. It can reference the inherited
280
+ environment and earlier bindings in the same physical file; it cannot reference
281
+ a config mapping or another dotenv file. Later assignment does not recompute an
282
+ earlier interpolated value.
283
+
284
+ In dotenv syntax, a bare `KEY` is valid but contributes no assignment, while
285
+ `KEY=` contributes an explicit empty string. Missing files, invalid UTF-8, and
286
+ malformed syntax stop the command before a runtime child starts.
287
+
288
+ The CLI applies command-owned values after this merge: the selected config path
289
+ becomes `AGENTSEEK_GRAPHS`, and `dev` forces `STUDIO_AUTH_LOCAL_DEV=true`.
290
+ Host and port options are passed as child argv and do not rewrite environment
291
+ keys with similar names.
295
292
 
296
293
  ### Common usage
297
294
 
@@ -653,6 +650,8 @@ parent api build --config ./langgraph.json -t my-api:dev
653
650
  - `REDIS_URL=redis://127.0.0.1:6379/0`
654
651
  - `REDIS_RUN_QUEUE_KEY=agentseek:runs:pending`
655
652
  - `REDIS_RUN_PROCESSING_KEY=agentseek:runs:processing`
653
+ - `WORKER_CONCURRENT_JOBS=10` bounds concurrently executing jobs in one
654
+ worker process
656
655
  - `REDIS_WORKER_LOCK_KEY=agentseek:worker:active`
657
656
  - `REDIS_WORKER_LOCK_TTL_SECONDS=30`
658
657
  - `REDIS_STREAM_MAXLEN=10000`
@@ -181,7 +181,7 @@ uv run agentseek-api dev --config ./langgraph.json
181
181
  ╠═╣│ ┬├┤ │││ │ ╚═╗├┤ ├┤ ├┴┐
182
182
  ╩ ╩└─┘└─┘┘└┘ ┴ ╚═╝└─┘└─┘┴ ┴
183
183
 
184
- AgentSeek v0.2.0
184
+ AgentSeek v0.2.2
185
185
 
186
186
  - 🚀 API: http://localhost:2024
187
187
  - 📚 Docs: http://localhost:2024/docs
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "agentseek-api"
3
- version = "0.2.0"
3
+ version = "0.2.2"
4
4
  description = "AgentSeek API core runtime with OceanBase checkpoints."
5
5
  readme = "README.md"
6
6
  requires-python = ">=3.12"
@@ -9,22 +9,23 @@ dependencies = [
9
9
  "uvicorn>=0.30.0",
10
10
  "pydantic>=2.8.0",
11
11
  "pydantic-settings>=2.4.0",
12
- "sqlalchemy>=2.0.0",
12
+ "sqlalchemy>=2.0.12",
13
13
  "greenlet>=3.1.0",
14
14
  "asyncpg>=0.29.0",
15
15
  "aiomysql>=0.2.0",
16
16
  "aiosqlite>=0.20.0",
17
17
  "redis>=5.0.0",
18
- "langgraph>=1.0.3",
18
+ "langgraph>=1.0.6",
19
19
  "langgraph-sdk>=0.3.5",
20
- "langchain-core>=1.0.0",
20
+ "langchain-core>=1.2.5",
21
21
  "langchain-openai>=1.0.0",
22
22
  "langchain-anthropic>=1.0.0",
23
23
  "langchain-oceanbase==0.6.0",
24
24
  "cryptography>=45.0.0",
25
25
  "pymysql>=1.1.0",
26
26
  "langchain>=0.3.9",
27
- "mcp>=1.27.1",
27
+ "mcp>=1.27.1,<2",
28
+ "python-dotenv>=1.0,<1.3",
28
29
  "scalar-fastapi>=1.0.3",
29
30
  ]
30
31
 
@@ -39,7 +40,7 @@ agentseek-api = "agentseek_api.cli:main"
39
40
  [dependency-groups]
40
41
  dev = [
41
42
  "pytest>=8.0.0",
42
- "pytest-asyncio>=0.23.0",
43
+ "pytest-asyncio>=0.23.5",
43
44
  "pytest-cov>=5.0.0",
44
45
  "httpx>=0.27.0",
45
46
  "ruff>=0.6.0",
@@ -9,6 +9,7 @@ CONFIG_PATH="${CONFIG_PATH:-examples/docker_ci_auth/manifest.json}"
9
9
  NETWORK_NAME="${NETWORK_NAME:-agentseek-redis-runtime}"
10
10
  BACKEND_CONTAINER="${BACKEND_CONTAINER:-agentseek-redis-backend}"
11
11
  REDIS_CONTAINER="${REDIS_CONTAINER:-agentseek-redis}"
12
+ REDIS_HOST_PORT="${REDIS_HOST_PORT:-6391}"
12
13
  API_CONTAINER="${API_CONTAINER:-agentseek-redis-api}"
13
14
  WORKER_CONTAINER="${WORKER_CONTAINER:-agentseek-redis-worker}"
14
15
  API_PORT="${API_PORT:-8126}"
@@ -17,13 +18,23 @@ SEEKDB_DOCKER_IMAGE="${SEEKDB_DOCKER_IMAGE:-}"
17
18
  OCEANBASE_DOCKER_MODE="${OCEANBASE_DOCKER_MODE:-mini}"
18
19
  STATE_DIR="${STATE_DIR:-$ROOT_DIR/.tmp/redis-runtime}"
19
20
  RESUME_STATE_FILE="$STATE_DIR/resume-state.json"
21
+ SHUTDOWN_STATE_FILE=""
22
+ REDIS_WORKER_LOCK_KEY="${REDIS_WORKER_LOCK_KEY:-agentseek:worker:active}"
23
+ WORKER_CONCURRENT_JOBS="${WORKER_CONCURRENT_JOBS:-10}"
20
24
 
21
25
  cleanup() {
22
- stop_worker
26
+ local status=$?
27
+
28
+ trap - EXIT
29
+ stop_worker >/dev/null 2>&1 || true
23
30
  docker rm -f "$API_CONTAINER" >/dev/null 2>&1 || true
24
31
  docker rm -f "$REDIS_CONTAINER" >/dev/null 2>&1 || true
25
32
  docker rm -f "$BACKEND_CONTAINER" >/dev/null 2>&1 || true
26
33
  docker network rm "$NETWORK_NAME" >/dev/null 2>&1 || true
34
+ if [[ -n "$SHUTDOWN_STATE_FILE" ]]; then
35
+ rm -f "$SHUTDOWN_STATE_FILE" || true
36
+ fi
37
+ exit "$status"
27
38
  }
28
39
 
29
40
  print_logs() {
@@ -113,6 +124,21 @@ PY
113
124
  fi
114
125
  }
115
126
 
127
+ wait_for_redis() {
128
+ local attempt
129
+
130
+ for ((attempt = 1; attempt <= 30; attempt++)); do
131
+ if docker exec "$REDIS_CONTAINER" redis-cli ping >/dev/null 2>&1; then
132
+ return 0
133
+ fi
134
+ sleep 1
135
+ done
136
+
137
+ echo "Redis did not become ready" >&2
138
+ print_logs
139
+ return 1
140
+ }
141
+
116
142
  ensure_database_exists() {
117
143
  uv run python - <<'PY'
118
144
  import os
@@ -181,19 +207,70 @@ PY
181
207
  }
182
208
 
183
209
  stop_worker() {
184
- if docker ps --format '{{.Names}}' | grep -Fxq "$WORKER_CONTAINER"; then
185
- docker stop -t 10 "$WORKER_CONTAINER" >/dev/null 2>&1 || true
210
+ local timeout="${1:-10}"
211
+ local container_id
212
+ local running
213
+ local status
214
+
215
+ if container_id="$(docker ps -aq --filter "name=^/${WORKER_CONTAINER}$")"; then
216
+ :
217
+ else
218
+ status=$?
219
+ print_logs >&2
220
+ return "$status"
221
+ fi
222
+ if [[ -z "$container_id" ]]; then
223
+ return 0
224
+ fi
225
+
226
+ if running="$(docker inspect --format '{{.State.Running}}' "$container_id")"; then
227
+ :
228
+ else
229
+ status=$?
230
+ print_logs >&2
231
+ return "$status"
232
+ fi
233
+ if [[ "$running" == "true" ]]; then
234
+ if docker stop -t "$timeout" "$WORKER_CONTAINER" >/dev/null; then
235
+ :
236
+ else
237
+ status=$?
238
+ print_logs >&2
239
+ return "$status"
240
+ fi
241
+ fi
242
+ if docker rm -f "$WORKER_CONTAINER" >/dev/null; then
243
+ :
244
+ else
245
+ status=$?
246
+ print_logs >&2
247
+ return "$status"
248
+ fi
249
+ if docker exec "$REDIS_CONTAINER" redis-cli DEL "$REDIS_WORKER_LOCK_KEY" >/dev/null; then
250
+ return 0
251
+ else
252
+ status=$?
253
+ print_logs >&2
254
+ return "$status"
186
255
  fi
187
- docker rm -f "$WORKER_CONTAINER" >/dev/null 2>&1 || true
188
256
  }
189
257
 
190
258
  start_worker() {
191
- stop_worker
192
- docker run -d \
259
+ local status
260
+
261
+ if stop_worker; then
262
+ :
263
+ else
264
+ status=$?
265
+ return "$status"
266
+ fi
267
+ if docker run -d \
193
268
  --name "$WORKER_CONTAINER" \
194
269
  --network "$NETWORK_NAME" \
195
270
  -e EXECUTOR_BACKEND=redis \
196
271
  -e REDIS_URL="redis://${REDIS_CONTAINER}:6379/0" \
272
+ -e REDIS_WORKER_LOCK_KEY="${REDIS_WORKER_LOCK_KEY}" \
273
+ -e WORKER_CONCURRENT_JOBS="${WORKER_CONCURRENT_JOBS}" \
197
274
  -e SEEKDB_URL="${SEEKDB_URL}" \
198
275
  -e OCEANBASE_HOST="${BACKEND_CONTAINER}" \
199
276
  -e OCEANBASE_PORT="${OCEANBASE_PORT}" \
@@ -201,7 +278,28 @@ start_worker() {
201
278
  -e OCEANBASE_PASSWORD="${OCEANBASE_PASSWORD}" \
202
279
  -e OCEANBASE_DB_NAME="${OCEANBASE_DB_NAME}" \
203
280
  "$IMAGE_TAG" \
204
- python -m agentseek_api.cli worker >/dev/null
281
+ python -m agentseek_api.cli worker >/dev/null; then
282
+ return 0
283
+ else
284
+ status=$?
285
+ print_logs >&2
286
+ return "$status"
287
+ fi
288
+ }
289
+
290
+ run_probe() {
291
+ local status
292
+
293
+ if uv run python scripts/verify_worker_concurrency.py \
294
+ --base-url "$BASE_URL" \
295
+ --redis-url "redis://127.0.0.1:${REDIS_HOST_PORT}/0" \
296
+ "$@"; then
297
+ return 0
298
+ else
299
+ status=$?
300
+ print_logs >&2
301
+ return "$status"
302
+ fi
205
303
  }
206
304
 
207
305
  start_backend() {
@@ -243,6 +341,7 @@ set_backend_defaults "$SEEKDB_DOCKER_BACKEND"
243
341
  docker network rm "$NETWORK_NAME" >/dev/null 2>&1 || true
244
342
  docker network create "$NETWORK_NAME" >/dev/null
245
343
  mkdir -p "$STATE_DIR"
344
+ SHUTDOWN_STATE_FILE="$(mktemp "$STATE_DIR/shutdown-state.XXXXXX")"
246
345
 
247
346
  uv run agentseek-api build --config "$CONFIG_PATH" -t "$IMAGE_TAG"
248
347
 
@@ -252,8 +351,20 @@ docker rm -f "$REDIS_CONTAINER" >/dev/null 2>&1 || true
252
351
  docker run -d \
253
352
  --name "$REDIS_CONTAINER" \
254
353
  --network "$NETWORK_NAME" \
354
+ -p "127.0.0.1:${REDIS_HOST_PORT}:6379" \
255
355
  redis:7-alpine >/dev/null
256
356
 
357
+ wait_for_redis
358
+
359
+ if ! AGENTSEEK_TEST_REDIS_URL="redis://127.0.0.1:${REDIS_HOST_PORT}/0" \
360
+ uv run pytest \
361
+ tests/integration/test_live_redis_stream_persistence.py \
362
+ tests/integration/test_live_redis_queue.py \
363
+ -q; then
364
+ print_logs
365
+ exit 1
366
+ fi
367
+
257
368
  wait_for_backend
258
369
  ensure_database_exists
259
370
 
@@ -294,3 +405,21 @@ if ! uv run python scripts/verify_docker_api.py --base-url "$BASE_URL" --mode re
294
405
  print_logs
295
406
  exit 1
296
407
  fi
408
+
409
+ WORKER_CONCURRENCY_SUITE_STARTED_SECONDS=$SECONDS
410
+ echo "worker concurrency probe suite started" >&2
411
+
412
+ WORKER_CONCURRENT_JOBS=10
413
+ start_worker
414
+ run_probe --mode fanout
415
+
416
+ WORKER_CONCURRENT_JOBS=2
417
+ start_worker
418
+ run_probe --mode bounded
419
+ run_probe --mode failure
420
+ run_probe --mode shutdown-seed >"$SHUTDOWN_STATE_FILE"
421
+ stop_worker 1
422
+ start_worker
423
+ run_probe --mode shutdown-check --state-file "$SHUTDOWN_STATE_FILE"
424
+
425
+ echo "worker concurrency probe suite completed in $((SECONDS - WORKER_CONCURRENCY_SUITE_STARTED_SECONDS))s" >&2
@@ -0,0 +1,109 @@
1
+ """Verify host environment resolution with all direct dependency floors."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import os
6
+ import subprocess
7
+ import sys
8
+ import tempfile
9
+ import tomllib
10
+ from pathlib import Path
11
+
12
+
13
+ def main() -> None:
14
+ repository = Path(__file__).resolve().parents[1]
15
+ project = tomllib.loads((repository / "pyproject.toml").read_text(encoding="utf-8"))
16
+ requirements = list(project["project"]["dependencies"])
17
+ requirements.append("pytest>=8.0.0")
18
+ requirements.append("pytest-asyncio>=0.23.5")
19
+
20
+ with tempfile.TemporaryDirectory(prefix="agentseek-minimum-") as directory:
21
+ environment = Path(directory) / ".venv"
22
+ subprocess.run(
23
+ [
24
+ "uv",
25
+ "venv",
26
+ "--python",
27
+ "3.12",
28
+ str(environment),
29
+ ],
30
+ check=True,
31
+ )
32
+ python = environment / (
33
+ "Scripts/python.exe" if sys.platform == "win32" else "bin/python"
34
+ )
35
+ subprocess.run(
36
+ [
37
+ "uv",
38
+ "pip",
39
+ "install",
40
+ "--python",
41
+ str(python),
42
+ "--resolution",
43
+ "lowest-direct",
44
+ *requirements,
45
+ ],
46
+ check=True,
47
+ )
48
+ subprocess.run(
49
+ [
50
+ "uv",
51
+ "pip",
52
+ "install",
53
+ "--python",
54
+ str(python),
55
+ "--no-deps",
56
+ "-e",
57
+ str(repository),
58
+ ],
59
+ check=True,
60
+ )
61
+
62
+ version = subprocess.run(
63
+ [
64
+ str(python),
65
+ "-c",
66
+ (
67
+ "import importlib.metadata; "
68
+ "print(importlib.metadata.version('python-dotenv'))"
69
+ ),
70
+ ],
71
+ check=True,
72
+ capture_output=True,
73
+ text=True,
74
+ )
75
+ assert version.stdout.strip() == "1.0.0"
76
+
77
+ cli_env = dict(os.environ)
78
+ cli_env.pop("PYTHONPATH", None)
79
+ cli_env["PORT"] = "not-an-integer"
80
+ version_result = subprocess.run(
81
+ [str(python), "-m", "agentseek_api.cli", "version"],
82
+ cwd=repository,
83
+ env=cli_env,
84
+ check=True,
85
+ capture_output=True,
86
+ text=True,
87
+ )
88
+ expected_version = project["project"]["version"]
89
+ assert version_result.stdout.strip() == f"agentseek-api {expected_version}"
90
+
91
+ test_env = dict(os.environ)
92
+ test_env.pop("PYTHONPATH", None)
93
+ subprocess.run(
94
+ [
95
+ str(python),
96
+ "-m",
97
+ "pytest",
98
+ "tests/unit/test_dotenv_adapter.py",
99
+ "tests/unit/test_runtime_environment.py",
100
+ "-q",
101
+ ],
102
+ cwd=repository,
103
+ env=test_env,
104
+ check=True,
105
+ )
106
+
107
+
108
+ if __name__ == "__main__":
109
+ main()