devops-bot-sdk 1.6.93__tar.gz → 1.7.6__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.93 → devops_bot_sdk-1.7.6}/PKG-INFO +1 -1
- {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.6}/devops_bot_sdk.egg-info/PKG-INFO +1 -1
- {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.6}/devops_bot_sdk.egg-info/SOURCES.txt +14 -0
- {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.6}/sdk/__init__.py +2 -2
- {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.6}/sdk/activity/collectors/windows_eventlog.py +36 -3
- devops_bot_sdk-1.7.6/sdk/agent_sharing.py +138 -0
- {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.6}/sdk/agents/chat.py +16 -5
- {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.6}/sdk/cli.py +320 -13
- {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.6}/sdk/client.py +90 -0
- devops_bot_sdk-1.7.6/sdk/deferred_tickets.py +113 -0
- devops_bot_sdk-1.7.6/sdk/help_actions.py +265 -0
- {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.6}/sdk/helpdesk.py +108 -21
- {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.6}/sdk/helpdesk_kb.md +84 -2
- {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.6}/sdk/ipc/handlers.py +816 -604
- {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.6}/sdk/local_exec.py +12 -2
- devops_bot_sdk-1.7.6/sdk/log_colors.py +92 -0
- devops_bot_sdk-1.7.6/sdk/model_policy.py +172 -0
- {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.6}/sdk/run_auto.py +120 -19
- {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.6}/sdk/schedule_tickets.py +2 -0
- {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.6}/sdk/scheduler.py +3 -0
- devops_bot_sdk-1.7.6/sdk/ticket_board.py +104 -0
- {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.6}/sdk/tickets.py +81 -4
- {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.6}/sdk/ui/api.py +172 -9
- {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.6}/sdk/ui/dashboard.py +15 -2
- {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.6}/sdk/ui/models.py +13 -0
- {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.6}/sdk/ui/runner.py +1 -0
- {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.6}/sdk/ui/static/app.js +552 -91
- {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.6}/sdk/ui/static/custom-agents.html +41 -0
- devops_bot_sdk-1.7.6/sdk/ui/static/index.html +70 -0
- devops_bot_sdk-1.7.6/sdk/ui/static/schedules.html +163 -0
- {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.6}/sdk/ui/static/styles.css +338 -45
- {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.6}/sdk/ui/static/tickets.html +1 -0
- {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.6}/tests/test_activity_collectors.py +27 -0
- {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.6}/tests/test_agent_crud_cli.py +31 -0
- {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.6}/tests/test_agent_listing.py +89 -1
- devops_bot_sdk-1.7.6/tests/test_agent_sharing.py +199 -0
- {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.6}/tests/test_crash_recovery.py +1 -1
- devops_bot_sdk-1.7.6/tests/test_deferred_tickets.py +157 -0
- {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.6}/tests/test_done_transition.py +71 -0
- devops_bot_sdk-1.7.6/tests/test_help_actions.py +113 -0
- devops_bot_sdk-1.7.6/tests/test_help_questions.py +71 -0
- {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.6}/tests/test_helpdesk.py +8 -9
- {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.6}/tests/test_local_exec_provider.py +34 -0
- devops_bot_sdk-1.7.6/tests/test_log_colors_backlog.py +91 -0
- devops_bot_sdk-1.7.6/tests/test_model_policy.py +100 -0
- {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.6}/tests/test_panel_help.py +1 -1
- devops_bot_sdk-1.7.6/tests/test_parallel_tickets.py +259 -0
- {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.6}/tests/test_plan_new_command.py +7 -3
- {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.6}/tests/test_task_file_format_doc.py +13 -8
- devops_bot_sdk-1.7.6/tests/test_ticket_board.py +80 -0
- {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.6}/tests/test_ticket_cli.py +94 -4
- {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.6}/tests/test_ticket_schedule_and_agent.py +1 -1
- {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.6}/tests/test_ticket_speed_fixes.py +3 -2
- {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.6}/tests/test_tier_flag_parity.py +2 -2
- devops_bot_sdk-1.6.93/sdk/ui/static/index.html +0 -68
- devops_bot_sdk-1.6.93/sdk/ui/static/schedules.html +0 -160
- {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.6}/README.md +0 -0
- {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.6}/devops_bot_sdk.egg-info/dependency_links.txt +0 -0
- {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.6}/devops_bot_sdk.egg-info/entry_points.txt +0 -0
- {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.6}/devops_bot_sdk.egg-info/requires.txt +0 -0
- {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.6}/devops_bot_sdk.egg-info/top_level.txt +0 -0
- {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.6}/pyproject.toml +0 -0
- {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.6}/sdk/activity/__init__.py +0 -0
- {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.6}/sdk/activity/classifier.py +0 -0
- {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.6}/sdk/activity/collectors/__init__.py +0 -0
- {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.6}/sdk/activity/collectors/common.py +0 -0
- {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.6}/sdk/activity/collectors/linux_auditd.py +0 -0
- {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.6}/sdk/activity/collectors/macos_eslogger.py +0 -0
- {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.6}/sdk/activity/models.py +0 -0
- {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.6}/sdk/activity/os_setup.py +0 -0
- {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.6}/sdk/activity/recorder.py +0 -0
- {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.6}/sdk/activity/redact.py +0 -0
- {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.6}/sdk/activity/settings.py +0 -0
- {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.6}/sdk/activity/shipper.py +0 -0
- {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.6}/sdk/activity/spool.py +0 -0
- {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.6}/sdk/agentd.py +0 -0
- {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.6}/sdk/agents/__init__.py +0 -0
- {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.6}/sdk/agents/activity.py +0 -0
- {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.6}/sdk/agents/builder.py +0 -0
- {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.6}/sdk/agents/connectors.py +0 -0
- {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.6}/sdk/agents/engines/__init__.py +0 -0
- {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.6}/sdk/agents/engines/claude_code.py +0 -0
- {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.6}/sdk/agents/engines/http.py +0 -0
- {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.6}/sdk/agents/engines/mcp.py +0 -0
- {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.6}/sdk/agents/engines/n8n.py +0 -0
- {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.6}/sdk/agents/engines/shell.py +0 -0
- {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.6}/sdk/agents/integrations.py +0 -0
- {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.6}/sdk/agents/inventory.py +0 -0
- {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.6}/sdk/agents/library/__init__.py +0 -0
- {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.6}/sdk/agents/manifest.py +0 -0
- {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.6}/sdk/agents/prompt_studio.py +0 -0
- {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.6}/sdk/agents/prompt_template.py +0 -0
- {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.6}/sdk/agents/prompt_vars.py +0 -0
- {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.6}/sdk/agents/run_log.py +0 -0
- {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.6}/sdk/agents/schedules.py +0 -0
- {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.6}/sdk/agents/secrets.py +0 -0
- {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.6}/sdk/agents/ticket_run.py +0 -0
- {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.6}/sdk/agents/usage.py +0 -0
- {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.6}/sdk/agents/varstore.py +0 -0
- {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.6}/sdk/browser_profile.py +0 -0
- {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.6}/sdk/claude_usage.py +0 -0
- {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.6}/sdk/collectors/__init__.py +0 -0
- {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.6}/sdk/collectors/files.py +0 -0
- {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.6}/sdk/collectors/process.py +0 -0
- {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.6}/sdk/collectors/screenshot.py +0 -0
- {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.6}/sdk/config.py +0 -0
- {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.6}/sdk/crucial.py +0 -0
- {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.6}/sdk/custom_agents.py +0 -0
- {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.6}/sdk/departments.py +0 -0
- {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.6}/sdk/design_verify/__init__.py +0 -0
- {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.6}/sdk/design_verify/assets.py +0 -0
- {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.6}/sdk/design_verify/bootstrap.py +0 -0
- {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.6}/sdk/design_verify/browser.py +0 -0
- {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.6}/sdk/design_verify/compare.py +0 -0
- {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.6}/sdk/design_verify/loop.py +0 -0
- {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.6}/sdk/estimator.py +0 -0
- {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.6}/sdk/exceptions.py +0 -0
- {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.6}/sdk/fallback_handoff.py +0 -0
- {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.6}/sdk/firewall.py +0 -0
- {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.6}/sdk/formats.py +0 -0
- {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.6}/sdk/git_ops.py +0 -0
- {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.6}/sdk/github_fetch.py +0 -0
- {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.6}/sdk/github_ingest.py +0 -0
- {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.6}/sdk/graph_recon.py +0 -0
- {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.6}/sdk/graphify.py +0 -0
- {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.6}/sdk/hooks/__init__.py +0 -0
- {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.6}/sdk/hooks/crucial_guard.py +0 -0
- {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.6}/sdk/intake.py +0 -0
- {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.6}/sdk/ipc/__init__.py +0 -0
- {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.6}/sdk/ipc/electron_bridge.py +0 -0
- {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.6}/sdk/journal.py +0 -0
- {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.6}/sdk/memory_guard.py +0 -0
- {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.6}/sdk/models/__init__.py +0 -0
- {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.6}/sdk/models/envelope.py +0 -0
- {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.6}/sdk/models/requests.py +0 -0
- {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.6}/sdk/models/responses.py +0 -0
- {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.6}/sdk/models/snapshots.py +0 -0
- {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.6}/sdk/phase_timer.py +0 -0
- {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.6}/sdk/plan_run.py +0 -0
- {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.6}/sdk/platform_compat.py +0 -0
- {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.6}/sdk/prd_progress.py +0 -0
- {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.6}/sdk/proof_readers.py +0 -0
- {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.6}/sdk/providers.py +0 -0
- {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.6}/sdk/py.typed +0 -0
- {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.6}/sdk/resume.py +0 -0
- {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.6}/sdk/router.py +0 -0
- {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.6}/sdk/self_report.py +0 -0
- {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.6}/sdk/self_report_local.py +0 -0
- {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.6}/sdk/sse.py +0 -0
- {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.6}/sdk/swagger.py +0 -0
- {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.6}/sdk/task_file.py +0 -0
- {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.6}/sdk/task_types.py +0 -0
- {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.6}/sdk/test.py +0 -0
- {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.6}/sdk/test_pipeline.py +0 -0
- {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.6}/sdk/ticket_fields.py +0 -0
- {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.6}/sdk/tiers/__init__.py +0 -0
- {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.6}/sdk/tiers/mini_agent.py +0 -0
- {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.6}/sdk/ui/__init__.py +0 -0
- {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.6}/sdk/ui/health.py +0 -0
- {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.6}/sdk/ui/ip_allowlist.py +0 -0
- {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.6}/sdk/ui/jobs.py +0 -0
- {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.6}/sdk/ui/security.py +0 -0
- {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.6}/sdk/ui/server.py +0 -0
- {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.6}/sdk/ui/service.py +0 -0
- {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.6}/sdk/ui/session.py +0 -0
- {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.6}/sdk/ui/setup_manager.py +0 -0
- {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.6}/sdk/ui/static/agents.html +0 -0
- {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.6}/sdk/ui/static/chat.html +0 -0
- {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.6}/sdk/ui/static/default-agents.html +0 -0
- {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.6}/sdk/ui/static/help.html +0 -0
- {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.6}/sdk/ui/static/report.html +0 -0
- {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.6}/sdk/ui/static/runs.html +0 -0
- {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.6}/sdk/ui/static/setup.html +0 -0
- {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.6}/sdk/ui/swagger.py +0 -0
- {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.6}/sdk/updater.py +0 -0
- {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.6}/sdk/url_access.py +0 -0
- {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.6}/sdk/vps_health.py +0 -0
- {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.6}/sdk/vps_identity.py +0 -0
- {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.6}/sdk/write_hook.py +0 -0
- {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.6}/setup.cfg +0 -0
- {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.6}/tests/test_activity_claude_runs.py +0 -0
- {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.6}/tests/test_activity_core.py +0 -0
- {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.6}/tests/test_activity_live_tracking.py +0 -0
- {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.6}/tests/test_activity_macos.py +0 -0
- {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.6}/tests/test_activity_os_setup.py +0 -0
- {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.6}/tests/test_activity_pipeline.py +0 -0
- {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.6}/tests/test_agent_activity.py +0 -0
- {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.6}/tests/test_agent_activity_tracking.py +0 -0
- {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.6}/tests/test_agent_chat_features.py +0 -0
- {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.6}/tests/test_agent_prompt_async.py +0 -0
- {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.6}/tests/test_agent_prompt_models.py +0 -0
- {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.6}/tests/test_agent_run_ticket.py +0 -0
- {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.6}/tests/test_agent_schedules.py +0 -0
- {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.6}/tests/test_agent_workspace_settings.py +0 -0
- {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.6}/tests/test_agents_connectors_builder.py +0 -0
- {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.6}/tests/test_allowed_tools_config.py +0 -0
- {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.6}/tests/test_approval_park.py +0 -0
- {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.6}/tests/test_auto_agent_dispatch.py +0 -0
- {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.6}/tests/test_auto_ticket_queue.py +0 -0
- {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.6}/tests/test_browser_profile.py +0 -0
- {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.6}/tests/test_cheap_tier.py +0 -0
- {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.6}/tests/test_claude_usage_gate.py +0 -0
- {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.6}/tests/test_client_jira_projects.py +0 -0
- {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.6}/tests/test_config_token_diagnostics.py +0 -0
- {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.6}/tests/test_configure_token_owner.py +0 -0
- {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.6}/tests/test_console_encoding.py +0 -0
- {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.6}/tests/test_create_safe_retry.py +0 -0
- {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.6}/tests/test_departments.py +0 -0
- {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.6}/tests/test_epic_decompose_run.py +0 -0
- {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.6}/tests/test_epic_inherited_agent_id.py +0 -0
- {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.6}/tests/test_epic_session_isolation.py +0 -0
- {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.6}/tests/test_estimator.py +0 -0
- {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.6}/tests/test_fallback_cli.py +0 -0
- {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.6}/tests/test_fallback_cli_upgrade.py +0 -0
- {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.6}/tests/test_firewall_open_on_update.py +0 -0
- {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.6}/tests/test_formats.py +0 -0
- {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.6}/tests/test_git_action.py +0 -0
- {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.6}/tests/test_github_fetch.py +0 -0
- {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.6}/tests/test_github_ingest.py +0 -0
- {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.6}/tests/test_graph_recon.py +0 -0
- {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.6}/tests/test_graphify_build.py +0 -0
- {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.6}/tests/test_graphify_hook_install.py +0 -0
- {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.6}/tests/test_health.py +0 -0
- {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.6}/tests/test_help_attachments.py +0 -0
- {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.6}/tests/test_infographic_data.py +0 -0
- {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.6}/tests/test_intake_job_outcome.py +0 -0
- {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.6}/tests/test_intake_plan_review.py +0 -0
- {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.6}/tests/test_journal.py +0 -0
- {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.6}/tests/test_limit_fallback_handoff.py +0 -0
- {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.6}/tests/test_mcp_route_contract.py +0 -0
- {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.6}/tests/test_memory_guard.py +0 -0
- {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.6}/tests/test_panel_ticket_schedules.py +0 -0
- {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.6}/tests/test_phase_timer.py +0 -0
- {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.6}/tests/test_plan_run_activity.py +0 -0
- {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.6}/tests/test_pr_identity.py +0 -0
- {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.6}/tests/test_prd_artifact.py +0 -0
- {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.6}/tests/test_project_path_resolution.py +0 -0
- {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.6}/tests/test_proof_readers.py +0 -0
- {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.6}/tests/test_providers.py +0 -0
- {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.6}/tests/test_recon_session_isolation.py +0 -0
- {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.6}/tests/test_resume.py +0 -0
- {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.6}/tests/test_router.py +0 -0
- {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.6}/tests/test_run_auto_agent_only.py +0 -0
- {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.6}/tests/test_run_outputs.py +0 -0
- {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.6}/tests/test_run_verdict_is_honest.py +0 -0
- {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.6}/tests/test_schedule_api.py +0 -0
- {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.6}/tests/test_schedule_outputs_and_plans.py +0 -0
- {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.6}/tests/test_schedule_tickets.py +0 -0
- {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.6}/tests/test_scheduler.py +0 -0
- {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.6}/tests/test_scheduler_transient_retry.py +0 -0
- {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.6}/tests/test_self_report.py +0 -0
- {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.6}/tests/test_service_token_warning.py +0 -0
- {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.6}/tests/test_stale_panel_restart.py +0 -0
- {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.6}/tests/test_swagger_command.py +0 -0
- {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.6}/tests/test_task_file_and_plan_run.py +0 -0
- {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.6}/tests/test_ticket_fields.py +0 -0
- {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.6}/tests/test_ticket_run_resolve_by_id.py +0 -0
- {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.6}/tests/test_ui_gate.py +0 -0
- {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.6}/tests/test_ui_lifespan.py +0 -0
- {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.6}/tests/test_update_timer.py +0 -0
- {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.6}/tests/test_updater_extras.py +0 -0
- {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.6}/tests/test_updater_ignores_cwd.py +0 -0
- {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.6}/tests/test_updater_pep668.py +0 -0
- {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.6}/tests/test_updater_reports_the_truth.py +0 -0
- {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.6}/tests/test_url_access.py +0 -0
- {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.6}/tests/test_vps_health.py +0 -0
- {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.6}/tests/test_vps_only_reporting.py +0 -0
- {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.6}/tests/test_windows_loop_identity.py +0 -0
- {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.6}/tests/test_windows_panel_task.py +0 -0
- {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.6}/tests/test_windows_stop_and_pidfile.py +0 -0
- {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.6}/tests/test_windows_task_paths.py +0 -0
- {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.6}/tests/test_write_hook.py +0 -0
|
@@ -7,6 +7,7 @@ devops_bot_sdk.egg-info/entry_points.txt
|
|
|
7
7
|
devops_bot_sdk.egg-info/requires.txt
|
|
8
8
|
devops_bot_sdk.egg-info/top_level.txt
|
|
9
9
|
sdk/__init__.py
|
|
10
|
+
sdk/agent_sharing.py
|
|
10
11
|
sdk/agentd.py
|
|
11
12
|
sdk/browser_profile.py
|
|
12
13
|
sdk/claude_usage.py
|
|
@@ -15,6 +16,7 @@ sdk/client.py
|
|
|
15
16
|
sdk/config.py
|
|
16
17
|
sdk/crucial.py
|
|
17
18
|
sdk/custom_agents.py
|
|
19
|
+
sdk/deferred_tickets.py
|
|
18
20
|
sdk/departments.py
|
|
19
21
|
sdk/estimator.py
|
|
20
22
|
sdk/exceptions.py
|
|
@@ -26,12 +28,15 @@ sdk/github_fetch.py
|
|
|
26
28
|
sdk/github_ingest.py
|
|
27
29
|
sdk/graph_recon.py
|
|
28
30
|
sdk/graphify.py
|
|
31
|
+
sdk/help_actions.py
|
|
29
32
|
sdk/helpdesk.py
|
|
30
33
|
sdk/helpdesk_kb.md
|
|
31
34
|
sdk/intake.py
|
|
32
35
|
sdk/journal.py
|
|
33
36
|
sdk/local_exec.py
|
|
37
|
+
sdk/log_colors.py
|
|
34
38
|
sdk/memory_guard.py
|
|
39
|
+
sdk/model_policy.py
|
|
35
40
|
sdk/phase_timer.py
|
|
36
41
|
sdk/plan_run.py
|
|
37
42
|
sdk/platform_compat.py
|
|
@@ -52,6 +57,7 @@ sdk/task_file.py
|
|
|
52
57
|
sdk/task_types.py
|
|
53
58
|
sdk/test.py
|
|
54
59
|
sdk/test_pipeline.py
|
|
60
|
+
sdk/ticket_board.py
|
|
55
61
|
sdk/ticket_fields.py
|
|
56
62
|
sdk/tickets.py
|
|
57
63
|
sdk/updater.py
|
|
@@ -162,6 +168,7 @@ tests/test_agent_prompt_async.py
|
|
|
162
168
|
tests/test_agent_prompt_models.py
|
|
163
169
|
tests/test_agent_run_ticket.py
|
|
164
170
|
tests/test_agent_schedules.py
|
|
171
|
+
tests/test_agent_sharing.py
|
|
165
172
|
tests/test_agent_workspace_settings.py
|
|
166
173
|
tests/test_agents_connectors_builder.py
|
|
167
174
|
tests/test_allowed_tools_config.py
|
|
@@ -177,6 +184,7 @@ tests/test_configure_token_owner.py
|
|
|
177
184
|
tests/test_console_encoding.py
|
|
178
185
|
tests/test_crash_recovery.py
|
|
179
186
|
tests/test_create_safe_retry.py
|
|
187
|
+
tests/test_deferred_tickets.py
|
|
180
188
|
tests/test_departments.py
|
|
181
189
|
tests/test_done_transition.py
|
|
182
190
|
tests/test_epic_decompose_run.py
|
|
@@ -194,7 +202,9 @@ tests/test_graph_recon.py
|
|
|
194
202
|
tests/test_graphify_build.py
|
|
195
203
|
tests/test_graphify_hook_install.py
|
|
196
204
|
tests/test_health.py
|
|
205
|
+
tests/test_help_actions.py
|
|
197
206
|
tests/test_help_attachments.py
|
|
207
|
+
tests/test_help_questions.py
|
|
198
208
|
tests/test_helpdesk.py
|
|
199
209
|
tests/test_infographic_data.py
|
|
200
210
|
tests/test_intake_job_outcome.py
|
|
@@ -202,10 +212,13 @@ tests/test_intake_plan_review.py
|
|
|
202
212
|
tests/test_journal.py
|
|
203
213
|
tests/test_limit_fallback_handoff.py
|
|
204
214
|
tests/test_local_exec_provider.py
|
|
215
|
+
tests/test_log_colors_backlog.py
|
|
205
216
|
tests/test_mcp_route_contract.py
|
|
206
217
|
tests/test_memory_guard.py
|
|
218
|
+
tests/test_model_policy.py
|
|
207
219
|
tests/test_panel_help.py
|
|
208
220
|
tests/test_panel_ticket_schedules.py
|
|
221
|
+
tests/test_parallel_tickets.py
|
|
209
222
|
tests/test_phase_timer.py
|
|
210
223
|
tests/test_plan_new_command.py
|
|
211
224
|
tests/test_plan_run_activity.py
|
|
@@ -231,6 +244,7 @@ tests/test_stale_panel_restart.py
|
|
|
231
244
|
tests/test_swagger_command.py
|
|
232
245
|
tests/test_task_file_and_plan_run.py
|
|
233
246
|
tests/test_task_file_format_doc.py
|
|
247
|
+
tests/test_ticket_board.py
|
|
234
248
|
tests/test_ticket_cli.py
|
|
235
249
|
tests/test_ticket_fields.py
|
|
236
250
|
tests/test_ticket_run_resolve_by_id.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.7.6
|
|
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.7.6" # 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
|
|
@@ -80,12 +80,45 @@ class WinEvent:
|
|
|
80
80
|
data: dict[str, str]
|
|
81
81
|
|
|
82
82
|
|
|
83
|
+
#: Characters XML 1.0 forbids. ``wevtutil`` writes them unescaped — most often an ESC
|
|
84
|
+
#: from coloured terminal output in a 4688 command line — and expat rejects the whole
|
|
85
|
+
#: document with "not well-formed (invalid token)".
|
|
86
|
+
_XML_INVALID = re.compile(r"[\x00-\x08\x0b\x0c\x0e-\x1f]")
|
|
87
|
+
#: Start of each top-level record; the ``[\s>]`` keeps ``<EventID>`` / ``<EventData>`` out.
|
|
88
|
+
_EVENT_START = re.compile(r"(?=<Event[\s>])")
|
|
89
|
+
|
|
90
|
+
|
|
83
91
|
def parse_events(xml_text: str | None) -> list[WinEvent]:
|
|
84
|
-
"""Parse ``wevtutil qe ... /f:xml`` output (a bare run of ``<Event>`` elements).
|
|
85
|
-
|
|
92
|
+
"""Parse ``wevtutil qe ... /f:xml`` output (a bare run of ``<Event>`` elements).
|
|
93
|
+
|
|
94
|
+
Never lets one bad record poison the batch. The poll loop only advances its
|
|
95
|
+
bookmark past records that parsed, so a batch that failed as a whole was re-read
|
|
96
|
+
and re-failed every poll forever — the machine silently stopped reporting.
|
|
97
|
+
Characters XML forbids are replaced first; if the batch still does not parse,
|
|
98
|
+
each record is parsed on its own and the unparseable ones are skipped.
|
|
99
|
+
"""
|
|
100
|
+
xml_text = _XML_INVALID.sub("�", (xml_text or "").strip())
|
|
86
101
|
if not xml_text:
|
|
87
102
|
return []
|
|
88
|
-
|
|
103
|
+
try:
|
|
104
|
+
return _parse_root(ET.fromstring(f"<Events>{xml_text}</Events>"))
|
|
105
|
+
except ET.ParseError as exc:
|
|
106
|
+
logger.warning("eventlog: batch did not parse (%s); parsing records one by one", exc)
|
|
107
|
+
out: list[WinEvent] = []
|
|
108
|
+
skipped = 0
|
|
109
|
+
for chunk in _EVENT_START.split(xml_text):
|
|
110
|
+
if not chunk.strip():
|
|
111
|
+
continue
|
|
112
|
+
try:
|
|
113
|
+
out.extend(_parse_root(ET.fromstring(f"<Events>{chunk}</Events>")))
|
|
114
|
+
except ET.ParseError:
|
|
115
|
+
skipped += 1
|
|
116
|
+
if skipped:
|
|
117
|
+
logger.warning("eventlog: skipped %d unparseable record(s)", skipped)
|
|
118
|
+
return out
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
def _parse_root(root: ET.Element) -> list[WinEvent]:
|
|
89
122
|
out: list[WinEvent] = []
|
|
90
123
|
for ev in root.iter(f"{_NS}Event"):
|
|
91
124
|
sysnode = ev.find(f"{_NS}System")
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
"""Share your custom agents with a person or a team — they accept before it appears.
|
|
2
|
+
|
|
3
|
+
The one implementation behind ``agentos agent share|shares|accept|decline|unshare``
|
|
4
|
+
and the Custom Agents page. State lives on the AI backend (devops-bot-ai, Mongo
|
|
5
|
+
``agent_shares``); the SDK never stores a share.
|
|
6
|
+
|
|
7
|
+
Lifecycle: the OWNER shares an agent ``--to`` people (email or name) and/or a team
|
|
8
|
+
by name ("AI Team" → one invite per member). Each recipient gets a ``pending``
|
|
9
|
+
invite and ACCEPTS or DECLINES it; only accepted shares show up in their "Shared
|
|
10
|
+
with me" list and become runnable (``sdk.agents.chat.resolve_agent`` reads them).
|
|
11
|
+
It is a live reference, not a copy: the owner's later edits reach recipients, and
|
|
12
|
+
the owner can revoke at any time. Secret NAMES travel with the agent; values never
|
|
13
|
+
do — a recipient stores their own keys (``agentos agent set-key``).
|
|
14
|
+
|
|
15
|
+
Every function returns a dict with ``ok`` and, on failure, ``error``; none raise.
|
|
16
|
+
"""
|
|
17
|
+
from __future__ import annotations
|
|
18
|
+
|
|
19
|
+
from typing import Any
|
|
20
|
+
|
|
21
|
+
_NOT_DEPLOYED = ("agent sharing isn't available on the AI backend yet — it ships with "
|
|
22
|
+
"the devops-bot-ai update; ask your admin to deploy it")
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
def _fail(client, fallback: str) -> dict:
|
|
26
|
+
err = getattr(client, "last_share_error", None) or {}
|
|
27
|
+
status = err.get("statusCode") if isinstance(err, dict) else None
|
|
28
|
+
detail = err.get("detail") if isinstance(err, dict) else None
|
|
29
|
+
if isinstance(detail, dict):
|
|
30
|
+
detail = detail.get("message") or detail.get("detail") or str(detail)
|
|
31
|
+
if detail is None and isinstance(err, dict):
|
|
32
|
+
detail = err.get("error")
|
|
33
|
+
text = str(detail or "").strip()
|
|
34
|
+
# A backend without sharing answers 404, or 405 where an older `/agents/{name}`
|
|
35
|
+
# route swallows the path — FastAPI's own bodies, not a real share error.
|
|
36
|
+
if status in (404, 405) and (not text or text.lower() in ("not found", "method not allowed")):
|
|
37
|
+
return {"ok": False, "error": _NOT_DEPLOYED, "status": status}
|
|
38
|
+
return {"ok": False, "error": text or fallback, "status": status}
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
async def targets(client, q: str = "", kind: str = "all") -> dict:
|
|
42
|
+
"""People, teams and departments (names, emails, member counts) for the picker."""
|
|
43
|
+
res = await client.share_targets(q, kind)
|
|
44
|
+
if res is None:
|
|
45
|
+
return _fail(client, "could not search people, teams and departments")
|
|
46
|
+
return {"ok": True, "people": res.get("people") or [], "teams": res.get("teams") or [],
|
|
47
|
+
"departments": res.get("departments") or []}
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
async def share(client, agent: str, to: list[str], message: str = "") -> dict:
|
|
51
|
+
to = [t.strip() for t in to if t and t.strip()]
|
|
52
|
+
if not to:
|
|
53
|
+
return {"ok": False, "error": "say who to share with: --to \"Name\" or --to \"Team name\""}
|
|
54
|
+
res = await client.share_agent(agent, to, message)
|
|
55
|
+
if res is None:
|
|
56
|
+
return _fail(client, "share failed")
|
|
57
|
+
return {"ok": True, "shared": res.get("shared") or [], "skipped": res.get("skipped") or [],
|
|
58
|
+
"unresolved": res.get("unresolved") or []}
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
async def shares(client, direction: str = "incoming", status: str = "all") -> dict:
|
|
62
|
+
res = await client.list_shares(direction, status)
|
|
63
|
+
if res is None:
|
|
64
|
+
return _fail(client, "could not list shares")
|
|
65
|
+
return {"ok": True, "shares": res.get("shares") or []}
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
async def _resolve_id(client, ref: str, direction: str) -> tuple[str | None, str]:
|
|
69
|
+
"""A share id, or a unique prefix of one (the CLI shows 8 characters)."""
|
|
70
|
+
ref = (ref or "").strip()
|
|
71
|
+
listed = await shares(client, direction, "all")
|
|
72
|
+
if not listed["ok"]:
|
|
73
|
+
return None, listed["error"]
|
|
74
|
+
hits = [s for s in listed["shares"] if str(s.get("id", "")).startswith(ref)]
|
|
75
|
+
if len(hits) == 1:
|
|
76
|
+
return str(hits[0]["id"]), ""
|
|
77
|
+
if not hits:
|
|
78
|
+
return None, f"no share {ref!r} — see `agentos agent shares`"
|
|
79
|
+
return None, f"{ref!r} matches {len(hits)} shares — give more of the id"
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
async def respond(client, ref: str, accept: bool) -> dict:
|
|
83
|
+
"""Accept or decline one incoming invite (``ref`` = id or unique prefix)."""
|
|
84
|
+
share_id, err = await _resolve_id(client, ref, "incoming")
|
|
85
|
+
if not share_id:
|
|
86
|
+
return {"ok": False, "error": err}
|
|
87
|
+
res = await client.respond_share(share_id, "accept" if accept else "decline")
|
|
88
|
+
if res is None:
|
|
89
|
+
return _fail(client, "could not " + ("accept" if accept else "decline"))
|
|
90
|
+
return {"ok": True, "share": res}
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
async def accept_all(client) -> dict:
|
|
94
|
+
pending = await shares(client, "incoming", "pending")
|
|
95
|
+
if not pending["ok"]:
|
|
96
|
+
return pending
|
|
97
|
+
done, failed = [], []
|
|
98
|
+
for s in pending["shares"]:
|
|
99
|
+
res = await client.respond_share(str(s["id"]), "accept")
|
|
100
|
+
(done if res is not None else failed).append(s)
|
|
101
|
+
return {"ok": not failed, "accepted": done, "failed": failed,
|
|
102
|
+
**({"error": f"{len(failed)} could not be accepted"} if failed else {})}
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
async def revoke(client, ref: str) -> dict:
|
|
106
|
+
"""Owner revokes a share they made, or a recipient removes one they hold."""
|
|
107
|
+
share_id, err = await _resolve_id(client, ref, "outgoing")
|
|
108
|
+
if not share_id:
|
|
109
|
+
share_id, err = await _resolve_id(client, ref, "incoming")
|
|
110
|
+
if not share_id:
|
|
111
|
+
return {"ok": False, "error": err}
|
|
112
|
+
res = await client.revoke_share(share_id)
|
|
113
|
+
if res is None:
|
|
114
|
+
return _fail(client, "could not remove the share")
|
|
115
|
+
return {"ok": True, "share": res}
|
|
116
|
+
|
|
117
|
+
|
|
118
|
+
def who(share: dict[str, Any], direction: str) -> str:
|
|
119
|
+
"""The other party of a share, for display."""
|
|
120
|
+
if direction == "incoming":
|
|
121
|
+
name, email = share.get("owner_name"), share.get("owner_email")
|
|
122
|
+
else:
|
|
123
|
+
name, email = share.get("recipient_name"), share.get("recipient_email")
|
|
124
|
+
via = share.get("via_team") or {}
|
|
125
|
+
label = name or email or "?"
|
|
126
|
+
if email and name:
|
|
127
|
+
label = f"{name} <{email}>"
|
|
128
|
+
if not via.get("name"):
|
|
129
|
+
return label
|
|
130
|
+
return label + f" (via {'department' if via.get('kind') == 'department' else 'team'} {via['name']})"
|
|
131
|
+
|
|
132
|
+
|
|
133
|
+
def recipient_label(item: dict[str, Any]) -> str:
|
|
134
|
+
"""A skipped/unresolved row's person by NAME — never the raw record or id."""
|
|
135
|
+
r = item.get("recipient") or {}
|
|
136
|
+
if isinstance(r, dict) and (r.get("name") or r.get("email")):
|
|
137
|
+
return r.get("name") or r.get("email")
|
|
138
|
+
return str(item.get("to") or "?")
|
|
@@ -25,6 +25,7 @@ from sdk.agents.prompt_vars import substitute_variables
|
|
|
25
25
|
from sdk.agents import secrets as agent_secrets
|
|
26
26
|
from sdk.agents import varstore as agent_varstore
|
|
27
27
|
from sdk.agents import run_log
|
|
28
|
+
from sdk.exceptions import BackendFeatureMissing
|
|
28
29
|
|
|
29
30
|
logger = logging.getLogger("sdk.agents.chat")
|
|
30
31
|
|
|
@@ -58,6 +59,8 @@ async def _fetch_rows(fetch) -> list[dict]:
|
|
|
58
59
|
await asyncio.sleep(delay)
|
|
59
60
|
try:
|
|
60
61
|
return await fetch() or []
|
|
62
|
+
except BackendFeatureMissing:
|
|
63
|
+
raise # the endpoint is absent: retrying cannot change that
|
|
61
64
|
except Exception as exc: # noqa: BLE001 — classified by the caller
|
|
62
65
|
last = exc
|
|
63
66
|
assert last is not None
|
|
@@ -129,13 +132,17 @@ async def resolve_agent(name: str, client=None) -> AgentManifest:
|
|
|
129
132
|
reasons: list[str] = []
|
|
130
133
|
unreadable = False
|
|
131
134
|
for label, attr in (("your agents", "list_custom_agents"),
|
|
132
|
-
("department defaults", "list_department_agents")
|
|
135
|
+
("department defaults", "list_department_agents"),
|
|
136
|
+
# Accepted shares (sdk/agent_sharing.py): runnable like your own.
|
|
137
|
+
("agents shared with you", "list_shared_agents")):
|
|
133
138
|
fetch = getattr(client, attr, None)
|
|
134
139
|
if fetch is None:
|
|
135
140
|
continue
|
|
136
141
|
try:
|
|
137
142
|
rows = await _fetch_rows(fetch)
|
|
138
143
|
except Exception as exc: # noqa: BLE001 — a fetch failure is not "not found"
|
|
144
|
+
if attr == "list_shared_agents" and isinstance(exc, BackendFeatureMissing):
|
|
145
|
+
continue # a backend without sharing has none to offer — not "unreadable"
|
|
139
146
|
unreadable = True
|
|
140
147
|
reasons.append(f"{label} could not be fetched ({str(exc) or type(exc).__name__})")
|
|
141
148
|
continue
|
|
@@ -150,7 +157,8 @@ async def resolve_agent(name: str, client=None) -> AgentManifest:
|
|
|
150
157
|
)
|
|
151
158
|
|
|
152
159
|
detail = "; ".join(reasons) if reasons else (
|
|
153
|
-
"not in ~/.agentos/agents/, your backend agents,
|
|
160
|
+
"not in ~/.agentos/agents/, your backend agents, your department defaults, "
|
|
161
|
+
"or agents shared with you"
|
|
154
162
|
)
|
|
155
163
|
if unreadable:
|
|
156
164
|
manifest = await _gateway_manifest(client, name)
|
|
@@ -267,6 +275,7 @@ async def run_agent(
|
|
|
267
275
|
trigger: str = "",
|
|
268
276
|
kind: str = "run",
|
|
269
277
|
client=None,
|
|
278
|
+
extra_env: dict[str, str] | None = None,
|
|
270
279
|
) -> dict:
|
|
271
280
|
"""Run an agent once against its own standing prompt — NOT a chat turn.
|
|
272
281
|
|
|
@@ -285,7 +294,8 @@ async def run_agent(
|
|
|
285
294
|
``trigger`` / ``kind`` are recorded in the run's output file so a reader can
|
|
286
295
|
tell a cron firing from someone pressing Run. ``client`` lets a caller that
|
|
287
296
|
already has a :class:`BackendClient` reuse it instead of having one built per
|
|
288
|
-
run (see :func:`resolve_agent`).
|
|
297
|
+
run (see :func:`resolve_agent`). ``extra_env`` is added to the agent process's
|
|
298
|
+
environment on top of its stored keys (the scheduler marks its runs this way).
|
|
289
299
|
|
|
290
300
|
Returns the engine's normalized result dict. Raises ``ValueError`` if any
|
|
291
301
|
``{{variable}}`` is left unfilled — the UI gates the Run button on this, and
|
|
@@ -324,14 +334,15 @@ async def run_agent(
|
|
|
324
334
|
variables=variables, trigger=trigger,
|
|
325
335
|
)
|
|
326
336
|
teed = _tee_events(log_path, on_event)
|
|
337
|
+
run_env = {**(stored_secrets or {}), **(extra_env or {})} or None
|
|
327
338
|
|
|
328
339
|
if manifest.engine in ("claude_code", "model"):
|
|
329
340
|
result = await claude_code_engine.run(
|
|
330
341
|
turn, skill_text, mcp_config, project_path=project_path,
|
|
331
|
-
on_event=teed, extra_env=
|
|
342
|
+
on_event=teed, extra_env=run_env,
|
|
332
343
|
)
|
|
333
344
|
elif manifest.engine == "shell":
|
|
334
|
-
result = await shell_engine.run(turn, extra_env=
|
|
345
|
+
result = await shell_engine.run(turn, extra_env=run_env)
|
|
335
346
|
else:
|
|
336
347
|
result = {
|
|
337
348
|
"ok": False,
|