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.
- {agentseek_api-0.2.0 → agentseek_api-0.2.2}/.env.example +1 -0
- {agentseek_api-0.2.0 → agentseek_api-0.2.2}/.github/workflows/ci.yml +15 -2
- agentseek_api-0.2.2/CHANGELOG.md +88 -0
- agentseek_api-0.2.0/README.md → agentseek_api-0.2.2/PKG-INFO +64 -2
- agentseek_api-0.2.0/PKG-INFO → agentseek_api-0.2.2/README.md +32 -33
- {agentseek_api-0.2.0 → agentseek_api-0.2.2}/README.zh-CN.md +1 -1
- {agentseek_api-0.2.0 → agentseek_api-0.2.2}/pyproject.toml +7 -6
- {agentseek_api-0.2.0 → agentseek_api-0.2.2}/scripts/test-redis-runtime.sh +136 -7
- agentseek_api-0.2.2/scripts/test_minimum_cli_dependencies.py +109 -0
- agentseek_api-0.2.2/scripts/verify_worker_concurrency.py +528 -0
- agentseek_api-0.2.2/src/agentseek_api/__init__.py +1 -0
- {agentseek_api-0.2.0 → agentseek_api-0.2.2}/src/agentseek_api/api/assistants.py +48 -6
- {agentseek_api-0.2.0 → agentseek_api-0.2.2}/src/agentseek_api/api/runs.py +12 -0
- {agentseek_api-0.2.0 → agentseek_api-0.2.2}/src/agentseek_api/cli.py +148 -59
- agentseek_api-0.2.2/src/agentseek_api/constants.py +3 -0
- {agentseek_api-0.2.0 → agentseek_api-0.2.2}/src/agentseek_api/core/database.py +12 -1
- agentseek_api-0.2.2/src/agentseek_api/dotenv_adapter.py +69 -0
- agentseek_api-0.2.2/src/agentseek_api/process_supervisor.py +1531 -0
- agentseek_api-0.2.2/src/agentseek_api/runtime_entrypoint.py +59 -0
- {agentseek_api-0.2.0 → agentseek_api-0.2.2}/src/agentseek_api/services/redis_queue.py +18 -0
- {agentseek_api-0.2.0 → agentseek_api-0.2.2}/src/agentseek_api/services/run_executor.py +30 -1
- {agentseek_api-0.2.0 → agentseek_api-0.2.2}/src/agentseek_api/services/run_preparation.py +27 -0
- {agentseek_api-0.2.0 → agentseek_api-0.2.2}/src/agentseek_api/services/stream_persistence.py +20 -5
- {agentseek_api-0.2.0 → agentseek_api-0.2.2}/src/agentseek_api/settings.py +2 -1
- agentseek_api-0.2.2/src/agentseek_api/worker.py +347 -0
- {agentseek_api-0.2.0 → agentseek_api-0.2.2}/tests/e2e/test_langsmith_compat_live.py +3 -3
- agentseek_api-0.2.2/tests/fixtures/runtime_settings_probe/sitecustomize.py +69 -0
- agentseek_api-0.2.2/tests/fixtures/termination_tree.py +67 -0
- {agentseek_api-0.2.0 → agentseek_api-0.2.2}/tests/integration/test_assistants_compat.py +2 -2
- agentseek_api-0.2.2/tests/integration/test_assistants_config_context_sync.py +145 -0
- agentseek_api-0.2.2/tests/integration/test_cli_runtime_processes.py +812 -0
- {agentseek_api-0.2.0 → agentseek_api-0.2.2}/tests/integration/test_langsmith_compat_coverage.py +2 -2
- agentseek_api-0.2.2/tests/integration/test_live_redis_queue.py +69 -0
- agentseek_api-0.2.2/tests/integration/test_live_redis_stream_persistence.py +75 -0
- {agentseek_api-0.2.0 → agentseek_api-0.2.2}/tests/integration/test_metadata_db_config.py +23 -8
- agentseek_api-0.2.2/tests/integration/test_runs_streaming.py +301 -0
- {agentseek_api-0.2.0 → agentseek_api-0.2.2}/tests/integration/test_stream_persistence.py +85 -1
- {agentseek_api-0.2.0 → agentseek_api-0.2.2}/tests/unit/test_assistant_routes_unit.py +4 -4
- {agentseek_api-0.2.0 → agentseek_api-0.2.2}/tests/unit/test_cli.py +689 -80
- agentseek_api-0.2.2/tests/unit/test_dotenv_adapter.py +89 -0
- agentseek_api-0.2.2/tests/unit/test_process_supervisor.py +2860 -0
- {agentseek_api-0.2.0 → agentseek_api-0.2.2}/tests/unit/test_redis_queue.py +26 -0
- agentseek_api-0.2.2/tests/unit/test_redis_runtime_script.py +68 -0
- agentseek_api-0.2.2/tests/unit/test_run_controls_validation.py +27 -0
- {agentseek_api-0.2.0 → agentseek_api-0.2.2}/tests/unit/test_run_executor.py +267 -1
- {agentseek_api-0.2.0 → agentseek_api-0.2.2}/tests/unit/test_run_preparation.py +139 -0
- agentseek_api-0.2.2/tests/unit/test_runtime_entrypoint.py +171 -0
- agentseek_api-0.2.2/tests/unit/test_runtime_environment.py +603 -0
- agentseek_api-0.2.2/tests/unit/test_worker.py +650 -0
- agentseek_api-0.2.2/tests/unit/test_worker_concurrency_probe.py +581 -0
- {agentseek_api-0.2.0 → agentseek_api-0.2.2}/uv.lock +8 -6
- agentseek_api-0.2.0/CHANGELOG.md +0 -22
- agentseek_api-0.2.0/src/agentseek_api/__init__.py +0 -1
- agentseek_api-0.2.0/src/agentseek_api/worker.py +0 -103
- agentseek_api-0.2.0/tests/integration/test_runs_streaming.py +0 -142
- agentseek_api-0.2.0/tests/unit/test_worker.py +0 -155
- {agentseek_api-0.2.0 → agentseek_api-0.2.2}/.dockerignore +0 -0
- {agentseek_api-0.2.0 → agentseek_api-0.2.2}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
- {agentseek_api-0.2.0 → agentseek_api-0.2.2}/.github/workflows/live-provider-streaming.yml +0 -0
- {agentseek_api-0.2.0 → agentseek_api-0.2.2}/.github/workflows/release.yml +0 -0
- {agentseek_api-0.2.0 → agentseek_api-0.2.2}/.gitignore +0 -0
- {agentseek_api-0.2.0 → agentseek_api-0.2.2}/AGENTS.md +0 -0
- {agentseek_api-0.2.0 → agentseek_api-0.2.2}/CONTRIBUTING.md +0 -0
- {agentseek_api-0.2.0 → agentseek_api-0.2.2}/LICENSE +0 -0
- {agentseek_api-0.2.0 → agentseek_api-0.2.2}/Makefile +0 -0
- {agentseek_api-0.2.0 → agentseek_api-0.2.2}/examples/README.md +0 -0
- {agentseek_api-0.2.0 → agentseek_api-0.2.2}/examples/__init__.py +0 -0
- {agentseek_api-0.2.0 → agentseek_api-0.2.2}/examples/assistant_config/agentseek.json +0 -0
- {agentseek_api-0.2.0 → agentseek_api-0.2.2}/examples/assistant_config/graph.py +0 -0
- {agentseek_api-0.2.0 → agentseek_api-0.2.2}/examples/auth/api_key_auth.py +0 -0
- {agentseek_api-0.2.0 → agentseek_api-0.2.2}/examples/auth/bearer_token_auth.py +0 -0
- {agentseek_api-0.2.0 → agentseek_api-0.2.2}/examples/auth/custom_backend.py +0 -0
- {agentseek_api-0.2.0 → agentseek_api-0.2.2}/examples/auth/jwt.md +0 -0
- {agentseek_api-0.2.0 → agentseek_api-0.2.2}/examples/auth/jwt_auth.py +0 -0
- {agentseek_api-0.2.0 → agentseek_api-0.2.2}/examples/custom_routes/app.py +0 -0
- {agentseek_api-0.2.0 → agentseek_api-0.2.2}/examples/docker_ci_auth/auth_backend.py +0 -0
- {agentseek_api-0.2.0 → agentseek_api-0.2.2}/examples/docker_ci_auth/manifest.json +0 -0
- {agentseek_api-0.2.0 → agentseek_api-0.2.2}/examples/external_graph/__init__.py +0 -0
- {agentseek_api-0.2.0 → agentseek_api-0.2.2}/examples/external_graph/graph.py +0 -0
- {agentseek_api-0.2.0 → agentseek_api-0.2.2}/examples/external_graph/manifest.json +0 -0
- {agentseek_api-0.2.0 → agentseek_api-0.2.2}/examples/external_graph/run.py +0 -0
- {agentseek_api-0.2.0 → agentseek_api-0.2.2}/examples/graphs/__init__.py +0 -0
- {agentseek_api-0.2.0 → agentseek_api-0.2.2}/examples/graphs/react_agent/__init__.py +0 -0
- {agentseek_api-0.2.0 → agentseek_api-0.2.2}/examples/graphs/react_agent/graph.py +0 -0
- {agentseek_api-0.2.0 → agentseek_api-0.2.2}/examples/graphs/store_memory/graph.py +0 -0
- {agentseek_api-0.2.0 → agentseek_api-0.2.2}/examples/graphs/stress_test/__init__.py +0 -0
- {agentseek_api-0.2.0 → agentseek_api-0.2.2}/examples/graphs/stress_test/graph.py +0 -0
- {agentseek_api-0.2.0 → agentseek_api-0.2.2}/examples/graphs/stress_tool_agent/__init__.py +0 -0
- {agentseek_api-0.2.0 → agentseek_api-0.2.2}/examples/graphs/stress_tool_agent/graph.py +0 -0
- {agentseek_api-0.2.0 → agentseek_api-0.2.2}/examples/graphs/subgraph_agent/__init__.py +0 -0
- {agentseek_api-0.2.0 → agentseek_api-0.2.2}/examples/graphs/subgraph_agent/graph.py +0 -0
- {agentseek_api-0.2.0 → agentseek_api-0.2.2}/examples/graphs/subgraph_hitl_agent/__init__.py +0 -0
- {agentseek_api-0.2.0 → agentseek_api-0.2.2}/examples/graphs/subgraph_hitl_agent/graph.py +0 -0
- {agentseek_api-0.2.0 → agentseek_api-0.2.2}/examples/live_provider_graphs/__init__.py +0 -0
- {agentseek_api-0.2.0 → agentseek_api-0.2.2}/examples/live_provider_graphs/graph.py +0 -0
- {agentseek_api-0.2.0 → agentseek_api-0.2.2}/examples/live_provider_graphs/manifest.json +0 -0
- {agentseek_api-0.2.0 → agentseek_api-0.2.2}/examples/minimal_agentseek/agentseek.json +0 -0
- {agentseek_api-0.2.0 → agentseek_api-0.2.2}/examples/minimal_agentseek/graph.py +0 -0
- {agentseek_api-0.2.0 → agentseek_api-0.2.2}/examples/run_sample_graphs.py +0 -0
- {agentseek_api-0.2.0 → agentseek_api-0.2.2}/examples/sample_graphs_manifest.json +0 -0
- {agentseek_api-0.2.0 → agentseek_api-0.2.2}/scripts/build_live_provider_matrix.py +0 -0
- {agentseek_api-0.2.0 → agentseek_api-0.2.2}/scripts/seekdb_checkpoint_smoke.py +0 -0
- {agentseek_api-0.2.0 → agentseek_api-0.2.2}/scripts/seekdb_embed_launcher.py +0 -0
- {agentseek_api-0.2.0 → agentseek_api-0.2.2}/scripts/test-checkpoints.sh +0 -0
- {agentseek_api-0.2.0 → agentseek_api-0.2.2}/scripts/test-cli-dev-samples.sh +0 -0
- {agentseek_api-0.2.0 → agentseek_api-0.2.2}/scripts/test-cli-docker.sh +0 -0
- {agentseek_api-0.2.0 → agentseek_api-0.2.2}/scripts/test-live-provider.sh +0 -0
- {agentseek_api-0.2.0 → agentseek_api-0.2.2}/scripts/test-seekdb.sh +0 -0
- {agentseek_api-0.2.0 → agentseek_api-0.2.2}/scripts/test_cli_config_autodiscovery.py +0 -0
- {agentseek_api-0.2.0 → agentseek_api-0.2.2}/scripts/test_cli_dev_studio_smoke.py +0 -0
- {agentseek_api-0.2.0 → agentseek_api-0.2.2}/scripts/test_cli_embed_serve_smoke.py +0 -0
- {agentseek_api-0.2.0 → agentseek_api-0.2.2}/scripts/test_cli_serve_smoke.py +0 -0
- {agentseek_api-0.2.0 → agentseek_api-0.2.2}/scripts/verify_docker_api.py +0 -0
- {agentseek_api-0.2.0 → agentseek_api-0.2.2}/src/agentseek_api/a2a_server.py +0 -0
- {agentseek_api-0.2.0 → agentseek_api-0.2.2}/src/agentseek_api/api/__init__.py +0 -0
- {agentseek_api-0.2.0 → agentseek_api-0.2.2}/src/agentseek_api/api/crons.py +0 -0
- {agentseek_api-0.2.0 → agentseek_api-0.2.2}/src/agentseek_api/api/stateless_runs.py +0 -0
- {agentseek_api-0.2.0 → agentseek_api-0.2.2}/src/agentseek_api/api/store.py +0 -0
- {agentseek_api-0.2.0 → agentseek_api-0.2.2}/src/agentseek_api/api/streaming.py +0 -0
- {agentseek_api-0.2.0 → agentseek_api-0.2.2}/src/agentseek_api/api/threads.py +0 -0
- {agentseek_api-0.2.0 → agentseek_api-0.2.2}/src/agentseek_api/core/__init__.py +0 -0
- {agentseek_api-0.2.0 → agentseek_api-0.2.2}/src/agentseek_api/core/a2a_config.py +0 -0
- {agentseek_api-0.2.0 → agentseek_api-0.2.2}/src/agentseek_api/core/app_loader.py +0 -0
- {agentseek_api-0.2.0 → agentseek_api-0.2.2}/src/agentseek_api/core/auth_deps.py +0 -0
- {agentseek_api-0.2.0 → agentseek_api-0.2.2}/src/agentseek_api/core/auth_middleware.py +0 -0
- {agentseek_api-0.2.0 → agentseek_api-0.2.2}/src/agentseek_api/core/config_file.py +0 -0
- {agentseek_api-0.2.0 → agentseek_api-0.2.2}/src/agentseek_api/core/content_type_fix.py +0 -0
- {agentseek_api-0.2.0 → agentseek_api-0.2.2}/src/agentseek_api/core/cors_config.py +0 -0
- {agentseek_api-0.2.0 → agentseek_api-0.2.2}/src/agentseek_api/core/http_config.py +0 -0
- {agentseek_api-0.2.0 → agentseek_api-0.2.2}/src/agentseek_api/core/mcp_config.py +0 -0
- {agentseek_api-0.2.0 → agentseek_api-0.2.2}/src/agentseek_api/core/oceanbase_checkpointer.py +0 -0
- {agentseek_api-0.2.0 → agentseek_api-0.2.2}/src/agentseek_api/core/orm.py +0 -0
- {agentseek_api-0.2.0 → agentseek_api-0.2.2}/src/agentseek_api/core/runtime_store.py +0 -0
- {agentseek_api-0.2.0 → agentseek_api-0.2.2}/src/agentseek_api/core/store_config.py +0 -0
- {agentseek_api-0.2.0 → agentseek_api-0.2.2}/src/agentseek_api/main.py +0 -0
- {agentseek_api-0.2.0 → agentseek_api-0.2.2}/src/agentseek_api/mcp_server.py +0 -0
- {agentseek_api-0.2.0 → agentseek_api-0.2.2}/src/agentseek_api/models/__init__.py +0 -0
- {agentseek_api-0.2.0 → agentseek_api-0.2.2}/src/agentseek_api/models/api.py +0 -0
- {agentseek_api-0.2.0 → agentseek_api-0.2.2}/src/agentseek_api/models/auth.py +0 -0
- {agentseek_api-0.2.0 → agentseek_api-0.2.2}/src/agentseek_api/models/protocol.py +0 -0
- {agentseek_api-0.2.0 → agentseek_api-0.2.2}/src/agentseek_api/scheduler.py +0 -0
- {agentseek_api-0.2.0 → agentseek_api-0.2.2}/src/agentseek_api/services/__init__.py +0 -0
- {agentseek_api-0.2.0 → agentseek_api-0.2.2}/src/agentseek_api/services/cron_models.py +0 -0
- {agentseek_api-0.2.0 → agentseek_api-0.2.2}/src/agentseek_api/services/cron_rrule.py +0 -0
- {agentseek_api-0.2.0 → agentseek_api-0.2.2}/src/agentseek_api/services/cron_scheduler.py +0 -0
- {agentseek_api-0.2.0 → agentseek_api-0.2.2}/src/agentseek_api/services/cron_service.py +0 -0
- {agentseek_api-0.2.0 → agentseek_api-0.2.2}/src/agentseek_api/services/cron_webhooks.py +0 -0
- {agentseek_api-0.2.0 → agentseek_api-0.2.2}/src/agentseek_api/services/default_assistants.py +0 -0
- {agentseek_api-0.2.0 → agentseek_api-0.2.2}/src/agentseek_api/services/executor.py +0 -0
- {agentseek_api-0.2.0 → agentseek_api-0.2.2}/src/agentseek_api/services/langgraph_service.py +0 -0
- {agentseek_api-0.2.0 → agentseek_api-0.2.2}/src/agentseek_api/services/run_jobs.py +0 -0
- {agentseek_api-0.2.0 → agentseek_api-0.2.2}/src/agentseek_api/services/run_state.py +0 -0
- {agentseek_api-0.2.0 → agentseek_api-0.2.2}/src/agentseek_api/services/sample_graphs.py +0 -0
- {agentseek_api-0.2.0 → agentseek_api-0.2.2}/src/agentseek_api/services/sse.py +0 -0
- {agentseek_api-0.2.0 → agentseek_api-0.2.2}/src/agentseek_api/services/stream_modes.py +0 -0
- {agentseek_api-0.2.0 → agentseek_api-0.2.2}/src/agentseek_api/services/thread_checkpoint_store.py +0 -0
- {agentseek_api-0.2.0 → agentseek_api-0.2.2}/src/agentseek_api/services/thread_protocol.py +0 -0
- {agentseek_api-0.2.0 → agentseek_api-0.2.2}/src/agentseek_api/services/thread_service.py +0 -0
- {agentseek_api-0.2.0 → agentseek_api-0.2.2}/tests/__init__.py +0 -0
- {agentseek_api-0.2.0 → agentseek_api-0.2.2}/tests/conftest.py +0 -0
- {agentseek_api-0.2.0 → agentseek_api-0.2.2}/tests/e2e/__init__.py +0 -0
- {agentseek_api-0.2.0 → agentseek_api-0.2.2}/tests/e2e/conftest.py +0 -0
- {agentseek_api-0.2.0 → agentseek_api-0.2.2}/tests/e2e/e2e_inprocess_flow.py +0 -0
- {agentseek_api-0.2.0 → agentseek_api-0.2.2}/tests/e2e/e2e_live_http_flow.py +0 -0
- {agentseek_api-0.2.0 → agentseek_api-0.2.2}/tests/e2e/e2e_live_http_multi_graph.py +0 -0
- {agentseek_api-0.2.0 → agentseek_api-0.2.2}/tests/e2e/e2e_live_http_resume_flow.py +0 -0
- {agentseek_api-0.2.0 → agentseek_api-0.2.2}/tests/e2e/fixtures/langgraph.store-e2e.json +0 -0
- {agentseek_api-0.2.0 → agentseek_api-0.2.2}/tests/e2e/live_provider_helpers.py +0 -0
- {agentseek_api-0.2.0 → agentseek_api-0.2.2}/tests/e2e/test_a2a_live.py +0 -0
- {agentseek_api-0.2.0 → agentseek_api-0.2.2}/tests/e2e/test_cron_api_live.py +0 -0
- {agentseek_api-0.2.0 → agentseek_api-0.2.2}/tests/e2e/test_cron_scheduler_live.py +0 -0
- {agentseek_api-0.2.0 → agentseek_api-0.2.2}/tests/e2e/test_live_provider_api.py +0 -0
- {agentseek_api-0.2.0 → agentseek_api-0.2.2}/tests/e2e/test_live_provider_mcp.py +0 -0
- {agentseek_api-0.2.0 → agentseek_api-0.2.2}/tests/e2e/test_mcp_live.py +0 -0
- {agentseek_api-0.2.0 → agentseek_api-0.2.2}/tests/e2e/test_real_api_flow.py +0 -0
- {agentseek_api-0.2.0 → agentseek_api-0.2.2}/tests/integration/test_a2a_endpoint.py +0 -0
- {agentseek_api-0.2.0 → agentseek_api-0.2.2}/tests/integration/test_agent_card.py +0 -0
- {agentseek_api-0.2.0 → agentseek_api-0.2.2}/tests/integration/test_agents_aliases.py +0 -0
- {agentseek_api-0.2.0 → agentseek_api-0.2.2}/tests/integration/test_assistants_crud.py +0 -0
- {agentseek_api-0.2.0 → agentseek_api-0.2.2}/tests/integration/test_assistants_ordering.py +0 -0
- {agentseek_api-0.2.0 → agentseek_api-0.2.2}/tests/integration/test_auth_coverage_gaps.py +0 -0
- {agentseek_api-0.2.0 → agentseek_api-0.2.2}/tests/integration/test_auth_handlers.py +0 -0
- {agentseek_api-0.2.0 → agentseek_api-0.2.2}/tests/integration/test_auth_route_enforcement.py +0 -0
- {agentseek_api-0.2.0 → agentseek_api-0.2.2}/tests/integration/test_auth_scope_matrix.py +0 -0
- {agentseek_api-0.2.0 → agentseek_api-0.2.2}/tests/integration/test_core_api_flow.py +0 -0
- {agentseek_api-0.2.0 → agentseek_api-0.2.2}/tests/integration/test_cron_api.py +0 -0
- {agentseek_api-0.2.0 → agentseek_api-0.2.2}/tests/integration/test_langsmith_compat_extra.py +0 -0
- {agentseek_api-0.2.0 → agentseek_api-0.2.2}/tests/integration/test_live_provider_streaming.py +0 -0
- {agentseek_api-0.2.0 → agentseek_api-0.2.2}/tests/integration/test_mcp_endpoint.py +0 -0
- {agentseek_api-0.2.0 → agentseek_api-0.2.2}/tests/integration/test_protocol_v2_streaming.py +0 -0
- {agentseek_api-0.2.0 → agentseek_api-0.2.2}/tests/integration/test_run_cancellation_async.py +0 -0
- {agentseek_api-0.2.0 → agentseek_api-0.2.2}/tests/integration/test_runs_compat.py +0 -0
- {agentseek_api-0.2.0 → agentseek_api-0.2.2}/tests/integration/test_runs_crud.py +0 -0
- {agentseek_api-0.2.0 → agentseek_api-0.2.2}/tests/integration/test_runs_ordering.py +0 -0
- {agentseek_api-0.2.0 → agentseek_api-0.2.2}/tests/integration/test_runs_resume.py +0 -0
- {agentseek_api-0.2.0 → agentseek_api-0.2.2}/tests/integration/test_runs_streaming_errors.py +0 -0
- {agentseek_api-0.2.0 → agentseek_api-0.2.2}/tests/integration/test_runs_validation.py +0 -0
- {agentseek_api-0.2.0 → agentseek_api-0.2.2}/tests/integration/test_runs_wait_and_get.py +0 -0
- {agentseek_api-0.2.0 → agentseek_api-0.2.2}/tests/integration/test_runs_wait_timeout.py +0 -0
- {agentseek_api-0.2.0 → agentseek_api-0.2.2}/tests/integration/test_scheduler_runtime.py +0 -0
- {agentseek_api-0.2.0 → agentseek_api-0.2.2}/tests/integration/test_stateless_runs_crud.py +0 -0
- {agentseek_api-0.2.0 → agentseek_api-0.2.2}/tests/integration/test_store_api.py +0 -0
- {agentseek_api-0.2.0 → agentseek_api-0.2.2}/tests/integration/test_system_endpoints.py +0 -0
- {agentseek_api-0.2.0 → agentseek_api-0.2.2}/tests/integration/test_threads_compat.py +0 -0
- {agentseek_api-0.2.0 → agentseek_api-0.2.2}/tests/integration/test_threads_crud.py +0 -0
- {agentseek_api-0.2.0 → agentseek_api-0.2.2}/tests/integration/test_threads_ordering.py +0 -0
- {agentseek_api-0.2.0 → agentseek_api-0.2.2}/tests/unit/test_a2a_config.py +0 -0
- {agentseek_api-0.2.0 → agentseek_api-0.2.2}/tests/unit/test_a2a_server.py +0 -0
- {agentseek_api-0.2.0 → agentseek_api-0.2.2}/tests/unit/test_app_loader.py +0 -0
- {agentseek_api-0.2.0 → agentseek_api-0.2.2}/tests/unit/test_auth.py +0 -0
- {agentseek_api-0.2.0 → agentseek_api-0.2.2}/tests/unit/test_auth_deps.py +0 -0
- {agentseek_api-0.2.0 → agentseek_api-0.2.2}/tests/unit/test_auth_internals.py +0 -0
- {agentseek_api-0.2.0 → agentseek_api-0.2.2}/tests/unit/test_checkpoint_guards.py +0 -0
- {agentseek_api-0.2.0 → agentseek_api-0.2.2}/tests/unit/test_content_type_fix.py +0 -0
- {agentseek_api-0.2.0 → agentseek_api-0.2.2}/tests/unit/test_cron_rrule.py +0 -0
- {agentseek_api-0.2.0 → agentseek_api-0.2.2}/tests/unit/test_cron_service.py +0 -0
- {agentseek_api-0.2.0 → agentseek_api-0.2.2}/tests/unit/test_cron_webhooks.py +0 -0
- {agentseek_api-0.2.0 → agentseek_api-0.2.2}/tests/unit/test_custom_routers.py +0 -0
- {agentseek_api-0.2.0 → agentseek_api-0.2.2}/tests/unit/test_database_manager.py +0 -0
- {agentseek_api-0.2.0 → agentseek_api-0.2.2}/tests/unit/test_default_assistants.py +0 -0
- {agentseek_api-0.2.0 → agentseek_api-0.2.2}/tests/unit/test_examples.py +0 -0
- {agentseek_api-0.2.0 → agentseek_api-0.2.2}/tests/unit/test_executor.py +0 -0
- {agentseek_api-0.2.0 → agentseek_api-0.2.2}/tests/unit/test_graph_manifest.py +0 -0
- {agentseek_api-0.2.0 → agentseek_api-0.2.2}/tests/unit/test_http_config.py +0 -0
- {agentseek_api-0.2.0 → agentseek_api-0.2.2}/tests/unit/test_langgraph_service.py +0 -0
- {agentseek_api-0.2.0 → agentseek_api-0.2.2}/tests/unit/test_live_provider_e2e_config.py +0 -0
- {agentseek_api-0.2.0 → agentseek_api-0.2.2}/tests/unit/test_live_provider_graphs.py +0 -0
- {agentseek_api-0.2.0 → agentseek_api-0.2.2}/tests/unit/test_live_provider_matrix.py +0 -0
- {agentseek_api-0.2.0 → agentseek_api-0.2.2}/tests/unit/test_mcp_config.py +0 -0
- {agentseek_api-0.2.0 → agentseek_api-0.2.2}/tests/unit/test_mcp_server.py +0 -0
- {agentseek_api-0.2.0 → agentseek_api-0.2.2}/tests/unit/test_oceanbase_checkpointer.py +0 -0
- {agentseek_api-0.2.0 → agentseek_api-0.2.2}/tests/unit/test_openapi_auth_config.py +0 -0
- {agentseek_api-0.2.0 → agentseek_api-0.2.2}/tests/unit/test_run_jobs.py +0 -0
- {agentseek_api-0.2.0 → agentseek_api-0.2.2}/tests/unit/test_run_state.py +0 -0
- {agentseek_api-0.2.0 → agentseek_api-0.2.2}/tests/unit/test_runtime_store.py +0 -0
- {agentseek_api-0.2.0 → agentseek_api-0.2.2}/tests/unit/test_sample_graphs.py +0 -0
- {agentseek_api-0.2.0 → agentseek_api-0.2.2}/tests/unit/test_scheduler.py +0 -0
- {agentseek_api-0.2.0 → agentseek_api-0.2.2}/tests/unit/test_scheduler_process.py +0 -0
- {agentseek_api-0.2.0 → agentseek_api-0.2.2}/tests/unit/test_seekdb_checkpoint_smoke.py +0 -0
- {agentseek_api-0.2.0 → agentseek_api-0.2.2}/tests/unit/test_seekdb_embed_launcher.py +0 -0
- {agentseek_api-0.2.0 → agentseek_api-0.2.2}/tests/unit/test_sse_keepalive.py +0 -0
- {agentseek_api-0.2.0 → agentseek_api-0.2.2}/tests/unit/test_store_config.py +0 -0
- {agentseek_api-0.2.0 → agentseek_api-0.2.2}/tests/unit/test_stream_modes.py +0 -0
- {agentseek_api-0.2.0 → agentseek_api-0.2.2}/tests/unit/test_stream_persistence_helpers.py +0 -0
- {agentseek_api-0.2.0 → agentseek_api-0.2.2}/tests/unit/test_thread_checkpoint_store.py +0 -0
- {agentseek_api-0.2.0 → agentseek_api-0.2.2}/tests/unit/test_thread_protocol.py +0 -0
- {agentseek_api-0.2.0 → agentseek_api-0.2.2}/tests/unit/test_thread_routes_unit.py +0 -0
- {agentseek_api-0.2.0 → agentseek_api-0.2.2}/tests/unit/test_thread_service.py +0 -0
|
@@ -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:
|
|
94
|
-
|
|
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.
|
|
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`:
|
|
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.
|
|
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`:
|
|
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`
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "agentseek-api"
|
|
3
|
-
version = "0.2.
|
|
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.
|
|
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.
|
|
18
|
+
"langgraph>=1.0.6",
|
|
19
19
|
"langgraph-sdk>=0.3.5",
|
|
20
|
-
"langchain-core>=1.
|
|
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.
|
|
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
|
-
|
|
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
|
-
|
|
185
|
-
|
|
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
|
-
|
|
192
|
-
|
|
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()
|