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,101 @@
|
|
|
1
|
+
"""Mutable view-model for the full-screen TUI.
|
|
2
|
+
|
|
3
|
+
Holds only what the footer/header need to render. The footer HUD fields
|
|
4
|
+
(``context_pct`` / ``tokens`` / ``cost_usd``) are wired live: ``loop.py`` seeds
|
|
5
|
+
them when the session is built and refreshes them after each turn (and mid-turn,
|
|
6
|
+
throttled) from the session's usage summary + context cache. Other fields are
|
|
7
|
+
toggled by the user via Tab (persona) / Shift+Tab (execution mode).
|
|
8
|
+
|
|
9
|
+
``exec_mode`` mirrors ``session.mode`` and is the single authority for what the
|
|
10
|
+
agent is allowed to do without asking. There is deliberately no second
|
|
11
|
+
approval-policy flag here: an independent "auto-approve" toggle could silently
|
|
12
|
+
answer every gate that ``review`` mode raised, leaving the footer advertising a
|
|
13
|
+
guarded mode while the session behaved like ``fullaccess``.
|
|
14
|
+
"""
|
|
15
|
+
|
|
16
|
+
from __future__ import annotations
|
|
17
|
+
|
|
18
|
+
from dataclasses import dataclass
|
|
19
|
+
|
|
20
|
+
PLAN_MODE = "plan"
|
|
21
|
+
ACT_MODE = "act"
|
|
22
|
+
|
|
23
|
+
# Shift+Tab cycles the execution mode in this order (wrapping). This is the same
|
|
24
|
+
# set the /mode picker offers, kept in escalating-capability order so the cycle
|
|
25
|
+
# reads as "loosen the guards one notch" rather than an arbitrary rotation.
|
|
26
|
+
# ``fullaccess`` is included deliberately — the caller echoes its warning every
|
|
27
|
+
# time the cycle lands there, so reaching the unguarded mode is never silent.
|
|
28
|
+
EXEC_MODE_CYCLE: tuple[str, ...] = ("readonly", "review", "auto", "fullaccess")
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
def next_exec_mode(current: str) -> str:
|
|
32
|
+
"""Return the execution mode one step along :data:`EXEC_MODE_CYCLE`.
|
|
33
|
+
|
|
34
|
+
An unknown or empty ``current`` starts the cycle at its first entry, so a
|
|
35
|
+
session whose mode has not been synced yet still advances predictably
|
|
36
|
+
instead of raising.
|
|
37
|
+
"""
|
|
38
|
+
normalized = str(current or "").strip().lower()
|
|
39
|
+
try:
|
|
40
|
+
index = EXEC_MODE_CYCLE.index(normalized)
|
|
41
|
+
except ValueError:
|
|
42
|
+
return EXEC_MODE_CYCLE[0]
|
|
43
|
+
return EXEC_MODE_CYCLE[(index + 1) % len(EXEC_MODE_CYCLE)]
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
@dataclass
|
|
47
|
+
class TuiState:
|
|
48
|
+
model_name: str = ""
|
|
49
|
+
# Non-empty while the shell is available but model calls are not (for
|
|
50
|
+
# example, a selected subscription still needs browser authentication).
|
|
51
|
+
connection_status: str = ""
|
|
52
|
+
tokens: int = 0
|
|
53
|
+
# Session cost. ``None`` means pricing is unknown (an unmetered/free model with
|
|
54
|
+
# real usage) — the footer renders that as "n/a" rather than a misleading
|
|
55
|
+
# "$0.0000". A literal 0.0 means nothing has been spent yet.
|
|
56
|
+
cost_usd: float | None = 0.0
|
|
57
|
+
cost_unknown_calls: int = 0 # calls whose cost couldn't be metered (footer "+N")
|
|
58
|
+
# Preformatted billing status (for example ``subscription`` or ``~$0.0123``).
|
|
59
|
+
# Empty retains the legacy numeric fallback for callers that do not have a
|
|
60
|
+
# UsageSummary available yet.
|
|
61
|
+
cost_display: str = ""
|
|
62
|
+
mode: str = ACT_MODE # "plan" | "act"
|
|
63
|
+
exec_mode: str = "" # execution mode: review | auto | readonly | fullaccess
|
|
64
|
+
# Active persona (code|architect|ask|debug); "" or "code" renders no
|
|
65
|
+
# persona badge — the execution-mode badge alone stays authoritative.
|
|
66
|
+
persona: str = ""
|
|
67
|
+
# Forge: True while the user is inside a Forge planning session (ui_mode ==
|
|
68
|
+
# "forge"); drives the footer FORGE badge + the forge-specific placeholder.
|
|
69
|
+
forge_mode: bool = False
|
|
70
|
+
forge_run_id: str = "" # short run id shown in the FORGE badge, e.g. "run-1a2b"
|
|
71
|
+
# Name of the subagent currently running through auto-delegation; drives
|
|
72
|
+
# the footer badge so the user knows nested work is active. Empty otherwise.
|
|
73
|
+
active_subagent: str = ""
|
|
74
|
+
# Every concurrently running subagent, in start order. ``active_subagent``
|
|
75
|
+
# remains the compatibility view of the most recently started survivor.
|
|
76
|
+
active_subagents: tuple[str, ...] = ()
|
|
77
|
+
username: str = ""
|
|
78
|
+
workspace: str = "" # short display form, e.g. "~/coder-plugin-install"
|
|
79
|
+
branch: str = "" # git branch name, e.g. "feat/tui-rebuild"
|
|
80
|
+
usage_hud_enabled: bool = True
|
|
81
|
+
# Conversation headroom %, seeded from the session before first paint.
|
|
82
|
+
# ``None`` means "not measured yet" so a failed compute reads n/a in the
|
|
83
|
+
# footer instead of a fabricated 100%.
|
|
84
|
+
context_pct: float | None = None
|
|
85
|
+
|
|
86
|
+
@property
|
|
87
|
+
def plan_mode(self) -> bool:
|
|
88
|
+
return self.mode == PLAN_MODE
|
|
89
|
+
|
|
90
|
+
def toggle_mode(self) -> str:
|
|
91
|
+
self.mode = PLAN_MODE if self.mode == ACT_MODE else ACT_MODE
|
|
92
|
+
return self.mode
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
__all__ = [
|
|
96
|
+
"TuiState",
|
|
97
|
+
"PLAN_MODE",
|
|
98
|
+
"ACT_MODE",
|
|
99
|
+
"EXEC_MODE_CYCLE",
|
|
100
|
+
"next_exec_mode",
|
|
101
|
+
]
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
"""Per-subagent visual identity — accent colour only.
|
|
2
|
+
|
|
3
|
+
One tiny authority (like ``forge_status``) so the transcript spawn line, the
|
|
4
|
+
live status, and the footer badge can never disagree about who a given
|
|
5
|
+
subagent is. Activity comes from runtime events, never from role narration.
|
|
6
|
+
Result attribution prints the registry name alone and deliberately does not
|
|
7
|
+
consult this module — a subagent wears no per-agent symbol, so there is
|
|
8
|
+
nothing to keep in sync.
|
|
9
|
+
|
|
10
|
+
The name is the identity: the shared ``↪``/``↩`` marks say only that a nested
|
|
11
|
+
run started or ended, never which agent it was. Colours are distinct from the
|
|
12
|
+
fixed mode accents (green chat, violet forge, cyan brand) so a
|
|
13
|
+
subagent badge never impersonates a mode. Custom subagents get a colour picked
|
|
14
|
+
deterministically from the name — the same agent looks the same every run.
|
|
15
|
+
"""
|
|
16
|
+
|
|
17
|
+
from __future__ import annotations
|
|
18
|
+
|
|
19
|
+
import zlib
|
|
20
|
+
from dataclasses import dataclass
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
@dataclass(frozen=True)
|
|
24
|
+
class SubagentIdentity:
|
|
25
|
+
color: str
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
_BUILTIN_IDENTITIES: dict[str, SubagentIdentity] = {
|
|
29
|
+
"frontend-engineer": SubagentIdentity("#a371f7"),
|
|
30
|
+
# Silver keeps delegated work visually distinct from the main modes.
|
|
31
|
+
"visual-designer": SubagentIdentity("#c9d1d9"),
|
|
32
|
+
"explorer": SubagentIdentity("#58a6ff"),
|
|
33
|
+
"implementer": SubagentIdentity("#f0883e"),
|
|
34
|
+
"debugger": SubagentIdentity("#f47067"),
|
|
35
|
+
"verifier": SubagentIdentity("#79c0ff"),
|
|
36
|
+
"code-reviewer": SubagentIdentity("#db61a2"),
|
|
37
|
+
"dependency-scout": SubagentIdentity("#8c959f"),
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
_FALLBACK_COLORS: tuple[str, ...] = (
|
|
41
|
+
"#58a6ff",
|
|
42
|
+
"#f0883e",
|
|
43
|
+
"#db61a2",
|
|
44
|
+
"#39c5cf",
|
|
45
|
+
"#f47067",
|
|
46
|
+
"#d2a8ff",
|
|
47
|
+
)
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
def subagent_identity(name: str) -> SubagentIdentity:
|
|
51
|
+
"""Identity for ``name`` (built-in aliases resolved, e.g. explore→explorer)."""
|
|
52
|
+
clean = str(name or "").strip().lower()
|
|
53
|
+
try:
|
|
54
|
+
from ...subagents import canonical_subagent_name
|
|
55
|
+
|
|
56
|
+
clean = canonical_subagent_name(clean) or clean
|
|
57
|
+
except Exception: # noqa: BLE001 - identity lookup must never raise
|
|
58
|
+
pass
|
|
59
|
+
known = _BUILTIN_IDENTITIES.get(clean)
|
|
60
|
+
if known is not None:
|
|
61
|
+
return known
|
|
62
|
+
digest = zlib.crc32(clean.encode("utf-8", "replace"))
|
|
63
|
+
return SubagentIdentity(_FALLBACK_COLORS[digest % len(_FALLBACK_COLORS)])
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
__all__ = ["SubagentIdentity", "subagent_identity"]
|
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
"""Pure row construction for the terminal TUI's live subagent panel.
|
|
2
|
+
|
|
3
|
+
The panel is a bounded live tail, not a transcript. This module deliberately
|
|
4
|
+
owns no prompt_toolkit state: callers supply the latest child status and the
|
|
5
|
+
entries accumulated from incremental scheduler reads.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from __future__ import annotations
|
|
9
|
+
|
|
10
|
+
from typing import Any
|
|
11
|
+
|
|
12
|
+
from ...subagent_labels import subagent_identity
|
|
13
|
+
|
|
14
|
+
ENTRY_BUFFER_CAP = 240
|
|
15
|
+
|
|
16
|
+
_MIDDLE_DOT = "\u00b7"
|
|
17
|
+
_ELLIPSIS = "\u2026"
|
|
18
|
+
|
|
19
|
+
_S_HEAD = "class:tui.subpanel.head"
|
|
20
|
+
_S_STATE = "class:tui.subpanel.state"
|
|
21
|
+
_S_DIM = "class:tui.subpanel.dim"
|
|
22
|
+
_S_TOOL = "class:tui.subpanel.tool"
|
|
23
|
+
_S_RESULT = "class:tui.subpanel.result"
|
|
24
|
+
_S_ASSISTANT = "class:tui.subpanel.assistant"
|
|
25
|
+
_S_USER = "class:tui.subpanel.user"
|
|
26
|
+
_S_HINT = "class:tui.subpanel.hint"
|
|
27
|
+
|
|
28
|
+
_ENTRY_STYLE = {
|
|
29
|
+
"tool": (_S_TOOL, "\u25b8 "),
|
|
30
|
+
"tool_result": (_S_RESULT, "\u2713 "),
|
|
31
|
+
"tool_error": (_S_RESULT, "\u2717 "),
|
|
32
|
+
"assistant": (_S_ASSISTANT, "a: "),
|
|
33
|
+
"user": (_S_USER, "u: "),
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
def append_bounded_entries(
|
|
38
|
+
existing: list[dict[str, str]],
|
|
39
|
+
incoming: list[dict[str, str]],
|
|
40
|
+
*,
|
|
41
|
+
limit: int = ENTRY_BUFFER_CAP,
|
|
42
|
+
) -> list[dict[str, str]]:
|
|
43
|
+
"""Append normalized entries while retaining only the newest ``limit``."""
|
|
44
|
+
cap = max(1, int(limit))
|
|
45
|
+
combined = [*existing, *incoming]
|
|
46
|
+
return combined[-cap:]
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
def _fit_segments(segments: list[tuple[str, str]], width: int) -> list[tuple[str, str]]:
|
|
50
|
+
out: list[tuple[str, str]] = []
|
|
51
|
+
used = 0
|
|
52
|
+
for style, value in segments:
|
|
53
|
+
text = str(value or "")
|
|
54
|
+
if not text:
|
|
55
|
+
continue
|
|
56
|
+
room = width - used
|
|
57
|
+
if room <= 0:
|
|
58
|
+
break
|
|
59
|
+
if len(text) <= room:
|
|
60
|
+
out.append((style, text))
|
|
61
|
+
used += len(text)
|
|
62
|
+
continue
|
|
63
|
+
clipped = text[: room - 1].rstrip() + _ELLIPSIS if room >= 2 else _ELLIPSIS
|
|
64
|
+
out.append((style, clipped[:room]))
|
|
65
|
+
break
|
|
66
|
+
return out
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
def _elapsed_label(value: Any) -> str:
|
|
70
|
+
try:
|
|
71
|
+
elapsed_ms = max(0, int(value or 0))
|
|
72
|
+
except (TypeError, ValueError):
|
|
73
|
+
elapsed_ms = 0
|
|
74
|
+
if elapsed_ms < 1000:
|
|
75
|
+
return f"{elapsed_ms}ms"
|
|
76
|
+
seconds = elapsed_ms // 1000
|
|
77
|
+
if seconds < 60:
|
|
78
|
+
return f"{seconds}s"
|
|
79
|
+
minutes, seconds = divmod(seconds, 60)
|
|
80
|
+
if minutes < 60:
|
|
81
|
+
return f"{minutes}m {seconds}s"
|
|
82
|
+
hours, minutes = divmod(minutes, 60)
|
|
83
|
+
return f"{hours}h {minutes}m"
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
def quiet_time_label(status: dict[str, Any]) -> str:
|
|
87
|
+
"""Return a deterministic quiet-age label once the existing interval passes."""
|
|
88
|
+
if str(status.get("state") or "").strip().lower() != "running":
|
|
89
|
+
return ""
|
|
90
|
+
try:
|
|
91
|
+
age_s = max(0.0, float(status.get("last_event_age_s") or 0.0))
|
|
92
|
+
threshold_s = max(0.0, float(status.get("activity_threshold_s") or 0.0))
|
|
93
|
+
except (TypeError, ValueError):
|
|
94
|
+
return ""
|
|
95
|
+
if threshold_s <= 0.0 or age_s < threshold_s:
|
|
96
|
+
return ""
|
|
97
|
+
return f"quiet {_elapsed_label(int(age_s * 1000))}"
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
def _header_row(
|
|
101
|
+
status: dict[str, Any],
|
|
102
|
+
*,
|
|
103
|
+
width: int,
|
|
104
|
+
position: int,
|
|
105
|
+
total: int,
|
|
106
|
+
) -> list[tuple[str, str]]:
|
|
107
|
+
name = subagent_identity(
|
|
108
|
+
status.get("subagent") or status.get("run_id") or "subagent",
|
|
109
|
+
status.get("label"),
|
|
110
|
+
)
|
|
111
|
+
state = str(status.get("state") or "unknown").strip()
|
|
112
|
+
workspace = str(status.get("workspace_view") or "shared").strip()
|
|
113
|
+
try:
|
|
114
|
+
steps = max(0, int(status.get("steps_completed") or 0))
|
|
115
|
+
except (TypeError, ValueError):
|
|
116
|
+
steps = 0
|
|
117
|
+
separator = f" {_MIDDLE_DOT} "
|
|
118
|
+
quiet = quiet_time_label(status)
|
|
119
|
+
return _fit_segments(
|
|
120
|
+
[
|
|
121
|
+
(_S_HEAD, name),
|
|
122
|
+
(_S_DIM, separator),
|
|
123
|
+
(_S_STATE, state),
|
|
124
|
+
(_S_DIM, separator),
|
|
125
|
+
(_S_DIM, _elapsed_label(status.get("elapsed_ms"))),
|
|
126
|
+
(_S_DIM, separator),
|
|
127
|
+
(_S_DIM, f"{steps} step{'s' if steps != 1 else ''}"),
|
|
128
|
+
(_S_DIM, separator),
|
|
129
|
+
(_S_DIM, workspace),
|
|
130
|
+
(_S_DIM, separator if quiet else ""),
|
|
131
|
+
(_S_DIM, quiet),
|
|
132
|
+
(_S_DIM, f" view {max(1, position)}/{max(1, total)}"),
|
|
133
|
+
],
|
|
134
|
+
width,
|
|
135
|
+
)
|
|
136
|
+
|
|
137
|
+
|
|
138
|
+
def _entry_rows(entry: dict[str, str], width: int) -> list[list[tuple[str, str]]]:
|
|
139
|
+
kind = str(entry.get("kind") or "").strip()
|
|
140
|
+
style, lead = _ENTRY_STYLE.get(kind, (_S_DIM, "- "))
|
|
141
|
+
summary = " ".join(str(entry.get("summary") or "").split())
|
|
142
|
+
return [_fit_segments([(_S_DIM, lead), (style, summary)], width)]
|
|
143
|
+
|
|
144
|
+
|
|
145
|
+
def subagent_panel_rows(
|
|
146
|
+
status: dict[str, Any],
|
|
147
|
+
entries: list[dict[str, str]],
|
|
148
|
+
*,
|
|
149
|
+
width: int,
|
|
150
|
+
height: int,
|
|
151
|
+
position: int,
|
|
152
|
+
total: int,
|
|
153
|
+
) -> list[list[tuple[str, str]]]:
|
|
154
|
+
"""Render header, newest body entries, and footer within ``height`` rows."""
|
|
155
|
+
width = max(12, int(width))
|
|
156
|
+
height = max(2, int(height))
|
|
157
|
+
body_height = max(0, height - 2)
|
|
158
|
+
selected: list[list[list[tuple[str, str]]]] = []
|
|
159
|
+
used = 0
|
|
160
|
+
for entry in reversed(entries):
|
|
161
|
+
wrapped = _entry_rows(entry, width)
|
|
162
|
+
if used and used + len(wrapped) > body_height:
|
|
163
|
+
break
|
|
164
|
+
room = body_height - used
|
|
165
|
+
if room <= 0:
|
|
166
|
+
break
|
|
167
|
+
selected.append(wrapped[:room])
|
|
168
|
+
used += min(len(wrapped), room)
|
|
169
|
+
body_rows = [row for group in reversed(selected) for row in group]
|
|
170
|
+
footer = _fit_segments(
|
|
171
|
+
[(_S_HINT, f"ctrl+b / ctrl+n to switch {_MIDDLE_DOT} esc to close")],
|
|
172
|
+
width,
|
|
173
|
+
)
|
|
174
|
+
return [
|
|
175
|
+
_header_row(status, width=width, position=position, total=total),
|
|
176
|
+
*body_rows,
|
|
177
|
+
footer,
|
|
178
|
+
]
|
|
179
|
+
|
|
180
|
+
|
|
181
|
+
__all__ = [
|
|
182
|
+
"ENTRY_BUFFER_CAP",
|
|
183
|
+
"append_bounded_entries",
|
|
184
|
+
"quiet_time_label",
|
|
185
|
+
"subagent_panel_rows",
|
|
186
|
+
]
|