ai-engineering-init 1.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 (313) hide show
  1. package/.claude/agents/code-reviewer.md +139 -0
  2. package/.claude/agents/project-manager.md +159 -0
  3. package/.claude/audio/completed.wav +0 -0
  4. package/.claude/commands/add-todo.md +255 -0
  5. package/.claude/commands/check.md +210 -0
  6. package/.claude/commands/crud.md +454 -0
  7. package/.claude/commands/dev.md +503 -0
  8. package/.claude/commands/init-docs.md +681 -0
  9. package/.claude/commands/next.md +251 -0
  10. package/.claude/commands/progress.md +242 -0
  11. package/.claude/commands/start.md +199 -0
  12. package/.claude/commands/sync.md +307 -0
  13. package/.claude/commands/update-status.md +428 -0
  14. package/.claude/docs/Mixin/344/275/277/347/224/250/346/214/207/345/215/227.md +299 -0
  15. package/.claude/docs/README.md +167 -0
  16. package/.claude/docs//345/211/215/347/253/257/345/274/200/345/217/221/346/214/207/345/215/227.md +599 -0
  17. package/.claude/docs//345/220/216/347/253/257/345/274/200/345/217/221/346/214/207/345/215/227.md +726 -0
  18. package/.claude/docs//345/267/245/344/275/234/346/265/201/345/274/200/345/217/221/346/214/207/345/215/227.md +714 -0
  19. package/.claude/docs//345/267/245/345/205/267/347/261/273/344/275/277/347/224/250/346/214/207/345/215/227.md +463 -0
  20. package/.claude/docs//346/225/260/346/215/256/345/272/223/350/256/276/350/256/241/350/247/204/350/214/203.md +390 -0
  21. package/.claude/docs//346/226/260/345/212/237/350/203/275/345/274/200/345/217/221/346/265/201/347/250/213/350/247/204/350/214/203.md +688 -0
  22. package/.claude/docs//346/226/260/351/241/271/347/233/256/345/274/200/345/217/221/346/265/201/347/250/213.md +365 -0
  23. package/.claude/docs//346/241/206/346/236/266/350/257/264/346/230/216.md +393 -0
  24. package/.claude/docs//350/267/257/347/224/261/351/205/215/347/275/256/346/214/207/345/215/227.md +246 -0
  25. package/.claude/framework-config.json +73 -0
  26. package/.claude/hooks/pre-tool-use.js +117 -0
  27. package/.claude/hooks/skill-forced-eval.js +167 -0
  28. package/.claude/hooks/stop.js +58 -0
  29. package/.claude/settings.json +41 -0
  30. package/.claude/skills/add-skill/SKILL.md +352 -0
  31. package/.claude/skills/api-development/SKILL.md +560 -0
  32. package/.claude/skills/architecture-design/SKILL.md +756 -0
  33. package/.claude/skills/backend-annotations/SKILL.md +674 -0
  34. package/.claude/skills/banana-image/CHANGELOG.md +37 -0
  35. package/.claude/skills/banana-image/README.md +146 -0
  36. package/.claude/skills/banana-image/SKILL.md +164 -0
  37. package/.claude/skills/banana-image/assets/logo.png +0 -0
  38. package/.claude/skills/banana-image/references/advanced-usage.md +189 -0
  39. package/.claude/skills/banana-image/scripts/apply_template.py +125 -0
  40. package/.claude/skills/banana-image/scripts/banana_image_exec.ts +412 -0
  41. package/.claude/skills/banana-image/scripts/batch_prep.py +82 -0
  42. package/.claude/skills/banana-image/scripts/package-lock.json +1437 -0
  43. package/.claude/skills/banana-image/scripts/package.json +18 -0
  44. package/.claude/skills/banana-image/scripts/requirements.txt +10 -0
  45. package/.claude/skills/banana-image/templates/poster.json +22 -0
  46. package/.claude/skills/banana-image/templates/product.json +17 -0
  47. package/.claude/skills/banana-image/templates/social.json +22 -0
  48. package/.claude/skills/banana-image/templates/thumbnail.json +17 -0
  49. package/.claude/skills/brainstorm/SKILL.md +648 -0
  50. package/.claude/skills/bug-detective/SKILL.md +1206 -0
  51. package/.claude/skills/code-patterns/SKILL.md +590 -0
  52. package/.claude/skills/collaborating-with-codex/SKILL.md +174 -0
  53. package/.claude/skills/collaborating-with-codex/scripts/codex_bridge.py +275 -0
  54. package/.claude/skills/collaborating-with-gemini/SKILL.md +194 -0
  55. package/.claude/skills/collaborating-with-gemini/scripts/gemini_bridge.py +275 -0
  56. package/.claude/skills/crud-development/SKILL.md +649 -0
  57. package/.claude/skills/data-permission/SKILL.md +599 -0
  58. package/.claude/skills/database-ops/SKILL.md +407 -0
  59. package/.claude/skills/error-handler/SKILL.md +371 -0
  60. package/.claude/skills/file-oss-management/SKILL.md +863 -0
  61. package/.claude/skills/git-workflow/SKILL.md +375 -0
  62. package/.claude/skills/json-serialization/SKILL.md +357 -0
  63. package/.claude/skills/leniu-api-development/SKILL.md +803 -0
  64. package/.claude/skills/leniu-architecture-design/SKILL.md +598 -0
  65. package/.claude/skills/leniu-backend-annotations/SKILL.md +664 -0
  66. package/.claude/skills/leniu-code-patterns/SKILL.md +365 -0
  67. package/.claude/skills/leniu-crud-development/SKILL.md +1110 -0
  68. package/.claude/skills/leniu-data-permission/SKILL.md +256 -0
  69. package/.claude/skills/leniu-database-ops/SKILL.md +426 -0
  70. package/.claude/skills/leniu-error-handler/SKILL.md +462 -0
  71. package/.claude/skills/leniu-java-amount-handling/SKILL.md +461 -0
  72. package/.claude/skills/leniu-java-code-style/SKILL.md +510 -0
  73. package/.claude/skills/leniu-java-concurrent/SKILL.md +400 -0
  74. package/.claude/skills/leniu-java-entity/SKILL.md +751 -0
  75. package/.claude/skills/leniu-java-export/SKILL.md +560 -0
  76. package/.claude/skills/leniu-java-logging/SKILL.md +832 -0
  77. package/.claude/skills/leniu-java-mq/SKILL.md +338 -0
  78. package/.claude/skills/leniu-java-mybatis/SKILL.md +640 -0
  79. package/.claude/skills/leniu-java-report-query-param/SKILL.md +291 -0
  80. package/.claude/skills/leniu-java-task/SKILL.md +367 -0
  81. package/.claude/skills/leniu-java-total-line/SKILL.md +195 -0
  82. package/.claude/skills/leniu-marketing-price-rule-customizer/SKILL.md +301 -0
  83. package/.claude/skills/leniu-marketing-recharge-rule-customizer/SKILL.md +285 -0
  84. package/.claude/skills/leniu-mealtime/SKILL.md +215 -0
  85. package/.claude/skills/leniu-redis-cache/SKILL.md +316 -0
  86. package/.claude/skills/leniu-security-guard/SKILL.md +520 -0
  87. package/.claude/skills/leniu-utils-toolkit/SKILL.md +380 -0
  88. package/.claude/skills/openspec-apply-change/SKILL.md +156 -0
  89. package/.claude/skills/openspec-archive-change/SKILL.md +114 -0
  90. package/.claude/skills/openspec-bulk-archive-change/SKILL.md +246 -0
  91. package/.claude/skills/openspec-continue-change/SKILL.md +118 -0
  92. package/.claude/skills/openspec-explore/SKILL.md +290 -0
  93. package/.claude/skills/openspec-ff-change/SKILL.md +101 -0
  94. package/.claude/skills/openspec-new-change/SKILL.md +74 -0
  95. package/.claude/skills/openspec-onboard/SKILL.md +529 -0
  96. package/.claude/skills/openspec-sync-specs/SKILL.md +138 -0
  97. package/.claude/skills/openspec-verify-change/SKILL.md +168 -0
  98. package/.claude/skills/performance-doctor/SKILL.md +627 -0
  99. package/.claude/skills/project-navigator/SKILL.md +305 -0
  100. package/.claude/skills/redis-cache/SKILL.md +839 -0
  101. package/.claude/skills/scheduled-jobs/SKILL.md +633 -0
  102. package/.claude/skills/security-guard/SKILL.md +748 -0
  103. package/.claude/skills/sms-mail/SKILL.md +766 -0
  104. package/.claude/skills/social-login/SKILL.md +668 -0
  105. package/.claude/skills/store-pc/SKILL.md +366 -0
  106. package/.claude/skills/task-tracker/SKILL.md +307 -0
  107. package/.claude/skills/tech-decision/SKILL.md +393 -0
  108. package/.claude/skills/tenant-management/SKILL.md +603 -0
  109. package/.claude/skills/test-development/SKILL.md +755 -0
  110. package/.claude/skills/ui-pc/SKILL.md +438 -0
  111. package/.claude/skills/utils-toolkit/SKILL.md +615 -0
  112. package/.claude/skills/websocket-sse/SKILL.md +716 -0
  113. package/.claude/skills/workflow-engine/SKILL.md +676 -0
  114. package/.claude/templates//345/276/205/345/212/236/346/270/205/345/215/225/346/250/241/346/235/277.md +56 -0
  115. package/.claude/templates//351/234/200/346/261/202/346/226/207/346/241/243/346/250/241/346/235/277.md +85 -0
  116. package/.claude/templates//351/241/271/347/233/256/347/212/266/346/200/201/346/250/241/346/235/277.md +43 -0
  117. package/.codex/skills/add-skill/SKILL.md +352 -0
  118. package/.codex/skills/add-todo/SKILL.md +269 -0
  119. package/.codex/skills/api-development/SKILL.md +693 -0
  120. package/.codex/skills/architecture-design/SKILL.md +628 -0
  121. package/.codex/skills/backend-annotations/SKILL.md +664 -0
  122. package/.codex/skills/banana-image/CHANGELOG.md +37 -0
  123. package/.codex/skills/banana-image/README.md +146 -0
  124. package/.codex/skills/banana-image/SKILL.md +164 -0
  125. package/.codex/skills/banana-image/assets/logo.png +0 -0
  126. package/.codex/skills/banana-image/references/advanced-usage.md +189 -0
  127. package/.codex/skills/banana-image/scripts/apply_template.py +125 -0
  128. package/.codex/skills/banana-image/scripts/banana_image_exec.ts +412 -0
  129. package/.codex/skills/banana-image/scripts/batch_prep.py +82 -0
  130. package/.codex/skills/banana-image/scripts/package-lock.json +1437 -0
  131. package/.codex/skills/banana-image/scripts/package.json +18 -0
  132. package/.codex/skills/banana-image/scripts/requirements.txt +10 -0
  133. package/.codex/skills/banana-image/templates/poster.json +22 -0
  134. package/.codex/skills/banana-image/templates/product.json +17 -0
  135. package/.codex/skills/banana-image/templates/social.json +22 -0
  136. package/.codex/skills/banana-image/templates/thumbnail.json +17 -0
  137. package/.codex/skills/brainstorm/SKILL.md +648 -0
  138. package/.codex/skills/bug-detective/SKILL.md +1206 -0
  139. package/.codex/skills/check/SKILL.md +367 -0
  140. package/.codex/skills/code-patterns/SKILL.md +442 -0
  141. package/.codex/skills/collaborating-with-codex/SKILL.md +174 -0
  142. package/.codex/skills/collaborating-with-codex/scripts/codex_bridge.py +275 -0
  143. package/.codex/skills/collaborating-with-gemini/SKILL.md +194 -0
  144. package/.codex/skills/collaborating-with-gemini/scripts/gemini_bridge.py +275 -0
  145. package/.codex/skills/crud/SKILL.md +265 -0
  146. package/.codex/skills/crud-development/SKILL.md +637 -0
  147. package/.codex/skills/data-permission/SKILL.md +591 -0
  148. package/.codex/skills/database-ops/SKILL.md +553 -0
  149. package/.codex/skills/dev/SKILL.md +187 -0
  150. package/.codex/skills/error-handler/SKILL.md +361 -0
  151. package/.codex/skills/file-oss-management/SKILL.md +863 -0
  152. package/.codex/skills/git-workflow/SKILL.md +375 -0
  153. package/.codex/skills/init-docs/SKILL.md +194 -0
  154. package/.codex/skills/json-serialization/SKILL.md +357 -0
  155. package/.codex/skills/leniu-api-development/SKILL.md +803 -0
  156. package/.codex/skills/leniu-architecture-design/SKILL.md +594 -0
  157. package/.codex/skills/leniu-backend-annotations/SKILL.md +662 -0
  158. package/.codex/skills/leniu-code-patterns/SKILL.md +365 -0
  159. package/.codex/skills/leniu-crud-development/SKILL.md +1110 -0
  160. package/.codex/skills/leniu-data-permission/SKILL.md +256 -0
  161. package/.codex/skills/leniu-database-ops/SKILL.md +426 -0
  162. package/.codex/skills/leniu-error-handler/SKILL.md +462 -0
  163. package/.codex/skills/leniu-java-amount-handling/SKILL.md +461 -0
  164. package/.codex/skills/leniu-java-code-style/SKILL.md +510 -0
  165. package/.codex/skills/leniu-java-concurrent/SKILL.md +400 -0
  166. package/.codex/skills/leniu-java-entity/SKILL.md +751 -0
  167. package/.codex/skills/leniu-java-export/SKILL.md +560 -0
  168. package/.codex/skills/leniu-java-logging/SKILL.md +832 -0
  169. package/.codex/skills/leniu-java-mq/SKILL.md +338 -0
  170. package/.codex/skills/leniu-java-mybatis/SKILL.md +640 -0
  171. package/.codex/skills/leniu-java-report-query-param/SKILL.md +291 -0
  172. package/.codex/skills/leniu-java-task/SKILL.md +367 -0
  173. package/.codex/skills/leniu-java-total-line/SKILL.md +195 -0
  174. package/.codex/skills/leniu-marketing-price-rule-customizer/SKILL.md +301 -0
  175. package/.codex/skills/leniu-marketing-recharge-rule-customizer/SKILL.md +285 -0
  176. package/.codex/skills/leniu-mealtime/SKILL.md +215 -0
  177. package/.codex/skills/leniu-redis-cache/SKILL.md +316 -0
  178. package/.codex/skills/leniu-security-guard/SKILL.md +520 -0
  179. package/.codex/skills/leniu-utils-toolkit/SKILL.md +378 -0
  180. package/.codex/skills/next/SKILL.md +137 -0
  181. package/.codex/skills/openspec-apply-change/SKILL.md +156 -0
  182. package/.codex/skills/openspec-archive-change/SKILL.md +114 -0
  183. package/.codex/skills/openspec-bulk-archive-change/SKILL.md +246 -0
  184. package/.codex/skills/openspec-continue-change/SKILL.md +118 -0
  185. package/.codex/skills/openspec-explore/SKILL.md +290 -0
  186. package/.codex/skills/openspec-ff-change/SKILL.md +101 -0
  187. package/.codex/skills/openspec-new-change/SKILL.md +74 -0
  188. package/.codex/skills/openspec-onboard/SKILL.md +529 -0
  189. package/.codex/skills/openspec-sync-specs/SKILL.md +138 -0
  190. package/.codex/skills/openspec-verify-change/SKILL.md +168 -0
  191. package/.codex/skills/performance-doctor/SKILL.md +627 -0
  192. package/.codex/skills/progress/SKILL.md +193 -0
  193. package/.codex/skills/project-navigator/SKILL.md +286 -0
  194. package/.codex/skills/redis-cache/SKILL.md +829 -0
  195. package/.codex/skills/scheduled-jobs/SKILL.md +633 -0
  196. package/.codex/skills/security-guard/SKILL.md +739 -0
  197. package/.codex/skills/sms-mail/SKILL.md +766 -0
  198. package/.codex/skills/social-login/SKILL.md +668 -0
  199. package/.codex/skills/start/SKILL.md +154 -0
  200. package/.codex/skills/store-pc/SKILL.md +491 -0
  201. package/.codex/skills/sync/SKILL.md +149 -0
  202. package/.codex/skills/task-tracker/SKILL.md +307 -0
  203. package/.codex/skills/tech-decision/SKILL.md +393 -0
  204. package/.codex/skills/tenant-management/SKILL.md +603 -0
  205. package/.codex/skills/test-development/SKILL.md +755 -0
  206. package/.codex/skills/ui-pc/SKILL.md +475 -0
  207. package/.codex/skills/update-status/SKILL.md +159 -0
  208. package/.codex/skills/utils-toolkit/SKILL.md +593 -0
  209. package/.codex/skills/websocket-sse/SKILL.md +716 -0
  210. package/.codex/skills/workflow-engine/SKILL.md +676 -0
  211. package/.cursor/agents/code-reviewer.md +139 -0
  212. package/.cursor/agents/project-manager.md +159 -0
  213. package/.cursor/commands/opsx-apply.md +152 -0
  214. package/.cursor/commands/opsx-archive.md +157 -0
  215. package/.cursor/commands/opsx-bulk-archive.md +242 -0
  216. package/.cursor/commands/opsx-continue.md +114 -0
  217. package/.cursor/commands/opsx-explore.md +174 -0
  218. package/.cursor/commands/opsx-ff.md +94 -0
  219. package/.cursor/commands/opsx-new.md +69 -0
  220. package/.cursor/commands/opsx-onboard.md +525 -0
  221. package/.cursor/commands/opsx-sync.md +134 -0
  222. package/.cursor/commands/opsx-verify.md +164 -0
  223. package/.cursor/mcp.json +22 -0
  224. package/.cursor/skills/add-skill/SKILL.md +352 -0
  225. package/.cursor/skills/api-development/SKILL.md +560 -0
  226. package/.cursor/skills/architecture-design/SKILL.md +756 -0
  227. package/.cursor/skills/backend-annotations/SKILL.md +674 -0
  228. package/.cursor/skills/banana-image/CHANGELOG.md +37 -0
  229. package/.cursor/skills/banana-image/README.md +146 -0
  230. package/.cursor/skills/banana-image/SKILL.md +164 -0
  231. package/.cursor/skills/banana-image/assets/logo.png +0 -0
  232. package/.cursor/skills/banana-image/references/advanced-usage.md +189 -0
  233. package/.cursor/skills/banana-image/scripts/apply_template.py +125 -0
  234. package/.cursor/skills/banana-image/scripts/banana_image_exec.ts +412 -0
  235. package/.cursor/skills/banana-image/scripts/batch_prep.py +82 -0
  236. package/.cursor/skills/banana-image/scripts/package-lock.json +1437 -0
  237. package/.cursor/skills/banana-image/scripts/package.json +18 -0
  238. package/.cursor/skills/banana-image/scripts/requirements.txt +10 -0
  239. package/.cursor/skills/banana-image/templates/poster.json +22 -0
  240. package/.cursor/skills/banana-image/templates/product.json +17 -0
  241. package/.cursor/skills/banana-image/templates/social.json +22 -0
  242. package/.cursor/skills/banana-image/templates/thumbnail.json +17 -0
  243. package/.cursor/skills/brainstorm/SKILL.md +648 -0
  244. package/.cursor/skills/bug-detective/SKILL.md +1206 -0
  245. package/.cursor/skills/code-patterns/SKILL.md +590 -0
  246. package/.cursor/skills/collaborating-with-codex/SKILL.md +174 -0
  247. package/.cursor/skills/collaborating-with-codex/scripts/codex_bridge.py +275 -0
  248. package/.cursor/skills/collaborating-with-gemini/SKILL.md +194 -0
  249. package/.cursor/skills/collaborating-with-gemini/scripts/gemini_bridge.py +275 -0
  250. package/.cursor/skills/crud-development/SKILL.md +649 -0
  251. package/.cursor/skills/data-permission/SKILL.md +599 -0
  252. package/.cursor/skills/database-ops/SKILL.md +407 -0
  253. package/.cursor/skills/error-handler/SKILL.md +371 -0
  254. package/.cursor/skills/file-oss-management/SKILL.md +863 -0
  255. package/.cursor/skills/git-workflow/SKILL.md +375 -0
  256. package/.cursor/skills/json-serialization/SKILL.md +357 -0
  257. package/.cursor/skills/leniu-api-development/SKILL.md +803 -0
  258. package/.cursor/skills/leniu-architecture-design/SKILL.md +598 -0
  259. package/.cursor/skills/leniu-backend-annotations/SKILL.md +664 -0
  260. package/.cursor/skills/leniu-code-patterns/SKILL.md +365 -0
  261. package/.cursor/skills/leniu-crud-development/SKILL.md +1110 -0
  262. package/.cursor/skills/leniu-data-permission/SKILL.md +256 -0
  263. package/.cursor/skills/leniu-database-ops/SKILL.md +426 -0
  264. package/.cursor/skills/leniu-error-handler/SKILL.md +462 -0
  265. package/.cursor/skills/leniu-java-amount-handling/SKILL.md +461 -0
  266. package/.cursor/skills/leniu-java-code-style/SKILL.md +510 -0
  267. package/.cursor/skills/leniu-java-concurrent/SKILL.md +400 -0
  268. package/.cursor/skills/leniu-java-entity/SKILL.md +751 -0
  269. package/.cursor/skills/leniu-java-export/SKILL.md +560 -0
  270. package/.cursor/skills/leniu-java-logging/SKILL.md +832 -0
  271. package/.cursor/skills/leniu-java-mq/SKILL.md +338 -0
  272. package/.cursor/skills/leniu-java-mybatis/SKILL.md +640 -0
  273. package/.cursor/skills/leniu-java-report-query-param/SKILL.md +291 -0
  274. package/.cursor/skills/leniu-java-task/SKILL.md +367 -0
  275. package/.cursor/skills/leniu-java-total-line/SKILL.md +195 -0
  276. package/.cursor/skills/leniu-marketing-price-rule-customizer/SKILL.md +301 -0
  277. package/.cursor/skills/leniu-marketing-recharge-rule-customizer/SKILL.md +285 -0
  278. package/.cursor/skills/leniu-mealtime/SKILL.md +215 -0
  279. package/.cursor/skills/leniu-redis-cache/SKILL.md +316 -0
  280. package/.cursor/skills/leniu-security-guard/SKILL.md +520 -0
  281. package/.cursor/skills/leniu-utils-toolkit/SKILL.md +380 -0
  282. package/.cursor/skills/openspec-apply-change/SKILL.md +156 -0
  283. package/.cursor/skills/openspec-archive-change/SKILL.md +114 -0
  284. package/.cursor/skills/openspec-bulk-archive-change/SKILL.md +246 -0
  285. package/.cursor/skills/openspec-continue-change/SKILL.md +118 -0
  286. package/.cursor/skills/openspec-explore/SKILL.md +290 -0
  287. package/.cursor/skills/openspec-ff-change/SKILL.md +101 -0
  288. package/.cursor/skills/openspec-new-change/SKILL.md +74 -0
  289. package/.cursor/skills/openspec-onboard/SKILL.md +529 -0
  290. package/.cursor/skills/openspec-sync-specs/SKILL.md +138 -0
  291. package/.cursor/skills/openspec-verify-change/SKILL.md +168 -0
  292. package/.cursor/skills/performance-doctor/SKILL.md +627 -0
  293. package/.cursor/skills/project-navigator/SKILL.md +305 -0
  294. package/.cursor/skills/redis-cache/SKILL.md +839 -0
  295. package/.cursor/skills/scheduled-jobs/SKILL.md +633 -0
  296. package/.cursor/skills/security-guard/SKILL.md +748 -0
  297. package/.cursor/skills/sms-mail/SKILL.md +766 -0
  298. package/.cursor/skills/social-login/SKILL.md +668 -0
  299. package/.cursor/skills/store-pc/SKILL.md +366 -0
  300. package/.cursor/skills/task-tracker/SKILL.md +307 -0
  301. package/.cursor/skills/tech-decision/SKILL.md +393 -0
  302. package/.cursor/skills/tenant-management/SKILL.md +603 -0
  303. package/.cursor/skills/test-development/SKILL.md +755 -0
  304. package/.cursor/skills/ui-pc/SKILL.md +438 -0
  305. package/.cursor/skills/utils-toolkit/SKILL.md +615 -0
  306. package/.cursor/skills/websocket-sse/SKILL.md +716 -0
  307. package/.cursor/skills/workflow-engine/SKILL.md +676 -0
  308. package/AGENTS.md +669 -0
  309. package/CLAUDE.md +205 -0
  310. package/README.md +205 -0
  311. package/bin/index.js +179 -0
  312. package/init.sh +178 -0
  313. package/package.json +27 -0
@@ -0,0 +1,412 @@
1
+ #!/usr/bin/env npx tsx
2
+ /**
3
+ * Banana Image - Gemini AI 图片生成执行脚本
4
+ * 直接调用 Gemini API,不依赖 MCP 服务
5
+ */
6
+
7
+ import { GoogleGenAI, Part } from "@google/genai";
8
+ import * as fs from "fs";
9
+ import * as path from "path";
10
+ import { ProxyAgent, setGlobalDispatcher } from "undici";
11
+
12
+ // 配置代理支持
13
+ const proxyUrl = process.env.HTTPS_PROXY || process.env.HTTP_PROXY;
14
+ if (proxyUrl) {
15
+ const dispatcher = new ProxyAgent(proxyUrl);
16
+ setGlobalDispatcher(dispatcher);
17
+ }
18
+
19
+ // ============================================================================
20
+ // 类型定义
21
+ // ============================================================================
22
+
23
+ interface BananaImageOptions {
24
+ prompt: string;
25
+ model?: "flash" | "pro";
26
+ aspectRatio?: string;
27
+ resolution?: string;
28
+ negativePrompt?: string;
29
+ outputDir?: string;
30
+ enableGrounding?: boolean;
31
+ inputImage?: string;
32
+ systemInstruction?: string;
33
+ count?: number;
34
+ }
35
+
36
+ interface GeneratedImage {
37
+ path: string;
38
+ width?: number;
39
+ height?: number;
40
+ model: string;
41
+ prompt: string;
42
+ }
43
+
44
+ interface BananaImageResult {
45
+ success: boolean;
46
+ images?: GeneratedImage[];
47
+ error?: string;
48
+ metadata?: {
49
+ model: string;
50
+ aspectRatio?: string;
51
+ resolution?: string;
52
+ duration: number;
53
+ };
54
+ }
55
+
56
+ // ============================================================================
57
+ // 常量
58
+ // ============================================================================
59
+
60
+ const MODEL_MAP = {
61
+ flash: "gemini-2.5-flash-image",
62
+ pro: "gemini-3-pro-image-preview",
63
+ } as const;
64
+
65
+ const VALID_ASPECT_RATIOS = [
66
+ "1:1",
67
+ "2:3",
68
+ "3:2",
69
+ "3:4",
70
+ "4:3",
71
+ "4:5",
72
+ "5:4",
73
+ "9:16",
74
+ "16:9",
75
+ "21:9",
76
+ ];
77
+
78
+ const VALID_RESOLUTIONS = ["1K", "2K", "4K"];
79
+
80
+ const DEFAULT_OUTPUT_DIR = path.join(process.cwd(), "images");
81
+
82
+ // ============================================================================
83
+ // 工具函数
84
+ // ============================================================================
85
+
86
+ function generateFilename(prefix: string = "banana"): string {
87
+ const timestamp = new Date().toISOString().replace(/[:.]/g, "-");
88
+ const random = Math.random().toString(36).substring(2, 8);
89
+ return `${prefix}_${timestamp}_${random}.png`;
90
+ }
91
+
92
+ function ensureOutputDir(dir: string): void {
93
+ if (!fs.existsSync(dir)) {
94
+ fs.mkdirSync(dir, { recursive: true });
95
+ }
96
+ }
97
+
98
+ function loadImageAsBase64(imagePath: string): string {
99
+ const buffer = fs.readFileSync(imagePath);
100
+ return buffer.toString("base64");
101
+ }
102
+
103
+ function getMimeType(imagePath: string): string {
104
+ const ext = path.extname(imagePath).toLowerCase();
105
+ const mimeTypes: Record<string, string> = {
106
+ ".png": "image/png",
107
+ ".jpg": "image/jpeg",
108
+ ".jpeg": "image/jpeg",
109
+ ".gif": "image/gif",
110
+ ".webp": "image/webp",
111
+ };
112
+ return mimeTypes[ext] || "image/png";
113
+ }
114
+
115
+ // ============================================================================
116
+ // 核心生成逻辑
117
+ // ============================================================================
118
+
119
+ async function generateImages(
120
+ options: BananaImageOptions,
121
+ ): Promise<BananaImageResult> {
122
+ const startTime = Date.now();
123
+
124
+ // 验证 API Key
125
+ const apiKey = process.env.GEMINI_API_KEY;
126
+ if (!apiKey) {
127
+ return {
128
+ success: false,
129
+ error: "GEMINI_API_KEY environment variable is not set",
130
+ };
131
+ }
132
+
133
+ // 参数处理
134
+ const modelTier = options.model || "pro";
135
+ const modelName = MODEL_MAP[modelTier];
136
+ const outputDir = options.outputDir || DEFAULT_OUTPUT_DIR;
137
+ const aspectRatio = options.aspectRatio || "1:1";
138
+ const resolution = options.resolution || (modelTier === "pro" ? "4K" : "1K");
139
+ const count = Math.min(options.count || 1, 4);
140
+
141
+ // 验证参数
142
+ if (
143
+ options.aspectRatio &&
144
+ !VALID_ASPECT_RATIOS.includes(options.aspectRatio)
145
+ ) {
146
+ return {
147
+ success: false,
148
+ error: `Invalid aspect ratio: ${options.aspectRatio}. Valid: ${VALID_ASPECT_RATIOS.join(", ")}`,
149
+ };
150
+ }
151
+
152
+ if (
153
+ options.resolution &&
154
+ !VALID_RESOLUTIONS.includes(options.resolution.toUpperCase())
155
+ ) {
156
+ return {
157
+ success: false,
158
+ error: `Invalid resolution: ${options.resolution}. Valid: ${VALID_RESOLUTIONS.join(", ")}`,
159
+ };
160
+ }
161
+
162
+ ensureOutputDir(outputDir);
163
+
164
+ try {
165
+ // 支持自定义 API 地址(如第三方代理)
166
+ const apiBase = process.env.GEMINI_API_BASE || process.env.GOOGLE_API_BASE;
167
+ const aiConfig: { apiKey: string; httpOptions?: { baseUrl: string } } = { apiKey };
168
+ if (apiBase) {
169
+ aiConfig.httpOptions = { baseUrl: apiBase };
170
+ }
171
+ const ai = new GoogleGenAI(aiConfig);
172
+
173
+ // 构建内容
174
+ const contents: (string | Part)[] = [];
175
+
176
+ // 添加系统指令
177
+ if (options.systemInstruction) {
178
+ contents.push(options.systemInstruction);
179
+ }
180
+
181
+ // 添加输入图片(编辑模式)
182
+ if (options.inputImage && fs.existsSync(options.inputImage)) {
183
+ const imageData = loadImageAsBase64(options.inputImage);
184
+ const mimeType = getMimeType(options.inputImage);
185
+ contents.push({
186
+ inlineData: {
187
+ data: imageData,
188
+ mimeType,
189
+ },
190
+ });
191
+ }
192
+
193
+ // 构建提示词
194
+ let fullPrompt = options.prompt;
195
+ if (options.negativePrompt) {
196
+ fullPrompt += `\n\nAvoid: ${options.negativePrompt}`;
197
+ }
198
+ contents.push(fullPrompt);
199
+
200
+ // 构建配置
201
+ // 注意:只有 Pro 模型支持 imageConfig 和 tools
202
+ const config: Record<string, unknown> = {};
203
+
204
+ if (modelTier === "pro") {
205
+ // Pro 模型支持宽高比和分辨率配置
206
+ config.imageConfig = {
207
+ aspectRatio,
208
+ imageSize: resolution.toUpperCase(),
209
+ };
210
+
211
+ // Google Search grounding
212
+ if (options.enableGrounding) {
213
+ config.tools = [{ googleSearch: {} }];
214
+ }
215
+ }
216
+ // Flash 模型不支持 imageConfig,使用默认配置
217
+
218
+ // 调用 API
219
+ const generatedImages: GeneratedImage[] = [];
220
+
221
+ for (let i = 0; i < count; i++) {
222
+ const response = await ai.models.generateContent({
223
+ model: modelName,
224
+ contents: contents.length === 1 ? contents[0] : contents,
225
+ config,
226
+ });
227
+
228
+ // 提取图片
229
+ const candidates = response.candidates || [];
230
+ for (const candidate of candidates) {
231
+ const parts = candidate.content?.parts || [];
232
+ for (const part of parts) {
233
+ if ("inlineData" in part && part.inlineData?.data) {
234
+ const filename = generateFilename(`banana_${modelTier}`);
235
+ const filePath = path.join(outputDir, filename);
236
+
237
+ // 保存图片
238
+ const buffer = Buffer.from(part.inlineData.data, "base64");
239
+ fs.writeFileSync(filePath, buffer);
240
+
241
+ generatedImages.push({
242
+ path: filePath,
243
+ model: modelName,
244
+ prompt: options.prompt,
245
+ });
246
+ }
247
+ }
248
+ }
249
+ }
250
+
251
+ if (generatedImages.length === 0) {
252
+ return {
253
+ success: false,
254
+ error: "No images were generated. The content may have been filtered.",
255
+ };
256
+ }
257
+
258
+ const duration = Date.now() - startTime;
259
+
260
+ return {
261
+ success: true,
262
+ images: generatedImages,
263
+ metadata: {
264
+ model: modelName,
265
+ aspectRatio,
266
+ resolution,
267
+ duration,
268
+ },
269
+ };
270
+ } catch (error) {
271
+ const errorMessage = error instanceof Error ? error.message : String(error);
272
+ return {
273
+ success: false,
274
+ error: `Image generation failed: ${errorMessage}`,
275
+ };
276
+ }
277
+ }
278
+
279
+ // ============================================================================
280
+ // CLI 入口
281
+ // ============================================================================
282
+
283
+ function printUsage(): void {
284
+ console.log(`
285
+ Banana Image - Gemini AI 图片生成
286
+
287
+ Usage:
288
+ npx tsx banana_image_exec.ts [options]
289
+
290
+ Options:
291
+ --prompt, -p <text> 图片描述(必需)
292
+ --model, -m <type> 模型选择: flash | pro (默认: pro)
293
+ --aspect-ratio, -a <r> 宽高比: 1:1, 16:9, 9:16, 4:3, 3:2, 21:9 等
294
+ --resolution, -r <res> 分辨率: 1K, 2K, 4K (默认: Pro=4K, Flash=1K)
295
+ --negative, -n <text> 排除内容描述
296
+ --output, -o <dir> 输出目录 (默认: ./images)
297
+ --grounding, -g 启用 Google Search 锚定 (仅 Pro)
298
+ --input, -i <path> 输入图片路径(编辑模式)
299
+ --system, -s <text> 系统指令
300
+ --count, -c <num> 生成数量 (1-4)
301
+ --help, -h 显示帮助
302
+
303
+ Examples:
304
+ # 快速生成
305
+ npx tsx banana_image_exec.ts -p "可爱的柴犬" -m flash
306
+
307
+ # 4K 高质量
308
+ npx tsx banana_image_exec.ts -p "专业产品照片" -m pro -r 4K -a 4:5
309
+
310
+ # 编辑图片
311
+ npx tsx banana_image_exec.ts -p "将背景改为黄昏" -i /path/to/image.png
312
+ `);
313
+ }
314
+
315
+ function parseArgs(): BananaImageOptions | null {
316
+ const args = process.argv.slice(2);
317
+
318
+ if (args.length === 0 || args.includes("--help") || args.includes("-h")) {
319
+ printUsage();
320
+ return null;
321
+ }
322
+
323
+ const options: BananaImageOptions = {
324
+ prompt: "",
325
+ };
326
+
327
+ for (let i = 0; i < args.length; i++) {
328
+ const arg = args[i];
329
+ const next = args[i + 1];
330
+
331
+ switch (arg) {
332
+ case "--prompt":
333
+ case "-p":
334
+ options.prompt = next || "";
335
+ i++;
336
+ break;
337
+ case "--model":
338
+ case "-m":
339
+ if (next === "flash" || next === "pro") {
340
+ options.model = next;
341
+ }
342
+ i++;
343
+ break;
344
+ case "--aspect-ratio":
345
+ case "-a":
346
+ options.aspectRatio = next;
347
+ i++;
348
+ break;
349
+ case "--resolution":
350
+ case "-r":
351
+ options.resolution = next;
352
+ i++;
353
+ break;
354
+ case "--negative":
355
+ case "-n":
356
+ options.negativePrompt = next;
357
+ i++;
358
+ break;
359
+ case "--output":
360
+ case "-o":
361
+ options.outputDir = next;
362
+ i++;
363
+ break;
364
+ case "--grounding":
365
+ case "-g":
366
+ options.enableGrounding = true;
367
+ break;
368
+ case "--input":
369
+ case "-i":
370
+ options.inputImage = next;
371
+ i++;
372
+ break;
373
+ case "--system":
374
+ case "-s":
375
+ options.systemInstruction = next;
376
+ i++;
377
+ break;
378
+ case "--count":
379
+ case "-c":
380
+ options.count = parseInt(next, 10) || 1;
381
+ i++;
382
+ break;
383
+ }
384
+ }
385
+
386
+ if (!options.prompt) {
387
+ console.error("Error: --prompt is required");
388
+ printUsage();
389
+ return null;
390
+ }
391
+
392
+ return options;
393
+ }
394
+
395
+ async function main(): Promise<void> {
396
+ const options = parseArgs();
397
+ if (!options) {
398
+ process.exit(1);
399
+ }
400
+
401
+ const result = await generateImages(options);
402
+ console.log(JSON.stringify(result, null, 2));
403
+
404
+ if (!result.success) {
405
+ process.exit(1);
406
+ }
407
+ }
408
+
409
+ main().catch((error) => {
410
+ console.error(JSON.stringify({ success: false, error: String(error) }));
411
+ process.exit(1);
412
+ });
@@ -0,0 +1,82 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ 批量图片生成准备脚本
4
+ 将文本文件(每行一个 prompt)或 CSV 转换为 JSON 格式的 prompt 列表
5
+ """
6
+
7
+ import sys
8
+ import json
9
+ import csv
10
+ import argparse
11
+ from pathlib import Path
12
+
13
+
14
+ def parse_text_file(filepath: Path) -> list[dict]:
15
+ """解析纯文本文件,每行一个 prompt"""
16
+ prompts = []
17
+ with open(filepath, "r", encoding="utf-8") as f:
18
+ for i, line in enumerate(f, 1):
19
+ line = line.strip()
20
+ if line and not line.startswith("#"):
21
+ prompts.append({"id": i, "prompt": line})
22
+ return prompts
23
+
24
+
25
+ def parse_csv_file(filepath: Path, prompt_column: str = "prompt") -> list[dict]:
26
+ """解析 CSV 文件,提取指定列作为 prompt"""
27
+ prompts = []
28
+ with open(filepath, "r", encoding="utf-8") as f:
29
+ reader = csv.DictReader(f)
30
+ for i, row in enumerate(reader, 1):
31
+ prompt = row.get(prompt_column) or row.get(list(row.keys())[0])
32
+ if prompt and prompt.strip():
33
+ entry = {"id": i, "prompt": prompt.strip()}
34
+ # 保留其他列作为参数
35
+ for key, value in row.items():
36
+ if key != prompt_column and value:
37
+ entry[key] = value
38
+ prompts.append(entry)
39
+ return prompts
40
+
41
+
42
+ def main():
43
+ parser = argparse.ArgumentParser(
44
+ description="将文本或 CSV 文件转换为批量生成的 JSON 格式"
45
+ )
46
+ parser.add_argument("file", help="输入文件路径")
47
+ parser.add_argument(
48
+ "--column", "-c", default="prompt", help="CSV 中 prompt 所在列名 (默认: prompt)"
49
+ )
50
+ parser.add_argument("--output", "-o", help="输出文件路径 (默认: 标准输出)")
51
+
52
+ args = parser.parse_args()
53
+ filepath = Path(args.file)
54
+
55
+ if not filepath.exists():
56
+ print(json.dumps({"error": f"文件不存在: {filepath}"}))
57
+ sys.exit(1)
58
+
59
+ try:
60
+ if filepath.suffix.lower() == ".csv":
61
+ prompts = parse_csv_file(filepath, args.column)
62
+ else:
63
+ prompts = parse_text_file(filepath)
64
+
65
+ result = {"source": str(filepath), "count": len(prompts), "prompts": prompts}
66
+
67
+ output = json.dumps(result, ensure_ascii=False, indent=2)
68
+
69
+ if args.output:
70
+ with open(args.output, "w", encoding="utf-8") as f:
71
+ f.write(output)
72
+ print(f"已保存到: {args.output}")
73
+ else:
74
+ print(output)
75
+
76
+ except Exception as e:
77
+ print(json.dumps({"error": str(e)}))
78
+ sys.exit(1)
79
+
80
+
81
+ if __name__ == "__main__":
82
+ main()