alloy-runtime-cli 0.1.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (451) hide show
  1. alloy_runtime_cli-0.1.0.dist-info/METADATA +61 -0
  2. alloy_runtime_cli-0.1.0.dist-info/RECORD +451 -0
  3. alloy_runtime_cli-0.1.0.dist-info/WHEEL +5 -0
  4. alloy_runtime_cli-0.1.0.dist-info/entry_points.txt +2 -0
  5. alloy_runtime_cli-0.1.0.dist-info/top_level.txt +1 -0
  6. cli/__init__.py +0 -0
  7. cli/commands/__init__.py +0 -0
  8. cli/commands/admin/__init__.py +0 -0
  9. cli/commands/admin/bootstrap_command.py +118 -0
  10. cli/commands/admin/credentials/__init__.py +0 -0
  11. cli/commands/admin/credentials/create/__init__.py +0 -0
  12. cli/commands/admin/credentials/create/command.py +148 -0
  13. cli/commands/admin/credentials/create/presenter.py +16 -0
  14. cli/commands/admin/credentials/grant/__init__.py +0 -0
  15. cli/commands/admin/credentials/grant/command.py +119 -0
  16. cli/commands/admin/credentials/grant/fields.py +33 -0
  17. cli/commands/admin/credentials/grant/presenter.py +23 -0
  18. cli/commands/agents/__init__.py +0 -0
  19. cli/commands/agents/create/__init__.py +0 -0
  20. cli/commands/agents/create/command.py +475 -0
  21. cli/commands/agents/create/fields.py +64 -0
  22. cli/commands/agents/create/presenter.py +68 -0
  23. cli/commands/agents/delete/__init__.py +0 -0
  24. cli/commands/agents/delete/command.py +47 -0
  25. cli/commands/agents/delete/presenter.py +16 -0
  26. cli/commands/agents/get/command.py +37 -0
  27. cli/commands/agents/get/presenter.py +32 -0
  28. cli/commands/agents/list/__init__.py +1 -0
  29. cli/commands/agents/list/command.py +54 -0
  30. cli/commands/agents/list/presenter.py +82 -0
  31. cli/commands/agents/update/__init__.py +0 -0
  32. cli/commands/agents/update/command.py +435 -0
  33. cli/commands/agents/update/fields.py +40 -0
  34. cli/commands/agents/update/presenter.py +68 -0
  35. cli/commands/audio/__init__.py +0 -0
  36. cli/commands/audio/transcribe/__init__.py +0 -0
  37. cli/commands/audio/transcribe/command.py +144 -0
  38. cli/commands/audio/transcribe/presenter.py +15 -0
  39. cli/commands/auth/__init__.py +0 -0
  40. cli/commands/auth/login/__init__.py +0 -0
  41. cli/commands/auth/login/command.py +80 -0
  42. cli/commands/auth/signup/__init__.py +0 -0
  43. cli/commands/auth/signup/command.py +115 -0
  44. cli/commands/billing/__init__.py +1 -0
  45. cli/commands/billing/costs/__init__.py +1 -0
  46. cli/commands/billing/costs/by_agent/__init__.py +1 -0
  47. cli/commands/billing/costs/by_agent/command.py +57 -0
  48. cli/commands/billing/costs/by_agent/presenter.py +81 -0
  49. cli/commands/billing/costs/by_model/__init__.py +1 -0
  50. cli/commands/billing/costs/by_model/command.py +57 -0
  51. cli/commands/billing/costs/by_model/presenter.py +80 -0
  52. cli/commands/billing/costs/daily/__init__.py +1 -0
  53. cli/commands/billing/costs/daily/command.py +55 -0
  54. cli/commands/billing/costs/daily/presenter.py +75 -0
  55. cli/commands/billing/costs/summary/__init__.py +1 -0
  56. cli/commands/billing/costs/summary/command.py +57 -0
  57. cli/commands/billing/costs/summary/presenter.py +42 -0
  58. cli/commands/billing/projects/__init__.py +1 -0
  59. cli/commands/billing/projects/create/__init__.py +1 -0
  60. cli/commands/billing/projects/create/command.py +60 -0
  61. cli/commands/billing/projects/create/presenter.py +26 -0
  62. cli/commands/billing/projects/get/__init__.py +1 -0
  63. cli/commands/billing/projects/get/command.py +33 -0
  64. cli/commands/billing/projects/get/presenter.py +32 -0
  65. cli/commands/billing/projects/list/__init__.py +1 -0
  66. cli/commands/billing/projects/list/command.py +40 -0
  67. cli/commands/billing/projects/list/presenter.py +57 -0
  68. cli/commands/content/__init__.py +1 -0
  69. cli/commands/content/delete/__init__.py +0 -0
  70. cli/commands/content/delete/command.py +49 -0
  71. cli/commands/content/delete/presenter.py +18 -0
  72. cli/commands/content/edit/__init__.py +1 -0
  73. cli/commands/content/edit/command.py +155 -0
  74. cli/commands/content/edit/editor.py +150 -0
  75. cli/commands/content/edit/presenter.py +146 -0
  76. cli/commands/content/get/__init__.py +1 -0
  77. cli/commands/content/get/command.py +39 -0
  78. cli/commands/content/get/presenter.py +176 -0
  79. cli/commands/content/list/__init__.py +1 -0
  80. cli/commands/content/list/command.py +347 -0
  81. cli/commands/content/list/export_formatters.py +409 -0
  82. cli/commands/content/list/export_handler.py +165 -0
  83. cli/commands/content/list/presenter.py +190 -0
  84. cli/commands/credentials/__init__.py +0 -0
  85. cli/commands/credentials/create/__init__.py +0 -0
  86. cli/commands/credentials/create/command.py +165 -0
  87. cli/commands/credentials/create/fields.py +38 -0
  88. cli/commands/credentials/create/presenter.py +20 -0
  89. cli/commands/credentials/update/__init__.py +0 -0
  90. cli/commands/credentials/update/command.py +53 -0
  91. cli/commands/credentials/update/fields.py +71 -0
  92. cli/commands/credentials/update/presenter.py +16 -0
  93. cli/commands/flag_utils.py +366 -0
  94. cli/commands/generate/__init__.py +0 -0
  95. cli/commands/generate/cancel/__init__.py +1 -0
  96. cli/commands/generate/cancel/command.py +44 -0
  97. cli/commands/generate/cancel/presenter.py +26 -0
  98. cli/commands/generate/status/__init__.py +1 -0
  99. cli/commands/generate/status/command.py +58 -0
  100. cli/commands/generate/status/presenter.py +78 -0
  101. cli/commands/generate/text/__init__.py +0 -0
  102. cli/commands/generate/text/command.py +1325 -0
  103. cli/commands/generate/text/concurrent_renderer.py +355 -0
  104. cli/commands/generate/text/presenter.py +287 -0
  105. cli/commands/generate/text/stream_renderer.py +129 -0
  106. cli/commands/knowledge/__init__.py +0 -0
  107. cli/commands/knowledge/collections/__init__.py +0 -0
  108. cli/commands/knowledge/collections/cluster/__init__.py +0 -0
  109. cli/commands/knowledge/collections/cluster/command.py +64 -0
  110. cli/commands/knowledge/collections/cluster/presenter.py +74 -0
  111. cli/commands/knowledge/collections/cluster_status/__init__.py +0 -0
  112. cli/commands/knowledge/collections/cluster_status/command.py +46 -0
  113. cli/commands/knowledge/collections/cluster_status/presenter.py +10 -0
  114. cli/commands/knowledge/collections/create/__init__.py +0 -0
  115. cli/commands/knowledge/collections/create/command.py +137 -0
  116. cli/commands/knowledge/collections/create/presenter.py +38 -0
  117. cli/commands/knowledge/collections/delete/__init__.py +1 -0
  118. cli/commands/knowledge/collections/delete/command.py +47 -0
  119. cli/commands/knowledge/collections/delete/presenter.py +20 -0
  120. cli/commands/knowledge/collections/get/__init__.py +1 -0
  121. cli/commands/knowledge/collections/get/command.py +30 -0
  122. cli/commands/knowledge/collections/get/presenter.py +44 -0
  123. cli/commands/knowledge/collections/list/__init__.py +1 -0
  124. cli/commands/knowledge/collections/list/command.py +41 -0
  125. cli/commands/knowledge/collections/list/presenter.py +68 -0
  126. cli/commands/knowledge/collections/update/__init__.py +0 -0
  127. cli/commands/knowledge/collections/update/command.py +97 -0
  128. cli/commands/knowledge/collections/update/presenter.py +42 -0
  129. cli/commands/knowledge/documents/__init__.py +0 -0
  130. cli/commands/knowledge/documents/bulk_metadata/__init__.py +0 -0
  131. cli/commands/knowledge/documents/bulk_metadata/command.py +119 -0
  132. cli/commands/knowledge/documents/bulk_metadata/presenter.py +36 -0
  133. cli/commands/knowledge/documents/delete/__init__.py +0 -0
  134. cli/commands/knowledge/documents/delete/command.py +47 -0
  135. cli/commands/knowledge/documents/delete/presenter.py +20 -0
  136. cli/commands/knowledge/documents/get/__init__.py +0 -0
  137. cli/commands/knowledge/documents/get/command.py +39 -0
  138. cli/commands/knowledge/documents/get/presenter.py +78 -0
  139. cli/commands/knowledge/documents/ingest/__init__.py +0 -0
  140. cli/commands/knowledge/documents/ingest/command.py +222 -0
  141. cli/commands/knowledge/documents/ingest/presenter.py +41 -0
  142. cli/commands/knowledge/documents/list/__init__.py +0 -0
  143. cli/commands/knowledge/documents/list/command.py +69 -0
  144. cli/commands/knowledge/documents/list/presenter.py +86 -0
  145. cli/commands/knowledge/documents/reingest/__init__.py +0 -0
  146. cli/commands/knowledge/documents/reingest/command.py +102 -0
  147. cli/commands/knowledge/documents/reingest/presenter.py +70 -0
  148. cli/commands/knowledge/documents/update/__init__.py +0 -0
  149. cli/commands/knowledge/documents/update/command.py +85 -0
  150. cli/commands/knowledge/documents/update/presenter.py +37 -0
  151. cli/commands/knowledge/recover/__init__.py +0 -0
  152. cli/commands/knowledge/recover/command.py +46 -0
  153. cli/commands/knowledge/recover/presenter.py +79 -0
  154. cli/commands/knowledge/search/__init__.py +0 -0
  155. cli/commands/knowledge/search/command.py +218 -0
  156. cli/commands/knowledge/search/presenter.py +111 -0
  157. cli/commands/knowledge/synthesis/__init__.py +0 -0
  158. cli/commands/knowledge/synthesis/create/__init__.py +0 -0
  159. cli/commands/knowledge/synthesis/create/command.py +127 -0
  160. cli/commands/knowledge/synthesis/create/presenter.py +33 -0
  161. cli/commands/knowledge/synthesis/delete/__init__.py +0 -0
  162. cli/commands/knowledge/synthesis/delete/command.py +53 -0
  163. cli/commands/knowledge/synthesis/delete/presenter.py +31 -0
  164. cli/commands/knowledge/synthesis/get/__init__.py +0 -0
  165. cli/commands/knowledge/synthesis/get/command.py +55 -0
  166. cli/commands/knowledge/synthesis/get/presenter.py +114 -0
  167. cli/commands/knowledge/synthesis/list/__init__.py +0 -0
  168. cli/commands/knowledge/synthesis/list/command.py +132 -0
  169. cli/commands/knowledge/synthesis/list/presenter.py +84 -0
  170. cli/commands/knowledge/synthesis/refresh/__init__.py +0 -0
  171. cli/commands/knowledge/synthesis/refresh/command.py +42 -0
  172. cli/commands/knowledge/synthesis/refresh/presenter.py +33 -0
  173. cli/commands/knowledge/synthesis/update/__init__.py +0 -0
  174. cli/commands/knowledge/synthesis/update/command.py +76 -0
  175. cli/commands/knowledge/synthesis/update/presenter.py +41 -0
  176. cli/commands/models/__init__.py +0 -0
  177. cli/commands/models/list/__init__.py +0 -0
  178. cli/commands/models/list/command.py +84 -0
  179. cli/commands/models/list/presenter.py +114 -0
  180. cli/commands/organizations/__init__.py +0 -0
  181. cli/commands/organizations/create/command.py +32 -0
  182. cli/commands/organizations/create/presenter.py +9 -0
  183. cli/commands/pipelines/__init__.py +1 -0
  184. cli/commands/pipelines/approvals/__init__.py +1 -0
  185. cli/commands/pipelines/approvals/decide_command.py +77 -0
  186. cli/commands/pipelines/approvals/get_command.py +44 -0
  187. cli/commands/pipelines/approvals/presenter.py +56 -0
  188. cli/commands/pipelines/costs/__init__.py +1 -0
  189. cli/commands/pipelines/costs/command.py +57 -0
  190. cli/commands/pipelines/costs/daily_command.py +54 -0
  191. cli/commands/pipelines/costs/daily_presenter.py +59 -0
  192. cli/commands/pipelines/costs/presenter.py +37 -0
  193. cli/commands/pipelines/create/__init__.py +1 -0
  194. cli/commands/pipelines/create/command.py +103 -0
  195. cli/commands/pipelines/create/presenter.py +22 -0
  196. cli/commands/pipelines/env_vars/__init__.py +1 -0
  197. cli/commands/pipelines/env_vars/command.py +51 -0
  198. cli/commands/pipelines/env_vars/presenter.py +16 -0
  199. cli/commands/pipelines/execute/__init__.py +1 -0
  200. cli/commands/pipelines/execute/command.py +142 -0
  201. cli/commands/pipelines/execute/presenter.py +47 -0
  202. cli/commands/pipelines/executions/__init__.py +1 -0
  203. cli/commands/pipelines/executions/costs/__init__.py +1 -0
  204. cli/commands/pipelines/executions/costs/command.py +48 -0
  205. cli/commands/pipelines/executions/costs/presenter.py +29 -0
  206. cli/commands/pipelines/executions/costs_by_model/__init__.py +1 -0
  207. cli/commands/pipelines/executions/costs_by_model/command.py +50 -0
  208. cli/commands/pipelines/executions/costs_by_model/presenter.py +78 -0
  209. cli/commands/pipelines/executions/costs_by_step/__init__.py +1 -0
  210. cli/commands/pipelines/executions/costs_by_step/command.py +50 -0
  211. cli/commands/pipelines/executions/costs_by_step/presenter.py +72 -0
  212. cli/commands/pipelines/executions/get_command.py +38 -0
  213. cli/commands/pipelines/executions/list_command.py +123 -0
  214. cli/commands/pipelines/executions/presenter.py +131 -0
  215. cli/commands/pipelines/executions/rerun_command.py +41 -0
  216. cli/commands/pipelines/executions/update/__init__.py +1 -0
  217. cli/commands/pipelines/executions/update/command.py +110 -0
  218. cli/commands/pipelines/executions/update/presenter.py +28 -0
  219. cli/commands/pipelines/get/__init__.py +1 -0
  220. cli/commands/pipelines/get/command.py +33 -0
  221. cli/commands/pipelines/get/presenter.py +48 -0
  222. cli/commands/pipelines/list/__init__.py +1 -0
  223. cli/commands/pipelines/list/command.py +53 -0
  224. cli/commands/pipelines/list/presenter.py +66 -0
  225. cli/commands/pipelines/schedules/__init__.py +1 -0
  226. cli/commands/pipelines/schedules/create_command.py +119 -0
  227. cli/commands/pipelines/schedules/create_presenter.py +35 -0
  228. cli/commands/pipelines/schedules/delete_command.py +52 -0
  229. cli/commands/pipelines/schedules/env_vars_command.py +59 -0
  230. cli/commands/pipelines/schedules/env_vars_presenter.py +16 -0
  231. cli/commands/pipelines/schedules/get_command.py +38 -0
  232. cli/commands/pipelines/schedules/list_command.py +33 -0
  233. cli/commands/pipelines/schedules/once_command.py +90 -0
  234. cli/commands/pipelines/schedules/once_presenter.py +30 -0
  235. cli/commands/pipelines/schedules/presenter.py +104 -0
  236. cli/commands/pipelines/schedules/update_command.py +139 -0
  237. cli/commands/pipelines/schedules/update_presenter.py +29 -0
  238. cli/commands/render/__init__.py +0 -0
  239. cli/commands/render/html_to_image/__init__.py +0 -0
  240. cli/commands/render/html_to_image/command.py +170 -0
  241. cli/commands/schemas/__init__.py +0 -0
  242. cli/commands/schemas/create/__init__.py +0 -0
  243. cli/commands/schemas/create/command.py +122 -0
  244. cli/commands/schemas/create/presenter.py +53 -0
  245. cli/commands/schemas/delete/command.py +45 -0
  246. cli/commands/schemas/delete/presenter.py +9 -0
  247. cli/commands/schemas/get/__init__.py +0 -0
  248. cli/commands/schemas/get/command.py +56 -0
  249. cli/commands/schemas/get/presenter.py +129 -0
  250. cli/commands/schemas/list/__init__.py +0 -0
  251. cli/commands/schemas/list/command.py +64 -0
  252. cli/commands/schemas/list/presenter.py +133 -0
  253. cli/commands/schemas/update/__init__.py +0 -0
  254. cli/commands/schemas/update/command.py +369 -0
  255. cli/commands/schemas/update/presenter.py +53 -0
  256. cli/commands/sessions/__init__.py +1 -0
  257. cli/commands/sessions/delete/__init__.py +1 -0
  258. cli/commands/sessions/delete/command.py +47 -0
  259. cli/commands/sessions/delete/presenter.py +10 -0
  260. cli/commands/sessions/get/__init__.py +1 -0
  261. cli/commands/sessions/get/command.py +42 -0
  262. cli/commands/sessions/get/presenter.py +59 -0
  263. cli/commands/sessions/list/__init__.py +1 -0
  264. cli/commands/sessions/list/command.py +61 -0
  265. cli/commands/sessions/list/presenter.py +68 -0
  266. cli/commands/sessions/messages/__init__.py +1 -0
  267. cli/commands/sessions/messages/command.py +78 -0
  268. cli/commands/sessions/messages/presenter.py +79 -0
  269. cli/commands/shared_flags.py +500 -0
  270. cli/commands/sync/__init__.py +0 -0
  271. cli/commands/sync/command.py +45 -0
  272. cli/commands/sync/presenter.py +49 -0
  273. cli/commands/tags/__init__.py +1 -0
  274. cli/commands/tags/create/__init__.py +1 -0
  275. cli/commands/tags/create/command.py +60 -0
  276. cli/commands/tags/delete/__init__.py +1 -0
  277. cli/commands/tags/delete/command.py +47 -0
  278. cli/commands/tags/delete/presenter.py +10 -0
  279. cli/commands/tags/get/command.py +31 -0
  280. cli/commands/tags/get/presenter.py +23 -0
  281. cli/commands/tags/list/__init__.py +1 -0
  282. cli/commands/tags/list/command.py +52 -0
  283. cli/commands/tags/list/presenter.py +49 -0
  284. cli/commands/tags/update/command.py +64 -0
  285. cli/commands/tags/update/presenter.py +9 -0
  286. cli/commands/templates/__init__.py +0 -0
  287. cli/commands/templates/create/__init__.py +0 -0
  288. cli/commands/templates/create/command.py +152 -0
  289. cli/commands/templates/create/presenter.py +86 -0
  290. cli/commands/templates/delete/__init__.py +0 -0
  291. cli/commands/templates/delete/command.py +47 -0
  292. cli/commands/templates/delete/presenter.py +16 -0
  293. cli/commands/templates/get/__init__.py +0 -0
  294. cli/commands/templates/get/command.py +52 -0
  295. cli/commands/templates/get/presenter.py +233 -0
  296. cli/commands/templates/get_by_version/command.py +32 -0
  297. cli/commands/templates/get_by_version/presenter.py +30 -0
  298. cli/commands/templates/list/__init__.py +1 -0
  299. cli/commands/templates/list/command.py +102 -0
  300. cli/commands/templates/list/presenter.py +93 -0
  301. cli/commands/templates/render/__init__.py +0 -0
  302. cli/commands/templates/render/command.py +115 -0
  303. cli/commands/templates/render/presenter.py +276 -0
  304. cli/commands/templates/update/__init__.py +0 -0
  305. cli/commands/templates/update/command.py +199 -0
  306. cli/commands/templates/update/presenter.py +94 -0
  307. cli/commands/templates/version/__init__.py +1 -0
  308. cli/commands/templates/version/command.py +116 -0
  309. cli/commands/templates/version/presenter.py +100 -0
  310. cli/commands/tool_configs/__init__.py +0 -0
  311. cli/commands/tool_configs/create/__init__.py +0 -0
  312. cli/commands/tool_configs/create/command.py +118 -0
  313. cli/commands/tool_configs/create/presenter.py +53 -0
  314. cli/commands/tool_configs/delete/__init__.py +0 -0
  315. cli/commands/tool_configs/delete/command.py +47 -0
  316. cli/commands/tool_configs/delete/presenter.py +18 -0
  317. cli/commands/tool_configs/get/__init__.py +0 -0
  318. cli/commands/tool_configs/get/command.py +31 -0
  319. cli/commands/tool_configs/get/presenter.py +62 -0
  320. cli/commands/tool_configs/list/__init__.py +0 -0
  321. cli/commands/tool_configs/list/command.py +59 -0
  322. cli/commands/tool_configs/list/presenter.py +60 -0
  323. cli/commands/tool_configs/update/__init__.py +0 -0
  324. cli/commands/tool_configs/update/command.py +128 -0
  325. cli/commands/tool_configs/update/presenter.py +53 -0
  326. cli/commands/tools/__init__.py +1 -0
  327. cli/commands/tools/get/__init__.py +1 -0
  328. cli/commands/tools/get/command.py +42 -0
  329. cli/commands/tools/get/presenter.py +45 -0
  330. cli/commands/tools/list/__init__.py +1 -0
  331. cli/commands/tools/list/command.py +56 -0
  332. cli/commands/tools/list/presenter.py +44 -0
  333. cli/commands/users/__init__.py +0 -0
  334. cli/commands/users/create/command.py +53 -0
  335. cli/commands/users/create/presenter.py +9 -0
  336. cli/commands/whoami/__init__.py +0 -0
  337. cli/commands/whoami/command.py +42 -0
  338. cli/infrastructure/__init__.py +0 -0
  339. cli/infrastructure/auth_storage.py +71 -0
  340. cli/infrastructure/client_factory.py +36 -0
  341. cli/infrastructure/command.py +75 -0
  342. cli/infrastructure/config.py +188 -0
  343. cli/infrastructure/console.py +27 -0
  344. cli/infrastructure/editor.py +138 -0
  345. cli/infrastructure/error_display.py +178 -0
  346. cli/infrastructure/field_extractor.py +360 -0
  347. cli/infrastructure/file_content.py +210 -0
  348. cli/infrastructure/filter_parser.py +256 -0
  349. cli/infrastructure/formatters/__init__.py +0 -0
  350. cli/infrastructure/formatters/base.py +99 -0
  351. cli/infrastructure/formatters/compact_formatter.py +245 -0
  352. cli/infrastructure/formatters/json_formatter.py +84 -0
  353. cli/infrastructure/formatters/lines_formatter.py +102 -0
  354. cli/infrastructure/formatting/__init__.py +0 -0
  355. cli/infrastructure/formatting/fields.py +193 -0
  356. cli/infrastructure/forms/__init__.py +0 -0
  357. cli/infrastructure/forms/agent_picker.py +123 -0
  358. cli/infrastructure/forms/agent_tool_editor.py +384 -0
  359. cli/infrastructure/forms/agent_tools_manager.py +212 -0
  360. cli/infrastructure/forms/base_picker.py +469 -0
  361. cli/infrastructure/forms/components.py +126 -0
  362. cli/infrastructure/forms/json_schema_builder.py +149 -0
  363. cli/infrastructure/forms/model_picker.py +134 -0
  364. cli/infrastructure/forms/parsers.py +173 -0
  365. cli/infrastructure/forms/resolution_modal.py +302 -0
  366. cli/infrastructure/forms/schema_picker.py +137 -0
  367. cli/infrastructure/forms/tag_management_modal.py +103 -0
  368. cli/infrastructure/forms/tag_picker.py +207 -0
  369. cli/infrastructure/forms/template_picker.py +131 -0
  370. cli/infrastructure/forms/tool_config_picker.py +130 -0
  371. cli/infrastructure/forms/tool_picker.py +103 -0
  372. cli/infrastructure/injection/__init__.py +0 -0
  373. cli/infrastructure/injection/parser.py +302 -0
  374. cli/infrastructure/injection/resolver.py +399 -0
  375. cli/infrastructure/kv_parser.py +130 -0
  376. cli/infrastructure/local_storage.py +227 -0
  377. cli/infrastructure/macro_parser.py +215 -0
  378. cli/infrastructure/output.py +192 -0
  379. cli/infrastructure/provider_setup.py +81 -0
  380. cli/infrastructure/renderers/__init__.py +0 -0
  381. cli/infrastructure/renderers/entity_renderer.py +77 -0
  382. cli/infrastructure/renderers/list_renderer.py +114 -0
  383. cli/infrastructure/scope_utils.py +47 -0
  384. cli/infrastructure/spinner.py +101 -0
  385. cli/infrastructure/tui/__init__.py +0 -0
  386. cli/infrastructure/tui/clipboard.py +41 -0
  387. cli/infrastructure/tui/formatters.py +105 -0
  388. cli/infrastructure/tui/preview.py +14 -0
  389. cli/infrastructure/tui/selectable.py +198 -0
  390. cli/infrastructure/validation/__init__.py +0 -0
  391. cli/infrastructure/validation/tag_validation.py +74 -0
  392. cli/main.py +759 -0
  393. cli/tui/__init__.py +0 -0
  394. cli/tui/app.py +199 -0
  395. cli/tui/app_store.py +73 -0
  396. cli/tui/chat/__init__.py +0 -0
  397. cli/tui/chat/commands/__init__.py +0 -0
  398. cli/tui/chat/commands/base.py +65 -0
  399. cli/tui/chat/commands/create_session.py +135 -0
  400. cli/tui/chat/commands/load_session.py +119 -0
  401. cli/tui/chat/commands/regenerate.py +120 -0
  402. cli/tui/chat/commands/reload_session.py +63 -0
  403. cli/tui/chat/commands/send_message.py +190 -0
  404. cli/tui/chat/commands/undo.py +66 -0
  405. cli/tui/chat/editor.py +71 -0
  406. cli/tui/chat/messages.py +223 -0
  407. cli/tui/chat/pane.py +141 -0
  408. cli/tui/chat/renderers/__init__.py +0 -0
  409. cli/tui/chat/renderers/base.py +72 -0
  410. cli/tui/chat/renderers/markdown.py +250 -0
  411. cli/tui/chat/renderers/plain.py +83 -0
  412. cli/tui/chat/screen.py +1155 -0
  413. cli/tui/chat/services/__init__.py +0 -0
  414. cli/tui/chat/services/injection.py +386 -0
  415. cli/tui/chat/services/name_generator.py +256 -0
  416. cli/tui/chat/slash_commands.py +424 -0
  417. cli/tui/chat/store.py +280 -0
  418. cli/tui/chat/types.py +220 -0
  419. cli/tui/chat/widgets/__init__.py +0 -0
  420. cli/tui/chat/widgets/chat_header.py +75 -0
  421. cli/tui/chat/widgets/chat_input.py +362 -0
  422. cli/tui/chat/widgets/injection_popup.py +161 -0
  423. cli/tui/chat/widgets/message_display.py +287 -0
  424. cli/tui/chat/widgets/session_sidebar.py +214 -0
  425. cli/tui/chat/widgets/welcome_screen.py +290 -0
  426. cli/tui/screens/__init__.py +0 -0
  427. cli/tui/screens/agents.py +344 -0
  428. cli/tui/screens/base.py +301 -0
  429. cli/tui/screens/content.py +508 -0
  430. cli/tui/screens/dashboard.py +89 -0
  431. cli/tui/screens/models.py +96 -0
  432. cli/tui/screens/nav_screen.py +186 -0
  433. cli/tui/screens/schemas.py +522 -0
  434. cli/tui/screens/templates.py +734 -0
  435. cli/tui/screens/tool_configs.py +335 -0
  436. cli/tui/styles/__init__.py +0 -0
  437. cli/tui/widgets/__init__.py +0 -0
  438. cli/tui/widgets/agent_create_modal.py +139 -0
  439. cli/tui/widgets/agent_form_modal.py +659 -0
  440. cli/tui/widgets/agent_update_modal.py +299 -0
  441. cli/tui/widgets/base_form_modal.py +77 -0
  442. cli/tui/widgets/confirm_modal.py +75 -0
  443. cli/tui/widgets/help_modal.py +145 -0
  444. cli/tui/widgets/new_session_modal.py +328 -0
  445. cli/tui/widgets/schema_create_modal.py +271 -0
  446. cli/tui/widgets/schema_update_modal.py +188 -0
  447. cli/tui/widgets/status_footer.py +147 -0
  448. cli/tui/widgets/template_create_modal.py +502 -0
  449. cli/tui/widgets/template_update_modal.py +308 -0
  450. cli/tui/widgets/tool_config_create_modal.py +216 -0
  451. cli/tui/widgets/tool_config_update_modal.py +208 -0
cli/tui/__init__.py ADDED
File without changes
cli/tui/app.py ADDED
@@ -0,0 +1,199 @@
1
+ """Unified Alloy Runtime Terminal Application.
2
+
3
+ This module provides the main Textual application that serves as the unified TUI
4
+ for Alloy Runtime. It uses a screen-based architecture where each main view
5
+ (Chat, Agents, Templates, Content, Schemas) is a proper Textual Screen.
6
+
7
+ The app uses:
8
+ - Screen stack for navigation between main views
9
+ - AppStore for shared state following Textual's "App as Store" pattern
10
+ - Priority bindings for global navigation that work regardless of focus
11
+ """
12
+
13
+ from typing import Literal
14
+
15
+ from textual.app import App
16
+
17
+ from cli.tui.app_store import AppStore
18
+ from cli.tui.chat.screen import ChatScreen
19
+ from cli.tui.screens.agents import AgentsScreen
20
+ from cli.tui.screens.content import ContentScreen
21
+ from cli.tui.screens.dashboard import DashboardScreen
22
+ from cli.tui.screens.schemas import SchemasScreen
23
+ from cli.tui.screens.templates import TemplatesScreen
24
+ from cli.tui.screens.tool_configs import ToolConfigsScreen
25
+ from cli.tui.widgets.status_footer import StatusFooter
26
+ from alloy_runtime_sdk.logging.config import get_logger
27
+
28
+ logger = get_logger(__name__)
29
+
30
+ SeverityLevel = Literal["information", "warning", "error"]
31
+
32
+
33
+ class AlloyRuntimeApp(App[None]):
34
+ """Unified Alloy Runtime Terminal Application.
35
+
36
+ A full-featured TUI that provides:
37
+ - Screen-based navigation between major sections
38
+ - Consistent keyboard shortcuts across all views (c/a/t/s/m for switching)
39
+ - Integrated chat, browse, and create workflows
40
+ - Simple shared store accessible via self.app.store
41
+
42
+ Navigation:
43
+ - c: Chat screen
44
+ - a: Agents screen
45
+ - t: Templates screen
46
+ - m: Content (media) screen
47
+ - s: Schemas screen
48
+ - d: Dashboard overlay
49
+ - ?: Help modal
50
+
51
+ All screens inherit from NavScreen which provides these navigation bindings
52
+ as priority bindings, ensuring they work regardless of focus state.
53
+ """
54
+
55
+ CSS_PATH = [
56
+ "styles/app.tcss",
57
+ "styles/browser.tcss",
58
+ "styles/chat.tcss",
59
+ "styles/modals.tcss",
60
+ "styles/forms.tcss",
61
+ "styles/dashboard.tcss",
62
+ ]
63
+
64
+ # No bindings at app level - all bindings are on screens
65
+ # This avoids conflicts and ensures proper screen isolation
66
+ BINDINGS = []
67
+
68
+ # Register screens with the app
69
+ SCREENS = {
70
+ "chat": ChatScreen,
71
+ "agents": AgentsScreen,
72
+ "templates": TemplatesScreen,
73
+ "content": ContentScreen,
74
+ "schemas": SchemasScreen,
75
+ "tool_configs": ToolConfigsScreen,
76
+ }
77
+
78
+ theme: str = "tokyo-night" # type: ignore[assignment]
79
+
80
+ def __init__(self, api_url: str, api_key: str):
81
+ """Initialize the Alloy Runtime app.
82
+
83
+ Args:
84
+ api_url: Base API URL for the server
85
+ api_key: API key for authentication
86
+ """
87
+ super().__init__()
88
+ # Create the simple store - screens access via self.app.store
89
+ self.store = AppStore(api_url=api_url, api_key=api_key)
90
+ # Track current screen for navigation
91
+ self._current_screen_id: str = "chat"
92
+ logger.info("tui_app_initialized", api_url=api_url)
93
+
94
+ def on_mount(self) -> None:
95
+ """Set up initial state on startup."""
96
+ logger.info("tui_app_mounted")
97
+ # Push the dashboard screen first, then the chat screen
98
+ # Dashboard will be shown as an overlay
99
+ self.push_screen("chat")
100
+ self.push_screen(DashboardScreen(), self._on_dashboard_dismiss)
101
+
102
+ def _on_dashboard_dismiss(self, screen_id: str | None) -> None:
103
+ """Handle dashboard dismissal by switching to the selected screen.
104
+
105
+ Args:
106
+ screen_id: The screen ID to navigate to (e.g., "chat", "agents"), or None if dismissed without selection
107
+ """
108
+ if screen_id is None:
109
+ return
110
+
111
+ # Extract just the screen name from tab-* format if needed
112
+ if screen_id.startswith("tab-"):
113
+ screen_id = screen_id[4:] # Remove "tab-" prefix
114
+
115
+ logger.info("dashboard_dismissed", target_screen=screen_id)
116
+ self.switch_to_screen(screen_id)
117
+
118
+ def switch_to_screen(self, screen_id: str) -> None:
119
+ """Switch to a different screen.
120
+
121
+ This method handles screen switching by:
122
+ 1. Popping the current screen
123
+ 2. Pushing the new screen
124
+
125
+ Args:
126
+ screen_id: The ID of the screen to switch to (chat, agents, templates, content, schemas)
127
+ """
128
+ if screen_id == self._current_screen_id:
129
+ return # Already on this screen
130
+
131
+ if screen_id not in self.SCREENS:
132
+ logger.warning("unknown_screen_id", screen_id=screen_id)
133
+ return
134
+
135
+ logger.info(
136
+ "switching_screen", from_screen=self._current_screen_id, to_screen=screen_id
137
+ )
138
+
139
+ # Use switch_screen for clean transitions
140
+ self._current_screen_id = screen_id
141
+ self.switch_screen(screen_id) # pyright: ignore[reportUnknownMemberType]
142
+
143
+ def notify(
144
+ self,
145
+ message: str,
146
+ *,
147
+ title: str = "",
148
+ severity: SeverityLevel = "information",
149
+ timeout: float | None = None,
150
+ markup: bool = True,
151
+ ) -> None:
152
+ """Show a notification in the status footer instead of a toast.
153
+
154
+ This overrides the default App.notify() to route notifications
155
+ to our vim-style StatusFooter widget if available.
156
+
157
+ Args:
158
+ message: The notification message
159
+ title: Optional title (ignored for status bar)
160
+ severity: One of "information", "warning", "error"
161
+ timeout: Seconds before clearing (default varies by severity)
162
+ markup: Whether message contains markup (ignored for status bar)
163
+ """
164
+ # Errors get longer display time (6s) so users can read them
165
+ if timeout is not None:
166
+ effective_timeout = timeout
167
+ elif severity == "error":
168
+ effective_timeout = 6.0
169
+ else:
170
+ effective_timeout = 2.0
171
+ try:
172
+ footer = self.screen.query_one(StatusFooter)
173
+ footer.show_notification(
174
+ message, severity=severity, timeout=effective_timeout
175
+ )
176
+ except Exception:
177
+ # Fall back to parent if footer not found
178
+ super().notify(
179
+ message, title=title, severity=severity, timeout=timeout, markup=markup
180
+ )
181
+
182
+ async def on_unmount(self) -> None:
183
+ """Clean up on app exit."""
184
+ logger.info("tui_app_shutting_down")
185
+ await self.store.close()
186
+ logger.info("tui_app_shutdown_complete")
187
+
188
+
189
+ def run_app(api_url: str, api_key: str) -> None:
190
+ """Run the Alloy Runtime Terminal app.
191
+
192
+ Args:
193
+ api_url: Base API URL for the server
194
+ api_key: API key for authentication
195
+ """
196
+ logger.info("tui_app_starting", api_url=api_url)
197
+ app = AlloyRuntimeApp(api_url=api_url, api_key=api_key)
198
+ app.run()
199
+ logger.info("tui_app_exited")
cli/tui/app_store.py ADDED
@@ -0,0 +1,73 @@
1
+ """Simple application store for shared state.
2
+
3
+ This module provides a minimal store that holds:
4
+ - API credentials (read-only config)
5
+ - Shared ApiClient instance (lazy initialization)
6
+ - Agent cache for cross-screen sharing
7
+
8
+ This replaces the previous ELM-style architecture with Textual's
9
+ recommended "App as Store" pattern - simple and direct.
10
+ """
11
+
12
+ from alloy_runtime_sdk.api_client.client import ApiClient
13
+ from alloy_runtime_types.dtos.agents import AgentSummary
14
+
15
+
16
+ class AppStore:
17
+ """Simple app-wide store for shared state.
18
+
19
+ Usage:
20
+ store = AppStore(api_url="...", api_key="...")
21
+ client = await store.get_client()
22
+
23
+ Screens access via self.app.store (Textual's recommended pattern).
24
+ """
25
+
26
+ def __init__(self, api_url: str, api_key: str) -> None:
27
+ """Initialize the store.
28
+
29
+ Args:
30
+ api_url: Base URL for the API server
31
+ api_key: API key for authentication
32
+ """
33
+ self.api_url = api_url.rstrip("/")
34
+ self.api_key = api_key
35
+ self._client: ApiClient | None = None
36
+ self._client_entered: bool = False
37
+
38
+ # Cross-screen cache for agent picker in chat
39
+ self.agent_cache: list[AgentSummary] = []
40
+
41
+ async def get_client(self) -> ApiClient:
42
+ """Get the shared server client instance.
43
+
44
+ Creates and connects on first use, reuses thereafter.
45
+
46
+ Returns:
47
+ Connected ApiClient instance
48
+
49
+ Raises:
50
+ Exception: If connection fails
51
+ """
52
+ if self._client is None:
53
+ self._client = ApiClient(
54
+ base_url=self.api_url,
55
+ api_key=self.api_key,
56
+ timeout=30.0,
57
+ )
58
+
59
+ if not self._client_entered:
60
+ await self._client.__aenter__()
61
+ self._client_entered = True
62
+
63
+ return self._client
64
+
65
+ async def close(self) -> None:
66
+ """Close the client connection.
67
+
68
+ Should be called when the application exits.
69
+ """
70
+ if self._client and self._client_entered:
71
+ await self._client.__aexit__(None, None, None)
72
+ self._client_entered = False
73
+ self._client = None
File without changes
File without changes
@@ -0,0 +1,65 @@
1
+ """Base command protocol and utilities for chat commands.
2
+
3
+ Commands encapsulate async operations, making them:
4
+ - Testable in isolation with mocked dependencies
5
+ - Reusable across different contexts (UI, CLI, scripts)
6
+ - Single-responsibility focused
7
+ """
8
+
9
+ from dataclasses import dataclass
10
+ from typing import Generic, Protocol, TypeVar
11
+
12
+ T = TypeVar("T")
13
+ U = TypeVar("U")
14
+
15
+
16
+ class Command(Protocol[T]):
17
+ """Protocol for chat commands.
18
+
19
+ Commands are dataclasses that encapsulate all dependencies needed
20
+ to execute an async operation. They return a CommandResult with
21
+ the outcome.
22
+
23
+ Example:
24
+ @dataclass
25
+ class SendMessageCommand:
26
+ client: ApiClient
27
+ store: ChatStore
28
+ session_id: UUID
29
+ message: str
30
+
31
+ async def execute(self) -> CommandResult[str]:
32
+ # ... implementation
33
+ """
34
+
35
+ async def execute(self) -> "CommandResult[T]":
36
+ """Execute the command and return result."""
37
+ ...
38
+
39
+
40
+ @dataclass(frozen=True)
41
+ class CommandResult(Generic[T]):
42
+ """Result wrapper for command execution.
43
+
44
+ Provides a consistent way to handle success/failure without exceptions
45
+ bubbling up to the UI layer.
46
+
47
+ Attributes:
48
+ success: Whether the command succeeded.
49
+ data: The result data if successful.
50
+ error: Error message if failed.
51
+ """
52
+
53
+ success: bool
54
+ data: T | None = None
55
+ error: str | None = None
56
+
57
+ @classmethod
58
+ def ok(cls: type["CommandResult[U]"], data: U) -> "CommandResult[U]":
59
+ """Create a successful result."""
60
+ return cls(success=True, data=data)
61
+
62
+ @classmethod
63
+ def fail(cls: type["CommandResult[U]"], error: str) -> "CommandResult[U]":
64
+ """Create a failed result."""
65
+ return cls(success=False, error=error)
@@ -0,0 +1,135 @@
1
+ """Command for creating a new chat session."""
2
+
3
+ from dataclasses import dataclass
4
+ from uuid import UUID
5
+
6
+ from alloy_runtime_sdk.api_client.client import ApiClient
7
+ from alloy_runtime_types.dtos.sessions import CreateSessionRequest
8
+ from alloy_runtime_sdk.logging.config import get_logger
9
+
10
+ from cli.tui.chat.commands.base import CommandResult
11
+ from cli.tui.chat.store import ChatStore
12
+ from cli.tui.chat.types import ChatPhase
13
+
14
+ logger = get_logger(__name__)
15
+
16
+
17
+ @dataclass
18
+ class CreateSessionResult:
19
+ """Result data for create session operation.
20
+
21
+ Supports both agent mode and direct model mode.
22
+
23
+ Attributes:
24
+ session_id: ID of the newly created session.
25
+ session_name: Name of the session.
26
+ agent_id: ID of the agent (agent mode).
27
+ agent_name: Name of the agent (agent mode).
28
+ provider_key: Provider key (model mode).
29
+ provider_model_name: Model name (model mode).
30
+ system_instruction: System instruction (model mode).
31
+ """
32
+
33
+ session_id: UUID
34
+ session_name: str | None
35
+ # Agent mode
36
+ agent_id: UUID | None = None
37
+ agent_name: str | None = None
38
+ # Model mode
39
+ provider_key: str | None = None
40
+ provider_model_name: str | None = None
41
+ system_instruction: str | None = None
42
+
43
+
44
+ @dataclass
45
+ class CreateSessionCommand:
46
+ """Command to create a new chat session.
47
+
48
+ Supports two modes:
49
+ - Agent mode: Uses agent_id/agent_name
50
+ - Model mode: Uses provider_key/provider_model_name/system_instruction
51
+
52
+ This command:
53
+ 1. Transitions store to CREATING_SESSION phase
54
+ 2. Sends create request to the API
55
+ 3. Updates store with new session context
56
+ 4. Clears any existing messages
57
+ 5. Transitions back to IDLE
58
+
59
+ Attributes:
60
+ client: Server client for API calls.
61
+ store: Chat store for state management.
62
+ name: Optional name for the session.
63
+ agent_id: ID of the agent to use (agent mode).
64
+ agent_name: Name of the agent (agent mode).
65
+ provider_key: Provider key (model mode).
66
+ provider_model_name: Model name (model mode).
67
+ system_instruction: System instruction (model mode).
68
+ """
69
+
70
+ client: ApiClient
71
+ store: ChatStore
72
+ name: str | None
73
+ # Agent mode
74
+ agent_id: UUID | None = None
75
+ agent_name: str | None = None
76
+ # Model mode
77
+ provider_key: str | None = None
78
+ provider_model_name: str | None = None
79
+ system_instruction: str | None = None
80
+
81
+ async def execute(self) -> CommandResult[CreateSessionResult]:
82
+ """Execute the create session operation.
83
+
84
+ Returns:
85
+ CommandResult with new session data on success.
86
+ """
87
+ logger.info(
88
+ "create_session_starting",
89
+ agent_id=str(self.agent_id) if self.agent_id else None,
90
+ agent_name=self.agent_name,
91
+ model=self.provider_model_name,
92
+ )
93
+ self.store.set_phase(ChatPhase.CREATING_SESSION)
94
+
95
+ try:
96
+ # Create session request - agent is optional
97
+ # For model mode, we don't associate an agent with the session
98
+ request = CreateSessionRequest(
99
+ name=self.name,
100
+ agent=str(self.agent_id) if self.agent_id else None,
101
+ )
102
+ session = await self.client.create_session(request)
103
+
104
+ # Update store with new session
105
+ self.store.set_session(
106
+ session_id=session.id,
107
+ session_name=self.name,
108
+ agent_id=self.agent_id,
109
+ agent_name=self.agent_name,
110
+ message_count=0,
111
+ provider_key=self.provider_key,
112
+ model_name=self.provider_model_name,
113
+ system_instruction=self.system_instruction,
114
+ )
115
+ self.store.set_messages([])
116
+ self.store.set_phase(ChatPhase.IDLE)
117
+
118
+ logger.info("create_session_completed", session_id=str(session.id))
119
+ return CommandResult[CreateSessionResult](
120
+ success=True,
121
+ data=CreateSessionResult(
122
+ session_id=session.id,
123
+ session_name=self.name,
124
+ agent_id=self.agent_id,
125
+ agent_name=self.agent_name,
126
+ provider_key=self.provider_key,
127
+ provider_model_name=self.provider_model_name,
128
+ system_instruction=self.system_instruction,
129
+ ),
130
+ )
131
+
132
+ except Exception as e:
133
+ logger.warning("create_session_failed", error=str(e))
134
+ self.store.set_phase(ChatPhase.IDLE)
135
+ return CommandResult[CreateSessionResult](success=False, error=str(e))
@@ -0,0 +1,119 @@
1
+ """Command for loading a chat session and its messages."""
2
+
3
+ from dataclasses import dataclass
4
+ from uuid import UUID
5
+
6
+ from alloy_runtime_sdk.api_client.client import ApiClient
7
+ from alloy_runtime_types.dtos.sessions import MessageResponse
8
+ from alloy_runtime_sdk.logging.config import get_logger
9
+
10
+ from cli.tui.chat.commands.base import CommandResult
11
+ from cli.tui.chat.store import ChatStore
12
+ from cli.tui.chat.types import ChatPhase
13
+
14
+ logger = get_logger(__name__)
15
+
16
+
17
+ @dataclass
18
+ class LoadSessionResult:
19
+ """Result data for load session operation.
20
+
21
+ Attributes:
22
+ session_id: ID of the loaded session.
23
+ session_name: Name of the session.
24
+ agent_id: ID of the agent (extracted from messages).
25
+ agent_name: Name of the agent (if available).
26
+ messages: List of messages in the session.
27
+ total_messages: Total message count.
28
+ """
29
+
30
+ session_id: UUID
31
+ session_name: str | None
32
+ agent_id: UUID | None
33
+ agent_name: str | None
34
+ messages: list[MessageResponse]
35
+ total_messages: int
36
+
37
+
38
+ @dataclass
39
+ class LoadSessionCommand:
40
+ """Command to load a chat session and its messages.
41
+
42
+ This command:
43
+ 1. Transitions store to LOADING_SESSION phase
44
+ 2. Fetches session data from the API
45
+ 3. Extracts agent info from messages
46
+ 4. Updates store with session context and messages
47
+ 5. Transitions back to IDLE
48
+
49
+ Attributes:
50
+ client: Server client for API calls.
51
+ store: Chat store for state management.
52
+ session_id: ID of the session to load.
53
+ message_limit: Maximum number of messages to fetch.
54
+ """
55
+
56
+ client: ApiClient
57
+ store: ChatStore
58
+ session_id: UUID
59
+ message_limit: int = 100
60
+
61
+ async def execute(self) -> CommandResult[LoadSessionResult]:
62
+ """Execute the load session operation.
63
+
64
+ Returns:
65
+ CommandResult with session data on success.
66
+ """
67
+ logger.info("load_session_starting", session_id=str(self.session_id))
68
+ self.store.set_phase(ChatPhase.LOADING_SESSION)
69
+
70
+ try:
71
+ session = await self.client.get_session(
72
+ self.session_id, limit=self.message_limit
73
+ )
74
+
75
+ # Extract agent info from messages
76
+ agent_id = None
77
+ agent_name = None
78
+ for msg in reversed(session.messages):
79
+ if msg.role == "assistant" and msg.agent_execution:
80
+ exec_meta = msg.agent_execution
81
+ if exec_meta.agent_id:
82
+ agent_id = exec_meta.agent_id
83
+ break
84
+
85
+ # Update store with session data
86
+ self.store.set_session(
87
+ session_id=self.session_id,
88
+ session_name=session.name,
89
+ agent_id=agent_id,
90
+ agent_name=agent_name,
91
+ message_count=session.total_messages,
92
+ )
93
+ self.store.set_messages(list(session.messages))
94
+ self.store.set_phase(ChatPhase.IDLE)
95
+
96
+ logger.info(
97
+ "load_session_completed",
98
+ session_id=str(self.session_id),
99
+ session_name=session.name,
100
+ message_count=len(session.messages),
101
+ )
102
+ return CommandResult[LoadSessionResult](
103
+ success=True,
104
+ data=LoadSessionResult(
105
+ session_id=self.session_id,
106
+ session_name=session.name,
107
+ agent_id=agent_id,
108
+ agent_name=agent_name,
109
+ messages=list(session.messages),
110
+ total_messages=session.total_messages,
111
+ ),
112
+ )
113
+
114
+ except Exception as e:
115
+ logger.warning(
116
+ "load_session_failed", session_id=str(self.session_id), error=str(e)
117
+ )
118
+ self.store.set_phase(ChatPhase.IDLE)
119
+ return CommandResult[LoadSessionResult](success=False, error=str(e))