@axhub/acp 0.1.0

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 (488) hide show
  1. package/.next/BUILD_ID +1 -0
  2. package/.next/app-path-routes-manifest.json +21 -0
  3. package/.next/build-manifest.json +22 -0
  4. package/.next/export-marker.json +6 -0
  5. package/.next/fallback-build-manifest.json +13 -0
  6. package/.next/images-manifest.json +68 -0
  7. package/.next/next-minimal-server.js.nft.json +1 -0
  8. package/.next/next-server.js.nft.json +1 -0
  9. package/.next/package.json +1 -0
  10. package/.next/prerender-manifest.json +90 -0
  11. package/.next/required-server-files.js +336 -0
  12. package/.next/required-server-files.json +336 -0
  13. package/.next/routes-manifest.json +171 -0
  14. package/.next/server/app/_global-error/page/app-paths-manifest.json +3 -0
  15. package/.next/server/app/_global-error/page/build-manifest.json +18 -0
  16. package/.next/server/app/_global-error/page/next-font-manifest.json +6 -0
  17. package/.next/server/app/_global-error/page/react-loadable-manifest.json +1 -0
  18. package/.next/server/app/_global-error/page/server-reference-manifest.json +4 -0
  19. package/.next/server/app/_global-error/page.js +10 -0
  20. package/.next/server/app/_global-error/page.js.nft.json +1 -0
  21. package/.next/server/app/_global-error/page_client-reference-manifest.js +3 -0
  22. package/.next/server/app/_global-error.html +1 -0
  23. package/.next/server/app/_global-error.meta +15 -0
  24. package/.next/server/app/_global-error.rsc +15 -0
  25. package/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +5 -0
  26. package/.next/server/app/_global-error.segments/_full.segment.rsc +15 -0
  27. package/.next/server/app/_global-error.segments/_head.segment.rsc +6 -0
  28. package/.next/server/app/_global-error.segments/_index.segment.rsc +5 -0
  29. package/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -0
  30. package/.next/server/app/_not-found/page/app-paths-manifest.json +3 -0
  31. package/.next/server/app/_not-found/page/build-manifest.json +18 -0
  32. package/.next/server/app/_not-found/page/next-font-manifest.json +6 -0
  33. package/.next/server/app/_not-found/page/react-loadable-manifest.json +1 -0
  34. package/.next/server/app/_not-found/page/server-reference-manifest.json +4 -0
  35. package/.next/server/app/_not-found/page.js +13 -0
  36. package/.next/server/app/_not-found/page.js.nft.json +1 -0
  37. package/.next/server/app/_not-found/page_client-reference-manifest.js +3 -0
  38. package/.next/server/app/_not-found.html +1 -0
  39. package/.next/server/app/_not-found.meta +16 -0
  40. package/.next/server/app/_not-found.rsc +17 -0
  41. package/.next/server/app/_not-found.segments/_full.segment.rsc +17 -0
  42. package/.next/server/app/_not-found.segments/_head.segment.rsc +6 -0
  43. package/.next/server/app/_not-found.segments/_index.segment.rsc +6 -0
  44. package/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +5 -0
  45. package/.next/server/app/_not-found.segments/_not-found.segment.rsc +5 -0
  46. package/.next/server/app/_not-found.segments/_tree.segment.rsc +2 -0
  47. package/.next/server/app/api/acp/capabilities/route/app-paths-manifest.json +3 -0
  48. package/.next/server/app/api/acp/capabilities/route/build-manifest.json +9 -0
  49. package/.next/server/app/api/acp/capabilities/route/server-reference-manifest.json +4 -0
  50. package/.next/server/app/api/acp/capabilities/route.js +9 -0
  51. package/.next/server/app/api/acp/capabilities/route.js.nft.json +1 -0
  52. package/.next/server/app/api/acp/capabilities/route_client-reference-manifest.js +3 -0
  53. package/.next/server/app/api/acp/commands/route/app-paths-manifest.json +3 -0
  54. package/.next/server/app/api/acp/commands/route/build-manifest.json +9 -0
  55. package/.next/server/app/api/acp/commands/route/server-reference-manifest.json +4 -0
  56. package/.next/server/app/api/acp/commands/route.js +6 -0
  57. package/.next/server/app/api/acp/commands/route.js.nft.json +1 -0
  58. package/.next/server/app/api/acp/commands/route_client-reference-manifest.js +3 -0
  59. package/.next/server/app/api/acp/runtime/route/app-paths-manifest.json +3 -0
  60. package/.next/server/app/api/acp/runtime/route/build-manifest.json +9 -0
  61. package/.next/server/app/api/acp/runtime/route/server-reference-manifest.json +4 -0
  62. package/.next/server/app/api/acp/runtime/route.js +6 -0
  63. package/.next/server/app/api/acp/runtime/route.js.nft.json +1 -0
  64. package/.next/server/app/api/acp/runtime/route_client-reference-manifest.js +3 -0
  65. package/.next/server/app/api/chat/route/app-paths-manifest.json +3 -0
  66. package/.next/server/app/api/chat/route/build-manifest.json +9 -0
  67. package/.next/server/app/api/chat/route/server-reference-manifest.json +4 -0
  68. package/.next/server/app/api/chat/route.js +9 -0
  69. package/.next/server/app/api/chat/route.js.nft.json +1 -0
  70. package/.next/server/app/api/chat/route_client-reference-manifest.js +3 -0
  71. package/.next/server/app/api/conversations/[threadId]/messages/route/app-paths-manifest.json +3 -0
  72. package/.next/server/app/api/conversations/[threadId]/messages/route/build-manifest.json +9 -0
  73. package/.next/server/app/api/conversations/[threadId]/messages/route/server-reference-manifest.json +4 -0
  74. package/.next/server/app/api/conversations/[threadId]/messages/route.js +8 -0
  75. package/.next/server/app/api/conversations/[threadId]/messages/route.js.nft.json +1 -0
  76. package/.next/server/app/api/conversations/[threadId]/messages/route_client-reference-manifest.js +3 -0
  77. package/.next/server/app/api/conversations/[threadId]/route/app-paths-manifest.json +3 -0
  78. package/.next/server/app/api/conversations/[threadId]/route/build-manifest.json +9 -0
  79. package/.next/server/app/api/conversations/[threadId]/route/server-reference-manifest.json +4 -0
  80. package/.next/server/app/api/conversations/[threadId]/route.js +8 -0
  81. package/.next/server/app/api/conversations/[threadId]/route.js.nft.json +1 -0
  82. package/.next/server/app/api/conversations/[threadId]/route_client-reference-manifest.js +3 -0
  83. package/.next/server/app/api/conversations/route/app-paths-manifest.json +3 -0
  84. package/.next/server/app/api/conversations/route/build-manifest.json +9 -0
  85. package/.next/server/app/api/conversations/route/server-reference-manifest.json +4 -0
  86. package/.next/server/app/api/conversations/route.js +8 -0
  87. package/.next/server/app/api/conversations/route.js.nft.json +1 -0
  88. package/.next/server/app/api/conversations/route_client-reference-manifest.js +3 -0
  89. package/.next/server/app/api/local-files/image/route/app-paths-manifest.json +3 -0
  90. package/.next/server/app/api/local-files/image/route/build-manifest.json +9 -0
  91. package/.next/server/app/api/local-files/image/route/server-reference-manifest.json +4 -0
  92. package/.next/server/app/api/local-files/image/route.js +6 -0
  93. package/.next/server/app/api/local-files/image/route.js.nft.json +1 -0
  94. package/.next/server/app/api/local-files/image/route_client-reference-manifest.js +3 -0
  95. package/.next/server/app/api/local-files/open/route/app-paths-manifest.json +3 -0
  96. package/.next/server/app/api/local-files/open/route/build-manifest.json +9 -0
  97. package/.next/server/app/api/local-files/open/route/server-reference-manifest.json +4 -0
  98. package/.next/server/app/api/local-files/open/route.js +6 -0
  99. package/.next/server/app/api/local-files/open/route.js.nft.json +1 -0
  100. package/.next/server/app/api/local-files/open/route_client-reference-manifest.js +3 -0
  101. package/.next/server/app/api/output-artifacts/workspace/route/app-paths-manifest.json +3 -0
  102. package/.next/server/app/api/output-artifacts/workspace/route/build-manifest.json +9 -0
  103. package/.next/server/app/api/output-artifacts/workspace/route/server-reference-manifest.json +4 -0
  104. package/.next/server/app/api/output-artifacts/workspace/route.js +6 -0
  105. package/.next/server/app/api/output-artifacts/workspace/route.js.nft.json +1 -0
  106. package/.next/server/app/api/output-artifacts/workspace/route_client-reference-manifest.js +3 -0
  107. package/.next/server/app/api/tools/image-generation/files/[id]/route/app-paths-manifest.json +3 -0
  108. package/.next/server/app/api/tools/image-generation/files/[id]/route/build-manifest.json +9 -0
  109. package/.next/server/app/api/tools/image-generation/files/[id]/route/server-reference-manifest.json +4 -0
  110. package/.next/server/app/api/tools/image-generation/files/[id]/route.js +7 -0
  111. package/.next/server/app/api/tools/image-generation/files/[id]/route.js.nft.json +1 -0
  112. package/.next/server/app/api/tools/image-generation/files/[id]/route_client-reference-manifest.js +3 -0
  113. package/.next/server/app/api/tools/image-generation/records/route/app-paths-manifest.json +3 -0
  114. package/.next/server/app/api/tools/image-generation/records/route/build-manifest.json +9 -0
  115. package/.next/server/app/api/tools/image-generation/records/route/server-reference-manifest.json +4 -0
  116. package/.next/server/app/api/tools/image-generation/records/route.js +7 -0
  117. package/.next/server/app/api/tools/image-generation/records/route.js.nft.json +1 -0
  118. package/.next/server/app/api/tools/image-generation/records/route_client-reference-manifest.js +3 -0
  119. package/.next/server/app/api/tools/user-choice/route/app-paths-manifest.json +3 -0
  120. package/.next/server/app/api/tools/user-choice/route/build-manifest.json +9 -0
  121. package/.next/server/app/api/tools/user-choice/route/server-reference-manifest.json +4 -0
  122. package/.next/server/app/api/tools/user-choice/route.js +6 -0
  123. package/.next/server/app/api/tools/user-choice/route.js.nft.json +1 -0
  124. package/.next/server/app/api/tools/user-choice/route_client-reference-manifest.js +3 -0
  125. package/.next/server/app/favicon.ico/route/app-paths-manifest.json +3 -0
  126. package/.next/server/app/favicon.ico/route/build-manifest.json +9 -0
  127. package/.next/server/app/favicon.ico/route.js +7 -0
  128. package/.next/server/app/favicon.ico/route.js.nft.json +1 -0
  129. package/.next/server/app/favicon.ico.body +0 -0
  130. package/.next/server/app/favicon.ico.meta +1 -0
  131. package/.next/server/app/page/app-paths-manifest.json +3 -0
  132. package/.next/server/app/page/build-manifest.json +18 -0
  133. package/.next/server/app/page/next-font-manifest.json +6 -0
  134. package/.next/server/app/page/react-loadable-manifest.json +1 -0
  135. package/.next/server/app/page/server-reference-manifest.json +4 -0
  136. package/.next/server/app/page.js +14 -0
  137. package/.next/server/app/page.js.nft.json +1 -0
  138. package/.next/server/app/page_client-reference-manifest.js +3 -0
  139. package/.next/server/app/session/[provider]/[sessionId]/page/app-paths-manifest.json +3 -0
  140. package/.next/server/app/session/[provider]/[sessionId]/page/build-manifest.json +18 -0
  141. package/.next/server/app/session/[provider]/[sessionId]/page/next-font-manifest.json +6 -0
  142. package/.next/server/app/session/[provider]/[sessionId]/page/react-loadable-manifest.json +1 -0
  143. package/.next/server/app/session/[provider]/[sessionId]/page/server-reference-manifest.json +4 -0
  144. package/.next/server/app/session/[provider]/[sessionId]/page.js +16 -0
  145. package/.next/server/app/session/[provider]/[sessionId]/page.js.nft.json +1 -0
  146. package/.next/server/app/session/[provider]/[sessionId]/page_client-reference-manifest.js +3 -0
  147. package/.next/server/app/thread/[threadId]/page/app-paths-manifest.json +3 -0
  148. package/.next/server/app/thread/[threadId]/page/build-manifest.json +18 -0
  149. package/.next/server/app/thread/[threadId]/page/next-font-manifest.json +6 -0
  150. package/.next/server/app/thread/[threadId]/page/react-loadable-manifest.json +1 -0
  151. package/.next/server/app/thread/[threadId]/page/server-reference-manifest.json +4 -0
  152. package/.next/server/app/thread/[threadId]/page.js +15 -0
  153. package/.next/server/app/thread/[threadId]/page.js.nft.json +1 -0
  154. package/.next/server/app/thread/[threadId]/page_client-reference-manifest.js +3 -0
  155. package/.next/server/app-paths-manifest.json +21 -0
  156. package/.next/server/chunks/0zjb_server_app_api_conversations_[threadId]_messages_route_actions_0poed25.js +3 -0
  157. package/.next/server/chunks/0zjb_server_app_api_tools_image-generation_files_[id]_route_actions_0-tbvpw.js +3 -0
  158. package/.next/server/chunks/0zjb_server_app_api_tools_image-generation_records_route_actions_0vu38s2.js +3 -0
  159. package/.next/server/chunks/[externals]_next_dist_0.m~pv6._.js +3 -0
  160. package/.next/server/chunks/[root-of-the-server]__04xq..~._.js +3 -0
  161. package/.next/server/chunks/[root-of-the-server]__07sxz4_._.js +3 -0
  162. package/.next/server/chunks/[root-of-the-server]__0dwg3fr._.js +178 -0
  163. package/.next/server/chunks/[root-of-the-server]__0eanzwb._.js +3 -0
  164. package/.next/server/chunks/[root-of-the-server]__0gqx~5k._.js +3 -0
  165. package/.next/server/chunks/[root-of-the-server]__0iokgmz._.js +3 -0
  166. package/.next/server/chunks/[root-of-the-server]__0j-lxr4._.js +3 -0
  167. package/.next/server/chunks/[root-of-the-server]__0ly6hop._.js +3 -0
  168. package/.next/server/chunks/[root-of-the-server]__0nil~wi._.js +3 -0
  169. package/.next/server/chunks/[root-of-the-server]__0tmhg7j._.js +3 -0
  170. package/.next/server/chunks/[root-of-the-server]__0txmfnw._.js +4 -0
  171. package/.next/server/chunks/[root-of-the-server]__0wo0b8z._.js +3 -0
  172. package/.next/server/chunks/[root-of-the-server]__0~mtsby._.js +3 -0
  173. package/.next/server/chunks/[root-of-the-server]__10-n4io._.js +3 -0
  174. package/.next/server/chunks/[root-of-the-server]__10g507v._.js +3 -0
  175. package/.next/server/chunks/[turbopack]_runtime.js +903 -0
  176. package/.next/server/chunks/_next-internal_server_app_api_acp_capabilities_route_actions_08lck.p.js +3 -0
  177. package/.next/server/chunks/_next-internal_server_app_api_acp_commands_route_actions_0as.2z6.js +3 -0
  178. package/.next/server/chunks/_next-internal_server_app_api_acp_runtime_route_actions_0o1ybkn.js +3 -0
  179. package/.next/server/chunks/_next-internal_server_app_api_chat_route_actions_0tmcf6..js +3 -0
  180. package/.next/server/chunks/_next-internal_server_app_api_conversations_[threadId]_route_actions_12yq8z_.js +3 -0
  181. package/.next/server/chunks/_next-internal_server_app_api_conversations_route_actions_131xv69.js +3 -0
  182. package/.next/server/chunks/_next-internal_server_app_api_local-files_image_route_actions_0f~10mn.js +3 -0
  183. package/.next/server/chunks/_next-internal_server_app_api_local-files_open_route_actions_026mg-2.js +3 -0
  184. package/.next/server/chunks/_next-internal_server_app_api_output-artifacts_workspace_route_actions_1239-n7.js +3 -0
  185. package/.next/server/chunks/_next-internal_server_app_api_tools_user-choice_route_actions_09xqbn_.js +3 -0
  186. package/.next/server/chunks/_next-internal_server_app_favicon_ico_route_actions_095lj93.js +3 -0
  187. package/.next/server/chunks/instrumentation_ts_0zq9-xz._.js +3 -0
  188. package/.next/server/chunks/lib_conversations_store_ts_0gzcj38._.js +7 -0
  189. package/.next/server/chunks/node_modules_@vercel_oidc_dist_token_0zdeuds.js +3 -0
  190. package/.next/server/chunks/node_modules_next_00hve1e._.js +13 -0
  191. package/.next/server/chunks/ssr/[root-of-the-server]__02qo-zr._.js +19 -0
  192. package/.next/server/chunks/ssr/[root-of-the-server]__0488vn3._.js +3 -0
  193. package/.next/server/chunks/ssr/[root-of-the-server]__08e5v4-._.js +3 -0
  194. package/.next/server/chunks/ssr/[root-of-the-server]__08iwq-u._.js +3 -0
  195. package/.next/server/chunks/ssr/[root-of-the-server]__0a1m1mq._.js +3 -0
  196. package/.next/server/chunks/ssr/[root-of-the-server]__0i9qg2.._.js +33 -0
  197. package/.next/server/chunks/ssr/[root-of-the-server]__0icm-_h._.js +3 -0
  198. package/.next/server/chunks/ssr/[root-of-the-server]__0piffp7._.js +3 -0
  199. package/.next/server/chunks/ssr/[root-of-the-server]__0xn-a8p._.js +3 -0
  200. package/.next/server/chunks/ssr/[root-of-the-server]__0~c929r._.js +33 -0
  201. package/.next/server/chunks/ssr/[turbopack]_runtime.js +903 -0
  202. package/.next/server/chunks/ssr/_0-oaqqe._.js +6 -0
  203. package/.next/server/chunks/ssr/_006q235._.js +3 -0
  204. package/.next/server/chunks/ssr/_03.pm1z._.js +108 -0
  205. package/.next/server/chunks/ssr/_0txwi90._.js +3 -0
  206. package/.next/server/chunks/ssr/_next-internal_server_app__global-error_page_actions_0k77kol.js +3 -0
  207. package/.next/server/chunks/ssr/_next-internal_server_app__not-found_page_actions_0eq97pa.js +3 -0
  208. package/.next/server/chunks/ssr/_next-internal_server_app_page_actions_09-gtaw.js +3 -0
  209. package/.next/server/chunks/ssr/_next-internal_server_app_session_[provider]_[sessionId]_page_actions_0_67qh_.js +3 -0
  210. package/.next/server/chunks/ssr/_next-internal_server_app_thread_[threadId]_page_actions_11mcypo.js +3 -0
  211. package/.next/server/chunks/ssr/lib_conversations_store_ts_0-pd6d3._.js +4 -0
  212. package/.next/server/chunks/ssr/node_modules_09w7yel._.js +33 -0
  213. package/.next/server/chunks/ssr/node_modules_0tev5qq._.js +3 -0
  214. package/.next/server/chunks/ssr/node_modules_@vercel_oidc_dist_token_0yj7kvj.js +3 -0
  215. package/.next/server/chunks/ssr/node_modules_next_dist_09jzzl8._.js +3 -0
  216. package/.next/server/chunks/ssr/node_modules_next_dist_0h9llsw._.js +6 -0
  217. package/.next/server/chunks/ssr/node_modules_next_dist_0t-hj0x._.js +3 -0
  218. package/.next/server/chunks/ssr/node_modules_next_dist_client_components_0inhx6q._.js +3 -0
  219. package/.next/server/chunks/ssr/node_modules_next_dist_client_components_builtin_forbidden_0ghu-f7.js +3 -0
  220. package/.next/server/chunks/ssr/node_modules_next_dist_client_components_builtin_global-error_0lgvd_..js +3 -0
  221. package/.next/server/chunks/ssr/node_modules_next_dist_client_components_builtin_unauthorized_0cjv-23.js +3 -0
  222. package/.next/server/chunks/ssr/node_modules_next_dist_esm_build_templates_app-page_00297nb.js +4 -0
  223. package/.next/server/chunks/ssr/node_modules_next_dist_esm_build_templates_app-page_002l7yi.js +4 -0
  224. package/.next/server/chunks/ssr/node_modules_next_dist_esm_build_templates_app-page_02suzhc.js +4 -0
  225. package/.next/server/chunks/ssr/node_modules_next_dist_esm_build_templates_app-page_04x9gct.js +4 -0
  226. package/.next/server/chunks/ssr/node_modules_next_dist_esm_build_templates_app-page_0nsg22r.js +4 -0
  227. package/.next/server/chunks/tools_image-generation_service_mjs_0k_th7-._.js +3 -0
  228. package/.next/server/edge/chunks/_0e82_ds._.js +3 -0
  229. package/.next/server/edge/chunks/turbopack-node_modules_next_dist_esm_build_templates_edge-wrapper_00ue99t.js +3 -0
  230. package/.next/server/functions-config-manifest.json +11 -0
  231. package/.next/server/instrumentation/middleware-manifest.json +12 -0
  232. package/.next/server/instrumentation.js +4 -0
  233. package/.next/server/instrumentation.js.nft.json +1 -0
  234. package/.next/server/interception-route-rewrite-manifest.js +1 -0
  235. package/.next/server/middleware-build-manifest.js +22 -0
  236. package/.next/server/middleware-manifest.json +6 -0
  237. package/.next/server/next-font-manifest.js +1 -0
  238. package/.next/server/next-font-manifest.json +6 -0
  239. package/.next/server/pages/404.html +1 -0
  240. package/.next/server/pages/500.html +1 -0
  241. package/.next/server/pages-manifest.json +4 -0
  242. package/.next/server/prefetch-hints.json +1 -0
  243. package/.next/server/server-reference-manifest.js +1 -0
  244. package/.next/server/server-reference-manifest.json +5 -0
  245. package/.next/static/chunks/01xlw8hd842-c.js +1 -0
  246. package/.next/static/chunks/03edqrb4zdj~g.js +31 -0
  247. package/.next/static/chunks/03qq5fxc~pg00.js +1 -0
  248. package/.next/static/chunks/03~yq9q893hmn.js +1 -0
  249. package/.next/static/chunks/0l-_vd.~~z2bw.js +2 -0
  250. package/.next/static/chunks/0qid5lwcbx9s0.js +1 -0
  251. package/.next/static/chunks/0t.k8~x~sghva.js +4 -0
  252. package/.next/static/chunks/0tmpufzgpw2-w.js +1 -0
  253. package/.next/static/chunks/0v_ue~msygctw.js +1 -0
  254. package/.next/static/chunks/0y2l0xgouorae.css +1 -0
  255. package/.next/static/chunks/0zftsky7gte_9.js +102 -0
  256. package/.next/static/chunks/13nvdsh0e09d0.js +1 -0
  257. package/.next/static/chunks/1610ha42i.fl~.css +1 -0
  258. package/.next/static/chunks/turbopack-0mxz-ap91rcoe.js +1 -0
  259. package/.next/static/mbk_N5Gs4ZJg3lciRL6ya/_buildManifest.js +11 -0
  260. package/.next/static/mbk_N5Gs4ZJg3lciRL6ya/_clientMiddlewareManifest.js +1 -0
  261. package/.next/static/mbk_N5Gs4ZJg3lciRL6ya/_ssgManifest.js +1 -0
  262. package/.next/static/media/favicon.0x3dzn~oxb6tn.ico +0 -0
  263. package/README.md +113 -0
  264. package/THIRD_PARTY_NOTICES.md +34 -0
  265. package/bin/acp.mjs +224 -0
  266. package/dist/app/globals.css +146 -0
  267. package/dist/components/assistant-ui/acp-command-menu.d.ts +2 -0
  268. package/dist/components/assistant-ui/acp-command-menu.mjs +176 -0
  269. package/dist/components/assistant-ui/acp-elicitation-option-list.d.ts +3 -0
  270. package/dist/components/assistant-ui/acp-elicitation-option-list.mjs +157 -0
  271. package/dist/components/assistant-ui/acp-selectors.d.ts +2 -0
  272. package/dist/components/assistant-ui/acp-selectors.mjs +301 -0
  273. package/dist/components/assistant-ui/acp-tool-content.d.ts +4 -0
  274. package/dist/components/assistant-ui/acp-tool-content.mjs +127 -0
  275. package/dist/components/assistant-ui/addons/host.d.ts +4 -0
  276. package/dist/components/assistant-ui/addons/host.mjs +85 -0
  277. package/dist/components/assistant-ui/addons/image-generation-records-section.d.ts +14 -0
  278. package/dist/components/assistant-ui/addons/image-generation-records-section.mjs +116 -0
  279. package/dist/components/assistant-ui/addons/output-artifacts-section.d.ts +9 -0
  280. package/dist/components/assistant-ui/addons/output-artifacts-section.mjs +24 -0
  281. package/dist/components/assistant-ui/addons/output-artifacts.d.ts +14 -0
  282. package/dist/components/assistant-ui/addons/output-artifacts.mjs +87 -0
  283. package/dist/components/assistant-ui/addons/plan-addon.d.ts +2 -0
  284. package/dist/components/assistant-ui/addons/plan-addon.mjs +39 -0
  285. package/dist/components/assistant-ui/addons/plan-data.d.ts +5 -0
  286. package/dist/components/assistant-ui/addons/plan-data.mjs +97 -0
  287. package/dist/components/assistant-ui/addons/registry.d.ts +2 -0
  288. package/dist/components/assistant-ui/addons/registry.mjs +8 -0
  289. package/dist/components/assistant-ui/addons/types.d.ts +13 -0
  290. package/dist/components/assistant-ui/addons/types.mjs +1 -0
  291. package/dist/components/assistant-ui/attachment.d.ts +7 -0
  292. package/dist/components/assistant-ui/attachment.mjs +88 -0
  293. package/dist/components/assistant-ui/file.d.ts +37 -0
  294. package/dist/components/assistant-ui/file.mjs +107 -0
  295. package/dist/components/assistant-ui/image-generation-settings-dialog.d.ts +4 -0
  296. package/dist/components/assistant-ui/image-generation-settings-dialog.mjs +28 -0
  297. package/dist/components/assistant-ui/image.d.ts +51 -0
  298. package/dist/components/assistant-ui/image.mjs +215 -0
  299. package/dist/components/assistant-ui/markdown-text.d.ts +2 -0
  300. package/dist/components/assistant-ui/markdown-text.mjs +208 -0
  301. package/dist/components/assistant-ui/thread/composer.d.ts +27 -0
  302. package/dist/components/assistant-ui/thread/composer.mjs +15 -0
  303. package/dist/components/assistant-ui/thread/context-chips.d.ts +2 -0
  304. package/dist/components/assistant-ui/thread/context-chips.mjs +123 -0
  305. package/dist/components/assistant-ui/thread/empty-state.d.ts +9 -0
  306. package/dist/components/assistant-ui/thread/empty-state.mjs +24 -0
  307. package/dist/components/assistant-ui/thread/index.d.ts +11 -0
  308. package/dist/components/assistant-ui/thread/index.mjs +43 -0
  309. package/dist/components/assistant-ui/thread/message-list.d.ts +3 -0
  310. package/dist/components/assistant-ui/thread/message-list.mjs +16 -0
  311. package/dist/components/assistant-ui/thread/messages.d.ts +9 -0
  312. package/dist/components/assistant-ui/thread/messages.mjs +71 -0
  313. package/dist/components/assistant-ui/thread/scroll-to-bottom.d.ts +2 -0
  314. package/dist/components/assistant-ui/thread/scroll-to-bottom.mjs +8 -0
  315. package/dist/components/assistant-ui/thread-list.d.ts +2 -0
  316. package/dist/components/assistant-ui/thread-list.mjs +31 -0
  317. package/dist/components/assistant-ui/thread.d.ts +1 -0
  318. package/dist/components/assistant-ui/thread.mjs +2 -0
  319. package/dist/components/assistant-ui/threadlist-sidebar.d.ts +6 -0
  320. package/dist/components/assistant-ui/threadlist-sidebar.mjs +32 -0
  321. package/dist/components/assistant-ui/tool-fallback.d.ts +31 -0
  322. package/dist/components/assistant-ui/tool-fallback.mjs +114 -0
  323. package/dist/components/assistant-ui/tooltip-icon-button.d.ts +7 -0
  324. package/dist/components/assistant-ui/tooltip-icon-button.mjs +23 -0
  325. package/dist/components/icons/github.d.ts +3 -0
  326. package/dist/components/icons/github.mjs +4 -0
  327. package/dist/components/theme-toggle.d.ts +1 -0
  328. package/dist/components/theme-toggle.mjs +26 -0
  329. package/dist/components/tool-ui/option-list.d.ts +34 -0
  330. package/dist/components/tool-ui/option-list.mjs +163 -0
  331. package/dist/components/ui/avatar.d.ts +11 -0
  332. package/dist/components/ui/avatar.mjs +40 -0
  333. package/dist/components/ui/button.d.ts +10 -0
  334. package/dist/components/ui/button.mjs +47 -0
  335. package/dist/components/ui/collapsible.d.ts +5 -0
  336. package/dist/components/ui/collapsible.mjs +27 -0
  337. package/dist/components/ui/dialog.d.ts +17 -0
  338. package/dist/components/ui/dialog.mjs +58 -0
  339. package/dist/components/ui/input.d.ts +3 -0
  340. package/dist/components/ui/input.mjs +18 -0
  341. package/dist/components/ui/label.d.ts +4 -0
  342. package/dist/components/ui/label.mjs +20 -0
  343. package/dist/components/ui/scroll-area.d.ts +5 -0
  344. package/dist/components/ui/scroll-area.mjs +26 -0
  345. package/dist/components/ui/select.d.ts +13 -0
  346. package/dist/components/ui/select.mjs +59 -0
  347. package/dist/components/ui/separator.d.ts +4 -0
  348. package/dist/components/ui/separator.mjs +20 -0
  349. package/dist/components/ui/sheet.d.ts +14 -0
  350. package/dist/components/ui/sheet.mjs +61 -0
  351. package/dist/components/ui/sidebar.d.ts +69 -0
  352. package/dist/components/ui/sidebar.mjs +245 -0
  353. package/dist/components/ui/skeleton.d.ts +2 -0
  354. package/dist/components/ui/skeleton.mjs +18 -0
  355. package/dist/components/ui/switch.d.ts +4 -0
  356. package/dist/components/ui/switch.mjs +20 -0
  357. package/dist/components/ui/tabs.d.ts +7 -0
  358. package/dist/components/ui/tabs.mjs +32 -0
  359. package/dist/components/ui/tooltip.d.ts +7 -0
  360. package/dist/components/ui/tooltip.mjs +32 -0
  361. package/dist/hooks/use-mobile.d.ts +1 -0
  362. package/dist/hooks/use-mobile.mjs +15 -0
  363. package/dist/lib/acp2aisdk/capabilities.d.ts +6 -0
  364. package/dist/lib/acp2aisdk/capabilities.mjs +210 -0
  365. package/dist/lib/acp2aisdk/capability-cache.d.ts +17 -0
  366. package/dist/lib/acp2aisdk/capability-cache.mjs +259 -0
  367. package/dist/lib/acp2aisdk/client-context.d.ts +38 -0
  368. package/dist/lib/acp2aisdk/client-context.mjs +247 -0
  369. package/dist/lib/acp2aisdk/commands.d.ts +11 -0
  370. package/dist/lib/acp2aisdk/commands.mjs +121 -0
  371. package/dist/lib/acp2aisdk/config-options.d.ts +3 -0
  372. package/dist/lib/acp2aisdk/config-options.mjs +86 -0
  373. package/dist/lib/acp2aisdk/context.d.ts +88 -0
  374. package/dist/lib/acp2aisdk/context.mjs +33 -0
  375. package/dist/lib/acp2aisdk/default-capabilities.d.ts +275 -0
  376. package/dist/lib/acp2aisdk/default-capabilities.mjs +421 -0
  377. package/dist/lib/acp2aisdk/elicitation.d.ts +37 -0
  378. package/dist/lib/acp2aisdk/elicitation.mjs +193 -0
  379. package/dist/lib/acp2aisdk/hitl.d.ts +25 -0
  380. package/dist/lib/acp2aisdk/hitl.mjs +134 -0
  381. package/dist/lib/acp2aisdk/index.d.ts +12 -0
  382. package/dist/lib/acp2aisdk/index.mjs +182 -0
  383. package/dist/lib/acp2aisdk/mcp-servers.d.ts +17 -0
  384. package/dist/lib/acp2aisdk/mcp-servers.mjs +153 -0
  385. package/dist/lib/acp2aisdk/model-selection.d.ts +16 -0
  386. package/dist/lib/acp2aisdk/model-selection.mjs +65 -0
  387. package/dist/lib/acp2aisdk/prompt-history.d.ts +9 -0
  388. package/dist/lib/acp2aisdk/prompt-history.mjs +168 -0
  389. package/dist/lib/acp2aisdk/provider-compat.d.ts +85 -0
  390. package/dist/lib/acp2aisdk/provider-compat.mjs +501 -0
  391. package/dist/lib/acp2aisdk/provider-registry.d.ts +15 -0
  392. package/dist/lib/acp2aisdk/provider-registry.mjs +196 -0
  393. package/dist/lib/acp2aisdk/response.d.ts +3 -0
  394. package/dist/lib/acp2aisdk/response.mjs +33 -0
  395. package/dist/lib/acp2aisdk/runtime-options.d.ts +2 -0
  396. package/dist/lib/acp2aisdk/runtime-options.mjs +10 -0
  397. package/dist/lib/acp2aisdk/session-runtime.d.ts +5 -0
  398. package/dist/lib/acp2aisdk/session-runtime.mjs +186 -0
  399. package/dist/lib/acp2aisdk/session-store.d.ts +31 -0
  400. package/dist/lib/acp2aisdk/session-store.mjs +169 -0
  401. package/dist/lib/acp2aisdk/skill-command-cache.d.ts +20 -0
  402. package/dist/lib/acp2aisdk/skill-command-cache.mjs +122 -0
  403. package/dist/lib/acp2aisdk/stream-metadata.d.ts +10 -0
  404. package/dist/lib/acp2aisdk/stream-metadata.mjs +251 -0
  405. package/dist/lib/acp2aisdk/types.d.ts +129 -0
  406. package/dist/lib/acp2aisdk/types.mjs +0 -0
  407. package/dist/lib/acp2aisdk/vendor/acp-ai-provider/index.d.ts +10 -0
  408. package/dist/lib/acp2aisdk/vendor/acp-ai-provider/index.mjs +10 -0
  409. package/dist/lib/acp2aisdk/vendor/acp-ai-provider/package/index.mjs +1945 -0
  410. package/dist/lib/api/client.d.ts +93 -0
  411. package/dist/lib/api/client.mjs +199 -0
  412. package/dist/lib/api/cors.d.ts +2 -0
  413. package/dist/lib/api/cors.mjs +47 -0
  414. package/dist/lib/conversations/client-adapter.d.ts +21 -0
  415. package/dist/lib/conversations/client-adapter.mjs +329 -0
  416. package/dist/lib/conversations/message-repository.d.ts +8 -0
  417. package/dist/lib/conversations/message-repository.mjs +87 -0
  418. package/dist/lib/conversations/store.d.ts +17 -0
  419. package/dist/lib/conversations/store.mjs +678 -0
  420. package/dist/lib/conversations/types.d.ts +92 -0
  421. package/dist/lib/conversations/types.mjs +0 -0
  422. package/dist/lib/local-image-files.d.ts +5 -0
  423. package/dist/lib/local-image-files.mjs +76 -0
  424. package/dist/lib/local-image-paths.d.ts +7 -0
  425. package/dist/lib/local-image-paths.mjs +106 -0
  426. package/dist/lib/output-artifacts/workspace.d.ts +8 -0
  427. package/dist/lib/output-artifacts/workspace.mjs +174 -0
  428. package/dist/lib/provider-history/codex.d.ts +4 -0
  429. package/dist/lib/provider-history/codex.mjs +272 -0
  430. package/dist/lib/provider-history/index.d.ts +7 -0
  431. package/dist/lib/provider-history/index.mjs +88 -0
  432. package/dist/lib/provider-history/types.d.ts +31 -0
  433. package/dist/lib/provider-history/types.mjs +0 -0
  434. package/dist/lib/server-runtime.d.ts +22 -0
  435. package/dist/lib/server-runtime.mjs +78 -0
  436. package/dist/lib/url-routing.d.ts +18 -0
  437. package/dist/lib/url-routing.mjs +59 -0
  438. package/dist/lib/utils.d.ts +2 -0
  439. package/dist/lib/utils.mjs +5 -0
  440. package/dist/lib/workspace-metadata.d.ts +2 -0
  441. package/dist/lib/workspace-metadata.mjs +20 -0
  442. package/dist/public-api/react.d.ts +14 -0
  443. package/dist/public-api/react.mjs +16 -0
  444. package/dist/public-api/runtime.d.ts +8 -0
  445. package/dist/public-api/runtime.mjs +7 -0
  446. package/dist/public-api/server.d.ts +5 -0
  447. package/dist/public-api/server.mjs +4 -0
  448. package/dist/public-api/styles.css +1 -0
  449. package/dist/public-api/ui.d.ts +13 -0
  450. package/dist/public-api/ui.mjs +13 -0
  451. package/dist/tools/client-registry.d.ts +9 -0
  452. package/dist/tools/client-registry.mjs +70 -0
  453. package/dist/tools/image-generation/client.d.ts +18 -0
  454. package/dist/tools/image-generation/client.mjs +31 -0
  455. package/dist/tools/image-generation/config.d.ts +9 -0
  456. package/dist/tools/image-generation/config.example.json +14 -0
  457. package/dist/tools/image-generation/config.mjs +11 -0
  458. package/dist/tools/image-generation/mcp-server.mjs +87 -0
  459. package/dist/tools/image-generation/registry.d.ts +13 -0
  460. package/dist/tools/image-generation/registry.mjs +30 -0
  461. package/dist/tools/image-generation/server.d.ts +6 -0
  462. package/dist/tools/image-generation/server.mjs +58 -0
  463. package/dist/tools/image-generation/service.mjs +978 -0
  464. package/dist/tools/image-generation/shared.d.ts +103 -0
  465. package/dist/tools/image-generation/shared.mjs +80 -0
  466. package/dist/tools/image-generation/storage.d.ts +22 -0
  467. package/dist/tools/image-generation/storage.mjs +8 -0
  468. package/dist/tools/image-generation/ui-detail.d.ts +26 -0
  469. package/dist/tools/image-generation/ui-detail.mjs +109 -0
  470. package/dist/tools/image-generation/ui.d.ts +8 -0
  471. package/dist/tools/image-generation/ui.mjs +121 -0
  472. package/dist/tools/registry.d.ts +32 -0
  473. package/dist/tools/registry.mjs +142 -0
  474. package/dist/tools/ui-registry.d.ts +3 -0
  475. package/dist/tools/ui-registry.mjs +20 -0
  476. package/dist/tools/user-choice/client.d.ts +10 -0
  477. package/dist/tools/user-choice/client.mjs +18 -0
  478. package/dist/tools/user-choice/registry.d.ts +12 -0
  479. package/dist/tools/user-choice/registry.mjs +21 -0
  480. package/dist/tools/user-choice/server.d.ts +6 -0
  481. package/dist/tools/user-choice/server.mjs +42 -0
  482. package/dist/tools/user-choice/shared.d.ts +79 -0
  483. package/dist/tools/user-choice/shared.mjs +56 -0
  484. package/dist/tools/user-choice/store.d.ts +19 -0
  485. package/dist/tools/user-choice/store.mjs +95 -0
  486. package/dist/tools/user-choice/ui.d.ts +3 -0
  487. package/dist/tools/user-choice/ui.mjs +396 -0
  488. package/package.json +118 -0
@@ -0,0 +1,978 @@
1
+ import crypto from "node:crypto";
2
+ import fsSync from "node:fs";
3
+ import fs from "node:fs/promises";
4
+ import path from "node:path";
5
+ import { fileURLToPath } from "node:url";
6
+
7
+ export const IMAGE_GENERATION_MCP_NAME = "acp-ui-image-generation";
8
+ export const IMAGE_GENERATION_TOOL_NAME = "generate_image";
9
+ export const IMAGE_GENERATION_TOOL_ID = "image-generation";
10
+
11
+ const TOOL_DIR = path.dirname(fileURLToPath(import.meta.url));
12
+ const INDEX_FILE = "index.json";
13
+ const CONVERSATION_STORE_PATH = path.join(
14
+ ".axhub",
15
+ "sessions",
16
+ "conversations.json",
17
+ );
18
+ const DEFAULT_CONFIG = {
19
+ provider: "openai",
20
+ baseUrl: "https://api.openai.com/v1",
21
+ apiKey: "",
22
+ model: "",
23
+ outputDir: ".axhub/sessions/image-generation",
24
+ maxInputBytes: 10 * 1024 * 1024,
25
+ maxOutputBytes: 50 * 1024 * 1024,
26
+ downloadTimeoutMs: 30_000,
27
+ requestTimeoutMs: 180_000,
28
+ allowSavePath: true,
29
+ savePathBaseDir: ".",
30
+ savePathPattern: "",
31
+ preservePrompt: true,
32
+ };
33
+ const PROMPT_REWRITE_GUARD_PREFIX =
34
+ "Use the following text as the complete prompt. Do not rewrite it:";
35
+ const SUPPORTED_MIME_TYPES = new Set(["image/png", "image/jpeg", "image/webp"]);
36
+
37
+ function isRecord(value) {
38
+ return Boolean(value) && typeof value === "object" && !Array.isArray(value);
39
+ }
40
+
41
+ function createId() {
42
+ return crypto.randomBytes(16).toString("hex");
43
+ }
44
+
45
+ function nowIso() {
46
+ return new Date().toISOString();
47
+ }
48
+
49
+ function normalizeWorkspacePath(workspacePath) {
50
+ const fallback = path.resolve(/* turbopackIgnore: true */ process.cwd());
51
+ const raw =
52
+ typeof workspacePath === "string" && workspacePath.trim()
53
+ ? workspacePath.trim()
54
+ : fallback;
55
+ const resolved = path.resolve(/* turbopackIgnore: true */ raw);
56
+ try {
57
+ return fsSync.statSync(/* turbopackIgnore: true */ resolved).isDirectory()
58
+ ? resolved
59
+ : fallback;
60
+ } catch {
61
+ return fallback;
62
+ }
63
+ }
64
+
65
+ function readJsonFile(filePath) {
66
+ if (!fsSync.existsSync(/* turbopackIgnore: true */ filePath)) return null;
67
+ return JSON.parse(
68
+ fsSync.readFileSync(/* turbopackIgnore: true */ filePath, "utf8"),
69
+ );
70
+ }
71
+
72
+ function stringValue(value, fallback) {
73
+ return typeof value === "string" && value.trim() ? value.trim() : fallback;
74
+ }
75
+
76
+ function booleanValue(value, fallback) {
77
+ return typeof value === "boolean" ? value : fallback;
78
+ }
79
+
80
+ function numberValue(value, fallback) {
81
+ return typeof value === "number" && Number.isFinite(value) && value > 0
82
+ ? value
83
+ : fallback;
84
+ }
85
+
86
+ function mergeConfig(base, raw) {
87
+ if (!isRecord(raw)) return base;
88
+ return {
89
+ ...base,
90
+ provider: stringValue(raw.provider, base.provider),
91
+ baseUrl: stringValue(raw.baseUrl, base.baseUrl).replace(/\/+$/, ""),
92
+ apiKey: stringValue(raw.apiKey, base.apiKey),
93
+ model: stringValue(raw.model, base.model),
94
+ outputDir: stringValue(raw.outputDir, base.outputDir),
95
+ maxInputBytes: numberValue(raw.maxInputBytes, base.maxInputBytes),
96
+ maxOutputBytes: numberValue(raw.maxOutputBytes, base.maxOutputBytes),
97
+ downloadTimeoutMs: numberValue(
98
+ raw.downloadTimeoutMs,
99
+ base.downloadTimeoutMs,
100
+ ),
101
+ requestTimeoutMs: numberValue(raw.requestTimeoutMs, base.requestTimeoutMs),
102
+ allowSavePath: booleanValue(raw.allowSavePath, base.allowSavePath),
103
+ savePathBaseDir: stringValue(raw.savePathBaseDir, base.savePathBaseDir),
104
+ savePathPattern: stringValue(raw.savePathPattern, base.savePathPattern),
105
+ preservePrompt: booleanValue(raw.preservePrompt, base.preservePrompt),
106
+ };
107
+ }
108
+
109
+ function normalizeRuntimeSettings(value) {
110
+ if (!isRecord(value)) return null;
111
+ return {
112
+ ...(typeof value.baseUrl === "string" && value.baseUrl.trim()
113
+ ? { baseUrl: value.baseUrl.trim().replace(/\/+$/, "") }
114
+ : {}),
115
+ ...(typeof value.apiKey === "string" && value.apiKey.trim()
116
+ ? { apiKey: value.apiKey.trim() }
117
+ : {}),
118
+ ...(typeof value.model === "string" && value.model.trim()
119
+ ? { model: value.model.trim() }
120
+ : {}),
121
+ ...(typeof value.savePathPattern === "string" &&
122
+ value.savePathPattern.trim()
123
+ ? { savePathPattern: value.savePathPattern.trim() }
124
+ : {}),
125
+ ...(typeof value.preservePrompt === "boolean"
126
+ ? { preservePrompt: value.preservePrompt }
127
+ : {}),
128
+ };
129
+ }
130
+
131
+ function getConversationStorePath(workspacePath) {
132
+ const overridePath = process.env.ACP_UI_CONVERSATION_STORE;
133
+ if (overridePath)
134
+ return path.resolve(/* turbopackIgnore: true */ overridePath);
135
+ return path.join(
136
+ /* turbopackIgnore: true */ normalizeWorkspacePath(workspacePath),
137
+ CONVERSATION_STORE_PATH,
138
+ );
139
+ }
140
+
141
+ function readThreadRuntimeSettings({ workspacePath, threadId }) {
142
+ const normalizedThreadId =
143
+ typeof threadId === "string" && threadId.trim() ? threadId.trim() : null;
144
+ if (!normalizedThreadId) return null;
145
+ try {
146
+ const store = readJsonFile(getConversationStorePath(workspacePath));
147
+ const conversations = Array.isArray(store?.conversations)
148
+ ? store.conversations
149
+ : [];
150
+ const conversation = conversations.find(
151
+ (entry) =>
152
+ isRecord(entry) &&
153
+ entry.threadId === normalizedThreadId &&
154
+ entry.status !== "deleted",
155
+ );
156
+ const builtinToolSettings = conversation?.builtinToolSettings;
157
+ return normalizeRuntimeSettings(
158
+ builtinToolSettings?.[IMAGE_GENERATION_TOOL_ID] ??
159
+ builtinToolSettings?.imageGeneration,
160
+ );
161
+ } catch {
162
+ return null;
163
+ }
164
+ }
165
+
166
+ function resolveOutputDir(outputDir, workspacePath) {
167
+ if (path.isAbsolute(outputDir)) return outputDir;
168
+ return path.resolve(
169
+ /* turbopackIgnore: true */ normalizeWorkspacePath(workspacePath),
170
+ outputDir,
171
+ );
172
+ }
173
+
174
+ function resolveSavePathBaseDir(savePathBaseDir, workspacePath) {
175
+ const workspace = normalizeWorkspacePath(workspacePath);
176
+ if (path.isAbsolute(savePathBaseDir)) return savePathBaseDir;
177
+ return path.resolve(/* turbopackIgnore: true */ workspace, savePathBaseDir);
178
+ }
179
+
180
+ export function getImageGenerationToolDir() {
181
+ return TOOL_DIR;
182
+ }
183
+
184
+ export function loadImageGenerationConfig(options = {}) {
185
+ const exampleConfig = readJsonFile(
186
+ path.join(TOOL_DIR, "config.example.json"),
187
+ );
188
+ const localConfig = readJsonFile(path.join(TOOL_DIR, "config.local.json"));
189
+ const threadRuntimeSettings = readThreadRuntimeSettings({
190
+ workspacePath: options.workspacePath,
191
+ threadId: options.threadId,
192
+ });
193
+ const runtimeSettings = normalizeRuntimeSettings(options.runtimeSettings);
194
+ const merged = mergeConfig(
195
+ mergeConfig(
196
+ mergeConfig(mergeConfig(DEFAULT_CONFIG, exampleConfig), localConfig),
197
+ threadRuntimeSettings,
198
+ ),
199
+ runtimeSettings,
200
+ );
201
+ return {
202
+ ...merged,
203
+ outputDir: resolveOutputDir(merged.outputDir, options.workspacePath),
204
+ savePathBaseDir: resolveSavePathBaseDir(
205
+ merged.savePathBaseDir,
206
+ options.workspacePath,
207
+ ),
208
+ };
209
+ }
210
+
211
+ function mimeToExtension(mimeType) {
212
+ if (mimeType === "image/jpeg") return "jpg";
213
+ if (mimeType === "image/webp") return "webp";
214
+ return "png";
215
+ }
216
+
217
+ function normalizeSavePathPattern(value) {
218
+ if (typeof value !== "string") return null;
219
+ const pattern = value.trim().replace(/\\/g, "/");
220
+ if (!pattern || pattern.startsWith("/") || pattern.includes("\0"))
221
+ return null;
222
+ if (pattern.split("/").some((segment) => segment === "..")) return null;
223
+ if (!pattern.includes("<index>") && !pattern.includes("{index}")) return null;
224
+ if (!path.basename(pattern)) return null;
225
+ return pattern;
226
+ }
227
+
228
+ function savePathFromPattern({ pattern, index, mimeType, params }) {
229
+ const normalizedPattern = normalizeSavePathPattern(pattern);
230
+ if (!normalizedPattern) return null;
231
+ const extension = mimeToExtension(
232
+ mimeType || mimeFromOutputFormat(params?.outputFormat),
233
+ );
234
+ return normalizedPattern
235
+ .replace(/<index>/g, String(index))
236
+ .replace(/\{index\}/g, String(index))
237
+ .replace(/<ext>/g, extension)
238
+ .replace(/\{ext\}/g, extension);
239
+ }
240
+
241
+ function availableSavePathFromPattern({
242
+ pattern,
243
+ mimeType,
244
+ params,
245
+ config,
246
+ workspacePath,
247
+ }) {
248
+ for (let index = 1; index <= 999; index += 1) {
249
+ const savePath = savePathFromPattern({ pattern, index, mimeType, params });
250
+ if (!savePath) return null;
251
+ const resolved = resolveValidatedSavePath({
252
+ savePath,
253
+ config,
254
+ workspacePath,
255
+ });
256
+ if (
257
+ resolved &&
258
+ !fsSync.existsSync(/* turbopackIgnore: true */ resolved.absolutePath)
259
+ )
260
+ return savePath;
261
+ }
262
+ throw new Error("No available image savePathPattern slot.");
263
+ }
264
+
265
+ function sniffMime(buffer, fallback) {
266
+ if (
267
+ buffer.length >= 8 &&
268
+ buffer[0] === 0x89 &&
269
+ buffer[1] === 0x50 &&
270
+ buffer[2] === 0x4e &&
271
+ buffer[3] === 0x47
272
+ ) {
273
+ return "image/png";
274
+ }
275
+ if (buffer.length >= 3 && buffer[0] === 0xff && buffer[1] === 0xd8) {
276
+ return "image/jpeg";
277
+ }
278
+ if (
279
+ buffer.length >= 12 &&
280
+ buffer.subarray(0, 4).toString("ascii") === "RIFF" &&
281
+ buffer.subarray(8, 12).toString("ascii") === "WEBP"
282
+ ) {
283
+ return "image/webp";
284
+ }
285
+ return fallback ?? "application/octet-stream";
286
+ }
287
+
288
+ function assertSupportedImage(buffer, mimeType, maxBytes) {
289
+ if (buffer.byteLength > maxBytes) {
290
+ throw new Error(
291
+ `Input image is too large (${buffer.byteLength} bytes, max ${maxBytes}).`,
292
+ );
293
+ }
294
+ if (!SUPPORTED_MIME_TYPES.has(mimeType)) {
295
+ throw new Error(`Unsupported input image MIME type: ${mimeType}.`);
296
+ }
297
+ }
298
+
299
+ function isPathInside(parent, candidate) {
300
+ const relative = path.relative(parent, candidate);
301
+ return (
302
+ Boolean(relative) &&
303
+ !relative.startsWith("..") &&
304
+ !path.isAbsolute(relative)
305
+ );
306
+ }
307
+
308
+ function isPathInsideOrEqual(parent, candidate) {
309
+ const relative = path.relative(parent, candidate);
310
+ return (
311
+ relative === "" ||
312
+ (!relative.startsWith("..") && !path.isAbsolute(relative))
313
+ );
314
+ }
315
+
316
+ function normalizeSavePath(savePath) {
317
+ if (typeof savePath !== "string") return null;
318
+ const normalized = savePath.trim().replace(/\\/g, "/");
319
+ return normalized || null;
320
+ }
321
+
322
+ function resolveValidatedSavePath({ savePath, config, workspacePath }) {
323
+ const normalized = normalizeSavePath(savePath);
324
+ if (!normalized) return null;
325
+ if (!config.allowSavePath) {
326
+ throw new Error("Custom image savePath is disabled in config.");
327
+ }
328
+ if (path.isAbsolute(normalized)) {
329
+ throw new Error("Image savePath must be relative to the workspace.");
330
+ }
331
+ if (normalized.split("/").some((part) => part === "..")) {
332
+ throw new Error("Image savePath cannot contain '..' path segments.");
333
+ }
334
+ if (normalized.endsWith("/")) {
335
+ throw new Error("Image savePath must include a file name.");
336
+ }
337
+
338
+ const workspace = normalizeWorkspacePath(workspacePath);
339
+ const baseDir = path.resolve(config.savePathBaseDir);
340
+ const absolutePath = path.resolve(baseDir, normalized);
341
+ if (!isPathInsideOrEqual(workspace, baseDir)) {
342
+ throw new Error(
343
+ "Configured image savePathBaseDir is outside the workspace.",
344
+ );
345
+ }
346
+ if (!isPathInsideOrEqual(workspace, absolutePath)) {
347
+ throw new Error("Image savePath must resolve inside the workspace.");
348
+ }
349
+ if (!isPathInsideOrEqual(baseDir, absolutePath)) {
350
+ throw new Error("Image savePath must resolve inside savePathBaseDir.");
351
+ }
352
+
353
+ return {
354
+ relativePath: path.relative(workspace, absolutePath).replace(/\\/g, "/"),
355
+ absolutePath,
356
+ };
357
+ }
358
+
359
+ function fileNameFromSavePath(savePath, fallback) {
360
+ if (!savePath) return fallback;
361
+ const baseName = path.basename(savePath);
362
+ return baseName && baseName !== "." ? baseName : fallback;
363
+ }
364
+
365
+ function parseDataUrl(value) {
366
+ const match = /^data:([^;,]+);base64,([\s\S]+)$/.exec(value);
367
+ if (!match) throw new Error("Invalid data URL image input.");
368
+ return {
369
+ mimeType: match[1].toLowerCase(),
370
+ buffer: Buffer.from(match[2], "base64"),
371
+ };
372
+ }
373
+
374
+ async function loadPathImage(source, config, workspacePath) {
375
+ const imagePath = path.resolve(
376
+ /* turbopackIgnore: true */ workspacePath,
377
+ source.value,
378
+ );
379
+ const outputPath = path.resolve(/* turbopackIgnore: true */ config.outputDir);
380
+ if (
381
+ !isPathInside(workspacePath, imagePath) &&
382
+ !isPathInside(outputPath, imagePath)
383
+ ) {
384
+ throw new Error(
385
+ `Input image path is outside the workspace and image-generation output directory: ${source.value}`,
386
+ );
387
+ }
388
+ const buffer = await fs.readFile(imagePath);
389
+ const mimeType = sniffMime(buffer, source.mimeType);
390
+ assertSupportedImage(buffer, mimeType, config.maxInputBytes);
391
+ return {
392
+ buffer,
393
+ mimeType,
394
+ filename:
395
+ source.filename ||
396
+ path.basename(imagePath) ||
397
+ `input.${mimeToExtension(mimeType)}`,
398
+ };
399
+ }
400
+
401
+ async function loadUrlImage(source, config) {
402
+ const url = new URL(source.value);
403
+ if (url.protocol !== "http:" && url.protocol !== "https:") {
404
+ throw new Error("Only http(s) image URLs are supported.");
405
+ }
406
+ const response = await fetch(url, {
407
+ signal: AbortSignal.timeout(config.downloadTimeoutMs),
408
+ });
409
+ if (!response.ok) {
410
+ throw new Error(`Failed to download image URL: ${response.status}.`);
411
+ }
412
+ const buffer = Buffer.from(await response.arrayBuffer());
413
+ const mimeType = sniffMime(
414
+ buffer,
415
+ response.headers.get("content-type")?.split(";")[0] ?? source.mimeType,
416
+ );
417
+ assertSupportedImage(buffer, mimeType, config.maxInputBytes);
418
+ return {
419
+ buffer,
420
+ mimeType,
421
+ filename:
422
+ source.filename ||
423
+ path.basename(url.pathname) ||
424
+ `input.${mimeToExtension(mimeType)}`,
425
+ };
426
+ }
427
+
428
+ async function loadInlineImage(source, config) {
429
+ const parsed =
430
+ source.type === "data_url"
431
+ ? parseDataUrl(source.value)
432
+ : {
433
+ mimeType: source.mimeType ?? "application/octet-stream",
434
+ buffer: Buffer.from(source.value, "base64"),
435
+ };
436
+ const mimeType = sniffMime(parsed.buffer, parsed.mimeType);
437
+ assertSupportedImage(parsed.buffer, mimeType, config.maxInputBytes);
438
+ return {
439
+ buffer: parsed.buffer,
440
+ mimeType,
441
+ filename: source.filename || `input.${mimeToExtension(mimeType)}`,
442
+ };
443
+ }
444
+
445
+ function normalizeParams(input, config) {
446
+ return {
447
+ model: input.model || config.model,
448
+ ...(typeof input.size === "string" && input.size.trim()
449
+ ? { size: input.size.trim() }
450
+ : {}),
451
+ ...(typeof input.quality === "string" && input.quality.trim()
452
+ ? { quality: input.quality.trim() }
453
+ : {}),
454
+ ...(typeof input.outputFormat === "string" && input.outputFormat.trim()
455
+ ? { outputFormat: input.outputFormat.trim() }
456
+ : {}),
457
+ ...(typeof input.background === "string" && input.background.trim()
458
+ ? { background: input.background.trim() }
459
+ : {}),
460
+ };
461
+ }
462
+
463
+ function appendFormParams(formData, params, prompt) {
464
+ formData.set("model", params.model);
465
+ formData.set("prompt", prompt);
466
+ formData.set("n", "1");
467
+ if (params.size) formData.set("size", params.size);
468
+ if (params.quality) formData.set("quality", params.quality);
469
+ if (params.outputFormat) formData.set("output_format", params.outputFormat);
470
+ if (params.background) formData.set("background", params.background);
471
+ }
472
+
473
+ function buildImageApiPrompt(prompt, config) {
474
+ const normalizedPrompt = String(prompt ?? "");
475
+ if (!config.preservePrompt) return normalizedPrompt;
476
+ if (normalizedPrompt.startsWith(PROMPT_REWRITE_GUARD_PREFIX)) {
477
+ return normalizedPrompt;
478
+ }
479
+ return `${PROMPT_REWRITE_GUARD_PREFIX}\n${normalizedPrompt}`;
480
+ }
481
+
482
+ function mimeFromOutputFormat(outputFormat) {
483
+ if (outputFormat === "jpeg") return "image/jpeg";
484
+ if (outputFormat === "webp") return "image/webp";
485
+ return "image/png";
486
+ }
487
+
488
+ function summarizeRawResponse(value) {
489
+ if (!isRecord(value)) return undefined;
490
+ const data = Array.isArray(value.data)
491
+ ? value.data.map((item) => {
492
+ if (!isRecord(item)) return item;
493
+ return {
494
+ ...item,
495
+ b64_json:
496
+ typeof item.b64_json === "string" ? "[base64]" : item.b64_json,
497
+ };
498
+ })
499
+ : undefined;
500
+ return {
501
+ ...(typeof value.id === "string" ? { id: value.id } : {}),
502
+ ...(typeof value.created === "number" ? { created: value.created } : {}),
503
+ ...(data ? { data } : {}),
504
+ };
505
+ }
506
+
507
+ async function fetchImageUrl(url, config) {
508
+ const response = await fetch(url, {
509
+ signal: AbortSignal.timeout(config.downloadTimeoutMs),
510
+ });
511
+ if (!response.ok) throw new Error("Failed to fetch generated image URL.");
512
+ const buffer = Buffer.from(await response.arrayBuffer());
513
+ const mimeType = sniffMime(
514
+ buffer,
515
+ response.headers.get("content-type")?.split(";")[0] ?? undefined,
516
+ );
517
+ return { buffer, mimeType };
518
+ }
519
+
520
+ async function requestImageApi({ config, input, params, inputImages }) {
521
+ const endpoint =
522
+ inputImages.length > 0
523
+ ? `${config.baseUrl}/images/edits`
524
+ : `${config.baseUrl}/images/generations`;
525
+ const headers = new Headers({
526
+ Authorization: `Bearer ${config.apiKey}`,
527
+ });
528
+ const prompt = buildImageApiPrompt(input.prompt, config);
529
+ let body;
530
+
531
+ if (inputImages.length > 0) {
532
+ const formData = new FormData();
533
+ appendFormParams(formData, params, prompt);
534
+ for (const image of inputImages) {
535
+ formData.append(
536
+ "image[]",
537
+ new Blob([new Uint8Array(image.buffer)], { type: image.mimeType }),
538
+ image.filename,
539
+ );
540
+ }
541
+ body = formData;
542
+ } else {
543
+ headers.set("content-type", "application/json");
544
+ body = JSON.stringify({
545
+ model: params.model,
546
+ prompt,
547
+ n: 1,
548
+ ...(params.size ? { size: params.size } : {}),
549
+ ...(params.quality ? { quality: params.quality } : {}),
550
+ ...(params.outputFormat ? { output_format: params.outputFormat } : {}),
551
+ ...(params.background ? { background: params.background } : {}),
552
+ });
553
+ }
554
+
555
+ const response = await fetch(endpoint, {
556
+ method: "POST",
557
+ headers,
558
+ body,
559
+ signal: AbortSignal.timeout(config.requestTimeoutMs),
560
+ });
561
+ const responseText = await response.text();
562
+ let payload = null;
563
+ try {
564
+ payload = responseText ? JSON.parse(responseText) : null;
565
+ } catch {
566
+ payload = responseText;
567
+ }
568
+ if (!response.ok) {
569
+ const message =
570
+ isRecord(payload) && isRecord(payload.error)
571
+ ? JSON.stringify(payload.error)
572
+ : responseText || `${response.status} ${response.statusText}`;
573
+ throw new Error(`Image API request failed: ${message}`);
574
+ }
575
+ return payload;
576
+ }
577
+
578
+ async function readIndex(outputDir) {
579
+ try {
580
+ const raw = await fs.readFile(
581
+ /* turbopackIgnore: true */ path.join(outputDir, INDEX_FILE),
582
+ "utf8",
583
+ );
584
+ const parsed = JSON.parse(raw);
585
+ return {
586
+ images: isRecord(parsed?.images) ? parsed.images : {},
587
+ records: Array.isArray(parsed?.records) ? parsed.records : [],
588
+ };
589
+ } catch (error) {
590
+ if (error.code === "ENOENT") return { images: {}, records: [] };
591
+ throw error;
592
+ }
593
+ }
594
+
595
+ async function writeIndex(outputDir, index) {
596
+ await fs.mkdir(/* turbopackIgnore: true */ outputDir, { recursive: true });
597
+ const tempPath = path.join(outputDir, `${INDEX_FILE}.tmp`);
598
+ await fs.writeFile(
599
+ /* turbopackIgnore: true */ tempPath,
600
+ JSON.stringify(index, null, 2),
601
+ "utf8",
602
+ );
603
+ await fs.rename(
604
+ /* turbopackIgnore: true */ tempPath,
605
+ /* turbopackIgnore: true */ path.join(outputDir, INDEX_FILE),
606
+ );
607
+ }
608
+
609
+ function storedImageUrl(id, workspacePath) {
610
+ const params = new URLSearchParams();
611
+ if (workspacePath) params.set("workspacePath", workspacePath);
612
+ const query = params.toString();
613
+ return `/api/tools/image-generation/files/${id}${query ? `?${query}` : ""}`;
614
+ }
615
+
616
+ function localImageUrl(filePath) {
617
+ const params = new URLSearchParams({ path: filePath });
618
+ return `/api/local-files/image?${params.toString()}`;
619
+ }
620
+
621
+ function hydrateImage(image, workspacePath) {
622
+ if (!isRecord(image) || typeof image.id !== "string") return null;
623
+ if (
624
+ typeof image.savedPath === "string" &&
625
+ typeof image.absolutePath === "string"
626
+ ) {
627
+ return {
628
+ ...image,
629
+ url: localImageUrl(image.absolutePath),
630
+ };
631
+ }
632
+ return {
633
+ ...image,
634
+ url: storedImageUrl(image.id, workspacePath),
635
+ };
636
+ }
637
+
638
+ function hydrateRecord(record, fallbackWorkspacePath) {
639
+ if (!isRecord(record) || typeof record.id !== "string") return null;
640
+ const workspacePath =
641
+ typeof record.workspacePath === "string" && record.workspacePath.trim()
642
+ ? record.workspacePath
643
+ : fallbackWorkspacePath;
644
+ return {
645
+ ...record,
646
+ threadId: typeof record.threadId === "string" ? record.threadId : null,
647
+ workspacePath,
648
+ images: Array.isArray(record.images)
649
+ ? record.images
650
+ .map((image) => hydrateImage(image, workspacePath))
651
+ .filter(Boolean)
652
+ : [],
653
+ };
654
+ }
655
+
656
+ export async function saveGeneratedImage({
657
+ config,
658
+ data,
659
+ mimeType,
660
+ revisedPrompt,
661
+ actualParams,
662
+ width,
663
+ height,
664
+ workspacePath,
665
+ savePath,
666
+ }) {
667
+ if (data.byteLength > config.maxOutputBytes) {
668
+ throw new Error(
669
+ `Generated image is too large (${data.byteLength} bytes, max ${config.maxOutputBytes}).`,
670
+ );
671
+ }
672
+ const resolvedSavePath = resolveValidatedSavePath({
673
+ savePath,
674
+ config,
675
+ workspacePath,
676
+ });
677
+ await fs.mkdir(/* turbopackIgnore: true */ config.outputDir, {
678
+ recursive: true,
679
+ });
680
+ const id = createId();
681
+ const fileName = `${id}.${mimeToExtension(mimeType)}`;
682
+ const absolutePath =
683
+ resolvedSavePath?.absolutePath ?? path.join(config.outputDir, fileName);
684
+ if (resolvedSavePath) {
685
+ await fs.mkdir(
686
+ /* turbopackIgnore: true */ path.dirname(resolvedSavePath.absolutePath),
687
+ {
688
+ recursive: true,
689
+ },
690
+ );
691
+ await fs.writeFile(
692
+ /* turbopackIgnore: true */ resolvedSavePath.absolutePath,
693
+ data,
694
+ { flag: "wx" },
695
+ );
696
+ } else {
697
+ await fs.writeFile(/* turbopackIgnore: true */ absolutePath, data);
698
+ }
699
+
700
+ const image = {
701
+ id,
702
+ fileName: fileNameFromSavePath(resolvedSavePath?.relativePath, fileName),
703
+ mimeType,
704
+ sizeBytes: data.byteLength,
705
+ url: resolvedSavePath
706
+ ? localImageUrl(resolvedSavePath.absolutePath)
707
+ : storedImageUrl(id, workspacePath),
708
+ ...(resolvedSavePath ? { savedPath: resolvedSavePath.relativePath } : {}),
709
+ ...(width ? { width } : {}),
710
+ ...(height ? { height } : {}),
711
+ ...(revisedPrompt ? { revisedPrompt } : {}),
712
+ ...(actualParams ? { actualParams } : {}),
713
+ };
714
+ const index = await readIndex(config.outputDir);
715
+ index.images[id] = {
716
+ ...image,
717
+ createdAt: nowIso(),
718
+ absolutePath,
719
+ };
720
+ await writeIndex(config.outputDir, index);
721
+ return image;
722
+ }
723
+
724
+ async function saveImageGenerationRecord(config, record) {
725
+ const index = await readIndex(config.outputDir);
726
+ index.records = [
727
+ record,
728
+ ...index.records.filter((entry) => entry?.id !== record.id),
729
+ ];
730
+ await writeIndex(config.outputDir, index);
731
+ return record;
732
+ }
733
+
734
+ function outputToRecord({ output, id, workspacePath, threadId, source }) {
735
+ const timestamp = nowIso();
736
+ return {
737
+ id,
738
+ requestId: output.requestId,
739
+ threadId: threadId || null,
740
+ workspacePath,
741
+ source,
742
+ status: output.status,
743
+ provider: output.provider,
744
+ prompt: output.prompt,
745
+ ...(output.revisedPrompt ? { revisedPrompt: output.revisedPrompt } : {}),
746
+ requestedParams: output.requestedParams,
747
+ actualParams: output.actualParams,
748
+ images: output.images,
749
+ durationMs: output.durationMs,
750
+ ...(output.error ? { error: output.error } : {}),
751
+ createdAt: timestamp,
752
+ updatedAt: timestamp,
753
+ };
754
+ }
755
+
756
+ function failedOutput({ recordId, config, input, params, startedAt, error }) {
757
+ const message = error instanceof Error ? error.message : String(error);
758
+ return {
759
+ status: "failed",
760
+ recordId,
761
+ requestId: `img_error_${Date.now().toString(36)}`,
762
+ provider: config?.provider ?? "unknown",
763
+ prompt: typeof input?.prompt === "string" ? input.prompt : "",
764
+ requestedParams: params ?? {},
765
+ actualParams: {},
766
+ images: [],
767
+ durationMs: Date.now() - startedAt,
768
+ error: message,
769
+ };
770
+ }
771
+
772
+ function normalizeSource(value) {
773
+ return value === "mcp" ? "mcp" : "api";
774
+ }
775
+
776
+ async function generateImageOrThrow({ input, config, workspacePath }) {
777
+ if (
778
+ !isRecord(input) ||
779
+ typeof input.prompt !== "string" ||
780
+ !input.prompt.trim()
781
+ ) {
782
+ throw new Error("Image generation prompt is required.");
783
+ }
784
+ if (!config.apiKey) {
785
+ throw new Error(
786
+ 'Image generation API key is missing. Pass builtinToolSettings["image-generation"].apiKey or configure tools/image-generation/config.local.json.',
787
+ );
788
+ }
789
+ if (!config.model) {
790
+ throw new Error(
791
+ 'Image generation model is missing. Pass builtinToolSettings["image-generation"].model or configure tools/image-generation/config.local.json.',
792
+ );
793
+ }
794
+
795
+ const params = normalizeParams(input, config);
796
+ const inputImages = await Promise.all(
797
+ (input.images ?? []).map((source) =>
798
+ source.type === "path"
799
+ ? loadPathImage(source, config, workspacePath)
800
+ : source.type === "url"
801
+ ? loadUrlImage(source, config)
802
+ : loadInlineImage(source, config),
803
+ ),
804
+ );
805
+ const payload = await requestImageApi({ config, input, params, inputImages });
806
+ const items =
807
+ isRecord(payload) && Array.isArray(payload.data) ? payload.data : [];
808
+ let image = null;
809
+ for (const item of items) {
810
+ if (!isRecord(item)) continue;
811
+ const revisedPrompt =
812
+ typeof item.revised_prompt === "string" ? item.revised_prompt : undefined;
813
+ let buffer = null;
814
+ let mimeType = mimeFromOutputFormat(params.outputFormat);
815
+ if (typeof item.b64_json === "string") {
816
+ buffer = Buffer.from(item.b64_json, "base64");
817
+ mimeType = sniffMime(buffer, mimeType);
818
+ } else if (typeof item.url === "string") {
819
+ const fetched = await fetchImageUrl(item.url, config);
820
+ buffer = fetched.buffer;
821
+ mimeType = fetched.mimeType;
822
+ }
823
+ if (!buffer) continue;
824
+ const savePath =
825
+ typeof input.savePath === "string" && input.savePath.trim()
826
+ ? input.savePath
827
+ : availableSavePathFromPattern({
828
+ pattern: config.savePathPattern,
829
+ mimeType,
830
+ params,
831
+ config,
832
+ workspacePath,
833
+ });
834
+ image = await saveGeneratedImage({
835
+ config,
836
+ data: buffer,
837
+ mimeType,
838
+ revisedPrompt,
839
+ actualParams: params,
840
+ workspacePath,
841
+ savePath,
842
+ });
843
+ break;
844
+ }
845
+
846
+ if (!image) {
847
+ throw new Error("Image API response did not include any images.");
848
+ }
849
+
850
+ return { image, params, payload };
851
+ }
852
+
853
+ export async function generateImage(input, options = {}) {
854
+ const workspacePath = normalizeWorkspacePath(options.workspacePath);
855
+ const threadId =
856
+ typeof options.threadId === "string" && options.threadId.trim()
857
+ ? options.threadId.trim()
858
+ : null;
859
+ const source = normalizeSource(options.source);
860
+ const recordId = createId();
861
+ const startedAt = Date.now();
862
+ const config = loadImageGenerationConfig({
863
+ workspacePath,
864
+ threadId,
865
+ runtimeSettings: options.runtimeSettings,
866
+ });
867
+ let params = null;
868
+
869
+ try {
870
+ if (isRecord(input)) params = normalizeParams(input, config);
871
+ const result = await generateImageOrThrow({ input, config, workspacePath });
872
+ params = result.params;
873
+ const revisedPrompt = result.image.revisedPrompt;
874
+ const output = {
875
+ status: "completed",
876
+ recordId,
877
+ requestId:
878
+ isRecord(result.payload) && typeof result.payload.id === "string"
879
+ ? result.payload.id
880
+ : `img_${Date.now().toString(36)}`,
881
+ provider: config.provider,
882
+ prompt: input.prompt,
883
+ ...(revisedPrompt ? { revisedPrompt } : {}),
884
+ requestedParams: params,
885
+ actualParams: params,
886
+ images: [result.image],
887
+ durationMs: Date.now() - startedAt,
888
+ rawResponseSummary: summarizeRawResponse(result.payload),
889
+ };
890
+ const record = outputToRecord({
891
+ output,
892
+ id: recordId,
893
+ workspacePath,
894
+ threadId,
895
+ source,
896
+ });
897
+ await saveImageGenerationRecord(config, record);
898
+ return output;
899
+ } catch (error) {
900
+ const output = failedOutput({
901
+ recordId,
902
+ config,
903
+ input,
904
+ params,
905
+ startedAt,
906
+ error,
907
+ });
908
+ const record = outputToRecord({
909
+ output,
910
+ id: recordId,
911
+ workspacePath,
912
+ threadId,
913
+ source,
914
+ });
915
+ await saveImageGenerationRecord(config, record);
916
+ return output;
917
+ }
918
+ }
919
+
920
+ export async function listImageGenerationRecords(options = {}) {
921
+ const workspacePath = normalizeWorkspacePath(options.workspacePath);
922
+ const config = loadImageGenerationConfig({ workspacePath });
923
+ const threadId =
924
+ typeof options.threadId === "string" && options.threadId.trim()
925
+ ? options.threadId.trim()
926
+ : null;
927
+ const limit = Number.isFinite(options.limit)
928
+ ? Math.max(1, Math.floor(options.limit))
929
+ : 20;
930
+ const index = await readIndex(config.outputDir);
931
+ return index.records
932
+ .map((record) => hydrateRecord(record, workspacePath))
933
+ .filter(Boolean)
934
+ .filter((record) => !threadId || record.threadId === threadId)
935
+ .sort((left, right) =>
936
+ String(right.updatedAt ?? right.createdAt ?? "").localeCompare(
937
+ String(left.updatedAt ?? left.createdAt ?? ""),
938
+ ),
939
+ )
940
+ .slice(0, limit);
941
+ }
942
+
943
+ export async function getStoredImage(options, id) {
944
+ const workspacePath = normalizeWorkspacePath(options?.workspacePath);
945
+ if (!/^[a-f0-9]{32}$/.test(id)) return null;
946
+ const config = loadImageGenerationConfig({ workspacePath });
947
+ const index = await readIndex(config.outputDir);
948
+ const image = index.images[id];
949
+ if (!image) return null;
950
+ const absolutePath =
951
+ typeof image.absolutePath === "string"
952
+ ? image.absolutePath
953
+ : path.join(config.outputDir, image.fileName);
954
+ const resolvedOutputDir = path.resolve(config.outputDir);
955
+ const resolvedPath = path.resolve(absolutePath);
956
+ if (typeof image.savedPath === "string") {
957
+ const workspace = normalizeWorkspacePath(workspacePath);
958
+ if (!isPathInsideOrEqual(workspace, resolvedPath)) {
959
+ return null;
960
+ }
961
+ return {
962
+ ...image,
963
+ url: localImageUrl(resolvedPath),
964
+ absolutePath: resolvedPath,
965
+ };
966
+ }
967
+ if (
968
+ resolvedPath !== resolvedOutputDir &&
969
+ !resolvedPath.startsWith(`${resolvedOutputDir}${path.sep}`)
970
+ ) {
971
+ return null;
972
+ }
973
+ return {
974
+ ...image,
975
+ url: storedImageUrl(id, workspacePath),
976
+ absolutePath: resolvedPath,
977
+ };
978
+ }