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,299 @@
1
+ """Agent update modal for editing existing agents.
2
+
3
+ Provides a comprehensive modal screen that allows users to edit an existing agent
4
+ with all its current fields pre-populated.
5
+ """
6
+
7
+ from typing import Any
8
+
9
+ from textual import work
10
+ from textual.widgets import Input, TextArea
11
+
12
+ from alloy_runtime_sdk.api_client.client import ApiClient
13
+ from alloy_runtime_types.dtos.agents import (
14
+ GetAgentResponse,
15
+ UpdateAgentRequest,
16
+ )
17
+ from alloy_runtime_types.dtos.models import ModelListItemResponse
18
+ from alloy_runtime_types.enums.ownership_scope import OwnershipScope
19
+
20
+ from cli.infrastructure.forms.schema_picker import SchemaPicker
21
+ from cli.infrastructure.forms.tag_picker import TagPicker
22
+ from cli.infrastructure.forms.template_picker import TemplatePicker
23
+ from cli.tui.widgets.agent_form_modal import AgentFormModal, AgentFormResult
24
+
25
+
26
+ class AgentUpdateModal(AgentFormModal):
27
+ """Modal for updating an existing agent.
28
+
29
+ Pre-populates all form fields with the current agent configuration.
30
+ Scope cannot be changed after creation.
31
+
32
+ Usage:
33
+ def on_agent_updated(result: AgentFormResult | None):
34
+ if result is not None:
35
+ self.notify(f"Updated agent: {result.agent_name}")
36
+ self._do_search("") # Refresh list
37
+
38
+ client = await self.app.store.get_client()
39
+ agent = await client.get_agent(agent_id)
40
+ self.app.push_screen(
41
+ AgentUpdateModal(client=client, agent=agent),
42
+ on_agent_updated
43
+ )
44
+ """
45
+
46
+ def __init__(
47
+ self,
48
+ client: ApiClient,
49
+ agent: GetAgentResponse,
50
+ **kwargs: Any,
51
+ ) -> None:
52
+ """Initialize the agent update modal.
53
+
54
+ Args:
55
+ client: ApiClient instance for API calls
56
+ agent: The agent to edit (full details from get_agent)
57
+ """
58
+ super().__init__(client=client, **kwargs)
59
+ self._agent = agent
60
+
61
+ def _get_modal_title(self) -> str:
62
+ """Return the modal title."""
63
+ return f"Edit Agent: {self._agent.name}"
64
+
65
+ def _get_submit_button_text(self) -> str:
66
+ """Return the submit button text."""
67
+ return "Update Agent"
68
+
69
+ def _is_scope_editable(self) -> bool:
70
+ """Return whether the scope can be changed (not allowed for updates)."""
71
+ return False
72
+
73
+ def on_mount(self) -> None:
74
+ """Populate form fields with existing agent data."""
75
+ super().on_mount()
76
+ self._populate_form_async()
77
+
78
+ @work(exclusive=True)
79
+ async def _populate_form_async(self) -> None:
80
+ """Populate all form fields with the existing agent data (async for API calls)."""
81
+ agent = self._agent
82
+
83
+ # Basic fields
84
+ self._set_name(agent.name)
85
+ self._set_description(agent.description)
86
+
87
+ # Scope (read-only, just display)
88
+ scope = self._infer_scope_from_agent(agent)
89
+ self._set_scope(scope)
90
+
91
+ # Models - need to convert AgentModelResponse to ModelListItemResponse-like objects
92
+ if agent.models:
93
+ model_items = [
94
+ ModelListItemResponse(
95
+ provider_key=m.provider_key.value, # Use .value to get string from enum
96
+ provider_model_name=m.provider_model_name,
97
+ is_active=True, # Assume active since it's assigned to agent
98
+ input_modalities=["text"], # Default, actual not stored on agent
99
+ output_modalities=["text"], # Default, actual not stored on agent
100
+ )
101
+ for m in sorted(agent.models, key=lambda x: x.preference_order)
102
+ ]
103
+ self._set_models(model_items)
104
+
105
+ # Tags - need to convert AgentTagResponse to dict format
106
+ if agent.tags:
107
+ tag_items = [
108
+ {
109
+ "tag_path": t.tag_path,
110
+ "display_name": t.display_name,
111
+ "id": str(t.tag_id),
112
+ }
113
+ for t in agent.tags
114
+ ]
115
+ self._set_tags(tag_items)
116
+
117
+ # Base agent
118
+ if agent.base_agent_id:
119
+ self._set_base_agent(str(agent.base_agent_id), "Base Agent")
120
+
121
+ # System instruction template - fetch actual data
122
+ if agent.system_instruction_version_id:
123
+ template_data = await self._fetch_template_data(
124
+ str(agent.system_instruction_version_id)
125
+ )
126
+ if template_data:
127
+ # Use the set_initial_selection with full data for proper display
128
+ template_picker = self.query_one(
129
+ "#system-template-picker", TemplatePicker
130
+ )
131
+ template_picker.set_initial_selection(template_data)
132
+
133
+ # Output schema - fetch actual data
134
+ if agent.output_schema_id:
135
+ schema_data = await self._fetch_schema_data(str(agent.output_schema_id))
136
+ if schema_data:
137
+ # Use the set_initial_selection with full data for proper display
138
+ output_schema_picker = self.query_one(
139
+ "#output-schema-picker", SchemaPicker
140
+ )
141
+ output_schema_picker.set_initial_selection(schema_data)
142
+
143
+ # Generation params
144
+ if agent.generation_params:
145
+ self._set_generation_params(agent.generation_params)
146
+
147
+ # Default headers
148
+ if agent.default_request_headers:
149
+ self._set_default_headers(agent.default_request_headers)
150
+
151
+ # Tools
152
+ if agent.tools:
153
+ self._set_tools(agent.tools)
154
+
155
+ def _infer_scope_from_agent(self, agent: GetAgentResponse) -> OwnershipScope:
156
+ """Infer the scope from agent ownership fields."""
157
+ if agent.user_id:
158
+ return OwnershipScope.USER
159
+ elif agent.organization_id:
160
+ return OwnershipScope.ORGANIZATION
161
+ else:
162
+ return OwnershipScope.GLOBAL
163
+
164
+ async def _fetch_template_data(self, version_id: str) -> dict[str, Any] | None:
165
+ """Fetch the template data for a given version ID.
166
+
167
+ Args:
168
+ version_id: Template version UUID
169
+
170
+ Returns:
171
+ Template data dict for display, or None if fetch fails
172
+ """
173
+ try:
174
+ # Get template by version ID using the new endpoint
175
+ from uuid import UUID
176
+
177
+ response = await self._client.get_template_by_version(UUID(version_id))
178
+
179
+ # Find the specific version to get its version number
180
+ matching_version = next(
181
+ (v for v in response.versions if str(v.id) == version_id), None
182
+ )
183
+ version_number = matching_version.version if matching_version else "?"
184
+
185
+ # Build data dict that matches what the picker's formatter expects
186
+ return {
187
+ "latest_version_id": version_id,
188
+ "name": response.template.name,
189
+ "latest_version_number": version_number,
190
+ "visibility_id": response.template.visibility_id,
191
+ "content_type_id": response.template.content_type_id,
192
+ }
193
+ except Exception:
194
+ # If fetch fails, create a minimal fallback dict
195
+ return {
196
+ "latest_version_id": version_id,
197
+ "name": f"Template ({version_id[:8]}...)",
198
+ "latest_version_number": "?",
199
+ "visibility_id": "private",
200
+ "content_type_id": "",
201
+ }
202
+
203
+ async def _fetch_schema_data(self, schema_id: str) -> dict[str, Any] | None:
204
+ """Fetch the schema data for a given schema ID.
205
+
206
+ Args:
207
+ schema_id: Schema UUID
208
+
209
+ Returns:
210
+ Schema data dict for display, or None if fetch fails
211
+ """
212
+ try:
213
+ response = await self._client.get_schema(schema_id)
214
+ # Build data dict that matches what the picker's formatter expects
215
+ return {
216
+ "id": schema_id,
217
+ "schema_name": response.schema_name,
218
+ "version": response.version,
219
+ "schema_format_id": response.schema_format_id,
220
+ "user_id": str(response.user_id) if response.user_id else None,
221
+ "organization_id": str(response.organization_id)
222
+ if response.organization_id
223
+ else None,
224
+ "description": response.description,
225
+ }
226
+ except Exception:
227
+ # If fetch fails, create a minimal fallback dict
228
+ return {
229
+ "id": schema_id,
230
+ "schema_name": f"Schema ({schema_id[:8]}...)",
231
+ "version": "?",
232
+ "schema_format_id": "unknown",
233
+ "user_id": None,
234
+ "organization_id": None,
235
+ "description": None,
236
+ }
237
+
238
+ async def _submit_form(self) -> AgentFormResult:
239
+ """Submit the form to update the agent."""
240
+ request = self._build_update_request()
241
+ response = await self._client.update_agent(self._agent.id, request)
242
+
243
+ return AgentFormResult(
244
+ agent_id=str(response.id),
245
+ agent_name=response.name,
246
+ is_update=True,
247
+ )
248
+
249
+ def _build_update_request(self) -> UpdateAgentRequest:
250
+ """Build the UpdateAgentRequest from form fields."""
251
+ # Name
252
+ name = self.query_one("#name-input", Input).value.strip()
253
+
254
+ # Models
255
+ model_configs = self._build_model_configs()
256
+
257
+ # Tags
258
+ tag_picker = self.query_one("#tag-picker", TagPicker)
259
+ tags = tag_picker.selected_tags
260
+
261
+ # Description
262
+ description = self.query_one("#description-input", Input).value.strip() or None
263
+
264
+ # System instruction template
265
+ template_picker = self.query_one("#system-template-picker", TemplatePicker)
266
+ system_instruction_version_id = self._parse_uuid(
267
+ template_picker.selected_id, "System Template"
268
+ )
269
+
270
+ # Schemas
271
+ output_schema_picker = self.query_one("#output-schema-picker", SchemaPicker)
272
+ output_schema_id = self._parse_uuid(
273
+ output_schema_picker.selected_id, "Output Schema"
274
+ )
275
+
276
+ # Output schema from JSON builder
277
+ output_schema = self._get_output_schema()
278
+
279
+ # Generation parameters
280
+ gen_params = self._build_generation_params()
281
+
282
+ # Default headers
283
+ default_headers = self._parse_json(
284
+ self.query_one("#default-headers-textarea", TextArea).text,
285
+ "Default Headers",
286
+ )
287
+
288
+ return UpdateAgentRequest(
289
+ name=name,
290
+ models=model_configs,
291
+ tags=tags,
292
+ description=description,
293
+ system_instruction_version_id=system_instruction_version_id,
294
+ output_schema_id=output_schema_id,
295
+ output_schema=output_schema,
296
+ default_request_headers=default_headers,
297
+ generation_params=gen_params,
298
+ tools=self._build_tools(),
299
+ )
@@ -0,0 +1,77 @@
1
+ """Base class for form modals with error handling.
2
+
3
+ Provides common functionality for all form modals:
4
+ - Standard cancel/submit bindings
5
+ - Error display methods
6
+ - Auto-hide error on input change
7
+ """
8
+
9
+ from typing import Generic, TypeVar
10
+
11
+ from textual import on
12
+ from textual.binding import Binding
13
+ from textual.screen import ModalScreen
14
+ from textual.widgets import Input, Static, TextArea
15
+
16
+ T = TypeVar("T")
17
+
18
+
19
+ class BaseFormModal(ModalScreen[T | None], Generic[T]):
20
+ """Abstract base for all form modals with error handling.
21
+
22
+ Provides:
23
+ - Standard cancel/submit bindings (escape, ctrl+s)
24
+ - Error display methods (_show_error, _hide_error)
25
+ - Auto-hide error on input/textarea change
26
+ - Standard action_cancel implementation
27
+
28
+ Subclasses must:
29
+ - Include Static(id="error-display") in compose()
30
+ - Implement action_submit()
31
+
32
+ Usage:
33
+ class MyModal(BaseFormModal[MyResult]):
34
+ def compose(self) -> ComposeResult:
35
+ # ... form fields ...
36
+ yield Static("", id="error-display", classes="error-display")
37
+ # ... buttons ...
38
+
39
+ def action_submit(self) -> None:
40
+ try:
41
+ self._validate()
42
+ self._hide_error()
43
+ self._finalize()
44
+ except ValueError as e:
45
+ self._show_error(str(e))
46
+ """
47
+
48
+ BINDINGS = [
49
+ Binding("escape", "cancel", "Cancel", show=True),
50
+ Binding("ctrl+s", "submit", "Submit", show=True, priority=True),
51
+ ]
52
+
53
+ def _show_error(self, message: str) -> None:
54
+ """Show an error message."""
55
+ error_display = self.query_one("#error-display", Static)
56
+ error_display.update(f"[red]Error: {message}[/]")
57
+ error_display.add_class("visible")
58
+
59
+ def _hide_error(self) -> None:
60
+ """Hide the error display."""
61
+ error_display = self.query_one("#error-display", Static)
62
+ error_display.update("")
63
+ error_display.remove_class("visible")
64
+
65
+ def action_cancel(self) -> None:
66
+ """Cancel and dismiss the modal."""
67
+ self.dismiss(None)
68
+
69
+ @on(Input.Changed)
70
+ def on_input_changed(self, event: Input.Changed) -> None:
71
+ """Auto-hide error when any input changes."""
72
+ self._hide_error()
73
+
74
+ @on(TextArea.Changed)
75
+ def on_textarea_changed(self, event: TextArea.Changed) -> None:
76
+ """Auto-hide error when any textarea changes."""
77
+ self._hide_error()
@@ -0,0 +1,75 @@
1
+ """Confirmation modal for destructive actions."""
2
+
3
+ from typing import Any
4
+
5
+ from textual import on
6
+ from textual.app import ComposeResult
7
+ from textual.binding import Binding
8
+ from textual.containers import Horizontal, Vertical
9
+ from textual.screen import ModalScreen
10
+ from textual.widgets import Button, Static
11
+
12
+
13
+ class ConfirmModal(ModalScreen[bool]):
14
+ """Modal for confirming destructive actions.
15
+
16
+ Usage:
17
+ def callback(confirmed: bool) -> None:
18
+ if confirmed:
19
+ # Perform action
20
+ pass
21
+
22
+ self.app.push_screen(
23
+ ConfirmModal(
24
+ title="Delete Agent",
25
+ message="Delete agent 'my-agent'? This cannot be undone.",
26
+ ),
27
+ callback
28
+ )
29
+ """
30
+
31
+ BINDINGS = [
32
+ Binding("escape", "cancel", "Cancel", show=True),
33
+ Binding("n", "cancel", "No", show=False),
34
+ ]
35
+
36
+ def __init__(
37
+ self,
38
+ title: str = "Confirm Action",
39
+ message: str = "Are you sure?",
40
+ **kwargs: Any,
41
+ ) -> None:
42
+ """Initialize the confirmation modal.
43
+
44
+ Args:
45
+ title: Modal title
46
+ message: Confirmation message to display
47
+ **kwargs: Additional keyword arguments for ModalScreen
48
+ """
49
+ super().__init__(**kwargs)
50
+ self._title = title
51
+ self._message = message
52
+
53
+ def compose(self) -> ComposeResult:
54
+ """Compose the modal layout."""
55
+ with Vertical(id="confirm-modal"):
56
+ yield Static(self._title, classes="modal-title")
57
+ yield Static(self._message, id="confirm-message")
58
+
59
+ with Horizontal(classes="button-row"):
60
+ yield Button("Cancel", id="cancel-btn", variant="default")
61
+ yield Button("Confirm", id="confirm-btn", variant="error")
62
+
63
+ @on(Button.Pressed, "#confirm-btn")
64
+ def on_confirm_pressed(self, event: Button.Pressed) -> None:
65
+ """Confirm the action."""
66
+ self.dismiss(True)
67
+
68
+ @on(Button.Pressed, "#cancel-btn")
69
+ def on_cancel_pressed(self, event: Button.Pressed) -> None:
70
+ """Cancel the action."""
71
+ self.dismiss(False)
72
+
73
+ def action_cancel(self) -> None:
74
+ """Cancel via escape or n key."""
75
+ self.dismiss(False)
@@ -0,0 +1,145 @@
1
+ """Help modal showing keyboard shortcuts and features.
2
+
3
+ Provides a modal screen with comprehensive keyboard shortcut reference
4
+ for all screens in the TUI application.
5
+ """
6
+
7
+ from typing import Any
8
+
9
+ from textual import on
10
+ from textual.app import ComposeResult
11
+ from textual.binding import Binding
12
+ from textual.containers import Vertical, VerticalScroll
13
+ from textual.screen import ModalScreen
14
+ from textual.widgets import Button, Static
15
+
16
+
17
+ class HelpModal(ModalScreen[None]):
18
+ """Modal showing keyboard shortcuts and help information.
19
+
20
+ Usage:
21
+ self.app.push_screen(HelpModal())
22
+ """
23
+
24
+ BINDINGS = [
25
+ Binding("escape", "close", "Close", show=True),
26
+ Binding("q", "close", "Close", show=False),
27
+ ]
28
+
29
+ def __init__(self, **kwargs: Any) -> None:
30
+ super().__init__(**kwargs)
31
+
32
+ def compose(self) -> ComposeResult:
33
+ with Vertical():
34
+ yield Static("Keyboard Shortcuts", classes="modal-title")
35
+
36
+ with VerticalScroll():
37
+ # Global navigation (works everywhere)
38
+ yield Static("[bold]Global Navigation[/]", classes="section-title")
39
+ yield Static("[cyan]c[/] Switch to Chat screen")
40
+ yield Static("[cyan]a[/] Switch to Agents screen")
41
+ yield Static("[cyan]t[/] Switch to Templates screen")
42
+ yield Static("[cyan]m[/] Switch to Content (media) screen")
43
+ yield Static("[cyan]s[/] Switch to Schemas screen")
44
+ yield Static("[cyan]g[/] Switch to Tool Configs screen")
45
+ yield Static("[cyan]d[/] Show Dashboard")
46
+ yield Static("[cyan]?[/] Show this help")
47
+ yield Static("[cyan]Ctrl+C[/] Quit application")
48
+
49
+ # Chat screen
50
+ yield Static("[bold]Chat Screen[/]", classes="section-title")
51
+ yield Static("[cyan]Ctrl+N[/] New chat session")
52
+ yield Static("[cyan]Ctrl+D[/] Send message")
53
+ yield Static("[cyan]Ctrl+E[/] Open message in $EDITOR")
54
+ yield Static("[cyan]Ctrl+R[/] Regenerate last response")
55
+ yield Static("[cyan]Ctrl+U[/] Undo last turn")
56
+ yield Static("[cyan]Ctrl+Y[/] Copy last response")
57
+ yield Static("[cyan]Ctrl+Shift+Y[/] Copy all messages")
58
+ yield Static("[cyan]Ctrl+L[/] Clear display")
59
+ yield Static("[cyan]Ctrl+B[/] Toggle sidebar")
60
+ yield Static("[cyan]Escape[/] Cancel streaming / Focus input")
61
+ yield Static("[cyan]g[/] Scroll to top")
62
+ yield Static("[cyan]G[/] Scroll to bottom")
63
+
64
+ # Chat split view
65
+ yield Static("[bold]Chat Split View[/]", classes="section-title")
66
+ yield Static("[cyan]Ctrl+Shift+S[/] Toggle split view")
67
+ yield Static("[cyan]Ctrl+Shift+Tab[/] Switch between panes")
68
+ yield Static("[cyan]Ctrl+Shift+Y[/] Toggle sync mode (send to both)")
69
+
70
+ # Welcome screen (when no session active)
71
+ yield Static(
72
+ "[bold]Welcome Screen (Agent Quick Select)[/]",
73
+ classes="section-title",
74
+ )
75
+ yield Static("[cyan]1-9[/] Select agent by number")
76
+
77
+ # Browser screens (Agents/Templates/Content/Schemas)
78
+ yield Static(
79
+ "[bold]Browser Screens (Agents/Templates/Content/Schemas)[/]",
80
+ classes="section-title",
81
+ )
82
+ yield Static("[cyan]Ctrl+F[/] Focus search input")
83
+ yield Static("[cyan]Ctrl+R[/] Refresh results")
84
+ yield Static("[cyan]Ctrl+Y[/] Copy name/content")
85
+ yield Static("[cyan]Ctrl+N[/] Create new item")
86
+ yield Static("[cyan]Escape[/] Focus list")
87
+ yield Static("[cyan]Enter[/] Copy name/content")
88
+ yield Static("[cyan]Up/Down[/] Navigate list")
89
+
90
+ # Agents specific
91
+ yield Static("[bold]Agents Screen[/]", classes="section-title")
92
+ yield Static("[cyan]Ctrl+E[/] Edit selected agent")
93
+ yield Static("[cyan]Ctrl+D[/] Delete selected agent")
94
+
95
+ # Templates specific
96
+ yield Static("[bold]Templates Screen[/]", classes="section-title")
97
+ yield Static("[cyan]Ctrl+Shift+Y[/] Copy template content")
98
+ yield Static("[cyan]Ctrl+E[/] Edit template in $EDITOR")
99
+ yield Static("[cyan]Ctrl+U[/] Edit template name/description")
100
+ yield Static("[cyan]Ctrl+V[/] Create new version")
101
+ yield Static("[cyan]Ctrl+O[/] Render and open template")
102
+
103
+ # Content specific
104
+ yield Static("[bold]Content Screen[/]", classes="section-title")
105
+ yield Static(
106
+ "[cyan]Three search inputs:[/] Fuzzy, Tag filter, External ID"
107
+ )
108
+ yield Static(
109
+ "[cyan]Ctrl+I[/] Copy ID (external_id if set, else UUID)"
110
+ )
111
+ yield Static("[cyan]Ctrl+T[/] Manage tags")
112
+ yield Static("[cyan]Ctrl+E[/] View in $EDITOR")
113
+ yield Static("[cyan]Ctrl+D[/] Delete selected content")
114
+
115
+ # Schemas specific
116
+ yield Static("[bold]Schemas Screen[/]", classes="section-title")
117
+ yield Static("[cyan]Ctrl+Shift+Y[/] Copy schema definition")
118
+ yield Static("[cyan]Ctrl+E[/] Edit definition in $EDITOR")
119
+ yield Static("[cyan]Ctrl+U[/] Edit schema name/description")
120
+ yield Static("[cyan]Ctrl+V[/] Create new version")
121
+
122
+ # Tool Configs specific
123
+ yield Static("[bold]Tool Configs Screen[/]", classes="section-title")
124
+ yield Static("[cyan]Ctrl+E[/] Edit selected config")
125
+ yield Static(
126
+ "[cyan]Ctrl+D[/] Delete selected config (blocked if in use)"
127
+ )
128
+
129
+ # Modals
130
+ yield Static("[bold]Modals & Dialogs[/]", classes="section-title")
131
+ yield Static("[cyan]Escape[/] Cancel / Close modal")
132
+ yield Static("[cyan]Ctrl+S[/] Submit form")
133
+ yield Static("[cyan]n[/] Cancel (confirmation dialogs)")
134
+
135
+ with Vertical(classes="button-row"):
136
+ yield Button("Close", id="close-btn", variant="primary")
137
+
138
+ @on(Button.Pressed, "#close-btn")
139
+ def on_close_pressed(self, event: Button.Pressed) -> None:
140
+ """Close the modal."""
141
+ self.dismiss(None)
142
+
143
+ def action_close(self) -> None:
144
+ """Close via escape or q key."""
145
+ self.dismiss(None)