iac-code 0.9.0__tar.gz → 0.9.1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (473) hide show
  1. {iac_code-0.9.0 → iac_code-0.9.1}/PKG-INFO +1 -1
  2. iac_code-0.9.1/src/iac_code/__init__.py +2 -0
  3. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/a2a/executor.py +23 -3
  4. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/a2a/pipeline_executor.py +96 -4
  5. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/a2a/pipeline_recovery.py +6 -0
  6. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/a2a/pipeline_snapshot.py +73 -0
  7. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/a2a/task_store.py +22 -0
  8. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/agent/agent_loop.py +35 -5
  9. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/agent/agent_tool.py +1 -0
  10. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/cli/main.py +54 -0
  11. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/cli/output_formats.py +8 -3
  12. iac_code-0.9.1/src/iac_code/cli/process_events.py +56 -0
  13. iac_code-0.9.1/src/iac_code/cli/process_mode.py +1084 -0
  14. iac_code-0.9.1/src/iac_code/cli/process_protocol.py +282 -0
  15. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/i18n/locales/de/LC_MESSAGES/messages.mo +0 -0
  16. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/i18n/locales/de/LC_MESSAGES/messages.po +84 -13
  17. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/i18n/locales/es/LC_MESSAGES/messages.mo +0 -0
  18. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/i18n/locales/es/LC_MESSAGES/messages.po +84 -13
  19. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/i18n/locales/fr/LC_MESSAGES/messages.mo +0 -0
  20. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/i18n/locales/fr/LC_MESSAGES/messages.po +84 -13
  21. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/i18n/locales/ja/LC_MESSAGES/messages.mo +0 -0
  22. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/i18n/locales/ja/LC_MESSAGES/messages.po +84 -13
  23. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/i18n/locales/pt/LC_MESSAGES/messages.mo +0 -0
  24. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/i18n/locales/pt/LC_MESSAGES/messages.po +84 -13
  25. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/i18n/locales/zh/LC_MESSAGES/messages.mo +0 -0
  26. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/i18n/locales/zh/LC_MESSAGES/messages.po +84 -13
  27. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/pipeline/engine/ask_user_question_tool.py +9 -0
  28. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/pipeline/engine/complete_step_tool.py +7 -0
  29. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/pipeline/engine/display_replay.py +125 -0
  30. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/pipeline/engine/interrupt.py +12 -4
  31. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/pipeline/engine/pipeline_runner.py +23 -3
  32. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/pipeline/engine/prompts/interrupt_judge.md +5 -3
  33. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/pipeline/engine/step_executor.py +53 -34
  34. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/pipeline/selling/pipeline.yaml +5 -5
  35. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/pipeline/selling/prompts/deploying.md +3 -3
  36. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/pipeline/selling/skills/iac-aliyun-deploying/SKILL.md +8 -3
  37. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/pipeline/selling/tools/ros_deploy_tool.py +95 -6
  38. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/services/agent_factory.py +99 -12
  39. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/services/permissions/trusted_roots.py +8 -2
  40. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/services/session_layout.py +3 -0
  41. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/skills/skill_tool.py +1 -0
  42. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/tools/base.py +10 -1
  43. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/tools/bash/path_validation.py +5 -1
  44. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/tools/bash/permissions.py +2 -0
  45. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/tools/cloud/aliyun/aliyun_api.py +28 -3
  46. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/tools/cloud/aliyun/ros_stack.py +52 -5
  47. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/tools/cloud/aliyun/ros_template_tools.py +11 -24
  48. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/tools/cloud/aliyun/template_source.py +88 -1
  49. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/tools/cloud/base_api.py +9 -1
  50. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/tools/cloud/base_stack.py +11 -1
  51. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/tools/glob.py +30 -26
  52. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/tools/grep.py +15 -7
  53. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/tools/list_files.py +2 -0
  54. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/tools/path_safety.py +23 -5
  55. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/tools/read_file.py +2 -0
  56. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/tools/tool_executor.py +3 -0
  57. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/types/permissions.py +2 -0
  58. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/ui/pipeline_display_replay.py +40 -0
  59. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/ui/renderer.py +42 -2
  60. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/ui/repl.py +17 -2
  61. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code.egg-info/PKG-INFO +1 -1
  62. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code.egg-info/SOURCES.txt +3 -0
  63. iac_code-0.9.0/src/iac_code/__init__.py +0 -2
  64. {iac_code-0.9.0 → iac_code-0.9.1}/LICENSE +0 -0
  65. {iac_code-0.9.0 → iac_code-0.9.1}/MANIFEST.in +0 -0
  66. {iac_code-0.9.0 → iac_code-0.9.1}/README.md +0 -0
  67. {iac_code-0.9.0 → iac_code-0.9.1}/pyproject.toml +0 -0
  68. {iac_code-0.9.0 → iac_code-0.9.1}/setup.cfg +0 -0
  69. {iac_code-0.9.0 → iac_code-0.9.1}/setup.py +0 -0
  70. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/a2a/__init__.py +0 -0
  71. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/a2a/agent_card.py +0 -0
  72. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/a2a/app.py +0 -0
  73. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/a2a/artifacts.py +0 -0
  74. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/a2a/backup.py +0 -0
  75. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/a2a/client.py +0 -0
  76. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/a2a/events.py +0 -0
  77. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/a2a/exposure.py +0 -0
  78. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/a2a/jsonrpc_passthrough.py +0 -0
  79. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/a2a/metadata_redaction.py +0 -0
  80. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/a2a/metrics.py +0 -0
  81. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/a2a/parts.py +0 -0
  82. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/a2a/persistence.py +0 -0
  83. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/a2a/pipeline_events.py +0 -0
  84. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/a2a/pipeline_journal.py +0 -0
  85. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/a2a/pipeline_paths.py +0 -0
  86. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/a2a/pipeline_performance.py +0 -0
  87. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/a2a/pipeline_stream.py +0 -0
  88. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/a2a/push.py +0 -0
  89. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/a2a/push_queue.py +0 -0
  90. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/a2a/push_secrets.py +0 -0
  91. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/a2a/push_worker.py +0 -0
  92. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/a2a/router.py +0 -0
  93. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/a2a/runtime_overrides.py +0 -0
  94. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/a2a/signing.py +0 -0
  95. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/a2a/thinking_metadata.py +0 -0
  96. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/a2a/transport.py +0 -0
  97. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/a2a/transports/__init__.py +0 -0
  98. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/a2a/transports/base.py +0 -0
  99. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/a2a/transports/dispatcher.py +0 -0
  100. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/a2a/transports/grpc.py +0 -0
  101. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/a2a/transports/grpc_jsonrpc.py +0 -0
  102. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/a2a/transports/http.py +0 -0
  103. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/a2a/transports/redis_streams.py +0 -0
  104. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/a2a/transports/stdio.py +0 -0
  105. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/a2a/transports/unix.py +0 -0
  106. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/a2a/transports/websocket.py +0 -0
  107. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/a2a/types.py +0 -0
  108. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/acp/__init__.py +0 -0
  109. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/acp/convert.py +0 -0
  110. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/acp/http_sse.py +0 -0
  111. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/acp/mcp.py +0 -0
  112. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/acp/metrics.py +0 -0
  113. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/acp/server.py +0 -0
  114. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/acp/session.py +0 -0
  115. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/acp/slash_registry.py +0 -0
  116. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/acp/state.py +0 -0
  117. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/acp/tools.py +0 -0
  118. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/acp/types.py +0 -0
  119. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/acp/version.py +0 -0
  120. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/agent/__init__.py +0 -0
  121. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/agent/agent_types.py +0 -0
  122. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/agent/message.py +0 -0
  123. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/agent/system_prompt.py +0 -0
  124. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/cli/__init__.py +0 -0
  125. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/cli/headless.py +0 -0
  126. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/cli/install_git_bash.py +0 -0
  127. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/cli/update.py +0 -0
  128. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/commands/__init__.py +0 -0
  129. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/commands/auth.py +0 -0
  130. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/commands/clear.py +0 -0
  131. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/commands/compact.py +0 -0
  132. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/commands/debug.py +0 -0
  133. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/commands/effort.py +0 -0
  134. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/commands/exit.py +0 -0
  135. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/commands/help.py +0 -0
  136. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/commands/memory.py +0 -0
  137. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/commands/model.py +0 -0
  138. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/commands/prompt.py +0 -0
  139. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/commands/registry.py +0 -0
  140. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/commands/rename.py +0 -0
  141. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/commands/resume.py +0 -0
  142. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/commands/skills.py +0 -0
  143. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/commands/status.py +0 -0
  144. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/commands/tasks.py +0 -0
  145. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/commands/thinking_enabled.py +0 -0
  146. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/config.py +0 -0
  147. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/i18n/__init__.py +0 -0
  148. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/mcp/__init__.py +0 -0
  149. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/mcp/cli.py +0 -0
  150. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/mcp/client.py +0 -0
  151. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/mcp/config.py +0 -0
  152. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/mcp/env_expansion.py +0 -0
  153. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/mcp/errors.py +0 -0
  154. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/mcp/manager.py +0 -0
  155. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/mcp/oauth.py +0 -0
  156. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/mcp/output.py +0 -0
  157. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/mcp/prompts.py +0 -0
  158. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/mcp/skills.py +0 -0
  159. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/mcp/storage.py +0 -0
  160. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/mcp/tools.py +0 -0
  161. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/mcp/types.py +0 -0
  162. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/memory/__init__.py +0 -0
  163. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/memory/memory_manager.py +0 -0
  164. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/memory/memory_tools.py +0 -0
  165. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/memory/project_memory.py +0 -0
  166. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/memory/recall.py +0 -0
  167. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/pipeline/__init__.py +0 -0
  168. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/pipeline/config.py +0 -0
  169. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/pipeline/constants.py +0 -0
  170. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/pipeline/display_names.py +0 -0
  171. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/pipeline/engine/__init__.py +0 -0
  172. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/pipeline/engine/architecture_graph.py +0 -0
  173. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/pipeline/engine/architecture_meta.py +0 -0
  174. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/pipeline/engine/architecture_metas/Categories.json +0 -0
  175. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/pipeline/engine/architecture_metas/config.json +0 -0
  176. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/pipeline/engine/architecture_metas/products.json +0 -0
  177. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/pipeline/engine/architecture_resource_inventory.py +0 -0
  178. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/pipeline/engine/architecture_rule_candidates.py +0 -0
  179. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/pipeline/engine/architecture_rule_drafts.py +0 -0
  180. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/pipeline/engine/architecture_rule_facts.py +0 -0
  181. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/pipeline/engine/architecture_rules.json +0 -0
  182. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/pipeline/engine/architecture_rules.py +0 -0
  183. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/pipeline/engine/architecture_semantic_planning.py +0 -0
  184. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/pipeline/engine/cleanup.py +0 -0
  185. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/pipeline/engine/completion_guard_state.py +0 -0
  186. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/pipeline/engine/context.py +0 -0
  187. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/pipeline/engine/events.py +0 -0
  188. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/pipeline/engine/handoff.py +0 -0
  189. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/pipeline/engine/loader.py +0 -0
  190. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/pipeline/engine/observability.py +0 -0
  191. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/pipeline/engine/prerequisites.py +0 -0
  192. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/pipeline/engine/public_errors.py +0 -0
  193. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/pipeline/engine/recovery.py +0 -0
  194. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/pipeline/engine/resume_recovery.py +0 -0
  195. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/pipeline/engine/session.py +0 -0
  196. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/pipeline/engine/show_diagram_tool.py +0 -0
  197. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/pipeline/engine/state_machine.py +0 -0
  198. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/pipeline/engine/step_spec.py +0 -0
  199. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/pipeline/engine/sub_pipeline_executor.py +0 -0
  200. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/pipeline/engine/transcript_storage.py +0 -0
  201. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/pipeline/engine/types.py +0 -0
  202. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/pipeline/engine/ui_contract.py +0 -0
  203. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/pipeline/engine/user_input.py +0 -0
  204. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/pipeline/selling/hooks/deploying.py +5 -5
  205. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/pipeline/selling/prompts/architecture_planning.md +0 -0
  206. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/pipeline/selling/prompts/confirm_and_select.a2a.md +0 -0
  207. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/pipeline/selling/prompts/confirm_and_select.md +0 -0
  208. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/pipeline/selling/prompts/cost_estimating.md +0 -0
  209. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/pipeline/selling/prompts/evaluate_candidates.md +0 -0
  210. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/pipeline/selling/prompts/intent_parsing.md +0 -0
  211. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/pipeline/selling/prompts/reviewing.md +0 -0
  212. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/pipeline/selling/prompts/template_generating.md +0 -0
  213. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/pipeline/selling/references/cloud-products/ecs.md +0 -0
  214. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/pipeline/selling/references/cloud-products/oss.md +0 -0
  215. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/pipeline/selling/references/cloud-products/rds.md +0 -0
  216. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/pipeline/selling/references/cloud-products/redis.md +0 -0
  217. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/pipeline/selling/references/cloud-products/slb.md +0 -0
  218. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/pipeline/selling/references/cloud-products/vpc.md +0 -0
  219. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/pipeline/selling/references/ros-template.md +0 -0
  220. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/pipeline/selling/references/template-parameter-recommendation.md +0 -0
  221. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/pipeline/selling/references/template-parameters.md +0 -0
  222. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/pipeline/selling/references/terraform-template.md +0 -0
  223. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/pipeline/selling/skills/iac-aliyun-architecture/SKILL.md +0 -0
  224. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/pipeline/selling/skills/iac-aliyun-architecture/evals.json +0 -0
  225. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/pipeline/selling/skills/iac-aliyun-cost/SKILL.md +0 -0
  226. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/pipeline/selling/skills/iac-aliyun-cost/evals.json +0 -0
  227. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/pipeline/selling/skills/iac-aliyun-cost/references/cloud-products/ecs.md +0 -0
  228. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/pipeline/selling/skills/iac-aliyun-cost/references/cloud-products/oss.md +0 -0
  229. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/pipeline/selling/skills/iac-aliyun-cost/references/cloud-products/rds.md +0 -0
  230. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/pipeline/selling/skills/iac-aliyun-cost/references/cloud-products/redis.md +0 -0
  231. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/pipeline/selling/skills/iac-aliyun-cost/references/cloud-products/slb.md +0 -0
  232. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/pipeline/selling/skills/iac-aliyun-cost/references/cloud-products/vpc.md +0 -0
  233. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/pipeline/selling/skills/iac-aliyun-cost/references/ros-template.md +0 -0
  234. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/pipeline/selling/skills/iac-aliyun-cost/references/template-parameter-recommendation.md +0 -0
  235. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/pipeline/selling/skills/iac-aliyun-cost/references/template-parameters.md +0 -0
  236. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/pipeline/selling/skills/iac-aliyun-cost/references/terraform-template.md +0 -0
  237. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/pipeline/selling/skills/iac-aliyun-deploying/evals.json +0 -0
  238. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/pipeline/selling/skills/iac-aliyun-deploying/references/cloud-products/ecs.md +0 -0
  239. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/pipeline/selling/skills/iac-aliyun-deploying/references/cloud-products/oss.md +0 -0
  240. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/pipeline/selling/skills/iac-aliyun-deploying/references/cloud-products/rds.md +0 -0
  241. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/pipeline/selling/skills/iac-aliyun-deploying/references/cloud-products/redis.md +0 -0
  242. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/pipeline/selling/skills/iac-aliyun-deploying/references/cloud-products/slb.md +0 -0
  243. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/pipeline/selling/skills/iac-aliyun-deploying/references/cloud-products/vpc.md +0 -0
  244. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/pipeline/selling/skills/iac-aliyun-deploying/references/ros-template.md +0 -0
  245. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/pipeline/selling/skills/iac-aliyun-deploying/references/template-parameter-recommendation.md +0 -0
  246. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/pipeline/selling/skills/iac-aliyun-deploying/references/template-parameters.md +0 -0
  247. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/pipeline/selling/skills/iac-aliyun-deploying/references/terraform-template.md +0 -0
  248. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/pipeline/selling/skills/iac-aliyun-intent/SKILL.md +0 -0
  249. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/pipeline/selling/skills/iac-aliyun-intent/evals.json +0 -0
  250. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/pipeline/selling/skills/iac-aliyun-review/SKILL.md +0 -0
  251. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/pipeline/selling/skills/iac-aliyun-review/evals.json +0 -0
  252. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/pipeline/selling/skills/iac-aliyun-template-generating/SKILL.md +0 -0
  253. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/pipeline/selling/skills/iac-aliyun-template-generating/evals.json +0 -0
  254. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/pipeline/selling/skills/iac-aliyun-template-generating/references/cloud-products/ecs.md +0 -0
  255. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/pipeline/selling/skills/iac-aliyun-template-generating/references/cloud-products/oss.md +0 -0
  256. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/pipeline/selling/skills/iac-aliyun-template-generating/references/cloud-products/rds.md +0 -0
  257. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/pipeline/selling/skills/iac-aliyun-template-generating/references/cloud-products/redis.md +0 -0
  258. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/pipeline/selling/skills/iac-aliyun-template-generating/references/cloud-products/slb.md +0 -0
  259. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/pipeline/selling/skills/iac-aliyun-template-generating/references/cloud-products/vpc.md +0 -0
  260. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/pipeline/selling/skills/iac-aliyun-template-generating/references/ros-template.md +0 -0
  261. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/pipeline/selling/skills/iac-aliyun-template-generating/references/template-parameter-recommendation.md +0 -0
  262. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/pipeline/selling/skills/iac-aliyun-template-generating/references/template-parameters.md +0 -0
  263. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/pipeline/selling/skills/iac-aliyun-template-generating/references/terraform-template.md +0 -0
  264. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/pipeline/selling/tools/__init__.py +0 -0
  265. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/pipeline/selling/tools/infraguard_scan_tool.py +0 -0
  266. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/pipeline/selling/tools/ros_template_tools.py +0 -0
  267. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/pipeline/selling/tools/show_candidate_detail_tool.py +0 -0
  268. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/providers/__init__.py +0 -0
  269. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/providers/anthropic_provider.py +0 -0
  270. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/providers/azure_openai_provider.py +0 -0
  271. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/providers/base.py +0 -0
  272. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/providers/dashscope_provider.py +0 -0
  273. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/providers/deepseek_provider.py +0 -0
  274. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/providers/gemini_provider.py +0 -0
  275. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/providers/kimi_provider.py +0 -0
  276. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/providers/lmstudio_provider.py +0 -0
  277. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/providers/manager.py +0 -0
  278. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/providers/minimax_provider.py +0 -0
  279. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/providers/modelscope_provider.py +0 -0
  280. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/providers/ollama_provider.py +0 -0
  281. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/providers/openai_provider.py +0 -0
  282. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/providers/openrouter_provider.py +0 -0
  283. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/providers/registry.py +0 -0
  284. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/providers/request_logging.py +0 -0
  285. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/providers/request_policy.py +0 -0
  286. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/providers/retry.py +0 -0
  287. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/providers/siliconflow_provider.py +0 -0
  288. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/providers/stream_watchdog.py +0 -0
  289. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/providers/thinking.py +0 -0
  290. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/providers/volcengine_provider.py +0 -0
  291. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/providers/zhipu_provider.py +0 -0
  292. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/services/__init__.py +0 -0
  293. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/services/capabilities/__init__.py +0 -0
  294. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/services/capabilities/auto_detect.py +0 -0
  295. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/services/capabilities/multimodal.py +0 -0
  296. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/services/cloud_credentials.py +0 -0
  297. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/services/context_manager.py +0 -0
  298. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/services/permissions/__init__.py +0 -0
  299. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/services/permissions/audit.py +0 -0
  300. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/services/permissions/loader.py +0 -0
  301. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/services/permissions/pipeline.py +0 -0
  302. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/services/permissions/rule_scope.py +0 -0
  303. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/services/permissions/storage.py +0 -0
  304. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/services/providers/__init__.py +0 -0
  305. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/services/providers/aliyun.py +0 -0
  306. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/services/providers/aliyun_oauth.py +0 -0
  307. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/services/qwenpaw_source.py +0 -0
  308. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/services/session_backup.py +0 -0
  309. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/services/session_index.py +0 -0
  310. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/services/session_metadata.py +0 -0
  311. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/services/session_resolver.py +0 -0
  312. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/services/session_storage.py +0 -0
  313. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/services/session_usage.py +0 -0
  314. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/services/telemetry/__init__.py +0 -0
  315. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/services/telemetry/attributes.py +0 -0
  316. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/services/telemetry/client.py +0 -0
  317. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/services/telemetry/config.py +0 -0
  318. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/services/telemetry/constants.py +0 -0
  319. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/services/telemetry/content_serializer.py +0 -0
  320. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/services/telemetry/events.py +0 -0
  321. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/services/telemetry/fallback.py +0 -0
  322. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/services/telemetry/identity.py +0 -0
  323. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/services/telemetry/metrics.py +0 -0
  324. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/services/telemetry/names.py +0 -0
  325. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/services/telemetry/sanitize.py +0 -0
  326. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/services/telemetry/sink.py +0 -0
  327. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/services/telemetry/tracing.py +0 -0
  328. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/services/telemetry/types.py +0 -0
  329. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/services/token_budget.py +0 -0
  330. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/services/token_counter.py +0 -0
  331. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/services/update_checker.py +0 -0
  332. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/skills/__init__.py +0 -0
  333. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/skills/auto_trigger.py +0 -0
  334. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/skills/bundled/__init__.py +0 -0
  335. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/skills/bundled/iac_aliyun/SKILL.md +0 -0
  336. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/skills/bundled/iac_aliyun/__init__.py +0 -0
  337. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/skills/bundled/iac_aliyun/auto_trigger.py +0 -0
  338. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/skills/bundled/iac_aliyun/references/cloud-products/ecs.md +0 -0
  339. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/skills/bundled/iac_aliyun/references/cloud-products/oss.md +0 -0
  340. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/skills/bundled/iac_aliyun/references/cloud-products/rds.md +0 -0
  341. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/skills/bundled/iac_aliyun/references/cloud-products/redis.md +0 -0
  342. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/skills/bundled/iac_aliyun/references/cloud-products/slb.md +0 -0
  343. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/skills/bundled/iac_aliyun/references/cloud-products/vpc.md +0 -0
  344. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/skills/bundled/iac_aliyun/references/ros-template.md +0 -0
  345. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/skills/bundled/iac_aliyun/references/template-parameter-recommendation.md +0 -0
  346. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/skills/bundled/iac_aliyun/references/template-parameters.md +0 -0
  347. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/skills/bundled/iac_aliyun/references/terraform-template.md +0 -0
  348. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/skills/bundled/iac_aliyun/scripts/tf2ros.py +0 -0
  349. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/skills/bundled/pac_aliyun/SKILL.md +0 -0
  350. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/skills/bundled/pac_aliyun/__init__.py +0 -0
  351. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/skills/bundled/pac_aliyun/auto_trigger.py +0 -0
  352. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/skills/bundled/pac_aliyun/references/infraguard-policy-generation.md +0 -0
  353. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/skills/bundled/simplify.py +0 -0
  354. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/skills/discovery.py +0 -0
  355. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/skills/frontmatter.py +0 -0
  356. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/skills/listing.py +0 -0
  357. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/skills/loader.py +0 -0
  358. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/skills/management.py +0 -0
  359. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/skills/processor.py +0 -0
  360. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/skills/renderer.py +0 -0
  361. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/skills/settings.py +0 -0
  362. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/skills/skill_definition.py +0 -0
  363. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/state/__init__.py +0 -0
  364. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/state/app_state.py +0 -0
  365. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/tasks/__init__.py +0 -0
  366. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/tasks/notification_queue.py +0 -0
  367. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/tasks/task_state.py +0 -0
  368. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/tasks/task_tools.py +0 -0
  369. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/tools/__init__.py +0 -0
  370. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/tools/bash/__init__.py +0 -0
  371. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/tools/bash/argv_safety.py +0 -0
  372. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/tools/bash/bash_tool.py +0 -0
  373. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/tools/bash/command_parser.py +0 -0
  374. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/tools/bash/mode_validation.py +0 -0
  375. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/tools/bash/readonly_commands.py +0 -0
  376. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/tools/bash/rule_matching.py +0 -0
  377. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/tools/bash/safety_checks.py +0 -0
  378. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/tools/cloud/__init__.py +0 -0
  379. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/tools/cloud/aliyun/__init__.py +0 -0
  380. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/tools/cloud/aliyun/aliyun_doc_search.py +0 -0
  381. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/tools/cloud/aliyun/api_hooks.py +0 -0
  382. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/tools/cloud/aliyun/endpoints.yml +0 -0
  383. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/tools/cloud/aliyun/hooks/__init__.py +0 -0
  384. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/tools/cloud/aliyun/hooks/ros_parameters.py +0 -0
  385. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/tools/cloud/aliyun/hooks/ros_validate.py +0 -0
  386. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/tools/cloud/aliyun/ros_client.py +0 -0
  387. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/tools/cloud/aliyun/ros_stack_instances.py +0 -0
  388. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/tools/cloud/aliyun/ros_yaml.py +0 -0
  389. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/tools/cloud/aliyun/user_agent.py +0 -0
  390. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/tools/cloud/registry.py +0 -0
  391. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/tools/cloud/types.py +0 -0
  392. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/tools/edit_file.py +0 -0
  393. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/tools/result_storage.py +0 -0
  394. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/tools/web_fetch.py +0 -0
  395. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/tools/write_file.py +0 -0
  396. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/types/__init__.py +0 -0
  397. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/types/skill_source.py +0 -0
  398. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/types/stream_events.py +0 -0
  399. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/ui/__init__.py +0 -0
  400. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/ui/banner.py +0 -0
  401. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/ui/components/__init__.py +0 -0
  402. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/ui/components/candidate_selection.py +0 -0
  403. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/ui/components/dialog.py +0 -0
  404. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/ui/components/divider.py +0 -0
  405. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/ui/components/fuzzy_picker.py +0 -0
  406. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/ui/components/parallel_tabs.py +0 -0
  407. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/ui/components/progress_bar.py +0 -0
  408. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/ui/components/search_box.py +0 -0
  409. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/ui/components/select.py +0 -0
  410. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/ui/components/status_icon.py +0 -0
  411. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/ui/components/tabs.py +0 -0
  412. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/ui/core/__init__.py +0 -0
  413. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/ui/core/in_place_render.py +0 -0
  414. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/ui/core/input_history.py +0 -0
  415. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/ui/core/key_event.py +0 -0
  416. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/ui/core/prompt_input.py +0 -0
  417. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/ui/core/raw_input.py +0 -0
  418. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/ui/core/raw_input_win.py +0 -0
  419. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/ui/core/screen.py +0 -0
  420. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/ui/diagram_rendering.py +0 -0
  421. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/ui/dialogs/__init__.py +0 -0
  422. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/ui/dialogs/global_search.py +0 -0
  423. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/ui/dialogs/history_search.py +0 -0
  424. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/ui/dialogs/memory.py +0 -0
  425. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/ui/dialogs/memory_editor.py +0 -0
  426. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/ui/dialogs/model_picker.py +0 -0
  427. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/ui/dialogs/quick_open.py +0 -0
  428. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/ui/dialogs/resume_picker.py +0 -0
  429. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/ui/dialogs/skills_picker.py +0 -0
  430. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/ui/keybindings/__init__.py +0 -0
  431. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/ui/keybindings/manager.py +0 -0
  432. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/ui/pipeline_styles.py +0 -0
  433. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/ui/spinner.py +0 -0
  434. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/ui/stream_accumulator.py +0 -0
  435. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/ui/suggestions/__init__.py +0 -0
  436. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/ui/suggestions/aggregator.py +0 -0
  437. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/ui/suggestions/command_provider.py +0 -0
  438. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/ui/suggestions/directory_provider.py +0 -0
  439. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/ui/suggestions/file_provider.py +0 -0
  440. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/ui/suggestions/shell_history_provider.py +0 -0
  441. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/ui/suggestions/skill_provider.py +0 -0
  442. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/ui/suggestions/token_extractor.py +0 -0
  443. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/ui/suggestions/types.py +0 -0
  444. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/ui/transcript_view.py +0 -0
  445. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/utils/__init__.py +0 -0
  446. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/utils/background_housekeeping.py +0 -0
  447. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/utils/cleanup.py +0 -0
  448. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/utils/console.py +0 -0
  449. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/utils/file_security.py +0 -0
  450. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/utils/image/__init__.py +0 -0
  451. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/utils/image/clipboard.py +0 -0
  452. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/utils/image/format_detect.py +0 -0
  453. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/utils/image/pasted_content.py +0 -0
  454. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/utils/image/processor.py +0 -0
  455. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/utils/image/resizer.py +0 -0
  456. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/utils/image/store.py +0 -0
  457. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/utils/json_utils.py +0 -0
  458. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/utils/log.py +0 -0
  459. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/utils/path_components.py +0 -0
  460. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/utils/path_locks.py +0 -0
  461. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/utils/platform.py +0 -0
  462. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/utils/project_paths.py +0 -0
  463. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/utils/public_errors.py +0 -0
  464. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/utils/public_paths.py +0 -0
  465. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/utils/signals.py +0 -0
  466. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/utils/state_io.py +0 -0
  467. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/utils/tool_input_parser.py +0 -0
  468. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/utils/tool_result_redaction.py +0 -0
  469. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code/utils/windows_paths.py +0 -0
  470. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code.egg-info/dependency_links.txt +0 -0
  471. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code.egg-info/entry_points.txt +0 -0
  472. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code.egg-info/requires.txt +0 -0
  473. {iac_code-0.9.0 → iac_code-0.9.1}/src/iac_code.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: iac_code
3
- Version: 0.9.0
3
+ Version: 0.9.1
4
4
  Summary: Your AI-powered Infrastructure as Code assistant
5
5
  Classifier: Programming Language :: Python :: 3
6
6
  Classifier: Programming Language :: Python :: 3.10
@@ -0,0 +1,2 @@
1
+ __version__ = "0.9.1"
2
+ __release_date__ = "2026-07-10"
@@ -39,7 +39,11 @@ from iac_code.a2a.pipeline_events import PipelineA2AContext, PipelineEventTransl
39
39
  from iac_code.a2a.pipeline_executor import IacCodeA2APipelineExecutor, recoverable_task_id_from_sidecar
40
40
  from iac_code.a2a.pipeline_journal import A2APipelineJournal
41
41
  from iac_code.a2a.pipeline_paths import existing_a2a_pipeline_dir_for_session
42
- from iac_code.a2a.pipeline_snapshot import A2APipelineSnapshotStore, reduce_pipeline_events
42
+ from iac_code.a2a.pipeline_snapshot import (
43
+ A2APipelineSnapshotStore,
44
+ reduce_pipeline_events,
45
+ snapshot_needs_backup_commit_repair,
46
+ )
43
47
  from iac_code.a2a.pipeline_stream import BACKUP_COMMITTED_EVENT_TYPE, PipelineA2AEventPublisher
44
48
  from iac_code.a2a.runtime_overrides import (
45
49
  a2a_request_context,
@@ -89,14 +93,21 @@ from iac_code.utils.public_paths import build_public_path_roots
89
93
 
90
94
  logger = logging.getLogger(__name__)
91
95
  _CONTEXT_LOCK_ACQUIRE_TIMEOUT_SECONDS = 1
96
+ _CANCEL_ACTIVE_TASK_DRAIN_TIMEOUT_SECONDS = 30
92
97
  _ERROR_TEXT_MAX_CHARS = 1000
93
98
  _DEFERRED_CLEANUP_PROMPTS_FILENAME = "cleanup-deferred-prompts.json"
99
+ _A2A_SAFE_MODE_ENV = "IAC_CODE_A2A_SAFE_MODE"
100
+ _TRUTHY_ENV_VALUES = {"1", "true", "yes", "on"}
94
101
 
95
102
 
96
103
  def _format_exception(exc: BaseException) -> str:
97
104
  return public_exception_summary(exc, max_chars=_ERROR_TEXT_MAX_CHARS)
98
105
 
99
106
 
107
+ def _a2a_safe_mode_enabled() -> bool:
108
+ return os.environ.get(_A2A_SAFE_MODE_ENV, "").strip().lower() in _TRUTHY_ENV_VALUES
109
+
110
+
100
111
  A2APermissionResolver: TypeAlias = Callable[[Any], "bool | Awaitable[bool]"]
101
112
 
102
113
 
@@ -428,7 +439,12 @@ def _a2a_pipeline_state_for_session(
428
439
  (_a2a_pipeline_sequence_number(event.get("sequence")) for event in journal_events if isinstance(event, dict)),
429
440
  default=0,
430
441
  )
431
- if journal_events and (not isinstance(snapshot, dict) or journal_sequence != snapshot_sequence):
442
+ needs_backup_commit_repair = (
443
+ isinstance(snapshot, dict) and snapshot_needs_backup_commit_repair(snapshot, journal_events)
444
+ )
445
+ if journal_events and (
446
+ not isinstance(snapshot, dict) or journal_sequence != snapshot_sequence or needs_backup_commit_repair
447
+ ):
432
448
  snapshot = reduce_pipeline_events(journal_events)
433
449
  if not isinstance(snapshot, dict):
434
450
  return None
@@ -1001,6 +1017,7 @@ class IacCodeA2AExecutor(AgentExecutor):
1001
1017
  session_id=session_id,
1002
1018
  cwd=cwd,
1003
1019
  resume_messages=resume_messages,
1020
+ a2a_safe_mode=_a2a_safe_mode_enabled(),
1004
1021
  )
1005
1022
  )
1006
1023
 
@@ -1329,7 +1346,10 @@ class IacCodeA2AExecutor(AgentExecutor):
1329
1346
  async def cancel(self, context: RequestContext, event_queue: EventQueue) -> None:
1330
1347
  task_id = context.task_id
1331
1348
  context_id = context.context_id or "unknown"
1332
- if task_id and await self._task_store.cancel_task(task_id):
1349
+ if task_id and await self._task_store.cancel_task_and_wait(
1350
+ task_id,
1351
+ timeout=_CANCEL_ACTIVE_TASK_DRAIN_TIMEOUT_SECONDS,
1352
+ ):
1333
1353
  await self._publish_status(
1334
1354
  event_queue,
1335
1355
  task_id=task_id,
@@ -90,6 +90,13 @@ _TERMINAL_EVENT_BY_SIDECAR_STATUS = {
90
90
  _PENDING_QUESTION_NOT_ROUTED = "not_routed"
91
91
  _PENDING_QUESTION_ANSWERED = "answered"
92
92
  _PENDING_QUESTION_STALE_FINISHED = "stale_finished"
93
+ _ACTIVE_INTERRUPT_TERMINAL_WAIT_TIMEOUT_SECONDS = 30.0
94
+
95
+
96
+ def _new_set_asyncio_event() -> asyncio.Event:
97
+ event = asyncio.Event()
98
+ event.set()
99
+ return event
93
100
 
94
101
 
95
102
  class WaitingInputCancelResult(str, Enum):
@@ -143,6 +150,7 @@ class A2APipelineRuntime:
143
150
  restart_after_interrupt: bool = False
144
151
  pause_after_interrupt: bool = False
145
152
  restart_requested: asyncio.Event = field(default_factory=asyncio.Event)
153
+ interrupt_settled: asyncio.Event = field(default_factory=_new_set_asyncio_event)
146
154
 
147
155
 
148
156
  @dataclass(frozen=True)
@@ -574,7 +582,7 @@ class IacCodeA2APipelineExecutor:
574
582
  ctx.active_task_id = task.task_id
575
583
  elif task.active_task is owner_task:
576
584
  task.active_task = None
577
- if ctx.active_task_id == task.task_id and getattr(pipeline, "sidecar_status", None) != "running":
585
+ if ctx.active_task_id == task.task_id:
578
586
  ctx.active_task_id = None
579
587
  if replacement_owner is owner_task and hasattr(ctx.runtime, "active_owner_task"):
580
588
  ctx.runtime.active_owner_task = None
@@ -725,6 +733,8 @@ class IacCodeA2APipelineExecutor:
725
733
  paused = False
726
734
  verdict: Any | None = None
727
735
  interrupt_received_published = False
736
+ interrupt_settled = _interrupt_settled_event(runtime)
737
+ interrupt_settled.clear()
728
738
  try:
729
739
  publish_interrupt_received = getattr(publisher, "publish_interrupt_received", None)
730
740
  if callable(publish_interrupt_received):
@@ -743,9 +753,8 @@ class IacCodeA2APipelineExecutor:
743
753
  apply_hard_interrupt = getattr(pipeline, "apply_hard_interrupt", None)
744
754
  if callable(apply_hard_interrupt):
745
755
  parameters = inspect.signature(apply_hard_interrupt).parameters
746
- if pipeline_input.has_images and (
747
- "source_input" in parameters
748
- or any(parameter.kind == inspect.Parameter.VAR_KEYWORD for parameter in parameters.values())
756
+ if "source_input" in parameters or any(
757
+ parameter.kind == inspect.Parameter.VAR_KEYWORD for parameter in parameters.values()
749
758
  ):
750
759
  applied = apply_hard_interrupt(verdict, source_input=runner_input)
751
760
  else:
@@ -818,6 +827,7 @@ class IacCodeA2APipelineExecutor:
818
827
  await self._complete_backup_blocked_transition(task=task, ctx=ctx)
819
828
  return True
820
829
  finally:
830
+ interrupt_settled.set()
821
831
  if paused and not bool(getattr(verdict, "paused", False)):
822
832
  resume_agent_loops = getattr(pipeline, "resume_agent_loops", None)
823
833
  if callable(resume_agent_loops):
@@ -1148,6 +1158,22 @@ class IacCodeA2APipelineExecutor:
1148
1158
  finally:
1149
1159
  next_task = None
1150
1160
 
1161
+ interrupt_action = await _consume_active_interrupt_action_before_terminal(runtime, event)
1162
+ if interrupt_action == "restart":
1163
+ close_stream_on_exit = True
1164
+ return _StreamConsumeResult(
1165
+ had_events=had_events,
1166
+ restart_requested=True,
1167
+ terminal_handoff_unavailable=terminal_handoff_unavailable,
1168
+ )
1169
+ if interrupt_action == "pause":
1170
+ close_stream_on_exit = True
1171
+ return _StreamConsumeResult(
1172
+ had_events=had_events,
1173
+ restart_requested=False,
1174
+ terminal_handoff_unavailable=terminal_handoff_unavailable,
1175
+ )
1176
+
1151
1177
  had_events = True
1152
1178
  await publish_mcp_warnings(
1153
1179
  publisher.event_queue,
@@ -3410,6 +3436,72 @@ def _restart_requested_event(runtime: Any) -> asyncio.Event:
3410
3436
  return restart_requested
3411
3437
 
3412
3438
 
3439
+ def _interrupt_settled_event(runtime: Any) -> asyncio.Event:
3440
+ interrupt_settled = getattr(runtime, "interrupt_settled", None)
3441
+ if isinstance(interrupt_settled, asyncio.Event):
3442
+ return interrupt_settled
3443
+ interrupt_settled = _new_set_asyncio_event()
3444
+ runtime.interrupt_settled = interrupt_settled
3445
+ return interrupt_settled
3446
+
3447
+
3448
+ async def _consume_active_interrupt_action_before_terminal(runtime: Any, event: Any) -> str | None:
3449
+ if not _is_pipeline_terminal_stream_event(event):
3450
+ return None
3451
+
3452
+ action = _consume_requested_interrupt_action(runtime)
3453
+ if action is not None:
3454
+ return action
3455
+
3456
+ interrupt_settled = _interrupt_settled_event(runtime)
3457
+ if interrupt_settled.is_set():
3458
+ return None
3459
+
3460
+ restart_event = _restart_requested_event(runtime)
3461
+ settled_task = asyncio.create_task(interrupt_settled.wait())
3462
+ restart_task = asyncio.create_task(restart_event.wait())
3463
+ try:
3464
+ done, _pending = await asyncio.wait(
3465
+ {settled_task, restart_task},
3466
+ timeout=_ACTIVE_INTERRUPT_TERMINAL_WAIT_TIMEOUT_SECONDS,
3467
+ return_when=asyncio.FIRST_COMPLETED,
3468
+ )
3469
+ finally:
3470
+ await _cancel_task_safely(settled_task)
3471
+ await _cancel_task_safely(restart_task)
3472
+
3473
+ action = _consume_requested_interrupt_action(runtime)
3474
+ if action is not None:
3475
+ return action
3476
+
3477
+ if not done and not interrupt_settled.is_set():
3478
+ logger.warning(
3479
+ "Timed out waiting for active A2A pipeline interrupt before publishing terminal pipeline event"
3480
+ )
3481
+ return None
3482
+
3483
+
3484
+ def _consume_requested_interrupt_action(runtime: Any) -> str | None:
3485
+ restart_event = _restart_requested_event(runtime)
3486
+ if bool(getattr(runtime, "restart_after_interrupt", False)) and restart_event.is_set():
3487
+ restart_event.clear()
3488
+ runtime.restart_after_interrupt = False
3489
+ return "restart"
3490
+ if bool(getattr(runtime, "pause_after_interrupt", False)) and restart_event.is_set():
3491
+ restart_event.clear()
3492
+ runtime.pause_after_interrupt = False
3493
+ return "pause"
3494
+ return None
3495
+
3496
+
3497
+ def _is_pipeline_terminal_stream_event(event: Any) -> bool:
3498
+ return isinstance(event, PipelineEvent) and event.type in {
3499
+ PipelineEventType.PIPELINE_COMPLETED,
3500
+ PipelineEventType.PIPELINE_ERROR,
3501
+ PipelineEventType.BACKUP_BLOCKED,
3502
+ }
3503
+
3504
+
3413
3505
  def _is_active_task_record(task: Any, active_task_id: str | None) -> bool:
3414
3506
  return active_task_id is not None and getattr(task, "task_id", None) == active_task_id
3415
3507
 
@@ -13,6 +13,7 @@ from iac_code.a2a.pipeline_snapshot import (
13
13
  reduce_pipeline_events,
14
14
  sanitize_pipeline_artifact_uris,
15
15
  sanitize_pipeline_cleanup_private_fields,
16
+ snapshot_needs_backup_commit_repair,
16
17
  )
17
18
  from iac_code.i18n import _
18
19
 
@@ -71,6 +72,11 @@ class A2APipelineRecoveryService:
71
72
  else:
72
73
  replay_events = _events_for_task(events, task_id=recovery_task_id, context_id=context_id)
73
74
 
75
+ if snapshot_needs_backup_commit_repair(snapshot, replay_events):
76
+ snapshot = reduce_pipeline_events(replay_events)
77
+ snapshot_store.save(snapshot)
78
+ snapshot = snapshot_store.load() or snapshot
79
+
74
80
  if (
75
81
  snapshot is not None
76
82
  and _snapshot_schema_is_stale(snapshot)
@@ -1122,6 +1122,78 @@ def _backup_ack_authoritative_events(events: list[dict[str, Any]]) -> list[dict[
1122
1122
  return authoritative
1123
1123
 
1124
1124
 
1125
+ def snapshot_needs_backup_commit_repair(snapshot: dict[str, Any] | None, events: list[dict[str, Any]]) -> bool:
1126
+ if not isinstance(snapshot, dict):
1127
+ return False
1128
+ pending_publications = _pending_backup_publications_from_snapshot(snapshot)
1129
+ if not pending_publications:
1130
+ return False
1131
+
1132
+ matching_events = [
1133
+ event
1134
+ for event in events
1135
+ if isinstance(event, dict) and _event_matches_snapshot_task_context(event, snapshot)
1136
+ ]
1137
+ committed_by_id: dict[str, dict[str, Any]] = {}
1138
+ committed_by_sequence_type: dict[tuple[int, str], dict[str, Any]] = {}
1139
+ for event in matching_events:
1140
+ if not _is_committed_backup_publication(event):
1141
+ continue
1142
+ event_id = _string_or_none(event.get("eventId"))
1143
+ event_type = _string_or_none(event.get("eventType")) or ""
1144
+ sequence = _sequence_value(event)
1145
+ if event_id:
1146
+ committed_by_id[event_id] = event
1147
+ committed_by_sequence_type[(sequence, event_type)] = event
1148
+
1149
+ if not committed_by_id and not committed_by_sequence_type:
1150
+ return False
1151
+
1152
+ for event in matching_events:
1153
+ if event.get("eventType") != _BACKUP_COMMITTED_EVENT_TYPE:
1154
+ continue
1155
+ data = _dict_or_empty(event.get("data"))
1156
+ committed_event = None
1157
+ committed_event_id = _string_or_none(data.get("committedEventId"))
1158
+ if committed_event_id:
1159
+ committed_event = committed_by_id.get(committed_event_id)
1160
+ if committed_event is None:
1161
+ committed_event_type = _string_or_none(data.get("committedEventType")) or ""
1162
+ committed_event = committed_by_sequence_type.get(
1163
+ (_sequence_number(data.get("committedSequence")), committed_event_type),
1164
+ )
1165
+ if committed_event is None:
1166
+ continue
1167
+ committed_event_type = _string_or_none(committed_event.get("eventType"))
1168
+ committed_sequence = _sequence_value(committed_event)
1169
+ for pending in pending_publications:
1170
+ if (
1171
+ committed_event_type == _string_or_none(pending.get("eventType"))
1172
+ and committed_sequence >= _sequence_value(pending)
1173
+ ):
1174
+ return True
1175
+ return False
1176
+
1177
+
1178
+ def _pending_backup_publications_from_snapshot(snapshot: dict[str, Any]) -> list[dict[str, Any]]:
1179
+ publications: list[dict[str, Any]] = []
1180
+ for key in ("pendingTerminal", "pendingNormalHandoff"):
1181
+ publication = snapshot.get(key)
1182
+ if isinstance(publication, dict) and _publication_visibility(publication) == _PENDING_BACKUP_VISIBILITY:
1183
+ publications.append(publication)
1184
+ return publications
1185
+
1186
+
1187
+ def _event_matches_snapshot_task_context(event: dict[str, Any], snapshot: dict[str, Any]) -> bool:
1188
+ context_id = _string_or_none(snapshot.get("contextId"))
1189
+ if context_id is not None and event.get("contextId") != context_id:
1190
+ return False
1191
+ task_id = _string_or_none(snapshot.get("taskId"))
1192
+ if task_id is None:
1193
+ return True
1194
+ return event.get("taskId") == task_id or event.get("deliveryTaskId") == task_id
1195
+
1196
+
1125
1197
  def _publication_visibility(event: dict[str, Any]) -> str | None:
1126
1198
  value = _string_or_none(event.get("visibility"))
1127
1199
  if value is not None:
@@ -1685,4 +1757,5 @@ __all__ = [
1685
1757
  "SNAPSHOT_SCHEMA_VERSION",
1686
1758
  "reduce_pipeline_events",
1687
1759
  "sanitize_pipeline_cleanup_private_fields",
1760
+ "snapshot_needs_backup_commit_repair",
1688
1761
  ]
@@ -431,6 +431,28 @@ class A2ATaskStore(TaskStore):
431
431
  record.active_task.cancel()
432
432
  return True
433
433
 
434
+ async def cancel_task_and_wait(self, task_id: str, *, timeout: float | None = None) -> bool:
435
+ async with self._mutation_lock:
436
+ record = self._tasks.get(validate_protocol_id(task_id))
437
+ if record is None or record.active_task is None or record.active_task.done():
438
+ return False
439
+ active_task = record.active_task
440
+ active_task.cancel()
441
+
442
+ if active_task is asyncio.current_task():
443
+ return True
444
+ try:
445
+ if timeout is None:
446
+ await asyncio.shield(active_task)
447
+ else:
448
+ await asyncio.wait_for(asyncio.shield(active_task), timeout=timeout)
449
+ except asyncio.CancelledError:
450
+ if not active_task.done():
451
+ raise
452
+ except TimeoutError:
453
+ logger.warning("Timed out waiting for canceled A2A task %s to finish", task_id)
454
+ return True
455
+
434
456
  async def is_task_active(self, task_id: str) -> bool:
435
457
  async with self._mutation_lock:
436
458
  record = self._tasks.get(validate_protocol_id(task_id))
@@ -1067,6 +1067,16 @@ class AgentLoop:
1067
1067
  context.relative_read_directories,
1068
1068
  list(effective_perm_ctx.relative_read_directories),
1069
1069
  )
1070
+ _extend_unique(
1071
+ context.strict_read_directories,
1072
+ list(getattr(effective_perm_ctx, "strict_read_directories", [])),
1073
+ )
1074
+ context.read_path_violation_behavior = getattr(
1075
+ effective_perm_ctx,
1076
+ "read_path_violation_behavior",
1077
+ context.read_path_violation_behavior,
1078
+ )
1079
+ context.permission_context = effective_perm_ctx
1070
1080
  permission = await check_tool_permission(tool, request.input, effective_perm_ctx)
1071
1081
  else:
1072
1082
  permission = await tool.check_permissions(request.input, {"cwd": context.cwd})
@@ -1266,7 +1276,7 @@ class AgentLoop:
1266
1276
  tool_use_id=req.id,
1267
1277
  content=processed.content,
1268
1278
  is_error=result.is_error,
1269
- metadata=self._tool_result_block_metadata(processed),
1279
+ metadata=self._tool_result_block_metadata(processed, result_metadata),
1270
1280
  )
1271
1281
  )
1272
1282
 
@@ -1396,10 +1406,30 @@ class AgentLoop:
1396
1406
  return cls._merge_tool_render_metadata(metadata, render_metadata)
1397
1407
 
1398
1408
  @staticmethod
1399
- def _tool_result_block_metadata(processed: Any) -> dict[str, Any]:
1400
- if not getattr(processed, "is_externalized", False) or not getattr(processed, "file_path", None):
1401
- return {}
1402
- return {EXTERNALIZED_RESULT_PATH_METADATA_KEY: str(processed.file_path)}
1409
+ def _tool_result_block_metadata(processed: Any, result_metadata: dict[str, Any] | None = None) -> dict[str, Any]:
1410
+ metadata: dict[str, Any] = {}
1411
+ if getattr(processed, "is_externalized", False) and getattr(processed, "file_path", None):
1412
+ metadata[EXTERNALIZED_RESULT_PATH_METADATA_KEY] = str(processed.file_path)
1413
+
1414
+ if isinstance(result_metadata, dict):
1415
+ render_metadata = result_metadata.get(TOOL_RENDER_METADATA_KEY)
1416
+ if isinstance(render_metadata, dict):
1417
+ safe_render_metadata: dict[str, Any] = {}
1418
+ for key in (
1419
+ TOOL_RENDER_DISPLAY_NAME_KEY,
1420
+ TOOL_RENDER_RESULT_COMPACT_KEY,
1421
+ TOOL_RENDER_RESULT_VERBOSE_KEY,
1422
+ ):
1423
+ value = render_metadata.get(key)
1424
+ if isinstance(value, str):
1425
+ safe_render_metadata[key] = value
1426
+ value = render_metadata.get(TOOL_RENDER_VERBOSE_RESULT_IN_TRANSCRIPT_KEY)
1427
+ if isinstance(value, bool):
1428
+ safe_render_metadata[TOOL_RENDER_VERBOSE_RESULT_IN_TRANSCRIPT_KEY] = value
1429
+ if safe_render_metadata:
1430
+ metadata[TOOL_RENDER_METADATA_KEY] = safe_render_metadata
1431
+
1432
+ return metadata
1403
1433
 
1404
1434
  def _mark_read_memory_tool_result(self, request: ToolCallRequest, result: ToolResult) -> None:
1405
1435
  if request.name != "read_memory" or result.is_error or self._memory_recall_service is None:
@@ -65,6 +65,7 @@ async def run_sub_agent(
65
65
  system_prompt=system_prompt,
66
66
  tool_registry=sub_registry or parent_tool_registry,
67
67
  max_turns=defn.max_turns,
68
+ cwd=cwd,
68
69
  permission_context=permission_context,
69
70
  )
70
71
 
@@ -103,6 +103,7 @@ def main(
103
103
  model: str = typer.Option("", "--model", "-m", help=_("LLM model to use")),
104
104
  prompt: str = typer.Option("", "--prompt", "-p", help=_("Non-interactive mode: run a single prompt and exit")),
105
105
  output_format: str = typer.Option("text", "--output-format", help=_("Output format: text, json, stream-json")),
106
+ input_format: str = typer.Option("text", "--input-format", help=_("Input format: text, stream-json")),
106
107
  max_turns: int = typer.Option(100, "--max-turns", help=_("Maximum agent turns in headless mode")),
107
108
  debug: bool = typer.Option(False, "--debug", "-d", help=_("Enable debug logging")),
108
109
  verbose: bool = typer.Option(False, "--verbose", help=_("Show headless progress on stderr")),
@@ -177,6 +178,59 @@ def main(
177
178
  typer.echo(_("Error: --resume and --continue cannot be used together."), err=True)
178
179
  raise typer.Exit(1)
179
180
 
181
+ normalized_input_format = (input_format or "text").strip().lower()
182
+ if normalized_input_format not in {"text", "stream-json"}:
183
+ typer.echo(_("Invalid --input-format '{}'. Valid values: text, stream-json").format(input_format), err=True)
184
+ raise typer.Exit(1)
185
+
186
+ if normalized_input_format == "stream-json":
187
+ normalized_output_format = (output_format or "text").strip().lower()
188
+ if prompt:
189
+ typer.echo(_("--prompt cannot be used with --input-format stream-json."), err=True)
190
+ raise typer.Exit(1)
191
+ if normalized_output_format != "stream-json":
192
+ typer.echo(_("--input-format stream-json requires --output-format stream-json."), err=True)
193
+ raise typer.Exit(1)
194
+
195
+ from iac_code.pipeline.config import get_run_mode
196
+
197
+ run_mode = get_run_mode()
198
+
199
+ if not model:
200
+ try:
201
+ model = load_saved_model() or DEFAULT_MODEL
202
+ except ValueError as exc:
203
+ typer.echo(str(exc), err=True)
204
+ raise typer.Exit(1)
205
+
206
+ if permission_mode:
207
+ from iac_code.services.permissions.loader import parse_cli_permission_mode
208
+
209
+ try:
210
+ parse_cli_permission_mode(permission_mode)
211
+ except ValueError as exc:
212
+ typer.echo(str(exc), err=True)
213
+ raise typer.Exit(1) from exc
214
+
215
+ setup_logging(session_id="process-mode", debug=debug)
216
+
217
+ from iac_code.cli.process_mode import ProcessModeOptions, ProcessModeRunner
218
+
219
+ cli_allowed = [s.strip() for s in allowed_tools.split(",") if s.strip()] if allowed_tools else None
220
+ cli_disallowed = [s.strip() for s in disallowed_tools.split(",") if s.strip()] if disallowed_tools else None
221
+ runner = ProcessModeRunner(
222
+ ProcessModeOptions(
223
+ model=model,
224
+ cwd=os.getcwd(),
225
+ run_mode=run_mode.value,
226
+ max_turns=max_turns,
227
+ cli_allowed_tools=cli_allowed,
228
+ cli_disallowed_tools=cli_disallowed,
229
+ cli_permission_mode=permission_mode or None,
230
+ )
231
+ )
232
+ raise SystemExit(asyncio.run(runner.run()))
233
+
180
234
  fmt = None
181
235
  if prompt:
182
236
  from iac_code.cli.output_formats import OutputFormat
@@ -81,7 +81,8 @@ def _sanitize_public_value(value: Any, *, public_path_roots: list[dict[str, str]
81
81
  return value
82
82
 
83
83
 
84
- def _stream_json_event_data(event: StreamEvent) -> dict[str, Any]:
84
+ def stream_json_event_data(event: StreamEvent) -> dict[str, Any]:
85
+ """Return the public stream-json representation for a stream event."""
85
86
  if isinstance(event, ToolUseStartEvent):
86
87
  return {
87
88
  "tool_use_id": event.tool_use_id,
@@ -120,7 +121,7 @@ def _stream_json_event_data(event: StreamEvent) -> dict[str, Any]:
120
121
  if isinstance(event, SubPipelineStreamEvent):
121
122
  return {
122
123
  "candidate_index": event.candidate_index,
123
- "inner": _stream_json_event_data(event.inner),
124
+ "inner": stream_json_event_data(event.inner),
124
125
  "sub_pipeline_id": event.sub_pipeline_id,
125
126
  "type": event.type,
126
127
  }
@@ -140,6 +141,10 @@ def _stream_json_event_data(event: StreamEvent) -> dict[str, Any]:
140
141
  return data
141
142
 
142
143
 
144
+ def _stream_json_event_data(event: StreamEvent) -> dict[str, Any]:
145
+ return stream_json_event_data(event)
146
+
147
+
143
148
  class TextWriter:
144
149
  """Writes only assistant text content to the output stream.
145
150
 
@@ -231,7 +236,7 @@ class StreamJsonWriter:
231
236
  self._stream = stream or sys.stdout
232
237
 
233
238
  def handle(self, event: StreamEvent) -> None:
234
- data = _stream_json_event_data(event)
239
+ data = stream_json_event_data(event)
235
240
  self._stream.write(json.dumps(data, ensure_ascii=False, default=str))
236
241
  self._stream.write("\n")
237
242
  self._stream.flush()
@@ -0,0 +1,56 @@
1
+ """Event and error mapping for CLI process mode."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import asyncio
6
+ from dataclasses import dataclass
7
+ from typing import Any
8
+
9
+ from iac_code.cli.output_formats import stream_json_event_data
10
+ from iac_code.cli.process_protocol import ProcessFrameValidationError, SDKErrorPayload, SDKProcessRuntimeError
11
+ from iac_code.providers.manager import ProviderNotConfiguredError
12
+ from iac_code.types.stream_events import ErrorEvent
13
+ from iac_code.utils.public_errors import sanitize_public_text
14
+
15
+
16
+ @dataclass(frozen=True)
17
+ class ProcessSerializedEvent:
18
+ """Already-public event payload to embed in a process-mode stream_event frame."""
19
+
20
+ payload: dict[str, Any]
21
+
22
+
23
+ class ProcessEventSerializer:
24
+ """Serialize internal stream events to the public stream-json event shape."""
25
+
26
+ def serialize(self, event: Any) -> dict:
27
+ if isinstance(event, ProcessSerializedEvent):
28
+ return event.payload
29
+ return stream_json_event_data(event)
30
+
31
+
32
+ class ProcessErrorMapper:
33
+ """Map runtime exceptions and error events to stable process-mode error payloads."""
34
+
35
+ def from_event(self, event: ErrorEvent) -> SDKErrorPayload:
36
+ return SDKErrorPayload(
37
+ code="stream_error",
38
+ message=sanitize_public_text(event.error),
39
+ retryable=event.is_retryable,
40
+ error_id=event.error_id,
41
+ )
42
+
43
+ def from_exception(self, exc: BaseException) -> SDKErrorPayload:
44
+ if isinstance(exc, SDKProcessRuntimeError):
45
+ return exc.payload
46
+ if isinstance(exc, ProcessFrameValidationError):
47
+ return SDKErrorPayload(code=exc.code, message=exc.message, retryable=exc.retryable)
48
+ if isinstance(exc, ProviderNotConfiguredError):
49
+ return SDKErrorPayload(
50
+ code="provider_not_configured",
51
+ message=sanitize_public_text(str(exc)),
52
+ retryable=False,
53
+ )
54
+ if isinstance(exc, asyncio.CancelledError):
55
+ return SDKErrorPayload(code="turn_canceled", message="Turn canceled.", retryable=False)
56
+ return SDKErrorPayload(code="internal_error", message=sanitize_public_text(str(exc)), retryable=False)