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,502 @@
1
+ """Template creation modal for creating new templates.
2
+
3
+ Provides a comprehensive modal screen that allows users to create a new template
4
+ with all required fields, external editor integration, and macro resolution.
5
+ """
6
+
7
+ from dataclasses import dataclass
8
+ from typing import TYPE_CHECKING, Any
9
+
10
+ from textual import on, work
11
+ from textual.app import ComposeResult
12
+ from textual.containers import Horizontal, VerticalScroll
13
+ from textual.widgets import (
14
+ Button,
15
+ Checkbox,
16
+ Input,
17
+ Label,
18
+ RadioButton,
19
+ RadioSet,
20
+ Static,
21
+ )
22
+
23
+ from cli.tui.widgets.base_form_modal import BaseFormModal
24
+
25
+ from alloy_runtime_sdk.api_client.client import ApiClient
26
+ from alloy_runtime_types.dtos.templates import CreateTemplateRequest
27
+ from alloy_runtime_types.enums.template_enums import (
28
+ TemplateContentType,
29
+ TemplateVisibility,
30
+ )
31
+
32
+ from cli.infrastructure.editor import EditorError, open_editor_with_hints
33
+ from cli.infrastructure.forms.resolution_modal import ResolutionModal
34
+ from cli.infrastructure.forms.tag_picker import TagPicker
35
+ from cli.infrastructure.macro_parser import (
36
+ MacroMatch,
37
+ build_jinja_replacement,
38
+ compile_content,
39
+ deduplicate_macros,
40
+ parse_macros,
41
+ )
42
+
43
+ if TYPE_CHECKING:
44
+ from cli.tui.app import AlloyRuntimeApp
45
+
46
+
47
+ @dataclass
48
+ class TemplateCreateResult:
49
+ """Result of successful template creation."""
50
+
51
+ template_id: str
52
+ template_name: str
53
+ version_id: str
54
+ version_number: int
55
+
56
+
57
+ class TemplateCreateModal(BaseFormModal[TemplateCreateResult]):
58
+ """Modal for creating a new template.
59
+
60
+ Provides a comprehensive form with:
61
+ - Required fields: name, content type, visibility, tags
62
+ - External editor integration for content
63
+ - Macro resolution flow for @fragment, @text, @json, @schema
64
+ - Optional fields: description, upsert, escape_jinja
65
+
66
+ Usage:
67
+ def on_template_created(result: TemplateCreateResult | None):
68
+ if result is not None:
69
+ # Template was created successfully
70
+ self.notify(f"Created template: {result.template_name}")
71
+ self._do_search("") # Refresh list
72
+
73
+ client = await self.app.store.get_client()
74
+ self.app.push_screen(
75
+ TemplateCreateModal(client=client),
76
+ on_template_created
77
+ )
78
+ """
79
+
80
+ app: "AlloyRuntimeApp"
81
+
82
+ def __init__(
83
+ self,
84
+ client: ApiClient,
85
+ **kwargs: Any,
86
+ ) -> None:
87
+ """Initialize the template creation modal.
88
+
89
+ Args:
90
+ client: ApiClient instance for API calls
91
+ """
92
+ super().__init__(**kwargs)
93
+ self._client = client
94
+
95
+ # Template content state
96
+ self._content: str = ""
97
+ self._pending_macros: list[MacroMatch] = [] # Unique macros to resolve
98
+ self._all_macros: list[MacroMatch] = [] # All macros for replacement mapping
99
+ self._replacements: dict[str, str] = {}
100
+ self._current_macro_index: int = 0
101
+ self._macros_resolved: bool = False
102
+
103
+ def compose(self) -> ComposeResult:
104
+ with VerticalScroll(id="template-create-modal"):
105
+ yield Label("Create New Template", classes="modal-title")
106
+
107
+ # ===== REQUIRED FIELDS =====
108
+ yield Static("[bold]Required[/]", classes="form-section")
109
+
110
+ yield Static(
111
+ "Name (lowercase, dots/dashes/underscores)", classes="field-label"
112
+ )
113
+ yield Input(
114
+ placeholder="e.g., email.welcome-header, system.default_prompt",
115
+ id="name-input",
116
+ )
117
+
118
+ yield Static("Content Type", classes="field-label")
119
+ with RadioSet(id="content-type-radios"):
120
+ yield RadioButton("System Instruction", id="type-system", value=True)
121
+ yield RadioButton("User Message", id="type-user")
122
+ yield RadioButton("Fragment", id="type-fragment")
123
+
124
+ yield Static("Visibility", classes="field-label")
125
+ with RadioSet(id="visibility-radios"):
126
+ yield RadioButton("Private", id="vis-private", value=True)
127
+ yield RadioButton("Organization", id="vis-org")
128
+ yield RadioButton("Public", id="vis-public")
129
+
130
+ # ===== TEMPLATE CONTENT =====
131
+ yield Static("[bold]Template Content[/]", classes="form-section")
132
+
133
+ yield Static(
134
+ "No content yet. Click 'Edit Content' to open your editor.",
135
+ id="content-status",
136
+ classes="content-status no-content",
137
+ )
138
+
139
+ with Horizontal(classes="content-buttons"):
140
+ yield Button(
141
+ "Edit Content",
142
+ id="edit-content-btn",
143
+ variant="primary",
144
+ )
145
+ yield Button(
146
+ "Resolve Macros",
147
+ id="resolve-macros-btn",
148
+ variant="warning",
149
+ disabled=True,
150
+ )
151
+
152
+ yield Static("Tags (required)", classes="field-label")
153
+ yield TagPicker(
154
+ client=self._client,
155
+ placeholder="Search tags...",
156
+ empty_message="No tags selected (required)",
157
+ id="tag-picker",
158
+ )
159
+
160
+ # ===== OPTIONAL FIELDS =====
161
+ yield Static("[bold]Optional[/]", classes="form-section")
162
+
163
+ yield Static("Description", classes="field-label")
164
+ yield Input(
165
+ placeholder="Brief description of this template's purpose",
166
+ id="description-input",
167
+ )
168
+
169
+ with Horizontal(classes="checkbox-row"):
170
+ yield Checkbox(
171
+ "Return existing if name exists (upsert)",
172
+ id="upsert-checkbox",
173
+ )
174
+
175
+ with Horizontal(classes="checkbox-row"):
176
+ yield Checkbox(
177
+ "Escape Jinja syntax ({{, {%, {#)",
178
+ id="escape-jinja-checkbox",
179
+ )
180
+
181
+ # Error display
182
+ yield Static("", id="error-display", classes="error-display")
183
+
184
+ with Horizontal(classes="button-row"):
185
+ yield Button("Create", id="create-btn", variant="success")
186
+ yield Button("Cancel", id="cancel-btn", variant="default")
187
+
188
+ def on_mount(self) -> None:
189
+ """Focus the name input on mount."""
190
+ self.query_one("#name-input", Input).focus()
191
+
192
+ @on(Button.Pressed, "#edit-content-btn")
193
+ def on_edit_content_pressed(self, event: Button.Pressed) -> None:
194
+ """Open the external editor for content editing."""
195
+ with self.app.suspend():
196
+ try:
197
+ content = open_editor_with_hints(self._content)
198
+ if content is not None:
199
+ self._content = content
200
+ # Reset resolution state when content changes
201
+ self._macros_resolved = False
202
+ self._replacements = {}
203
+ self._update_content_status()
204
+ except EditorError as e:
205
+ self._show_error(str(e))
206
+
207
+ @on(Button.Pressed, "#resolve-macros-btn")
208
+ def on_resolve_macros_pressed(self, event: Button.Pressed) -> None:
209
+ """Start the macro resolution flow."""
210
+ self._start_macro_resolution()
211
+
212
+ @on(Button.Pressed, "#create-btn")
213
+ def on_create_pressed(self, event: Button.Pressed) -> None:
214
+ """Handle create button press."""
215
+ self.action_submit()
216
+
217
+ @on(Button.Pressed, "#cancel-btn")
218
+ def on_cancel_pressed(self, event: Button.Pressed) -> None:
219
+ """Handle cancel button press."""
220
+ self.dismiss(None)
221
+
222
+ def action_submit(self) -> None:
223
+ """Handle form submission."""
224
+ try:
225
+ self._validate_fields()
226
+
227
+ # Check if there are unresolved macros
228
+ macros = parse_macros(self._content)
229
+ if macros and not self._macros_resolved:
230
+ self._show_error(
231
+ f"Found {len(macros)} unresolved macro(s). "
232
+ "Click 'Resolve Macros' first, or remove the macros from your content."
233
+ )
234
+ return
235
+
236
+ # Clear any previous error
237
+ self._hide_error()
238
+
239
+ # Submit to API
240
+ self._finalize_submission()
241
+
242
+ except ValueError as e:
243
+ self._show_error(str(e))
244
+
245
+ def _validate_fields(self) -> None:
246
+ """Validate all required fields."""
247
+ import re
248
+
249
+ name = self.query_one("#name-input", Input).value.strip()
250
+ if not name:
251
+ raise ValueError("Name is required")
252
+
253
+ if not re.match(r"^[a-z0-9._-]+$", name):
254
+ raise ValueError(
255
+ "Name must be lowercase alphanumeric with dots, dashes, or underscores only"
256
+ )
257
+
258
+ if not self._content.strip():
259
+ raise ValueError(
260
+ "Template content is required. Click 'Edit Content' to add content."
261
+ )
262
+
263
+ tag_picker = self.query_one("#tag-picker", TagPicker)
264
+ tag_paths = tag_picker.selected_tags
265
+ if not tag_paths:
266
+ raise ValueError("At least one tag is required")
267
+
268
+ def _update_content_status(self) -> None:
269
+ """Update the content status display and resolve button state."""
270
+ status = self.query_one("#content-status", Static)
271
+ resolve_btn = self.query_one("#resolve-macros-btn", Button)
272
+
273
+ if not self._content.strip():
274
+ status.update("No content yet. Click 'Edit Content' to open your editor.")
275
+ status.remove_class("has-content", "has-macros", "macros-resolved")
276
+ status.add_class("no-content")
277
+ resolve_btn.disabled = True
278
+ return
279
+
280
+ # Parse macros from content
281
+ all_macros = parse_macros(self._content)
282
+ unique_macros = deduplicate_macros(all_macros)
283
+ char_count = len(self._content)
284
+ line_count = self._content.count("\n") + 1
285
+
286
+ if unique_macros:
287
+ if self._macros_resolved:
288
+ # Macros have been resolved
289
+ resolved_keys = {
290
+ (m.macro_type, m.query)
291
+ for m in all_macros
292
+ if m.original_text in self._replacements
293
+ }
294
+ resolved_count = len(resolved_keys)
295
+ skipped_count = len(unique_macros) - resolved_count
296
+
297
+ total_instances = len(all_macros)
298
+ status_text = (
299
+ f"Content: {char_count} chars, {line_count} lines\n"
300
+ f"Macros resolved: {resolved_count}/{len(unique_macros)} unique"
301
+ )
302
+ if total_instances > len(unique_macros):
303
+ status_text += f" ({total_instances} total instances)"
304
+ if skipped_count > 0:
305
+ status_text += f"\n({skipped_count} skipped - will remain as-is)"
306
+ status.update(status_text)
307
+ status.remove_class("no-content", "has-content", "has-macros")
308
+ status.add_class("macros-resolved")
309
+ resolve_btn.disabled = False
310
+ resolve_btn.label = "Re-resolve Macros"
311
+ else:
312
+ # Macros found but not yet resolved
313
+ macro_summary = ", ".join(
314
+ f"@{m.macro_type}({m.query[:20]}...)"
315
+ if len(m.query) > 20
316
+ else f"@{m.macro_type}({m.query})"
317
+ for m in unique_macros[:3]
318
+ )
319
+ if len(unique_macros) > 3:
320
+ macro_summary += f", +{len(unique_macros) - 3} more"
321
+
322
+ total_instances = len(all_macros)
323
+ instance_note = ""
324
+ if total_instances > len(unique_macros):
325
+ instance_note = f" ({total_instances} total instances)"
326
+
327
+ status.update(
328
+ f"Content: {char_count} chars, {line_count} lines\n"
329
+ f"Macros found: {len(unique_macros)} unique{instance_note} - {macro_summary}\n"
330
+ f"[bold]Click 'Resolve Macros' before submitting[/bold]"
331
+ )
332
+ status.remove_class("no-content", "has-content", "macros-resolved")
333
+ status.add_class("has-macros")
334
+ resolve_btn.disabled = False
335
+ resolve_btn.label = "Resolve Macros"
336
+ else:
337
+ status.update(f"Content ready: {char_count} chars, {line_count} lines")
338
+ status.remove_class("no-content", "has-macros", "macros-resolved")
339
+ status.add_class("has-content")
340
+ resolve_btn.disabled = True
341
+
342
+ def _start_macro_resolution(self) -> None:
343
+ """Start the macro resolution flow."""
344
+ self._all_macros = parse_macros(self._content)
345
+ self._pending_macros = deduplicate_macros(self._all_macros)
346
+ self._replacements = {}
347
+ self._current_macro_index = 0
348
+ self._macros_resolved = False
349
+
350
+ if self._pending_macros:
351
+ self._process_next_macro()
352
+ else:
353
+ self.app.notify("No macros to resolve", severity="information")
354
+
355
+ def _process_next_macro(self) -> None:
356
+ """Process the next macro in the queue."""
357
+ if self._current_macro_index >= len(self._pending_macros):
358
+ # All macros processed
359
+ self._macros_resolved = True
360
+ self._update_content_status()
361
+
362
+ resolved_keys = {
363
+ (m.macro_type, m.query)
364
+ for m in self._all_macros
365
+ if m.original_text in self._replacements
366
+ }
367
+ resolved_count = len(resolved_keys)
368
+ total_unique = len(self._pending_macros)
369
+ total_instances = len(self._all_macros)
370
+
371
+ if total_instances > total_unique:
372
+ self.app.notify(
373
+ f"Resolution complete: {resolved_count}/{total_unique} unique macros resolved ({total_instances} instances)",
374
+ severity="information",
375
+ )
376
+ else:
377
+ self.app.notify(
378
+ f"Resolution complete: {resolved_count}/{total_unique} macros resolved",
379
+ severity="information",
380
+ )
381
+ return
382
+
383
+ macro = self._pending_macros[self._current_macro_index]
384
+
385
+ # Open resolution modal for this macro
386
+ self.app.push_screen(
387
+ ResolutionModal(
388
+ client=self._client,
389
+ macro_type=macro.macro_type,
390
+ query=macro.query,
391
+ ),
392
+ self._on_macro_resolved,
393
+ )
394
+
395
+ def _on_macro_resolved(self, result: dict[str, Any] | None) -> None:
396
+ """Callback when a macro resolution modal is dismissed."""
397
+ macro = self._pending_macros[self._current_macro_index]
398
+
399
+ if result is not None:
400
+ # User selected a value
401
+ resolved_value = result["value"]
402
+ jinja_replacement = build_jinja_replacement(
403
+ macro.macro_type, resolved_value
404
+ )
405
+
406
+ # Find all macros with the same (macro_type, query) and add replacements
407
+ matching_count = 0
408
+ for m in self._all_macros:
409
+ if m.macro_type == macro.macro_type and m.query == macro.query:
410
+ self._replacements[m.original_text] = jinja_replacement
411
+ matching_count += 1
412
+
413
+ if matching_count > 1:
414
+ self.app.notify(
415
+ f"Resolved {matching_count} instances of @{macro.macro_type}({macro.query}) -> {result['display']}",
416
+ severity="information",
417
+ )
418
+ else:
419
+ self.app.notify(
420
+ f"Resolved {macro.original_text} -> {result['display']}",
421
+ severity="information",
422
+ )
423
+ else:
424
+ # User skipped this macro
425
+ self.app.notify(
426
+ f"Skipped resolution for {macro.original_text}",
427
+ severity="warning",
428
+ )
429
+
430
+ # Move to next macro
431
+ self._current_macro_index += 1
432
+ self._process_next_macro()
433
+
434
+ @work(exclusive=True)
435
+ async def _finalize_submission(self) -> None:
436
+ """Compile content and submit to API."""
437
+ try:
438
+ # Apply all replacements
439
+ final_content = compile_content(self._content, self._replacements)
440
+
441
+ # Build the request
442
+ request = self._build_request(final_content)
443
+
444
+ # Submit to API
445
+ response = await self._client.create_template(request)
446
+
447
+ # Return success result
448
+ result = TemplateCreateResult(
449
+ template_id=str(response.template.id),
450
+ template_name=response.template.name,
451
+ version_id=str(response.version.id),
452
+ version_number=response.version.version,
453
+ )
454
+ self.dismiss(result)
455
+
456
+ except Exception as e:
457
+ self._show_error(f"Failed to create template: {e}")
458
+
459
+ # Template-specific RadioSet parsers (not scope-related)
460
+ def _get_content_type(self) -> TemplateContentType:
461
+ """Get content type from RadioSet."""
462
+ radios = self.query_one("#content-type-radios", RadioSet)
463
+ pressed = radios.pressed_button
464
+ if pressed is None or pressed.id == "type-system":
465
+ return TemplateContentType.SYSTEM_INSTRUCTION
466
+ elif pressed.id == "type-user":
467
+ return TemplateContentType.USER_MESSAGE
468
+ else:
469
+ return TemplateContentType.FRAGMENT
470
+
471
+ def _get_visibility(self) -> TemplateVisibility:
472
+ """Get visibility from RadioSet."""
473
+ radios = self.query_one("#visibility-radios", RadioSet)
474
+ pressed = radios.pressed_button
475
+ if pressed is None or pressed.id == "vis-private":
476
+ return TemplateVisibility.PRIVATE
477
+ elif pressed.id == "vis-org":
478
+ return TemplateVisibility.ORGANIZATION
479
+ else:
480
+ return TemplateVisibility.PUBLIC
481
+
482
+ def _build_request(self, final_content: str) -> CreateTemplateRequest:
483
+ """Build the API request."""
484
+ name = self.query_one("#name-input", Input).value.strip()
485
+ description = self.query_one("#description-input", Input).value.strip() or None
486
+
487
+ tag_picker = self.query_one("#tag-picker", TagPicker)
488
+ tag_paths = tag_picker.selected_tags
489
+
490
+ upsert = self.query_one("#upsert-checkbox", Checkbox).value
491
+ escape_jinja = self.query_one("#escape-jinja-checkbox", Checkbox).value
492
+
493
+ return CreateTemplateRequest(
494
+ name=name,
495
+ content_type=self._get_content_type(),
496
+ visibility=self._get_visibility(),
497
+ initial_content=final_content,
498
+ tag_paths=tag_paths,
499
+ description=description,
500
+ upsert=upsert,
501
+ escape_jinja=escape_jinja,
502
+ )