devops-bot-sdk 1.6.34__tar.gz → 1.6.38__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.
- {devops_bot_sdk-1.6.34 → devops_bot_sdk-1.6.38}/PKG-INFO +1 -1
- {devops_bot_sdk-1.6.34 → devops_bot_sdk-1.6.38}/devops_bot_sdk.egg-info/PKG-INFO +1 -1
- {devops_bot_sdk-1.6.34 → devops_bot_sdk-1.6.38}/devops_bot_sdk.egg-info/SOURCES.txt +10 -2
- {devops_bot_sdk-1.6.34 → devops_bot_sdk-1.6.38}/devops_bot_sdk.egg-info/entry_points.txt +1 -0
- {devops_bot_sdk-1.6.34 → devops_bot_sdk-1.6.38}/pyproject.toml +1 -0
- {devops_bot_sdk-1.6.34 → devops_bot_sdk-1.6.38}/sdk/__init__.py +2 -2
- {devops_bot_sdk-1.6.34 → devops_bot_sdk-1.6.38}/sdk/cli.py +36 -1
- {devops_bot_sdk-1.6.34 → devops_bot_sdk-1.6.38}/sdk/client.py +104 -35
- {devops_bot_sdk-1.6.34 → devops_bot_sdk-1.6.38}/sdk/config.py +9 -1
- devops_bot_sdk-1.6.38/sdk/firewall.py +472 -0
- devops_bot_sdk-1.6.38/sdk/github_fetch.py +198 -0
- devops_bot_sdk-1.6.38/sdk/github_ingest.py +618 -0
- {devops_bot_sdk-1.6.34 → devops_bot_sdk-1.6.38}/sdk/intake.py +126 -1
- {devops_bot_sdk-1.6.34 → devops_bot_sdk-1.6.38}/sdk/run_auto.py +17 -24
- devops_bot_sdk-1.6.38/sdk/swagger.py +356 -0
- {devops_bot_sdk-1.6.34 → devops_bot_sdk-1.6.38}/sdk/ui/api.py +0 -27
- {devops_bot_sdk-1.6.34 → devops_bot_sdk-1.6.38}/sdk/ui/ip_allowlist.py +43 -16
- {devops_bot_sdk-1.6.34 → devops_bot_sdk-1.6.38}/sdk/ui/models.py +0 -13
- devops_bot_sdk-1.6.38/sdk/ui/server.py +309 -0
- devops_bot_sdk-1.6.38/sdk/ui/swagger.py +167 -0
- {devops_bot_sdk-1.6.34 → devops_bot_sdk-1.6.38}/sdk/updater.py +42 -0
- devops_bot_sdk-1.6.38/sdk/vps_health.py +264 -0
- devops_bot_sdk-1.6.38/tests/test_firewall_open_on_update.py +213 -0
- devops_bot_sdk-1.6.38/tests/test_github_fetch.py +216 -0
- {devops_bot_sdk-1.6.34 → devops_bot_sdk-1.6.38}/tests/test_github_ingest.py +105 -4
- devops_bot_sdk-1.6.38/tests/test_intake_job_outcome.py +180 -0
- devops_bot_sdk-1.6.38/tests/test_swagger_command.py +260 -0
- devops_bot_sdk-1.6.38/tests/test_ui_gate.py +351 -0
- devops_bot_sdk-1.6.38/tests/test_ui_lifespan.py +89 -0
- devops_bot_sdk-1.6.34/sdk/github_ingest.py +0 -161
- devops_bot_sdk-1.6.34/sdk/ui/server.py +0 -189
- devops_bot_sdk-1.6.34/sdk/ui/static/login.html +0 -111
- devops_bot_sdk-1.6.34/sdk/vps_health.py +0 -111
- devops_bot_sdk-1.6.34/tests/test_otp_login.py +0 -178
- {devops_bot_sdk-1.6.34 → devops_bot_sdk-1.6.38}/README.md +0 -0
- {devops_bot_sdk-1.6.34 → devops_bot_sdk-1.6.38}/devops_bot_sdk.egg-info/dependency_links.txt +0 -0
- {devops_bot_sdk-1.6.34 → devops_bot_sdk-1.6.38}/devops_bot_sdk.egg-info/requires.txt +0 -0
- {devops_bot_sdk-1.6.34 → devops_bot_sdk-1.6.38}/devops_bot_sdk.egg-info/top_level.txt +0 -0
- {devops_bot_sdk-1.6.34 → devops_bot_sdk-1.6.38}/sdk/agentd.py +0 -0
- {devops_bot_sdk-1.6.34 → devops_bot_sdk-1.6.38}/sdk/agents/__init__.py +0 -0
- {devops_bot_sdk-1.6.34 → devops_bot_sdk-1.6.38}/sdk/agents/activity.py +0 -0
- {devops_bot_sdk-1.6.34 → devops_bot_sdk-1.6.38}/sdk/agents/builder.py +0 -0
- {devops_bot_sdk-1.6.34 → devops_bot_sdk-1.6.38}/sdk/agents/chat.py +0 -0
- {devops_bot_sdk-1.6.34 → devops_bot_sdk-1.6.38}/sdk/agents/connectors.py +0 -0
- {devops_bot_sdk-1.6.34 → devops_bot_sdk-1.6.38}/sdk/agents/engines/__init__.py +0 -0
- {devops_bot_sdk-1.6.34 → devops_bot_sdk-1.6.38}/sdk/agents/engines/claude_code.py +0 -0
- {devops_bot_sdk-1.6.34 → devops_bot_sdk-1.6.38}/sdk/agents/engines/http.py +0 -0
- {devops_bot_sdk-1.6.34 → devops_bot_sdk-1.6.38}/sdk/agents/engines/mcp.py +0 -0
- {devops_bot_sdk-1.6.34 → devops_bot_sdk-1.6.38}/sdk/agents/engines/n8n.py +0 -0
- {devops_bot_sdk-1.6.34 → devops_bot_sdk-1.6.38}/sdk/agents/engines/shell.py +0 -0
- {devops_bot_sdk-1.6.34 → devops_bot_sdk-1.6.38}/sdk/agents/integrations.py +0 -0
- {devops_bot_sdk-1.6.34 → devops_bot_sdk-1.6.38}/sdk/agents/inventory.py +0 -0
- {devops_bot_sdk-1.6.34 → devops_bot_sdk-1.6.38}/sdk/agents/library/__init__.py +0 -0
- {devops_bot_sdk-1.6.34 → devops_bot_sdk-1.6.38}/sdk/agents/manifest.py +0 -0
- {devops_bot_sdk-1.6.34 → devops_bot_sdk-1.6.38}/sdk/agents/prompt_studio.py +0 -0
- {devops_bot_sdk-1.6.34 → devops_bot_sdk-1.6.38}/sdk/agents/prompt_template.py +0 -0
- {devops_bot_sdk-1.6.34 → devops_bot_sdk-1.6.38}/sdk/agents/prompt_vars.py +0 -0
- {devops_bot_sdk-1.6.34 → devops_bot_sdk-1.6.38}/sdk/agents/run_log.py +0 -0
- {devops_bot_sdk-1.6.34 → devops_bot_sdk-1.6.38}/sdk/agents/schedules.py +0 -0
- {devops_bot_sdk-1.6.34 → devops_bot_sdk-1.6.38}/sdk/agents/secrets.py +0 -0
- {devops_bot_sdk-1.6.34 → devops_bot_sdk-1.6.38}/sdk/agents/ticket_run.py +0 -0
- {devops_bot_sdk-1.6.34 → devops_bot_sdk-1.6.38}/sdk/agents/usage.py +0 -0
- {devops_bot_sdk-1.6.34 → devops_bot_sdk-1.6.38}/sdk/agents/varstore.py +0 -0
- {devops_bot_sdk-1.6.34 → devops_bot_sdk-1.6.38}/sdk/browser_profile.py +0 -0
- {devops_bot_sdk-1.6.34 → devops_bot_sdk-1.6.38}/sdk/collectors/__init__.py +0 -0
- {devops_bot_sdk-1.6.34 → devops_bot_sdk-1.6.38}/sdk/collectors/files.py +0 -0
- {devops_bot_sdk-1.6.34 → devops_bot_sdk-1.6.38}/sdk/collectors/process.py +0 -0
- {devops_bot_sdk-1.6.34 → devops_bot_sdk-1.6.38}/sdk/collectors/screenshot.py +0 -0
- {devops_bot_sdk-1.6.34 → devops_bot_sdk-1.6.38}/sdk/crucial.py +0 -0
- {devops_bot_sdk-1.6.34 → devops_bot_sdk-1.6.38}/sdk/departments.py +0 -0
- {devops_bot_sdk-1.6.34 → devops_bot_sdk-1.6.38}/sdk/design_verify/__init__.py +0 -0
- {devops_bot_sdk-1.6.34 → devops_bot_sdk-1.6.38}/sdk/design_verify/assets.py +0 -0
- {devops_bot_sdk-1.6.34 → devops_bot_sdk-1.6.38}/sdk/design_verify/bootstrap.py +0 -0
- {devops_bot_sdk-1.6.34 → devops_bot_sdk-1.6.38}/sdk/design_verify/browser.py +0 -0
- {devops_bot_sdk-1.6.34 → devops_bot_sdk-1.6.38}/sdk/design_verify/compare.py +0 -0
- {devops_bot_sdk-1.6.34 → devops_bot_sdk-1.6.38}/sdk/design_verify/loop.py +0 -0
- {devops_bot_sdk-1.6.34 → devops_bot_sdk-1.6.38}/sdk/estimator.py +0 -0
- {devops_bot_sdk-1.6.34 → devops_bot_sdk-1.6.38}/sdk/exceptions.py +0 -0
- {devops_bot_sdk-1.6.34 → devops_bot_sdk-1.6.38}/sdk/formats.py +0 -0
- {devops_bot_sdk-1.6.34 → devops_bot_sdk-1.6.38}/sdk/git_ops.py +0 -0
- {devops_bot_sdk-1.6.34 → devops_bot_sdk-1.6.38}/sdk/graph_recon.py +0 -0
- {devops_bot_sdk-1.6.34 → devops_bot_sdk-1.6.38}/sdk/graphify.py +0 -0
- {devops_bot_sdk-1.6.34 → devops_bot_sdk-1.6.38}/sdk/hooks/__init__.py +0 -0
- {devops_bot_sdk-1.6.34 → devops_bot_sdk-1.6.38}/sdk/hooks/crucial_guard.py +0 -0
- {devops_bot_sdk-1.6.34 → devops_bot_sdk-1.6.38}/sdk/ipc/__init__.py +0 -0
- {devops_bot_sdk-1.6.34 → devops_bot_sdk-1.6.38}/sdk/ipc/electron_bridge.py +0 -0
- {devops_bot_sdk-1.6.34 → devops_bot_sdk-1.6.38}/sdk/ipc/handlers.py +0 -0
- {devops_bot_sdk-1.6.34 → devops_bot_sdk-1.6.38}/sdk/journal.py +0 -0
- {devops_bot_sdk-1.6.34 → devops_bot_sdk-1.6.38}/sdk/local_exec.py +0 -0
- {devops_bot_sdk-1.6.34 → devops_bot_sdk-1.6.38}/sdk/models/__init__.py +0 -0
- {devops_bot_sdk-1.6.34 → devops_bot_sdk-1.6.38}/sdk/models/envelope.py +0 -0
- {devops_bot_sdk-1.6.34 → devops_bot_sdk-1.6.38}/sdk/models/requests.py +0 -0
- {devops_bot_sdk-1.6.34 → devops_bot_sdk-1.6.38}/sdk/models/responses.py +0 -0
- {devops_bot_sdk-1.6.34 → devops_bot_sdk-1.6.38}/sdk/models/snapshots.py +0 -0
- {devops_bot_sdk-1.6.34 → devops_bot_sdk-1.6.38}/sdk/phase_timer.py +0 -0
- {devops_bot_sdk-1.6.34 → devops_bot_sdk-1.6.38}/sdk/plan_run.py +0 -0
- {devops_bot_sdk-1.6.34 → devops_bot_sdk-1.6.38}/sdk/platform_compat.py +0 -0
- {devops_bot_sdk-1.6.34 → devops_bot_sdk-1.6.38}/sdk/prd_progress.py +0 -0
- {devops_bot_sdk-1.6.34 → devops_bot_sdk-1.6.38}/sdk/proof_readers.py +0 -0
- {devops_bot_sdk-1.6.34 → devops_bot_sdk-1.6.38}/sdk/providers.py +0 -0
- {devops_bot_sdk-1.6.34 → devops_bot_sdk-1.6.38}/sdk/py.typed +0 -0
- {devops_bot_sdk-1.6.34 → devops_bot_sdk-1.6.38}/sdk/resume.py +0 -0
- {devops_bot_sdk-1.6.34 → devops_bot_sdk-1.6.38}/sdk/router.py +0 -0
- {devops_bot_sdk-1.6.34 → devops_bot_sdk-1.6.38}/sdk/scheduler.py +0 -0
- {devops_bot_sdk-1.6.34 → devops_bot_sdk-1.6.38}/sdk/self_report.py +0 -0
- {devops_bot_sdk-1.6.34 → devops_bot_sdk-1.6.38}/sdk/self_report_local.py +0 -0
- {devops_bot_sdk-1.6.34 → devops_bot_sdk-1.6.38}/sdk/sse.py +0 -0
- {devops_bot_sdk-1.6.34 → devops_bot_sdk-1.6.38}/sdk/task_file.py +0 -0
- {devops_bot_sdk-1.6.34 → devops_bot_sdk-1.6.38}/sdk/task_types.py +0 -0
- {devops_bot_sdk-1.6.34 → devops_bot_sdk-1.6.38}/sdk/test.py +0 -0
- {devops_bot_sdk-1.6.34 → devops_bot_sdk-1.6.38}/sdk/test_pipeline.py +0 -0
- {devops_bot_sdk-1.6.34 → devops_bot_sdk-1.6.38}/sdk/ticket_fields.py +0 -0
- {devops_bot_sdk-1.6.34 → devops_bot_sdk-1.6.38}/sdk/tiers/__init__.py +0 -0
- {devops_bot_sdk-1.6.34 → devops_bot_sdk-1.6.38}/sdk/tiers/mini_agent.py +0 -0
- {devops_bot_sdk-1.6.34 → devops_bot_sdk-1.6.38}/sdk/ui/__init__.py +0 -0
- {devops_bot_sdk-1.6.34 → devops_bot_sdk-1.6.38}/sdk/ui/dashboard.py +0 -0
- {devops_bot_sdk-1.6.34 → devops_bot_sdk-1.6.38}/sdk/ui/health.py +0 -0
- {devops_bot_sdk-1.6.34 → devops_bot_sdk-1.6.38}/sdk/ui/jobs.py +0 -0
- {devops_bot_sdk-1.6.34 → devops_bot_sdk-1.6.38}/sdk/ui/runner.py +0 -0
- {devops_bot_sdk-1.6.34 → devops_bot_sdk-1.6.38}/sdk/ui/security.py +0 -0
- {devops_bot_sdk-1.6.34 → devops_bot_sdk-1.6.38}/sdk/ui/service.py +0 -0
- {devops_bot_sdk-1.6.34 → devops_bot_sdk-1.6.38}/sdk/ui/session.py +0 -0
- {devops_bot_sdk-1.6.34 → devops_bot_sdk-1.6.38}/sdk/ui/setup_manager.py +0 -0
- {devops_bot_sdk-1.6.34 → devops_bot_sdk-1.6.38}/sdk/ui/static/agents.html +0 -0
- {devops_bot_sdk-1.6.34 → devops_bot_sdk-1.6.38}/sdk/ui/static/app.js +0 -0
- {devops_bot_sdk-1.6.34 → devops_bot_sdk-1.6.38}/sdk/ui/static/chat.html +0 -0
- {devops_bot_sdk-1.6.34 → devops_bot_sdk-1.6.38}/sdk/ui/static/custom-agents.html +0 -0
- {devops_bot_sdk-1.6.34 → devops_bot_sdk-1.6.38}/sdk/ui/static/default-agents.html +0 -0
- {devops_bot_sdk-1.6.34 → devops_bot_sdk-1.6.38}/sdk/ui/static/index.html +0 -0
- {devops_bot_sdk-1.6.34 → devops_bot_sdk-1.6.38}/sdk/ui/static/report.html +0 -0
- {devops_bot_sdk-1.6.34 → devops_bot_sdk-1.6.38}/sdk/ui/static/runs.html +0 -0
- {devops_bot_sdk-1.6.34 → devops_bot_sdk-1.6.38}/sdk/ui/static/schedules.html +0 -0
- {devops_bot_sdk-1.6.34 → devops_bot_sdk-1.6.38}/sdk/ui/static/setup.html +0 -0
- {devops_bot_sdk-1.6.34 → devops_bot_sdk-1.6.38}/sdk/ui/static/styles.css +0 -0
- {devops_bot_sdk-1.6.34 → devops_bot_sdk-1.6.38}/sdk/ui/static/tickets.html +0 -0
- {devops_bot_sdk-1.6.34 → devops_bot_sdk-1.6.38}/sdk/url_access.py +0 -0
- {devops_bot_sdk-1.6.34 → devops_bot_sdk-1.6.38}/sdk/write_hook.py +0 -0
- {devops_bot_sdk-1.6.34 → devops_bot_sdk-1.6.38}/setup.cfg +0 -0
- {devops_bot_sdk-1.6.34 → devops_bot_sdk-1.6.38}/tests/test_agent_activity.py +0 -0
- {devops_bot_sdk-1.6.34 → devops_bot_sdk-1.6.38}/tests/test_agent_activity_tracking.py +0 -0
- {devops_bot_sdk-1.6.34 → devops_bot_sdk-1.6.38}/tests/test_agent_chat_features.py +0 -0
- {devops_bot_sdk-1.6.34 → devops_bot_sdk-1.6.38}/tests/test_agent_listing.py +0 -0
- {devops_bot_sdk-1.6.34 → devops_bot_sdk-1.6.38}/tests/test_agent_prompt_async.py +0 -0
- {devops_bot_sdk-1.6.34 → devops_bot_sdk-1.6.38}/tests/test_agent_prompt_models.py +0 -0
- {devops_bot_sdk-1.6.34 → devops_bot_sdk-1.6.38}/tests/test_agent_run_ticket.py +0 -0
- {devops_bot_sdk-1.6.34 → devops_bot_sdk-1.6.38}/tests/test_agent_schedules.py +0 -0
- {devops_bot_sdk-1.6.34 → devops_bot_sdk-1.6.38}/tests/test_agent_workspace_settings.py +0 -0
- {devops_bot_sdk-1.6.34 → devops_bot_sdk-1.6.38}/tests/test_agents_connectors_builder.py +0 -0
- {devops_bot_sdk-1.6.34 → devops_bot_sdk-1.6.38}/tests/test_allowed_tools_config.py +0 -0
- {devops_bot_sdk-1.6.34 → devops_bot_sdk-1.6.38}/tests/test_auto_agent_dispatch.py +0 -0
- {devops_bot_sdk-1.6.34 → devops_bot_sdk-1.6.38}/tests/test_browser_profile.py +0 -0
- {devops_bot_sdk-1.6.34 → devops_bot_sdk-1.6.38}/tests/test_cheap_tier.py +0 -0
- {devops_bot_sdk-1.6.34 → devops_bot_sdk-1.6.38}/tests/test_client_jira_projects.py +0 -0
- {devops_bot_sdk-1.6.34 → devops_bot_sdk-1.6.38}/tests/test_config_token_diagnostics.py +0 -0
- {devops_bot_sdk-1.6.34 → devops_bot_sdk-1.6.38}/tests/test_configure_token_owner.py +0 -0
- {devops_bot_sdk-1.6.34 → devops_bot_sdk-1.6.38}/tests/test_console_encoding.py +0 -0
- {devops_bot_sdk-1.6.34 → devops_bot_sdk-1.6.38}/tests/test_departments.py +0 -0
- {devops_bot_sdk-1.6.34 → devops_bot_sdk-1.6.38}/tests/test_epic_decompose_run.py +0 -0
- {devops_bot_sdk-1.6.34 → devops_bot_sdk-1.6.38}/tests/test_epic_inherited_agent_id.py +0 -0
- {devops_bot_sdk-1.6.34 → devops_bot_sdk-1.6.38}/tests/test_epic_session_isolation.py +0 -0
- {devops_bot_sdk-1.6.34 → devops_bot_sdk-1.6.38}/tests/test_estimator.py +0 -0
- {devops_bot_sdk-1.6.34 → devops_bot_sdk-1.6.38}/tests/test_formats.py +0 -0
- {devops_bot_sdk-1.6.34 → devops_bot_sdk-1.6.38}/tests/test_git_action.py +0 -0
- {devops_bot_sdk-1.6.34 → devops_bot_sdk-1.6.38}/tests/test_graph_recon.py +0 -0
- {devops_bot_sdk-1.6.34 → devops_bot_sdk-1.6.38}/tests/test_graphify_build.py +0 -0
- {devops_bot_sdk-1.6.34 → devops_bot_sdk-1.6.38}/tests/test_graphify_hook_install.py +0 -0
- {devops_bot_sdk-1.6.34 → devops_bot_sdk-1.6.38}/tests/test_health.py +0 -0
- {devops_bot_sdk-1.6.34 → devops_bot_sdk-1.6.38}/tests/test_intake_plan_review.py +0 -0
- {devops_bot_sdk-1.6.34 → devops_bot_sdk-1.6.38}/tests/test_journal.py +0 -0
- {devops_bot_sdk-1.6.34 → devops_bot_sdk-1.6.38}/tests/test_local_exec_provider.py +0 -0
- {devops_bot_sdk-1.6.34 → devops_bot_sdk-1.6.38}/tests/test_phase_timer.py +0 -0
- {devops_bot_sdk-1.6.34 → devops_bot_sdk-1.6.38}/tests/test_plan_new_command.py +0 -0
- {devops_bot_sdk-1.6.34 → devops_bot_sdk-1.6.38}/tests/test_plan_run_activity.py +0 -0
- {devops_bot_sdk-1.6.34 → devops_bot_sdk-1.6.38}/tests/test_prd_artifact.py +0 -0
- {devops_bot_sdk-1.6.34 → devops_bot_sdk-1.6.38}/tests/test_proof_readers.py +0 -0
- {devops_bot_sdk-1.6.34 → devops_bot_sdk-1.6.38}/tests/test_providers.py +0 -0
- {devops_bot_sdk-1.6.34 → devops_bot_sdk-1.6.38}/tests/test_recon_session_isolation.py +0 -0
- {devops_bot_sdk-1.6.34 → devops_bot_sdk-1.6.38}/tests/test_resume.py +0 -0
- {devops_bot_sdk-1.6.34 → devops_bot_sdk-1.6.38}/tests/test_router.py +0 -0
- {devops_bot_sdk-1.6.34 → devops_bot_sdk-1.6.38}/tests/test_run_auto_agent_only.py +0 -0
- {devops_bot_sdk-1.6.34 → devops_bot_sdk-1.6.38}/tests/test_run_outputs.py +0 -0
- {devops_bot_sdk-1.6.34 → devops_bot_sdk-1.6.38}/tests/test_schedule_api.py +0 -0
- {devops_bot_sdk-1.6.34 → devops_bot_sdk-1.6.38}/tests/test_scheduler.py +0 -0
- {devops_bot_sdk-1.6.34 → devops_bot_sdk-1.6.38}/tests/test_self_report.py +0 -0
- {devops_bot_sdk-1.6.34 → devops_bot_sdk-1.6.38}/tests/test_service_token_warning.py +0 -0
- {devops_bot_sdk-1.6.34 → devops_bot_sdk-1.6.38}/tests/test_task_file_and_plan_run.py +0 -0
- {devops_bot_sdk-1.6.34 → devops_bot_sdk-1.6.38}/tests/test_task_file_format_doc.py +0 -0
- {devops_bot_sdk-1.6.34 → devops_bot_sdk-1.6.38}/tests/test_ticket_fields.py +0 -0
- {devops_bot_sdk-1.6.34 → devops_bot_sdk-1.6.38}/tests/test_ticket_run_resolve_by_id.py +0 -0
- {devops_bot_sdk-1.6.34 → devops_bot_sdk-1.6.38}/tests/test_ticket_speed_fixes.py +0 -0
- {devops_bot_sdk-1.6.34 → devops_bot_sdk-1.6.38}/tests/test_tier_flag_parity.py +0 -0
- {devops_bot_sdk-1.6.34 → devops_bot_sdk-1.6.38}/tests/test_update_timer.py +0 -0
- {devops_bot_sdk-1.6.34 → devops_bot_sdk-1.6.38}/tests/test_updater_extras.py +0 -0
- {devops_bot_sdk-1.6.34 → devops_bot_sdk-1.6.38}/tests/test_url_access.py +0 -0
- {devops_bot_sdk-1.6.34 → devops_bot_sdk-1.6.38}/tests/test_vps_health.py +0 -0
- {devops_bot_sdk-1.6.34 → devops_bot_sdk-1.6.38}/tests/test_write_hook.py +0 -0
|
@@ -16,8 +16,10 @@ sdk/crucial.py
|
|
|
16
16
|
sdk/departments.py
|
|
17
17
|
sdk/estimator.py
|
|
18
18
|
sdk/exceptions.py
|
|
19
|
+
sdk/firewall.py
|
|
19
20
|
sdk/formats.py
|
|
20
21
|
sdk/git_ops.py
|
|
22
|
+
sdk/github_fetch.py
|
|
21
23
|
sdk/github_ingest.py
|
|
22
24
|
sdk/graph_recon.py
|
|
23
25
|
sdk/graphify.py
|
|
@@ -38,6 +40,7 @@ sdk/scheduler.py
|
|
|
38
40
|
sdk/self_report.py
|
|
39
41
|
sdk/self_report_local.py
|
|
40
42
|
sdk/sse.py
|
|
43
|
+
sdk/swagger.py
|
|
41
44
|
sdk/task_file.py
|
|
42
45
|
sdk/task_types.py
|
|
43
46
|
sdk/test.py
|
|
@@ -106,13 +109,13 @@ sdk/ui/server.py
|
|
|
106
109
|
sdk/ui/service.py
|
|
107
110
|
sdk/ui/session.py
|
|
108
111
|
sdk/ui/setup_manager.py
|
|
112
|
+
sdk/ui/swagger.py
|
|
109
113
|
sdk/ui/static/agents.html
|
|
110
114
|
sdk/ui/static/app.js
|
|
111
115
|
sdk/ui/static/chat.html
|
|
112
116
|
sdk/ui/static/custom-agents.html
|
|
113
117
|
sdk/ui/static/default-agents.html
|
|
114
118
|
sdk/ui/static/index.html
|
|
115
|
-
sdk/ui/static/login.html
|
|
116
119
|
sdk/ui/static/report.html
|
|
117
120
|
sdk/ui/static/runs.html
|
|
118
121
|
sdk/ui/static/schedules.html
|
|
@@ -142,17 +145,19 @@ tests/test_epic_decompose_run.py
|
|
|
142
145
|
tests/test_epic_inherited_agent_id.py
|
|
143
146
|
tests/test_epic_session_isolation.py
|
|
144
147
|
tests/test_estimator.py
|
|
148
|
+
tests/test_firewall_open_on_update.py
|
|
145
149
|
tests/test_formats.py
|
|
146
150
|
tests/test_git_action.py
|
|
151
|
+
tests/test_github_fetch.py
|
|
147
152
|
tests/test_github_ingest.py
|
|
148
153
|
tests/test_graph_recon.py
|
|
149
154
|
tests/test_graphify_build.py
|
|
150
155
|
tests/test_graphify_hook_install.py
|
|
151
156
|
tests/test_health.py
|
|
157
|
+
tests/test_intake_job_outcome.py
|
|
152
158
|
tests/test_intake_plan_review.py
|
|
153
159
|
tests/test_journal.py
|
|
154
160
|
tests/test_local_exec_provider.py
|
|
155
|
-
tests/test_otp_login.py
|
|
156
161
|
tests/test_phase_timer.py
|
|
157
162
|
tests/test_plan_new_command.py
|
|
158
163
|
tests/test_plan_run_activity.py
|
|
@@ -168,12 +173,15 @@ tests/test_schedule_api.py
|
|
|
168
173
|
tests/test_scheduler.py
|
|
169
174
|
tests/test_self_report.py
|
|
170
175
|
tests/test_service_token_warning.py
|
|
176
|
+
tests/test_swagger_command.py
|
|
171
177
|
tests/test_task_file_and_plan_run.py
|
|
172
178
|
tests/test_task_file_format_doc.py
|
|
173
179
|
tests/test_ticket_fields.py
|
|
174
180
|
tests/test_ticket_run_resolve_by_id.py
|
|
175
181
|
tests/test_ticket_speed_fixes.py
|
|
176
182
|
tests/test_tier_flag_parity.py
|
|
183
|
+
tests/test_ui_gate.py
|
|
184
|
+
tests/test_ui_lifespan.py
|
|
177
185
|
tests/test_update_timer.py
|
|
178
186
|
tests/test_updater_extras.py
|
|
179
187
|
tests/test_url_access.py
|
|
@@ -54,6 +54,7 @@ agentos = "sdk.cli:main" # unified CLI: configure/agent/integ
|
|
|
54
54
|
agentos-auto = "sdk.run_auto:main" # run orchestrate-auto LOCALLY (co_ token from config)
|
|
55
55
|
agentos-agentd = "sdk.agentd:main" # long-running custom-agent daemon
|
|
56
56
|
agentos-ui = "sdk.ui.server:main" # local web control panel (needs the [ui] extra)
|
|
57
|
+
agentos-swagger = "sdk.swagger:main" # where /docs is + can you reach it (= `agentos swagger`)
|
|
57
58
|
|
|
58
59
|
[project.urls]
|
|
59
60
|
Homepage = "https://agentos.io"
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"""AgentOS Desktop SDK — thin HTTPS/SSE client for the Electron app.
|
|
2
2
|
|
|
3
|
-
Version: 1.6.
|
|
3
|
+
Version: 1.6.38
|
|
4
4
|
|
|
5
5
|
Public surface:
|
|
6
6
|
BackendClient.from_config() — create client from ~/.agentos/config.toml
|
|
@@ -34,7 +34,7 @@ Rules:
|
|
|
34
34
|
- All data egress through submit_webhook only
|
|
35
35
|
"""
|
|
36
36
|
|
|
37
|
-
__version__ = "1.6.
|
|
37
|
+
__version__ = "1.6.38" # SINGLE SOURCE OF TRUTH — bump on every change; pyproject,
|
|
38
38
|
__author__ = "AgentOS" # sdk.client.SDK_VERSION and the UI server version all read this.
|
|
39
39
|
|
|
40
40
|
from sdk.client import BackendClient
|
|
@@ -58,6 +58,30 @@ Command surface:
|
|
|
58
58
|
agentos integration rm <name>
|
|
59
59
|
Remove a registered integration.
|
|
60
60
|
|
|
61
|
+
agentos firewall [--apply] [--any] [--revoke IP] [--port N]
|
|
62
|
+
Print the host-firewall rules that open the agentos-ui port to every IP in
|
|
63
|
+
the application allowlist (`sdk.config.get_allowed_ips`), for THIS OS — ufw
|
|
64
|
+
on Linux, `netsh advfirewall` on Windows, a pf note on macOS. Prints by
|
|
65
|
+
default; `--apply` executes them and needs root / Administrator. The host
|
|
66
|
+
firewall is a separate layer the allowlist cannot reach, and the two drifting
|
|
67
|
+
apart is what silently blinded every VPS when the backend's egress IP moved.
|
|
68
|
+
`--any` opens the port to every source instead, leaving
|
|
69
|
+
IPAllowlistMiddleware as the gate — the more robust choice when the
|
|
70
|
+
backend's egress IP can move, since a stale per-IP kernel rule drops the
|
|
71
|
+
SYN before the allowlist is ever consulted. This is what runs
|
|
72
|
+
automatically after a self-update. See sdk.firewall.
|
|
73
|
+
|
|
74
|
+
agentos swagger [--open] [--json [PATH]] [--port N]
|
|
75
|
+
Where the panel's Swagger UI is and whether it can actually be reached:
|
|
76
|
+
the URL derived from the bind address the service was installed with,
|
|
77
|
+
whether a co_ token is configured (masked), how many operations the spec
|
|
78
|
+
has, and a ufw/netsh diff against sdk.config.get_allowed_ips when the HOST
|
|
79
|
+
firewall would drop the port — a layer the SDK's own allowlist cannot see.
|
|
80
|
+
`--open` launches a browser; `--json` writes openapi.json from
|
|
81
|
+
create_app().openapi() with no server running (`--json -` pipes it).
|
|
82
|
+
Also flags routes registered twice, since the second copy is dead code.
|
|
83
|
+
Needs the [ui] extra for the route count and --json. See sdk.swagger.
|
|
84
|
+
|
|
61
85
|
agentos report submit [--date YYYY-MM-DD] (--text "…" | --file PATH)
|
|
62
86
|
[--project NAME] [--proof PATH|URL]… [--no-wait]
|
|
63
87
|
Report work that never reached Jira or GitHub, attach proofs (local
|
|
@@ -139,6 +163,14 @@ def main() -> None:
|
|
|
139
163
|
_github_command(rest)
|
|
140
164
|
return
|
|
141
165
|
|
|
166
|
+
if noun == "firewall":
|
|
167
|
+
from sdk import firewall
|
|
168
|
+
sys.exit(firewall.cli(rest))
|
|
169
|
+
|
|
170
|
+
if noun == "swagger":
|
|
171
|
+
from sdk import swagger
|
|
172
|
+
sys.exit(swagger.cli(rest))
|
|
173
|
+
|
|
142
174
|
if noun == "report":
|
|
143
175
|
_report_command(rest)
|
|
144
176
|
return
|
|
@@ -152,7 +184,7 @@ def main() -> None:
|
|
|
152
184
|
|
|
153
185
|
|
|
154
186
|
def _print_usage() -> None:
|
|
155
|
-
print("usage: agentos <configure|chat|agent|integration|default-agents|agentd|github|report|browser> ...")
|
|
187
|
+
print("usage: agentos <configure|chat|agent|integration|default-agents|agentd|github|report|browser|firewall|swagger> ...")
|
|
156
188
|
print()
|
|
157
189
|
print(" agentos configure [--rotate]")
|
|
158
190
|
print(" agentos chat [--product-id ID] [--pv-id ID] [--no-autorun] # requirements → ticket")
|
|
@@ -164,6 +196,9 @@ def _print_usage() -> None:
|
|
|
164
196
|
print(" agentos github <ingest [--days N]|status> # PR ingestion; --days N backfills N days")
|
|
165
197
|
print(" agentos report <submit|list|show ID> # report work Jira/GitHub never saw")
|
|
166
198
|
print(" agentos browser <login URL|status|logout> # sign in once; private links become readable")
|
|
199
|
+
print(" agentos firewall [--apply] [--revoke IP] [--port N] # open the UI port to the allowlisted IPs")
|
|
200
|
+
print(" agentos firewall --any [--apply] # open the UI port to any source (allowlist is the gate)")
|
|
201
|
+
print(" agentos swagger [--open] [--json [PATH]] # where /docs is, and can you reach it")
|
|
167
202
|
|
|
168
203
|
|
|
169
204
|
# ── agent ────────────────────────────────────────────────────────────────
|
|
@@ -45,6 +45,13 @@ logger = logging.getLogger(__name__)
|
|
|
45
45
|
# agents without a lookup on every run.
|
|
46
46
|
_AGENT_ID_CACHE: dict[str, str] = {}
|
|
47
47
|
|
|
48
|
+
# GitHub access token, keyed by the co_ token that fetched it → (token, expires_at
|
|
49
|
+
# monotonic). Keyed per credential so two clients on one box never share a token.
|
|
50
|
+
# Without this the token is re-fetched on EVERY call, which is what
|
|
51
|
+
# tests/test_ticket_speed_fixes.py::TestGithubTokenCache guards against.
|
|
52
|
+
_GITHUB_TOKEN_CACHE: dict[str, tuple[str, float]] = {}
|
|
53
|
+
_GITHUB_TOKEN_TTL_S = float(os.getenv("AGENTOS_GITHUB_TOKEN_TTL_S", "") or 1800.0)
|
|
54
|
+
|
|
48
55
|
# GitHub access token, keyed by the co_ token that fetched it → (token, expires_at
|
|
49
56
|
# monotonic). Keyed per credential so two clients on one box never share a token.
|
|
50
57
|
_GITHUB_TOKEN_CACHE: dict[str, tuple[str, float]] = {}
|
|
@@ -952,51 +959,113 @@ class BackendClient:
|
|
|
952
959
|
co_ token. Best-effort: returns None on any failure so a run without a
|
|
953
960
|
connected GitHub account still proceeds (clone/PR steps just won't auth).
|
|
954
961
|
"""
|
|
962
|
+
import time as _time
|
|
963
|
+
|
|
964
|
+
now = _time.monotonic()
|
|
965
|
+
cached = _GITHUB_TOKEN_CACHE.get(self._token)
|
|
966
|
+
if cached and now < cached[1]:
|
|
967
|
+
return cached[0]
|
|
955
968
|
record = await self.github_token_record()
|
|
956
|
-
|
|
969
|
+
token = (record or {}).get("accessToken") or None
|
|
970
|
+
if token:
|
|
971
|
+
_GITHUB_TOKEN_CACHE[self._token] = (token, now + _GITHUB_TOKEN_TTL_S)
|
|
972
|
+
return token
|
|
957
973
|
|
|
958
|
-
async def ingest_github_prs(self, since: str | None = None) -> dict:
|
|
974
|
+
async def ingest_github_prs(self, since: str | None = None) -> dict | None:
|
|
959
975
|
"""POST {AI}/api/v1/github/prs — trigger this user's daily PR ingestion.
|
|
960
976
|
|
|
961
|
-
The
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
977
|
+
The daily trigger. The work runs on the AI backend (LLM summarise, the
|
|
978
|
+
downstream daily-summary forward, the Qdrant upsert); the SDK only decides
|
|
979
|
+
WHEN, because only this machine knows its own catch-up watermark.
|
|
980
|
+
|
|
981
|
+
The backend resolves the caller's GitHub link server-side from the co_ token
|
|
982
|
+
in ``Authorization`` and OVERWRITES whatever the body sends
|
|
983
|
+
(``docs/GITHUB_SCHEDULING_SDK_MIGRATION.md`` §7/§9 — that endpoint used to
|
|
984
|
+
take a GitHub access token in an unauthenticated body). So this deliberately
|
|
985
|
+
sends NO credentials: a client that still supplied them would be shipping a
|
|
986
|
+
secret the server ignores.
|
|
987
|
+
|
|
988
|
+
``since`` is an ISO date (``YYYY-MM-DD``) → the backend's ``date_from``.
|
|
989
|
+
Omitted means "today", which is what a never-missed run wants; the cron sends
|
|
990
|
+
the watermark instead so a machine that was off does not lose days.
|
|
991
|
+
|
|
992
|
+
Returns the response JSON (``{status, job_id, status_url, ...}``) or **None**
|
|
993
|
+
on any failure — never raises into the cron. WHY it failed lands in
|
|
994
|
+
``self.last_ingest_error`` (``{status, body, retryable}``), which the
|
|
995
|
+
scheduler needs to tell a busy backend (retry in 30 min) from a rejected
|
|
996
|
+
request (wait for the next slot).
|
|
970
997
|
"""
|
|
971
|
-
|
|
998
|
+
payload = [{
|
|
972
999
|
"userId": self._user_id_from_token(),
|
|
973
|
-
"
|
|
974
|
-
"githubAccessToken": "",
|
|
975
|
-
"apiTokenHash": self._token,
|
|
976
|
-
"date_from": since,
|
|
1000
|
+
"apiTokenHash": self._token, # downstream daily-summary Authorization
|
|
977
1001
|
}]
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
1002
|
+
if since:
|
|
1003
|
+
payload[0]["date_from"] = since
|
|
1004
|
+
self.last_ingest_error = {}
|
|
1005
|
+
try:
|
|
1006
|
+
async with httpx.AsyncClient(timeout=60.0) as client:
|
|
1007
|
+
resp = await client.post(
|
|
1008
|
+
self._url("/api/v1/github/prs"), json=payload, headers=self._headers,
|
|
1009
|
+
)
|
|
1010
|
+
if resp.status_code >= 400:
|
|
1011
|
+
body = resp.text[:500]
|
|
1012
|
+
logger.warning("client.ingest_github_prs failed status=%s body=%s",
|
|
1013
|
+
resp.status_code, body[:200])
|
|
1014
|
+
self.last_ingest_error = {
|
|
1015
|
+
"status": resp.status_code,
|
|
1016
|
+
"body": body,
|
|
1017
|
+
"retryable": is_retryable_backend_error(resp.status_code, body),
|
|
1018
|
+
}
|
|
1019
|
+
return None
|
|
1020
|
+
return resp.json()
|
|
1021
|
+
except Exception as exc: # noqa: BLE001 — a cron must not die on a blip
|
|
1022
|
+
logger.warning("client.ingest_github_prs error err=%s", exc)
|
|
1023
|
+
# A transport failure (timeout, reset, DNS blip) is as retryable as an
|
|
1024
|
+
# exhausted pool — the backend may simply be busy.
|
|
1025
|
+
self.last_ingest_error = {"status": 0, "body": str(exc)[:500], "retryable": True}
|
|
1026
|
+
return None
|
|
1027
|
+
|
|
1028
|
+
async def ingest_github_prs_raw(self, prs: list[dict],
|
|
1029
|
+
since: str | None = None) -> dict | None:
|
|
1030
|
+
"""POST {AI}/api/v1/github/prs/raw — PRs THIS machine already fetched.
|
|
984
1031
|
|
|
985
|
-
|
|
986
|
-
|
|
1032
|
+
The counterpart to :meth:`ingest_github_prs`. That one asks the backend to
|
|
1033
|
+
fetch with a GitHub token the platform has to hold; this one sends records
|
|
1034
|
+
`sdk.github_fetch` produced with the developer's own `gh`, so no GitHub
|
|
1035
|
+
credential exists on the platform at all, the request runs under that
|
|
1036
|
+
developer's own rate limit, and their private repos resolve.
|
|
987
1037
|
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
1038
|
+
Only PR DATA travels. The backend resolves the GitHub username and user id
|
|
1039
|
+
from the ``co_`` token server-side and files the records under those, so this
|
|
1040
|
+
cannot be used to attribute PRs to anyone else.
|
|
1041
|
+
|
|
1042
|
+
Same contract as `ingest_github_prs`: the response JSON on success,
|
|
1043
|
+
**None** on any failure, with the reason in ``self.last_ingest_error``.
|
|
993
1044
|
"""
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
|
|
1045
|
+
self.last_ingest_error = {}
|
|
1046
|
+
body: dict = {"prs": prs}
|
|
1047
|
+
if since:
|
|
1048
|
+
body["date_from"] = since
|
|
1049
|
+
try:
|
|
1050
|
+
async with httpx.AsyncClient(timeout=120.0) as client:
|
|
1051
|
+
resp = await client.post(
|
|
1052
|
+
self._url("/api/v1/github/prs/raw"), json=body, headers=self._headers,
|
|
1053
|
+
)
|
|
1054
|
+
if resp.status_code >= 400:
|
|
1055
|
+
detail = resp.text[:500]
|
|
1056
|
+
logger.warning("client.ingest_github_prs_raw failed status=%s body=%s",
|
|
1057
|
+
resp.status_code, detail[:200])
|
|
1058
|
+
self.last_ingest_error = {
|
|
1059
|
+
"status": resp.status_code,
|
|
1060
|
+
"body": detail,
|
|
1061
|
+
"retryable": is_retryable_backend_error(resp.status_code, detail),
|
|
1062
|
+
}
|
|
1063
|
+
return None
|
|
1064
|
+
return resp.json()
|
|
1065
|
+
except Exception as exc: # noqa: BLE001 — a cron must not die on a blip
|
|
1066
|
+
logger.warning("client.ingest_github_prs_raw error err=%s", exc)
|
|
1067
|
+
self.last_ingest_error = {"status": 0, "body": str(exc)[:500], "retryable": True}
|
|
1068
|
+
return None
|
|
1000
1069
|
|
|
1001
1070
|
async def move_to_backlog(self, task_id: str) -> bool:
|
|
1002
1071
|
"""PUT {BE}/tasks-ml/{id} status=backlog (best-effort).
|
|
@@ -192,7 +192,15 @@ def _dotenv_value(key: str) -> str:
|
|
|
192
192
|
# backend can reach EVERY VPS's /api/ui/* out of the box (no per-VPS .env needed);
|
|
193
193
|
# always allowed, treated as permanent (not removable via the API). Extend/override
|
|
194
194
|
# with AGENTOS_UI_ALLOWED_IPS in .env or the process env.
|
|
195
|
-
|
|
195
|
+
#
|
|
196
|
+
# A LIST, not one value, because the backend's egress address is not stable: when it
|
|
197
|
+
# moved to 20.127.87.169 every VPS silently stopped answering `GET /api/v1/vps/health`
|
|
198
|
+
# (30s hang, then 502 — the SYNs were dropped at the host firewall, observed
|
|
199
|
+
# 2026-09-03). Both addresses stay listed rather than swapping, so a rollback or a
|
|
200
|
+
# blue/green pair does not re-break it. Note the host firewall is a SEPARATE layer this
|
|
201
|
+
# list cannot reach: `sudo ufw allow from <ip> to any port 8765 proto tcp` is still
|
|
202
|
+
# required per VPS. See docs/VPS_HEALTH_AND_GITHUB_INGEST_DIAGNOSIS.md #5.
|
|
203
|
+
_DEFAULT_ALLOWED_IPS: list[str] = ["20.12.201.148", "20.127.87.169"]
|
|
196
204
|
|
|
197
205
|
|
|
198
206
|
def _parse_token_list(raw: str) -> list[str]:
|