phronomy 0.27.0 → 0.29.0
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.
- checksums.yaml +4 -4
- data/.mutant.yml +9 -9
- data/CHANGELOG.md +52 -0
- data/CONTRIBUTING.md +8 -8
- data/README.md +28 -7
- data/benchmark/bench_agent_invoke.rb +25 -50
- data/benchmark/bench_context_assembler.rb +14 -11
- data/benchmark/bench_regression.rb +1 -1
- data/benchmark/bench_tool_schema.rb +1 -1
- data/docs/application-recipes.md +229 -0
- data/docs/architecture/agent-chat-and-state-ownership.md +7 -1
- data/docs/architecture/agent-transition-ownership.md +13 -89
- data/docs/architecture/backend-groups.md +152 -0
- data/docs/architecture/before-llm-input.md +3 -3
- data/docs/architecture/context-management.md +1 -1
- data/docs/architecture/dx05-agent-scope.md +119 -0
- data/docs/architecture/dx05-workflow-task-state.md +134 -0
- data/docs/architecture/error-api-review.md +245 -0
- data/docs/architecture/execution-abstraction-review.md +88 -0
- data/docs/architecture/execution-boundaries.md +28 -0
- data/docs/architecture/execution-metadata-and-values.md +6 -0
- data/docs/architecture/multi-agent-handoff.md +6 -5
- data/docs/architecture/persistence.md +27 -9
- data/docs/architecture/r8-unit1.md +104 -0
- data/docs/architecture/r8-unit10.md +72 -0
- data/docs/architecture/r8-unit11.md +71 -0
- data/docs/architecture/r8-unit12.md +67 -0
- data/docs/architecture/r8-unit13.md +61 -0
- data/docs/architecture/r8-unit14.md +72 -0
- data/docs/architecture/r8-unit15.md +65 -0
- data/docs/architecture/r8-unit16.md +54 -0
- data/docs/architecture/r8-unit17.md +73 -0
- data/docs/architecture/r8-unit18.md +92 -0
- data/docs/architecture/r8-unit19.md +61 -0
- data/docs/architecture/r8-unit2.md +55 -0
- data/docs/architecture/r8-unit20.md +51 -0
- data/docs/architecture/r8-unit21.md +79 -0
- data/docs/architecture/r8-unit22.md +74 -0
- data/docs/architecture/r8-unit23.md +81 -0
- data/docs/architecture/r8-unit3.md +130 -0
- data/docs/architecture/r8-unit4.md +79 -0
- data/docs/architecture/r8-unit5.md +115 -0
- data/docs/architecture/r8-unit6.md +71 -0
- data/docs/architecture/r8-unit7.md +70 -0
- data/docs/architecture/r8-unit8.md +78 -0
- data/docs/architecture/r8-unit9.md +73 -0
- data/docs/architecture/refactoring-closure.md +10 -1
- data/docs/architecture/remaining-refactoring-plan.md +16 -0
- data/docs/architecture/storage-execution-boundaries.md +54 -0
- data/docs/architecture/tool-schema-recording-gap.md +6 -0
- data/docs/architecture/tracing.md +1 -1
- data/docs/architecture/workflow-terminal-ownership-design.md +2 -2
- data/docs/architecture.md +24 -11
- data/docs/decisions/015-tool-public-facade-and-rbs-boundary.md +3 -3
- data/docs/decisions/027-llm-adapter-provider-boundary.md +2 -0
- data/docs/decisions/030-agent-handoff-domain-and-durable-responsibility.md +2 -0
- data/docs/decisions/031-durable-multi-agent-coordination.md +2 -0
- data/docs/decisions/032-storage-backend-composition.md +5 -0
- data/docs/decisions/034-handoff-runner-coordination-ownership.md +2 -0
- data/docs/decisions/035-tool-executor-capability-ownership.md +1 -1
- data/docs/decisions/038-responsibility-based-source-layout.md +14 -0
- data/docs/decisions/039-runtime-configuration-lifecycle-ownership.md +8 -0
- data/docs/decisions/040-configuration-default-composition.md +12 -1
- data/docs/decisions/045-worker-input-restriction-ownership.md +4 -0
- data/docs/decisions/051-execution-outcome-worker-ownership.md +2 -0
- data/docs/decisions/056-workflow-terminal-policy-ownership.md +1 -1
- data/docs/decisions/058-neutral-storage-primitives.md +5 -0
- data/docs/decisions/059-backend-contracts-and-async-clients.md +74 -0
- data/docs/decisions/060-runtime-settings-and-application-configuration.md +86 -0
- data/docs/decisions/061-persistence-failure-contracts.md +89 -0
- data/docs/decisions/062-content-store-service.md +52 -0
- data/docs/decisions/063-execution-contracts-and-services.md +88 -0
- data/docs/decisions/064-agent-execution-and-multi-agent-responsibility.md +36 -0
- data/docs/decisions/065-vector-and-embeddings-common-operations.md +38 -0
- data/docs/decisions/066-llm-and-tool-operation-contracts.md +20 -0
- data/docs/decisions/067-agent-progress-and-engine-connection.md +29 -0
- data/docs/decisions/068-agent-tool-child-progress-and-tool-operation.md +36 -0
- data/docs/decisions/README.md +18 -1
- data/docs/execution-boundaries-preview.md +45 -0
- data/docs/failure-reason-codes.md +45 -0
- data/docs/features.md +12 -4
- data/docs/getting-started.md +52 -48
- data/docs/migrations/0.22.md +2 -2
- data/docs/migrations/durable-semantic-coordination-v2.md +2 -0
- data/docs/migrations/handoff-runner-multi-agent.md +2 -0
- data/docs/migrations/persistence-failure-contracts.md +67 -0
- data/docs/migrations/r8-unit10.md +36 -0
- data/docs/migrations/r8-unit11.md +33 -0
- data/docs/migrations/r8-unit12.md +31 -0
- data/docs/migrations/r8-unit13.md +36 -0
- data/docs/migrations/r8-unit14.md +31 -0
- data/docs/migrations/r8-unit15.md +31 -0
- data/docs/migrations/r8-unit16.md +26 -0
- data/docs/migrations/r8-unit17.md +28 -0
- data/docs/migrations/r8-unit18.md +29 -0
- data/docs/migrations/r8-unit19.md +28 -0
- data/docs/migrations/r8-unit20.md +24 -0
- data/docs/migrations/r8-unit21.md +28 -0
- data/docs/migrations/r8-unit22.md +29 -0
- data/docs/migrations/r8-unit23.md +20 -0
- data/docs/migrations/r8-unit4.md +67 -0
- data/docs/migrations/r8-unit5.md +75 -0
- data/docs/migrations/r8-unit6.md +109 -0
- data/docs/migrations/r8-unit7.md +31 -0
- data/docs/migrations/r8-unit8.md +33 -0
- data/docs/migrations/r8-unit9.md +28 -0
- data/docs/migrations/storage-async-client.md +103 -0
- data/docs/migrations/vector-async-clients.md +110 -0
- data/docs/ordered-event-delivery.md +54 -0
- data/docs/persistence-backends.md +38 -21
- data/docs/runtime-and-concurrency.md +26 -1
- data/docs/workflow-completion.md +92 -0
- data/gemfiles/http_minimum.gemfile +5 -0
- data/lib/phronomy/agent/admission.rb +78 -0
- data/lib/phronomy/agent/{lifecycle_contract/agent_already_exists_error.rb → agent_already_exists_error.rb} +1 -1
- data/lib/phronomy/agent/{lifecycle_contract/agent_busy_error.rb → agent_busy_error.rb} +1 -1
- data/lib/phronomy/agent/agent_not_found_error.rb +16 -0
- data/lib/phronomy/agent/{lifecycle_contract/agent_purged_error.rb → agent_purged_error.rb} +1 -1
- data/lib/phronomy/agent/agent_unloaded_error.rb +14 -0
- data/lib/phronomy/agent/api/agent.rb +13 -0
- data/lib/phronomy/{recovery → agent/api}/execution_rehydration_required_error.rb +1 -1
- data/lib/phronomy/agent/async_event_api.rb +132 -103
- data/lib/phronomy/agent/base.rb +146 -113
- data/lib/phronomy/agent/before_llm_input.rb +70 -0
- data/lib/phronomy/agent/composition/run_once.rb +1 -1
- data/lib/phronomy/agent/{context_assembly/context_candidate_resolver.rb → context_candidate_resolver.rb} +2 -2
- data/lib/phronomy/agent/{context_assembly/context_assembler.rb → context_preparation.rb} +35 -221
- data/lib/phronomy/agent/control_request.rb +21 -0
- data/lib/phronomy/agent/execution/agent_execution.rb +1 -1
- data/lib/phronomy/agent/execution/agent_invocation.rb +27 -53
- data/lib/phronomy/agent/execution/approval_resume_commit.rb +1 -1
- data/lib/phronomy/agent/execution/dispatch_preparation.rb +17 -127
- data/lib/phronomy/agent/execution/exact_execution.rb +55 -32
- data/lib/phronomy/agent/execution/execution_cancellation.rb +8 -4
- data/lib/phronomy/agent/execution/execution_coordinator.rb +229 -407
- data/lib/phronomy/agent/execution/execution_metadata.rb +1 -0
- data/lib/phronomy/agent/execution/execution_outcome_committer.rb +71 -127
- data/lib/phronomy/agent/execution/execution_registry.rb +6 -2
- data/lib/phronomy/agent/execution/execution_session_runner.rb +22 -27
- data/lib/phronomy/agent/execution/initial_preparation.rb +19 -120
- data/lib/phronomy/agent/execution/{agent_invocation_session_builder.rb → invocation_actions.rb} +54 -194
- data/lib/phronomy/agent/execution/invocation_transitions.rb +39 -1
- data/lib/phronomy/agent/execution/runtime_record_encoder.rb +8 -11
- data/lib/phronomy/agent/execution_change.rb +161 -0
- data/lib/phronomy/agent/execution_environment.rb +36 -0
- data/lib/phronomy/agent/execution_extension_state.rb +21 -0
- data/lib/phronomy/agent/execution_observation.rb +35 -0
- data/lib/phronomy/agent/filterable.rb +188 -0
- data/lib/phronomy/agent/handoff/{handoff_context.rb → transfer_context.rb} +4 -4
- data/lib/phronomy/agent/handoff/{handoff_projection.rb → transfer_projection.rb} +14 -33
- data/lib/phronomy/{llm_contract/transport_error.rb → agent/handoff_error.rb} +1 -1
- data/lib/phronomy/agent/journal/journal_projection.rb +1 -1
- data/lib/phronomy/agent/knowledge_item.rb +13 -0
- data/lib/phronomy/agent/lifecycle/agent_root.rb +1 -1
- data/lib/phronomy/agent/lifecycle/lifetime_api.rb +76 -0
- data/lib/phronomy/agent/lifecycle/operation_lease.rb +33 -0
- data/lib/phronomy/agent/lifecycle/operation_result.rb +53 -0
- data/lib/phronomy/agent/lifecycle/ownership_registry.rb +117 -31
- data/lib/phronomy/agent/lifecycle/scope.rb +198 -0
- data/lib/phronomy/agent/lifecycle/scope_cleanup_error.rb +19 -0
- data/lib/phronomy/agent/lifecycle/unload_transition.rb +78 -0
- data/lib/phronomy/agent/persistence/agent_repository.rb +29 -21
- data/lib/phronomy/agent/persistence/cancellation_repository.rb +51 -0
- data/lib/phronomy/agent/persistence/codec.rb +1 -21
- data/lib/phronomy/agent/persistence/execution_repository.rb +57 -41
- data/lib/phronomy/agent/persistence/journal_repository.rb +27 -18
- data/lib/phronomy/agent/persistence/records.rb +33 -0
- data/lib/phronomy/agent/persistence/retention_repository.rb +70 -0
- data/lib/phronomy/agent/persistence/storage_schema.rb +7 -2
- data/lib/phronomy/agent/persistence/watermark.rb +13 -11
- data/lib/phronomy/agent/recovery/invocation_restorer.rb +13 -21
- data/lib/phronomy/agent/recovery/recovery_coordinator/continuation.rb +13 -12
- data/lib/phronomy/agent/recovery/recovery_coordinator/installation.rb +34 -34
- data/lib/phronomy/agent/recovery/recovery_coordinator/resolution.rb +33 -39
- data/lib/phronomy/agent/recovery/recovery_coordinator.rb +28 -25
- data/lib/phronomy/agent/recovery/recovery_rules.rb +119 -0
- data/lib/phronomy/agent/recovery/recovery_support.rb +10 -19
- data/lib/phronomy/agent/reserved_execution.rb +16 -0
- data/lib/phronomy/agent/retention.rb +17 -0
- data/lib/phronomy/agent/runtime_binding/engine_environment.rb +60 -0
- data/lib/phronomy/agent/runtime_binding/engine_session_builder.rb +34 -0
- data/lib/phronomy/agent/runtime_binding/phase_machine_builder.rb +64 -0
- data/lib/phronomy/agent/runtime_binding/tool_session_builder.rb +34 -0
- data/lib/phronomy/agent/{context_assembly/ruby_llm_materializer.rb → runtime_input.rb} +18 -35
- data/lib/phronomy/agent/{context_assembly/saved_context_reader.rb → saved_context_reader.rb} +6 -4
- data/lib/phronomy/agent/settings.rb +47 -0
- data/lib/phronomy/agent/{context_assembly/state_writer.rb → state_writer.rb} +4 -3
- data/lib/phronomy/agent/store.rb +253 -0
- data/lib/phronomy/agent/{lifecycle_contract/stream_callback_error.rb → stream_callback_error.rb} +3 -3
- data/lib/phronomy/agent/tool_execution/tool_binding.rb +4 -64
- data/lib/phronomy/agent/tool_execution/tool_invocation.rb +50 -219
- data/lib/phronomy/agent/tool_execution/tool_invocation_actions.rb +107 -0
- data/lib/phronomy/agent/tool_execution/tool_invocation_transitions.rb +70 -0
- data/lib/phronomy/common/error.rb +65 -1
- data/lib/phronomy/configuration/runtime_settings.rb +49 -0
- data/lib/phronomy/content_store/base.rb +7 -2
- data/lib/phronomy/content_store/storage_schema.rb +1 -0
- data/lib/phronomy/content_store/stored_contents.rb +2 -1
- data/lib/phronomy/context/assembly.rb +195 -0
- data/lib/phronomy/{llm_contract/context_budget_exceeded_error.rb → context/budget_exceeded_error.rb} +3 -1
- data/lib/phronomy/context/candidate.rb +51 -0
- data/lib/phronomy/context/constraint.rb +47 -0
- data/lib/phronomy/{agent/context_contract → context}/context_plan.rb +1 -1
- data/lib/phronomy/{agent/context_contract → context}/context_plan_validator.rb +3 -3
- data/lib/phronomy/{agent/context_contract → context}/context_policy.rb +1 -1
- data/lib/phronomy/{agent/context_contract → context}/context_policy_input.rb +1 -1
- data/lib/phronomy/{agent/context_assembly → context}/context_policy_input_builder.rb +1 -1
- data/lib/phronomy/context/default_policy.rb +140 -0
- data/lib/phronomy/context/final_budget_validator.rb +33 -0
- data/lib/phronomy/{agent/context_contract → context}/llm_input_build_context.rb +1 -1
- data/lib/phronomy/{agent/context_contract → context}/llm_input_manifest.rb +19 -19
- data/lib/phronomy/{agent/context_contract → context}/llm_input_patch.rb +1 -1
- data/lib/phronomy/context/manifest_error.rb +10 -0
- data/lib/phronomy/context/prompt_template.rb +98 -0
- data/lib/phronomy/{vector_store → documents}/loader/base.rb +1 -1
- data/lib/phronomy/{vector_store → documents}/loader/csv_loader.rb +2 -2
- data/lib/phronomy/{vector_store → documents}/loader/markdown_loader.rb +3 -3
- data/lib/phronomy/{vector_store → documents}/loader/plain_text_loader.rb +2 -2
- data/lib/phronomy/{vector_store → documents}/splitter/base.rb +1 -1
- data/lib/phronomy/{vector_store → documents}/splitter/fixed_size_splitter.rb +2 -2
- data/lib/phronomy/{vector_store → documents}/splitter/recursive_splitter.rb +2 -2
- data/lib/phronomy/embeddings/async/async_client.rb +44 -0
- data/lib/phronomy/embeddings/authentication_error.rb +11 -0
- data/lib/phronomy/embeddings/backends/ruby_llm_embeddings.rb +52 -0
- data/lib/phronomy/embeddings/base.rb +43 -0
- data/lib/phronomy/embeddings/invalid_result_error.rb +11 -0
- data/lib/phronomy/embeddings/rate_limit_error.rb +11 -0
- data/lib/phronomy/embeddings/transport_error.rb +11 -0
- data/lib/phronomy/engine/concurrency/offload_pool.rb +36 -21
- data/lib/phronomy/engine/concurrency/pool_registry.rb +47 -12
- data/lib/phronomy/engine/diagnostics.rb +1 -1
- data/lib/phronomy/engine/event_loop.rb +7 -7
- data/lib/phronomy/engine/execution_binding.rb +23 -0
- data/lib/phronomy/engine/execution_receiver_binding.rb +43 -0
- data/lib/phronomy/engine/fsm_protocol.rb +1 -6
- data/lib/phronomy/engine/fsm_session.rb +3 -3
- data/lib/phronomy/engine/metrics.rb +16 -14
- data/lib/phronomy/engine/runtime/timer_queue.rb +1 -1
- data/lib/phronomy/engine/runtime.rb +25 -12
- data/lib/phronomy/engine/terminal_decision.rb +7 -0
- data/lib/phronomy/execution/async_operation.rb +41 -0
- data/lib/phronomy/{engine → execution}/blocking.rb +2 -2
- data/lib/phronomy/{engine → execution}/concurrency/cancellation_token.rb +1 -1
- data/lib/phronomy/{engine → execution}/concurrency/deadline.rb +0 -17
- data/lib/phronomy/{engine → execution}/concurrency/physical_completion_task.rb +1 -1
- data/lib/phronomy/{engine → execution}/concurrency/result_collector.rb +1 -1
- data/lib/phronomy/{engine → execution}/concurrency/result_composition.rb +33 -12
- data/lib/phronomy/{engine/concurrency/subscriptions.rb → execution/concurrency/result_subscriptions.rb} +14 -18
- data/lib/phronomy/execution/concurrency/subscriptions.rb +25 -0
- data/lib/phronomy/{engine → execution}/execution.rb +61 -27
- data/lib/phronomy/{engine → execution}/execution_cancellation_error.rb +2 -2
- data/lib/phronomy/execution/execution_receiver.rb +78 -0
- data/lib/phronomy/execution/execution_scope_state.rb +35 -0
- data/lib/phronomy/{engine → execution}/execution_timeout_error.rb +2 -2
- data/lib/phronomy/{engine → execution}/invocation_context.rb +0 -15
- data/lib/phronomy/execution/invocation_controls.rb +73 -0
- data/lib/phronomy/execution/runnable.rb +24 -0
- data/lib/phronomy/{engine → execution}/task_result.rb +9 -4
- data/lib/phronomy/execution/wait_policy.rb +24 -0
- data/lib/phronomy/filter/{contract/filter_block_error.rb → filter_block_error.rb} +3 -3
- data/lib/phronomy/generation/generator_verifier/agent_operation.rb +65 -0
- data/lib/phronomy/generation/generator_verifier/default_parser.rb +27 -0
- data/lib/phronomy/generation/generator_verifier/workflow_builder.rb +2 -2
- data/lib/phronomy/generation/generator_verifier.rb +7 -7
- data/lib/phronomy/generation/low_confidence_error.rb +2 -2
- data/lib/phronomy/integrations/ordered_event_delivery.rb +208 -0
- data/lib/phronomy/llm_adapter/async/async_client.rb +47 -0
- data/lib/phronomy/{llm_contract → llm_adapter}/authentication_error.rb +3 -1
- data/lib/phronomy/llm_adapter/backends/ruby_llm.rb +183 -0
- data/lib/phronomy/llm_adapter/base.rb +49 -68
- data/lib/phronomy/{llm_contract → llm_adapter}/context_length_error.rb +3 -1
- data/lib/phronomy/llm_adapter/invalid_result_error.rb +10 -0
- data/lib/phronomy/llm_adapter/message.rb +62 -0
- data/lib/phronomy/{llm_contract → llm_adapter}/rate_limit_error.rb +3 -1
- data/lib/phronomy/llm_adapter/request.rb +79 -0
- data/lib/phronomy/llm_adapter/response.rb +36 -0
- data/lib/phronomy/llm_adapter/stream_chunk.rb +18 -0
- data/lib/phronomy/llm_adapter/token_usage.rb +64 -0
- data/lib/phronomy/llm_adapter/transport_error.rb +9 -0
- data/lib/phronomy/llm_adapter.rb +3 -16
- data/lib/phronomy/multi_agent/admission_registry.rb +1 -8
- data/lib/phronomy/multi_agent/durable_subagent_coordinator.rb +108 -84
- data/lib/phronomy/multi_agent/execution_environment.rb +29 -0
- data/lib/phronomy/{agent/handoff → multi_agent}/handoff.rb +2 -2
- data/lib/phronomy/{agent/handoff → multi_agent}/handoff_capability_factory.rb +21 -2
- data/lib/phronomy/multi_agent/handoff_participant.rb +79 -0
- data/lib/phronomy/{agent/handoff → multi_agent}/handoff_policy.rb +1 -1
- data/lib/phronomy/multi_agent/handoff_runner.rb +77 -100
- data/lib/phronomy/{agent/handoff → multi_agent}/handoff_state.rb +1 -1
- data/lib/phronomy/multi_agent/orchestrator.rb +61 -75
- data/lib/phronomy/multi_agent/persistence/codec.rb +20 -0
- data/lib/phronomy/multi_agent/persistence/handoff_state_repository.rb +77 -0
- data/lib/phronomy/multi_agent/persistence/records.rb +27 -0
- data/lib/phronomy/multi_agent/persistence/storage_schema.rb +21 -0
- data/lib/phronomy/multi_agent/persistence/team_execution_repository.rb +60 -44
- data/lib/phronomy/multi_agent/persistence/team_repository.rb +29 -21
- data/lib/phronomy/multi_agent/reserved_child_admission.rb +88 -0
- data/lib/phronomy/multi_agent/runtime_binding/engine_environment.rb +35 -0
- data/lib/phronomy/multi_agent/shared_state.rb +2 -2
- data/lib/phronomy/multi_agent/store.rb +156 -0
- data/lib/phronomy/multi_agent/team_busy_error.rb +18 -0
- data/lib/phronomy/multi_agent/team_coordinator.rb +99 -77
- data/lib/phronomy/multi_agent/team_not_found_error.rb +18 -0
- data/lib/phronomy/multi_agent/team_ownership_registry.rb +2 -12
- data/lib/phronomy/output_parser/parse_error.rb +7 -0
- data/lib/phronomy/persistence/content_repository.rb +26 -0
- data/lib/phronomy/persistence/errors.rb +16 -0
- data/lib/phronomy/persistence/migration/initial_format_migration.rb +2 -2
- data/lib/phronomy/persistence/persistence.rb +23 -0
- data/lib/phronomy/persistence/save_outcome.rb +24 -0
- data/lib/phronomy/persistence/snapshot_comparison.rb +81 -0
- data/lib/phronomy/persistence/storage_boundary.rb +32 -0
- data/lib/phronomy/persistence/transaction.rb +86 -0
- data/lib/phronomy/persistence_composition/storage_schema.rb +9 -4
- data/lib/phronomy/persistence_composition/stores.rb +34 -0
- data/lib/phronomy/persistence_composition/unit4_migration.rb +276 -0
- data/lib/phronomy/runtime_composition/agent_defaults.rb +5 -1
- data/lib/phronomy/runtime_composition/configuration.rb +146 -0
- data/lib/phronomy/runtime_composition/evaluation_defaults.rb +7 -0
- data/lib/phronomy/runtime_composition/execution_defaults.rb +5 -0
- data/lib/phronomy/runtime_composition/generation_defaults.rb +6 -0
- data/lib/phronomy/runtime_composition/global_configuration.rb +38 -0
- data/lib/phronomy/runtime_composition/multi_agent_defaults.rb +9 -0
- data/lib/phronomy/runtime_composition/workflow_defaults.rb +4 -0
- data/lib/phronomy/storage/async/async_client.rb +60 -0
- data/lib/phronomy/storage/backend.rb +8 -2
- data/lib/phronomy/storage/condition_failed_error.rb +2 -2
- data/lib/phronomy/storage/unique_constraint_error.rb +2 -2
- data/lib/phronomy/testing/eval/metrics.rb +1 -1
- data/lib/phronomy/testing/eval/scorer/llm_judge.rb +19 -3
- data/lib/phronomy/testing/persistence_contract/a_content_store.rb +2 -2
- data/lib/phronomy/testing/persistence_contract/a_journal_repository.rb +6 -6
- data/lib/phronomy/testing/persistence_contract/a_persistence_backend.rb +55 -52
- data/lib/phronomy/testing/persistence_contract/a_workflow_state_repository.rb +3 -3
- data/lib/phronomy/testing/persistence_contract/an_agent_repository.rb +7 -7
- data/lib/phronomy/testing/persistence_contract/an_execution_repository.rb +11 -11
- data/lib/phronomy/testing/persistence_contract/coordination_repositories.rb +57 -51
- data/lib/phronomy/testing/persistence_contract/neutral_storage_primitives.rb +1 -1
- data/lib/phronomy/testing/persistence_contract/storage_transaction_boundaries.rb +23 -22
- data/lib/phronomy/tool/authorization.rb +77 -0
- data/lib/phronomy/tool/base.rb +551 -9
- data/lib/phronomy/tool/call_request.rb +40 -0
- data/lib/phronomy/{agent/tool_execution/tool_definition_set.rb → tool/definition_set.rb} +7 -8
- data/lib/phronomy/tool/operation.rb +88 -0
- data/lib/phronomy/tool/schema.rb +214 -0
- data/lib/phronomy/tool/settings.rb +31 -0
- data/lib/phronomy/tool/tool_error.rb +7 -0
- data/lib/phronomy/tool/tool_executor.rb +58 -0
- data/lib/phronomy/tools/agent.rb +22 -90
- data/lib/phronomy/tools/mcp.rb +21 -14
- data/lib/phronomy/tools/vector_search.rb +4 -4
- data/lib/phronomy/tracing/automatic.rb +11 -6
- data/lib/phronomy/tracing/base.rb +36 -7
- data/lib/phronomy/tracing/observation.rb +37 -0
- data/lib/phronomy/tracing/open_telemetry_tracer.rb +4 -29
- data/lib/phronomy/tracing/settings.rb +36 -0
- data/lib/phronomy/vector_store/{async_backend.rb → async/async_client.rb} +35 -29
- data/lib/phronomy/vector_store/{in_memory.rb → backends/in_memory.rb} +12 -10
- data/lib/phronomy/vector_store/{pgvector.rb → backends/pgvector.rb} +44 -16
- data/lib/phronomy/vector_store/{redis_search.rb → backends/redis_search.rb} +74 -37
- data/lib/phronomy/vector_store/base.rb +118 -49
- data/lib/phronomy/vector_store/invalid_result_error.rb +12 -0
- data/lib/phronomy/vector_store.rb +2 -17
- data/lib/phronomy/version.rb +1 -1
- data/lib/phronomy/workflow/completion.rb +11 -0
- data/lib/phronomy/workflow/execution/workflow.rb +37 -9
- data/lib/phronomy/workflow/execution/workflow_action_rules.rb +67 -0
- data/lib/phronomy/workflow/execution/workflow_context.rb +2 -2
- data/lib/phronomy/workflow/execution/workflow_execution_environment.rb +28 -0
- data/lib/phronomy/workflow/execution/workflow_execution_registry.rb +77 -8
- data/lib/phronomy/workflow/execution/workflow_runner.rb +105 -92
- data/lib/phronomy/workflow/execution/workflow_settings.rb +28 -0
- data/lib/phronomy/workflow/execution/workflow_task_execution.rb +153 -0
- data/lib/phronomy/workflow/execution/workflow_task_reception.rb +72 -0
- data/lib/phronomy/workflow/execution/workflow_task_resume_error.rb +14 -0
- data/lib/phronomy/workflow/persistence/state_repository.rb +28 -22
- data/lib/phronomy/workflow/persistence/storage_schema.rb +13 -0
- data/lib/phronomy/workflow/runtime_binding/workflow_engine_environment.rb +61 -0
- data/lib/phronomy/workflow/runtime_binding/workflow_phase_machine_builder.rb +158 -0
- data/lib/phronomy/workflow/runtime_binding/workflow_task_session.rb +76 -0
- data/lib/phronomy/workflow/{execution → runtime_binding}/workflow_terminal_policy.rb +4 -4
- data/lib/phronomy.rb +63 -16
- data/scripts/api_snapshot.rb +47 -15
- data/scripts/check_readme_ruby.rb +24 -29
- data/scripts/check_readme_runnable.rb +92 -81
- data/sig/_private/phronomy/agent/settings.rbs +19 -0
- data/sig/_private/phronomy/configuration/runtime_settings.rbs +20 -0
- data/sig/_private/phronomy/llm_adapter/async/async_client.rbs +10 -0
- data/sig/_private/phronomy/multi_agent/store.rbs +8 -0
- data/sig/_private/phronomy/persistence/storage_boundary.rbs +7 -0
- data/sig/_private/phronomy/tool/settings.rbs +13 -0
- data/sig/_private/phronomy/tracing/settings.rbs +15 -0
- data/sig/_private/phronomy/workflow/execution/workflow_settings.rbs +13 -0
- data/sig/phronomy/agent/admission.rbs +19 -0
- data/sig/phronomy/agent/agent_not_found_error.rbs +6 -0
- data/sig/phronomy/agent/agent_unloaded_error.rbs +6 -0
- data/sig/phronomy/agent/execution_contract.rbs +132 -0
- data/sig/phronomy/agent/execution_environment.rbs +20 -0
- data/sig/phronomy/agent/store.rbs +73 -0
- data/sig/phronomy/agent/stream_callback_error.rbs +8 -0
- data/sig/phronomy/agent.rbs +29 -135
- data/sig/phronomy/common.rbs +7 -0
- data/sig/phronomy/content_store/contracts.rbs +13 -0
- data/sig/phronomy/context.rbs +152 -0
- data/sig/phronomy/embeddings/async/async_client.rbs +9 -0
- data/sig/phronomy/embeddings/base.rbs +23 -0
- data/sig/phronomy/engine/concurrency/timer_bindings.rbs +22 -0
- data/sig/phronomy/engine/control_bindings.rbs +11 -0
- data/sig/phronomy/engine/control_protocols.rbs +23 -0
- data/sig/phronomy/engine/execution_binding.rbs +6 -0
- data/sig/phronomy/engine/execution_receiver.rbs +15 -0
- data/sig/phronomy/engine/observability.rbs +13 -0
- data/sig/phronomy/execution/async_operation.rbs +7 -0
- data/sig/phronomy/execution/blocking.rbs +5 -0
- data/sig/phronomy/execution/concurrency/cancellation_token.rbs +13 -0
- data/sig/phronomy/execution/concurrency/deadline.rbs +10 -0
- data/sig/phronomy/execution/concurrency/result_composition.rbs +7 -0
- data/sig/phronomy/execution/control_protocols.rbs +18 -0
- data/sig/phronomy/execution/errors.rbs +7 -0
- data/sig/phronomy/execution/execution.rbs +41 -0
- data/sig/phronomy/execution/execution_receiver.rbs +40 -0
- data/sig/phronomy/execution/execution_scope_state.rbs +9 -0
- data/sig/phronomy/execution/invocation_context.rbs +18 -0
- data/sig/phronomy/execution/invocation_controls.rbs +13 -0
- data/sig/phronomy/execution/task_result.rbs +29 -0
- data/sig/phronomy/extensions.rbs +1 -21
- data/sig/phronomy/filter/filter_block_error.rbs +6 -0
- data/sig/phronomy/generation/low_confidence_error.rbs +6 -0
- data/sig/phronomy/handoff.rbs +10 -4
- data/sig/phronomy/integrations.rbs +14 -0
- data/sig/phronomy/llm_adapter/backends/ruby_llm.rbs +6 -0
- data/sig/phronomy/llm_adapter/base.rbs +14 -0
- data/sig/phronomy/llm_adapter/usage.rbs +14 -0
- data/sig/phronomy/llm_adapter/values.rbs +43 -0
- data/sig/phronomy/llm_context_window.rbs +10 -0
- data/sig/phronomy/multi_agent/reserved_child_admission.rbs +8 -0
- data/sig/phronomy/multi_agent/store.rbs +54 -0
- data/sig/phronomy/multi_agent/team_busy_error.rbs +8 -0
- data/sig/phronomy/multi_agent/team_not_found_error.rbs +8 -0
- data/sig/phronomy/multi_agent.rbs +6 -3
- data/sig/phronomy/persistence/errors.rbs +18 -0
- data/sig/phronomy/persistence/migration.rbs +13 -0
- data/sig/phronomy/persistence/transaction.rbs +19 -0
- data/sig/phronomy/persistence.rbs +1 -99
- data/sig/phronomy/persistence_composition.rbs +19 -0
- data/sig/phronomy/runtime_composition/configuration.rbs +36 -0
- data/sig/phronomy/storage/async/async_client.rbs +8 -0
- data/sig/phronomy/storage/backends/in_memory.rbs +9 -0
- data/sig/phronomy/{storage.rbs → storage/contracts.rbs} +4 -18
- data/sig/phronomy/tool.rbs +48 -4
- data/sig/phronomy/tracing/observation.rbs +7 -0
- data/sig/phronomy/vector_store/async/async_client.rbs +13 -0
- data/sig/phronomy/vector_store/base.rbs +23 -0
- data/sig/phronomy/workflow/execution/workflow_execution_environment.rbs +15 -0
- data/sig/phronomy/workflow/runtime_binding/workflow_terminal_policy.rbs +7 -0
- data/sig/phronomy/workflow/store.rbs +8 -0
- data/sig/phronomy/workflow.rbs +5 -1
- data/sig/phronomy.rbs +4 -49
- metadata +365 -117
- data/lib/phronomy/agent/concerns/before_llm_input.rb +0 -66
- data/lib/phronomy/agent/concerns/error_translation.rb +0 -45
- data/lib/phronomy/agent/concerns/filterable.rb +0 -184
- data/lib/phronomy/agent/context/capability/base.rb +0 -548
- data/lib/phronomy/agent/context/capability/tool_executor.rb +0 -62
- data/lib/phronomy/agent/context/instruction/prompt_template.rb +0 -102
- data/lib/phronomy/agent/context_assembly/runtime_chat_builder.rb +0 -36
- data/lib/phronomy/agent/context_assembly/token_budget_resolver.rb +0 -22
- data/lib/phronomy/agent/context_parts/validators/final_budget_validator.rb +0 -37
- data/lib/phronomy/agent/context_policies/default.rb +0 -142
- data/lib/phronomy/agent/execution/phase_machine_builder.rb +0 -101
- data/lib/phronomy/agent/execution/provider_call_outcome.rb +0 -106
- data/lib/phronomy/agent/handoff/handoff_execution_coordinator.rb +0 -15
- data/lib/phronomy/agent/handoff/handoff_outcome_committer.rb +0 -131
- data/lib/phronomy/agent/handoff/handoff_request.rb +0 -45
- data/lib/phronomy/agent/lifecycle_contract/handoff_error.rb +0 -7
- data/lib/phronomy/agent/persistence/handoff_state_repository.rb +0 -58
- data/lib/phronomy/agent/persistence/queries.rb +0 -61
- data/lib/phronomy/agent/selection/candidate.rb +0 -53
- data/lib/phronomy/agent/selection/constraint.rb +0 -49
- data/lib/phronomy/agent/tool_execution/tool_call_intercepted.rb +0 -29
- data/lib/phronomy/agent/tool_execution/tool_invocation_session_builder.rb +0 -276
- data/lib/phronomy/configuration/configuration.rb +0 -68
- data/lib/phronomy/configuration/global_configuration.rb +0 -26
- data/lib/phronomy/engine/concurrency/cancellation_scope.rb +0 -124
- data/lib/phronomy/engine/concurrency/operation_binding.rb +0 -43
- data/lib/phronomy/engine/execution_receiver.rb +0 -65
- data/lib/phronomy/engine/runnable.rb +0 -54
- data/lib/phronomy/llm_adapter/ruby_llm.rb +0 -47
- data/lib/phronomy/llm_contract/token_usage.rb +0 -85
- data/lib/phronomy/multi_agent/persistence/queries.rb +0 -30
- data/lib/phronomy/multi_agent/storage_contract/team_storage_schema.rb +0 -15
- data/lib/phronomy/output_parser/contract/parse_error.rb +0 -7
- data/lib/phronomy/persistence/api/persistence.rb +0 -140
- data/lib/phronomy/persistence_composition/repositories.rb +0 -77
- data/lib/phronomy/recovery/recovery.rb +0 -186
- data/lib/phronomy/tool/contract/tool_error.rb +0 -7
- data/lib/phronomy/vector_store/embeddings/base.rb +0 -44
- data/lib/phronomy/vector_store/embeddings/ruby_llm_embeddings.rb +0 -47
- data/lib/phronomy/workflow/phase_machine_builder.rb +0 -205
- data/lib/phronomy/workflow/storage_contract/workflow_storage_schema.rb +0 -9
- data/sig/phronomy/execution_receiver.rbs +0 -34
- data/sig/phronomy/llm_adapter.rbs +0 -11
- data/sig/phronomy/runtime.rbs +0 -76
- /data/lib/phronomy/agent/{context_assembly/context_importer.rb → context_importer.rb} +0 -0
- /data/lib/phronomy/{engine → execution}/backpressure_error.rb +0 -0
- /data/lib/phronomy/{engine → execution}/cancellation_error.rb +0 -0
- /data/lib/phronomy/{engine → execution}/concurrency/worker_input_restricted.rb +0 -0
- /data/lib/phronomy/{engine → execution}/event_loop_reentrancy_error.rb +0 -0
- /data/lib/phronomy/{engine → execution}/invalid_async_entry_action_error.rb +0 -0
- /data/lib/phronomy/{engine → execution}/invalid_async_transition_action_error.rb +0 -0
- /data/lib/phronomy/{engine → execution}/invalid_async_workflow_action_error.rb +0 -0
- /data/lib/phronomy/{engine → execution}/pool_shutdown_error.rb +0 -0
- /data/lib/phronomy/{engine → execution}/recursion_limit_error.rb +0 -0
- /data/lib/phronomy/{engine → execution}/runtime_shutdown_error.rb +0 -0
- /data/lib/phronomy/{engine → execution}/runtime_shutdown_reentrancy_error.rb +0 -0
- /data/lib/phronomy/{engine → execution}/scheduler_reentrancy_error.rb +0 -0
- /data/lib/phronomy/{engine → execution}/timeout_error.rb +0 -0
data/lib/phronomy/agent/base.rb
CHANGED
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require_relative "../
|
|
3
|
+
require_relative "../execution/concurrency/worker_input_restricted"
|
|
4
4
|
|
|
5
5
|
require "securerandom"
|
|
6
|
-
require_relative "
|
|
7
|
-
require_relative "
|
|
8
|
-
require_relative "concerns/error_translation"
|
|
6
|
+
require_relative "filterable"
|
|
7
|
+
require_relative "before_llm_input"
|
|
9
8
|
|
|
10
9
|
module Phronomy
|
|
11
10
|
module Agent
|
|
@@ -36,9 +35,8 @@ module Phronomy
|
|
|
36
35
|
include Phronomy::Concurrency::WorkerInputRestricted
|
|
37
36
|
|
|
38
37
|
include Phronomy::Runnable
|
|
39
|
-
include
|
|
40
|
-
include
|
|
41
|
-
include Concerns::ErrorTranslation
|
|
38
|
+
include Filterable
|
|
39
|
+
include BeforeLLMInput
|
|
42
40
|
|
|
43
41
|
APPROVAL_CONFIGURATION_INIT_MUTEX = Mutex.new
|
|
44
42
|
private_constant :APPROVAL_CONFIGURATION_INIT_MUTEX
|
|
@@ -48,7 +46,7 @@ module Phronomy
|
|
|
48
46
|
if name
|
|
49
47
|
@model = name
|
|
50
48
|
else
|
|
51
|
-
@model || Phronomy.
|
|
49
|
+
@model || Phronomy::Agent::Settings.current.default_model
|
|
52
50
|
end
|
|
53
51
|
end
|
|
54
52
|
|
|
@@ -129,18 +127,18 @@ module Phronomy
|
|
|
129
127
|
end
|
|
130
128
|
end
|
|
131
129
|
|
|
132
|
-
# Binds one Application-constructed ContextPolicy instance to this
|
|
130
|
+
# Binds one Application-constructed Phronomy::Context::ContextPolicy instance to this
|
|
133
131
|
# Agent class. Policy binding is Application code/runtime wiring rather
|
|
134
132
|
# than durable Agent state.
|
|
135
133
|
def context_policy(*args)
|
|
136
134
|
if args.empty?
|
|
137
135
|
return @context_policy if instance_variable_defined?(:@context_policy)
|
|
138
136
|
return superclass.context_policy if superclass.respond_to?(:context_policy)
|
|
139
|
-
|
|
137
|
+
raise Phronomy::ConfigurationError, "Agent ContextPolicy has not been configured"
|
|
140
138
|
end
|
|
141
|
-
unless args.length == 1 && args.first.is_a?(ContextPolicy)
|
|
139
|
+
unless args.length == 1 && args.first.is_a?(Phronomy::Context::ContextPolicy)
|
|
142
140
|
raise ArgumentError,
|
|
143
|
-
"context_policy expects one Phronomy::
|
|
141
|
+
"context_policy expects one Phronomy::Context::ContextPolicy instance"
|
|
144
142
|
end
|
|
145
143
|
|
|
146
144
|
@context_policy = args.first
|
|
@@ -171,6 +169,7 @@ module Phronomy
|
|
|
171
169
|
agent_id: SecureRandom.uuid,
|
|
172
170
|
context: nil,
|
|
173
171
|
knowledge: [],
|
|
172
|
+
retention: nil,
|
|
174
173
|
persistence: nil,
|
|
175
174
|
metadata: {},
|
|
176
175
|
on_event: nil,
|
|
@@ -180,6 +179,7 @@ module Phronomy
|
|
|
180
179
|
agent_id: agent_id,
|
|
181
180
|
context: context,
|
|
182
181
|
knowledge: knowledge,
|
|
182
|
+
retention: retention,
|
|
183
183
|
persistence: persistence,
|
|
184
184
|
metadata: metadata,
|
|
185
185
|
on_event: on_event,
|
|
@@ -189,7 +189,7 @@ module Phronomy
|
|
|
189
189
|
|
|
190
190
|
# Resolves one existing logical Agent. A live process-local owner wins
|
|
191
191
|
# without a Persistence reload; otherwise the durable Agent is hydrated.
|
|
192
|
-
def load(agent_id, persistence:, on_event: nil, &event_block)
|
|
192
|
+
def load(agent_id, persistence:, on_event: nil, execution_wiring: {}, &event_block)
|
|
193
193
|
raise ArgumentError, "persistence is required" unless persistence
|
|
194
194
|
if on_event && event_block
|
|
195
195
|
raise ArgumentError, "Provide either on_event: or a block, not both"
|
|
@@ -199,10 +199,9 @@ module Phronomy
|
|
|
199
199
|
raise ArgumentError, "agent_id must not be empty" if key.empty?
|
|
200
200
|
|
|
201
201
|
listener_supplied = !on_event.nil? || !event_block.nil?
|
|
202
|
-
runtime = Phronomy::Runtime.instance
|
|
203
202
|
materialized = false
|
|
204
203
|
|
|
205
|
-
agent = OwnershipRegistry.
|
|
204
|
+
agent = OwnershipRegistry.current.load(key, expected_class: self) do |owner_runtime|
|
|
206
205
|
materialized = true
|
|
207
206
|
instance = __construct_owned_agent(
|
|
208
207
|
owner_runtime,
|
|
@@ -210,6 +209,7 @@ module Phronomy
|
|
|
210
209
|
agent_id: key,
|
|
211
210
|
persistence: persistence,
|
|
212
211
|
load_existing: true,
|
|
212
|
+
execution_wiring: execution_wiring,
|
|
213
213
|
on_event: on_event,
|
|
214
214
|
&event_block
|
|
215
215
|
)
|
|
@@ -236,14 +236,14 @@ module Phronomy
|
|
|
236
236
|
key = agent_id.to_s
|
|
237
237
|
raise ArgumentError, "agent_id must not be empty" if key.empty?
|
|
238
238
|
|
|
239
|
-
OwnershipRegistry.
|
|
239
|
+
OwnershipRegistry.existing_current&.get(key, expected_class: self)
|
|
240
240
|
end
|
|
241
241
|
|
|
242
242
|
# Resolves the live Agent instance that currently owns execution_id in
|
|
243
243
|
# this process. The Runtime returns only a read-only ownership view;
|
|
244
244
|
# mutable Agent execution state remains EventLoop-owned.
|
|
245
245
|
def live_for_execution(execution_id)
|
|
246
|
-
owner = Phronomy::Agent::ExecutionRegistry.
|
|
246
|
+
owner = Phronomy::Agent::ExecutionRegistry.existing_current&.agent_execution_owner(execution_id)
|
|
247
247
|
unless owner
|
|
248
248
|
raise Phronomy::ExecutionRehydrationRequiredError,
|
|
249
249
|
"no live execution owner for #{execution_id}; durable rehydration is required"
|
|
@@ -268,9 +268,15 @@ module Phronomy
|
|
|
268
268
|
end
|
|
269
269
|
end
|
|
270
270
|
|
|
271
|
+
# Bound at Agent construction; no execution may silently switch Runtime.
|
|
271
272
|
# @api private
|
|
272
|
-
def
|
|
273
|
-
@
|
|
273
|
+
def __execution_environment
|
|
274
|
+
@_phronomy_runtime_owner || ExecutionEnvironment.current
|
|
275
|
+
end
|
|
276
|
+
|
|
277
|
+
# @api private
|
|
278
|
+
def __execution_wiring
|
|
279
|
+
@_phronomy_execution_wiring || {}.freeze
|
|
274
280
|
end
|
|
275
281
|
|
|
276
282
|
# Framework-owned idempotent Tool operations opt into exact replay.
|
|
@@ -279,26 +285,33 @@ module Phronomy
|
|
|
279
285
|
|
|
280
286
|
# @api private
|
|
281
287
|
def __framework_call?(name)
|
|
282
|
-
__framework_tool_replayable?(name) || Array(
|
|
288
|
+
__framework_tool_replayable?(name) || Array(__execution_wiring[:phronomy_control_bindings]).any? { |binding| binding.tool_name == name }
|
|
283
289
|
end
|
|
284
290
|
|
|
285
|
-
# Captured Tool wiring is supplied explicitly; this hook only writes semantic values.
|
|
286
|
-
# @api private
|
|
287
|
-
def __prepare_coordination_record(execution, tx:) = execution
|
|
288
|
-
|
|
289
291
|
# Runtime configuration only; no value returned here is serialized.
|
|
290
292
|
# @api private
|
|
291
293
|
def __invocation_config(config) = config
|
|
292
294
|
|
|
295
|
+
def knowledge_snapshot
|
|
296
|
+
__with_operation { persistence.knowledge_snapshot(agent_id: agent_id) }
|
|
297
|
+
end
|
|
298
|
+
|
|
299
|
+
# Listener inheritance is an explicit orchestration choice, not a private getter.
|
|
300
|
+
def event_listener
|
|
301
|
+
__with_operation(read_only: true) { _phronomy_event_listener }
|
|
302
|
+
end
|
|
303
|
+
|
|
293
304
|
attr_reader :agent_id, :persistence
|
|
294
305
|
|
|
295
306
|
def initialize(
|
|
296
307
|
agent_id: nil,
|
|
297
308
|
context: nil,
|
|
298
309
|
knowledge: [],
|
|
310
|
+
retention: nil,
|
|
299
311
|
persistence: nil,
|
|
300
312
|
metadata: {},
|
|
301
313
|
load_existing: false,
|
|
314
|
+
execution_wiring: {},
|
|
302
315
|
on_event: nil,
|
|
303
316
|
&event_block
|
|
304
317
|
)
|
|
@@ -306,6 +319,11 @@ module Phronomy
|
|
|
306
319
|
raise ArgumentError, "Provide either on_event: or a block, not both"
|
|
307
320
|
end
|
|
308
321
|
@_phronomy_event_listener = on_event || event_block
|
|
322
|
+
@_phronomy_execution_wiring = execution_wiring.dup.freeze
|
|
323
|
+
@initial_retention = retention
|
|
324
|
+
if retention && retention.agent_id != agent_id.to_s
|
|
325
|
+
raise ArgumentError, "retention must refer to the new Agent"
|
|
326
|
+
end
|
|
309
327
|
|
|
310
328
|
reserved_agent_id = @_phronomy_reserved_agent_id
|
|
311
329
|
effective_agent_id = if agent_id.nil?
|
|
@@ -337,9 +355,8 @@ module Phronomy
|
|
|
337
355
|
"load_existing: is an internal hydration option; use .load(agent_id, persistence:)"
|
|
338
356
|
end
|
|
339
357
|
|
|
340
|
-
runtime = Phronomy::Runtime.instance
|
|
341
358
|
begin
|
|
342
|
-
OwnershipRegistry.
|
|
359
|
+
OwnershipRegistry.current.create(effective_agent_id, expected_class: self.class) do |owner_runtime|
|
|
343
360
|
__prepare_runtime_owner!(owner_runtime, effective_agent_id)
|
|
344
361
|
initialize_owned_state(
|
|
345
362
|
agent_id: effective_agent_id,
|
|
@@ -351,72 +368,88 @@ module Phronomy
|
|
|
351
368
|
)
|
|
352
369
|
self
|
|
353
370
|
end
|
|
354
|
-
rescue Phronomy::
|
|
371
|
+
rescue Phronomy::Persistence::ConflictError => error
|
|
355
372
|
raise Phronomy::AgentAlreadyExistsError,
|
|
356
373
|
"Agent #{effective_agent_id.inspect} already exists durably: #{error.message}"
|
|
357
374
|
end
|
|
358
375
|
end
|
|
359
376
|
|
|
360
377
|
def agent_root
|
|
361
|
-
|
|
362
|
-
|
|
378
|
+
__with_operation(read_only: true) do
|
|
379
|
+
__assert_agent_accessible!
|
|
380
|
+
@root
|
|
381
|
+
end
|
|
363
382
|
end
|
|
364
383
|
|
|
365
384
|
def journal_projection
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
385
|
+
__with_operation(read_only: true) do
|
|
386
|
+
__assert_agent_accessible!
|
|
387
|
+
Agent::JournalProjection.new(
|
|
388
|
+
agent_root: @root,
|
|
389
|
+
records: _journal_records_snapshot
|
|
390
|
+
)
|
|
391
|
+
end
|
|
371
392
|
end
|
|
372
393
|
|
|
373
394
|
def transcript
|
|
374
|
-
|
|
395
|
+
__with_operation(read_only: true) do
|
|
396
|
+
journal_projection.transcript_records
|
|
397
|
+
end
|
|
375
398
|
end
|
|
376
399
|
|
|
377
400
|
def clear_transcript!
|
|
378
|
-
|
|
379
|
-
root
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
401
|
+
__with_operation do
|
|
402
|
+
mutate_context!(:transcript_cleared) do |root|
|
|
403
|
+
root.with(
|
|
404
|
+
agent_revision: root.agent_revision + 1,
|
|
405
|
+
context_revision: root.context_revision + 1,
|
|
406
|
+
transcript_generation: root.transcript_generation + 1
|
|
407
|
+
)
|
|
408
|
+
end
|
|
384
409
|
end
|
|
385
410
|
end
|
|
386
411
|
|
|
387
412
|
def clear_knowledge!
|
|
388
|
-
|
|
389
|
-
root
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
413
|
+
__with_operation do
|
|
414
|
+
mutate_context!(:knowledge_cleared) do |root|
|
|
415
|
+
root.with(
|
|
416
|
+
agent_revision: root.agent_revision + 1,
|
|
417
|
+
context_revision: root.context_revision + 1
|
|
418
|
+
)
|
|
419
|
+
end
|
|
393
420
|
end
|
|
394
421
|
end
|
|
395
422
|
|
|
396
423
|
def add_knowledge(content, metadata: {})
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
424
|
+
__with_operation do
|
|
425
|
+
__assert_live_agent!
|
|
426
|
+
current = agent_root
|
|
427
|
+
update = state_writer.add_knowledge(root: current, content: content, metadata: metadata)
|
|
428
|
+
apply_state_update(update)
|
|
429
|
+
self
|
|
430
|
+
end
|
|
402
431
|
end
|
|
403
432
|
|
|
404
433
|
def reset_context!
|
|
405
|
-
|
|
406
|
-
root
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
434
|
+
__with_operation do
|
|
435
|
+
mutate_context!(:context_reset) do |root|
|
|
436
|
+
root.with(
|
|
437
|
+
agent_revision: root.agent_revision + 1,
|
|
438
|
+
context_revision: root.context_revision + 1,
|
|
439
|
+
transcript_generation: root.transcript_generation + 1
|
|
440
|
+
)
|
|
441
|
+
end
|
|
411
442
|
end
|
|
412
443
|
end
|
|
413
444
|
|
|
414
445
|
def close!
|
|
415
|
-
|
|
416
|
-
root
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
446
|
+
__with_operation do
|
|
447
|
+
mutate_context!(:agent_closed, context_affecting: false) do |root|
|
|
448
|
+
root.with(
|
|
449
|
+
agent_revision: root.agent_revision + 1,
|
|
450
|
+
lifecycle_status: :closed
|
|
451
|
+
)
|
|
452
|
+
end
|
|
420
453
|
end
|
|
421
454
|
end
|
|
422
455
|
|
|
@@ -427,7 +460,7 @@ module Phronomy
|
|
|
427
460
|
runtime = @_phronomy_runtime_owner
|
|
428
461
|
registry = OwnershipRegistry.for(runtime)
|
|
429
462
|
token = registry.begin_purge(self)
|
|
430
|
-
if
|
|
463
|
+
if runtime.existing_registry&.agent_execution_admitted?(agent_id)
|
|
431
464
|
registry.abort_purge(self, token)
|
|
432
465
|
raise Phronomy::AgentBusyError,
|
|
433
466
|
"Agent #{agent_id.inspect} has a nonterminal top-level execution"
|
|
@@ -436,20 +469,19 @@ module Phronomy
|
|
|
436
469
|
begin
|
|
437
470
|
persistence.transaction do |tx|
|
|
438
471
|
tx.executions.assert_idle!(agent_id)
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
end
|
|
443
|
-
tx.handoff_states.delete(agent_id, expected_revision: routing.handoff_revision)
|
|
472
|
+
tx.guard_agent!(agent_id)
|
|
473
|
+
unless tx.retentions.list(agent_id).empty?
|
|
474
|
+
raise Phronomy::AgentBusyError, "Agent #{agent_id} is retained by durable coordination history"
|
|
444
475
|
end
|
|
476
|
+
tx.cancellations.delete_for_agent(agent_id)
|
|
445
477
|
tx.journals.delete(agent_id)
|
|
446
478
|
tx.executions.delete_for_agent(agent_id)
|
|
447
479
|
tx.agents.delete(agent_id)
|
|
448
480
|
end
|
|
449
481
|
rescue Phronomy::AgentBusyError,
|
|
450
|
-
Phronomy::
|
|
451
|
-
Phronomy::
|
|
452
|
-
Phronomy::
|
|
482
|
+
Phronomy::Persistence::ConflictError,
|
|
483
|
+
Phronomy::Persistence::NotFoundError,
|
|
484
|
+
Phronomy::Persistence::SerializationError,
|
|
453
485
|
ArgumentError
|
|
454
486
|
registry.abort_purge(self, token)
|
|
455
487
|
raise
|
|
@@ -532,7 +564,7 @@ module Phronomy
|
|
|
532
564
|
|
|
533
565
|
# @api private
|
|
534
566
|
def __release_runtime_owner!(runtime)
|
|
535
|
-
return self if @_phronomy_runtime_owner_state
|
|
567
|
+
return self if %i[purged unloaded].include?(@_phronomy_runtime_owner_state)
|
|
536
568
|
return self unless @_phronomy_runtime_owner.equal?(runtime)
|
|
537
569
|
|
|
538
570
|
@_phronomy_runtime_owner_state = :released
|
|
@@ -560,14 +592,19 @@ module Phronomy
|
|
|
560
592
|
load_existing:
|
|
561
593
|
)
|
|
562
594
|
@persistence = persistence ||
|
|
563
|
-
Phronomy.
|
|
595
|
+
Phronomy::Agent::Settings.current.agent_store ||
|
|
564
596
|
DefaultPersistence.build
|
|
565
597
|
@agent_id = agent_id.to_s.freeze
|
|
566
598
|
|
|
567
599
|
if load_existing
|
|
568
600
|
root = records = nil
|
|
569
601
|
@persistence.transaction do |tx|
|
|
570
|
-
|
|
602
|
+
begin
|
|
603
|
+
root = tx.agents.load(@agent_id)
|
|
604
|
+
rescue Phronomy::Persistence::NotFoundError => error
|
|
605
|
+
raise if error.is_a?(Phronomy::AgentNotFoundError)
|
|
606
|
+
raise Phronomy::AgentNotFoundError.new(agent_id: @agent_id), cause: error
|
|
607
|
+
end
|
|
571
608
|
records = tx.journals.read(
|
|
572
609
|
@agent_id,
|
|
573
610
|
limit: root.journal_position
|
|
@@ -607,7 +644,7 @@ module Phronomy
|
|
|
607
644
|
def create_agent_root!(context:, knowledge:, metadata:)
|
|
608
645
|
definition = self.class.agent_definition
|
|
609
646
|
state_writer.create_root(
|
|
610
|
-
definition: definition, context: context, knowledge: knowledge, metadata: metadata
|
|
647
|
+
definition: definition, context: context, knowledge: knowledge, metadata: metadata, retention: @initial_retention
|
|
611
648
|
)
|
|
612
649
|
end
|
|
613
650
|
|
|
@@ -644,11 +681,13 @@ module Phronomy
|
|
|
644
681
|
public
|
|
645
682
|
|
|
646
683
|
def tool_approval_policy(&block)
|
|
647
|
-
|
|
648
|
-
|
|
684
|
+
__with_operation do
|
|
685
|
+
__assert_live_agent!
|
|
686
|
+
raise ArgumentError, "tool_approval_policy requires a block" unless block
|
|
649
687
|
|
|
650
|
-
|
|
651
|
-
|
|
688
|
+
_approval_configuration_mutex.synchronize { @tool_approval_policy = block }
|
|
689
|
+
self
|
|
690
|
+
end
|
|
652
691
|
end
|
|
653
692
|
|
|
654
693
|
private
|
|
@@ -659,6 +698,8 @@ module Phronomy
|
|
|
659
698
|
true
|
|
660
699
|
when :purged
|
|
661
700
|
raise Phronomy::AgentPurgedError, "Agent #{agent_id.inspect} has been purged"
|
|
701
|
+
when :unloaded
|
|
702
|
+
raise Phronomy::AgentUnloadedError.new(agent_id: agent_id)
|
|
662
703
|
when :purging
|
|
663
704
|
raise Phronomy::Error, "Agent #{agent_id.inspect} is being purged"
|
|
664
705
|
when :recovery_required
|
|
@@ -708,7 +749,7 @@ module Phronomy
|
|
|
708
749
|
end
|
|
709
750
|
|
|
710
751
|
def _check_event_loop_reentrancy(sync_method, async_method)
|
|
711
|
-
if Phronomy::
|
|
752
|
+
if Phronomy::WaitPolicy.blocking_forbidden?
|
|
712
753
|
raise Phronomy::EventLoopReentrancyError,
|
|
713
754
|
"#{self.class.name}##{sync_method} cannot run on the EventLoop thread. " \
|
|
714
755
|
"Use #{async_method} and return immediately."
|
|
@@ -716,19 +757,15 @@ module Phronomy
|
|
|
716
757
|
end
|
|
717
758
|
|
|
718
759
|
def _complete_result_task(task, result)
|
|
760
|
+
task.finish_operation! if task.respond_to?(:finish_operation!)
|
|
719
761
|
task.complete(result)
|
|
720
762
|
end
|
|
721
763
|
|
|
722
764
|
def _fail_result_task(task, error)
|
|
765
|
+
task.finish_operation! if task.respond_to?(:finish_operation!)
|
|
723
766
|
task.fail(error)
|
|
724
767
|
end
|
|
725
768
|
|
|
726
|
-
def _translated_error(error)
|
|
727
|
-
translate_and_reraise!(error)
|
|
728
|
-
rescue => translated
|
|
729
|
-
translated
|
|
730
|
-
end
|
|
731
|
-
|
|
732
769
|
def _deliver_stream_event(listener, event)
|
|
733
770
|
return unless listener
|
|
734
771
|
|
|
@@ -772,7 +809,7 @@ module Phronomy
|
|
|
772
809
|
end
|
|
773
810
|
|
|
774
811
|
def _warn_stream_callback_error(message)
|
|
775
|
-
logger = Phronomy.
|
|
812
|
+
logger = Phronomy::RuntimeSettings.current.logger
|
|
776
813
|
unless logger
|
|
777
814
|
_kernel_warn_safely(message)
|
|
778
815
|
return
|
|
@@ -820,36 +857,28 @@ module Phronomy
|
|
|
820
857
|
meta
|
|
821
858
|
end
|
|
822
859
|
|
|
823
|
-
def
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
projection.system,
|
|
828
|
-
cache: projection.model_config["cache_instructions"],
|
|
829
|
-
provider: projection.model_config["provider"]
|
|
830
|
-
)
|
|
831
|
-
end
|
|
832
|
-
projection.tool_classes.each do |tool_class|
|
|
833
|
-
chat.with_tools(prepare_tool_class(tool_class, invocation: invocation))
|
|
860
|
+
def prepare_runtime_input(projection, invocation:)
|
|
861
|
+
tools = projection.tool_classes.map do |tool|
|
|
862
|
+
prepared = prepare_tool_class(tool, invocation: invocation)
|
|
863
|
+
prepared.is_a?(Class) ? prepared.new : prepared
|
|
834
864
|
end
|
|
835
|
-
|
|
836
|
-
|
|
865
|
+
invocation.tools = tools.to_h { |tool| [tool.name.to_sym, tool] }.freeze
|
|
866
|
+
invocation.messages = projection.messages.dup
|
|
867
|
+
invocation
|
|
837
868
|
end
|
|
838
869
|
|
|
839
|
-
def
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
}
|
|
846
|
-
RuntimeChatBuilder.build(config)
|
|
870
|
+
def build_llm_request(projection, invocation:)
|
|
871
|
+
definitions = Phronomy::Tool::DefinitionSet.build(tools: invocation.tools.values).definitions
|
|
872
|
+
Phronomy::LLMAdapter::Request.new(
|
|
873
|
+
model_config: projection.model_config, system: projection.system,
|
|
874
|
+
messages: invocation.messages, tools: definitions, message: projection.ask_message
|
|
875
|
+
)
|
|
847
876
|
end
|
|
848
877
|
|
|
849
878
|
def build_instructions(input)
|
|
850
879
|
instr = self.class.instructions
|
|
851
880
|
case instr
|
|
852
|
-
when Phronomy::
|
|
881
|
+
when Phronomy::Context::PromptTemplate
|
|
853
882
|
vars = input.is_a?(Hash) ? input : {input: input}
|
|
854
883
|
instr.format_system(**vars) || instr.format(**vars)
|
|
855
884
|
when String then instr
|
|
@@ -858,10 +887,6 @@ module Phronomy
|
|
|
858
887
|
end
|
|
859
888
|
end
|
|
860
889
|
|
|
861
|
-
def apply_instructions(chat, text, cache: false, provider: nil)
|
|
862
|
-
RuntimeChatBuilder.apply_instructions(chat, text, cache: cache, provider: provider)
|
|
863
|
-
end
|
|
864
|
-
|
|
865
890
|
def extract_message(input)
|
|
866
891
|
case input
|
|
867
892
|
when String then input
|
|
@@ -884,6 +909,14 @@ module Phronomy
|
|
|
884
909
|
raise Phronomy::CancellationError, message
|
|
885
910
|
end
|
|
886
911
|
|
|
912
|
+
def tool_definition_set(additional_tools: [])
|
|
913
|
+
runtime_tools = (self.class.tools + Array(additional_tools)).freeze
|
|
914
|
+
Phronomy::Tool::DefinitionSet.build(
|
|
915
|
+
tools: runtime_tools.map { |tool| prepare_tool_class(tool) },
|
|
916
|
+
runtime_tools: runtime_tools
|
|
917
|
+
)
|
|
918
|
+
end
|
|
919
|
+
|
|
887
920
|
def prepare_tool_class(tool_class, invocation: nil)
|
|
888
921
|
return tool_class unless tool_class.is_a?(Class)
|
|
889
922
|
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Phronomy
|
|
4
|
+
module Agent
|
|
5
|
+
module BeforeLLMInput
|
|
6
|
+
def self.included(base)
|
|
7
|
+
base.extend(ClassMethods)
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
module ClassMethods
|
|
11
|
+
def before_llm_input(callable = nil, &block)
|
|
12
|
+
if callable.nil? && !block_given?
|
|
13
|
+
@before_llm_input
|
|
14
|
+
else
|
|
15
|
+
@before_llm_input = callable || block
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def _before_llm_input = @before_llm_input
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def before_llm_input
|
|
23
|
+
__with_operation(read_only: true) { @before_llm_input }
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def before_llm_input=(value)
|
|
27
|
+
__with_operation { @before_llm_input = value }
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
private
|
|
31
|
+
|
|
32
|
+
def run_before_llm_input_hooks(call_sequence:, config:)
|
|
33
|
+
hooks = [
|
|
34
|
+
Phronomy::Agent::Settings.current.before_llm_input,
|
|
35
|
+
self.class._before_llm_input,
|
|
36
|
+
@before_llm_input
|
|
37
|
+
].compact
|
|
38
|
+
return Phronomy::Context::LLMInputPatch.empty if hooks.empty?
|
|
39
|
+
|
|
40
|
+
definition = self.class.agent_definition
|
|
41
|
+
context = Phronomy::Context::LLMInputBuildContext.new(
|
|
42
|
+
agent_id: agent_id,
|
|
43
|
+
agent_definition_id: definition.fetch(:id),
|
|
44
|
+
agent_definition_version: definition.fetch(:version),
|
|
45
|
+
config: config,
|
|
46
|
+
call_sequence: call_sequence
|
|
47
|
+
)
|
|
48
|
+
model_patch = {}
|
|
49
|
+
segments = []
|
|
50
|
+
|
|
51
|
+
hooks.each do |hook|
|
|
52
|
+
result = hook.call(context)
|
|
53
|
+
check_cancellation!(config, "invocation cancelled during before_llm_input hook")
|
|
54
|
+
next if result.nil?
|
|
55
|
+
unless result.is_a?(Phronomy::Context::LLMInputPatch)
|
|
56
|
+
raise TypeError,
|
|
57
|
+
"before_llm_input must return Phronomy::Context::LLMInputPatch or nil, got #{result.class}"
|
|
58
|
+
end
|
|
59
|
+
model_patch.merge!(result.model_config_patch) if result.model_config_patch
|
|
60
|
+
segments.concat(Array(result.segment_candidates))
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
Phronomy::Context::LLMInputPatch.new(
|
|
64
|
+
model_config_patch: model_patch.empty? ? nil : model_patch,
|
|
65
|
+
segment_candidates: segments.empty? ? nil : segments
|
|
66
|
+
)
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
end
|
|
@@ -18,7 +18,7 @@ module Phronomy
|
|
|
18
18
|
raise ArgumentError, "Provide either on_event: or a block, not both"
|
|
19
19
|
end
|
|
20
20
|
|
|
21
|
-
persistence = Phronomy::
|
|
21
|
+
persistence = Phronomy::PersistenceComposition.agent
|
|
22
22
|
agent = definition.create(
|
|
23
23
|
context: context,
|
|
24
24
|
knowledge: knowledge,
|
|
@@ -43,7 +43,7 @@ module Phronomy
|
|
|
43
43
|
"source_sequence" => record.sequence
|
|
44
44
|
)
|
|
45
45
|
|
|
46
|
-
|
|
46
|
+
Phronomy::Context::Candidate.new(
|
|
47
47
|
candidate_id: "record:#{record.record_id}",
|
|
48
48
|
source_kind: source_kind,
|
|
49
49
|
category: record.kind,
|
|
@@ -55,7 +55,7 @@ module Phronomy
|
|
|
55
55
|
llm_call_id: record.llm_call_id,
|
|
56
56
|
tool_call_id: tool_call_id,
|
|
57
57
|
sequence: sequence,
|
|
58
|
-
constraint:
|
|
58
|
+
constraint: Phronomy::Context::Constraint.selectable(origin: :context_policy),
|
|
59
59
|
priority: (source_kind == :working) ? 100 : 0,
|
|
60
60
|
metadata: metadata
|
|
61
61
|
)
|