agentengine-sdk-python 0.8.5__py3-none-any.whl → 0.8.6__py3-none-any.whl

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 (851) hide show
  1. {agentengine_sdk_python-0.8.5.dist-info → agentengine_sdk_python-0.8.6.dist-info}/METADATA +12 -8
  2. {agentengine_sdk_python-0.8.5.dist-info → agentengine_sdk_python-0.8.6.dist-info}/RECORD +823 -388
  3. ksadk/_async_iterators.py +79 -0
  4. ksadk/_build_provenance.json +1 -1
  5. ksadk/_model_anthropic.py +49 -0
  6. ksadk/_model_input.py +86 -0
  7. ksadk/_model_json.py +40 -0
  8. ksadk/_model_reasoning.py +17 -0
  9. ksadk/_model_refusal.py +20 -0
  10. ksadk/_model_sse.py +163 -0
  11. ksadk/a2a/__init__.py +157 -167
  12. ksadk/a2a/_invocation_state.py +86 -0
  13. ksadk/a2a/_space_client_events.py +33 -22
  14. ksadk/a2a/adk.py +194 -0
  15. ksadk/a2a/adk_invocation_context.py +242 -0
  16. ksadk/a2a/adk_runtime.py +126 -0
  17. ksadk/a2a/adk_tools.py +319 -0
  18. ksadk/a2a/bootstrap.py +149 -23
  19. ksadk/a2a/build_validation.py +147 -0
  20. ksadk/a2a/card.py +23 -15
  21. ksadk/a2a/codex.py +160 -0
  22. ksadk/a2a/codex_checkpoint.py +111 -0
  23. ksadk/a2a/codex_recovery.py +96 -0
  24. ksadk/a2a/codex_recovery_events.py +123 -0
  25. ksadk/a2a/codex_runtime.py +198 -0
  26. ksadk/a2a/codex_session_checkpoint.py +162 -0
  27. ksadk/a2a/composition.py +88 -0
  28. ksadk/a2a/context_store.py +118 -19
  29. ksadk/a2a/control_plane.py +108 -106
  30. ksadk/a2a/event_adapter.py +92 -193
  31. ksadk/a2a/executor.py +257 -85
  32. ksadk/a2a/exposure.py +106 -0
  33. ksadk/a2a/external_transport.py +3 -4
  34. ksadk/a2a/identity.py +106 -12
  35. ksadk/a2a/ids.py +14 -3
  36. ksadk/a2a/inbound_kernel.py +133 -0
  37. ksadk/a2a/interaction_wire.py +76 -0
  38. ksadk/a2a/invocation_checkpoint.py +274 -0
  39. ksadk/a2a/invocation_policy.py +87 -0
  40. ksadk/a2a/invocation_publication.py +210 -0
  41. ksadk/a2a/invocation_service.py +972 -0
  42. ksadk/a2a/invocation_types.py +459 -0
  43. ksadk/a2a/kernel_task_adapter.py +259 -0
  44. ksadk/a2a/langgraph.py +20 -7
  45. ksadk/a2a/langgraph_invocation_context.py +136 -0
  46. ksadk/a2a/langgraph_managed.py +150 -0
  47. ksadk/a2a/langgraph_recovery.py +32 -0
  48. ksadk/a2a/langgraph_runtime.py +89 -0
  49. ksadk/a2a/langgraph_tool_runtime.py +132 -0
  50. ksadk/a2a/langgraph_tools.py +63 -0
  51. ksadk/a2a/message_digest.py +40 -0
  52. ksadk/a2a/platform.py +389 -0
  53. ksadk/a2a/policy_refs.py +13 -0
  54. ksadk/a2a/presentation.py +402 -0
  55. ksadk/a2a/product_kernel_facts.py +177 -0
  56. ksadk/a2a/product_key.py +99 -0
  57. ksadk/a2a/protocol_errors.py +116 -0
  58. ksadk/a2a/result_text.py +49 -0
  59. ksadk/a2a/resume_store.py +93 -3
  60. ksadk/a2a/routes.py +6 -1
  61. ksadk/a2a/runtime_approval.py +198 -0
  62. ksadk/a2a/runtime_input.py +151 -0
  63. ksadk/a2a/server.py +16 -7
  64. ksadk/a2a/space_client.py +101 -16
  65. ksadk/a2a/task_adapter.py +19 -5
  66. ksadk/a2a/task_event_dispatcher.py +39 -2
  67. ksadk/a2a/task_event_outbox.py +215 -0
  68. ksadk/a2a/task_event_outbox_owned.py +130 -0
  69. ksadk/a2a/task_store.py +37 -0
  70. ksadk/a2a/tool_activity.py +176 -0
  71. ksadk/a2a/workload_tokens.py +134 -0
  72. ksadk/api/client.py +32 -79
  73. ksadk/api/sse_stream.py +96 -0
  74. ksadk/builders/code_builder.py +83 -106
  75. ksadk/builders/container_builder.py +11 -29
  76. ksadk/builders/framework_requirements.py +2 -0
  77. ksadk/builders/managed_runtime_builder.py +12 -0
  78. ksadk/builders/source_provenance.py +87 -0
  79. ksadk/cli/cmd_a2a.py +43 -0
  80. ksadk/cli/cmd_build.py +9 -0
  81. ksadk/cli/cmd_deploy.py +27 -2
  82. ksadk/cli/cmd_invoke.py +45 -92
  83. ksadk/cli/cmd_studio.py +5 -1
  84. ksadk/cli/cmd_web.py +2 -0
  85. ksadk/cli/hosted_invoke.py +206 -0
  86. ksadk/cli/invoke_content.py +60 -0
  87. ksadk/cli/runtime_bootstrap.py +27 -5
  88. ksadk/codex/_expert_request_reader.py +48 -0
  89. ksadk/codex/a2a_tools.py +140 -0
  90. ksadk/codex/async_approval.py +169 -0
  91. ksadk/codex/async_client.py +938 -0
  92. ksadk/codex/async_proxy.py +216 -0
  93. ksadk/codex/base_runtime.py +25 -0
  94. ksadk/codex/client.py +3 -1048
  95. ksadk/codex/client_payloads.py +85 -0
  96. ksadk/codex/rollout_checkpoint.py +264 -0
  97. ksadk/codex/runtime.py +290 -54
  98. ksadk/common/auth.py +2 -2
  99. ksadk/common/cloud_headers.py +36 -0
  100. ksadk/common/diagnostics.py +34 -0
  101. ksadk/common/kop_client.py +2 -1
  102. ksadk/configs/env_registry.py +106 -127
  103. ksadk/configs/env_registry_a2a.py +173 -0
  104. ksadk/configs/env_registry_studio.py +53 -5
  105. ksadk/configs/global_config.py +1 -0
  106. ksadk/configs/settings.py +6 -0
  107. ksadk/context_engine/assembler.py +9 -0
  108. ksadk/context_engine/contributors.py +80 -17
  109. ksadk/context_engine/instruction_authority.py +18 -0
  110. ksadk/conversations/attachments.py +53 -15
  111. ksadk/conversations/contracts.py +28 -9
  112. ksadk/conversations/message_projection.py +30 -125
  113. ksadk/conversations/message_projection_blocks.py +137 -0
  114. ksadk/conversations/model_context.py +11 -3
  115. ksadk/conversations/projector.py +63 -0
  116. ksadk/conversations/runtime_compaction.py +7 -2
  117. ksadk/conversations/runtime_input.py +16 -4
  118. ksadk/conversations/runtime_payloads.py +4 -0
  119. ksadk/conversations/runtime_persistence.py +192 -24
  120. ksadk/conversations/runtime_preparation.py +85 -6
  121. ksadk/conversations/runtime_projection.py +217 -0
  122. ksadk/conversations/runtime_resume.py +141 -70
  123. ksadk/conversations/tool_receipt_resume.py +387 -0
  124. ksadk/conversations/tool_receipts.py +32 -0
  125. ksadk/deployment/env_forward.py +5 -0
  126. ksadk/deployment/manager.py +15 -6
  127. ksadk/deployment/providers/serverless.py +76 -136
  128. ksadk/deployment/providers/serverless_payloads.py +122 -0
  129. ksadk/evaluation/agent_eval_client.py +2 -1
  130. ksadk/evaluation/contracts.py +78 -3
  131. ksadk/evaluation/evaluators.py +166 -1
  132. ksadk/evaluation/evidence.py +271 -4
  133. ksadk/evaluation/local_adapter.py +76 -12
  134. ksadk/evaluation/studio_build_adapter.py +73 -9
  135. ksadk/events/adapters/_a2a_checkpoint.py +151 -0
  136. ksadk/events/adapters/_a2a_snapshot.py +18 -14
  137. ksadk/events/adapters/_a2a_support.py +15 -3
  138. ksadk/events/adapters/_a2a_tool_activity.py +123 -0
  139. ksadk/events/adapters/_codex_errors.py +49 -0
  140. ksadk/events/adapters/_langgraph_support.py +12 -1
  141. ksadk/events/adapters/a2a.py +54 -26
  142. ksadk/events/adapters/adk.py +188 -30
  143. ksadk/events/adapters/codex.py +33 -7
  144. ksadk/events/adapters/langgraph.py +16 -6
  145. ksadk/events/canonical.py +5 -0
  146. ksadk/events/canonical_store.py +200 -4
  147. ksadk/events/reducer.py +82 -0
  148. ksadk/events/run_authority.py +176 -0
  149. ksadk/harness/__init__.py +4 -0
  150. ksadk/harness/artifact_adapters/__init__.py +1 -0
  151. ksadk/harness/artifact_adapters/native_page_budget.py +172 -0
  152. ksadk/harness/artifact_adapters/native_search.py +249 -0
  153. ksadk/harness/artifact_adapters/native_search_budget.py +134 -0
  154. ksadk/harness/artifact_adapters/native_store.py +115 -0
  155. ksadk/harness/artifact_adapters/native_tool.py +222 -0
  156. ksadk/harness/artifact_store.py +26 -9
  157. ksadk/harness/browser_adapters/__init__.py +6 -0
  158. ksadk/harness/browser_adapters/native_browser_tool.py +92 -0
  159. ksadk/harness/browser_adapters/native_dom_snapshot.py +187 -0
  160. ksadk/harness/browser_adapters/native_playwright.py +953 -0
  161. ksadk/harness/browser_adapters/native_vision.py +295 -0
  162. ksadk/harness/capability_adapters/__init__.py +1 -0
  163. ksadk/harness/capability_adapters/native_dsh.py +289 -0
  164. ksadk/harness/capability_runtime.py +104 -9
  165. ksadk/harness/compaction_record.py +31 -0
  166. ksadk/harness/compiler.py +3 -3
  167. ksadk/harness/config.py +28 -5
  168. ksadk/harness/conformance/contract.py +9 -11
  169. ksadk/harness/context_engine.py +18 -33
  170. ksadk/harness/context_sections.py +397 -0
  171. ksadk/harness/diagnostic_adapters/__init__.py +1 -0
  172. ksadk/harness/diagnostic_adapters/contracts.py +70 -0
  173. ksadk/harness/diagnostic_adapters/lsp_rpc.py +210 -0
  174. ksadk/harness/diagnostic_adapters/native_lsp.py +286 -0
  175. ksadk/harness/engine/completion_guard.py +16 -1
  176. ksadk/harness/engine/context_pipeline.py +864 -92
  177. ksadk/harness/engine/graph_builder.py +123 -630
  178. ksadk/harness/engine/hooked_reasoner.py +380 -0
  179. ksadk/harness/engine/langgraph.py +126 -8
  180. ksadk/harness/engine/mcp_disclosure.py +65 -114
  181. ksadk/harness/engine/phases/__init__.py +6 -0
  182. ksadk/harness/engine/phases/context.py +48 -0
  183. ksadk/harness/engine/phases/interaction.py +31 -0
  184. ksadk/harness/engine/phases/reason.py +552 -0
  185. ksadk/harness/engine/phases/tools.py +638 -0
  186. ksadk/harness/engine/policy_runtime.py +21 -10
  187. ksadk/harness/engine/postgres_checkpointer.py +325 -2
  188. ksadk/harness/engine/run_control_bridge.py +21 -1
  189. ksadk/harness/engine/run_types.py +10 -0
  190. ksadk/harness/engine/skill_disclosure.py +98 -12
  191. ksadk/harness/engine/steering.py +177 -0
  192. ksadk/harness/engine/subagents.py +18 -1
  193. ksadk/harness/engine/tool_dispatch.py +112 -7
  194. ksadk/harness/events.py +39 -2
  195. ksadk/harness/execution_policy.py +10 -0
  196. ksadk/harness/hooks.py +259 -0
  197. ksadk/harness/loop/reason.py +281 -36
  198. ksadk/harness/loop/tools.py +157 -12
  199. ksadk/harness/managed_runtime.py +254 -94
  200. ksadk/harness/mcp_disclosure_contract.py +85 -0
  201. ksadk/harness/mcp_result_policy.py +44 -0
  202. ksadk/harness/mcp_runtime.py +33 -0
  203. ksadk/harness/micro_compact.py +69 -0
  204. ksadk/harness/model_adapters/__init__.py +1 -0
  205. ksadk/harness/model_adapters/native_mcp_media.py +100 -0
  206. ksadk/harness/model_adapters/native_mcp_result.py +36 -0
  207. ksadk/harness/model_adapters/native_openai.py +703 -0
  208. ksadk/harness/model_capability.py +223 -8
  209. ksadk/harness/model_provider.py +214 -4
  210. ksadk/harness/multimodal.py +57 -0
  211. ksadk/harness/native/__init__.py +1 -0
  212. ksadk/harness/native/activation_contract.py +25 -0
  213. ksadk/harness/native/activation_recovery.py +29 -0
  214. ksadk/harness/native/adapters.py +291 -0
  215. ksadk/harness/native/artifact_contract.py +14 -0
  216. ksadk/harness/native/artifact_partial_read_capacity.py +171 -0
  217. ksadk/harness/native/artifact_read_capacity.py +182 -0
  218. ksadk/harness/native/artifact_read_contract.py +27 -0
  219. ksadk/harness/native/artifact_runtime.py +408 -0
  220. ksadk/harness/native/artifact_search_capacity.py +206 -0
  221. ksadk/harness/native/artifact_search_contract.py +40 -0
  222. ksadk/harness/native/artifact_single_read_capacity.py +170 -0
  223. ksadk/harness/native/browser_contract.py +229 -0
  224. ksadk/harness/native/browser_recovery.py +183 -0
  225. ksadk/harness/native/capabilities.py +204 -0
  226. ksadk/harness/native/child_approval.py +60 -0
  227. ksadk/harness/native/child_budget.py +136 -0
  228. ksadk/harness/native/child_cancellation.py +80 -0
  229. ksadk/harness/native/child_input.py +98 -0
  230. ksadk/harness/native/child_input_runtime.py +59 -0
  231. ksadk/harness/native/child_interruption.py +81 -0
  232. ksadk/harness/native/child_lifecycle.py +246 -0
  233. ksadk/harness/native/child_lifecycle_contract.py +91 -0
  234. ksadk/harness/native/child_notifications.py +75 -0
  235. ksadk/harness/native/child_promotion.py +66 -0
  236. ksadk/harness/native/command_runtime.py +99 -0
  237. ksadk/harness/native/completion.py +302 -0
  238. ksadk/harness/native/completion_text.py +116 -0
  239. ksadk/harness/native/context.py +358 -0
  240. ksadk/harness/native/context_artifact_page.py +75 -0
  241. ksadk/harness/native/context_compaction_projection.py +131 -0
  242. ksadk/harness/native/context_contributions.py +320 -0
  243. ksadk/harness/native/context_contributor_contract.py +133 -0
  244. ksadk/harness/native/context_driver.py +820 -0
  245. ksadk/harness/native/context_fresh_tools.py +49 -0
  246. ksadk/harness/native/context_history.py +272 -0
  247. ksadk/harness/native/context_microcompact.py +61 -0
  248. ksadk/harness/native/context_partial_summary.py +58 -0
  249. ksadk/harness/native/context_partition.py +492 -0
  250. ksadk/harness/native/context_pruning.py +275 -0
  251. ksadk/harness/native/context_reduction.py +60 -0
  252. ksadk/harness/native/context_replay.py +148 -0
  253. ksadk/harness/native/context_request_projection.py +526 -0
  254. ksadk/harness/native/context_runtime.py +976 -0
  255. ksadk/harness/native/context_runtime_contracts.py +409 -0
  256. ksadk/harness/native/context_search.py +112 -0
  257. ksadk/harness/native/context_source_fragments.py +188 -0
  258. ksadk/harness/native/context_source_progress.py +119 -0
  259. ksadk/harness/native/context_summary_planning.py +788 -0
  260. ksadk/harness/native/context_summary_recovery.py +105 -0
  261. ksadk/harness/native/delivery_review.py +331 -0
  262. ksadk/harness/native/delivery_review_contract.py +54 -0
  263. ksadk/harness/native/effect_admission.py +82 -0
  264. ksadk/harness/native/effect_control.py +318 -0
  265. ksadk/harness/native/effect_receipts.py +729 -0
  266. ksadk/harness/native/effect_runtime.py +303 -0
  267. ksadk/harness/native/effective_configuration.py +28 -0
  268. ksadk/harness/native/engine.py +945 -0
  269. ksadk/harness/native/final_output.py +34 -0
  270. ksadk/harness/native/final_submission.py +58 -0
  271. ksadk/harness/native/finalization_workspace.py +96 -0
  272. ksadk/harness/native/fork.py +151 -0
  273. ksadk/harness/native/guidance.py +91 -0
  274. ksadk/harness/native/history.py +381 -0
  275. ksadk/harness/native/hook_executor.py +205 -0
  276. ksadk/harness/native/hook_runtime_contract.py +282 -0
  277. ksadk/harness/native/interaction_observation.py +117 -0
  278. ksadk/harness/native/lease.py +103 -0
  279. ksadk/harness/native/machine.py +974 -0
  280. ksadk/harness/native/mcp_result_governance.py +156 -0
  281. ksadk/harness/native/model.py +570 -0
  282. ksadk/harness/native/model_feedback.py +63 -0
  283. ksadk/harness/native/model_input.py +30 -0
  284. ksadk/harness/native/model_recovery_contract.py +35 -0
  285. ksadk/harness/native/model_replay.py +128 -0
  286. ksadk/harness/native/model_request.py +133 -0
  287. ksadk/harness/native/model_runtime.py +196 -0
  288. ksadk/harness/native/model_takeover.py +419 -0
  289. ksadk/harness/native/model_tool_batch.py +40 -0
  290. ksadk/harness/native/observed_progress.py +46 -0
  291. ksadk/harness/native/operator_guidance.py +201 -0
  292. ksadk/harness/native/output_contract.py +80 -0
  293. ksadk/harness/native/output_recovery.py +24 -0
  294. ksadk/harness/native/ports.py +749 -0
  295. ksadk/harness/native/precompact_hook_runtime.py +171 -0
  296. ksadk/harness/native/replay_context.py +149 -0
  297. ksadk/harness/native/request_media.py +112 -0
  298. ksadk/harness/native/restore_contract.py +16 -0
  299. ksadk/harness/native/run_clock.py +120 -0
  300. ksadk/harness/native/state.py +436 -0
  301. ksadk/harness/native/steering.py +170 -0
  302. ksadk/harness/native/stop_hook_runtime.py +151 -0
  303. ksadk/harness/native/studio_admission.py +29 -0
  304. ksadk/harness/native/subagents.py +86 -0
  305. ksadk/harness/native/task_policy.py +99 -0
  306. ksadk/harness/native/task_progress.py +86 -0
  307. ksadk/harness/native/terminal_verification.py +43 -0
  308. ksadk/harness/native/tool_argument_feedback.py +178 -0
  309. ksadk/harness/native/tool_budget.py +253 -0
  310. ksadk/harness/native/tool_error_streak.py +89 -0
  311. ksadk/harness/native/tool_hook_runtime.py +343 -0
  312. ksadk/harness/native/tool_input_validation.py +58 -0
  313. ksadk/harness/native/tool_interruption.py +96 -0
  314. ksadk/harness/native/tool_observation.py +259 -0
  315. ksadk/harness/native/tool_progress.py +223 -0
  316. ksadk/harness/native/tool_recovery.py +25 -0
  317. ksadk/harness/native/tool_scheduling.py +33 -0
  318. ksadk/harness/native/tool_schema.py +126 -0
  319. ksadk/harness/native/transitions.py +151 -0
  320. ksadk/harness/native/turn_control.py +98 -0
  321. ksadk/harness/native/user_document.py +98 -0
  322. ksadk/harness/native/user_document_capture.py +49 -0
  323. ksadk/harness/native/user_input.py +87 -0
  324. ksadk/harness/native/verification.py +432 -0
  325. ksadk/harness/native/verification_binding.py +40 -0
  326. ksadk/harness/native/verification_runtime.py +233 -0
  327. ksadk/harness/native/verification_workspace.py +67 -0
  328. ksadk/harness/native_driver_failure.py +123 -0
  329. ksadk/harness/native_facade.py +977 -0
  330. ksadk/harness/native_factory.py +244 -0
  331. ksadk/harness/native_projection.py +503 -0
  332. ksadk/harness/native_runtime.py +621 -0
  333. ksadk/harness/native_shadow.py +250 -0
  334. ksadk/harness/native_shadow_inputs.py +146 -0
  335. ksadk/harness/progress_adapters/__init__.py +5 -0
  336. ksadk/harness/progress_adapters/native_todo.py +75 -0
  337. ksadk/harness/prompt_cache.py +65 -3
  338. ksadk/harness/public_activity.py +59 -0
  339. ksadk/harness/public_output.py +30 -0
  340. ksadk/harness/public_summary.py +36 -0
  341. ksadk/harness/reasoner.py +331 -22
  342. ksadk/harness/rpc.py +200 -0
  343. ksadk/harness/run_control.py +107 -2
  344. ksadk/harness/runtime.py +11 -2
  345. ksadk/harness/runtime_capabilities.py +71 -1
  346. ksadk/harness/sandbox_backend.py +203 -0
  347. ksadk/harness/sdk.py +153 -0
  348. ksadk/harness/session_store.py +370 -24
  349. ksadk/harness/skill_adapters/__init__.py +1 -0
  350. ksadk/harness/skill_adapters/native_bundle.py +148 -0
  351. ksadk/harness/skill_adapters/native_disclosure.py +306 -0
  352. ksadk/harness/skill_intent.py +47 -0
  353. ksadk/harness/skill_runtime.py +74 -16
  354. ksadk/harness/spec.py +20 -10
  355. ksadk/harness/state.py +2 -0
  356. ksadk/harness/stores/__init__.py +14 -0
  357. ksadk/harness/stores/native_command_settlement.py +65 -0
  358. ksadk/harness/stores/native_contract.py +311 -0
  359. ksadk/harness/stores/native_memory.py +326 -0
  360. ksadk/harness/stores/native_memory_archive.py +70 -0
  361. ksadk/harness/stores/native_migration_cli.py +91 -0
  362. ksadk/harness/stores/native_outbox.py +56 -0
  363. ksadk/harness/stores/native_sqlite.py +782 -0
  364. ksadk/harness/stores/native_sqlite_audit.py +29 -0
  365. ksadk/harness/stores/native_sqlite_migration.py +252 -0
  366. ksadk/harness/subagent.py +12 -2
  367. ksadk/harness/subagent_adapters/checkpoint_recovery.py +120 -0
  368. ksadk/harness/subagent_adapters/native_background_child.py +803 -0
  369. ksadk/harness/subagent_adapters/native_child.py +819 -0
  370. ksadk/harness/subagent_adapters/native_child_approval.py +128 -0
  371. ksadk/harness/subagent_adapters/native_child_continuation.py +51 -0
  372. ksadk/harness/subagent_adapters/native_child_result.py +392 -0
  373. ksadk/harness/subagent_adapters/prepared_recovery.py +120 -0
  374. ksadk/harness/tool_display.py +75 -0
  375. ksadk/harness/tool_display_contract.py +134 -0
  376. ksadk/harness/tool_output.py +141 -0
  377. ksadk/harness/tool_policy.py +3 -0
  378. ksadk/harness/tool_result_policy.py +216 -0
  379. ksadk/harness/tools.py +52 -0
  380. ksadk/harness/workspace_adapters/__init__.py +6 -0
  381. ksadk/harness/workspace_adapters/native_directory.py +180 -0
  382. ksadk/harness/workspace_adapters/native_git.py +208 -0
  383. ksadk/harness/workspace_adapters/native_isolation.py +350 -0
  384. ksadk/interaction/providers/langgraph.py +8 -1
  385. ksadk/kernel/bootstrap.py +144 -160
  386. ksadk/kernel/contract_fingerprints.py +45 -1
  387. ksadk/kernel/contracts.py +25 -0
  388. ksadk/kernel/control.py +153 -33
  389. ksadk/kernel/execution_grants.py +209 -2
  390. ksadk/kernel/execution_grants_memory.py +127 -8
  391. ksadk/kernel/execution_grants_postgres.py +188 -10
  392. ksadk/kernel/execution_grants_sqlite.py +235 -9
  393. ksadk/kernel/execution_host_ingress.py +1071 -0
  394. ksadk/kernel/history_projection.py +120 -0
  395. ksadk/kernel/ingress.py +117 -204
  396. ksadk/kernel/ingress_bootstrap.py +268 -0
  397. ksadk/kernel/legacy_history.py +179 -0
  398. ksadk/kernel/memory_store.py +38 -48
  399. ksadk/kernel/memory_store_projection.py +63 -0
  400. ksadk/kernel/postgres_event_log.py +181 -0
  401. ksadk/kernel/postgres_store.py +167 -198
  402. ksadk/kernel/readiness.py +125 -0
  403. ksadk/kernel/recovery.py +89 -3
  404. ksadk/kernel/recovery_projection.py +124 -0
  405. ksadk/kernel/runtime_checkpoint.py +34 -0
  406. ksadk/kernel/sql/001_agent_kernel.sql +5 -0
  407. ksadk/kernel/sqlite_schema.py +100 -0
  408. ksadk/kernel/sqlite_store.py +147 -216
  409. ksadk/kernel/store.py +47 -15
  410. ksadk/kernel/teams_artifact_tools.py +392 -0
  411. ksadk/kernel/teams_effects.py +851 -0
  412. ksadk/kernel/teams_execution_context.py +408 -0
  413. ksadk/kernel/teams_host_http.py +237 -0
  414. ksadk/kernel/teams_material_transport.py +245 -0
  415. ksadk/kernel/teams_materials.py +318 -0
  416. ksadk/kernel/teams_runtime_bootstrap.py +604 -0
  417. ksadk/kernel/teams_tool_runtime.py +273 -0
  418. ksadk/kernel/teams_workspace.py +259 -0
  419. ksadk/kernel/worker.py +323 -332
  420. ksadk/kernel/worker_controls.py +454 -0
  421. ksadk/kernel/worker_identity.py +27 -0
  422. ksadk/kernel/worker_interactions.py +197 -0
  423. ksadk/knowledge_base/client.py +15 -1
  424. ksadk/managed_runtime.py +29 -2
  425. ksadk/memory/adk/backends/http_ltm_backend.py +2 -1
  426. ksadk/memory/adk/backends/sdk_ltm_backend.py +15 -1
  427. ksadk/memory/adk/bounded_database_session_service.py +232 -0
  428. ksadk/memory/adk/resilient_session_service.py +115 -15
  429. ksadk/memory/adk/short_term_memory.py +8 -9
  430. ksadk/memory/extraction.py +120 -7
  431. ksadk/memory/providers/local_candidates.py +183 -0
  432. ksadk/memory/providers/local_sqlite.py +252 -78
  433. ksadk/memory/resolved_policy.py +12 -7
  434. ksadk/model_gateway/__init__.py +29 -0
  435. ksadk/model_gateway/client.py +253 -0
  436. ksadk/model_gateway/events.py +113 -0
  437. ksadk/model_gateway/matrix.py +297 -0
  438. ksadk/model_proxy/compat.py +670 -0
  439. ksadk/model_proxy/server.py +10 -7
  440. ksadk/model_proxy/transform.py +37 -9
  441. ksadk/plugins/bridges/dsh.py +18 -20
  442. ksadk/plugins/bridges/dsh_profile_manifest.py +36 -0
  443. ksadk/plugins/builtin_resources.py +199 -0
  444. ksadk/plugins/builtins.py +380 -186
  445. ksadk/plugins/context_contributor.py +15 -4
  446. ksadk/plugins/dsh_dependency_policy.py +41 -0
  447. ksadk/plugins/dsh_toolchain.py +24 -35
  448. ksadk/plugins/execution_host.py +8 -0
  449. ksadk/plugins/host.py +73 -5
  450. ksadk/plugins/kernel_adapter.py +44 -1
  451. ksadk/plugins/memory_provider.py +180 -0
  452. ksadk/plugins/providers/_process_group.py +50 -0
  453. ksadk/plugins/providers/bundles/dsh-knowledge/index.mjs +24 -2
  454. ksadk/plugins/providers/bundles/dsh-knowledge/package.json +1 -1
  455. ksadk/plugins/providers/bundles/dsh-memory/package.json +1 -1
  456. ksadk/plugins/providers/bundles/dsh-skill-center/package.json +1 -1
  457. ksadk/plugins/providers/bundles/dsh-teams-tools/package.json +1 -1
  458. ksadk/plugins/providers/bundles/ksadk-dsh-capability-host/package.json +1 -1
  459. ksadk/plugins/providers/codex.py +42 -38
  460. ksadk/plugins/providers/codex_native.py +20 -0
  461. ksadk/plugins/providers/codex_skills.py +46 -0
  462. ksadk/plugins/providers/dsh_capabilities.py +16 -171
  463. ksadk/plugins/providers/dsh_connector_lease.py +225 -0
  464. ksadk/plugins/providers/dsh_mcp.py +163 -1
  465. ksadk/plugins/providers/harness.py +247 -34
  466. ksadk/plugins/providers/harness_context.py +61 -0
  467. ksadk/plugins/providers/harness_contributions.py +241 -0
  468. ksadk/plugins/providers/harness_delegation.py +91 -14
  469. ksadk/plugins/providers/harness_hooks.py +121 -0
  470. ksadk/plugins/providers/harness_managed.py +269 -175
  471. ksadk/plugins/providers/harness_tools.py +165 -36
  472. ksadk/plugins/providers/legacy_catalog.py +1 -1
  473. ksadk/plugins/providers/mcp_projection.py +100 -3
  474. ksadk/plugins/providers/platform_resources.py +16 -6
  475. ksadk/plugins/teams/application.py +3 -143
  476. ksadk/plugins/teams/build_artifacts.py +460 -0
  477. ksadk/plugins/teams/cloud_contract_fingerprints.py +22 -0
  478. ksadk/plugins/teams/cloud_contracts.py +928 -0
  479. ksadk/plugins/teams/cloud_permits.py +250 -0
  480. ksadk/plugins/teams/domain.py +201 -148
  481. ksadk/plugins/teams/effect_contracts.py +255 -0
  482. ksadk/plugins/teams/execution_projection.py +255 -0
  483. ksadk/plugins/teams/leader_decisions.py +106 -0
  484. ksadk/plugins/teams/postgres_store.py +299 -85
  485. ksadk/plugins/teams/release_contracts.py +60 -0
  486. ksadk/plugins/teams/runtime.py +116 -40
  487. ksadk/plugins/teams/store.py +214 -6
  488. ksadk/plugins/teams/task_decisions.py +21 -8
  489. ksadk/plugins/teams/tool_service.py +152 -0
  490. ksadk/plugins/teams/transport.py +8 -3
  491. ksadk/resource_runtime/skill_runtime.py +3 -0
  492. ksadk/resource_runtime/socket_server.py +11 -0
  493. ksadk/resource_runtime/worker.py +28 -4
  494. ksadk/runners/_adk_a2a_stream.py +122 -0
  495. ksadk/runners/_adk_canonical_stream.py +474 -0
  496. ksadk/runners/_langgraph_canonical_streams.py +527 -0
  497. ksadk/runners/_langgraph_runner_streams.py +6 -400
  498. ksadk/runners/_langgraph_tool_projection.py +86 -0
  499. ksadk/runners/_langgraph_tools_transformer.py +27 -0
  500. ksadk/runners/adk_runner.py +195 -290
  501. ksadk/runners/base_runner.py +6 -5
  502. ksadk/runners/langgraph_runner.py +82 -86
  503. ksadk/runners/utils/loader.py +28 -14
  504. ksadk/runtime/_runner_adapter/a2ui_surface.py +145 -0
  505. ksadk/runtime/_runner_adapter/gateway_approvals.py +93 -0
  506. ksadk/runtime/_runner_adapter/stream_mapping.py +83 -128
  507. ksadk/runtime/adapter.py +40 -3
  508. ksadk/runtime/conversation_execution.py +4 -2
  509. ksadk/runtime/executor.py +97 -7
  510. ksadk/runtime/factory.py +13 -6
  511. ksadk/runtime/framework_adapters.py +184 -10
  512. ksadk/runtime/hosted_finalizer.py +4 -6
  513. ksadk/runtime/launch.py +2 -0
  514. ksadk/runtime/runner_adapter.py +123 -13
  515. ksadk/runtime_context.py +2 -0
  516. ksadk/sandbox/backends/e2b.py +30 -4
  517. ksadk/sandbox/backends/local_process.py +10 -0
  518. ksadk/sandbox/e2b_connection.py +9 -1
  519. ksadk/sandbox/local_controls.py +32 -2
  520. ksadk/sandbox/local_launcher.py +34 -0
  521. ksadk/server/factory.py +178 -25
  522. ksadk/server/history_deadline.py +158 -0
  523. ksadk/server/history_page_cache.py +129 -0
  524. ksadk/server/routes/checkpoint_audit.py +88 -0
  525. ksadk/server/routes/checkpoint_listing.py +294 -0
  526. ksadk/server/routes/checkpoint_resolution.py +73 -20
  527. ksadk/server/routes/control.py +51 -3
  528. ksadk/server/routes/display_projection.py +154 -0
  529. ksadk/server/routes/kernel_ingress.py +17 -2
  530. ksadk/server/routes/misc.py +102 -12
  531. ksadk/server/routes/models.py +25 -1
  532. ksadk/server/routes/openai_compat.py +6 -0
  533. ksadk/server/routes/projection.py +159 -216
  534. ksadk/server/routes/run.py +6 -2
  535. ksadk/server/routes/sessions.py +301 -342
  536. ksadk/server/routes/streaming.py +68 -15
  537. ksadk/server/routes/tool_receipt_claim_routes.py +107 -0
  538. ksadk/server/routes/workspace.py +5 -2
  539. ksadk/server/static/assets/{ArtifactsPanel-C1YoaKhx.js → ArtifactsPanel-CILaW-fC.js} +1 -1
  540. ksadk/server/static/assets/{CodeBlock-DHuAWfr5.js → CodeBlock-BVrNVtJC.js} +1 -1
  541. ksadk/server/static/assets/{MathMessageMarkdown-cvdrBwYr.js → MathMessageMarkdown-Dp7c4wWD.js} +1 -1
  542. ksadk/server/static/assets/{MermaidBlock-DeBkbJvI.js → MermaidBlock-Dxop8Rd7.js} +6 -6
  543. ksadk/server/static/assets/{NativeTerminalPanel-oJj44_sV.js → NativeTerminalPanel-Cjjz8B30.js} +1 -1
  544. ksadk/server/static/assets/{abnfDiagram-VCTEODGH-Dhfv25o2.js → abnfDiagram-VCTEODGH-ckWDmOzw.js} +1 -1
  545. ksadk/server/static/assets/{arc-C35w-pn1.js → arc-DqxJede-.js} +1 -1
  546. ksadk/server/static/assets/architecture-7GRP2DOG-pn_DuLy6.js +1 -0
  547. ksadk/server/static/assets/{architectureDiagram-5GKGNRK7-FoMY_u6D.js → architectureDiagram-5GKGNRK7-SEQA4bVi.js} +1 -1
  548. ksadk/server/static/assets/{blockDiagram-NRAW4CY4-zD4Rt7oE.js → blockDiagram-NRAW4CY4-pM0B-6NJ.js} +1 -1
  549. ksadk/server/static/assets/{c4Diagram-UCG6FXSJ-BCtGGkhN.js → c4Diagram-UCG6FXSJ-m2tuCNVq.js} +1 -1
  550. ksadk/server/static/assets/channel-fySsnkft.js +1 -0
  551. ksadk/server/static/assets/chunk-2Q5K7J3B-BheGxKRQ.js +1 -0
  552. ksadk/server/static/assets/{chunk-5VM5RSS4-C2Ms13_k.js → chunk-5VM5RSS4-GJHDr9Ww.js} +1 -1
  553. ksadk/server/static/assets/{chunk-F27PBJKO-BoTj-qgx.js → chunk-F27PBJKO-CbAN45AV.js} +1 -1
  554. ksadk/server/static/assets/{chunk-G27WJ6UU-DOMyyjHH.js → chunk-G27WJ6UU-D5ngbbzF.js} +1 -1
  555. ksadk/server/static/assets/{chunk-JWPE2WC7-DbJJqDli.js → chunk-JWPE2WC7-Cc5IwuYC.js} +1 -1
  556. ksadk/server/static/assets/{chunk-LCL6LL3I-CLuRCt_W.js → chunk-LCL6LL3I-CprgDDdJ.js} +1 -1
  557. ksadk/server/static/assets/{chunk-POPQ4Y6H-D0Dz847e.js → chunk-POPQ4Y6H-CDZhSy82.js} +1 -1
  558. ksadk/server/static/assets/{chunk-RHFEMEQ7-BWSRzEcd.js → chunk-RHFEMEQ7-CZchUNro.js} +1 -1
  559. ksadk/server/static/assets/{chunk-SVP7TREG-CPoHqkCY.js → chunk-SVP7TREG-BVruqk6T.js} +1 -1
  560. ksadk/server/static/assets/{chunk-XXDRQBXY-Bx1jS-X-.js → chunk-XXDRQBXY-4ld9SxPN.js} +1 -1
  561. ksadk/server/static/assets/classDiagram-DTDB5LWJ-DSfLtNYm.js +1 -0
  562. ksadk/server/static/assets/classDiagram-v2-JRS7N3AN-DSfLtNYm.js +1 -0
  563. ksadk/server/static/assets/{cose-bilkent-JH36ORCC-LzyWm4m0.js → cose-bilkent-JH36ORCC-Dmyyk_Vp.js} +1 -1
  564. ksadk/server/static/assets/cynefin-OW5HDTMX-PFWIGtvA.js +1 -0
  565. ksadk/server/static/assets/{cynefinDiagram-5FMLGOSQ-BlW_bHED.js → cynefinDiagram-5FMLGOSQ-BIyq3EJb.js} +1 -1
  566. ksadk/server/static/assets/{dagre-3AP2YEHR-Bu_S86_i.js → dagre-3AP2YEHR-eBw08Qdk.js} +1 -1
  567. ksadk/server/static/assets/{dagre-B7nCawed.js → dagre-DfvnEf45.js} +1 -1
  568. ksadk/server/static/assets/{diagram-S7CK7UJ4-W_Zow2Km.js → diagram-S7CK7UJ4-CUSrE3Mg.js} +1 -1
  569. ksadk/server/static/assets/{diagram-UQ7AKVKN-CLIKAHON.js → diagram-UQ7AKVKN-Dq5Zw2gy.js} +1 -1
  570. ksadk/server/static/assets/{diagram-VSXAHHWV-Dv6_QAlN.js → diagram-VSXAHHWV-DyUHfNwT.js} +1 -1
  571. ksadk/server/static/assets/{diagram-VX7I27RA-BWAWRDtZ.js → diagram-VX7I27RA-CREmM89O.js} +1 -1
  572. ksadk/server/static/assets/{diagram-Z3DM3KII-XA_rWMss.js → diagram-Z3DM3KII-Dw9zhHUK.js} +1 -1
  573. ksadk/server/static/assets/{dist-CGt_UGeO.js → dist-0uJ4tdx6.js} +1 -1
  574. ksadk/server/static/assets/{dist-C0J5_3qM.js → dist-AEv-vXf-.js} +1 -1
  575. ksadk/server/static/assets/{dist-CIpWk_5f.js → dist-B49GzZDb.js} +1 -1
  576. ksadk/server/static/assets/{dist-B3bA05-e.js → dist-B8Myiet9.js} +1 -1
  577. ksadk/server/static/assets/{dist-DWfdmz9s.js → dist-BBsYarrI.js} +1 -1
  578. ksadk/server/static/assets/{dist-BLpRy_Yx.js → dist-BQMrUwdI.js} +1 -1
  579. ksadk/server/static/assets/{dist-CIRMvUM4.js → dist-BX_-FENW.js} +1 -1
  580. ksadk/server/static/assets/{dist-BdNFAney.js → dist-CD4L6ymH.js} +1 -1
  581. ksadk/server/static/assets/{dist-n3n6t_FO.js → dist-CHpW1BHj.js} +1 -1
  582. ksadk/server/static/assets/{dist-DppE_r-D.js → dist-CVPau3tn.js} +1 -1
  583. ksadk/server/static/assets/{dist-qe8xjesy.js → dist-C_qdxcSH.js} +1 -1
  584. ksadk/server/static/assets/{dist-2vL2sAdF.js → dist-Co68Apq4.js} +1 -1
  585. ksadk/server/static/assets/{dist-1nXCdsej.js → dist-Cp2PaOMY.js} +1 -1
  586. ksadk/server/static/assets/{dist-DNKuMzWc.js → dist-CuR5Bgme.js} +1 -1
  587. ksadk/server/static/assets/{dist-t6MzE0jU.js → dist-DDSyLEOX.js} +1 -1
  588. ksadk/server/static/assets/{dist-CPyieXEf.js → dist-DUxO0R99.js} +1 -1
  589. ksadk/server/static/assets/{dist-DyG6Ya-z.js → dist-QzbGrED_.js} +1 -1
  590. ksadk/server/static/assets/{dist-0X_j2Rcc.js → dist-bupkyEBZ.js} +1 -1
  591. ksadk/server/static/assets/{dist-mqD5TZup.js → dist-cxTGfdqx.js} +1 -1
  592. ksadk/server/static/assets/{dist-M-SrdhhZ.js → dist-hL5p1til.js} +1 -1
  593. ksadk/server/static/assets/{dist-D-92S-Fd.js → dist-lOy23y43.js} +1 -1
  594. ksadk/server/static/assets/{dist-BO_UwatH.js → dist-pq-nD33R.js} +1 -1
  595. ksadk/server/static/assets/{ebnfDiagram-PWID7BFC-BfCzF1Xi.js → ebnfDiagram-PWID7BFC-BS5LdNoR.js} +1 -1
  596. ksadk/server/static/assets/{erDiagram-SSCWMZ5O-Dpz9_0zn.js → erDiagram-SSCWMZ5O-Bv1QtiY-.js} +1 -1
  597. ksadk/server/static/assets/eventmodeling-NTZA5JFV-DsM4upQX.js +1 -0
  598. ksadk/server/static/assets/flowDiagram-A5DVABFB-D5NA16k9.js +1 -0
  599. ksadk/server/static/assets/{ganttDiagram-EL5Y4UJY-DDaG1f4_.js → ganttDiagram-EL5Y4UJY-musi-e0G.js} +1 -1
  600. ksadk/server/static/assets/gitGraph-4MIJSDKK-DUCVz-ih.js +1 -0
  601. ksadk/server/static/assets/{gitGraphDiagram-WWUBYQGX-DcxzRwYC.js → gitGraphDiagram-WWUBYQGX-DH37EGkG.js} +1 -1
  602. ksadk/server/static/assets/index-CZdkAvsv.js +244 -0
  603. ksadk/server/static/assets/index-CvXdHgF3.css +2 -0
  604. ksadk/server/static/assets/info-A6RAGUB7-rw0ZNHZp.js +1 -0
  605. ksadk/server/static/assets/{infoDiagram-RXCK75RN-CYMdn6lQ.js → infoDiagram-RXCK75RN-C1kEtv2y.js} +1 -1
  606. ksadk/server/static/assets/{ishikawaDiagram-5VMMS53U-CLHFAD6c.js → ishikawaDiagram-5VMMS53U-BCNPyMka.js} +1 -1
  607. ksadk/server/static/assets/{journeyDiagram-EYS64GPL-BHSKQGAl.js → journeyDiagram-EYS64GPL--cDbKnjP.js} +1 -1
  608. ksadk/server/static/assets/{kanban-definition-3QL26DDD-D5W3tjTT.js → kanban-definition-3QL26DDD-R1rAVw2f.js} +1 -1
  609. ksadk/server/static/assets/{katex-mtjOi4KM.js → katex-BT-X-V7U.js} +1 -1
  610. ksadk/server/static/assets/{linear-BETqsxE_.js → linear-DTR631iG.js} +1 -1
  611. ksadk/server/static/assets/{mermaid-parser.core-DPWrvs90.js → mermaid-parser.core-DfFzJhX8.js} +2 -2
  612. ksadk/server/static/assets/{mindmap-definition-FBJOCRG2-CJG2mfBP.js → mindmap-definition-FBJOCRG2-D4by_rmk.js} +1 -1
  613. ksadk/server/static/assets/packet-AYTQ26CC-Ca4Hvki9.js +1 -0
  614. ksadk/server/static/assets/{pegDiagram-XKGWAZYB-GjAPNaqn.js → pegDiagram-XKGWAZYB-xWXPEh0c.js} +1 -1
  615. ksadk/server/static/assets/pie-WAS4IAKB-hwiz6fbw.js +1 -0
  616. ksadk/server/static/assets/{pieDiagram-E7YTZNPT-ToIewrqr.js → pieDiagram-E7YTZNPT-BudBDlCI.js} +1 -1
  617. ksadk/server/static/assets/{quadrantDiagram-AXDQQJYC-4d78KiEY.js → quadrantDiagram-AXDQQJYC-DXZ0PCJF.js} +1 -1
  618. ksadk/server/static/assets/radar-RG4KPBEZ-BR1oZXLM.js +1 -0
  619. ksadk/server/static/assets/railroad-74A4TZTK-DfgEISfX.js +1 -0
  620. ksadk/server/static/assets/railroad-abnf-HS5TGJTU-CWOC3rdk.js +1 -0
  621. ksadk/server/static/assets/railroad-ebnf-LZEXJU2U-CiRvHCLY.js +1 -0
  622. ksadk/server/static/assets/railroad-peg-WCYAUIDC-DSDDyJ2f.js +1 -0
  623. ksadk/server/static/assets/{railroadDiagram-O6MQD6OU-DKzx4xfv.js → railroadDiagram-O6MQD6OU-BdAYRYB8.js} +1 -1
  624. ksadk/server/static/assets/{requirementDiagram-EFPCY7ZU-CJYljxQS.js → requirementDiagram-EFPCY7ZU-CBBmaL70.js} +1 -1
  625. ksadk/server/static/assets/{sankeyDiagram-P5KCCOFB-DLU2fV1w.js → sankeyDiagram-P5KCCOFB-Doc3rdwp.js} +1 -1
  626. ksadk/server/static/assets/{sequenceDiagram-WJ2MYXX4-CVqysrA9.js → sequenceDiagram-WJ2MYXX4-0J8R8hWW.js} +1 -1
  627. ksadk/server/static/assets/{sizeCapture-X5ZJPWSS-BUxfmTHc.js → sizeCapture-X5ZJPWSS-CfFLlWsK.js} +1 -1
  628. ksadk/server/static/assets/{stateDiagram-HBIQ2CUA-CNFgYI9E.js → stateDiagram-HBIQ2CUA-jBwkjtTy.js} +1 -1
  629. ksadk/server/static/assets/stateDiagram-v2-4QOOHH4V-Cw1fPb5w.js +1 -0
  630. ksadk/server/static/assets/{swimlanes-XN3QIQJK-B6qCMe8N.js → swimlanes-XN3QIQJK-B0WxTQf8.js} +1 -1
  631. ksadk/server/static/assets/swimlanesDiagram-VK2B7HYN-Cc3JMBAF.js +8 -0
  632. ksadk/server/static/assets/{timeline-definition-24CTP7MA-CMD3x_U_.js → timeline-definition-24CTP7MA-BfCT_75A.js} +1 -1
  633. ksadk/server/static/assets/treeView-Q6P3EWNA-C05SJHxo.js +1 -0
  634. ksadk/server/static/assets/treemap-WGGIJYW6-BqNLAhc3.js +1 -0
  635. ksadk/server/static/assets/{vennDiagram-4TSXK5OY-BqtUqvXM.js → vennDiagram-4TSXK5OY-9gX1VMDC.js} +1 -1
  636. ksadk/server/static/assets/wardley-WFR3VGLG-DokNktqB.js +1 -0
  637. ksadk/server/static/assets/{wardleyDiagram-VM6X3IG4-B5KfDjI-.js → wardleyDiagram-VM6X3IG4-sEs_BP6O.js} +1 -1
  638. ksadk/server/static/assets/{xychartDiagram-S5SC5T6Z-BaUlSZrn.js → xychartDiagram-S5SC5T6Z-Ll4jvUN9.js} +1 -1
  639. ksadk/server/static/index.html +2 -2
  640. ksadk/sessions/__init__.py +8 -1
  641. ksadk/sessions/_checkpoint_resume_audit.py +44 -0
  642. ksadk/sessions/_in_memory_query.py +112 -0
  643. ksadk/sessions/_local_service_sync.py +157 -156
  644. ksadk/sessions/_local_state_sync.py +152 -0
  645. ksadk/sessions/_local_tables.py +2 -0
  646. ksadk/sessions/_postgres_checkpoint_read.py +323 -0
  647. ksadk/sessions/_postgres_checkpoint_stats.py +330 -0
  648. ksadk/sessions/_postgres_history_read.py +678 -0
  649. ksadk/sessions/_postgres_schema.py +44 -2
  650. ksadk/sessions/_postgres_tables.py +2 -0
  651. ksadk/sessions/_postgres_tool_receipts.py +169 -0
  652. ksadk/sessions/_resilient_read.py +630 -0
  653. ksadk/sessions/_tool_receipt_sync.py +119 -0
  654. ksadk/sessions/agent_identity.py +16 -0
  655. ksadk/sessions/base.py +278 -0
  656. ksadk/sessions/db_budget.py +332 -0
  657. ksadk/sessions/errors.py +12 -0
  658. ksadk/sessions/history_budget.py +36 -0
  659. ksadk/sessions/history_identity.py +27 -0
  660. ksadk/sessions/in_memory.py +376 -113
  661. ksadk/sessions/local_service.py +345 -0
  662. ksadk/sessions/postgres_service.py +515 -549
  663. ksadk/sessions/resilience.py +21 -14
  664. ksadk/sessions/resilient.py +611 -504
  665. ksadk/skills/loader.py +44 -2
  666. ksadk/skills/runtime/backends/e2b.py +17 -14
  667. ksadk/skills/service_client.py +6 -1
  668. ksadk/studio/a2a_bindings.py +407 -0
  669. ksadk/studio/a2a_orchestration.py +178 -0
  670. ksadk/studio/active_run_output.py +92 -0
  671. ksadk/studio/activity_records.py +542 -0
  672. ksadk/studio/agent_configuration.py +173 -0
  673. ksadk/studio/api.py +219 -389
  674. ksadk/studio/api_a2a_routes.py +93 -0
  675. ksadk/studio/api_catalog_routes.py +13 -0
  676. ksadk/studio/api_cloud_chat_routes.py +382 -0
  677. ksadk/studio/api_contracts.py +23 -0
  678. ksadk/studio/attachment_store.py +14 -2
  679. ksadk/studio/build_resolution.py +117 -0
  680. ksadk/studio/build_singleflight.py +37 -0
  681. ksadk/studio/builder.py +20 -2
  682. ksadk/studio/capabilities.py +8 -3
  683. ksadk/studio/cloud.py +83 -377
  684. ksadk/studio/cloud_gateways.py +424 -0
  685. ksadk/studio/cloud_shared_web.py +7 -0
  686. ksadk/studio/codex_agent_service.py +17 -0
  687. ksadk/studio/codex_manifest.py +5 -1
  688. ksadk/studio/codex_provider_build.py +65 -0
  689. ksadk/studio/compiler.py +102 -6
  690. ksadk/studio/contract_base.py +19 -0
  691. ksadk/studio/contracts.py +231 -201
  692. ksadk/studio/dsh_application.py +58 -12
  693. ksadk/studio/dsh_capability_service.py +17 -171
  694. ksadk/studio/dsh_mcp_transport.py +191 -0
  695. ksadk/studio/event_store.py +17 -0
  696. ksadk/studio/execution_host.py +84 -11
  697. ksadk/studio/framework_run.py +18 -0
  698. ksadk/studio/interaction_submission.py +265 -0
  699. ksadk/studio/kernel_registry.py +12 -1
  700. ksadk/studio/lifecycle_status.py +43 -0
  701. ksadk/studio/model_buffered_wire.py +227 -0
  702. ksadk/studio/model_chat_tools.py +143 -0
  703. ksadk/studio/model_client.py +1241 -761
  704. ksadk/studio/model_content_stream.py +129 -0
  705. ksadk/studio/model_credentials.py +196 -0
  706. ksadk/studio/model_profile_service.py +65 -31
  707. ksadk/studio/model_request_projection.py +284 -0
  708. ksadk/studio/model_responses_content.py +296 -0
  709. ksadk/studio/model_usage.py +109 -0
  710. ksadk/studio/model_wire_failure.py +110 -0
  711. ksadk/studio/model_wire_identity.py +138 -0
  712. ksadk/studio/model_wire_snapshot.py +45 -0
  713. ksadk/studio/model_wire_tools.py +283 -0
  714. ksadk/studio/native_acceptance.py +68 -0
  715. ksadk/studio/native_approval.py +111 -0
  716. ksadk/studio/native_browser_port.py +861 -0
  717. ksadk/studio/native_child_mcp.py +87 -0
  718. ksadk/studio/native_child_publication.py +68 -0
  719. ksadk/studio/native_child_skills.py +72 -0
  720. ksadk/studio/native_child_workspace.py +176 -0
  721. ksadk/studio/native_command_policy.py +53 -0
  722. ksadk/studio/native_context_port.py +326 -0
  723. ksadk/studio/native_context_registration.py +54 -0
  724. ksadk/studio/native_document_input.py +88 -0
  725. ksadk/studio/native_final_shape.py +852 -0
  726. ksadk/studio/native_gateway_stream.py +69 -0
  727. ksadk/studio/native_hook_port.py +145 -0
  728. ksadk/studio/native_hook_registration.py +70 -0
  729. ksadk/studio/native_inventory_disclosure.py +223 -0
  730. ksadk/studio/native_kernel_admission.py +84 -0
  731. ksadk/studio/native_language_diagnostics.py +320 -0
  732. ksadk/studio/native_mcp_disclosure.py +198 -0
  733. ksadk/studio/native_mcp_tool_port.py +219 -0
  734. ksadk/studio/native_memory_acceptance.py +362 -0
  735. ksadk/studio/native_memory_context.py +266 -0
  736. ksadk/studio/native_memory_flush.py +174 -0
  737. ksadk/studio/native_memory_sources.py +80 -0
  738. ksadk/studio/native_memory_tool_port.py +360 -0
  739. ksadk/studio/native_memory_turn.py +183 -0
  740. ksadk/studio/native_model_port.py +765 -0
  741. ksadk/studio/native_model_recovery.py +126 -0
  742. ksadk/studio/native_options.py +75 -0
  743. ksadk/studio/native_output_fields.py +58 -0
  744. ksadk/studio/native_planning.py +156 -0
  745. ksadk/studio/native_product.py +988 -0
  746. ksadk/studio/native_read_budget.py +426 -0
  747. ksadk/studio/native_recovery.py +171 -0
  748. ksadk/studio/native_scope.py +35 -0
  749. ksadk/studio/native_session_context_port.py +141 -0
  750. ksadk/studio/native_session_engine.py +14 -0
  751. ksadk/studio/native_skill_source.py +74 -0
  752. ksadk/studio/native_subagent_port.py +700 -0
  753. ksadk/studio/native_terminal_recovery.py +95 -0
  754. ksadk/studio/native_test_action.py +610 -0
  755. ksadk/studio/native_tool_port.py +477 -0
  756. ksadk/studio/native_user_input.py +60 -0
  757. ksadk/studio/native_verification_presentation.py +65 -0
  758. ksadk/studio/native_workspace_diagnostics.py +183 -0
  759. ksadk/studio/native_workspace_port.py +43 -0
  760. ksadk/studio/operations.py +34 -9
  761. ksadk/studio/plugin_composition.py +26 -10
  762. ksadk/studio/plugin_kernel_adapter.py +75 -1
  763. ksadk/studio/plugin_native_activation.py +163 -0
  764. ksadk/studio/plugin_runtime.py +639 -119
  765. ksadk/studio/plugin_runtime_admission.py +57 -0
  766. ksadk/studio/presentation.py +92 -0
  767. ksadk/studio/public_output_store.py +69 -0
  768. ksadk/studio/resource_authority.py +11 -3
  769. ksadk/studio/resource_catalog.py +8 -12
  770. ksadk/studio/run_activity.py +338 -385
  771. ksadk/studio/run_controls.py +185 -0
  772. ksadk/studio/run_service.py +908 -319
  773. ksadk/studio/run_submission_receipts.py +68 -0
  774. ksadk/studio/runtime_catalog.py +23 -4
  775. ksadk/studio/runtime_prewarm.py +22 -0
  776. ksadk/studio/scheduler_assistant.py +4 -1
  777. ksadk/studio/service.py +356 -282
  778. ksadk/studio/service_settings.py +229 -0
  779. ksadk/studio/shared_web.py +393 -169
  780. ksadk/studio/shared_web_response_events.py +180 -0
  781. ksadk/studio/shared_web_run_state.py +133 -0
  782. ksadk/studio/skill_discovery.py +305 -3
  783. ksadk/studio/static/assets/ChannelsPage-xX5HlMId.js +8 -0
  784. ksadk/studio/static/assets/{CodeBlock-DMIf4h33-UIqo-BPW.js → CodeBlock-DMIf4h33-CkufcPYo.js} +3 -3
  785. ksadk/studio/static/assets/{MathMessageMarkdown-BesSeCYl-OhNwH4K9.js → MathMessageMarkdown-BesSeCYl-DYG1Wzbx.js} +1 -1
  786. ksadk/studio/static/assets/{MessageMarkdown-CwMTvgFj-g0I-I4dD.js → MessageMarkdown-CwMTvgFj-BeyLyQHu.js} +2 -2
  787. ksadk/studio/static/assets/TeamsPage-CCaaGaVp.js +3 -0
  788. ksadk/studio/static/assets/index-C7DNDik2.css +2 -0
  789. ksadk/studio/static/assets/index-Cy68gTlH.js +265 -0
  790. ksadk/studio/static/index.html +3 -3
  791. ksadk/studio/teams_catalog.py +33 -0
  792. ksadk/studio/teams_installation.py +4 -1
  793. ksadk/studio/teams_node.py +4 -0
  794. ksadk/studio/teams_node_factory.py +558 -0
  795. ksadk/studio/teams_node_runner.py +3 -0
  796. ksadk/studio/teams_node_v1.py +935 -0
  797. ksadk/studio/teams_remote.py +259 -37
  798. ksadk/studio/templates.py +1 -0
  799. ksadk/studio/workspace_plugins.py +3 -1
  800. ksadk/tools/a2a_policy.py +5 -0
  801. ksadk/tools/artifact_observation.py +53 -0
  802. ksadk/tools/captured_source_artifact.py +68 -0
  803. ksadk/tools/schema.py +34 -0
  804. ksadk/toolsets/__init__.py +82 -88
  805. ksadk/toolsets/a2a.py +89 -89
  806. ksadk/toolsets/sandbox.py +377 -6
  807. ksadk/toolsets/skill_management.py +315 -0
  808. ksadk/toolsets/tool_selection.py +94 -0
  809. ksadk/toolsets/workspace.py +342 -324
  810. ksadk/toolsets/workspace_editing.py +291 -0
  811. ksadk/toolsets/workspace_model_observation.py +104 -0
  812. ksadk/toolsets/workspace_mutation.py +75 -0
  813. ksadk/toolsets/workspace_read_budget.py +216 -0
  814. ksadk/toolsets/workspace_search.py +192 -0
  815. ksadk/toolsets/workspace_search_process.py +129 -0
  816. ksadk/toolsets/workspace_state.py +6 -0
  817. ksadk/version.py +1 -1
  818. ksadk_runtime_common/http_headers.py +18 -0
  819. ksadk_runtime_common/workspace_files/router.py +2 -1
  820. ksadk/server/static/assets/architecture-7GRP2DOG-BCsa26zi.js +0 -1
  821. ksadk/server/static/assets/channel-_KDifNys.js +0 -1
  822. ksadk/server/static/assets/chunk-2Q5K7J3B-HdVkJ9F0.js +0 -1
  823. ksadk/server/static/assets/classDiagram-DTDB5LWJ-BVCW3ZqZ.js +0 -1
  824. ksadk/server/static/assets/classDiagram-v2-JRS7N3AN-BVCW3ZqZ.js +0 -1
  825. ksadk/server/static/assets/cynefin-OW5HDTMX-CNXjFctL.js +0 -1
  826. ksadk/server/static/assets/eventmodeling-NTZA5JFV-B5-8RH9c.js +0 -1
  827. ksadk/server/static/assets/flowDiagram-A5DVABFB-BppFxEKw.js +0 -1
  828. ksadk/server/static/assets/gitGraph-4MIJSDKK-B-AhYj4C.js +0 -1
  829. ksadk/server/static/assets/index-BMd2mucF.css +0 -2
  830. ksadk/server/static/assets/index-D5qyyhTH.js +0 -244
  831. ksadk/server/static/assets/info-A6RAGUB7-0uiKrC35.js +0 -1
  832. ksadk/server/static/assets/packet-AYTQ26CC-BVTmZ_cw.js +0 -1
  833. ksadk/server/static/assets/pie-WAS4IAKB-DyfxBU7V.js +0 -1
  834. ksadk/server/static/assets/radar-RG4KPBEZ-FFontjL2.js +0 -1
  835. ksadk/server/static/assets/railroad-74A4TZTK-D0Uidzen.js +0 -1
  836. ksadk/server/static/assets/railroad-abnf-HS5TGJTU-BOo_9T2h.js +0 -1
  837. ksadk/server/static/assets/railroad-ebnf-LZEXJU2U-D6-BjW7Z.js +0 -1
  838. ksadk/server/static/assets/railroad-peg-WCYAUIDC-CXx__yMm.js +0 -1
  839. ksadk/server/static/assets/stateDiagram-v2-4QOOHH4V-BXAFScz8.js +0 -1
  840. ksadk/server/static/assets/swimlanesDiagram-VK2B7HYN-uIQ2lJKH.js +0 -8
  841. ksadk/server/static/assets/treeView-Q6P3EWNA-CK5GgucZ.js +0 -1
  842. ksadk/server/static/assets/treemap-WGGIJYW6-Bq1u1SpG.js +0 -1
  843. ksadk/server/static/assets/wardley-WFR3VGLG-QAt06uEz.js +0 -1
  844. ksadk/studio/static/assets/ChannelsPage-D_PGmKVq.js +0 -8
  845. ksadk/studio/static/assets/TeamsPage-DqX4HWKQ.js +0 -3
  846. ksadk/studio/static/assets/index-CfEnms6Y.css +0 -2
  847. ksadk/studio/static/assets/index-Dp61rOWZ.js +0 -0
  848. {agentengine_sdk_python-0.8.5.dist-info → agentengine_sdk_python-0.8.6.dist-info}/WHEEL +0 -0
  849. {agentengine_sdk_python-0.8.5.dist-info → agentengine_sdk_python-0.8.6.dist-info}/entry_points.txt +0 -0
  850. {agentengine_sdk_python-0.8.5.dist-info → agentengine_sdk_python-0.8.6.dist-info}/licenses/LICENSE +0 -0
  851. {agentengine_sdk_python-0.8.5.dist-info → agentengine_sdk_python-0.8.6.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,820 @@
1
+ """Connect context planning to committed run state, without owning model I/O."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import hashlib
6
+ import json
7
+
8
+ from .completion import VerificationReport
9
+ from .context import (
10
+ AcceptanceProgress,
11
+ ExecutionContinuityState,
12
+ PlanningProgress,
13
+ VerificationProgress,
14
+ )
15
+ from .context_contributor_contract import contributor_expired
16
+ from .context_fresh_tools import FRESH_TOOL_OBSERVATION_POLICY
17
+ from .context_partial_summary import PARTIAL_SUMMARY_POLICY, commit_completed_prefix
18
+ from .context_reduction import SUMMARY_REDUCTION_POLICY, replan_summary_projection
19
+ from .context_runtime import (
20
+ READER_SUMMARY_POLICY_VERSION,
21
+ CompactionController,
22
+ CompactionHistory,
23
+ CompactionProjectionOverflow,
24
+ CompactionRequest,
25
+ ContextPlanner,
26
+ ContextRuntimeError,
27
+ )
28
+ from .context_source_progress import source_read_progress
29
+ from .context_summary_recovery import SUMMARY_RETRY_POLICY, repartition_failed_summary
30
+ from .delivery_review import delivery_review_messages, review_pending, unavailable_review
31
+ from .machine import host_resolved_candidate
32
+ from .model import ModelTurnResult
33
+ from .model_replay import replay_binding_failure
34
+ from .operator_guidance import stage_guidance
35
+ from .ports import ArtifactRef, RunConfiguration
36
+ from .precompact_hook_runtime import (
37
+ planned_precompact_state,
38
+ precompact_feedback_keys,
39
+ precompact_feedback_messages,
40
+ )
41
+ from .state import CommitBatch, RunPhase, RunSnapshot, move, workspace_observation_cursor
42
+ from .stop_hook_runtime import hook_feedback_messages
43
+ from .tool_budget import (
44
+ finalization_only,
45
+ model_instructions,
46
+ model_tool_catalog,
47
+ model_turn_control,
48
+ )
49
+ from .tool_hook_runtime import pending_hook_operation_keys, tool_hook_feedback_messages
50
+ from .transitions import commit_transition, effect_operation_key, finish, prepare_effect
51
+ from .verification_binding import verification_subject_context_digest
52
+
53
+
54
+ class ContextDriver:
55
+ def __init__(
56
+ self,
57
+ planner: ContextPlanner | None,
58
+ workspace_revision: str,
59
+ *,
60
+ workspace_tracking: bool = False,
61
+ replay_context_policy: str | None = None,
62
+ ):
63
+ if not workspace_revision.strip():
64
+ raise ValueError("workspace revision must be explicit")
65
+ self.planner = planner
66
+ self.workspace_revision = workspace_revision
67
+ self.workspace_tracking = workspace_tracking
68
+ self.binding = (
69
+ hashlib.sha256(
70
+ json.dumps(
71
+ {
72
+ "tokenizer": planner.tokenizer_id,
73
+ "summary_budget_unit": planner.summary_budget_unit,
74
+ **(
75
+ {"summary_budget_mode": planner.summary_budget_mode}
76
+ if planner.summary_budget_mode != "strict"
77
+ else {}
78
+ ),
79
+ "policy": planner.policy.model_dump(mode="json"),
80
+ "workspace_revision": workspace_revision,
81
+ "workspace_tracking": workspace_tracking,
82
+ "request_projection": "ksadk.native.turn-control/v2",
83
+ "source_capacity_projection": "sealed-artifact-batch/v1",
84
+ "compaction_admission": "finalization-reserve/v1",
85
+ "compaction_accounting": "closed-contract-roots/v1",
86
+ "message_replay_context": "native-anthropic-input-prefix/v2",
87
+ "fresh_tool_observation": FRESH_TOOL_OBSERVATION_POLICY,
88
+ "reader_observation_projection": READER_SUMMARY_POLICY_VERSION,
89
+ "summary_projection_reduction": SUMMARY_REDUCTION_POLICY,
90
+ "summary_failure_repartition": SUMMARY_RETRY_POLICY,
91
+ "summary_partial_commit": PARTIAL_SUMMARY_POLICY,
92
+ **(
93
+ {"summary_completion_policy": planner.summary_completion_policy}
94
+ if planner.summary_completion_policy is not None
95
+ else {}
96
+ ),
97
+ **(
98
+ {"subagent_continuity_policy": planner.subagent_continuity_policy}
99
+ if planner.subagent_continuity_policy is not None
100
+ else {}
101
+ ),
102
+ **(
103
+ {"source_progress_policy": planner.source_progress_policy}
104
+ if planner.source_progress_policy is not None
105
+ else {}
106
+ ),
107
+ },
108
+ sort_keys=True,
109
+ ).encode()
110
+ ).hexdigest()
111
+ if planner
112
+ else (hashlib.sha256(
113
+ b"native-anthropic-input-prefix/v2|no-planner"
114
+ ).hexdigest() if replay_context_policy is not None else "")
115
+ )
116
+
117
+ def continuity(self, snapshot: RunSnapshot, config: RunConfiguration):
118
+ required = tuple(i.acceptance_id for i in config.contract.items if i.required)
119
+ report = (
120
+ VerificationReport.model_validate(snapshot.verification)
121
+ if snapshot.verification is not None
122
+ else None
123
+ )
124
+ cursor = snapshot.verification_tool_calls
125
+ validated = (
126
+ report is not None
127
+ and cursor is not None
128
+ and cursor <= snapshot.tool_calls
129
+ and report.contract_revision == config.contract.revision
130
+ )
131
+ since = snapshot.tool_calls - cursor if validated else None
132
+ current_binding = (
133
+ validated
134
+ and report.subject_context_digest == verification_subject_context_digest(snapshot)
135
+ )
136
+ candidate = snapshot.candidate or {}
137
+ same_candidate = report is not None and all(
138
+ candidate.get(key) == getattr(report, key)
139
+ for key in (
140
+ "candidate_id",
141
+ "subject_digest",
142
+ "subject_context_digest",
143
+ "environment_digest",
144
+ )
145
+ )
146
+ by_id = {item.acceptance_id: item for item in report.items} if report else {}
147
+ progress = []
148
+ for item in config.contract.items:
149
+ previous = by_id.get(item.acceptance_id)
150
+ status = "pending"
151
+ needs_reverification = True
152
+ if current_binding and since == 0 and previous is not None:
153
+ if previous.status in {"failed", "blocked"}:
154
+ status = previous.status
155
+ elif (
156
+ previous.status == "passed"
157
+ and (same_candidate or not candidate)
158
+ and previous.evidence_refs
159
+ and previous.verification_method != "model_assisted"
160
+ ):
161
+ status = "passed"
162
+ needs_reverification = not same_candidate
163
+ progress.append(
164
+ AcceptanceProgress(
165
+ acceptance_id=item.acceptance_id,
166
+ required=item.required,
167
+ status=status,
168
+ last_verdict=previous.status if previous else None,
169
+ needs_reverification=needs_reverification,
170
+ safe_summary=previous.safe_summary if previous else "",
171
+ repair_target=(
172
+ previous.repair_target if current_binding and previous else None
173
+ ),
174
+ evidence_refs=previous.evidence_refs if previous else (),
175
+ verifier_id=previous.verifier_id if previous else None,
176
+ verifier_version=previous.verifier_version if previous else None,
177
+ verification_method=(
178
+ previous.verification_method if previous else item.verification_method
179
+ ),
180
+ repairable=(
181
+ previous.repairable
182
+ if previous is not None and previous.repairable is not None
183
+ else report.repairable
184
+ if previous is not None and report is not None
185
+ else None
186
+ ),
187
+ )
188
+ )
189
+ # A passed checkpoint item is finished implementation work on this
190
+ # unchanged subject, but still needs a fresh final-candidate verdict.
191
+ # Pending work is the repair queue, not the final verification set.
192
+ pending = tuple(
193
+ i.acceptance_id
194
+ for i in progress
195
+ if validated
196
+ and i.required
197
+ and i.status != "passed"
198
+ and i.last_verdict in {"failed", "blocked", "not_run"}
199
+ and i.repairable is not False
200
+ )
201
+ pending_verification = tuple(
202
+ i.acceptance_id
203
+ for i in progress
204
+ if i.required and (i.status != "passed" or i.needs_reverification)
205
+ )
206
+ unresolved = snapshot.unresolved_interaction_observation or {}
207
+ unresolved_ref = unresolved.get("evidence_ref")
208
+ unresolved_ref = unresolved_ref if isinstance(unresolved_ref, str) else None
209
+ unresolved_entry = unresolved.get("entry_path")
210
+ # These are host-written transcript metadata, never fields parsed from
211
+ # tool content. Scope/run/goal and the direct-tool cursor constrain refs.
212
+ refs = tuple(
213
+ dict.fromkeys(
214
+ message["receipt_ref"]
215
+ for message in snapshot.messages
216
+ if message.get("role") == "tool"
217
+ and isinstance(message.get("receipt_ref"), str)
218
+ and message["receipt_ref"].startswith(f"{snapshot.run_id}:effect:")
219
+ and message.get("receipt_goal_revision") == snapshot.goal_revision
220
+ and type(message.get("receipt_tool_call")) is int
221
+ and (cursor if validated else 0)
222
+ < message["receipt_tool_call"]
223
+ <= snapshot.tool_calls
224
+ )
225
+ )
226
+ # Compaction retries consume model calls while sealing the same source.
227
+ # Keep its captured control until sealing; ordinary preparation then
228
+ # derives a fresh control from the updated shared budget.
229
+ control = (
230
+ CompactionRequest.model_validate(snapshot.compaction_request).turn_control
231
+ if snapshot.phase == RunPhase.COMPACTING and snapshot.compaction_request
232
+ else model_turn_control(snapshot, config)
233
+ )
234
+ if review_pending(snapshot):
235
+ next_action = (
236
+ "Return the host-requested delivery review JSON from current observations; "
237
+ "review findings are diagnostics and cannot pass acceptance."
238
+ )
239
+ elif snapshot.pending_interaction:
240
+ next_action = "Resolve the pending interaction before continuing its tool execution."
241
+ elif snapshot.pending_tools:
242
+ next_action = "Finish pending tools, then assess the verification observations."
243
+ elif control is not None:
244
+ next_action = control.instruction
245
+ elif unresolved_ref and isinstance(unresolved_entry, str):
246
+ next_action = (
247
+ f"Recheck the failed browser interaction on {unresolved_entry} with an actual "
248
+ "action after repair; a screenshot-only check does not clear the error."
249
+ )
250
+ elif pending:
251
+ next_action = (
252
+ "Inspect the latest verification and tool observations; repair if needed, then "
253
+ f"verify {', '.join(pending)} against a new candidate before claiming completion."
254
+ )
255
+ else:
256
+ next_action = None
257
+ if self.workspace_tracking:
258
+ workspace_revision = snapshot.workspace_revision
259
+ workspace_state = snapshot.workspace_observation_status
260
+ workspace_changed_paths = snapshot.workspace_changed_paths
261
+ workspace_reason = snapshot.workspace_observation_reason
262
+ else:
263
+ workspace_revision = (
264
+ self.workspace_revision
265
+ if self.workspace_revision != "unavailable" and snapshot.tool_calls == 0
266
+ else None
267
+ )
268
+ workspace_state = "initial" if workspace_revision is not None else "unavailable"
269
+ workspace_changed_paths = ()
270
+ workspace_reason = None
271
+ artifacts = tuple(ArtifactRef.model_validate(ref) for ref in snapshot.artifact_refs)
272
+ return ExecutionContinuityState(
273
+ goal=snapshot.goal,
274
+ goal_revision=snapshot.goal_revision,
275
+ pending_hook_operation_keys=(
276
+ *pending_hook_operation_keys(snapshot), *precompact_feedback_keys(snapshot),
277
+ ),
278
+ contract_digest=snapshot.contract_digest,
279
+ required_acceptance_ids=required,
280
+ pending_work=pending,
281
+ pending_verification=pending_verification,
282
+ failure_fingerprints=tuple(
283
+ value for value in (snapshot.failure_fingerprint, unresolved_ref) if value
284
+ ),
285
+ evidence_refs=tuple(
286
+ dict.fromkeys(
287
+ (
288
+ *(ref for item in progress for ref in item.evidence_refs),
289
+ *((unresolved_ref,) if unresolved_ref else ()),
290
+ )
291
+ )
292
+ ),
293
+ artifact_refs=tuple(ref.uri for ref in artifacts),
294
+ next_action=next_action,
295
+ # Dynamic observations are host effects. Without that port, a
296
+ # pinned initial binding cannot attest to code after tool effects.
297
+ workspace_revision=workspace_revision,
298
+ observed_progress_revision=snapshot.observed_progress_revision,
299
+ workspace_state=workspace_state,
300
+ workspace_changed_paths=workspace_changed_paths,
301
+ workspace_observation_reason=workspace_reason,
302
+ acceptance_progress=tuple(progress),
303
+ last_verification=(
304
+ VerificationProgress(
305
+ candidate_id=report.candidate_id,
306
+ contract_revision=report.contract_revision,
307
+ subject_digest=report.subject_digest,
308
+ subject_context_digest=report.subject_context_digest,
309
+ environment_digest=report.environment_digest,
310
+ binding_validated=current_binding,
311
+ tool_calls_at_verification=cursor,
312
+ tool_calls_since_verification=since,
313
+ )
314
+ if report is not None
315
+ else None
316
+ ),
317
+ tool_receipt_refs=refs,
318
+ task_progress=tuple(
319
+ PlanningProgress.model_validate({**item, "authority": "model_planning_only"})
320
+ for item in snapshot.task_progress
321
+ ),
322
+ task_progress_revision=snapshot.task_progress_revision,
323
+ artifact_state="available" if artifacts else "unknown",
324
+ pending_interaction_refs=(
325
+ (snapshot.pending_interaction,) if snapshot.pending_interaction else ()
326
+ ),
327
+ unresolved_observation_refs=(unresolved_ref,) if unresolved_ref else (),
328
+ pending_tool_call_ids=tuple(call["call_id"] for call in snapshot.pending_tools),
329
+ pending_subagent_refs=tuple(dict.fromkeys((
330
+ *(child.child_run_id for child in snapshot.child_budget_reservations
331
+ if child.settled_usage_digest is None),
332
+ *snapshot.pending_child_observation_ids,
333
+ ))),
334
+ pending_guidance_ids=snapshot.pending_guidance_ids,
335
+ context_source_operation_key=(
336
+ snapshot.context_source_receipt.get("operation_key")
337
+ if snapshot.context_source_receipt is not None
338
+ and snapshot.context_source_receipt.get("model_call_cursor") is not None
339
+ else None
340
+ ),
341
+ accounted_subagent_run_ids=(
342
+ snapshot.child_run_ids
343
+ if self.planner is not None
344
+ and self.planner.subagent_continuity_policy == "accounted_child_runs/v1"
345
+ else ()
346
+ ),
347
+ source_read_progress=(
348
+ source_read_progress(snapshot, config.tools,
349
+ max_chars=self.planner.policy.fresh_read_max_chars)
350
+ if self.planner is not None
351
+ and self.planner.source_progress_policy == "receipt-source-progress/v2"
352
+ else ()
353
+ ),
354
+ )
355
+
356
+ def prepare(self, snapshot: RunSnapshot, config: RunConfiguration) -> CommitBatch:
357
+ if snapshot.model_budget_claimed >= config.limits.max_model_calls:
358
+ return commit_transition(
359
+ snapshot,
360
+ finish(snapshot, "budget_exhausted", "model_budget_exhausted"),
361
+ "budget.exhausted",
362
+ )
363
+ rich = [source for source in config.context_sources
364
+ if source.contributor_policy is not None]
365
+ source_cursor = (snapshot.context_source_receipt or {}).get("model_call_cursor")
366
+ expired = contributor_expired(snapshot.context_source_receipt) if rich else False
367
+ refresh = (snapshot.context_source_goal_revision != snapshot.goal_revision
368
+ or (rich and source_cursor != snapshot.model_calls and (
369
+ expired or any(source.contributor_policy.capabilities.cacheability == "none"
370
+ for source in rich)
371
+ )))
372
+ if config.context_sources and refresh:
373
+ payload = {"goal_revision": snapshot.goal_revision}
374
+ if rich:
375
+ try:
376
+ payload["input_budget"] = self.planner.contributor_budget(
377
+ profile=config.profile, instructions=model_instructions(snapshot, config),
378
+ tools=model_tool_catalog(snapshot, config), messages=snapshot.messages,
379
+ continuity=self.continuity(snapshot, config).model_copy(update={
380
+ "context_source_operation_key": effect_operation_key(snapshot),
381
+ }), contract=config.contract,
382
+ history=CompactionHistory.model_validate(snapshot.compaction_history),
383
+ turn_control=model_turn_control(snapshot, config),
384
+ )
385
+ except (ValueError, TypeError):
386
+ return commit_transition(snapshot,
387
+ finish(snapshot, "blocked", "context_counter_invalid"),
388
+ "context.blocked")
389
+ return prepare_effect(snapshot, "context", payload)
390
+ if expired:
391
+ return commit_transition(snapshot,
392
+ finish(snapshot, "blocked", "context_source_expired"),
393
+ "context.blocked")
394
+ cursor = workspace_observation_cursor(snapshot, "model")
395
+ if self.workspace_tracking and snapshot.workspace_observation_cursor != cursor:
396
+ return prepare_effect(snapshot, "workspace", {"cursor": cursor})
397
+ if resolved := host_resolved_candidate(snapshot, config):
398
+ return resolved
399
+ reserve = config.limits.verification_reserve_model_calls
400
+ idle = config.limits.verification_idle_tool_calls
401
+ budget_boundary = bool(
402
+ reserve
403
+ and snapshot.model_budget_claimed
404
+ >= config.limits.max_model_calls - reserve
405
+ )
406
+ idle_boundary = bool(
407
+ idle
408
+ and snapshot.last_workspace_mutation_tool_call is not None
409
+ and snapshot.tool_calls - snapshot.last_workspace_mutation_tool_call >= idle
410
+ )
411
+ browser_boundary = bool(
412
+ config.workspace_observation_policy is not None
413
+ and snapshot.last_web_mutation_tool_call is not None
414
+ and snapshot.last_web_mutation_tool_call
415
+ > (snapshot.checkpoint_web_mutation_tool_call or 0)
416
+ and isinstance(snapshot.last_browser_observation, dict)
417
+ and snapshot.last_browser_observation.get("tool_call") == snapshot.tool_calls
418
+ and snapshot.tool_calls >= snapshot.last_web_mutation_tool_call
419
+ )
420
+ if (
421
+ not review_pending(snapshot)
422
+ and (budget_boundary or idle_boundary or browser_boundary)
423
+ and self.workspace_tracking
424
+ and snapshot.tool_calls
425
+ and snapshot.workspace_revision is not None
426
+ and snapshot.workspace_dirty_since_checkpoint
427
+ and snapshot.workspace_revision != snapshot.checkpoint_workspace_revision
428
+ ):
429
+ candidate = {
430
+ "candidate_id": (
431
+ f"{snapshot.run_id}:checkpoint:{snapshot.model_calls}:{snapshot.tool_calls}"
432
+ ),
433
+ "final_text": "",
434
+ "purpose": "checkpoint",
435
+ }
436
+ updated = move(snapshot, RunPhase.VERIFYING).model_copy(
437
+ update={"candidate": candidate, "prepared_context": None}
438
+ )
439
+ return commit_transition(
440
+ snapshot,
441
+ updated,
442
+ "verification.checkpoint_started",
443
+ {"workspace_revision": snapshot.workspace_revision},
444
+ )
445
+ if config.profile.operator_guidance_policy == "journaled-system/v1":
446
+ ledger = ContextPlanner._host_ledger(self.continuity(snapshot, config), config.contract)
447
+ base_messages = delivery_review_messages(snapshot)
448
+ projected_messages = precompact_feedback_messages(snapshot, tool_hook_feedback_messages(
449
+ snapshot, hook_feedback_messages(snapshot, base_messages),
450
+ ))
451
+ additions = stage_guidance(
452
+ projected_messages, profile=config.profile,
453
+ run_id=snapshot.run_id, goal_revision=snapshot.goal_revision,
454
+ model_call=snapshot.model_calls, base_instructions=config.instructions,
455
+ instructions=model_instructions(snapshot, config), ledger=ledger,
456
+ control=model_turn_control(snapshot, config),
457
+ purpose="delivery_review" if review_pending(snapshot) else "task",
458
+ )
459
+ if additions:
460
+ # Persist admitted Hook observations before the guidance that
461
+ # follows them. Their original producer checks and provenance
462
+ # remain authoritative; a system notice never absorbs raw data.
463
+ additions = (*projected_messages[len(base_messages):], *additions)
464
+ updates = ({"delivery_review": snapshot.delivery_review.model_copy(update={
465
+ "continuation_messages": (
466
+ *snapshot.delivery_review.continuation_messages, *additions,
467
+ ),
468
+ })} if review_pending(snapshot) else {"messages": (*snapshot.messages, *additions)})
469
+ return commit_transition(snapshot, snapshot.model_copy(update=updates),
470
+ "model.guidance_staged", {
471
+ "guidance_key": additions[-1]["guidance_key"],
472
+ "policy": config.profile.operator_guidance_policy,
473
+ })
474
+ if self.planner is None:
475
+ return commit_transition(
476
+ snapshot, move(snapshot, RunPhase.REQUESTING_MODEL), "run.phase_changed"
477
+ )
478
+ plan = self.planner.plan(
479
+ source_revision=snapshot.revision,
480
+ model_turn=snapshot.model_calls,
481
+ profile=config.profile,
482
+ instructions=(config.instructions
483
+ if config.profile.operator_guidance_policy == "journaled-system/v1"
484
+ else model_instructions(snapshot, config)),
485
+ tools=model_tool_catalog(snapshot, config),
486
+ context_tools=config.tools,
487
+ messages=precompact_feedback_messages(snapshot, tool_hook_feedback_messages(
488
+ snapshot, hook_feedback_messages(snapshot, delivery_review_messages(snapshot))
489
+ )),
490
+ continuity=self.continuity(snapshot, config),
491
+ contract=config.contract,
492
+ history=CompactionHistory.model_validate(snapshot.compaction_history),
493
+ force_compaction=snapshot.force_compaction,
494
+ turn_control=model_turn_control(snapshot, config),
495
+ allow_compaction=not finalization_only(snapshot, config),
496
+ )
497
+ if review_pending(snapshot) and plan.action in {"blocked", "compact"}:
498
+ # Never compact a review projection into the implementation
499
+ # transcript. An oversized diagnostic is unavailable, not passed.
500
+ reason = "review_context_budget_unavailable"
501
+ return commit_transition(
502
+ snapshot, unavailable_review(snapshot, reason),
503
+ "completion.delivery_review_unavailable", {"reason": reason},
504
+ )
505
+ if plan.action == "blocked":
506
+ return commit_transition(
507
+ snapshot,
508
+ finish(snapshot, "blocked", plan.reason),
509
+ "context.blocked",
510
+ {"reason": plan.reason},
511
+ )
512
+ if plan.action == "compact":
513
+ hook_state = planned_precompact_state(snapshot, config, plan.request)
514
+ retained_refs = set(plan.request.retained_message_refs)
515
+ retained_messages = tuple(
516
+ item for item in plan.request.old_messages if item.message_id in retained_refs
517
+ )
518
+ updated = move(snapshot, RunPhase.COMPACTING).model_copy(
519
+ update={
520
+ "compaction_request": plan.request.model_dump(mode="json"),
521
+ "prepared_context": None,
522
+ "precompact_hook_state": hook_state,
523
+ }
524
+ )
525
+ return commit_transition(
526
+ snapshot,
527
+ updated,
528
+ "context.precompact_started" if hook_state and hook_state["next_hook_index"] == 0
529
+ else "context.compaction_started",
530
+ {
531
+ "source_revision": snapshot.revision,
532
+ "source_message_count": len(plan.request.old_messages),
533
+ "retained_message_count": len(retained_messages),
534
+ "retained_tool_result_count": sum(
535
+ item.role == "tool" for item in retained_messages
536
+ ),
537
+ "retained_input_tokens": sum(item.token_count for item in retained_messages),
538
+ "summary_input_tokens": plan.request.summary_counted_input_tokens,
539
+ "window_tokens": plan.request.budget.window_tokens,
540
+ "fixed_tokens": plan.request.budget.fixed_tokens,
541
+ "max_output_tokens": plan.request.budget.max_output_tokens,
542
+ "input_capacity": plan.request.budget.input_capacity,
543
+ "target_ratio": self.planner.policy.target_ratio,
544
+ "trigger_ratio": self.planner.policy.trigger_ratio,
545
+ },
546
+ )
547
+ updated = move(snapshot, RunPhase.REQUESTING_MODEL).model_copy(
548
+ update={
549
+ "prepared_context": plan.prepared.model_dump(mode="json"),
550
+ "compaction_request": None,
551
+ "compaction_history": (
552
+ {**snapshot.compaction_history,
553
+ "abandoned_replay_digests": list(plan.prepared.abandoned_replay_digests)}
554
+ if plan.prepared.abandoned_replay_digests else snapshot.compaction_history
555
+ ),
556
+ }
557
+ )
558
+ return commit_transition(
559
+ snapshot,
560
+ updated,
561
+ "context.prepared",
562
+ {
563
+ "counted_input_tokens": plan.prepared.counted_input_tokens,
564
+ "tokenizer_id": plan.prepared.tokenizer_id,
565
+ **({"tool_result_pruning":
566
+ plan.prepared.tool_result_pruning.model_dump(mode="json")}
567
+ if plan.prepared.tool_result_pruning is not None else {}),
568
+ },
569
+ )
570
+
571
+ def prepare_verification(self, snapshot: RunSnapshot) -> CommitBatch | None:
572
+ if not self.workspace_tracking:
573
+ return None
574
+ cursor = workspace_observation_cursor(snapshot, "verification")
575
+ if snapshot.workspace_observation_cursor == cursor:
576
+ return None
577
+ return prepare_effect(
578
+ snapshot,
579
+ "workspace",
580
+ {"cursor": cursor, "purpose": "verification"},
581
+ )
582
+
583
+ def begin_summary(self, snapshot: RunSnapshot, config: RunConfiguration) -> CommitBatch:
584
+ if self.planner is None or snapshot.compaction_request is None:
585
+ return commit_transition(
586
+ snapshot,
587
+ finish(snapshot, "blocked", "context_compaction_unavailable"),
588
+ "context.blocked",
589
+ )
590
+ if snapshot.model_budget_claimed >= config.limits.max_model_calls:
591
+ return commit_transition(
592
+ snapshot,
593
+ finish(snapshot, "budget_exhausted", "model_budget_exhausted"),
594
+ "budget.exhausted",
595
+ )
596
+ if finalization_only(snapshot, config):
597
+ try:
598
+ compacted = commit_completed_prefix(
599
+ CompactionController(self.planner),
600
+ CompactionRequest.model_validate(snapshot.compaction_request),
601
+ current_revision=snapshot.revision,
602
+ current_continuity=self.continuity(snapshot, config),
603
+ current_messages=snapshot.messages,
604
+ )
605
+ except (ContextRuntimeError, ValueError):
606
+ compacted = None
607
+ if compacted is not None:
608
+ return commit_transition(
609
+ snapshot,
610
+ move(snapshot, RunPhase.PREPARING_CONTEXT).model_copy(update={
611
+ "compaction_history": compacted.history.model_dump(mode="json"),
612
+ "compaction_request": None, "prepared_context": None,
613
+ "force_compaction": False, "model_errors": 0, "provider_errors": 0,
614
+ }),
615
+ "context.compaction_partial_sealed",
616
+ {"reason": "model_budget_reserved", "policy": PARTIAL_SUMMARY_POLICY,
617
+ "retained_message_count": len(compacted.history.retained_message_refs)},
618
+ )
619
+ # A retry/continuation or restored checkpoint can reach the
620
+ # reserve after compaction began. Abandon only the unsealed
621
+ # projection and replan from committed history for delivery.
622
+ return commit_transition(
623
+ snapshot,
624
+ move(snapshot, RunPhase.PREPARING_CONTEXT).model_copy(update={
625
+ "compaction_request": None,
626
+ "prepared_context": None,
627
+ "model_errors": 0,
628
+ "provider_errors": 0,
629
+ }),
630
+ "context.compaction_deferred",
631
+ {"reason": "model_budget_reserved"},
632
+ )
633
+ if snapshot.compaction_request.get("fresh_tool_observation_policy") is not None:
634
+ try:
635
+ request = CompactionRequest.model_validate(snapshot.compaction_request)
636
+ CompactionController(self.planner)._validate_source(
637
+ request, snapshot.revision, self.continuity(snapshot, config), snapshot.messages
638
+ )
639
+ except (ContextRuntimeError, ValueError) as error:
640
+ reason = str(error) if isinstance(error, ContextRuntimeError) else (
641
+ "context_compaction_request_invalid"
642
+ )
643
+ return commit_transition(
644
+ snapshot, finish(snapshot, "blocked", reason),
645
+ "context.blocked", {"reason": reason},
646
+ )
647
+ return prepare_effect(snapshot, "model", {"purpose": "compaction"})
648
+
649
+ def seal(self, snapshot: RunSnapshot, result: ModelTurnResult, config: RunConfiguration):
650
+ from .model_input import input_binding_failure, observe_input
651
+
652
+ provider_error = result.response_kind == "provider_retryable_error"
653
+ updated = snapshot.model_copy(
654
+ update={
655
+ "pending_intent": None,
656
+ "model_calls": snapshot.model_calls + 1,
657
+ "provider_errors": snapshot.provider_errors + 1 if provider_error else 0,
658
+ }
659
+ )
660
+ if failure := input_binding_failure(config.profile, result.input_receipt):
661
+ return finish(updated, "failed", failure)
662
+ updated = observe_input(updated, result.input_receipt)
663
+ if failure := replay_binding_failure(
664
+ config.profile, result.provider_replay,
665
+ required=result.response_kind in {"tool_calls", "final_candidate", "output_limit"},
666
+ ):
667
+ return finish(updated, "failed", failure)
668
+ bounded_summary = (
669
+ self.planner is not None
670
+ and self.planner.summary_completion_policy == "bounded-committed-summary/v1"
671
+ and result.response_kind == "output_limit"
672
+ and bool(result.text.strip())
673
+ )
674
+ if bounded_summary and result.text_commit_version != "provider-finished-text/v1":
675
+ return finish(updated, "blocked", "context_summary_provider_commit_missing")
676
+ if (result.response_kind == "output_limit" and result.text.strip()
677
+ and self.planner and not bounded_summary):
678
+ try:
679
+ request = CompactionRequest.model_validate(snapshot.compaction_request)
680
+ continued = CompactionController(self.planner).continue_summary(
681
+ request,
682
+ result.text,
683
+ current_revision=snapshot.revision,
684
+ current_continuity=self.continuity(snapshot, config),
685
+ current_messages=snapshot.messages,
686
+ provider_replay=result.provider_replay,
687
+ )
688
+ except (ContextRuntimeError, ValueError) as exc:
689
+ return finish(
690
+ updated,
691
+ "blocked",
692
+ str(exc)
693
+ if isinstance(exc, ContextRuntimeError)
694
+ else "compaction_seal_rejected",
695
+ )
696
+ return updated.model_copy(
697
+ update={
698
+ "model_errors": 0,
699
+ "provider_errors": 0,
700
+ "compaction_request": continued.model_dump(mode="json"),
701
+ }
702
+ )
703
+ if result.response_kind in {
704
+ "provider_retryable_error",
705
+ "empty_response",
706
+ "malformed_tool_call",
707
+ "output_limit",
708
+ "context_overflow",
709
+ } and not bounded_summary:
710
+ errors = updated.provider_errors if provider_error else snapshot.model_errors + 1
711
+ updated = updated.model_copy(update={"model_errors": 0 if provider_error else errors})
712
+ limit = (
713
+ config.profile.max_provider_retries
714
+ if provider_error
715
+ else config.profile.max_retries
716
+ )
717
+ if errors <= limit:
718
+ if result.response_kind in {"output_limit", "context_overflow"}:
719
+ if self.planner is None:
720
+ return finish(updated, "blocked", "compaction_summary_incomplete")
721
+ try:
722
+ retried = repartition_failed_summary(
723
+ self.planner,
724
+ CompactionRequest.model_validate(snapshot.compaction_request),
725
+ current_revision=snapshot.revision,
726
+ current_continuity=self.continuity(snapshot, config),
727
+ current_messages=snapshot.messages,
728
+ )
729
+ except (ContextRuntimeError, ValueError) as exc:
730
+ return finish(
731
+ updated, "blocked", str(exc)
732
+ if isinstance(exc, ContextRuntimeError) else "compaction_seal_rejected",
733
+ )
734
+ if retried is not None:
735
+ return updated.model_copy(update={
736
+ "compaction_request": retried.model_dump(mode="json"),
737
+ })
738
+ if result.response_kind == "context_overflow":
739
+ return finish(updated, "blocked", "compaction_summary_incomplete")
740
+ # No summary has been sealed, so retain the exact compaction
741
+ # request and retry with a fresh model effect/operation key.
742
+ return updated
743
+ return finish(updated, "blocked", "compaction_summary_retry_exhausted")
744
+ if ((result.response_kind != "final_candidate" and not bounded_summary)
745
+ or self.planner is None):
746
+ return finish(updated, "blocked", "compaction_summary_incomplete")
747
+ updated = updated.model_copy(update={"model_errors": 0, "provider_errors": 0})
748
+ try:
749
+ request = CompactionRequest.model_validate(snapshot.compaction_request)
750
+ if bounded_summary:
751
+ # This is a lossy, untrusted memory projection, never a final
752
+ # task candidate. Source coverage and window validation below
753
+ # still apply, and this receipt consumed one shared model call.
754
+ request = request.model_copy(update={"summary_output_limited": True})
755
+ compacted = CompactionController(self.planner).advance(
756
+ request,
757
+ result.text,
758
+ current_revision=snapshot.revision,
759
+ current_continuity=self.continuity(snapshot, config),
760
+ current_messages=snapshot.messages,
761
+ )
762
+ except ContextRuntimeError as exc:
763
+ if isinstance(exc, CompactionProjectionOverflow):
764
+ reduced = replan_summary_projection(
765
+ self.planner, snapshot, updated, config, self.continuity(snapshot, config)
766
+ )
767
+ if reduced is not None:
768
+ return reduced
769
+ if str(exc) == "context_summary_budget_exceeded":
770
+ errors = snapshot.model_errors + 1
771
+ if errors <= config.profile.max_retries:
772
+ feedback = (
773
+ "\nThe previous summary exceeded the hard output limit. "
774
+ f"Keep the next summary below {request.summary_max_tokens} "
775
+ f"{self.planner.summary_budget_unit}; use much shorter wording."
776
+ )
777
+ retried = request.model_copy(
778
+ update={
779
+ "summary_instructions": request.summary_instructions + feedback,
780
+ # The hard summary ceiling is counted by the host.
781
+ # Reducing a provider token cap can truncate hidden
782
+ # reasoning without making the visible text shorter.
783
+ "summary_output_tokens": request.summary_output_tokens,
784
+ "summary_messages": (
785
+ request.summary_messages[: -2 * request.summary_continuations]
786
+ if request.summary_continuations
787
+ else request.summary_messages
788
+ ),
789
+ "summary_fragments": (),
790
+ "summary_continuations": 0,
791
+ "summary_output_limited": snapshot.compaction_request.get(
792
+ "summary_output_limited", False
793
+ ),
794
+ }
795
+ )
796
+ return updated.model_copy(
797
+ update={
798
+ "model_errors": errors,
799
+ "compaction_request": retried.model_dump(mode="json"),
800
+ }
801
+ )
802
+ return finish(updated, "blocked", str(exc))
803
+ except ValueError:
804
+ return finish(updated, "blocked", "compaction_seal_rejected")
805
+ if isinstance(compacted, CompactionRequest):
806
+ return updated.model_copy(
807
+ update={"compaction_request": compacted.model_dump(mode="json")}
808
+ )
809
+ return move(updated, RunPhase.PREPARING_CONTEXT).model_copy(
810
+ update={
811
+ "compaction_history": compacted.history.model_dump(mode="json"),
812
+ "compaction_request": None,
813
+ "prepared_context": None,
814
+ "force_compaction": False,
815
+ # A sealed rewrite starts a different request root. Recovery
816
+ # attempts on the previous root are no longer consecutive;
817
+ # shared model/compaction/stagnation budgets still apply.
818
+ "context_overflows": 0,
819
+ }
820
+ )