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,130 @@
1
+ """HTTPie-style key-value parser for CLI options.
2
+
3
+ Provides parsing for key=value and key:=json syntax, allowing users to
4
+ build JSON objects without writing literal JSON strings.
5
+
6
+ Syntax:
7
+ key=value -> {"key": "value"} (string value)
8
+ key:=value -> {"key": <parsed JSON>} (raw JSON: numbers, bools, arrays, objects)
9
+
10
+ Examples:
11
+ name=John -> {"name": "John"}
12
+ count:=5 -> {"count": 5}
13
+ active:=true -> {"active": true}
14
+ tags:='["a","b"]' -> {"tags": ["a", "b"]}
15
+ url=https://foo.com -> {"url": "https://foo.com"} (= in value is preserved)
16
+
17
+ Usage with Typer:
18
+ from cli.infrastructure.kv_parser import kv_pairs_callback
19
+
20
+ @app.command()
21
+ def my_command(
22
+ variables: Annotated[
23
+ list[str] | None,
24
+ typer.Option(
25
+ "--var", "-v",
26
+ help="Variables in key=value or key:=json format",
27
+ callback=kv_pairs_callback,
28
+ ),
29
+ ] = None,
30
+ ) -> None:
31
+ # variables is now a dict[str, Any]
32
+ ...
33
+ """
34
+
35
+ import json
36
+ from typing import Any
37
+
38
+ import typer
39
+
40
+
41
+ def parse_kv_pairs(values: list[str] | None) -> dict[str, Any]:
42
+ """Parse a list of key=value or key:=json strings into a dictionary.
43
+
44
+ Args:
45
+ values: List of strings in "key=value" or "key:=json" format.
46
+ Can be None or empty.
47
+
48
+ Returns:
49
+ Dictionary with parsed key-value pairs. Empty dict if input is None/empty.
50
+
51
+ Raises:
52
+ typer.BadParameter: If a value has invalid format or invalid JSON for :=
53
+
54
+ Examples:
55
+ >>> parse_kv_pairs(["name=John", "age:=30"])
56
+ {"name": "John", "age": 30}
57
+
58
+ >>> parse_kv_pairs(["active:=true", "tags:=['a','b']"])
59
+ {"active": True, "tags": ["a", "b"]}
60
+
61
+ >>> parse_kv_pairs(None)
62
+ {}
63
+ """
64
+ if not values:
65
+ return {}
66
+
67
+ result: dict[str, Any] = {}
68
+
69
+ for item in values:
70
+ # Check for raw JSON syntax first (`:=`)
71
+ if ":=" in item:
72
+ key, raw_value = item.split(":=", 1)
73
+ key = key.strip()
74
+
75
+ if not key:
76
+ raise typer.BadParameter(
77
+ f"Missing key in '{item}'. Expected format: key:=json_value"
78
+ )
79
+
80
+ try:
81
+ result[key] = json.loads(raw_value)
82
+ except json.JSONDecodeError as e:
83
+ raise typer.BadParameter(
84
+ f"Invalid JSON for key '{key}': {raw_value}. Error: {e}"
85
+ )
86
+
87
+ # Check for string syntax (`=`)
88
+ elif "=" in item:
89
+ key, value = item.split("=", 1)
90
+ key = key.strip()
91
+
92
+ if not key:
93
+ raise typer.BadParameter(
94
+ f"Missing key in '{item}'. Expected format: key=value"
95
+ )
96
+
97
+ result[key] = value
98
+
99
+ else:
100
+ raise typer.BadParameter(
101
+ f"Invalid format: '{item}'. Expected 'key=value' or 'key:=json_value'"
102
+ )
103
+
104
+ return result
105
+
106
+
107
+ def kv_pairs_callback(values: list[str] | None) -> dict[str, Any]:
108
+ """Typer callback that transforms key-value pairs into a dictionary.
109
+
110
+ Use this as a callback for typer.Option to accept httpie-style key-value
111
+ pairs that get parsed into a dictionary before reaching your command function.
112
+
113
+ Args:
114
+ values: List of strings from repeated option usage (e.g., -v a=1 -v b=2)
115
+
116
+ Returns:
117
+ Parsed dictionary
118
+
119
+ Example:
120
+ @app.command()
121
+ def cmd(
122
+ vars: Annotated[
123
+ list[str] | None,
124
+ typer.Option("--var", "-v", callback=kv_pairs_callback),
125
+ ] = None,
126
+ ):
127
+ # vars is a dict here, not list[str]
128
+ print(vars) # {"a": "1", "b": 2}
129
+ """
130
+ return parse_kv_pairs(values)
@@ -0,0 +1,227 @@
1
+ """Local JSON storage for CLI persistent data.
2
+
3
+ Provides a scalable storage system for various CLI features like command history,
4
+ preferences, cached data, etc. Data is stored in ~/.alloy-runtime/storage.json.
5
+ """
6
+
7
+ import json
8
+ import os
9
+ from pathlib import Path
10
+ from typing import Any, cast
11
+
12
+
13
+ CONFIG_DIR = Path.home() / ".alloy-runtime"
14
+ STORAGE_FILE = CONFIG_DIR / "storage.json"
15
+
16
+ # Default limits for various storage features
17
+ MAX_COMMAND_HISTORY = 15
18
+
19
+
20
+ class LocalStorage:
21
+ """JSON-based local storage for CLI persistent data.
22
+
23
+ Provides getter/setter methods for various storage features.
24
+ Data is automatically persisted to ~/.alloy-runtime/storage.json.
25
+
26
+ Example:
27
+ storage = LocalStorage()
28
+
29
+ # Command history
30
+ storage.add_command("Hello, how are you?")
31
+ history = storage.get_command_history()
32
+
33
+ # Future features can add their own sections
34
+ storage.set("preferences", "theme", "dark")
35
+ theme = storage.get("preferences", "theme", default="light")
36
+ """
37
+
38
+ def __init__(self) -> None:
39
+ self._data: dict[str, Any] = self._load()
40
+
41
+ def _load(self) -> dict[str, Any]:
42
+ """Load storage data from disk."""
43
+ if not STORAGE_FILE.exists():
44
+ return self._default_data()
45
+
46
+ try:
47
+ with open(STORAGE_FILE, encoding="utf-8") as f:
48
+ data = json.load(f)
49
+ # Ensure all expected keys exist
50
+ return self._merge_with_defaults(data)
51
+ except (json.JSONDecodeError, OSError):
52
+ # If file is corrupted, start fresh
53
+ return self._default_data()
54
+
55
+ def _default_data(self) -> dict[str, Any]:
56
+ """Return default storage structure."""
57
+ return {
58
+ "command_history": [],
59
+ "preferences": {},
60
+ "cache": {},
61
+ }
62
+
63
+ def _merge_with_defaults(self, data: dict[str, Any]) -> dict[str, Any]:
64
+ """Merge loaded data with defaults to ensure all keys exist."""
65
+ defaults = self._default_data()
66
+ for key, value in defaults.items():
67
+ if key not in data:
68
+ data[key] = value
69
+ return data
70
+
71
+ def _save(self) -> None:
72
+ """Save storage data to disk."""
73
+ CONFIG_DIR.mkdir(exist_ok=True, mode=0o700)
74
+
75
+ with open(STORAGE_FILE, "w", encoding="utf-8") as f:
76
+ json.dump(self._data, f, indent=2)
77
+
78
+ # Set secure file permissions
79
+ os.chmod(STORAGE_FILE, 0o600)
80
+
81
+ # -------------------------------------------------------------------------
82
+ # Command History Methods
83
+ # -------------------------------------------------------------------------
84
+
85
+ def get_command_history(self) -> list[str]:
86
+ """Get the command history list.
87
+
88
+ Returns:
89
+ List of previously sent messages, most recent last.
90
+ """
91
+ history = self._data.get("command_history", [])
92
+ if isinstance(history, list):
93
+ return [str(item) for item in cast(list[Any], history)]
94
+ return []
95
+
96
+ def add_command(self, command: str) -> None:
97
+ """Add a command to history.
98
+
99
+ Maintains a maximum of MAX_COMMAND_HISTORY entries.
100
+ Duplicates are allowed (same message can appear multiple times).
101
+
102
+ Args:
103
+ command: The user message to add to history.
104
+ """
105
+ command = command.strip()
106
+ if not command:
107
+ return
108
+
109
+ history_data = self._data.get("command_history", [])
110
+ history: list[str]
111
+ if isinstance(history_data, list):
112
+ history = [str(item) for item in cast(list[Any], history_data)]
113
+ else:
114
+ history = []
115
+ history.append(command)
116
+
117
+ # Trim to max size, keeping most recent
118
+ if len(history) > MAX_COMMAND_HISTORY:
119
+ history = history[-MAX_COMMAND_HISTORY:]
120
+
121
+ self._data["command_history"] = history
122
+ self._save()
123
+
124
+ def clear_command_history(self) -> None:
125
+ """Clear all command history."""
126
+ self._data["command_history"] = []
127
+ self._save()
128
+
129
+ # -------------------------------------------------------------------------
130
+ # Generic Getter/Setter Methods (for future features)
131
+ # -------------------------------------------------------------------------
132
+
133
+ def get(self, section: str, key: str, default: Any = None) -> Any:
134
+ """Get a value from a storage section.
135
+
136
+ Args:
137
+ section: The storage section (e.g., "preferences", "cache")
138
+ key: The key within the section
139
+ default: Default value if key doesn't exist
140
+
141
+ Returns:
142
+ The stored value or default
143
+ """
144
+ section_data = self._data.get(section)
145
+ if isinstance(section_data, dict):
146
+ typed_section_data = cast(dict[str, Any], section_data)
147
+ return typed_section_data.get(key, default)
148
+ return default
149
+
150
+ def set(self, section: str, key: str, value: Any) -> None:
151
+ """Set a value in a storage section.
152
+
153
+ Args:
154
+ section: The storage section (e.g., "preferences", "cache")
155
+ key: The key within the section
156
+ value: The value to store (must be JSON-serializable)
157
+ """
158
+ if section not in self._data:
159
+ self._data[section] = {}
160
+
161
+ section_data = self._data[section]
162
+ if isinstance(section_data, dict):
163
+ typed_section_data = cast(dict[str, Any], section_data)
164
+ typed_section_data[key] = value
165
+ self._save()
166
+
167
+ def delete(self, section: str, key: str) -> bool:
168
+ """Delete a key from a storage section.
169
+
170
+ Args:
171
+ section: The storage section
172
+ key: The key to delete
173
+
174
+ Returns:
175
+ True if key was deleted, False if it didn't exist
176
+ """
177
+ section_data = self._data.get(section)
178
+ if isinstance(section_data, dict) and key in section_data:
179
+ typed_section_data = cast(dict[str, Any], section_data)
180
+ del typed_section_data[key]
181
+ self._save()
182
+ return True
183
+ return False
184
+
185
+ def get_section(self, section: str) -> dict[str, Any]:
186
+ """Get an entire storage section.
187
+
188
+ Args:
189
+ section: The storage section name
190
+
191
+ Returns:
192
+ The section data as a dict, or empty dict if not found
193
+ """
194
+ section_data = self._data.get(section)
195
+ if isinstance(section_data, dict):
196
+ typed_section_data = cast(dict[str, Any], section_data)
197
+ return dict(typed_section_data)
198
+ return {}
199
+
200
+ def clear_section(self, section: str) -> None:
201
+ """Clear all data in a storage section.
202
+
203
+ Args:
204
+ section: The storage section to clear
205
+ """
206
+ if section in self._data:
207
+ if section == "command_history":
208
+ self._data[section] = []
209
+ else:
210
+ self._data[section] = {}
211
+ self._save()
212
+
213
+
214
+ # Singleton instance for convenience
215
+ _storage: LocalStorage | None = None
216
+
217
+
218
+ def get_storage() -> LocalStorage:
219
+ """Get the global LocalStorage instance.
220
+
221
+ Returns:
222
+ The singleton LocalStorage instance.
223
+ """
224
+ global _storage
225
+ if _storage is None:
226
+ _storage = LocalStorage()
227
+ return _storage
@@ -0,0 +1,215 @@
1
+ """Macro parser for template content.
2
+
3
+ Parses @macro(query) syntax in template content and provides compilation
4
+ to transform macros into valid Jinja2 syntax.
5
+
6
+ Supported macros:
7
+ - @fragment(query) -> {% include 'fragment_name' %}
8
+ - @text(query) -> {{ text('uuid_or_external_id') }}
9
+ - @json(query) -> {{ json('uuid_or_external_id') }}
10
+ - @schema(query) -> {{ schema('name_or_uuid') }}
11
+ """
12
+
13
+ import re
14
+ from dataclasses import dataclass
15
+
16
+ # Regex to match @type(query) macros
17
+ # Group 1: macro type (e.g., "fragment", "text", "json", "schema")
18
+ # Group 2: query string (e.g., "header", "article summary")
19
+ MACRO_PATTERN = re.compile(r"@(\w+)\((.*?)\)")
20
+
21
+ # Regex patterns for Jinja2 syntax detection in rendered output
22
+ # These match Jinja2 constructs that survived rendering (e.g., from {% raw %} blocks)
23
+ JINJA_EXPRESSION_PATTERN = re.compile(r"\{\{.*?\}\}", re.DOTALL) # {{ ... }}
24
+ JINJA_STATEMENT_PATTERN = re.compile(r"\{%.*?%\}", re.DOTALL) # {% ... %}
25
+ JINJA_COMMENT_PATTERN = re.compile(r"\{#.*?#\}", re.DOTALL) # {# ... #}
26
+
27
+ # Valid macro types that we support
28
+ VALID_MACRO_TYPES = frozenset({"fragment", "text", "json", "schema"})
29
+
30
+
31
+ @dataclass
32
+ class MacroMatch:
33
+ """Represents a parsed macro from template content."""
34
+
35
+ macro_type: str
36
+ query: str
37
+ original_text: str
38
+ start: int
39
+ end: int
40
+
41
+ def __repr__(self) -> str:
42
+ return f"MacroMatch({self.macro_type}, {self.query!r})"
43
+
44
+
45
+ def parse_macros(content: str) -> list[MacroMatch]:
46
+ """Parse all valid macros from template content.
47
+
48
+ Args:
49
+ content: Template content potentially containing macros
50
+
51
+ Returns:
52
+ List of MacroMatch objects for valid macros, in order of appearance
53
+ """
54
+ matches: list[MacroMatch] = []
55
+ for match in MACRO_PATTERN.finditer(content):
56
+ macro_type = match.group(1)
57
+ query = match.group(2).strip()
58
+
59
+ # Only include valid macro types
60
+ if macro_type in VALID_MACRO_TYPES:
61
+ matches.append(
62
+ MacroMatch(
63
+ macro_type=macro_type,
64
+ query=query,
65
+ original_text=match.group(0),
66
+ start=match.start(),
67
+ end=match.end(),
68
+ )
69
+ )
70
+
71
+ return matches
72
+
73
+
74
+ def deduplicate_macros(macros: list[MacroMatch]) -> list[MacroMatch]:
75
+ """Deduplicate macros by (macro_type, query) keeping first occurrence.
76
+
77
+ When the same macro (same type and query) appears multiple times in content,
78
+ this returns only the first occurrence. Useful for resolution flows where
79
+ the user should only need to resolve each unique macro once.
80
+
81
+ Args:
82
+ macros: List of MacroMatch objects (from parse_macros)
83
+
84
+ Returns:
85
+ List of unique MacroMatch objects, preserving order of first appearance
86
+ """
87
+ seen: set[tuple[str, str]] = set()
88
+ unique: list[MacroMatch] = []
89
+ for macro in macros:
90
+ key = (macro.macro_type, macro.query)
91
+ if key not in seen:
92
+ seen.add(key)
93
+ unique.append(macro)
94
+ return unique
95
+
96
+
97
+ def compile_content(content: str, replacements: dict[str, str]) -> str:
98
+ """Apply macro replacements to template content.
99
+
100
+ Args:
101
+ content: Original template content with macros
102
+ replacements: Mapping of original macro text to replacement Jinja syntax
103
+
104
+ Returns:
105
+ Compiled content with macros replaced
106
+ """
107
+ result = content
108
+ for original, replacement in replacements.items():
109
+ result = result.replace(original, replacement)
110
+ return result
111
+
112
+
113
+ def build_jinja_replacement(macro_type: str, resolved_value: str) -> str:
114
+ """Build the Jinja2 replacement syntax for a resolved macro.
115
+
116
+ Args:
117
+ macro_type: Type of macro (fragment, text, json, schema)
118
+ resolved_value: The resolved value (fragment name, content part UUID/external_id, or schema name/UUID)
119
+
120
+ Returns:
121
+ Valid Jinja2 syntax string
122
+
123
+ Note:
124
+ - fragment uses the template NAME (not UUID) because the renderer resolves by name
125
+ - text/json use UUIDs or external_ids to reference content parts
126
+ - schema uses the schema NAME (or UUID) because the renderer supports both
127
+ """
128
+ if macro_type == "fragment":
129
+ # Fragment uses name, not UUID
130
+ return f"{{% include '{resolved_value}' %}}"
131
+ elif macro_type == "text":
132
+ return f"{{{{ text('{resolved_value}') }}}}"
133
+ elif macro_type == "json":
134
+ return f"{{{{ json('{resolved_value}') }}}}"
135
+ elif macro_type == "schema":
136
+ return f"{{{{ schema('{resolved_value}') }}}}"
137
+ else:
138
+ raise ValueError(f"Unknown macro type: {macro_type}")
139
+
140
+
141
+ @dataclass
142
+ class JinjaSyntaxMatch:
143
+ """Represents a Jinja2 syntax match found in rendered content."""
144
+
145
+ syntax_type: str # "expression", "statement", or "comment"
146
+ content: str # The full matched text including delimiters
147
+ start: int
148
+ end: int
149
+
150
+ def __repr__(self) -> str:
151
+ preview = self.content[:50] + "..." if len(self.content) > 50 else self.content
152
+ return f"JinjaSyntaxMatch({self.syntax_type}, {preview!r})"
153
+
154
+
155
+ def extract_jinja_syntax(content: str) -> list[JinjaSyntaxMatch]:
156
+ """Extract all Jinja2 syntax from rendered content.
157
+
158
+ Finds Jinja2 expressions ({{ }}), statements ({% %}), and comments ({# #})
159
+ that remain in the rendered output. These typically come from {% raw %} blocks
160
+ or escaped content that should be preserved for later use.
161
+
162
+ Args:
163
+ content: Rendered template content
164
+
165
+ Returns:
166
+ List of JinjaSyntaxMatch objects in order of appearance, deduplicated
167
+ """
168
+ matches: list[JinjaSyntaxMatch] = []
169
+ seen_content: set[str] = set()
170
+
171
+ # Find expressions {{ ... }}
172
+ for match in JINJA_EXPRESSION_PATTERN.finditer(content):
173
+ text = match.group(0)
174
+ if text not in seen_content:
175
+ seen_content.add(text)
176
+ matches.append(
177
+ JinjaSyntaxMatch(
178
+ syntax_type="expression",
179
+ content=text,
180
+ start=match.start(),
181
+ end=match.end(),
182
+ )
183
+ )
184
+
185
+ # Find statements {% ... %}
186
+ for match in JINJA_STATEMENT_PATTERN.finditer(content):
187
+ text = match.group(0)
188
+ if text not in seen_content:
189
+ seen_content.add(text)
190
+ matches.append(
191
+ JinjaSyntaxMatch(
192
+ syntax_type="statement",
193
+ content=text,
194
+ start=match.start(),
195
+ end=match.end(),
196
+ )
197
+ )
198
+
199
+ # Find comments {# ... #}
200
+ for match in JINJA_COMMENT_PATTERN.finditer(content):
201
+ text = match.group(0)
202
+ if text not in seen_content:
203
+ seen_content.add(text)
204
+ matches.append(
205
+ JinjaSyntaxMatch(
206
+ syntax_type="comment",
207
+ content=text,
208
+ start=match.start(),
209
+ end=match.end(),
210
+ )
211
+ )
212
+
213
+ # Sort by position in content
214
+ matches.sort(key=lambda m: m.start)
215
+ return matches