kiapi 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 (465) hide show
  1. kiapi/__init__.py +3 -0
  2. kiapi/__main__.py +4 -0
  3. kiapi/api/__init__.py +26 -0
  4. kiapi/api/_constants/require_auth.py +14 -0
  5. kiapi/api/_helpers/build_job_responses.py +73 -0
  6. kiapi/api/_helpers/build_openapi.py +55 -0
  7. kiapi/api/_helpers/build_train_responses.py +21 -0
  8. kiapi/api/_helpers/get_accept.py +20 -0
  9. kiapi/api/_helpers/get_ctx.py +7 -0
  10. kiapi/api/_helpers/get_worker.py +7 -0
  11. kiapi/api/_helpers/register_capability_endpoints.py +70 -0
  12. kiapi/api/_helpers/submit_and_maybe_wait.py +113 -0
  13. kiapi/api/_settings.py +50 -0
  14. kiapi/api/_views/async_job_response.py +21 -0
  15. kiapi/api/_views/capability_model_spec.py +49 -0
  16. kiapi/api/app.py +150 -0
  17. kiapi/api/audio/acestep/_views/extract_response.py +57 -0
  18. kiapi/api/audio/acestep/_views/track_response.py +57 -0
  19. kiapi/api/audio/acestep/router.py +190 -0
  20. kiapi/api/audio/audiogen/_views/audio_response.py +46 -0
  21. kiapi/api/audio/audiogen/router.py +77 -0
  22. kiapi/api/chat/_views/chat_completion_response.py +71 -0
  23. kiapi/api/chat/router.py +253 -0
  24. kiapi/api/embedding/_views/embedding_response.py +35 -0
  25. kiapi/api/embedding/router.py +82 -0
  26. kiapi/api/files/_operations/get_file.py +14 -0
  27. kiapi/api/files/_operations/get_file_id.py +18 -0
  28. kiapi/api/files/_views/file_delete_response.py +14 -0
  29. kiapi/api/files/_views/file_list_response.py +15 -0
  30. kiapi/api/files/router.py +105 -0
  31. kiapi/api/health/_views/health_response.py +26 -0
  32. kiapi/api/health/router.py +28 -0
  33. kiapi/api/image/depthpro/_views/estimate_response.py +70 -0
  34. kiapi/api/image/depthpro/router.py +81 -0
  35. kiapi/api/image/ernie/_views/image_response.py +50 -0
  36. kiapi/api/image/ernie/router.py +181 -0
  37. kiapi/api/image/flux2/_views/image_response.py +53 -0
  38. kiapi/api/image/flux2/router.py +197 -0
  39. kiapi/api/image/ideogram4/_views/image_response.py +55 -0
  40. kiapi/api/image/ideogram4/router.py +87 -0
  41. kiapi/api/image/qwen/_views/image_response.py +47 -0
  42. kiapi/api/image/qwen/router.py +141 -0
  43. kiapi/api/image/seedvr2/_views/image_response.py +50 -0
  44. kiapi/api/image/seedvr2/router.py +83 -0
  45. kiapi/api/image/zimage/_views/image_response.py +49 -0
  46. kiapi/api/image/zimage/router.py +131 -0
  47. kiapi/api/jobs/_operations/get_job_id.py +18 -0
  48. kiapi/api/jobs/_views/job_delete_response.py +19 -0
  49. kiapi/api/jobs/_views/job_list_response.py +15 -0
  50. kiapi/api/jobs/router.py +62 -0
  51. kiapi/api/models/_schemas/openai_model_spec.py +26 -0
  52. kiapi/api/models/_views/model_list_response.py +15 -0
  53. kiapi/api/models/router.py +29 -0
  54. kiapi/api/video/ltx2/_views/__init__.py +1 -0
  55. kiapi/api/video/ltx2/_views/video_response.py +59 -0
  56. kiapi/api/video/ltx2/router.py +89 -0
  57. kiapi/api/web/_views/__init__.py +7 -0
  58. kiapi/api/web/_views/fetch_api_request.py +26 -0
  59. kiapi/api/web/_views/fetch_error_response.py +25 -0
  60. kiapi/api/web/router.py +302 -0
  61. kiapi/capabilities/__init__.py +24 -0
  62. kiapi/capabilities/_exceptions/CapabilityError.py +2 -0
  63. kiapi/capabilities/_exceptions/ValidationError.py +2 -0
  64. kiapi/capabilities/_helpers/attach_mflux_progress.py +50 -0
  65. kiapi/capabilities/_helpers/get_file_path.py +20 -0
  66. kiapi/capabilities/_helpers/resolve_file_ref.py +16 -0
  67. kiapi/capabilities/acestep/README.ja.md +174 -0
  68. kiapi/capabilities/acestep/README.md +167 -0
  69. kiapi/capabilities/acestep/__init__.py +37 -0
  70. kiapi/capabilities/acestep/_constants/description.py +122 -0
  71. kiapi/capabilities/acestep/_exceptions/ace_step_engine_error.py +2 -0
  72. kiapi/capabilities/acestep/_helpers/register.py +96 -0
  73. kiapi/capabilities/acestep/_models/acestep.py +105 -0
  74. kiapi/capabilities/acestep/_operations/handle_cover.py +23 -0
  75. kiapi/capabilities/acestep/_operations/handle_extract.py +38 -0
  76. kiapi/capabilities/acestep/_operations/handle_generate.py +18 -0
  77. kiapi/capabilities/acestep/_operations/handle_repaint.py +25 -0
  78. kiapi/capabilities/acestep/_operations/resolve_ace_step_paths.py +30 -0
  79. kiapi/capabilities/acestep/_operations/resolve_cover_params.py +21 -0
  80. kiapi/capabilities/acestep/_operations/resolve_engine.py +10 -0
  81. kiapi/capabilities/acestep/_operations/resolve_extract_params.py +24 -0
  82. kiapi/capabilities/acestep/_operations/resolve_generate_params.py +18 -0
  83. kiapi/capabilities/acestep/_operations/resolve_repaint_params.py +22 -0
  84. kiapi/capabilities/acestep/_schemas/ace_step_paths.py +29 -0
  85. kiapi/capabilities/acestep/_services/ace_step_engine.py +143 -0
  86. kiapi/capabilities/acestep/_settings.py +82 -0
  87. kiapi/capabilities/acestep/_views/ace_step_base.py +61 -0
  88. kiapi/capabilities/acestep/_views/cover_params.py +26 -0
  89. kiapi/capabilities/acestep/_views/cover_request.py +49 -0
  90. kiapi/capabilities/acestep/_views/extract_params.py +24 -0
  91. kiapi/capabilities/acestep/_views/extract_request.py +33 -0
  92. kiapi/capabilities/acestep/_views/generate_params.py +25 -0
  93. kiapi/capabilities/acestep/_views/generate_request.py +54 -0
  94. kiapi/capabilities/acestep/_views/repaint_params.py +27 -0
  95. kiapi/capabilities/acestep/_views/repaint_request.py +51 -0
  96. kiapi/capabilities/acestep/_views/track_params.py +7 -0
  97. kiapi/capabilities/acestep/worker_subprocess.py +247 -0
  98. kiapi/capabilities/audiogen/README.ja.md +49 -0
  99. kiapi/capabilities/audiogen/README.md +48 -0
  100. kiapi/capabilities/audiogen/__init__.py +25 -0
  101. kiapi/capabilities/audiogen/_constants/description.py +60 -0
  102. kiapi/capabilities/audiogen/_helpers/attach_audiogen_progress.py +27 -0
  103. kiapi/capabilities/audiogen/_helpers/register.py +42 -0
  104. kiapi/capabilities/audiogen/_helpers/validate_generate.py +14 -0
  105. kiapi/capabilities/audiogen/_models/audiogen.py +98 -0
  106. kiapi/capabilities/audiogen/_operations/handle_generate.py +27 -0
  107. kiapi/capabilities/audiogen/_operations/resolve_generate_params.py +25 -0
  108. kiapi/capabilities/audiogen/_settings.py +34 -0
  109. kiapi/capabilities/audiogen/_views/generate_params.py +14 -0
  110. kiapi/capabilities/audiogen/_views/generate_request.py +96 -0
  111. kiapi/capabilities/chat/README.ja.md +822 -0
  112. kiapi/capabilities/chat/README.md +806 -0
  113. kiapi/capabilities/chat/__init__.py +25 -0
  114. kiapi/capabilities/chat/_constants/description.py +163 -0
  115. kiapi/capabilities/chat/_helpers/register.py +67 -0
  116. kiapi/capabilities/chat/_models/qwen3_5.py +183 -0
  117. kiapi/capabilities/chat/_models/qwen3_omni.py +242 -0
  118. kiapi/capabilities/chat/_operations/apply_template.py +74 -0
  119. kiapi/capabilities/chat/_operations/completed_hermes_tool_call_text.py +9 -0
  120. kiapi/capabilities/chat/_operations/emit_streaming_response.py +297 -0
  121. kiapi/capabilities/chat/_operations/ensure_streaming_detokenizer_compat.py +49 -0
  122. kiapi/capabilities/chat/_operations/format_response.py +72 -0
  123. kiapi/capabilities/chat/_operations/handle_chat.py +25 -0
  124. kiapi/capabilities/chat/_operations/parse_hermes_tool_calls.py +63 -0
  125. kiapi/capabilities/chat/_operations/parse_json_tool_calls.py +66 -0
  126. kiapi/capabilities/chat/_operations/parse_messages.py +326 -0
  127. kiapi/capabilities/chat/_operations/resolve_chat_params.py +50 -0
  128. kiapi/capabilities/chat/_operations/stream_text_from_tokens.py +32 -0
  129. kiapi/capabilities/chat/_operations/strip_tool_calls.py +15 -0
  130. kiapi/capabilities/chat/_settings.py +74 -0
  131. kiapi/capabilities/chat/_utils/apply_parallel_tool_call_policy.py +17 -0
  132. kiapi/capabilities/chat/_utils/apply_seed.py +8 -0
  133. kiapi/capabilities/chat/_utils/load_audio_mono.py +31 -0
  134. kiapi/capabilities/chat/_utils/load_mlx_vlm.py +12 -0
  135. kiapi/capabilities/chat/_utils/warmup_params.py +26 -0
  136. kiapi/capabilities/chat/_views/chat_params.py +34 -0
  137. kiapi/capabilities/chat/_views/chat_request.py +153 -0
  138. kiapi/capabilities/depthpro/README.ja.md +131 -0
  139. kiapi/capabilities/depthpro/README.md +124 -0
  140. kiapi/capabilities/depthpro/__init__.py +23 -0
  141. kiapi/capabilities/depthpro/_constants/description.py +39 -0
  142. kiapi/capabilities/depthpro/_helpers/register.py +46 -0
  143. kiapi/capabilities/depthpro/_helpers/validate_estimate.py +32 -0
  144. kiapi/capabilities/depthpro/_models/depthpro.py +144 -0
  145. kiapi/capabilities/depthpro/_operations/handle_estimate.py +50 -0
  146. kiapi/capabilities/depthpro/_operations/is_quantize_override.py +12 -0
  147. kiapi/capabilities/depthpro/_operations/resolve_estimate_params.py +24 -0
  148. kiapi/capabilities/depthpro/_settings.py +46 -0
  149. kiapi/capabilities/depthpro/_views/estimate_params.py +21 -0
  150. kiapi/capabilities/depthpro/_views/estimate_request.py +63 -0
  151. kiapi/capabilities/embedding/README.ja.md +137 -0
  152. kiapi/capabilities/embedding/README.md +128 -0
  153. kiapi/capabilities/embedding/__init__.py +24 -0
  154. kiapi/capabilities/embedding/_constants/description.py +47 -0
  155. kiapi/capabilities/embedding/_helpers/register.py +66 -0
  156. kiapi/capabilities/embedding/_models/qwen3_text.py +53 -0
  157. kiapi/capabilities/embedding/_models/qwen3_vl.py +97 -0
  158. kiapi/capabilities/embedding/_operations/format_response.py +24 -0
  159. kiapi/capabilities/embedding/_operations/handle_embed.py +24 -0
  160. kiapi/capabilities/embedding/_operations/parse_inputs.py +108 -0
  161. kiapi/capabilities/embedding/_operations/resolve_embed_params.py +18 -0
  162. kiapi/capabilities/embedding/_settings.py +27 -0
  163. kiapi/capabilities/embedding/_utils/to_vector.py +20 -0
  164. kiapi/capabilities/embedding/_views/embed_params.py +17 -0
  165. kiapi/capabilities/embedding/_views/embed_request.py +39 -0
  166. kiapi/capabilities/ernie/README.ja.md +242 -0
  167. kiapi/capabilities/ernie/README.md +223 -0
  168. kiapi/capabilities/ernie/__init__.py +34 -0
  169. kiapi/capabilities/ernie/_constants/description.py +71 -0
  170. kiapi/capabilities/ernie/_helpers/register.py +60 -0
  171. kiapi/capabilities/ernie/_helpers/validate_edit.py +19 -0
  172. kiapi/capabilities/ernie/_helpers/validate_generate.py +8 -0
  173. kiapi/capabilities/ernie/_models/ernie.py +356 -0
  174. kiapi/capabilities/ernie/_operations/handle_edit.py +39 -0
  175. kiapi/capabilities/ernie/_operations/handle_generate.py +38 -0
  176. kiapi/capabilities/ernie/_operations/handle_train.py +77 -0
  177. kiapi/capabilities/ernie/_operations/is_quantize_override.py +16 -0
  178. kiapi/capabilities/ernie/_operations/resolve_edit_params.py +44 -0
  179. kiapi/capabilities/ernie/_operations/resolve_generate_params.py +40 -0
  180. kiapi/capabilities/ernie/_operations/resolve_lora_params.py +23 -0
  181. kiapi/capabilities/ernie/_operations/resolve_train_params.py +43 -0
  182. kiapi/capabilities/ernie/_operations/validate_common.py +33 -0
  183. kiapi/capabilities/ernie/_schemas/lora_ref.py +27 -0
  184. kiapi/capabilities/ernie/_settings.py +151 -0
  185. kiapi/capabilities/ernie/_views/edit_params.py +36 -0
  186. kiapi/capabilities/ernie/_views/edit_request.py +142 -0
  187. kiapi/capabilities/ernie/_views/generate_params.py +32 -0
  188. kiapi/capabilities/ernie/_views/generate_request.py +127 -0
  189. kiapi/capabilities/ernie/_views/train_params.py +28 -0
  190. kiapi/capabilities/ernie/_views/train_request.py +96 -0
  191. kiapi/capabilities/flux2/README.ja.md +260 -0
  192. kiapi/capabilities/flux2/README.md +241 -0
  193. kiapi/capabilities/flux2/__init__.py +36 -0
  194. kiapi/capabilities/flux2/_constants/description.py +81 -0
  195. kiapi/capabilities/flux2/_helpers/register.py +98 -0
  196. kiapi/capabilities/flux2/_helpers/validate_edit.py +12 -0
  197. kiapi/capabilities/flux2/_helpers/validate_generate.py +8 -0
  198. kiapi/capabilities/flux2/_models/flux2.py +396 -0
  199. kiapi/capabilities/flux2/_operations/handle_edit.py +44 -0
  200. kiapi/capabilities/flux2/_operations/handle_generate.py +46 -0
  201. kiapi/capabilities/flux2/_operations/handle_train.py +105 -0
  202. kiapi/capabilities/flux2/_operations/is_quantize_override.py +16 -0
  203. kiapi/capabilities/flux2/_operations/resolve_edit_params.py +43 -0
  204. kiapi/capabilities/flux2/_operations/resolve_generate_params.py +44 -0
  205. kiapi/capabilities/flux2/_operations/resolve_lora_params.py +23 -0
  206. kiapi/capabilities/flux2/_operations/resolve_train_params.py +42 -0
  207. kiapi/capabilities/flux2/_operations/role_spec.py +13 -0
  208. kiapi/capabilities/flux2/_operations/split_repo.py +11 -0
  209. kiapi/capabilities/flux2/_operations/validate_common.py +35 -0
  210. kiapi/capabilities/flux2/_schemas/lora_ref.py +27 -0
  211. kiapi/capabilities/flux2/_settings.py +181 -0
  212. kiapi/capabilities/flux2/_views/edit_params.py +36 -0
  213. kiapi/capabilities/flux2/_views/edit_request.py +145 -0
  214. kiapi/capabilities/flux2/_views/generate_params.py +36 -0
  215. kiapi/capabilities/flux2/_views/generate_request.py +150 -0
  216. kiapi/capabilities/flux2/_views/train_params.py +32 -0
  217. kiapi/capabilities/flux2/_views/train_request.py +102 -0
  218. kiapi/capabilities/ideogram4/README.ja.md +230 -0
  219. kiapi/capabilities/ideogram4/README.md +219 -0
  220. kiapi/capabilities/ideogram4/__init__.py +24 -0
  221. kiapi/capabilities/ideogram4/_constants/description.py +65 -0
  222. kiapi/capabilities/ideogram4/_helpers/register.py +44 -0
  223. kiapi/capabilities/ideogram4/_helpers/validate_generate.py +31 -0
  224. kiapi/capabilities/ideogram4/_models/ideogram4.py +120 -0
  225. kiapi/capabilities/ideogram4/_operations/handle_generate.py +30 -0
  226. kiapi/capabilities/ideogram4/_operations/is_quantize_override.py +12 -0
  227. kiapi/capabilities/ideogram4/_operations/resolve_generate_params.py +30 -0
  228. kiapi/capabilities/ideogram4/_settings.py +89 -0
  229. kiapi/capabilities/ideogram4/_views/generate_params.py +27 -0
  230. kiapi/capabilities/ideogram4/_views/generate_request.py +118 -0
  231. kiapi/capabilities/ltx2/README.ja.md +287 -0
  232. kiapi/capabilities/ltx2/README.md +274 -0
  233. kiapi/capabilities/ltx2/__init__.py +26 -0
  234. kiapi/capabilities/ltx2/_constants/description.py +81 -0
  235. kiapi/capabilities/ltx2/_helpers/register.py +58 -0
  236. kiapi/capabilities/ltx2/_helpers/validate_generate.py +42 -0
  237. kiapi/capabilities/ltx2/_models/ltx2.py +106 -0
  238. kiapi/capabilities/ltx2/_operations/detect_mode.py +19 -0
  239. kiapi/capabilities/ltx2/_operations/handle_generate.py +52 -0
  240. kiapi/capabilities/ltx2/_operations/resolve_generate_params.py +31 -0
  241. kiapi/capabilities/ltx2/_settings.py +93 -0
  242. kiapi/capabilities/ltx2/_views/generate_params.py +34 -0
  243. kiapi/capabilities/ltx2/_views/generate_request.py +151 -0
  244. kiapi/capabilities/qwen/README.ja.md +251 -0
  245. kiapi/capabilities/qwen/README.md +235 -0
  246. kiapi/capabilities/qwen/__init__.py +30 -0
  247. kiapi/capabilities/qwen/_constants/description.py +53 -0
  248. kiapi/capabilities/qwen/_helpers/register.py +60 -0
  249. kiapi/capabilities/qwen/_helpers/validate_edit.py +12 -0
  250. kiapi/capabilities/qwen/_helpers/validate_generate.py +12 -0
  251. kiapi/capabilities/qwen/_models/qwen.py +224 -0
  252. kiapi/capabilities/qwen/_operations/handle_edit.py +44 -0
  253. kiapi/capabilities/qwen/_operations/handle_generate.py +46 -0
  254. kiapi/capabilities/qwen/_operations/is_quantize_override.py +15 -0
  255. kiapi/capabilities/qwen/_operations/resolve_edit_params.py +35 -0
  256. kiapi/capabilities/qwen/_operations/resolve_generate_params.py +39 -0
  257. kiapi/capabilities/qwen/_operations/resolve_lora_params.py +23 -0
  258. kiapi/capabilities/qwen/_operations/validate_common.py +32 -0
  259. kiapi/capabilities/qwen/_schemas/lora_ref.py +27 -0
  260. kiapi/capabilities/qwen/_settings.py +107 -0
  261. kiapi/capabilities/qwen/_views/edit_params.py +36 -0
  262. kiapi/capabilities/qwen/_views/edit_request.py +138 -0
  263. kiapi/capabilities/qwen/_views/generate_params.py +37 -0
  264. kiapi/capabilities/qwen/_views/generate_request.py +149 -0
  265. kiapi/capabilities/seedvr2/README.ja.md +234 -0
  266. kiapi/capabilities/seedvr2/README.md +219 -0
  267. kiapi/capabilities/seedvr2/__init__.py +24 -0
  268. kiapi/capabilities/seedvr2/_constants/description.py +46 -0
  269. kiapi/capabilities/seedvr2/_helpers/register.py +60 -0
  270. kiapi/capabilities/seedvr2/_helpers/validate_upscale.py +52 -0
  271. kiapi/capabilities/seedvr2/_models/seedvr2.py +140 -0
  272. kiapi/capabilities/seedvr2/_operations/handle_upscale.py +42 -0
  273. kiapi/capabilities/seedvr2/_operations/is_quantize_override.py +12 -0
  274. kiapi/capabilities/seedvr2/_operations/resolve_upscale_params.py +30 -0
  275. kiapi/capabilities/seedvr2/_settings.py +74 -0
  276. kiapi/capabilities/seedvr2/_views/upscale_params.py +27 -0
  277. kiapi/capabilities/seedvr2/_views/upscale_request.py +94 -0
  278. kiapi/capabilities/web/README.ja.md +187 -0
  279. kiapi/capabilities/web/README.md +171 -0
  280. kiapi/capabilities/web/__init__.py +30 -0
  281. kiapi/capabilities/web/_constants/description.py +38 -0
  282. kiapi/capabilities/web/_exceptions/FetchError.py +24 -0
  283. kiapi/capabilities/web/_exceptions/SearchBackendError.py +11 -0
  284. kiapi/capabilities/web/_helpers/register.py +59 -0
  285. kiapi/capabilities/web/_models/crawl4ai.py +32 -0
  286. kiapi/capabilities/web/_models/searxng.py +44 -0
  287. kiapi/capabilities/web/_operations/handle_fetch.py +145 -0
  288. kiapi/capabilities/web/_operations/handle_search.py +56 -0
  289. kiapi/capabilities/web/_operations/resolve_fetch_params.py +19 -0
  290. kiapi/capabilities/web/_operations/resolve_search_params.py +34 -0
  291. kiapi/capabilities/web/_operations/resolve_searxng_config_dir.py +21 -0
  292. kiapi/capabilities/web/_services/__init__.py +1 -0
  293. kiapi/capabilities/web/_services/web_backend_process.py +144 -0
  294. kiapi/capabilities/web/_settings.py +138 -0
  295. kiapi/capabilities/web/_views/fetch_params.py +27 -0
  296. kiapi/capabilities/web/_views/fetch_request.py +29 -0
  297. kiapi/capabilities/web/_views/fetch_result.py +20 -0
  298. kiapi/capabilities/web/_views/search_params.py +43 -0
  299. kiapi/capabilities/web/_views/search_request.py +93 -0
  300. kiapi/capabilities/web/_views/search_response.py +49 -0
  301. kiapi/capabilities/web/resources/__init__.py +0 -0
  302. kiapi/capabilities/web/resources/searxng/__init__.py +0 -0
  303. kiapi/capabilities/web/resources/searxng/settings.yml +11 -0
  304. kiapi/capabilities/zimage/README.ja.md +249 -0
  305. kiapi/capabilities/zimage/README.md +231 -0
  306. kiapi/capabilities/zimage/__init__.py +34 -0
  307. kiapi/capabilities/zimage/_constants/description.py +73 -0
  308. kiapi/capabilities/zimage/_helpers/register.py +62 -0
  309. kiapi/capabilities/zimage/_helpers/validate_generate.py +37 -0
  310. kiapi/capabilities/zimage/_models/zimage.py +278 -0
  311. kiapi/capabilities/zimage/_operations/handle_generate.py +38 -0
  312. kiapi/capabilities/zimage/_operations/handle_train.py +78 -0
  313. kiapi/capabilities/zimage/_operations/is_quantize_override.py +11 -0
  314. kiapi/capabilities/zimage/_operations/resolve_generate_params.py +39 -0
  315. kiapi/capabilities/zimage/_operations/resolve_lora_params.py +23 -0
  316. kiapi/capabilities/zimage/_operations/resolve_train_params.py +38 -0
  317. kiapi/capabilities/zimage/_schemas/lora_ref.py +27 -0
  318. kiapi/capabilities/zimage/_settings.py +166 -0
  319. kiapi/capabilities/zimage/_views/generate_params.py +23 -0
  320. kiapi/capabilities/zimage/_views/generate_request.py +127 -0
  321. kiapi/capabilities/zimage/_views/train_params.py +22 -0
  322. kiapi/capabilities/zimage/_views/train_request.py +101 -0
  323. kiapi/cli/__init__.py +11 -0
  324. kiapi/cli/_helpers/dedupe_resources.py +12 -0
  325. kiapi/cli/_helpers/register_all_capabilities.py +36 -0
  326. kiapi/cli/_helpers/run_resources.py +24 -0
  327. kiapi/cli/_helpers/select_specs.py +67 -0
  328. kiapi/cli/activate/_operations/preflight_hf_access.py +129 -0
  329. kiapi/cli/activate/cli.py +37 -0
  330. kiapi/cli/check/_helpers/check_audio_acestep_turbo.py +22 -0
  331. kiapi/cli/check/_helpers/check_audio_acestep_xl_base.py +22 -0
  332. kiapi/cli/check/_helpers/check_audio_audiogen_medium.py +24 -0
  333. kiapi/cli/check/_helpers/check_chat_chat_qwen3_6_27b.py +19 -0
  334. kiapi/cli/check/_helpers/check_chat_chat_qwen3_omni.py +19 -0
  335. kiapi/cli/check/_helpers/check_embedding_embedding_qwen3_embedding_8b.py +14 -0
  336. kiapi/cli/check/_helpers/check_embedding_embedding_qwen3_vl_embedding_2b.py +19 -0
  337. kiapi/cli/check/_helpers/check_image_depthpro_base.py +21 -0
  338. kiapi/cli/check/_helpers/check_image_ernie_base.py +23 -0
  339. kiapi/cli/check/_helpers/check_image_ernie_turbo.py +23 -0
  340. kiapi/cli/check/_helpers/check_image_flux2_klein_9b.py +23 -0
  341. kiapi/cli/check/_helpers/check_image_flux2_klein_base_4b.py +23 -0
  342. kiapi/cli/check/_helpers/check_image_flux2_klein_base_9b.py +23 -0
  343. kiapi/cli/check/_helpers/check_image_ideogram4_fp8.py +23 -0
  344. kiapi/cli/check/_helpers/check_image_qwen_edit_2509.py +27 -0
  345. kiapi/cli/check/_helpers/check_image_qwen_image.py +23 -0
  346. kiapi/cli/check/_helpers/check_image_seedvr2_3b.py +23 -0
  347. kiapi/cli/check/_helpers/check_image_seedvr2_7b.py +23 -0
  348. kiapi/cli/check/_helpers/check_image_zimage_base.py +23 -0
  349. kiapi/cli/check/_helpers/check_image_zimage_turbo.py +23 -0
  350. kiapi/cli/check/_helpers/check_video_ltx2_distilled.py +26 -0
  351. kiapi/cli/check/_helpers/check_web_web_fetch.py +14 -0
  352. kiapi/cli/check/_helpers/check_web_web_search.py +14 -0
  353. kiapi/cli/check/_operations/build_check_result.py +20 -0
  354. kiapi/cli/check/_operations/check_context.py +10 -0
  355. kiapi/cli/check/_operations/create_sample_image.py +46 -0
  356. kiapi/cli/check/_schemas/check_result.py +12 -0
  357. kiapi/cli/check/cli.py +89 -0
  358. kiapi/cli/cli.py +29 -0
  359. kiapi/cli/config/cli.py +17 -0
  360. kiapi/cli/config/edit/cli.py +32 -0
  361. kiapi/cli/config/init/cli.py +33 -0
  362. kiapi/cli/config/show/cli.py +13 -0
  363. kiapi/cli/config/template/cli.py +36 -0
  364. kiapi/cli/deactivate/cli.py +49 -0
  365. kiapi/cli/run/asgi.py +16 -0
  366. kiapi/cli/run/cli.py +59 -0
  367. kiapi/cli/service/__init__.py +5 -0
  368. kiapi/cli/service/_services/service_manager.py +107 -0
  369. kiapi/cli/service/cli.py +19 -0
  370. kiapi/cli/service/install/cli.py +17 -0
  371. kiapi/cli/service/start/cli.py +22 -0
  372. kiapi/cli/service/status/cli.py +81 -0
  373. kiapi/cli/service/stop/cli.py +19 -0
  374. kiapi/cli/service/uninstall/cli.py +16 -0
  375. kiapi/cli/status/cli.py +226 -0
  376. kiapi/core/app/__init__.py +16 -0
  377. kiapi/core/app/_schemas/app_context.py +28 -0
  378. kiapi/core/app/_services/user_directory.py +59 -0
  379. kiapi/core/app/_settings.py +46 -0
  380. kiapi/core/capability/__init__.py +11 -0
  381. kiapi/core/capability/_schemas/capability_spec.py +17 -0
  382. kiapi/core/capability/_services/capability_spec_registry.py +21 -0
  383. kiapi/core/config/__init__.py +11 -0
  384. kiapi/core/config/_exceptions/user_config_error.py +2 -0
  385. kiapi/core/config/_helpers/get_user_settings_path.py +7 -0
  386. kiapi/core/config/_helpers/load_user_settings.py +54 -0
  387. kiapi/core/file/__init__.py +37 -0
  388. kiapi/core/file/_helpers/create_file_store.py +7 -0
  389. kiapi/core/file/_helpers/resolve_file_ref.py +90 -0
  390. kiapi/core/file/_schemas/file_data_url_ref.py +19 -0
  391. kiapi/core/file/_schemas/file_id_ref.py +16 -0
  392. kiapi/core/file/_schemas/file_record.py +46 -0
  393. kiapi/core/file/_schemas/file_url_ref.py +16 -0
  394. kiapi/core/file/_services/file_store.py +138 -0
  395. kiapi/core/file/_settings.py +22 -0
  396. kiapi/core/file/_types/file_id.py +2 -0
  397. kiapi/core/file/_types/file_ref.py +12 -0
  398. kiapi/core/file/_views/resolved_file_ref.py +16 -0
  399. kiapi/core/job/__init__.py +24 -0
  400. kiapi/core/job/_enums/job_status.py +9 -0
  401. kiapi/core/job/_helpers/creep_progress.py +123 -0
  402. kiapi/core/job/_models/job.py +121 -0
  403. kiapi/core/job/_services/job_store.py +33 -0
  404. kiapi/core/job/_services/progress_reporter.py +79 -0
  405. kiapi/core/job/_types/job_id.py +3 -0
  406. kiapi/core/job/_types/job_result.py +5 -0
  407. kiapi/core/job/_types/job_type.py +4 -0
  408. kiapi/core/logging/__init__.py +14 -0
  409. kiapi/core/logging/_helpers/get_log_level.py +8 -0
  410. kiapi/core/logging/_helpers/setup_logger.py +14 -0
  411. kiapi/core/logging/_settings.py +34 -0
  412. kiapi/core/logging/_types/log_level.py +3 -0
  413. kiapi/core/memory/__init__.py +21 -0
  414. kiapi/core/memory/_exceptions/memory_budget_error.py +2 -0
  415. kiapi/core/memory/_helpers/create_memory_manager.py +17 -0
  416. kiapi/core/memory/_operations/log_memory_limit.py +29 -0
  417. kiapi/core/memory/_operations/resolve_effective_memory_limit_gb.py +13 -0
  418. kiapi/core/memory/_operations/resolve_framework_strategy.py +42 -0
  419. kiapi/core/memory/_schemas/framework_strategy.py +14 -0
  420. kiapi/core/memory/_schemas/memory_stats.py +24 -0
  421. kiapi/core/memory/_schemas/resident_model.py +14 -0
  422. kiapi/core/memory/_schemas/resident_model_stats.py +49 -0
  423. kiapi/core/memory/_services/memory_manager.py +257 -0
  424. kiapi/core/memory/_settings.py +36 -0
  425. kiapi/core/memory/_types/framework_name.py +4 -0
  426. kiapi/core/memory/_types/resident_key.py +4 -0
  427. kiapi/core/model/__init__.py +36 -0
  428. kiapi/core/model/_exceptions/unknown_model_error.py +2 -0
  429. kiapi/core/model/_schemas/model_spec.py +145 -0
  430. kiapi/core/model/_services/model_registry.py +85 -0
  431. kiapi/core/model/_types/model_alias.py +2 -0
  432. kiapi/core/model/_types/model_domain.py +6 -0
  433. kiapi/core/model/_types/model_family.py +5 -0
  434. kiapi/core/model/_types/model_key.py +8 -0
  435. kiapi/core/model/_types/model_name.py +4 -0
  436. kiapi/core/model/_types/model_repo.py +3 -0
  437. kiapi/core/net/__init__.py +16 -0
  438. kiapi/core/net/_exceptions/unsafe_url_error.py +7 -0
  439. kiapi/core/net/_helpers/verify_public_url.py +68 -0
  440. kiapi/core/net/_settings.py +28 -0
  441. kiapi/core/setup/__init__.py +25 -0
  442. kiapi/core/setup/_exceptions/setup_required_error.py +2 -0
  443. kiapi/core/setup/_schemas/docker_image_resource.py +37 -0
  444. kiapi/core/setup/_schemas/hf_snapshot_resource.py +50 -0
  445. kiapi/core/setup/_schemas/local_path_resource.py +43 -0
  446. kiapi/core/setup/_schemas/python_package_resource.py +58 -0
  447. kiapi/core/setup/_schemas/python_venv_resource.py +63 -0
  448. kiapi/core/setup/_schemas/setup_status.py +7 -0
  449. kiapi/core/setup/_schemas/url_file_resource.py +43 -0
  450. kiapi/core/setup/_services/setup_manager.py +331 -0
  451. kiapi/core/setup/_types/setup_resource.py +21 -0
  452. kiapi/core/setup/_types/setup_target.py +11 -0
  453. kiapi/core/workdir/__init__.py +8 -0
  454. kiapi/core/workdir/_helpers/create_work_dir.py +11 -0
  455. kiapi/core/workdir/_settings.py +21 -0
  456. kiapi/core/worker/__init__.py +23 -0
  457. kiapi/core/worker/_helpers/create_worker.py +9 -0
  458. kiapi/core/worker/_services/worker.py +165 -0
  459. kiapi/core/worker/_settings.py +36 -0
  460. kiapi/core/worker/_types/job_thunk.py +6 -0
  461. kiapi-0.1.0.dist-info/METADATA +337 -0
  462. kiapi-0.1.0.dist-info/RECORD +465 -0
  463. kiapi-0.1.0.dist-info/WHEEL +4 -0
  464. kiapi-0.1.0.dist-info/entry_points.txt +2 -0
  465. kiapi-0.1.0.dist-info/licenses/LICENSE +21 -0
@@ -0,0 +1,253 @@
1
+ """Chat API: OpenAI-compatible ``POST /v1/chat/completions``.
2
+
3
+ Internally still a job (so it shows up in /v1/jobs and shares the single-flight
4
+ worker). Non-streaming callers wait for the completion dict. Streaming callers
5
+ receive OpenAI-style SSE chunks while the worker thread generates; the final job
6
+ result remains inspectable through /v1/jobs.
7
+ """
8
+
9
+ import asyncio
10
+ import base64
11
+ import binascii
12
+ import json
13
+ import logging
14
+ import re
15
+ from collections.abc import AsyncIterator
16
+ from copy import deepcopy
17
+ from typing import Any
18
+
19
+ from fastapi import APIRouter, Depends, HTTPException
20
+ from fastapi.responses import StreamingResponse
21
+
22
+ from kiapi.api import (
23
+ REQUIRE_AUTH,
24
+ get_ctx,
25
+ get_worker,
26
+ register_capability_endpoints,
27
+ )
28
+ from kiapi.api._settings import settings_manager
29
+ from kiapi.capabilities.chat import ChatRequest, handle_chat
30
+ from kiapi.core.app import AppContext
31
+ from kiapi.core.memory import MemoryBudgetError
32
+ from kiapi.core.model import UnknownModelError, model_registry
33
+ from kiapi.core.setup import SetupRequiredError
34
+ from kiapi.core.worker import Worker
35
+
36
+ from ._views.chat_completion_response import ChatCompletionResponse
37
+
38
+ logger = logging.getLogger(__name__)
39
+
40
+ router = APIRouter(dependencies=REQUIRE_AUTH)
41
+
42
+ _BASE64_PLACEHOLDER = "<base64_encoded_data>"
43
+
44
+ _DATA_URL_BASE64 = re.compile(
45
+ r"^(?P<prefix>data:[^,]*;base64,)(?P<data>.*)$",
46
+ re.DOTALL,
47
+ )
48
+
49
+
50
+ @router.post(
51
+ "/v1/chat/completions",
52
+ response_model=None,
53
+ responses={
54
+ 200: {
55
+ "model": ChatCompletionResponse,
56
+ "description": (
57
+ "Non-streaming: the full `chat.completion` object. "
58
+ "Streaming (`stream: true`): an OpenAI `text/event-stream` of "
59
+ "`chat.completion.chunk` events, each `data: {...}`, terminated "
60
+ "by `data: [DONE]`. Tool calls arrive as `delta.tool_calls`; the "
61
+ "final chunk carries `finish_reason`."
62
+ ),
63
+ "content": {
64
+ "text/event-stream": {"schema": {"type": "string", "format": "binary"}},
65
+ },
66
+ },
67
+ 400: {"description": "Invalid request, unknown model, or bad input/modality."},
68
+ 503: {"description": "Model not set up, or memory budget exceeded."},
69
+ 504: {"description": "Sync timeout exceeded; the job keeps running."},
70
+ },
71
+ )
72
+ async def chat_completions(
73
+ req: ChatRequest,
74
+ ctx: AppContext = Depends(get_ctx),
75
+ worker: Worker = Depends(get_worker),
76
+ ) -> dict | StreamingResponse:
77
+ """Generate a chat completion (OpenAI-compatible).
78
+
79
+ Accepts the OpenAI `chat.completions` request shape with multimodal
80
+ `messages` (text / image / audio / video), function `tools`, and
81
+ `tool_choice`. The resolved `model` (see GET /v1/models) determines which
82
+ input modalities are accepted.
83
+
84
+ Every request runs as a single-flight job, so it appears in /v1/jobs and is
85
+ serialized with all other generation. Non-streaming callers wait up to the
86
+ sync timeout and receive the full `chat.completion`; on timeout the job
87
+ keeps running and can be polled at /v1/jobs/{id}. Set `stream: true` to
88
+ receive incremental `chat.completion.chunk` SSE events instead.
89
+ """
90
+ settings = settings_manager.get_settings()
91
+
92
+ logger.debug(
93
+ "chat/completions request validated: %s",
94
+ _redacted_chat_request_dump(req),
95
+ )
96
+
97
+ if req.stream:
98
+ try:
99
+ model_registry.resolve("chat", req.model)
100
+ except UnknownModelError as exc:
101
+ raise HTTPException(status_code=400, detail=str(exc)) # noqa: B904
102
+
103
+ loop = asyncio.get_running_loop()
104
+ queue: asyncio.Queue[dict | None] = asyncio.Queue()
105
+
106
+ def emit(chunk: dict) -> None:
107
+ loop.call_soon_threadsafe(queue.put_nowait, chunk)
108
+
109
+ def finish_stream() -> None:
110
+ loop.call_soon_threadsafe(queue.put_nowait, None)
111
+
112
+ def thunk(): # type: ignore
113
+ try:
114
+ return handle_chat(ctx, req, emit=emit)
115
+ finally:
116
+ finish_stream()
117
+
118
+ job = ctx.job_store.create(
119
+ type="chat", params={"model": req.model, "stream": True}
120
+ )
121
+ fut = await worker.submit(job, thunk)
122
+
123
+ async def events() -> AsyncIterator[str]:
124
+ try:
125
+ while True:
126
+ item = await queue.get()
127
+ if item is None:
128
+ break
129
+ yield _sse(item)
130
+
131
+ try:
132
+ await asyncio.shield(fut)
133
+ except Exception as exc:
134
+ yield _sse(_stream_error(exc))
135
+ yield _sse("[DONE]")
136
+ except asyncio.CancelledError:
137
+ # The running worker job is not preemptible; let it finish and
138
+ # keep its final state in the job store.
139
+ return
140
+
141
+ return StreamingResponse(
142
+ events(),
143
+ media_type="text/event-stream",
144
+ headers={
145
+ "Cache-Control": "no-cache",
146
+ "X-Accel-Buffering": "no",
147
+ },
148
+ )
149
+
150
+ job = ctx.job_store.create(type="chat", params={"model": req.model})
151
+ fut = await worker.submit(job, lambda: handle_chat(ctx, req))
152
+
153
+ try:
154
+ return await asyncio.wait_for(fut, timeout=settings.sync_timeout_s)
155
+ except TimeoutError:
156
+ raise HTTPException( # noqa: B904
157
+ status_code=504,
158
+ detail=f"chat job {job.id} exceeded sync timeout "
159
+ f"({settings.sync_timeout_s}s); it keeps running — poll /v1/jobs/{job.id}",
160
+ )
161
+ except UnknownModelError as exc:
162
+ raise HTTPException(status_code=400, detail=str(exc)) # noqa: B904
163
+ except SetupRequiredError as exc:
164
+ raise HTTPException(status_code=503, detail=str(exc)) # noqa: B904
165
+ except MemoryBudgetError as exc:
166
+ raise HTTPException(status_code=503, detail=str(exc)) # noqa: B904
167
+ except Exception as exc:
168
+ # MediaError/CapabilityError (bad input / unsupported modality) → 400.
169
+ if exc.__class__.__name__ in ("MediaError", "CapabilityError"):
170
+ raise HTTPException(status_code=400, detail=str(exc)) # noqa: B904
171
+ raise HTTPException(status_code=500, detail=f"generation failed: {exc}") # noqa: B904
172
+
173
+
174
+ register_capability_endpoints(router, name="chat", base_path="/v1/chat")
175
+
176
+
177
+ def _redact_data_url(value: str) -> str:
178
+ m = _DATA_URL_BASE64.match(value)
179
+ if not m:
180
+ return value
181
+ return f"{m.group('prefix')}{_BASE64_PLACEHOLDER}"
182
+
183
+
184
+ def _looks_like_base64(value: str) -> bool:
185
+ """Heuristic for bare media payloads; avoids redacting ordinary short text."""
186
+ s = value.strip()
187
+ if len(s) < 128:
188
+ return False
189
+ try:
190
+ base64.b64decode(s, validate=True)
191
+ except (binascii.Error, ValueError):
192
+ return False
193
+ return True
194
+
195
+
196
+ def _redact_media_source(value: Any, *, bare_base64: bool = False) -> Any:
197
+ if not isinstance(value, str):
198
+ return value
199
+ redacted = _redact_data_url(value)
200
+ if redacted != value:
201
+ return redacted
202
+ if bare_base64 and _looks_like_base64(value):
203
+ return _BASE64_PLACEHOLDER
204
+ return value
205
+
206
+
207
+ def _redact_content_part(part: Any) -> Any:
208
+ if not isinstance(part, dict):
209
+ return part
210
+
211
+ out = deepcopy(part)
212
+ for key in ("image_url", "audio_url", "video_url"):
213
+ container = out.get(key)
214
+ if isinstance(container, dict) and "url" in container:
215
+ container["url"] = _redact_media_source(container["url"])
216
+ elif isinstance(container, str):
217
+ out[key] = _redact_media_source(container)
218
+
219
+ for key in ("input_audio", "input_video"):
220
+ container = out.get(key)
221
+ if isinstance(container, dict) and "data" in container:
222
+ container["data"] = _BASE64_PLACEHOLDER
223
+ elif isinstance(container, str):
224
+ out[key] = _redact_media_source(container, bare_base64=True)
225
+
226
+ for key in ("image", "audio", "video"):
227
+ if key in out:
228
+ out[key] = _redact_media_source(out[key], bare_base64=True)
229
+
230
+ return out
231
+
232
+
233
+ def _redacted_chat_request_dump(req: ChatRequest) -> str:
234
+ data = req.model_dump(mode="json")
235
+ messages = data.get("messages")
236
+ if isinstance(messages, list):
237
+ for msg in messages:
238
+ if not isinstance(msg, dict):
239
+ continue
240
+ content = msg.get("content")
241
+ if isinstance(content, list):
242
+ msg["content"] = [_redact_content_part(part) for part in content]
243
+ return json.dumps(data, ensure_ascii=False, indent=2)
244
+
245
+
246
+ def _sse(payload) -> str: # type: ignore
247
+ if payload == "[DONE]":
248
+ return "data: [DONE]\n\n"
249
+ return f"data: {json.dumps(payload, ensure_ascii=False)}\n\n"
250
+
251
+
252
+ def _stream_error(exc: BaseException) -> dict:
253
+ return {"error": {"message": str(exc), "type": exc.__class__.__name__}}
@@ -0,0 +1,35 @@
1
+ """``/v1/embedding`` response model.
2
+
3
+ Mirrors the dict shaped by ``capabilities/embedding/_operations/format_response``
4
+ so the response is self-describing in OpenAPI. It is an output-side projection of
5
+ the model result (not a model-coupled view), so it lives under
6
+ ``api/embedding/_views``.
7
+
8
+ ``EmbeddingResponse`` is the sole public element; the nested pieces are private
9
+ since nothing references them on their own.
10
+ """
11
+
12
+ from pydantic import BaseModel, Field
13
+
14
+
15
+ class _Usage(BaseModel):
16
+ prompt_tokens: int = Field(
17
+ description="Tokens in the embedded input (0 when the model does not report it)."
18
+ )
19
+ total_tokens: int = Field(
20
+ description="Total tokens accounted for; equals `prompt_tokens` (no generation)."
21
+ )
22
+
23
+
24
+ class _Timings(BaseModel):
25
+ total_s: float = Field(description="Wall-clock embedding time in seconds.")
26
+
27
+
28
+ class EmbeddingResponse(BaseModel):
29
+ model: str = Field(description="Resolved model name that produced the vector.")
30
+ embedding: list[float] = Field(
31
+ description="L2-normalized, last-token-pooled embedding vector for the item."
32
+ )
33
+ dimension: int = Field(description="Length of `embedding` (vector dimensionality).")
34
+ usage: _Usage = Field(description="Token accounting for the request.")
35
+ timings: _Timings = Field(description="kiapi extension: server-side timing.")
@@ -0,0 +1,82 @@
1
+ """Embedding API: ``POST /v1/embedding`` (sync only).
2
+
3
+ Like chat, still a job internally (shows up in /v1/jobs, shares the single-flight
4
+ worker), but no async mode: the caller always gets the vector back. A sync wait
5
+ that exceeds ``sync_timeout_s`` is an error (504).
6
+ """
7
+
8
+ import asyncio
9
+
10
+ from fastapi import APIRouter, Depends, HTTPException
11
+
12
+ from kiapi.api import (
13
+ REQUIRE_AUTH,
14
+ get_ctx,
15
+ get_worker,
16
+ register_capability_endpoints,
17
+ )
18
+ from kiapi.api._settings import settings_manager
19
+ from kiapi.capabilities.embedding import EmbedRequest, handle_embed
20
+ from kiapi.core.app import AppContext
21
+ from kiapi.core.memory import MemoryBudgetError
22
+ from kiapi.core.model import UnknownModelError
23
+ from kiapi.core.setup import SetupRequiredError
24
+ from kiapi.core.worker import Worker
25
+
26
+ from ._views.embedding_response import EmbeddingResponse
27
+
28
+ router = APIRouter(dependencies=REQUIRE_AUTH)
29
+
30
+
31
+ @router.post(
32
+ "/v1/embedding",
33
+ response_model=EmbeddingResponse,
34
+ responses={
35
+ 400: {"description": "Unknown model, empty input, or unsupported modality."},
36
+ 503: {"description": "Model not set up, or memory budget exceeded."},
37
+ 504: {"description": "Sync timeout exceeded; the job keeps running."},
38
+ },
39
+ )
40
+ async def embedding(
41
+ req: EmbedRequest,
42
+ ctx: AppContext = Depends(get_ctx),
43
+ worker: Worker = Depends(get_worker),
44
+ ) -> dict:
45
+ """Embed a single item (one field per modality).
46
+
47
+ Send `text` and/or `image` in one request (one item, not OpenAI's array
48
+ `input`). The resolved `model` (see GET /v1/embedding/models) determines which
49
+ modalities are accepted; provide at least one input it supports. Returns one
50
+ L2-normalized, last-token-pooled vector with its `dimension`.
51
+
52
+ Embedding runs as a single-flight job, so it appears in /v1/jobs and is
53
+ serialized with all other generation, but there is no async mode: the caller
54
+ always waits for the vector. A wait that exceeds the sync timeout returns 504
55
+ while the job keeps running and can be polled at /v1/jobs/{id}.
56
+ """
57
+ settings = settings_manager.get_settings()
58
+
59
+ job = ctx.job_store.create(type="embedding", params={"model": req.model})
60
+ fut = await worker.submit(job, lambda: handle_embed(ctx, req))
61
+
62
+ try:
63
+ return await asyncio.wait_for(fut, timeout=settings.sync_timeout_s)
64
+ except TimeoutError:
65
+ raise HTTPException( # noqa: B904
66
+ status_code=504,
67
+ detail=f"embedding job {job.id} exceeded sync timeout "
68
+ f"({settings.sync_timeout_s}s); poll /v1/jobs/{job.id}",
69
+ )
70
+ except UnknownModelError as exc:
71
+ raise HTTPException(status_code=400, detail=str(exc)) # noqa: B904
72
+ except SetupRequiredError as exc:
73
+ raise HTTPException(status_code=503, detail=str(exc)) # noqa: B904
74
+ except MemoryBudgetError as exc:
75
+ raise HTTPException(status_code=503, detail=str(exc)) # noqa: B904
76
+ except Exception as exc:
77
+ if exc.__class__.__name__ in ("MediaError", "CapabilityError"):
78
+ raise HTTPException(status_code=400, detail=str(exc)) # noqa: B904
79
+ raise HTTPException(status_code=500, detail=f"embedding failed: {exc}") # noqa: B904
80
+
81
+
82
+ register_capability_endpoints(router, name="embedding", base_path="/v1/embedding")
@@ -0,0 +1,14 @@
1
+ from typing import Annotated
2
+
3
+ from fastapi import File, UploadFile
4
+
5
+
6
+ def _get_file(
7
+ file: Annotated[
8
+ UploadFile,
9
+ File(
10
+ description="File bytes to store and reference from inference requests.",
11
+ ),
12
+ ],
13
+ ) -> UploadFile:
14
+ return file
@@ -0,0 +1,18 @@
1
+ from typing import Annotated
2
+
3
+ from fastapi import Path
4
+
5
+ from kiapi.core.file import FileID
6
+
7
+
8
+ def _get_file_id(
9
+ file_id: Annotated[
10
+ str,
11
+ Path(
12
+ pattern=r"^file_[0-9a-f]+$",
13
+ description="Persistent file id returned by the Files API.",
14
+ examples=["file_0123456789abcdef"],
15
+ ),
16
+ ],
17
+ ) -> FileID:
18
+ return file_id
@@ -0,0 +1,14 @@
1
+ from pydantic import BaseModel, Field
2
+
3
+
4
+ class FileDeleteResponse(BaseModel):
5
+ deleted: bool = Field(
6
+ ...,
7
+ description="True when the file record and stored bytes were deleted.",
8
+ examples=[True],
9
+ )
10
+ file_id: str = Field(
11
+ ...,
12
+ description="Deleted file id.",
13
+ examples=["file_0123456789abcdef"],
14
+ )
@@ -0,0 +1,15 @@
1
+ from pydantic import BaseModel, Field
2
+
3
+ from kiapi.core.file import FileRecord
4
+
5
+
6
+ class FileListResponse(BaseModel):
7
+ object: str = Field(
8
+ default="list",
9
+ description="OpenAI-style list envelope marker.",
10
+ examples=["list"],
11
+ )
12
+ data: list[FileRecord] = Field(
13
+ default_factory=list,
14
+ description="Stored files, including uploaded inputs and generated artifacts.",
15
+ )
@@ -0,0 +1,105 @@
1
+ """Files API: upload / list / get / download / delete. Unified across capabilities."""
2
+
3
+ from fastapi import APIRouter, Depends, HTTPException, UploadFile
4
+ from fastapi.responses import FileResponse
5
+
6
+ from kiapi.api import REQUIRE_AUTH, get_ctx
7
+ from kiapi.core.app import AppContext
8
+ from kiapi.core.file import FileID, FileRecord
9
+
10
+ from ._operations.get_file import _get_file
11
+ from ._operations.get_file_id import _get_file_id
12
+ from ._views.file_delete_response import FileDeleteResponse
13
+ from ._views.file_list_response import FileListResponse
14
+
15
+ router = APIRouter(prefix="/v1/files", dependencies=REQUIRE_AUTH)
16
+
17
+
18
+ @router.post("", response_model=FileRecord)
19
+ async def upload(
20
+ file: UploadFile = Depends(_get_file),
21
+ ctx: AppContext = Depends(get_ctx),
22
+ ) -> FileRecord:
23
+ """Store a file and return a reusable file_id.
24
+
25
+ Uploaded files become persistent Files API records. Use the returned
26
+ file_id as a FileRef input for generation/editing endpoints, or download
27
+ the bytes later with GET /v1/files/{file_id}/download.
28
+ """
29
+ data = await file.read()
30
+ return ctx.file_store.put_bytes(
31
+ data,
32
+ filename=file.filename or "upload",
33
+ content_type=file.content_type,
34
+ )
35
+
36
+
37
+ @router.get("", response_model=FileListResponse)
38
+ async def list_files(ctx: AppContext = Depends(get_ctx)) -> FileListResponse:
39
+ """List stored files.
40
+
41
+ Files include explicit uploads and generated artifacts. File records are
42
+ disk-backed and can outlive in-memory jobs across process restarts.
43
+ """
44
+ return FileListResponse(data=ctx.file_store.list())
45
+
46
+
47
+ @router.get("/{file_id}", response_model=FileRecord)
48
+ async def get_file(
49
+ file_id: FileID = Depends(_get_file_id),
50
+ ctx: AppContext = Depends(get_ctx),
51
+ ) -> FileRecord:
52
+ """Get metadata for a stored file.
53
+
54
+ This returns metadata only, not file bytes. Use the download endpoint when
55
+ the client needs the artifact body.
56
+ """
57
+ rec = ctx.file_store.get(file_id)
58
+ if rec is None:
59
+ raise HTTPException(status_code=404, detail=f"unknown file {file_id!r}")
60
+ return rec
61
+
62
+
63
+ @router.get(
64
+ "/{file_id}/download",
65
+ responses={
66
+ 200: {
67
+ "description": "Stored file bytes.",
68
+ "content": {
69
+ "application/octet-stream": {
70
+ "schema": {"type": "string", "format": "binary"}
71
+ }
72
+ },
73
+ },
74
+ 404: {"description": "Unknown file_id."},
75
+ },
76
+ )
77
+ async def download_file(
78
+ file_id: FileID = Depends(_get_file_id),
79
+ ctx: AppContext = Depends(get_ctx),
80
+ ) -> FileResponse:
81
+ """Download stored file bytes.
82
+
83
+ The response media type is the stored file's content_type, such as
84
+ image/png, audio/wav, video/mp4, text/markdown, or application/pdf.
85
+ """
86
+ rec = ctx.file_store.get(file_id)
87
+ if rec is None:
88
+ raise HTTPException(status_code=404, detail=f"unknown file {file_id!r}")
89
+ return FileResponse(rec.path, media_type=rec.content_type, filename=rec.filename)
90
+
91
+
92
+ @router.delete("/{file_id}", response_model=FileDeleteResponse)
93
+ async def delete_file(
94
+ file_id: FileID = Depends(_get_file_id),
95
+ ctx: AppContext = Depends(get_ctx),
96
+ ) -> dict:
97
+ """Delete a stored file.
98
+
99
+ Deleting a file removes the stored bytes and metadata. Existing job records
100
+ may still mention the deleted file_id in artifacts, but the file can no
101
+ longer be downloaded.
102
+ """
103
+ if not ctx.file_store.delete(file_id):
104
+ raise HTTPException(status_code=404, detail=f"unknown file {file_id!r}")
105
+ return {"deleted": True, "file_id": file_id}
@@ -0,0 +1,26 @@
1
+ from pydantic import BaseModel, Field
2
+
3
+ from kiapi.core.memory import MemoryStats
4
+
5
+
6
+ class HealthResponse(BaseModel):
7
+ status: str = Field(
8
+ ...,
9
+ description="Service health marker. The value is ok when the API process is accepting requests.",
10
+ examples=["ok"],
11
+ )
12
+ warm: bool = Field(
13
+ ...,
14
+ description="Whether startup warmup has finished. Warmup may skip models that are not activated.",
15
+ examples=[True],
16
+ )
17
+ queue_len: int = Field(
18
+ ...,
19
+ ge=0,
20
+ description="Number of jobs waiting in the single-flight worker queue.",
21
+ examples=[0],
22
+ )
23
+ memory: MemoryStats = Field(
24
+ ...,
25
+ description="Resident model memory budget and loaded model snapshot.",
26
+ )
@@ -0,0 +1,28 @@
1
+ from fastapi import APIRouter, Depends
2
+
3
+ from kiapi.api import get_ctx, get_worker
4
+ from kiapi.core.app import AppContext
5
+ from kiapi.core.worker import Worker
6
+
7
+ from ._views.health_response import HealthResponse
8
+
9
+ router = APIRouter()
10
+
11
+
12
+ @router.get("/health", response_model=HealthResponse)
13
+ async def health(
14
+ ctx: AppContext = Depends(get_ctx),
15
+ worker: Worker = Depends(get_worker),
16
+ ) -> dict:
17
+ """Inspect server readiness, queue depth, and resident model memory.
18
+
19
+ Use this endpoint to see whether warmup has finished, how many jobs are
20
+ queued behind the single-flight worker, and which resident models currently
21
+ count against the global memory budget.
22
+ """
23
+ return {
24
+ "status": "ok",
25
+ "warm": worker.warm,
26
+ "queue_len": worker.queue.qsize(),
27
+ "memory": ctx.memory_manager.stats(),
28
+ }
@@ -0,0 +1,70 @@
1
+ """``/v1/image/depthpro/estimate`` result payload (the Job ``result`` shape).
2
+
3
+ Mirrors the dict returned by ``capabilities/depthpro/_models/depthpro._estimate``
4
+ so the depth-map result is self-describing in OpenAPI. It is an output-side
5
+ projection of the model result (not a model-coupled view), so it lives under
6
+ ``api/image/depthpro/_views``.
7
+
8
+ ``EstimateResponse`` is the sole public element; nested pieces stay private.
9
+ """
10
+
11
+ from typing import Any
12
+
13
+ from pydantic import BaseModel, Field
14
+
15
+
16
+ class _Timings(BaseModel):
17
+ total_s: float = Field(
18
+ description="Wall-clock depth-estimation time in seconds (model run only)."
19
+ )
20
+
21
+
22
+ class EstimateResponse(BaseModel):
23
+ """Capability-specific ``result`` for a succeeded depthpro estimate job."""
24
+
25
+ model: str = Field(
26
+ description="Resolved model variant that produced the depth map."
27
+ )
28
+
29
+ depth_image_file_id: str = Field(
30
+ description=(
31
+ "Files-API id of the grayscale depth PNG (near = bright, far = dark). "
32
+ "Fetch metadata at GET /v1/files/{id} or bytes at /download. This is "
33
+ "also the artifact returned as raw bytes by a single-artifact sync call."
34
+ )
35
+ )
36
+ depth_image_bytes: int = Field(description="Size of the depth PNG in bytes.")
37
+ depth_data_file_id: str | None = Field(
38
+ description=(
39
+ "Files-API id of the compressed NPZ holding the raw float depth array "
40
+ "plus min/max depth, or null when `include_depth_data` was false."
41
+ )
42
+ )
43
+ depth_data_bytes: int | None = Field(
44
+ description="Size of the NPZ in bytes, or null when no depth data was stored."
45
+ )
46
+
47
+ input_width: int = Field(description="Width in pixels of the submitted image.")
48
+ input_height: int = Field(description="Height in pixels of the submitted image.")
49
+ input_mode: str = Field(
50
+ description="PIL mode of the submitted image (e.g. RGB, L, RGBA)."
51
+ )
52
+
53
+ width: int = Field(description="Width in pixels of the produced depth map.")
54
+ height: int = Field(description="Height in pixels of the produced depth map.")
55
+ mode: str = Field(description="PIL mode of the produced depth PNG (typically L).")
56
+
57
+ array_shape: list[int] = Field(
58
+ description="Shape of the raw depth array stored in the NPZ (rows, cols)."
59
+ )
60
+ min_depth: float = Field(
61
+ description="Minimum depth value in the raw array, in meters."
62
+ )
63
+ max_depth: float = Field(
64
+ description="Maximum depth value in the raw array, in meters."
65
+ )
66
+
67
+ params: dict[str, Any] = Field(
68
+ description="Resolved parameters used for the run (model, quantize, etc.)."
69
+ )
70
+ timings: _Timings = Field(description="kiapi extension: server-side timing.")