aisolate-agent 0.3.4__tar.gz → 0.3.6__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {aisolate_agent-0.3.4 → aisolate_agent-0.3.6}/PKG-INFO +2 -2
- {aisolate_agent-0.3.4 → aisolate_agent-0.3.6}/README.md +1 -1
- {aisolate_agent-0.3.4 → aisolate_agent-0.3.6}/pyproject.toml +1 -1
- {aisolate_agent-0.3.4 → aisolate_agent-0.3.6}/src/aisolate/agent/agent.py +3 -0
- {aisolate_agent-0.3.4 → aisolate_agent-0.3.6}/src/aisolate/agent/config/agent_settings.py +8 -0
- {aisolate_agent-0.3.4 → aisolate_agent-0.3.6}/src/aisolate/agent/core/context.py +5 -0
- {aisolate_agent-0.3.4 → aisolate_agent-0.3.6}/src/aisolate/agent/core/spine_compaction.py +7 -0
- {aisolate_agent-0.3.4 → aisolate_agent-0.3.6}/src/aisolate/agent/states/executing.py +155 -19
- {aisolate_agent-0.3.4 → aisolate_agent-0.3.6}/src/aisolate/agent/tests/test_core/test_spine_compaction.py +14 -0
- aisolate_agent-0.3.6/src/aisolate/agent/tests/test_package_import_surface.py +30 -0
- aisolate_agent-0.3.6/src/aisolate/agent/tests/test_states/test_progress_ledger.py +367 -0
- aisolate_agent-0.3.6/src/aisolate/agent/tests/test_tools/test_python_executor_window.py +84 -0
- {aisolate_agent-0.3.4 → aisolate_agent-0.3.6}/src/aisolate/agent/tests/test_tools/test_subagent_failure_contract.py +1 -0
- {aisolate_agent-0.3.4 → aisolate_agent-0.3.6}/src/aisolate/agent/tools/platform/python_executor.py +23 -11
- {aisolate_agent-0.3.4 → aisolate_agent-0.3.6}/src/aisolate/agent/tools/platform/subagent.py +3 -0
- aisolate_agent-0.3.6/src/aisolate/common/execution_protocol.py +3 -0
- {aisolate_agent-0.3.4 → aisolate_agent-0.3.6}/src/aisolate_agent.egg-info/PKG-INFO +2 -2
- {aisolate_agent-0.3.4 → aisolate_agent-0.3.6}/src/aisolate_agent.egg-info/SOURCES.txt +3 -0
- aisolate_agent-0.3.4/src/aisolate/agent/tests/test_states/test_progress_ledger.py +0 -190
- {aisolate_agent-0.3.4 → aisolate_agent-0.3.6}/setup.cfg +0 -0
- {aisolate_agent-0.3.4 → aisolate_agent-0.3.6}/src/aisolate/__init__.py +0 -0
- {aisolate_agent-0.3.4 → aisolate_agent-0.3.6}/src/aisolate/agent/__init__.py +0 -0
- {aisolate_agent-0.3.4 → aisolate_agent-0.3.6}/src/aisolate/agent/config/__init__.py +0 -0
- {aisolate_agent-0.3.4 → aisolate_agent-0.3.6}/src/aisolate/agent/config/prompts/__init__.py +0 -0
- {aisolate_agent-0.3.4 → aisolate_agent-0.3.6}/src/aisolate/agent/config/state_llm.py +0 -0
- {aisolate_agent-0.3.4 → aisolate_agent-0.3.6}/src/aisolate/agent/core/__init__.py +0 -0
- {aisolate_agent-0.3.4 → aisolate_agent-0.3.6}/src/aisolate/agent/core/artifacts.py +0 -0
- {aisolate_agent-0.3.4 → aisolate_agent-0.3.6}/src/aisolate/agent/core/budget.py +0 -0
- {aisolate_agent-0.3.4 → aisolate_agent-0.3.6}/src/aisolate/agent/core/conversation_log.py +0 -0
- {aisolate_agent-0.3.4 → aisolate_agent-0.3.6}/src/aisolate/agent/core/events.py +0 -0
- {aisolate_agent-0.3.4 → aisolate_agent-0.3.6}/src/aisolate/agent/core/exceptions.py +0 -0
- {aisolate_agent-0.3.4 → aisolate_agent-0.3.6}/src/aisolate/agent/core/graph.py +0 -0
- {aisolate_agent-0.3.4 → aisolate_agent-0.3.6}/src/aisolate/agent/core/initial_state.py +0 -0
- {aisolate_agent-0.3.4 → aisolate_agent-0.3.6}/src/aisolate/agent/core/llm_response.py +0 -0
- {aisolate_agent-0.3.4 → aisolate_agent-0.3.6}/src/aisolate/agent/core/policy.py +0 -0
- {aisolate_agent-0.3.4 → aisolate_agent-0.3.6}/src/aisolate/agent/core/protocols.py +0 -0
- {aisolate_agent-0.3.4 → aisolate_agent-0.3.6}/src/aisolate/agent/core/snapshot.py +0 -0
- {aisolate_agent-0.3.4 → aisolate_agent-0.3.6}/src/aisolate/agent/core/tests/test_context_snapshots.py +0 -0
- {aisolate_agent-0.3.4 → aisolate_agent-0.3.6}/src/aisolate/agent/core/tests/test_snapshot.py +0 -0
- {aisolate_agent-0.3.4 → aisolate_agent-0.3.6}/src/aisolate/agent/core/views.py +0 -0
- {aisolate_agent-0.3.4 → aisolate_agent-0.3.6}/src/aisolate/agent/core/workspace.py +0 -0
- {aisolate_agent-0.3.4 → aisolate_agent-0.3.6}/src/aisolate/agent/graphs.py +0 -0
- {aisolate_agent-0.3.4 → aisolate_agent-0.3.6}/src/aisolate/agent/logging/__init__.py +0 -0
- {aisolate_agent-0.3.4 → aisolate_agent-0.3.6}/src/aisolate/agent/logging/config.py +0 -0
- {aisolate_agent-0.3.4 → aisolate_agent-0.3.6}/src/aisolate/agent/logging/factory.py +0 -0
- {aisolate_agent-0.3.4 → aisolate_agent-0.3.6}/src/aisolate/agent/logging/unified_logger.py +0 -0
- {aisolate_agent-0.3.4 → aisolate_agent-0.3.6}/src/aisolate/agent/main.py +0 -0
- {aisolate_agent-0.3.4 → aisolate_agent-0.3.6}/src/aisolate/agent/memory/__init__.py +0 -0
- {aisolate_agent-0.3.4 → aisolate_agent-0.3.6}/src/aisolate/agent/memory/models.py +0 -0
- {aisolate_agent-0.3.4 → aisolate_agent-0.3.6}/src/aisolate/agent/states/__init__.py +0 -0
- {aisolate_agent-0.3.4 → aisolate_agent-0.3.6}/src/aisolate/agent/states/base.py +0 -0
- {aisolate_agent-0.3.4 → aisolate_agent-0.3.6}/src/aisolate/agent/states/clarification.py +0 -0
- {aisolate_agent-0.3.4 → aisolate_agent-0.3.6}/src/aisolate/agent/states/compaction.py +0 -0
- {aisolate_agent-0.3.4 → aisolate_agent-0.3.6}/src/aisolate/agent/states/critic.py +0 -0
- {aisolate_agent-0.3.4 → aisolate_agent-0.3.6}/src/aisolate/agent/states/expert_synthesis.py +0 -0
- {aisolate_agent-0.3.4 → aisolate_agent-0.3.6}/src/aisolate/agent/states/finished.py +0 -0
- {aisolate_agent-0.3.4 → aisolate_agent-0.3.6}/src/aisolate/agent/states/hitl_pause.py +0 -0
- {aisolate_agent-0.3.4 → aisolate_agent-0.3.6}/src/aisolate/agent/states/outputs.py +0 -0
- {aisolate_agent-0.3.4 → aisolate_agent-0.3.6}/src/aisolate/agent/states/planning.py +0 -0
- {aisolate_agent-0.3.4 → aisolate_agent-0.3.6}/src/aisolate/agent/states/task.py +0 -0
- {aisolate_agent-0.3.4 → aisolate_agent-0.3.6}/src/aisolate/agent/status.py +0 -0
- {aisolate_agent-0.3.4 → aisolate_agent-0.3.6}/src/aisolate/agent/strategies/__init__.py +0 -0
- {aisolate_agent-0.3.4 → aisolate_agent-0.3.6}/src/aisolate/agent/strategies/llm/__init__.py +0 -0
- {aisolate_agent-0.3.4 → aisolate_agent-0.3.6}/src/aisolate/agent/strategies/llm/base.py +0 -0
- {aisolate_agent-0.3.4 → aisolate_agent-0.3.6}/src/aisolate/agent/strategies/llm/harmony.py +0 -0
- {aisolate_agent-0.3.4 → aisolate_agent-0.3.6}/src/aisolate/agent/strategies/llm/oai.py +0 -0
- {aisolate_agent-0.3.4 → aisolate_agent-0.3.6}/src/aisolate/agent/strategies/llm/qwen.py +0 -0
- {aisolate_agent-0.3.4 → aisolate_agent-0.3.6}/src/aisolate/agent/strategies/memory/__init__.py +0 -0
- {aisolate_agent-0.3.4 → aisolate_agent-0.3.6}/src/aisolate/agent/strategies/memory/in_memory.py +0 -0
- {aisolate_agent-0.3.4 → aisolate_agent-0.3.6}/src/aisolate/agent/strategies/memory/tests/test_in_memory.py +0 -0
- {aisolate_agent-0.3.4 → aisolate_agent-0.3.6}/src/aisolate/agent/strategies/memory/vector.py +0 -0
- {aisolate_agent-0.3.4 → aisolate_agent-0.3.6}/src/aisolate/agent/substrate.py +0 -0
- {aisolate_agent-0.3.4 → aisolate_agent-0.3.6}/src/aisolate/agent/telemetry/__init__.py +0 -0
- {aisolate_agent-0.3.4 → aisolate_agent-0.3.6}/src/aisolate/agent/telemetry/decorators.py +0 -0
- {aisolate_agent-0.3.4 → aisolate_agent-0.3.6}/src/aisolate/agent/telemetry/factory.py +0 -0
- {aisolate_agent-0.3.4 → aisolate_agent-0.3.6}/src/aisolate/agent/telemetry/interface.py +0 -0
- {aisolate_agent-0.3.4 → aisolate_agent-0.3.6}/src/aisolate/agent/telemetry/noop.py +0 -0
- {aisolate_agent-0.3.4 → aisolate_agent-0.3.6}/src/aisolate/agent/telemetry/openinference.py +0 -0
- {aisolate_agent-0.3.4 → aisolate_agent-0.3.6}/src/aisolate/agent/telemetry/opentelemetry_impl.py +0 -0
- {aisolate_agent-0.3.4 → aisolate_agent-0.3.6}/src/aisolate/agent/telemetry/utils.py +0 -0
- {aisolate_agent-0.3.4 → aisolate_agent-0.3.6}/src/aisolate/agent/tests/__init__.py +0 -0
- {aisolate_agent-0.3.4 → aisolate_agent-0.3.6}/src/aisolate/agent/tests/conftest.py +0 -0
- {aisolate_agent-0.3.4 → aisolate_agent-0.3.6}/src/aisolate/agent/tests/fakes.py +0 -0
- {aisolate_agent-0.3.4 → aisolate_agent-0.3.6}/src/aisolate/agent/tests/test_core/__init__.py +0 -0
- {aisolate_agent-0.3.4 → aisolate_agent-0.3.6}/src/aisolate/agent/tests/test_core/test_architecture_assumptions.py +0 -0
- {aisolate_agent-0.3.4 → aisolate_agent-0.3.6}/src/aisolate/agent/tests/test_core/test_artifact_rows.py +0 -0
- {aisolate_agent-0.3.4 → aisolate_agent-0.3.6}/src/aisolate/agent/tests/test_core/test_change_bridge_echo.py +0 -0
- {aisolate_agent-0.3.4 → aisolate_agent-0.3.6}/src/aisolate/agent/tests/test_core/test_conversation_log.py +0 -0
- {aisolate_agent-0.3.4 → aisolate_agent-0.3.6}/src/aisolate/agent/tests/test_core/test_delegated_lineage_restore.py +0 -0
- {aisolate_agent-0.3.4 → aisolate_agent-0.3.6}/src/aisolate/agent/tests/test_core/test_event_agent_name_stamping.py +0 -0
- {aisolate_agent-0.3.4 → aisolate_agent-0.3.6}/src/aisolate/agent/tests/test_core/test_execute_turn_review_pending.py +0 -0
- {aisolate_agent-0.3.4 → aisolate_agent-0.3.6}/src/aisolate/agent/tests/test_core/test_firewall_property.py +0 -0
- {aisolate_agent-0.3.4 → aisolate_agent-0.3.6}/src/aisolate/agent/tests/test_core/test_graph.py +0 -0
- {aisolate_agent-0.3.4 → aisolate_agent-0.3.6}/src/aisolate/agent/tests/test_core/test_initial_state.py +0 -0
- {aisolate_agent-0.3.4 → aisolate_agent-0.3.6}/src/aisolate/agent/tests/test_core/test_legacy_snapshot.py +0 -0
- {aisolate_agent-0.3.4 → aisolate_agent-0.3.6}/src/aisolate/agent/tests/test_core/test_live_capture.py +0 -0
- {aisolate_agent-0.3.4 → aisolate_agent-0.3.6}/src/aisolate/agent/tests/test_core/test_locale_prelude.py +0 -0
- {aisolate_agent-0.3.4 → aisolate_agent-0.3.6}/src/aisolate/agent/tests/test_core/test_policy.py +0 -0
- {aisolate_agent-0.3.4 → aisolate_agent-0.3.6}/src/aisolate/agent/tests/test_core/test_restore_review_posture.py +0 -0
- {aisolate_agent-0.3.4 → aisolate_agent-0.3.6}/src/aisolate/agent/tests/test_core/test_resume_semantics.py +0 -0
- {aisolate_agent-0.3.4 → aisolate_agent-0.3.6}/src/aisolate/agent/tests/test_core/test_run_streaming_cancel.py +0 -0
- {aisolate_agent-0.3.4 → aisolate_agent-0.3.6}/src/aisolate/agent/tests/test_core/test_state_llm_overrides.py +0 -0
- {aisolate_agent-0.3.4 → aisolate_agent-0.3.6}/src/aisolate/agent/tests/test_core/test_state_transitions.py +0 -0
- {aisolate_agent-0.3.4 → aisolate_agent-0.3.6}/src/aisolate/agent/tests/test_core/test_status_summarizer.py +0 -0
- {aisolate_agent-0.3.4 → aisolate_agent-0.3.6}/src/aisolate/agent/tests/test_core/test_subagent_graph.py +0 -0
- {aisolate_agent-0.3.4 → aisolate_agent-0.3.6}/src/aisolate/agent/tests/test_core/test_substrate.py +0 -0
- {aisolate_agent-0.3.4 → aisolate_agent-0.3.6}/src/aisolate/agent/tests/test_core/test_token_accumulation.py +0 -0
- {aisolate_agent-0.3.4 → aisolate_agent-0.3.6}/src/aisolate/agent/tests/test_core/test_turn_started_events.py +0 -0
- {aisolate_agent-0.3.4 → aisolate_agent-0.3.6}/src/aisolate/agent/tests/test_core/test_turn_usage_isolation.py +0 -0
- {aisolate_agent-0.3.4 → aisolate_agent-0.3.6}/src/aisolate/agent/tests/test_core/test_uniform_state.py +0 -0
- {aisolate_agent-0.3.4 → aisolate_agent-0.3.6}/src/aisolate/agent/tests/test_core/test_views.py +0 -0
- {aisolate_agent-0.3.4 → aisolate_agent-0.3.6}/src/aisolate/agent/tests/test_core/test_workspace_bridge_attribution.py +0 -0
- {aisolate_agent-0.3.4 → aisolate_agent-0.3.6}/src/aisolate/agent/tests/test_core/test_workspace_capture.py +0 -0
- {aisolate_agent-0.3.4 → aisolate_agent-0.3.6}/src/aisolate/agent/tests/test_core/test_workspace_changed_event.py +0 -0
- {aisolate_agent-0.3.4 → aisolate_agent-0.3.6}/src/aisolate/agent/tests/test_e2e/__init__.py +0 -0
- {aisolate_agent-0.3.4 → aisolate_agent-0.3.6}/src/aisolate/agent/tests/test_e2e/conftest.py +0 -0
- {aisolate_agent-0.3.4 → aisolate_agent-0.3.6}/src/aisolate/agent/tests/test_e2e/test_delegation_file_paths.py +0 -0
- {aisolate_agent-0.3.4 → aisolate_agent-0.3.6}/src/aisolate/agent/tests/test_e2e/test_delegation_recovery.py +0 -0
- {aisolate_agent-0.3.4 → aisolate_agent-0.3.6}/src/aisolate/agent/tests/test_e2e/test_locale_helpers.py +0 -0
- {aisolate_agent-0.3.4 → aisolate_agent-0.3.6}/src/aisolate/agent/tests/test_e2e/test_size_compaction.py +0 -0
- {aisolate_agent-0.3.4 → aisolate_agent-0.3.6}/src/aisolate/agent/tests/test_e2e/test_stall_clone_96919cf1.py +0 -0
- {aisolate_agent-0.3.4 → aisolate_agent-0.3.6}/src/aisolate/agent/tests/test_e2e/test_truncation_wedge_5b90b101.py +0 -0
- {aisolate_agent-0.3.4 → aisolate_agent-0.3.6}/src/aisolate/agent/tests/test_e2e/test_workspace_lifecycle.py +0 -0
- {aisolate_agent-0.3.4 → aisolate_agent-0.3.6}/src/aisolate/agent/tests/test_integration/__init__.py +0 -0
- {aisolate_agent-0.3.4 → aisolate_agent-0.3.6}/src/aisolate/agent/tests/test_integration/helpers.py +0 -0
- {aisolate_agent-0.3.4 → aisolate_agent-0.3.6}/src/aisolate/agent/tests/test_integration/test_flagship_loop.py +0 -0
- {aisolate_agent-0.3.4 → aisolate_agent-0.3.6}/src/aisolate/agent/tests/test_integration/test_followup_roundtrips.py +0 -0
- {aisolate_agent-0.3.4 → aisolate_agent-0.3.6}/src/aisolate/agent/tests/test_integration/test_full_workflow.py +0 -0
- {aisolate_agent-0.3.4 → aisolate_agent-0.3.6}/src/aisolate/agent/tests/test_integration/test_prompt_template_contract.py +0 -0
- {aisolate_agent-0.3.4 → aisolate_agent-0.3.6}/src/aisolate/agent/tests/test_integration/test_restore_roundtrips.py +0 -0
- {aisolate_agent-0.3.4 → aisolate_agent-0.3.6}/src/aisolate/agent/tests/test_integration/test_stalled_and_acceptance.py +0 -0
- {aisolate_agent-0.3.4 → aisolate_agent-0.3.6}/src/aisolate/agent/tests/test_states/__init__.py +0 -0
- {aisolate_agent-0.3.4 → aisolate_agent-0.3.6}/src/aisolate/agent/tests/test_states/test_compact_for_llm.py +0 -0
- {aisolate_agent-0.3.4 → aisolate_agent-0.3.6}/src/aisolate/agent/tests/test_states/test_critic_enforcer.py +0 -0
- {aisolate_agent-0.3.4 → aisolate_agent-0.3.6}/src/aisolate/agent/tests/test_states/test_critic_review_cap.py +0 -0
- {aisolate_agent-0.3.4 → aisolate_agent-0.3.6}/src/aisolate/agent/tests/test_states/test_emission_map.py +0 -0
- {aisolate_agent-0.3.4 → aisolate_agent-0.3.6}/src/aisolate/agent/tests/test_states/test_executing_metadata.py +0 -0
- {aisolate_agent-0.3.4 → aisolate_agent-0.3.6}/src/aisolate/agent/tests/test_states/test_executing_prefix_stability.py +0 -0
- {aisolate_agent-0.3.4 → aisolate_agent-0.3.6}/src/aisolate/agent/tests/test_states/test_executing_review_routing.py +0 -0
- {aisolate_agent-0.3.4 → aisolate_agent-0.3.6}/src/aisolate/agent/tests/test_states/test_planning_artifact.py +0 -0
- {aisolate_agent-0.3.4 → aisolate_agent-0.3.6}/src/aisolate/agent/tests/test_states/test_planning_metadata.py +0 -0
- {aisolate_agent-0.3.4 → aisolate_agent-0.3.6}/src/aisolate/agent/tests/test_states/test_selection.py +0 -0
- {aisolate_agent-0.3.4 → aisolate_agent-0.3.6}/src/aisolate/agent/tests/test_states/test_size_compaction_wiring.py +0 -0
- {aisolate_agent-0.3.4 → aisolate_agent-0.3.6}/src/aisolate/agent/tests/test_states/test_stall_recovery.py +0 -0
- {aisolate_agent-0.3.4 → aisolate_agent-0.3.6}/src/aisolate/agent/tests/test_strategies/__init__.py +0 -0
- {aisolate_agent-0.3.4 → aisolate_agent-0.3.6}/src/aisolate/agent/tests/test_strategies/test_identity_block.py +0 -0
- {aisolate_agent-0.3.4 → aisolate_agent-0.3.6}/src/aisolate/agent/tests/test_strategies/test_llm_generate_span.py +0 -0
- {aisolate_agent-0.3.4 → aisolate_agent-0.3.6}/src/aisolate/agent/tests/test_strategies/test_llm_providers.py +0 -0
- {aisolate_agent-0.3.4 → aisolate_agent-0.3.6}/src/aisolate/agent/tests/test_strategies/test_llm_watchdog.py +0 -0
- {aisolate_agent-0.3.4 → aisolate_agent-0.3.6}/src/aisolate/agent/tests/test_strategies/test_prepare_history_contract.py +0 -0
- {aisolate_agent-0.3.4 → aisolate_agent-0.3.6}/src/aisolate/agent/tests/test_strategies/test_qwen_retry.py +0 -0
- {aisolate_agent-0.3.4 → aisolate_agent-0.3.6}/src/aisolate/agent/tests/test_strategies/test_qwen_strategy.py +0 -0
- {aisolate_agent-0.3.4 → aisolate_agent-0.3.6}/src/aisolate/agent/tests/test_strategies/test_qwen_truncation.py +0 -0
- {aisolate_agent-0.3.4 → aisolate_agent-0.3.6}/src/aisolate/agent/tests/test_strategies/test_qwen_workspace_envelope.py +0 -0
- {aisolate_agent-0.3.4 → aisolate_agent-0.3.6}/src/aisolate/agent/tests/test_strategies/test_scripted_llm_contract.py +0 -0
- {aisolate_agent-0.3.4 → aisolate_agent-0.3.6}/src/aisolate/agent/tests/test_strategies/test_telemetry_attributes.py +0 -0
- {aisolate_agent-0.3.4 → aisolate_agent-0.3.6}/src/aisolate/agent/tests/test_strategies/test_turn_budget_block.py +0 -0
- {aisolate_agent-0.3.4 → aisolate_agent-0.3.6}/src/aisolate/agent/tests/test_tools/__init__.py +0 -0
- {aisolate_agent-0.3.4 → aisolate_agent-0.3.6}/src/aisolate/agent/tests/test_tools/test_bundle_and_restore.py +0 -0
- {aisolate_agent-0.3.4 → aisolate_agent-0.3.6}/src/aisolate/agent/tests/test_tools/test_delegation_identity.py +0 -0
- {aisolate_agent-0.3.4 → aisolate_agent-0.3.6}/src/aisolate/agent/tests/test_tools/test_edit_blocks.py +0 -0
- {aisolate_agent-0.3.4 → aisolate_agent-0.3.6}/src/aisolate/agent/tests/test_tools/test_fake_executor.py +0 -0
- {aisolate_agent-0.3.4 → aisolate_agent-0.3.6}/src/aisolate/agent/tests/test_tools/test_handover_sidecars.py +0 -0
- {aisolate_agent-0.3.4 → aisolate_agent-0.3.6}/src/aisolate/agent/tests/test_tools/test_load_handover_resolution.py +0 -0
- {aisolate_agent-0.3.4 → aisolate_agent-0.3.6}/src/aisolate/agent/tests/test_tools/test_output_refs.py +0 -0
- {aisolate_agent-0.3.4 → aisolate_agent-0.3.6}/src/aisolate/agent/tests/test_tools/test_sandbox_import_surface.py +0 -0
- {aisolate_agent-0.3.4 → aisolate_agent-0.3.6}/src/aisolate/agent/tests/test_tools/test_send_actions_error.py +0 -0
- {aisolate_agent-0.3.4 → aisolate_agent-0.3.6}/src/aisolate/agent/tests/test_tools/test_shell_executing_loop.py +0 -0
- {aisolate_agent-0.3.4 → aisolate_agent-0.3.6}/src/aisolate/agent/tests/test_tools/test_shell_tools.py +0 -0
- {aisolate_agent-0.3.4 → aisolate_agent-0.3.6}/src/aisolate/agent/tests/test_tools/test_subagent_handover.py +0 -0
- {aisolate_agent-0.3.4 → aisolate_agent-0.3.6}/src/aisolate/agent/tests/test_tools/test_three_tier_tools.py +0 -0
- {aisolate_agent-0.3.4 → aisolate_agent-0.3.6}/src/aisolate/agent/tests/test_tools/test_workspace_actions.py +0 -0
- {aisolate_agent-0.3.4 → aisolate_agent-0.3.6}/src/aisolate/agent/tests/test_tools/test_workspace_tools.py +0 -0
- {aisolate_agent-0.3.4 → aisolate_agent-0.3.6}/src/aisolate/agent/tools/__init__.py +0 -0
- {aisolate_agent-0.3.4 → aisolate_agent-0.3.6}/src/aisolate/agent/tools/actions/__init__.py +0 -0
- {aisolate_agent-0.3.4 → aisolate_agent-0.3.6}/src/aisolate/agent/tools/actions/base.py +0 -0
- {aisolate_agent-0.3.4 → aisolate_agent-0.3.6}/src/aisolate/agent/tools/actions/final_answer.py +0 -0
- {aisolate_agent-0.3.4 → aisolate_agent-0.3.6}/src/aisolate/agent/tools/actions/load_handover.py +0 -0
- {aisolate_agent-0.3.4 → aisolate_agent-0.3.6}/src/aisolate/agent/tools/actions/visit_page_action.py +0 -0
- {aisolate_agent-0.3.4 → aisolate_agent-0.3.6}/src/aisolate/agent/tools/actions/web_search_action.py +0 -0
- {aisolate_agent-0.3.4 → aisolate_agent-0.3.6}/src/aisolate/agent/tools/actions/wikipedia_search_action.py +0 -0
- {aisolate_agent-0.3.4 → aisolate_agent-0.3.6}/src/aisolate/agent/tools/actions/workspace.py +0 -0
- {aisolate_agent-0.3.4 → aisolate_agent-0.3.6}/src/aisolate/agent/tools/base.py +0 -0
- {aisolate_agent-0.3.4 → aisolate_agent-0.3.6}/src/aisolate/agent/tools/execution.py +0 -0
- {aisolate_agent-0.3.4 → aisolate_agent-0.3.6}/src/aisolate/agent/tools/functions/__init__.py +0 -0
- {aisolate_agent-0.3.4 → aisolate_agent-0.3.6}/src/aisolate/agent/tools/functions/base.py +0 -0
- {aisolate_agent-0.3.4 → aisolate_agent-0.3.6}/src/aisolate/agent/tools/functions/hitl.py +0 -0
- {aisolate_agent-0.3.4 → aisolate_agent-0.3.6}/src/aisolate/agent/tools/models.py +0 -0
- {aisolate_agent-0.3.4 → aisolate_agent-0.3.6}/src/aisolate/agent/tools/platform/__init__.py +0 -0
- {aisolate_agent-0.3.4 → aisolate_agent-0.3.6}/src/aisolate/agent/tools/platform/base.py +0 -0
- {aisolate_agent-0.3.4 → aisolate_agent-0.3.6}/src/aisolate/agent/tools/platform/edit_blocks.py +0 -0
- {aisolate_agent-0.3.4 → aisolate_agent-0.3.6}/src/aisolate/agent/tools/platform/files_ops.py +0 -0
- {aisolate_agent-0.3.4 → aisolate_agent-0.3.6}/src/aisolate/agent/tools/platform/shell.py +0 -0
- {aisolate_agent-0.3.4 → aisolate_agent-0.3.6}/src/aisolate/agent/tools/platform/web_search.py +0 -0
- {aisolate_agent-0.3.4 → aisolate_agent-0.3.6}/src/aisolate/agent/tools/platform/workspace_tools.py +0 -0
- {aisolate_agent-0.3.4 → aisolate_agent-0.3.6}/src/aisolate/agent/tools/routing.py +0 -0
- {aisolate_agent-0.3.4 → aisolate_agent-0.3.6}/src/aisolate/agent/trace.py +0 -0
- {aisolate_agent-0.3.4 → aisolate_agent-0.3.6}/src/aisolate/agent/utils.py +0 -0
- {aisolate_agent-0.3.4 → aisolate_agent-0.3.6}/src/aisolate/common/__init__.py +0 -0
- {aisolate_agent-0.3.4 → aisolate_agent-0.3.6}/src/aisolate/common/codec.py +0 -0
- {aisolate_agent-0.3.4 → aisolate_agent-0.3.6}/src/aisolate/common/errors.py +0 -0
- {aisolate_agent-0.3.4 → aisolate_agent-0.3.6}/src/aisolate/common/models.py +0 -0
- {aisolate_agent-0.3.4 → aisolate_agent-0.3.6}/src/aisolate/common/output_window.py +0 -0
- {aisolate_agent-0.3.4 → aisolate_agent-0.3.6}/src/aisolate/common/tests/__init__.py +0 -0
- {aisolate_agent-0.3.4 → aisolate_agent-0.3.6}/src/aisolate/common/tests/fake_vm.py +0 -0
- {aisolate_agent-0.3.4 → aisolate_agent-0.3.6}/src/aisolate/common/tests/fixtures.py +0 -0
- {aisolate_agent-0.3.4 → aisolate_agent-0.3.6}/src/aisolate/common/tests/test_codec_channel.py +0 -0
- {aisolate_agent-0.3.4 → aisolate_agent-0.3.6}/src/aisolate/common/tests/test_output_window.py +0 -0
- {aisolate_agent-0.3.4 → aisolate_agent-0.3.6}/src/aisolate/common/tests/utils.py +0 -0
- {aisolate_agent-0.3.4 → aisolate_agent-0.3.6}/src/aisolate/logging/__init__.py +0 -0
- {aisolate_agent-0.3.4 → aisolate_agent-0.3.6}/src/aisolate/logging/formatters.py +0 -0
- {aisolate_agent-0.3.4 → aisolate_agent-0.3.6}/src/aisolate/logging/processors.py +0 -0
- {aisolate_agent-0.3.4 → aisolate_agent-0.3.6}/src/aisolate_agent.egg-info/dependency_links.txt +0 -0
- {aisolate_agent-0.3.4 → aisolate_agent-0.3.6}/src/aisolate_agent.egg-info/entry_points.txt +0 -0
- {aisolate_agent-0.3.4 → aisolate_agent-0.3.6}/src/aisolate_agent.egg-info/requires.txt +0 -0
- {aisolate_agent-0.3.4 → aisolate_agent-0.3.6}/src/aisolate_agent.egg-info/top_level.txt +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: aisolate-agent
|
|
3
|
-
Version: 0.3.
|
|
3
|
+
Version: 0.3.6
|
|
4
4
|
Summary: AI Agent with intelligent planning and reasoning
|
|
5
5
|
License: Apache-2.0
|
|
6
6
|
Requires-Python: >=3.10
|
|
@@ -30,7 +30,7 @@ AI Agent with intelligent planning and reasoning
|
|
|
30
30
|
## Local Installation
|
|
31
31
|
|
|
32
32
|
```bash
|
|
33
|
-
pip install path/to/aisolate_agent-0.3.
|
|
33
|
+
pip install path/to/aisolate_agent-0.3.6-py3-none-any.whl
|
|
34
34
|
```
|
|
35
35
|
|
|
36
36
|
## Usage
|
|
@@ -1501,6 +1501,9 @@ class Agent:
|
|
|
1501
1501
|
context.spine_compactor = SizeCompactor.from_settings(
|
|
1502
1502
|
self.settings
|
|
1503
1503
|
)
|
|
1504
|
+
context.max_consecutive_failures = (
|
|
1505
|
+
self.settings.max_consecutive_failures
|
|
1506
|
+
)
|
|
1504
1507
|
if context.remote_python_executor is not None:
|
|
1505
1508
|
context.remote_python_executor.output_window = (
|
|
1506
1509
|
self.settings.output_window_chars
|
|
@@ -18,6 +18,14 @@ class AgentSettings(BaseSettings):
|
|
|
18
18
|
default=3,
|
|
19
19
|
description="Maximum number of recovery attempts for failed operations",
|
|
20
20
|
)
|
|
21
|
+
max_consecutive_failures: int = Field(
|
|
22
|
+
default=5,
|
|
23
|
+
description=(
|
|
24
|
+
"Consecutive failed tool executions (regardless of error text) "
|
|
25
|
+
"tolerated before the stall ladder intervenes; 0 disables the "
|
|
26
|
+
"failure signal"
|
|
27
|
+
),
|
|
28
|
+
)
|
|
21
29
|
|
|
22
30
|
debug_mode: bool = Field(
|
|
23
31
|
default=False, description="Enable debug logging and additional validation"
|
|
@@ -333,6 +333,11 @@ class AgentContext:
|
|
|
333
333
|
# first turn's reported usage.
|
|
334
334
|
self.spine_compactor: Optional[Any] = None
|
|
335
335
|
|
|
336
|
+
# Consecutive-failure threshold for the executing ledger, stamped
|
|
337
|
+
# from AgentSettings by the run owner alongside spine_compactor.
|
|
338
|
+
# None = the ledger's own default; 0 disables the signal.
|
|
339
|
+
self.max_consecutive_failures: Optional[int] = None
|
|
340
|
+
|
|
336
341
|
# The user's locale (AgentSettings.locale), stamped by the run owner
|
|
337
342
|
# like workspace_root_display; the identity block renders it so
|
|
338
343
|
# number/date/time formatting in user-facing output follows the
|
|
@@ -184,6 +184,13 @@ def build_summary(context: "AgentContext", dropped: Sequence[Event]) -> str:
|
|
|
184
184
|
"disk (re-read it when needed), and your checklist, memory, and "
|
|
185
185
|
"workspace listing render below as always."
|
|
186
186
|
]
|
|
187
|
+
if getattr(context, "remote_python_executor", None) is not None:
|
|
188
|
+
lines.append(
|
|
189
|
+
"The source of the condensed cells is still in the kernel: "
|
|
190
|
+
"successful cells are collected in .aisolate/cells_ok.py, and "
|
|
191
|
+
"%history / In[n] hold the full input history — recover code "
|
|
192
|
+
"from there instead of rewriting it from memory."
|
|
193
|
+
)
|
|
187
194
|
|
|
188
195
|
finished = [
|
|
189
196
|
rec
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
import json
|
|
4
4
|
import os
|
|
5
|
+
import re
|
|
5
6
|
from typing import Any, Dict, List, Optional, Set, Tuple, TYPE_CHECKING
|
|
6
7
|
|
|
7
8
|
from openai_harmony import Role
|
|
@@ -84,10 +85,12 @@ class ProgressLedger:
|
|
|
84
85
|
"""One progress ledger per executing run — two signals, one owner.
|
|
85
86
|
|
|
86
87
|
Signal 1 (terminal): the exact no-progress count. A turn with no action,
|
|
87
|
-
or a
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
88
|
+
or a repeated observation, increments it; a novel observation or a
|
|
89
|
+
drafted answer resets it; at ``MAX_NO_PROGRESS`` the run stalls. This is
|
|
90
|
+
the only signal allowed to end a run — it proves zero information gain.
|
|
91
|
+
Repeat identity ignores nondeterministic tokens (UUIDs, long hex ids,
|
|
92
|
+
memory addresses): a retried upload whose object name embeds a fresh
|
|
93
|
+
``uuid4().hex`` per attempt is the same failure, not new information.
|
|
91
94
|
|
|
92
95
|
Signal 2 (advisory): the checklist stall clock. Every executing turn
|
|
93
96
|
observes the ``task.md`` fingerprint; once it has not advanced for
|
|
@@ -96,22 +99,48 @@ class ProgressLedger:
|
|
|
96
99
|
``CHECKLIST_REMINDER_EVERY`` further stalled turns. It never terminates
|
|
97
100
|
the run — budget exhaustion is an honest, recoverable outcome, and a
|
|
98
101
|
coarse heuristic must not kill legitimately long single-item work.
|
|
102
|
+
|
|
103
|
+
Signal 3 (terminal, shares the ladder): consecutive failed executions.
|
|
104
|
+
Repeat identity misses a wedge whose error text genuinely shifts between
|
|
105
|
+
attempts; a run that cannot execute ANYTHING successfully for
|
|
106
|
+
``max_consecutive_failures`` turns is wedged regardless. One success
|
|
107
|
+
resets the count. The threshold is settable per run
|
|
108
|
+
(``AgentSettings.max_consecutive_failures``); 0 disables.
|
|
99
109
|
"""
|
|
100
110
|
|
|
101
111
|
#: Consecutive no-progress turns tolerated before the run stalls.
|
|
102
112
|
MAX_NO_PROGRESS = 5
|
|
103
113
|
|
|
114
|
+
#: Default consecutive failed executions tolerated before escalation.
|
|
115
|
+
MAX_CONSECUTIVE_FAILURES = 5
|
|
116
|
+
|
|
104
117
|
#: Executing turns without checklist advance before the notice fires.
|
|
105
118
|
CHECKLIST_STALL_TURNS = 8
|
|
106
119
|
|
|
107
120
|
#: Further stalled turns between notice repetitions.
|
|
108
121
|
CHECKLIST_REMINDER_EVERY = 4
|
|
109
122
|
|
|
123
|
+
#: Nondeterministic tokens scrubbed before repeat comparison: memory
|
|
124
|
+
#: addresses, dashed UUIDs, and long hex runs (``uuid4().hex`` object
|
|
125
|
+
#: names, digests). The hex rule requires at least one a-f letter so
|
|
126
|
+
#: plain large numbers (real data) never collapse into a false repeat.
|
|
127
|
+
_NONDETERMINISTIC = re.compile(
|
|
128
|
+
r"0x[0-9a-fA-F]{4,}"
|
|
129
|
+
r"|[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}"
|
|
130
|
+
r"|(?=[0-9]*[a-f])[0-9a-f]{16,}"
|
|
131
|
+
)
|
|
132
|
+
|
|
110
133
|
def __init__(self) -> None:
|
|
111
134
|
self.no_progress_count: int = 0
|
|
112
135
|
self._seen_results: Set[str] = set()
|
|
113
136
|
self._checklist_fingerprint: Optional[str] = None
|
|
114
137
|
self._stall_turns: int = 0
|
|
138
|
+
self.max_consecutive_failures: int = self.MAX_CONSECUTIVE_FAILURES
|
|
139
|
+
self.consecutive_failures: int = 0
|
|
140
|
+
|
|
141
|
+
@classmethod
|
|
142
|
+
def _fingerprint(cls, observation: str) -> str:
|
|
143
|
+
return cls._NONDETERMINISTIC.sub("•", observation)
|
|
115
144
|
|
|
116
145
|
# -- signal 2: checklist stall clock ---------------------------------
|
|
117
146
|
|
|
@@ -159,11 +188,12 @@ class ProgressLedger:
|
|
|
159
188
|
# -- signal 1: exact no-progress count --------------------------------
|
|
160
189
|
|
|
161
190
|
def observe_result(self, compacted: str) -> bool:
|
|
162
|
-
"""Account one observation; ``True`` for a
|
|
163
|
-
|
|
191
|
+
"""Account one observation; ``True`` for a repeat (up to random ids)."""
|
|
192
|
+
fingerprint = self._fingerprint(compacted)
|
|
193
|
+
if fingerprint in self._seen_results:
|
|
164
194
|
self.no_progress_count += 1
|
|
165
195
|
return True
|
|
166
|
-
self._seen_results.add(
|
|
196
|
+
self._seen_results.add(fingerprint)
|
|
167
197
|
self.no_progress_count = 0
|
|
168
198
|
return False
|
|
169
199
|
|
|
@@ -176,8 +206,38 @@ class ProgressLedger:
|
|
|
176
206
|
self.no_progress_count = 0
|
|
177
207
|
|
|
178
208
|
def reset_counter(self) -> None:
|
|
179
|
-
"""Start a fresh
|
|
209
|
+
"""Start a fresh window on both terminal signals (recovery granted)."""
|
|
180
210
|
self.no_progress_count = 0
|
|
211
|
+
self.consecutive_failures = 0
|
|
212
|
+
|
|
213
|
+
# -- signal 3: consecutive failed executions ---------------------------
|
|
214
|
+
|
|
215
|
+
def observe_failure(self, ok: bool) -> None:
|
|
216
|
+
"""Account one execution outcome; a success resets the streak."""
|
|
217
|
+
self.consecutive_failures = 0 if ok else self.consecutive_failures + 1
|
|
218
|
+
|
|
219
|
+
@property
|
|
220
|
+
def failure_stalled(self) -> bool:
|
|
221
|
+
return (
|
|
222
|
+
self.max_consecutive_failures > 0
|
|
223
|
+
and self.consecutive_failures >= self.max_consecutive_failures
|
|
224
|
+
)
|
|
225
|
+
|
|
226
|
+
def failure_notice(self) -> Optional[str]:
|
|
227
|
+
"""In-band warning on the two failures before the threshold."""
|
|
228
|
+
if self.max_consecutive_failures <= 0:
|
|
229
|
+
return None
|
|
230
|
+
remaining = self.max_consecutive_failures - self.consecutive_failures
|
|
231
|
+
if remaining <= 0 or remaining > 2:
|
|
232
|
+
return None
|
|
233
|
+
return (
|
|
234
|
+
f"\n[framework notice] {self.consecutive_failures} consecutive "
|
|
235
|
+
"executions have failed. If the blocker is external (a service "
|
|
236
|
+
"down, missing data), stop retrying — record it and work on "
|
|
237
|
+
"something else or deliver with the gap named. After "
|
|
238
|
+
f"{remaining} more consecutive failure(s) the framework "
|
|
239
|
+
"intervenes."
|
|
240
|
+
)
|
|
181
241
|
|
|
182
242
|
def clear_seen(self) -> None:
|
|
183
243
|
"""Forget seen observations (a re-planned cycle starts clean)."""
|
|
@@ -190,8 +250,9 @@ class ProgressLedger:
|
|
|
190
250
|
def repeat_notice(self, remaining: int) -> str:
|
|
191
251
|
"""The in-band first response to a repeated observation."""
|
|
192
252
|
return (
|
|
193
|
-
"\n[framework notice] This result is
|
|
194
|
-
"
|
|
253
|
+
"\n[framework notice] This result is identical to an earlier "
|
|
254
|
+
"one in this run (ignoring random identifiers) — the call added "
|
|
255
|
+
"no new information. "
|
|
195
256
|
f"After {remaining} more repeated result(s) the framework "
|
|
196
257
|
"intervenes and will eventually end the run. If the task is "
|
|
197
258
|
"complete, deliver NOW by calling final_answer(...); otherwise "
|
|
@@ -281,6 +342,10 @@ class ExecutingState(AbstractState):
|
|
|
281
342
|
context.set_state_hint("tool_choice", "required")
|
|
282
343
|
context.set_state_hint("reasoning_effort", "medium")
|
|
283
344
|
|
|
345
|
+
limit = getattr(context, "max_consecutive_failures", None)
|
|
346
|
+
if limit is not None:
|
|
347
|
+
self._ledger.max_consecutive_failures = limit
|
|
348
|
+
|
|
284
349
|
# Remove HITL tools — clarification phase is over, the agent must
|
|
285
350
|
# execute autonomously. Keeping ask_user available tempts the LLM
|
|
286
351
|
# into asking trivial preference questions mid-execution; there is
|
|
@@ -503,12 +568,18 @@ class ExecutingState(AbstractState):
|
|
|
503
568
|
truncated = len(compacted) < len(output)
|
|
504
569
|
|
|
505
570
|
# Progress accounting on the STORED result bytes (the pre-annotation
|
|
506
|
-
# compacted form): a
|
|
507
|
-
# to the trace. The first response is in-band — the model
|
|
508
|
-
# the observation itself, that it is repeating and how to
|
|
571
|
+
# compacted form, normalized for random ids): a repeat added zero new
|
|
572
|
+
# information to the trace. The first response is in-band — the model
|
|
573
|
+
# is told, in the observation itself, that it is repeating and how to
|
|
574
|
+
# deliver.
|
|
509
575
|
# Only a model that ignores the notice until the threshold stalls the
|
|
510
576
|
# run; the crossing repeat emits nothing, it had nothing to add.
|
|
511
|
-
|
|
577
|
+
# Both terminal signals observe every result; at most ONE escalates a
|
|
578
|
+
# turn (a repeated failure is also a failure — climbing both ladders
|
|
579
|
+
# at once would skip rungs).
|
|
580
|
+
repeated_observation = self._ledger.observe_result(compacted)
|
|
581
|
+
self._ledger.observe_failure(ok)
|
|
582
|
+
if repeated_observation:
|
|
512
583
|
logger.warning(
|
|
513
584
|
"Repeated observation adds no new information",
|
|
514
585
|
state="executing",
|
|
@@ -528,6 +599,25 @@ class ExecutingState(AbstractState):
|
|
|
528
599
|
- self._ledger.no_progress_count
|
|
529
600
|
)
|
|
530
601
|
compacted += self._ledger.repeat_notice(remaining)
|
|
602
|
+
elif self._ledger.failure_stalled:
|
|
603
|
+
logger.warning(
|
|
604
|
+
"Consecutive execution failures crossed the threshold",
|
|
605
|
+
state="executing",
|
|
606
|
+
consecutive_failures=self._ledger.consecutive_failures,
|
|
607
|
+
)
|
|
608
|
+
stalled = self._escalate_stall(
|
|
609
|
+
context, repeated=tool_name, reason="failures"
|
|
610
|
+
)
|
|
611
|
+
if stalled is not None:
|
|
612
|
+
return stalled
|
|
613
|
+
compacted += (
|
|
614
|
+
"\n[framework notice] Course change required — follow "
|
|
615
|
+
"the steering instruction below."
|
|
616
|
+
)
|
|
617
|
+
else:
|
|
618
|
+
failure_notice = self._ledger.failure_notice()
|
|
619
|
+
if failure_notice is not None:
|
|
620
|
+
compacted += failure_notice
|
|
531
621
|
|
|
532
622
|
stall_notice = self._ledger.checklist_stall_notice()
|
|
533
623
|
if stall_notice is not None:
|
|
@@ -549,30 +639,48 @@ class ExecutingState(AbstractState):
|
|
|
549
639
|
)
|
|
550
640
|
|
|
551
641
|
def _escalate_stall(
|
|
552
|
-
self, context: "AgentContext", repeated: str
|
|
642
|
+
self, context: "AgentContext", repeated: str, reason: str = "repeat"
|
|
553
643
|
) -> Optional[Stalled]:
|
|
554
644
|
"""Advance the stall ladder one rung; ``None`` grants a recovery.
|
|
555
645
|
|
|
646
|
+
Both terminal signals share the ONE ladder position
|
|
647
|
+
(``context.stall_recoveries``); ``reason`` selects the steering text
|
|
648
|
+
("repeat" = identical observations, "failures" = consecutive failed
|
|
649
|
+
executions).
|
|
650
|
+
|
|
556
651
|
Rung 1: steering + fresh no-progress window, the loop continues.
|
|
557
652
|
Rung 2: re-plan steering, ``Stalled`` routes to planning.
|
|
558
653
|
Rung 3: ``Stalled`` routes to finished — the run ends, loudly.
|
|
559
654
|
"""
|
|
560
655
|
context.stall_recoveries += 1
|
|
561
656
|
rung = context.stall_recoveries
|
|
562
|
-
count =
|
|
657
|
+
count = (
|
|
658
|
+
self._ledger.consecutive_failures
|
|
659
|
+
if reason == "failures"
|
|
660
|
+
else self._ledger.no_progress_count
|
|
661
|
+
)
|
|
563
662
|
logger.warning(
|
|
564
663
|
"Stall threshold crossed",
|
|
565
664
|
state="executing",
|
|
566
665
|
escalation=rung,
|
|
567
|
-
|
|
666
|
+
reason=reason,
|
|
667
|
+
count=count,
|
|
568
668
|
repeated=repeated,
|
|
569
669
|
)
|
|
570
670
|
if rung == 1:
|
|
571
|
-
self._pending_steering =
|
|
671
|
+
self._pending_steering = (
|
|
672
|
+
self._failure_recovery_steering(repeated, count)
|
|
673
|
+
if reason == "failures"
|
|
674
|
+
else self._recovery_steering(repeated, count)
|
|
675
|
+
)
|
|
572
676
|
self._ledger.reset_counter()
|
|
573
677
|
return None
|
|
574
678
|
if rung == 2:
|
|
575
|
-
self._pending_steering =
|
|
679
|
+
self._pending_steering = (
|
|
680
|
+
self._failure_replan_steering(repeated, count)
|
|
681
|
+
if reason == "failures"
|
|
682
|
+
else self._replan_steering(repeated)
|
|
683
|
+
)
|
|
576
684
|
self._ledger.reset_counter()
|
|
577
685
|
self._ledger.clear_seen()
|
|
578
686
|
return Stalled(text="", no_progress_count=count)
|
|
@@ -593,6 +701,34 @@ class ExecutingState(AbstractState):
|
|
|
593
701
|
"partial results, naming exactly what is missing and why."
|
|
594
702
|
)
|
|
595
703
|
|
|
704
|
+
@staticmethod
|
|
705
|
+
def _failure_recovery_steering(tool: str, count: int) -> str:
|
|
706
|
+
return (
|
|
707
|
+
"[framework steering — repeated failures] The last "
|
|
708
|
+
f"{count} '{tool}' executions ALL failed. Whatever you are "
|
|
709
|
+
"retrying is not going to succeed by repetition. Decide now:\n"
|
|
710
|
+
"1. If the blocker is external (a service or endpoint down, "
|
|
711
|
+
"missing data), STOP calling it — record the blocker "
|
|
712
|
+
"(write_memory) and continue with work that does not need it.\n"
|
|
713
|
+
"2. If your code is failing, step back: print the intermediate "
|
|
714
|
+
"state, simplify to a minimal version, and rebuild from what "
|
|
715
|
+
"works.\n"
|
|
716
|
+
"3. If nothing can proceed, call final_answer with your best "
|
|
717
|
+
"partial results, naming exactly what is blocked and why."
|
|
718
|
+
)
|
|
719
|
+
|
|
720
|
+
@staticmethod
|
|
721
|
+
def _failure_replan_steering(tool: str, count: int) -> str:
|
|
722
|
+
return (
|
|
723
|
+
"[framework steering — approach failed] Executions kept failing "
|
|
724
|
+
f"(last {count} '{tool}' calls) despite a corrective "
|
|
725
|
+
"instruction: the current plan's approach is not working. "
|
|
726
|
+
"Re-plan now. In the revised plan: treat the failing "
|
|
727
|
+
"step/service as unavailable and route around it; reuse the "
|
|
728
|
+
"workspace results that already exist instead of redoing "
|
|
729
|
+
"completed work."
|
|
730
|
+
)
|
|
731
|
+
|
|
596
732
|
@staticmethod
|
|
597
733
|
def _replan_steering(repeated: str) -> str:
|
|
598
734
|
return (
|
|
@@ -222,6 +222,20 @@ def test_summary_carries_registry_and_failure_lines():
|
|
|
222
222
|
assert "Boom: file not found" in summary
|
|
223
223
|
|
|
224
224
|
|
|
225
|
+
def test_summary_points_at_kernel_history_on_the_jupyter_lane():
|
|
226
|
+
log = _spine_log(2)
|
|
227
|
+
dropped = select_settled_range(
|
|
228
|
+
log.events(), keep_recent_pairs=0, target_tokens=10_000
|
|
229
|
+
)
|
|
230
|
+
jupyter_ctx = SimpleNamespace(conversation=log, remote_python_executor=object())
|
|
231
|
+
summary = build_summary(jupyter_ctx, dropped)
|
|
232
|
+
assert ".aisolate/cells_ok.py" in summary
|
|
233
|
+
assert "%history" in summary
|
|
234
|
+
|
|
235
|
+
shell_ctx = SimpleNamespace(conversation=log)
|
|
236
|
+
assert "%history" not in build_summary(shell_ctx, dropped)
|
|
237
|
+
|
|
238
|
+
|
|
225
239
|
def test_squash_event_shape_matches_the_view_contracts():
|
|
226
240
|
"""kernel author + ok:True + no tool_call_id: passes paired_tools_only,
|
|
227
241
|
passes ok_code_only (the acceptance view), renders as a TOOL turn."""
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
"""Package-boundary checks for the independently released agent."""
|
|
2
|
+
|
|
3
|
+
import subprocess
|
|
4
|
+
import sys
|
|
5
|
+
import textwrap
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
def test_agent_imports_without_sandbox_package():
|
|
9
|
+
script = textwrap.dedent(
|
|
10
|
+
"""
|
|
11
|
+
import sys
|
|
12
|
+
|
|
13
|
+
class SandboxBlocker:
|
|
14
|
+
def find_spec(self, name, path=None, target=None):
|
|
15
|
+
if name == "aisolate.sandbox" or name.startswith("aisolate.sandbox."):
|
|
16
|
+
raise ModuleNotFoundError("aisolate.sandbox is not part of aisolate-agent")
|
|
17
|
+
|
|
18
|
+
sys.meta_path.insert(0, SandboxBlocker())
|
|
19
|
+
|
|
20
|
+
import aisolate.agent
|
|
21
|
+
"""
|
|
22
|
+
)
|
|
23
|
+
process = subprocess.run(
|
|
24
|
+
[sys.executable, "-c", script],
|
|
25
|
+
capture_output=True,
|
|
26
|
+
text=True,
|
|
27
|
+
timeout=120,
|
|
28
|
+
check=False,
|
|
29
|
+
)
|
|
30
|
+
assert process.returncode == 0, process.stderr
|