multi-forge 1.1.3__tar.gz → 1.1.4__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {multi_forge-1.1.3 → multi_forge-1.1.4}/.gitignore +4 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/PKG-INFO +4 -2
- {multi_forge-1.1.3 → multi_forge-1.1.4}/pyproject.toml +10 -6
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/backend/adapters/litellm.py +14 -10
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/cli/hooks/direct_commands.py +4 -6
- multi_forge-1.1.4/src/forge/cli/session_derived_preflight.py +41 -0
- multi_forge-1.1.4/src/forge/cli/session_effort_hint.py +78 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/cli/session_fork.py +13 -4
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/cli/session_launch_args.py +5 -1
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/cli/session_lifecycle.py +20 -19
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/cli/session_model.py +54 -2
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/cli/session_resume_modes.py +3 -2
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/cli/status_line.py +3 -1
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/cli/statusline/context.py +28 -5
- multi_forge-1.1.4/src/forge/cli/statusline/effort.py +37 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/cli/statusline/formatting.py +34 -77
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/cli/statusline/names.py +1 -2
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/cli/statusline/palette.py +1 -7
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/cli/statusline/registry.py +30 -48
- multi_forge-1.1.4/src/forge/cli/statusline/routing.py +50 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/cli/statusline/sources.py +10 -1
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/config/defaults/templates/openrouter-deepseek.yaml +3 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/config/defaults/templates/openrouter-kimi.yaml +4 -2
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/config/defaults/templates/openrouter-minimax.yaml +3 -1
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/core/data/model_catalog.yaml +72 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/core/data/model_routes.yaml +126 -0
- multi_forge-1.1.4/src/forge/core/effort_observation.py +31 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/core/invoker/codex.py +8 -2
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/core/invoker/codex_fork.py +3 -2
- multi_forge-1.1.4/src/forge/core/llm/clients/effort.py +19 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/core/llm/clients/litellm.py +41 -17
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/core/llm/clients/openai_compat.py +2 -3
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/core/llm/clients/openrouter.py +12 -1
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/core/llm/protocols.py +6 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/core/ops/claude_session.py +55 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/core/ops/codex_interactive.py +47 -1
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/core/ops/session.py +11 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/core/ops/session_fork_preflight.py +2 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/core/ops/session_model.py +60 -10
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/core/reactive/env.py +19 -1
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/core/reactive/reviewer_runtime.py +6 -1
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/core/reactive/reviewer_settings.py +15 -15
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/core/reactive/session_runner.py +24 -15
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/core/reactive/supervisor_auth.py +8 -6
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/core/run_id.py +30 -1
- multi_forge-1.1.4/src/forge/core/worker_controls.py +74 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/policy/semantic/supervisor.py +2 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/policy/team/handlers.py +1 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/proxy/client_adapter.py +5 -0
- multi_forge-1.1.4/src/forge/proxy/effort_observation.py +60 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/proxy/passthrough.py +5 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/proxy/passthrough_ingress.py +76 -2
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/proxy/reasoning.py +38 -24
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/proxy/runtime_truth.py +90 -12
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/proxy/server.py +24 -5
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/review/engine.py +5 -2
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/review/models.py +3 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/session/claude/invoke.py +2 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/session/codex_invoke.py +60 -5
- multi_forge-1.1.4/src/forge/session/derived_overrides.py +160 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/session/exceptions.py +10 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/session/launch_confirmation.py +8 -3
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/session/manager.py +19 -18
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/session/memory_writer.py +2 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/session/overrides.py +28 -4
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/session/rewind.py +3 -1
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/session/shadow_curation.py +2 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/session/transfer.py +64 -22
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/sidecar/container.py +17 -3
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/skills/qa/resources/checklist/4-proxy.md +3 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/skills/qa/resources/checklist.md +2 -2
- {multi_forge-1.1.3 → multi_forge-1.1.4}/LICENSE +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/NOTICE +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/README.md +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/agents/.gitkeep +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/commands/.gitkeep +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/__init__.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/backend/__init__.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/backend/adapters/__init__.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/backend/creation.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/backend/registry.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/backend/remote/__init__.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/backend/remote/base.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/backend/remote/openrouter.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/backend/sources.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/cli/__init__.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/cli/activity.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/cli/auth.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/cli/backend.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/cli/claude.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/cli/codex.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/cli/config_cmd.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/cli/consumer_lane_freeze.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/cli/editor.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/cli/extensions.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/cli/gc.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/cli/guards.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/cli/hooks/__init__.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/cli/hooks/_group.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/cli/hooks/_helpers.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/cli/hooks/authority.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/cli/hooks/codex_patch.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/cli/hooks/codex_policy.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/cli/hooks/codex_policy_feedback.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/cli/hooks/codex_stop.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/cli/hooks/codex_transfer.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/cli/hooks/commands.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/cli/hooks/policy.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/cli/hooks/protocols.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/cli/hooks/read_hygiene.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/cli/hooks/verification.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/cli/info.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/cli/logs.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/cli/main.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/cli/memory.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/cli/memory_report.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/cli/memory_writer.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/cli/model.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/cli/output.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/cli/policy.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/cli/proxy.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/cli/proxy_audit.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/cli/proxy_costs.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/cli/runtime.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/cli/search.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/cli/session.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/cli/session_adopt.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/cli/session_authority.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/cli/session_authority_options.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/cli/session_codex.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/cli/session_delete.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/cli/session_lane.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/cli/session_manage.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/cli/session_memory.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/cli/session_repair.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/cli/session_rewind.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/cli/session_route_recovery.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/cli/session_routing.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/cli/session_supervisor_options.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/cli/statusline/__init__.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/cli/statusline/rendering.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/cli/statusline/throttle.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/cli/statusline/types.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/cli/supervisor_auth.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/cli/telemetry.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/cli/trace.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/cli/transfer.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/cli/workflow.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/cli/workspace.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/config/__init__.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/config/dataclass_utils.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/config/defaults/__init__.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/config/defaults/backends/__init__.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/config/defaults/backends/litellm.yaml +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/config/defaults/templates/__init__.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/config/defaults/templates/anthropic-passthrough.yaml +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/config/defaults/templates/codex-responses-local.yaml +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/config/defaults/templates/litellm-anthropic-local.yaml +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/config/defaults/templates/litellm-anthropic.yaml +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/config/defaults/templates/litellm-gemini-flash-local.yaml +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/config/defaults/templates/litellm-gemini-local.yaml +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/config/defaults/templates/litellm-gemini-test.yaml +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/config/defaults/templates/litellm-gemini.yaml +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/config/defaults/templates/litellm-openai-codex-local.yaml +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/config/defaults/templates/litellm-openai-local.yaml +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/config/defaults/templates/litellm-openai.yaml +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/config/defaults/templates/openrouter-anthropic.yaml +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/config/defaults/templates/openrouter-gemini-flash.yaml +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/config/defaults/templates/openrouter-gemini.yaml +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/config/defaults/templates/openrouter-glm.yaml +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/config/defaults/templates/openrouter-openai-codex.yaml +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/config/defaults/templates/openrouter-openai.yaml +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/config/defaults/templates/openrouter-qwen.yaml +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/config/loader.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/config/schema.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/core/__init__.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/core/auth/__init__.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/core/auth/capabilities.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/core/auth/credentials_file.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/core/auth/protocols.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/core/auth/secrets.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/core/auth/template_secrets.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/core/backend_dependency.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/core/credential_registry.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/core/data/__init__.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/core/data/model_practices.yaml +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/core/data/system_prompt_addendums/__init__.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/core/data/system_prompt_addendums/gemini.md +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/core/data/system_prompt_addendums/openai.md +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/core/effort.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/core/identifiers.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/core/invoker/__init__.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/core/invoker/_lifecycle.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/core/invoker/claude.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/core/invoker/codex_stream.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/core/invoker/types.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/core/judgments/__init__.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/core/judgments/openrouter.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/core/judgments/types.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/core/judgments/usage.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/core/lanes.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/core/llm/__init__.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/core/llm/clients/__init__.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/core/llm/clients/base.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/core/llm/credentials.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/core/llm/detection.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/core/llm/errors.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/core/llm/openrouter_policy.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/core/llm/types.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/core/logging.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/core/metric_formatting.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/core/models/__init__.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/core/models/catalog.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/core/models/direct_model.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/core/models/model_practices.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/core/models/model_reference.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/core/models/model_routes.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/core/models/types.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/core/naming.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/core/native_review_types.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/core/ops/__init__.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/core/ops/backend_reconcile.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/core/ops/codex_adopt.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/core/ops/codex_bridge.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/core/ops/codex_enrollment.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/core/ops/codex_session.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/core/ops/codex_thread_index.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/core/ops/context.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/core/ops/gc.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/core/ops/policy.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/core/ops/provider_trace.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/core/ops/proxy.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/core/ops/resolution.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/core/ops/session_active.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/core/ops/session_adopt.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/core/ops/session_authority.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/core/ops/session_authority_launch.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/core/ops/session_context.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/core/ops/session_fork_execution.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/core/ops/session_model_routing.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/core/ops/session_repair.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/core/ops/session_routing.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/core/ops/transfer.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/core/ops/usage_summary.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/core/ops/workspace.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/core/paths.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/core/process.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/core/provider_types.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/core/reactive/__init__.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/core/reactive/codex_reviewer_home.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/core/reactive/cost_tracking.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/core/reactive/headless_json.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/core/reactive/llm_call.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/core/reactive/proxy.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/core/reactive/routing.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/core/reactive/structured_output.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/core/reactive/tagger.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/core/reactive/throttle.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/core/reactive/watchdog.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/core/runtime/__init__.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/core/runtime/codex_feedback.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/core/runtime/codex_preflight.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/core/runtime/codex_preflight_cache.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/core/runtime/codex_review_source.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/core/runtime/codex_rollouts.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/core/runtime/codex_turn_enrollment.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/core/runtime/launch_args.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/core/runtime/registry.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/core/runtime_vocab.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/core/state/__init__.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/core/state/exceptions.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/core/state/io.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/core/state/lock.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/core/state/retention.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/core/state/timestamps.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/core/state/versioned_store.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/core/telemetry/__init__.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/core/telemetry/caps.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/core/telemetry/downstream.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/core/telemetry/downstream_retention.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/core/telemetry/jsonl_io.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/core/telemetry/upstream.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/core/telemetry/vocabulary.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/core/tiers.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/core/transcript.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/core/typing_helpers.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/core/usage/__init__.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/core/usage/billing.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/core/usage/correlation.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/core/usage/emit.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/core/usage/ledger.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/core/usage/measurement.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/core/usage/vocabulary.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/core/wire_shapes.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/core/workqueue/__init__.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/core/workqueue/queue.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/core/workqueue/types.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/install/__init__.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/install/codex_hooks.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/install/doctor.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/install/exceptions.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/install/hook_dispatcher.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/install/hook_migration.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/install/hooks.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/install/installer.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/install/models.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/install/module_planning.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/install/ownership.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/install/path_policy.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/install/preset.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/install/project_compat.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/install/project_registry.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/install/runtime_removal.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/install/settings_merge.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/install/settings_rollback.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/install/skill_cache.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/install/skill_compiler.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/install/skill_planning.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/install/skill_validation.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/install/tracking.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/install/unmanaged.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/install/version.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/policy/__init__.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/policy/action_identity.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/policy/deterministic/__init__.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/policy/deterministic/base.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/policy/deterministic/coding_standards.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/policy/deterministic/registry.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/policy/deterministic/tdd.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/policy/diff.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/policy/engine.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/policy/protocols.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/policy/queries.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/policy/semantic/__init__.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/policy/semantic/attempts.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/policy/semantic/deadline.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/policy/semantic/identity.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/policy/semantic/native_codex.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/policy/semantic/plan_check.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/policy/semantic/plan_source.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/policy/semantic/shadow.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/policy/semantic/shadow_runner.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/policy/semantic/stop_review.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/policy/semantic/turn_evidence.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/policy/semantic/verdict.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/policy/store.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/policy/supervisor_lane_degrade.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/policy/team/__init__.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/policy/team/config.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/policy/team/prompts.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/policy/types.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/proxy/__init__.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/proxy/accounting_persistence.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/proxy/audit_logger.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/proxy/base_client.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/proxy/client_factory.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/proxy/converters.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/proxy/cost_logger.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/proxy/cost_tracker.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/proxy/data_models.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/proxy/error_hints.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/proxy/intercept.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/proxy/metrics.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/proxy/model_routes.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/proxy/ports.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/proxy/provider_trace_logger.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/proxy/proxies.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/proxy/proxy_identity.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/proxy/proxy_orchestrator.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/proxy/proxy_startup.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/proxy/request_id.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/proxy/response_headers.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/proxy/responses_ingress.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/proxy/responses_passthrough.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/proxy/sse_framing.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/proxy/stream_relay.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/proxy/utils.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/review/__init__.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/review/adversarial.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/review/backend_readiness.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/review/consensus.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/review/resources/__init__.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/review/resources/code_consensus_evaluation.md +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/review/resources/code_debate_evaluation.md +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/review/resources/codereview-performance.md +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/review/resources/codereview-quick.md +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/review/resources/codereview-security.md +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/review/resources/codereview.md +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/review/resources/consensus_evaluation.md +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/review/resources/debate_evaluation.md +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/review/resources/docreview-quick.md +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/review/resources/docreview.md +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/review/resources/thinkdeep.md +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/review/routing.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/review/synthesis.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/review/worker_preparation.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/runtime_config.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/search/__init__.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/search/bm25_store.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/search/cleanup.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/search/content_store.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/search/engine.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/search/exceptions.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/search/extractor.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/search/index_state.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/search/store.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/search/tokenizer.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/session/__init__.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/session/active.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/session/addendum.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/session/artifacts.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/session/authority.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/session/claude/__init__.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/session/claude/cleanup.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/session/claude/paths.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/session/claude/relocate.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/session/cleanup.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/session/cleanup_content.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/session/cleanup_dependencies.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/session/cleanup_git.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/session/cleanup_state.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/session/codex_handoff.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/session/config.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/session/consumer_lanes.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/session/context_limit.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/session/context_rendering.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/session/deletion.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/session/effective.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/session/events.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/session/git.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/session/hooks/__init__.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/session/hooks/models.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/session/hooks/producers.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/session/hooks/session_start.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/session/identity.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/session/index.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/session/launch.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/session/launchability.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/session/memory_inheritance.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/session/model_pin.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/session/models.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/session/passport.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/session/plan_resolution.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/session/prev_sessions.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/session/project_memory.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/session/purge_native.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/session/routing.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/session/store.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/session/validation.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/session/verification_config.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/session/workers.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/session/workspace.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/session/worktree/__init__.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/session/worktree/cleanup.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/session/worktree/config_copy.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/session/worktree/create.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/sidecar/__init__.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/sidecar/docker.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/skills/analyze/content.md +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/skills/analyze/forge-skill.yaml +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/skills/challenge/content.md +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/skills/challenge/forge-skill.yaml +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/skills/consensus/content.md +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/skills/consensus/forge-skill.yaml +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/skills/consensus/resources/synthesis.md +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/skills/debate/content.md +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/skills/debate/forge-skill.yaml +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/skills/panel/content.md +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/skills/panel/forge-skill.yaml +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/skills/panel/resources/synthesis.md +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/skills/qa/SKILL.md +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/skills/qa/resources/checklist/0-enable.md +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/skills/qa/resources/checklist/1-preflight.md +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/skills/qa/resources/checklist/10-resume.md +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/skills/qa/resources/checklist/11-config.md +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/skills/qa/resources/checklist/12-search.md +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/skills/qa/resources/checklist/13-policy.md +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/skills/qa/resources/checklist/14-workflow.md +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/skills/qa/resources/checklist/15-skills.md +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/skills/qa/resources/checklist/16-memory.md +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/skills/qa/resources/checklist/17-info.md +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/skills/qa/resources/checklist/18-disable.md +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/skills/qa/resources/checklist/19-uninstall.md +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/skills/qa/resources/checklist/2-extension.md +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/skills/qa/resources/checklist/20-cleanup.md +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/skills/qa/resources/checklist/3-authentication.md +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/skills/qa/resources/checklist/5-session.md +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/skills/qa/resources/checklist/6-hook.md +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/skills/qa/resources/checklist/7-costs.md +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/skills/qa/resources/checklist/8-status-line.md +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/skills/qa/resources/checklist/9-direct-commands.md +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/skills/qa/resources/coverage-map.md +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/skills/qa/resources/execution-budget.json +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/skills/qa/resources/report-template.md +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/skills/qa/resources/runtime-matrix.json +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/skills/qa/scripts/qa-artifact.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/skills/qa/scripts/qa-run-metrics.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/skills/qa/scripts/qa-selection.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/skills/qa/scripts/start-container.sh +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/skills/qa/scripts/walkthrough-state.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/skills/review/content.md +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/skills/review/forge-skill.yaml +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/skills/review/references/claude-4.6.md +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/skills/review/references/claude-4.8.md +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/skills/review/references/gemini-3.1.md +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/skills/review/references/gpt-5.5.md +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/skills/review/references/skills-writing-guide.md +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/skills/review/resources/code-anthropic.md +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/skills/review/resources/code-gemini.md +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/skills/review/resources/code-openai.md +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/skills/review/resources/code.md +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/skills/review-docs/content.md +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/skills/review-docs/forge-skill.yaml +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/skills/review-docs/resources/docs-anthropic.md +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/skills/review-docs/resources/docs-gemini.md +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/skills/review-docs/resources/docs-openai.md +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/skills/review-docs/resources/docs.md +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/skills/smoke-test/content.md +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/skills/smoke-test/forge-skill.yaml +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/skills/smoke-test/scripts/smoke-test.sh +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/skills/understand/content.md +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/skills/understand/forge-skill.yaml +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/skills/understand/resources/code-anthropic.md +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/skills/understand/resources/code-gemini.md +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/skills/understand/resources/code-openai.md +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/skills/understand/resources/code.md +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/skills/understand/resources/docs-anthropic.md +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/skills/understand/resources/docs-gemini.md +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/skills/understand/resources/docs-openai.md +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/skills/understand/resources/docs.md +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/skills/walkthrough/SKILL.md +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/skills/walkthrough/resources/checklist.md +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/skills/walkthrough/resources/journey-map.md +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/skills/walkthrough/scripts/claude-wrapper.sh +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/skills/walkthrough/scripts/cleanup-owned.sh +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/skills/walkthrough/scripts/package-identity.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/skills/walkthrough/scripts/protected-paths.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/skills/walkthrough/scripts/run-in-repo.sh +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/skills/walkthrough/scripts/setup-test-repo.sh +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/skills/walkthrough/scripts/walkthrough-report.py +0 -0
- {multi_forge-1.1.3 → multi_forge-1.1.4}/src/skills/walkthrough/scripts/walkthrough-state.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: multi-forge
|
|
3
|
-
Version: 1.1.
|
|
3
|
+
Version: 1.1.4
|
|
4
4
|
Summary: Multi-runtime agent toolkit: proxy routing, cost control, session management, policy enforcement, and workflow orchestration
|
|
5
5
|
Project-URL: Homepage, https://github.com/hapa1i/multi-forge
|
|
6
6
|
Project-URL: Repository, https://github.com/hapa1i/multi-forge
|
|
@@ -30,11 +30,13 @@ Requires-Dist: click>=8.3.1
|
|
|
30
30
|
Requires-Dist: coolname<6,>=5.0.0
|
|
31
31
|
Requires-Dist: cryptography>=50.0.0
|
|
32
32
|
Requires-Dist: dacite>=1.8.0
|
|
33
|
+
Requires-Dist: dnspython>=2.9.0
|
|
33
34
|
Requires-Dist: expression<6,>=5.6.0
|
|
34
35
|
Requires-Dist: fastapi-sso<1,>=0.19.0
|
|
35
36
|
Requires-Dist: fastapi<0.137,>=0.136.3
|
|
37
|
+
Requires-Dist: filelock>=4.2.1
|
|
36
38
|
Requires-Dist: httpx>=0.25.0
|
|
37
|
-
Requires-Dist: litellm==1.102.
|
|
39
|
+
Requires-Dist: litellm==1.102.2
|
|
38
40
|
Requires-Dist: multidict<7,>=6.9.1
|
|
39
41
|
Requires-Dist: oauthlib<5,>=4.0.0
|
|
40
42
|
Requires-Dist: openai>=1.0.0
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "multi-forge"
|
|
3
|
-
version = "1.1.
|
|
3
|
+
version = "1.1.4"
|
|
4
4
|
description = "Multi-runtime agent toolkit: proxy routing, cost control, session management, policy enforcement, and workflow orchestration"
|
|
5
5
|
readme = "README.md"
|
|
6
6
|
license = "Apache-2.0"
|
|
@@ -42,7 +42,7 @@ dependencies = [
|
|
|
42
42
|
# Proxy dependencies (previously optional, now core). Forge owns the
|
|
43
43
|
# default-Uvicorn LiteLLM startup set because the upstream `proxy` extra
|
|
44
44
|
# caps cryptography below Forge's patched floor. This set is start/health
|
|
45
|
-
# validated through LiteLLM 1.102.
|
|
45
|
+
# validated through LiteLLM 1.102.2; run scripts/test-wheel-runtime.sh before
|
|
46
46
|
# raising the ceiling. Alternate servers, databases, and cloud integrations
|
|
47
47
|
# remain outside Forge's runtime path.
|
|
48
48
|
"aiohttp>=3.14.4,<4",
|
|
@@ -53,11 +53,15 @@ dependencies = [
|
|
|
53
53
|
# Exclude the compromised CA trust roots from clean installations too.
|
|
54
54
|
"certifi>=2026.10.19",
|
|
55
55
|
"cryptography>=50.0.0",
|
|
56
|
+
# Keep email-validator's transitive DNS security floor in wheel metadata despite no direct Forge import.
|
|
57
|
+
"dnspython>=2.9.0",
|
|
56
58
|
# LiteLLM 1.95 imports outbound-credential tagged unions at startup.
|
|
57
59
|
"expression>=5.6.0,<6",
|
|
58
60
|
# Keep FastAPI's lock-proven route-tree behavior; upgrade it separately.
|
|
59
61
|
"fastapi>=0.136.3,<0.137",
|
|
60
62
|
"fastapi-sso>=0.19.0,<1",
|
|
63
|
+
# Keep huggingface-hub's transitive file-lock security floor in wheel metadata despite no direct Forge import.
|
|
64
|
+
"filelock>=4.2.1",
|
|
61
65
|
# Runtime security floors belong in wheel metadata, not only uv constraints.
|
|
62
66
|
"multidict>=6.9.1,<7",
|
|
63
67
|
"oauthlib>=4.0.0,<5",
|
|
@@ -75,7 +79,7 @@ dependencies = [
|
|
|
75
79
|
"watchfiles>=0.20",
|
|
76
80
|
"websockets>=15.0.1,<16",
|
|
77
81
|
# Packaged Gemini 3.8 Flash metadata and the verified proxy runtime.
|
|
78
|
-
"litellm==1.102.
|
|
82
|
+
"litellm==1.102.2",
|
|
79
83
|
]
|
|
80
84
|
|
|
81
85
|
[project.scripts]
|
|
@@ -165,8 +169,7 @@ build-constraint-dependencies = [
|
|
|
165
169
|
"trove-classifiers==2026.9.21.13",
|
|
166
170
|
]
|
|
167
171
|
constraint-dependencies = [
|
|
168
|
-
"
|
|
169
|
-
"virtualenv>=21.14.12",
|
|
172
|
+
"virtualenv>=21.14.13",
|
|
170
173
|
"mcp>=1.28.1",
|
|
171
174
|
"Pygments>=2.20.0",
|
|
172
175
|
"pyasn1>=0.6.4",
|
|
@@ -185,8 +188,9 @@ dev = [
|
|
|
185
188
|
"pytest-cov>=4.1.0",
|
|
186
189
|
"pytest-asyncio>=0.23.0",
|
|
187
190
|
"pytest-mock>=3.15.1",
|
|
191
|
+
"pytest-xdist>=3.8.0",
|
|
188
192
|
"ruff>=0.15.0",
|
|
189
|
-
"black>=26.
|
|
193
|
+
"black>=26.10.1",
|
|
190
194
|
"mypy>=1.13.0",
|
|
191
195
|
"pyright>=1.1.0",
|
|
192
196
|
"pytest-rerunfailures>=14.0",
|
|
@@ -24,6 +24,8 @@ from forge.backend.registry import ManagedBackendProcess
|
|
|
24
24
|
from forge.core.paths import get_forge_home
|
|
25
25
|
from forge.core.state import now_iso
|
|
26
26
|
|
|
27
|
+
STARTUP_HEALTH_TIMEOUT_S = 30.0
|
|
28
|
+
|
|
27
29
|
|
|
28
30
|
class LiteLLMAdapter(BackendAdapter):
|
|
29
31
|
"""Adapter for managing LiteLLM backend processes.
|
|
@@ -38,7 +40,7 @@ class LiteLLMAdapter(BackendAdapter):
|
|
|
38
40
|
which checks BackendDependency.required_env_vars before starting.
|
|
39
41
|
"""
|
|
40
42
|
|
|
41
|
-
def _wait_for_health(self, port: int, timeout: float =
|
|
43
|
+
def _wait_for_health(self, port: int, timeout: float = STARTUP_HEALTH_TIMEOUT_S) -> bool:
|
|
42
44
|
"""Wait for backend to become healthy.
|
|
43
45
|
|
|
44
46
|
Uses /health/liveliness (not /health) because the full health endpoint
|
|
@@ -53,18 +55,20 @@ class LiteLLMAdapter(BackendAdapter):
|
|
|
53
55
|
Returns:
|
|
54
56
|
True if healthy within timeout, False otherwise
|
|
55
57
|
"""
|
|
56
|
-
|
|
58
|
+
deadline = time.monotonic() + timeout
|
|
57
59
|
url = f"http://localhost:{port}/health/liveliness"
|
|
58
60
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
response = client.get(url)
|
|
61
|
+
with httpx.Client(timeout=httpx.Timeout(2.0)) as client:
|
|
62
|
+
while (remaining := deadline - time.monotonic()) > 0:
|
|
63
|
+
try:
|
|
64
|
+
response = client.get(url, timeout=min(2.0, remaining))
|
|
63
65
|
if response.status_code == 200:
|
|
64
66
|
return True
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
67
|
+
except httpx.RequestError:
|
|
68
|
+
pass
|
|
69
|
+
remaining = deadline - time.monotonic()
|
|
70
|
+
if remaining > 0:
|
|
71
|
+
time.sleep(min(0.5, remaining))
|
|
68
72
|
|
|
69
73
|
return False
|
|
70
74
|
|
|
@@ -107,7 +111,7 @@ class LiteLLMAdapter(BackendAdapter):
|
|
|
107
111
|
start_new_session=True, # Detach from parent
|
|
108
112
|
)
|
|
109
113
|
|
|
110
|
-
if not self._wait_for_health(port, timeout=
|
|
114
|
+
if not self._wait_for_health(port, timeout=STARTUP_HEALTH_TIMEOUT_S):
|
|
111
115
|
try:
|
|
112
116
|
os.killpg(proc.pid, signal.SIGKILL)
|
|
113
117
|
except ProcessLookupError:
|
|
@@ -213,10 +213,7 @@ def _handle_session_model(argv: list[str]) -> None:
|
|
|
213
213
|
|
|
214
214
|
from forge.core.ops.context import ExecutionContext
|
|
215
215
|
from forge.core.ops.session import ForgeOpError
|
|
216
|
-
from forge.core.ops.session_model import
|
|
217
|
-
MODEL_REPORT_LIMITATIONS,
|
|
218
|
-
get_session_model_report,
|
|
219
|
-
)
|
|
216
|
+
from forge.core.ops.session_model import get_session_model_report
|
|
220
217
|
from forge.session.exceptions import ForgeSessionError
|
|
221
218
|
|
|
222
219
|
try:
|
|
@@ -232,10 +229,11 @@ def _handle_session_model(argv: list[str]) -> None:
|
|
|
232
229
|
return
|
|
233
230
|
from forge.cli.session_model import session_model_summary_rows
|
|
234
231
|
|
|
232
|
+
payload = report.to_dict()
|
|
235
233
|
lines = ["Session model:"]
|
|
236
|
-
lines.extend(f" {field}: {value}" for field, value in session_model_summary_rows(
|
|
234
|
+
lines.extend(f" {field}: {value}" for field, value in session_model_summary_rows(payload))
|
|
237
235
|
lines.append("Limitations:")
|
|
238
|
-
lines.extend(f" - {limitation}" for limitation in
|
|
236
|
+
lines.extend(f" - {limitation}" for limitation in payload["limitations"])
|
|
239
237
|
click.echo(json.dumps({"decision": "block", "reason": "\n".join(lines)}))
|
|
240
238
|
|
|
241
239
|
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
"""Early structural admission and recovery for CLI session derivation."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import sys
|
|
6
|
+
|
|
7
|
+
from forge.cli.output import err_console, handle_session_error, print_error, print_tip
|
|
8
|
+
from forge.session.derived_overrides import validate_derived_session_overrides
|
|
9
|
+
from forge.session.exceptions import (
|
|
10
|
+
ForgeSessionError,
|
|
11
|
+
ManifestCorruptedError,
|
|
12
|
+
ManifestValidationError,
|
|
13
|
+
)
|
|
14
|
+
from forge.session.models import SessionState
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
def handle_derived_session_error(error: ForgeSessionError) -> None:
|
|
18
|
+
"""Keep strict manifest failures on the explicit repair/restoration path."""
|
|
19
|
+
if isinstance(error, (ManifestCorruptedError, ManifestValidationError)):
|
|
20
|
+
# The legacy version diagnostic embeds deletion advice in its reason.
|
|
21
|
+
reason = error.reason.removesuffix(" Delete this session and recreate it.")
|
|
22
|
+
print_error(f"Invalid session manifest at '{error.path}': {reason}")
|
|
23
|
+
print_tip(
|
|
24
|
+
"Repair the named manifest explicitly or restore a known-good copy before retrying.", console=err_console
|
|
25
|
+
)
|
|
26
|
+
sys.exit(1)
|
|
27
|
+
handle_session_error(error)
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
def preflight_resume(state: SessionState, *, fresh: bool, force_resumable: bool) -> None:
|
|
31
|
+
"""Validate only resume paths that will derive a child, before realizing routing."""
|
|
32
|
+
from forge.cli.session import _peek_active_session_entry
|
|
33
|
+
|
|
34
|
+
if not fresh and (
|
|
35
|
+
not force_resumable or _peek_active_session_entry(state.name, forge_root=state.forge_root) is None
|
|
36
|
+
):
|
|
37
|
+
return
|
|
38
|
+
try:
|
|
39
|
+
validate_derived_session_overrides(state)
|
|
40
|
+
except ForgeSessionError as error:
|
|
41
|
+
handle_derived_session_error(error)
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
"""Launch-only guidance for translated managed Claude sessions."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import shlex
|
|
6
|
+
from pathlib import Path
|
|
7
|
+
|
|
8
|
+
import click
|
|
9
|
+
|
|
10
|
+
from forge.cli.output import err_console, print_tip
|
|
11
|
+
from forge.core.ops.claude_session import ClaudeLaunchReady
|
|
12
|
+
from forge.core.wire_shapes import ANTHROPIC_PASSTHROUGH
|
|
13
|
+
from forge.session.artifacts import resolve_forge_root
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
def print_derived_effort_hint(event: ClaudeLaunchReady) -> None:
|
|
17
|
+
"""Explain derived effort using the existing launch-time proxy snapshot."""
|
|
18
|
+
ctx = click.get_current_context(silent=True)
|
|
19
|
+
runtime = event.runtime
|
|
20
|
+
if (
|
|
21
|
+
ctx is None
|
|
22
|
+
or ctx.parent is None
|
|
23
|
+
or ctx.parent.command.name != "session"
|
|
24
|
+
or ctx.command.name not in {"start", "resume", "fork", "incognito"}
|
|
25
|
+
or ctx.params.get("effort") is not None
|
|
26
|
+
or ctx.params.get("no_launch")
|
|
27
|
+
or ctx.params.get("json_output")
|
|
28
|
+
or ctx.params.get("json")
|
|
29
|
+
or not (event.template or event.proxy_id)
|
|
30
|
+
or runtime is None
|
|
31
|
+
or not runtime.is_proxy
|
|
32
|
+
or runtime.wire_shape is None
|
|
33
|
+
or runtime.wire_shape == ANTHROPIC_PASSTHROUGH
|
|
34
|
+
):
|
|
35
|
+
return
|
|
36
|
+
if event.template is not None and runtime.template != event.template:
|
|
37
|
+
return
|
|
38
|
+
if event.proxy_id is not None and runtime.proxy_id != event.proxy_id:
|
|
39
|
+
return
|
|
40
|
+
proxy_runtime = runtime.raw.get("runtime")
|
|
41
|
+
defaults = proxy_runtime.get("llm_defaults_by_tier") if isinstance(proxy_runtime, dict) else None
|
|
42
|
+
defaults = defaults if isinstance(defaults, dict) else {}
|
|
43
|
+
projected_tier = event.model_route.selected_tier if event.model_route else None
|
|
44
|
+
minimum = "the selected tier minimum"
|
|
45
|
+
floors = []
|
|
46
|
+
for tier in ("haiku", "sonnet", "opus"):
|
|
47
|
+
if projected_tier is not None and projected_tier != tier:
|
|
48
|
+
continue
|
|
49
|
+
tier_defaults = defaults.get(tier)
|
|
50
|
+
floor = tier_defaults.get("reasoning_effort") if isinstance(tier_defaults, dict) else None
|
|
51
|
+
if isinstance(floor, str) and floor in {"none", "minimal", "low", "medium", "high", "xhigh", "max"}:
|
|
52
|
+
floors.append(f"{tier}: {floor}")
|
|
53
|
+
if floors:
|
|
54
|
+
label = "configured minimums: " if projected_tier is None else ""
|
|
55
|
+
minimum += f" ({label}{', '.join(floors)})"
|
|
56
|
+
|
|
57
|
+
# Creation has already committed, including unnamed forks and fresh resumes.
|
|
58
|
+
# Durable route intent makes a short resume command sufficient on the next launch.
|
|
59
|
+
args = ["forge", "session", "resume", event.session]
|
|
60
|
+
guidance = "After exiting, opt in to client effort with:"
|
|
61
|
+
if event.incognito:
|
|
62
|
+
args = ["forge", "session", "incognito", "--proxy", event.proxy_id or event.template or ""]
|
|
63
|
+
if event.model_route is not None:
|
|
64
|
+
args.extend(["--model", event.model_route.requested_model, "--model-tier", event.model_route.selected_tier])
|
|
65
|
+
elif event.direct_model is not None:
|
|
66
|
+
args.extend(["--model", event.direct_model])
|
|
67
|
+
guidance = "This incognito session is deleted on exit. Opt in on a new incognito launch with:"
|
|
68
|
+
args.extend(["--effort", "<level>"])
|
|
69
|
+
command = shlex.join(args)
|
|
70
|
+
if not event.incognito and event.forge_root and Path(event.forge_root).resolve() != resolve_forge_root(Path.cwd()):
|
|
71
|
+
command = f"cd {shlex.quote(event.forge_root)} && {command}"
|
|
72
|
+
print_tip(
|
|
73
|
+
f"Effort is derived from thinking and {minimum}.",
|
|
74
|
+
guidance,
|
|
75
|
+
commands=[command],
|
|
76
|
+
blank_before=False,
|
|
77
|
+
console=err_console,
|
|
78
|
+
)
|
|
@@ -17,12 +17,13 @@ from forge.cli.session import ( # noqa: E402
|
|
|
17
17
|
_print_routing_summary,
|
|
18
18
|
_resolve_routing_from_cli,
|
|
19
19
|
console,
|
|
20
|
-
handle_session_error,
|
|
21
20
|
)
|
|
22
21
|
from forge.cli.session_authority_options import (
|
|
23
22
|
authority_creation_options,
|
|
24
23
|
parse_creation_authority,
|
|
25
24
|
)
|
|
25
|
+
from forge.cli.session_derived_preflight import handle_derived_session_error
|
|
26
|
+
from forge.cli.session_effort_hint import ClaudeLaunchReady, print_derived_effort_hint
|
|
26
27
|
from forge.cli.session_launch_args import (
|
|
27
28
|
RuntimePassthroughCommand,
|
|
28
29
|
checked_launch_args,
|
|
@@ -116,6 +117,9 @@ class _ClaudeForkCliPresenter:
|
|
|
116
117
|
def before_launch(self, forge_root: Path) -> None:
|
|
117
118
|
_warn_before_claude_launch(forge_root)
|
|
118
119
|
|
|
120
|
+
def on_launch_ready(self, event: ClaudeLaunchReady) -> None:
|
|
121
|
+
print_derived_effort_hint(event)
|
|
122
|
+
|
|
119
123
|
def on_routing_payload(self, payload: dict[str, Any]) -> None:
|
|
120
124
|
_render_model_route_payload(payload)
|
|
121
125
|
|
|
@@ -327,7 +331,12 @@ def _render_fork_execution_error(error: ForkExecutionError) -> None:
|
|
|
327
331
|
default=None,
|
|
328
332
|
help=_MODEL_TIER_HELP,
|
|
329
333
|
)
|
|
330
|
-
@click.option(
|
|
334
|
+
@click.option(
|
|
335
|
+
"--incognito",
|
|
336
|
+
"-i",
|
|
337
|
+
is_flag=True,
|
|
338
|
+
help="Attempt guarded purge of the fork after runtime exit",
|
|
339
|
+
)
|
|
331
340
|
@click.option("--worktree", "-w", is_flag=True, help="Create git worktree for fork isolation")
|
|
332
341
|
@click.option("--branch", "-b", help="Override branch name (implies --worktree)")
|
|
333
342
|
@click.option("--no-launch", is_flag=True, help="Create fork without launching Claude")
|
|
@@ -556,7 +565,7 @@ def fork(
|
|
|
556
565
|
print_error(f"session '{parent}' not found")
|
|
557
566
|
sys.exit(1)
|
|
558
567
|
except ForgeSessionError as e:
|
|
559
|
-
|
|
568
|
+
handle_derived_session_error(e)
|
|
560
569
|
return
|
|
561
570
|
|
|
562
571
|
for notice in preflight.notices:
|
|
@@ -741,7 +750,7 @@ def fork(
|
|
|
741
750
|
print_error(f"session '{parent}' not found")
|
|
742
751
|
sys.exit(1)
|
|
743
752
|
except ForgeSessionError as e:
|
|
744
|
-
|
|
753
|
+
handle_derived_session_error(e)
|
|
745
754
|
return
|
|
746
755
|
|
|
747
756
|
for event in execution.events:
|
|
@@ -72,7 +72,11 @@ def checked_launch_args(
|
|
|
72
72
|
print_error("--effort and runtime arguments after '--' apply only to a launch; drop them or --no-launch")
|
|
73
73
|
sys.exit(1)
|
|
74
74
|
try:
|
|
75
|
-
return validate_launch_args(
|
|
75
|
+
return validate_launch_args(
|
|
76
|
+
args,
|
|
77
|
+
runtime=runtime,
|
|
78
|
+
advisory=authority is not None and authority.is_advisory,
|
|
79
|
+
)
|
|
76
80
|
except LaunchArgsError as e:
|
|
77
81
|
print_error(str(e))
|
|
78
82
|
sys.exit(1)
|
|
@@ -36,6 +36,10 @@ from forge.cli.session import ( # noqa: E402
|
|
|
36
36
|
logger,
|
|
37
37
|
)
|
|
38
38
|
from forge.cli.session import session as _session_untyped # noqa: E402
|
|
39
|
+
from forge.cli.session_derived_preflight import (
|
|
40
|
+
handle_derived_session_error,
|
|
41
|
+
preflight_resume,
|
|
42
|
+
)
|
|
39
43
|
from forge.core.models.direct_model import (
|
|
40
44
|
resolve_direct_model_pin,
|
|
41
45
|
token_estimate_multiplier_for_direct_model,
|
|
@@ -106,6 +110,7 @@ from forge.session.transfer import ResumeStrategy, parse_lineage_depth
|
|
|
106
110
|
|
|
107
111
|
session = cast(click.Group, _session_untyped) # type: ignore[has-type] # circular re-export
|
|
108
112
|
|
|
113
|
+
from forge.cli import session_effort_hint as effort_hint # noqa: E402
|
|
109
114
|
from forge.cli.session_authority_options import ( # noqa: E402
|
|
110
115
|
authority_creation_options,
|
|
111
116
|
parse_creation_authority,
|
|
@@ -618,6 +623,9 @@ class _ClaudeStartCliPresenter:
|
|
|
618
623
|
def before_launch(self, forge_root: Path) -> None:
|
|
619
624
|
_warn_before_claude_launch(forge_root)
|
|
620
625
|
|
|
626
|
+
def on_launch_ready(self, event: effort_hint.ClaudeLaunchReady) -> None:
|
|
627
|
+
effort_hint.print_derived_effort_hint(event)
|
|
628
|
+
|
|
621
629
|
def on_routing_payload(self, payload: dict[str, Any]) -> None:
|
|
622
630
|
_render_model_route_payload(payload)
|
|
623
631
|
|
|
@@ -690,6 +698,9 @@ class _ClaudeResumeCliPresenter:
|
|
|
690
698
|
def before_launch(self, forge_root: Path) -> None:
|
|
691
699
|
_warn_before_claude_launch(forge_root)
|
|
692
700
|
|
|
701
|
+
def on_launch_ready(self, event: effort_hint.ClaudeLaunchReady) -> None:
|
|
702
|
+
effort_hint.print_derived_effort_hint(event)
|
|
703
|
+
|
|
693
704
|
def on_routing_payload(self, payload: dict[str, Any]) -> None:
|
|
694
705
|
_render_model_route_payload(payload)
|
|
695
706
|
|
|
@@ -1542,10 +1553,10 @@ def resume(
|
|
|
1542
1553
|
)
|
|
1543
1554
|
sys.exit(1)
|
|
1544
1555
|
except ForgeSessionError as e:
|
|
1545
|
-
handle_session_error(e)
|
|
1556
|
+
(handle_derived_session_error if fresh or force else handle_session_error)(e)
|
|
1546
1557
|
return
|
|
1547
1558
|
except ForgeSessionError as e:
|
|
1548
|
-
handle_session_error(e)
|
|
1559
|
+
(handle_derived_session_error if fresh or force else handle_session_error)(e)
|
|
1549
1560
|
return
|
|
1550
1561
|
|
|
1551
1562
|
from forge.session.launchability import require_session_worktree
|
|
@@ -1597,8 +1608,10 @@ def resume(
|
|
|
1597
1608
|
|
|
1598
1609
|
enforce_target_project_compatibility(Path(target_forge_root))
|
|
1599
1610
|
|
|
1600
|
-
|
|
1601
|
-
|
|
1611
|
+
preflight_resume(manifest, fresh=fresh, force_resumable=force and _has_confirmed_claude_session(manifest))
|
|
1612
|
+
|
|
1613
|
+
# A --fresh child can select authority explicitly. Active --force relaunch
|
|
1614
|
+
# applies advisory-only inheritance when it creates the child below.
|
|
1602
1615
|
launched_authority = manifest.intent.authority
|
|
1603
1616
|
if fresh:
|
|
1604
1617
|
launched_authority = authority if authority_explicit else inherited_authority(manifest.intent.authority)
|
|
@@ -1855,7 +1868,7 @@ def resume(
|
|
|
1855
1868
|
render_model_route=render_model_route,
|
|
1856
1869
|
launch_args=launch_args,
|
|
1857
1870
|
)
|
|
1858
|
-
|
|
1871
|
+
else:
|
|
1859
1872
|
active_entry = _get_active_session_entry(name, forge_root=manifest.forge_root)
|
|
1860
1873
|
if active_entry is not None and not force:
|
|
1861
1874
|
print_error(
|
|
@@ -1901,18 +1914,6 @@ def resume(
|
|
|
1901
1914
|
render_model_route=render_model_route,
|
|
1902
1915
|
launch_args=launch_args,
|
|
1903
1916
|
)
|
|
1904
|
-
else:
|
|
1905
|
-
_launch_as_child(
|
|
1906
|
-
manager=manager,
|
|
1907
|
-
parent_name=name,
|
|
1908
|
-
parent=manifest,
|
|
1909
|
-
routing=routing,
|
|
1910
|
-
direct=direct,
|
|
1911
|
-
direct_model_override=normalized_direct_model,
|
|
1912
|
-
model_route_selection=model_route_selection,
|
|
1913
|
-
render_model_route=render_model_route,
|
|
1914
|
-
launch_args=launch_args,
|
|
1915
|
-
)
|
|
1916
1917
|
|
|
1917
1918
|
|
|
1918
1919
|
def _launch_in_place(
|
|
@@ -2079,7 +2080,7 @@ def _launch_as_child(
|
|
|
2079
2080
|
try:
|
|
2080
2081
|
parent, child = manager.relaunch_session(parent_name, forge_root=parent.forge_root)
|
|
2081
2082
|
except ForgeSessionError as e:
|
|
2082
|
-
|
|
2083
|
+
handle_derived_session_error(e)
|
|
2083
2084
|
return
|
|
2084
2085
|
|
|
2085
2086
|
context_limit = (
|
|
@@ -2233,7 +2234,7 @@ def _resume_fresh(
|
|
|
2233
2234
|
authority_explicit=authority_explicit,
|
|
2234
2235
|
)
|
|
2235
2236
|
except ForgeSessionError as e:
|
|
2236
|
-
|
|
2237
|
+
handle_derived_session_error(e)
|
|
2237
2238
|
return
|
|
2238
2239
|
except ValueError as e:
|
|
2239
2240
|
print_error(str(e))
|
|
@@ -8,6 +8,7 @@ from typing import Any
|
|
|
8
8
|
|
|
9
9
|
import click
|
|
10
10
|
from rich.table import Table
|
|
11
|
+
from rich.text import Text
|
|
11
12
|
|
|
12
13
|
from forge.cli.output import err_console, print_error
|
|
13
14
|
from forge.cli.session import console
|
|
@@ -45,7 +46,7 @@ def show_cmd(session_name: str | None, as_json: bool) -> None:
|
|
|
45
46
|
table.add_column("Field", style="bold")
|
|
46
47
|
table.add_column("Value")
|
|
47
48
|
for field, value in session_model_summary_rows(payload):
|
|
48
|
-
table.add_row(field, value)
|
|
49
|
+
table.add_row(field, Text(value))
|
|
49
50
|
console.print(table)
|
|
50
51
|
console.print("\n[bold]Limitations[/bold]")
|
|
51
52
|
for limitation in payload["limitations"]:
|
|
@@ -100,16 +101,67 @@ def session_model_summary_rows(payload: dict[str, Any]) -> list[tuple[str, str]]
|
|
|
100
101
|
("Runtime", payload["runtime"]),
|
|
101
102
|
("Active", "yes" if payload["active"] else "no"),
|
|
102
103
|
("Intent", payload["route_intent"]["kind"]),
|
|
103
|
-
(
|
|
104
|
+
(
|
|
105
|
+
"Committed route",
|
|
106
|
+
commit["kind"] if commit and commit["kind"] else "unavailable",
|
|
107
|
+
),
|
|
104
108
|
("Route evidence", commit["evidence_source"] if commit else "none"),
|
|
105
109
|
("History", payload["history_status"] or "no claim"),
|
|
106
110
|
("Live proxy", live["evidence_source"]),
|
|
107
111
|
("Default tier", live["default_tier"] or "-"),
|
|
108
112
|
("Launch marking entries", str(len(payload["marking"]["launch_entries"]))),
|
|
109
113
|
("Live marking entries", str(len(payload["marking"]["live_proxy_entries"]))),
|
|
114
|
+
*_effort_summary_rows(payload["effort"]),
|
|
110
115
|
]
|
|
111
116
|
|
|
112
117
|
|
|
118
|
+
def _effort_summary_rows(effort: dict[str, Any]) -> list[tuple[str, str]]:
|
|
119
|
+
if effort["status"] != "observed":
|
|
120
|
+
reason = str(effort["reason"] or "unavailable").replace("_", " ")
|
|
121
|
+
return [("Effort", f"unknown ({reason})")]
|
|
122
|
+
|
|
123
|
+
rows = [
|
|
124
|
+
("Effort launch", effort["launch_id"]),
|
|
125
|
+
("Effort backend", effort["backend_id"] or "unknown"),
|
|
126
|
+
]
|
|
127
|
+
for tier in ("opus", "sonnet", "haiku"):
|
|
128
|
+
record = effort["observations"].get(tier)
|
|
129
|
+
if record is None:
|
|
130
|
+
continue
|
|
131
|
+
label = tier.capitalize()
|
|
132
|
+
opt_in = "yes" if record["opt_in"] else "no"
|
|
133
|
+
applicable = "yes" if record["client_applicable"] else "no"
|
|
134
|
+
used = "yes" if record["source"] == "client" else "no"
|
|
135
|
+
supported = ", ".join(record["supported"]) if record["supported"] is not None else "not catalogued"
|
|
136
|
+
applied = "dropped" if record["wire"] == "dropped" else record["applied"] or "unset"
|
|
137
|
+
rows.extend(
|
|
138
|
+
[
|
|
139
|
+
(f"{label} effort", applied),
|
|
140
|
+
(f"{label} requested", record["requested"] or "unset"),
|
|
141
|
+
(
|
|
142
|
+
f"{label} client effort",
|
|
143
|
+
f"opt-in: {opt_in}; applicable: {applicable}; used: {used}",
|
|
144
|
+
),
|
|
145
|
+
(f"{label} thinking", record["thinking"] or "unset"),
|
|
146
|
+
(f"{label} derived", record["derived"] or "unset"),
|
|
147
|
+
(f"{label} minimum", record["floor"] or "unset"),
|
|
148
|
+
(f"{label} pre-clamp", record["pre_clamp"] or "unset"),
|
|
149
|
+
(f"{label} supported", supported),
|
|
150
|
+
(
|
|
151
|
+
f"{label} resolved",
|
|
152
|
+
f"{record['resolved'] or 'unset'} ({record['source']})",
|
|
153
|
+
),
|
|
154
|
+
(f"{label} tier source", record["tier_source"]),
|
|
155
|
+
(f"{label} model", record["mapped_model"]),
|
|
156
|
+
(f"{label} wire", record["wire"] or "unset"),
|
|
157
|
+
(f"{label} observed", record["observed_at"]),
|
|
158
|
+
]
|
|
159
|
+
)
|
|
160
|
+
if record["note"]:
|
|
161
|
+
rows.append((f"{label} note", record["note"]))
|
|
162
|
+
return rows
|
|
163
|
+
|
|
164
|
+
|
|
113
165
|
def _model_slot_summary(snapshots: object) -> str:
|
|
114
166
|
if not isinstance(snapshots, list):
|
|
115
167
|
return "-"
|
|
@@ -6,6 +6,7 @@ import sys
|
|
|
6
6
|
from pathlib import Path
|
|
7
7
|
|
|
8
8
|
from forge.cli.output import console, handle_session_error, print_error_with_tip
|
|
9
|
+
from forge.cli.session_derived_preflight import handle_derived_session_error
|
|
9
10
|
from forge.cli.session_routing import ResolvedRouting
|
|
10
11
|
from forge.core.ops.claude_session import ClaudeResumeAction, ResumeLaunchPlan
|
|
11
12
|
from forge.core.ops.session_model_routing import ResolvedModelRoute
|
|
@@ -67,7 +68,7 @@ def _resume_fresh_rewind(
|
|
|
67
68
|
instance_sink=published_instances.append,
|
|
68
69
|
)
|
|
69
70
|
except ForgeSessionError as e:
|
|
70
|
-
|
|
71
|
+
handle_derived_session_error(e)
|
|
71
72
|
return
|
|
72
73
|
|
|
73
74
|
instance_id = published_instances[0] if published_instances else None
|
|
@@ -218,7 +219,7 @@ def _resume_fresh_native(
|
|
|
218
219
|
instance_sink=published_instances.append,
|
|
219
220
|
)
|
|
220
221
|
except ForgeSessionError as e:
|
|
221
|
-
|
|
222
|
+
handle_derived_session_error(e)
|
|
222
223
|
return
|
|
223
224
|
|
|
224
225
|
instance_id = published_instances[0] if published_instances else None
|
|
@@ -79,7 +79,9 @@ def status_line() -> None:
|
|
|
79
79
|
logger.debug("status-line: required sources=%s", sorted(source.value for source in plan.sources))
|
|
80
80
|
|
|
81
81
|
if StatusSource.PROXY in plan.sources:
|
|
82
|
-
is_proxy, runtime, is_proxy_authoritative = status_sources.detect_proxy(
|
|
82
|
+
is_proxy, runtime, is_proxy_authoritative = status_sources.detect_proxy(
|
|
83
|
+
include_effort=any(segment.name == "model" for segment in plan.segments)
|
|
84
|
+
)
|
|
83
85
|
else:
|
|
84
86
|
is_proxy, runtime, is_proxy_authoritative = False, None, False
|
|
85
87
|
|