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,469 @@
1
+ """Base search picker classes with common patterns.
2
+
3
+ Provides abstract base classes for building search pickers that fetch data
4
+ from the server API on each keystroke. Two variants are provided:
5
+
6
+ - SingleSelectPicker: For selecting a single item (agents, schemas, templates)
7
+ - MultiSelectPicker: For selecting multiple items (models, tags)
8
+
9
+ Both handle the common patterns of:
10
+ - Input field with search
11
+ - OptionList displaying results
12
+ - Status line showing search state
13
+ - Selected display showing current selection(s)
14
+ - Debounced API calls via @work(exclusive=True)
15
+ - Error handling for API failures
16
+ """
17
+
18
+ from abc import abstractmethod
19
+ from typing import Any, Generic, TypeVar
20
+
21
+ from textual import on, work
22
+ from textual.app import ComposeResult
23
+ from textual.containers import Vertical
24
+ from textual.message import Message
25
+ from textual.widget import Widget
26
+ from textual.widgets import Input, OptionList, Static
27
+ from textual.widgets.option_list import Option
28
+
29
+ from alloy_runtime_sdk.api_client.client import ApiClient
30
+ from alloy_runtime_sdk.exceptions.errors import RequestError
31
+
32
+ # Type variable for the item type stored in search results
33
+ TItem = TypeVar("TItem")
34
+
35
+
36
+ class BaseSearchPicker(Widget, Generic[TItem]):
37
+ """Abstract base class for search pickers.
38
+
39
+ Subclasses must implement:
40
+ - _fetch_items(query): Fetch items from API
41
+ - _format_item(item): Format item for display in option list
42
+ - _get_item_id(item): Get unique identifier for an item
43
+ - _is_item_selected(item): Check if item is currently selected
44
+ - _handle_item_selection(index): Handle selection of item at index
45
+ - _format_selection_display(): Format current selection for display
46
+ - _get_result_count_message(count): Get status message for result count
47
+ """
48
+
49
+ # All pickers use the shared .picker CSS class from forms.tcss
50
+ DEFAULT_CLASSES = "picker"
51
+
52
+ def __init__(
53
+ self,
54
+ client: ApiClient,
55
+ placeholder: str = "Type to search...",
56
+ empty_message: str = "No selection",
57
+ fetch_on_mount: bool = False,
58
+ **kwargs: Any,
59
+ ) -> None:
60
+ """Initialize the picker.
61
+
62
+ Args:
63
+ client: ApiClient instance for API calls
64
+ placeholder: Placeholder text for search input
65
+ empty_message: Message shown when nothing is selected
66
+ fetch_on_mount: If True, fetch initial results on mount (e.g., recent items)
67
+ """
68
+ super().__init__(**kwargs)
69
+ self._client = client
70
+ self._placeholder = placeholder
71
+ self._empty_message = empty_message
72
+ self._search_results: list[TItem] = []
73
+ self._last_query: str = ""
74
+ self._fetch_on_mount = fetch_on_mount
75
+
76
+ def compose(self) -> ComposeResult:
77
+ with Vertical():
78
+ yield Input(placeholder=self._placeholder, id="search-input")
79
+ yield OptionList(id="search-options")
80
+ yield Static("Type to search...", classes="status-line", id="status")
81
+ yield Static(self._empty_message, classes="selected-display", id="selected")
82
+
83
+ def on_mount(self) -> None:
84
+ """Optionally fetch initial results on mount."""
85
+ if self._fetch_on_mount:
86
+ self._fetch_initial()
87
+
88
+ @on(Input.Changed, "#search-input")
89
+ def on_search_changed(self, event: Input.Changed) -> None:
90
+ """Fetch results from API on each keystroke."""
91
+ query = event.value.strip()
92
+ if query != self._last_query:
93
+ self._last_query = query
94
+ self._search(query)
95
+
96
+ @work(exclusive=True, group="picker_search")
97
+ async def _fetch_initial(self) -> None:
98
+ """Fetch initial results on mount (e.g., recent items)."""
99
+ status = self.query_one("#status", Static)
100
+ status.update("Loading...")
101
+
102
+ try:
103
+ self._search_results = await self._fetch_items("")
104
+ self._update_options()
105
+
106
+ count = len(self._search_results)
107
+ if count > 0:
108
+ status.update(f"{count} recent - type to filter")
109
+ else:
110
+ status.update("Type to search...")
111
+
112
+ except Exception as e:
113
+ status.update(f"[red]Error: {e}[/]")
114
+ self._search_results = []
115
+
116
+ @work(exclusive=True, group="picker_search")
117
+ async def _search(self, query: str) -> None:
118
+ """Fetch items matching query from the API."""
119
+ status = self.query_one("#status", Static)
120
+ options = self.query_one("#search-options", OptionList)
121
+
122
+ if not query:
123
+ if self._fetch_on_mount:
124
+ # Re-fetch initial results when query is cleared
125
+ await self._do_search("")
126
+ return
127
+ else:
128
+ status.update("Type to search...")
129
+ options.clear_options()
130
+ self._search_results = []
131
+ return
132
+
133
+ await self._do_search(query)
134
+
135
+ async def _do_search(self, query: str) -> None:
136
+ """Perform the actual search."""
137
+ status = self.query_one("#status", Static)
138
+ options = self.query_one("#search-options", OptionList)
139
+
140
+ status.update("Searching...")
141
+
142
+ try:
143
+ self._search_results = await self._fetch_items(query)
144
+ self._update_options()
145
+
146
+ count = len(self._search_results)
147
+ if query:
148
+ status.update(self._get_result_count_message(count))
149
+ elif count > 0:
150
+ status.update(f"{count} recent - type to filter")
151
+ else:
152
+ status.update("Type to search...")
153
+
154
+ except RequestError as e:
155
+ status.update(f"[red]Error: {e}[/]")
156
+ self._search_results = []
157
+ options.clear_options()
158
+ except Exception as e:
159
+ status.update(f"[red]Error: {e}[/]")
160
+ self._search_results = []
161
+ options.clear_options()
162
+
163
+ def _update_options(self) -> None:
164
+ """Update the option list with current search results."""
165
+ options = self.query_one("#search-options", OptionList)
166
+ options.clear_options()
167
+
168
+ for i, item in enumerate(self._search_results):
169
+ display_text = self._format_item(item)
170
+ if self._is_item_selected(item):
171
+ display_text = f"[green]✓[/] {display_text}"
172
+ else:
173
+ display_text = f" {display_text}"
174
+ options.add_option(Option(display_text, id=f"opt-{i}"))
175
+
176
+ if self._search_results:
177
+ options.highlighted = 0
178
+
179
+ def _update_selected_display(self) -> None:
180
+ """Update the display of selected item(s)."""
181
+ display = self.query_one("#selected", Static)
182
+ selection_text = self._format_selection_display()
183
+ if selection_text:
184
+ display.update(selection_text)
185
+ display.add_class("has-selection")
186
+ else:
187
+ display.update(self._empty_message)
188
+ display.remove_class("has-selection")
189
+
190
+ @on(OptionList.OptionSelected, "#search-options")
191
+ def on_option_selected(self, event: OptionList.OptionSelected) -> None:
192
+ """Handle option selection via click or enter."""
193
+ self._handle_item_selection(event.option_index)
194
+
195
+ @abstractmethod
196
+ async def _fetch_items(self, query: str) -> list[TItem]:
197
+ """Fetch items from API matching query.
198
+
199
+ Args:
200
+ query: Search query string
201
+
202
+ Returns:
203
+ List of items matching the query
204
+ """
205
+ ...
206
+
207
+ @abstractmethod
208
+ def _format_item(self, item: TItem) -> str:
209
+ """Format item for display in option list.
210
+
211
+ Args:
212
+ item: Item to format
213
+
214
+ Returns:
215
+ Formatted string for display
216
+ """
217
+ ...
218
+
219
+ @abstractmethod
220
+ def _get_item_id(self, item: TItem) -> str:
221
+ """Get unique identifier for an item.
222
+
223
+ Args:
224
+ item: Item to get ID for
225
+
226
+ Returns:
227
+ Unique identifier string
228
+ """
229
+ ...
230
+
231
+ @abstractmethod
232
+ def _is_item_selected(self, item: TItem) -> bool:
233
+ """Check if an item is currently selected.
234
+
235
+ Args:
236
+ item: Item to check
237
+
238
+ Returns:
239
+ True if item is selected
240
+ """
241
+ ...
242
+
243
+ @abstractmethod
244
+ def _handle_item_selection(self, index: int) -> None:
245
+ """Handle selection of item at the given index.
246
+
247
+ Args:
248
+ index: Index of item in search results
249
+ """
250
+ ...
251
+
252
+ @abstractmethod
253
+ def _format_selection_display(self) -> str | None:
254
+ """Format current selection for display.
255
+
256
+ Returns:
257
+ Formatted string for display, or None if nothing selected
258
+ """
259
+ ...
260
+
261
+ def _get_result_count_message(self, count: int) -> str:
262
+ """Get status message for result count.
263
+
264
+ Args:
265
+ count: Number of results found
266
+
267
+ Returns:
268
+ Status message string
269
+ """
270
+ if count == 0:
271
+ return "No results found"
272
+ return f"{count} result{'s' if count != 1 else ''} - Enter to select"
273
+
274
+ @abstractmethod
275
+ def clear(self) -> None:
276
+ """Clear the current selection."""
277
+ ...
278
+
279
+
280
+ class SingleSelectPicker(BaseSearchPicker[TItem], Generic[TItem]):
281
+ """Base class for single-selection pickers.
282
+
283
+ Handles the common pattern of selecting one item from search results
284
+ with toggle behavior (selecting same item deselects it).
285
+
286
+ Subclasses must implement:
287
+ - _fetch_items(query): Fetch items from API
288
+ - _format_item(item): Format item for display
289
+ - _get_item_id(item): Get unique identifier for item
290
+ """
291
+
292
+ class SelectionChanged(Message):
293
+ """Posted when selection changes."""
294
+
295
+ def __init__(self, selected_id: str | None, selected_item: Any | None) -> None:
296
+ self.selected_id = selected_id
297
+ self.selected_item = selected_item
298
+ super().__init__()
299
+
300
+ def __init__(
301
+ self,
302
+ client: ApiClient,
303
+ placeholder: str = "Type to search...",
304
+ empty_message: str = "No selection",
305
+ **kwargs: Any,
306
+ ) -> None:
307
+ super().__init__(
308
+ client=client,
309
+ placeholder=placeholder,
310
+ empty_message=empty_message,
311
+ **kwargs,
312
+ )
313
+ self._selected_item: TItem | None = None
314
+
315
+ @property
316
+ def selected_id(self) -> str | None:
317
+ """Get the ID of the selected item, or None if nothing selected."""
318
+ if self._selected_item is None:
319
+ return None
320
+ return self._get_item_id(self._selected_item)
321
+
322
+ @property
323
+ def selected_item(self) -> TItem | None:
324
+ """Get the full selected item, or None if nothing selected."""
325
+ return self._selected_item
326
+
327
+ def _is_item_selected(self, item: TItem) -> bool:
328
+ """Check if an item is currently selected."""
329
+ if self._selected_item is None:
330
+ return False
331
+ return self._get_item_id(item) == self._get_item_id(self._selected_item)
332
+
333
+ def _handle_item_selection(self, index: int) -> None:
334
+ """Handle selection of item at the given index with toggle behavior."""
335
+ if index < 0 or index >= len(self._search_results):
336
+ return
337
+
338
+ item = self._search_results[index]
339
+
340
+ # Toggle selection if clicking the same item
341
+ if self._selected_item is not None and self._get_item_id(
342
+ item
343
+ ) == self._get_item_id(self._selected_item):
344
+ self._selected_item = None
345
+ else:
346
+ self._selected_item = item
347
+
348
+ self._update_selected_display()
349
+ self._update_options()
350
+ self.post_message(self.SelectionChanged(self.selected_id, self._selected_item))
351
+
352
+ def _format_selection_display(self) -> str | None:
353
+ """Format current selection for display."""
354
+ if self._selected_item is None:
355
+ return None
356
+ display_text = self._format_item(self._selected_item)
357
+ return f"[bold green]Selected:[/] {display_text}"
358
+
359
+ def clear(self) -> None:
360
+ """Clear the selection."""
361
+ self._selected_item = None
362
+ self._update_selected_display()
363
+ self.post_message(self.SelectionChanged(None, None))
364
+
365
+ def set_initial_selection(self, item: TItem) -> None:
366
+ """Set initial selection without triggering search.
367
+
368
+ Use this to pre-populate the picker with an existing value.
369
+ Should be called after mount.
370
+
371
+ Args:
372
+ item: Item to set as initial selection
373
+ """
374
+ self._selected_item = item
375
+ self._update_selected_display()
376
+
377
+
378
+ class MultiSelectPicker(BaseSearchPicker[TItem], Generic[TItem]):
379
+ """Base class for multi-selection pickers.
380
+
381
+ Handles the common pattern of selecting multiple items from search results.
382
+ Items can be toggled on/off independently.
383
+
384
+ Subclasses must implement:
385
+ - _fetch_items(query): Fetch items from API
386
+ - _format_item(item): Format item for display
387
+ - _get_item_id(item): Get unique identifier for item
388
+ - _format_selection_display(): Format the multi-selection display
389
+ """
390
+
391
+ class SelectionChanged(Message):
392
+ """Posted when selection changes."""
393
+
394
+ def __init__(self, selected_items: list[Any]) -> None:
395
+ self.selected_items = selected_items
396
+ super().__init__()
397
+
398
+ def __init__(
399
+ self,
400
+ client: ApiClient,
401
+ placeholder: str = "Type to search...",
402
+ empty_message: str = "No selection",
403
+ **kwargs: Any,
404
+ ) -> None:
405
+ super().__init__(
406
+ client=client,
407
+ placeholder=placeholder,
408
+ empty_message=empty_message,
409
+ **kwargs,
410
+ )
411
+ # Store selected items as dict for O(1) lookup by ID
412
+ self._selected_items: dict[str, TItem] = {}
413
+
414
+ @property
415
+ def selected_ids(self) -> list[str]:
416
+ """Get the IDs of all selected items."""
417
+ return list(self._selected_items.keys())
418
+
419
+ @property
420
+ def selected_items(self) -> list[TItem]:
421
+ """Get all selected items."""
422
+ return list(self._selected_items.values())
423
+
424
+ def _is_item_selected(self, item: TItem) -> bool:
425
+ """Check if an item is currently selected."""
426
+ return self._get_item_id(item) in self._selected_items
427
+
428
+ def _handle_item_selection(self, index: int) -> None:
429
+ """Handle selection of item at the given index with toggle behavior."""
430
+ if index < 0 or index >= len(self._search_results):
431
+ return
432
+
433
+ item = self._search_results[index]
434
+ item_id = self._get_item_id(item)
435
+
436
+ # Toggle selection
437
+ if item_id in self._selected_items:
438
+ del self._selected_items[item_id]
439
+ else:
440
+ self._selected_items[item_id] = item
441
+
442
+ self._update_selected_display()
443
+ self._update_options()
444
+ self._post_selection_changed()
445
+
446
+ def _post_selection_changed(self) -> None:
447
+ """Post selection changed message. Override for custom message types."""
448
+ self.post_message(self.SelectionChanged(self.selected_items))
449
+
450
+ def clear(self) -> None:
451
+ """Clear all selections."""
452
+ self._selected_items.clear()
453
+ self._update_selected_display()
454
+ self._post_selection_changed()
455
+
456
+ def set_initial_selections(self, items: list[TItem]) -> None:
457
+ """Set initial selections without triggering search.
458
+
459
+ Use this to pre-populate the picker with existing values.
460
+ Should be called after mount.
461
+
462
+ Args:
463
+ items: Items to set as initial selections (order is preserved)
464
+ """
465
+ self._selected_items.clear()
466
+ for item in items:
467
+ item_id = self._get_item_id(item)
468
+ self._selected_items[item_id] = item
469
+ self._update_selected_display()
@@ -0,0 +1,126 @@
1
+ """Reusable styled form components for Textual apps.
2
+
3
+ This module provides low-level, styled form components that can be composed
4
+ to create consistent-looking forms across the CLI. Each component is just
5
+ a styled wrapper - you wire up your own logic.
6
+
7
+ Usage:
8
+ from cli.infrastructure.forms.components import (
9
+ FormContainer,
10
+ FormTitle,
11
+ FormSection,
12
+ FormField,
13
+ FormRow,
14
+ FormButtons,
15
+ FormError,
16
+ )
17
+
18
+ def compose(self) -> ComposeResult:
19
+ with FormContainer():
20
+ yield FormTitle("Create Something")
21
+ yield FormError(id="error")
22
+
23
+ yield FormSection("Required")
24
+ with FormRow():
25
+ yield FormField("Name", Input(id="name"))
26
+ yield FormField("Type", Select(..., id="type"))
27
+
28
+ yield FormSection("Optional")
29
+ with FormRow():
30
+ yield FormField("Description", Input(id="desc"))
31
+
32
+ yield FormButtons()
33
+ """
34
+
35
+ from typing import Any
36
+
37
+ from textual.app import ComposeResult
38
+ from textual.containers import Center, Horizontal, Vertical, VerticalScroll
39
+ from textual.widget import Widget
40
+ from textual.widgets import Button, Static
41
+
42
+
43
+ class FormContainer(VerticalScroll):
44
+ """Scrollable container for a form."""
45
+
46
+ def __init__(self, **kwargs: Any) -> None:
47
+ super().__init__(**kwargs)
48
+ self.add_class("form-container")
49
+
50
+
51
+ class FormTitle(Static):
52
+ """Centered form title."""
53
+
54
+ def __init__(self, title: str, **kwargs: Any) -> None:
55
+ super().__init__(title, **kwargs)
56
+ self.add_class("form-title")
57
+
58
+
59
+ class FormSection(Static):
60
+ """Section header within a form."""
61
+
62
+ def __init__(self, title: str, **kwargs: Any) -> None:
63
+ super().__init__(title, **kwargs)
64
+ self.add_class("form-section")
65
+
66
+
67
+ class FormField(Vertical):
68
+ """A labeled form field container. Pass any widget as the input."""
69
+
70
+ def __init__(self, label: str, input_widget: Widget, **kwargs: Any) -> None:
71
+ super().__init__(**kwargs)
72
+ self.add_class("form-field")
73
+ self._label = label
74
+ self._input_widget = input_widget
75
+
76
+ def compose(self) -> ComposeResult:
77
+ yield Static(self._label, classes="form-field-label")
78
+ yield self._input_widget
79
+
80
+
81
+ class FormRow(Horizontal):
82
+ """Horizontal row for side-by-side fields."""
83
+
84
+ def __init__(self, **kwargs: Any) -> None:
85
+ super().__init__(**kwargs)
86
+ self.add_class("form-row")
87
+
88
+
89
+ class FormError(Static):
90
+ """Error message display. Call show(msg) and hide()."""
91
+
92
+ def __init__(self, **kwargs: Any) -> None:
93
+ super().__init__("", **kwargs)
94
+ self.add_class("form-error")
95
+
96
+ def show(self, message: str) -> None:
97
+ """Show an error message."""
98
+ self.update(f"Error: {message}")
99
+ self.add_class("visible")
100
+
101
+ def hide(self) -> None:
102
+ """Hide the error message."""
103
+ self.remove_class("visible")
104
+
105
+
106
+ class FormButtons(Center):
107
+ """Centered submit/cancel button row."""
108
+
109
+ def __init__(
110
+ self,
111
+ submit_label: str = "Submit",
112
+ cancel_label: str = "Cancel",
113
+ submit_id: str = "submit-btn",
114
+ cancel_id: str = "cancel-btn",
115
+ **kwargs: Any,
116
+ ) -> None:
117
+ super().__init__(**kwargs)
118
+ self.add_class("form-buttons")
119
+ self._submit_label = submit_label
120
+ self._cancel_label = cancel_label
121
+ self._submit_id = submit_id
122
+ self._cancel_id = cancel_id
123
+
124
+ def compose(self) -> ComposeResult:
125
+ yield Button(self._submit_label, id=self._submit_id, variant="success")
126
+ yield Button(self._cancel_label, id=self._cancel_id, variant="error")