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
@@ -0,0 +1,129 @@
1
+ """Presenter for schema get command output."""
2
+
3
+ import json
4
+ import sys
5
+
6
+ from rich.console import Console
7
+ from rich.panel import Panel
8
+ from rich.table import Table
9
+ from rich.text import Text
10
+
11
+ from cli.infrastructure.formatting.fields import (
12
+ format_datetime,
13
+ format_optional,
14
+ format_uuid,
15
+ )
16
+ from alloy_runtime_types.dtos.schemas import GetSchemaResponse
17
+
18
+
19
+ def _derive_scope(response: GetSchemaResponse) -> str:
20
+ """Derive scope string from organization_id and user_id fields.
21
+
22
+ Args:
23
+ response: Schema response from server
24
+
25
+ Returns:
26
+ Scope string: user, organization, or global
27
+ """
28
+ if response.organization_id is not None and response.user_id is None:
29
+ return "organization"
30
+ elif response.user_id is not None:
31
+ return "user"
32
+ else:
33
+ return "global"
34
+
35
+
36
+ def _format_definition_for_display(
37
+ schema_format_id: str, schema_definition: str
38
+ ) -> str:
39
+ """Format schema definition for display.
40
+
41
+ JSON schemas are pretty-printed, regex patterns shown as-is.
42
+
43
+ Args:
44
+ schema_format_id: Format type (json_schema, regex)
45
+ schema_definition: The schema definition string
46
+
47
+ Returns:
48
+ Formatted definition string
49
+ """
50
+ if schema_format_id == "json_schema":
51
+ try:
52
+ # Parse and pretty-print JSON
53
+ parsed = json.loads(schema_definition)
54
+ return json.dumps(parsed, indent=2, ensure_ascii=False)
55
+ except (json.JSONDecodeError, TypeError):
56
+ # If parsing fails, return as-is
57
+ return schema_definition
58
+ else:
59
+ # Regex or other formats - return as-is
60
+ return schema_definition
61
+
62
+
63
+ def present_schema_details(response: GetSchemaResponse) -> None:
64
+ """Present schema details with Rich formatting.
65
+
66
+ Metadata goes to stderr (visible in terminal but not piped).
67
+ Schema definition goes to stdout (for piping to other commands).
68
+
69
+ Args:
70
+ response: GetSchemaResponse from server
71
+ """
72
+ # Create console for stderr output (metadata)
73
+ stderr_console = Console(file=sys.stderr, force_terminal=True)
74
+
75
+ # Print success message to stderr
76
+ stderr_console.print(
77
+ f"[green]✓[/green] Schema retrieved: {response.schema_name} (v{response.version})"
78
+ )
79
+
80
+ # Build metadata table
81
+ metadata_table = Table(show_header=False, box=None, padding=(0, 1))
82
+ metadata_table.add_column("Field", style="dim", width=20)
83
+ metadata_table.add_column("Value")
84
+
85
+ metadata_table.add_row("ID", format_uuid(response.id, short=False))
86
+ metadata_table.add_row("Name", response.schema_name)
87
+ metadata_table.add_row("Format", response.schema_format_id)
88
+ metadata_table.add_row("Version", str(response.version))
89
+ metadata_table.add_row("Description", format_optional(response.description))
90
+ metadata_table.add_row("Scope", _derive_scope(response))
91
+ metadata_table.add_row("Is Latest", "Yes" if response.is_latest else "No")
92
+ metadata_table.add_row(
93
+ "Organization ID",
94
+ format_optional(response.organization_id, lambda x: format_uuid(x, short=True)),
95
+ )
96
+ metadata_table.add_row(
97
+ "User ID",
98
+ format_optional(response.user_id, lambda x: format_uuid(x, short=True)),
99
+ )
100
+ metadata_table.add_row("Created At", format_datetime(response.created_at))
101
+
102
+ # Display metadata panel to stderr
103
+ metadata_panel = Panel(
104
+ metadata_table,
105
+ title=f"Schema: {response.schema_name}",
106
+ border_style="blue",
107
+ )
108
+ stderr_console.print(metadata_panel)
109
+
110
+ # Format and display definition to stdout for piping
111
+ formatted_definition = _format_definition_for_display(
112
+ response.schema_format_id, response.schema_definition
113
+ )
114
+
115
+ # Also show definition preview in a panel to stderr
116
+ preview_text = (
117
+ formatted_definition
118
+ if len(formatted_definition) <= 500
119
+ else formatted_definition[:500] + "\n... (truncated in preview)"
120
+ )
121
+ definition_panel = Panel(
122
+ Text(preview_text, style="dim"),
123
+ title=f"Schema Definition Preview ({response.schema_format_id})",
124
+ border_style="green",
125
+ )
126
+ stderr_console.print(definition_panel)
127
+
128
+ # Print full definition to stdout for piping
129
+ print(formatted_definition, file=sys.stdout)
File without changes
@@ -0,0 +1,64 @@
1
+ """Schemas list command implementation."""
2
+
3
+ from typing import Optional
4
+
5
+ import typer
6
+
7
+ from cli.commands.schemas.list.presenter import present_schemas_list
8
+ from cli.infrastructure.command import async_command, authenticated_client
9
+
10
+
11
+ def schemas_list_command(
12
+ search: Optional[str] = typer.Option(
13
+ None,
14
+ "-s",
15
+ "--search",
16
+ help="Fuzzy search terms",
17
+ ),
18
+ schema_format: Optional[str] = typer.Option(
19
+ None,
20
+ "--schema-format",
21
+ help="Filter: json_schema or regex",
22
+ ),
23
+ limit: int = typer.Option(
24
+ 50,
25
+ "-l",
26
+ "--limit",
27
+ min=1,
28
+ max=100,
29
+ help="Max results",
30
+ ),
31
+ offset: int = typer.Option(
32
+ 0,
33
+ "--offset",
34
+ min=0,
35
+ help="Skip N results",
36
+ ),
37
+ ) -> None:
38
+ """List schemas.
39
+
40
+ Examples:
41
+ ai schemas list
42
+ ai schemas list -s "user profile"
43
+ ai schemas list --schema-format json_schema
44
+ ai schemas list -l 20
45
+ """
46
+ _execute_list(
47
+ search=search, schema_format=schema_format, limit=limit, offset=offset
48
+ )
49
+
50
+
51
+ @async_command
52
+ async def _execute_list(
53
+ search: Optional[str], schema_format: Optional[str], limit: int, offset: int
54
+ ) -> None:
55
+ """Execute list schemas operation."""
56
+ async with authenticated_client() as (_config, client):
57
+ response = await client.list_schemas(
58
+ search=search,
59
+ schema_format=schema_format,
60
+ limit=limit,
61
+ offset=offset,
62
+ )
63
+
64
+ present_schemas_list(response)
@@ -0,0 +1,133 @@
1
+ """Presenter for schemas list command output."""
2
+
3
+ from pydantic import BaseModel, Field
4
+ from alloy_runtime_types.dtos.schemas import ListSchemasResponse, SchemaSummary
5
+
6
+ from cli.infrastructure.scope_utils import format_scope_label
7
+ from cli.infrastructure.output import OutputService
8
+ from cli.infrastructure.renderers.list_renderer import ColumnConfig
9
+
10
+
11
+ class SchemaDisplay(BaseModel):
12
+ """Schema with computed scope field for display."""
13
+
14
+ id: str = Field(..., description="Schema ID")
15
+ schema_name: str = Field(..., description="Schema name")
16
+ version: int = Field(..., description="Version number")
17
+ schema_format_id: str = Field(..., description="Format type")
18
+ description: str | None = Field(None, description="Description")
19
+ scope: str = Field(..., description="Ownership scope")
20
+ created_at: str = Field(..., description="Creation date")
21
+
22
+
23
+ def _format_description(description: str | None) -> str:
24
+ """Format description for display, truncating if too long.
25
+
26
+ Args:
27
+ description: Optional description text
28
+
29
+ Returns:
30
+ Formatted description string
31
+ """
32
+ if not description:
33
+ return "-"
34
+ if len(description) > 120:
35
+ return description[:117] + "..."
36
+ return description
37
+
38
+
39
+ def _transform_schema_for_display(schema: SchemaSummary) -> SchemaDisplay:
40
+ """Transform schema summary into display model with computed fields.
41
+
42
+ Args:
43
+ schema: Schema summary from API
44
+
45
+ Returns:
46
+ SchemaDisplay with computed scope field
47
+ """
48
+ return SchemaDisplay(
49
+ id=str(schema.id),
50
+ schema_name=schema.schema_name,
51
+ version=schema.version,
52
+ schema_format_id=schema.schema_format_id,
53
+ description=schema.description,
54
+ scope=format_scope_label(
55
+ str(schema.organization_id) if schema.organization_id else None,
56
+ str(schema.user_id) if schema.user_id else None,
57
+ ),
58
+ created_at=schema.created_at.strftime("%Y-%m-%d") if schema.created_at else "-",
59
+ )
60
+
61
+
62
+ def present_schemas_list(response: ListSchemasResponse) -> None:
63
+ """Present list of schemas with Rich table formatting.
64
+
65
+ Args:
66
+ response: List schemas response from server
67
+ """
68
+ output = OutputService.get()
69
+
70
+ if not response.schemas:
71
+ output.info("No schemas found")
72
+ return
73
+
74
+ # Transform schemas for display
75
+ display_items = [_transform_schema_for_display(s) for s in response.schemas]
76
+
77
+ # Define table columns with compact layout configuration
78
+ # Line 1 (primary): ID, version, format, scope, created - machine-readable data
79
+ # Line 2 (detail): Name, description - human-readable content
80
+ columns = [
81
+ ColumnConfig(
82
+ source_field="id",
83
+ header_label="ID",
84
+ compact_line=1,
85
+ compact_style="cyan",
86
+ ),
87
+ ColumnConfig(
88
+ source_field="version",
89
+ header_label="Ver",
90
+ align="right",
91
+ formatter=lambda x: f"v{x}" if x else "-",
92
+ compact_line=1,
93
+ compact_style="yellow",
94
+ ),
95
+ ColumnConfig(
96
+ source_field="schema_format_id",
97
+ header_label="Format",
98
+ compact_line=1,
99
+ compact_style="magenta",
100
+ ),
101
+ ColumnConfig(
102
+ source_field="scope",
103
+ header_label="Scope",
104
+ compact_line=1,
105
+ compact_style="dim",
106
+ ),
107
+ ColumnConfig(
108
+ source_field="created_at",
109
+ header_label="Created",
110
+ compact_line=1,
111
+ compact_style="blue",
112
+ ),
113
+ ColumnConfig(
114
+ source_field="schema_name",
115
+ header_label="Name",
116
+ compact_line=2,
117
+ compact_style="white bold",
118
+ ),
119
+ ColumnConfig(
120
+ source_field="description",
121
+ header_label="Description",
122
+ formatter=_format_description,
123
+ compact_line=2,
124
+ compact_style="dim",
125
+ ),
126
+ ]
127
+
128
+ # Render table
129
+ output.table(
130
+ items=display_items, # type: ignore[arg-type]
131
+ title=f"Schemas ({response.total})",
132
+ columns=columns,
133
+ )
File without changes
@@ -0,0 +1,369 @@
1
+ """Schema update command implementation."""
2
+
3
+ import json
4
+ import os
5
+ import shutil
6
+ import subprocess
7
+ import tempfile
8
+ from pathlib import Path
9
+ from typing import Optional
10
+
11
+ import typer
12
+
13
+ from cli.commands.shared_flags import CLEAR_DESCRIPTION, DESCRIPTION, FILE_INPUT
14
+ from cli.commands.schemas.update.presenter import present_schema_update_success
15
+ from cli.infrastructure.command import async_command, authenticated_client
16
+ from cli.infrastructure.file_content import FileContentError, resolve_content
17
+ from alloy_runtime_types.dtos.schemas import UpdateSchemaRequest
18
+ from alloy_runtime_sdk.exceptions.errors import NotFoundError
19
+
20
+
21
+ class EditorError(Exception):
22
+ """Raised when editor operations fail."""
23
+
24
+
25
+ def _get_editor() -> str:
26
+ """Get the user's preferred editor.
27
+
28
+ Checks in order:
29
+ 1. $EDITOR environment variable
30
+ 2. $VISUAL environment variable
31
+ 3. Common editors on PATH (nano, vim, vi)
32
+
33
+ Returns:
34
+ Path/name of editor to use
35
+
36
+ Raises:
37
+ EditorError: If no suitable editor is found
38
+ """
39
+ # Check environment variables first
40
+ editor = os.environ.get("EDITOR") or os.environ.get("VISUAL")
41
+ if editor:
42
+ return editor
43
+
44
+ # Fall back to common editors
45
+ for fallback in ("nano", "vim", "vi"):
46
+ if shutil.which(fallback):
47
+ return fallback
48
+
49
+ raise EditorError(
50
+ "No editor found. Set $EDITOR environment variable or install nano/vim."
51
+ )
52
+
53
+
54
+ def _open_editor_for_schema(initial_content: str, schema_format: str) -> str | None:
55
+ """Open editor with schema-specific file extension for syntax highlighting.
56
+
57
+ Args:
58
+ initial_content: Initial schema definition content
59
+ schema_format: Schema format ID (json_schema or regex)
60
+
61
+ Returns:
62
+ Edited content or None if editor failed
63
+
64
+ Raises:
65
+ EditorError: If no editor is available
66
+ """
67
+ editor = _get_editor()
68
+
69
+ # Choose file extension based on schema format
70
+ if schema_format == "json_schema":
71
+ suffix = ".json"
72
+ # Pretty-print JSON for better editing experience
73
+ try:
74
+ parsed = json.loads(initial_content)
75
+ initial_content = json.dumps(parsed, indent=2, ensure_ascii=False)
76
+ except (json.JSONDecodeError, TypeError):
77
+ # If parsing fails, use as-is
78
+ pass
79
+ else:
80
+ # Regex pattern
81
+ suffix = ".txt"
82
+
83
+ # Create temp file
84
+ with tempfile.NamedTemporaryFile(
85
+ mode="w",
86
+ suffix=suffix,
87
+ delete=False,
88
+ ) as f:
89
+ f.write(initial_content)
90
+ temp_path = Path(f.name)
91
+
92
+ try:
93
+ # Get file modification time before editing
94
+ mtime_before = temp_path.stat().st_mtime
95
+
96
+ # Open editor and wait for it to close
97
+ editor_parts = editor.split()
98
+ cmd = editor_parts + [str(temp_path)]
99
+
100
+ result = subprocess.call(cmd)
101
+
102
+ if result != 0:
103
+ return None
104
+
105
+ # Check if file was modified
106
+ mtime_after = temp_path.stat().st_mtime
107
+ if mtime_after == mtime_before:
108
+ # File wasn't modified - still return content in case no changes needed
109
+ pass
110
+
111
+ # Read the edited content
112
+ content = temp_path.read_text()
113
+ return content
114
+
115
+ finally:
116
+ # Clean up temp file
117
+ try:
118
+ temp_path.unlink()
119
+ except OSError:
120
+ pass # Best effort cleanup
121
+
122
+
123
+ def schemas_update_command(
124
+ schema: str = typer.Argument(..., help="Schema name or UUID"),
125
+ # Metadata fields
126
+ description: Optional[str] = DESCRIPTION,
127
+ # Definition fields
128
+ definition: Optional[str] = typer.Option(
129
+ None,
130
+ "-D",
131
+ "--definition",
132
+ help="Schema definition (or @file)",
133
+ ),
134
+ definition_file: Optional[Path] = FILE_INPUT,
135
+ # Clear flags
136
+ clear_description: bool = CLEAR_DESCRIPTION,
137
+ ) -> None:
138
+ """Update an existing schema.
139
+
140
+ By default, opens interactive editor. Use flags for non-interactive mode.
141
+ Name and format cannot be changed.
142
+
143
+ Examples:
144
+
145
+ # Interactive (default)
146
+ ai schemas update my-schema
147
+
148
+ # Update description
149
+ ai schemas update my-schema -d "New description"
150
+
151
+ # Update definition from file
152
+ ai schemas update my-schema -f schema.json
153
+
154
+ # Update definition inline
155
+ ai schemas update my-schema -D '{"type": "object", ...}'
156
+ """
157
+ # Validate definition source - can't have both file and inline
158
+ if definition_file is not None and definition is not None:
159
+ raise typer.BadParameter("Cannot specify both --file and --definition")
160
+
161
+ # Validate clear flags
162
+ if clear_description and description is not None:
163
+ raise typer.BadParameter(
164
+ "Cannot specify both --description and --clear-description"
165
+ )
166
+
167
+ # Check if any flags were provided (non-interactive mode)
168
+ has_flags = any(
169
+ [
170
+ description is not None,
171
+ definition is not None,
172
+ definition_file is not None,
173
+ clear_description,
174
+ ]
175
+ )
176
+
177
+ if has_flags:
178
+ # Non-interactive mode - execute with provided flags
179
+ _execute_update_non_interactive(
180
+ schema_identifier=schema,
181
+ description=description,
182
+ definition=definition,
183
+ definition_file=definition_file,
184
+ clear_description=clear_description,
185
+ )
186
+ else:
187
+ # Interactive mode - fetch current data and launch editor
188
+ _execute_update_interactive(schema_identifier=schema)
189
+
190
+
191
+ def _execute_update_interactive(schema_identifier: str) -> None:
192
+ """Launch interactive editor for updating schema.
193
+
194
+ This function is synchronous because editor operations are blocking.
195
+ We use asyncio.run() just for the initial schema fetch, then
196
+ run the editor synchronously.
197
+
198
+ Args:
199
+ schema_identifier: Schema name or UUID
200
+
201
+ Raises:
202
+ ConfigurationError: If environment variables are missing
203
+ AuthenticationError: If API key is invalid
204
+ NotFoundError: If schema doesn't exist
205
+ ServerError: If server returns 5xx error
206
+ """
207
+ import asyncio
208
+
209
+ from cli.infrastructure.error_display import display_error
210
+ from cli.infrastructure.output import OutputService
211
+
212
+ try:
213
+ # Fetch current schema data (async operation, run in its own event loop)
214
+ async def fetch_schema():
215
+ async with authenticated_client() as (_, client):
216
+ return await client.get_schema(schema_identifier)
217
+
218
+ try:
219
+ current_data = asyncio.run(fetch_schema())
220
+ except NotFoundError:
221
+ raise typer.BadParameter(
222
+ f"Schema '{schema_identifier}' not found. "
223
+ "Use 'ai schemas list' to see available schemas."
224
+ )
225
+
226
+ output = OutputService.get()
227
+
228
+ # Show current schema info
229
+ output.info(
230
+ f"Schema: {current_data.schema_name} (v{current_data.version})\n"
231
+ f"Format: {current_data.schema_format_id}\n"
232
+ f"Description: {current_data.description or '(none)'}"
233
+ )
234
+
235
+ # Open editor with current definition
236
+ with output.console.status(
237
+ f"Opening editor for {current_data.schema_name}...", spinner="dots"
238
+ ):
239
+ pass # Just show briefly before opening editor
240
+
241
+ try:
242
+ edited_content = _open_editor_for_schema(
243
+ initial_content=current_data.schema_definition,
244
+ schema_format=current_data.schema_format_id,
245
+ )
246
+ except EditorError as e:
247
+ raise typer.BadParameter(str(e))
248
+
249
+ if edited_content is None:
250
+ output.warning("Editor exited with error. Update cancelled.")
251
+ raise typer.Exit(code=0)
252
+
253
+ # Check if definition was modified
254
+ definition_changed = (
255
+ edited_content.strip() != current_data.schema_definition.strip()
256
+ )
257
+
258
+ if not definition_changed:
259
+ output.info("No changes to schema definition. Update cancelled.")
260
+ raise typer.Exit(code=0)
261
+
262
+ # Prompt for description update
263
+ output.info("\nSchema definition has been modified.")
264
+ update_description = typer.confirm(
265
+ "Do you want to update the description as well?",
266
+ default=False,
267
+ )
268
+
269
+ new_description: Optional[str] = None
270
+ if update_description:
271
+ new_description = typer.prompt(
272
+ "Enter new description (leave empty to clear)",
273
+ default=current_data.description or "",
274
+ )
275
+ # Empty string means clear (strip to handle whitespace-only input)
276
+ if new_description and not new_description.strip():
277
+ new_description = ""
278
+
279
+ # Build request
280
+ request = UpdateSchemaRequest(
281
+ schema_definition=edited_content.strip(),
282
+ description=new_description,
283
+ )
284
+
285
+ # Execute update via API
286
+ async def update_schema():
287
+ async with authenticated_client() as (_, client):
288
+ # Resolve to UUID (server only accepts UUID for update)
289
+ return await client.update_schema(current_data.id, request)
290
+
291
+ response = asyncio.run(update_schema())
292
+
293
+ # Present success output
294
+ present_schema_update_success(response)
295
+
296
+ except typer.Exit:
297
+ # Re-raise Exit exceptions (don't treat as errors)
298
+ raise
299
+ except Exception as e:
300
+ display_error(e)
301
+ raise typer.Exit(code=1)
302
+
303
+
304
+ @async_command
305
+ async def _execute_update_non_interactive(
306
+ schema_identifier: str,
307
+ description: Optional[str],
308
+ definition: Optional[str],
309
+ definition_file: Optional[Path],
310
+ clear_description: bool,
311
+ ) -> None:
312
+ """Execute the schema update operation in non-interactive mode.
313
+
314
+ Args:
315
+ schema_identifier: Schema name or UUID
316
+ description: Optional new description
317
+ definition: Optional new definition (inline or @file)
318
+ definition_file: Optional definition file path
319
+ clear_description: If True, clear the description
320
+
321
+ Raises:
322
+ ConfigurationError: If environment variables are missing
323
+ AuthenticationError: If API key is invalid
324
+ NotFoundError: If schema doesn't exist
325
+ ValidationError: If update data is invalid
326
+ ServerError: If server returns 5xx error
327
+ """
328
+ # Resolve content from @file references
329
+ try:
330
+ definition = resolve_content(definition)
331
+ except FileContentError as e:
332
+ raise typer.BadParameter(str(e))
333
+
334
+ # Get definition from file if specified
335
+ schema_definition: Optional[str] = None
336
+ if definition_file is not None:
337
+ schema_definition = definition_file.read_text()
338
+ elif definition is not None:
339
+ schema_definition = definition
340
+
341
+ # Handle description
342
+ final_description: Optional[str] = description
343
+ if clear_description:
344
+ final_description = ""
345
+
346
+ # Build update request - only include fields that were explicitly provided
347
+ request = UpdateSchemaRequest(
348
+ description=final_description
349
+ if (description is not None or clear_description)
350
+ else None,
351
+ schema_definition=schema_definition,
352
+ )
353
+
354
+ # Execute API call with authenticated client
355
+ async with authenticated_client() as (_config, client):
356
+ # First resolve schema identifier to get UUID and current data
357
+ try:
358
+ schema_data = await client.get_schema(schema_identifier)
359
+ except NotFoundError:
360
+ raise typer.BadParameter(
361
+ f"Schema '{schema_identifier}' not found. "
362
+ "Use 'ai schemas list' to see available schemas."
363
+ )
364
+
365
+ # Execute update (server requires UUID)
366
+ response = await client.update_schema(schema_data.id, request)
367
+
368
+ # Present success output
369
+ present_schema_update_success(response)