phronomy 0.25.0 → 0.27.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/CHANGELOG.md +71 -0
- data/CONTRIBUTING.md +4 -4
- data/README.md +14 -7
- data/VERIFY.sh +27 -27
- data/benchmark/bench_agent_invoke.rb +26 -22
- data/benchmark/bench_context_assembler.rb +4 -5
- data/benchmark/bench_regression.rb +1 -1
- data/docs/architecture/agent-chat-and-state-ownership.md +147 -0
- data/docs/architecture/agent-configuration-and-tool-binding.md +139 -0
- data/docs/architecture/agent-context.md +5 -3
- data/docs/architecture/agent-transition-ownership.md +89 -0
- data/docs/architecture/before-llm-input.md +6 -0
- data/docs/architecture/context-management.md +30 -0
- data/docs/architecture/context-preparation-steps.md +90 -0
- data/docs/architecture/entry-action-and-team-wording.md +72 -0
- data/docs/architecture/execution-metadata-and-values.md +80 -0
- data/docs/architecture/generator-verifier-ownership.md +111 -0
- data/docs/architecture/multi-agent-handoff.md +8 -2
- data/docs/architecture/persistence-refactoring-plan.md +50 -0
- data/docs/architecture/persistence.md +29 -6
- data/docs/architecture/refactoring-closure.md +334 -0
- data/docs/architecture/remaining-refactoring-plan.md +374 -0
- data/docs/architecture/rubyllm-2-token-ownership.md +82 -0
- data/docs/architecture/tool-schema-recording-gap.md +50 -0
- data/docs/architecture/tracing.md +4 -4
- data/docs/architecture/workflow-terminal-ownership-design.md +104 -0
- data/docs/architecture.md +209 -0
- data/docs/async-composition.md +205 -0
- data/docs/decisions/010-cooperative-first-concurrency.md +23 -23
- data/docs/decisions/014-unified-persistence-durable-state.md +11 -0
- data/docs/decisions/024-event-loop-single-writer-agent-runtime.md +5 -1
- data/docs/decisions/025-process-local-agent-ownership-and-runtime-admission.md +13 -3
- data/docs/decisions/026-workflow-runtime-admission-and-durable-terminal-barrier.md +5 -1
- data/docs/decisions/030-agent-handoff-domain-and-durable-responsibility.md +5 -0
- data/docs/decisions/031-durable-multi-agent-coordination.md +5 -0
- data/docs/decisions/032-storage-backend-composition.md +80 -0
- data/docs/decisions/033-domain-persistence-ownership.md +79 -0
- data/docs/decisions/034-handoff-runner-coordination-ownership.md +76 -0
- data/docs/decisions/035-tool-executor-capability-ownership.md +68 -0
- data/docs/decisions/036-context-contract-ownership.md +86 -0
- data/docs/decisions/037-common-definition-ownership.md +62 -0
- data/docs/decisions/038-responsibility-based-source-layout.md +131 -0
- data/docs/decisions/039-runtime-configuration-lifecycle-ownership.md +74 -0
- data/docs/decisions/040-configuration-default-composition.md +94 -0
- data/docs/decisions/041-feature-owned-identity-registries.md +100 -0
- data/docs/decisions/042-feature-owned-execution-state.md +106 -0
- data/docs/decisions/043-storage-execution-constraint-notifications.md +75 -0
- data/docs/decisions/044-agent-default-and-one-shot-composition.md +106 -0
- data/docs/decisions/045-worker-input-restriction-ownership.md +100 -0
- data/docs/decisions/046-agent-responsibility-layout-and-shared-records.md +110 -0
- data/docs/decisions/047-recovered-execution-continuation-contract.md +116 -0
- data/docs/decisions/048-dispatch-preparation-worker-ownership.md +120 -0
- data/docs/decisions/049-initial-preparation-worker-ownership.md +111 -0
- data/docs/decisions/050-approval-resume-snapshot-and-commit-ownership.md +98 -0
- data/docs/decisions/051-execution-outcome-worker-ownership.md +151 -0
- data/docs/decisions/052-tool-invocation-restoration-ownership.md +92 -0
- data/docs/decisions/053-shared-state-coordination-ownership.md +71 -0
- data/docs/decisions/054-workflow-terminal-save-single-owner.md +76 -0
- data/docs/decisions/055-terminal-observer-failure-settlement.md +60 -0
- data/docs/decisions/056-workflow-terminal-policy-ownership.md +87 -0
- data/docs/decisions/057-storage-transaction-boundaries.md +73 -0
- data/docs/decisions/058-neutral-storage-primitives.md +78 -0
- data/docs/decisions/README.md +35 -6
- data/docs/design/durable-semantic-coordination/IMPLEMENTATION_DESIGN_V2.md +6 -0
- data/docs/design/durable-semantic-coordination/IMPLEMENTATION_REPORT.md +6 -0
- data/docs/features.md +21 -12
- data/docs/getting-started.md +10 -10
- data/docs/migrations/0.15.md +5 -0
- data/docs/migrations/durable-semantic-coordination-v2.md +7 -1
- data/docs/migrations/handoff-runner-multi-agent.md +35 -0
- data/docs/migrations/neutral-storage-spi.md +43 -0
- data/docs/migrations/parallel-tool-chat-removal.md +49 -0
- data/docs/migrations/shared-state-multi-agent.md +44 -0
- data/docs/migrations/storage-backend-composition.md +117 -0
- data/docs/migrations/storage-transaction-boundaries.md +74 -0
- data/docs/persistence-backends.md +162 -204
- data/docs/runtime-and-concurrency.md +205 -60
- data/lib/phronomy/agent/api/agent.rb +17 -0
- data/lib/phronomy/agent/async_event_api.rb +2 -2
- data/lib/phronomy/agent/base.rb +55 -251
- data/lib/phronomy/{agent.rb → agent/composition/run_once.rb} +4 -13
- data/lib/phronomy/agent/context/capability/base.rb +67 -26
- data/lib/phronomy/agent/context/capability/tool_executor.rb +62 -0
- data/lib/phronomy/agent/{context_assembler.rb → context_assembly/context_assembler.rb} +143 -88
- data/lib/phronomy/agent/{context_importer.rb → context_assembly/context_importer.rb} +2 -2
- data/lib/phronomy/agent/{ruby_llm_materializer.rb → context_assembly/ruby_llm_materializer.rb} +4 -7
- data/lib/phronomy/agent/context_assembly/runtime_chat_builder.rb +36 -0
- data/lib/phronomy/agent/context_assembly/saved_context_reader.rb +53 -0
- data/lib/phronomy/agent/context_assembly/state_writer.rb +165 -0
- data/lib/phronomy/agent/context_assembly/token_budget_resolver.rb +22 -0
- data/lib/phronomy/agent/{context_plan.rb → context_contract/context_plan.rb} +1 -1
- data/lib/phronomy/agent/{context_policy_input.rb → context_contract/context_policy_input.rb} +6 -6
- data/lib/phronomy/agent/{llm_input_build_context.rb → context_contract/llm_input_build_context.rb} +1 -1
- data/lib/phronomy/agent/{llm_input_manifest.rb → context_contract/llm_input_manifest.rb} +20 -20
- data/lib/phronomy/agent/{llm_input_patch.rb → context_contract/llm_input_patch.rb} +2 -2
- data/lib/phronomy/agent/{agent_execution.rb → execution/agent_execution.rb} +8 -4
- data/lib/phronomy/agent/{agent_invocation.rb → execution/agent_invocation.rb} +8 -13
- data/lib/phronomy/agent/{agent_invocation_session_builder.rb → execution/agent_invocation_session_builder.rb} +20 -96
- data/lib/phronomy/agent/execution/approval_resume_commit.rb +108 -0
- data/lib/phronomy/agent/execution/dispatch_preparation.rb +305 -0
- data/lib/phronomy/agent/{exact_execution.rb → execution/exact_execution.rb} +12 -13
- data/lib/phronomy/agent/{execution_cancellation.rb → execution/execution_cancellation.rb} +2 -3
- data/lib/phronomy/agent/execution/execution_coordinator.rb +1925 -0
- data/lib/phronomy/agent/execution/execution_failure.rb +30 -0
- data/lib/phronomy/agent/execution/execution_metadata.rb +53 -0
- data/lib/phronomy/agent/execution/execution_outcome_committer.rb +344 -0
- data/lib/phronomy/agent/execution/execution_registry.rb +459 -0
- data/lib/phronomy/agent/execution/execution_session_runner.rb +118 -0
- data/lib/phronomy/agent/execution/initial_preparation.rb +421 -0
- data/lib/phronomy/agent/execution/invocation_transitions.rb +86 -0
- data/lib/phronomy/agent/{phase_machine_builder.rb → execution/phase_machine_builder.rb} +22 -73
- data/lib/phronomy/agent/{provider_call_outcome.rb → execution/provider_call_outcome.rb} +9 -9
- data/lib/phronomy/agent/execution/runtime_record_encoder.rb +210 -0
- data/lib/phronomy/agent/{handoff_context.rb → handoff/handoff_context.rb} +2 -2
- data/lib/phronomy/agent/handoff/handoff_execution_coordinator.rb +15 -0
- data/lib/phronomy/agent/handoff/handoff_outcome_committer.rb +131 -0
- data/lib/phronomy/agent/{handoff_state.rb → handoff/handoff_state.rb} +1 -1
- data/lib/phronomy/agent/{journal_projection.rb → journal/journal_projection.rb} +4 -0
- data/lib/phronomy/agent/{journal_record.rb → journal/journal_record.rb} +3 -3
- data/lib/phronomy/agent/{llm_call_record.rb → journal/llm_call_record.rb} +2 -2
- data/lib/phronomy/agent/{agent_root.rb → lifecycle/agent_root.rb} +6 -2
- data/lib/phronomy/agent/lifecycle/default_persistence.rb +29 -0
- data/lib/phronomy/{engine/runtime/agent_ownership_registry.rb → agent/lifecycle/ownership_registry.rb} +24 -10
- data/lib/phronomy/{agent_already_exists_error.rb → agent/lifecycle_contract/agent_already_exists_error.rb} +2 -0
- data/lib/phronomy/{agent_busy_error.rb → agent/lifecycle_contract/agent_busy_error.rb} +2 -0
- data/lib/phronomy/{agent_purged_error.rb → agent/lifecycle_contract/agent_purged_error.rb} +2 -0
- data/lib/phronomy/agent/lifecycle_contract/handoff_error.rb +7 -0
- data/lib/phronomy/{stream_callback_error.rb → agent/lifecycle_contract/stream_callback_error.rb} +2 -0
- data/lib/phronomy/agent/persistence/agent_repository.rb +61 -0
- data/lib/phronomy/agent/persistence/codec.rb +358 -0
- data/lib/phronomy/agent/persistence/execution_repository.rb +108 -0
- data/lib/phronomy/agent/persistence/handoff_state_repository.rb +58 -0
- data/lib/phronomy/agent/persistence/journal_repository.rb +54 -0
- data/lib/phronomy/agent/persistence/queries.rb +61 -0
- data/lib/phronomy/agent/persistence/storage_schema.rb +24 -0
- data/lib/phronomy/agent/persistence/watermark.rb +27 -0
- data/lib/phronomy/agent/recovery/invocation_restorer.rb +132 -0
- data/lib/phronomy/agent/{recovery_coordinator → recovery/recovery_coordinator}/continuation.rb +21 -45
- data/lib/phronomy/agent/{recovery_coordinator → recovery/recovery_coordinator}/installation.rb +36 -41
- data/lib/phronomy/agent/{recovery_coordinator → recovery/recovery_coordinator}/resolution.rb +37 -40
- data/lib/phronomy/agent/{recovery_coordinator.rb → recovery/recovery_coordinator.rb} +9 -13
- data/lib/phronomy/agent/recovery/recovery_support.rb +227 -0
- data/lib/phronomy/agent/selection/candidate.rb +1 -1
- data/lib/phronomy/agent/{approval_evaluation_request.rb → tool_execution/approval_evaluation_request.rb} +1 -12
- data/lib/phronomy/agent/{tool_approval_request.rb → tool_execution/tool_approval_request.rb} +1 -10
- data/lib/phronomy/agent/tool_execution/tool_binding.rb +90 -0
- data/lib/phronomy/agent/{tool_call_intercepted.rb → tool_execution/tool_call_intercepted.rb} +2 -2
- data/lib/phronomy/agent/{tool_definition_set.rb → tool_execution/tool_definition_set.rb} +9 -4
- data/lib/phronomy/agent/{tool_invocation.rb → tool_execution/tool_invocation.rb} +69 -34
- data/lib/phronomy/agent/{tool_invocation_session_builder.rb → tool_execution/tool_invocation_session_builder.rb} +2 -2
- data/lib/phronomy/common/configuration_error.rb +7 -0
- data/lib/phronomy/common/error.rb +5 -0
- data/lib/phronomy/{agent → common/values}/immutable.rb +9 -1
- data/lib/phronomy/common/values/serializable.rb +32 -0
- data/lib/phronomy/{configuration.rb → configuration/configuration.rb} +14 -5
- data/lib/phronomy/configuration/global_configuration.rb +26 -0
- data/lib/phronomy/content_store/storage_schema.rb +11 -0
- data/lib/phronomy/content_store/stored_contents.rb +43 -0
- data/lib/phronomy/engine/backpressure_error.rb +7 -0
- data/lib/phronomy/{blocking.rb → engine/blocking.rb} +15 -8
- data/lib/phronomy/engine/cancellation_error.rb +7 -0
- data/lib/phronomy/engine/concurrency/cancellation_token.rb +4 -0
- data/lib/phronomy/engine/concurrency/offload_pool.rb +29 -16
- data/lib/phronomy/engine/concurrency/operation_binding.rb +43 -0
- data/lib/phronomy/engine/concurrency/physical_completion_task.rb +4 -62
- data/lib/phronomy/engine/concurrency/result_collector.rb +99 -0
- data/lib/phronomy/engine/concurrency/result_composition.rb +145 -0
- data/lib/phronomy/engine/concurrency/subscriptions.rb +68 -0
- data/lib/phronomy/engine/concurrency/worker_input_restricted.rb +14 -0
- data/lib/phronomy/engine/event_loop.rb +160 -626
- data/lib/phronomy/engine/event_loop_reentrancy_error.rb +8 -0
- data/lib/phronomy/engine/execution.rb +229 -0
- data/lib/phronomy/engine/execution_cancellation_error.rb +14 -0
- data/lib/phronomy/engine/execution_receiver.rb +65 -0
- data/lib/phronomy/engine/execution_timeout_error.rb +14 -0
- data/lib/phronomy/engine/fsm_protocol.rb +14 -0
- data/lib/phronomy/engine/fsm_session.rb +38 -31
- data/lib/phronomy/{invalid_async_entry_action_error.rb → engine/invalid_async_entry_action_error.rb} +3 -1
- data/lib/phronomy/{invalid_async_transition_action_error.rb → engine/invalid_async_transition_action_error.rb} +3 -1
- data/lib/phronomy/{invalid_async_workflow_action_error.rb → engine/invalid_async_workflow_action_error.rb} +3 -1
- data/lib/phronomy/{invocation_context.rb → engine/invocation_context.rb} +13 -1
- data/lib/phronomy/engine/pool_shutdown_error.rb +7 -0
- data/lib/phronomy/engine/recursion_limit_error.rb +7 -0
- data/lib/phronomy/engine/runtime/timer_queue.rb +11 -0
- data/lib/phronomy/engine/runtime.rb +80 -84
- data/lib/phronomy/engine/runtime_shutdown_error.rb +7 -0
- data/lib/phronomy/engine/runtime_shutdown_reentrancy_error.rb +7 -0
- data/lib/phronomy/engine/scheduler_reentrancy_error.rb +9 -0
- data/lib/phronomy/engine/{task.rb → task_result.rb} +101 -42
- data/lib/phronomy/engine/timeout_error.rb +7 -0
- data/lib/phronomy/filter/contract/filter_block_error.rb +14 -0
- data/lib/phronomy/generation/generator_verifier/agent_result_receiver.rb +89 -0
- data/lib/phronomy/generation/generator_verifier/pipeline_state.rb +57 -0
- data/lib/phronomy/generation/generator_verifier/workflow_builder.rb +112 -0
- data/lib/phronomy/generation/generator_verifier.rb +118 -0
- data/lib/phronomy/generation/low_confidence_error.rb +14 -0
- data/lib/phronomy/llm_adapter/base.rb +2 -2
- data/lib/phronomy/llm_context_window/token_budget.rb +6 -7
- data/lib/phronomy/llm_contract/authentication_error.rb +7 -0
- data/lib/phronomy/{context_budget_exceeded_error.rb → llm_contract/context_budget_exceeded_error.rb} +2 -0
- data/lib/phronomy/llm_contract/context_length_error.rb +7 -0
- data/lib/phronomy/llm_contract/rate_limit_error.rb +7 -0
- data/lib/phronomy/{token_usage.rb → llm_contract/token_usage.rb} +2 -2
- data/lib/phronomy/llm_contract/transport_error.rb +7 -0
- data/lib/phronomy/multi_agent/admission_registry.rb +22 -2
- data/lib/phronomy/multi_agent/durable_subagent_coordinator.rb +8 -8
- data/lib/phronomy/{agent → multi_agent}/handoff_runner.rb +18 -17
- data/lib/phronomy/multi_agent/orchestrator.rb +36 -68
- data/lib/phronomy/multi_agent/persistence/codec.rb +55 -0
- data/lib/phronomy/multi_agent/persistence/queries.rb +30 -0
- data/lib/phronomy/multi_agent/persistence/team_execution_repository.rb +108 -0
- data/lib/phronomy/multi_agent/persistence/team_repository.rb +61 -0
- data/lib/phronomy/{agent → multi_agent}/shared_state.rb +56 -39
- data/lib/phronomy/multi_agent/storage_contract/team_storage_schema.rb +15 -0
- data/lib/phronomy/multi_agent/team_coordinator.rb +21 -18
- data/lib/phronomy/multi_agent/team_execution.rb +1 -1
- data/lib/phronomy/{engine/runtime → multi_agent}/team_ownership_registry.rb +14 -4
- data/lib/phronomy/multi_agent/team_root.rb +1 -1
- data/lib/phronomy/output_parser/contract/parse_error.rb +7 -0
- data/lib/phronomy/persistence/api/persistence.rb +140 -0
- data/lib/phronomy/persistence/migration/initial_format_migration.rb +19 -19
- data/lib/phronomy/persistence_composition/repositories.rb +77 -0
- data/lib/phronomy/persistence_composition/storage_schema.rb +24 -0
- data/lib/phronomy/{execution_rehydration_required_error.rb → recovery/execution_rehydration_required_error.rb} +2 -0
- data/lib/phronomy/{recovery.rb → recovery/recovery.rb} +1 -1
- data/lib/phronomy/runtime_composition/agent_defaults.rb +7 -0
- data/lib/phronomy/runtime_composition/configuration_defaults.rb +9 -0
- data/lib/phronomy/runtime_composition/global_runtime.rb +19 -0
- data/lib/phronomy/storage/backend.rb +101 -0
- data/lib/phronomy/storage/backends/in_memory.rb +157 -0
- data/lib/phronomy/storage/blob_conflict_error.rb +10 -0
- data/lib/phronomy/storage/blobs.rb +31 -0
- data/lib/phronomy/storage/condition.rb +25 -0
- data/lib/phronomy/storage/condition_failed_error.rb +16 -0
- data/lib/phronomy/storage/conflict_error.rb +9 -0
- data/lib/phronomy/{persistence → storage}/durable_record.rb +12 -12
- data/lib/phronomy/storage/entry.rb +33 -0
- data/lib/phronomy/storage/guard_ref.rb +13 -0
- data/lib/phronomy/storage/not_found_error.rb +9 -0
- data/lib/phronomy/storage/record_codec.rb +177 -0
- data/lib/phronomy/storage/records.rb +61 -0
- data/lib/phronomy/storage/resource.rb +126 -0
- data/lib/phronomy/storage/scope.rb +25 -0
- data/lib/phronomy/storage/serialization_error.rb +9 -0
- data/lib/phronomy/storage/streams.rb +44 -0
- data/lib/phronomy/storage/transaction_error.rb +10 -0
- data/lib/phronomy/storage/unique_constraint_error.rb +17 -0
- data/lib/phronomy/storage/unsupported_backend_error.rb +9 -0
- data/lib/phronomy/storage/validation.rb +53 -0
- data/lib/phronomy/storage/view.rb +131 -0
- data/lib/phronomy/testing/eval/scorer/llm_judge.rb +5 -3
- data/lib/phronomy/testing/fake_clock.rb +13 -9
- data/lib/phronomy/testing/persistence_contract/a_content_store.rb +1 -1
- data/lib/phronomy/testing/persistence_contract/a_journal_repository.rb +4 -4
- data/lib/phronomy/testing/persistence_contract/a_persistence_backend.rb +10 -7
- data/lib/phronomy/testing/persistence_contract/a_workflow_state_repository.rb +2 -2
- data/lib/phronomy/testing/persistence_contract/an_agent_repository.rb +6 -6
- data/lib/phronomy/testing/persistence_contract/an_execution_repository.rb +6 -6
- data/lib/phronomy/testing/persistence_contract/coordination_repositories.rb +8 -8
- data/lib/phronomy/testing/persistence_contract/neutral_storage_primitives.rb +263 -0
- data/lib/phronomy/testing/persistence_contract/storage_transaction_boundaries.rb +123 -0
- data/lib/phronomy/testing/persistence_contract.rb +4 -0
- data/lib/phronomy/tool/contract/tool_error.rb +7 -0
- data/lib/phronomy/tools/agent.rb +6 -6
- data/lib/phronomy/vector_store/async_backend.rb +5 -5
- data/lib/phronomy/vector_store/embeddings/base.rb +2 -2
- data/lib/phronomy/version.rb +1 -1
- data/lib/phronomy/{workflow.rb → workflow/execution/workflow.rb} +10 -8
- data/lib/phronomy/{workflow_context.rb → workflow/execution/workflow_context.rb} +4 -0
- data/lib/phronomy/workflow/execution/workflow_context_ownership_error.rb +7 -0
- data/lib/phronomy/workflow/execution/workflow_execution_registry.rb +188 -0
- data/lib/phronomy/{workflow_runner.rb → workflow/execution/workflow_runner.rb} +126 -75
- data/lib/phronomy/workflow/execution/workflow_terminal_policy.rb +40 -0
- data/lib/phronomy/workflow/persistence/codec.rb +153 -0
- data/lib/phronomy/workflow/persistence/state_repository.rb +57 -0
- data/lib/phronomy/workflow/phase_machine_builder.rb +8 -8
- data/lib/phronomy/workflow/storage_contract/workflow_storage_schema.rb +9 -0
- data/lib/phronomy.rb +52 -94
- data/scripts/api_snapshot.rb +4 -2
- data/scripts/storage_spi_snapshot.rb +36 -0
- data/sig/phronomy/agent.rbs +4 -5
- data/sig/phronomy/execution_receiver.rbs +34 -0
- data/sig/phronomy/extensions.rbs +5 -5
- data/sig/phronomy/handoff.rbs +4 -2
- data/sig/phronomy/multi_agent.rbs +19 -3
- data/sig/phronomy/persistence.rbs +7 -91
- data/sig/phronomy/runtime.rbs +34 -7
- data/sig/phronomy/storage.rbs +174 -0
- data/sig/phronomy/tool.rbs +11 -2
- data/sig/phronomy/workflow.rbs +1 -1
- metadata +236 -99
- data/lib/phronomy/agent/execution_coordinator.rb +0 -3138
- data/lib/phronomy/agent/handoff_execution_coordinator.rb +0 -143
- data/lib/phronomy/agent/recovery_support.rb +0 -504
- data/lib/phronomy/agent/token_budget_resolver.rb +0 -70
- data/lib/phronomy/agent/tool_executor.rb +0 -55
- data/lib/phronomy/generator_verifier.rb +0 -369
- data/lib/phronomy/invalid_context_budget_configuration_error.rb +0 -8
- data/lib/phronomy/multi_agent/fan_out_invocation.rb +0 -137
- data/lib/phronomy/multi_agent/fan_out_session_builder.rb +0 -118
- data/lib/phronomy/multi_agent/parallel_tool_chat.rb +0 -116
- data/lib/phronomy/persistence/durable_codec.rb +0 -706
- data/lib/phronomy/persistence/in_memory.rb +0 -690
- data/lib/phronomy/persistence/repository_facades.rb +0 -535
- data/lib/phronomy/persistence.rb +0 -276
- data/lib/phronomy/ruby_llm_patches.rb +0 -24
- data/lib/phronomy/workflow_recovery.rb +0 -123
- /data/lib/phronomy/agent/{context_candidate_resolver.rb → context_assembly/context_candidate_resolver.rb} +0 -0
- /data/lib/phronomy/agent/{context_policy_input_builder.rb → context_assembly/context_policy_input_builder.rb} +0 -0
- /data/lib/phronomy/agent/{context_plan_validator.rb → context_contract/context_plan_validator.rb} +0 -0
- /data/lib/phronomy/agent/{context_policy.rb → context_contract/context_policy.rb} +0 -0
- /data/lib/phronomy/agent/{llm_operation_result.rb → execution/llm_operation_result.rb} +0 -0
- /data/lib/phronomy/agent/{handoff.rb → handoff/handoff.rb} +0 -0
- /data/lib/phronomy/agent/{handoff_capability_factory.rb → handoff/handoff_capability_factory.rb} +0 -0
- /data/lib/phronomy/agent/{handoff_policy.rb → handoff/handoff_policy.rb} +0 -0
- /data/lib/phronomy/agent/{handoff_projection.rb → handoff/handoff_projection.rb} +0 -0
- /data/lib/phronomy/agent/{handoff_request.rb → handoff/handoff_request.rb} +0 -0
- /data/lib/phronomy/{canonical_json.rb → common/canonical_json.rb} +0 -0
- /data/lib/phronomy/{diagnostics.rb → engine/diagnostics.rb} +0 -0
- /data/lib/phronomy/{event.rb → engine/event.rb} +0 -0
- /data/lib/phronomy/{metrics.rb → engine/metrics.rb} +0 -0
- /data/lib/phronomy/{runnable.rb → engine/runnable.rb} +0 -0
data/lib/phronomy.rb
CHANGED
|
@@ -2,12 +2,13 @@
|
|
|
2
2
|
|
|
3
3
|
require "zeitwerk"
|
|
4
4
|
require "ruby_llm"
|
|
5
|
-
require_relative "phronomy/
|
|
5
|
+
require_relative "phronomy/version"
|
|
6
6
|
|
|
7
7
|
loader = Zeitwerk::Loader.for_gem
|
|
8
8
|
loader.inflector.inflect("ruby_llm_embeddings" => "RubyLLMEmbeddings")
|
|
9
9
|
loader.inflector.inflect("rag" => "RAG")
|
|
10
10
|
loader.inflector.inflect("fsm_session" => "FSMSession")
|
|
11
|
+
loader.inflector.inflect("fsm_protocol" => "FSMProtocol")
|
|
11
12
|
loader.inflector.inflect("llm_adapter" => "LLMAdapter")
|
|
12
13
|
loader.inflector.inflect("llm_operation_result" => "LLMOperationResult")
|
|
13
14
|
loader.inflector.inflect("ruby_llm" => "RubyLLM")
|
|
@@ -18,104 +19,61 @@ loader.inflector.inflect("llm_input_manifest" => "LLMInputManifest")
|
|
|
18
19
|
loader.inflector.inflect("llm_input_build_context" => "LLMInputBuildContext")
|
|
19
20
|
loader.inflector.inflect("llm_input_patch" => "LLMInputPatch")
|
|
20
21
|
loader.inflector.inflect("before_llm_input" => "BeforeLLMInput")
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
loader.
|
|
24
|
-
|
|
25
|
-
#
|
|
22
|
+
# These responsibility directories do not add a public Ruby namespace.
|
|
23
|
+
%w[common configuration engine generation llm_contract recovery].each do |directory|
|
|
24
|
+
loader.collapse("#{__dir__}/phronomy/#{directory}")
|
|
25
|
+
end
|
|
26
|
+
# Agent responsibility directories retain the existing Agent constant names.
|
|
27
|
+
%w[
|
|
28
|
+
context_contract lifecycle execution tool_execution context_assembly
|
|
29
|
+
journal handoff recovery
|
|
30
|
+
].each do |directory|
|
|
31
|
+
loader.collapse("#{__dir__}/phronomy/agent/#{directory}")
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
# A nested root is independent of its enclosing Ruby namespace. Keep existing
|
|
35
|
+
# Phronomy::Workflow, Phronomy::WorkflowContext, and other canonical constants
|
|
36
|
+
# beside the feature they belong to, without aliases or a new partial-load API.
|
|
37
|
+
%w[
|
|
38
|
+
agent/api
|
|
39
|
+
agent/lifecycle_contract
|
|
40
|
+
filter/contract
|
|
41
|
+
output_parser/contract
|
|
42
|
+
persistence/api
|
|
43
|
+
tool/contract
|
|
44
|
+
workflow/execution
|
|
45
|
+
workflow/storage_contract
|
|
46
|
+
multi_agent/storage_contract
|
|
47
|
+
].each do |directory|
|
|
48
|
+
loader.push_dir("#{__dir__}/phronomy/#{directory}", namespace: Phronomy)
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
# These files wire composition, reopen namespaces, or patch a dependency.
|
|
52
|
+
loader.ignore(
|
|
53
|
+
"#{__dir__}/phronomy/configuration/global_configuration.rb",
|
|
54
|
+
"#{__dir__}/phronomy/agent/composition",
|
|
55
|
+
"#{__dir__}/phronomy/runtime_composition/agent_defaults.rb",
|
|
56
|
+
"#{__dir__}/phronomy/runtime_composition/configuration_defaults.rb",
|
|
57
|
+
"#{__dir__}/phronomy/runtime_composition/global_runtime.rb"
|
|
58
|
+
)
|
|
59
|
+
# Persistence conformance support must never make production loading require RSpec.
|
|
26
60
|
loader.ignore(
|
|
27
61
|
"#{__dir__}/phronomy/testing/persistence_contract.rb",
|
|
28
62
|
"#{__dir__}/phronomy/testing/persistence_contract"
|
|
29
63
|
)
|
|
30
64
|
loader.setup
|
|
31
65
|
|
|
32
|
-
require_relative "phronomy/
|
|
33
|
-
require_relative "phronomy/token_usage"
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
class Error < StandardError; end
|
|
37
|
-
class ParseError < Error; end
|
|
38
|
-
class RecursionLimitError < Error; end
|
|
39
|
-
class ToolError < Error; end
|
|
40
|
-
class TimeoutError < Error; end
|
|
41
|
-
class ConfigurationError < Error; end
|
|
42
|
-
class HandoffError < Error; end
|
|
43
|
-
|
|
44
|
-
class TransportError < Error; end
|
|
45
|
-
class RateLimitError < TransportError; end
|
|
46
|
-
class AuthenticationError < TransportError; end
|
|
47
|
-
class ContextLengthError < Error; end
|
|
48
|
-
class CancellationError < Error; end
|
|
49
|
-
|
|
50
|
-
# Raised when a synchronous API would block the EventLoop control thread.
|
|
51
|
-
class EventLoopReentrancyError < Error; end
|
|
52
|
-
|
|
53
|
-
# Backward-compatible error class name for callers that still rescue the old
|
|
54
|
-
# scheduler-oriented exception. New code should use EventLoopReentrancyError.
|
|
55
|
-
class SchedulerReentrancyError < EventLoopReentrancyError; end
|
|
66
|
+
require_relative "phronomy/runtime_composition/configuration_defaults"
|
|
67
|
+
require_relative "phronomy/llm_contract/token_usage"
|
|
68
|
+
require_relative "phronomy/configuration/global_configuration"
|
|
69
|
+
require_relative "phronomy/runtime_composition/global_runtime"
|
|
56
70
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
def initialize(result)
|
|
64
|
-
@result = result
|
|
65
|
-
super("Answer confidence #{result.confidence} is below the required threshold")
|
|
66
|
-
end
|
|
67
|
-
end
|
|
68
|
-
|
|
69
|
-
class FilterBlockError < Error
|
|
70
|
-
attr_reader :filter
|
|
71
|
-
|
|
72
|
-
def initialize(message, filter: nil)
|
|
73
|
-
super(message)
|
|
74
|
-
@filter = filter
|
|
75
|
-
end
|
|
76
|
-
end
|
|
77
|
-
|
|
78
|
-
class PoolShutdownError < Error; end
|
|
79
|
-
class BackpressureError < Error; end
|
|
80
|
-
|
|
81
|
-
class WorkflowContextOwnershipError < Error; end
|
|
82
|
-
|
|
83
|
-
class << self
|
|
84
|
-
def configuration
|
|
85
|
-
@configuration ||= Configuration.new
|
|
86
|
-
end
|
|
87
|
-
|
|
88
|
-
def configure
|
|
89
|
-
yield configuration
|
|
90
|
-
end
|
|
91
|
-
|
|
92
|
-
def reset_configuration!
|
|
93
|
-
@configuration = Configuration.new
|
|
94
|
-
end
|
|
95
|
-
|
|
96
|
-
def with_configuration
|
|
97
|
-
original = @configuration&.dup
|
|
98
|
-
yield configuration
|
|
99
|
-
ensure
|
|
100
|
-
@configuration = original
|
|
101
|
-
end
|
|
102
|
-
|
|
103
|
-
def reset_runtime!(timeout: configuration.event_loop_stop_grace_seconds)
|
|
104
|
-
previous_grace = @configuration&.event_loop_stop_grace_seconds
|
|
105
|
-
result = Runtime.reset_default!(timeout: timeout)
|
|
106
|
-
|
|
107
|
-
new_configuration = Configuration.new
|
|
108
|
-
if previous_grace
|
|
109
|
-
new_configuration.event_loop_stop_grace_seconds = previous_grace
|
|
110
|
-
end
|
|
111
|
-
@configuration = new_configuration
|
|
112
|
-
result
|
|
113
|
-
end
|
|
114
|
-
end
|
|
115
|
-
end
|
|
71
|
+
# Explicitly install the Agent namespace extensions even if its factory
|
|
72
|
+
# contract was loaded first. Composition owns both concrete binding and the
|
|
73
|
+
# run_once method definition; neither is required from Agent execution files.
|
|
74
|
+
require_relative "phronomy/agent/api/agent"
|
|
75
|
+
require_relative "phronomy/runtime_composition/agent_defaults"
|
|
76
|
+
require_relative "phronomy/agent/composition/run_once"
|
|
116
77
|
|
|
117
|
-
#
|
|
118
|
-
|
|
119
|
-
# Agent namespace is materialized.
|
|
120
|
-
require_relative "phronomy/recovery"
|
|
121
|
-
require_relative "phronomy/workflow_recovery"
|
|
78
|
+
# Load the common recovery vocabulary during ordinary application loading.
|
|
79
|
+
require_relative "phronomy/recovery/recovery"
|
data/scripts/api_snapshot.rb
CHANGED
|
@@ -36,7 +36,7 @@ PUBLIC_API_ENTRIES = [
|
|
|
36
36
|
# Beta
|
|
37
37
|
Phronomy::Agent::Handoff,
|
|
38
38
|
Phronomy::Agent::HandoffPolicy,
|
|
39
|
-
Phronomy::
|
|
39
|
+
Phronomy::MultiAgent::HandoffRunner,
|
|
40
40
|
Phronomy::MultiAgent::Orchestrator,
|
|
41
41
|
Phronomy::MultiAgent::TeamCoordinator,
|
|
42
42
|
Phronomy::Filter::Base,
|
|
@@ -70,7 +70,9 @@ def snapshot_entry(klass)
|
|
|
70
70
|
"public_instance_methods" => own_methods
|
|
71
71
|
}
|
|
72
72
|
else
|
|
73
|
-
|
|
73
|
+
internal_context_methods = (klass == Phronomy::InvocationContext) ?
|
|
74
|
+
%i[__bind_execution __execution_scope] : []
|
|
75
|
+
instance_methods = (klass.public_instance_methods - BASELINE_INSTANCE_METHODS - internal_context_methods).sort
|
|
74
76
|
class_methods = (klass.public_methods(false) - BASELINE_CLASS_METHODS).sort
|
|
75
77
|
{
|
|
76
78
|
"name" => klass.name,
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
#!/usr/bin/env ruby
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
4
|
+
require "json"
|
|
5
|
+
require_relative "../lib/phronomy"
|
|
6
|
+
|
|
7
|
+
# Explicit SPI 2 scope, independent of the Stable/Beta product API snapshot.
|
|
8
|
+
# Private dispatch and domain composition helpers are deliberately excluded.
|
|
9
|
+
surfaces = {
|
|
10
|
+
Phronomy::Persistence => Phronomy::Persistence.public_instance_methods(false).sort,
|
|
11
|
+
Phronomy::Storage::Backend => %i[initialize capabilities transaction resources view],
|
|
12
|
+
Phronomy::Storage::Backends::InMemory => %i[initialize capabilities],
|
|
13
|
+
Phronomy::Storage::View => %i[records streams blobs check!],
|
|
14
|
+
Phronomy::Storage::Resource => %i[initialize id kind attributes immutable_attributes indexes unique guard validate_attributes index_values],
|
|
15
|
+
Phronomy::Storage::Records => %i[resource insert read fetch replace delete scan delete_matching],
|
|
16
|
+
Phronomy::Storage::Streams => %i[resource append read head delete],
|
|
17
|
+
Phronomy::Storage::Blobs => %i[resource put_if_absent fetch exist?],
|
|
18
|
+
Phronomy::Storage::GuardRef => %i[initialize resource key],
|
|
19
|
+
Phronomy::Storage::Condition::RevisionIs => %i[initialize resource key expected],
|
|
20
|
+
Phronomy::Storage::Condition::StreamHeadIs => %i[initialize resource stream expected],
|
|
21
|
+
Phronomy::Storage::Condition::NoRows => %i[initialize resource index equals],
|
|
22
|
+
Phronomy::Storage::Entry::Record => %i[initialize key revision attributes record],
|
|
23
|
+
Phronomy::Storage::Entry::Stream => %i[initialize position id record],
|
|
24
|
+
Phronomy::Storage::Entry::Append => %i[initialize id record],
|
|
25
|
+
Phronomy::Storage::Entry::Blob => %i[initialize key bytes attributes],
|
|
26
|
+
Phronomy::Storage::UniqueConstraintError => %i[initialize resource constraint],
|
|
27
|
+
Phronomy::Storage::ConditionFailedError => %i[initialize condition]
|
|
28
|
+
}
|
|
29
|
+
snapshot = {spi_version: 2, capabilities: Phronomy::Storage::Backend::REQUIRED_CAPABILITIES,
|
|
30
|
+
surfaces: surfaces.to_h { |type, names| [type.name, names.sort.to_h { |name| [name, type.instance_method(name).parameters] }] }}
|
|
31
|
+
json = JSON.pretty_generate(snapshot) + "\n"
|
|
32
|
+
if ARGV.include?("--write")
|
|
33
|
+
File.write(File.expand_path("../spec/fixtures/storage_spi_v2_snapshot.json", __dir__), json)
|
|
34
|
+
else
|
|
35
|
+
puts json
|
|
36
|
+
end
|
data/sig/phronomy/agent.rbs
CHANGED
|
@@ -190,7 +190,6 @@ module Phronomy
|
|
|
190
190
|
def self.max_iterations: (?Integer value) -> Integer
|
|
191
191
|
def self.cache_instructions: (?bool enabled) -> bool?
|
|
192
192
|
def self.max_output_tokens: (?Integer value) -> Integer?
|
|
193
|
-
def self.context_window: (?Integer value) -> Integer?
|
|
194
193
|
def self.context_policy: () -> ContextPolicy
|
|
195
194
|
| (ContextPolicy policy) -> ContextPolicy
|
|
196
195
|
def self.agent_definition: () -> Hash[Symbol, untyped]
|
|
@@ -213,18 +212,18 @@ module Phronomy
|
|
|
213
212
|
# Public operation methods no longer accept per-invocation event listeners
|
|
214
213
|
# or event-listener blocks.
|
|
215
214
|
def invoke: (untyped input, ?config: Hash[untyped, untyped], ?invocation_context: untyped) -> Hash[Symbol, untyped]
|
|
216
|
-
def invoke_async: (untyped input, ?config: Hash[untyped, untyped], ?invocation_context: untyped) ->
|
|
215
|
+
def invoke_async: (untyped input, ?config: Hash[untyped, untyped], ?invocation_context: untyped) -> TaskResult[Hash[Symbol, untyped]]
|
|
217
216
|
def stream: (untyped input, ?config: Hash[untyped, untyped], ?invocation_context: untyped) -> Hash[Symbol, untyped]
|
|
218
|
-
def stream_async: (untyped input, ?config: Hash[untyped, untyped], ?invocation_context: untyped) ->
|
|
217
|
+
def stream_async: (untyped input, ?config: Hash[untyped, untyped], ?invocation_context: untyped) -> TaskResult[Hash[Symbol, untyped]]
|
|
219
218
|
|
|
220
219
|
def approve: (String execution_id, approval_request_id: String, ?approved: bool, ?config: Hash[untyped, untyped]) -> untyped
|
|
221
|
-
def approve_async: (String execution_id, approval_request_id: String, ?approved: bool, ?config: Hash[untyped, untyped]) ->
|
|
220
|
+
def approve_async: (String execution_id, approval_request_id: String, ?approved: bool, ?config: Hash[untyped, untyped]) -> TaskResult[untyped]
|
|
222
221
|
|
|
223
222
|
# Resolves a factual Recovery ambiguity. result: is meaningful for
|
|
224
223
|
# :succeeded; error: is required for :failed; neither is used by
|
|
225
224
|
# :not_performed.
|
|
226
225
|
def resolve: (String execution_id, expected_execution_revision: Integer, subject: Hash[Symbol, untyped], outcome: Symbol, ?result: untyped, ?error: Exception) -> untyped
|
|
227
|
-
def resolve_async: (String execution_id, expected_execution_revision: Integer, subject: Hash[Symbol, untyped], outcome: Symbol, ?result: untyped, ?error: Exception) ->
|
|
226
|
+
def resolve_async: (String execution_id, expected_execution_revision: Integer, subject: Hash[Symbol, untyped], outcome: Symbol, ?result: untyped, ?error: Exception) -> TaskResult[untyped]
|
|
228
227
|
|
|
229
228
|
def transcript: () -> Array[untyped]
|
|
230
229
|
def add_knowledge: (untyped content, ?metadata: Hash[untyped, untyped]) -> self
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
module Phronomy
|
|
2
|
+
# Internal Engine contract (ADR-042); not an application extension SPI.
|
|
3
|
+
class ExecutionReceiver
|
|
4
|
+
def self.for: (EventLoop event_loop) -> instance
|
|
5
|
+
def self.existing_for: (Runtime runtime) -> instance?
|
|
6
|
+
def initialize: (event_loop: EventLoop) -> void
|
|
7
|
+
def __bound_to?: (EventLoop event_loop) -> bool
|
|
8
|
+
def idle?: () -> bool
|
|
9
|
+
def deliver: (untyped message) -> untyped
|
|
10
|
+
def shutdown: (error: Exception?) -> untyped
|
|
11
|
+
def session_retired: (String fsm_session_id, reason: Symbol) -> untyped
|
|
12
|
+
|
|
13
|
+
private
|
|
14
|
+
|
|
15
|
+
def synchronize: [V] () { () -> V } -> V
|
|
16
|
+
def admit: [V] () { () -> V } -> V
|
|
17
|
+
def post_message: (untyped message, ?admission: bool, ?completion: TaskResult[untyped]?) -> bool
|
|
18
|
+
def assert_event_loop_thread!: () -> void
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
class EventLoop
|
|
22
|
+
def __execution_receiver: (key: untyped) -> ExecutionReceiver?
|
|
23
|
+
def __register_execution_receiver: (key: untyped, receiver: ExecutionReceiver) -> ExecutionReceiver
|
|
24
|
+
def __synchronize_execution_state: [V] () { () -> V } -> V
|
|
25
|
+
def __admit_execution: [V] (ExecutionReceiver receiver) { () -> V } -> V
|
|
26
|
+
def __post_execution: (ExecutionReceiver receiver, untyped message, ?admission: bool, ?completion: TaskResult[untyped]?) -> bool
|
|
27
|
+
def __route_execution_event: (ExecutionReceiver receiver) { () -> untyped } -> bool
|
|
28
|
+
def __receiver_cleanup_complete?: () -> bool
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
class Runtime
|
|
32
|
+
def __event_loop_if_initialized: () -> EventLoop?
|
|
33
|
+
end
|
|
34
|
+
end
|
data/sig/phronomy/extensions.rbs
CHANGED
|
@@ -28,16 +28,16 @@ module Phronomy
|
|
|
28
28
|
def clear: () -> untyped
|
|
29
29
|
def size: () -> Integer
|
|
30
30
|
|
|
31
|
-
def add_async: (id: String, embedding: Array[Float], ?metadata: Hash[untyped, untyped], ?cancellation_token: Concurrency::CancellationToken?, ?timeout: Numeric?) ->
|
|
32
|
-
def search_async: (query_embedding: Array[Float], ?k: Integer, ?cancellation_token: Concurrency::CancellationToken?, ?timeout: Numeric?) ->
|
|
33
|
-
def remove_async: (id: String, ?cancellation_token: Concurrency::CancellationToken?, ?timeout: Numeric?) ->
|
|
34
|
-
def clear_async: (?cancellation_token: Concurrency::CancellationToken?, ?timeout: Numeric?) ->
|
|
31
|
+
def add_async: (id: String, embedding: Array[Float], ?metadata: Hash[untyped, untyped], ?cancellation_token: Concurrency::CancellationToken?, ?timeout: Numeric?) -> TaskResult[untyped]
|
|
32
|
+
def search_async: (query_embedding: Array[Float], ?k: Integer, ?cancellation_token: Concurrency::CancellationToken?, ?timeout: Numeric?) -> TaskResult[Array[Hash[Symbol, untyped]]]
|
|
33
|
+
def remove_async: (id: String, ?cancellation_token: Concurrency::CancellationToken?, ?timeout: Numeric?) -> TaskResult[untyped]
|
|
34
|
+
def clear_async: (?cancellation_token: Concurrency::CancellationToken?, ?timeout: Numeric?) -> TaskResult[untyped]
|
|
35
35
|
end
|
|
36
36
|
|
|
37
37
|
module Embeddings
|
|
38
38
|
class Base
|
|
39
39
|
def embed: (String text, ?Concurrency::CancellationToken? cancellation_token) -> Array[Float]
|
|
40
|
-
def embed_async: (String text, ?Concurrency::CancellationToken? cancellation_token, ?timeout: Numeric?) ->
|
|
40
|
+
def embed_async: (String text, ?Concurrency::CancellationToken? cancellation_token, ?timeout: Numeric?) -> TaskResult[Array[Float]]
|
|
41
41
|
end
|
|
42
42
|
end
|
|
43
43
|
end
|
data/sig/phronomy/handoff.rbs
CHANGED
|
@@ -25,14 +25,16 @@ module Phronomy
|
|
|
25
25
|
def selectable_categories: () -> Array[Symbol]
|
|
26
26
|
def to_h: () -> Hash[String, Hash[String, String]]
|
|
27
27
|
end
|
|
28
|
+
end
|
|
28
29
|
|
|
30
|
+
module MultiAgent
|
|
29
31
|
class HandoffRunner
|
|
30
32
|
MAX_HANDOFFS: Integer
|
|
31
33
|
|
|
32
34
|
attr_reader main_agent: ::Phronomy::Agent::Base
|
|
33
|
-
attr_reader handoffs: Array[Handoff]
|
|
35
|
+
attr_reader handoffs: Array[::Phronomy::Agent::Handoff]
|
|
34
36
|
|
|
35
|
-
def initialize: (main_agent: ::Phronomy::Agent::Base, ?handoffs: Array[Handoff]) -> void
|
|
37
|
+
def initialize: (main_agent: ::Phronomy::Agent::Base, ?handoffs: Array[::Phronomy::Agent::Handoff]) -> void
|
|
36
38
|
def invoke: (untyped input, ?config: Hash[Symbol, untyped]) -> Hash[Symbol, untyped]
|
|
37
39
|
def result: (String execution_id) -> Hash[Symbol, untyped]
|
|
38
40
|
def cancel: (String execution_id) -> Hash[Symbol, untyped]
|
|
@@ -1,13 +1,29 @@
|
|
|
1
1
|
module Phronomy
|
|
2
2
|
module MultiAgent
|
|
3
|
+
class SharedState
|
|
4
|
+
class KnowledgeStore
|
|
5
|
+
def self.new: () -> instance
|
|
6
|
+
def read_all: () -> Array[Hash[Symbol, untyped]]
|
|
7
|
+
def write: (agent: untyped, content: untyped, cycle: untyped) -> nil
|
|
8
|
+
def size: () -> Integer
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def self.new: () -> instance
|
|
12
|
+
def self.member: (singleton(::Phronomy::Agent::Base) klass, ?instruction: untyped) -> Array[Hash[Symbol, untyped]]
|
|
13
|
+
def self.coordination: (?untyped text) -> untyped
|
|
14
|
+
def self.max_cycles: (?untyped value) -> Integer?
|
|
15
|
+
def self.timeout: (?untyped value) -> Float?
|
|
16
|
+
def self.terminate_when: () ?{ (KnowledgeStore) -> untyped } -> untyped
|
|
17
|
+
def self.aggregate: () ?{ (KnowledgeStore) -> untyped } -> untyped
|
|
18
|
+
def invoke: (untyped input, ?config: Hash[Symbol, untyped]) -> Hash[Symbol, untyped]
|
|
19
|
+
end
|
|
20
|
+
|
|
3
21
|
class Orchestrator < ::Phronomy::Agent::Base
|
|
4
22
|
def self.subagent: (Symbol | String name, singleton(::Phronomy::Agent::Base) agent_class, ?on_error: Symbol, ?inherit_knowledge: bool) -> untyped
|
|
5
23
|
def self.registered_subagents: () -> Hash[Symbol | String, untyped]
|
|
6
24
|
def resume: (String execution_id, ?config: Hash[Symbol, untyped]) -> Hash[Symbol, untyped]
|
|
7
25
|
def dispatch_parallel: (*Hash[Symbol, untyped] tasks, ?max_concurrency: Integer?, ?on_error: Symbol, ?timeout: Numeric?, ?cancellation_token: untyped, ?invocation_context: untyped, ?inherit_knowledge: bool) -> Array[untyped]
|
|
8
|
-
def dispatch_parallel_async: (*Hash[Symbol, untyped] tasks, ?max_concurrency: Integer?, ?on_error: Symbol, ?timeout: Numeric?, ?cancellation_token: untyped, ?invocation_context: untyped, ?inherit_knowledge: bool) -> ::Phronomy::
|
|
9
|
-
def fan_out: (agent: singleton(::Phronomy::Agent::Base), inputs: Array[untyped], ?config: Hash[Symbol, untyped], ?max_concurrency: Integer?, ?on_error: Symbol, ?timeout: Numeric?, ?cancellation_token: untyped, ?invocation_context: untyped, ?inherit_knowledge: bool) -> Array[untyped]
|
|
10
|
-
def fan_out_async: (agent: singleton(::Phronomy::Agent::Base), inputs: Array[untyped], ?config: Hash[Symbol, untyped], ?max_concurrency: Integer?, ?on_error: Symbol, ?timeout: Numeric?, ?cancellation_token: untyped, ?invocation_context: untyped, ?inherit_knowledge: bool) -> ::Phronomy::Task[untyped]
|
|
26
|
+
def dispatch_parallel_async: (*Hash[Symbol, untyped] tasks, ?max_concurrency: Integer?, ?on_error: Symbol, ?timeout: Numeric?, ?cancellation_token: untyped, ?invocation_context: untyped, ?inherit_knowledge: bool) -> ::Phronomy::TaskResult[untyped]
|
|
11
27
|
end
|
|
12
28
|
|
|
13
29
|
class TeamCoordinator
|
|
@@ -1,10 +1,4 @@
|
|
|
1
1
|
module Phronomy
|
|
2
|
-
interface _ContentRepository
|
|
3
|
-
def put: (String bytes, canonicalization_version: untyped) -> String
|
|
4
|
-
def fetch: (String content_id) -> String
|
|
5
|
-
def exist?: (String content_id) -> bool
|
|
6
|
-
end
|
|
7
|
-
|
|
8
2
|
# Runtime/domain-facing repository interfaces.
|
|
9
3
|
interface _AgentRepository
|
|
10
4
|
def create: (untyped root) -> untyped
|
|
@@ -40,37 +34,6 @@ module Phronomy
|
|
|
40
34
|
# Backend-side record repository interfaces. DurableRecord is the opaque data
|
|
41
35
|
# carrier. Identity/revision/index metadata is passed separately so backends do
|
|
42
36
|
# not need to interpret DurableRecord#payload.
|
|
43
|
-
interface _BackendAgentRecordRepository
|
|
44
|
-
def create: (agent_id: String, agent_revision: Integer, record: Persistence::DurableRecord) -> Persistence::DurableRecord
|
|
45
|
-
def load: (String agent_id) -> Persistence::DurableRecord
|
|
46
|
-
def save: (String agent_id, expected_revision: Integer, next_revision: Integer, record: Persistence::DurableRecord) -> Persistence::DurableRecord
|
|
47
|
-
def delete: (String agent_id) -> untyped
|
|
48
|
-
end
|
|
49
|
-
|
|
50
|
-
interface _BackendJournalRecordRepository
|
|
51
|
-
def append: (String agent_id, expected_position: Integer, records: Array[Persistence::DurableRecord], record_ids: Array[String]) -> Array[Persistence::DurableRecord]
|
|
52
|
-
def read: (String agent_id, ?after: Integer?, ?limit: Integer?) -> Array[Persistence::DurableRecord]
|
|
53
|
-
def head: (String agent_id) -> Integer
|
|
54
|
-
def delete: (String agent_id) -> untyped
|
|
55
|
-
end
|
|
56
|
-
|
|
57
|
-
interface _BackendExecutionRecordRepository
|
|
58
|
-
def create_active: (execution_id: String, agent_id: String, execution_revision: Integer, record: Persistence::DurableRecord) -> Persistence::DurableRecord
|
|
59
|
-
def load: (String execution_id) -> Persistence::DurableRecord
|
|
60
|
-
def save: (String execution_id, expected_revision: Integer, next_revision: Integer, agent_id: String, active: bool, record: Persistence::DurableRecord) -> Persistence::DurableRecord
|
|
61
|
-
def list_active: (String agent_id) -> Array[Persistence::DurableRecord]
|
|
62
|
-
def list: (String agent_id, ?after: String?, ?limit: Integer) -> Array[Persistence::DurableRecord]
|
|
63
|
-
def delete: (String execution_id) -> untyped
|
|
64
|
-
def delete_for_agent: (String agent_id) -> untyped
|
|
65
|
-
def assert_idle!: (String agent_id) -> untyped
|
|
66
|
-
end
|
|
67
|
-
|
|
68
|
-
interface _BackendWorkflowStateRecordRepository
|
|
69
|
-
def load: (String workflow_instance_id) -> Persistence::DurableRecord?
|
|
70
|
-
def save: (String workflow_instance_id, expected_revision: Integer?, next_revision: Integer, record: Persistence::DurableRecord) -> Persistence::DurableRecord
|
|
71
|
-
def delete: (String workflow_instance_id, expected_revision: Integer) -> untyped
|
|
72
|
-
end
|
|
73
|
-
|
|
74
37
|
interface _HandoffStateRepository
|
|
75
38
|
def load: (String main_agent_id) -> untyped
|
|
76
39
|
def save: (String main_agent_id, expected_revision: Integer?, state: untyped) -> untyped
|
|
@@ -95,34 +58,6 @@ module Phronomy
|
|
|
95
58
|
def assert_idle!: (String team_id) -> untyped
|
|
96
59
|
end
|
|
97
60
|
|
|
98
|
-
interface _BackendHandoffStateRecordRepository
|
|
99
|
-
def load: (String main_agent_id) -> Persistence::DurableRecord?
|
|
100
|
-
def save: (String main_agent_id, expected_revision: Integer?, next_revision: Integer, active_agent_id: String, record: Persistence::DurableRecord) -> Persistence::DurableRecord
|
|
101
|
-
def delete: (String main_agent_id, expected_revision: Integer) -> untyped
|
|
102
|
-
end
|
|
103
|
-
|
|
104
|
-
interface _BackendTeamRecordRepository
|
|
105
|
-
def create: (team_id: String, team_revision: Integer, record: Persistence::DurableRecord) -> Persistence::DurableRecord
|
|
106
|
-
def load: (String team_id) -> Persistence::DurableRecord
|
|
107
|
-
def save: (String team_id, expected_revision: Integer, next_revision: Integer, record: Persistence::DurableRecord) -> Persistence::DurableRecord
|
|
108
|
-
def delete: (String team_id) -> untyped
|
|
109
|
-
end
|
|
110
|
-
|
|
111
|
-
interface _BackendTeamExecutionRecordRepository
|
|
112
|
-
def create_active: (team_execution_id: String, team_id: String, execution_revision: Integer, record: Persistence::DurableRecord) -> Persistence::DurableRecord
|
|
113
|
-
def load: (String team_execution_id) -> Persistence::DurableRecord
|
|
114
|
-
def save: (String team_execution_id, expected_revision: Integer, next_revision: Integer, team_id: String, active: bool, record: Persistence::DurableRecord) -> Persistence::DurableRecord
|
|
115
|
-
def list_active: (String team_id) -> Array[Persistence::DurableRecord]
|
|
116
|
-
def list: (String team_id, ?after: String?, ?limit: Integer) -> Array[Persistence::DurableRecord]
|
|
117
|
-
def delete: (String team_execution_id) -> untyped
|
|
118
|
-
def delete_for_team: (String team_id) -> untyped
|
|
119
|
-
def assert_idle!: (String team_id) -> untyped
|
|
120
|
-
end
|
|
121
|
-
|
|
122
|
-
interface _BackendWatermark
|
|
123
|
-
def assert_agent_watermark!: (agent_id: String, agent_revision: Integer, journal_position: Integer) -> true
|
|
124
|
-
end
|
|
125
|
-
|
|
126
61
|
interface _PersistenceTransactionView
|
|
127
62
|
def contents: () -> _ContentRepository
|
|
128
63
|
def agents: () -> _AgentRepository
|
|
@@ -136,36 +71,16 @@ module Phronomy
|
|
|
136
71
|
end
|
|
137
72
|
|
|
138
73
|
class Persistence
|
|
139
|
-
class ConflictError < Phronomy::Error
|
|
140
|
-
end
|
|
141
|
-
class NotFoundError < Phronomy::Error
|
|
142
|
-
end
|
|
143
|
-
class UnsupportedBackendError < Phronomy::Error
|
|
144
|
-
end
|
|
145
|
-
class SerializationError < Phronomy::Error
|
|
146
|
-
end
|
|
147
|
-
|
|
148
|
-
class DurableRecord
|
|
149
|
-
FORMAT_VERSION_PATTERN: Regexp
|
|
150
|
-
attr_reader record_type: String
|
|
151
|
-
attr_reader format_version: String
|
|
152
|
-
attr_reader payload: Hash[String, untyped]
|
|
153
|
-
def initialize: (record_type: String, format_version: String, payload: Hash[String, untyped]) -> void
|
|
154
|
-
def copy: () -> DurableRecord
|
|
155
|
-
end
|
|
156
|
-
|
|
157
74
|
module Migration
|
|
158
75
|
module InitialFormatMigration
|
|
159
|
-
def self.agent_root: (Hash[untyped, untyped] hash) -> DurableRecord
|
|
160
|
-
def self.agent_execution: (Hash[untyped, untyped] hash) -> DurableRecord
|
|
161
|
-
def self.journal_record: (Hash[untyped, untyped] hash) -> DurableRecord
|
|
162
|
-
def self.workflow_state: (workflow_instance_id: String, revision: Integer, snapshot: Hash[untyped, untyped]) -> DurableRecord
|
|
76
|
+
def self.agent_root: (Hash[untyped, untyped] hash) -> Storage::DurableRecord
|
|
77
|
+
def self.agent_execution: (Hash[untyped, untyped] hash) -> Storage::DurableRecord
|
|
78
|
+
def self.journal_record: (Hash[untyped, untyped] hash) -> Storage::DurableRecord
|
|
79
|
+
def self.workflow_state: (workflow_instance_id: String, revision: Integer, snapshot: Hash[untyped, untyped]) -> Storage::DurableRecord
|
|
163
80
|
def self.llm_input_manifest: (Hash[untyped, untyped] hash) -> Hash[String, untyped]
|
|
164
81
|
end
|
|
165
82
|
end
|
|
166
83
|
|
|
167
|
-
REQUIRED_CAPABILITIES: Hash[Symbol, bool]
|
|
168
|
-
|
|
169
84
|
attr_reader contents: _ContentRepository
|
|
170
85
|
attr_reader agents: _AgentRepository
|
|
171
86
|
attr_reader journals: _JournalRepository
|
|
@@ -180,10 +95,11 @@ module Phronomy
|
|
|
180
95
|
def team_execution_result: (String team_execution_id) -> Hash[Symbol, untyped]
|
|
181
96
|
def list_team_executions: (String team_id, ?after: String?, ?limit: Integer) -> Array[untyped]
|
|
182
97
|
|
|
183
|
-
|
|
98
|
+
attr_reader backend: _StorageBackend
|
|
99
|
+
def initialize: (backend: _StorageBackend) -> void
|
|
100
|
+
def self.in_memory: () -> Persistence
|
|
184
101
|
def capabilities: () -> Hash[Symbol, bool]
|
|
185
102
|
def transaction: () { (_PersistenceTransactionView) -> untyped } -> untyped
|
|
186
|
-
def build_transaction_view: (contents: _ContentRepository, agents: _BackendAgentRecordRepository, journals: _BackendJournalRecordRepository, executions: _BackendExecutionRecordRepository, workflow_states: _BackendWorkflowStateRecordRepository, handoff_states: _BackendHandoffStateRecordRepository, teams: _BackendTeamRecordRepository, team_executions: _BackendTeamExecutionRecordRepository, watermark: _BackendWatermark) -> _PersistenceTransactionView
|
|
187
103
|
def assert_agent_watermark!: (agent_id: String, agent_revision: Integer, journal_position: Integer) -> true
|
|
188
104
|
end
|
|
189
105
|
end
|
data/sig/phronomy/runtime.rbs
CHANGED
|
@@ -1,17 +1,44 @@
|
|
|
1
1
|
module Phronomy
|
|
2
|
-
class
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
2
|
+
class TaskResult[A]
|
|
3
|
+
class Outcome[V]
|
|
4
|
+
attr_reader index: Integer
|
|
5
|
+
attr_reader status: (:completed | :failed | :cancelled | :unfinished)
|
|
6
|
+
attr_reader value: V?
|
|
7
|
+
attr_reader error: Exception?
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def self.completed: [V] (V value, ?name: String?) -> TaskResult[V]
|
|
11
|
+
| (?name: String?) -> TaskResult[nil]
|
|
12
|
+
def self.failed: (Exception error, ?name: String?) -> TaskResult[untyped]
|
|
13
|
+
def self.all_settled: [V] (Array[TaskResult[V]] results) -> TaskResult[Array[Outcome[V]]]
|
|
6
14
|
attr_reader name: String?
|
|
7
|
-
attr_reader parent:
|
|
15
|
+
attr_reader parent: TaskResult[untyped]?
|
|
8
16
|
|
|
9
17
|
def status: () -> (:pending | :completed | :failed | :cancelled)
|
|
10
18
|
def done?: () -> bool
|
|
11
19
|
def alive?: () -> bool
|
|
12
20
|
def wait_result: (?timeout: Numeric?) -> A
|
|
13
21
|
def on_complete: () { (A?, Exception?) -> void } -> self
|
|
14
|
-
def map: [B] () { (A) -> B } ->
|
|
22
|
+
def map: [B] () { (A) -> B } -> TaskResult[B]
|
|
23
|
+
def flat_map: [B] () { (A) -> TaskResult[B] } -> TaskResult[B]
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
class Execution
|
|
27
|
+
attr_reader invocation_context: InvocationContext
|
|
28
|
+
|
|
29
|
+
def self.run_async: [I, V] (Array[I] inputs, ?timeout: Numeric?, ?cancellation_token: Concurrency::CancellationToken?, ?invocation_context: InvocationContext?) { (I, Execution) -> TaskResult[V] } -> TaskResult[Array[TaskResult::Outcome[V]]]
|
|
30
|
+
def self.run: [I, V] (Array[I] inputs, ?timeout: Numeric?, ?cancellation_token: Concurrency::CancellationToken?, ?invocation_context: InvocationContext?) { (I, Execution) -> TaskResult[V] } -> Array[TaskResult::Outcome[V]]
|
|
31
|
+
def observe: [V] (TaskResult[V] source_result) -> TaskResult[V]
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
class ExecutionTimeoutError < TimeoutError
|
|
35
|
+
attr_reader outcomes: Array[TaskResult::Outcome[untyped]]
|
|
36
|
+
def initialize: (?String message, outcomes: Array[TaskResult::Outcome[untyped]]) -> void
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
class ExecutionCancellationError < CancellationError
|
|
40
|
+
attr_reader outcomes: Array[TaskResult::Outcome[untyped]]
|
|
41
|
+
def initialize: (?String message, outcomes: Array[TaskResult::Outcome[untyped]]) -> void
|
|
15
42
|
end
|
|
16
43
|
|
|
17
44
|
module Concurrency
|
|
@@ -44,6 +71,6 @@ end
|
|
|
44
71
|
|
|
45
72
|
module Phronomy
|
|
46
73
|
module Blocking
|
|
47
|
-
def self.call_async: [V] (?timeout: Numeric?, ?cancellation_token: Concurrency::CancellationToken?) { () -> V } ->
|
|
74
|
+
def self.call_async: [V] (?timeout: Numeric?, ?cancellation_token: Concurrency::CancellationToken?, ?invocation_context: InvocationContext?) { () -> V } -> TaskResult[V]
|
|
48
75
|
end
|
|
49
76
|
end
|