iac-code 0.2.1__tar.gz → 0.2.3__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 (272) hide show
  1. {iac_code-0.2.1 → iac_code-0.2.3}/PKG-INFO +1 -1
  2. iac_code-0.2.3/src/iac_code/__init__.py +2 -0
  3. {iac_code-0.2.1 → iac_code-0.2.3}/src/iac_code/a2a/events.py +10 -8
  4. {iac_code-0.2.1 → iac_code-0.2.3}/src/iac_code/a2a/executor.py +22 -1
  5. {iac_code-0.2.1 → iac_code-0.2.3}/src/iac_code/acp/session.py +11 -0
  6. {iac_code-0.2.1 → iac_code-0.2.3}/src/iac_code/cli/main.py +166 -6
  7. {iac_code-0.2.1 → iac_code-0.2.3}/src/iac_code/commands/__init__.py +9 -0
  8. {iac_code-0.2.1 → iac_code-0.2.3}/src/iac_code/commands/registry.py +7 -1
  9. {iac_code-0.2.1 → iac_code-0.2.3}/src/iac_code/config.py +1 -1
  10. {iac_code-0.2.1 → iac_code-0.2.3}/src/iac_code/i18n/locales/de/LC_MESSAGES/messages.mo +0 -0
  11. {iac_code-0.2.1 → iac_code-0.2.3}/src/iac_code/i18n/locales/de/LC_MESSAGES/messages.po +162 -88
  12. {iac_code-0.2.1 → iac_code-0.2.3}/src/iac_code/i18n/locales/es/LC_MESSAGES/messages.mo +0 -0
  13. {iac_code-0.2.1 → iac_code-0.2.3}/src/iac_code/i18n/locales/es/LC_MESSAGES/messages.po +169 -88
  14. {iac_code-0.2.1 → iac_code-0.2.3}/src/iac_code/i18n/locales/fr/LC_MESSAGES/messages.mo +0 -0
  15. {iac_code-0.2.1 → iac_code-0.2.3}/src/iac_code/i18n/locales/fr/LC_MESSAGES/messages.po +169 -88
  16. {iac_code-0.2.1 → iac_code-0.2.3}/src/iac_code/i18n/locales/ja/LC_MESSAGES/messages.mo +0 -0
  17. {iac_code-0.2.1 → iac_code-0.2.3}/src/iac_code/i18n/locales/ja/LC_MESSAGES/messages.po +156 -88
  18. {iac_code-0.2.1 → iac_code-0.2.3}/src/iac_code/i18n/locales/pt/LC_MESSAGES/messages.mo +0 -0
  19. {iac_code-0.2.1 → iac_code-0.2.3}/src/iac_code/i18n/locales/pt/LC_MESSAGES/messages.po +164 -88
  20. {iac_code-0.2.1 → iac_code-0.2.3}/src/iac_code/i18n/locales/zh/LC_MESSAGES/messages.mo +0 -0
  21. {iac_code-0.2.1 → iac_code-0.2.3}/src/iac_code/i18n/locales/zh/LC_MESSAGES/messages.po +155 -89
  22. {iac_code-0.2.1 → iac_code-0.2.3}/src/iac_code/providers/manager.py +3 -3
  23. {iac_code-0.2.1 → iac_code-0.2.3}/src/iac_code/providers/registry.py +5 -2
  24. {iac_code-0.2.1 → iac_code-0.2.3}/src/iac_code/providers/thinking.py +4 -0
  25. {iac_code-0.2.1 → iac_code-0.2.3}/src/iac_code/services/telemetry/__init__.py +11 -0
  26. {iac_code-0.2.1 → iac_code-0.2.3}/src/iac_code/services/telemetry/client.py +31 -10
  27. {iac_code-0.2.1 → iac_code-0.2.3}/src/iac_code/services/telemetry/names.py +1 -1
  28. {iac_code-0.2.1 → iac_code-0.2.3}/src/iac_code/skills/bundled/iac_aliyun/SKILL.md +14 -13
  29. {iac_code-0.2.1 → iac_code-0.2.3}/src/iac_code/tools/cloud/aliyun/aliyun_api.py +20 -1
  30. iac_code-0.2.3/src/iac_code/tools/cloud/aliyun/api_hooks.py +54 -0
  31. iac_code-0.2.3/src/iac_code/tools/cloud/aliyun/hooks/ros_parameters.py +76 -0
  32. iac_code-0.2.3/src/iac_code/tools/cloud/aliyun/hooks/ros_validate.py +157 -0
  33. {iac_code-0.2.1 → iac_code-0.2.3}/src/iac_code/tools/cloud/aliyun/ros_stack.py +15 -5
  34. iac_code-0.2.3/src/iac_code/tools/cloud/aliyun/ros_yaml.py +102 -0
  35. {iac_code-0.2.1 → iac_code-0.2.3}/src/iac_code/ui/core/input_history.py +31 -7
  36. {iac_code-0.2.1 → iac_code-0.2.3}/src/iac_code/ui/core/prompt_input.py +83 -36
  37. {iac_code-0.2.1 → iac_code-0.2.3}/src/iac_code/ui/renderer.py +10 -4
  38. {iac_code-0.2.1 → iac_code-0.2.3}/src/iac_code/ui/repl.py +47 -7
  39. iac_code-0.2.3/src/iac_code/utils/image/__init__.py +0 -0
  40. {iac_code-0.2.1 → iac_code-0.2.3}/src/iac_code/utils/image/clipboard.py +31 -0
  41. {iac_code-0.2.1 → iac_code-0.2.3}/src/iac_code.egg-info/PKG-INFO +1 -1
  42. {iac_code-0.2.1 → iac_code-0.2.3}/src/iac_code.egg-info/SOURCES.txt +5 -0
  43. iac_code-0.2.1/src/iac_code/__init__.py +0 -2
  44. {iac_code-0.2.1 → iac_code-0.2.3}/LICENSE +0 -0
  45. {iac_code-0.2.1 → iac_code-0.2.3}/MANIFEST.in +0 -0
  46. {iac_code-0.2.1 → iac_code-0.2.3}/README.md +0 -0
  47. {iac_code-0.2.1 → iac_code-0.2.3}/pyproject.toml +0 -0
  48. {iac_code-0.2.1 → iac_code-0.2.3}/setup.cfg +0 -0
  49. {iac_code-0.2.1 → iac_code-0.2.3}/setup.py +0 -0
  50. {iac_code-0.2.1 → iac_code-0.2.3}/src/iac_code/a2a/__init__.py +0 -0
  51. {iac_code-0.2.1 → iac_code-0.2.3}/src/iac_code/a2a/agent_card.py +0 -0
  52. {iac_code-0.2.1 → iac_code-0.2.3}/src/iac_code/a2a/app.py +0 -0
  53. {iac_code-0.2.1 → iac_code-0.2.3}/src/iac_code/a2a/artifacts.py +0 -0
  54. {iac_code-0.2.1 → iac_code-0.2.3}/src/iac_code/a2a/client.py +0 -0
  55. {iac_code-0.2.1 → iac_code-0.2.3}/src/iac_code/a2a/metrics.py +0 -0
  56. {iac_code-0.2.1 → iac_code-0.2.3}/src/iac_code/a2a/parts.py +0 -0
  57. {iac_code-0.2.1 → iac_code-0.2.3}/src/iac_code/a2a/persistence.py +0 -0
  58. {iac_code-0.2.1 → iac_code-0.2.3}/src/iac_code/a2a/push.py +0 -0
  59. {iac_code-0.2.1 → iac_code-0.2.3}/src/iac_code/a2a/push_queue.py +0 -0
  60. {iac_code-0.2.1 → iac_code-0.2.3}/src/iac_code/a2a/push_secrets.py +0 -0
  61. {iac_code-0.2.1 → iac_code-0.2.3}/src/iac_code/a2a/push_worker.py +0 -0
  62. {iac_code-0.2.1 → iac_code-0.2.3}/src/iac_code/a2a/router.py +0 -0
  63. {iac_code-0.2.1 → iac_code-0.2.3}/src/iac_code/a2a/signing.py +0 -0
  64. {iac_code-0.2.1 → iac_code-0.2.3}/src/iac_code/a2a/task_store.py +0 -0
  65. {iac_code-0.2.1 → iac_code-0.2.3}/src/iac_code/a2a/transport.py +0 -0
  66. {iac_code-0.2.1 → iac_code-0.2.3}/src/iac_code/a2a/transports/__init__.py +0 -0
  67. {iac_code-0.2.1 → iac_code-0.2.3}/src/iac_code/a2a/transports/base.py +0 -0
  68. {iac_code-0.2.1 → iac_code-0.2.3}/src/iac_code/a2a/transports/dispatcher.py +0 -0
  69. {iac_code-0.2.1 → iac_code-0.2.3}/src/iac_code/a2a/transports/grpc.py +0 -0
  70. {iac_code-0.2.1 → iac_code-0.2.3}/src/iac_code/a2a/transports/grpc_jsonrpc.py +0 -0
  71. {iac_code-0.2.1 → iac_code-0.2.3}/src/iac_code/a2a/transports/http.py +0 -0
  72. {iac_code-0.2.1 → iac_code-0.2.3}/src/iac_code/a2a/transports/redis_streams.py +0 -0
  73. {iac_code-0.2.1 → iac_code-0.2.3}/src/iac_code/a2a/transports/stdio.py +0 -0
  74. {iac_code-0.2.1 → iac_code-0.2.3}/src/iac_code/a2a/transports/unix.py +0 -0
  75. {iac_code-0.2.1 → iac_code-0.2.3}/src/iac_code/a2a/transports/websocket.py +0 -0
  76. {iac_code-0.2.1 → iac_code-0.2.3}/src/iac_code/a2a/types.py +0 -0
  77. {iac_code-0.2.1 → iac_code-0.2.3}/src/iac_code/acp/__init__.py +0 -0
  78. {iac_code-0.2.1 → iac_code-0.2.3}/src/iac_code/acp/convert.py +0 -0
  79. {iac_code-0.2.1 → iac_code-0.2.3}/src/iac_code/acp/http_sse.py +0 -0
  80. {iac_code-0.2.1 → iac_code-0.2.3}/src/iac_code/acp/mcp.py +0 -0
  81. {iac_code-0.2.1 → iac_code-0.2.3}/src/iac_code/acp/metrics.py +0 -0
  82. {iac_code-0.2.1 → iac_code-0.2.3}/src/iac_code/acp/server.py +0 -0
  83. {iac_code-0.2.1 → iac_code-0.2.3}/src/iac_code/acp/slash_registry.py +0 -0
  84. {iac_code-0.2.1 → iac_code-0.2.3}/src/iac_code/acp/state.py +0 -0
  85. {iac_code-0.2.1 → iac_code-0.2.3}/src/iac_code/acp/tools.py +0 -0
  86. {iac_code-0.2.1 → iac_code-0.2.3}/src/iac_code/acp/types.py +0 -0
  87. {iac_code-0.2.1 → iac_code-0.2.3}/src/iac_code/acp/version.py +0 -0
  88. {iac_code-0.2.1 → iac_code-0.2.3}/src/iac_code/agent/__init__.py +0 -0
  89. {iac_code-0.2.1 → iac_code-0.2.3}/src/iac_code/agent/agent_loop.py +0 -0
  90. {iac_code-0.2.1 → iac_code-0.2.3}/src/iac_code/agent/agent_tool.py +0 -0
  91. {iac_code-0.2.1 → iac_code-0.2.3}/src/iac_code/agent/agent_types.py +0 -0
  92. {iac_code-0.2.1 → iac_code-0.2.3}/src/iac_code/agent/message.py +0 -0
  93. {iac_code-0.2.1 → iac_code-0.2.3}/src/iac_code/agent/system_prompt.py +0 -0
  94. {iac_code-0.2.1 → iac_code-0.2.3}/src/iac_code/cli/__init__.py +0 -0
  95. {iac_code-0.2.1 → iac_code-0.2.3}/src/iac_code/cli/headless.py +0 -0
  96. {iac_code-0.2.1 → iac_code-0.2.3}/src/iac_code/cli/output_formats.py +0 -0
  97. {iac_code-0.2.1 → iac_code-0.2.3}/src/iac_code/commands/auth.py +0 -0
  98. {iac_code-0.2.1 → iac_code-0.2.3}/src/iac_code/commands/clear.py +0 -0
  99. {iac_code-0.2.1 → iac_code-0.2.3}/src/iac_code/commands/compact.py +0 -0
  100. {iac_code-0.2.1 → iac_code-0.2.3}/src/iac_code/commands/debug.py +0 -0
  101. {iac_code-0.2.1 → iac_code-0.2.3}/src/iac_code/commands/effort.py +0 -0
  102. {iac_code-0.2.1 → iac_code-0.2.3}/src/iac_code/commands/exit.py +0 -0
  103. {iac_code-0.2.1 → iac_code-0.2.3}/src/iac_code/commands/help.py +0 -0
  104. {iac_code-0.2.1 → iac_code-0.2.3}/src/iac_code/commands/model.py +0 -0
  105. {iac_code-0.2.1 → iac_code-0.2.3}/src/iac_code/commands/resume.py +0 -0
  106. {iac_code-0.2.1 → iac_code-0.2.3}/src/iac_code/commands/tasks.py +0 -0
  107. {iac_code-0.2.1 → iac_code-0.2.3}/src/iac_code/i18n/__init__.py +0 -0
  108. {iac_code-0.2.1 → iac_code-0.2.3}/src/iac_code/memory/__init__.py +0 -0
  109. {iac_code-0.2.1 → iac_code-0.2.3}/src/iac_code/memory/memory_manager.py +0 -0
  110. {iac_code-0.2.1 → iac_code-0.2.3}/src/iac_code/memory/memory_tools.py +0 -0
  111. {iac_code-0.2.1 → iac_code-0.2.3}/src/iac_code/providers/__init__.py +0 -0
  112. {iac_code-0.2.1 → iac_code-0.2.3}/src/iac_code/providers/anthropic_provider.py +0 -0
  113. {iac_code-0.2.1 → iac_code-0.2.3}/src/iac_code/providers/azure_openai_provider.py +0 -0
  114. {iac_code-0.2.1 → iac_code-0.2.3}/src/iac_code/providers/base.py +0 -0
  115. {iac_code-0.2.1 → iac_code-0.2.3}/src/iac_code/providers/dashscope_provider.py +0 -0
  116. {iac_code-0.2.1 → iac_code-0.2.3}/src/iac_code/providers/deepseek_provider.py +0 -0
  117. {iac_code-0.2.1 → iac_code-0.2.3}/src/iac_code/providers/gemini_provider.py +0 -0
  118. {iac_code-0.2.1 → iac_code-0.2.3}/src/iac_code/providers/kimi_provider.py +0 -0
  119. {iac_code-0.2.1 → iac_code-0.2.3}/src/iac_code/providers/lmstudio_provider.py +0 -0
  120. {iac_code-0.2.1 → iac_code-0.2.3}/src/iac_code/providers/minimax_provider.py +0 -0
  121. {iac_code-0.2.1 → iac_code-0.2.3}/src/iac_code/providers/modelscope_provider.py +0 -0
  122. {iac_code-0.2.1 → iac_code-0.2.3}/src/iac_code/providers/ollama_provider.py +0 -0
  123. {iac_code-0.2.1 → iac_code-0.2.3}/src/iac_code/providers/openai_provider.py +0 -0
  124. {iac_code-0.2.1 → iac_code-0.2.3}/src/iac_code/providers/openrouter_provider.py +0 -0
  125. {iac_code-0.2.1 → iac_code-0.2.3}/src/iac_code/providers/retry.py +0 -0
  126. {iac_code-0.2.1 → iac_code-0.2.3}/src/iac_code/providers/siliconflow_provider.py +0 -0
  127. {iac_code-0.2.1 → iac_code-0.2.3}/src/iac_code/providers/stream_watchdog.py +0 -0
  128. {iac_code-0.2.1 → iac_code-0.2.3}/src/iac_code/providers/volcengine_provider.py +0 -0
  129. {iac_code-0.2.1 → iac_code-0.2.3}/src/iac_code/providers/zhipu_provider.py +0 -0
  130. {iac_code-0.2.1 → iac_code-0.2.3}/src/iac_code/services/__init__.py +0 -0
  131. {iac_code-0.2.1 → iac_code-0.2.3}/src/iac_code/services/agent_factory.py +0 -0
  132. {iac_code-0.2.1 → iac_code-0.2.3}/src/iac_code/services/capabilities/__init__.py +0 -0
  133. {iac_code-0.2.1 → iac_code-0.2.3}/src/iac_code/services/capabilities/auto_detect.py +0 -0
  134. {iac_code-0.2.1 → iac_code-0.2.3}/src/iac_code/services/capabilities/multimodal.py +0 -0
  135. {iac_code-0.2.1 → iac_code-0.2.3}/src/iac_code/services/cloud_credentials.py +0 -0
  136. {iac_code-0.2.1 → iac_code-0.2.3}/src/iac_code/services/context_manager.py +0 -0
  137. {iac_code-0.2.1 → iac_code-0.2.3}/src/iac_code/services/permissions/__init__.py +0 -0
  138. {iac_code-0.2.1 → iac_code-0.2.3}/src/iac_code/services/permissions/loader.py +0 -0
  139. {iac_code-0.2.1 → iac_code-0.2.3}/src/iac_code/services/permissions/pipeline.py +0 -0
  140. {iac_code-0.2.1 → iac_code-0.2.3}/src/iac_code/services/permissions/storage.py +0 -0
  141. {iac_code-0.2.1 → iac_code-0.2.3}/src/iac_code/services/providers/__init__.py +0 -0
  142. {iac_code-0.2.1 → iac_code-0.2.3}/src/iac_code/services/providers/aliyun.py +0 -0
  143. {iac_code-0.2.1 → iac_code-0.2.3}/src/iac_code/services/qwenpaw_source.py +0 -0
  144. {iac_code-0.2.1 → iac_code-0.2.3}/src/iac_code/services/session_index.py +0 -0
  145. {iac_code-0.2.1 → iac_code-0.2.3}/src/iac_code/services/session_storage.py +0 -0
  146. {iac_code-0.2.1 → iac_code-0.2.3}/src/iac_code/services/telemetry/attributes.py +0 -0
  147. {iac_code-0.2.1 → iac_code-0.2.3}/src/iac_code/services/telemetry/config.py +0 -0
  148. {iac_code-0.2.1 → iac_code-0.2.3}/src/iac_code/services/telemetry/constants.py +0 -0
  149. {iac_code-0.2.1 → iac_code-0.2.3}/src/iac_code/services/telemetry/content_serializer.py +0 -0
  150. {iac_code-0.2.1 → iac_code-0.2.3}/src/iac_code/services/telemetry/events.py +0 -0
  151. {iac_code-0.2.1 → iac_code-0.2.3}/src/iac_code/services/telemetry/fallback.py +0 -0
  152. {iac_code-0.2.1 → iac_code-0.2.3}/src/iac_code/services/telemetry/identity.py +0 -0
  153. {iac_code-0.2.1 → iac_code-0.2.3}/src/iac_code/services/telemetry/metrics.py +0 -0
  154. {iac_code-0.2.1 → iac_code-0.2.3}/src/iac_code/services/telemetry/sanitize.py +0 -0
  155. {iac_code-0.2.1 → iac_code-0.2.3}/src/iac_code/services/telemetry/sink.py +0 -0
  156. {iac_code-0.2.1 → iac_code-0.2.3}/src/iac_code/services/telemetry/tracing.py +0 -0
  157. {iac_code-0.2.1 → iac_code-0.2.3}/src/iac_code/services/telemetry/types.py +0 -0
  158. {iac_code-0.2.1 → iac_code-0.2.3}/src/iac_code/services/token_budget.py +0 -0
  159. {iac_code-0.2.1 → iac_code-0.2.3}/src/iac_code/services/token_counter.py +0 -0
  160. {iac_code-0.2.1 → iac_code-0.2.3}/src/iac_code/skills/__init__.py +0 -0
  161. {iac_code-0.2.1 → iac_code-0.2.3}/src/iac_code/skills/bundled/__init__.py +0 -0
  162. {iac_code-0.2.1 → iac_code-0.2.3}/src/iac_code/skills/bundled/iac_aliyun/__init__.py +0 -0
  163. {iac_code-0.2.1 → iac_code-0.2.3}/src/iac_code/skills/bundled/iac_aliyun/references/cloud-products/ecs.md +0 -0
  164. {iac_code-0.2.1 → iac_code-0.2.3}/src/iac_code/skills/bundled/iac_aliyun/references/cloud-products/oss.md +0 -0
  165. {iac_code-0.2.1 → iac_code-0.2.3}/src/iac_code/skills/bundled/iac_aliyun/references/cloud-products/rds.md +0 -0
  166. {iac_code-0.2.1 → iac_code-0.2.3}/src/iac_code/skills/bundled/iac_aliyun/references/cloud-products/redis.md +0 -0
  167. {iac_code-0.2.1 → iac_code-0.2.3}/src/iac_code/skills/bundled/iac_aliyun/references/cloud-products/slb.md +0 -0
  168. {iac_code-0.2.1 → iac_code-0.2.3}/src/iac_code/skills/bundled/iac_aliyun/references/cloud-products/vpc.md +0 -0
  169. {iac_code-0.2.1 → iac_code-0.2.3}/src/iac_code/skills/bundled/iac_aliyun/references/ros-template.md +0 -0
  170. {iac_code-0.2.1 → iac_code-0.2.3}/src/iac_code/skills/bundled/iac_aliyun/references/template-parameters.md +0 -0
  171. {iac_code-0.2.1 → iac_code-0.2.3}/src/iac_code/skills/bundled/iac_aliyun/references/terraform-template.md +0 -0
  172. {iac_code-0.2.1 → iac_code-0.2.3}/src/iac_code/skills/bundled/iac_aliyun/scripts/tf2ros.py +0 -0
  173. {iac_code-0.2.1 → iac_code-0.2.3}/src/iac_code/skills/bundled/simplify.py +0 -0
  174. {iac_code-0.2.1 → iac_code-0.2.3}/src/iac_code/skills/discovery.py +0 -0
  175. {iac_code-0.2.1 → iac_code-0.2.3}/src/iac_code/skills/frontmatter.py +0 -0
  176. {iac_code-0.2.1 → iac_code-0.2.3}/src/iac_code/skills/listing.py +0 -0
  177. {iac_code-0.2.1 → iac_code-0.2.3}/src/iac_code/skills/loader.py +0 -0
  178. {iac_code-0.2.1 → iac_code-0.2.3}/src/iac_code/skills/processor.py +0 -0
  179. {iac_code-0.2.1 → iac_code-0.2.3}/src/iac_code/skills/renderer.py +0 -0
  180. {iac_code-0.2.1 → iac_code-0.2.3}/src/iac_code/skills/skill_definition.py +0 -0
  181. {iac_code-0.2.1 → iac_code-0.2.3}/src/iac_code/skills/skill_tool.py +0 -0
  182. {iac_code-0.2.1 → iac_code-0.2.3}/src/iac_code/state/__init__.py +0 -0
  183. {iac_code-0.2.1 → iac_code-0.2.3}/src/iac_code/state/app_state.py +0 -0
  184. {iac_code-0.2.1 → iac_code-0.2.3}/src/iac_code/tasks/__init__.py +0 -0
  185. {iac_code-0.2.1 → iac_code-0.2.3}/src/iac_code/tasks/notification_queue.py +0 -0
  186. {iac_code-0.2.1 → iac_code-0.2.3}/src/iac_code/tasks/task_state.py +0 -0
  187. {iac_code-0.2.1 → iac_code-0.2.3}/src/iac_code/tasks/task_tools.py +0 -0
  188. {iac_code-0.2.1 → iac_code-0.2.3}/src/iac_code/tools/__init__.py +0 -0
  189. {iac_code-0.2.1 → iac_code-0.2.3}/src/iac_code/tools/base.py +0 -0
  190. {iac_code-0.2.1 → iac_code-0.2.3}/src/iac_code/tools/bash/__init__.py +0 -0
  191. {iac_code-0.2.1 → iac_code-0.2.3}/src/iac_code/tools/bash/bash_tool.py +0 -0
  192. {iac_code-0.2.1 → iac_code-0.2.3}/src/iac_code/tools/bash/command_parser.py +0 -0
  193. {iac_code-0.2.1 → iac_code-0.2.3}/src/iac_code/tools/bash/mode_validation.py +0 -0
  194. {iac_code-0.2.1 → iac_code-0.2.3}/src/iac_code/tools/bash/path_validation.py +0 -0
  195. {iac_code-0.2.1 → iac_code-0.2.3}/src/iac_code/tools/bash/permissions.py +0 -0
  196. {iac_code-0.2.1 → iac_code-0.2.3}/src/iac_code/tools/bash/readonly_commands.py +0 -0
  197. {iac_code-0.2.1 → iac_code-0.2.3}/src/iac_code/tools/bash/rule_matching.py +0 -0
  198. {iac_code-0.2.1 → iac_code-0.2.3}/src/iac_code/tools/bash/safety_checks.py +0 -0
  199. {iac_code-0.2.1 → iac_code-0.2.3}/src/iac_code/tools/cloud/__init__.py +0 -0
  200. {iac_code-0.2.1 → iac_code-0.2.3}/src/iac_code/tools/cloud/aliyun/__init__.py +0 -0
  201. {iac_code-0.2.1 → iac_code-0.2.3}/src/iac_code/tools/cloud/aliyun/aliyun_doc_search.py +0 -0
  202. {iac_code-0.2.1 → iac_code-0.2.3}/src/iac_code/tools/cloud/aliyun/endpoints.yml +0 -0
  203. {iac_code-0.2.1/src/iac_code/ui/components → iac_code-0.2.3/src/iac_code/tools/cloud/aliyun/hooks}/__init__.py +0 -0
  204. {iac_code-0.2.1 → iac_code-0.2.3}/src/iac_code/tools/cloud/aliyun/ros_client.py +0 -0
  205. {iac_code-0.2.1 → iac_code-0.2.3}/src/iac_code/tools/cloud/aliyun/ros_stack_instances.py +0 -0
  206. {iac_code-0.2.1 → iac_code-0.2.3}/src/iac_code/tools/cloud/base_api.py +0 -0
  207. {iac_code-0.2.1 → iac_code-0.2.3}/src/iac_code/tools/cloud/base_stack.py +0 -0
  208. {iac_code-0.2.1 → iac_code-0.2.3}/src/iac_code/tools/cloud/registry.py +0 -0
  209. {iac_code-0.2.1 → iac_code-0.2.3}/src/iac_code/tools/cloud/types.py +0 -0
  210. {iac_code-0.2.1 → iac_code-0.2.3}/src/iac_code/tools/edit_file.py +0 -0
  211. {iac_code-0.2.1 → iac_code-0.2.3}/src/iac_code/tools/glob.py +0 -0
  212. {iac_code-0.2.1 → iac_code-0.2.3}/src/iac_code/tools/grep.py +0 -0
  213. {iac_code-0.2.1 → iac_code-0.2.3}/src/iac_code/tools/list_files.py +0 -0
  214. {iac_code-0.2.1 → iac_code-0.2.3}/src/iac_code/tools/read_file.py +0 -0
  215. {iac_code-0.2.1 → iac_code-0.2.3}/src/iac_code/tools/result_storage.py +0 -0
  216. {iac_code-0.2.1 → iac_code-0.2.3}/src/iac_code/tools/tool_executor.py +0 -0
  217. {iac_code-0.2.1 → iac_code-0.2.3}/src/iac_code/tools/web_fetch.py +0 -0
  218. {iac_code-0.2.1 → iac_code-0.2.3}/src/iac_code/tools/write_file.py +0 -0
  219. {iac_code-0.2.1 → iac_code-0.2.3}/src/iac_code/types/__init__.py +0 -0
  220. {iac_code-0.2.1 → iac_code-0.2.3}/src/iac_code/types/permissions.py +0 -0
  221. {iac_code-0.2.1 → iac_code-0.2.3}/src/iac_code/types/skill_source.py +0 -0
  222. {iac_code-0.2.1 → iac_code-0.2.3}/src/iac_code/types/stream_events.py +0 -0
  223. {iac_code-0.2.1 → iac_code-0.2.3}/src/iac_code/ui/__init__.py +0 -0
  224. {iac_code-0.2.1 → iac_code-0.2.3}/src/iac_code/ui/banner.py +0 -0
  225. {iac_code-0.2.1/src/iac_code/ui/core → iac_code-0.2.3/src/iac_code/ui/components}/__init__.py +0 -0
  226. {iac_code-0.2.1 → iac_code-0.2.3}/src/iac_code/ui/components/dialog.py +0 -0
  227. {iac_code-0.2.1 → iac_code-0.2.3}/src/iac_code/ui/components/divider.py +0 -0
  228. {iac_code-0.2.1 → iac_code-0.2.3}/src/iac_code/ui/components/fuzzy_picker.py +0 -0
  229. {iac_code-0.2.1 → iac_code-0.2.3}/src/iac_code/ui/components/progress_bar.py +0 -0
  230. {iac_code-0.2.1 → iac_code-0.2.3}/src/iac_code/ui/components/search_box.py +0 -0
  231. {iac_code-0.2.1 → iac_code-0.2.3}/src/iac_code/ui/components/select.py +0 -0
  232. {iac_code-0.2.1 → iac_code-0.2.3}/src/iac_code/ui/components/status_icon.py +0 -0
  233. {iac_code-0.2.1 → iac_code-0.2.3}/src/iac_code/ui/components/tabs.py +0 -0
  234. {iac_code-0.2.1/src/iac_code/ui/dialogs → iac_code-0.2.3/src/iac_code/ui/core}/__init__.py +0 -0
  235. {iac_code-0.2.1 → iac_code-0.2.3}/src/iac_code/ui/core/in_place_render.py +0 -0
  236. {iac_code-0.2.1 → iac_code-0.2.3}/src/iac_code/ui/core/key_event.py +0 -0
  237. {iac_code-0.2.1 → iac_code-0.2.3}/src/iac_code/ui/core/raw_input.py +0 -0
  238. {iac_code-0.2.1 → iac_code-0.2.3}/src/iac_code/ui/core/screen.py +0 -0
  239. {iac_code-0.2.1/src/iac_code/ui/keybindings → iac_code-0.2.3/src/iac_code/ui/dialogs}/__init__.py +0 -0
  240. {iac_code-0.2.1 → iac_code-0.2.3}/src/iac_code/ui/dialogs/global_search.py +0 -0
  241. {iac_code-0.2.1 → iac_code-0.2.3}/src/iac_code/ui/dialogs/history_search.py +0 -0
  242. {iac_code-0.2.1 → iac_code-0.2.3}/src/iac_code/ui/dialogs/model_picker.py +0 -0
  243. {iac_code-0.2.1 → iac_code-0.2.3}/src/iac_code/ui/dialogs/quick_open.py +0 -0
  244. {iac_code-0.2.1 → iac_code-0.2.3}/src/iac_code/ui/dialogs/resume_picker.py +0 -0
  245. {iac_code-0.2.1/src/iac_code/ui/suggestions → iac_code-0.2.3/src/iac_code/ui/keybindings}/__init__.py +0 -0
  246. {iac_code-0.2.1 → iac_code-0.2.3}/src/iac_code/ui/keybindings/manager.py +0 -0
  247. {iac_code-0.2.1 → iac_code-0.2.3}/src/iac_code/ui/spinner.py +0 -0
  248. {iac_code-0.2.1/src/iac_code/utils → iac_code-0.2.3/src/iac_code/ui/suggestions}/__init__.py +0 -0
  249. {iac_code-0.2.1 → iac_code-0.2.3}/src/iac_code/ui/suggestions/aggregator.py +0 -0
  250. {iac_code-0.2.1 → iac_code-0.2.3}/src/iac_code/ui/suggestions/command_provider.py +0 -0
  251. {iac_code-0.2.1 → iac_code-0.2.3}/src/iac_code/ui/suggestions/directory_provider.py +0 -0
  252. {iac_code-0.2.1 → iac_code-0.2.3}/src/iac_code/ui/suggestions/file_provider.py +0 -0
  253. {iac_code-0.2.1 → iac_code-0.2.3}/src/iac_code/ui/suggestions/shell_history_provider.py +0 -0
  254. {iac_code-0.2.1 → iac_code-0.2.3}/src/iac_code/ui/suggestions/token_extractor.py +0 -0
  255. {iac_code-0.2.1 → iac_code-0.2.3}/src/iac_code/ui/suggestions/types.py +0 -0
  256. {iac_code-0.2.1 → iac_code-0.2.3}/src/iac_code/ui/transcript_view.py +0 -0
  257. {iac_code-0.2.1/src/iac_code/utils/image → iac_code-0.2.3/src/iac_code/utils}/__init__.py +0 -0
  258. {iac_code-0.2.1 → iac_code-0.2.3}/src/iac_code/utils/background_housekeeping.py +0 -0
  259. {iac_code-0.2.1 → iac_code-0.2.3}/src/iac_code/utils/cleanup.py +0 -0
  260. {iac_code-0.2.1 → iac_code-0.2.3}/src/iac_code/utils/image/format_detect.py +0 -0
  261. {iac_code-0.2.1 → iac_code-0.2.3}/src/iac_code/utils/image/pasted_content.py +0 -0
  262. {iac_code-0.2.1 → iac_code-0.2.3}/src/iac_code/utils/image/processor.py +0 -0
  263. {iac_code-0.2.1 → iac_code-0.2.3}/src/iac_code/utils/image/resizer.py +0 -0
  264. {iac_code-0.2.1 → iac_code-0.2.3}/src/iac_code/utils/image/store.py +0 -0
  265. {iac_code-0.2.1 → iac_code-0.2.3}/src/iac_code/utils/json_utils.py +0 -0
  266. {iac_code-0.2.1 → iac_code-0.2.3}/src/iac_code/utils/log.py +0 -0
  267. {iac_code-0.2.1 → iac_code-0.2.3}/src/iac_code/utils/project_paths.py +0 -0
  268. {iac_code-0.2.1 → iac_code-0.2.3}/src/iac_code/utils/tool_input_parser.py +0 -0
  269. {iac_code-0.2.1 → iac_code-0.2.3}/src/iac_code.egg-info/dependency_links.txt +0 -0
  270. {iac_code-0.2.1 → iac_code-0.2.3}/src/iac_code.egg-info/entry_points.txt +0 -0
  271. {iac_code-0.2.1 → iac_code-0.2.3}/src/iac_code.egg-info/requires.txt +0 -0
  272. {iac_code-0.2.1 → iac_code-0.2.3}/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.2.1
3
+ Version: 0.2.3
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.2.3"
2
+ __release_date__ = "2026-05-25"
@@ -31,6 +31,7 @@ from iac_code.types.stream_events import (
31
31
  )
32
32
 
33
33
  _METADATA_MAX_CHARS = 4000
34
+ _ERROR_TEXT_MAX_CHARS = 1000
34
35
  _METADATA_MAX_DEPTH = 32
35
36
  logger = logging.getLogger(__name__)
36
37
  A2APermissionResolver: TypeAlias = Callable[[PermissionRequestEvent], "bool | Awaitable[bool]"]
@@ -298,18 +299,19 @@ async def publish_stream_event(
298
299
  return None
299
300
 
300
301
  if isinstance(event, ErrorEvent):
302
+ if event.is_retryable:
303
+ text = "A temporary error occurred. Please retry."
304
+ state = TaskState.TASK_STATE_INPUT_REQUIRED
305
+ else:
306
+ raw = event.error or "Unknown error"
307
+ text = raw[:_ERROR_TEXT_MAX_CHARS]
308
+ state = TaskState.TASK_STATE_FAILED
301
309
  await _enqueue_status(
302
310
  event_queue,
303
311
  task_id=task_id,
304
312
  context_id=context_id,
305
- state=TaskState.TASK_STATE_INPUT_REQUIRED if event.is_retryable else TaskState.TASK_STATE_FAILED,
306
- message=_agent_text_message(
307
- task_id=task_id,
308
- context_id=context_id,
309
- text="A temporary error occurred. Please retry."
310
- if event.is_retryable
311
- else "An internal error occurred.",
312
- ),
313
+ state=state,
314
+ message=_agent_text_message(task_id=task_id, context_id=context_id, text=text),
313
315
  )
314
316
  return None
315
317
 
@@ -29,6 +29,16 @@ from iac_code.services.session_storage import SessionStorage
29
29
 
30
30
  logger = logging.getLogger(__name__)
31
31
  _CONTEXT_LOCK_ACQUIRE_TIMEOUT_SECONDS = 1
32
+ _ERROR_TEXT_MAX_CHARS = 1000
33
+
34
+
35
+ def _format_exception(exc: BaseException) -> str:
36
+ message = str(exc)
37
+ if not message:
38
+ return type(exc).__name__
39
+ return f"{type(exc).__name__}: {message[:_ERROR_TEXT_MAX_CHARS]}"
40
+
41
+
32
42
  A2APermissionResolver: TypeAlias = Callable[[Any], "bool | Awaitable[bool]"]
33
43
 
34
44
 
@@ -274,6 +284,17 @@ class IacCodeA2AExecutor(AgentExecutor):
274
284
  ctx.touch()
275
285
  task.touch()
276
286
  self._task_store.mirror_context(ctx)
287
+ # Force-flush telemetry between tasks. The a2a server may run in
288
+ # an ephemeral sandbox that's destroyed immediately after the
289
+ # response is delivered, before the natural batch interval or
290
+ # process-exit graceful_shutdown can run. Synchronous flush is
291
+ # offloaded to a worker thread so the event loop is not blocked.
292
+ from iac_code.services.telemetry import flush_telemetry
293
+
294
+ try:
295
+ await asyncio.to_thread(flush_telemetry)
296
+ except Exception:
297
+ logger.debug("flush_telemetry after task failed", exc_info=True)
277
298
  finally:
278
299
  lock.release()
279
300
 
@@ -338,7 +359,7 @@ class IacCodeA2AExecutor(AgentExecutor):
338
359
  if status == 401:
339
360
  return "Authentication required. Please configure your API credentials."
340
361
  logger.exception("Unhandled A2A executor error")
341
- return "An internal error occurred."
362
+ return _format_exception(exc)
342
363
 
343
364
  async def _publish_status(
344
365
  self,
@@ -351,6 +351,17 @@ class ACPSession:
351
351
  duration_ms = (time.monotonic() - prompt_start) * 1000
352
352
  if self._metrics is not None:
353
353
  self._metrics.record_prompt(duration_ms)
354
+ # Force-flush telemetry between prompts. The acp server may run in
355
+ # an ephemeral sandbox that's destroyed immediately after the
356
+ # response is delivered, before the natural batch interval or
357
+ # process-exit graceful_shutdown can run. Synchronous flush is
358
+ # offloaded to a worker thread so the event loop is not blocked.
359
+ from iac_code.services.telemetry import flush_telemetry
360
+
361
+ try:
362
+ await asyncio.to_thread(flush_telemetry)
363
+ except Exception:
364
+ logger.debug("flush_telemetry after prompt failed", exc_info=True)
354
365
 
355
366
  self.touch()
356
367
 
@@ -311,14 +311,91 @@ def acp(
311
311
  debug: bool = typer.Option(False, "--debug", "-d", help=_("Enable debug logging")),
312
312
  ) -> None:
313
313
  """Run iac-code as an ACP server."""
314
- if transport == "http":
315
- from iac_code.acp import acp_main_http
314
+ import atexit
315
+ import signal as _signal_mod
316
+ import time
317
+
318
+ from iac_code.services.telemetry import add_metric, bootstrap_telemetry, graceful_shutdown, log_event
319
+ from iac_code.services.telemetry.names import Events, Metrics
320
+
321
+ telemetry_session_id = f"acp-server-{uuid.uuid4()}"
322
+ bootstrap_telemetry(session_id=telemetry_session_id)
323
+ log_event(
324
+ Events.SESSION_STARTED,
325
+ {
326
+ "mode": "acp-server",
327
+ "transport": transport,
328
+ },
329
+ )
330
+ add_metric(Metrics.SESSION_COUNT, 1, {})
316
331
 
317
- acp_main_http(host=host, port=port, debug=debug)
318
- else:
319
- from iac_code.acp import acp_main
332
+ started = time.monotonic()
333
+ exit_reason = "normal"
334
+ _finalized = [False]
335
+
336
+ def _finalize_telemetry(reason_override: str | None = None) -> None:
337
+ if _finalized[0]:
338
+ return
339
+ _finalized[0] = True
340
+ final_reason = reason_override or exit_reason
341
+ try:
342
+ log_event(
343
+ Events.SESSION_EXITED,
344
+ {
345
+ "mode": "acp-server",
346
+ "reason": final_reason,
347
+ "duration_s": int(time.monotonic() - started),
348
+ },
349
+ )
350
+ finally:
351
+ graceful_shutdown()
352
+
353
+ atexit.register(_finalize_telemetry, "atexit")
354
+
355
+ def _telemetry_excepthook(exc_type, exc_value, traceback_obj):
356
+ try:
357
+ log_event(
358
+ Events.EXCEPTION_UNCAUGHT,
359
+ {
360
+ "error_name": exc_type.__name__,
361
+ "location": "acp",
362
+ },
363
+ )
364
+ _finalize_telemetry(f"exception:{exc_type.__name__}")
365
+ finally:
366
+ sys.__excepthook__(exc_type, exc_value, traceback_obj)
367
+
368
+ sys.excepthook = _telemetry_excepthook
369
+
370
+ _prev_sigterm = _signal_mod.getsignal(_signal_mod.SIGTERM)
371
+ _prev_sigint = _signal_mod.getsignal(_signal_mod.SIGINT)
372
+
373
+ def _telemetry_signal_handler(signum, frame):
374
+ _finalize_telemetry(f"signal:{signum}")
375
+ prev = _prev_sigterm if signum == _signal_mod.SIGTERM else _prev_sigint
376
+ if callable(prev):
377
+ prev(signum, frame) # ty: ignore[call-top-callable]
378
+ return
379
+ _signal_mod.signal(signum, _signal_mod.SIG_DFL)
380
+ os.kill(os.getpid(), signum)
381
+
382
+ _signal_mod.signal(_signal_mod.SIGTERM, _telemetry_signal_handler)
383
+ _signal_mod.signal(_signal_mod.SIGINT, _telemetry_signal_handler)
384
+
385
+ try:
386
+ if transport == "http":
387
+ from iac_code.acp import acp_main_http
320
388
 
321
- acp_main(debug=debug)
389
+ acp_main_http(host=host, port=port, debug=debug)
390
+ else:
391
+ from iac_code.acp import acp_main
392
+
393
+ acp_main(debug=debug)
394
+ except Exception:
395
+ exit_reason = "error"
396
+ raise
397
+ finally:
398
+ _finalize_telemetry()
322
399
 
323
400
 
324
401
  def _load_a2a_config(path: str) -> dict[str, Any]:
@@ -506,6 +583,86 @@ def a2a(
506
583
  err=True,
507
584
  )
508
585
  raise typer.Exit(1) from exc
586
+
587
+ import atexit
588
+ import signal as _signal_mod
589
+ import time
590
+
591
+ from iac_code.services.telemetry import add_metric, bootstrap_telemetry, graceful_shutdown, log_event
592
+ from iac_code.services.telemetry.names import Events, Metrics
593
+
594
+ telemetry_session_id = f"a2a-server-{uuid.uuid4()}"
595
+ bootstrap_telemetry(session_id=telemetry_session_id)
596
+ log_event(
597
+ Events.SESSION_STARTED,
598
+ {
599
+ "mode": "a2a-server",
600
+ "transport": transport,
601
+ },
602
+ )
603
+ add_metric(Metrics.SESSION_COUNT, 1, {})
604
+
605
+ started = time.monotonic()
606
+ exit_reason = "normal"
607
+ _finalized = [False]
608
+
609
+ def _finalize_telemetry(reason_override: str | None = None) -> None:
610
+ if _finalized[0]:
611
+ return
612
+ _finalized[0] = True
613
+ final_reason = reason_override or exit_reason
614
+ try:
615
+ log_event(
616
+ Events.SESSION_EXITED,
617
+ {
618
+ "mode": "a2a-server",
619
+ "reason": final_reason,
620
+ "duration_s": int(time.monotonic() - started),
621
+ },
622
+ )
623
+ finally:
624
+ graceful_shutdown()
625
+
626
+ # atexit fires on normal interpreter exit, including after uvicorn returns
627
+ # from a graceful shutdown — covers the path where the finally below also
628
+ # ran (idempotent via the flag).
629
+ atexit.register(_finalize_telemetry, "atexit")
630
+
631
+ def _telemetry_excepthook(exc_type, exc_value, traceback_obj):
632
+ try:
633
+ log_event(
634
+ Events.EXCEPTION_UNCAUGHT,
635
+ {
636
+ "error_name": exc_type.__name__,
637
+ "location": "a2a",
638
+ },
639
+ )
640
+ _finalize_telemetry(f"exception:{exc_type.__name__}")
641
+ finally:
642
+ sys.__excepthook__(exc_type, exc_value, traceback_obj)
643
+
644
+ sys.excepthook = _telemetry_excepthook
645
+
646
+ # Install our own SIGTERM/SIGINT handlers BEFORE uvicorn does its own. In
647
+ # the common path uvicorn replaces these and triggers graceful shutdown
648
+ # itself, after which the finally below runs. These handlers only fire if
649
+ # a signal arrives before uvicorn installs its own (or if uvicorn never
650
+ # got a chance to) — the ARMS sandbox SIGTERM-then-SIGKILL pattern.
651
+ _prev_sigterm = _signal_mod.getsignal(_signal_mod.SIGTERM)
652
+ _prev_sigint = _signal_mod.getsignal(_signal_mod.SIGINT)
653
+
654
+ def _telemetry_signal_handler(signum, frame):
655
+ _finalize_telemetry(f"signal:{signum}")
656
+ prev = _prev_sigterm if signum == _signal_mod.SIGTERM else _prev_sigint
657
+ if callable(prev):
658
+ prev(signum, frame) # ty: ignore[call-top-callable]
659
+ return
660
+ _signal_mod.signal(signum, _signal_mod.SIG_DFL)
661
+ os.kill(os.getpid(), signum)
662
+
663
+ _signal_mod.signal(_signal_mod.SIGTERM, _telemetry_signal_handler)
664
+ _signal_mod.signal(_signal_mod.SIGINT, _telemetry_signal_handler)
665
+
509
666
  try:
510
667
  if transport == "unix" and not socket_path:
511
668
  raise RuntimeError("socket-path is required in --config for --transport unix.")
@@ -547,8 +704,11 @@ def a2a(
547
704
  auto_approve_permissions=auto_approve_permissions,
548
705
  )
549
706
  except RuntimeError as exc:
707
+ exit_reason = "error"
550
708
  typer.echo(str(exc), err=True)
551
709
  raise typer.Exit(1) from exc
710
+ finally:
711
+ _finalize_telemetry()
552
712
 
553
713
 
554
714
  @a2a_client_app.command(name="call", help=_("Send a prompt to an A2A JSON-RPC endpoint."))
@@ -22,6 +22,7 @@ def create_default_registry() -> CommandRegistry:
22
22
  description=_("Show available commands"),
23
23
  handler=help_command,
24
24
  aliases=["?"],
25
+ history_mode="session",
25
26
  )
26
27
  )
27
28
  registry.register(
@@ -29,6 +30,7 @@ def create_default_registry() -> CommandRegistry:
29
30
  name="clear",
30
31
  description=_("Clear conversation history"),
31
32
  handler=clear_command,
33
+ history_mode="session",
32
34
  )
33
35
  )
34
36
  registry.register(
@@ -37,6 +39,7 @@ def create_default_registry() -> CommandRegistry:
37
39
  description=_("Show or switch model"),
38
40
  handler=model_command,
39
41
  arg_names=["model_name"],
42
+ history_mode="session",
40
43
  )
41
44
  )
42
45
  registry.register(
@@ -45,6 +48,7 @@ def create_default_registry() -> CommandRegistry:
45
48
  description=_("Show or switch thinking effort"),
46
49
  handler=effort_command,
47
50
  arg_names=["level"],
51
+ history_mode="session",
48
52
  )
49
53
  )
50
54
  registry.register(
@@ -53,6 +57,7 @@ def create_default_registry() -> CommandRegistry:
53
57
  description=_("Compact conversation context"),
54
58
  handler=compact_command,
55
59
  progress_label=_("Compacting conversation"),
60
+ history_mode="session",
56
61
  )
57
62
  )
58
63
  registry.register(
@@ -61,6 +66,7 @@ def create_default_registry() -> CommandRegistry:
61
66
  description=_("Exit the application"),
62
67
  handler=exit_command,
63
68
  aliases=["quit", "q"],
69
+ history_mode="none",
64
70
  )
65
71
  )
66
72
  registry.register(
@@ -69,6 +75,7 @@ def create_default_registry() -> CommandRegistry:
69
75
  description=_("Authenticate with LLM provider"),
70
76
  handler=auth_command,
71
77
  aliases=["login"],
78
+ history_mode="session",
72
79
  )
73
80
  )
74
81
  registry.register(
@@ -77,6 +84,7 @@ def create_default_registry() -> CommandRegistry:
77
84
  description=_("Toggle debug logging"),
78
85
  handler=debug_command,
79
86
  arg_hint="[on|off]",
87
+ history_mode="session",
80
88
  )
81
89
  )
82
90
  registry.register(
@@ -85,6 +93,7 @@ def create_default_registry() -> CommandRegistry:
85
93
  description=_("Resume a previous session"),
86
94
  handler=resume_command,
87
95
  arg_hint=_("[conversation id or search term]"),
96
+ history_mode="session",
88
97
  )
89
98
  )
90
99
  return registry
@@ -3,7 +3,7 @@
3
3
  from __future__ import annotations
4
4
 
5
5
  from dataclasses import dataclass, field
6
- from typing import TYPE_CHECKING, Any, Awaitable, Callable
6
+ from typing import TYPE_CHECKING, Any, Awaitable, Callable, Literal
7
7
 
8
8
  from iac_code.types.skill_source import SkillSource
9
9
 
@@ -42,6 +42,12 @@ class LocalCommand(Command):
42
42
  progress_label: str | None = None
43
43
  """When set, the REPL shows a spinner with this label while the handler runs.
44
44
  Use for commands that perform slow async work (e.g. an LLM call)."""
45
+ history_mode: Literal["persist", "session", "none"] = "persist"
46
+ """Controls how the command is recorded in input history.
47
+ - "persist": saved to disk (default, for normal commands).
48
+ - "session": kept in memory for the current session only.
49
+ - "none": never recorded in history.
50
+ """
45
51
 
46
52
 
47
53
  @dataclass
@@ -16,7 +16,7 @@ from typing import Any
16
16
  import yaml
17
17
 
18
18
  # Default LLM model used when no model is saved in settings
19
- DEFAULT_MODEL = "qwen3.6-plus"
19
+ DEFAULT_MODEL = "qwen3.7-max"
20
20
 
21
21
  # Configuration directory
22
22
  _CONFIG_DIR_NAME = ".iac-code"