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,77 @@
|
|
|
1
|
+
# ruff: noqa: F401,F403,F405,I001
|
|
2
|
+
from __future__ import annotations
|
|
3
|
+
|
|
4
|
+
from . import cli_common as _cli_common
|
|
5
|
+
from . import chat_state as _chat_state
|
|
6
|
+
from . import startup as _startup
|
|
7
|
+
from . import chat_terminal as _chat_terminal
|
|
8
|
+
from . import welcome as _welcome
|
|
9
|
+
from . import chat_resume_helpers as _chat_resume_helpers
|
|
10
|
+
from . import chat_status as _chat_status
|
|
11
|
+
from . import forge_helpers as _forge_helpers
|
|
12
|
+
from . import execution_helpers as _execution_helpers
|
|
13
|
+
from . import prompt_helpers as _prompt_helpers
|
|
14
|
+
from . import update as _update
|
|
15
|
+
|
|
16
|
+
from .cli_common import *
|
|
17
|
+
from .chat_state import *
|
|
18
|
+
from .startup import *
|
|
19
|
+
from .chat_terminal import *
|
|
20
|
+
from .welcome import *
|
|
21
|
+
from .chat_resume_helpers import *
|
|
22
|
+
from .chat_status import *
|
|
23
|
+
from .forge_helpers import *
|
|
24
|
+
from .execution_helpers import *
|
|
25
|
+
from .prompt_helpers import *
|
|
26
|
+
from .update import *
|
|
27
|
+
|
|
28
|
+
_CLI_SURFACE_MODULES = (
|
|
29
|
+
_cli_common,
|
|
30
|
+
_chat_state,
|
|
31
|
+
_startup,
|
|
32
|
+
_chat_terminal,
|
|
33
|
+
_welcome,
|
|
34
|
+
_chat_resume_helpers,
|
|
35
|
+
_chat_status,
|
|
36
|
+
_forge_helpers,
|
|
37
|
+
_execution_helpers,
|
|
38
|
+
_prompt_helpers,
|
|
39
|
+
_update,
|
|
40
|
+
)
|
|
41
|
+
|
|
42
|
+
_CLI_SURFACE_INTERNAL_NAMES = {
|
|
43
|
+
"_CLI_SURFACE_INTERNAL_NAMES",
|
|
44
|
+
"_CLI_SURFACE_MODULES",
|
|
45
|
+
"_chat_resume_helpers",
|
|
46
|
+
"_chat_state",
|
|
47
|
+
"_chat_status",
|
|
48
|
+
"_chat_terminal",
|
|
49
|
+
"_cli_common",
|
|
50
|
+
"_execution_helpers",
|
|
51
|
+
"_forge_helpers",
|
|
52
|
+
"_prompt_helpers",
|
|
53
|
+
"_startup",
|
|
54
|
+
"_sync_module_globals",
|
|
55
|
+
"_update",
|
|
56
|
+
"_welcome",
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
def _sync_module_globals() -> None:
|
|
61
|
+
surface_globals = globals()
|
|
62
|
+
for module in _CLI_SURFACE_MODULES:
|
|
63
|
+
module_globals = module.__dict__
|
|
64
|
+
for name, value in surface_globals.items():
|
|
65
|
+
if name.startswith("__") or name in _CLI_SURFACE_INTERNAL_NAMES:
|
|
66
|
+
continue
|
|
67
|
+
module_globals[name] = value
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
_sync_module_globals()
|
|
71
|
+
|
|
72
|
+
__all__ = [
|
|
73
|
+
name
|
|
74
|
+
for name in globals()
|
|
75
|
+
if (not name.startswith("__") or name == "__version__")
|
|
76
|
+
and name not in _CLI_SURFACE_INTERNAL_NAMES
|
|
77
|
+
]
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import json
|
|
4
|
+
import os
|
|
5
|
+
import sys
|
|
6
|
+
|
|
7
|
+
import typer
|
|
8
|
+
|
|
9
|
+
from ...branding import env_get
|
|
10
|
+
from ...config import (
|
|
11
|
+
ConfigError,
|
|
12
|
+
clear_persisted_api_key,
|
|
13
|
+
config_path,
|
|
14
|
+
credentials_path,
|
|
15
|
+
ensure_subscription_menu_managed_key,
|
|
16
|
+
load_config,
|
|
17
|
+
resolve_api_key,
|
|
18
|
+
save_config,
|
|
19
|
+
save_persisted_api_key,
|
|
20
|
+
set_config_value,
|
|
21
|
+
)
|
|
22
|
+
from . import _patchable
|
|
23
|
+
from ._shared import _console
|
|
24
|
+
|
|
25
|
+
config_app = typer.Typer(add_completion=False, help="Configuration commands.")
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
@config_app.command("show")
|
|
29
|
+
def config_show() -> None:
|
|
30
|
+
console = _console()
|
|
31
|
+
cfg = _patchable("load_config", load_config)()
|
|
32
|
+
data = cfg.model_dump()
|
|
33
|
+
data["config_path"] = os.fspath(config_path())
|
|
34
|
+
api_key = _patchable("resolve_api_key", resolve_api_key)()
|
|
35
|
+
data["api_key_set"] = bool(api_key.key)
|
|
36
|
+
data["api_key_source"] = "stored" if api_key.source == "stored:legacy" else api_key.source
|
|
37
|
+
data["credentials_path"] = os.fspath(credentials_path())
|
|
38
|
+
data["active_profile"] = str((cfg.extra_fields or {}).get("active_profile") or "")
|
|
39
|
+
role_models = (cfg.extra_fields or {}).get("role_models")
|
|
40
|
+
forge_role_models = (cfg.extra_fields or {}).get("forge_role_models")
|
|
41
|
+
data["role_models"] = dict(role_models) if isinstance(role_models, dict) else {}
|
|
42
|
+
data["forge_role_models"] = (
|
|
43
|
+
dict(forge_role_models) if isinstance(forge_role_models, dict) else {}
|
|
44
|
+
)
|
|
45
|
+
console.print_json(json.dumps(data))
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
@config_app.command("menu")
|
|
49
|
+
def config_menu_cmd() -> None:
|
|
50
|
+
"""Open the inline configuration menu."""
|
|
51
|
+
from ..config_menu import run_config_menu
|
|
52
|
+
|
|
53
|
+
result = run_config_menu()
|
|
54
|
+
if result.saved:
|
|
55
|
+
n = len(result.changes) + (1 if result.api_key_changed else 0)
|
|
56
|
+
typer.echo(f"Saved {n} change(s).")
|
|
57
|
+
return
|
|
58
|
+
typer.echo("Cancelled — no changes saved.")
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
@config_app.command("set")
|
|
62
|
+
def config_set(
|
|
63
|
+
key: str = typer.Argument(..., help="Key to set."),
|
|
64
|
+
value: str = typer.Argument(..., help="Value to set."),
|
|
65
|
+
) -> None:
|
|
66
|
+
console = _console()
|
|
67
|
+
cfg = _patchable("load_config", load_config)()
|
|
68
|
+
try:
|
|
69
|
+
ensure_subscription_menu_managed_key(cfg, key)
|
|
70
|
+
cfg = set_config_value(cfg, key, value)
|
|
71
|
+
save_config(cfg)
|
|
72
|
+
except ConfigError as e:
|
|
73
|
+
console.print(f"[red]Config error:[/red] {e}")
|
|
74
|
+
raise typer.Exit(code=2) from e
|
|
75
|
+
console.print(f"Saved {key} in {config_path()}")
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
@config_app.command("set-api-key")
|
|
79
|
+
def config_set_api_key(
|
|
80
|
+
env_var: str | None = typer.Option(
|
|
81
|
+
None,
|
|
82
|
+
"--env-var",
|
|
83
|
+
help="Copy the API key from this environment variable.",
|
|
84
|
+
),
|
|
85
|
+
stdin: bool = typer.Option(
|
|
86
|
+
False,
|
|
87
|
+
"--stdin",
|
|
88
|
+
help="Read the API key from standard input.",
|
|
89
|
+
),
|
|
90
|
+
) -> None:
|
|
91
|
+
console = _console()
|
|
92
|
+
if env_var and stdin:
|
|
93
|
+
console.print("[red]Config error:[/red] Use either --env-var or --stdin, not both.")
|
|
94
|
+
raise typer.Exit(code=2)
|
|
95
|
+
|
|
96
|
+
if env_var:
|
|
97
|
+
env_name = env_var.strip()
|
|
98
|
+
if not env_name:
|
|
99
|
+
console.print("[red]Config error:[/red] --env-var must be non-empty.")
|
|
100
|
+
raise typer.Exit(code=2)
|
|
101
|
+
key = str(env_get(env_name) or "").strip()
|
|
102
|
+
if not key:
|
|
103
|
+
console.print(f"[red]Config error:[/red] Environment variable {env_name} is not set.")
|
|
104
|
+
raise typer.Exit(code=2)
|
|
105
|
+
elif stdin:
|
|
106
|
+
key = sys.stdin.read().strip()
|
|
107
|
+
if not key:
|
|
108
|
+
console.print("[red]Config error:[/red] API key is empty.")
|
|
109
|
+
raise typer.Exit(code=2)
|
|
110
|
+
else:
|
|
111
|
+
key = typer.prompt("API key", hide_input=True).strip()
|
|
112
|
+
if not key:
|
|
113
|
+
console.print("[red]Config error:[/red] API key is empty.")
|
|
114
|
+
raise typer.Exit(code=2)
|
|
115
|
+
|
|
116
|
+
try:
|
|
117
|
+
save_persisted_api_key(key)
|
|
118
|
+
except ConfigError as e:
|
|
119
|
+
console.print(f"[red]Config error:[/red] {e}")
|
|
120
|
+
raise typer.Exit(code=2) from e
|
|
121
|
+
console.print(f"Saved API key in {credentials_path()}")
|
|
122
|
+
|
|
123
|
+
|
|
124
|
+
@config_app.command("clear-api-key")
|
|
125
|
+
def config_clear_api_key() -> None:
|
|
126
|
+
console = _console()
|
|
127
|
+
removed = clear_persisted_api_key()
|
|
128
|
+
if removed:
|
|
129
|
+
console.print(f"Removed persisted API key from {credentials_path()}")
|
|
130
|
+
return
|
|
131
|
+
console.print(f"No persisted API key found at {credentials_path()}")
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from pathlib import Path
|
|
4
|
+
|
|
5
|
+
import typer
|
|
6
|
+
|
|
7
|
+
from ...skills import load_repo_conventions, render_repo_conventions_context
|
|
8
|
+
from ._shared import _console, _resolve_tool_workspace_root, _Table
|
|
9
|
+
|
|
10
|
+
conventions_app = typer.Typer(
|
|
11
|
+
add_completion=False,
|
|
12
|
+
help="Repo conventions diagnostics for AGENTS.md / CLAUDE.md / CONVENTIONS.md.",
|
|
13
|
+
)
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
@conventions_app.command("list")
|
|
17
|
+
def conventions_list(
|
|
18
|
+
path: Path = typer.Option(Path("."), "--path", help="Workspace, repository, or file path."),
|
|
19
|
+
) -> None:
|
|
20
|
+
console = _console()
|
|
21
|
+
focus_path = path.expanduser().resolve()
|
|
22
|
+
workspace_root = _resolve_tool_workspace_root(
|
|
23
|
+
path=focus_path if focus_path.is_dir() else focus_path.parent
|
|
24
|
+
)
|
|
25
|
+
documents = load_repo_conventions(
|
|
26
|
+
focus_path=focus_path,
|
|
27
|
+
workspace_root=workspace_root,
|
|
28
|
+
)
|
|
29
|
+
console.print(f"[dim]Workspace root:[/dim] {workspace_root.as_posix()}")
|
|
30
|
+
console.print(f"[dim]Focus path:[/dim] {focus_path.as_posix()}")
|
|
31
|
+
if not documents:
|
|
32
|
+
console.print("No repo conventions found.")
|
|
33
|
+
return
|
|
34
|
+
|
|
35
|
+
table = _Table(title="Repo Conventions")
|
|
36
|
+
table.add_column("priority")
|
|
37
|
+
table.add_column("name")
|
|
38
|
+
table.add_column("trust")
|
|
39
|
+
table.add_column("chars")
|
|
40
|
+
table.add_column("path")
|
|
41
|
+
for priority, document in enumerate(documents, start=1):
|
|
42
|
+
try:
|
|
43
|
+
display_path = document.path.relative_to(workspace_root).as_posix()
|
|
44
|
+
except ValueError:
|
|
45
|
+
display_path = document.path.as_posix()
|
|
46
|
+
table.add_row(
|
|
47
|
+
str(priority),
|
|
48
|
+
document.name,
|
|
49
|
+
document.trust_level,
|
|
50
|
+
str(len(document.content)),
|
|
51
|
+
display_path,
|
|
52
|
+
)
|
|
53
|
+
console.print(table)
|
|
54
|
+
console.print("[dim]Priority order is highest precedence first within repo conventions.[/dim]")
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
@conventions_app.command("render")
|
|
58
|
+
def conventions_render(
|
|
59
|
+
path: Path = typer.Option(Path("."), "--path", help="Workspace, repository, or file path."),
|
|
60
|
+
max_chars: int = typer.Option(
|
|
61
|
+
4000,
|
|
62
|
+
"--max-chars",
|
|
63
|
+
min=256,
|
|
64
|
+
help="Maximum rendered repo-conventions context size.",
|
|
65
|
+
),
|
|
66
|
+
) -> None:
|
|
67
|
+
console = _console()
|
|
68
|
+
focus_path = path.expanduser().resolve()
|
|
69
|
+
workspace_root = _resolve_tool_workspace_root(
|
|
70
|
+
path=focus_path if focus_path.is_dir() else focus_path.parent
|
|
71
|
+
)
|
|
72
|
+
documents = load_repo_conventions(
|
|
73
|
+
focus_path=focus_path,
|
|
74
|
+
workspace_root=workspace_root,
|
|
75
|
+
)
|
|
76
|
+
rendered = render_repo_conventions_context(
|
|
77
|
+
documents=documents,
|
|
78
|
+
max_chars=max_chars,
|
|
79
|
+
)
|
|
80
|
+
console.print(f"[dim]Workspace root:[/dim] {workspace_root.as_posix()}")
|
|
81
|
+
console.print(f"[dim]Focus path:[/dim] {focus_path.as_posix()}")
|
|
82
|
+
if rendered is None:
|
|
83
|
+
console.print("No repo conventions found.")
|
|
84
|
+
return
|
|
85
|
+
console.print(rendered, end="")
|
|
@@ -0,0 +1,350 @@
|
|
|
1
|
+
# ruff: noqa: F401,F403,F405,I001
|
|
2
|
+
# Legacy split module: dependencies are synced by cli_surface.py.
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from ...task_dependencies import infer_ordered_predecessor_dependency
|
|
6
|
+
from .cli_common import *
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
def _snapshot_workspace_tree(root: Path) -> dict[str, str]:
|
|
10
|
+
return _shared_snapshot_workspace_tree(root)
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def _capture_task_local_workspace_baseline(
|
|
14
|
+
root: Path,
|
|
15
|
+
*,
|
|
16
|
+
before_commit: str | None,
|
|
17
|
+
) -> Any:
|
|
18
|
+
return _shared_capture_task_local_workspace_baseline(
|
|
19
|
+
root,
|
|
20
|
+
before_commit=before_commit,
|
|
21
|
+
)
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
def _cleanup_task_local_workspace_baseline(baseline: Any) -> None:
|
|
25
|
+
_shared_cleanup_task_local_workspace_baseline(baseline)
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
def _git_diff_text(root: Path) -> str | None:
|
|
29
|
+
if shutil.which("git") is None:
|
|
30
|
+
return None
|
|
31
|
+
proc = subprocess.run(
|
|
32
|
+
["git", "-C", os.fspath(root), "diff"],
|
|
33
|
+
capture_output=True,
|
|
34
|
+
text=True,
|
|
35
|
+
check=False,
|
|
36
|
+
)
|
|
37
|
+
if proc.returncode != 0:
|
|
38
|
+
return None
|
|
39
|
+
return proc.stdout
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
def _git_changed_files(root: Path) -> list[str]:
|
|
43
|
+
return _shared_git_changed_files(root)
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
def _build_execution_reporting_diff(root: Path) -> Any:
|
|
47
|
+
return _shared_build_execution_reporting_diff(root)
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
def _build_execution_reporting_diff_with_commit_range(
|
|
51
|
+
root: Path,
|
|
52
|
+
*,
|
|
53
|
+
before_commit: str | None,
|
|
54
|
+
after_commit: str | None,
|
|
55
|
+
) -> Any:
|
|
56
|
+
return _shared_build_execution_reporting_diff_with_commit_range(
|
|
57
|
+
root,
|
|
58
|
+
before_commit=before_commit,
|
|
59
|
+
after_commit=after_commit,
|
|
60
|
+
)
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
def _build_workspace_snapshot_reporting_diff(
|
|
64
|
+
root: Path,
|
|
65
|
+
*,
|
|
66
|
+
before_snapshot: dict[str, str],
|
|
67
|
+
after_snapshot: dict[str, str],
|
|
68
|
+
) -> Any:
|
|
69
|
+
return _shared_build_workspace_snapshot_reporting_diff(
|
|
70
|
+
root,
|
|
71
|
+
before_snapshot=before_snapshot,
|
|
72
|
+
after_snapshot=after_snapshot,
|
|
73
|
+
)
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
def _build_task_local_workspace_reporting_diff(
|
|
77
|
+
root: Path,
|
|
78
|
+
*,
|
|
79
|
+
baseline: Any,
|
|
80
|
+
after_commit: str | None,
|
|
81
|
+
) -> Any:
|
|
82
|
+
return _shared_build_task_local_workspace_reporting_diff(
|
|
83
|
+
root,
|
|
84
|
+
baseline=baseline,
|
|
85
|
+
after_commit=after_commit,
|
|
86
|
+
)
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
def _snapshot_session_logs(cfg: AppConfig) -> set[Path]:
|
|
90
|
+
return _shared_snapshot_session_logs(cfg)
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
def _execution_private_sessions_dir(
|
|
94
|
+
*,
|
|
95
|
+
cfg: AppConfig,
|
|
96
|
+
run_id: str,
|
|
97
|
+
task_id: str,
|
|
98
|
+
workspace_root: Path,
|
|
99
|
+
) -> Path:
|
|
100
|
+
return _shared_execution_private_sessions_dir(
|
|
101
|
+
cfg=cfg,
|
|
102
|
+
run_id=run_id,
|
|
103
|
+
task_id=task_id,
|
|
104
|
+
workspace_root=workspace_root,
|
|
105
|
+
)
|
|
106
|
+
|
|
107
|
+
|
|
108
|
+
def _cleanup_execution_private_sessions_dir(path: Path) -> None:
|
|
109
|
+
_shared_cleanup_execution_private_sessions_dir(path)
|
|
110
|
+
|
|
111
|
+
|
|
112
|
+
def _write_exec_log_artifacts(
|
|
113
|
+
*,
|
|
114
|
+
paths: Any,
|
|
115
|
+
task_id: str,
|
|
116
|
+
cfg: AppConfig,
|
|
117
|
+
no_log: bool,
|
|
118
|
+
before_logs: set[Path] | None,
|
|
119
|
+
sessions_dir: Path | None = None,
|
|
120
|
+
expected_session_id: str | None = None,
|
|
121
|
+
) -> Any:
|
|
122
|
+
return _shared_write_exec_log_artifacts(
|
|
123
|
+
paths=paths,
|
|
124
|
+
task_id=task_id,
|
|
125
|
+
cfg=cfg,
|
|
126
|
+
no_log=no_log,
|
|
127
|
+
before_logs=before_logs,
|
|
128
|
+
sessions_dir=sessions_dir,
|
|
129
|
+
expected_session_id=expected_session_id,
|
|
130
|
+
)
|
|
131
|
+
|
|
132
|
+
|
|
133
|
+
def _write_execution_context_artifact(
|
|
134
|
+
*,
|
|
135
|
+
paths: Any,
|
|
136
|
+
task_id: str,
|
|
137
|
+
context_text: str,
|
|
138
|
+
) -> Path:
|
|
139
|
+
return _shared_write_execution_context_artifact(
|
|
140
|
+
run_paths=paths,
|
|
141
|
+
task_id=task_id,
|
|
142
|
+
context_text=context_text,
|
|
143
|
+
)
|
|
144
|
+
|
|
145
|
+
|
|
146
|
+
def _write_execution_budget_artifact(
|
|
147
|
+
*,
|
|
148
|
+
paths: Any,
|
|
149
|
+
task_id: str,
|
|
150
|
+
payload: dict[str, Any],
|
|
151
|
+
) -> Path:
|
|
152
|
+
return _shared_write_execution_budget_artifact(
|
|
153
|
+
run_paths=paths,
|
|
154
|
+
task_id=task_id,
|
|
155
|
+
payload=payload,
|
|
156
|
+
)
|
|
157
|
+
|
|
158
|
+
|
|
159
|
+
def _resolve_managed_task_step_budget(
|
|
160
|
+
*,
|
|
161
|
+
cfg: AppConfig,
|
|
162
|
+
plan: dict[str, Any],
|
|
163
|
+
task: dict[str, Any],
|
|
164
|
+
kind: str = "managed_task",
|
|
165
|
+
mode: str | None = None,
|
|
166
|
+
verification_enabled: bool,
|
|
167
|
+
max_steps_override: int | None = None,
|
|
168
|
+
attempt_count: int | None = None,
|
|
169
|
+
image_count: int = 0,
|
|
170
|
+
conflict_file_count: int = 0,
|
|
171
|
+
):
|
|
172
|
+
return _shared_resolve_managed_task_step_budget(
|
|
173
|
+
cfg=cfg,
|
|
174
|
+
plan=plan,
|
|
175
|
+
task=task,
|
|
176
|
+
kind=kind,
|
|
177
|
+
mode=mode,
|
|
178
|
+
verification_enabled=verification_enabled,
|
|
179
|
+
max_steps_override=max_steps_override,
|
|
180
|
+
attempt_count=attempt_count,
|
|
181
|
+
image_count=image_count,
|
|
182
|
+
conflict_file_count=conflict_file_count,
|
|
183
|
+
)
|
|
184
|
+
|
|
185
|
+
|
|
186
|
+
def _prepare_task_execution_knowledge(
|
|
187
|
+
*,
|
|
188
|
+
run_paths: RunPaths,
|
|
189
|
+
task: dict[str, Any],
|
|
190
|
+
selection_label: str,
|
|
191
|
+
extra_paths: list[str] | None = None,
|
|
192
|
+
limit: int = 4,
|
|
193
|
+
) -> Any:
|
|
194
|
+
return _shared_prepare_task_execution_knowledge(
|
|
195
|
+
run_paths=run_paths,
|
|
196
|
+
task=task,
|
|
197
|
+
selection_label=selection_label,
|
|
198
|
+
extra_paths=extra_paths,
|
|
199
|
+
limit=limit,
|
|
200
|
+
)
|
|
201
|
+
|
|
202
|
+
|
|
203
|
+
def _mirror_selected_knowledge_into_worktree(
|
|
204
|
+
*,
|
|
205
|
+
materialized: Any,
|
|
206
|
+
run_paths: RunPaths,
|
|
207
|
+
worktree_repo_path: Path,
|
|
208
|
+
) -> None:
|
|
209
|
+
_shared_mirror_selected_knowledge_into_worktree(
|
|
210
|
+
materialized=materialized,
|
|
211
|
+
run_paths=run_paths,
|
|
212
|
+
worktree_repo_path=worktree_repo_path,
|
|
213
|
+
)
|
|
214
|
+
|
|
215
|
+
|
|
216
|
+
def _task_dependency_blockers(plan: dict[str, Any], task: dict[str, Any]) -> list[str]:
|
|
217
|
+
blockers: list[str] = []
|
|
218
|
+
deps = task.get("dependencies") or []
|
|
219
|
+
for dep_id in deps:
|
|
220
|
+
dep_task = find_task(plan, str(dep_id))
|
|
221
|
+
if dep_task is None:
|
|
222
|
+
blockers.append(f"{dep_id} (missing)")
|
|
223
|
+
continue
|
|
224
|
+
dep_status = str(dep_task.get("status") or "")
|
|
225
|
+
if dep_status != "done":
|
|
226
|
+
blockers.append(f"{dep_id} ({dep_status or 'unknown'})")
|
|
227
|
+
tasks = [item for item in plan.get("tasks") or [] if isinstance(item, dict)]
|
|
228
|
+
inferred = infer_ordered_predecessor_dependency(tasks=tasks, task=task)
|
|
229
|
+
if inferred is not None and inferred.depends_on not in {str(dep).strip() for dep in deps}:
|
|
230
|
+
dep_task = find_task(plan, inferred.depends_on)
|
|
231
|
+
if dep_task is None:
|
|
232
|
+
blockers.append(f"{inferred.depends_on} (missing, inferred)")
|
|
233
|
+
else:
|
|
234
|
+
dep_status = str(dep_task.get("status") or "")
|
|
235
|
+
if dep_status != "done":
|
|
236
|
+
blockers.append(f"{inferred.depends_on} ({dep_status or 'unknown'}, inferred)")
|
|
237
|
+
return blockers
|
|
238
|
+
|
|
239
|
+
|
|
240
|
+
def _safe_task_file_component(task_id: str) -> str:
|
|
241
|
+
return _shared_safe_task_file_component(task_id)
|
|
242
|
+
|
|
243
|
+
|
|
244
|
+
def _normalize_scope_mode(scope: str) -> str:
|
|
245
|
+
value = scope.strip().lower()
|
|
246
|
+
if value not in _SCOPE_MODES:
|
|
247
|
+
raise ForgeError("Invalid --scope. Use one of: off, warn, strict.")
|
|
248
|
+
return value
|
|
249
|
+
|
|
250
|
+
|
|
251
|
+
def _normalize_verify_mode(value: str) -> str:
|
|
252
|
+
try:
|
|
253
|
+
return normalize_verify_mode(value)
|
|
254
|
+
except VerifyError as e:
|
|
255
|
+
raise ForgeError(str(e)) from e
|
|
256
|
+
|
|
257
|
+
|
|
258
|
+
def _remote_report_lines(record: dict[str, Any] | None) -> list[str]:
|
|
259
|
+
if not record:
|
|
260
|
+
return []
|
|
261
|
+
lines: list[str] = [
|
|
262
|
+
f"remote={record.get('remote') or '-'} provider={record.get('provider') or 'unknown'}",
|
|
263
|
+
(
|
|
264
|
+
f"pushed_branch={record.get('pushed_branch')} "
|
|
265
|
+
f"pushed_base={record.get('pushed_base')} "
|
|
266
|
+
f"created_pr={record.get('created_pr')}"
|
|
267
|
+
),
|
|
268
|
+
]
|
|
269
|
+
pr_url = str(record.get("pr_url") or "").strip()
|
|
270
|
+
if pr_url:
|
|
271
|
+
lines.append(f"pr_url={pr_url}")
|
|
272
|
+
pr_id = str(record.get("pr_number_or_iid") or "").strip()
|
|
273
|
+
if pr_id:
|
|
274
|
+
lines.append(f"pr_number_or_iid={pr_id}")
|
|
275
|
+
|
|
276
|
+
branch_push_output = str(record.get("branch_push_output") or "").strip()
|
|
277
|
+
if branch_push_output:
|
|
278
|
+
lines.append(f"branch_push_output={truncate_output(branch_push_output, max_chars=300)}")
|
|
279
|
+
base_push_output = str(record.get("base_push_output") or "").strip()
|
|
280
|
+
if base_push_output:
|
|
281
|
+
lines.append(f"base_push_output={truncate_output(base_push_output, max_chars=300)}")
|
|
282
|
+
pr_output = str(record.get("pr_output") or "").strip()
|
|
283
|
+
if pr_output:
|
|
284
|
+
lines.append(f"pr_output={truncate_output(pr_output, max_chars=300)}")
|
|
285
|
+
|
|
286
|
+
raw_errors = record.get("errors")
|
|
287
|
+
if isinstance(raw_errors, list):
|
|
288
|
+
for err in raw_errors:
|
|
289
|
+
msg = str(err).strip()
|
|
290
|
+
if msg:
|
|
291
|
+
lines.append(f"error={truncate_output(msg, max_chars=300)}")
|
|
292
|
+
return lines
|
|
293
|
+
|
|
294
|
+
|
|
295
|
+
def _print_usage_summary_from_logs(
|
|
296
|
+
*,
|
|
297
|
+
console: Console,
|
|
298
|
+
title: str,
|
|
299
|
+
log_paths: list[Path],
|
|
300
|
+
) -> None:
|
|
301
|
+
summary = aggregate_usage_from_session_logs(log_paths)
|
|
302
|
+
rows = summary.by_model_rows()
|
|
303
|
+
if not rows:
|
|
304
|
+
return
|
|
305
|
+
table = _Table(title=title)
|
|
306
|
+
table.add_column("model")
|
|
307
|
+
table.add_column("prompt_tokens", justify="right")
|
|
308
|
+
table.add_column("completion_tokens", justify="right")
|
|
309
|
+
table.add_column("total_tokens", justify="right")
|
|
310
|
+
table.add_column("cost_usd", justify="right")
|
|
311
|
+
table.add_column("unknown_pricing", justify="right")
|
|
312
|
+
table.add_column("usage_source(api/est)", justify="right")
|
|
313
|
+
for row in rows:
|
|
314
|
+
unknown_count = int(row.get("unknown_cost_count") or 0)
|
|
315
|
+
cost_display = _format_cost_with_unknown(
|
|
316
|
+
known_cost=_known_cost_value(row),
|
|
317
|
+
unknown_calls=unknown_count,
|
|
318
|
+
style="table",
|
|
319
|
+
)
|
|
320
|
+
table.add_row(
|
|
321
|
+
str(row.get("model") or "-"),
|
|
322
|
+
str(int(row.get("prompt_tokens") or 0)),
|
|
323
|
+
str(int(row.get("completion_tokens") or 0)),
|
|
324
|
+
str(int(row.get("total_tokens") or 0)),
|
|
325
|
+
cost_display,
|
|
326
|
+
str(unknown_count),
|
|
327
|
+
(f"{int(row.get('api_usage_calls') or 0)}/{int(row.get('estimate_usage_calls') or 0)}"),
|
|
328
|
+
)
|
|
329
|
+
totals = summary.totals()
|
|
330
|
+
total_cost = _format_cost_with_unknown(
|
|
331
|
+
known_cost=_known_cost_value(totals),
|
|
332
|
+
unknown_calls=int(totals.get("unknown_cost_calls") or 0),
|
|
333
|
+
style="table",
|
|
334
|
+
)
|
|
335
|
+
table.add_row(
|
|
336
|
+
"TOTAL",
|
|
337
|
+
str(int(totals.get("prompt_tokens") or 0)),
|
|
338
|
+
str(int(totals.get("completion_tokens") or 0)),
|
|
339
|
+
str(int(totals.get("total_tokens") or 0)),
|
|
340
|
+
total_cost,
|
|
341
|
+
str(int(totals.get("unknown_cost_calls") or 0)),
|
|
342
|
+
(
|
|
343
|
+
f"{int(totals.get('api_usage_calls') or 0)}/"
|
|
344
|
+
f"{int(totals.get('estimate_usage_calls') or 0)}"
|
|
345
|
+
),
|
|
346
|
+
)
|
|
347
|
+
console.print(table)
|
|
348
|
+
|
|
349
|
+
|
|
350
|
+
__all__ = [name for name in globals() if (not name.startswith("__") or name == "__version__")]
|