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,409 @@
1
+ """Export formatters for content list results.
2
+
3
+ Provides various output formats for exporting content items:
4
+ - markdown: Markdown list or grouped headers
5
+ - xml: XML tags with content
6
+ - numbered: Numbered list
7
+ - plain: Plain text (content only)
8
+ - json: JSON array
9
+ """
10
+
11
+ import json
12
+ from abc import ABC, abstractmethod
13
+ from typing import Any
14
+
15
+ from alloy_runtime_types.dtos.content import ContentPartItemResponse
16
+
17
+
18
+ class ContentExportFormatter(ABC):
19
+ """Base class for content export formatters."""
20
+
21
+ @abstractmethod
22
+ def format(
23
+ self, items: list[ContentPartItemResponse], group_by: str | None = None
24
+ ) -> str:
25
+ """Format content items for export.
26
+
27
+ Args:
28
+ items: List of content part items to format
29
+ group_by: Optional tag prefix to group items by
30
+
31
+ Returns:
32
+ Formatted string ready for output
33
+ """
34
+ pass
35
+
36
+ def _get_content(self, item: ContentPartItemResponse) -> str:
37
+ """Extract content text from item.
38
+
39
+ Args:
40
+ item: Content part item
41
+
42
+ Returns:
43
+ Content as string (text or JSON-serialized structured content)
44
+ """
45
+ if item.content_text:
46
+ return item.content_text
47
+ if item.content_structured:
48
+ return json.dumps(item.content_structured, ensure_ascii=False)
49
+ return ""
50
+
51
+ def _group_items(
52
+ self, items: list[ContentPartItemResponse], group_by: str
53
+ ) -> dict[str, list[ContentPartItemResponse]]:
54
+ """Group items by tag path matching the group_by prefix.
55
+
56
+ Examples:
57
+ group_by="ads" groups by first subtag: ads.headline -> "headline"
58
+ group_by="ads.headline" groups by exact match -> "ads.headline"
59
+
60
+ Args:
61
+ items: List of content items to group
62
+ group_by: Tag prefix to group by
63
+
64
+ Returns:
65
+ Dictionary mapping group names to lists of items
66
+ """
67
+ groups: dict[str, list[ContentPartItemResponse]] = {}
68
+ ungrouped: list[ContentPartItemResponse] = []
69
+
70
+ for item in items:
71
+ matched = False
72
+ for tag in item.tags:
73
+ if tag.tag_path.startswith(group_by):
74
+ # Extract the grouping key
75
+ remaining = tag.tag_path[len(group_by) :].lstrip(".")
76
+ if remaining:
77
+ # Use first component after prefix
78
+ key = remaining.split(".")[0]
79
+ else:
80
+ # Exact match - use full tag path
81
+ key = tag.tag_path
82
+
83
+ if key not in groups:
84
+ groups[key] = []
85
+ groups[key].append(item)
86
+ matched = True
87
+ break
88
+
89
+ if not matched:
90
+ ungrouped.append(item)
91
+
92
+ if ungrouped:
93
+ groups["(ungrouped)"] = ungrouped
94
+
95
+ return groups
96
+
97
+
98
+ class MarkdownFormatter(ContentExportFormatter):
99
+ """Format content as markdown with numbered headers.
100
+
101
+ Output format (flat):
102
+ ## Item 1
103
+
104
+ <content>
105
+
106
+ ## Item 2
107
+
108
+ <content>
109
+
110
+ Output format (grouped):
111
+ ## group_name
112
+
113
+ ### Item 1
114
+
115
+ <content>
116
+
117
+ ### Item 2
118
+
119
+ <content>
120
+ """
121
+
122
+ def format(
123
+ self, items: list[ContentPartItemResponse], group_by: str | None = None
124
+ ) -> str:
125
+ """Format items as markdown.
126
+
127
+ Args:
128
+ items: Content items to format
129
+ group_by: Optional tag prefix for grouping
130
+
131
+ Returns:
132
+ Markdown formatted string
133
+ """
134
+ if group_by:
135
+ return self._format_grouped(items, group_by)
136
+ return self._format_flat(items)
137
+
138
+ def _format_flat(self, items: list[ContentPartItemResponse]) -> str:
139
+ """Format items with numbered headers."""
140
+ sections: list[str] = []
141
+ for i, item in enumerate(items, 1):
142
+ content = self._get_content(item)
143
+ sections.append(f"## Item {i}\n\n{content}")
144
+ return "\n\n".join(sections)
145
+
146
+ def _format_grouped(
147
+ self, items: list[ContentPartItemResponse], group_by: str
148
+ ) -> str:
149
+ """Format items grouped by tag prefix with nested headers."""
150
+ groups = self._group_items(items, group_by)
151
+ sections: list[str] = []
152
+ for group_name, group_items in groups.items():
153
+ group_sections: list[str] = [f"## {group_name}"]
154
+ for i, item in enumerate(group_items, 1):
155
+ content = self._get_content(item)
156
+ group_sections.append(f"### Item {i}\n\n{content}")
157
+ sections.append("\n\n".join(group_sections))
158
+ return "\n\n".join(sections)
159
+
160
+
161
+ class XmlFormatter(ContentExportFormatter):
162
+ """Format content as XML tags.
163
+
164
+ Uses CDATA sections to preserve raw content without escaping,
165
+ which is important when content itself contains XML (e.g., system prompts).
166
+ """
167
+
168
+ def format(
169
+ self, items: list[ContentPartItemResponse], group_by: str | None = None
170
+ ) -> str:
171
+ """Format items as XML.
172
+
173
+ Args:
174
+ items: Content items to format
175
+ group_by: Optional tag prefix for grouping
176
+
177
+ Returns:
178
+ XML formatted string
179
+ """
180
+ if group_by:
181
+ return self._format_grouped(items, group_by)
182
+ return self._format_flat(items)
183
+
184
+ def _wrap_cdata(self, text: str) -> str:
185
+ """Wrap content in CDATA section to preserve raw content.
186
+
187
+ Handles the edge case where content contains ']]>' by splitting
188
+ into multiple CDATA sections.
189
+ """
190
+ # Handle edge case: content contains CDATA end marker
191
+ if "]]>" in text:
192
+ # Split at ]]> and rejoin with separate CDATA sections
193
+ text = text.replace("]]>", "]]]]><![CDATA[>")
194
+ return f"<![CDATA[{text}]]>"
195
+
196
+ def _safe_tag_name(self, name: str) -> str:
197
+ """Convert a name to a valid XML tag name."""
198
+ # Replace dots and other invalid chars with underscores
199
+ safe = name.replace(".", "_").replace("-", "_").replace(" ", "_")
200
+ # Ensure starts with letter or underscore
201
+ if safe and not (safe[0].isalpha() or safe[0] == "_"):
202
+ safe = "_" + safe
203
+ return safe or "item"
204
+
205
+ def _format_flat(self, items: list[ContentPartItemResponse]) -> str:
206
+ """Format items as a flat XML list."""
207
+ lines = ["<content_items>"]
208
+ for item in items:
209
+ content = self._get_content(item)
210
+ # Use first tag as element name, or "item"
211
+ tag_name = (
212
+ self._safe_tag_name(item.tags[0].tag_path) if item.tags else "item"
213
+ )
214
+ lines.append(f" <{tag_name}>{self._wrap_cdata(content)}</{tag_name}>")
215
+ lines.append("</content_items>")
216
+ return "\n".join(lines)
217
+
218
+ def _format_grouped(
219
+ self, items: list[ContentPartItemResponse], group_by: str
220
+ ) -> str:
221
+ """Format items grouped by tag prefix."""
222
+ groups = self._group_items(items, group_by)
223
+ lines = ["<content_items>"]
224
+ for group_name, group_items in groups.items():
225
+ safe_name = self._safe_tag_name(group_name)
226
+ lines.append(f" <{safe_name}>")
227
+ for item in group_items:
228
+ content = self._get_content(item)
229
+ lines.append(f" <item>{self._wrap_cdata(content)}</item>")
230
+ lines.append(f" </{safe_name}>")
231
+ lines.append("</content_items>")
232
+ return "\n".join(lines)
233
+
234
+
235
+ class NumberedFormatter(ContentExportFormatter):
236
+ """Format content as numbered list."""
237
+
238
+ def format(
239
+ self, items: list[ContentPartItemResponse], group_by: str | None = None
240
+ ) -> str:
241
+ """Format items as numbered list.
242
+
243
+ Args:
244
+ items: Content items to format
245
+ group_by: Optional tag prefix for grouping
246
+
247
+ Returns:
248
+ Numbered list string
249
+ """
250
+ if group_by:
251
+ return self._format_grouped(items, group_by)
252
+ return self._format_flat(items)
253
+
254
+ def _format_flat(self, items: list[ContentPartItemResponse]) -> str:
255
+ """Format items as a flat numbered list."""
256
+ lines: list[str] = []
257
+ for i, item in enumerate(items, 1):
258
+ content = self._get_content(item)
259
+ # Handle multi-line content
260
+ content_lines = content.split("\n")
261
+ if len(content_lines) == 1:
262
+ lines.append(f"{i}. {content}")
263
+ else:
264
+ lines.append(f"{i}. {content_lines[0]}")
265
+ padding = " " * (len(str(i)) + 2)
266
+ for continuation in content_lines[1:]:
267
+ lines.append(f"{padding}{continuation}")
268
+ return "\n".join(lines)
269
+
270
+ def _format_grouped(
271
+ self, items: list[ContentPartItemResponse], group_by: str
272
+ ) -> str:
273
+ """Format items grouped by tag prefix."""
274
+ groups = self._group_items(items, group_by)
275
+ lines: list[str] = []
276
+ for group_name, group_items in groups.items():
277
+ lines.append(f"[{group_name}]")
278
+ for i, item in enumerate(group_items, 1):
279
+ content = self._get_content(item)
280
+ content_lines = content.split("\n")
281
+ if len(content_lines) == 1:
282
+ lines.append(f" {i}. {content}")
283
+ else:
284
+ lines.append(f" {i}. {content_lines[0]}")
285
+ padding = " " * (len(str(i)) + 4)
286
+ for continuation in content_lines[1:]:
287
+ lines.append(f"{padding}{continuation}")
288
+ lines.append("")
289
+ return "\n".join(lines).rstrip()
290
+
291
+
292
+ class PlainFormatter(ContentExportFormatter):
293
+ """Format content as plain text (content only, one per line)."""
294
+
295
+ def format(
296
+ self, items: list[ContentPartItemResponse], group_by: str | None = None
297
+ ) -> str:
298
+ """Format items as plain text.
299
+
300
+ Grouping adds blank lines between groups but no headers.
301
+
302
+ Args:
303
+ items: Content items to format
304
+ group_by: Optional tag prefix for grouping
305
+
306
+ Returns:
307
+ Plain text string with content only
308
+ """
309
+ if group_by:
310
+ return self._format_grouped(items, group_by)
311
+ return self._format_flat(items)
312
+
313
+ def _format_flat(self, items: list[ContentPartItemResponse]) -> str:
314
+ """Format items as plain text."""
315
+ lines: list[str] = []
316
+ for item in items:
317
+ content = self._get_content(item)
318
+ lines.append(content)
319
+ return "\n".join(lines)
320
+
321
+ def _format_grouped(
322
+ self, items: list[ContentPartItemResponse], group_by: str
323
+ ) -> str:
324
+ """Format items grouped by tag prefix with blank line separators."""
325
+ groups = self._group_items(items, group_by)
326
+ sections: list[str] = []
327
+ for group_items in groups.values():
328
+ section_lines: list[str] = []
329
+ for item in group_items:
330
+ content = self._get_content(item)
331
+ section_lines.append(content)
332
+ sections.append("\n".join(section_lines))
333
+ return "\n\n".join(sections)
334
+
335
+
336
+ class JsonExportFormatter(ContentExportFormatter):
337
+ """Format content as JSON array."""
338
+
339
+ def format(
340
+ self, items: list[ContentPartItemResponse], group_by: str | None = None
341
+ ) -> str:
342
+ """Format items as JSON.
343
+
344
+ Args:
345
+ items: Content items to format
346
+ group_by: Optional tag prefix for grouping
347
+
348
+ Returns:
349
+ JSON string (array or object if grouped)
350
+ """
351
+ if group_by:
352
+ return self._format_grouped(items, group_by)
353
+ return self._format_flat(items)
354
+
355
+ def _item_to_dict(self, item: ContentPartItemResponse) -> dict[str, Any]:
356
+ """Convert content item to dictionary for JSON serialization."""
357
+ return {
358
+ "id": str(item.id),
359
+ "content_type": item.content_type_id,
360
+ "content": item.content_text or item.content_structured,
361
+ "tags": [t.tag_path for t in item.tags],
362
+ "created_at": item.created_at.isoformat() if item.created_at else None,
363
+ }
364
+
365
+ def _format_flat(self, items: list[ContentPartItemResponse]) -> str:
366
+ """Format items as JSON array."""
367
+ data = [self._item_to_dict(item) for item in items]
368
+ return json.dumps(data, indent=2, ensure_ascii=False)
369
+
370
+ def _format_grouped(
371
+ self, items: list[ContentPartItemResponse], group_by: str
372
+ ) -> str:
373
+ """Format items as JSON object with groups."""
374
+ groups = self._group_items(items, group_by)
375
+ data = {
376
+ group_name: [self._item_to_dict(item) for item in group_items]
377
+ for group_name, group_items in groups.items()
378
+ }
379
+ return json.dumps(data, indent=2, ensure_ascii=False)
380
+
381
+
382
+ # Registry of available export formatters
383
+ EXPORT_FORMATTERS: dict[str, type[ContentExportFormatter]] = {
384
+ "markdown": MarkdownFormatter,
385
+ "xml": XmlFormatter,
386
+ "numbered": NumberedFormatter,
387
+ "plain": PlainFormatter,
388
+ "json": JsonExportFormatter,
389
+ }
390
+
391
+
392
+ def get_export_formatter(format_name: str) -> ContentExportFormatter | None:
393
+ """Get an export formatter instance by name.
394
+
395
+ Args:
396
+ format_name: Name of the format (markdown, xml, numbered, plain, json)
397
+
398
+ Returns:
399
+ Formatter instance or None if format not found
400
+ """
401
+ formatter_cls = EXPORT_FORMATTERS.get(format_name)
402
+ if formatter_cls:
403
+ return formatter_cls()
404
+ return None
405
+
406
+
407
+ def get_available_formats() -> list[str]:
408
+ """Get list of available export format names."""
409
+ return list(EXPORT_FORMATTERS.keys())
@@ -0,0 +1,165 @@
1
+ """Export handler for content list results.
2
+
3
+ Routes formatted content to various destinations:
4
+ - console: Print to stdout
5
+ - clipboard: Copy using pyperclip
6
+ - file: Write to specified path
7
+ """
8
+
9
+ import sys
10
+ from pathlib import Path
11
+ from typing import Any
12
+
13
+ from alloy_runtime_types.dtos.content import ContentPartItemResponse
14
+
15
+ from cli.commands.content.list.export_formatters import (
16
+ EXPORT_FORMATTERS,
17
+ get_available_formats,
18
+ )
19
+ from cli.infrastructure.output import OutputService
20
+
21
+ # Import pyperclip at module level for easier mocking in tests
22
+ pyperclip: Any | None = None
23
+ try:
24
+ import pyperclip as _pyperclip
25
+ except ImportError:
26
+ pass
27
+ else:
28
+ pyperclip = _pyperclip
29
+
30
+ PYPERCLIP_AVAILABLE = pyperclip is not None
31
+
32
+
33
+ def export_content(
34
+ items: list[ContentPartItemResponse],
35
+ export_format: str,
36
+ output_mode: str,
37
+ output_file: str | None,
38
+ group_by: str | None,
39
+ ) -> bool:
40
+ """Export content items to specified destination.
41
+
42
+ Args:
43
+ items: List of content part items to export
44
+ export_format: Format name (markdown, xml, numbered, plain, json)
45
+ output_mode: Destination (console, clipboard, file)
46
+ output_file: File path for file output mode
47
+ group_by: Optional tag prefix to group items by
48
+
49
+ Returns:
50
+ True on success, False on failure
51
+ """
52
+ output = OutputService.get()
53
+
54
+ # Validate format
55
+ formatter_cls = EXPORT_FORMATTERS.get(export_format)
56
+ if not formatter_cls:
57
+ available = ", ".join(get_available_formats())
58
+ output.warning(
59
+ f"Unknown export format: '{export_format}'. Available: {available}"
60
+ )
61
+ return False
62
+
63
+ # Check for empty items
64
+ if not items:
65
+ output.info("No content items to export")
66
+ return True
67
+
68
+ # Format the content
69
+ formatter = formatter_cls()
70
+ formatted_content = formatter.format(items, group_by)
71
+
72
+ # Route to destination
73
+ if output_mode == "clipboard":
74
+ return _copy_to_clipboard(formatted_content, len(items), output)
75
+ elif output_mode == "file":
76
+ return _save_to_file(formatted_content, output_file, len(items), output)
77
+ else: # console (default)
78
+ return _print_to_console(formatted_content, output)
79
+
80
+
81
+ def _print_to_console(content: str, _output: OutputService) -> bool:
82
+ """Print formatted content to stdout.
83
+
84
+ Args:
85
+ content: Formatted content string
86
+ output: Output service for messages
87
+
88
+ Returns:
89
+ True on success
90
+ """
91
+ try:
92
+ print(content, file=sys.stdout)
93
+ return True
94
+ except (BrokenPipeError, IOError):
95
+ # Pipe was closed (e.g., piping to head)
96
+ return True
97
+
98
+
99
+ def _copy_to_clipboard(content: str, item_count: int, output: OutputService) -> bool:
100
+ """Copy formatted content to clipboard.
101
+
102
+ Args:
103
+ content: Formatted content string
104
+ item_count: Number of items exported (for status message)
105
+ output: Output service for messages
106
+
107
+ Returns:
108
+ True on success, False on failure
109
+ """
110
+ if not PYPERCLIP_AVAILABLE or pyperclip is None:
111
+ output.warning("pyperclip not installed. Install with: pip install pyperclip")
112
+ output.info("Falling back to console output...")
113
+ print(content, file=sys.stdout)
114
+ return False
115
+
116
+ try:
117
+ pyperclip.copy(content)
118
+ output.success(
119
+ f"Exported {item_count} item(s) to clipboard ({len(content):,} characters)"
120
+ )
121
+ return True
122
+ except Exception as e:
123
+ output.warning(f"Failed to copy to clipboard: {e}")
124
+ output.info("Falling back to console output...")
125
+ print(content, file=sys.stdout)
126
+ return False
127
+
128
+
129
+ def _save_to_file(
130
+ content: str, output_file: str | None, item_count: int, output: OutputService
131
+ ) -> bool:
132
+ """Save formatted content to a file.
133
+
134
+ Args:
135
+ content: Formatted content string
136
+ output_file: Target file path
137
+ item_count: Number of items exported (for status message)
138
+ output: Output service for messages
139
+
140
+ Returns:
141
+ True on success, False on failure
142
+ """
143
+ if not output_file:
144
+ output.warning("No output file specified (use --output-file)")
145
+ return False
146
+
147
+ try:
148
+ file_path = Path(output_file).expanduser().resolve()
149
+
150
+ # Ensure parent directory exists
151
+ file_path.parent.mkdir(parents=True, exist_ok=True)
152
+
153
+ # Write the content
154
+ file_path.write_text(content, encoding="utf-8")
155
+
156
+ output.success(
157
+ f"Exported {item_count} item(s) to {file_path} ({len(content):,} characters)"
158
+ )
159
+ return True
160
+ except PermissionError:
161
+ output.warning(f"Permission denied: Cannot write to '{output_file}'")
162
+ return False
163
+ except OSError as e:
164
+ output.warning(f"Failed to save file: {e}")
165
+ return False