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,37 @@
1
+ """Presenter for knowledge document update metadata command output."""
2
+
3
+ import json
4
+
5
+ from rich.panel import Panel
6
+ from rich.table import Table
7
+
8
+ from cli.infrastructure.formatting.fields import format_datetime, format_uuid
9
+ from cli.infrastructure.output import OutputService
10
+ from alloy_runtime_types.dtos.knowledge import UpdateDocumentMetadataResponse
11
+
12
+
13
+ def present_update_metadata_result(
14
+ response: UpdateDocumentMetadataResponse,
15
+ ) -> None:
16
+ """Present document metadata update result.
17
+
18
+ Args:
19
+ response: UpdateDocumentMetadataResponse from server
20
+ """
21
+ output = OutputService.get()
22
+
23
+ output.success(f"Document '{response.title}' metadata updated")
24
+
25
+ table = Table(show_header=False, box=None, padding=(0, 1))
26
+ table.add_column("Field", style="dim")
27
+ table.add_column("Value")
28
+
29
+ table.add_row("ID", format_uuid(response.id, short=False))
30
+ table.add_row("Collection ID", format_uuid(response.collection_id, short=False))
31
+ table.add_row("Title", response.title)
32
+ if response.metadata:
33
+ table.add_row("Metadata", json.dumps(response.metadata, indent=2))
34
+ table.add_row("Updated At", format_datetime(response.updated_at))
35
+
36
+ panel = Panel(table, title="Document Updated", border_style="green")
37
+ output.console.print(panel)
File without changes
@@ -0,0 +1,46 @@
1
+ """Knowledge recover command implementation."""
2
+
3
+ from typing import Optional
4
+
5
+ import typer
6
+
7
+ from cli.commands.knowledge.recover.presenter import present_recovery_result
8
+ from cli.infrastructure.command import async_command, authenticated_client
9
+ from alloy_runtime_types.dtos.knowledge import RecoverDocumentsRequest
10
+
11
+
12
+ def knowledge_recover_command(
13
+ max_retries: Optional[int] = typer.Option(
14
+ None,
15
+ "-r",
16
+ "--max-retries",
17
+ min=1,
18
+ max=10,
19
+ help="Override max retry attempts (default: 3)",
20
+ ),
21
+ ) -> None:
22
+ """Recover stuck documents.
23
+
24
+ Finds documents stuck in 'processing' or 'pending' state and either
25
+ re-queues them for processing or marks them as permanently failed.
26
+
27
+ Documents can get stuck when:
28
+ - Processing is interrupted (container crash, API timeout, etc.)
29
+ - Celery never picks up the task (message lost, worker unavailable)
30
+
31
+ Examples:
32
+ ai2 knowledge recover
33
+ ai2 kb recover --max-retries 5
34
+ """
35
+ _execute_recover(max_retries=max_retries)
36
+
37
+
38
+ @async_command
39
+ async def _execute_recover(max_retries: Optional[int]) -> None:
40
+ """Execute document recovery operation."""
41
+ request = RecoverDocumentsRequest(max_retries=max_retries) if max_retries else None
42
+
43
+ async with authenticated_client() as (_config, client):
44
+ response = await client.recover_documents(request)
45
+
46
+ present_recovery_result(response)
@@ -0,0 +1,79 @@
1
+ """Presenter for document recovery output."""
2
+
3
+ from uuid import UUID
4
+
5
+ from rich.panel import Panel
6
+ from rich.table import Table
7
+
8
+ from cli.infrastructure.formatting.fields import format_uuid
9
+ from cli.infrastructure.output import OutputService
10
+ from alloy_runtime_types.dtos.knowledge import RecoverDocumentsResponse
11
+
12
+
13
+ def present_recovery_result(response: RecoverDocumentsResponse) -> None:
14
+ """Present document recovery results.
15
+
16
+ Args:
17
+ response: Recovery response from server
18
+ """
19
+ output = OutputService.get()
20
+
21
+ total_affected = (
22
+ response.recovered_count + response.failed_count + response.requeued_count
23
+ )
24
+
25
+ if total_affected == 0:
26
+ output.info("No stuck documents found")
27
+ return
28
+
29
+ output.success("Document recovery completed")
30
+
31
+ # Build summary table
32
+ table = Table(show_header=False, box=None, padding=(0, 1))
33
+ table.add_column("Metric", style="dim")
34
+ table.add_column("Value")
35
+
36
+ table.add_row("Documents recovered", str(response.recovered_count))
37
+ table.add_row("Documents re-queued", str(response.requeued_count))
38
+ table.add_row("Documents permanently failed", str(response.failed_count))
39
+
40
+ panel = Panel(table, title="Recovery Summary", border_style="green")
41
+ output.console.print(panel)
42
+
43
+ # Show document IDs if any
44
+ if response.requeued_document_ids:
45
+ _present_document_ids(
46
+ output, "Re-queued for processing", response.requeued_document_ids
47
+ )
48
+
49
+ if response.recovered_document_ids:
50
+ _present_document_ids(
51
+ output, "Reset for retry", response.recovered_document_ids
52
+ )
53
+
54
+ if response.failed_document_ids:
55
+ _present_document_ids(
56
+ output, "Permanently failed", response.failed_document_ids, style="red"
57
+ )
58
+
59
+
60
+ def _present_document_ids(
61
+ output: OutputService,
62
+ title: str,
63
+ doc_ids: list[UUID],
64
+ style: str = "cyan",
65
+ max_display: int = 10,
66
+ ) -> None:
67
+ """Present a list of document IDs."""
68
+ if not doc_ids:
69
+ return
70
+
71
+ output.console.print(f"\n[{style}]{title}:[/{style}]")
72
+
73
+ displayed: list[UUID] = doc_ids[:max_display]
74
+ for doc_id in displayed:
75
+ output.console.print(f" {format_uuid(doc_id, short=False)}")
76
+
77
+ remaining = len(doc_ids) - max_display
78
+ if remaining > 0:
79
+ output.console.print(f" [dim]...and {remaining} more[/dim]")
File without changes
@@ -0,0 +1,218 @@
1
+ """Knowledge search command implementation."""
2
+
3
+ import json
4
+ from typing import Any, Optional
5
+ from uuid import UUID
6
+
7
+ import typer
8
+
9
+ from cli.commands.flag_utils import validate_uuid
10
+ from cli.commands.knowledge.search.presenter import present_search_results
11
+ from cli.infrastructure.command import async_command, authenticated_client
12
+ from alloy_runtime_types.dtos.knowledge import SearchRequest
13
+
14
+
15
+ def knowledge_search_command(
16
+ query: str = typer.Argument(..., help="Search query"),
17
+ collections: Optional[str] = typer.Option(
18
+ None,
19
+ "-C",
20
+ "--collections",
21
+ help="Comma-separated collection IDs to search",
22
+ ),
23
+ collection_filter: Optional[str] = typer.Option(
24
+ None,
25
+ "-F",
26
+ "--collection-filter",
27
+ help="Filter by collection name pattern (e.g., 'Product*')",
28
+ ),
29
+ tag_filter: Optional[str] = typer.Option(
30
+ None,
31
+ "-T",
32
+ "--tag-filter",
33
+ help="Filter by document tag pattern (e.g., 'engineering.*', 'docs')",
34
+ ),
35
+ top_k: int = typer.Option(
36
+ 5,
37
+ "-k",
38
+ "--top-k",
39
+ min=1,
40
+ max=20,
41
+ help="Number of results to return (1-20)",
42
+ ),
43
+ hyde_agent: Optional[str] = typer.Option(
44
+ None,
45
+ "--hyde-agent",
46
+ help="Agent ID for HyDE hypothetical document generation",
47
+ ),
48
+ hyde_template: Optional[str] = typer.Option(
49
+ None,
50
+ "--hyde-template",
51
+ help="Template ID for HyDE hypothetical document generation",
52
+ ),
53
+ decomposition_agent: Optional[str] = typer.Option(
54
+ None,
55
+ "--decomposition-agent",
56
+ help="Agent ID for query decomposition",
57
+ ),
58
+ decomposition_template: Optional[str] = typer.Option(
59
+ None,
60
+ "--decomposition-template",
61
+ help="Template ID for query decomposition",
62
+ ),
63
+ rerank_instruction: Optional[str] = typer.Option(
64
+ None,
65
+ "-r",
66
+ "--rerank-instruction",
67
+ help="Custom instruction for reranking (e.g., 'Prioritize recent docs')",
68
+ ),
69
+ min_confidence: Optional[float] = typer.Option(
70
+ None,
71
+ "--min-confidence",
72
+ min=0.0,
73
+ max=1.0,
74
+ help="Minimum confidence threshold (0.0-1.0)",
75
+ ),
76
+ retrieval_k: Optional[int] = typer.Option(
77
+ None,
78
+ "--retrieval-k",
79
+ min=1,
80
+ max=1000,
81
+ help="Override initial candidate retrieval count",
82
+ ),
83
+ metadata_filter: Optional[str] = typer.Option(
84
+ None,
85
+ "--metadata-filter",
86
+ help='Filter by chunk metadata as JSON (e.g., \'{"author": "John"}\')',
87
+ ),
88
+ output: str = typer.Option(
89
+ "table",
90
+ "-o",
91
+ "--output",
92
+ help="Output format: 'table' or 'json'",
93
+ ),
94
+ ) -> None:
95
+ """Search the knowledge base.
96
+
97
+ Performs semantic search across document collections using hybrid retrieval
98
+ (vector + full-text search). Opt in to HyDE or query decomposition by
99
+ providing the corresponding agent and template IDs.
100
+
101
+ Examples:
102
+ ai2 knowledge search "How do I authenticate?"
103
+ ai2 kb search "API documentation" --collection-filter "Product*"
104
+ ai2 kb search "complex query" \\
105
+ --hyde-agent <id> --hyde-template <id> \\
106
+ --decomposition-agent <id> --decomposition-template <id>
107
+ ai2 kb search "test query" --output json
108
+ ai2 kb search "query" --retrieval-k 100
109
+ ai2 kb search "query" --metadata-filter '{"author": "John"}'
110
+ """
111
+ _execute_search_from_flags(
112
+ query=query,
113
+ collections=collections,
114
+ collection_filter=collection_filter,
115
+ tag_filter=tag_filter,
116
+ top_k=top_k,
117
+ hyde_agent=hyde_agent,
118
+ hyde_template=hyde_template,
119
+ decomposition_agent=decomposition_agent,
120
+ decomposition_template=decomposition_template,
121
+ rerank_instruction=rerank_instruction,
122
+ min_confidence=min_confidence,
123
+ retrieval_k=retrieval_k,
124
+ metadata_filter=metadata_filter,
125
+ output=output,
126
+ )
127
+
128
+
129
+ def _execute_search_from_flags(
130
+ query: str,
131
+ collections: Optional[str],
132
+ collection_filter: Optional[str],
133
+ tag_filter: Optional[str],
134
+ top_k: int,
135
+ hyde_agent: Optional[str],
136
+ hyde_template: Optional[str],
137
+ decomposition_agent: Optional[str],
138
+ decomposition_template: Optional[str],
139
+ rerank_instruction: Optional[str],
140
+ min_confidence: Optional[float],
141
+ retrieval_k: Optional[int],
142
+ metadata_filter: Optional[str],
143
+ output: str,
144
+ ) -> None:
145
+ """Validate flags and build search request."""
146
+ output_format = output.lower()
147
+ if output_format not in ("table", "json"):
148
+ raise typer.BadParameter(
149
+ f"Invalid output format '{output}'. Valid: table, json"
150
+ )
151
+
152
+ collection_ids: list[UUID] | None = None
153
+ if collections:
154
+ parsed_collection_ids: list[UUID] = []
155
+ for cid in collections.split(","):
156
+ cid = cid.strip()
157
+ if cid:
158
+ parsed_collection_ids.append(validate_uuid(cid, "collection"))
159
+ collection_ids = parsed_collection_ids
160
+
161
+ hyde_agent_id: UUID | None = None
162
+ hyde_template_id: UUID | None = None
163
+ decomposition_agent_id: UUID | None = None
164
+ decomposition_template_id: UUID | None = None
165
+
166
+ if hyde_agent:
167
+ hyde_agent_id = validate_uuid(hyde_agent, "hyde-agent")
168
+ if hyde_template:
169
+ hyde_template_id = validate_uuid(hyde_template, "hyde-template")
170
+ if decomposition_agent:
171
+ decomposition_agent_id = validate_uuid(
172
+ decomposition_agent, "decomposition-agent"
173
+ )
174
+ if decomposition_template:
175
+ decomposition_template_id = validate_uuid(
176
+ decomposition_template, "decomposition-template"
177
+ )
178
+
179
+ parsed_metadata_filter: dict[str, Any] | None = None
180
+ if metadata_filter:
181
+ try:
182
+ parsed_metadata_filter = json.loads(metadata_filter)
183
+ if not isinstance(parsed_metadata_filter, dict):
184
+ raise typer.BadParameter(
185
+ "--metadata-filter must be a JSON object, not "
186
+ f"{type(parsed_metadata_filter).__name__}"
187
+ )
188
+ except json.JSONDecodeError as e:
189
+ raise typer.BadParameter(f"Invalid JSON in --metadata-filter: {e}")
190
+
191
+ request = SearchRequest(
192
+ query=query,
193
+ collection_ids=collection_ids,
194
+ collection_filter=collection_filter,
195
+ top_k=top_k,
196
+ metadata_filter=parsed_metadata_filter,
197
+ tag_filter=tag_filter,
198
+ source_date_from=None,
199
+ source_date_to=None,
200
+ rerank_instruction=rerank_instruction,
201
+ retrieval_k=retrieval_k,
202
+ min_retrieval_confidence=min_confidence,
203
+ hyde_agent_id=hyde_agent_id,
204
+ hyde_template_id=hyde_template_id,
205
+ decomposition_agent_id=decomposition_agent_id,
206
+ decomposition_template_id=decomposition_template_id,
207
+ )
208
+
209
+ _execute_search(request, output_format)
210
+
211
+
212
+ @async_command
213
+ async def _execute_search(request: SearchRequest, output_format: str) -> None:
214
+ """Execute knowledge base search."""
215
+ async with authenticated_client() as (_config, client):
216
+ response = await client.search_knowledge(request)
217
+
218
+ present_search_results(response, output_format)
@@ -0,0 +1,111 @@
1
+ """Presenter for knowledge search output."""
2
+
3
+ import json
4
+
5
+ from rich.panel import Panel
6
+ from rich.table import Table
7
+
8
+ from cli.infrastructure.output import OutputService
9
+ from alloy_runtime_types.dtos.knowledge import SearchResponse
10
+
11
+
12
+ def present_search_results(response: SearchResponse, output_format: str) -> None:
13
+ """Present search results in specified format.
14
+
15
+ Args:
16
+ response: Search response from server
17
+ output_format: Output format ('table' or 'json')
18
+ """
19
+ if output_format == "json":
20
+ _present_json_results(response)
21
+ else:
22
+ _present_table_results(response)
23
+
24
+
25
+ def _present_table_results(response: SearchResponse) -> None:
26
+ """Present search results as formatted table."""
27
+ output = OutputService.get()
28
+
29
+ if not response.results:
30
+ output.info(f"No results found for: {response.query}")
31
+ return
32
+
33
+ # Build summary panel
34
+ summary_table = Table(show_header=False, box=None, padding=(0, 1))
35
+ summary_table.add_column("Field", style="dim")
36
+ summary_table.add_column("Value")
37
+
38
+ summary_table.add_row("Query", response.query)
39
+ summary_table.add_row("Results", str(len(response.results)))
40
+ summary_table.add_row("Candidates evaluated", str(response.total_candidates))
41
+ summary_table.add_row("Avg relevance", f"{response.avg_relevance_score:.3f}")
42
+
43
+ # Add timing breakdown
44
+ timing_parts: list[str] = []
45
+ for key, value in response.timing_ms.items():
46
+ timing_parts.append(f"{key}={value}ms")
47
+ if timing_parts:
48
+ summary_table.add_row("Timing", ", ".join(timing_parts))
49
+
50
+ summary_panel = Panel(summary_table, title="Search Summary", border_style="blue")
51
+ output.console.print(summary_panel)
52
+
53
+ # Show transformations if applied
54
+ if response.transformations_applied:
55
+ output.console.print(
56
+ f"\n[dim]Transformations applied:[/dim] "
57
+ f"[cyan]{', '.join(response.transformations_applied)}[/cyan]"
58
+ )
59
+
60
+ if response.sub_queries_used:
61
+ output.console.print("[dim]Sub-queries used:[/dim]")
62
+ for i, sq in enumerate(response.sub_queries_used, 1):
63
+ output.console.print(f" [cyan]{i}.[/cyan] {sq}")
64
+
65
+ # Build results table
66
+ output.console.print()
67
+ results_table = Table(title="Results", show_header=True, header_style="bold")
68
+ results_table.add_column("#", style="dim", width=3, justify="right")
69
+ results_table.add_column("Document", style="white", no_wrap=True, max_width=30)
70
+ results_table.add_column("Score", style="cyan", width=7, justify="right")
71
+ results_table.add_column("Content", style="dim", overflow="ellipsis")
72
+
73
+ low_confidence_results: list[int] = []
74
+ for i, result in enumerate(response.results, 1):
75
+ # Truncate content preview
76
+ content_preview = result.content.replace("\n", " ")[:100]
77
+ if len(result.content) > 100:
78
+ content_preview += "..."
79
+
80
+ # Mark low confidence results
81
+ score_display = f"{result.relevance_score:.3f}"
82
+ if result.low_confidence:
83
+ score_display = f"[yellow]{score_display}*[/yellow]"
84
+ low_confidence_results.append(i)
85
+
86
+ results_table.add_row(
87
+ str(i),
88
+ result.document_title,
89
+ score_display,
90
+ content_preview,
91
+ )
92
+
93
+ output.console.print(results_table)
94
+
95
+ # Show low confidence warning
96
+ if low_confidence_results:
97
+ output.console.print(
98
+ f"\n[yellow]* Results {', '.join(map(str, low_confidence_results))} "
99
+ "are below the confidence threshold[/yellow]"
100
+ )
101
+
102
+
103
+ def _present_json_results(response: SearchResponse) -> None:
104
+ """Present search results as JSON."""
105
+ output = OutputService.get()
106
+
107
+ # Convert response to JSON-serializable dict
108
+ data = response.model_dump(mode="json")
109
+
110
+ # Pretty-print JSON
111
+ output.console.print_json(json.dumps(data))
File without changes
File without changes
@@ -0,0 +1,127 @@
1
+ """Knowledge synthesis create command implementation."""
2
+
3
+ from typing import Annotated, Optional
4
+ from uuid import UUID
5
+
6
+ import typer
7
+
8
+ from cli.commands.flag_utils import validate_uuid
9
+ from cli.commands.knowledge.synthesis.create.presenter import (
10
+ present_synthesis_create_success,
11
+ )
12
+ from cli.infrastructure.command import async_command, authenticated_client
13
+ from cli.infrastructure.kv_parser import parse_kv_pairs
14
+ from alloy_runtime_types.dtos.knowledge import CreateSynthesisRequest
15
+
16
+
17
+ def knowledge_synthesis_create_command(
18
+ topic: str = typer.Option(
19
+ ...,
20
+ "-t",
21
+ "--topic",
22
+ help="Topic to research and synthesize",
23
+ ),
24
+ collections: str = typer.Option(
25
+ ...,
26
+ "-C",
27
+ "--collections",
28
+ help="Comma-separated collection UUIDs to include",
29
+ ),
30
+ agent: str = typer.Option(
31
+ ...,
32
+ "-a",
33
+ "--agent",
34
+ help="Synthesizer agent UUID (must have rag_search tool)",
35
+ ),
36
+ template: str = typer.Option(
37
+ ...,
38
+ "-T",
39
+ "--template",
40
+ help="Synthesis template UUID (receives {{ topic }} variable)",
41
+ ),
42
+ title: Optional[str] = typer.Option(
43
+ None,
44
+ "--title",
45
+ help="Title for the synthesis (defaults to topic)",
46
+ ),
47
+ metadata: Annotated[
48
+ Optional[list[str]],
49
+ typer.Option(
50
+ "-m",
51
+ "--metadata",
52
+ help="Metadata (key=value or key:=json). Repeatable.",
53
+ ),
54
+ ] = None,
55
+ ) -> None:
56
+ """Create a corpus-level synthesis.
57
+
58
+ A synthesis uses an agent with RAG tools to research a topic across
59
+ specified collections and generate a comprehensive response. The
60
+ synthesis is processed asynchronously - poll the synthesis status
61
+ to check for completion.
62
+
63
+ Examples:
64
+ ai2 knowledge synthesis create -t "API authentication methods" \\
65
+ -C <collection-uuid> -a <agent-uuid> -T <template-uuid>
66
+
67
+ ai2 kb synthesis create -t "Product roadmap summary" \\
68
+ -C <col1>,<col2> -a <agent> -T <template> --title "Q1 Roadmap"
69
+
70
+ ai2 kb synthesis create -t "Security best practices" \\
71
+ -C <collection> -a <agent> -T <template> -m priority=high
72
+ """
73
+ _execute_create_from_flags(
74
+ topic=topic,
75
+ collections=collections,
76
+ agent=agent,
77
+ template=template,
78
+ title=title,
79
+ metadata=metadata,
80
+ )
81
+
82
+
83
+ def _execute_create_from_flags(
84
+ topic: str,
85
+ collections: str,
86
+ agent: str,
87
+ template: str,
88
+ title: Optional[str],
89
+ metadata: Optional[list[str]],
90
+ ) -> None:
91
+ """Build and execute synthesis creation from command flags."""
92
+ # Parse collection IDs
93
+ collection_ids: list[UUID] = []
94
+ for cid in collections.split(","):
95
+ cid = cid.strip()
96
+ if cid:
97
+ collection_ids.append(validate_uuid(cid, "collection"))
98
+
99
+ if not collection_ids:
100
+ raise typer.BadParameter("At least one collection UUID is required")
101
+
102
+ # Validate agent and template UUIDs
103
+ agent_id = validate_uuid(agent, "agent")
104
+ template_id = validate_uuid(template, "template")
105
+
106
+ # Parse metadata (httpie style)
107
+ parsed_metadata = parse_kv_pairs(metadata) if metadata else None
108
+
109
+ request = CreateSynthesisRequest(
110
+ topic=topic,
111
+ collection_ids=collection_ids,
112
+ synthesizer_agent_id=agent_id,
113
+ synthesis_template_id=template_id,
114
+ title=title,
115
+ metadata=parsed_metadata,
116
+ )
117
+
118
+ _execute_create(request)
119
+
120
+
121
+ @async_command
122
+ async def _execute_create(request: CreateSynthesisRequest) -> None:
123
+ """Execute the synthesis creation with the given request."""
124
+ async with authenticated_client() as (_config, client):
125
+ response = await client.create_synthesis(request)
126
+
127
+ present_synthesis_create_success(response)
@@ -0,0 +1,33 @@
1
+ """Presenter for synthesis creation output."""
2
+
3
+ from rich.panel import Panel
4
+ from rich.table import Table
5
+
6
+ from cli.infrastructure.formatting.fields import format_uuid
7
+ from cli.infrastructure.output import OutputService
8
+ from alloy_runtime_types.dtos.knowledge import CreateSynthesisResponse
9
+
10
+
11
+ def present_synthesis_create_success(response: CreateSynthesisResponse) -> None:
12
+ """Present successful synthesis creation.
13
+
14
+ Args:
15
+ response: Synthesis creation response from server
16
+ """
17
+ output = OutputService.get()
18
+
19
+ output.success("Synthesis queued for generation")
20
+
21
+ # Build a simple table for entity display
22
+ table = Table(show_header=False, box=None, padding=(0, 1))
23
+ table.add_column("Field", style="dim")
24
+ table.add_column("Value")
25
+
26
+ table.add_row("Synthesis ID", format_uuid(response.synthesis_id, short=False))
27
+ table.add_row("Status", f"[yellow]{response.status}[/yellow]")
28
+ table.add_row("Message", response.message)
29
+
30
+ panel = Panel(table, title="Synthesis Created", border_style="green")
31
+ output.console.print(panel)
32
+
33
+ output.info(f"Poll status with: ai2 kb synthesis get {response.synthesis_id}")
File without changes