AbstractRuntime 0.7.0__tar.gz → 0.7.1__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.7.0 → abstractruntime-0.7.1}/CHANGELOG.md +17 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/PKG-INFO +3 -3
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/README.md +2 -2
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/docs/api.md +2 -2
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/docs/architecture.md +1 -1
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/llms-full.txt +5 -5
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/llms.txt +1 -1
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/pyproject.toml +1 -1
- abstractruntime-0.7.1/release-notes.md +14 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/src/abstractruntime/memory/token_budget.py +39 -3
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/src/abstractruntime/session_history.py +49 -1
- abstractruntime-0.7.1/tests/test_history_window_multimodal.py +142 -0
- abstractruntime-0.7.0/release-notes.md +0 -94
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/.github/workflows/ci.yml +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/.github/workflows/release.yml +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/.gitignore +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/ACKNOWLEDGMENTS.md +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/CODE_OF_CONDUCT.md +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/CONTRIBUTING.md +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/LICENSE +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/ROADMAP.md +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/SECURITY.md +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/docs/README.md +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/docs/adr/0001_layered_coupling_with_abstractcore.md +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/docs/adr/0002_execution_modes_local_remote_hybrid.md +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/docs/adr/0003_provenance_tamper_evident_hash_chain.md +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/docs/adr/0004_runtime_owns_run_scoped_media_execution_truth.md +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/docs/adr/0005_runtime_owns_abstractcore_host_discovery_queries.md +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/docs/adr/0006_runtime_owns_durable_abstractcore_bloc_prompt_cache.md +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/docs/adr/0007_runtime_relays_core_owned_model_residency_truth.md +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/docs/adr/README.md +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/docs/artifacts.md +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/docs/automations.md +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/docs/backlog/README.md +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/docs/backlog/completed/001_runtime_kernel.md +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/docs/backlog/completed/002_persistence_and_ledger.md +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/docs/backlog/completed/0030_runtime_host_facades_for_comms_telegram_and_tool_specs.md +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/docs/backlog/completed/0032_runtime_durable_outbound_comms_truth.md +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/docs/backlog/completed/0033_runtime_host_local_prompt_cache_export_import_surface.md +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/docs/backlog/completed/0035_model_residency_provider_truth_for_local_http_clients.md +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/docs/backlog/completed/0037_visualflow_generate_music_node_compiler_parity.md +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/docs/backlog/completed/0039_runtime_music_structure_prompt_bool_contract.md +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/docs/backlog/completed/003_wait_primitives.md +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/docs/backlog/completed/0040_task_agnostic_local_residency_listing.md +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/docs/backlog/completed/0041_runtime_hardware_extras_avoid_nonpermissive_document_stacks.md +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/docs/backlog/completed/0042_core_vision_upscale_and_parameter_surface.md +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/docs/backlog/completed/0043_runtime_vision_adapter_and_batch_surface.md +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/docs/backlog/completed/004_scheduler_driver.md +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/docs/backlog/completed/005_abstractcore_integration.md +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/docs/backlog/completed/006_snapshots_bookmarks.md +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/docs/backlog/completed/007_provenance_hash_chain.md +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/docs/backlog/completed/009_artifact_store.md +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/docs/backlog/completed/010_examples_and_composition.md +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/docs/backlog/completed/011_subworkflow_support.md +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/docs/backlog/completed/012_run_store_query_and_scheduler_support.md +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/docs/backlog/completed/013_effect_retries_and_idempotency.md +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/docs/backlog/completed/016_runtime_aware_parameters.md +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/docs/backlog/completed/019_runtime_host_facade_for_core_operator_surfaces.md +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/docs/backlog/completed/020_runtime_gateway_install_boundary.md +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/docs/backlog/completed/021_runtime_gateway_env_namespace_cleanup.md +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/docs/backlog/completed/022_model_residency_control_plane.md +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/docs/backlog/completed/023_truthful_local_media_residency_boundaries.md +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/docs/backlog/completed/024_runtime_owned_run_scoped_media_execution.md +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/docs/backlog/completed/026_runtime_host_discovery_facade_for_core_catalogs.md +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/docs/backlog/completed/027_runtime_durable_bloc_prompt_cache_facade.md +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/docs/backlog/completed/028_runtime_bloc_kv_lifecycle_and_pruning.md +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/docs/backlog/completed/029_runtime_music_generation_and_discovery_via_abstractcore.md +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/docs/backlog/completed/0846_mlx_instance_scheduling_and_execution_controls.md +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/docs/backlog/completed/0847_automations_v1_controller_contracts_occurrences_triggers.md +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/docs/backlog/deprecated/001_integrations_abstractcore.md +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/docs/backlog/deprecated/001_runtime_kernel.md +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/docs/backlog/deprecated/002_persistence_and_ledger.md +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/docs/backlog/deprecated/002_snapshots_bookmarks.md +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/docs/backlog/deprecated/0034_agent_runtime_convenience_constructor.md +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/docs/backlog/deprecated/003_provenance_ledger_chain.md +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/docs/backlog/deprecated/003_wait_resume_and_scheduler.md +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/docs/backlog/deprecated/004_effect_handlers_and_integrations.md +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/docs/backlog/deprecated/004_tests.md +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/docs/backlog/deprecated/005_docs_updates.md +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/docs/backlog/deprecated/005_examples_and_composition.md +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/docs/backlog/deprecated/006_ai_fingerprint_and_provenance.md +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/docs/backlog/deprecated/DEPRECATED_README.md +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/docs/backlog/deprecated/README.md +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/docs/backlog/deprecated/abstractruntime_docs_final_02a7373b.plan.md +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/docs/backlog/planned/0070_standalone_wui_browser_session_security_contract.md +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/docs/backlog/planned/008_signatures_and_keys.md +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/docs/backlog/planned/014_remote_tool_worker_executor.md +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/docs/backlog/planned/017_limit_warnings_and_observability.md +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/docs/backlog/planned/018_workspace_access_policy_for_media_and_tools.md +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/docs/backlog/planned/0233_real_run_cancellation.md +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/docs/backlog/planned/025_runtime_retention_and_purge_contract.md +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/docs/backlog/planned/026_context_checkpoint_self_compression.md +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/docs/backlog/planned/027_quote_provenance_discipline.md +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/docs/backlog/planned/028_selective_artifact_rehydration.md +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/docs/backlog/planned/0845_session_prompt_cache_resume_and_purge_contract.md +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/docs/backlog/planned/0848_automations_v2_external_event_inbox_and_run_triggers.md +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/docs/backlog/planned/runtime_portability/0065_portable_process_and_lock_layer.md +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/docs/backlog/planned/runtime_portability/0066_portable_io_and_media_reader.md +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/docs/backlog/planned/runtime_portability/README.md +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/docs/backlog/planned/runtime_systemic_reliability/0044_meta_analysis_record.md +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/docs/backlog/planned/runtime_systemic_reliability/0045_crash_replay_harness_and_ordering_invariant.md +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/docs/backlog/planned/runtime_systemic_reliability/0046_per_run_driver_exclusion.md +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/docs/backlog/planned/runtime_systemic_reliability/0047_indexed_idempotency_lookup.md +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/docs/backlog/planned/runtime_systemic_reliability/0048_durable_io_unification.md +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/docs/backlog/planned/runtime_systemic_reliability/0049_llm_client_mechanical_split.md +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/docs/backlog/planned/runtime_systemic_reliability/0050_control_sidecar_all_writers.md +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/docs/backlog/planned/runtime_systemic_reliability/0051_runtime_owned_durable_event_mailbox.md +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/docs/backlog/planned/runtime_systemic_reliability/0052_sync_store_event_loop_tripwire.md +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/docs/backlog/planned/runtime_systemic_reliability/0053_bounded_run_vars_growth.md +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/docs/backlog/planned/runtime_systemic_reliability/0054_runtime_health_counters.md +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/docs/backlog/planned/runtime_systemic_reliability/0055_jsonl_store_honesty.md +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/docs/backlog/planned/runtime_systemic_reliability/0064_prompt_cache_fingerprint_stability.md +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/docs/backlog/planned/runtime_systemic_reliability/0067_durable_write_discipline.md +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/docs/backlog/planned/runtime_systemic_reliability/0068_hot_path_store_reads.md +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/docs/backlog/planned/runtime_systemic_reliability/README.md +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/docs/backlog/proposed/0031_runtime_tool_spec_adapters_for_gateway_and_mcp.md +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/docs/backlog/proposed/0036_local_media_residency_bridge_to_core_residency.md +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/docs/backlog/proposed/0038_core_server_pool_residency_affinity.md +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/docs/backlog/proposed/0069_document_renderer_professional_figures.md +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/docs/backlog/proposed/runtime_systemic_reliability/0056_schema_version_and_quarantine_loading.md +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/docs/backlog/proposed/runtime_systemic_reliability/0057_trust_boundary_stamp_registry.md +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/docs/backlog/proposed/runtime_systemic_reliability/0058_terminal_run_archival_helper.md +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/docs/backlog/proposed/runtime_systemic_reliability/0059_memory_span_handler_extraction.md +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/docs/backlog/proposed/runtime_systemic_reliability/0060_visualflow_compiler_decomposition.md +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/docs/backlog/proposed/runtime_systemic_reliability/0061_root_api_deprecation_machinery.md +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/docs/backlog/proposed/runtime_systemic_reliability/0062_dependency_honesty_extras.md +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/docs/backlog/proposed/runtime_systemic_reliability/0063_b3_envelope_lane_unification.md +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/docs/backlog/proposed/runtime_systemic_reliability/README.md +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/docs/entity-runtime.md +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/docs/evidence.md +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/docs/faq.md +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/docs/getting-started.md +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/docs/integrations/abstractcore.md +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/docs/limits.md +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/docs/manual_testing.md +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/docs/mcp-worker.md +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/docs/proposal.md +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/docs/provenance.md +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/docs/snapshots.md +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/docs/tool-approval.md +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/docs/tools-comms.md +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/docs/troubleshooting.md +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/docs/workflow-bundles.md +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/emails.config.example.yaml +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/examples/01_hello_world.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/examples/02_ask_user.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/examples/03_wait_until.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/examples/04_multi_step.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/examples/05_persistence.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/examples/06_llm_integration.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/examples/07_react_agent.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/examples/README.md +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/mkdocs.yml +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/pytest.ini +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/scripts/backfill_diary_edges.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/scripts/generate_llms_full.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/src/abstractruntime/__init__.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/src/abstractruntime/automation_queries.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/src/abstractruntime/automations/__init__.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/src/abstractruntime/automations/adapters.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/src/abstractruntime/automations/attention.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/src/abstractruntime/automations/bundle.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/src/abstractruntime/automations/bundles/automation-controller/flows/controller.json +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/src/abstractruntime/automations/bundles/automation-controller/manifest.json +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/src/abstractruntime/automations/commands.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/src/abstractruntime/automations/controller.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/src/abstractruntime/automations/ledger.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/src/abstractruntime/automations/models.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/src/abstractruntime/automations/service.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/src/abstractruntime/core/__init__.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/src/abstractruntime/core/config.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/src/abstractruntime/core/effect_cancellation.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/src/abstractruntime/core/event_keys.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/src/abstractruntime/core/health.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/src/abstractruntime/core/live_deltas.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/src/abstractruntime/core/models.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/src/abstractruntime/core/policy.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/src/abstractruntime/core/progress_channel.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/src/abstractruntime/core/run_attribution.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/src/abstractruntime/core/run_identity.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/src/abstractruntime/core/run_lifecycle.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/src/abstractruntime/core/runtime.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/src/abstractruntime/core/spec.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/src/abstractruntime/core/tool_scope.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/src/abstractruntime/core/vars.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/src/abstractruntime/documents/__init__.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/src/abstractruntime/documents/charts.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/src/abstractruntime/documents/docx.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/src/abstractruntime/documents/pdf.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/src/abstractruntime/evidence/__init__.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/src/abstractruntime/evidence/recorder.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/src/abstractruntime/history_bundle.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/src/abstractruntime/identity/__init__.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/src/abstractruntime/identity/act_only.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/src/abstractruntime/identity/chat.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/src/abstractruntime/identity/communities.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/src/abstractruntime/identity/diary.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/src/abstractruntime/identity/digest.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/src/abstractruntime/identity/entity_runtime.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/src/abstractruntime/identity/fingerprint.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/src/abstractruntime/identity/lease.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/src/abstractruntime/identity/life.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/src/abstractruntime/identity/memory_reader.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/src/abstractruntime/identity/night_voice.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/src/abstractruntime/identity/phase_graph.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/src/abstractruntime/identity/phase_spec.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/src/abstractruntime/identity/prelude.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/src/abstractruntime/identity/prompt_overlay.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/src/abstractruntime/identity/reflection.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/src/abstractruntime/identity/spec/entity_phases.vendored.json +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/src/abstractruntime/identity/substrate.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/src/abstractruntime/identity/tool_effects.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/src/abstractruntime/identity/tool_policy.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/src/abstractruntime/identity/tools.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/src/abstractruntime/identity/visit_workflow.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/src/abstractruntime/integrations/__init__.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/src/abstractruntime/integrations/abstractcore/__init__.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/src/abstractruntime/integrations/abstractcore/agora_tools.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/src/abstractruntime/integrations/abstractcore/comms_facade.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/src/abstractruntime/integrations/abstractcore/config_facade.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/src/abstractruntime/integrations/abstractcore/constants.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/src/abstractruntime/integrations/abstractcore/data_registry_facade.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/src/abstractruntime/integrations/abstractcore/default_tools.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/src/abstractruntime/integrations/abstractcore/discovery_facade.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/src/abstractruntime/integrations/abstractcore/discovery_queries.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/src/abstractruntime/integrations/abstractcore/effect_handlers.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/src/abstractruntime/integrations/abstractcore/embeddings_client.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/src/abstractruntime/integrations/abstractcore/factory.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/src/abstractruntime/integrations/abstractcore/host_facade.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/src/abstractruntime/integrations/abstractcore/llm_client.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/src/abstractruntime/integrations/abstractcore/local_helper_tools.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/src/abstractruntime/integrations/abstractcore/logging.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/src/abstractruntime/integrations/abstractcore/mcp_worker.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/src/abstractruntime/integrations/abstractcore/media_subprocess.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/src/abstractruntime/integrations/abstractcore/observability.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/src/abstractruntime/integrations/abstractcore/output_specs.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/src/abstractruntime/integrations/abstractcore/run_facade.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/src/abstractruntime/integrations/abstractcore/session_attachments.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/src/abstractruntime/integrations/abstractcore/summarizer.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/src/abstractruntime/integrations/abstractcore/telegram_facade.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/src/abstractruntime/integrations/abstractcore/tool_effects.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/src/abstractruntime/integrations/abstractcore/tool_executor.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/src/abstractruntime/integrations/abstractcore/tool_inventory_facade.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/src/abstractruntime/integrations/abstractcore/workspace_scoped_tools.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/src/abstractruntime/integrations/abstractmemory/__init__.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/src/abstractruntime/integrations/abstractmemory/brain_handlers.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/src/abstractruntime/integrations/abstractmemory/effect_handlers.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/src/abstractruntime/integrations/abstractmemory/identity_support.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/src/abstractruntime/integrations/abstractmemory/seam_handlers.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/src/abstractruntime/memory/__init__.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/src/abstractruntime/memory/active_context.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/src/abstractruntime/memory/active_memory.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/src/abstractruntime/memory/compaction.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/src/abstractruntime/memory/kg_packets.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/src/abstractruntime/memory/memact_composer.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/src/abstractruntime/memory/recall_levels.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/src/abstractruntime/rendering/__init__.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/src/abstractruntime/rendering/agent_trace_report.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/src/abstractruntime/rendering/json_stringify.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/src/abstractruntime/scheduler/__init__.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/src/abstractruntime/scheduler/convenience.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/src/abstractruntime/scheduler/multi_store.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/src/abstractruntime/scheduler/registry.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/src/abstractruntime/scheduler/scheduler.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/src/abstractruntime/session_turns.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/src/abstractruntime/storage/__init__.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/src/abstractruntime/storage/artifacts.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/src/abstractruntime/storage/base.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/src/abstractruntime/storage/commands.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/src/abstractruntime/storage/in_memory.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/src/abstractruntime/storage/json_files.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/src/abstractruntime/storage/lease.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/src/abstractruntime/storage/ledger_chain.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/src/abstractruntime/storage/ledger_slim.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/src/abstractruntime/storage/observable.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/src/abstractruntime/storage/offloading.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/src/abstractruntime/storage/serialize.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/src/abstractruntime/storage/snapshots.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/src/abstractruntime/storage/sqlite.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/src/abstractruntime/storage/steer_sidecar.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/src/abstractruntime/triggers/__init__.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/src/abstractruntime/triggers/manual.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/src/abstractruntime/triggers/protocol.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/src/abstractruntime/triggers/registry.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/src/abstractruntime/triggers/schedule.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/src/abstractruntime/turn_grounding.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/src/abstractruntime/utils/__init__.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/src/abstractruntime/utils/atomic_files.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/src/abstractruntime/utils/file_filters.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/src/abstractruntime/utils/workspace_paths.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/src/abstractruntime/visualflow_compiler/__init__.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/src/abstractruntime/visualflow_compiler/adapters/__init__.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/src/abstractruntime/visualflow_compiler/adapters/agent_adapter.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/src/abstractruntime/visualflow_compiler/adapters/context_adapter.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/src/abstractruntime/visualflow_compiler/adapters/control_adapter.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/src/abstractruntime/visualflow_compiler/adapters/effect_adapter.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/src/abstractruntime/visualflow_compiler/adapters/event_adapter.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/src/abstractruntime/visualflow_compiler/adapters/function_adapter.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/src/abstractruntime/visualflow_compiler/adapters/memact_adapter.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/src/abstractruntime/visualflow_compiler/adapters/subflow_adapter.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/src/abstractruntime/visualflow_compiler/adapters/variable_adapter.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/src/abstractruntime/visualflow_compiler/compiler.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/src/abstractruntime/visualflow_compiler/flow.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/src/abstractruntime/visualflow_compiler/visual/__init__.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/src/abstractruntime/visualflow_compiler/visual/agent_ids.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/src/abstractruntime/visualflow_compiler/visual/builtins.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/src/abstractruntime/visualflow_compiler/visual/code_executor.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/src/abstractruntime/visualflow_compiler/visual/execution_metrics.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/src/abstractruntime/visualflow_compiler/visual/executor.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/src/abstractruntime/visualflow_compiler/visual/function_library.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/src/abstractruntime/visualflow_compiler/visual/models.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/src/abstractruntime/visualflow_compiler/visual/multi_entry_lowering.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/src/abstractruntime/visualflow_compiler/visual/pin_expressions.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/src/abstractruntime/workflow_bundle/__init__.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/src/abstractruntime/workflow_bundle/models.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/src/abstractruntime/workflow_bundle/packer.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/src/abstractruntime/workflow_bundle/reader.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/src/abstractruntime/workflow_bundle/registry.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/README.md +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/automation_harness.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/conftest.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_abstractcore_comms_facade.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_abstractcore_discovery_facade.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_abstractcore_host_facade.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_abstractcore_run_facade.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_abstractcore_telegram_facade.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_active_context_policy.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_active_memory.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_agora_agent_alias_identity.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_agora_tools_http.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_analyze_media_addressing_and_walling.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_answer_user_effect.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_artifacts.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_automation_commands.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_automation_controller.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_automation_controller_recovery.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_automation_definition.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_automation_discussion_isolation.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_automation_growing_context.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_automation_index.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_automation_next_fire.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_automation_occurrence_recovery.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_automation_replay_read_only.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_automation_retry.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_automation_session_turns.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_automation_status.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_automation_tool_approval.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_browser_probe_target_walling.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_budget_law_no_unrequested_caps.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_capability_default_reasoning.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_chat_summarizer_integration.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_code_node_restricted_python.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_command_store.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_compaction_helpers.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_compaction_summarizer_route.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_config_facade_models_engines.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_control_adapter_while.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_controller_bundle_packaged.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_crash_ordering_inversions.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_create_if_absent.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_data_registry_facade.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_default_tools_camera_gating.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_default_tools_comms_gating.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_default_tools_include_skim_files.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_default_tools_include_skim_folders.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_default_tools_include_skim_web.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_default_tools_search_files_executor.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_diary_capture.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_diary_write_rescue.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_directory_lease.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_disabled_toolsets_seam.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_discovery_survives_unbuildable_default.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_discovery_tts_unavailable_reason.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_discovery_voice_openai_api_key.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_discussion_session_anchor.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_document_markdown_tables.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_document_renderers_hr_quote.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_durable_toolsets.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_durable_write_discipline.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_e2e_tool_calls_idempotency_lmstudio.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_effect_cancellation.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_effect_issuance_idempotency.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_effect_payload_stays_json_serializable.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_election_consequence_teaching.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_emergence_experiment.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_emit_event_uses_wait_index.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_emit_event_without_workflow_registry.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_endpoint_profile_route_context.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_entity_awake_memory_fixes.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_entity_brain_effects.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_entity_chat_driver.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_entity_chat_tools_reflection.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_entity_diary.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_entity_execute_tool.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_entity_fetch_url_tool.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_entity_history_window.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_entity_life_loop.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_entity_memory_richness.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_entity_phase_graph_conformance.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_entity_react_visit_window.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_entity_recent_memories.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_entity_runtime.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_entity_search_memory.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_entity_sleep_bound_and_yield_attribution.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_entity_substrate_resolution.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_entity_visit_honesty.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_entity_workspace_cap.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_entity_workspace_tools.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_event_wait_index.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_every_path_bearing_tool_is_walled.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_evidence_recorder.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_evidence_recorder_post_policy_envelope.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_execute_command_output_offload.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_execution_capability_discovery.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_explicit_eject_other_clients.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_factory_default_retry_policy.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_factory_timeouts_default_to_abstractcore_config.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_format_repair_nudge.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_fresh_install_no_provider.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_gateway_facades_c4899.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_git_read_only_refiner.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_hf_process_residency_merge.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_hot_path_store_reads.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_indexed_idempotency_lookup.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_integration_abstractcore.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_integrations_abstractcore.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_json_file_run_store_children_index.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_json_run_cache_bound.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_json_store_scan_memo.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_jsonl_ledger_recovery.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_kg_learn_and_recall_contract.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_ledger_chain.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_ledger_record_slimming.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_ledger_subscription.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_live_token_deltas.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_llm_call_media_artifact_refs.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_llm_call_media_artifact_refs_persist_across_restart.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_llm_call_media_uses_source_path_label.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_llm_call_payload_shape_refusal.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_llm_call_requires_prompt.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_llm_call_response_schema_normalization.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_llm_call_structured_output_fallback.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_llm_call_text_phase_progress.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_llm_call_truncation_retry_contract.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_llm_call_use_context_appends_turn.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_llm_call_verbatim_payload_capture.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_llm_client_grounding_tail.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_llm_client_media_artifacts.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_llm_client_system_context.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_llm_client_tool_call_parsing.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_llm_retry_classification.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_llm_streaming_on_token.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_local_helper_tool_exposure.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_local_residency_host_sweep.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_local_runtime_timeout_kwarg_policy.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_max_iterations_ceiling.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_mcp_remote_tool_executor.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_mcp_worker_logging.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_mcp_worker_security.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_mcp_worker_stdio.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_media_artifact_resolution.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_media_capability_default_routing.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_media_subprocess.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_memact_composer_from_kg_result.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_memory_appraise_handler.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_memory_communities.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_memory_kg_assert_attributes_defaults.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_memory_kg_packets.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_memory_kg_predicate_aliasing.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_memory_kg_query_packetization_restart.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_memory_kg_query_recall_level_policy.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_memory_kg_semantic_query_ranking.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_memory_note_effect.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_memory_query_effect.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_memory_query_rich_filters.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_memory_scope_and_rehydrate_effect.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_memory_seam_handlers.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_memory_seam_sqlite_durability.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_memory_tag_effect.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_mlx_generation_serialization.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_mlx_process_residency_merge.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_model_eject_cancel.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_model_residency_clean_switch.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_model_residency_control_plane.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_model_residency_lock_and_context_estimate.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_multi_store_scheduler.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_multimodal_abstractcore_integration.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_native_mlx_application_wiring.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_native_mlx_execution_controls_live.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_native_tool_channel.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_night_voice.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_no_default_provider_refusal_ux.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_offload_answer_chain_c4978.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_offloaded_node_traces_report_unknown_not_zero.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_offloading.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_packaging_extras.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_parallel_readonly_tool_execution.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_pause_resume.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_pdf_unicode_rendering.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_personal_cycle.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_phantom_attachment_index.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_phase_graph_artifact_control.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_phase_graph_obedience.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_phase_vocabulary_migration.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_pooled_client_strips_construction_cache_key.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_prompt_cache_export_import.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_prompt_cache_fingerprint_stability.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_prompt_cache_modules.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_prompt_cache_posture_inheritance.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_prompt_cache_thinking_and_prompt_only.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_prompt_overlay.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_provider_endpoint_profile_resolution.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_provider_pin_routing_isolation.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_queryable_run_store.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_read_file_fallback_to_session_attachments.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_read_idle_threading.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_readoption_experiment.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_real_integration.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_realize_election.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_recall_levels_policy.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_remote_client_cancel.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_remote_llm_client.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_remote_speculation_defaults.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_rendering_agent_trace_report.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_rendering_json_stringify.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_report_branding.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_resume_concurrent_same_wait.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_retry_idempotency.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_run_history_bundle.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_run_index_workspace_root.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_run_mutation_lock.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_run_scoped_tool_policy.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_run_tool_scope_ceiling.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_runtime_browser_session_boundary.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_runtime_config_max_output_tokens_fallback.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_runtime_default_provider_model_refresh.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_runtime_effect_invocation_trace.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_runtime_health_and_bounded_vars.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_runtime_install_boundary.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_runtime_llm_call_grounding_in_ledger.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_runtime_node_traces.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_runtime_start_seeds_tool_support.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_runtime_tick_step_gate.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_scheduler.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_send_email_refiner.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_session_attachments_registry_and_open_tool.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_session_history.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_session_prompt_cache_attribution.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_session_prompt_cache_visibility.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_session_route_stamp.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_session_start_cost.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_shell_tool_exposure.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_snapshots.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_speculation_inheritance.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_speculation_reaches_provider_construction.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_sqlite_ledger_store.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_start_subworkflow_async_wait.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_start_subworkflow_inherit_context_merges_messages.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_start_subworkflow_workspace_inheritance.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_steer_sidecar.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_storage_deletion.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_structured_output_schema_enum.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_subworkflow.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_terminal_effect_completion.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_terminal_resume_appends_ledger_completion.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_thinking_inheritance.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_tick_completion_includes_output_in_ledger.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_tool_approval_executor.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_tool_approval_resume_executes.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_tool_approval_wait_key_identity.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_tool_calls_idempotency_keys.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_tool_catalog.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_tool_descriptor_registry.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_tool_executor_argument_sanitization.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_tool_executor_error_output_detection.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_tool_executor_filename_alias.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_tool_executor_kwarg_canonicalization.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_tool_executor_read_file_aliases.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_tool_executor_timeout.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_tool_inventory_facade.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_tool_invoke_effect.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_tool_policy_and_mounts.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_tool_wait_allowlist_safety.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_topic_election_world_model.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_trace_context_propagation.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_trigger_registry.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_trigger_schedule_math.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_turn_grounding_byte_stability.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_turn_grounding_carriers_a3.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_vars_query_effect.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_visit_ab_fixture.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_visit_midturn_elections.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_visit_midturn_resume.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_visit_workflow.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_visual_agent_output_context_includes_messages.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_visual_agent_skills_block_passthrough.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_visual_agent_tool_observations_persist_across_restart.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_visual_agent_use_context_inherits_attachments.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_visual_agent_use_context_persists_tool_observations.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_visual_agent_use_context_persists_turn.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_visual_entity_memory_nodes.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_visual_flow_end_effect_only_persistence.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_visual_llm_call_partial_override.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_visual_llm_call_schema_ref_resolution.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_visual_memact_compose_node.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_visual_memory_kg_query_outputs_propagate.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_visual_memory_kg_resolve_outputs_propagate.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_visual_multi_entry_loop_overrides.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_visual_unknown_node_type_refuses.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_visual_wait_event_deadline_passthrough.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_visualflow_add_message_builtin.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_visualflow_add_message_node_appends_to_active_context.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_visualflow_agora_react_agent.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_visualflow_call_tool_node.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_visualflow_capability_routes_and_thinking.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_visualflow_compiler_basic.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_visualflow_context_and_builder_nodes.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_visualflow_continue_on_error.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_visualflow_edit_json_schema_node.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_visualflow_event_inbox_react_agent.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_visualflow_file_nodes_workspace.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_visualflow_function_library.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_visualflow_get_element_node.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_visualflow_get_random_element_node.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_visualflow_get_var_node.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_visualflow_has_tools_builtin.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_visualflow_llm_call_context_attachments_map_to_media.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_visualflow_llm_call_multimodal_output.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_visualflow_make_object_node.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_visualflow_media_nodes.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_visualflow_memory_effect_nodes.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_visualflow_memory_source_pins.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_visualflow_pin_expressions.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_visualflow_prompt_only.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_visualflow_random_nodes.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_visualflow_schema_enum_switch.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_visualflow_string_contains_replace.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_visualflow_tool_parameters_node.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_voice_openai_api_key_path.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_w4_feelings_lens.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_wait_event_deadline.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_wait_event_prompt_metadata.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_wait_until_streak.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_wait_until_utc_normalization.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_workflow_bundle_registry.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_workspace_builtin_deny.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_workspace_policy_absolute_reanchor.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_workspace_policy_allowlist_mode.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_workspace_policy_mount_virtual_paths.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_workspace_policy_tool_calls_persist_across_restart.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_workspace_prompt_context.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_workspace_read_only.py +0 -0
- {abstractruntime-0.7.0 → abstractruntime-0.7.1}/tests/test_write_chart.py +0 -0
|
@@ -7,6 +7,23 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [0.7.1] - 2026-09-28
|
|
11
|
+
|
|
12
|
+
### Fixed
|
|
13
|
+
|
|
14
|
+
- **Images in replayed history stay images.** When the history window drops older turns, it writes a
|
|
15
|
+
`[#TRUNCATION: ...]` notice at the start of the oldest kept message. If that message held a list of content parts
|
|
16
|
+
(text plus an image, `[{"type": "text", ...}, {"type": "image_url", ...}]`), the notice turned the whole list into
|
|
17
|
+
one string, so the model received the image's base64 as text. The notice is now added as one text part and every
|
|
18
|
+
other part is left exactly as it was. A message that starts with its `<runtime_metadata>` envelope keeps it first.
|
|
19
|
+
This affects `announce_dropped` and `window_transcript`, and so the gateway's `/runs/start` client-context window and
|
|
20
|
+
any replay that keeps images. Content of any other type is left untouched and a warning is logged.
|
|
21
|
+
- **An image no longer counts as tens of thousands of tokens in the window.** `estimate_message_tokens` turned a
|
|
22
|
+
content-part list into a string, so a 150 KB inline image counted about 50,000 tokens and pushed every older turn out
|
|
23
|
+
of the history window. Text parts now count their text, and each media part (image, audio, file) counts a flat 512
|
|
24
|
+
tokens (`MEDIA_PART_TOKEN_ESTIMATE`, AbstractCore's per-image fallback). The input-budget trim
|
|
25
|
+
(`trim_messages_to_max_input_tokens`) uses the same estimate.
|
|
26
|
+
|
|
10
27
|
## [0.7.0] - 2026-09-28
|
|
11
28
|
|
|
12
29
|
Replayed session history is one window: the most recent 50,000 tokens of whole turns, recorded in the run.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: AbstractRuntime
|
|
3
|
-
Version: 0.7.
|
|
3
|
+
Version: 0.7.1
|
|
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
|
|
@@ -54,7 +54,7 @@ Description-Content-Type: text/markdown
|
|
|
54
54
|
|
|
55
55
|
It is designed for long-running workflows that must survive restarts and explicitly model blocking (human input, timers, external events, subworkflows) without keeping Python stacks alive.
|
|
56
56
|
|
|
57
|
-
**Version:** 0.7.
|
|
57
|
+
**Version:** 0.7.1 • **Python:** 3.10+
|
|
58
58
|
|
|
59
59
|
**Status:** pre-1.0 (API may evolve). For production use, pin versions and follow `CHANGELOG.md`.
|
|
60
60
|
|
|
@@ -146,7 +146,7 @@ state = rt.resume(
|
|
|
146
146
|
assert state.status.value == "completed"
|
|
147
147
|
```
|
|
148
148
|
|
|
149
|
-
## What’s included (v0.7.
|
|
149
|
+
## What’s included (v0.7.1)
|
|
150
150
|
|
|
151
151
|
Kernel (import-light):
|
|
152
152
|
- workflow graphs: `WorkflowSpec` (`src/abstractruntime/core/spec.py`)
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
It is designed for long-running workflows that must survive restarts and explicitly model blocking (human input, timers, external events, subworkflows) without keeping Python stacks alive.
|
|
6
6
|
|
|
7
|
-
**Version:** 0.7.
|
|
7
|
+
**Version:** 0.7.1 • **Python:** 3.10+
|
|
8
8
|
|
|
9
9
|
**Status:** pre-1.0 (API may evolve). For production use, pin versions and follow `CHANGELOG.md`.
|
|
10
10
|
|
|
@@ -96,7 +96,7 @@ state = rt.resume(
|
|
|
96
96
|
assert state.status.value == "completed"
|
|
97
97
|
```
|
|
98
98
|
|
|
99
|
-
## What’s included (v0.7.
|
|
99
|
+
## What’s included (v0.7.1)
|
|
100
100
|
|
|
101
101
|
Kernel (import-light):
|
|
102
102
|
- workflow graphs: `WorkflowSpec` (`src/abstractruntime/core/spec.py`)
|
|
@@ -252,10 +252,10 @@ Implementation: `src/abstractruntime/session_turns.py`, `src/abstractruntime/ses
|
|
|
252
252
|
|
|
253
253
|
- `select_session_turns(run_store, session_id, *, include_occurrences=True, until_ms=None, automation_id=None, through_occurrence=None, include_drafts=False, limit=50)` (package root): a session's turns, oldest first. Turns are parent-less runs except automation controllers, plus automation occurrences (a retried occurrence counts once, as its newest attempt); child runs, runtime-internal runs, legacy scheduled wrappers and draft-test runs are left out
|
|
254
254
|
- `session_chat_messages(run_store=, ledger_store=, artifact_store=, session_id=, max_tokens=HISTORY_REPLAY_MAX_TOKENS, until_ms=None, exclude_run_ids=None, automation_id=None, through_occurrence=None, strict=False)` (package root): the session's completed turns as user/assistant message pairs; in a discussion session the discussion's seed comes first. Returns a `ReplayedHistory` (a list of messages) whose `.report` says what was replayed and dropped. `strict=True` raises `SessionHistoryError` (`reason_code = "history_unavailable"`) instead of returning a partial history. `max_messages`, `max_total_chars` and `max_chars_per_message` (keyword-only, default `None`) are the caps retired in 0.7.0: they are accepted so hosts built against 0.6 (AbstractGateway 0.6.0) still get their history, and ignored. Passing any of them logs one warning and names them in `report["ignored_inputs"]`
|
|
255
|
-
- The history window: `HISTORY_REPLAY_MAX_TOKENS = 50_000` (package root). Replay keeps the most recent turns that fit 50,000 estimated tokens, newest first, as whole messages. There is no message-count cap and no character cap, and no message is ever cut. The fold stops at the first older turn that does not fit, so the window has no gaps. A total of exactly 50,000 tokens fits. One exception: when the newest turn alone is larger than the window, it is kept whole (`oversize_turn_kept: true`), because cutting it would lose content and dropping it would replay nothing. The model can use the rest of its context window; if a turn is too large for the model, the provider reports the error. Tokens are counted with `abstractruntime.memory.token_budget.estimate_message_tokens
|
|
255
|
+
- The history window: `HISTORY_REPLAY_MAX_TOKENS = 50_000` (package root). Replay keeps the most recent turns that fit 50,000 estimated tokens, newest first, as whole messages. There is no message-count cap and no character cap, and no message is ever cut. The fold stops at the first older turn that does not fit, so the window has no gaps. A total of exactly 50,000 tokens fits. One exception: when the newest turn alone is larger than the window, it is kept whole (`oversize_turn_kept: true`), because cutting it would lose content and dropping it would replay nothing. The model can use the rest of its context window; if a turn is too large for the model, the provider reports the error. Tokens are counted with `abstractruntime.memory.token_budget.estimate_message_tokens`: for a content-part list it counts the text parts' text plus `MEDIA_PART_TOKEN_ESTIMATE` (512) for each media part (`MEDIA_PART_TYPES`: image, audio, file), never the part's base64; any other part (a tool result, a thinking block) counts by its text (0.7.1). `max_tokens` must be a positive int
|
|
256
256
|
- `ReplayedHistory.report`: `{policy: "most_recent_whole_turns", max_tokens, token_estimator, replayed_messages, replayed_tokens, dropped_messages, dropped_tokens, dropped_counts_complete, oversize_turn_kept}`. Replay stops reading once the window is full, so in a long session `dropped_counts_complete` is `false` and the dropped counts cover only the turns it read. When turns were dropped, the oldest replayed message starts with a `[#TRUNCATION: N earlier message(s) ... were dropped from replay by the history window ...]` line (ADR-0026). Hosts record the report in the run as `vars._runtime.session_history`
|
|
257
257
|
- `fold_history_window(pairs, *, max_tokens=HISTORY_REPLAY_MAX_TOKENS)` (package root): the window itself, applied to chronological turns (lists of whole messages); returns `(kept, report)`
|
|
258
|
-
- `announce_dropped(messages, report, *, stamp_metadata=True)` (package root): writes the window's `[#TRUNCATION: ...]` notice at the start of the oldest kept message, in place, when `report` says turns were dropped. Use it after your own `fold_history_window` call (for example on client-sent history) so the notice matches session replay. `stamp_metadata=True` also adds `metadata.replay_truncated` and `metadata.history_window` to that message; pass `False` for plain role/content messages. `_announce_dropped` is kept as an alias of the pre-0.7.0 private name
|
|
258
|
+
- `announce_dropped(messages, report, *, stamp_metadata=True)` (package root): writes the window's `[#TRUNCATION: ...]` notice at the start of the oldest kept message, in place, when `report` says turns were dropped. Use it after your own `fold_history_window` call (for example on client-sent history) so the notice matches session replay. `stamp_metadata=True` also adds `metadata.replay_truncated` and `metadata.history_window` to that message; pass `False` for plain role/content messages. When the message's content is a content-part list (`[{"type": "text", ...}, {"type": "image_url", ...}]`), the notice is added as one `{"type": "text"}` part and every other part is left as it is, so images stay images (0.7.1); a stamped head keeps its `<runtime_metadata>` envelope first. Content of any other type is left untouched and a warning is logged. `_announce_dropped` is kept as an alias of the pre-0.7.0 private name
|
|
259
259
|
- `window_transcript(messages, *, max_tokens=HISTORY_REPLAY_MAX_TOKENS, current_turn_start=None)` (package root): the same window over a transcript you already hold (a turn is a user message and the messages after it). `current_turn_start` is the index of the message that opened the turn in progress: from there on everything is one turn, the newest, always kept whole (`oversize_turn_kept` when it alone exceeds the window), whatever user-role messages a loop adds inside it; an index out of range raises `ValueError`. Returns a `ReplayedHistory` of copies with the notice written by `announce_dropped(..., stamp_metadata=False)`. The entity chat driver and the entity visit workflow use it for their prompts. The visit records the report in `vars._runtime.session_history`; the chat driver puts it on `TurnReport.history_window`. On the react visit arm, BRIDGE sets `_runtime.history_window_tokens` (50,000) and `_runtime.history_window_turn_start` (the visitor's message) and the AbstractAgent react loop (0.3.17 or newer) sends `window_transcript(context.messages)` on each call and records the report; the stored transcript stays whole. The report carries `window_applied: true`; with an older AbstractAgent that records no window the turn still completes, a warning is logged and the report is `{"window_applied": false, "reason": "agent_too_old", ...}` (the whole transcript was sent). When the oldest kept message carries a `<runtime_metadata>` envelope, the notice is written after it
|
|
260
260
|
- `session_attribution(run_store, session_id)` (`abstractruntime.core.run_attribution`): `None` or `{"kind": "chat" | "automation" | "occurrence" | "discussion", ...}`; a discussion adds its validated root, automation, occurrence and workspace. Raises `SessionAttributionError` when the lookup cannot be completed
|
|
261
261
|
- `is_draft_lifecycle(run_lifecycle)` (package root): whether a run's lifecycle value marks a draft test run
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# AbstractRuntime — Architecture
|
|
2
2
|
|
|
3
3
|
> Updated: 2026-09-28
|
|
4
|
-
> Version: 0.7.
|
|
4
|
+
> Version: 0.7.1
|
|
5
5
|
> Scope: this describes **what is implemented in this repository**.
|
|
6
6
|
|
|
7
7
|
AbstractRuntime is a **durable workflow runtime**: it executes workflow graphs as a persisted state machine with explicit waits (user, time, events, jobs, subworkflows). A run can pause for hours/days and resume **without** keeping Python stacks/coroutines alive.
|
|
@@ -52,7 +52,7 @@ See llms.txt for the linked index.
|
|
|
52
52
|
|
|
53
53
|
It is designed for long-running workflows that must survive restarts and explicitly model blocking (human input, timers, external events, subworkflows) without keeping Python stacks alive.
|
|
54
54
|
|
|
55
|
-
**Version:** 0.7.
|
|
55
|
+
**Version:** 0.7.1 • **Python:** 3.10+
|
|
56
56
|
|
|
57
57
|
**Status:** pre-1.0 (API may evolve). For production use, pin versions and follow `CHANGELOG.md`.
|
|
58
58
|
|
|
@@ -144,7 +144,7 @@ state = rt.resume(
|
|
|
144
144
|
assert state.status.value == "completed"
|
|
145
145
|
```
|
|
146
146
|
|
|
147
|
-
## What’s included (v0.7.
|
|
147
|
+
## What’s included (v0.7.1)
|
|
148
148
|
|
|
149
149
|
Kernel (import-light):
|
|
150
150
|
- workflow graphs: `WorkflowSpec` (`src/abstractruntime/core/spec.py`)
|
|
@@ -430,7 +430,7 @@ rt = create_local_runtime(provider="ollama", model="qwen3:4b")
|
|
|
430
430
|
# AbstractRuntime — Architecture
|
|
431
431
|
|
|
432
432
|
> Updated: 2026-09-28
|
|
433
|
-
> Version: 0.7.
|
|
433
|
+
> Version: 0.7.1
|
|
434
434
|
> Scope: this describes **what is implemented in this repository**.
|
|
435
435
|
|
|
436
436
|
AbstractRuntime is a **durable workflow runtime**: it executes workflow graphs as a persisted state machine with explicit waits (user, time, events, jobs, subworkflows). A run can pause for hours/days and resume **without** keeping Python stacks/coroutines alive.
|
|
@@ -1107,10 +1107,10 @@ Implementation: `src/abstractruntime/session_turns.py`, `src/abstractruntime/ses
|
|
|
1107
1107
|
|
|
1108
1108
|
- `select_session_turns(run_store, session_id, *, include_occurrences=True, until_ms=None, automation_id=None, through_occurrence=None, include_drafts=False, limit=50)` (package root): a session's turns, oldest first. Turns are parent-less runs except automation controllers, plus automation occurrences (a retried occurrence counts once, as its newest attempt); child runs, runtime-internal runs, legacy scheduled wrappers and draft-test runs are left out
|
|
1109
1109
|
- `session_chat_messages(run_store=, ledger_store=, artifact_store=, session_id=, max_tokens=HISTORY_REPLAY_MAX_TOKENS, until_ms=None, exclude_run_ids=None, automation_id=None, through_occurrence=None, strict=False)` (package root): the session's completed turns as user/assistant message pairs; in a discussion session the discussion's seed comes first. Returns a `ReplayedHistory` (a list of messages) whose `.report` says what was replayed and dropped. `strict=True` raises `SessionHistoryError` (`reason_code = "history_unavailable"`) instead of returning a partial history. `max_messages`, `max_total_chars` and `max_chars_per_message` (keyword-only, default `None`) are the caps retired in 0.7.0: they are accepted so hosts built against 0.6 (AbstractGateway 0.6.0) still get their history, and ignored. Passing any of them logs one warning and names them in `report["ignored_inputs"]`
|
|
1110
|
-
- The history window: `HISTORY_REPLAY_MAX_TOKENS = 50_000` (package root). Replay keeps the most recent turns that fit 50,000 estimated tokens, newest first, as whole messages. There is no message-count cap and no character cap, and no message is ever cut. The fold stops at the first older turn that does not fit, so the window has no gaps. A total of exactly 50,000 tokens fits. One exception: when the newest turn alone is larger than the window, it is kept whole (`oversize_turn_kept: true`), because cutting it would lose content and dropping it would replay nothing. The model can use the rest of its context window; if a turn is too large for the model, the provider reports the error. Tokens are counted with `abstractruntime.memory.token_budget.estimate_message_tokens
|
|
1110
|
+
- The history window: `HISTORY_REPLAY_MAX_TOKENS = 50_000` (package root). Replay keeps the most recent turns that fit 50,000 estimated tokens, newest first, as whole messages. There is no message-count cap and no character cap, and no message is ever cut. The fold stops at the first older turn that does not fit, so the window has no gaps. A total of exactly 50,000 tokens fits. One exception: when the newest turn alone is larger than the window, it is kept whole (`oversize_turn_kept: true`), because cutting it would lose content and dropping it would replay nothing. The model can use the rest of its context window; if a turn is too large for the model, the provider reports the error. Tokens are counted with `abstractruntime.memory.token_budget.estimate_message_tokens`: for a content-part list it counts the text parts' text plus `MEDIA_PART_TOKEN_ESTIMATE` (512) for each media part (`MEDIA_PART_TYPES`: image, audio, file), never the part's base64; any other part (a tool result, a thinking block) counts by its text (0.7.1). `max_tokens` must be a positive int
|
|
1111
1111
|
- `ReplayedHistory.report`: `{policy: "most_recent_whole_turns", max_tokens, token_estimator, replayed_messages, replayed_tokens, dropped_messages, dropped_tokens, dropped_counts_complete, oversize_turn_kept}`. Replay stops reading once the window is full, so in a long session `dropped_counts_complete` is `false` and the dropped counts cover only the turns it read. When turns were dropped, the oldest replayed message starts with a `[#TRUNCATION: N earlier message(s) ... were dropped from replay by the history window ...]` line (ADR-0026). Hosts record the report in the run as `vars._runtime.session_history`
|
|
1112
1112
|
- `fold_history_window(pairs, *, max_tokens=HISTORY_REPLAY_MAX_TOKENS)` (package root): the window itself, applied to chronological turns (lists of whole messages); returns `(kept, report)`
|
|
1113
|
-
- `announce_dropped(messages, report, *, stamp_metadata=True)` (package root): writes the window's `[#TRUNCATION: ...]` notice at the start of the oldest kept message, in place, when `report` says turns were dropped. Use it after your own `fold_history_window` call (for example on client-sent history) so the notice matches session replay. `stamp_metadata=True` also adds `metadata.replay_truncated` and `metadata.history_window` to that message; pass `False` for plain role/content messages. `_announce_dropped` is kept as an alias of the pre-0.7.0 private name
|
|
1113
|
+
- `announce_dropped(messages, report, *, stamp_metadata=True)` (package root): writes the window's `[#TRUNCATION: ...]` notice at the start of the oldest kept message, in place, when `report` says turns were dropped. Use it after your own `fold_history_window` call (for example on client-sent history) so the notice matches session replay. `stamp_metadata=True` also adds `metadata.replay_truncated` and `metadata.history_window` to that message; pass `False` for plain role/content messages. When the message's content is a content-part list (`[{"type": "text", ...}, {"type": "image_url", ...}]`), the notice is added as one `{"type": "text"}` part and every other part is left as it is, so images stay images (0.7.1); a stamped head keeps its `<runtime_metadata>` envelope first. Content of any other type is left untouched and a warning is logged. `_announce_dropped` is kept as an alias of the pre-0.7.0 private name
|
|
1114
1114
|
- `window_transcript(messages, *, max_tokens=HISTORY_REPLAY_MAX_TOKENS, current_turn_start=None)` (package root): the same window over a transcript you already hold (a turn is a user message and the messages after it). `current_turn_start` is the index of the message that opened the turn in progress: from there on everything is one turn, the newest, always kept whole (`oversize_turn_kept` when it alone exceeds the window), whatever user-role messages a loop adds inside it; an index out of range raises `ValueError`. Returns a `ReplayedHistory` of copies with the notice written by `announce_dropped(..., stamp_metadata=False)`. The entity chat driver and the entity visit workflow use it for their prompts. The visit records the report in `vars._runtime.session_history`; the chat driver puts it on `TurnReport.history_window`. On the react visit arm, BRIDGE sets `_runtime.history_window_tokens` (50,000) and `_runtime.history_window_turn_start` (the visitor's message) and the AbstractAgent react loop (0.3.17 or newer) sends `window_transcript(context.messages)` on each call and records the report; the stored transcript stays whole. The report carries `window_applied: true`; with an older AbstractAgent that records no window the turn still completes, a warning is logged and the report is `{"window_applied": false, "reason": "agent_too_old", ...}` (the whole transcript was sent). When the oldest kept message carries a `<runtime_metadata>` envelope, the notice is written after it
|
|
1115
1115
|
- `session_attribution(run_store, session_id)` (`abstractruntime.core.run_attribution`): `None` or `{"kind": "chat" | "automation" | "occurrence" | "discussion", ...}`; a discussion adds its validated root, automation, occurrence and workspace. Raises `SessionAttributionError` when the lookup cannot be completed
|
|
1116
1116
|
- `is_draft_lifecycle(run_lifecycle)` (package root): whether a run's lifecycle value marks a draft test run
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
> Durable workflow runtime (interrupt → checkpoint → resume) with an append-only execution ledger.
|
|
4
4
|
|
|
5
5
|
- Python: 3.10+ (see `pyproject.toml`)
|
|
6
|
-
- Version: 0.7.
|
|
6
|
+
- Version: 0.7.1
|
|
7
7
|
- Ecosystem: [AbstractFramework](https://github.com/lpalbou/AbstractFramework) umbrella, integrates with [AbstractCore](https://github.com/lpalbou/abstractcore)
|
|
8
8
|
- Hard invariant: `RunState.vars` must be JSON-serializable (`src/abstractruntime/core/models.py`)
|
|
9
9
|
- Current AbstractCore baseline: base `abstractruntime` installs `abstractcore[remote,tools,vision,voice,audio,music]>=2.18.0`
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
### Fixed
|
|
2
|
+
|
|
3
|
+
- **Images in replayed history stay images.** When the history window drops older turns, it writes a
|
|
4
|
+
`[#TRUNCATION: ...]` notice at the start of the oldest kept message. If that message held a list of content parts
|
|
5
|
+
(text plus an image, `[{"type": "text", ...}, {"type": "image_url", ...}]`), the notice turned the whole list into
|
|
6
|
+
one string, so the model received the image's base64 as text. The notice is now added as one text part and every
|
|
7
|
+
other part is left exactly as it was. A message that starts with its `<runtime_metadata>` envelope keeps it first.
|
|
8
|
+
This affects `announce_dropped` and `window_transcript`, and so the gateway's `/runs/start` client-context window and
|
|
9
|
+
any replay that keeps images. Content of any other type is left untouched and a warning is logged.
|
|
10
|
+
- **An image no longer counts as tens of thousands of tokens in the window.** `estimate_message_tokens` turned a
|
|
11
|
+
content-part list into a string, so a 150 KB inline image counted about 50,000 tokens and pushed every older turn out
|
|
12
|
+
of the history window. Text parts now count their text, and each media part (image, audio, file) counts a flat 512
|
|
13
|
+
tokens (`MEDIA_PART_TOKEN_ESTIMATE`, AbstractCore's per-image fallback). The input-budget trim
|
|
14
|
+
(`trim_messages_to_max_input_tokens`) uses the same estimate.
|
|
@@ -10,6 +10,7 @@ budget (ADR-0008) even when the underlying model supports much larger contexts.
|
|
|
10
10
|
|
|
11
11
|
from __future__ import annotations
|
|
12
12
|
|
|
13
|
+
import json
|
|
13
14
|
import logging
|
|
14
15
|
from typing import Any, Dict, Iterable, List, Optional
|
|
15
16
|
|
|
@@ -35,15 +36,50 @@ def estimate_tokens(text: str, *, model: Optional[str] = None) -> int:
|
|
|
35
36
|
return max(1, int(len(s) / 4))
|
|
36
37
|
|
|
37
38
|
|
|
39
|
+
# Flat estimate for one non-text content part (an image, a file) — AbstractCore's
|
|
40
|
+
# own fallback per image (`VLMTokenCalculator` base_tokens). The real cost depends
|
|
41
|
+
# on the model and the image size; what matters here is that it is a bounded
|
|
42
|
+
# per-part cost, not the length of the part's base64 payload.
|
|
43
|
+
MEDIA_PART_TOKEN_ESTIMATE = 512
|
|
44
|
+
# Content-part types that carry media (an image, audio or a file), counted at the flat estimate.
|
|
45
|
+
# Every other part (tool_result, thinking, ...) is counted by its text, never flat.
|
|
46
|
+
MEDIA_PART_TYPES = frozenset({"image_url", "image", "input_image", "input_audio", "audio", "file"})
|
|
47
|
+
|
|
48
|
+
|
|
38
49
|
def estimate_message_tokens(message: Dict[str, Any], *, model: Optional[str] = None) -> int:
|
|
39
|
-
"""Estimate tokens for a chat message dict (role+content).
|
|
50
|
+
"""Estimate tokens for a chat message dict (role+content).
|
|
51
|
+
|
|
52
|
+
A content-part list (OpenAI-style `[{"type": "text", ...}, {"type":
|
|
53
|
+
"image_url", ...}]`) counts the text of its text parts, plus
|
|
54
|
+
`MEDIA_PART_TOKEN_ESTIMATE` for each media part (`MEDIA_PART_TYPES`); any
|
|
55
|
+
other part is counted by its serialized text. Before 0.7.1 the list
|
|
56
|
+
was stringified, so an inline image counted as its base64 text (~50,000
|
|
57
|
+
tokens for a 150 KB image) and pushed every older turn out of the window.
|
|
58
|
+
"""
|
|
40
59
|
if not isinstance(message, dict):
|
|
41
60
|
return 0
|
|
42
61
|
role = str(message.get("role") or "").strip()
|
|
43
|
-
|
|
62
|
+
raw = message.get("content")
|
|
63
|
+
media_parts = 0
|
|
64
|
+
if isinstance(raw, list):
|
|
65
|
+
texts: List[str] = []
|
|
66
|
+
for part in raw:
|
|
67
|
+
if isinstance(part, dict) and isinstance(part.get("text"), str) and "text" in str(part.get("type") or "text"):
|
|
68
|
+
texts.append(part["text"])
|
|
69
|
+
elif isinstance(part, str):
|
|
70
|
+
texts.append(part)
|
|
71
|
+
elif isinstance(part, dict) and str(part.get("type") or "") in MEDIA_PART_TYPES:
|
|
72
|
+
media_parts += 1
|
|
73
|
+
elif isinstance(part, dict) and part.get("type") == "text":
|
|
74
|
+
continue # an empty or non-string text part carries nothing
|
|
75
|
+
else:
|
|
76
|
+
texts.append(json.dumps(part, ensure_ascii=False, default=str))
|
|
77
|
+
content = "\n".join(texts)
|
|
78
|
+
else:
|
|
79
|
+
content = "" if raw is None else str(raw)
|
|
44
80
|
# Include a small role prefix so token estimation reflects chat formatting overhead.
|
|
45
81
|
text = f"{role}: {content}" if role else content
|
|
46
|
-
return estimate_tokens(text, model=model)
|
|
82
|
+
return estimate_tokens(text, model=model) + media_parts * MEDIA_PART_TOKEN_ESTIMATE
|
|
47
83
|
|
|
48
84
|
|
|
49
85
|
def trim_messages_to_max_input_tokens(
|
|
@@ -236,6 +236,23 @@ def announce_dropped(messages: List[Dict[str, Any]], report: Dict[str, Any], *,
|
|
|
236
236
|
`stamp_metadata=False` leaves the message's keys as they were (plain
|
|
237
237
|
role/content transcripts that go straight to a model client); the notice
|
|
238
238
|
in the content is the same.
|
|
239
|
+
|
|
240
|
+
Content shapes (0.7.1):
|
|
241
|
+
- a string (or empty/None): the notice is a prefix line, after the
|
|
242
|
+
message's own `<runtime_metadata>` envelope when it has one;
|
|
243
|
+
- a content-part list (OpenAI-style `[{"type": "text", ...},
|
|
244
|
+
{"type": "image_url", ...}]`, the shape AbstractCore accepts): the
|
|
245
|
+
notice is inserted as ONE `{"type": "text"}` part and every other part
|
|
246
|
+
is kept as is (images byte-identical). Prefixing it to the list used to
|
|
247
|
+
turn the whole content into a string, so the model read the image's
|
|
248
|
+
base64 as text. Without an envelope the notice part goes first. With
|
|
249
|
+
one (it heads the first text part, where the payload boundary looks
|
|
250
|
+
for it), that part is split: the envelope stays alone in it, the
|
|
251
|
+
notice part follows, then the part's remaining text as its own text
|
|
252
|
+
part — joined with newlines, the text reads exactly as the string path;
|
|
253
|
+
- anything else: the content is left untouched (rewriting an unknown
|
|
254
|
+
shape could corrupt it) and a warning is logged; with
|
|
255
|
+
`stamp_metadata=True` the metadata still records the drop.
|
|
239
256
|
"""
|
|
240
257
|
if not messages or int(report.get("dropped_messages") or 0) <= 0:
|
|
241
258
|
return
|
|
@@ -257,7 +274,19 @@ def announce_dropped(messages: List[Dict[str, Any]], report: Dict[str, Any], *,
|
|
|
257
274
|
# payload boundary would otherwise stack a second one in front).
|
|
258
275
|
from .turn_grounding import split_head_grounding # lazy: the grounding helpers load AbstractCore
|
|
259
276
|
|
|
260
|
-
|
|
277
|
+
content = head.get("content")
|
|
278
|
+
if isinstance(content, list):
|
|
279
|
+
head["content"] = _notice_into_parts(content, notice, split_head_grounding)
|
|
280
|
+
return
|
|
281
|
+
if content is not None and not isinstance(content, str):
|
|
282
|
+
logger.warning(
|
|
283
|
+
"history window: the oldest kept message has %s content; the #TRUNCATION notice "
|
|
284
|
+
"was not written into it (%s message(s) dropped)",
|
|
285
|
+
type(content).__name__,
|
|
286
|
+
report["dropped_messages"],
|
|
287
|
+
)
|
|
288
|
+
return
|
|
289
|
+
envelope, rest = split_head_grounding(content or "")
|
|
261
290
|
if envelope:
|
|
262
291
|
sep = "" if envelope.endswith("\n") else "\n"
|
|
263
292
|
head["content"] = f"{envelope}{sep}{notice}\n{rest.lstrip(chr(10))}"
|
|
@@ -265,6 +294,25 @@ def announce_dropped(messages: List[Dict[str, Any]], report: Dict[str, Any], *,
|
|
|
265
294
|
head["content"] = f"{notice}\n{rest}"
|
|
266
295
|
|
|
267
296
|
|
|
297
|
+
def _is_text_part(part: Any) -> bool:
|
|
298
|
+
return isinstance(part, dict) and str(part.get("type") or "").strip().lower() == "text"
|
|
299
|
+
|
|
300
|
+
|
|
301
|
+
def _notice_into_parts(parts: List[Any], notice: str, split_head_grounding: Any) -> List[Any]:
|
|
302
|
+
"""A new part list with the notice as one text part (see `announce_dropped`)."""
|
|
303
|
+
out = list(parts)
|
|
304
|
+
notice_part = {"type": "text", "text": notice}
|
|
305
|
+
first = next((i for i, part in enumerate(out) if _is_text_part(part)), None)
|
|
306
|
+
if first is not None:
|
|
307
|
+
envelope, rest = split_head_grounding(out[first].get("text"))
|
|
308
|
+
if envelope:
|
|
309
|
+
head_part = {**out[first], "text": envelope.rstrip("\n")}
|
|
310
|
+
tail = rest.lstrip("\n")
|
|
311
|
+
replacement = [head_part, notice_part] + ([{**out[first], "text": tail}] if tail else [])
|
|
312
|
+
return out[:first] + replacement + out[first + 1 :]
|
|
313
|
+
return [notice_part] + out
|
|
314
|
+
|
|
315
|
+
|
|
268
316
|
# The pre-0.7.0 private name, kept for callers that imported it.
|
|
269
317
|
_announce_dropped = announce_dropped
|
|
270
318
|
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
"""The history window over multimodal messages (0.7.1).
|
|
2
|
+
|
|
3
|
+
A message's content may be an OpenAI-style part list (`[{"type": "text", ...},
|
|
4
|
+
{"type": "image_url", ...}]`, the shape AbstractCore's providers and the
|
|
5
|
+
runtime's own media path build). The window's drop notice must go in as a TEXT
|
|
6
|
+
PART — prefixing it to the content used to turn the whole list into a string,
|
|
7
|
+
so the model received the image's base64 as text. And the window's token
|
|
8
|
+
estimate must not count that base64 as text either.
|
|
9
|
+
"""
|
|
10
|
+
|
|
11
|
+
from __future__ import annotations
|
|
12
|
+
|
|
13
|
+
import copy
|
|
14
|
+
|
|
15
|
+
from abstractruntime.memory.token_budget import MEDIA_PART_TOKEN_ESTIMATE, estimate_message_tokens
|
|
16
|
+
from abstractruntime.session_history import announce_dropped, fold_history_window, window_transcript
|
|
17
|
+
|
|
18
|
+
_B64 = "iVBORw0KGgo" + "A" * 200_000 + "=="
|
|
19
|
+
_IMAGE = {"type": "image_url", "image_url": {"url": f"data:image/png;base64,{_B64}", "detail": "high"}}
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
def _report(dropped: int = 2) -> dict:
|
|
23
|
+
return {**fold_history_window([], max_tokens=10)[1], "dropped_messages": dropped, "dropped_tokens": 9}
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
def _notice_of(report: dict) -> str:
|
|
27
|
+
probe = [{"role": "user", "content": ""}]
|
|
28
|
+
announce_dropped(probe, report, stamp_metadata=False)
|
|
29
|
+
return probe[0]["content"].rstrip("\n")
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
def test_list_content_keeps_its_image_and_gains_one_notice_text_part() -> None:
|
|
33
|
+
image = copy.deepcopy(_IMAGE)
|
|
34
|
+
messages = [{"role": "user", "content": [{"type": "text", "text": "what is this?"}, image]}]
|
|
35
|
+
announce_dropped(messages, _report(), stamp_metadata=False)
|
|
36
|
+
|
|
37
|
+
content = messages[0]["content"]
|
|
38
|
+
assert isinstance(content, list) and len(content) == 3
|
|
39
|
+
notice, text, img = content
|
|
40
|
+
assert notice["type"] == "text" and notice["text"].startswith("[#TRUNCATION: 2 earlier message(s)")
|
|
41
|
+
assert set(notice) == {"type", "text"}
|
|
42
|
+
assert text == {"type": "text", "text": "what is this?"}
|
|
43
|
+
assert img == _IMAGE and img["image_url"]["url"].endswith(_B64)
|
|
44
|
+
assert all(_B64 not in p.get("text", "") for p in content)
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
def test_list_content_with_a_stamped_head_keeps_the_envelope_first() -> None:
|
|
48
|
+
from abstractruntime.turn_grounding import message_carries_grounding_envelope, stamp_user_turn_grounding
|
|
49
|
+
|
|
50
|
+
stamped = [{"role": "user", "content": "hello"}]
|
|
51
|
+
assert stamp_user_turn_grounding(stamped)
|
|
52
|
+
head_text = stamped[0]["content"]
|
|
53
|
+
envelope = head_text[: head_text.index("hello")]
|
|
54
|
+
|
|
55
|
+
messages = [{"role": "user", "content": [{"type": "text", "text": head_text}, copy.deepcopy(_IMAGE)]}]
|
|
56
|
+
report = _report()
|
|
57
|
+
announce_dropped(messages, report, stamp_metadata=False)
|
|
58
|
+
|
|
59
|
+
content = messages[0]["content"]
|
|
60
|
+
assert isinstance(content, list)
|
|
61
|
+
assert content[-1] == _IMAGE
|
|
62
|
+
texts = [p["text"] for p in content if p.get("type") == "text"]
|
|
63
|
+
# The envelope still heads the first text part, exactly once in the message.
|
|
64
|
+
assert texts[0].startswith(envelope.rstrip("\n")) and "hello" not in texts[0]
|
|
65
|
+
assert sum(t.count("<runtime_metadata>") for t in texts) == 1
|
|
66
|
+
assert message_carries_grounding_envelope(messages[0])
|
|
67
|
+
# One text part carries the notice, then the turn's own words.
|
|
68
|
+
assert texts[1] == _notice_of(report)
|
|
69
|
+
assert texts[2] == "hello"
|
|
70
|
+
# Joined the way providers join text parts, it reads as the string path does.
|
|
71
|
+
as_string = [{"role": "user", "content": head_text}]
|
|
72
|
+
announce_dropped(as_string, report, stamp_metadata=False)
|
|
73
|
+
assert "\n".join(texts) == as_string[0]["content"]
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
def test_string_content_is_unchanged() -> None:
|
|
77
|
+
report = _report()
|
|
78
|
+
messages = [{"role": "user", "content": "hello"}]
|
|
79
|
+
announce_dropped(messages, report, stamp_metadata=False)
|
|
80
|
+
assert messages[0]["content"] == (
|
|
81
|
+
"[#TRUNCATION: 2 earlier message(s) of this session (~9 tokens) were dropped from replay by the "
|
|
82
|
+
"history window (the most recent 10 tokens, whole turns; abstractruntime.session_history); "
|
|
83
|
+
"this history starts mid-conversation]\nhello"
|
|
84
|
+
)
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
def test_list_content_without_a_text_part_gains_the_notice_first() -> None:
|
|
88
|
+
messages = [{"role": "user", "content": [copy.deepcopy(_IMAGE)]}]
|
|
89
|
+
announce_dropped(messages, _report(), stamp_metadata=False)
|
|
90
|
+
content = messages[0]["content"]
|
|
91
|
+
assert len(content) == 2 and content[0]["type"] == "text" and content[1] == _IMAGE
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
def test_unknown_content_type_is_left_untouched() -> None:
|
|
95
|
+
odd = {"custom": "shape"}
|
|
96
|
+
messages = [{"role": "user", "content": odd}]
|
|
97
|
+
announce_dropped(messages, _report())
|
|
98
|
+
assert messages[0]["content"] is odd
|
|
99
|
+
assert messages[0]["metadata"]["replay_truncated"] is True
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
def test_window_transcript_keeps_an_image_turn_as_parts() -> None:
|
|
103
|
+
messages = [
|
|
104
|
+
{"role": "user", "content": "old " * 2000},
|
|
105
|
+
{"role": "assistant", "content": "old answer"},
|
|
106
|
+
{"role": "user", "content": [{"type": "text", "text": "look"}, copy.deepcopy(_IMAGE)]},
|
|
107
|
+
{"role": "assistant", "content": "a cat"},
|
|
108
|
+
]
|
|
109
|
+
out = window_transcript(messages, max_tokens=2000)
|
|
110
|
+
assert out.report["dropped_messages"] == 2
|
|
111
|
+
head = out[0]["content"]
|
|
112
|
+
assert isinstance(head, list) and head[-1] == _IMAGE
|
|
113
|
+
assert head[0]["text"].startswith("[#TRUNCATION:")
|
|
114
|
+
assert messages[2]["content"][0] == {"type": "text", "text": "look"} # input not mutated
|
|
115
|
+
assert len(messages[2]["content"]) == 2
|
|
116
|
+
|
|
117
|
+
|
|
118
|
+
def test_token_estimate_counts_an_image_part_once_not_its_base64() -> None:
|
|
119
|
+
message = {"role": "user", "content": [{"type": "text", "text": "look"}, copy.deepcopy(_IMAGE)]}
|
|
120
|
+
tokens = estimate_message_tokens(message)
|
|
121
|
+
text_only = estimate_message_tokens({"role": "user", "content": "look"})
|
|
122
|
+
assert tokens == text_only + MEDIA_PART_TOKEN_ESTIMATE
|
|
123
|
+
# The base64 alone is ~50k tokens as text: it would push every older turn out.
|
|
124
|
+
assert tokens < 1000
|
|
125
|
+
|
|
126
|
+
|
|
127
|
+
def test_token_estimate_counts_every_text_part() -> None:
|
|
128
|
+
parts = [{"type": "text", "text": "alpha " * 100}, {"type": "text", "text": "beta " * 100}]
|
|
129
|
+
many = estimate_message_tokens({"role": "user", "content": parts})
|
|
130
|
+
one = estimate_message_tokens({"role": "user", "content": "alpha " * 100})
|
|
131
|
+
assert many > one
|
|
132
|
+
|
|
133
|
+
|
|
134
|
+
def test_token_estimate_counts_a_non_media_part_by_its_text_not_flat() -> None:
|
|
135
|
+
# An Anthropic-style tool_result or thinking part is text, however it is typed:
|
|
136
|
+
# it must never be counted as a flat media part.
|
|
137
|
+
big = "x " * 50_000
|
|
138
|
+
tool_part = {"role": "user", "content": [{"type": "tool_result", "tool_use_id": "t1", "content": big}]}
|
|
139
|
+
as_text = estimate_message_tokens({"role": "user", "content": big})
|
|
140
|
+
assert estimate_message_tokens(tool_part) >= as_text
|
|
141
|
+
empty_text = {"role": "user", "content": [{"type": "text"}]}
|
|
142
|
+
assert estimate_message_tokens(empty_text) < MEDIA_PART_TOKEN_ESTIMATE
|
|
@@ -1,94 +0,0 @@
|
|
|
1
|
-
Replayed session history is one window: the most recent 50,000 tokens of whole turns, recorded in the run.
|
|
2
|
-
Library callers of `session_chat_messages` and `automation_timeline_messages` should read the **Breaking** note.
|
|
3
|
-
|
|
4
|
-
### Changed
|
|
5
|
-
|
|
6
|
-
- The base install and the `apple` / `gpu` profiles require AbstractCore 2.18.0 or newer. Its voice extra brings
|
|
7
|
-
AbstractVoice 0.13.0, the first release that honours the `voice_openai_api_key` setting described below.
|
|
8
|
-
|
|
9
|
-
- **Session history replay is one window: the most recent 50,000 tokens.** `session_chat_messages` keeps the newest
|
|
10
|
-
turns that fit `HISTORY_REPLAY_MAX_TOKENS` (50,000) estimated tokens, as whole messages, newest first. The window has
|
|
11
|
-
no gaps, and a total of exactly 50,000 tokens fits. The 40-message cap, the 24,000-character total budget and the
|
|
12
|
-
8,000-character cut per message are removed, so no replayed message is ever cut. When the newest turn alone is larger
|
|
13
|
-
than the window, it is kept whole and the report says so (`oversize_turn_kept`). Tokens are counted with the existing
|
|
14
|
-
estimator, `memory.token_budget.estimate_message_tokens`. This window applies to automation growing mode (it
|
|
15
|
-
replaces the 40-message / 24,000-character limit of contract D), to discussion seeds (`automation_timeline_messages`)
|
|
16
|
-
and to host session seeding. The window is the only limit on replayed history; the model can use the rest of its
|
|
17
|
-
context window (operator ruling 2026-09-28, ADR-0026 §3: budgets are met by choosing whole turns, never by cutting
|
|
18
|
-
content).
|
|
19
|
-
- **Library API:** `session_chat_messages` still accepts `max_messages`, `max_chars_per_message` and
|
|
20
|
-
`max_total_chars` (keyword-only, default `None`) but IGNORES them: they no longer limit anything. Hosts built against
|
|
21
|
-
0.6 (AbstractGateway 0.6.0 passes `max_messages=40, max_total_chars=24000` and treats any error as "no history") keep
|
|
22
|
-
replaying their sessions under the window. Passing any of them logs one warning and names them in
|
|
23
|
-
`report["ignored_inputs"]`. Pass `max_tokens` (a positive int) to use a different window.
|
|
24
|
-
- **Breaking (library API):** `automation_timeline_messages` takes `max_tokens` instead of `max_messages` /
|
|
25
|
-
`max_chars_per_message` / `max_total_chars`. `GROWING_MAX_MESSAGES` and `GROWING_MAX_TOTAL_CHARS` are removed from
|
|
26
|
-
`abstractruntime.automations.models`.
|
|
27
|
-
- **The entity chat driver and the entity visit workflow use the same window.** They used to keep only the last 10
|
|
28
|
-
turns in the prompt, without saying so. Now every turn is kept, and each prompt carries the most recent 50,000 tokens
|
|
29
|
-
of whole turns, with the `[#TRUNCATION: ...]` line when older turns were dropped. The visit records the window's
|
|
30
|
-
report in `vars._runtime.session_history`; `ChatSession` puts it on `TurnReport.history_window` (and
|
|
31
|
-
`ChatSession.history_window`).
|
|
32
|
-
- **The react visit arm (the one AbstractGateway uses) sends the window too.** Its transcript is the durable
|
|
33
|
-
`context.messages`, sent by the AbstractAgent react loop on every call; before, nothing bounded it (after 12 turns of
|
|
34
|
-
~10k tokens a request was ~117k tokens, and a poisoned tool result rode every later turn). BRIDGE now sets
|
|
35
|
-
`_runtime.history_window_tokens` (50,000); the adapter sends `window_transcript(context.messages)` on every call —
|
|
36
|
-
a tool result stays with its turn, so a 495k-character tool result drops out of the request once a newer turn
|
|
37
|
-
exists — and records the report in `vars._runtime.session_history`. The stored transcript stays whole. BRIDGE also
|
|
38
|
-
records `_runtime.history_window_turn_start` (the visitor's message), and the window keeps the turn in progress whole
|
|
39
|
-
from there (`window_transcript(..., current_turn_start=)`): an `ask_user` answer or operator guidance inside the turn
|
|
40
|
-
no longer splits off the turn's own question and tool results; a turn larger than the window is kept whole and
|
|
41
|
-
reported as `oversize_turn_kept`. HARVEST
|
|
42
|
-
keeps a turn whose adapter recorded no window (AbstractAgent older than 0.3.17 sends the whole transcript) but
|
|
43
|
-
logs a warning ("abstractagent < 0.3.17 does not apply the history window; upgrade abstractagent") and records
|
|
44
|
-
`{"window_applied": false, "reason": "agent_too_old", ...}` in `vars._runtime.session_history` (counting the messages
|
|
45
|
-
the last request carried, not the reply stored after it); a windowed turn
|
|
46
|
-
records `window_applied: true`. **The window on the react arm needs AbstractAgent 0.3.17 or newer.**
|
|
47
|
-
- The `[#TRUNCATION: ...]` line is written after a stamped message's own `<runtime_metadata>` envelope, which stays at
|
|
48
|
-
the head (written in front, it made the payload boundary stack a second envelope).
|
|
49
|
-
- **Breaking (library API):** the `history_turns` parameter of `build_visit_workflow` and `ChatSession` is removed,
|
|
50
|
-
with `DEFAULT_HISTORY_TURNS` (no caller in the framework passed it). The entity visit no longer sets the
|
|
51
|
-
per-message character limits `_limits.max_tool_message_chars` (32,000) and `_limits.max_message_chars` (80,000) on
|
|
52
|
-
re-sent history, and `VISIT_HISTORY_TOOL_RESULT_CAP_CHARS` / `VISIT_HISTORY_MESSAGE_CAP_CHARS` are removed. A
|
|
53
|
-
single oversized tool result is still limited by AbstractAgent's own guard for oversized messages (200,000 characters).
|
|
54
|
-
- `trim_messages_to_max_input_tokens` (used only when a caller sets a positive `max_input_tokens`) keeps each tool
|
|
55
|
-
result together with the assistant tool call before it. It used to drop the call and keep the result, which
|
|
56
|
-
OpenAI-style APIs reject.
|
|
57
|
-
|
|
58
|
-
- **The context mode decides whether an automation's target reads history.** At admission the runtime sets
|
|
59
|
-
`use_context` (and `include_context` when present) to `true` for growing occurrences and `false` for independent
|
|
60
|
-
ones, and to `true` for discussion forks. A `use_context: false` frozen in an older definition no longer makes a
|
|
61
|
-
growing automation or a discussion replay nothing (basic-agent's `use_context` pin defaults to `false`). The run
|
|
62
|
-
records `_runtime.automation_context = {mode, use_context, target_use_context}`. Occurrences that were already
|
|
63
|
-
admitted before the upgrade keep their frozen inputs.
|
|
64
|
-
|
|
65
|
-
### Added
|
|
66
|
-
|
|
67
|
-
- Voice discovery (`local_get_voice_catalog`, `local_list_tts_models`, `local_list_stt_models`) accepts a
|
|
68
|
-
host-supplied `voice_openai_api_key` and passes it to AbstractVoice as the plugin setting of the same name (the
|
|
69
|
-
OpenAI credential for its `openai` engines; AbstractVoice reads no environment variable for it). The discovery
|
|
70
|
-
facade and the local clients accept and forward it (`AbstractCoreDiscoveryFacade.get_voice_catalog` /
|
|
71
|
-
`list_tts_models` / `list_stt_models(voice_openai_api_key=...)`); the remote client accepts it and never sends it.
|
|
72
|
-
In `llm_kwargs` it reaches the voice plugin through the provider's `config` and changes no text request; tests
|
|
73
|
-
prove this on real OpenAI, LM Studio, Ollama and MLX provider classes, with the network refused.
|
|
74
|
-
- **The window is recorded.** `session_chat_messages` and `automation_timeline_messages` return a `ReplayedHistory`
|
|
75
|
-
(a list of messages) with a `.report`: `policy`, `max_tokens`, `token_estimator`, `replayed_messages`,
|
|
76
|
-
`replayed_tokens`, `dropped_messages`, `dropped_tokens`, `dropped_counts_complete`, `oversize_turn_kept`. A growing
|
|
77
|
-
occurrence records it in `vars._runtime.session_history`, so the `automation.admitted` record's frozen inputs carry
|
|
78
|
-
it too. A discussion root records its seed window the same way. When older turns are dropped, the oldest replayed
|
|
79
|
-
message starts with a `[#TRUNCATION: ...]` line that gives the number of dropped messages and tokens and the window.
|
|
80
|
-
New exports at the package root: `HISTORY_REPLAY_MAX_TOKENS`, `ReplayedHistory`, `fold_history_window`,
|
|
81
|
-
`announce_dropped` (writes that `[#TRUNCATION: ...]` line after a host's own `fold_history_window` call, for example
|
|
82
|
-
on client-sent history; `session_history._announce_dropped` stays as an alias) and `window_transcript` (the window
|
|
83
|
-
over a transcript the caller already holds).
|
|
84
|
-
- `local_list_tts_models` reports why a provider cannot be listed: when the listing is unavailable, `error` carries
|
|
85
|
-
AbstractVoice's `unavailable_reason` (for example "no OpenAI API key is configured ..." or an unknown provider id).
|
|
86
|
-
It used to return `available: false, error: null`.
|
|
87
|
-
- Replay reads turns newest-first in batches that double in size, and stops once the window is full. A long session
|
|
88
|
-
therefore costs about as much as its window holds.
|
|
89
|
-
|
|
90
|
-
### Tests and CI
|
|
91
|
-
|
|
92
|
-
- CI installs the extras that exist (`.[test]`) and runs the history-window, entity window, automation timeline,
|
|
93
|
-
input-trim and voice-key tests. The five tests that need the sibling `abstractflow/` checkout or the
|
|
94
|
-
`abstractagent` package skip when those are absent (a standalone checkout or an sdist).
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{abstractruntime-0.7.0 → abstractruntime-0.7.1}/docs/adr/0001_layered_coupling_with_abstractcore.md
RENAMED
|
File without changes
|
{abstractruntime-0.7.0 → abstractruntime-0.7.1}/docs/adr/0002_execution_modes_local_remote_hybrid.md
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{abstractruntime-0.7.0 → abstractruntime-0.7.1}/docs/backlog/completed/001_runtime_kernel.md
RENAMED
|
File without changes
|
{abstractruntime-0.7.0 → abstractruntime-0.7.1}/docs/backlog/completed/002_persistence_and_ledger.md
RENAMED
|
File without changes
|