AbstractRuntime 0.10.5__tar.gz → 0.12.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/CHANGELOG.md +113 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/PKG-INFO +11 -9
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/README.md +6 -4
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/docs/README.md +5 -4
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/docs/api.md +30 -4
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/docs/architecture.md +101 -4
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/docs/artifacts.md +9 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/docs/automations.md +348 -13
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/docs/backlog/README.md +3 -1
- abstractruntime-0.12.0/docs/backlog/proposed/0849_conversation_search_tool_usage_outputs_and_thinking.md +40 -0
- abstractruntime-0.12.0/docs/backlog/proposed/0850_growing_automation_history_out_of_the_controller_ledger.md +83 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/docs/email.md +70 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/docs/faq.md +29 -2
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/docs/getting-started.md +1 -1
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/docs/integrations/abstractcore.md +2 -1
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/docs/troubleshooting.md +73 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/llms-full.txt +674 -33
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/llms.txt +12 -5
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/pyproject.toml +14 -5
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/pytest.ini +1 -0
- abstractruntime-0.12.0/release-notes.md +52 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/src/abstractruntime/automation_queries.py +9 -2
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/src/abstractruntime/automations/__init__.py +11 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/src/abstractruntime/automations/attention.py +110 -26
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/src/abstractruntime/automations/commands.py +42 -0
- abstractruntime-0.12.0/src/abstractruntime/automations/consumers.py +318 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/src/abstractruntime/automations/controller.py +207 -8
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/src/abstractruntime/automations/ledger.py +103 -1
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/src/abstractruntime/automations/models.py +54 -4
- abstractruntime-0.12.0/src/abstractruntime/automations/samples.py +325 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/src/abstractruntime/automations/service.py +135 -58
- abstractruntime-0.12.0/src/abstractruntime/automations/wakes.py +327 -0
- abstractruntime-0.12.0/src/abstractruntime/conversation_search.py +616 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/src/abstractruntime/core/models.py +6 -0
- abstractruntime-0.12.0/src/abstractruntime/core/publish.py +148 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/src/abstractruntime/core/run_attribution.py +5 -2
- abstractruntime-0.12.0/src/abstractruntime/core/run_origin.py +112 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/src/abstractruntime/core/runtime.py +132 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/src/abstractruntime/email/__init__.py +17 -1
- abstractruntime-0.12.0/src/abstractruntime/email/automations.py +199 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/src/abstractruntime/email/binding.py +36 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/src/abstractruntime/email/feeder.py +51 -10
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/src/abstractruntime/integrations/abstractcore/effect_handlers.py +6 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/src/abstractruntime/integrations/abstractcore/llm_client.py +36 -3
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/src/abstractruntime/integrations/abstractcore/tool_effects.py +3 -0
- abstractruntime-0.12.0/src/abstractruntime/mail_verbs.py +425 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/src/abstractruntime/storage/artifacts.py +92 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/src/abstractruntime/storage/base.py +30 -0
- abstractruntime-0.12.0/src/abstractruntime/storage/change_ring.py +30 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/src/abstractruntime/storage/in_memory.py +23 -1
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/src/abstractruntime/storage/json_files.py +872 -58
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/src/abstractruntime/storage/observable.py +26 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/src/abstractruntime/storage/offloading.py +15 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/src/abstractruntime/storage/sqlite.py +32 -1
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/src/abstractruntime/triggers/__init__.py +32 -1
- abstractruntime-0.12.0/src/abstractruntime/triggers/cloudevents.py +195 -0
- abstractruntime-0.12.0/src/abstractruntime/triggers/connection_events.py +232 -0
- abstractruntime-0.12.0/src/abstractruntime/triggers/connections.py +779 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/src/abstractruntime/triggers/email_received.py +174 -11
- abstractruntime-0.12.0/src/abstractruntime/triggers/event_frame.py +58 -0
- abstractruntime-0.12.0/src/abstractruntime/triggers/feed.py +523 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/src/abstractruntime/triggers/manual.py +13 -1
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/src/abstractruntime/triggers/protocol.py +46 -6
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/src/abstractruntime/triggers/registry.py +16 -1
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/src/abstractruntime/triggers/schedule.py +58 -1
- abstractruntime-0.12.0/src/abstractruntime/triggers/webhook.py +336 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/src/abstractruntime/visualflow_compiler/compiler.py +9 -1
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/src/abstractruntime/visualflow_compiler/visual/executor.py +57 -2
- abstractruntime-0.12.0/tests/fixtures/feeds/atom.xml +22 -0
- abstractruntime-0.12.0/tests/fixtures/feeds/rdf-not-a-feed.xml +6 -0
- abstractruntime-0.12.0/tests/fixtures/feeds/rss1-malformed.xml +8 -0
- abstractruntime-0.12.0/tests/fixtures/feeds/rss1.xml +41 -0
- abstractruntime-0.12.0/tests/fixtures/feeds/rss2.xml +24 -0
- abstractruntime-0.12.0/tests/media_endpoint_profile_probe.py +101 -0
- abstractruntime-0.12.0/tests/test_active_consumers_index.py +271 -0
- abstractruntime-0.12.0/tests/test_artifact_session_candidates.py +119 -0
- abstractruntime-0.12.0/tests/test_automation_list_reads.py +213 -0
- abstractruntime-0.12.0/tests/test_automation_named_policy_compiler.py +32 -0
- abstractruntime-0.12.0/tests/test_conversation_search.py +289 -0
- abstractruntime-0.12.0/tests/test_default_model_warmup_switch.py +49 -0
- abstractruntime-0.12.0/tests/test_email_feeder_batched.py +28 -0
- abstractruntime-0.12.0/tests/test_email_feeder_flags.py +45 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_email_gate_fixes.py +4 -1
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_email_inbox_and_trigger.py +11 -7
- abstractruntime-0.12.0/tests/test_email_received_mailbox_id.py +85 -0
- abstractruntime-0.12.0/tests/test_email_stream_consumers.py +76 -0
- abstractruntime-0.12.0/tests/test_event_index_cross_process.py +250 -0
- abstractruntime-0.12.0/tests/test_mail_verbs.py +312 -0
- abstractruntime-0.12.0/tests/test_mailbox_index.py +86 -0
- abstractruntime-0.12.0/tests/test_media_host_endpoint_resolver.py +92 -0
- abstractruntime-0.12.0/tests/test_occurrence_named_inputs.py +144 -0
- abstractruntime-0.12.0/tests/test_occurrence_samples.py +217 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_packaging_extras.py +4 -4
- abstractruntime-0.12.0/tests/test_publish_event.py +204 -0
- abstractruntime-0.12.0/tests/test_run_origin.py +83 -0
- abstractruntime-0.12.0/tests/test_run_store_change_token.py +105 -0
- abstractruntime-0.12.0/tests/test_schedule_run.py +254 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_schedule_v2_calendar.py +3 -1
- abstractruntime-0.12.0/tests/test_streamed_voice_namespace.py +36 -0
- abstractruntime-0.12.0/tests/test_trigger_cloudevents.py +113 -0
- abstractruntime-0.12.0/tests/test_trigger_connection_listening.py +164 -0
- abstractruntime-0.12.0/tests/test_trigger_connections.py +334 -0
- abstractruntime-0.12.0/tests/test_trigger_feed.py +315 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_trigger_registry.py +3 -2
- abstractruntime-0.12.0/tests/test_trigger_webhook.py +166 -0
- abstractruntime-0.12.0/tests/test_trusted_run_index.py +512 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_visual_entity_memory_nodes.py +2 -0
- abstractruntime-0.10.5/release-notes.md +0 -9
- abstractruntime-0.10.5/src/abstractruntime/email/automations.py +0 -104
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/.github/workflows/ci.yml +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/.github/workflows/release.yml +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/.gitignore +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/ACKNOWLEDGMENTS.md +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/CODE_OF_CONDUCT.md +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/CONTRIBUTING.md +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/LICENSE +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/ROADMAP.md +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/SECURITY.md +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/docs/adr/0001_layered_coupling_with_abstractcore.md +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/docs/adr/0002_execution_modes_local_remote_hybrid.md +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/docs/adr/0003_provenance_tamper_evident_hash_chain.md +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/docs/adr/0004_runtime_owns_run_scoped_media_execution_truth.md +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/docs/adr/0005_runtime_owns_abstractcore_host_discovery_queries.md +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/docs/adr/0006_runtime_owns_durable_abstractcore_bloc_prompt_cache.md +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/docs/adr/0007_runtime_relays_core_owned_model_residency_truth.md +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/docs/adr/README.md +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/docs/backlog/completed/001_runtime_kernel.md +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/docs/backlog/completed/002_persistence_and_ledger.md +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/docs/backlog/completed/0030_runtime_host_facades_for_comms_telegram_and_tool_specs.md +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/docs/backlog/completed/0032_runtime_durable_outbound_comms_truth.md +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/docs/backlog/completed/0033_runtime_host_local_prompt_cache_export_import_surface.md +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/docs/backlog/completed/0035_model_residency_provider_truth_for_local_http_clients.md +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/docs/backlog/completed/0037_visualflow_generate_music_node_compiler_parity.md +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/docs/backlog/completed/0039_runtime_music_structure_prompt_bool_contract.md +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/docs/backlog/completed/003_wait_primitives.md +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/docs/backlog/completed/0040_task_agnostic_local_residency_listing.md +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/docs/backlog/completed/0041_runtime_hardware_extras_avoid_nonpermissive_document_stacks.md +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/docs/backlog/completed/0042_core_vision_upscale_and_parameter_surface.md +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/docs/backlog/completed/0043_runtime_vision_adapter_and_batch_surface.md +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/docs/backlog/completed/004_scheduler_driver.md +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/docs/backlog/completed/005_abstractcore_integration.md +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/docs/backlog/completed/006_snapshots_bookmarks.md +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/docs/backlog/completed/007_provenance_hash_chain.md +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/docs/backlog/completed/009_artifact_store.md +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/docs/backlog/completed/010_examples_and_composition.md +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/docs/backlog/completed/011_subworkflow_support.md +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/docs/backlog/completed/012_run_store_query_and_scheduler_support.md +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/docs/backlog/completed/013_effect_retries_and_idempotency.md +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/docs/backlog/completed/016_runtime_aware_parameters.md +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/docs/backlog/completed/019_runtime_host_facade_for_core_operator_surfaces.md +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/docs/backlog/completed/020_runtime_gateway_install_boundary.md +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/docs/backlog/completed/021_runtime_gateway_env_namespace_cleanup.md +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/docs/backlog/completed/022_model_residency_control_plane.md +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/docs/backlog/completed/023_truthful_local_media_residency_boundaries.md +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/docs/backlog/completed/024_runtime_owned_run_scoped_media_execution.md +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/docs/backlog/completed/026_runtime_host_discovery_facade_for_core_catalogs.md +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/docs/backlog/completed/027_runtime_durable_bloc_prompt_cache_facade.md +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/docs/backlog/completed/028_runtime_bloc_kv_lifecycle_and_pruning.md +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/docs/backlog/completed/029_runtime_music_generation_and_discovery_via_abstractcore.md +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/docs/backlog/completed/0846_mlx_instance_scheduling_and_execution_controls.md +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/docs/backlog/completed/0847_automations_v1_controller_contracts_occurrences_triggers.md +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/docs/backlog/deprecated/001_integrations_abstractcore.md +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/docs/backlog/deprecated/001_runtime_kernel.md +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/docs/backlog/deprecated/002_persistence_and_ledger.md +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/docs/backlog/deprecated/002_snapshots_bookmarks.md +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/docs/backlog/deprecated/0034_agent_runtime_convenience_constructor.md +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/docs/backlog/deprecated/003_provenance_ledger_chain.md +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/docs/backlog/deprecated/003_wait_resume_and_scheduler.md +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/docs/backlog/deprecated/004_effect_handlers_and_integrations.md +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/docs/backlog/deprecated/004_tests.md +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/docs/backlog/deprecated/005_docs_updates.md +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/docs/backlog/deprecated/005_examples_and_composition.md +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/docs/backlog/deprecated/006_ai_fingerprint_and_provenance.md +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/docs/backlog/deprecated/DEPRECATED_README.md +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/docs/backlog/deprecated/README.md +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/docs/backlog/deprecated/abstractruntime_docs_final_02a7373b.plan.md +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/docs/backlog/planned/0070_standalone_wui_browser_session_security_contract.md +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/docs/backlog/planned/008_signatures_and_keys.md +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/docs/backlog/planned/014_remote_tool_worker_executor.md +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/docs/backlog/planned/017_limit_warnings_and_observability.md +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/docs/backlog/planned/018_workspace_access_policy_for_media_and_tools.md +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/docs/backlog/planned/0233_real_run_cancellation.md +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/docs/backlog/planned/025_runtime_retention_and_purge_contract.md +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/docs/backlog/planned/026_context_checkpoint_self_compression.md +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/docs/backlog/planned/027_quote_provenance_discipline.md +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/docs/backlog/planned/028_selective_artifact_rehydration.md +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/docs/backlog/planned/0845_session_prompt_cache_resume_and_purge_contract.md +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/docs/backlog/planned/0848_automations_v2_external_event_inbox_and_run_triggers.md +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/docs/backlog/planned/runtime_portability/0065_portable_process_and_lock_layer.md +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/docs/backlog/planned/runtime_portability/0066_portable_io_and_media_reader.md +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/docs/backlog/planned/runtime_portability/README.md +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/docs/backlog/planned/runtime_systemic_reliability/0044_meta_analysis_record.md +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/docs/backlog/planned/runtime_systemic_reliability/0045_crash_replay_harness_and_ordering_invariant.md +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/docs/backlog/planned/runtime_systemic_reliability/0046_per_run_driver_exclusion.md +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/docs/backlog/planned/runtime_systemic_reliability/0047_indexed_idempotency_lookup.md +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/docs/backlog/planned/runtime_systemic_reliability/0048_durable_io_unification.md +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/docs/backlog/planned/runtime_systemic_reliability/0049_llm_client_mechanical_split.md +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/docs/backlog/planned/runtime_systemic_reliability/0050_control_sidecar_all_writers.md +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/docs/backlog/planned/runtime_systemic_reliability/0051_runtime_owned_durable_event_mailbox.md +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/docs/backlog/planned/runtime_systemic_reliability/0052_sync_store_event_loop_tripwire.md +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/docs/backlog/planned/runtime_systemic_reliability/0053_bounded_run_vars_growth.md +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/docs/backlog/planned/runtime_systemic_reliability/0054_runtime_health_counters.md +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/docs/backlog/planned/runtime_systemic_reliability/0055_jsonl_store_honesty.md +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/docs/backlog/planned/runtime_systemic_reliability/0064_prompt_cache_fingerprint_stability.md +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/docs/backlog/planned/runtime_systemic_reliability/0067_durable_write_discipline.md +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/docs/backlog/planned/runtime_systemic_reliability/0068_hot_path_store_reads.md +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/docs/backlog/planned/runtime_systemic_reliability/README.md +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/docs/backlog/proposed/0031_runtime_tool_spec_adapters_for_gateway_and_mcp.md +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/docs/backlog/proposed/0036_local_media_residency_bridge_to_core_residency.md +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/docs/backlog/proposed/0038_core_server_pool_residency_affinity.md +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/docs/backlog/proposed/0069_document_renderer_professional_figures.md +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/docs/backlog/proposed/runtime_systemic_reliability/0056_schema_version_and_quarantine_loading.md +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/docs/backlog/proposed/runtime_systemic_reliability/0057_trust_boundary_stamp_registry.md +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/docs/backlog/proposed/runtime_systemic_reliability/0058_terminal_run_archival_helper.md +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/docs/backlog/proposed/runtime_systemic_reliability/0059_memory_span_handler_extraction.md +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/docs/backlog/proposed/runtime_systemic_reliability/0060_visualflow_compiler_decomposition.md +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/docs/backlog/proposed/runtime_systemic_reliability/0061_root_api_deprecation_machinery.md +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/docs/backlog/proposed/runtime_systemic_reliability/0062_dependency_honesty_extras.md +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/docs/backlog/proposed/runtime_systemic_reliability/0063_b3_envelope_lane_unification.md +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/docs/backlog/proposed/runtime_systemic_reliability/README.md +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/docs/entity-runtime.md +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/docs/evidence.md +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/docs/limits.md +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/docs/manual_testing.md +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/docs/mcp-worker.md +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/docs/proposal.md +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/docs/provenance.md +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/docs/snapshots.md +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/docs/tool-approval.md +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/docs/tools-comms.md +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/docs/workflow-bundles.md +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/examples/01_hello_world.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/examples/02_ask_user.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/examples/03_wait_until.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/examples/04_multi_step.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/examples/05_persistence.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/examples/06_llm_integration.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/examples/07_react_agent.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/examples/README.md +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/mkdocs.yml +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/scripts/backfill_diary_edges.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/scripts/generate_llms_full.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/src/abstractruntime/__init__.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/src/abstractruntime/automations/adapters.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/src/abstractruntime/automations/bundle.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/src/abstractruntime/automations/bundles/automation-controller/flows/controller.json +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/src/abstractruntime/automations/bundles/automation-controller/manifest.json +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/src/abstractruntime/core/__init__.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/src/abstractruntime/core/config.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/src/abstractruntime/core/effect_cancellation.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/src/abstractruntime/core/event_keys.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/src/abstractruntime/core/health.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/src/abstractruntime/core/live_deltas.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/src/abstractruntime/core/policy.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/src/abstractruntime/core/progress_channel.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/src/abstractruntime/core/run_identity.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/src/abstractruntime/core/run_lifecycle.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/src/abstractruntime/core/spec.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/src/abstractruntime/core/tool_scope.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/src/abstractruntime/core/vars.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/src/abstractruntime/documents/__init__.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/src/abstractruntime/documents/charts.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/src/abstractruntime/documents/docx.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/src/abstractruntime/documents/pdf.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/src/abstractruntime/email/actions.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/src/abstractruntime/email/frame.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/src/abstractruntime/email/inbox.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/src/abstractruntime/evidence/__init__.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/src/abstractruntime/evidence/recorder.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/src/abstractruntime/history_bundle.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/src/abstractruntime/identity/__init__.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/src/abstractruntime/identity/act_only.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/src/abstractruntime/identity/chat.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/src/abstractruntime/identity/communities.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/src/abstractruntime/identity/diary.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/src/abstractruntime/identity/digest.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/src/abstractruntime/identity/entity_runtime.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/src/abstractruntime/identity/fingerprint.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/src/abstractruntime/identity/lease.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/src/abstractruntime/identity/life.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/src/abstractruntime/identity/memory_reader.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/src/abstractruntime/identity/night_voice.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/src/abstractruntime/identity/phase_graph.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/src/abstractruntime/identity/phase_spec.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/src/abstractruntime/identity/prelude.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/src/abstractruntime/identity/prompt_overlay.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/src/abstractruntime/identity/reflection.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/src/abstractruntime/identity/spec/entity_phases.vendored.json +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/src/abstractruntime/identity/substrate.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/src/abstractruntime/identity/tool_effects.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/src/abstractruntime/identity/tool_policy.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/src/abstractruntime/identity/tools.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/src/abstractruntime/identity/visit_workflow.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/src/abstractruntime/integrations/__init__.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/src/abstractruntime/integrations/abstractcore/__init__.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/src/abstractruntime/integrations/abstractcore/agora_tools.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/src/abstractruntime/integrations/abstractcore/command_sandbox_host.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/src/abstractruntime/integrations/abstractcore/comms_facade.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/src/abstractruntime/integrations/abstractcore/config_facade.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/src/abstractruntime/integrations/abstractcore/constants.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/src/abstractruntime/integrations/abstractcore/data_registry_facade.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/src/abstractruntime/integrations/abstractcore/default_tools.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/src/abstractruntime/integrations/abstractcore/discovery_facade.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/src/abstractruntime/integrations/abstractcore/discovery_queries.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/src/abstractruntime/integrations/abstractcore/email_facade.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/src/abstractruntime/integrations/abstractcore/embeddings_client.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/src/abstractruntime/integrations/abstractcore/factory.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/src/abstractruntime/integrations/abstractcore/host_facade.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/src/abstractruntime/integrations/abstractcore/local_helper_tools.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/src/abstractruntime/integrations/abstractcore/logging.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/src/abstractruntime/integrations/abstractcore/mcp_facade.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/src/abstractruntime/integrations/abstractcore/mcp_worker.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/src/abstractruntime/integrations/abstractcore/media_subprocess.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/src/abstractruntime/integrations/abstractcore/observability.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/src/abstractruntime/integrations/abstractcore/output_specs.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/src/abstractruntime/integrations/abstractcore/run_facade.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/src/abstractruntime/integrations/abstractcore/server_facade.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/src/abstractruntime/integrations/abstractcore/session_attachments.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/src/abstractruntime/integrations/abstractcore/structured_facade.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/src/abstractruntime/integrations/abstractcore/summarizer.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/src/abstractruntime/integrations/abstractcore/telegram_facade.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/src/abstractruntime/integrations/abstractcore/tool_executor.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/src/abstractruntime/integrations/abstractcore/tool_inventory_facade.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/src/abstractruntime/integrations/abstractcore/workspace_scoped_tools.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/src/abstractruntime/integrations/abstractmemory/__init__.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/src/abstractruntime/integrations/abstractmemory/brain_handlers.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/src/abstractruntime/integrations/abstractmemory/effect_handlers.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/src/abstractruntime/integrations/abstractmemory/identity_support.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/src/abstractruntime/integrations/abstractmemory/seam_handlers.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/src/abstractruntime/memory/__init__.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/src/abstractruntime/memory/active_context.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/src/abstractruntime/memory/active_memory.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/src/abstractruntime/memory/compaction.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/src/abstractruntime/memory/kg_packets.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/src/abstractruntime/memory/memact_composer.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/src/abstractruntime/memory/recall_levels.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/src/abstractruntime/memory/token_budget.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/src/abstractruntime/rendering/__init__.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/src/abstractruntime/rendering/agent_trace_report.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/src/abstractruntime/rendering/json_stringify.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/src/abstractruntime/scheduler/__init__.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/src/abstractruntime/scheduler/convenience.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/src/abstractruntime/scheduler/multi_store.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/src/abstractruntime/scheduler/registry.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/src/abstractruntime/scheduler/scheduler.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/src/abstractruntime/session_history.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/src/abstractruntime/session_turns.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/src/abstractruntime/storage/__init__.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/src/abstractruntime/storage/commands.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/src/abstractruntime/storage/lease.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/src/abstractruntime/storage/ledger_chain.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/src/abstractruntime/storage/ledger_slim.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/src/abstractruntime/storage/serialize.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/src/abstractruntime/storage/snapshots.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/src/abstractruntime/storage/steer_sidecar.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/src/abstractruntime/turn_grounding.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/src/abstractruntime/utils/__init__.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/src/abstractruntime/utils/atomic_files.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/src/abstractruntime/utils/file_filters.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/src/abstractruntime/utils/workspace_paths.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/src/abstractruntime/visualflow_compiler/__init__.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/src/abstractruntime/visualflow_compiler/adapters/__init__.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/src/abstractruntime/visualflow_compiler/adapters/agent_adapter.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/src/abstractruntime/visualflow_compiler/adapters/context_adapter.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/src/abstractruntime/visualflow_compiler/adapters/control_adapter.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/src/abstractruntime/visualflow_compiler/adapters/effect_adapter.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/src/abstractruntime/visualflow_compiler/adapters/event_adapter.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/src/abstractruntime/visualflow_compiler/adapters/function_adapter.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/src/abstractruntime/visualflow_compiler/adapters/memact_adapter.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/src/abstractruntime/visualflow_compiler/adapters/subflow_adapter.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/src/abstractruntime/visualflow_compiler/adapters/variable_adapter.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/src/abstractruntime/visualflow_compiler/flow.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/src/abstractruntime/visualflow_compiler/visual/__init__.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/src/abstractruntime/visualflow_compiler/visual/agent_ids.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/src/abstractruntime/visualflow_compiler/visual/builtins.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/src/abstractruntime/visualflow_compiler/visual/code_executor.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/src/abstractruntime/visualflow_compiler/visual/execution_metrics.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/src/abstractruntime/visualflow_compiler/visual/function_library.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/src/abstractruntime/visualflow_compiler/visual/loop_back_check.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/src/abstractruntime/visualflow_compiler/visual/loop_limit_lowering.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/src/abstractruntime/visualflow_compiler/visual/models.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/src/abstractruntime/visualflow_compiler/visual/multi_entry_lowering.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/src/abstractruntime/visualflow_compiler/visual/pin_expressions.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/src/abstractruntime/visualflow_compiler/visual/reroute_lowering.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/src/abstractruntime/workflow_bundle/__init__.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/src/abstractruntime/workflow_bundle/models.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/src/abstractruntime/workflow_bundle/packer.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/src/abstractruntime/workflow_bundle/reader.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/src/abstractruntime/workflow_bundle/registry.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/README.md +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/automation_harness.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/conftest.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/email_wp2_support.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/fixtures/schedule_v1_corpus.json +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/live_email/conftest.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/live_email/live_email_support.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/live_email/test_email_live_runtime.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_abstractcore_comms_facade.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_abstractcore_discovery_facade.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_abstractcore_host_facade.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_abstractcore_run_facade.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_abstractcore_server_facade.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_abstractcore_structured_facade.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_abstractcore_telegram_facade.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_active_context_policy.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_active_index.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_active_memory.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_agora_agent_alias_identity.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_agora_tools_http.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_analyze_media_addressing_and_walling.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_answer_user_effect.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_artifacts.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_automation_calendar_schedule.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_automation_commands.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_automation_controller.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_automation_controller_recovery.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_automation_definition.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_automation_discussion_isolation.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_automation_email_results.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_automation_growing_context.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_automation_index.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_automation_next_fire.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_automation_occurrence_input_resolver.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_automation_occurrence_recovery.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_automation_replay_read_only.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_automation_retry.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_automation_session_turns.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_automation_status.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_automation_tool_approval.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_browser_probe_target_walling.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_budget_law_no_unrequested_caps.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_capability_default_reasoning.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_chat_summarizer_integration.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_code_node_imports.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_code_node_restricted_python.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_command_sandbox_host_facade.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_command_store.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_compaction_helpers.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_compaction_summarizer_route.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_config_facade_models_engines.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_config_facade_voice_input_hint.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_control_adapter_while.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_controller_bundle_packaged.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_crash_ordering_inversions.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_create_if_absent.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_data_registry_facade.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_default_tools_camera_gating.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_default_tools_comms_gating.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_default_tools_include_skim_files.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_default_tools_include_skim_folders.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_default_tools_include_skim_web.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_default_tools_search_files_executor.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_diary_capture.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_diary_write_rescue.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_directory_lease.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_disabled_toolsets_seam.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_discovery_survives_unbuildable_default.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_discovery_tts_unavailable_reason.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_discovery_voice_openai_api_key.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_discussion_session_anchor.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_document_markdown_tables.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_document_renderers_hr_quote.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_durable_toolsets.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_durable_write_discipline.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_e2e_tool_calls_idempotency_lmstudio.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_effect_cancellation.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_effect_issuance_idempotency.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_effect_payload_stays_json_serializable.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_election_consequence_teaching.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_email_binding_and_refiner.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_email_regate_fixes.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_email_review_fixes.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_email_self_trigger_loop.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_email_toolset_and_walls.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_emergence_experiment.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_emit_event_uses_wait_index.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_emit_event_without_workflow_registry.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_endpoint_profile_media_end_to_end.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_endpoint_profile_media_in_process.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_endpoint_profile_media_specs_keep_provider.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_endpoint_profile_route_context.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_entity_awake_memory_fixes.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_entity_brain_effects.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_entity_chat_driver.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_entity_chat_tools_reflection.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_entity_diary.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_entity_execute_tool.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_entity_fetch_url_tool.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_entity_history_window.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_entity_life_loop.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_entity_memory_richness.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_entity_phase_graph_conformance.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_entity_react_visit_window.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_entity_recent_memories.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_entity_runtime.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_entity_search_memory.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_entity_sleep_bound_and_yield_attribution.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_entity_substrate_resolution.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_entity_visit_honesty.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_entity_workspace_cap.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_entity_workspace_tools.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_event_wait_index.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_every_path_bearing_tool_is_walled.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_evidence_recorder.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_evidence_recorder_post_policy_envelope.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_execute_command_output_offload.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_execution_capability_discovery.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_explicit_eject_other_clients.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_factory_default_retry_policy.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_factory_timeouts_default_to_abstractcore_config.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_format_repair_nudge.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_fresh_install_no_provider.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_gateway_facades_c4899.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_git_read_only_refiner.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_hf_process_residency_merge.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_history_window_multimodal.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_hot_path_store_reads.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_indexed_idempotency_lookup.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_integration_abstractcore.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_integrations_abstractcore.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_json_file_run_store_children_index.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_json_run_cache_bound.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_json_store_scan_memo.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_jsonl_ledger_recovery.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_kg_learn_and_recall_contract.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_ledger_chain.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_ledger_record_slimming.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_ledger_subscription.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_live_token_deltas.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_llm_call_media_artifact_refs.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_llm_call_media_artifact_refs_persist_across_restart.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_llm_call_media_uses_source_path_label.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_llm_call_payload_shape_refusal.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_llm_call_requires_prompt.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_llm_call_response_schema_normalization.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_llm_call_structured_output_fallback.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_llm_call_text_phase_progress.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_llm_call_truncation_retry_contract.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_llm_call_use_context_appends_turn.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_llm_call_verbatim_payload_capture.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_llm_client_grounding_tail.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_llm_client_media_artifacts.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_llm_client_system_context.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_llm_client_tool_call_parsing.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_llm_retry_classification.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_llm_streaming_on_token.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_local_helper_tool_exposure.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_local_residency_host_sweep.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_local_runtime_timeout_kwarg_policy.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_max_iterations_ceiling.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_mcp_remote_tool_executor.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_mcp_runs_untrusted_and_facade.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_mcp_worker_logging.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_mcp_worker_security.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_mcp_worker_stdio.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_media_artifact_resolution.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_media_capability_default_routing.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_media_only_requests_skip_text_client.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_media_subprocess.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_memact_composer_from_kg_result.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_memory_appraise_handler.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_memory_communities.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_memory_kg_assert_attributes_defaults.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_memory_kg_packets.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_memory_kg_predicate_aliasing.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_memory_kg_query_packetization_restart.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_memory_kg_query_recall_level_policy.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_memory_kg_semantic_query_ranking.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_memory_note_effect.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_memory_query_effect.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_memory_query_rich_filters.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_memory_scope_and_rehydrate_effect.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_memory_seam_handlers.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_memory_seam_sqlite_durability.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_memory_tag_effect.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_mlx_generation_serialization.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_mlx_process_residency_merge.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_model_eject_cancel.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_model_residency_clean_switch.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_model_residency_control_plane.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_model_residency_lock_and_context_estimate.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_multi_store_scheduler.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_multimodal_abstractcore_integration.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_native_mlx_application_wiring.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_native_mlx_execution_controls_live.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_native_tool_channel.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_night_voice.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_no_default_provider_refusal_ux.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_offload_answer_chain_c4978.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_offloaded_node_traces_report_unknown_not_zero.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_offloading.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_parallel_readonly_tool_execution.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_pause_resume.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_pdf_unicode_rendering.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_personal_cycle.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_phantom_attachment_index.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_phase_graph_artifact_control.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_phase_graph_obedience.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_phase_vocabulary_migration.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_pooled_client_strips_construction_cache_key.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_prompt_cache_export_import.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_prompt_cache_fingerprint_stability.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_prompt_cache_modules.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_prompt_cache_posture_inheritance.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_prompt_cache_thinking_and_prompt_only.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_prompt_overlay.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_provider_endpoint_profile_resolution.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_provider_pin_routing_isolation.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_queryable_run_store.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_r12_workspace_sandbox.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_read_file_fallback_to_session_attachments.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_read_idle_threading.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_readoption_experiment.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_real_integration.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_realize_election.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_recall_levels_policy.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_remote_client_cancel.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_remote_llm_client.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_remote_speculation_defaults.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_rendering_agent_trace_report.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_rendering_json_stringify.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_report_branding.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_resident_media_generation.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_resume_concurrent_same_wait.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_retry_idempotency.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_run_history_bundle.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_run_index_workspace_root.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_run_mutation_lock.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_run_scoped_tool_policy.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_run_tool_scope_ceiling.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_runtime_browser_session_boundary.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_runtime_config_max_output_tokens_fallback.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_runtime_default_provider_model_refresh.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_runtime_effect_invocation_trace.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_runtime_health_and_bounded_vars.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_runtime_install_boundary.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_runtime_llm_call_grounding_in_ledger.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_runtime_node_traces.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_runtime_start_seeds_tool_support.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_runtime_tick_step_gate.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_schedule_v1_corpus.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_scheduler.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_send_email_refiner.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_send_email_self_default_policy.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_session_attachments_registry_and_open_tool.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_session_history.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_session_prompt_cache_attribution.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_session_prompt_cache_visibility.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_session_route_stamp.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_session_start_cost.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_shell_tool_exposure.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_snapshots.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_speculation_inheritance.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_speculation_reaches_provider_construction.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_sqlite_ledger_store.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_start_subworkflow_async_wait.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_start_subworkflow_inherit_context_merges_messages.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_start_subworkflow_workspace_inheritance.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_steer_sidecar.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_storage_deletion.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_structured_output_schema_enum.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_subworkflow.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_terminal_effect_completion.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_terminal_resume_appends_ledger_completion.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_thinking_inheritance.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_tick_completion_includes_output_in_ledger.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_tool_approval_executor.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_tool_approval_resume_executes.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_tool_approval_wait_key_identity.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_tool_calls_idempotency_keys.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_tool_catalog.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_tool_descriptor_registry.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_tool_executor_argument_sanitization.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_tool_executor_error_output_detection.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_tool_executor_filename_alias.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_tool_executor_kwarg_canonicalization.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_tool_executor_read_file_aliases.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_tool_executor_timeout.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_tool_inventory_facade.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_tool_invoke_effect.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_tool_policy_and_mounts.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_tool_wait_allowlist_safety.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_topic_election_world_model.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_trace_context_propagation.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_trigger_schedule_math.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_turn_grounding_byte_stability.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_turn_grounding_carriers_a3.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_vars_query_effect.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_visit_ab_fixture.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_visit_midturn_elections.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_visit_midturn_resume.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_visit_workflow.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_visual_agent_output_context_includes_messages.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_visual_agent_skills_block_passthrough.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_visual_agent_tool_observations_persist_across_restart.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_visual_agent_use_context_inherits_attachments.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_visual_agent_use_context_persists_tool_observations.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_visual_agent_use_context_persists_turn.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_visual_flow_end_effect_only_persistence.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_visual_llm_call_partial_override.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_visual_llm_call_schema_ref_resolution.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_visual_loop_back_out_of_body.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_visual_loop_limit_and_list_nodes.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_visual_loop_limit_on_wire.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_visual_memact_compose_node.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_visual_memory_kg_query_outputs_propagate.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_visual_memory_kg_resolve_outputs_propagate.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_visual_multi_entry_loop_overrides.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_visual_reroute_lowering.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_visual_set_vars_pins.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_visual_unknown_node_type_refuses.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_visual_wait_event_deadline_passthrough.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_visualflow_add_message_builtin.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_visualflow_add_message_node_appends_to_active_context.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_visualflow_agora_react_agent.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_visualflow_call_tool_node.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_visualflow_capability_routes_and_thinking.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_visualflow_compiler_basic.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_visualflow_context_and_builder_nodes.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_visualflow_continue_on_error.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_visualflow_edit_json_schema_node.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_visualflow_event_inbox_react_agent.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_visualflow_file_nodes_workspace.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_visualflow_function_library.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_visualflow_get_element_node.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_visualflow_get_random_element_node.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_visualflow_get_var_node.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_visualflow_has_tools_builtin.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_visualflow_llm_call_context_attachments_map_to_media.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_visualflow_llm_call_multimodal_output.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_visualflow_make_object_node.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_visualflow_media_nodes.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_visualflow_memory_effect_nodes.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_visualflow_memory_source_pins.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_visualflow_pin_expressions.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_visualflow_prompt_only.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_visualflow_random_nodes.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_visualflow_schema_enum_switch.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_visualflow_string_contains_replace.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_visualflow_tool_parameters_node.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_voice_openai_api_key_path.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_voice_stream_is_not_a_wait.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_w4_feelings_lens.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_wait_event_deadline.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_wait_event_prompt_metadata.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_wait_until_streak.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_wait_until_utc_normalization.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_workflow_bundle_registry.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_workspace_builtin_deny.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_workspace_context_allowed_workspaces.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_workspace_policy_absolute_reanchor.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_workspace_policy_allowlist_mode.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_workspace_policy_mount_virtual_paths.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_workspace_policy_tool_calls_persist_across_restart.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_workspace_prompt_context.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_workspace_read_only.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_workspace_writable_paths.py +0 -0
- {abstractruntime-0.10.5 → abstractruntime-0.12.0}/tests/test_write_chart.py +0 -0
|
@@ -5,6 +5,119 @@ All notable changes to AbstractRuntime will be documented in this file.
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
+
## [Unreleased]
|
|
9
|
+
|
|
10
|
+
## [0.12.0] - 2026-10-27
|
|
11
|
+
|
|
12
|
+
Requires AbstractCore 2.30.0 or newer (`EmailClient` mailbox verbs; Gmail labels on message summaries) and AbstractMemory 0.3.2 or newer.
|
|
13
|
+
|
|
14
|
+
First published release since 0.10.6: it also ships the 0.11.0 and 0.11.1 sections below.
|
|
15
|
+
|
|
16
|
+
### Added
|
|
17
|
+
|
|
18
|
+
- **Mail verbs for flows**: fixed-verb nodes `mail_search`, `mail_get`, `mail_mark`, `mail_label`, `mail_move`, `mail_delete`, `mail_send`, `mail_reply`, `mail_forward` and `mail_attachment` compile to `TOOL_INVOKE` effects (`mail.*`) the runtime runs on the run's mailbox (default: the trigger's, else the primary; `mailbox` names another by id, or by the address of the run's own or the primary mailbox; `ids` / `id` take one id, one Email record or a list), without an approval prompt and never mintable by a model. Built on AbstractCore 2.28.0's `EmailClient` verbs (`search` with a typed query, `get_many`, `mark`, `label`, `move`, `delete`, `download_attachment`, `session(write=...)`) and `EmailContext.send` / `reply` / `forward` (through `guarded_send`): one connection per verb, reads read-only, mailbox changes and sends refused on a read-only mailbox (`email_mailbox_read_only`). See [Mail verbs for flows](docs/email.md#mail-verbs-for-flows).
|
|
19
|
+
- **Publish to channel**: `EffectType.PUBLISH_EVENT` (node type `publish_event`) with `{channel, type?, title, body?, subject?, data?, alert?}`: the runtime validates it and hands it to the host (`Runtime.set_publish_event_handler`, `handler(run, payload, step_id)` with the effect's idempotency key as `step_id`, the same on a replayed step); the host appends a CloudEvents event with the `channel` extension to the user's stream (and an attention item when `alert`) and returns `{event_id, sequence, alerted}`, the node's result. Channels are free names applications subscribe to. See [Publish to channel](docs/automations.md#publish-to-channel).
|
|
20
|
+
- **The Email record**: one message shape for trigger inputs, samples and the mail verbs: `{id, message_id, mailbox, folder, thread_id, from, to, cc, subject, date, body_text, body_html, attachments: [{index, name, size, type, artifact}], seen, flagged, labels}`. `labels` merges the IMAP keywords with the message's Gmail labels (AbstractCore 2.29.0). The trigger's `messages` use it: their `id` is now the message's locator (`"<uidvalidity>:<uid>:<folder>"`) and the Message-ID moves to `message_id`.
|
|
21
|
+
|
|
22
|
+
- **Publish to channel: `recipient` and `channels`** (framework ADR-0041 follow-up, Notify me's Who / Where). The `PUBLISH_EVENT` payload gains `recipient` (default `"me"`; a name, so another account can be named later; the host decides) and `channels` (a non-empty list from `tray`, `watch`, `phone`, `email`, `console`, deduplicated in that order; absent or `"all"` = every channel; refused without `alert: true`), validated by `validate_publish` / `normalize_channels` (`DELIVERY_CHANNELS`). Defaults are omitted from the payload the host gets, and `handler(run, payload, step_id)` is unchanged, so older hosts keep working. The visual executor and compiler pass both from the node's pins or, else, its `effectConfig` (`publish_config_defaults`: Notify me saves `effectConfig.channels`). Tests: tests/test_publish_event.py (validation, the host receives the set, the compiled workflow passes the saved choice, a compiled Notify me end to end).
|
|
23
|
+
|
|
24
|
+
- **RSS 1.0 (RDF) feeds** for `feed.item@1`: `parse_feed` reads `<rdf:RDF>` documents with the RSS 1.0 channel and items (namespace `http://purl.org/rss/1.0/`), stdlib only, into the same item record as RSS 2.0 and Atom: `id` = the item's `rdf:about` (else the link), `published` = Dublin Core `dc:date` (else none), `summary` = `description` (else `content:encoded`), `author` = every `dc:creator`, joined with commas; `title` falls back to `dc:title`. The parsed feed's `kind` is `rss1`. An RDF document without an RSS 1.0 channel is refused (`FeedParseError`, so `feed_unreadable` on the connection). The fetcher also accepts `application/rdf+xml`. Nature (`https://www.nature.com/nature.rss`), Science (`https://www.science.org/rss/news_current.xml`, the journal's table of contents) and Deutsche Welle's RDF feed were refused before and now read.
|
|
25
|
+
|
|
26
|
+
### Changed
|
|
27
|
+
|
|
28
|
+
- **Dependency floors**: AbstractCore 2.30.0 (the published successor of 2.27-2.29, with the latest
|
|
29
|
+
AbstractVoice, AbstractVision, AbstractMusic and Abstract3D plugins) and AbstractMemory 0.3.2.
|
|
30
|
+
|
|
31
|
+
- **Mail verbs refuse in two plain ways.** A mailbox the person keeps Read only (AbstractCore's explicit `EmailAccount.access`, no longer "has SMTP") refuses `mark`, `label`, `move`, `delete`, `send`, `reply` and `forward` with `email_mailbox_read_only`: "This mailbox is read-only: automations only read it." / "In My email, turn on Read and write for <address> to change it or send from it." A Read and write mailbox without an outgoing server refuses `send`, `reply` and `forward` with the new `email_mailbox_cannot_send`: "This mailbox can't send: it has no outgoing server." / "In My email, add the outgoing server (SMTP) for <address>." Both before connecting.
|
|
32
|
+
|
|
33
|
+
### Fixed
|
|
34
|
+
|
|
35
|
+
- **A compiled Publish to channel / Notify me node runs.** The visual compiler adds `resume_to_node` (and the effect type under `type`) to every effect payload; `validate_publish` refused it ("invalid publish request: unknown publish field(s): ['resume_to_node']"), so every Publish to channel and Notify me node of a VisualFlow failed its step, and a node's own `type` pin replaced the effect type the compiler reads. The runtime now strips that envelope before validation (`core/publish.strip_visual_envelope`) and the executor carries the `type` pin as `event_type`.
|
|
36
|
+
- **A process that serves no model does not load one.** `MultiLocalAbstractCoreLLMClient` builds its default client at construction (a warm-up that, for a local MLX default, loads the weights: 15 GB for a 27B model) and again on a default switch. The gateway's split API process builds the same runtime as the runner process, so it loaded a second copy at boot. `set_default_model_warmup(False)` (`integrations.abstractcore.llm_client`, process-wide, no environment variable) defers the default client to its first call; `default_model_warmup()` reads it. Default on: nothing changes for a single process. Tests.
|
|
37
|
+
- **Events reach runs parked by another process.** In a split gateway (`serve --no-runner` + `abstractgateway runner` on one folder) the runner process parks a run in WAITING(EVENT) by re-saving a run it already saved as running, which writes no creation-log line, so the API process's event-wait index never heard of it and an event delivered there missed the waiter (same hole for a run that declared `events_mailbox` later). `JsonFileRunStore` now refreshes both indexes from the store's change signal before every lookup: when the creation log or the folder's mtime moved, or at least every 2 s (`EVENT_INDEX_REFRESH_S`), it stats the running and waiting runs and re-files the ones another process changed. Two stats when nothing moved; own saves never re-read; `event_index_stats()`. Tests: a real second process parks a run, an event delivered in this process resumes it (and the mailbox case); the 2 s floor; no pass when nothing moved.
|
|
38
|
+
- **Run listings come from memory (the trusted run index).** `JsonFileRunStore` answers every listing that is not RUNNING/WAITING or session-scoped (no status, a finished status, `role=`, `automation_id=`, `latest_occurrence_row`: about 61 call sites in the gateway) from its in-memory record of every run's listing fields once one complete pass has read the folder, instead of globbing and stat()ing every run file per call (11,500 files: a 0.25 s pass alone, minutes beside a busy thread). Changes reach it through the store's own writes, the creation log (new line `=<run_id>`: a finished run's file changed, written after publication), a re-read of its RUNNING/WAITING entries when the folder moved, and a background reconciliation (at most every 60 s when the folder or the log moved, at least every 10 min) that repairs and logs any difference. `trust_index=True` (default) / `False` (verify: the scan answers and is compared, `run_index_stats()["shadow_mismatches"]` counts differences); `reconcile_run_index()`; `OffloadingRunStore.run_index_stats()`. Memo hygiene on the way: a scan's read never overwrites a newer entry from this store's own save, a parsed file is memoized with the token of the file actually read (fstat), and the prune keeps entries whose file exists (created after the glob). Tests: differential (2,000 runs, two writers, after every step and after reconciliation), idle minute with zero run-file stats, second process through a store and bypassing the log, shadow mode.
|
|
39
|
+
- **Automation listings read the present, not the history.** `pending_waits` reads the run index's WAITING rows
|
|
40
|
+
attributed to the automation (occurrences and descendants) instead of walking every occurrence tree, and the new
|
|
41
|
+
`pending_waits_by_automation` answers a whole page from one read. The new `latest_occurrence(runtime, id)` (the
|
|
42
|
+
row of `list_occurrences(limit=1)`) reads the controller ledger backwards from its end and stops at the newest
|
|
43
|
+
admission (`automation_records_newest_first`, a lazy newest-first reader of JSONL ledgers);
|
|
44
|
+
`list_occurrences` resolves prompt artifacts for the returned page only; `list_attention` reads back to the seen
|
|
45
|
+
floor only. `normalize_occurrence_output(..., lazy=True)` resolves just the values it reads (an agent's output can
|
|
46
|
+
hold thousands of offloaded values). `list_automations(..., index_rows=...)` takes controller rows a host already
|
|
47
|
+
holds, and `automation_generation(run_store)` exposes the change counter to key them on. Measured on a copy of the
|
|
48
|
+
operator's plane (11,500 run files): the gateway's automations list went from 2.4 s to 0.22 s cold.
|
|
49
|
+
- **Ledger change signal.** `ObservableLedgerStore.change_token()` (a counter every append moves) and
|
|
50
|
+
`changed_run_ids(token)` (the runs whose ledger grew since, from the last 8,192 appends; `None` beyond), so a periodic
|
|
51
|
+
reader learns which ledgers grew without re-reading them. Process-local, like the subscriptions. The bounded record
|
|
52
|
+
behind both stores' `changed_run_ids` is `abstractruntime.storage.change_ring.ChangeRing`.
|
|
53
|
+
- **"Did any run change?" is one stat.** New `JsonFileRunStore.change_token()` (creation-log size + active-index counter,
|
|
54
|
+
moved by every save, create and delete) and `changed_run_ids(token)` (the runs behind the last 8,192 changes, or
|
|
55
|
+
`None` when unknown). The gateway runner compared a glob + stat of every run file every 0.5 s instead (32 ms on a
|
|
56
|
+
warm 11,500-run copy, 0.18 s on the operator's folder): the token costs about 1 µs and reads no file.
|
|
57
|
+
- **A session's artifacts without reading the whole catalog.** New `ArtifactStore.list_session_candidates(session_id, owner_run_id=)`:
|
|
58
|
+
the artifacts a session may see (owned by its memory run, tagged `session_id`, or tagged `shared`), newest first.
|
|
59
|
+
`FileArtifactStore` answers from three catalog indexes (two new expression indexes over the tags, built by the first
|
|
60
|
+
lookup in the caller's thread, never when the store opens): 1-7 ms on a 106k-artifact catalog, where reading the
|
|
61
|
+
catalog to filter in Python took 3.2 s. A catalog error raises; there is no fallback to reading every artifact.
|
|
62
|
+
- **"Who listens?" no longer reads every automation's run file.** `connection_usage`, `stream_consumers` / `wake_stream_consumers`, `email_trigger_consumers` / `wake_email_automations`, `connection_trigger_consumers` / `wake_connection_automations`, `prune_email_inbox` and the feed poll used to list the whole run index and load every controller run on every call: per connection row, per feed poll, per mailbox poll and per wake (measured on the operator's 11,499-run plane: 0.5 s per call quiet, 2.2 s beside a busy thread, 6-9 s for a 3-connection listing; 190% CPU while idle). They now answer from one **active-consumers index** per runtime (`abstractruntime.automations.consumers`: `{automation_id: trigger}` for the ACTIVE automations), in microseconds. It is rebuilt only when something changed, on the run store's automation generation (`invalidate_active_consumers`, keyed by the store's folder or database file): a JSON-file store bumps it on every save whose controller index row (the automation's status and trigger) is new or different, so any path of the process (a command, a decision, a controller failing or cancelled) is seen at once and ordinary controller saves bump nothing; `create_automation`, every applied automation command and any decision or reconciliation whose delta changes the definition or the `paused` / `exhausted` state bump it explicitly for every store; a 30-second TTL catches another process writing the same folder. A rebuild lists only the RUNNING and WAITING controller rows (a JSON-file store answers from its active index) and reads no run file: a controller's index row now carries `automation_consumer: {status, trigger}` (an older scan sidecar's controller rows are re-parsed once). New `connections_usage(runtime, connections)` answers a list from one snapshot. Answers are unchanged.
|
|
63
|
+
- Trigger messages keep their flags: the mail watcher stores each new message with its `flags` (\\Seen, \\Flagged, IMAP keywords) and Gmail `labels` (AbstractCore 2.29's `MessageSummary.labels`, on a Gmail server) as read, so an occurrence's Email record carries `seen`, `flagged` and `labels` like a sample's (they were null). Nothing else in the payload or the cursor changes.
|
|
64
|
+
|
|
65
|
+
## [0.11.1] - 2026-10-25
|
|
66
|
+
|
|
67
|
+
Requires AbstractCore 2.27.0 or newer (`EmailClient.session()` / `get_many()`).
|
|
68
|
+
|
|
69
|
+
### Added
|
|
70
|
+
|
|
71
|
+
- **The mail watcher reads a burst of new mail on one connection.** `EmailInboxFeeder.poll` lists and reads the new messages inside one `EmailClient.session()` and reads them with `get_many` (one header FETCH per 100, one body FETCH per text section) instead of one connection per message (~10 s each on a remote server). Payloads, the cursor (advanced message by message, only after each durable append), nothing marked read and the per-message failure count are unchanged; a message that breaks the batch read is read alone so only it fails. Needs AbstractCore with `EmailClient.session` / `get_many` (the release after 2.26.4).
|
|
72
|
+
|
|
73
|
+
- **Named occurrence inputs for flows**: an automation's occurrence receives its trigger's data as flat, named inputs beside `input_data.event`: `scheduled_at` and `occurrence` (schedules), `messages` and `mailbox` (`email.received@1`; `messages` stored as an artifact like the mail bodies), `items` and `feed` (`feed.item@1`), `calls` (`webhook.received@1`); a manual run adds none. Adapters implement `occurrence_inputs(...)`. A stored webhook call now keeps its headers (lower-cased, without the signature and credentials). The input and output contract (`response`, `success`, `notify`) is documented in [Occurrence inputs and outputs](docs/automations.md#occurrence-inputs-and-outputs-the-flow-contract).
|
|
74
|
+
|
|
75
|
+
- **Sample inputs for testing a triggered flow**: `sample_occurrence_inputs(runtime, source_id, source_version, config, count=100, principal=...)` returns the named inputs and `event` a real occurrence would receive, from real data and read only: the newest matching messages of the bound mailbox (20-second fetch budget, `truncated`), the latest feed items, the last stored webhook calls (or one documented sample call), `scheduled_at` = now for schedules. The event carries the CloudEvents extension `abstracttest: true`. Mail is read on one IMAP connection (`batched_newest_messages`: AbstractCore's `EmailClient.session()`, `search` and `get_many`; a body over 1 MB is skipped with a typed record, never cut; attachments never downloaded; nothing marked read), so 100 messages take a few round trips. See [Testing a triggered flow](docs/automations.md#testing-a-triggered-flow-with-sample-inputs).
|
|
76
|
+
|
|
77
|
+
### Changed
|
|
78
|
+
|
|
79
|
+
- **Feed connections are polled only while something listens.** `TriggerConnection` gains `paused` (default false) and `always_listen` (default false), set through `TriggerConnectionStore.create(...)` / `update(...)`; `status` keeps its meaning. `connection_usage(runtime, connection)` derives `{listening: "paused" | "listening" | "idle", used_by: <active automations reading the stream>}`, and `connection.to_dict(usage=...)` adds both fields. `poll_feed_connections` fetches only listening feed connections (an idle one is not fetched and stores nothing; its first poll after an automation binds again is a baseline) and its reports carry `listening` and `used_by`. `append_webhook_event` refuses a paused connection like a disabled one (409 `connection_disabled`); an idle webhook connection still accepts and stores calls (its `runtime=` argument is accepted and unused). See [Trigger connections](docs/automations.md#trigger-connections).
|
|
80
|
+
- `feed.item@1`'s connection fields read in plain language for forms: "Feed address", "Check every" (a number and a unit), "Most new items per check" and "When added" ("Ignore what is already there" / "Also deliver the latest items", `enumNames`); the field names and values are unchanged.
|
|
81
|
+
|
|
82
|
+
## [0.11.0] - 2026-10-25
|
|
83
|
+
|
|
84
|
+
### Added
|
|
85
|
+
|
|
86
|
+
- **`email.received@1` on a further mailbox** (framework backlog 1044): `config.account` accepts a mailbox id of the user (`"self"`, the default, and `"default"` stay the primary mailbox). The automation reads only that mailbox's inbox streams and its occurrences act for it (`_runtime.email_account` from `email_binding_for_trigger`); `message_matches` checks the mail's `account_ref` too. The descriptor's `account` schema is a pattern with default `"self"` (no longer `enum: ["self"]`). See [The email.received@1 trigger](docs/email.md#the-emailreceived1-trigger).
|
|
87
|
+
|
|
88
|
+
- **A note wake reaches the person** (framework backlog 1045 follow-up): `SCHEDULE_RUN` takes `notify` (default true for a `note`, false for a `task`); a notifying wake's definition carries `notify.always: true` with `notify.title` (the note) and `notify.body` (the note), so its completed occurrence raises an attention item (kind `notify`, body = the answer, else the note) whatever the answer's own `notify` says. `notify.always` / `title` / `body` are new optional fields of every definition's `notify`. The effect result reports `notify`.
|
|
89
|
+
|
|
90
|
+
- **Wakes: `EffectType.SCHEDULE_RUN`** (framework backlog 1045): a run schedules work for later (`at`, `after_s` or `on` a trigger event) with a `task` or a reminder `note`, as a new turn of its own session by default (`mode: same_session`) or in a fresh one. The runtime plans a one-shot automation (`automations.wakes.plan_schedule_run`): tools at most the caller's ceiling intersected with the request, never `schedule_run` itself, written as the occurrence's explicit `_runtime.allowed_tools`; approval `ask`, the caller's tool policy copied, untrusted callers make untrusted wakes; `origin_run_id` recorded and the occurrence's origin is `agent`. The host creates it through `Runtime.set_schedule_run_handler` (usually with `create_scheduled_run`) and appends `wake.scheduled` / `wake.cancelled` to the user's stream (`wake_scheduled_event`, `wake_cancelled_event`). Creation requests accept `session_id` (where a growing automation's occurrences run; the controller keeps `automation:<id>`), `origin_run_id`, `one_shot` and `untrusted_origin`; an occurrence's `session_kind` may be `chat`. `schedule_run` is classified as a delegation tool. See [Wakes](docs/automations.md#wakes-schedule_run).
|
|
91
|
+
|
|
92
|
+
- Several mailboxes per user (framework backlog 1044): `email_binding_for_trigger(binding, trigger)` binds an `email.received@1` automation whose `config.account` names a further mailbox of the same user to that mailbox (`<tenant>:<user>:<account_id>`; `self`, `default` or no value keep the runtime's own binding), with `account_ref_with_id` / `account_id_of_ref` (`abstractruntime.email`).
|
|
93
|
+
|
|
94
|
+
- **Webhook trigger `webhook.received@1`** (framework backlog 1042, runtime half): a webhook connection with a generated, sealed signing secret (`whsec_…`) or the creator's own, an optional `subject_path` and a replay window. `verify_standard_webhook(secret, headers, body, now, tolerance_s)` checks Standard Webhooks signatures (pure; reference vector tested), and `append_webhook_event(inbox, connection, body, headers)` maps one verified HTTP call to one event on the connection's stream (`webhook-id` as `subject`/`dedupekey`, so a replayed id is refused) and returns the status the host's route answers with (202 / 409 / 401 / 413 / 415). See [`webhook.received@1`](docs/automations.md#webhookreceived1).
|
|
95
|
+
|
|
96
|
+
- **Feed trigger `feed.item@1`** (framework backlog 1043): runs an automation on new items of an RSS 2.0 or Atom feed connection (`{url, every >= 60s, max_items, initial_items: skip|deliver}`). Standard-library parsing, conditional GET, item identity (Atom id / RSS guid / link) as `subject` and `dedupekey` so each item is appended once, the cursor in the connection stream's state, typed failures on the connection with a capped backoff. The host's plane runs the poller: `poll_feed_connections(runtime, store)` polls the due connections and wakes their automations (no thread started here). The items of one poll become one occurrence, with the items in `input_data.event.data.events` and, for a string prompt, in a fixed untrusted frame. A `network` pytest marker for the live test. See [`feed.item@1`](docs/automations.md#feeditem1).
|
|
97
|
+
|
|
98
|
+
- **CloudEvents trigger envelope** (framework backlog 1039): `TriggerEnvelope` carries the CloudEvents 1.0 attributes (`specversion`, `id`, `type` = `abstract.<source>.v<version>`, `source`, `time`, `subject`, `datacontenttype`) and extensions (`bindingid`, `connectionid`, `dedupekey`, `sequence`, `recordedtime`, `abstracttrust`; `correlationid`, `expirytime`, `traceparent` reserved) beside its original keys, which stay for this release. Every built-in source populates `subject`, `dedupekey` and `abstracttrust`; schedules add `payload.series = {rule, occurrence, scheduled_at, next_at, coalesced}`. Occurrences receive the envelope as `input_data.event` (`to_cloudevent`; `from_cloudevent` is the inverse; `CLOUDEVENT_JSON_SCHEMA`). The prompt header is unchanged. See [Occurrences](docs/automations.md#occurrences).
|
|
99
|
+
|
|
100
|
+
- **Run origin** (framework backlog 1038): `vars._meta.origin = {kind: person|trigger|agent|system, actor, client, ref}` records who or what started a run. `abstractruntime.core.run_origin.origin_for(...)` builds it for hosts (person and system runs), `stamp_origin` writes it once and `origin_of` reads it (None for older runs). Every automation occurrence now carries one from the controller: `trigger` with `ref {automation_id, occurrence_index, event_id, source}`, or `person` for a manual run now; the actor is the automation's owner (`_meta.automation_owner`, the `"<tenant>:<user>"` of the creation request). See [Run origin](docs/automations.md#run-origin).
|
|
101
|
+
|
|
102
|
+
- `wake_stream_consumers(runtime, stream)` / `stream_consumers(runtime, stream)` (`abstractruntime.email`, framework backlog 1042/1044): wake the automations that read ONE inbox stream, decided by their binding alone (`automation_reads_stream`): `trigger:<connection_id>` for a connection-bound binding, `email:<tenant>:<user>:<account_id>:<folder>` for an `email.received@1` binding of that mailbox (`config.account`; `self` or unset is the runtime's bound mailbox). `wake_email_automations(runtime, account_id=…)` and `email_trigger_consumers(runtime, account_id=…)` take an optional mailbox; `prune_email_inbox` also keeps the events a connection-bound automation has not read yet.
|
|
103
|
+
|
|
104
|
+
- `MailboxQueryableRunStore` (backlog 1046): `list_mailbox_runs(names=[…])` returns every running or waiting run
|
|
105
|
+
that declares one of the names as `events_mailbox`, and `next_wait_deadline()` the earliest wait deadline over
|
|
106
|
+
every waiting run. The in-memory, file (a lazily built mailbox index maintained on save and delete, every hit
|
|
107
|
+
re-verified on disk) and SQLite stores implement both; `OffloadingRunStore` forwards them. They let a host fan
|
|
108
|
+
durable events out and schedule wakes without a window of the newest runs.
|
|
109
|
+
|
|
110
|
+
- **Trigger connections** (framework backlog 1040): per-user instances of a trigger source, registered once and reused by any automation. `TriggerConnectionStore(plane_dir)` keeps one JSON file per connection (`<plane>/triggers/connections/<id>.json`, atomic writes), listed and changed per principal (`"<tenant>:<user>"`; another principal's connection reads like an unknown one), with secret fields and generated secrets sealed by AbstractCore's `SecretVault` (the mailbox credentials' sealing). Descriptors gain `needs_connection`, `connection_schema` and `connection_provider` (`schedule@1/2`, `manual@1`: none; `email.received@1`: a mailbox of the mail accounts). Each connection has one inbox stream `trigger:<connection_id>`; `test_fire` appends a synthetic `{data: {test: true}}` event to it and `wake_connection_automations` wakes the bound automations. `create_automation` and `automation.revise` refuse a binding whose `config.connection_id` is unknown, another principal's, of another source or disabled (`Runtime.set_trigger_connection_store`). `ConnectionEventAdapter` is the shared adapter of connection-bound sources (one coalesced admission per batch of stream events). See [Trigger connections](docs/automations.md#trigger-connections).
|
|
111
|
+
|
|
112
|
+
## [0.10.6] - 2026-10-18
|
|
113
|
+
|
|
114
|
+
### Added
|
|
115
|
+
|
|
116
|
+
- `abstractruntime.conversation_search.ConversationSearch`: keyword search over a plane's conversations: each turn's question and answer (as the session replay builds them) and its media, the artifacts it generated (kind and generation prompt, attributed to the turn whose run made them) and the attachments it was sent with (kind and file name); read-aloud audio and internal artifacts are not media. A hit on an artifact names it (`artifact`: id, owning run, kind, content type), so a client can show it. Its own SQLite file per plane, an FTS5 `trigram` index over text lowercased and without accents: words and parts of words, every word required, words of one or two letters as whole words, and a fuzzy pass that keeps a turn holding at least 60% of each word's trigrams (a typo still finds it). One hit per session (its best turn, a snippet, the match positions, where it matched: question, artifact or answer). Tool usage, tool outputs and intermediate thinking are not indexed: [backlog 0849](docs/backlog/proposed/0849_conversation_search_tool_usage_outputs_and_thinking.md). `sync(budget_s=…)` indexes what changed since the last call, newest sessions first, and reports what is left. Works with the file and the SQLite run stores; without the `trigram` tokenizer (SQLite < 3.34) it indexes whole words with prefixes.
|
|
117
|
+
|
|
118
|
+
- Automation definitions accept a named `policy.tool_policy` snapshot for per-tool Auto and Approve choices. The target tool ceiling remains authoritative; unspecified tools ask for approval. Messaging and untrusted-input restrictions remain enforced. See [Tool approval](docs/automations.md#tool-approval).
|
|
119
|
+
- Streamed read-aloud recordings (`_finalize_tts_stream_artifact`, the streamed-voice path of the AbstractCore integration) are stored under the voice namespace: their artifact tags carry `purpose=voice_playback`, `artifact_space=voice`, a `filename` and a logical `path` of `voice/tts-<id>.wav`, so a host can list a user's generated documents and attachments without the playback audio while playback and replay keep the same artifact ref and provenance. Test: `tests/test_streamed_voice_namespace.py`.
|
|
120
|
+
|
|
8
121
|
## [0.10.5] - 2026-10-18
|
|
9
122
|
|
|
10
123
|
### Changed
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: AbstractRuntime
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.12.0
|
|
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
|
|
@@ -20,8 +20,8 @@ Classifier: Programming Language :: Python :: 3.11
|
|
|
20
20
|
Classifier: Programming Language :: Python :: 3.12
|
|
21
21
|
Classifier: Programming Language :: Python :: 3.13
|
|
22
22
|
Requires-Python: >=3.10
|
|
23
|
-
Requires-Dist: abstractcore>=2.
|
|
24
|
-
Requires-Dist: abstractmemory>=0.3.
|
|
23
|
+
Requires-Dist: abstractcore>=2.30.0
|
|
24
|
+
Requires-Dist: abstractmemory>=0.3.2
|
|
25
25
|
Requires-Dist: abstractsemantics>=0.0.5
|
|
26
26
|
Requires-Dist: anyio<5.0.0,>=4.12.1
|
|
27
27
|
Requires-Dist: httpx<1.0.0,>=0.28.1
|
|
@@ -35,14 +35,14 @@ Requires-Dist: reportlab<5.0.0,>=4.0.0
|
|
|
35
35
|
Requires-Dist: restrictedpython>=7.0
|
|
36
36
|
Requires-Dist: unstructured[docx,odt,pptx,rtf,xlsx]<0.19.0,>=0.18.32
|
|
37
37
|
Provides-Extra: apple
|
|
38
|
-
Requires-Dist: abstractcore[apple]>=2.
|
|
38
|
+
Requires-Dist: abstractcore[apple]>=2.30.0; extra == 'apple'
|
|
39
39
|
Requires-Dist: setuptools<82.0.0,>=80.10.2; extra == 'apple'
|
|
40
40
|
Provides-Extra: docs
|
|
41
41
|
Requires-Dist: mkdocs-material>=9.0.0; extra == 'docs'
|
|
42
42
|
Requires-Dist: mkdocs>=1.6.0; extra == 'docs'
|
|
43
43
|
Requires-Dist: pymdown-extensions>=10.0; extra == 'docs'
|
|
44
44
|
Provides-Extra: gpu
|
|
45
|
-
Requires-Dist: abstractcore[gpu]>=2.
|
|
45
|
+
Requires-Dist: abstractcore[gpu]>=2.30.0; extra == 'gpu'
|
|
46
46
|
Requires-Dist: setuptools<82.0.0,>=77.0.3; extra == 'gpu'
|
|
47
47
|
Provides-Extra: test
|
|
48
48
|
Requires-Dist: aiosmtpd<2.0.0,>=1.4.4; extra == 'test'
|
|
@@ -83,7 +83,7 @@ Remote-light runtime:
|
|
|
83
83
|
pip install abstractruntime
|
|
84
84
|
```
|
|
85
85
|
|
|
86
|
-
The base install includes AbstractCore 2.
|
|
86
|
+
The base install includes AbstractCore 2.30.0 or newer (its light install:
|
|
87
87
|
remote providers, tools, vision, voice, audio, and music integration), plus the
|
|
88
88
|
`abstractruntime-mcp-worker` entry point. It keeps inference remote/light by
|
|
89
89
|
default: local engines such as MLX, vLLM, HuggingFace/Torch, Diffusers, and
|
|
@@ -159,13 +159,15 @@ Kernel (import-light):
|
|
|
159
159
|
- Stop that reaches the running effect: `Runtime.cancel_run(...)` signals the in-flight model or tool call, which ends as a `cancelled` ledger record (never retried); a model unload stops the calls using that model first (`docs/api.md`)
|
|
160
160
|
- host pause at step boundaries: `Runtime.tick(..., step_gate=...)`
|
|
161
161
|
- run-tree tool ceiling: an explicit `allowed_tools` list can only narrow across child runs, and approval policy never widens it
|
|
162
|
-
- automations: run a workflow on a schedule (`schedule@1` fixed UTC intervals; `schedule@2` adds daily, weekly and monthly rules at a wall time in an IANA time zone), when mail arrives (`email.received@1`, `docs/email.md`) or on request (`manual@1`) as a durable controller run whose occurrences are deterministic child runs and session turns, with commands, independent or growing context, discussions forked at any occurrence (own workspace, automation workspace mounted read-only), tool approval, typed waits and quiet-by-default notifications (`docs/automations.md`)
|
|
162
|
+
- automations: run a workflow on a schedule (`schedule@1` fixed UTC intervals; `schedule@2` adds daily, weekly and monthly rules at a wall time in an IANA time zone), when mail arrives in one of the user's mailboxes (`email.received@1`, `docs/email.md`), on new feed items (`feed.item@1`), on a signed webhook call (`webhook.received@1`) or on request (`manual@1`) as a durable controller run; per-user trigger connections (feed URLs, webhook endpoints with sealed signing secrets) reused by any automation; every occurrence receives its trigger as a CloudEvents 1.0 event (`input_data.event`) and records who or what started it (`_meta.origin`); runs can schedule work for later with `SCHEDULE_RUN` (a one-shot wake in the same session, at most the caller's tools, reminders that reach the person), whose occurrences are deterministic child runs and session turns, with commands, independent or growing context, discussions forked at any occurrence (own workspace, automation workspace mounted read-only), tool approval, typed waits and quiet-by-default notifications (`docs/automations.md`)
|
|
163
|
+
- flows that act and tell: mail verbs on the run's mailbox (`mail_search`, `mail_get`, `mail_mark`, `mail_label`, `mail_move`, `mail_delete`, `mail_send`, `mail_reply`, `mail_forward`, `mail_attachment`; changes and sends only on a mailbox the person keeps Read and write, `docs/email.md`) and Publish to channel (`PUBLISH_EVENT`: an event on the user's stream, optionally an alert with its `recipient` and `channels`, handed to the host through `Runtime.set_publish_event_handler`, `docs/automations.md`)
|
|
163
164
|
- explicit run ids: `Runtime.start(..., run_id=...)` creates a run only if the id is free (`RunStore.create_if_absent`), and `run_mutation_lock(run_id)` serializes a run's writers in a process
|
|
164
165
|
|
|
165
166
|
Durability + storage:
|
|
166
167
|
- stores: in-memory, JSON/JSONL, SQLite (`src/abstractruntime/storage/*`)
|
|
167
168
|
- durable command inbox primitives (idempotent, append-only): `CommandStore`, `CommandCursorStore` (`src/abstractruntime/storage/commands.py`, `src/abstractruntime/storage/sqlite.py`)
|
|
168
169
|
- artifacts + offloading (store large payloads by reference)
|
|
170
|
+
- large JSON run folders without scans: an in-memory active index and trusted run index (`trust_index`, `run_index_stats()`, background reconciliation), change tokens on the run store and the ledger (`change_token()`, `changed_run_ids()`), event-wait indexes that see another process's parked runs, and the active-consumers index for "who listens?" (`docs/architecture.md`, `docs/api.md`)
|
|
169
171
|
- snapshots/bookmarks (`docs/snapshots.md`)
|
|
170
172
|
- tamper-evident hash-chained ledger (`docs/provenance.md`)
|
|
171
173
|
|
|
@@ -239,8 +241,8 @@ sr = create_scheduled_runtime(
|
|
|
239
241
|
| [Architecture](docs/architecture.md) | Component map + diagrams |
|
|
240
242
|
| [Overview](docs/proposal.md) | Design goals, core concepts, and scope |
|
|
241
243
|
| [AbstractCore Integration](docs/integrations/abstractcore.md) | `LLM_CALL` / `TOOL_CALLS`, host facades, models/engines/host jobs |
|
|
242
|
-
| [Automations](docs/automations.md) | Scheduled and on-request workflows: controller, triggers, commands, context, discussions, storage guarantees |
|
|
243
|
-
| [Email](docs/email.md) | Email for each user: run-scoped account binding, sending without asking, the event inbox and mail feeder, the `email.received@1` trigger, the send-email action |
|
|
244
|
+
| [Automations](docs/automations.md) | Scheduled, event-driven and on-request workflows: controller, triggers (schedules, mail, feeds in RSS 2.0/RSS 1.0/Atom, webhooks), trigger connections, the CloudEvents envelope, run origin, wakes (`SCHEDULE_RUN`), Publish to channel (alerts with `recipient` and `channels`), commands, context, discussions, storage guarantees |
|
|
245
|
+
| [Email](docs/email.md) | Email for each user: run-scoped account binding, sending without asking, the event inbox and mail feeder, the `email.received@1` trigger on any of the user's mailboxes, mail verbs for flows (Read only / Read and write), the send-email action |
|
|
244
246
|
| [Artifacts](docs/artifacts.md) | Artifact identity, descriptors, catalog search and access stats |
|
|
245
247
|
| [Tool Approval](docs/tool-approval.md) | Tool risk tiers, run-policy ceiling, per-call refiners |
|
|
246
248
|
| [Comms Toolset](docs/tools-comms.md) | Opt-in email/WhatsApp/Telegram tools |
|
|
@@ -32,7 +32,7 @@ Remote-light runtime:
|
|
|
32
32
|
pip install abstractruntime
|
|
33
33
|
```
|
|
34
34
|
|
|
35
|
-
The base install includes AbstractCore 2.
|
|
35
|
+
The base install includes AbstractCore 2.30.0 or newer (its light install:
|
|
36
36
|
remote providers, tools, vision, voice, audio, and music integration), plus the
|
|
37
37
|
`abstractruntime-mcp-worker` entry point. It keeps inference remote/light by
|
|
38
38
|
default: local engines such as MLX, vLLM, HuggingFace/Torch, Diffusers, and
|
|
@@ -108,13 +108,15 @@ Kernel (import-light):
|
|
|
108
108
|
- Stop that reaches the running effect: `Runtime.cancel_run(...)` signals the in-flight model or tool call, which ends as a `cancelled` ledger record (never retried); a model unload stops the calls using that model first (`docs/api.md`)
|
|
109
109
|
- host pause at step boundaries: `Runtime.tick(..., step_gate=...)`
|
|
110
110
|
- run-tree tool ceiling: an explicit `allowed_tools` list can only narrow across child runs, and approval policy never widens it
|
|
111
|
-
- automations: run a workflow on a schedule (`schedule@1` fixed UTC intervals; `schedule@2` adds daily, weekly and monthly rules at a wall time in an IANA time zone), when mail arrives (`email.received@1`, `docs/email.md`) or on request (`manual@1`) as a durable controller run whose occurrences are deterministic child runs and session turns, with commands, independent or growing context, discussions forked at any occurrence (own workspace, automation workspace mounted read-only), tool approval, typed waits and quiet-by-default notifications (`docs/automations.md`)
|
|
111
|
+
- automations: run a workflow on a schedule (`schedule@1` fixed UTC intervals; `schedule@2` adds daily, weekly and monthly rules at a wall time in an IANA time zone), when mail arrives in one of the user's mailboxes (`email.received@1`, `docs/email.md`), on new feed items (`feed.item@1`), on a signed webhook call (`webhook.received@1`) or on request (`manual@1`) as a durable controller run; per-user trigger connections (feed URLs, webhook endpoints with sealed signing secrets) reused by any automation; every occurrence receives its trigger as a CloudEvents 1.0 event (`input_data.event`) and records who or what started it (`_meta.origin`); runs can schedule work for later with `SCHEDULE_RUN` (a one-shot wake in the same session, at most the caller's tools, reminders that reach the person), whose occurrences are deterministic child runs and session turns, with commands, independent or growing context, discussions forked at any occurrence (own workspace, automation workspace mounted read-only), tool approval, typed waits and quiet-by-default notifications (`docs/automations.md`)
|
|
112
|
+
- flows that act and tell: mail verbs on the run's mailbox (`mail_search`, `mail_get`, `mail_mark`, `mail_label`, `mail_move`, `mail_delete`, `mail_send`, `mail_reply`, `mail_forward`, `mail_attachment`; changes and sends only on a mailbox the person keeps Read and write, `docs/email.md`) and Publish to channel (`PUBLISH_EVENT`: an event on the user's stream, optionally an alert with its `recipient` and `channels`, handed to the host through `Runtime.set_publish_event_handler`, `docs/automations.md`)
|
|
112
113
|
- explicit run ids: `Runtime.start(..., run_id=...)` creates a run only if the id is free (`RunStore.create_if_absent`), and `run_mutation_lock(run_id)` serializes a run's writers in a process
|
|
113
114
|
|
|
114
115
|
Durability + storage:
|
|
115
116
|
- stores: in-memory, JSON/JSONL, SQLite (`src/abstractruntime/storage/*`)
|
|
116
117
|
- durable command inbox primitives (idempotent, append-only): `CommandStore`, `CommandCursorStore` (`src/abstractruntime/storage/commands.py`, `src/abstractruntime/storage/sqlite.py`)
|
|
117
118
|
- artifacts + offloading (store large payloads by reference)
|
|
119
|
+
- large JSON run folders without scans: an in-memory active index and trusted run index (`trust_index`, `run_index_stats()`, background reconciliation), change tokens on the run store and the ledger (`change_token()`, `changed_run_ids()`), event-wait indexes that see another process's parked runs, and the active-consumers index for "who listens?" (`docs/architecture.md`, `docs/api.md`)
|
|
118
120
|
- snapshots/bookmarks (`docs/snapshots.md`)
|
|
119
121
|
- tamper-evident hash-chained ledger (`docs/provenance.md`)
|
|
120
122
|
|
|
@@ -188,8 +190,8 @@ sr = create_scheduled_runtime(
|
|
|
188
190
|
| [Architecture](docs/architecture.md) | Component map + diagrams |
|
|
189
191
|
| [Overview](docs/proposal.md) | Design goals, core concepts, and scope |
|
|
190
192
|
| [AbstractCore Integration](docs/integrations/abstractcore.md) | `LLM_CALL` / `TOOL_CALLS`, host facades, models/engines/host jobs |
|
|
191
|
-
| [Automations](docs/automations.md) | Scheduled and on-request workflows: controller, triggers, commands, context, discussions, storage guarantees |
|
|
192
|
-
| [Email](docs/email.md) | Email for each user: run-scoped account binding, sending without asking, the event inbox and mail feeder, the `email.received@1` trigger, the send-email action |
|
|
193
|
+
| [Automations](docs/automations.md) | Scheduled, event-driven and on-request workflows: controller, triggers (schedules, mail, feeds in RSS 2.0/RSS 1.0/Atom, webhooks), trigger connections, the CloudEvents envelope, run origin, wakes (`SCHEDULE_RUN`), Publish to channel (alerts with `recipient` and `channels`), commands, context, discussions, storage guarantees |
|
|
194
|
+
| [Email](docs/email.md) | Email for each user: run-scoped account binding, sending without asking, the event inbox and mail feeder, the `email.received@1` trigger on any of the user's mailboxes, mail verbs for flows (Read only / Read and write), the send-email action |
|
|
193
195
|
| [Artifacts](docs/artifacts.md) | Artifact identity, descriptors, catalog search and access stats |
|
|
194
196
|
| [Tool Approval](docs/tool-approval.md) | Tool risk tiers, run-policy ceiling, per-call refiners |
|
|
195
197
|
| [Comms Toolset](docs/tools-comms.md) | Opt-in email/WhatsApp/Telegram tools |
|
|
@@ -17,8 +17,8 @@ In this repo, the AbstractCore wiring lives under `src/abstractruntime/integrati
|
|
|
17
17
|
- `../README.md` — install + quick start
|
|
18
18
|
- `getting-started.md` — first steps (recommended)
|
|
19
19
|
- `api.md` — public API surface (imports + pointers)
|
|
20
|
-
- `architecture.md` — how the runtime is structured (with diagrams)
|
|
21
|
-
- `troubleshooting.md` — symptom-oriented setup, runtime, and integration fixes
|
|
20
|
+
- `architecture.md` — how the runtime is structured (with diagrams), including how a JSON run store reads a large folder without scanning it (run index, change tokens, cross-process refresh)
|
|
21
|
+
- `troubleshooting.md` — symptom-oriented setup, runtime, and integration fixes (waits, automations, webhooks, mail steps, feeds, workspaces)
|
|
22
22
|
- `proposal.md` — design goals and scope boundaries
|
|
23
23
|
|
|
24
24
|
## Guides
|
|
@@ -28,15 +28,16 @@ In this repo, the AbstractCore wiring lives under `src/abstractruntime/integrati
|
|
|
28
28
|
- `artifacts.md` — Runtime artifact identity, descriptors, provenance, catalog search, and access stats
|
|
29
29
|
- `integrations/abstractcore.md` — wiring `LLM_CALL` / `TOOL_CALLS`, the `config_facade` models/engines/host-jobs passthroughs for hosts, the `structured_facade` response_format check for hosts, cached sessions with per-session prompt-cache listing/clearing, host memory snapshots, model-residency listings, locks and model switching, live token streaming, workspace-scoped tools, durable bloc prompt-cache control, media inputs, generated media outputs, video progress events, and tool approval waits via AbstractCore
|
|
30
30
|
- `tools-comms.md` — enabling the optional comms toolset (email/WhatsApp/Telegram)
|
|
31
|
-
- `email.md` — email for each user: run-scoped account binding and the host resolver, sending without asking (self and pre-authorised recipients), the durable event inbox and mail feeder, the `email.received@1` trigger, and the send-email action
|
|
31
|
+
- `email.md` — email for each user: run-scoped account binding and the host resolver, sending without asking (self and pre-authorised recipients), the durable event inbox and mail feeder, the `email.received@1` trigger on the primary or any other mailbox of the user, mail verbs for flows (changes and sends only on a Read and write mailbox: `email_mailbox_read_only`, `email_mailbox_cannot_send`), and the send-email action
|
|
32
32
|
- `tool-approval.md` — tool risk tiers, the run-policy rank ceiling, and per-call refiners (the `send_email` recipient rule: self and pre-authorised recipients)
|
|
33
33
|
- `api.md#workflowbundles-flow-and-visualflow-distribution` — VisualFlow compiler APIs, media nodes, and document nodes (`read_pdf` / `write_pdf` / `write_docx`)
|
|
34
34
|
- `api.md#sessions-and-history` — session history replay: one window, the most recent 50,000 tokens of whole turns (`HISTORY_REPLAY_MAX_TOKENS`), returned as a `ReplayedHistory` whose `.report` records what was replayed and dropped
|
|
35
|
+
- `api.md#conversation-search` — keyword search over a plane's conversations (`ConversationSearch`): questions, answers and the turn's artifacts, one SQLite FTS5 trigram index per plane, incremental `sync` with a time budget, exact then fuzzy matching
|
|
35
36
|
- `api.md#run-history-bundle-export-portable-replay-artifact` — run history bundles, including `resolved_actions` summaries for cross-client capability replay
|
|
36
37
|
|
|
37
38
|
## Features (reference)
|
|
38
39
|
|
|
39
|
-
- `automations.md` — automations: a workflow run on a schedule or on request as a durable controller run; triggers (`schedule@1`, `schedule@2` calendar rules in a time zone, `manual@1`, `email.received@1`, entry-point sources), commands, independent or growing context, discussions forked at any occurrence (own writable workspace, the automation's workspace mounted read-only), tool approval, typed waits, notifications and retries, and the storage guarantees (create-if-absent, per-run lock, turn roots, session kinds, one writer process per store)
|
|
40
|
+
- `automations.md` — automations: a workflow run on a schedule, on an event or on request as a durable controller run; triggers (`schedule@1`, `schedule@2` calendar rules in a time zone, `manual@1`, `email.received@1`, `feed.item@1` RSS 2.0 / RSS 1.0 / Atom, `webhook.received@1` Standard Webhooks, entry-point sources), per-user trigger connections, the CloudEvents envelope (`input_data.event`), run origin (`_meta.origin`), wakes (`SCHEDULE_RUN`: work later in the same session, with at most the caller's tools), Publish to channel (`PUBLISH_EVENT`, alerts with `recipient` and `channels`), commands, independent or growing context, discussions forked at any occurrence (own writable workspace, the automation's workspace mounted read-only), tool approval, typed waits, notifications and retries, and the storage guarantees (create-if-absent, per-run lock, turn roots, session kinds, one writer process per store)
|
|
40
41
|
- `entity-runtime.md` — per-entity runtimes for summoned entities: homes, the one-writer lease, act-only diary privacy (`$act_only` refs), durable visit waits with deadlines
|
|
41
42
|
- `evidence.md` — artifact-backed evidence capture for external-boundary tools
|
|
42
43
|
- `mcp-worker.md` — MCP worker CLI (`abstractruntime-mcp-worker`)
|
|
@@ -80,6 +80,7 @@ Implementation: `src/abstractruntime/core/runtime.py`.
|
|
|
80
80
|
- persists `CANCELLED`, then signals every effect of that run (and its in-flight descendants) executing in this process; the running attempt is recorded as `cancelled` (`StepStatus.CANCELLED`, never retried) with `cancelled_by` and `reason`, and no further effect starts
|
|
81
81
|
- `Runtime.set_default_provider_model(provider=..., model=...)`
|
|
82
82
|
- re-points the default provider/model seeded into new runs; pair it with the pooled client's `set_default_provider_model(...)` so both agree
|
|
83
|
+
- `Runtime.set_event_inbox(inbox)`, `Runtime.set_trigger_connection_store(store)` and `Runtime.set_schedule_run_handler(handler)`: the host seams of event-triggered automations, trigger connections and wakes (see [automations.md](automations.md#triggers) and [automations.md](automations.md#wakes-schedule_run))
|
|
83
84
|
- `Runtime.set_live_delta_sink(sink)` where `sink(event: dict) -> None`, or `None` to remove it
|
|
84
85
|
- receives live token deltas (`llm.delta`, `llm.delta_end`) for LLM calls of runs started with `_runtime.stream: true` (a boolean; `start` refuses any other value); nothing is written to the ledger. See [Live token streaming](integrations/abstractcore.md#live-token-streaming)
|
|
85
86
|
|
|
@@ -124,9 +125,13 @@ Run index and creation (all built-in run stores, including the offloading wrappe
|
|
|
124
125
|
- `create_if_absent(run) -> (run, created)`: creates a run only if its id is free and never overwrites an existing one; `store_supports_create_if_absent(store)` / `require_create_if_absent(store)` check a store first. Process-crash safe; power-loss durability is not claimed
|
|
125
126
|
- `list_run_index(status=, workflow_id=, session_id=, root_only=, limit=, oldest_first=, automation_id=, role=, session_kind=)`: lightweight rows carrying `automation_id`, `role`, `occurrence_index`, `session_kind` and `workspace_root` (the run's top-level `vars["workspace_root"]` as stored, stripped; `None` when absent); the three attribution filters take a value, a comma-separated string or a list; `root_only=True` returns turn roots (parent-less runs except automation controllers, plus automation occurrences)
|
|
126
127
|
- `session_kinds(session_id) -> frozenset` and `latest_occurrence_row(automation_id)`: indexed lookups used by session attribution and automation listings
|
|
128
|
+
- `MailboxQueryableRunStore` (in-memory, file, SQLite and offloading stores): `list_mailbox_runs(names=[...], limit=10_000)` returns every running or waiting run whose `events_mailbox` names one of the names (newest first; the file store keeps a mailbox index maintained on save and delete and re-verifies each hit on disk), and `next_wait_deadline()` the earliest wait deadline over all waiting runs (`WAIT_UNTIL`, or `WAIT_EVENT` with a deadline), or `None`. Hosts use them to fan durable events out and to schedule wakes without reading a window of the newest runs
|
|
127
129
|
- `JsonFileRunStore.warm_session_index()` builds the session and children indexes at host startup. Store objects and processes sharing one JSON run folder see each other's created and deleted runs through the creation journal `.runs_created.log`; v1 supports one writer process per store
|
|
128
130
|
- `JsonFileRunStore` answers `list_runs` / `list_run_index` for `status=running` or `status=waiting` (without `session_id`) from an in-memory **active index**: the set of active run ids, built from one directory scan (at host boot through `warm_session_index()`, else on the first such listing) and kept current by `save`, `create_if_absent`, `delete` and the creation journal. Every candidate is re-verified against its file at listing time, so a run that ended or vanished is never listed. Rows, order (file mtime, then file name, then the final `updated_at` sort), filters and limits are the same as the directory scan's; a listing of a 10,000-run store costs milliseconds instead of a full scan. `JsonFileRunStore(..., use_active_index=False)` keeps the plain scan. `rescan_active_index()` reconciles the index with the directory in the caller's thread; a background rescan runs at most every `JsonFileRunStore.ACTIVE_INDEX_RESCAN_S` (60 s) to pick up writers that bypass the store. `list_due_wait_until` (the scheduler's due-wait poll) takes its candidates from the index too. Other listings (a terminal status, no status, a session scope) scan as before.
|
|
129
|
-
-
|
|
131
|
+
- **Trusted run index** (`JsonFileRunStore(..., trust_index=True)`, the default): every listing the active index does not answer (no status or a finished status, no `session_id`: `list_run_index`, `list_runs`, `latest_occurrence_row`) is answered from memory once one complete pass (the active-index build, at host boot through `warm_session_index()`) has read every run file: ranked by file mtime then file name, same filters, rows and limits as the directory scan, with no glob and no stat of a run file (11,500 files: about 1-20 ms instead of a 0.25 s scan that waits for the interpreter lock under contention). It is kept current by the store's own saves, creates and deletes, the creation journal (including `=<run_id>`), and a re-read of its RUNNING/WAITING entries when the folder's mtime moved (another process ticking a run writes no journal line). A background **reconciliation** (the active-index rescan, a daemon thread, never on a caller's path) re-reads the folder at most every `ACTIVE_INDEX_RESCAN_S` (60 s) when the folder or the journal moved, and at least every `RUN_INDEX_FULL_RECONCILE_S` (600 s); a difference it finds (a writer that bypassed the journal) is repaired and logged as a warning. The risk is a stale row until then, never a lost run: `load()` reads disk. `trust_index=False` (**verify**, the shadow mode) answers every such listing with the directory scan, as before, and compares it with the in-memory answer. `run_index_stats()` (forwarded by `OffloadingRunStore`) returns `mode`, `complete`, `entries`, `active_entries`, `trusted_listings`, `scanned_listings`, `shadow_compared`, `shadow_mismatches` (verify mode: stable comparisons whose answers differed; 0 means the index would have answered every listing the same), `shadow_unstable` (a write overlapped the comparison: no verdict), `last_mismatch`, `reconciles`, `reconcile_repairs` and `last_reconcile`; each mismatch and each repair is also logged as a `JsonFileRunStore:` warning. `reconcile_run_index()` runs the reconciliation in the caller's thread. Needs the active index (`use_active_index=False` is the plain scan, without shadow).
|
|
132
|
+
- The creation journal (`.runs_created.log` in the run folder) carries one line per change another store object or process must learn about: `+<run_id>` created, `-<run_id>` deleted, `~<run_id>` became active again (resumed, re-opened, first save after a restart, or saved after another writer touched the file). Lines are written before the file change they announce; readers apply the lines they have not seen at their next lookup, and a line whose file has not landed yet (or does not read active yet) is re-checked until it does. Readers from AbstractRuntime 0.10.0 ignore `~` lines, and writers from 0.10.0 never write them: a re-open made by such a writer reaches other store objects through the periodic rescan. `=<run_id>`: a run that is not active changed its file (it finished, or a finished run was re-saved), written AFTER the file is published; older readers ignore it, and a change made by an older writer reaches the trusted run index through the reconciliation.
|
|
133
|
+
- `JsonFileRunStore` event-wait and mailbox indexes (`list_event_waiters`, `list_event_waiters_by_prefix`, `list_mailbox_runs`) see what another process saved on the same folder (a split gateway: API process + runner process). Before each lookup the store reads its change signal (the creation log's size and the folder's mtime): when either moved, or at least every `EVENT_INDEX_REFRESH_S` (2 s), it stats each running or waiting run and re-reads the ones whose file changed since it last filed them. An idle store pays two stats per lookup; its own saves are never re-read. `event_index_stats()` returns `{refreshes, refiled, tracked}`.
|
|
134
|
+
- `JsonFileRunStore.change_token()` answers "did any run of this folder change?" with one stat: `(creation-log size, active-index counter)`. Every save, create and delete through the store moves the counter; another process's create, delete or became-active line moves the log size. Not seen: another process re-saving a run that stays active (one ticking process per folder); ending a run, or re-saving a finished one, writes `=<run_id>`. `changed_run_ids(token)` names the runs this store changed since `token`, or `None` when that is unknown (the log moved, or more than 8,192 changes ago). `ObservableLedgerStore.change_token()` / `changed_run_ids(token)` do the same for ledger appends (process-local). The gateway runner's scan gate and its mail notification check compare these tokens instead of reading the directory.
|
|
130
135
|
|
|
131
136
|
Common decorators:
|
|
132
137
|
- `ObservableLedgerStore` for subscriptions (`src/abstractruntime/storage/observable.py`)
|
|
@@ -240,10 +245,19 @@ from abstractruntime.triggers import get_trigger_adapter, trigger_sources
|
|
|
240
245
|
- `create_automation(runtime, request, *, now=None, actor_id=None)`: creates the controller root run (the automation) with a deterministic id; raises `AutomationError` (`invalid_definition`, `unsupported_feature`, `unknown_trigger_source`, `identity_conflict`)
|
|
241
246
|
- `apply_automation_command(runtime, *, automation_id, command_id, type, payload=None, actor=None, expected_revision=None)`: the only writer of automation state; returns `{status: "applied" | "rejected", error?, duplicate}`; idempotent per `command_id`
|
|
242
247
|
- `record_automation_command_result(...)`: records a host-side failure of a command as a rejected result
|
|
243
|
-
- reads: `get_automation(run_store, id)`, `list_occurrences(runtime, id, cursor=, limit=)`, `list_attention(ledger_store, id, after_seq=, cursor=, limit=)`, `pending_waits(run_store, id, limit=)` with typed waits (`ask_user`, `tool_approval`, `event`) and `ANSWER_PAYLOADS`; `list_automations(run_store, status=, cursor=, limit=)`, `automation_summary(run)`, `latest_occurrence(run_store, id)`
|
|
248
|
+
- reads: `get_automation(run_store, id)`, `list_occurrences(runtime, id, cursor=, limit=)`, `list_attention(ledger_store, id, after_seq=, cursor=, limit=)`, `pending_waits(run_store, id, limit=)` with typed waits (`ask_user`, `tool_approval`, `event`) and `ANSWER_PAYLOADS`; `list_automations(run_store, status=, cursor=, limit=, index_rows=)`, `automation_summary(run)`, `latest_occurrence(run_store, id)` (the index row); from `abstractruntime.automations`: `latest_occurrence(runtime, id, user_turn=)` (the newest occurrence row, read from the ledger's end), `pending_waits_by_automation(run_store, limit=)` (one read for a whole listing), `automation_generation(runtime_or_store)` (the change counter a host keys its cached listings on) and the active-consumers index (`active_consumers_index`, `invalidate_active_consumers`; see `automations.md#trigger-connections`)
|
|
244
249
|
- `start_discussion(runtime, *, automation_id, occurrence_index, request_id, prompt, workspace_root, actor_id=None)`: a separate conversation forked at any occurrence N, seeded with the automation's whole timeline 1..N, working in its own writable `workspace_root` with the automation's workspace mounted read-only
|
|
245
250
|
- controller bundle: `register_controller_bundle(registry)`, `controller_workflow_spec()`, `controller_bundle_path()`; `CONTROLLER_WORKFLOW_ID` is `abstractframework.automation-controller@1.0.0:controller`
|
|
246
|
-
- trigger sources: `trigger_sources()`, `get_trigger_adapter(id, version)`, built-ins `schedule@1`, `schedule@2` (daily/weekly/monthly rules in an IANA time zone; `validate_time_zone`, `time_zone_names`), `manual@1` and `
|
|
251
|
+
- trigger sources: `trigger_sources()`, `get_trigger_adapter(id, version)`, built-ins `schedule@1`, `schedule@2` (daily/weekly/monthly rules in an IANA time zone; `validate_time_zone`, `time_zone_names`), `manual@1`, `email.received@1`, `feed.item@1` and `webhook.received@1`, third-party sources through the `abstractruntime.trigger_sources` entry-point group
|
|
252
|
+
- trigger connections (`abstractruntime.triggers.connections`): `TriggerConnectionStore(plane_dir, *, sealing_key_file=None)` (per-principal CRUD, sealed secrets), `connection_principal(tenant, user)`, `connection_stream(id)` (`trigger:<id>`), `append_connection_event(...)`, `test_fire(store, inbox, id, principal=)`, `validate_binding_connection(principal, binding, store)`, `wake_connection_automations(runtime, id)`, `Runtime.set_trigger_connection_store(store)`; `create_automation(..., principal=)` and `apply_automation_command(..., principal=)` check a binding's `config.connection_id`
|
|
253
|
+
- run origin (`abstractruntime.core.run_origin`): `origin_for(kind, *, actor=, client=, automation_id=, occurrence_index=, event_id=, source=, origin_run_id=, session_id=, bridge=)` builds `_meta.origin` (`person | trigger | agent | system`), `stamp_origin(vars, origin)`, `origin_of(vars)`; occurrences carry it from the controller
|
|
254
|
+
- CloudEvents envelope (`abstractruntime.triggers.cloudevents`): `to_cloudevent(envelope)`, `from_cloudevent(event)`, `with_cloudevent_attributes(...)`, `event_type(source_id, version)`, `CLOUDEVENT_JSON_SCHEMA`; occurrences receive `input_data.event`
|
|
255
|
+
- feed source `feed.item@1` (`abstractruntime.triggers.feed`): `parse_feed(bytes)`, `FeedPoller(store, inbox, fetch=)`, `poll_feed_connections(runtime, store, fetch=None, now=None)` (the host's poll step), `urllib_fetch` (conditional GET)
|
|
256
|
+
- webhook source `webhook.received@1` (`abstractruntime.triggers.webhook`): `verify_standard_webhook(secret, headers, body, now, tolerance_s=300)`, `append_webhook_event(inbox, connection, body, headers, *, secret=None, store=None, now=None)`, `sign_standard_webhook(...)`, `new_webhook_secret()`, `webhook_event_data(...)`
|
|
257
|
+
- wakes (`abstractruntime.automations.wakes`): `EffectType.SCHEDULE_RUN`, `Runtime.set_schedule_run_handler(handler)` (`handler(run, plan) -> {automation_id}`), `plan_schedule_run(run, payload, *, now, run_store=None, request_id=None)`, `create_scheduled_run(runtime, plan, *, target, tenant, user, workspace_root, notify=None)`, `wake_scheduled_event`, `wake_cancelled_event`; creation requests accept `session_id` (growing only), `origin_run_id`, `one_shot`, `untrusted_origin`
|
|
258
|
+
- sample inputs (`abstractruntime.automations.samples`): `sample_occurrence_inputs(runtime, source_id, source_version, config, *, count=100, principal=None, email_context=None, fetch=None)` -> `{inputs, resolve_vars, truncated, source, count}` (the named inputs + `event` with `abstracttest: true`, from real data, read only), `resolved_sample_inputs(sample, artifact_store=)`, `SampleError`
|
|
259
|
+
- mail verbs for flows (`abstractruntime.mail_verbs`): fixed verbs `mail.search`, `mail.get`, `mail.mark`, `mail.label`, `mail.move`, `mail.delete`, `mail.send`, `mail.reply`, `mail.forward`, `mail.attachment` run by the `TOOL_INVOKE` handler (node types `mail_*`); `run_mail_verb(run, name, arguments)`, `mail_verb_outcome(...)`, `MailVerbError`; the Email record `triggers.email_received.email_record(message, mailbox=)`, `email_id`, `parse_email_id`, `thread_id_of`. See [email.md](email.md#mail-verbs-for-flows)
|
|
260
|
+
- publish to channel (`abstractruntime.core.publish`): `EffectType.PUBLISH_EVENT` (node type `publish_event`), payload `{channel, type?, title, body?, subject?, data?, alert?, recipient? = "me", channels? (tray|watch|phone|email|console; absent = all)}`, `validate_publish(payload)`, `normalize_channels(value)`, `strip_visual_envelope(payload)`, `DELIVERY_CHANNELS`, `Runtime.set_publish_event_handler(handler)` with `handler(run, payload, step_id) -> {event_id, sequence, alerted}`. See [automations.md](automations.md#publish-to-channel)
|
|
247
261
|
- definition v2: `policy.email_allowed_recipients` (default `["self"]`), `policy.untrusted_input_tools` (default `[]`) and `notify.channels` (default `["console"]`); attention items carry `channels`
|
|
248
262
|
|
|
249
263
|
## Email
|
|
@@ -291,6 +305,16 @@ Implementation: `src/abstractruntime/session_turns.py`, `src/abstractruntime/ses
|
|
|
291
305
|
|
|
292
306
|
History bundles (`export_run_history_bundle`) and session replay use the same turn selection, so automation occurrences appear as turns (kind `occurrence`, with `automation_id` and `occurrence_index`) in both.
|
|
293
307
|
|
|
308
|
+
## Conversation search
|
|
309
|
+
|
|
310
|
+
Implementation: `src/abstractruntime/conversation_search.py`.
|
|
311
|
+
|
|
312
|
+
- `ConversationSearch(db_path, *, run_store, ledger_store, artifact_store=None, kinds=None)`: the keyword search index of one runtime plane. `db_path` is its own SQLite file in that plane's data folder (one index per plane, so a principal's search can only ever read the plane it was opened on; the file is disposable and is rebuilt when the schema changes). Each turn root (a question and its answer, as the session replay builds them) is one row, together with the turn's media: the artifacts its run generated (image, voice, video, music, by their generation prompt) and the attachments it was sent with (by their file name), each with its kind. Read-aloud audio, media saved without a prompt and internal artifacts are not indexed. `kinds` defaults to `INDEXED_KINDS` (`chat`, `discussion`): automation sessions are not indexed
|
|
313
|
+
- `sync(*, budget_s=3.0) -> SyncReport`: indexes what changed since the last call (turn roots whose `updated_at` moved, re-read by session, newest sessions first) within the time budget. `SyncReport`: `{indexed_turns, reindexed_sessions, pending_sessions, total_turns, seconds, complete, errors}`; `complete` is `False` while older conversations are still waiting, so a first search on a large plane can say it is still indexing
|
|
314
|
+
- `search(query, *, limit=20, sessions=None, exclude=None, session_kinds=None) -> list[SearchHit]`: one hit per session, best first. Text is indexed and queried lowercased and without accents (`normalize`) with the FTS5 `trigram` tokenizer: every query word of three or more characters must appear in the turn, as a word or part of one ("surviv" finds "overall survival"); words of one or two characters are matched as whole words; ranked by bm25, the question weighing more than the answer. When exact matches are fewer than `limit`, a fuzzy pass keeps turns holding at least `FUZZY_MIN` (60%) of each word's trigrams, so a typo still finds its turn (`fuzzy: true` on those hits). `sessions`, `exclude` and `session_kinds` filter inside the query, so a filter never empties a page that had matches further down. `limit` is clamped to 1–100
|
|
315
|
+
- `SearchHit` (`as_dict()`): `session_id`, `run_id` (the best turn), `prompt`, `snippet` (around the first match), `matched_in` (`question`, `answer` or `artifact`), `highlights` (`[start, length]` pairs in the snippet), `score`, `created_at`, `updated_at`, `session_kind`, `fuzzy`, and `artifact` when the match is an artifact: `{artifact_id, run_id, kind, content_type, name, prompt}`, `run_id` being the run that owns it (a host's artifact content route is scoped to that run)
|
|
316
|
+
- Without the `trigram` tokenizer (SQLite before 3.34) the index falls back to whole words with prefix matching. Tool usage, tool outputs and intermediate thinking are not indexed: [backlog 0849](backlog/proposed/0849_conversation_search_tool_usage_outputs_and_thinking.md)
|
|
317
|
+
|
|
294
318
|
## Run history bundle export (portable replay artifact)
|
|
295
319
|
|
|
296
320
|
Implementation: `src/abstractruntime/history_bundle.py`.
|
|
@@ -306,7 +330,7 @@ from Core route resolution and persisted from `LLM_CALL` results.
|
|
|
306
330
|
|
|
307
331
|
### AbstractCore (LLM + tools)
|
|
308
332
|
|
|
309
|
-
Requires: `pip install abstractruntime` (AbstractCore 2.
|
|
333
|
+
Requires: `pip install abstractruntime` (AbstractCore 2.30.0 or newer is part of the base install).
|
|
310
334
|
|
|
311
335
|
Implementation: `src/abstractruntime/integrations/abstractcore/*`.
|
|
312
336
|
|
|
@@ -322,6 +346,7 @@ Entry points:
|
|
|
322
346
|
- discovery-facade delegation is implemented by the configured AbstractCore LLM clients in `src/abstractruntime/integrations/abstractcore/llm_client.py` (`list_providers`, `list_provider_models`, `get_voice_catalog`, `list_tts_models`, `list_stt_models`, `list_music_providers`, `list_music_models`, `list_vision_provider_models`, `list_cached_vision_models`, `list_vision_adapters`)
|
|
323
347
|
- the host's OpenAI credential for AbstractVoice's `openai` engines, `voice_openai_api_key`, travels two ways. For discovery, pass it to `get_voice_catalog`, `list_tts_models` or `list_stt_models`; the local clients hand it to the voice plugin's config, and a remote client never sends it (a remote AbstractCore server uses its own voice configuration). For execution, put it in `create_local_runtime(llm_kwargs={"voice_openai_api_key": ...})`. Constructor kwargs become the provider's `config`, which is also the capability-plugin config. Providers read only the keys they name, so a `voice_*` key changes no text request (tests `tests/test_voice_openai_api_key_path.py`)
|
|
324
348
|
- host-facade client delegation is implemented by the configured AbstractCore LLM clients in `src/abstractruntime/integrations/abstractcore/llm_client.py` (`get_prompt_cache_capabilities`, `get_prompt_cache_stats`, `prompt_cache_set`, `prompt_cache_update`, `prompt_cache_fork`, `prompt_cache_clear`, `prompt_cache_prepare_modules`, `upsert_text_bloc`, `get_bloc_record`, `list_blocs`, `get_bloc_kv_manifest`, `ensure_bloc_kv_artifact`, `load_bloc_kv_artifact`, `list_bloc_kv_artifacts`, `delete_bloc_kv_artifact`, `prune_bloc_kv_artifacts`, `delete_bloc`, `get_model_residency_capabilities`, `list_model_residency`, `load_model_residency`, `unload_model_residency`, `get_memory_snapshot`, `list_session_prompt_caches`, `clear_session_prompt_caches`, `lock_model_residency`, `unlock_model_residency`, `get_context_estimate`); the last six are optional in the client contract, and the facade returns `{"ok": false, "supported": false, ...}` when the configured client does not implement one
|
|
349
|
+
- `integrations.abstractcore.llm_client.set_default_model_warmup(enabled)` (process-wide, no environment variable): whether a new `MultiLocalAbstractCoreLLMClient` builds (for a local model: loads) its default model at construction and on a default switch. Default on. A process that serves no model turns it off once at boot (the gateway's `serve --no-runner`); the default client is then built at its first call. `default_model_warmup()` reads the setting (see `integrations/abstractcore.md#unloading-and-switching-models`)
|
|
325
350
|
- switching the default model (`set_default_provider_model` on the pooled client) unloads the previous in-process model unless an owner in the process still uses it; `list_model_residency` diagnostics report `pending_ejects` and `last_switch_ejects`, and `unload_model_residency(runtime_id=...)` accepts any listed `local:<task>:<provider>:<model>` id, including `local:embedding:<provider>:<model>` rows (see `integrations/abstractcore.md#unloading-and-switching-models`)
|
|
326
351
|
- `lock_model_residency`, `unlock_model_residency`, and `get_context_estimate` accept an optional payload mapping and/or keyword arguments (keyword arguments win on conflicts); a lock requires provider-verified residency — locking a non-resident pair refuses with a structured `model_not_resident` payload (load with `lock: true` instead; remotely the Core server's HTTP 409 refusal is converted to the same payload), while unlock never requires residency so a locked-but-evicted pair is always releasable; a locked model refuses `unload_model_residency` with a structured `model_locked` payload — locally as a client-side per-`(provider, model)` lock, remotely by converting the Core server's HTTP 409 refusal — and unloads only with `force=true`, releasing the lock only after the unload succeeds
|
|
327
352
|
- the `MODEL_RESIDENCY` effect supports `list_loaded`, `load`, `unload`, `lock`, and `unlock` operations with the same soft-fail semantics; on `unload`, `force` is forwarded only when authored in the effect payload
|
|
@@ -352,6 +377,7 @@ Multimodal support:
|
|
|
352
377
|
- remote and hybrid clients support AbstractCore Server chat media content arrays plus image generation, image edits, image upscaling, text-to-video, image-to-video, speech, music generation, and transcription endpoints; pass an output-specific `model` for remote media provider routing, otherwise the server endpoint can use its configured capability default
|
|
353
378
|
- remote transcription requires one audio media item that resolves to a local file path or artifact-backed temporary file
|
|
354
379
|
- generated image/video/voice/music/audio bytes require a runtime `ArtifactStore`; the result contains `artifact_id` / `artifact_ref` instead of inline bytes
|
|
380
|
+
- streamed TTS playback artifacts carry `purpose=voice_playback`, `artifact_space=voice` and a logical `voice/tts-<id>.wav` path in their tags; hosts can separate read-aloud recordings from user attachments while retaining their artifact refs and provenance
|
|
355
381
|
- with the pooled local client (`MultiLocalAbstractCoreLLMClient`), a request whose outputs are all non-text (image, video, voice, music, transcription) and that carries no tools never builds the text client: it runs on AbstractCore's capability host (`CapabilityHostProvider`, no text model), and so does streaming TTS. A text default that cannot be built (an engine not installed) therefore never blocks speech or image generation
|
|
356
382
|
- media-only normalized results expose `runtime_provider` / `runtime_model` separately from `media_provider` / `media_model`
|
|
357
383
|
- local image/video generation runs in a one-shot subprocess (`execution_mode="local_one_shot_subprocess"`) unless every requested media model is resident (explicitly loaded with `load_model_residency`), in which case it runs in-process on the loaded pipeline (`execution_mode="resident_in_process"`, `resident_load_ids`)
|
|
@@ -286,6 +286,10 @@ Registered in `Runtime._register_builtin_handlers()` (`src/abstractruntime/core/
|
|
|
286
286
|
|
|
287
287
|
### Host-wired effects
|
|
288
288
|
The kernel defines the protocol; concrete integrations provide handlers:
|
|
289
|
+
- `PUBLISH_EVENT` ("Publish to channel"): the kernel validates the payload; the host's
|
|
290
|
+
`Runtime.set_publish_event_handler(...)` appends the event to the user's stream (see
|
|
291
|
+
[automations.md](automations.md#publish-to-channel))
|
|
292
|
+
- `SCHEDULE_RUN`: the kernel validates the request and plans a one-shot automation (tools at most the caller's ceiling, never `schedule_run` itself); the host's `Runtime.set_schedule_run_handler(...)` creates it, because only the host knows the target workflow, the owner and the workspace (see [automations.md](automations.md#wakes-schedule_run))
|
|
289
293
|
- `LLM_CALL`, `TOOL_CALLS`, `MODEL_RESIDENCY`: provided by AbstractCore integration (`src/abstractruntime/integrations/abstractcore/effect_handlers.py`). The integration supports local/remote/hybrid execution, cached sessions/prompt-cache control with per-session attribution and clearing, host memory snapshots, discovery/catalog snapshots, model residency including host-wide provider-server rows in listings, residency locks with `force`-gated unload and context-estimate relays, durable run-scoped media child runs, media inputs, generated media outputs, provider progress callbacks as ledger events, provider-key header routing for remote servers, passthrough tools, approval-gated local tool execution, and workspace-scoped file and shell tools (run vars `workspace_*`, inherited by child runs; the host's built-in deny prefixes are enforced without being rendered into the model's prompt).
|
|
290
294
|
- `MEMORY_KG_*`: provided by the AbstractMemory bridge (`src/abstractruntime/integrations/abstractmemory/effect_handlers.py`)
|
|
291
295
|
|
|
@@ -307,8 +311,66 @@ Decorators/helpers:
|
|
|
307
311
|
- `HashChainedLedgerStore` for tamper-evidence (`src/abstractruntime/storage/ledger_chain.py`)
|
|
308
312
|
- `ArtifactStore` + helpers (`src/abstractruntime/storage/artifacts.py`)
|
|
309
313
|
- `OffloadingRunStore` / `OffloadingLedgerStore` to keep checkpoints bounded (`src/abstractruntime/storage/offloading.py`)
|
|
314
|
+
- `MailboxQueryableRunStore` (`list_mailbox_runs`, `next_wait_deadline`) on every built-in run store, for event fan-out and wake scheduling without a recency window
|
|
310
315
|
- snapshots/bookmarks (`src/abstractruntime/storage/snapshots.py`)
|
|
311
316
|
|
|
317
|
+
### Reading a large run folder without scanning it
|
|
318
|
+
|
|
319
|
+
A JSON run folder can hold tens of thousands of run files. `JsonFileRunStore` keeps in memory what
|
|
320
|
+
listings and lookups need, so a host polling it never globs or stats every file:
|
|
321
|
+
|
|
322
|
+
```mermaid
|
|
323
|
+
flowchart LR
|
|
324
|
+
subgraph Writers["Writers on one run folder"]
|
|
325
|
+
Own["This store object<br/>(save / create / delete)"]
|
|
326
|
+
Other["Another process<br/>(a split host's other half)"]
|
|
327
|
+
end
|
|
328
|
+
Folder[("Run files<br/><run_id>.json")]
|
|
329
|
+
Log[(".runs_created.log<br/>+ - ~ = lines")]
|
|
330
|
+
subgraph Store["JsonFileRunStore (in memory)"]
|
|
331
|
+
Active["Active index<br/>RUNNING / WAITING"]
|
|
332
|
+
Trusted["Trusted run index<br/>every run's listing fields"]
|
|
333
|
+
Waits["Event-wait and<br/>mailbox indexes"]
|
|
334
|
+
Token["change_token()<br/>(log size, counter)"]
|
|
335
|
+
end
|
|
336
|
+
Recon["Reconciliation<br/>(background, ≤ 60 s when moved, ≥ every 10 min)"]
|
|
337
|
+
Own --> Folder
|
|
338
|
+
Own --> Log
|
|
339
|
+
Own --> Active
|
|
340
|
+
Own --> Trusted
|
|
341
|
+
Own --> Token
|
|
342
|
+
Other --> Folder
|
|
343
|
+
Other --> Log
|
|
344
|
+
Log -->|"next lookup"| Active
|
|
345
|
+
Log -->|"next lookup"| Trusted
|
|
346
|
+
Log -->|"size moved, or every 2 s"| Waits
|
|
347
|
+
Folder -.->|"mtime moved"| Waits
|
|
348
|
+
Folder -.->|"mtime moved: re-read RUNNING / WAITING entries"| Trusted
|
|
349
|
+
Recon -->|repairs, logs a warning| Trusted
|
|
350
|
+
Folder -.-> Recon
|
|
351
|
+
```
|
|
352
|
+
|
|
353
|
+
- **Active index**: `list_runs` / `list_run_index` for RUNNING or WAITING and the scheduler's due-wait
|
|
354
|
+
poll, re-verified against each file at listing time.
|
|
355
|
+
- **Trusted run index** (`trust_index=True`, the default): every other listing without a session
|
|
356
|
+
scope is answered from memory; `trust_index=False` (verify) answers with the scan and counts
|
|
357
|
+
differences (`run_index_stats()`). The background reconciliation repairs what a writer that
|
|
358
|
+
bypassed the creation journal left out; `load()` always reads disk.
|
|
359
|
+
- **Event-wait and mailbox indexes** see runs another process parked (refreshed before each
|
|
360
|
+
lookup when the journal or the folder moved, at least every 2 s).
|
|
361
|
+
- **Change tokens**: `JsonFileRunStore.change_token()` and `ObservableLedgerStore.change_token()`
|
|
362
|
+
(with `changed_run_ids(token)`) let a periodic reader skip a pass when nothing changed and read
|
|
363
|
+
only what did.
|
|
364
|
+
- **Active-consumers index** (`abstractruntime.automations.consumers`): one snapshot per runtime of
|
|
365
|
+
which ACTIVE automation reads which trigger, rebuilt on the store's automation generation, so
|
|
366
|
+
"who listens to this connection or mailbox?" reads no run file.
|
|
367
|
+
- **Artifacts**: `ArtifactStore.list_session_candidates(session_id, owner_run_id=)` answers a
|
|
368
|
+
session's artifacts through catalog indexes instead of reading the catalog.
|
|
369
|
+
|
|
370
|
+
Details and the exact counters: [api.md, Storage layer](api.md#storage-layer-durability-backends)
|
|
371
|
+
and [artifacts.md](artifacts.md). One process ticks a folder; see
|
|
372
|
+
[automations.md, Storage guarantees](automations.md#storage-guarantees).
|
|
373
|
+
|
|
312
374
|
## Drivers: scheduler
|
|
313
375
|
|
|
314
376
|
The scheduler is an in-process driver loop that resumes due waits and can deliver external events:
|
|
@@ -320,8 +382,9 @@ The scheduler is an in-process driver loop that resumes due waits and can delive
|
|
|
320
382
|
An automation runs a target workflow on a trigger, and is itself a durable run. The controller is a packaged
|
|
321
383
|
VisualFlow bundle (`abstractframework.automation-controller@1.0.0`) whose nodes are `automation` adapters; it waits on
|
|
322
384
|
one `WAIT_EVENT` with a deadline, starts each occurrence as an asynchronous `START_SUBWORKFLOW` child with a
|
|
323
|
-
deterministic id, and records every transition as an `automation.*` ledger record.
|
|
324
|
-
|
|
385
|
+
deterministic id, and records every transition as an `automation.*` ledger record. The controller needs no effect type or driver of its
|
|
386
|
+
own: a host drives it like any other run. A run creates a one-shot automation for later through `SCHEDULE_RUN` (a
|
|
387
|
+
wake). See [automations.md](automations.md).
|
|
325
388
|
|
|
326
389
|
```mermaid
|
|
327
390
|
flowchart LR
|
|
@@ -332,8 +395,10 @@ flowchart LR
|
|
|
332
395
|
subgraph Automations["automations/ + triggers/"]
|
|
333
396
|
Commands["apply_automation_command"]
|
|
334
397
|
Controller["controller run<br/>(automation-controller@1.0.0)"]
|
|
335
|
-
Triggers["trigger registry<br/>schedule@1, schedule@2, manual@1,<br/>email.received@1, entry-point sources"]
|
|
336
|
-
|
|
398
|
+
Triggers["trigger registry<br/>schedule@1, schedule@2, manual@1,<br/>email.received@1, feed.item@1,<br/>webhook.received@1, entry-point sources"]
|
|
399
|
+
Conns["trigger connections<br/>(per user: feed URL, webhook secret)"]
|
|
400
|
+
Inbox["event inbox<br/>(streams email:… and trigger:…,<br/>filled by the host's feeders)"]
|
|
401
|
+
Wakes["wakes<br/>(SCHEDULE_RUN plans,<br/>the host creates)"]
|
|
337
402
|
Queries["get_automation / list_occurrences /<br/>list_attention / pending_waits /<br/>list_automations"]
|
|
338
403
|
end
|
|
339
404
|
subgraph Runs["runs"]
|
|
@@ -353,6 +418,9 @@ flowchart LR
|
|
|
353
418
|
Loop --> Occ
|
|
354
419
|
Controller -->|"prepare / admit / rearm"| Triggers
|
|
355
420
|
Controller -->|"events after its cursor"| Inbox
|
|
421
|
+
Commands -.->|"create / revise:<br/>connection_id check"| Conns
|
|
422
|
+
Occ -->|"SCHEDULE_RUN"| Wakes
|
|
423
|
+
Wakes -->|"one-shot automation"| Commands
|
|
356
424
|
Controller -->|"START_SUBWORKFLOW run_id"| Occ
|
|
357
425
|
Occ --> Desc
|
|
358
426
|
Controller --> RS
|
|
@@ -363,6 +431,33 @@ flowchart LR
|
|
|
363
431
|
Queries --> LS
|
|
364
432
|
```
|
|
365
433
|
|
|
434
|
+
### Events reaching an occurrence
|
|
435
|
+
|
|
436
|
+
```mermaid
|
|
437
|
+
flowchart LR
|
|
438
|
+
subgraph Sources["host-side feeders"]
|
|
439
|
+
Mail["mail watcher<br/>(EmailInboxFeeder.poll)"]
|
|
440
|
+
Feed["feed poller<br/>(poll_feed_connections)"]
|
|
441
|
+
Hook["webhook route<br/>(append_webhook_event,<br/>Standard Webhooks check)"]
|
|
442
|
+
Test["console test-fire<br/>(test_fire)"]
|
|
443
|
+
end
|
|
444
|
+
Inbox["EventInbox<br/>stream per mailbox folder / per connection<br/>dedupe on dedupekey"]
|
|
445
|
+
Ctrl["controller run<br/>admit: adapter batches events<br/>after its cursor"]
|
|
446
|
+
Occ["occurrence run<br/>prompt: [Trigger …] header (+ untrusted frame)<br/>input_data.event: CloudEvents 1.0<br/>_meta.origin: trigger / person / agent"]
|
|
447
|
+
Mail --> Inbox
|
|
448
|
+
Feed --> Inbox
|
|
449
|
+
Hook --> Inbox
|
|
450
|
+
Test --> Inbox
|
|
451
|
+
Sources -.->|"wake the bound controllers"| Ctrl
|
|
452
|
+
Inbox --> Ctrl
|
|
453
|
+
Ctrl -->|"START_SUBWORKFLOW"| Occ
|
|
454
|
+
```
|
|
455
|
+
|
|
456
|
+
Feeders append one event per mail, feed item or webhook call to the inbox stream of a mailbox folder
|
|
457
|
+
(`email:<tenant>:<user>:<mailbox>:<folder>`) or of a trigger connection (`trigger:<connection_id>`), then wake the
|
|
458
|
+
automations bound to it. The controller reads only its own streams, its adapter turns the pending events into one
|
|
459
|
+
admission, and the occurrence receives the envelope as a CloudEvents 1.0 event beside its prompt header.
|
|
460
|
+
|
|
366
461
|
Email automations read the runtime's durable event inbox: the host's mail watcher appends each new message
|
|
367
462
|
(`abstractruntime.email.feeder`) and wakes the controller, and the `email.received@1` adapter batches the messages
|
|
368
463
|
after the automation's cursor. Tool calls resolve the executing run's email account through the host's per-runtime
|
|
@@ -378,6 +473,8 @@ Invariants the design rests on:
|
|
|
378
473
|
application.
|
|
379
474
|
- **One lock per run.** `run_mutation_lock(run_id)` serializes `tick`, `resume` commits and automation commands in a
|
|
380
475
|
process. v1 supports one writer process per store.
|
|
476
|
+
- **Origin is recorded once.** Every occurrence carries `_meta.origin` (`trigger`, `person` for a run-now, `agent`
|
|
477
|
+
for a wake) frozen with its inputs; hosts stamp the runs they start with `origin_for(...)`.
|
|
381
478
|
- **Turns are defined once.** `select_session_turns` decides which runs are a session's turns (parent-less runs
|
|
382
479
|
except controllers, plus occurrences). History bundles, session replay, growing context and discussion seeds all
|
|
383
480
|
use it, and `list_run_index(root_only=True)` returns the same turn roots.
|