phronomy 0.26.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.
Files changed (304) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +40 -0
  3. data/README.md +4 -0
  4. data/VERIFY.sh +27 -27
  5. data/benchmark/bench_agent_invoke.rb +26 -22
  6. data/benchmark/bench_context_assembler.rb +4 -5
  7. data/docs/architecture/agent-chat-and-state-ownership.md +147 -0
  8. data/docs/architecture/agent-configuration-and-tool-binding.md +139 -0
  9. data/docs/architecture/agent-context.md +4 -2
  10. data/docs/architecture/agent-transition-ownership.md +89 -0
  11. data/docs/architecture/before-llm-input.md +6 -0
  12. data/docs/architecture/context-management.md +30 -0
  13. data/docs/architecture/context-preparation-steps.md +90 -0
  14. data/docs/architecture/entry-action-and-team-wording.md +72 -0
  15. data/docs/architecture/execution-metadata-and-values.md +80 -0
  16. data/docs/architecture/generator-verifier-ownership.md +111 -0
  17. data/docs/architecture/multi-agent-handoff.md +8 -2
  18. data/docs/architecture/persistence-refactoring-plan.md +50 -0
  19. data/docs/architecture/persistence.md +27 -4
  20. data/docs/architecture/refactoring-closure.md +334 -0
  21. data/docs/architecture/remaining-refactoring-plan.md +374 -0
  22. data/docs/architecture/rubyllm-2-token-ownership.md +82 -0
  23. data/docs/architecture/tool-schema-recording-gap.md +50 -0
  24. data/docs/architecture/tracing.md +1 -1
  25. data/docs/architecture/workflow-terminal-ownership-design.md +104 -0
  26. data/docs/architecture.md +209 -0
  27. data/docs/decisions/014-unified-persistence-durable-state.md +11 -0
  28. data/docs/decisions/024-event-loop-single-writer-agent-runtime.md +5 -1
  29. data/docs/decisions/025-process-local-agent-ownership-and-runtime-admission.md +13 -3
  30. data/docs/decisions/026-workflow-runtime-admission-and-durable-terminal-barrier.md +5 -1
  31. data/docs/decisions/030-agent-handoff-domain-and-durable-responsibility.md +5 -0
  32. data/docs/decisions/031-durable-multi-agent-coordination.md +5 -0
  33. data/docs/decisions/032-storage-backend-composition.md +80 -0
  34. data/docs/decisions/033-domain-persistence-ownership.md +79 -0
  35. data/docs/decisions/034-handoff-runner-coordination-ownership.md +76 -0
  36. data/docs/decisions/035-tool-executor-capability-ownership.md +68 -0
  37. data/docs/decisions/036-context-contract-ownership.md +86 -0
  38. data/docs/decisions/037-common-definition-ownership.md +62 -0
  39. data/docs/decisions/038-responsibility-based-source-layout.md +131 -0
  40. data/docs/decisions/039-runtime-configuration-lifecycle-ownership.md +74 -0
  41. data/docs/decisions/040-configuration-default-composition.md +94 -0
  42. data/docs/decisions/041-feature-owned-identity-registries.md +100 -0
  43. data/docs/decisions/042-feature-owned-execution-state.md +106 -0
  44. data/docs/decisions/043-storage-execution-constraint-notifications.md +75 -0
  45. data/docs/decisions/044-agent-default-and-one-shot-composition.md +106 -0
  46. data/docs/decisions/045-worker-input-restriction-ownership.md +100 -0
  47. data/docs/decisions/046-agent-responsibility-layout-and-shared-records.md +110 -0
  48. data/docs/decisions/047-recovered-execution-continuation-contract.md +116 -0
  49. data/docs/decisions/048-dispatch-preparation-worker-ownership.md +120 -0
  50. data/docs/decisions/049-initial-preparation-worker-ownership.md +111 -0
  51. data/docs/decisions/050-approval-resume-snapshot-and-commit-ownership.md +98 -0
  52. data/docs/decisions/051-execution-outcome-worker-ownership.md +151 -0
  53. data/docs/decisions/052-tool-invocation-restoration-ownership.md +92 -0
  54. data/docs/decisions/053-shared-state-coordination-ownership.md +71 -0
  55. data/docs/decisions/054-workflow-terminal-save-single-owner.md +76 -0
  56. data/docs/decisions/055-terminal-observer-failure-settlement.md +60 -0
  57. data/docs/decisions/056-workflow-terminal-policy-ownership.md +87 -0
  58. data/docs/decisions/057-storage-transaction-boundaries.md +73 -0
  59. data/docs/decisions/058-neutral-storage-primitives.md +78 -0
  60. data/docs/decisions/README.md +35 -6
  61. data/docs/design/durable-semantic-coordination/IMPLEMENTATION_DESIGN_V2.md +6 -0
  62. data/docs/design/durable-semantic-coordination/IMPLEMENTATION_REPORT.md +6 -0
  63. data/docs/features.md +9 -3
  64. data/docs/getting-started.md +4 -4
  65. data/docs/migrations/0.15.md +5 -0
  66. data/docs/migrations/durable-semantic-coordination-v2.md +6 -0
  67. data/docs/migrations/handoff-runner-multi-agent.md +35 -0
  68. data/docs/migrations/neutral-storage-spi.md +43 -0
  69. data/docs/migrations/parallel-tool-chat-removal.md +49 -0
  70. data/docs/migrations/shared-state-multi-agent.md +44 -0
  71. data/docs/migrations/storage-backend-composition.md +117 -0
  72. data/docs/migrations/storage-transaction-boundaries.md +74 -0
  73. data/docs/persistence-backends.md +162 -204
  74. data/docs/runtime-and-concurrency.md +117 -32
  75. data/lib/phronomy/agent/api/agent.rb +17 -0
  76. data/lib/phronomy/agent/async_event_api.rb +2 -2
  77. data/lib/phronomy/agent/base.rb +51 -241
  78. data/lib/phronomy/{agent.rb → agent/composition/run_once.rb} +4 -13
  79. data/lib/phronomy/agent/context/capability/base.rb +67 -26
  80. data/lib/phronomy/agent/context/capability/tool_executor.rb +62 -0
  81. data/lib/phronomy/agent/{context_assembler.rb → context_assembly/context_assembler.rb} +143 -88
  82. data/lib/phronomy/agent/{context_importer.rb → context_assembly/context_importer.rb} +2 -2
  83. data/lib/phronomy/agent/{ruby_llm_materializer.rb → context_assembly/ruby_llm_materializer.rb} +4 -7
  84. data/lib/phronomy/agent/context_assembly/runtime_chat_builder.rb +36 -0
  85. data/lib/phronomy/agent/context_assembly/saved_context_reader.rb +53 -0
  86. data/lib/phronomy/agent/context_assembly/state_writer.rb +165 -0
  87. data/lib/phronomy/agent/context_assembly/token_budget_resolver.rb +22 -0
  88. data/lib/phronomy/agent/{context_plan.rb → context_contract/context_plan.rb} +1 -1
  89. data/lib/phronomy/agent/{context_policy_input.rb → context_contract/context_policy_input.rb} +6 -6
  90. data/lib/phronomy/agent/{llm_input_build_context.rb → context_contract/llm_input_build_context.rb} +1 -1
  91. data/lib/phronomy/agent/{llm_input_manifest.rb → context_contract/llm_input_manifest.rb} +20 -20
  92. data/lib/phronomy/agent/{llm_input_patch.rb → context_contract/llm_input_patch.rb} +2 -2
  93. data/lib/phronomy/agent/{agent_execution.rb → execution/agent_execution.rb} +8 -4
  94. data/lib/phronomy/agent/{agent_invocation.rb → execution/agent_invocation.rb} +8 -13
  95. data/lib/phronomy/agent/{agent_invocation_session_builder.rb → execution/agent_invocation_session_builder.rb} +19 -95
  96. data/lib/phronomy/agent/execution/approval_resume_commit.rb +108 -0
  97. data/lib/phronomy/agent/execution/dispatch_preparation.rb +305 -0
  98. data/lib/phronomy/agent/{exact_execution.rb → execution/exact_execution.rb} +9 -10
  99. data/lib/phronomy/agent/{execution_cancellation.rb → execution/execution_cancellation.rb} +2 -3
  100. data/lib/phronomy/agent/execution/execution_coordinator.rb +1925 -0
  101. data/lib/phronomy/agent/execution/execution_failure.rb +30 -0
  102. data/lib/phronomy/agent/execution/execution_metadata.rb +53 -0
  103. data/lib/phronomy/agent/execution/execution_outcome_committer.rb +344 -0
  104. data/lib/phronomy/agent/execution/execution_registry.rb +459 -0
  105. data/lib/phronomy/agent/execution/execution_session_runner.rb +118 -0
  106. data/lib/phronomy/agent/execution/initial_preparation.rb +421 -0
  107. data/lib/phronomy/agent/execution/invocation_transitions.rb +86 -0
  108. data/lib/phronomy/agent/{phase_machine_builder.rb → execution/phase_machine_builder.rb} +20 -71
  109. data/lib/phronomy/agent/{provider_call_outcome.rb → execution/provider_call_outcome.rb} +9 -9
  110. data/lib/phronomy/agent/execution/runtime_record_encoder.rb +210 -0
  111. data/lib/phronomy/agent/{handoff_context.rb → handoff/handoff_context.rb} +2 -2
  112. data/lib/phronomy/agent/handoff/handoff_execution_coordinator.rb +15 -0
  113. data/lib/phronomy/agent/handoff/handoff_outcome_committer.rb +131 -0
  114. data/lib/phronomy/agent/{handoff_state.rb → handoff/handoff_state.rb} +1 -1
  115. data/lib/phronomy/agent/{journal_projection.rb → journal/journal_projection.rb} +4 -0
  116. data/lib/phronomy/agent/{journal_record.rb → journal/journal_record.rb} +3 -3
  117. data/lib/phronomy/agent/{llm_call_record.rb → journal/llm_call_record.rb} +2 -2
  118. data/lib/phronomy/agent/{agent_root.rb → lifecycle/agent_root.rb} +6 -2
  119. data/lib/phronomy/agent/lifecycle/default_persistence.rb +29 -0
  120. data/lib/phronomy/{engine/runtime/agent_ownership_registry.rb → agent/lifecycle/ownership_registry.rb} +24 -10
  121. data/lib/phronomy/{agent_already_exists_error.rb → agent/lifecycle_contract/agent_already_exists_error.rb} +2 -0
  122. data/lib/phronomy/{agent_busy_error.rb → agent/lifecycle_contract/agent_busy_error.rb} +2 -0
  123. data/lib/phronomy/{agent_purged_error.rb → agent/lifecycle_contract/agent_purged_error.rb} +2 -0
  124. data/lib/phronomy/agent/lifecycle_contract/handoff_error.rb +7 -0
  125. data/lib/phronomy/{stream_callback_error.rb → agent/lifecycle_contract/stream_callback_error.rb} +2 -0
  126. data/lib/phronomy/agent/persistence/agent_repository.rb +61 -0
  127. data/lib/phronomy/agent/persistence/codec.rb +358 -0
  128. data/lib/phronomy/agent/persistence/execution_repository.rb +108 -0
  129. data/lib/phronomy/agent/persistence/handoff_state_repository.rb +58 -0
  130. data/lib/phronomy/agent/persistence/journal_repository.rb +54 -0
  131. data/lib/phronomy/agent/persistence/queries.rb +61 -0
  132. data/lib/phronomy/agent/persistence/storage_schema.rb +24 -0
  133. data/lib/phronomy/agent/persistence/watermark.rb +27 -0
  134. data/lib/phronomy/agent/recovery/invocation_restorer.rb +132 -0
  135. data/lib/phronomy/agent/{recovery_coordinator → recovery/recovery_coordinator}/continuation.rb +21 -45
  136. data/lib/phronomy/agent/{recovery_coordinator → recovery/recovery_coordinator}/installation.rb +32 -37
  137. data/lib/phronomy/agent/{recovery_coordinator → recovery/recovery_coordinator}/resolution.rb +37 -40
  138. data/lib/phronomy/agent/{recovery_coordinator.rb → recovery/recovery_coordinator.rb} +6 -10
  139. data/lib/phronomy/agent/recovery/recovery_support.rb +227 -0
  140. data/lib/phronomy/agent/selection/candidate.rb +1 -1
  141. data/lib/phronomy/agent/{approval_evaluation_request.rb → tool_execution/approval_evaluation_request.rb} +1 -12
  142. data/lib/phronomy/agent/{tool_approval_request.rb → tool_execution/tool_approval_request.rb} +1 -10
  143. data/lib/phronomy/agent/tool_execution/tool_binding.rb +90 -0
  144. data/lib/phronomy/agent/{tool_call_intercepted.rb → tool_execution/tool_call_intercepted.rb} +2 -2
  145. data/lib/phronomy/agent/{tool_definition_set.rb → tool_execution/tool_definition_set.rb} +9 -4
  146. data/lib/phronomy/agent/{tool_invocation.rb → tool_execution/tool_invocation.rb} +69 -34
  147. data/lib/phronomy/common/configuration_error.rb +7 -0
  148. data/lib/phronomy/common/error.rb +5 -0
  149. data/lib/phronomy/{agent → common/values}/immutable.rb +9 -1
  150. data/lib/phronomy/common/values/serializable.rb +32 -0
  151. data/lib/phronomy/{configuration.rb → configuration/configuration.rb} +14 -5
  152. data/lib/phronomy/configuration/global_configuration.rb +26 -0
  153. data/lib/phronomy/content_store/storage_schema.rb +11 -0
  154. data/lib/phronomy/content_store/stored_contents.rb +43 -0
  155. data/lib/phronomy/engine/backpressure_error.rb +7 -0
  156. data/lib/phronomy/{blocking.rb → engine/blocking.rb} +1 -1
  157. data/lib/phronomy/engine/cancellation_error.rb +7 -0
  158. data/lib/phronomy/engine/concurrency/cancellation_token.rb +4 -0
  159. data/lib/phronomy/engine/concurrency/offload_pool.rb +4 -0
  160. data/lib/phronomy/engine/concurrency/operation_binding.rb +1 -1
  161. data/lib/phronomy/engine/concurrency/worker_input_restricted.rb +14 -0
  162. data/lib/phronomy/engine/event_loop.rb +158 -624
  163. data/lib/phronomy/engine/event_loop_reentrancy_error.rb +8 -0
  164. data/lib/phronomy/{execution.rb → engine/execution.rb} +0 -7
  165. data/lib/phronomy/{execution_cancellation_error.rb → engine/execution_cancellation_error.rb} +2 -0
  166. data/lib/phronomy/engine/execution_receiver.rb +65 -0
  167. data/lib/phronomy/{execution_timeout_error.rb → engine/execution_timeout_error.rb} +2 -0
  168. data/lib/phronomy/engine/fsm_protocol.rb +14 -0
  169. data/lib/phronomy/engine/fsm_session.rb +35 -28
  170. data/lib/phronomy/{invalid_async_entry_action_error.rb → engine/invalid_async_entry_action_error.rb} +2 -0
  171. data/lib/phronomy/{invalid_async_transition_action_error.rb → engine/invalid_async_transition_action_error.rb} +2 -0
  172. data/lib/phronomy/{invalid_async_workflow_action_error.rb → engine/invalid_async_workflow_action_error.rb} +2 -0
  173. data/lib/phronomy/engine/pool_shutdown_error.rb +7 -0
  174. data/lib/phronomy/engine/recursion_limit_error.rb +7 -0
  175. data/lib/phronomy/engine/runtime.rb +80 -84
  176. data/lib/phronomy/engine/runtime_shutdown_error.rb +7 -0
  177. data/lib/phronomy/engine/runtime_shutdown_reentrancy_error.rb +7 -0
  178. data/lib/phronomy/engine/scheduler_reentrancy_error.rb +9 -0
  179. data/lib/phronomy/engine/task_result.rb +4 -0
  180. data/lib/phronomy/engine/timeout_error.rb +7 -0
  181. data/lib/phronomy/filter/contract/filter_block_error.rb +14 -0
  182. data/lib/phronomy/generation/generator_verifier/agent_result_receiver.rb +89 -0
  183. data/lib/phronomy/generation/generator_verifier/pipeline_state.rb +57 -0
  184. data/lib/phronomy/generation/generator_verifier/workflow_builder.rb +112 -0
  185. data/lib/phronomy/generation/generator_verifier.rb +118 -0
  186. data/lib/phronomy/generation/low_confidence_error.rb +14 -0
  187. data/lib/phronomy/llm_context_window/token_budget.rb +6 -7
  188. data/lib/phronomy/llm_contract/authentication_error.rb +7 -0
  189. data/lib/phronomy/{context_budget_exceeded_error.rb → llm_contract/context_budget_exceeded_error.rb} +2 -0
  190. data/lib/phronomy/llm_contract/context_length_error.rb +7 -0
  191. data/lib/phronomy/llm_contract/rate_limit_error.rb +7 -0
  192. data/lib/phronomy/{token_usage.rb → llm_contract/token_usage.rb} +2 -2
  193. data/lib/phronomy/llm_contract/transport_error.rb +7 -0
  194. data/lib/phronomy/multi_agent/admission_registry.rb +22 -2
  195. data/lib/phronomy/multi_agent/durable_subagent_coordinator.rb +5 -5
  196. data/lib/phronomy/{agent → multi_agent}/handoff_runner.rb +18 -17
  197. data/lib/phronomy/multi_agent/orchestrator.rb +2 -2
  198. data/lib/phronomy/multi_agent/persistence/codec.rb +55 -0
  199. data/lib/phronomy/multi_agent/persistence/queries.rb +30 -0
  200. data/lib/phronomy/multi_agent/persistence/team_execution_repository.rb +108 -0
  201. data/lib/phronomy/multi_agent/persistence/team_repository.rb +61 -0
  202. data/lib/phronomy/{agent → multi_agent}/shared_state.rb +56 -39
  203. data/lib/phronomy/multi_agent/storage_contract/team_storage_schema.rb +15 -0
  204. data/lib/phronomy/multi_agent/team_coordinator.rb +21 -18
  205. data/lib/phronomy/multi_agent/team_execution.rb +1 -1
  206. data/lib/phronomy/{engine/runtime → multi_agent}/team_ownership_registry.rb +14 -4
  207. data/lib/phronomy/multi_agent/team_root.rb +1 -1
  208. data/lib/phronomy/output_parser/contract/parse_error.rb +7 -0
  209. data/lib/phronomy/persistence/api/persistence.rb +140 -0
  210. data/lib/phronomy/persistence/migration/initial_format_migration.rb +19 -19
  211. data/lib/phronomy/persistence_composition/repositories.rb +77 -0
  212. data/lib/phronomy/persistence_composition/storage_schema.rb +24 -0
  213. data/lib/phronomy/{execution_rehydration_required_error.rb → recovery/execution_rehydration_required_error.rb} +2 -0
  214. data/lib/phronomy/{recovery.rb → recovery/recovery.rb} +1 -1
  215. data/lib/phronomy/runtime_composition/agent_defaults.rb +7 -0
  216. data/lib/phronomy/runtime_composition/configuration_defaults.rb +9 -0
  217. data/lib/phronomy/runtime_composition/global_runtime.rb +19 -0
  218. data/lib/phronomy/storage/backend.rb +101 -0
  219. data/lib/phronomy/storage/backends/in_memory.rb +157 -0
  220. data/lib/phronomy/storage/blob_conflict_error.rb +10 -0
  221. data/lib/phronomy/storage/blobs.rb +31 -0
  222. data/lib/phronomy/storage/condition.rb +25 -0
  223. data/lib/phronomy/storage/condition_failed_error.rb +16 -0
  224. data/lib/phronomy/storage/conflict_error.rb +9 -0
  225. data/lib/phronomy/{persistence → storage}/durable_record.rb +12 -12
  226. data/lib/phronomy/storage/entry.rb +33 -0
  227. data/lib/phronomy/storage/guard_ref.rb +13 -0
  228. data/lib/phronomy/storage/not_found_error.rb +9 -0
  229. data/lib/phronomy/storage/record_codec.rb +177 -0
  230. data/lib/phronomy/storage/records.rb +61 -0
  231. data/lib/phronomy/storage/resource.rb +126 -0
  232. data/lib/phronomy/storage/scope.rb +25 -0
  233. data/lib/phronomy/storage/serialization_error.rb +9 -0
  234. data/lib/phronomy/storage/streams.rb +44 -0
  235. data/lib/phronomy/storage/transaction_error.rb +10 -0
  236. data/lib/phronomy/storage/unique_constraint_error.rb +17 -0
  237. data/lib/phronomy/storage/unsupported_backend_error.rb +9 -0
  238. data/lib/phronomy/storage/validation.rb +53 -0
  239. data/lib/phronomy/storage/view.rb +131 -0
  240. data/lib/phronomy/testing/persistence_contract/a_content_store.rb +1 -1
  241. data/lib/phronomy/testing/persistence_contract/a_journal_repository.rb +4 -4
  242. data/lib/phronomy/testing/persistence_contract/a_persistence_backend.rb +10 -7
  243. data/lib/phronomy/testing/persistence_contract/a_workflow_state_repository.rb +2 -2
  244. data/lib/phronomy/testing/persistence_contract/an_agent_repository.rb +6 -6
  245. data/lib/phronomy/testing/persistence_contract/an_execution_repository.rb +6 -6
  246. data/lib/phronomy/testing/persistence_contract/coordination_repositories.rb +8 -8
  247. data/lib/phronomy/testing/persistence_contract/neutral_storage_primitives.rb +263 -0
  248. data/lib/phronomy/testing/persistence_contract/storage_transaction_boundaries.rb +123 -0
  249. data/lib/phronomy/testing/persistence_contract.rb +4 -0
  250. data/lib/phronomy/tool/contract/tool_error.rb +7 -0
  251. data/lib/phronomy/tools/agent.rb +1 -1
  252. data/lib/phronomy/version.rb +1 -1
  253. data/lib/phronomy/{workflow.rb → workflow/execution/workflow.rb} +8 -6
  254. data/lib/phronomy/{workflow_context.rb → workflow/execution/workflow_context.rb} +4 -0
  255. data/lib/phronomy/workflow/execution/workflow_context_ownership_error.rb +7 -0
  256. data/lib/phronomy/workflow/execution/workflow_execution_registry.rb +188 -0
  257. data/lib/phronomy/{workflow_runner.rb → workflow/execution/workflow_runner.rb} +122 -71
  258. data/lib/phronomy/workflow/execution/workflow_terminal_policy.rb +40 -0
  259. data/lib/phronomy/workflow/persistence/codec.rb +153 -0
  260. data/lib/phronomy/workflow/persistence/state_repository.rb +57 -0
  261. data/lib/phronomy/workflow/phase_machine_builder.rb +2 -2
  262. data/lib/phronomy/workflow/storage_contract/workflow_storage_schema.rb +9 -0
  263. data/lib/phronomy.rb +52 -94
  264. data/scripts/api_snapshot.rb +1 -1
  265. data/scripts/storage_spi_snapshot.rb +36 -0
  266. data/sig/phronomy/agent.rbs +0 -1
  267. data/sig/phronomy/execution_receiver.rbs +34 -0
  268. data/sig/phronomy/handoff.rbs +4 -2
  269. data/sig/phronomy/multi_agent.rbs +18 -0
  270. data/sig/phronomy/persistence.rbs +7 -91
  271. data/sig/phronomy/storage.rbs +174 -0
  272. data/sig/phronomy/tool.rbs +10 -1
  273. metadata +230 -99
  274. data/lib/phronomy/agent/execution_coordinator.rb +0 -3151
  275. data/lib/phronomy/agent/handoff_execution_coordinator.rb +0 -143
  276. data/lib/phronomy/agent/recovery_support.rb +0 -504
  277. data/lib/phronomy/agent/token_budget_resolver.rb +0 -70
  278. data/lib/phronomy/agent/tool_executor.rb +0 -55
  279. data/lib/phronomy/generator_verifier.rb +0 -369
  280. data/lib/phronomy/invalid_context_budget_configuration_error.rb +0 -8
  281. data/lib/phronomy/multi_agent/parallel_tool_chat.rb +0 -116
  282. data/lib/phronomy/persistence/durable_codec.rb +0 -706
  283. data/lib/phronomy/persistence/in_memory.rb +0 -690
  284. data/lib/phronomy/persistence/repository_facades.rb +0 -535
  285. data/lib/phronomy/persistence.rb +0 -276
  286. data/lib/phronomy/ruby_llm_patches.rb +0 -24
  287. data/lib/phronomy/workflow_recovery.rb +0 -123
  288. /data/lib/phronomy/agent/{context_candidate_resolver.rb → context_assembly/context_candidate_resolver.rb} +0 -0
  289. /data/lib/phronomy/agent/{context_policy_input_builder.rb → context_assembly/context_policy_input_builder.rb} +0 -0
  290. /data/lib/phronomy/agent/{context_plan_validator.rb → context_contract/context_plan_validator.rb} +0 -0
  291. /data/lib/phronomy/agent/{context_policy.rb → context_contract/context_policy.rb} +0 -0
  292. /data/lib/phronomy/agent/{llm_operation_result.rb → execution/llm_operation_result.rb} +0 -0
  293. /data/lib/phronomy/agent/{handoff.rb → handoff/handoff.rb} +0 -0
  294. /data/lib/phronomy/agent/{handoff_capability_factory.rb → handoff/handoff_capability_factory.rb} +0 -0
  295. /data/lib/phronomy/agent/{handoff_policy.rb → handoff/handoff_policy.rb} +0 -0
  296. /data/lib/phronomy/agent/{handoff_projection.rb → handoff/handoff_projection.rb} +0 -0
  297. /data/lib/phronomy/agent/{handoff_request.rb → handoff/handoff_request.rb} +0 -0
  298. /data/lib/phronomy/agent/{tool_invocation_session_builder.rb → tool_execution/tool_invocation_session_builder.rb} +0 -0
  299. /data/lib/phronomy/{canonical_json.rb → common/canonical_json.rb} +0 -0
  300. /data/lib/phronomy/{diagnostics.rb → engine/diagnostics.rb} +0 -0
  301. /data/lib/phronomy/{event.rb → engine/event.rb} +0 -0
  302. /data/lib/phronomy/{invocation_context.rb → engine/invocation_context.rb} +0 -0
  303. /data/lib/phronomy/{metrics.rb → engine/metrics.rb} +0 -0
  304. /data/lib/phronomy/{runnable.rb → engine/runnable.rb} +0 -0
@@ -0,0 +1,53 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Phronomy
4
+ module Agent
5
+ # Reads saved manifests and Provider output for continuation preparation.
6
+ # Callers perform these reads before applying live state on EventLoop.
7
+ # @api private
8
+ module SavedContextReader
9
+ module_function
10
+
11
+ def manifest_from_ref(agent, ref)
12
+ raw = agent.persistence.contents.fetch_json(ref)
13
+ Phronomy::Agent::LLMInputManifest.from_h(raw)
14
+ end
15
+
16
+ def materialize_projection(agent, manifest_ref)
17
+ manifest = manifest_from_ref(agent, manifest_ref)
18
+ projection = Phronomy::Agent::RubyLLMMaterializer.new(
19
+ agent: agent,
20
+ persistence: agent.persistence
21
+ ).materialize(manifest: manifest, manifest_ref: manifest_ref)
22
+ [manifest, projection]
23
+ end
24
+
25
+ def latest_assistant_record(execution, llm_call_id: nil)
26
+ Array(execution.working_records).reverse.find do |record|
27
+ record.kind.to_sym == :assistant_message &&
28
+ (llm_call_id.nil? || record.llm_call_id.to_s == llm_call_id.to_s)
29
+ end
30
+ end
31
+
32
+ def provider_output_and_usage(agent, execution)
33
+ assistant = latest_assistant_record(execution)
34
+ payload = assistant ? agent.persistence.contents.fetch_json(assistant.content_ref) : {}
35
+ output = payload["content"]
36
+
37
+ call = execution.llm_calls.last
38
+ usage_hash = if call&.usage_ref
39
+ agent.persistence.contents.fetch_json(call.usage_ref)
40
+ else
41
+ {}
42
+ end
43
+ usage = Phronomy::TokenUsage.new(
44
+ input: usage_hash["input"] || usage_hash[:input] || usage_hash["input_tokens"] || usage_hash[:input_tokens],
45
+ output: usage_hash["output"] || usage_hash[:output] || usage_hash["output_tokens"] || usage_hash[:output_tokens],
46
+ cached: usage_hash["cached"] || usage_hash[:cached] || usage_hash["cache_read_tokens"] || usage_hash[:cache_read_tokens] || usage_hash["cached_tokens"] || usage_hash[:cached_tokens],
47
+ cache_creation: usage_hash["cache_creation"] || usage_hash[:cache_creation] || usage_hash["cache_write_tokens"] || usage_hash[:cache_write_tokens] || usage_hash["cache_creation_tokens"] || usage_hash[:cache_creation_tokens]
48
+ )
49
+ [output, usage]
50
+ end
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,165 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Phronomy
4
+ module Agent
5
+ # Persists initial state and explicit idle-Agent context/lifecycle changes.
6
+ # Base owns live-state publication; execution commits have separate owners.
7
+ # @api private
8
+ class StateWriter
9
+ Update = Data.define(:root, :records)
10
+ private_constant :Update
11
+
12
+ def initialize(persistence:, agent_id:)
13
+ @persistence = persistence
14
+ @agent_id = agent_id
15
+ end
16
+
17
+ def create_root(definition:, context:, knowledge:, metadata:)
18
+ root = Agent::AgentRoot.create(
19
+ agent_id: agent_id,
20
+ agent_definition_id: definition.fetch(:id),
21
+ agent_definition_version: definition.fetch(:version),
22
+ metadata: metadata
23
+ )
24
+ persistence.transaction do |tx|
25
+ tx.agents.create(root)
26
+ records = initial_context_records(tx: tx, root: root, context: context)
27
+ records.concat(initial_knowledge_records(tx: tx, root: root, knowledge: knowledge))
28
+ unless records.empty?
29
+ appended = tx.journals.append(agent_id, expected_position: 0, records: records)
30
+ root = root.with(
31
+ agent_revision: 1,
32
+ context_revision: 1,
33
+ journal_position: appended.length
34
+ )
35
+ tx.agents.save(agent_id, expected_revision: 0, root: root)
36
+ end
37
+ end
38
+ root
39
+ end
40
+
41
+ def add_knowledge(root:, content:, metadata:)
42
+ current = root
43
+ next_root = nil
44
+ appended = nil
45
+ persistence.transaction do |tx|
46
+ tx.executions.assert_idle!(agent_id)
47
+ record = build_knowledge_record(
48
+ tx: tx,
49
+ root: current,
50
+ content: content,
51
+ metadata: metadata
52
+ )
53
+ appended = tx.journals.append(
54
+ agent_id,
55
+ expected_position: current.journal_position,
56
+ records: [record]
57
+ )
58
+ next_root = current.with(
59
+ agent_revision: current.agent_revision + 1,
60
+ context_revision: current.context_revision + 1,
61
+ journal_position: current.journal_position + appended.length
62
+ )
63
+ tx.agents.save(
64
+ agent_id,
65
+ expected_revision: current.agent_revision,
66
+ root: next_root
67
+ )
68
+ end
69
+ Update.new(root: next_root, records: appended)
70
+ end
71
+
72
+ def mutate_context(root:, kind:, context_affecting:)
73
+ current = root
74
+ next_root = nil
75
+ appended = nil
76
+ persistence.transaction do |tx|
77
+ tx.executions.assert_idle!(agent_id)
78
+ record = Agent::JournalRecord.new(
79
+ agent_id: agent_id,
80
+ kind: kind,
81
+ channel: :state,
82
+ context_generation: current.transcript_generation,
83
+ context_candidate: false
84
+ )
85
+ appended = tx.journals.append(
86
+ agent_id,
87
+ expected_position: current.journal_position,
88
+ records: [record]
89
+ )
90
+ proposed = yield(current)
91
+ next_root = proposed.with(
92
+ journal_position: current.journal_position + appended.length,
93
+ context_revision: context_affecting ?
94
+ yield_context_revision(current, proposed) : current.context_revision
95
+ )
96
+ tx.agents.save(
97
+ agent_id,
98
+ expected_revision: current.agent_revision,
99
+ root: next_root
100
+ )
101
+ end
102
+ Update.new(root: next_root, records: appended)
103
+ end
104
+
105
+ private
106
+
107
+ attr_reader :persistence, :agent_id
108
+
109
+ def initial_context_records(tx:, root:, context:)
110
+ return [] unless context
111
+
112
+ imported = context.respond_to?(:records) ? context :
113
+ Agent::ContextImporter.import_messages(context)
114
+ imported.records.map do |record|
115
+ content_ref = case record.content_format
116
+ when :text then tx.contents.put_text(record.content)
117
+ when :json then tx.contents.put_json(record.content)
118
+ else
119
+ raise ArgumentError,
120
+ "unsupported imported content format: #{record.content_format.inspect}"
121
+ end
122
+ Agent::JournalRecord.new(
123
+ agent_id: agent_id,
124
+ kind: record.kind,
125
+ channel: record.channel,
126
+ role: record.role,
127
+ content_ref: content_ref,
128
+ context_generation: root.transcript_generation,
129
+ context_candidate: true,
130
+ metadata: record.metadata
131
+ )
132
+ end
133
+ end
134
+
135
+ def initial_knowledge_records(tx:, root:, knowledge:)
136
+ Array(knowledge).map do |content|
137
+ build_knowledge_record(
138
+ tx: tx,
139
+ root: root,
140
+ content: content,
141
+ metadata: {}
142
+ )
143
+ end
144
+ end
145
+
146
+ def build_knowledge_record(tx:, root:, content:, metadata:)
147
+ Agent::JournalRecord.new(
148
+ agent_id: agent_id,
149
+ kind: :knowledge,
150
+ channel: :context,
151
+ role: :user,
152
+ content_ref: tx.contents.put_text(String(content)),
153
+ context_generation: root.transcript_generation,
154
+ context_candidate: true,
155
+ metadata: metadata || {}
156
+ )
157
+ end
158
+
159
+ def yield_context_revision(current, proposed)
160
+ (proposed.context_revision == current.context_revision) ?
161
+ current.context_revision + 1 : proposed.context_revision
162
+ end
163
+ end
164
+ end
165
+ end
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Phronomy
4
+ module Agent
5
+ # Resolves the input limit from RubyLLM's authoritative model registry.
6
+ class TokenBudgetResolver
7
+ def resolve(model_config)
8
+ config = model_config.to_h.transform_keys(&:to_s)
9
+ model_name = config["model"]
10
+ return nil unless model_name
11
+
12
+ model = RubyLLM.models.find(model_name, provider: config["provider"])
13
+ limit = model&.context_window
14
+ return nil unless limit.is_a?(Integer) && limit.positive?
15
+
16
+ Phronomy::LlmContextWindow::TokenBudget.new(max_input_tokens: limit)
17
+ rescue RubyLLM::ModelNotFoundError
18
+ nil
19
+ end
20
+ end
21
+ end
22
+ end
@@ -21,7 +21,7 @@ module Phronomy
21
21
  knowledge: Array(knowledge).freeze,
22
22
  tools: Array(tools).freeze,
23
23
  conversation: Array(conversation).map { |group| Array(group).freeze }.freeze,
24
- metadata: Immutable.copy(metadata || {})
24
+ metadata: Phronomy::Values::Immutable.copy(metadata || {})
25
25
  )
26
26
  freeze
27
27
  end
@@ -50,8 +50,8 @@ module Phronomy
50
50
  knowledge: normalized_knowledge,
51
51
  tools: normalized_tools,
52
52
  conversation: normalized_conversation,
53
- model_config: Immutable.copy(values[:model_config] || {}),
54
- metadata: Immutable.copy(values[:metadata] || {})
53
+ model_config: Phronomy::Values::Immutable.copy(values[:model_config] || {}),
54
+ metadata: Phronomy::Values::Immutable.copy(values[:metadata] || {})
55
55
  ))
56
56
  freeze
57
57
  end
@@ -145,7 +145,7 @@ module Phronomy
145
145
  ) do
146
146
  def initialize(**values)
147
147
  provenance = ContextPolicyInput.send(:normalize_provenance, values[:provenance])
148
- definition = Immutable.copy(values.fetch(:definition))
148
+ definition = Phronomy::Values::Immutable.copy(values.fetch(:definition))
149
149
  unless definition.is_a?(Hash) && definition["name"].to_s != ""
150
150
  raise ArgumentError, "ContextPolicyInput ToolItem definition requires a non-empty name"
151
151
  end
@@ -156,7 +156,7 @@ module Phronomy
156
156
  estimated_tokens: ContextPolicyInput.send(:normalize_estimated_tokens, values[:estimated_tokens]),
157
157
  required: !!values[:required],
158
158
  provenance: provenance,
159
- metadata: Immutable.copy(values[:metadata] || {})
159
+ metadata: Phronomy::Values::Immutable.copy(values[:metadata] || {})
160
160
  )
161
161
  raise ArgumentError, "ContextPolicyInput ToolItem id must not be empty" if id.empty?
162
162
  freeze
@@ -212,12 +212,12 @@ module Phronomy
212
212
  id: id,
213
213
  kind: kind,
214
214
  role: role,
215
- content: Immutable.copy(values[:content]),
215
+ content: Phronomy::Values::Immutable.copy(values[:content]),
216
216
  content_format: content_format,
217
217
  estimated_tokens: normalize_estimated_tokens(values[:estimated_tokens]),
218
218
  required: !!values[:required],
219
219
  provenance: normalize_provenance(values[:provenance]),
220
- metadata: Immutable.copy(values[:metadata] || {})
220
+ metadata: Phronomy::Values::Immutable.copy(values[:metadata] || {})
221
221
  }
222
222
  end
223
223
 
@@ -9,7 +9,7 @@ module Phronomy
9
9
  :config, :call_sequence
10
10
  ) do
11
11
  def initialize(**values)
12
- super(**values.merge(config: Immutable.copy(values.fetch(:config, {}))))
12
+ super(**values.merge(config: Phronomy::Values::Immutable.copy(values.fetch(:config, {}))))
13
13
  freeze
14
14
  end
15
15
  end
@@ -3,7 +3,7 @@
3
3
  module Phronomy
4
4
  module Agent
5
5
  # ContentStore-backed durable codec boundary for one Provider input manifest.
6
- # It is intentionally separate from Persistence::DurableRecord.
6
+ # It is intentionally separate from Storage::DurableRecord.
7
7
  class LLMInputManifest
8
8
  VERSION = "0.1"
9
9
  CALL_MODES = %i[ask complete].freeze
@@ -18,7 +18,7 @@ module Phronomy
18
18
  if delivery.nil? || !SEGMENT_DELIVERIES.include?(delivery.to_s)
19
19
  raise ArgumentError, "unknown Segment delivery: #{delivery.inspect}"
20
20
  end
21
- super(**values.merge(metadata: Immutable.copy(values[:metadata] || {})))
21
+ super(**values.merge(metadata: Phronomy::Values::Immutable.copy(values[:metadata] || {})))
22
22
  freeze
23
23
  end
24
24
 
@@ -62,7 +62,7 @@ module Phronomy
62
62
  label: label
63
63
  )
64
64
  unless SEGMENT_DELIVERIES.include?(delivery)
65
- raise Phronomy::Persistence::SerializationError,
65
+ raise Phronomy::Storage::SerializationError,
66
66
  "LLMInputManifest segment delivery must be one of #{SEGMENT_DELIVERIES.inspect}, got #{delivery.inspect}"
67
67
  end
68
68
  tool_call_id = LLMInputManifest.send(
@@ -87,10 +87,10 @@ module Phronomy
87
87
  tool_call_id: tool_call_id,
88
88
  metadata: metadata
89
89
  )
90
- rescue Phronomy::Persistence::SerializationError
90
+ rescue Phronomy::Storage::SerializationError
91
91
  raise
92
92
  rescue => error
93
- raise Phronomy::Persistence::SerializationError,
93
+ raise Phronomy::Storage::SerializationError,
94
94
  "invalid LLMInputManifest segment: #{error.class}: #{error.message}"
95
95
  end
96
96
 
@@ -162,7 +162,7 @@ module Phronomy
162
162
  label = "LLMInputManifest"
163
163
  version = source.fetch("version")
164
164
  unless version.is_a?(String) && version == VERSION
165
- raise Phronomy::Persistence::SerializationError,
165
+ raise Phronomy::Storage::SerializationError,
166
166
  "unsupported LLMInputManifest version: #{version.inspect}; " \
167
167
  "current version is #{VERSION.inspect}"
168
168
  end
@@ -229,10 +229,10 @@ module Phronomy
229
229
  adapter_name: adapter_name,
230
230
  adapter_version: adapter_version
231
231
  )
232
- rescue Phronomy::Persistence::SerializationError
232
+ rescue Phronomy::Storage::SerializationError
233
233
  raise
234
234
  rescue => error
235
- raise Phronomy::Persistence::SerializationError,
235
+ raise Phronomy::Storage::SerializationError,
236
236
  "invalid LLMInputManifest: #{error.class}: #{error.message}"
237
237
  end
238
238
 
@@ -262,11 +262,11 @@ module Phronomy
262
262
 
263
263
  def strict_source!(hash, required:, optional:, label:)
264
264
  unless hash.is_a?(Hash)
265
- raise Phronomy::Persistence::SerializationError,
265
+ raise Phronomy::Storage::SerializationError,
266
266
  "#{label} must be a Hash"
267
267
  end
268
268
  unless hash.keys.all? { |key| key.is_a?(String) }
269
- raise Phronomy::Persistence::SerializationError,
269
+ raise Phronomy::Storage::SerializationError,
270
270
  "#{label} keys must all be String"
271
271
  end
272
272
 
@@ -277,13 +277,13 @@ module Phronomy
277
277
  details = []
278
278
  details << "missing=#{missing.inspect}" unless missing.empty?
279
279
  details << "unknown=#{unknown.inspect}" unless unknown.empty?
280
- raise Phronomy::Persistence::SerializationError,
280
+ raise Phronomy::Storage::SerializationError,
281
281
  "#{label} schema mismatch (#{details.join(", ")})"
282
282
  end
283
283
  Phronomy::CanonicalJSON.dump(hash)
284
284
  hash
285
285
  rescue ArgumentError => error
286
- raise Phronomy::Persistence::SerializationError,
286
+ raise Phronomy::Storage::SerializationError,
287
287
  "#{label} is not canonical JSON compatible: #{error.message}"
288
288
  end
289
289
 
@@ -291,7 +291,7 @@ module Phronomy
291
291
  value = hash.fetch(key)
292
292
  return value if value.is_a?(Integer)
293
293
 
294
- raise Phronomy::Persistence::SerializationError,
294
+ raise Phronomy::Storage::SerializationError,
295
295
  "#{label} #{key} must be an Integer"
296
296
  end
297
297
 
@@ -299,7 +299,7 @@ module Phronomy
299
299
  value = hash.fetch(key)
300
300
  return value if value.is_a?(Integer) && value.positive?
301
301
 
302
- raise Phronomy::Persistence::SerializationError,
302
+ raise Phronomy::Storage::SerializationError,
303
303
  "#{label} #{key} must be a positive Integer"
304
304
  end
305
305
 
@@ -307,7 +307,7 @@ module Phronomy
307
307
  value = hash.fetch(key)
308
308
  return value if value.is_a?(Integer) && value >= 0
309
309
 
310
- raise Phronomy::Persistence::SerializationError,
310
+ raise Phronomy::Storage::SerializationError,
311
311
  "#{label} #{key} must be a non-negative Integer"
312
312
  end
313
313
 
@@ -315,7 +315,7 @@ module Phronomy
315
315
  value = hash.fetch(key)
316
316
  return value if value.is_a?(String) && !value.empty?
317
317
 
318
- raise Phronomy::Persistence::SerializationError,
318
+ raise Phronomy::Storage::SerializationError,
319
319
  "#{label} #{key} must be a non-empty String"
320
320
  end
321
321
 
@@ -323,7 +323,7 @@ module Phronomy
323
323
  value = hash[key]
324
324
  return value if value.nil? || value.is_a?(String)
325
325
 
326
- raise Phronomy::Persistence::SerializationError,
326
+ raise Phronomy::Storage::SerializationError,
327
327
  "#{label} #{key} must be a String or nil"
328
328
  end
329
329
 
@@ -331,7 +331,7 @@ module Phronomy
331
331
  value = hash.fetch(key)
332
332
  return value if value.is_a?(String) && allowed.include?(value)
333
333
 
334
- raise Phronomy::Persistence::SerializationError,
334
+ raise Phronomy::Storage::SerializationError,
335
335
  "#{label} #{key} must be one of #{allowed.inspect}"
336
336
  end
337
337
 
@@ -339,7 +339,7 @@ module Phronomy
339
339
  value = hash.fetch(key)
340
340
  return value if value.is_a?(Array)
341
341
 
342
- raise Phronomy::Persistence::SerializationError,
342
+ raise Phronomy::Storage::SerializationError,
343
343
  "#{label} #{key} must be an Array"
344
344
  end
345
345
 
@@ -347,7 +347,7 @@ module Phronomy
347
347
  value = hash.fetch(key)
348
348
  return value if value.is_a?(Hash)
349
349
 
350
- raise Phronomy::Persistence::SerializationError,
350
+ raise Phronomy::Storage::SerializationError,
351
351
  "#{label} #{key} must be a Hash"
352
352
  end
353
353
  end
@@ -7,8 +7,8 @@ module Phronomy
7
7
  LLMInputPatch = Data.define(:model_config_patch, :segment_candidates) do
8
8
  def initialize(model_config_patch: nil, segment_candidates: nil)
9
9
  super(
10
- model_config_patch: model_config_patch && Immutable.copy(model_config_patch),
11
- segment_candidates: segment_candidates && Immutable.copy(Array(segment_candidates))
10
+ model_config_patch: model_config_patch && Phronomy::Values::Immutable.copy(model_config_patch),
11
+ segment_candidates: segment_candidates && Phronomy::Values::Immutable.copy(Array(segment_candidates))
12
12
  )
13
13
  freeze
14
14
  end
@@ -1,11 +1,15 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require_relative "../../engine/concurrency/worker_input_restricted"
4
+
3
5
  require "securerandom"
4
6
  require "time"
5
7
 
6
8
  module Phronomy
7
9
  module Agent
8
10
  class AgentExecution
11
+ include Phronomy::Concurrency::WorkerInputRestricted
12
+
9
13
  ACTIVE_STATUSES = %i[preparing active suspended].freeze
10
14
  TERMINAL_STATUSES = %i[completed handed_off failed cancelled rejected blocked].freeze
11
15
  TRANSITIONS = {
@@ -55,13 +59,13 @@ module Phronomy
55
59
  ATTRIBUTES.each do |name|
56
60
  value = attributes.fetch(name)
57
61
  value = value.to_sym if %i[status phase].include?(name)
58
- instance_variable_set("@#{name}", Immutable.copy(value))
62
+ instance_variable_set("@#{name}", Phronomy::Values::Immutable.copy(value))
59
63
  end
60
64
  raise ArgumentError, "unknown execution status: #{status.inspect}" unless TRANSITIONS.key?(status)
61
65
  raise ArgumentError, "execution_revision must be non-negative" if execution_revision.negative?
62
- Immutable.validate_canonical_json!(metadata, label: "Execution metadata")
66
+ Phronomy::Values::Immutable.validate_canonical_json!(metadata, label: "Execution metadata")
63
67
  if approval_request
64
- Immutable.validate_canonical_json!(approval_request, label: "Approval request")
68
+ Phronomy::Values::Immutable.validate_canonical_json!(approval_request, label: "Approval request")
65
69
  end
66
70
  freeze
67
71
  end
@@ -86,7 +90,7 @@ module Phronomy
86
90
  end
87
91
 
88
92
  # Current semantic payload representation. Persistence format identity and
89
- # compatibility validation are owned by Persistence::DurableCodec.
93
+ # compatibility validation are owned by Agent::Persistence::Codec.
90
94
  # @api public
91
95
  def to_h
92
96
  ATTRIBUTES.to_h do |name|
@@ -1,22 +1,17 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require_relative "../../engine/concurrency/worker_input_restricted"
4
+
3
5
  require "securerandom"
4
6
  require "time"
5
7
 
6
8
  module Phronomy
7
9
  module Agent
8
10
  class AgentInvocation
11
+ include Phronomy::Concurrency::WorkerInputRestricted
12
+
9
13
  # execution_id is the logical Agent execution parent. Concrete Runtime
10
14
  # routing identity belongs only to the owning FSMSession incarnation.
11
- TOOL_EVENT_TYPES = %i[
12
- tool_authorized
13
- tool_approval_required
14
- tool_completed
15
- tool_failed
16
- tool_rejected
17
- tool_cancelled
18
- ].freeze
19
-
20
15
  LLM_EVENT_TYPES = %i[llm_completed llm_failed].freeze
21
16
  CALLBACK_FAILED_EVENTS = %i[application_callback_failed].freeze
22
17
  SETUP_FAILED_EVENTS = %i[llm_setup_failed tool_setup_failed].freeze
@@ -147,11 +142,11 @@ module Phronomy
147
142
  if durable_id.nil? &&
148
143
  Phronomy::Runtime.instance.event_loop.current?
149
144
  state =
150
- Phronomy::Runtime.instance.event_loop.agent_execution_state(
145
+ Phronomy::Agent::ExecutionRegistry.for(Phronomy::Runtime.instance.event_loop).agent_execution_state(
151
146
  execution_id
152
147
  )
153
148
  durable_id = state&.execution&.metadata&.fetch(
154
- RecoverySupport::PENDING_LLM_ID_KEY,
149
+ ExecutionMetadata::PENDING_LLM_ID_KEY,
155
150
  nil
156
151
  )
157
152
  end
@@ -209,7 +204,7 @@ module Phronomy
209
204
  return true
210
205
  end
211
206
 
212
- return false unless TOOL_EVENT_TYPES.include?(event.type)
207
+ return false unless InvocationTransitions::TOOL_EVENTS.include?(event.type)
213
208
 
214
209
  invocation = tool_invocation(event.payload&.fetch(:tool_invocation_id, nil))
215
210
  return true unless invocation
@@ -540,7 +535,7 @@ module Phronomy
540
535
  # listener receives the notification event separately.
541
536
  @runtime_events << StreamEvent.new(
542
537
  type: event.type,
543
- payload: Immutable.copy(event.payload)
538
+ payload: Phronomy::Values::Immutable.copy(event.payload)
544
539
  )
545
540
  listener = @callback_failure ? nil : @event_listener
546
541
  return unless listener