AbstractRuntime 0.10.1__tar.gz → 0.10.2__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.
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/CHANGELOG.md +22 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/PKG-INFO +1 -1
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/pyproject.toml +1 -1
- abstractruntime-0.10.2/release-notes.md +19 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/src/abstractruntime/visualflow_compiler/visual/code_executor.py +213 -18
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/src/abstractruntime/visualflow_compiler/visual/function_library.py +8 -6
- abstractruntime-0.10.2/tests/test_code_node_imports.py +212 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_visualflow_function_library.py +2 -2
- abstractruntime-0.10.1/release-notes.md +0 -4
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/.github/workflows/ci.yml +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/.github/workflows/release.yml +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/.gitignore +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/ACKNOWLEDGMENTS.md +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/CODE_OF_CONDUCT.md +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/CONTRIBUTING.md +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/LICENSE +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/README.md +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/ROADMAP.md +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/SECURITY.md +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/docs/README.md +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/docs/adr/0001_layered_coupling_with_abstractcore.md +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/docs/adr/0002_execution_modes_local_remote_hybrid.md +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/docs/adr/0003_provenance_tamper_evident_hash_chain.md +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/docs/adr/0004_runtime_owns_run_scoped_media_execution_truth.md +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/docs/adr/0005_runtime_owns_abstractcore_host_discovery_queries.md +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/docs/adr/0006_runtime_owns_durable_abstractcore_bloc_prompt_cache.md +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/docs/adr/0007_runtime_relays_core_owned_model_residency_truth.md +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/docs/adr/README.md +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/docs/api.md +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/docs/architecture.md +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/docs/artifacts.md +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/docs/automations.md +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/docs/backlog/README.md +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/docs/backlog/completed/001_runtime_kernel.md +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/docs/backlog/completed/002_persistence_and_ledger.md +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/docs/backlog/completed/0030_runtime_host_facades_for_comms_telegram_and_tool_specs.md +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/docs/backlog/completed/0032_runtime_durable_outbound_comms_truth.md +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/docs/backlog/completed/0033_runtime_host_local_prompt_cache_export_import_surface.md +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/docs/backlog/completed/0035_model_residency_provider_truth_for_local_http_clients.md +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/docs/backlog/completed/0037_visualflow_generate_music_node_compiler_parity.md +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/docs/backlog/completed/0039_runtime_music_structure_prompt_bool_contract.md +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/docs/backlog/completed/003_wait_primitives.md +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/docs/backlog/completed/0040_task_agnostic_local_residency_listing.md +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/docs/backlog/completed/0041_runtime_hardware_extras_avoid_nonpermissive_document_stacks.md +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/docs/backlog/completed/0042_core_vision_upscale_and_parameter_surface.md +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/docs/backlog/completed/0043_runtime_vision_adapter_and_batch_surface.md +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/docs/backlog/completed/004_scheduler_driver.md +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/docs/backlog/completed/005_abstractcore_integration.md +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/docs/backlog/completed/006_snapshots_bookmarks.md +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/docs/backlog/completed/007_provenance_hash_chain.md +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/docs/backlog/completed/009_artifact_store.md +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/docs/backlog/completed/010_examples_and_composition.md +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/docs/backlog/completed/011_subworkflow_support.md +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/docs/backlog/completed/012_run_store_query_and_scheduler_support.md +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/docs/backlog/completed/013_effect_retries_and_idempotency.md +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/docs/backlog/completed/016_runtime_aware_parameters.md +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/docs/backlog/completed/019_runtime_host_facade_for_core_operator_surfaces.md +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/docs/backlog/completed/020_runtime_gateway_install_boundary.md +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/docs/backlog/completed/021_runtime_gateway_env_namespace_cleanup.md +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/docs/backlog/completed/022_model_residency_control_plane.md +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/docs/backlog/completed/023_truthful_local_media_residency_boundaries.md +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/docs/backlog/completed/024_runtime_owned_run_scoped_media_execution.md +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/docs/backlog/completed/026_runtime_host_discovery_facade_for_core_catalogs.md +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/docs/backlog/completed/027_runtime_durable_bloc_prompt_cache_facade.md +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/docs/backlog/completed/028_runtime_bloc_kv_lifecycle_and_pruning.md +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/docs/backlog/completed/029_runtime_music_generation_and_discovery_via_abstractcore.md +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/docs/backlog/completed/0846_mlx_instance_scheduling_and_execution_controls.md +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/docs/backlog/completed/0847_automations_v1_controller_contracts_occurrences_triggers.md +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/docs/backlog/deprecated/001_integrations_abstractcore.md +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/docs/backlog/deprecated/001_runtime_kernel.md +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/docs/backlog/deprecated/002_persistence_and_ledger.md +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/docs/backlog/deprecated/002_snapshots_bookmarks.md +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/docs/backlog/deprecated/0034_agent_runtime_convenience_constructor.md +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/docs/backlog/deprecated/003_provenance_ledger_chain.md +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/docs/backlog/deprecated/003_wait_resume_and_scheduler.md +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/docs/backlog/deprecated/004_effect_handlers_and_integrations.md +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/docs/backlog/deprecated/004_tests.md +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/docs/backlog/deprecated/005_docs_updates.md +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/docs/backlog/deprecated/005_examples_and_composition.md +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/docs/backlog/deprecated/006_ai_fingerprint_and_provenance.md +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/docs/backlog/deprecated/DEPRECATED_README.md +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/docs/backlog/deprecated/README.md +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/docs/backlog/deprecated/abstractruntime_docs_final_02a7373b.plan.md +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/docs/backlog/planned/0070_standalone_wui_browser_session_security_contract.md +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/docs/backlog/planned/008_signatures_and_keys.md +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/docs/backlog/planned/014_remote_tool_worker_executor.md +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/docs/backlog/planned/017_limit_warnings_and_observability.md +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/docs/backlog/planned/018_workspace_access_policy_for_media_and_tools.md +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/docs/backlog/planned/0233_real_run_cancellation.md +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/docs/backlog/planned/025_runtime_retention_and_purge_contract.md +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/docs/backlog/planned/026_context_checkpoint_self_compression.md +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/docs/backlog/planned/027_quote_provenance_discipline.md +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/docs/backlog/planned/028_selective_artifact_rehydration.md +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/docs/backlog/planned/0845_session_prompt_cache_resume_and_purge_contract.md +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/docs/backlog/planned/0848_automations_v2_external_event_inbox_and_run_triggers.md +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/docs/backlog/planned/runtime_portability/0065_portable_process_and_lock_layer.md +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/docs/backlog/planned/runtime_portability/0066_portable_io_and_media_reader.md +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/docs/backlog/planned/runtime_portability/README.md +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/docs/backlog/planned/runtime_systemic_reliability/0044_meta_analysis_record.md +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/docs/backlog/planned/runtime_systemic_reliability/0045_crash_replay_harness_and_ordering_invariant.md +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/docs/backlog/planned/runtime_systemic_reliability/0046_per_run_driver_exclusion.md +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/docs/backlog/planned/runtime_systemic_reliability/0047_indexed_idempotency_lookup.md +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/docs/backlog/planned/runtime_systemic_reliability/0048_durable_io_unification.md +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/docs/backlog/planned/runtime_systemic_reliability/0049_llm_client_mechanical_split.md +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/docs/backlog/planned/runtime_systemic_reliability/0050_control_sidecar_all_writers.md +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/docs/backlog/planned/runtime_systemic_reliability/0051_runtime_owned_durable_event_mailbox.md +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/docs/backlog/planned/runtime_systemic_reliability/0052_sync_store_event_loop_tripwire.md +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/docs/backlog/planned/runtime_systemic_reliability/0053_bounded_run_vars_growth.md +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/docs/backlog/planned/runtime_systemic_reliability/0054_runtime_health_counters.md +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/docs/backlog/planned/runtime_systemic_reliability/0055_jsonl_store_honesty.md +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/docs/backlog/planned/runtime_systemic_reliability/0064_prompt_cache_fingerprint_stability.md +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/docs/backlog/planned/runtime_systemic_reliability/0067_durable_write_discipline.md +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/docs/backlog/planned/runtime_systemic_reliability/0068_hot_path_store_reads.md +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/docs/backlog/planned/runtime_systemic_reliability/README.md +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/docs/backlog/proposed/0031_runtime_tool_spec_adapters_for_gateway_and_mcp.md +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/docs/backlog/proposed/0036_local_media_residency_bridge_to_core_residency.md +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/docs/backlog/proposed/0038_core_server_pool_residency_affinity.md +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/docs/backlog/proposed/0069_document_renderer_professional_figures.md +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/docs/backlog/proposed/runtime_systemic_reliability/0056_schema_version_and_quarantine_loading.md +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/docs/backlog/proposed/runtime_systemic_reliability/0057_trust_boundary_stamp_registry.md +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/docs/backlog/proposed/runtime_systemic_reliability/0058_terminal_run_archival_helper.md +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/docs/backlog/proposed/runtime_systemic_reliability/0059_memory_span_handler_extraction.md +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/docs/backlog/proposed/runtime_systemic_reliability/0060_visualflow_compiler_decomposition.md +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/docs/backlog/proposed/runtime_systemic_reliability/0061_root_api_deprecation_machinery.md +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/docs/backlog/proposed/runtime_systemic_reliability/0062_dependency_honesty_extras.md +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/docs/backlog/proposed/runtime_systemic_reliability/0063_b3_envelope_lane_unification.md +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/docs/backlog/proposed/runtime_systemic_reliability/README.md +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/docs/email.md +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/docs/entity-runtime.md +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/docs/evidence.md +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/docs/faq.md +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/docs/getting-started.md +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/docs/integrations/abstractcore.md +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/docs/limits.md +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/docs/manual_testing.md +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/docs/mcp-worker.md +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/docs/proposal.md +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/docs/provenance.md +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/docs/snapshots.md +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/docs/tool-approval.md +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/docs/tools-comms.md +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/docs/troubleshooting.md +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/docs/workflow-bundles.md +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/examples/01_hello_world.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/examples/02_ask_user.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/examples/03_wait_until.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/examples/04_multi_step.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/examples/05_persistence.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/examples/06_llm_integration.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/examples/07_react_agent.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/examples/README.md +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/llms-full.txt +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/llms.txt +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/mkdocs.yml +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/pytest.ini +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/scripts/backfill_diary_edges.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/scripts/generate_llms_full.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/src/abstractruntime/__init__.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/src/abstractruntime/automation_queries.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/src/abstractruntime/automations/__init__.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/src/abstractruntime/automations/adapters.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/src/abstractruntime/automations/attention.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/src/abstractruntime/automations/bundle.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/src/abstractruntime/automations/bundles/automation-controller/flows/controller.json +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/src/abstractruntime/automations/bundles/automation-controller/manifest.json +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/src/abstractruntime/automations/commands.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/src/abstractruntime/automations/controller.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/src/abstractruntime/automations/ledger.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/src/abstractruntime/automations/models.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/src/abstractruntime/automations/service.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/src/abstractruntime/core/__init__.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/src/abstractruntime/core/config.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/src/abstractruntime/core/effect_cancellation.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/src/abstractruntime/core/event_keys.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/src/abstractruntime/core/health.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/src/abstractruntime/core/live_deltas.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/src/abstractruntime/core/models.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/src/abstractruntime/core/policy.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/src/abstractruntime/core/progress_channel.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/src/abstractruntime/core/run_attribution.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/src/abstractruntime/core/run_identity.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/src/abstractruntime/core/run_lifecycle.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/src/abstractruntime/core/runtime.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/src/abstractruntime/core/spec.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/src/abstractruntime/core/tool_scope.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/src/abstractruntime/core/vars.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/src/abstractruntime/documents/__init__.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/src/abstractruntime/documents/charts.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/src/abstractruntime/documents/docx.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/src/abstractruntime/documents/pdf.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/src/abstractruntime/email/__init__.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/src/abstractruntime/email/actions.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/src/abstractruntime/email/automations.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/src/abstractruntime/email/binding.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/src/abstractruntime/email/feeder.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/src/abstractruntime/email/frame.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/src/abstractruntime/email/inbox.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/src/abstractruntime/evidence/__init__.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/src/abstractruntime/evidence/recorder.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/src/abstractruntime/history_bundle.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/src/abstractruntime/identity/__init__.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/src/abstractruntime/identity/act_only.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/src/abstractruntime/identity/chat.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/src/abstractruntime/identity/communities.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/src/abstractruntime/identity/diary.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/src/abstractruntime/identity/digest.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/src/abstractruntime/identity/entity_runtime.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/src/abstractruntime/identity/fingerprint.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/src/abstractruntime/identity/lease.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/src/abstractruntime/identity/life.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/src/abstractruntime/identity/memory_reader.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/src/abstractruntime/identity/night_voice.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/src/abstractruntime/identity/phase_graph.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/src/abstractruntime/identity/phase_spec.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/src/abstractruntime/identity/prelude.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/src/abstractruntime/identity/prompt_overlay.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/src/abstractruntime/identity/reflection.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/src/abstractruntime/identity/spec/entity_phases.vendored.json +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/src/abstractruntime/identity/substrate.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/src/abstractruntime/identity/tool_effects.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/src/abstractruntime/identity/tool_policy.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/src/abstractruntime/identity/tools.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/src/abstractruntime/identity/visit_workflow.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/src/abstractruntime/integrations/__init__.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/src/abstractruntime/integrations/abstractcore/__init__.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/src/abstractruntime/integrations/abstractcore/agora_tools.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/src/abstractruntime/integrations/abstractcore/command_sandbox_host.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/src/abstractruntime/integrations/abstractcore/comms_facade.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/src/abstractruntime/integrations/abstractcore/config_facade.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/src/abstractruntime/integrations/abstractcore/constants.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/src/abstractruntime/integrations/abstractcore/data_registry_facade.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/src/abstractruntime/integrations/abstractcore/default_tools.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/src/abstractruntime/integrations/abstractcore/discovery_facade.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/src/abstractruntime/integrations/abstractcore/discovery_queries.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/src/abstractruntime/integrations/abstractcore/effect_handlers.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/src/abstractruntime/integrations/abstractcore/email_facade.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/src/abstractruntime/integrations/abstractcore/embeddings_client.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/src/abstractruntime/integrations/abstractcore/factory.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/src/abstractruntime/integrations/abstractcore/host_facade.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/src/abstractruntime/integrations/abstractcore/llm_client.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/src/abstractruntime/integrations/abstractcore/local_helper_tools.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/src/abstractruntime/integrations/abstractcore/logging.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/src/abstractruntime/integrations/abstractcore/mcp_facade.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/src/abstractruntime/integrations/abstractcore/mcp_worker.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/src/abstractruntime/integrations/abstractcore/media_subprocess.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/src/abstractruntime/integrations/abstractcore/observability.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/src/abstractruntime/integrations/abstractcore/output_specs.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/src/abstractruntime/integrations/abstractcore/run_facade.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/src/abstractruntime/integrations/abstractcore/server_facade.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/src/abstractruntime/integrations/abstractcore/session_attachments.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/src/abstractruntime/integrations/abstractcore/structured_facade.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/src/abstractruntime/integrations/abstractcore/summarizer.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/src/abstractruntime/integrations/abstractcore/telegram_facade.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/src/abstractruntime/integrations/abstractcore/tool_effects.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/src/abstractruntime/integrations/abstractcore/tool_executor.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/src/abstractruntime/integrations/abstractcore/tool_inventory_facade.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/src/abstractruntime/integrations/abstractcore/workspace_scoped_tools.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/src/abstractruntime/integrations/abstractmemory/__init__.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/src/abstractruntime/integrations/abstractmemory/brain_handlers.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/src/abstractruntime/integrations/abstractmemory/effect_handlers.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/src/abstractruntime/integrations/abstractmemory/identity_support.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/src/abstractruntime/integrations/abstractmemory/seam_handlers.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/src/abstractruntime/memory/__init__.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/src/abstractruntime/memory/active_context.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/src/abstractruntime/memory/active_memory.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/src/abstractruntime/memory/compaction.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/src/abstractruntime/memory/kg_packets.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/src/abstractruntime/memory/memact_composer.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/src/abstractruntime/memory/recall_levels.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/src/abstractruntime/memory/token_budget.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/src/abstractruntime/rendering/__init__.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/src/abstractruntime/rendering/agent_trace_report.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/src/abstractruntime/rendering/json_stringify.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/src/abstractruntime/scheduler/__init__.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/src/abstractruntime/scheduler/convenience.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/src/abstractruntime/scheduler/multi_store.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/src/abstractruntime/scheduler/registry.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/src/abstractruntime/scheduler/scheduler.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/src/abstractruntime/session_history.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/src/abstractruntime/session_turns.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/src/abstractruntime/storage/__init__.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/src/abstractruntime/storage/artifacts.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/src/abstractruntime/storage/base.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/src/abstractruntime/storage/commands.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/src/abstractruntime/storage/in_memory.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/src/abstractruntime/storage/json_files.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/src/abstractruntime/storage/lease.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/src/abstractruntime/storage/ledger_chain.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/src/abstractruntime/storage/ledger_slim.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/src/abstractruntime/storage/observable.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/src/abstractruntime/storage/offloading.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/src/abstractruntime/storage/serialize.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/src/abstractruntime/storage/snapshots.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/src/abstractruntime/storage/sqlite.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/src/abstractruntime/storage/steer_sidecar.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/src/abstractruntime/triggers/__init__.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/src/abstractruntime/triggers/email_received.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/src/abstractruntime/triggers/manual.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/src/abstractruntime/triggers/protocol.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/src/abstractruntime/triggers/registry.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/src/abstractruntime/triggers/schedule.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/src/abstractruntime/turn_grounding.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/src/abstractruntime/utils/__init__.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/src/abstractruntime/utils/atomic_files.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/src/abstractruntime/utils/file_filters.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/src/abstractruntime/utils/workspace_paths.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/src/abstractruntime/visualflow_compiler/__init__.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/src/abstractruntime/visualflow_compiler/adapters/__init__.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/src/abstractruntime/visualflow_compiler/adapters/agent_adapter.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/src/abstractruntime/visualflow_compiler/adapters/context_adapter.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/src/abstractruntime/visualflow_compiler/adapters/control_adapter.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/src/abstractruntime/visualflow_compiler/adapters/effect_adapter.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/src/abstractruntime/visualflow_compiler/adapters/event_adapter.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/src/abstractruntime/visualflow_compiler/adapters/function_adapter.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/src/abstractruntime/visualflow_compiler/adapters/memact_adapter.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/src/abstractruntime/visualflow_compiler/adapters/subflow_adapter.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/src/abstractruntime/visualflow_compiler/adapters/variable_adapter.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/src/abstractruntime/visualflow_compiler/compiler.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/src/abstractruntime/visualflow_compiler/flow.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/src/abstractruntime/visualflow_compiler/visual/__init__.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/src/abstractruntime/visualflow_compiler/visual/agent_ids.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/src/abstractruntime/visualflow_compiler/visual/builtins.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/src/abstractruntime/visualflow_compiler/visual/execution_metrics.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/src/abstractruntime/visualflow_compiler/visual/executor.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/src/abstractruntime/visualflow_compiler/visual/loop_back_check.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/src/abstractruntime/visualflow_compiler/visual/loop_limit_lowering.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/src/abstractruntime/visualflow_compiler/visual/models.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/src/abstractruntime/visualflow_compiler/visual/multi_entry_lowering.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/src/abstractruntime/visualflow_compiler/visual/pin_expressions.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/src/abstractruntime/visualflow_compiler/visual/reroute_lowering.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/src/abstractruntime/workflow_bundle/__init__.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/src/abstractruntime/workflow_bundle/models.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/src/abstractruntime/workflow_bundle/packer.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/src/abstractruntime/workflow_bundle/reader.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/src/abstractruntime/workflow_bundle/registry.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/README.md +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/automation_harness.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/conftest.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/email_wp2_support.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/fixtures/schedule_v1_corpus.json +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/live_email/conftest.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/live_email/live_email_support.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/live_email/test_email_live_runtime.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_abstractcore_comms_facade.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_abstractcore_discovery_facade.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_abstractcore_host_facade.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_abstractcore_run_facade.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_abstractcore_server_facade.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_abstractcore_structured_facade.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_abstractcore_telegram_facade.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_active_context_policy.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_active_index.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_active_memory.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_agora_agent_alias_identity.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_agora_tools_http.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_analyze_media_addressing_and_walling.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_answer_user_effect.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_artifacts.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_automation_calendar_schedule.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_automation_commands.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_automation_controller.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_automation_controller_recovery.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_automation_definition.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_automation_discussion_isolation.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_automation_email_results.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_automation_growing_context.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_automation_index.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_automation_next_fire.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_automation_occurrence_input_resolver.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_automation_occurrence_recovery.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_automation_replay_read_only.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_automation_retry.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_automation_session_turns.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_automation_status.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_automation_tool_approval.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_browser_probe_target_walling.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_budget_law_no_unrequested_caps.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_capability_default_reasoning.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_chat_summarizer_integration.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_code_node_restricted_python.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_command_sandbox_host_facade.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_command_store.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_compaction_helpers.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_compaction_summarizer_route.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_config_facade_models_engines.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_config_facade_voice_input_hint.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_control_adapter_while.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_controller_bundle_packaged.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_crash_ordering_inversions.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_create_if_absent.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_data_registry_facade.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_default_tools_camera_gating.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_default_tools_comms_gating.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_default_tools_include_skim_files.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_default_tools_include_skim_folders.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_default_tools_include_skim_web.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_default_tools_search_files_executor.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_diary_capture.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_diary_write_rescue.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_directory_lease.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_disabled_toolsets_seam.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_discovery_survives_unbuildable_default.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_discovery_tts_unavailable_reason.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_discovery_voice_openai_api_key.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_discussion_session_anchor.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_document_markdown_tables.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_document_renderers_hr_quote.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_durable_toolsets.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_durable_write_discipline.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_e2e_tool_calls_idempotency_lmstudio.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_effect_cancellation.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_effect_issuance_idempotency.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_effect_payload_stays_json_serializable.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_election_consequence_teaching.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_email_binding_and_refiner.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_email_gate_fixes.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_email_inbox_and_trigger.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_email_regate_fixes.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_email_review_fixes.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_email_self_trigger_loop.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_email_toolset_and_walls.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_emergence_experiment.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_emit_event_uses_wait_index.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_emit_event_without_workflow_registry.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_endpoint_profile_route_context.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_entity_awake_memory_fixes.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_entity_brain_effects.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_entity_chat_driver.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_entity_chat_tools_reflection.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_entity_diary.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_entity_execute_tool.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_entity_fetch_url_tool.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_entity_history_window.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_entity_life_loop.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_entity_memory_richness.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_entity_phase_graph_conformance.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_entity_react_visit_window.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_entity_recent_memories.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_entity_runtime.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_entity_search_memory.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_entity_sleep_bound_and_yield_attribution.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_entity_substrate_resolution.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_entity_visit_honesty.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_entity_workspace_cap.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_entity_workspace_tools.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_event_wait_index.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_every_path_bearing_tool_is_walled.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_evidence_recorder.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_evidence_recorder_post_policy_envelope.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_execute_command_output_offload.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_execution_capability_discovery.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_explicit_eject_other_clients.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_factory_default_retry_policy.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_factory_timeouts_default_to_abstractcore_config.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_format_repair_nudge.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_fresh_install_no_provider.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_gateway_facades_c4899.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_git_read_only_refiner.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_hf_process_residency_merge.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_history_window_multimodal.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_hot_path_store_reads.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_indexed_idempotency_lookup.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_integration_abstractcore.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_integrations_abstractcore.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_json_file_run_store_children_index.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_json_run_cache_bound.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_json_store_scan_memo.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_jsonl_ledger_recovery.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_kg_learn_and_recall_contract.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_ledger_chain.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_ledger_record_slimming.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_ledger_subscription.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_live_token_deltas.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_llm_call_media_artifact_refs.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_llm_call_media_artifact_refs_persist_across_restart.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_llm_call_media_uses_source_path_label.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_llm_call_payload_shape_refusal.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_llm_call_requires_prompt.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_llm_call_response_schema_normalization.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_llm_call_structured_output_fallback.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_llm_call_text_phase_progress.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_llm_call_truncation_retry_contract.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_llm_call_use_context_appends_turn.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_llm_call_verbatim_payload_capture.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_llm_client_grounding_tail.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_llm_client_media_artifacts.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_llm_client_system_context.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_llm_client_tool_call_parsing.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_llm_retry_classification.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_llm_streaming_on_token.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_local_helper_tool_exposure.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_local_residency_host_sweep.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_local_runtime_timeout_kwarg_policy.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_max_iterations_ceiling.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_mcp_remote_tool_executor.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_mcp_runs_untrusted_and_facade.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_mcp_worker_logging.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_mcp_worker_security.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_mcp_worker_stdio.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_media_artifact_resolution.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_media_capability_default_routing.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_media_only_requests_skip_text_client.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_media_subprocess.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_memact_composer_from_kg_result.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_memory_appraise_handler.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_memory_communities.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_memory_kg_assert_attributes_defaults.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_memory_kg_packets.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_memory_kg_predicate_aliasing.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_memory_kg_query_packetization_restart.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_memory_kg_query_recall_level_policy.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_memory_kg_semantic_query_ranking.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_memory_note_effect.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_memory_query_effect.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_memory_query_rich_filters.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_memory_scope_and_rehydrate_effect.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_memory_seam_handlers.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_memory_seam_sqlite_durability.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_memory_tag_effect.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_mlx_generation_serialization.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_mlx_process_residency_merge.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_model_eject_cancel.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_model_residency_clean_switch.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_model_residency_control_plane.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_model_residency_lock_and_context_estimate.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_multi_store_scheduler.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_multimodal_abstractcore_integration.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_native_mlx_application_wiring.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_native_mlx_execution_controls_live.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_native_tool_channel.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_night_voice.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_no_default_provider_refusal_ux.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_offload_answer_chain_c4978.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_offloaded_node_traces_report_unknown_not_zero.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_offloading.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_packaging_extras.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_parallel_readonly_tool_execution.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_pause_resume.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_pdf_unicode_rendering.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_personal_cycle.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_phantom_attachment_index.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_phase_graph_artifact_control.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_phase_graph_obedience.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_phase_vocabulary_migration.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_pooled_client_strips_construction_cache_key.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_prompt_cache_export_import.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_prompt_cache_fingerprint_stability.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_prompt_cache_modules.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_prompt_cache_posture_inheritance.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_prompt_cache_thinking_and_prompt_only.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_prompt_overlay.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_provider_endpoint_profile_resolution.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_provider_pin_routing_isolation.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_queryable_run_store.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_r12_workspace_sandbox.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_read_file_fallback_to_session_attachments.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_read_idle_threading.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_readoption_experiment.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_real_integration.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_realize_election.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_recall_levels_policy.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_remote_client_cancel.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_remote_llm_client.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_remote_speculation_defaults.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_rendering_agent_trace_report.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_rendering_json_stringify.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_report_branding.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_resident_media_generation.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_resume_concurrent_same_wait.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_retry_idempotency.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_run_history_bundle.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_run_index_workspace_root.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_run_mutation_lock.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_run_scoped_tool_policy.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_run_tool_scope_ceiling.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_runtime_browser_session_boundary.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_runtime_config_max_output_tokens_fallback.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_runtime_default_provider_model_refresh.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_runtime_effect_invocation_trace.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_runtime_health_and_bounded_vars.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_runtime_install_boundary.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_runtime_llm_call_grounding_in_ledger.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_runtime_node_traces.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_runtime_start_seeds_tool_support.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_runtime_tick_step_gate.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_schedule_v1_corpus.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_schedule_v2_calendar.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_scheduler.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_send_email_refiner.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_send_email_self_default_policy.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_session_attachments_registry_and_open_tool.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_session_history.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_session_prompt_cache_attribution.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_session_prompt_cache_visibility.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_session_route_stamp.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_session_start_cost.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_shell_tool_exposure.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_snapshots.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_speculation_inheritance.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_speculation_reaches_provider_construction.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_sqlite_ledger_store.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_start_subworkflow_async_wait.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_start_subworkflow_inherit_context_merges_messages.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_start_subworkflow_workspace_inheritance.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_steer_sidecar.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_storage_deletion.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_structured_output_schema_enum.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_subworkflow.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_terminal_effect_completion.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_terminal_resume_appends_ledger_completion.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_thinking_inheritance.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_tick_completion_includes_output_in_ledger.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_tool_approval_executor.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_tool_approval_resume_executes.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_tool_approval_wait_key_identity.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_tool_calls_idempotency_keys.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_tool_catalog.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_tool_descriptor_registry.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_tool_executor_argument_sanitization.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_tool_executor_error_output_detection.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_tool_executor_filename_alias.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_tool_executor_kwarg_canonicalization.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_tool_executor_read_file_aliases.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_tool_executor_timeout.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_tool_inventory_facade.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_tool_invoke_effect.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_tool_policy_and_mounts.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_tool_wait_allowlist_safety.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_topic_election_world_model.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_trace_context_propagation.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_trigger_registry.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_trigger_schedule_math.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_turn_grounding_byte_stability.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_turn_grounding_carriers_a3.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_vars_query_effect.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_visit_ab_fixture.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_visit_midturn_elections.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_visit_midturn_resume.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_visit_workflow.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_visual_agent_output_context_includes_messages.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_visual_agent_skills_block_passthrough.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_visual_agent_tool_observations_persist_across_restart.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_visual_agent_use_context_inherits_attachments.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_visual_agent_use_context_persists_tool_observations.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_visual_agent_use_context_persists_turn.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_visual_entity_memory_nodes.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_visual_flow_end_effect_only_persistence.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_visual_llm_call_partial_override.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_visual_llm_call_schema_ref_resolution.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_visual_loop_back_out_of_body.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_visual_loop_limit_and_list_nodes.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_visual_loop_limit_on_wire.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_visual_memact_compose_node.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_visual_memory_kg_query_outputs_propagate.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_visual_memory_kg_resolve_outputs_propagate.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_visual_multi_entry_loop_overrides.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_visual_reroute_lowering.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_visual_set_vars_pins.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_visual_unknown_node_type_refuses.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_visual_wait_event_deadline_passthrough.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_visualflow_add_message_builtin.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_visualflow_add_message_node_appends_to_active_context.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_visualflow_agora_react_agent.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_visualflow_call_tool_node.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_visualflow_capability_routes_and_thinking.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_visualflow_compiler_basic.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_visualflow_context_and_builder_nodes.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_visualflow_continue_on_error.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_visualflow_edit_json_schema_node.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_visualflow_event_inbox_react_agent.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_visualflow_file_nodes_workspace.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_visualflow_get_element_node.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_visualflow_get_random_element_node.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_visualflow_get_var_node.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_visualflow_has_tools_builtin.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_visualflow_llm_call_context_attachments_map_to_media.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_visualflow_llm_call_multimodal_output.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_visualflow_make_object_node.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_visualflow_media_nodes.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_visualflow_memory_effect_nodes.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_visualflow_memory_source_pins.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_visualflow_pin_expressions.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_visualflow_prompt_only.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_visualflow_random_nodes.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_visualflow_schema_enum_switch.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_visualflow_string_contains_replace.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_visualflow_tool_parameters_node.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_voice_openai_api_key_path.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_voice_stream_is_not_a_wait.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_w4_feelings_lens.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_wait_event_deadline.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_wait_event_prompt_metadata.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_wait_until_streak.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_wait_until_utc_normalization.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_workflow_bundle_registry.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_workspace_builtin_deny.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_workspace_context_allowed_workspaces.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_workspace_policy_absolute_reanchor.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_workspace_policy_allowlist_mode.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_workspace_policy_mount_virtual_paths.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_workspace_policy_tool_calls_persist_across_restart.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_workspace_prompt_context.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_workspace_read_only.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_workspace_writable_paths.py +0 -0
- {abstractruntime-0.10.1 → abstractruntime-0.10.2}/tests/test_write_chart.py +0 -0
|
@@ -5,6 +5,28 @@ All notable changes to AbstractRuntime will be documented in this file.
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
+
## [0.10.2] - 2026-10-16
|
|
9
|
+
|
|
10
|
+
### Changed
|
|
11
|
+
|
|
12
|
+
- **Code nodes can import Python's standard library.** In the `sandbox` permission mode, `import json`, `re`,
|
|
13
|
+
`datetime`, `math`, `collections`, `itertools`, `statistics`, `textwrap`, `hashlib`, `urllib.parse`… now
|
|
14
|
+
work, at the top of the code and inside functions, in both the RestrictedPython lane and the fallback lane, and
|
|
15
|
+
inside the function bodies of flow function libraries. The sandbox still refuses third-party packages, private
|
|
16
|
+
(`_`-prefixed) modules, and the standard-library modules that reach the machine or go around the sandbox's own
|
|
17
|
+
checks: processes and the operating system (`os`, `subprocess`, `threading`, `signal`, `ctypes`, `platform`…), files (`io`,
|
|
18
|
+
`pathlib`, `shutil`, `tempfile`, `glob`, `sqlite3`, `logging`, and the parsers that read a file by path: `xml`,
|
|
19
|
+
`configparser`, `argparse`…), the network (`socket`, `http`, `urllib.request`, `smtplib`…), code loading or
|
|
20
|
+
interpreter internals (`sys`, `importlib`, `pickle`, `types`, `inspect`…) and attribute access by name,
|
|
21
|
+
evaluated annotations or frames (`operator`, `typing`, `functools`, `traceback`). A refusal names the module
|
|
22
|
+
and the reason; `from x import *`, relative imports and the `__import__` call stay refused.
|
|
23
|
+
- **A Code node's return value must be JSON data.** `transform` returning a module, a function, a set, bytes or
|
|
24
|
+
any other value JSON cannot carry now fails with a sandbox error naming the value and where it sits
|
|
25
|
+
(`transform returned a value that cannot be sent as JSON: module 'time' at output[2]`), in every permission
|
|
26
|
+
mode, instead of a serializer crash later in the gateway's simulate reply or the run's persisted state. `full_access` (host policy) imports anything, as before.
|
|
27
|
+
The rule is applied twice: at compile time by `validate_code`, and at run time by the `__import__` bound into
|
|
28
|
+
the sandbox builtins. `get_code_execution_policy()` now lists `imports.denied_modules` for thin clients.
|
|
29
|
+
|
|
8
30
|
## [0.10.1] - 2026-10-16
|
|
9
31
|
|
|
10
32
|
### Changed
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: AbstractRuntime
|
|
3
|
-
Version: 0.10.
|
|
3
|
+
Version: 0.10.2
|
|
4
4
|
Summary: AbstractRuntime: a durable graph runner designed to pair with AbstractCore.
|
|
5
5
|
Project-URL: AbstractCore (website), https://www.abstractcore.ai/
|
|
6
6
|
Project-URL: AbstractRuntime (GitHub), https://github.com/lpalbou/abstractruntime
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
### Changed
|
|
2
|
+
|
|
3
|
+
- **Code nodes can import Python's standard library.** In the `sandbox` permission mode, `import json`, `re`,
|
|
4
|
+
`datetime`, `math`, `collections`, `itertools`, `statistics`, `textwrap`, `hashlib`, `urllib.parse`… now
|
|
5
|
+
work, at the top of the code and inside functions, in both the RestrictedPython lane and the fallback lane, and
|
|
6
|
+
inside the function bodies of flow function libraries. The sandbox still refuses third-party packages, private
|
|
7
|
+
(`_`-prefixed) modules, and the standard-library modules that reach the machine or go around the sandbox's own
|
|
8
|
+
checks: processes and the operating system (`os`, `subprocess`, `threading`, `signal`, `ctypes`, `platform`…), files (`io`,
|
|
9
|
+
`pathlib`, `shutil`, `tempfile`, `glob`, `sqlite3`, `logging`, and the parsers that read a file by path: `xml`,
|
|
10
|
+
`configparser`, `argparse`…), the network (`socket`, `http`, `urllib.request`, `smtplib`…), code loading or
|
|
11
|
+
interpreter internals (`sys`, `importlib`, `pickle`, `types`, `inspect`…) and attribute access by name,
|
|
12
|
+
evaluated annotations or frames (`operator`, `typing`, `functools`, `traceback`). A refusal names the module
|
|
13
|
+
and the reason; `from x import *`, relative imports and the `__import__` call stay refused.
|
|
14
|
+
- **A Code node's return value must be JSON data.** `transform` returning a module, a function, a set, bytes or
|
|
15
|
+
any other value JSON cannot carry now fails with a sandbox error naming the value and where it sits
|
|
16
|
+
(`transform returned a value that cannot be sent as JSON: module 'time' at output[2]`), in every permission
|
|
17
|
+
mode, instead of a serializer crash later in the gateway's simulate reply or the run's persisted state. `full_access` (host policy) imports anything, as before.
|
|
18
|
+
The rule is applied twice: at compile time by `validate_code`, and at run time by the `__import__` bound into
|
|
19
|
+
the sandbox builtins. `get_code_execution_policy()` now lists `imports.denied_modules` for thin clients.
|
|
@@ -8,8 +8,10 @@ without importing the web backend implementation.
|
|
|
8
8
|
from __future__ import annotations
|
|
9
9
|
|
|
10
10
|
import ast
|
|
11
|
+
import builtins as _builtins
|
|
11
12
|
import os
|
|
12
|
-
|
|
13
|
+
import sys
|
|
14
|
+
from typing import Any, Callable, Dict, Optional
|
|
13
15
|
|
|
14
16
|
# Try to import RestrictedPython, fall back to basic execution if not available
|
|
15
17
|
try:
|
|
@@ -83,6 +85,173 @@ if RESTRICTED_PYTHON_AVAILABLE:
|
|
|
83
85
|
super().check_name(node, name, allow_magic_methods)
|
|
84
86
|
|
|
85
87
|
|
|
88
|
+
# ---------------------------------------------------------------------------
|
|
89
|
+
# Imports in the sandbox: Python's own standard library, except the modules
|
|
90
|
+
# that reach outside the interpreter. One rule for the AST check at compile
|
|
91
|
+
# time (validate_code) and the ``__import__`` guard at run time (the guard is
|
|
92
|
+
# what actually gates: the AST check only makes the refusal early and clear).
|
|
93
|
+
# ---------------------------------------------------------------------------
|
|
94
|
+
|
|
95
|
+
# Top-level standard-library modules the sandbox refuses, each with the reason
|
|
96
|
+
# shown to the author. Grouped by what the module reaches.
|
|
97
|
+
SANDBOX_DENIED_MODULES: Dict[str, str] = {
|
|
98
|
+
# processes, the OS, the interpreter
|
|
99
|
+
**{m: "processes and the operating system" for m in (
|
|
100
|
+
"os", "posix", "nt", "posixpath", "ntpath", "genericpath", "subprocess", "multiprocessing",
|
|
101
|
+
"threading", "_thread", "concurrent", "asyncio", "signal", "ctypes", "resource", "pwd", "grp",
|
|
102
|
+
"pty", "tty", "termios", "fcntl", "pipes", "crypt", "spwd", "nis", "syslog", "mmap", "msvcrt",
|
|
103
|
+
"winreg", "winsound", "ossaudiodev", "locale", "getpass", "readline", "rlcompleter", "cmd",
|
|
104
|
+
"atexit", "faulthandler", "gc", "webbrowser", "antigravity", "this", "turtle", "turtledemo",
|
|
105
|
+
"tkinter", "curses", "idlelib",
|
|
106
|
+
# runs uname/sw_vers and reads /etc/os-release to answer
|
|
107
|
+
"platform",
|
|
108
|
+
)},
|
|
109
|
+
# files on the machine
|
|
110
|
+
**{m: "files on the machine" for m in (
|
|
111
|
+
"io", "pathlib", "shutil", "tempfile", "glob", "fileinput", "linecache", "filecmp", "zipfile",
|
|
112
|
+
"tarfile", "gzip", "bz2", "lzma", "dbm", "shelve", "sqlite3", "codecs", "logging", "wave", "aifc",
|
|
113
|
+
"sunau", "chunk", "sndhdr", "imghdr", "tokenize", "mailbox", "mailcap", "netrc", "uu", "cgi",
|
|
114
|
+
"cgitb", "pyclbr", "tabnanny",
|
|
115
|
+
# parsers and readers that take a file PATH (xml.*.parse, configparser.read,
|
|
116
|
+
# argparse's @argument-files, gettext's catalogs)
|
|
117
|
+
"xml", "pyexpat", "configparser", "argparse", "optparse", "gettext",
|
|
118
|
+
# read_mime_types(path) / MimeTypes.read(path)
|
|
119
|
+
"mimetypes",
|
|
120
|
+
)},
|
|
121
|
+
# the network
|
|
122
|
+
**{m: "the network" for m in (
|
|
123
|
+
"socket", "ssl", "select", "selectors", "socketserver", "http", "ftplib", "poplib", "imaplib",
|
|
124
|
+
"smtplib", "smtpd", "nntplib", "telnetlib", "xmlrpc", "wsgiref", "asynchat", "asyncore",
|
|
125
|
+
)},
|
|
126
|
+
# loading or running code, interpreter internals
|
|
127
|
+
**{m: "loading or running code" for m in (
|
|
128
|
+
"sys", "builtins", "importlib", "pkgutil", "runpy", "zipimport", "modulefinder", "code", "codeop",
|
|
129
|
+
"compileall", "py_compile", "marshal", "pickle", "pickletools", "copyreg", "types", "inspect",
|
|
130
|
+
"dis", "site", "sysconfig", "timeit", "doctest", "unittest", "pdb", "bdb", "trace", "profile",
|
|
131
|
+
"cProfile", "pstats", "tracemalloc", "test", "lib2to3", "pydoc", "pydoc_data", "ensurepip", "venv",
|
|
132
|
+
"zipapp", "distutils", "msilib", "__main__", "opcode", "symtable",
|
|
133
|
+
)},
|
|
134
|
+
# around the sandbox's own checks: attribute access by NAME (which the dunder
|
|
135
|
+
# rule cannot see), evaluation of annotation strings, access to frames
|
|
136
|
+
**{m: "around the sandbox's checks (attributes by name, evaluated annotations, frames)" for m in (
|
|
137
|
+
"operator", "typing", "functools", "traceback",
|
|
138
|
+
)},
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
# A refused package whose one pure submodule is allowed: ``urllib.parse``
|
|
142
|
+
# (URL parsing) is fine, ``urllib.request`` is the network.
|
|
143
|
+
SANDBOX_ALLOWED_SUBMODULES: frozenset = frozenset({"urllib.parse"})
|
|
144
|
+
|
|
145
|
+
_STDLIB_MODULE_NAMES: frozenset = frozenset(getattr(sys, "stdlib_module_names", ()))
|
|
146
|
+
|
|
147
|
+
|
|
148
|
+
def sandbox_import_reason(name: str) -> Optional[str]:
|
|
149
|
+
"""Why the sandbox refuses importing ``name`` — or None when it is allowed.
|
|
150
|
+
|
|
151
|
+
Allowed: a module of Python's own standard library whose top-level package
|
|
152
|
+
is not in SANDBOX_DENIED_MODULES (plus the listed pure submodules of a
|
|
153
|
+
refused package). Refused: everything else — third-party packages, private
|
|
154
|
+
(``_``-prefixed) modules, and the standard-library modules that reach
|
|
155
|
+
processes, files, the network or code loading. ``full_access`` (host
|
|
156
|
+
policy) lifts every limit.
|
|
157
|
+
"""
|
|
158
|
+
dotted = str(name or "").strip()
|
|
159
|
+
if not dotted:
|
|
160
|
+
return "an empty module name"
|
|
161
|
+
if dotted in SANDBOX_ALLOWED_SUBMODULES:
|
|
162
|
+
return None
|
|
163
|
+
top = dotted.split(".", 1)[0]
|
|
164
|
+
if top == "__future__":
|
|
165
|
+
return None
|
|
166
|
+
if top.startswith("_"):
|
|
167
|
+
return "a private module"
|
|
168
|
+
reason = SANDBOX_DENIED_MODULES.get(top)
|
|
169
|
+
if reason is not None:
|
|
170
|
+
return f"it reaches {reason}"
|
|
171
|
+
if top == "urllib":
|
|
172
|
+
return "it reaches the network; only urllib.parse is importable"
|
|
173
|
+
if top not in _STDLIB_MODULE_NAMES:
|
|
174
|
+
return "only Python's own standard library is importable"
|
|
175
|
+
return None
|
|
176
|
+
|
|
177
|
+
|
|
178
|
+
def sandbox_import_check(name: str, fromlist: Any = ()) -> None:
|
|
179
|
+
"""Raise CodeExecutionError when the sandbox refuses importing ``name``.
|
|
180
|
+
|
|
181
|
+
``fromlist`` are the names of a ``from name import a, b`` statement: a
|
|
182
|
+
refused package is still fine when every one of them is an allowed
|
|
183
|
+
submodule (``from urllib import parse``).
|
|
184
|
+
"""
|
|
185
|
+
reason = sandbox_import_reason(name)
|
|
186
|
+
if reason is not None and fromlist and all(
|
|
187
|
+
isinstance(item, str) and f"{name}.{item}" in SANDBOX_ALLOWED_SUBMODULES for item in fromlist
|
|
188
|
+
):
|
|
189
|
+
reason = None
|
|
190
|
+
if reason is not None:
|
|
191
|
+
raise CodeExecutionError(
|
|
192
|
+
f"import of '{name}' is not allowed in the sandbox: {reason} "
|
|
193
|
+
"(full_access lifts this limit)"
|
|
194
|
+
)
|
|
195
|
+
|
|
196
|
+
|
|
197
|
+
def _sandbox_import(name: str, globals: Any = None, locals: Any = None, fromlist: Any = (), level: int = 0) -> Any:
|
|
198
|
+
"""The sandbox's ``__import__``: the same rule as validate_code, applied
|
|
199
|
+
to the name that is actually imported at run time (relative imports are
|
|
200
|
+
refused: there is no package for them to be relative to)."""
|
|
201
|
+
if level:
|
|
202
|
+
raise CodeExecutionError("relative imports are not allowed in the sandbox")
|
|
203
|
+
sandbox_import_check(name, tuple(fromlist or ()))
|
|
204
|
+
return _builtins.__import__(name, globals, locals, fromlist or (), 0)
|
|
205
|
+
|
|
206
|
+
|
|
207
|
+
def sandbox_builtins(base: Any) -> Dict[str, Any]:
|
|
208
|
+
"""A copy of ``base`` builtins with the sandbox's ``__import__`` bound."""
|
|
209
|
+
out: Dict[str, Any] = dict(base)
|
|
210
|
+
out["__import__"] = _sandbox_import
|
|
211
|
+
return out
|
|
212
|
+
|
|
213
|
+
|
|
214
|
+
def _json_offender(value: Any, path: str = "output") -> Optional[tuple]:
|
|
215
|
+
"""The first value inside ``value`` that JSON cannot carry, as (path, type name)."""
|
|
216
|
+
if value is None or isinstance(value, (bool, int, float, str)):
|
|
217
|
+
return None
|
|
218
|
+
if isinstance(value, (list, tuple)):
|
|
219
|
+
for i, item in enumerate(value):
|
|
220
|
+
found = _json_offender(item, f"{path}[{i}]")
|
|
221
|
+
if found:
|
|
222
|
+
return found
|
|
223
|
+
return None
|
|
224
|
+
if isinstance(value, dict):
|
|
225
|
+
for key, item in value.items():
|
|
226
|
+
if not isinstance(key, (str, int, float, bool)) and key is not None:
|
|
227
|
+
return (f"{path} (key {key!r})", type(key).__name__)
|
|
228
|
+
found = _json_offender(item, f"{path}[{key!r}]")
|
|
229
|
+
if found:
|
|
230
|
+
return found
|
|
231
|
+
return None
|
|
232
|
+
name = type(value).__name__
|
|
233
|
+
if name == "module":
|
|
234
|
+
name = f"module '{getattr(value, '__name__', '?')}'"
|
|
235
|
+
elif name in ("function", "builtin_function_or_method", "method"):
|
|
236
|
+
name = f"function '{getattr(value, '__name__', '?')}'"
|
|
237
|
+
return (path, name)
|
|
238
|
+
|
|
239
|
+
|
|
240
|
+
def ensure_json_result(value: Any, function_name: str = "transform") -> Any:
|
|
241
|
+
"""Return ``value`` when JSON can carry it; otherwise raise a CodeExecutionError
|
|
242
|
+
that names the offending value and where it sits, so the author sees
|
|
243
|
+
"return os_time, not the module" instead of a serializer crash later
|
|
244
|
+
(the gateway's simulate reply, or the run's persisted state)."""
|
|
245
|
+
found = _json_offender(value)
|
|
246
|
+
if found is None:
|
|
247
|
+
return value
|
|
248
|
+
path, name = found
|
|
249
|
+
raise CodeExecutionError(
|
|
250
|
+
f"{function_name} returned a value that cannot be sent as JSON: {name} at {path}. "
|
|
251
|
+
"Return data: str, int, float, bool, None, lists and dicts of those."
|
|
252
|
+
)
|
|
253
|
+
|
|
254
|
+
|
|
86
255
|
def normalize_code_permissions(permissions: Any = "sandbox") -> str:
|
|
87
256
|
"""Return the canonical Code node execution permission mode."""
|
|
88
257
|
raw = str(permissions or "sandbox").strip().lower().replace("-", "_")
|
|
@@ -129,8 +298,17 @@ def get_code_execution_policy() -> Dict[str, Any]:
|
|
|
129
298
|
"label": "Sandbox",
|
|
130
299
|
"available": True,
|
|
131
300
|
"default": True,
|
|
132
|
-
"safety": "restricted_python",
|
|
133
|
-
"description":
|
|
301
|
+
"safety": "restricted_python" if RESTRICTED_PYTHON_AVAILABLE else "basic",
|
|
302
|
+
"description": (
|
|
303
|
+
"Protected Python execution: Python's standard library is importable, except the "
|
|
304
|
+
"modules that reach processes, files, the network or code loading; exec/eval, "
|
|
305
|
+
"dunder access and third-party packages are refused."
|
|
306
|
+
),
|
|
307
|
+
"imports": {
|
|
308
|
+
"allowed": "python standard library",
|
|
309
|
+
"denied_modules": sorted(SANDBOX_DENIED_MODULES),
|
|
310
|
+
"allowed_submodules": sorted(SANDBOX_ALLOWED_SUBMODULES),
|
|
311
|
+
},
|
|
134
312
|
},
|
|
135
313
|
{
|
|
136
314
|
"id": "full_access",
|
|
@@ -163,13 +341,24 @@ def validate_code(code: str) -> None:
|
|
|
163
341
|
raise CodeExecutionError(f"Syntax error: {e}") from e
|
|
164
342
|
|
|
165
343
|
for node in ast.walk(tree):
|
|
166
|
-
#
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
344
|
+
# Imports: Python's own standard library, minus the modules that reach
|
|
345
|
+
# the machine (sandbox_import_check); the run-time __import__ guard
|
|
346
|
+
# applies the same rule to whatever is actually imported.
|
|
347
|
+
if isinstance(node, ast.Import):
|
|
348
|
+
for alias in node.names:
|
|
349
|
+
sandbox_import_check(alias.name)
|
|
350
|
+
elif isinstance(node, ast.ImportFrom):
|
|
351
|
+
if node.level:
|
|
352
|
+
raise CodeExecutionError("relative imports are not allowed in the sandbox")
|
|
353
|
+
if any(alias.name == "*" for alias in node.names):
|
|
354
|
+
raise CodeExecutionError(f"'from {node.module} import *' is not allowed in the sandbox")
|
|
355
|
+
sandbox_import_check(node.module or "", tuple(alias.name for alias in node.names))
|
|
356
|
+
|
|
357
|
+
# Disallow exec/eval/compile and the dynamic import call (write `import x`)
|
|
171
358
|
if isinstance(node, ast.Call) and isinstance(node.func, ast.Name):
|
|
172
|
-
if node.func.id
|
|
359
|
+
if node.func.id == "__import__":
|
|
360
|
+
raise CodeExecutionError("'__import__' is not allowed in the sandbox: write `import <module>` instead")
|
|
361
|
+
if node.func.id in ("exec", "eval", "compile"):
|
|
173
362
|
raise CodeExecutionError(f"'{node.func.id}' is not allowed")
|
|
174
363
|
|
|
175
364
|
# Disallow dunder attributes
|
|
@@ -214,9 +403,10 @@ def _create_full_access_handler(code: str, function_name: str) -> Callable[[Any]
|
|
|
214
403
|
raise CodeExecutionError(f"'{function_name}' is not a callable function")
|
|
215
404
|
|
|
216
405
|
try:
|
|
217
|
-
|
|
406
|
+
result = func(input_data)
|
|
218
407
|
except Exception as e:
|
|
219
408
|
raise CodeExecutionError(f"Runtime error: {e}") from e
|
|
409
|
+
return ensure_json_result(result, function_name)
|
|
220
410
|
|
|
221
411
|
return handler
|
|
222
412
|
|
|
@@ -259,10 +449,11 @@ def _apply(func: Any, *args: Any, **kwargs: Any) -> Any:
|
|
|
259
449
|
def _sandbox_parse_json(text: Any) -> Any:
|
|
260
450
|
"""``parse_json(text)`` — the sandbox's JSON reader.
|
|
261
451
|
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
the CodeExecutionError family so they surface loudly with
|
|
452
|
+
Pin expressions have no imports, and code nodes had none when this helper
|
|
453
|
+
was added (the design verdict's amendment 4: "parser" helpers were
|
|
454
|
+
unbuildable inline); it stays the one-call JSON reader of both sandboxes.
|
|
455
|
+
Errors stay in the CodeExecutionError family so they surface loudly with
|
|
456
|
+
attribution.
|
|
266
457
|
"""
|
|
267
458
|
import json
|
|
268
459
|
|
|
@@ -433,7 +624,7 @@ def _create_restricted_handler(code: str, function_name: str) -> Callable[[Any],
|
|
|
433
624
|
|
|
434
625
|
def handler(input_data: Any) -> Any:
|
|
435
626
|
restricted_globals = {
|
|
436
|
-
"__builtins__": safe_builtins,
|
|
627
|
+
"__builtins__": sandbox_builtins(safe_builtins),
|
|
437
628
|
"_getiter_": default_guarded_getiter,
|
|
438
629
|
"_getitem_": default_guarded_getitem,
|
|
439
630
|
"_iter_unpack_sequence_": guarded_iter_unpack_sequence,
|
|
@@ -473,9 +664,10 @@ def _create_restricted_handler(code: str, function_name: str) -> Callable[[Any],
|
|
|
473
664
|
raise CodeExecutionError(f"'{function_name}' is not a callable function")
|
|
474
665
|
|
|
475
666
|
try:
|
|
476
|
-
|
|
667
|
+
result = func(input_data)
|
|
477
668
|
except Exception as e:
|
|
478
669
|
raise CodeExecutionError(f"Runtime error: {e}") from e
|
|
670
|
+
return ensure_json_result(result, function_name)
|
|
479
671
|
|
|
480
672
|
return handler
|
|
481
673
|
|
|
@@ -494,11 +686,13 @@ def _create_basic_handler(code: str, function_name: str) -> Callable[[Any], Any]
|
|
|
494
686
|
limited_globals = {
|
|
495
687
|
"__builtins__": {
|
|
496
688
|
# Same convenience set as the restricted lane (one source),
|
|
497
|
-
# plus the literal names bare exec needs
|
|
689
|
+
# plus the literal names bare exec needs and the sandbox's
|
|
690
|
+
# __import__ (standard library only, see sandbox_import_check).
|
|
498
691
|
**sandbox_helper_globals(),
|
|
499
692
|
"True": True,
|
|
500
693
|
"False": False,
|
|
501
694
|
"None": None,
|
|
695
|
+
"__import__": _sandbox_import,
|
|
502
696
|
}
|
|
503
697
|
}
|
|
504
698
|
|
|
@@ -528,8 +722,9 @@ def _create_basic_handler(code: str, function_name: str) -> Callable[[Any], Any]
|
|
|
528
722
|
raise CodeExecutionError(f"'{function_name}' is not a callable function")
|
|
529
723
|
|
|
530
724
|
try:
|
|
531
|
-
|
|
725
|
+
result = func(input_data)
|
|
532
726
|
except Exception as e:
|
|
533
727
|
raise CodeExecutionError(f"Runtime error: {e}") from e
|
|
728
|
+
return ensure_json_result(result, function_name)
|
|
534
729
|
|
|
535
730
|
return handler
|
|
@@ -70,6 +70,7 @@ from .code_executor import (
|
|
|
70
70
|
CodeExecutionError,
|
|
71
71
|
_apply,
|
|
72
72
|
_inplacevar,
|
|
73
|
+
sandbox_builtins,
|
|
73
74
|
sandbox_helper_globals,
|
|
74
75
|
validate_code,
|
|
75
76
|
)
|
|
@@ -152,11 +153,12 @@ def _validate_library_purity(name: str, code: str) -> None:
|
|
|
152
153
|
construction, so the process-lifetime shared namespace can never leak
|
|
153
154
|
state across runs/tenants. Build-time, loud, attributed by function name.
|
|
154
155
|
|
|
155
|
-
FIRST runs the SAME ``validate_code`` the code-node lane uses (imports
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
156
|
+
FIRST runs the SAME ``validate_code`` the code-node lane uses (imports
|
|
157
|
+
outside Python's standard library or of the modules that reach the
|
|
158
|
+
machine, exec/eval/compile/__import__, dunder-attribute access) — one
|
|
159
|
+
source, no drift ("one sandbox, one rule"). The library lane previously
|
|
160
|
+
skipped it and let in-body imports fail only at CALL time; now it refuses
|
|
161
|
+
at build exactly like a code node. The purity rules below are the tier-2 ADDITION
|
|
160
162
|
on top of that shared baseline.
|
|
161
163
|
"""
|
|
162
164
|
try:
|
|
@@ -232,7 +234,7 @@ def compile_function_library(
|
|
|
232
234
|
# mirrors the code-node sandbox EXACTLY (one sandbox, one rule) or bodies
|
|
233
235
|
# die at call time with bare sandbox-internal NameErrors.
|
|
234
236
|
shared_ns: Dict[str, Any] = {
|
|
235
|
-
"__builtins__": safe_builtins,
|
|
237
|
+
"__builtins__": sandbox_builtins(safe_builtins), # + the sandbox __import__ (standard library)
|
|
236
238
|
"_getiter_": default_guarded_getiter,
|
|
237
239
|
"_getitem_": default_guarded_getitem,
|
|
238
240
|
"_iter_unpack_sequence_": guarded_iter_unpack_sequence,
|
|
@@ -0,0 +1,212 @@
|
|
|
1
|
+
"""Imports in the Code-node sandbox: Python's own standard library, except the
|
|
2
|
+
modules that reach the machine (processes, files, network, code loading).
|
|
3
|
+
|
|
4
|
+
One rule, applied twice: validate_code refuses at compile time (early, clear
|
|
5
|
+
message), and the sandbox's ``__import__`` refuses at run time (what actually
|
|
6
|
+
gates, in both the RestrictedPython lane and the basic fallback lane).
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
from __future__ import annotations
|
|
10
|
+
|
|
11
|
+
import pytest
|
|
12
|
+
|
|
13
|
+
from abstractruntime.visualflow_compiler.visual import code_executor as ce
|
|
14
|
+
from abstractruntime.visualflow_compiler.visual.code_executor import (
|
|
15
|
+
CodeExecutionError,
|
|
16
|
+
SANDBOX_DENIED_MODULES,
|
|
17
|
+
create_code_handler,
|
|
18
|
+
get_code_execution_policy,
|
|
19
|
+
sandbox_import_reason,
|
|
20
|
+
validate_code,
|
|
21
|
+
)
|
|
22
|
+
from abstractruntime.visualflow_compiler.visual.function_library import FunctionLibraryError, compile_function_library
|
|
23
|
+
|
|
24
|
+
STDLIB_CODE = (
|
|
25
|
+
"import time\n"
|
|
26
|
+
"import json\n"
|
|
27
|
+
"from datetime import datetime\n"
|
|
28
|
+
"import textwrap\n"
|
|
29
|
+
"from urllib.parse import quote\n"
|
|
30
|
+
"from urllib import parse as urlparse\n"
|
|
31
|
+
"import collections, re\n"
|
|
32
|
+
"\n"
|
|
33
|
+
"def transform(_input):\n"
|
|
34
|
+
" inside = __import_in_body(_input)\n"
|
|
35
|
+
" return {\n"
|
|
36
|
+
" 'ctime': len(time.ctime()) > 0,\n"
|
|
37
|
+
" 'json': json.dumps({'a': 1}),\n"
|
|
38
|
+
" 'year': datetime(2026, 1, 2).year,\n"
|
|
39
|
+
" 'wrap': textwrap.shorten('a b c d', 7),\n"
|
|
40
|
+
" 'from_pkg': urlparse.quote('c d'),\n"
|
|
41
|
+
" 'quote': quote('a b'),\n"
|
|
42
|
+
" 'counter': dict(collections.Counter('aab')),\n"
|
|
43
|
+
" 're': re.sub('a', 'b', 'aa'),\n"
|
|
44
|
+
" 'inside': inside,\n"
|
|
45
|
+
" }\n"
|
|
46
|
+
"\n"
|
|
47
|
+
"def __import_in_body(x):\n"
|
|
48
|
+
" import math\n"
|
|
49
|
+
" from statistics import mean\n"
|
|
50
|
+
" return math.floor(mean([1, 2, 4]))\n"
|
|
51
|
+
).replace("__import_in_body", "helper")
|
|
52
|
+
|
|
53
|
+
EXPECTED = {"ctime": True, "json": '{"a": 1}', "year": 2026, "wrap": "a b c d", "from_pkg": "c%20d", "quote": "a%20b", "counter": {"a": 2, "b": 1}, "re": "bb", "inside": 2}
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
@pytest.fixture(params=["restricted", "basic"])
|
|
57
|
+
def lane(request, monkeypatch):
|
|
58
|
+
"""Both sandbox lanes: RestrictedPython, and the fallback used without it."""
|
|
59
|
+
if request.param == "restricted":
|
|
60
|
+
pytest.importorskip("RestrictedPython")
|
|
61
|
+
else:
|
|
62
|
+
monkeypatch.setattr(ce, "RESTRICTED_PYTHON_AVAILABLE", False)
|
|
63
|
+
return request.param
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
def test_standard_library_imports_run_in_the_sandbox(lane) -> None:
|
|
67
|
+
assert create_code_handler(STDLIB_CODE)({"input": None}) == EXPECTED
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
def test_future_annotations_import_is_allowed(lane) -> None:
|
|
71
|
+
code = "from __future__ import annotations\n\ndef transform(_input: dict) -> int:\n return len(_input)\n"
|
|
72
|
+
assert create_code_handler(code)({"a": 1, "b": 2}) == 2
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
def test_the_operator_example_import_time_then_ctime(lane) -> None:
|
|
76
|
+
code = "import time; os_time = time.ctime()\n\ndef transform(_input):\n return str(_input) + ' - ' + os_time[:3]\n"
|
|
77
|
+
out = create_code_handler(code)({"input": None})
|
|
78
|
+
assert out.startswith("{'input': None} - ") and len(out) == len("{'input': None} - ") + 3
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
@pytest.mark.parametrize(
|
|
82
|
+
"code, fragment",
|
|
83
|
+
[
|
|
84
|
+
("import os\n", "import of 'os' is not allowed in the sandbox: it reaches processes and the operating system"),
|
|
85
|
+
("from os import path\n", "import of 'os' is not allowed in the sandbox"),
|
|
86
|
+
("import os.path\n", "import of 'os.path' is not allowed in the sandbox: it reaches processes"),
|
|
87
|
+
("import subprocess\n", "it reaches processes and the operating system"),
|
|
88
|
+
("import pathlib\n", "it reaches files on the machine"),
|
|
89
|
+
("import io\n", "it reaches files on the machine"),
|
|
90
|
+
("import socket\n", "it reaches the network"),
|
|
91
|
+
("import urllib.request\n", "it reaches the network; only urllib.parse is importable"),
|
|
92
|
+
("import urllib\n", "only urllib.parse is importable"),
|
|
93
|
+
("from urllib import request\n", "it reaches the network; only urllib.parse is importable"),
|
|
94
|
+
("from urllib import parse, request\n", "only urllib.parse is importable"),
|
|
95
|
+
("import operator\n", "it reaches around the sandbox's checks (attributes by name, evaluated annotations, frames)"),
|
|
96
|
+
("import typing\n", "it reaches around the sandbox's checks"),
|
|
97
|
+
("import functools\n", "it reaches around the sandbox's checks"),
|
|
98
|
+
("import traceback\n", "it reaches around the sandbox's checks"),
|
|
99
|
+
("import xml.etree.ElementTree as ET\n", "import of 'xml.etree.ElementTree' is not allowed in the sandbox: it reaches files on the machine"),
|
|
100
|
+
("import configparser\n", "it reaches files on the machine"),
|
|
101
|
+
("import argparse\n", "it reaches files on the machine"),
|
|
102
|
+
("import importlib\n", "it reaches loading or running code"),
|
|
103
|
+
("import sys\n", "it reaches loading or running code"),
|
|
104
|
+
("import pickle\n", "it reaches loading or running code"),
|
|
105
|
+
("import numpy\n", "import of 'numpy' is not allowed in the sandbox: only Python's own standard library is importable"),
|
|
106
|
+
("import _io\n", "import of '_io' is not allowed in the sandbox: a private module"),
|
|
107
|
+
("from json import *\n", "'from json import *' is not allowed in the sandbox"),
|
|
108
|
+
("from . import x\n", "relative imports are not allowed in the sandbox"),
|
|
109
|
+
],
|
|
110
|
+
)
|
|
111
|
+
def test_refused_imports_fail_at_compile_time_with_the_reason(code: str, fragment: str) -> None:
|
|
112
|
+
with pytest.raises(CodeExecutionError, match=fragment.replace("(", "\\(").replace(")", "\\)").replace("*", "\\*").replace(".", "\\.")):
|
|
113
|
+
validate_code(code + "\ndef transform(_input):\n return 1\n")
|
|
114
|
+
# ...and every refusal names full_access as the way out, except the syntactic ones.
|
|
115
|
+
if "not allowed in the sandbox:" in fragment:
|
|
116
|
+
with pytest.raises(CodeExecutionError, match="full_access lifts this limit"):
|
|
117
|
+
validate_code(code + "\ndef transform(_input):\n return 1\n")
|
|
118
|
+
|
|
119
|
+
|
|
120
|
+
def test_dynamic_import_call_is_refused_with_the_alternative() -> None:
|
|
121
|
+
with pytest.raises(CodeExecutionError, match="'__import__' is not allowed in the sandbox: write `import <module>` instead"):
|
|
122
|
+
validate_code("def transform(_input):\n return __import__('time')\n")
|
|
123
|
+
|
|
124
|
+
|
|
125
|
+
def test_the_runtime_guard_applies_the_same_rule(lane) -> None:
|
|
126
|
+
"""The AST check can be sidestepped only by code the sandbox itself runs;
|
|
127
|
+
the __import__ bound into the sandbox builtins refuses the same names."""
|
|
128
|
+
assert ce._sandbox_import("json").dumps({"a": 1}) == '{"a": 1}'
|
|
129
|
+
with pytest.raises(CodeExecutionError, match="import of 'subprocess' is not allowed in the sandbox"):
|
|
130
|
+
ce._sandbox_import("subprocess")
|
|
131
|
+
with pytest.raises(CodeExecutionError, match="relative imports are not allowed"):
|
|
132
|
+
ce._sandbox_import("x", None, None, (), 1)
|
|
133
|
+
# `from urllib import parse` reaches the guard as the package + a fromlist: allowed for that one.
|
|
134
|
+
assert ce._sandbox_import("urllib", None, None, ("parse",), 0).parse.quote("a b") == "a%20b"
|
|
135
|
+
with pytest.raises(CodeExecutionError, match="only urllib.parse is importable"):
|
|
136
|
+
ce._sandbox_import("urllib", None, None, ("request",), 0)
|
|
137
|
+
# The handler's builtins carry that guard, not the interpreter's __import__.
|
|
138
|
+
code = "def transform(_input):\n import json\n return json.dumps(_input)\n"
|
|
139
|
+
assert create_code_handler(code)({"k": 1}) == '{"k": 1}'
|
|
140
|
+
|
|
141
|
+
|
|
142
|
+
def test_full_access_imports_anything(monkeypatch) -> None:
|
|
143
|
+
monkeypatch.setenv("ABSTRACTRUNTIME_CODE_FULL_ACCESS", "1")
|
|
144
|
+
code = "import os\n\ndef transform(_input):\n return os.sep\n"
|
|
145
|
+
assert create_code_handler(code, permissions="full_access")({}) in ("/", "\\")
|
|
146
|
+
# The sandbox still refuses it under the same host policy.
|
|
147
|
+
with pytest.raises(CodeExecutionError, match="import of 'os' is not allowed in the sandbox"):
|
|
148
|
+
create_code_handler(code)
|
|
149
|
+
|
|
150
|
+
|
|
151
|
+
def test_import_rule_reasons() -> None:
|
|
152
|
+
assert sandbox_import_reason("json") is None
|
|
153
|
+
assert sandbox_import_reason("collections.abc") is None
|
|
154
|
+
assert sandbox_import_reason("email.utils") is None
|
|
155
|
+
assert sandbox_import_reason("urllib.parse") is None
|
|
156
|
+
assert sandbox_import_reason("") == "an empty module name"
|
|
157
|
+
assert sandbox_import_reason("os") == "it reaches processes and the operating system"
|
|
158
|
+
assert sandbox_import_reason("tempfile") == "it reaches files on the machine"
|
|
159
|
+
assert sandbox_import_reason("http.client") == "it reaches the network"
|
|
160
|
+
assert sandbox_import_reason("types") == "it reaches loading or running code"
|
|
161
|
+
assert sandbox_import_reason("operator") == "it reaches around the sandbox's checks (attributes by name, evaluated annotations, frames)"
|
|
162
|
+
assert sandbox_import_reason("sched") is None and sandbox_import_reason("__future__") is None
|
|
163
|
+
assert sandbox_import_reason("platform") == "it reaches processes and the operating system"
|
|
164
|
+
assert sandbox_import_reason("mimetypes") == "it reaches files on the machine"
|
|
165
|
+
assert "sched_h" not in SANDBOX_DENIED_MODULES and "platform_h" not in SANDBOX_DENIED_MODULES
|
|
166
|
+
assert sandbox_import_reason("requests") == "only Python's own standard library is importable"
|
|
167
|
+
# Every denied module names a reason, and the list is the standard library's (or a
|
|
168
|
+
# historical member: modules removed by newer Pythons stay refused for older ones).
|
|
169
|
+
assert all(SANDBOX_DENIED_MODULES.values())
|
|
170
|
+
|
|
171
|
+
|
|
172
|
+
def test_policy_tells_thin_clients_what_the_sandbox_imports() -> None:
|
|
173
|
+
sandbox = next(m for m in get_code_execution_policy()["modes"] if m["id"] == "sandbox")
|
|
174
|
+
assert sandbox["imports"]["allowed"] == "python standard library"
|
|
175
|
+
assert {"os", "subprocess", "operator", "typing", "functools", "traceback", "xml"} <= set(sandbox["imports"]["denied_modules"])
|
|
176
|
+
assert sandbox["safety"] in ("restricted_python", "basic")
|
|
177
|
+
assert sandbox["imports"]["allowed_submodules"] == ["urllib.parse"]
|
|
178
|
+
assert "standard library is importable" in sandbox["description"]
|
|
179
|
+
|
|
180
|
+
|
|
181
|
+
def test_function_library_shares_the_rule() -> None:
|
|
182
|
+
lib = compile_function_library([{"name": "slug", "code": "def slug(s):\n import re\n return re.sub('[^a-z]+', '-', s.lower())\n"}])
|
|
183
|
+
assert lib["slug"]("Hello World") == "hello-world"
|
|
184
|
+
with pytest.raises(FunctionLibraryError, match="import of 'os' is not allowed in the sandbox"):
|
|
185
|
+
compile_function_library([{"name": "evil", "code": "def evil():\n import os\n return os.getcwd()\n"}])
|
|
186
|
+
|
|
187
|
+
|
|
188
|
+
# --- the returned value must be JSON data (operator 2026-10-16 14:37: HTTP 500
|
|
189
|
+
# "Unable to serialize unknown type: <class 'module'>" after `return _input, "...", time`)
|
|
190
|
+
|
|
191
|
+
def test_returning_a_module_is_a_clear_error_not_a_serializer_crash(lane) -> None:
|
|
192
|
+
code = "import time; os_time = time.ctime()\n\ndef transform(_input):\n return _input, ' - deterministic code: ', time\n"
|
|
193
|
+
with pytest.raises(CodeExecutionError, match=r"transform returned a value that cannot be sent as JSON: module 'time' at output\[2\]\. Return data"):
|
|
194
|
+
create_code_handler(code)({"input": None})
|
|
195
|
+
fixed = "import time; os_time = time.ctime()\n\ndef transform(_input):\n return _input, ' - deterministic code: ', os_time\n"
|
|
196
|
+
out = create_code_handler(fixed)({"input": None})
|
|
197
|
+
assert out[0] == {"input": None} and out[1] == " - deterministic code: " and isinstance(out[2], str)
|
|
198
|
+
|
|
199
|
+
|
|
200
|
+
def test_json_offender_paths(lane) -> None:
|
|
201
|
+
code = "def transform(_input):\n return {'a': [1, {'b': set([1])}]}\n"
|
|
202
|
+
with pytest.raises(CodeExecutionError, match=r"set at output\['a'\]\[1\]\['b'\]"):
|
|
203
|
+
create_code_handler(code)({})
|
|
204
|
+
code = "def transform(_input):\n return {'ok': [1, 2.5, 'x', None, True], 'nested': {'k': (1, 2)}}\n"
|
|
205
|
+
assert create_code_handler(code)({}) == {"ok": [1, 2.5, "x", None, True], "nested": {"k": (1, 2)}}
|
|
206
|
+
|
|
207
|
+
|
|
208
|
+
def test_full_access_results_must_be_json_too(monkeypatch) -> None:
|
|
209
|
+
monkeypatch.setenv("ABSTRACTRUNTIME_CODE_FULL_ACCESS", "1")
|
|
210
|
+
code = "import os\n\ndef transform(_input):\n return os\n"
|
|
211
|
+
with pytest.raises(CodeExecutionError, match="cannot be sent as JSON: module 'os' at output"):
|
|
212
|
+
create_code_handler(code, permissions="full_access")({})
|
|
@@ -337,7 +337,7 @@ def test_top_level_import_refused() -> None:
|
|
|
337
337
|
# A top-level import is refused — validate_code (shared with code nodes)
|
|
338
338
|
# catches imports first; the top-level-defs-only purity rule is a further
|
|
339
339
|
# backstop (see test_purity_refuses_top_level_mutable_container).
|
|
340
|
-
with pytest.raises(FunctionLibraryError, match="
|
|
340
|
+
with pytest.raises(FunctionLibraryError, match="import of 'os' is not allowed in the sandbox"):
|
|
341
341
|
compile_function_library(
|
|
342
342
|
[{"name": "evil", "code": "import os\ndef evil():\n return os.getcwd()\n"}]
|
|
343
343
|
)
|
|
@@ -347,7 +347,7 @@ def test_import_inside_body_refused() -> None:
|
|
|
347
347
|
# An import INSIDE a function body is structurally legal (a def) but the
|
|
348
348
|
# shared validate_code (same lane as code nodes) refuses imports at BUILD —
|
|
349
349
|
# one sandbox, one rule (the library lane must not be weaker).
|
|
350
|
-
with pytest.raises(FunctionLibraryError, match="
|
|
350
|
+
with pytest.raises(FunctionLibraryError, match="import of 'os' is not allowed in the sandbox"):
|
|
351
351
|
compile_function_library(
|
|
352
352
|
[{"name": "evil", "code": "def evil():\n import os\n return os.getcwd()\n"}]
|
|
353
353
|
)
|