devops-bot-sdk 1.6.62__tar.gz → 1.6.66__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.62 → devops_bot_sdk-1.6.66}/PKG-INFO +1 -1
- {devops_bot_sdk-1.6.62 → devops_bot_sdk-1.6.66}/devops_bot_sdk.egg-info/PKG-INFO +1 -1
- {devops_bot_sdk-1.6.62 → devops_bot_sdk-1.6.66}/devops_bot_sdk.egg-info/SOURCES.txt +2 -0
- {devops_bot_sdk-1.6.62 → devops_bot_sdk-1.6.66}/sdk/__init__.py +2 -2
- {devops_bot_sdk-1.6.62 → devops_bot_sdk-1.6.66}/sdk/activity/models.py +52 -0
- {devops_bot_sdk-1.6.62 → devops_bot_sdk-1.6.66}/sdk/activity/redact.py +4 -1
- {devops_bot_sdk-1.6.62 → devops_bot_sdk-1.6.66}/sdk/activity/shipper.py +28 -8
- {devops_bot_sdk-1.6.62 → devops_bot_sdk-1.6.66}/sdk/activity/spool.py +19 -5
- {devops_bot_sdk-1.6.62 → devops_bot_sdk-1.6.66}/sdk/cli.py +344 -33
- {devops_bot_sdk-1.6.62 → devops_bot_sdk-1.6.66}/sdk/client.py +131 -10
- devops_bot_sdk-1.6.66/sdk/custom_agents.py +507 -0
- {devops_bot_sdk-1.6.62 → devops_bot_sdk-1.6.66}/sdk/tickets.py +81 -48
- {devops_bot_sdk-1.6.62 → devops_bot_sdk-1.6.66}/sdk/ui/api.py +84 -0
- {devops_bot_sdk-1.6.62 → devops_bot_sdk-1.6.66}/sdk/ui/models.py +35 -0
- {devops_bot_sdk-1.6.62 → devops_bot_sdk-1.6.66}/sdk/ui/static/app.js +223 -4
- devops_bot_sdk-1.6.66/sdk/ui/static/custom-agents.html +152 -0
- {devops_bot_sdk-1.6.62 → devops_bot_sdk-1.6.66}/sdk/ui/static/styles.css +10 -0
- {devops_bot_sdk-1.6.62 → devops_bot_sdk-1.6.66}/tests/test_activity_core.py +1 -1
- {devops_bot_sdk-1.6.62 → devops_bot_sdk-1.6.66}/tests/test_activity_pipeline.py +61 -0
- devops_bot_sdk-1.6.66/tests/test_agent_crud_cli.py +740 -0
- {devops_bot_sdk-1.6.62 → devops_bot_sdk-1.6.66}/tests/test_ticket_cli.py +138 -57
- devops_bot_sdk-1.6.62/sdk/ui/static/custom-agents.html +0 -84
- {devops_bot_sdk-1.6.62 → devops_bot_sdk-1.6.66}/README.md +0 -0
- {devops_bot_sdk-1.6.62 → devops_bot_sdk-1.6.66}/devops_bot_sdk.egg-info/dependency_links.txt +0 -0
- {devops_bot_sdk-1.6.62 → devops_bot_sdk-1.6.66}/devops_bot_sdk.egg-info/entry_points.txt +0 -0
- {devops_bot_sdk-1.6.62 → devops_bot_sdk-1.6.66}/devops_bot_sdk.egg-info/requires.txt +0 -0
- {devops_bot_sdk-1.6.62 → devops_bot_sdk-1.6.66}/devops_bot_sdk.egg-info/top_level.txt +0 -0
- {devops_bot_sdk-1.6.62 → devops_bot_sdk-1.6.66}/pyproject.toml +0 -0
- {devops_bot_sdk-1.6.62 → devops_bot_sdk-1.6.66}/sdk/activity/__init__.py +0 -0
- {devops_bot_sdk-1.6.62 → devops_bot_sdk-1.6.66}/sdk/activity/classifier.py +0 -0
- {devops_bot_sdk-1.6.62 → devops_bot_sdk-1.6.66}/sdk/activity/collectors/__init__.py +0 -0
- {devops_bot_sdk-1.6.62 → devops_bot_sdk-1.6.66}/sdk/activity/collectors/common.py +0 -0
- {devops_bot_sdk-1.6.62 → devops_bot_sdk-1.6.66}/sdk/activity/collectors/linux_auditd.py +0 -0
- {devops_bot_sdk-1.6.62 → devops_bot_sdk-1.6.66}/sdk/activity/collectors/macos_eslogger.py +0 -0
- {devops_bot_sdk-1.6.62 → devops_bot_sdk-1.6.66}/sdk/activity/collectors/windows_eventlog.py +0 -0
- {devops_bot_sdk-1.6.62 → devops_bot_sdk-1.6.66}/sdk/activity/os_setup.py +0 -0
- {devops_bot_sdk-1.6.62 → devops_bot_sdk-1.6.66}/sdk/activity/recorder.py +0 -0
- {devops_bot_sdk-1.6.62 → devops_bot_sdk-1.6.66}/sdk/activity/settings.py +0 -0
- {devops_bot_sdk-1.6.62 → devops_bot_sdk-1.6.66}/sdk/agentd.py +0 -0
- {devops_bot_sdk-1.6.62 → devops_bot_sdk-1.6.66}/sdk/agents/__init__.py +0 -0
- {devops_bot_sdk-1.6.62 → devops_bot_sdk-1.6.66}/sdk/agents/activity.py +0 -0
- {devops_bot_sdk-1.6.62 → devops_bot_sdk-1.6.66}/sdk/agents/builder.py +0 -0
- {devops_bot_sdk-1.6.62 → devops_bot_sdk-1.6.66}/sdk/agents/chat.py +0 -0
- {devops_bot_sdk-1.6.62 → devops_bot_sdk-1.6.66}/sdk/agents/connectors.py +0 -0
- {devops_bot_sdk-1.6.62 → devops_bot_sdk-1.6.66}/sdk/agents/engines/__init__.py +0 -0
- {devops_bot_sdk-1.6.62 → devops_bot_sdk-1.6.66}/sdk/agents/engines/claude_code.py +0 -0
- {devops_bot_sdk-1.6.62 → devops_bot_sdk-1.6.66}/sdk/agents/engines/http.py +0 -0
- {devops_bot_sdk-1.6.62 → devops_bot_sdk-1.6.66}/sdk/agents/engines/mcp.py +0 -0
- {devops_bot_sdk-1.6.62 → devops_bot_sdk-1.6.66}/sdk/agents/engines/n8n.py +0 -0
- {devops_bot_sdk-1.6.62 → devops_bot_sdk-1.6.66}/sdk/agents/engines/shell.py +0 -0
- {devops_bot_sdk-1.6.62 → devops_bot_sdk-1.6.66}/sdk/agents/integrations.py +0 -0
- {devops_bot_sdk-1.6.62 → devops_bot_sdk-1.6.66}/sdk/agents/inventory.py +0 -0
- {devops_bot_sdk-1.6.62 → devops_bot_sdk-1.6.66}/sdk/agents/library/__init__.py +0 -0
- {devops_bot_sdk-1.6.62 → devops_bot_sdk-1.6.66}/sdk/agents/manifest.py +0 -0
- {devops_bot_sdk-1.6.62 → devops_bot_sdk-1.6.66}/sdk/agents/prompt_studio.py +0 -0
- {devops_bot_sdk-1.6.62 → devops_bot_sdk-1.6.66}/sdk/agents/prompt_template.py +0 -0
- {devops_bot_sdk-1.6.62 → devops_bot_sdk-1.6.66}/sdk/agents/prompt_vars.py +0 -0
- {devops_bot_sdk-1.6.62 → devops_bot_sdk-1.6.66}/sdk/agents/run_log.py +0 -0
- {devops_bot_sdk-1.6.62 → devops_bot_sdk-1.6.66}/sdk/agents/schedules.py +0 -0
- {devops_bot_sdk-1.6.62 → devops_bot_sdk-1.6.66}/sdk/agents/secrets.py +0 -0
- {devops_bot_sdk-1.6.62 → devops_bot_sdk-1.6.66}/sdk/agents/ticket_run.py +0 -0
- {devops_bot_sdk-1.6.62 → devops_bot_sdk-1.6.66}/sdk/agents/usage.py +0 -0
- {devops_bot_sdk-1.6.62 → devops_bot_sdk-1.6.66}/sdk/agents/varstore.py +0 -0
- {devops_bot_sdk-1.6.62 → devops_bot_sdk-1.6.66}/sdk/browser_profile.py +0 -0
- {devops_bot_sdk-1.6.62 → devops_bot_sdk-1.6.66}/sdk/collectors/__init__.py +0 -0
- {devops_bot_sdk-1.6.62 → devops_bot_sdk-1.6.66}/sdk/collectors/files.py +0 -0
- {devops_bot_sdk-1.6.62 → devops_bot_sdk-1.6.66}/sdk/collectors/process.py +0 -0
- {devops_bot_sdk-1.6.62 → devops_bot_sdk-1.6.66}/sdk/collectors/screenshot.py +0 -0
- {devops_bot_sdk-1.6.62 → devops_bot_sdk-1.6.66}/sdk/config.py +0 -0
- {devops_bot_sdk-1.6.62 → devops_bot_sdk-1.6.66}/sdk/crucial.py +0 -0
- {devops_bot_sdk-1.6.62 → devops_bot_sdk-1.6.66}/sdk/departments.py +0 -0
- {devops_bot_sdk-1.6.62 → devops_bot_sdk-1.6.66}/sdk/design_verify/__init__.py +0 -0
- {devops_bot_sdk-1.6.62 → devops_bot_sdk-1.6.66}/sdk/design_verify/assets.py +0 -0
- {devops_bot_sdk-1.6.62 → devops_bot_sdk-1.6.66}/sdk/design_verify/bootstrap.py +0 -0
- {devops_bot_sdk-1.6.62 → devops_bot_sdk-1.6.66}/sdk/design_verify/browser.py +0 -0
- {devops_bot_sdk-1.6.62 → devops_bot_sdk-1.6.66}/sdk/design_verify/compare.py +0 -0
- {devops_bot_sdk-1.6.62 → devops_bot_sdk-1.6.66}/sdk/design_verify/loop.py +0 -0
- {devops_bot_sdk-1.6.62 → devops_bot_sdk-1.6.66}/sdk/estimator.py +0 -0
- {devops_bot_sdk-1.6.62 → devops_bot_sdk-1.6.66}/sdk/exceptions.py +0 -0
- {devops_bot_sdk-1.6.62 → devops_bot_sdk-1.6.66}/sdk/firewall.py +0 -0
- {devops_bot_sdk-1.6.62 → devops_bot_sdk-1.6.66}/sdk/formats.py +0 -0
- {devops_bot_sdk-1.6.62 → devops_bot_sdk-1.6.66}/sdk/git_ops.py +0 -0
- {devops_bot_sdk-1.6.62 → devops_bot_sdk-1.6.66}/sdk/github_fetch.py +0 -0
- {devops_bot_sdk-1.6.62 → devops_bot_sdk-1.6.66}/sdk/github_ingest.py +0 -0
- {devops_bot_sdk-1.6.62 → devops_bot_sdk-1.6.66}/sdk/graph_recon.py +0 -0
- {devops_bot_sdk-1.6.62 → devops_bot_sdk-1.6.66}/sdk/graphify.py +0 -0
- {devops_bot_sdk-1.6.62 → devops_bot_sdk-1.6.66}/sdk/hooks/__init__.py +0 -0
- {devops_bot_sdk-1.6.62 → devops_bot_sdk-1.6.66}/sdk/hooks/crucial_guard.py +0 -0
- {devops_bot_sdk-1.6.62 → devops_bot_sdk-1.6.66}/sdk/intake.py +0 -0
- {devops_bot_sdk-1.6.62 → devops_bot_sdk-1.6.66}/sdk/ipc/__init__.py +0 -0
- {devops_bot_sdk-1.6.62 → devops_bot_sdk-1.6.66}/sdk/ipc/electron_bridge.py +0 -0
- {devops_bot_sdk-1.6.62 → devops_bot_sdk-1.6.66}/sdk/ipc/handlers.py +0 -0
- {devops_bot_sdk-1.6.62 → devops_bot_sdk-1.6.66}/sdk/journal.py +0 -0
- {devops_bot_sdk-1.6.62 → devops_bot_sdk-1.6.66}/sdk/local_exec.py +0 -0
- {devops_bot_sdk-1.6.62 → devops_bot_sdk-1.6.66}/sdk/memory_guard.py +0 -0
- {devops_bot_sdk-1.6.62 → devops_bot_sdk-1.6.66}/sdk/models/__init__.py +0 -0
- {devops_bot_sdk-1.6.62 → devops_bot_sdk-1.6.66}/sdk/models/envelope.py +0 -0
- {devops_bot_sdk-1.6.62 → devops_bot_sdk-1.6.66}/sdk/models/requests.py +0 -0
- {devops_bot_sdk-1.6.62 → devops_bot_sdk-1.6.66}/sdk/models/responses.py +0 -0
- {devops_bot_sdk-1.6.62 → devops_bot_sdk-1.6.66}/sdk/models/snapshots.py +0 -0
- {devops_bot_sdk-1.6.62 → devops_bot_sdk-1.6.66}/sdk/phase_timer.py +0 -0
- {devops_bot_sdk-1.6.62 → devops_bot_sdk-1.6.66}/sdk/plan_run.py +0 -0
- {devops_bot_sdk-1.6.62 → devops_bot_sdk-1.6.66}/sdk/platform_compat.py +0 -0
- {devops_bot_sdk-1.6.62 → devops_bot_sdk-1.6.66}/sdk/prd_progress.py +0 -0
- {devops_bot_sdk-1.6.62 → devops_bot_sdk-1.6.66}/sdk/proof_readers.py +0 -0
- {devops_bot_sdk-1.6.62 → devops_bot_sdk-1.6.66}/sdk/providers.py +0 -0
- {devops_bot_sdk-1.6.62 → devops_bot_sdk-1.6.66}/sdk/py.typed +0 -0
- {devops_bot_sdk-1.6.62 → devops_bot_sdk-1.6.66}/sdk/resume.py +0 -0
- {devops_bot_sdk-1.6.62 → devops_bot_sdk-1.6.66}/sdk/router.py +0 -0
- {devops_bot_sdk-1.6.62 → devops_bot_sdk-1.6.66}/sdk/run_auto.py +0 -0
- {devops_bot_sdk-1.6.62 → devops_bot_sdk-1.6.66}/sdk/scheduler.py +0 -0
- {devops_bot_sdk-1.6.62 → devops_bot_sdk-1.6.66}/sdk/self_report.py +0 -0
- {devops_bot_sdk-1.6.62 → devops_bot_sdk-1.6.66}/sdk/self_report_local.py +0 -0
- {devops_bot_sdk-1.6.62 → devops_bot_sdk-1.6.66}/sdk/sse.py +0 -0
- {devops_bot_sdk-1.6.62 → devops_bot_sdk-1.6.66}/sdk/swagger.py +0 -0
- {devops_bot_sdk-1.6.62 → devops_bot_sdk-1.6.66}/sdk/task_file.py +0 -0
- {devops_bot_sdk-1.6.62 → devops_bot_sdk-1.6.66}/sdk/task_types.py +0 -0
- {devops_bot_sdk-1.6.62 → devops_bot_sdk-1.6.66}/sdk/test.py +0 -0
- {devops_bot_sdk-1.6.62 → devops_bot_sdk-1.6.66}/sdk/test_pipeline.py +0 -0
- {devops_bot_sdk-1.6.62 → devops_bot_sdk-1.6.66}/sdk/ticket_fields.py +0 -0
- {devops_bot_sdk-1.6.62 → devops_bot_sdk-1.6.66}/sdk/tiers/__init__.py +0 -0
- {devops_bot_sdk-1.6.62 → devops_bot_sdk-1.6.66}/sdk/tiers/mini_agent.py +0 -0
- {devops_bot_sdk-1.6.62 → devops_bot_sdk-1.6.66}/sdk/ui/__init__.py +0 -0
- {devops_bot_sdk-1.6.62 → devops_bot_sdk-1.6.66}/sdk/ui/dashboard.py +0 -0
- {devops_bot_sdk-1.6.62 → devops_bot_sdk-1.6.66}/sdk/ui/health.py +0 -0
- {devops_bot_sdk-1.6.62 → devops_bot_sdk-1.6.66}/sdk/ui/ip_allowlist.py +0 -0
- {devops_bot_sdk-1.6.62 → devops_bot_sdk-1.6.66}/sdk/ui/jobs.py +0 -0
- {devops_bot_sdk-1.6.62 → devops_bot_sdk-1.6.66}/sdk/ui/runner.py +0 -0
- {devops_bot_sdk-1.6.62 → devops_bot_sdk-1.6.66}/sdk/ui/security.py +0 -0
- {devops_bot_sdk-1.6.62 → devops_bot_sdk-1.6.66}/sdk/ui/server.py +0 -0
- {devops_bot_sdk-1.6.62 → devops_bot_sdk-1.6.66}/sdk/ui/service.py +0 -0
- {devops_bot_sdk-1.6.62 → devops_bot_sdk-1.6.66}/sdk/ui/session.py +0 -0
- {devops_bot_sdk-1.6.62 → devops_bot_sdk-1.6.66}/sdk/ui/setup_manager.py +0 -0
- {devops_bot_sdk-1.6.62 → devops_bot_sdk-1.6.66}/sdk/ui/static/agents.html +0 -0
- {devops_bot_sdk-1.6.62 → devops_bot_sdk-1.6.66}/sdk/ui/static/chat.html +0 -0
- {devops_bot_sdk-1.6.62 → devops_bot_sdk-1.6.66}/sdk/ui/static/default-agents.html +0 -0
- {devops_bot_sdk-1.6.62 → devops_bot_sdk-1.6.66}/sdk/ui/static/index.html +0 -0
- {devops_bot_sdk-1.6.62 → devops_bot_sdk-1.6.66}/sdk/ui/static/report.html +0 -0
- {devops_bot_sdk-1.6.62 → devops_bot_sdk-1.6.66}/sdk/ui/static/runs.html +0 -0
- {devops_bot_sdk-1.6.62 → devops_bot_sdk-1.6.66}/sdk/ui/static/schedules.html +0 -0
- {devops_bot_sdk-1.6.62 → devops_bot_sdk-1.6.66}/sdk/ui/static/setup.html +0 -0
- {devops_bot_sdk-1.6.62 → devops_bot_sdk-1.6.66}/sdk/ui/static/tickets.html +0 -0
- {devops_bot_sdk-1.6.62 → devops_bot_sdk-1.6.66}/sdk/ui/swagger.py +0 -0
- {devops_bot_sdk-1.6.62 → devops_bot_sdk-1.6.66}/sdk/updater.py +0 -0
- {devops_bot_sdk-1.6.62 → devops_bot_sdk-1.6.66}/sdk/url_access.py +0 -0
- {devops_bot_sdk-1.6.62 → devops_bot_sdk-1.6.66}/sdk/vendor/aidraftsman-cli-0.1.0.tgz +0 -0
- {devops_bot_sdk-1.6.62 → devops_bot_sdk-1.6.66}/sdk/vps_health.py +0 -0
- {devops_bot_sdk-1.6.62 → devops_bot_sdk-1.6.66}/sdk/write_hook.py +0 -0
- {devops_bot_sdk-1.6.62 → devops_bot_sdk-1.6.66}/setup.cfg +0 -0
- {devops_bot_sdk-1.6.62 → devops_bot_sdk-1.6.66}/tests/test_activity_collectors.py +0 -0
- {devops_bot_sdk-1.6.62 → devops_bot_sdk-1.6.66}/tests/test_activity_macos.py +0 -0
- {devops_bot_sdk-1.6.62 → devops_bot_sdk-1.6.66}/tests/test_activity_os_setup.py +0 -0
- {devops_bot_sdk-1.6.62 → devops_bot_sdk-1.6.66}/tests/test_agent_activity.py +0 -0
- {devops_bot_sdk-1.6.62 → devops_bot_sdk-1.6.66}/tests/test_agent_activity_tracking.py +0 -0
- {devops_bot_sdk-1.6.62 → devops_bot_sdk-1.6.66}/tests/test_agent_chat_features.py +0 -0
- {devops_bot_sdk-1.6.62 → devops_bot_sdk-1.6.66}/tests/test_agent_listing.py +0 -0
- {devops_bot_sdk-1.6.62 → devops_bot_sdk-1.6.66}/tests/test_agent_prompt_async.py +0 -0
- {devops_bot_sdk-1.6.62 → devops_bot_sdk-1.6.66}/tests/test_agent_prompt_models.py +0 -0
- {devops_bot_sdk-1.6.62 → devops_bot_sdk-1.6.66}/tests/test_agent_run_ticket.py +0 -0
- {devops_bot_sdk-1.6.62 → devops_bot_sdk-1.6.66}/tests/test_agent_schedules.py +0 -0
- {devops_bot_sdk-1.6.62 → devops_bot_sdk-1.6.66}/tests/test_agent_workspace_settings.py +0 -0
- {devops_bot_sdk-1.6.62 → devops_bot_sdk-1.6.66}/tests/test_agents_connectors_builder.py +0 -0
- {devops_bot_sdk-1.6.62 → devops_bot_sdk-1.6.66}/tests/test_allowed_tools_config.py +0 -0
- {devops_bot_sdk-1.6.62 → devops_bot_sdk-1.6.66}/tests/test_auto_agent_dispatch.py +0 -0
- {devops_bot_sdk-1.6.62 → devops_bot_sdk-1.6.66}/tests/test_browser_profile.py +0 -0
- {devops_bot_sdk-1.6.62 → devops_bot_sdk-1.6.66}/tests/test_cheap_tier.py +0 -0
- {devops_bot_sdk-1.6.62 → devops_bot_sdk-1.6.66}/tests/test_client_jira_projects.py +0 -0
- {devops_bot_sdk-1.6.62 → devops_bot_sdk-1.6.66}/tests/test_config_token_diagnostics.py +0 -0
- {devops_bot_sdk-1.6.62 → devops_bot_sdk-1.6.66}/tests/test_configure_token_owner.py +0 -0
- {devops_bot_sdk-1.6.62 → devops_bot_sdk-1.6.66}/tests/test_console_encoding.py +0 -0
- {devops_bot_sdk-1.6.62 → devops_bot_sdk-1.6.66}/tests/test_crash_recovery.py +0 -0
- {devops_bot_sdk-1.6.62 → devops_bot_sdk-1.6.66}/tests/test_departments.py +0 -0
- {devops_bot_sdk-1.6.62 → devops_bot_sdk-1.6.66}/tests/test_done_transition.py +0 -0
- {devops_bot_sdk-1.6.62 → devops_bot_sdk-1.6.66}/tests/test_epic_decompose_run.py +0 -0
- {devops_bot_sdk-1.6.62 → devops_bot_sdk-1.6.66}/tests/test_epic_inherited_agent_id.py +0 -0
- {devops_bot_sdk-1.6.62 → devops_bot_sdk-1.6.66}/tests/test_epic_session_isolation.py +0 -0
- {devops_bot_sdk-1.6.62 → devops_bot_sdk-1.6.66}/tests/test_estimator.py +0 -0
- {devops_bot_sdk-1.6.62 → devops_bot_sdk-1.6.66}/tests/test_fallback_cli.py +0 -0
- {devops_bot_sdk-1.6.62 → devops_bot_sdk-1.6.66}/tests/test_firewall_open_on_update.py +0 -0
- {devops_bot_sdk-1.6.62 → devops_bot_sdk-1.6.66}/tests/test_formats.py +0 -0
- {devops_bot_sdk-1.6.62 → devops_bot_sdk-1.6.66}/tests/test_git_action.py +0 -0
- {devops_bot_sdk-1.6.62 → devops_bot_sdk-1.6.66}/tests/test_github_fetch.py +0 -0
- {devops_bot_sdk-1.6.62 → devops_bot_sdk-1.6.66}/tests/test_github_ingest.py +0 -0
- {devops_bot_sdk-1.6.62 → devops_bot_sdk-1.6.66}/tests/test_graph_recon.py +0 -0
- {devops_bot_sdk-1.6.62 → devops_bot_sdk-1.6.66}/tests/test_graphify_build.py +0 -0
- {devops_bot_sdk-1.6.62 → devops_bot_sdk-1.6.66}/tests/test_graphify_hook_install.py +0 -0
- {devops_bot_sdk-1.6.62 → devops_bot_sdk-1.6.66}/tests/test_health.py +0 -0
- {devops_bot_sdk-1.6.62 → devops_bot_sdk-1.6.66}/tests/test_intake_job_outcome.py +0 -0
- {devops_bot_sdk-1.6.62 → devops_bot_sdk-1.6.66}/tests/test_intake_plan_review.py +0 -0
- {devops_bot_sdk-1.6.62 → devops_bot_sdk-1.6.66}/tests/test_journal.py +0 -0
- {devops_bot_sdk-1.6.62 → devops_bot_sdk-1.6.66}/tests/test_local_exec_provider.py +0 -0
- {devops_bot_sdk-1.6.62 → devops_bot_sdk-1.6.66}/tests/test_mcp_route_contract.py +0 -0
- {devops_bot_sdk-1.6.62 → devops_bot_sdk-1.6.66}/tests/test_memory_guard.py +0 -0
- {devops_bot_sdk-1.6.62 → devops_bot_sdk-1.6.66}/tests/test_phase_timer.py +0 -0
- {devops_bot_sdk-1.6.62 → devops_bot_sdk-1.6.66}/tests/test_plan_new_command.py +0 -0
- {devops_bot_sdk-1.6.62 → devops_bot_sdk-1.6.66}/tests/test_plan_run_activity.py +0 -0
- {devops_bot_sdk-1.6.62 → devops_bot_sdk-1.6.66}/tests/test_pr_identity.py +0 -0
- {devops_bot_sdk-1.6.62 → devops_bot_sdk-1.6.66}/tests/test_prd_artifact.py +0 -0
- {devops_bot_sdk-1.6.62 → devops_bot_sdk-1.6.66}/tests/test_project_path_resolution.py +0 -0
- {devops_bot_sdk-1.6.62 → devops_bot_sdk-1.6.66}/tests/test_proof_readers.py +0 -0
- {devops_bot_sdk-1.6.62 → devops_bot_sdk-1.6.66}/tests/test_providers.py +0 -0
- {devops_bot_sdk-1.6.62 → devops_bot_sdk-1.6.66}/tests/test_recon_session_isolation.py +0 -0
- {devops_bot_sdk-1.6.62 → devops_bot_sdk-1.6.66}/tests/test_resume.py +0 -0
- {devops_bot_sdk-1.6.62 → devops_bot_sdk-1.6.66}/tests/test_router.py +0 -0
- {devops_bot_sdk-1.6.62 → devops_bot_sdk-1.6.66}/tests/test_run_auto_agent_only.py +0 -0
- {devops_bot_sdk-1.6.62 → devops_bot_sdk-1.6.66}/tests/test_run_outputs.py +0 -0
- {devops_bot_sdk-1.6.62 → devops_bot_sdk-1.6.66}/tests/test_run_verdict_is_honest.py +0 -0
- {devops_bot_sdk-1.6.62 → devops_bot_sdk-1.6.66}/tests/test_schedule_api.py +0 -0
- {devops_bot_sdk-1.6.62 → devops_bot_sdk-1.6.66}/tests/test_schedule_outputs_and_plans.py +0 -0
- {devops_bot_sdk-1.6.62 → devops_bot_sdk-1.6.66}/tests/test_scheduler.py +0 -0
- {devops_bot_sdk-1.6.62 → devops_bot_sdk-1.6.66}/tests/test_self_report.py +0 -0
- {devops_bot_sdk-1.6.62 → devops_bot_sdk-1.6.66}/tests/test_service_token_warning.py +0 -0
- {devops_bot_sdk-1.6.62 → devops_bot_sdk-1.6.66}/tests/test_stale_panel_restart.py +0 -0
- {devops_bot_sdk-1.6.62 → devops_bot_sdk-1.6.66}/tests/test_swagger_command.py +0 -0
- {devops_bot_sdk-1.6.62 → devops_bot_sdk-1.6.66}/tests/test_task_file_and_plan_run.py +0 -0
- {devops_bot_sdk-1.6.62 → devops_bot_sdk-1.6.66}/tests/test_task_file_format_doc.py +0 -0
- {devops_bot_sdk-1.6.62 → devops_bot_sdk-1.6.66}/tests/test_ticket_fields.py +0 -0
- {devops_bot_sdk-1.6.62 → devops_bot_sdk-1.6.66}/tests/test_ticket_run_resolve_by_id.py +0 -0
- {devops_bot_sdk-1.6.62 → devops_bot_sdk-1.6.66}/tests/test_ticket_speed_fixes.py +0 -0
- {devops_bot_sdk-1.6.62 → devops_bot_sdk-1.6.66}/tests/test_tier_flag_parity.py +0 -0
- {devops_bot_sdk-1.6.62 → devops_bot_sdk-1.6.66}/tests/test_ui_gate.py +0 -0
- {devops_bot_sdk-1.6.62 → devops_bot_sdk-1.6.66}/tests/test_ui_lifespan.py +0 -0
- {devops_bot_sdk-1.6.62 → devops_bot_sdk-1.6.66}/tests/test_update_timer.py +0 -0
- {devops_bot_sdk-1.6.62 → devops_bot_sdk-1.6.66}/tests/test_updater_extras.py +0 -0
- {devops_bot_sdk-1.6.62 → devops_bot_sdk-1.6.66}/tests/test_updater_pep668.py +0 -0
- {devops_bot_sdk-1.6.62 → devops_bot_sdk-1.6.66}/tests/test_updater_reports_the_truth.py +0 -0
- {devops_bot_sdk-1.6.62 → devops_bot_sdk-1.6.66}/tests/test_url_access.py +0 -0
- {devops_bot_sdk-1.6.62 → devops_bot_sdk-1.6.66}/tests/test_vps_health.py +0 -0
- {devops_bot_sdk-1.6.62 → devops_bot_sdk-1.6.66}/tests/test_windows_loop_identity.py +0 -0
- {devops_bot_sdk-1.6.62 → devops_bot_sdk-1.6.66}/tests/test_write_hook.py +0 -0
|
@@ -13,6 +13,7 @@ sdk/cli.py
|
|
|
13
13
|
sdk/client.py
|
|
14
14
|
sdk/config.py
|
|
15
15
|
sdk/crucial.py
|
|
16
|
+
sdk/custom_agents.py
|
|
16
17
|
sdk/departments.py
|
|
17
18
|
sdk/estimator.py
|
|
18
19
|
sdk/exceptions.py
|
|
@@ -147,6 +148,7 @@ tests/test_activity_pipeline.py
|
|
|
147
148
|
tests/test_agent_activity.py
|
|
148
149
|
tests/test_agent_activity_tracking.py
|
|
149
150
|
tests/test_agent_chat_features.py
|
|
151
|
+
tests/test_agent_crud_cli.py
|
|
150
152
|
tests/test_agent_listing.py
|
|
151
153
|
tests/test_agent_prompt_async.py
|
|
152
154
|
tests/test_agent_prompt_models.py
|
|
@@ -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.66
|
|
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.66" # 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
|
|
@@ -16,6 +16,7 @@ retried at any hop is stored once.
|
|
|
16
16
|
"""
|
|
17
17
|
from __future__ import annotations
|
|
18
18
|
|
|
19
|
+
import json
|
|
19
20
|
import os
|
|
20
21
|
import sys
|
|
21
22
|
import time
|
|
@@ -140,6 +141,57 @@ def _wire(obj: Any) -> dict[str, Any]:
|
|
|
140
141
|
return out
|
|
141
142
|
|
|
142
143
|
|
|
144
|
+
#: String caps the relay validates (devops-bot-ai ``modules/vps_activity/schemas.py``).
|
|
145
|
+
#: A value over its cap is a 422, and the shipper drops a row the relay refuses — so
|
|
146
|
+
#: one over-long path or command line used to cost the whole event. Clamp instead.
|
|
147
|
+
WIRE_MAX_CHARS: dict[str, dict[str, int]] = {
|
|
148
|
+
"event": {
|
|
149
|
+
"action": 100,
|
|
150
|
+
"osUser": 255,
|
|
151
|
+
"processName": 255,
|
|
152
|
+
"command": 20_000,
|
|
153
|
+
"target": 4096,
|
|
154
|
+
"agentRunId": 128,
|
|
155
|
+
"sessionKey": 128,
|
|
156
|
+
},
|
|
157
|
+
"session": {
|
|
158
|
+
"osUser": 255,
|
|
159
|
+
"remoteIp": 45,
|
|
160
|
+
"agentRunId": 128,
|
|
161
|
+
"initiatedByKey": 128,
|
|
162
|
+
},
|
|
163
|
+
}
|
|
164
|
+
_CLAMP_MARK = "…"
|
|
165
|
+
#: Free-form dicts the relay does not cap. Bounded here so that, with the string caps
|
|
166
|
+
#: above, no single row can outgrow a request (2 MB gzipped / 10 MB raw) — a row that
|
|
167
|
+
#: could would be 413'd on its own and dropped.
|
|
168
|
+
WIRE_DICT_FIELDS = ("metadata", "actorReasons")
|
|
169
|
+
MAX_DICT_FIELD_BYTES = 64 * 1024
|
|
170
|
+
|
|
171
|
+
|
|
172
|
+
def fit_wire_limits(kind: str, wire: dict[str, Any]) -> dict[str, Any]:
|
|
173
|
+
"""``wire`` with every over-long field shortened to fit the relay's limits."""
|
|
174
|
+
out = wire
|
|
175
|
+
|
|
176
|
+
def _set(name: str, value: Any) -> None:
|
|
177
|
+
nonlocal out
|
|
178
|
+
if out is wire:
|
|
179
|
+
out = dict(wire)
|
|
180
|
+
out[name] = value
|
|
181
|
+
|
|
182
|
+
for name, cap in WIRE_MAX_CHARS.get(kind, {}).items():
|
|
183
|
+
value = wire.get(name)
|
|
184
|
+
if isinstance(value, str) and len(value) > cap:
|
|
185
|
+
_set(name, value[: cap - len(_CLAMP_MARK)] + _CLAMP_MARK)
|
|
186
|
+
for name in WIRE_DICT_FIELDS:
|
|
187
|
+
value = wire.get(name)
|
|
188
|
+
if isinstance(value, dict):
|
|
189
|
+
size = len(json.dumps(value, separators=(",", ":"), default=str))
|
|
190
|
+
if size > MAX_DICT_FIELD_BYTES:
|
|
191
|
+
_set(name, {"truncated": True, "originalBytes": size})
|
|
192
|
+
return out
|
|
193
|
+
|
|
194
|
+
|
|
143
195
|
# ── models ───────────────────────────────────────────────────────────────────
|
|
144
196
|
|
|
145
197
|
|
|
@@ -72,6 +72,7 @@ _PATTERNS: list[tuple[re.Pattern[str], str]] = [
|
|
|
72
72
|
|
|
73
73
|
#: Hard cap so a pathological command line can't bloat the spool.
|
|
74
74
|
MAX_COMMAND_CHARS = 20_000
|
|
75
|
+
TRUNCATED = "…[truncated]"
|
|
75
76
|
|
|
76
77
|
|
|
77
78
|
def redact_command(command: str | None) -> str | None:
|
|
@@ -82,5 +83,7 @@ def redact_command(command: str | None) -> str | None:
|
|
|
82
83
|
for pattern, repl in _PATTERNS:
|
|
83
84
|
out = pattern.sub(repl, out)
|
|
84
85
|
if len(out) > MAX_COMMAND_CHARS:
|
|
85
|
-
|
|
86
|
+
# The marker counts toward the cap: the relay 422s anything longer, and the
|
|
87
|
+
# shipper drops a refused event rather than shipping it truncated.
|
|
88
|
+
out = out[: MAX_COMMAND_CHARS - len(TRUNCATED)] + TRUNCATED
|
|
86
89
|
return out
|
|
@@ -7,8 +7,9 @@ Delivery rules — a row leaves the spool ONLY when the relay answered 202 (or i
|
|
|
7
7
|
provably undeliverable):
|
|
8
8
|
|
|
9
9
|
2xx delivered → delete the chunk
|
|
10
|
-
network error, 5xx, 408
|
|
10
|
+
network error, 5xx, 408 retry (short backoff); if still failing, keep
|
|
11
11
|
everything and try again at the next flush
|
|
12
|
+
429 wait out the relay's 60 s window, then retry
|
|
12
13
|
401, 426 token / SDK version needs an operator → keep, stop
|
|
13
14
|
this flush (retrying in a tight loop helps nobody)
|
|
14
15
|
any other 4xx the relay READ the chunk and refused it. Dropping all
|
|
@@ -16,8 +17,9 @@ provably undeliverable):
|
|
|
16
17
|
so the chunk is BISECTED until the offending row is
|
|
17
18
|
isolated; only that single row is dropped.
|
|
18
19
|
|
|
19
|
-
A flush drains the whole spool, chunk by chunk (≤500 events / ≤
|
|
20
|
-
five minutes of full OS auditing is
|
|
20
|
+
A flush drains the whole spool, chunk by chunk (≤500 events / ≤4 MB each), paced under
|
|
21
|
+
the relay's 60-requests-a-minute budget, because five minutes of full OS auditing is
|
|
22
|
+
routinely thousands of events.
|
|
21
23
|
"""
|
|
22
24
|
from __future__ import annotations
|
|
23
25
|
|
|
@@ -36,9 +38,18 @@ logger = logging.getLogger("sdk.activity.shipper")
|
|
|
36
38
|
RETRY_DELAYS_S = (2.0, 8.0)
|
|
37
39
|
#: Safety cap on chunks per flush so one flush can't run away.
|
|
38
40
|
MAX_CHUNKS_PER_FLUSH = 200
|
|
41
|
+
#: The relay allows 60 batches per minute per token. Firing chunks back-to-back blew
|
|
42
|
+
#: through that after ~60 chunks; the 2 s / 8 s retries cannot outlast a 60 s window,
|
|
43
|
+
#: so the flush gave up and a busy host never caught up. Pace below the budget...
|
|
44
|
+
MIN_POST_GAP_S = 1.1
|
|
45
|
+
#: ...and if a 429 still lands (another process on the same token), wait the window
|
|
46
|
+
#: out rather than abandoning the flush.
|
|
47
|
+
RATE_LIMIT_WAIT_S = 61.0
|
|
48
|
+
MAX_RATE_LIMIT_WAITS = 3
|
|
39
49
|
|
|
40
50
|
_NEEDS_OPERATOR = {401, 426}
|
|
41
51
|
_TRANSIENT_4XX = {408, 429}
|
|
52
|
+
_RATE_LIMITED = 429
|
|
42
53
|
|
|
43
54
|
Sleep = Callable[[float], Awaitable[Any]]
|
|
44
55
|
|
|
@@ -73,20 +84,27 @@ def _verdict(status: int | None) -> str:
|
|
|
73
84
|
|
|
74
85
|
async def _attempt(sender: Sender, chunk: Chunk, sleep: Sleep) -> str:
|
|
75
86
|
"""One chunk with short in-flush retries → ``ok`` / ``drop`` / ``stop`` / ``later``."""
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
87
|
+
retry_delays = list(RETRY_DELAYS_S)
|
|
88
|
+
rate_limit_waits = 0
|
|
89
|
+
while True:
|
|
79
90
|
try:
|
|
80
91
|
status: int | None = await sender.post_vps_activity_batch(chunk.to_wire())
|
|
81
92
|
except Exception as exc: # noqa: BLE001 — httpx errors, DNS, TLS, ...
|
|
82
93
|
logger.warning("activity: ship failed (%s); will retry", exc)
|
|
83
94
|
status = None
|
|
95
|
+
if status == _RATE_LIMITED and rate_limit_waits < MAX_RATE_LIMIT_WAITS:
|
|
96
|
+
rate_limit_waits += 1
|
|
97
|
+
logger.info("activity: relay rate-limited; waiting %.0fs", RATE_LIMIT_WAIT_S)
|
|
98
|
+
await sleep(RATE_LIMIT_WAIT_S)
|
|
99
|
+
continue
|
|
84
100
|
verdict = _verdict(status)
|
|
85
101
|
if verdict != "retry":
|
|
86
102
|
if verdict == "stop":
|
|
87
103
|
logger.warning("activity: relay answered %s — needs operator attention", status)
|
|
88
104
|
return verdict
|
|
89
|
-
|
|
105
|
+
if not retry_delays:
|
|
106
|
+
return "later"
|
|
107
|
+
await sleep(retry_delays.pop(0))
|
|
90
108
|
|
|
91
109
|
|
|
92
110
|
async def _deliver(
|
|
@@ -135,10 +153,12 @@ async def flush_once(
|
|
|
135
153
|
from sdk.client import BackendClient
|
|
136
154
|
|
|
137
155
|
sender = BackendClient.from_config()
|
|
138
|
-
for
|
|
156
|
+
for i in range(max_chunks):
|
|
139
157
|
chunk = spool.next_chunk()
|
|
140
158
|
if not chunk:
|
|
141
159
|
break
|
|
160
|
+
if i:
|
|
161
|
+
await sleep(MIN_POST_GAP_S)
|
|
142
162
|
if not await _deliver(spool, sender, chunk, result, sleep):
|
|
143
163
|
break
|
|
144
164
|
else:
|
|
@@ -23,14 +23,21 @@ from dataclasses import dataclass, field
|
|
|
23
23
|
from pathlib import Path
|
|
24
24
|
from typing import Any
|
|
25
25
|
|
|
26
|
+
from sdk.activity.models import fit_wire_limits
|
|
27
|
+
|
|
26
28
|
logger = logging.getLogger("sdk.activity.spool")
|
|
27
29
|
|
|
28
30
|
#: Rows kept at most. ~200k events is days of a busy host; beyond it, shed oldest.
|
|
29
31
|
DEFAULT_MAX_ROWS = 200_000
|
|
30
|
-
#: Wire limits per request — the relay and the gateway enforce the same cap.
|
|
32
|
+
#: Wire limits per request — the relay and the gateway enforce the same row cap.
|
|
31
33
|
MAX_EVENTS_PER_CHUNK = 500
|
|
32
34
|
MAX_SESSIONS_PER_CHUNK = 500
|
|
33
|
-
|
|
35
|
+
#: Uncompressed JSON per request. The relay takes 10 MB decompressed / 2 MB gzipped;
|
|
36
|
+
#: audit JSON gzips well past 2:1, so 4 MB stays under both. A 1 MB cap meant a host
|
|
37
|
+
#: with long command lines sent small chunks, ran into the relay's per-minute request
|
|
38
|
+
#: budget and fell behind until the spool shed its oldest rows. A chunk that still
|
|
39
|
+
#: comes back 413 is bisected by the shipper, so this is a target, not a cliff.
|
|
40
|
+
MAX_CHUNK_BYTES = 4_000_000
|
|
34
41
|
|
|
35
42
|
_SCHEMA = """
|
|
36
43
|
CREATE TABLE IF NOT EXISTS spool (
|
|
@@ -110,7 +117,10 @@ class Spool:
|
|
|
110
117
|
with self._lock:
|
|
111
118
|
self._db.execute(
|
|
112
119
|
"INSERT OR IGNORE INTO spool (kind, key, payload) VALUES ('event', ?, ?)",
|
|
113
|
-
(
|
|
120
|
+
(
|
|
121
|
+
wire["eventId"],
|
|
122
|
+
json.dumps(fit_wire_limits("event", wire), separators=(",", ":")),
|
|
123
|
+
),
|
|
114
124
|
)
|
|
115
125
|
self._trim()
|
|
116
126
|
|
|
@@ -127,7 +137,10 @@ class Spool:
|
|
|
127
137
|
"INSERT INTO spool (kind, key, payload) VALUES ('session', ?, ?) "
|
|
128
138
|
"ON CONFLICT (kind, key) DO UPDATE SET "
|
|
129
139
|
"payload = excluded.payload, rev = rev + 1",
|
|
130
|
-
(
|
|
140
|
+
(
|
|
141
|
+
wire["externalKey"],
|
|
142
|
+
json.dumps(fit_wire_limits("session", wire), separators=(",", ":")),
|
|
143
|
+
),
|
|
131
144
|
)
|
|
132
145
|
self._trim()
|
|
133
146
|
|
|
@@ -176,7 +189,8 @@ class Spool:
|
|
|
176
189
|
break
|
|
177
190
|
if chunk.rows and size + len(payload) > max_bytes:
|
|
178
191
|
break
|
|
179
|
-
|
|
192
|
+
# Re-fit on the way out too: rows queued by an older SDK predate the clamp.
|
|
193
|
+
chunk.rows.append(Row(seq, rev, kind, fit_wire_limits(kind, json.loads(payload))))
|
|
180
194
|
n_events += kind == "event"
|
|
181
195
|
n_sessions += kind == "session"
|
|
182
196
|
size += len(payload)
|