alysis-code 0.13.0__py3-none-any.whl
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.
- alysis_code/__init__.py +3 -0
- alysis_code/__main__.py +4 -0
- alysis_code/_build_info.py +14 -0
- alysis_code/account_login.py +468 -0
- alysis_code/agent/README.md +35 -0
- alysis_code/agent/__init__.py +11 -0
- alysis_code/agent/acceptance_contract.py +2217 -0
- alysis_code/agent/blast_radius.py +1403 -0
- alysis_code/agent/cache_keepalive.py +227 -0
- alysis_code/agent/completion_certificate.py +366 -0
- alysis_code/agent/completion_gate.py +306 -0
- alysis_code/agent/empty_response_stall.py +403 -0
- alysis_code/agent/errors.py +28 -0
- alysis_code/agent/llm_calls.py +475 -0
- alysis_code/agent/mutation_classification.py +227 -0
- alysis_code/agent/prompt_context.py +2508 -0
- alysis_code/agent/read_ledger.py +253 -0
- alysis_code/agent/regression_baseline.py +642 -0
- alysis_code/agent/reproduction_first.py +610 -0
- alysis_code/agent/sensitive_output.py +629 -0
- alysis_code/agent/session.py +3218 -0
- alysis_code/agent/steering.py +191 -0
- alysis_code/agent/subagent_execution.py +5177 -0
- alysis_code/agent/subagent_workspace.py +666 -0
- alysis_code/agent/tools_assembly.py +4728 -0
- alysis_code/agent/turn/__init__.py +101 -0
- alysis_code/agent/turn/core.py +8483 -0
- alysis_code/agent/turn/events.py +113 -0
- alysis_code/agent/turn/exploration.py +590 -0
- alysis_code/agent/turn/interventions.py +65 -0
- alysis_code/agent/turn/read_cache.py +420 -0
- alysis_code/agent/turn/snapshot.py +179 -0
- alysis_code/agent/turn_contract.py +661 -0
- alysis_code/agent/turn_path.py +129 -0
- alysis_code/agent/verification.py +2885 -0
- alysis_code/agent/verification_commands.py +512 -0
- alysis_code/agent/verification_evidence.py +738 -0
- alysis_code/agent_loop.py +693 -0
- alysis_code/agent_runtimes/__init__.py +51 -0
- alysis_code/agent_runtimes/base.py +114 -0
- alysis_code/agent_runtimes/builtins.py +129 -0
- alysis_code/agent_runtimes/codex_cli.py +664 -0
- alysis_code/agent_runtimes/host.py +263 -0
- alysis_code/agent_runtimes/registry.py +64 -0
- alysis_code/agent_runtimes/service.py +150 -0
- alysis_code/agentbox_client.py +416 -0
- alysis_code/agentbox_integration.py +310 -0
- alysis_code/alysis_cloud.py +152 -0
- alysis_code/approval_scope.py +276 -0
- alysis_code/assets/README.md +33 -0
- alysis_code/assets/__init__.py +126 -0
- alysis_code/assets/asset_read_core.py +281 -0
- alysis_code/assets/budget_allocator.py +456 -0
- alysis_code/assets/comprehender.py +759 -0
- alysis_code/assets/index.py +654 -0
- alysis_code/assets/ingestion.py +275 -0
- alysis_code/assets/legacy_migration.py +413 -0
- alysis_code/assets/models.py +263 -0
- alysis_code/assets/ocr.py +239 -0
- alysis_code/assets/owl/ascii/f-000.txt +13 -0
- alysis_code/assets/owl/ascii/f-001.txt +13 -0
- alysis_code/assets/owl/ascii/f-002.txt +13 -0
- alysis_code/assets/owl/ascii/f-003.txt +13 -0
- alysis_code/assets/owl/ascii/f-004.txt +13 -0
- alysis_code/assets/owl/ascii/f-005.txt +13 -0
- alysis_code/assets/owl/ascii/f-006.txt +13 -0
- alysis_code/assets/owl/ascii/f-007.txt +13 -0
- alysis_code/assets/owl/ascii/f-008.txt +13 -0
- alysis_code/assets/owl/ascii/f-009.txt +13 -0
- alysis_code/assets/owl/ascii/f-010.txt +13 -0
- alysis_code/assets/owl/ascii/f-011.txt +13 -0
- alysis_code/assets/owl/ascii/f-012.txt +13 -0
- alysis_code/assets/owl/ascii/f-013.txt +13 -0
- alysis_code/assets/owl/ascii/f-014.txt +13 -0
- alysis_code/assets/owl/ascii/f-015.txt +13 -0
- alysis_code/assets/owl/ascii/f-016.txt +13 -0
- alysis_code/assets/owl/ascii/f-017.txt +13 -0
- alysis_code/assets/owl/ascii/f-018.txt +13 -0
- alysis_code/assets/owl/ascii/f-019.txt +13 -0
- alysis_code/assets/owl/ascii/f-020.txt +13 -0
- alysis_code/assets/owl/index.html +98 -0
- alysis_code/assets/owl/show-owl.sh +761 -0
- alysis_code/assets/paths.py +49 -0
- alysis_code/assets/plan_binding.py +326 -0
- alysis_code/assets/planner_context.py +466 -0
- alysis_code/assets/planner_tools.py +184 -0
- alysis_code/assets/prompts.py +101 -0
- alysis_code/assets/replanner_context.py +239 -0
- alysis_code/assets/surface.py +521 -0
- alysis_code/assets/untrusted_content.py +48 -0
- alysis_code/assets/usage_logger.py +94 -0
- alysis_code/assets/worker_mirror.py +428 -0
- alysis_code/assets/worker_section.py +303 -0
- alysis_code/assets/worker_tools.py +468 -0
- alysis_code/atomic_io.py +83 -0
- alysis_code/auth_diagnostics.py +272 -0
- alysis_code/background_runner.py +366 -0
- alysis_code/branding.py +270 -0
- alysis_code/budget_policy.py +390 -0
- alysis_code/build_identity.py +465 -0
- alysis_code/builtin_hooks/__init__.py +7 -0
- alysis_code/builtin_hooks/notify_done_windows.py +65 -0
- alysis_code/bwrap_etc.py +76 -0
- alysis_code/cancellation.py +41 -0
- alysis_code/capabilities.py +137 -0
- alysis_code/chatgpt_codex_static_provider.py +133 -0
- alysis_code/cli.py +51 -0
- alysis_code/cli_impl/__init__.py +1 -0
- alysis_code/cli_impl/assets_cli.py +537 -0
- alysis_code/cli_impl/assets_modal.py +412 -0
- alysis_code/cli_impl/chat/__init__.py +156 -0
- alysis_code/cli_impl/chat/commands.py +2616 -0
- alysis_code/cli_impl/chat/loop.py +4508 -0
- alysis_code/cli_impl/chat/mid_turn_policy.py +125 -0
- alysis_code/cli_impl/chat/rendering.py +444 -0
- alysis_code/cli_impl/chat/state.py +124 -0
- alysis_code/cli_impl/chat_resume.py +830 -0
- alysis_code/cli_impl/chat_slash_completer.py +258 -0
- alysis_code/cli_impl/commands/__init__.py +11 -0
- alysis_code/cli_impl/commands/_shared.py +89 -0
- alysis_code/cli_impl/commands/auth.py +623 -0
- alysis_code/cli_impl/commands/chat_resume_helpers.py +1531 -0
- alysis_code/cli_impl/commands/chat_state.py +158 -0
- alysis_code/cli_impl/commands/chat_status.py +1248 -0
- alysis_code/cli_impl/commands/chat_terminal.py +942 -0
- alysis_code/cli_impl/commands/chat_tui_panels.py +1018 -0
- alysis_code/cli_impl/commands/cli_common.py +1223 -0
- alysis_code/cli_impl/commands/cli_surface.py +77 -0
- alysis_code/cli_impl/commands/config.py +131 -0
- alysis_code/cli_impl/commands/conventions.py +85 -0
- alysis_code/cli_impl/commands/execution_helpers.py +350 -0
- alysis_code/cli_impl/commands/extensions.py +401 -0
- alysis_code/cli_impl/commands/forge.py +1282 -0
- alysis_code/cli_impl/commands/forge_asset_view.py +121 -0
- alysis_code/cli_impl/commands/forge_helpers.py +1215 -0
- alysis_code/cli_impl/commands/hooks.py +737 -0
- alysis_code/cli_impl/commands/ide_bridge.py +31 -0
- alysis_code/cli_impl/commands/mcp.py +700 -0
- alysis_code/cli_impl/commands/profile.py +453 -0
- alysis_code/cli_impl/commands/prompt_helpers.py +307 -0
- alysis_code/cli_impl/commands/report.py +88 -0
- alysis_code/cli_impl/commands/root.py +1118 -0
- alysis_code/cli_impl/commands/sandbox.py +184 -0
- alysis_code/cli_impl/commands/server.py +54 -0
- alysis_code/cli_impl/commands/sessions.py +252 -0
- alysis_code/cli_impl/commands/skills.py +404 -0
- alysis_code/cli_impl/commands/startup.py +946 -0
- alysis_code/cli_impl/commands/tools.py +335 -0
- alysis_code/cli_impl/commands/update.py +364 -0
- alysis_code/cli_impl/commands/welcome.py +972 -0
- alysis_code/cli_impl/config_menu.py +3882 -0
- alysis_code/cli_impl/forge.py +4509 -0
- alysis_code/cli_impl/forge_recovery.py +485 -0
- alysis_code/cli_impl/setup_wizard.py +2409 -0
- alysis_code/cli_impl/tui/__init__.py +58 -0
- alysis_code/cli_impl/tui/app.py +4551 -0
- alysis_code/cli_impl/tui/config.py +32 -0
- alysis_code/cli_impl/tui/config_flow.py +2754 -0
- alysis_code/cli_impl/tui/config_overlay.py +566 -0
- alysis_code/cli_impl/tui/content.py +78 -0
- alysis_code/cli_impl/tui/footer.py +218 -0
- alysis_code/cli_impl/tui/forge_status.py +136 -0
- alysis_code/cli_impl/tui/markdown.py +244 -0
- alysis_code/cli_impl/tui/owl.py +109 -0
- alysis_code/cli_impl/tui/plan_meta.py +477 -0
- alysis_code/cli_impl/tui/setup_app.py +519 -0
- alysis_code/cli_impl/tui/setup_flow.py +1622 -0
- alysis_code/cli_impl/tui/state.py +101 -0
- alysis_code/cli_impl/tui/subagent_identity.py +66 -0
- alysis_code/cli_impl/tui/subagent_panel.py +186 -0
- alysis_code/cli_impl/tui/surface.py +796 -0
- alysis_code/cli_impl/tui/transcript.py +514 -0
- alysis_code/cli_impl/tui/update_prompt.py +79 -0
- alysis_code/cli_impl/tui/workspace_guard.py +384 -0
- alysis_code/clipboard.py +172 -0
- alysis_code/code_review.py +1211 -0
- alysis_code/compaction/__init__.py +28 -0
- alysis_code/compaction/conversation_compactor.py +2932 -0
- alysis_code/compaction/importance.py +177 -0
- alysis_code/compaction/settings.py +297 -0
- alysis_code/compaction/tool_output_offload.py +447 -0
- alysis_code/config.py +3509 -0
- alysis_code/conflict_auto_resolver.py +895 -0
- alysis_code/context/__init__.py +1 -0
- alysis_code/context/tool_schema_budgeter.py +220 -0
- alysis_code/crash_diagnostics.py +282 -0
- alysis_code/custom_tools/README.md +34 -0
- alysis_code/custom_tools/__init__.py +43 -0
- alysis_code/custom_tools/discovery.py +903 -0
- alysis_code/custom_tools/runtime.py +1516 -0
- alysis_code/custom_tools/session.py +227 -0
- alysis_code/custom_tools/trust.py +232 -0
- alysis_code/diff_paths.py +113 -0
- alysis_code/direction_change.py +293 -0
- alysis_code/dispatch_timing.py +306 -0
- alysis_code/durable_service_manager.py +1236 -0
- alysis_code/edit_discipline.py +659 -0
- alysis_code/error_text.py +73 -0
- alysis_code/execution_budget.py +411 -0
- alysis_code/execution_context.py +915 -0
- alysis_code/execution_deadline.py +1065 -0
- alysis_code/execution_shared.py +1904 -0
- alysis_code/extensions/README.md +30 -0
- alysis_code/extensions/__init__.py +93 -0
- alysis_code/extensions/activation.py +138 -0
- alysis_code/extensions/install.py +1436 -0
- alysis_code/extensions/manifest.py +487 -0
- alysis_code/extensions/models.py +74 -0
- alysis_code/extensions/paths.py +56 -0
- alysis_code/extensions/registry.json +4 -0
- alysis_code/extensions/registry.py +52 -0
- alysis_code/extensions/state.py +83 -0
- alysis_code/extensions/workspace_trust.py +101 -0
- alysis_code/failed_task_evidence.py +369 -0
- alysis_code/failure_category.py +315 -0
- alysis_code/feedback_report.py +1647 -0
- alysis_code/file_classification.py +485 -0
- alysis_code/forge.py +2064 -0
- alysis_code/forge_completion.py +362 -0
- alysis_code/forge_events.py +475 -0
- alysis_code/frontmatter_utils.py +95 -0
- alysis_code/git_evidence.py +1181 -0
- alysis_code/git_ops.py +560 -0
- alysis_code/git_safe.py +62 -0
- alysis_code/git_worktrees.py +190 -0
- alysis_code/hooks/README.md +33 -0
- alysis_code/hooks/__init__.py +67 -0
- alysis_code/hooks/audit.py +171 -0
- alysis_code/hooks/config.py +225 -0
- alysis_code/hooks/dispatcher.py +1110 -0
- alysis_code/hooks/models.py +447 -0
- alysis_code/hooks/trust.py +202 -0
- alysis_code/host_actions.py +543 -0
- alysis_code/host_browser.py +103 -0
- alysis_code/ide/__init__.py +5 -0
- alysis_code/ide/activity_events.py +399 -0
- alysis_code/ide/approvals.py +337 -0
- alysis_code/ide/artifacts.py +153 -0
- alysis_code/ide/browser_egress_proxy.py +1076 -0
- alysis_code/ide/cdp_websocket_transport.py +1192 -0
- alysis_code/ide/change_ledger.py +1721 -0
- alysis_code/ide/context_blocks.py +979 -0
- alysis_code/ide/event_stream.py +531 -0
- alysis_code/ide/forge_protocol.py +3112 -0
- alysis_code/ide/forge_request_ledger.py +737 -0
- alysis_code/ide/health.py +965 -0
- alysis_code/ide/managed_browser.py +2251 -0
- alysis_code/ide/management_protocol.py +3414 -0
- alysis_code/ide/mcp_oauth_coordinator.py +744 -0
- alysis_code/ide/mcp_oauth_lifecycle.py +1504 -0
- alysis_code/ide/prompt_queue.py +1070 -0
- alysis_code/ide/protocol.py +191 -0
- alysis_code/ide/resumable_swarm.py +1543 -0
- alysis_code/ide/session_search.py +295 -0
- alysis_code/ide/stdio_bridge.py +9935 -0
- alysis_code/ide/structured_state.py +1579 -0
- alysis_code/ide/swarm_protocol.py +816 -0
- alysis_code/integration_gate.py +506 -0
- alysis_code/interactive_input_guard.py +39 -0
- alysis_code/interactive_plan_mode.py +26 -0
- alysis_code/internal_artifacts.py +179 -0
- alysis_code/knowledge_base.py +1409 -0
- alysis_code/knowledge_capture.py +1190 -0
- alysis_code/knowledge_librarian.py +605 -0
- alysis_code/language_policy.py +34 -0
- alysis_code/litellm_static_provider.py +535 -0
- alysis_code/llm/__init__.py +1 -0
- alysis_code/llm/anthropic_messages.py +2288 -0
- alysis_code/llm/base.py +71 -0
- alysis_code/llm/cache_capabilities.py +985 -0
- alysis_code/llm/cache_control_blocks.py +244 -0
- alysis_code/llm/cache_policy.py +388 -0
- alysis_code/llm/factory.py +373 -0
- alysis_code/llm/gemini_generate_content.py +2652 -0
- alysis_code/llm/gemini_interactions.py +739 -0
- alysis_code/llm/metadata.py +450 -0
- alysis_code/llm/openai_compat.py +2947 -0
- alysis_code/llm/openai_responses.py +2604 -0
- alysis_code/llm/protocols.py +609 -0
- alysis_code/llm/provider_limits.py +525 -0
- alysis_code/llm/request_plan.py +389 -0
- alysis_code/llm/request_shape.py +238 -0
- alysis_code/llm/streaming.py +108 -0
- alysis_code/llm/temperature_compat.py +78 -0
- alysis_code/llm/types.py +195 -0
- alysis_code/llm/usage_normalization.py +222 -0
- alysis_code/llm_error_display.py +315 -0
- alysis_code/logging_redaction.py +326 -0
- alysis_code/managed_host_deadline.py +196 -0
- alysis_code/mcp/README.md +33 -0
- alysis_code/mcp/__init__.py +24 -0
- alysis_code/mcp/client.py +1137 -0
- alysis_code/mcp/config.py +597 -0
- alysis_code/mcp/errors.py +113 -0
- alysis_code/mcp/forge_scope.py +154 -0
- alysis_code/mcp/jsonrpc.py +214 -0
- alysis_code/mcp/manager.py +2308 -0
- alysis_code/mcp/models.py +666 -0
- alysis_code/mcp/oauth.py +972 -0
- alysis_code/mcp/oauth_runtime.py +310 -0
- alysis_code/mcp/oauth_store.py +276 -0
- alysis_code/mcp/prompts.py +329 -0
- alysis_code/mcp/resources.py +295 -0
- alysis_code/mcp/roots.py +106 -0
- alysis_code/mcp/server_requests.py +75 -0
- alysis_code/mcp/token_store.py +859 -0
- alysis_code/mcp/transport_http.py +1338 -0
- alysis_code/mcp/transport_stdio.py +1267 -0
- alysis_code/mcp/untrusted_content.py +119 -0
- alysis_code/merge_conflict_reviewer.py +729 -0
- alysis_code/model_catalog/__init__.py +1 -0
- alysis_code/model_catalog/chatgpt_codex_subscription_snapshot.json +186 -0
- alysis_code/model_catalog/litellm_model_prices_snapshot.json +44715 -0
- alysis_code/model_catalog/litellm_model_prices_snapshot.meta.json +17 -0
- alysis_code/model_metadata_policy.py +223 -0
- alysis_code/model_metadata_utils.py +103 -0
- alysis_code/model_registry.py +1420 -0
- alysis_code/model_router.py +147 -0
- alysis_code/permission_policy.py +1016 -0
- alysis_code/personas.py +451 -0
- alysis_code/pipeline_facts.py +233 -0
- alysis_code/plan_assistant.py +4763 -0
- alysis_code/plan_mode.py +393 -0
- alysis_code/plan_reconciliation.py +1228 -0
- alysis_code/plan_repair.py +652 -0
- alysis_code/plan_validation.py +1099 -0
- alysis_code/planning_constraints.py +904 -0
- alysis_code/policy.py +95 -0
- alysis_code/preview_server.py +457 -0
- alysis_code/process_reaping.py +566 -0
- alysis_code/profile_presets.py +1834 -0
- alysis_code/profiles.py +666 -0
- alysis_code/provider_auth/__init__.py +29 -0
- alysis_code/provider_auth/base.py +99 -0
- alysis_code/provider_auth/openai_codex.py +951 -0
- alysis_code/provider_auth/registry.py +76 -0
- alysis_code/provider_auth/store.py +125 -0
- alysis_code/provider_diagnostics.py +1209 -0
- alysis_code/provider_model_catalog.py +685 -0
- alysis_code/provider_telemetry.py +1699 -0
- alysis_code/provider_url.py +75 -0
- alysis_code/reasoning_contracts.py +911 -0
- alysis_code/remote_sync.py +350 -0
- alysis_code/replanning.py +1195 -0
- alysis_code/repo_scan.py +1152 -0
- alysis_code/request_estimation.py +296 -0
- alysis_code/review_gate.py +617 -0
- alysis_code/run_lock.py +1141 -0
- alysis_code/run_outcome.py +58 -0
- alysis_code/run_provenance.py +774 -0
- alysis_code/run_state.py +445 -0
- alysis_code/runtime_artifacts.py +116 -0
- alysis_code/runtime_context_features.py +78 -0
- alysis_code/runtime_kind.py +52 -0
- alysis_code/safety/__init__.py +11 -0
- alysis_code/safety/mcp_sanitize.py +29 -0
- alysis_code/safety/safe_http.py +297 -0
- alysis_code/safety/subagent_report.py +184 -0
- alysis_code/sandbox_doctor.py +682 -0
- alysis_code/sandbox_runner.py +1025 -0
- alysis_code/sandbox_settings.py +423 -0
- alysis_code/serialized_paths.py +355 -0
- alysis_code/server/__init__.py +3 -0
- alysis_code/server/app.py +367 -0
- alysis_code/server/auth.py +34 -0
- alysis_code/server/job_config.py +30 -0
- alysis_code/server/settings.py +215 -0
- alysis_code/server/store.py +193 -0
- alysis_code/server/worker_runner.py +657 -0
- alysis_code/service_persistence.py +355 -0
- alysis_code/session_artifacts.py +108 -0
- alysis_code/session_metrics.py +331 -0
- alysis_code/session_store.py +624 -0
- alysis_code/skills/README.md +34 -0
- alysis_code/skills/__init__.py +104 -0
- alysis_code/skills/conventions.py +84 -0
- alysis_code/skills/discovery.py +176 -0
- alysis_code/skills/eval_models.py +232 -0
- alysis_code/skills/eval_runner.py +372 -0
- alysis_code/skills/evals.py +1344 -0
- alysis_code/skills/install.py +293 -0
- alysis_code/skills/loader.py +118 -0
- alysis_code/skills/matching.py +103 -0
- alysis_code/skills/models.py +71 -0
- alysis_code/skills/paths.py +56 -0
- alysis_code/skills/prompting.py +500 -0
- alysis_code/skills/scaffold.py +142 -0
- alysis_code/skills/state.py +441 -0
- alysis_code/skills/transactions.py +125 -0
- alysis_code/skills/validation.py +304 -0
- alysis_code/step_budget.py +238 -0
- alysis_code/subagent_labels.py +49 -0
- alysis_code/subagents.py +1072 -0
- alysis_code/surface/__init__.py +80 -0
- alysis_code/surface/base.py +305 -0
- alysis_code/surface/console.py +387 -0
- alysis_code/surface/events.py +372 -0
- alysis_code/surface/hidden_surface.py +529 -0
- alysis_code/surface/noop_surface.py +219 -0
- alysis_code/surface/rich_surface.py +1555 -0
- alysis_code/surface/styles.py +67 -0
- alysis_code/surface/theme.py +455 -0
- alysis_code/surface/types.py +100 -0
- alysis_code/swarm_backend.py +926 -0
- alysis_code/swarm_orchestrator.py +4020 -0
- alysis_code/swarm_scheduler.py +441 -0
- alysis_code/swarm_trace.py +429 -0
- alysis_code/swarm_worker.py +2119 -0
- alysis_code/swarm_write_guard.py +348 -0
- alysis_code/task_dependencies.py +170 -0
- alysis_code/task_readiness.py +992 -0
- alysis_code/task_scope.py +2148 -0
- alysis_code/terminal_manager.py +762 -0
- alysis_code/terminal_ownership.py +460 -0
- alysis_code/text_normalization.py +30 -0
- alysis_code/token_budget.py +97 -0
- alysis_code/tools/README.md +34 -0
- alysis_code/tools/__init__.py +1 -0
- alysis_code/tools/artifacts.py +127 -0
- alysis_code/tools/availability.py +188 -0
- alysis_code/tools/fs.py +1456 -0
- alysis_code/tools/git.py +461 -0
- alysis_code/tools/history.py +229 -0
- alysis_code/tools/http_timeout.py +78 -0
- alysis_code/tools/image_generation.py +552 -0
- alysis_code/tools/registry.py +2936 -0
- alysis_code/tools/repo_map.py +476 -0
- alysis_code/tools/search.py +563 -0
- alysis_code/tools/shell.py +135 -0
- alysis_code/tools/symbols.py +1350 -0
- alysis_code/tools/test_discovery.py +643 -0
- alysis_code/tools/web.py +482 -0
- alysis_code/tools/web_search.py +2012 -0
- alysis_code/tools/web_search_dashscope.py +557 -0
- alysis_code/tools/web_search_ddgs.py +221 -0
- alysis_code/tools/web_search_provider_adapters.py +1429 -0
- alysis_code/tools/web_search_tavily.py +194 -0
- alysis_code/updates.py +933 -0
- alysis_code/usage_tracker.py +1990 -0
- alysis_code/verification_command_analysis.py +1004 -0
- alysis_code/verification_contract.py +574 -0
- alysis_code/verification_failure_summary.py +273 -0
- alysis_code/verification_repair.py +385 -0
- alysis_code/verify_gate.py +3129 -0
- alysis_code/web_research.py +1872 -0
- alysis_code/web_search_adapters.py +66 -0
- alysis_code/web_search_policy.py +27 -0
- alysis_code/workspace_binding.py +389 -0
- alysis_code/workspace_binding_ui.py +408 -0
- alysis_code/workspace_context.py +273 -0
- alysis_code/workspace_isolation.py +138 -0
- alysis_code/workspace_provisioning.py +455 -0
- alysis_code-0.13.0.dist-info/METADATA +507 -0
- alysis_code-0.13.0.dist-info/RECORD +458 -0
- alysis_code-0.13.0.dist-info/WHEEL +4 -0
- alysis_code-0.13.0.dist-info/entry_points.txt +3 -0
- alysis_code-0.13.0.dist-info/licenses/LICENSE +176 -0
- alysis_code-0.13.0.dist-info/licenses/NOTICE +4 -0
|
@@ -0,0 +1,315 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import re
|
|
4
|
+
from enum import StrEnum
|
|
5
|
+
from typing import Any
|
|
6
|
+
|
|
7
|
+
import httpx
|
|
8
|
+
|
|
9
|
+
from .run_outcome import AGENT_FAILURE_EXIT_CODE, INFRASTRUCTURE_FAILURE_EXIT_CODE
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class FailureCategory(StrEnum):
|
|
13
|
+
INFRA_UNAVAILABLE = "infra_unavailable"
|
|
14
|
+
PROVIDER_UNAVAILABLE = "provider_unavailable"
|
|
15
|
+
PROVIDER_THROTTLED = "provider_throttled"
|
|
16
|
+
PROVIDER_ERROR = "provider_error"
|
|
17
|
+
PLANNER_FAILED = "planner_failed"
|
|
18
|
+
IMPLEMENTATION_FAILED = "implementation_failed"
|
|
19
|
+
VERIFICATION_FAILED = "verification_failed"
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
_THROTTLE_MESSAGE_MARKERS = (
|
|
23
|
+
"too many requests",
|
|
24
|
+
"rate limit",
|
|
25
|
+
"rate-limit",
|
|
26
|
+
"rate_limit",
|
|
27
|
+
"quota",
|
|
28
|
+
"concurrency quota",
|
|
29
|
+
"concurrent request",
|
|
30
|
+
"requests per minute",
|
|
31
|
+
"requests/minute",
|
|
32
|
+
"tokens per minute",
|
|
33
|
+
"tpm",
|
|
34
|
+
"rpm",
|
|
35
|
+
)
|
|
36
|
+
_QUOTA_CONTEXT_MARKERS = (
|
|
37
|
+
"exceeded",
|
|
38
|
+
"exhausted",
|
|
39
|
+
"insufficient",
|
|
40
|
+
"limit",
|
|
41
|
+
"rate",
|
|
42
|
+
"throttle",
|
|
43
|
+
)
|
|
44
|
+
_HTTP_429_RE = re.compile(r"\b(?:status[_ -]?code|http|error)?\s*429\b", re.IGNORECASE)
|
|
45
|
+
_INFRA_UNAVAILABLE_MARKERS = (
|
|
46
|
+
"docker daemon",
|
|
47
|
+
"docker.sock",
|
|
48
|
+
"/var/run/docker.sock",
|
|
49
|
+
"bwrap",
|
|
50
|
+
"bubblewrap",
|
|
51
|
+
"sandbox unavailable",
|
|
52
|
+
"verify sandbox unavailable",
|
|
53
|
+
"no usable backend",
|
|
54
|
+
"unable to launch verify environment",
|
|
55
|
+
)
|
|
56
|
+
_PROVIDER_UNAVAILABLE_MESSAGE_MARKERS = (
|
|
57
|
+
"connection aborted",
|
|
58
|
+
"connection refused",
|
|
59
|
+
"connection reset",
|
|
60
|
+
"connect timeout",
|
|
61
|
+
"connecttimeout",
|
|
62
|
+
"dns",
|
|
63
|
+
"incomplete chunked read",
|
|
64
|
+
"name or service not known",
|
|
65
|
+
"name resolution",
|
|
66
|
+
"network is unreachable",
|
|
67
|
+
"nodename nor servname",
|
|
68
|
+
"peer closed connection",
|
|
69
|
+
"read operation timed out",
|
|
70
|
+
"read error",
|
|
71
|
+
"read timeout",
|
|
72
|
+
"readtimeout",
|
|
73
|
+
"remote protocol error",
|
|
74
|
+
"server disconnected",
|
|
75
|
+
"server disconnect",
|
|
76
|
+
"temporary failure in name resolution",
|
|
77
|
+
"timed out",
|
|
78
|
+
)
|
|
79
|
+
_PROVIDER_STREAM_TRUNCATED_MESSAGE_MARKERS = (
|
|
80
|
+
"incomplete chunked read",
|
|
81
|
+
"peer closed connection",
|
|
82
|
+
"remote protocol error",
|
|
83
|
+
"server disconnected without sending complete message body",
|
|
84
|
+
"stream truncated",
|
|
85
|
+
"response body ended early",
|
|
86
|
+
)
|
|
87
|
+
_PROVIDER_UNAVAILABLE_STATUS_CODES = frozenset({408, *range(500, 600)})
|
|
88
|
+
_PROVIDER_PERMANENT_4XX_STATUS_CODES = frozenset(range(400, 500)) - {408, 429}
|
|
89
|
+
_CONTEXT_WINDOW_ERROR_MARKERS = (
|
|
90
|
+
"context_length_exceeded",
|
|
91
|
+
"context length exceeded",
|
|
92
|
+
"maximum context length",
|
|
93
|
+
"context window exceeded",
|
|
94
|
+
"exceeds the context window",
|
|
95
|
+
"exceeds this model's context",
|
|
96
|
+
"exceeds the model's context",
|
|
97
|
+
"prompt is too long",
|
|
98
|
+
"input is too long",
|
|
99
|
+
"input token count exceeds",
|
|
100
|
+
"too many input tokens",
|
|
101
|
+
"input token limit exceeded",
|
|
102
|
+
)
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
def failure_category_value(category: FailureCategory | str | None) -> str | None:
|
|
106
|
+
parsed = parse_failure_category(category)
|
|
107
|
+
return parsed.value if parsed is not None else None
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
def parse_failure_category(category: FailureCategory | str | None) -> FailureCategory | None:
|
|
111
|
+
if isinstance(category, FailureCategory):
|
|
112
|
+
return category
|
|
113
|
+
if category is None:
|
|
114
|
+
return None
|
|
115
|
+
try:
|
|
116
|
+
return FailureCategory(str(category).strip())
|
|
117
|
+
except ValueError:
|
|
118
|
+
return None
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
def empty_failure_category_counts() -> dict[str, int]:
|
|
122
|
+
return {category.value: 0 for category in FailureCategory}
|
|
123
|
+
|
|
124
|
+
|
|
125
|
+
def increment_failure_category_count(
|
|
126
|
+
counts: dict[str, int],
|
|
127
|
+
category: FailureCategory | str | None,
|
|
128
|
+
) -> None:
|
|
129
|
+
parsed = parse_failure_category(category)
|
|
130
|
+
if parsed is None:
|
|
131
|
+
return
|
|
132
|
+
counts[parsed.value] = int(counts.get(parsed.value, 0) or 0) + 1
|
|
133
|
+
|
|
134
|
+
|
|
135
|
+
def is_provider_throttling_error(error: Any) -> bool:
|
|
136
|
+
status_code = _extract_status_code(error)
|
|
137
|
+
if status_code == 429:
|
|
138
|
+
return True
|
|
139
|
+
|
|
140
|
+
message = str(error or "").casefold()
|
|
141
|
+
if not message:
|
|
142
|
+
return False
|
|
143
|
+
if _HTTP_429_RE.search(message):
|
|
144
|
+
return True
|
|
145
|
+
if any(marker in message for marker in _THROTTLE_MESSAGE_MARKERS):
|
|
146
|
+
return True
|
|
147
|
+
if "quota" in message and any(marker in message for marker in _QUOTA_CONTEXT_MARKERS):
|
|
148
|
+
return True
|
|
149
|
+
if "concurrency" in message and any(marker in message for marker in _QUOTA_CONTEXT_MARKERS):
|
|
150
|
+
return True
|
|
151
|
+
return False
|
|
152
|
+
|
|
153
|
+
|
|
154
|
+
def is_provider_unavailable_error(error: Any) -> bool:
|
|
155
|
+
return provider_unavailable_retry_reason(error) is not None
|
|
156
|
+
|
|
157
|
+
|
|
158
|
+
def provider_unavailable_retry_reason(error: Any) -> str | None:
|
|
159
|
+
status_code = _extract_status_code_from_chain(error)
|
|
160
|
+
if status_code in _PROVIDER_PERMANENT_4XX_STATUS_CODES:
|
|
161
|
+
return None
|
|
162
|
+
if status_code in _PROVIDER_UNAVAILABLE_STATUS_CODES:
|
|
163
|
+
return "provider_unavailable"
|
|
164
|
+
|
|
165
|
+
for exc in _iter_exception_chain(error):
|
|
166
|
+
if isinstance(exc, httpx.RemoteProtocolError):
|
|
167
|
+
return "provider_stream_truncated"
|
|
168
|
+
if isinstance(exc, httpx.ReadError | httpx.ReadTimeout):
|
|
169
|
+
if _message_has_stream_truncation_marker(str(exc)):
|
|
170
|
+
return "provider_stream_truncated"
|
|
171
|
+
return "provider_unavailable"
|
|
172
|
+
if isinstance(
|
|
173
|
+
exc,
|
|
174
|
+
httpx.ConnectError
|
|
175
|
+
| httpx.ConnectTimeout
|
|
176
|
+
| httpx.NetworkError
|
|
177
|
+
| httpx.PoolTimeout
|
|
178
|
+
| httpx.TransportError,
|
|
179
|
+
):
|
|
180
|
+
return "provider_unavailable"
|
|
181
|
+
|
|
182
|
+
message = _exception_chain_message(error)
|
|
183
|
+
if not message:
|
|
184
|
+
return None
|
|
185
|
+
if _message_has_stream_truncation_marker(message):
|
|
186
|
+
return "provider_stream_truncated"
|
|
187
|
+
if any(marker in message for marker in _PROVIDER_UNAVAILABLE_MESSAGE_MARKERS):
|
|
188
|
+
return "provider_unavailable"
|
|
189
|
+
return None
|
|
190
|
+
|
|
191
|
+
|
|
192
|
+
def is_infra_unavailable_error(error: Any) -> bool:
|
|
193
|
+
message = str(error or "").casefold()
|
|
194
|
+
if not message:
|
|
195
|
+
return False
|
|
196
|
+
return any(marker in message for marker in _INFRA_UNAVAILABLE_MARKERS)
|
|
197
|
+
|
|
198
|
+
|
|
199
|
+
def is_context_window_exceeded_error(error: Any) -> bool:
|
|
200
|
+
"""Recognize provider context-capacity failures across protocol adapters.
|
|
201
|
+
|
|
202
|
+
Adapters currently normalize provider error objects into ``LLMError`` text,
|
|
203
|
+
so this checks the full exception chain and deliberately requires
|
|
204
|
+
context/input/prompt-specific phrases rather than treating every HTTP 400
|
|
205
|
+
as compactable.
|
|
206
|
+
"""
|
|
207
|
+
|
|
208
|
+
message = _exception_chain_message(error)
|
|
209
|
+
if not message:
|
|
210
|
+
return False
|
|
211
|
+
return any(marker in message for marker in _CONTEXT_WINDOW_ERROR_MARKERS)
|
|
212
|
+
|
|
213
|
+
|
|
214
|
+
def extract_status_code(error: Any) -> int | None:
|
|
215
|
+
"""Best-effort HTTP status code from an error or its exception chain.
|
|
216
|
+
|
|
217
|
+
Reads a ``status_code``/``code`` attribute, a ``response.status_code``, or a
|
|
218
|
+
``... error NNN ...`` marker in the message, walking ``__cause__``/``__context__``.
|
|
219
|
+
Returns ``None`` when no status can be recovered.
|
|
220
|
+
"""
|
|
221
|
+
return _extract_status_code_from_chain(error)
|
|
222
|
+
|
|
223
|
+
|
|
224
|
+
def classify_failure_category(error: Any) -> FailureCategory:
|
|
225
|
+
"""Map an arbitrary exception onto a :class:`FailureCategory`.
|
|
226
|
+
|
|
227
|
+
Reuses the existing provider classifiers so the diagnostic vocabulary stays
|
|
228
|
+
consistent across the chat/run path, Forge workers, and delegated agents.
|
|
229
|
+
Ordering reflects specificity: throttling (HTTP 429 / rate-limit markers) and
|
|
230
|
+
infra-unavailability are checked before generic provider-unavailability, and a
|
|
231
|
+
readable-but-non-transient provider status (e.g. 400/401/403/404) is reported as
|
|
232
|
+
:attr:`FailureCategory.PROVIDER_ERROR` rather than being mistaken for a transient
|
|
233
|
+
outage or for an agent implementation failure. Errors carrying no provider signal
|
|
234
|
+
fall through to :attr:`FailureCategory.IMPLEMENTATION_FAILED`.
|
|
235
|
+
"""
|
|
236
|
+
if is_provider_throttling_error(error):
|
|
237
|
+
return FailureCategory.PROVIDER_THROTTLED
|
|
238
|
+
if is_infra_unavailable_error(error):
|
|
239
|
+
return FailureCategory.INFRA_UNAVAILABLE
|
|
240
|
+
if is_provider_unavailable_error(error):
|
|
241
|
+
return FailureCategory.PROVIDER_UNAVAILABLE
|
|
242
|
+
if extract_status_code(error) is not None:
|
|
243
|
+
return FailureCategory.PROVIDER_ERROR
|
|
244
|
+
return FailureCategory.IMPLEMENTATION_FAILED
|
|
245
|
+
|
|
246
|
+
|
|
247
|
+
def exit_code_for_failure(error: Any) -> int:
|
|
248
|
+
"""Return a process exit code that separates transient infrastructure failures."""
|
|
249
|
+
|
|
250
|
+
category = classify_failure_category(error)
|
|
251
|
+
if category in {
|
|
252
|
+
FailureCategory.INFRA_UNAVAILABLE,
|
|
253
|
+
FailureCategory.PROVIDER_UNAVAILABLE,
|
|
254
|
+
FailureCategory.PROVIDER_THROTTLED,
|
|
255
|
+
}:
|
|
256
|
+
return INFRASTRUCTURE_FAILURE_EXIT_CODE
|
|
257
|
+
return AGENT_FAILURE_EXIT_CODE
|
|
258
|
+
|
|
259
|
+
|
|
260
|
+
def _extract_status_code(error: Any) -> int | None:
|
|
261
|
+
for attr_name in ("status_code", "code"):
|
|
262
|
+
status_code = _coerce_status_code(getattr(error, attr_name, None))
|
|
263
|
+
if status_code is not None:
|
|
264
|
+
return status_code
|
|
265
|
+
|
|
266
|
+
response = getattr(error, "response", None)
|
|
267
|
+
if response is not None:
|
|
268
|
+
status_code = _coerce_status_code(getattr(response, "status_code", None))
|
|
269
|
+
if status_code is not None:
|
|
270
|
+
return status_code
|
|
271
|
+
|
|
272
|
+
match = re.search(r"\b(?:LLM|Responses)?\s*error\s+(\d{3})\b", str(error or ""), re.IGNORECASE)
|
|
273
|
+
if match is None:
|
|
274
|
+
return None
|
|
275
|
+
return _coerce_status_code(match.group(1))
|
|
276
|
+
|
|
277
|
+
|
|
278
|
+
def _extract_status_code_from_chain(error: Any) -> int | None:
|
|
279
|
+
for exc in _iter_exception_chain(error):
|
|
280
|
+
status_code = _extract_status_code(exc)
|
|
281
|
+
if status_code is not None:
|
|
282
|
+
return status_code
|
|
283
|
+
return None
|
|
284
|
+
|
|
285
|
+
|
|
286
|
+
def _iter_exception_chain(error: Any) -> list[Any]:
|
|
287
|
+
chain: list[Any] = []
|
|
288
|
+
seen: set[int] = set()
|
|
289
|
+
current = error
|
|
290
|
+
while current is not None and id(current) not in seen:
|
|
291
|
+
seen.add(id(current))
|
|
292
|
+
chain.append(current)
|
|
293
|
+
cause = getattr(current, "__cause__", None)
|
|
294
|
+
context = getattr(current, "__context__", None)
|
|
295
|
+
current = cause if cause is not None else context
|
|
296
|
+
return chain
|
|
297
|
+
|
|
298
|
+
|
|
299
|
+
def _exception_chain_message(error: Any) -> str:
|
|
300
|
+
return " ".join(str(exc or "").casefold() for exc in _iter_exception_chain(error))
|
|
301
|
+
|
|
302
|
+
|
|
303
|
+
def _message_has_stream_truncation_marker(message: str) -> bool:
|
|
304
|
+
normalized = str(message or "").casefold()
|
|
305
|
+
return any(marker in normalized for marker in _PROVIDER_STREAM_TRUNCATED_MESSAGE_MARKERS)
|
|
306
|
+
|
|
307
|
+
|
|
308
|
+
def _coerce_status_code(value: Any) -> int | None:
|
|
309
|
+
try:
|
|
310
|
+
status_code = int(value)
|
|
311
|
+
except (TypeError, ValueError):
|
|
312
|
+
return None
|
|
313
|
+
if status_code <= 0:
|
|
314
|
+
return None
|
|
315
|
+
return status_code
|