cue-ai 0.9.2 → 0.9.4

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 (278) hide show
  1. package/CHANGELOG.md +4 -3
  2. package/README.md +154 -394
  3. package/bin/cue-learnings +30 -4
  4. package/bin/cue-review-progress +0 -0
  5. package/bin/cue-review-watch +0 -0
  6. package/dist/cue.js +4328 -3108
  7. package/package.json +1 -1
  8. package/plugins/cue/commands/cue-switch.md +1 -1
  9. package/plugins/cue/commands/cue.md +1 -1
  10. package/profiles/backend/profile.yaml +4 -0
  11. package/profiles/browser/profile.yaml +4 -0
  12. package/profiles/career/profile.yaml +2 -13
  13. package/profiles/commerce/profile.yaml +0 -2
  14. package/profiles/coolify/profile.yaml +0 -1
  15. package/profiles/core/profile.yaml +78 -11
  16. package/profiles/dash-merge-test/profile.yaml +6 -1
  17. package/profiles/designer/profile.yaml +9 -1
  18. package/profiles/dropshipping/profile.yaml +69 -0
  19. package/profiles/frontend/profile.yaml +4 -0
  20. package/profiles/google-ads/profile.yaml +34 -0
  21. package/profiles/google-analytics/profile.yaml +34 -0
  22. package/profiles/google-drive/profile.yaml +34 -0
  23. package/profiles/gstack/profile.yaml +117 -29
  24. package/profiles/marketing/profile.yaml +0 -1
  25. package/profiles/media/README.md +70 -0
  26. package/profiles/media/profile.yaml +104 -0
  27. package/profiles/nano-banana/profile.yaml +52 -0
  28. package/profiles/ops/profile.yaml +1 -2
  29. package/profiles/secops/profile.yaml +3 -0
  30. package/profiles/skill-writer/profile.yaml +15 -0
  31. package/profiles/video/profile.yaml +3 -0
  32. package/profiles/web-frontend-base/profile.yaml +6 -0
  33. package/profiles/webshop/profile.yaml +0 -1
  34. package/profiles/webshop-google/profile.yaml +1 -0
  35. package/profiles/x-growth-bot/profile.yaml +2 -0
  36. package/resources/icons/generate-icons.py +2 -128
  37. package/resources/mcps/configs/claude.sanitized.json +88 -20
  38. package/resources/mcps/configs/claude_runtime.sanitized.json +40 -1
  39. package/resources/mcps/configs/codex.sanitized.json +29 -0
  40. package/resources/skills/skills/career/job-hunter/LICENSE +21 -0
  41. package/resources/skills/skills/career/job-hunter/README.md +323 -0
  42. package/resources/skills/skills/career/job-hunter/SKILL.md +91 -0
  43. package/resources/skills/skills/career/job-hunter/agents/README.md +96 -0
  44. package/resources/skills/skills/career/job-hunter/agents/apply-assessment-prep.md +195 -0
  45. package/resources/skills/skills/career/job-hunter/agents/apply-ats-scan.md +155 -0
  46. package/resources/skills/skills/career/job-hunter/agents/apply-bias-audit.md +224 -0
  47. package/resources/skills/skills/career/job-hunter/agents/apply-cover-letter.md +69 -0
  48. package/resources/skills/skills/career/job-hunter/agents/apply-decode-jd.md +117 -0
  49. package/resources/skills/skills/career/job-hunter/agents/apply-fit-score.md +183 -0
  50. package/resources/skills/skills/career/job-hunter/agents/apply-linkedin-audit.md +74 -0
  51. package/resources/skills/skills/career/job-hunter/agents/apply-linkedin-scrape.md +255 -0
  52. package/resources/skills/skills/career/job-hunter/agents/apply-portfolio-brief.md +123 -0
  53. package/resources/skills/skills/career/job-hunter/agents/apply-reality-check.md +164 -0
  54. package/resources/skills/skills/career/job-hunter/agents/apply-reference-prep.md +150 -0
  55. package/resources/skills/skills/career/job-hunter/agents/apply-rejection-analysis.md +172 -0
  56. package/resources/skills/skills/career/job-hunter/agents/apply-resume.md +70 -0
  57. package/resources/skills/skills/career/job-hunter/agents/apply-skills-gap-filler.md +109 -0
  58. package/resources/skills/skills/career/job-hunter/agents/career-internal.md +94 -0
  59. package/resources/skills/skills/career/job-hunter/agents/career-linkedin-content.md +173 -0
  60. package/resources/skills/skills/career/job-hunter/agents/career-linkedin-scanner.md +262 -0
  61. package/resources/skills/skills/career/job-hunter/agents/career-network-message.md +108 -0
  62. package/resources/skills/skills/career/job-hunter/agents/career-promote.md +102 -0
  63. package/resources/skills/skills/career/job-hunter/agents/career-review.md +71 -0
  64. package/resources/skills/skills/career/job-hunter/agents/interview-debrief.md +117 -0
  65. package/resources/skills/skills/career/job-hunter/agents/interview-mock.md +171 -0
  66. package/resources/skills/skills/career/job-hunter/agents/interview-panel-decoder.md +152 -0
  67. package/resources/skills/skills/career/job-hunter/agents/interview-prep.md +184 -0
  68. package/resources/skills/skills/career/job-hunter/agents/interview-question-bank.md +133 -0
  69. package/resources/skills/skills/career/job-hunter/agents/interview-research.md +148 -0
  70. package/resources/skills/skills/career/job-hunter/agents/offer-compare.md +117 -0
  71. package/resources/skills/skills/career/job-hunter/agents/offer-counteroffer.md +144 -0
  72. package/resources/skills/skills/career/job-hunter/agents/offer-deadline-manager.md +148 -0
  73. package/resources/skills/skills/career/job-hunter/agents/offer-negotiate.md +126 -0
  74. package/resources/skills/skills/career/job-hunter/agents/offer-schedule.md +99 -0
  75. package/resources/skills/skills/career/job-hunter/agents/offer-thankyou.md +80 -0
  76. package/resources/skills/skills/career/job-hunter/agents/search-company-research.md +146 -0
  77. package/resources/skills/skills/career/job-hunter/agents/search-follow-up.md +129 -0
  78. package/resources/skills/skills/career/job-hunter/agents/search-ghost-job-detector.md +152 -0
  79. package/resources/skills/skills/career/job-hunter/agents/search-inbox-scan.md +193 -0
  80. package/resources/skills/skills/career/job-hunter/agents/search-interview-scorecard.md +164 -0
  81. package/resources/skills/skills/career/job-hunter/agents/search-jobs.md +149 -0
  82. package/resources/skills/skills/career/job-hunter/agents/search-momentum-check.md +194 -0
  83. package/resources/skills/skills/career/job-hunter/agents/search-outreach.md +85 -0
  84. package/resources/skills/skills/career/job-hunter/agents/search-referral-finder.md +124 -0
  85. package/resources/skills/skills/career/job-hunter/agents/search-salary.md +96 -0
  86. package/resources/skills/skills/career/job-hunter/agents/search-send-email.md +109 -0
  87. package/resources/skills/skills/career/job-hunter/agents/search-tracker-update.md +127 -0
  88. package/resources/skills/skills/career/job-hunter/inputs/README.md +26 -0
  89. package/resources/skills/skills/career/job-hunter/inputs/apply-linkedin-url.txt +8 -0
  90. package/resources/skills/skills/career/job-hunter/inputs/interview-context.md +24 -0
  91. package/resources/skills/skills/career/job-hunter/inputs/job-description.md +20 -0
  92. package/resources/skills/skills/career/job-hunter/inputs/job-search-criteria.md +36 -0
  93. package/resources/skills/skills/career/job-hunter/inputs/my-linkedin.md +24 -0
  94. package/resources/skills/skills/career/job-hunter/inputs/my-resume.md +28 -0
  95. package/resources/skills/skills/career/job-hunter/inputs/search-outreach-target.md +24 -0
  96. package/resources/skills/skills/career/job-hunter/rules/README.md +37 -0
  97. package/resources/skills/skills/career/job-hunter/rules/writing-rules.md +81 -0
  98. package/resources/skills/skills/design/banana/SKILL.md +375 -0
  99. package/resources/skills/skills/design/banana/references/cost-tracking.md +47 -0
  100. package/resources/skills/skills/design/banana/references/gemini-models.md +236 -0
  101. package/resources/skills/skills/design/banana/references/mcp-tools.md +145 -0
  102. package/resources/skills/skills/design/banana/references/post-processing.md +192 -0
  103. package/resources/skills/skills/design/banana/references/presets.md +69 -0
  104. package/resources/skills/skills/design/banana/references/prompt-engineering.md +481 -0
  105. package/resources/skills/skills/design/banana/scripts/batch.py +97 -0
  106. package/resources/skills/skills/design/banana/scripts/cost_tracker.py +191 -0
  107. package/resources/skills/skills/design/banana/scripts/edit.py +159 -0
  108. package/resources/skills/skills/design/banana/scripts/generate.py +168 -0
  109. package/resources/skills/skills/design/banana/scripts/presets.py +154 -0
  110. package/resources/skills/skills/design/banana/scripts/setup_mcp.py +151 -0
  111. package/resources/skills/skills/design/banana/scripts/validate_setup.py +133 -0
  112. package/resources/skills/skills/gstack/ship/SKILL.md +13 -0
  113. package/resources/skills/skills/media/3d-logo-animation/SKILL.md +59 -0
  114. package/resources/skills/skills/media/action-figure-generator/SKILL.md +48 -0
  115. package/resources/skills/skills/media/ad-creative/SKILL.md +79 -0
  116. package/resources/skills/skills/media/ai-clipping/SKILL.md +194 -0
  117. package/resources/skills/skills/media/ai-clipping/scripts/run-ai-clipping.sh +200 -0
  118. package/resources/skills/skills/media/ai-fight-scene/SKILL.md +132 -0
  119. package/resources/skills/skills/media/amazon-product-listing/SKILL.md +68 -0
  120. package/resources/skills/skills/media/animal-video-generator/SKILL.md +59 -0
  121. package/resources/skills/skills/media/award-ceremony-video/SKILL.md +87 -0
  122. package/resources/skills/skills/media/blog-header/SKILL.md +61 -0
  123. package/resources/skills/skills/media/brand-kit/SKILL.md +72 -0
  124. package/resources/skills/skills/media/brochures/SKILL.md +65 -0
  125. package/resources/skills/skills/media/cartoon-dance-animation/SKILL.md +62 -0
  126. package/resources/skills/skills/media/character-story-video/SKILL.md +84 -0
  127. package/resources/skills/skills/media/chibi-collage-effect/SKILL.md +63 -0
  128. package/resources/skills/skills/media/cinema-director/SKILL.md +93 -0
  129. package/resources/skills/skills/media/cinema-director/scripts/generate-film.sh +78 -0
  130. package/resources/skills/skills/media/color-analysis-board/SKILL.md +71 -0
  131. package/resources/skills/skills/media/core-edit/SKILL.md +48 -0
  132. package/resources/skills/skills/media/core-edit/edit-image.sh +54 -0
  133. package/resources/skills/skills/media/core-edit/enhance-image.sh +191 -0
  134. package/resources/skills/skills/media/core-edit/lipsync.sh +144 -0
  135. package/resources/skills/skills/media/core-edit/video-effects.sh +193 -0
  136. package/resources/skills/skills/media/core-media/SKILL.md +49 -0
  137. package/resources/skills/skills/media/core-media/create-music.sh +169 -0
  138. package/resources/skills/skills/media/core-media/generate-image.sh +161 -0
  139. package/resources/skills/skills/media/core-media/generate-video.sh +137 -0
  140. package/resources/skills/skills/media/core-media/image-to-video.sh +228 -0
  141. package/resources/skills/skills/media/core-media/schema_data.json +18708 -0
  142. package/resources/skills/skills/media/core-media/upload.sh +41 -0
  143. package/resources/skills/skills/media/core-platform/SKILL.md +41 -0
  144. package/resources/skills/skills/media/core-platform/check-result.sh +37 -0
  145. package/resources/skills/skills/media/core-platform/setup.sh +31 -0
  146. package/resources/skills/skills/media/couple-grid-creator/SKILL.md +47 -0
  147. package/resources/skills/skills/media/design-guide/SKILL.md +73 -0
  148. package/resources/skills/skills/media/drone-style-video/SKILL.md +61 -0
  149. package/resources/skills/skills/media/fashion-try-on/SKILL.md +61 -0
  150. package/resources/skills/skills/media/floor-plan-rendering/SKILL.md +56 -0
  151. package/resources/skills/skills/media/freeze-effect-video/SKILL.md +100 -0
  152. package/resources/skills/skills/media/giant-product-showcase/SKILL.md +61 -0
  153. package/resources/skills/skills/media/instagram-post/SKILL.md +58 -0
  154. package/resources/skills/skills/media/interior-design/SKILL.md +61 -0
  155. package/resources/skills/skills/media/interior-design-visualizer/SKILL.md +57 -0
  156. package/resources/skills/skills/media/jewelry-product-video/SKILL.md +61 -0
  157. package/resources/skills/skills/media/kdenlive/SKILL.md +106 -0
  158. package/resources/skills/skills/media/kdenlive/scripts/assemble.sh +57 -0
  159. package/resources/skills/skills/media/kdenlive/scripts/common.sh +30 -0
  160. package/resources/skills/skills/media/kdenlive/scripts/inspect.sh +19 -0
  161. package/resources/skills/skills/media/kdenlive/scripts/reframe.sh +22 -0
  162. package/resources/skills/skills/media/kdenlive/scripts/render.sh +16 -0
  163. package/resources/skills/skills/media/kdenlive/scripts/title-card.sh +25 -0
  164. package/resources/skills/skills/media/keyboard-art-maker/SKILL.md +44 -0
  165. package/resources/skills/skills/media/logo-branding/SKILL.md +70 -0
  166. package/resources/skills/skills/media/logo-creator/SKILL.md +80 -0
  167. package/resources/skills/skills/media/logo-creator/scripts/create-logo.sh +38 -0
  168. package/resources/skills/skills/media/logo-generator/SKILL.md +56 -0
  169. package/resources/skills/skills/media/multi-angle-reshoot/SKILL.md +70 -0
  170. package/resources/skills/skills/media/multi-angle-shots/SKILL.md +73 -0
  171. package/resources/skills/skills/media/music-video/SKILL.md +61 -0
  172. package/resources/skills/skills/media/nano-banana/SKILL.md +80 -0
  173. package/resources/skills/skills/media/nano-banana/scripts/generate-nano-art.sh +54 -0
  174. package/resources/skills/skills/media/one-shot-video/SKILL.md +56 -0
  175. package/resources/skills/skills/media/photo-pack-generator/SKILL.md +205 -0
  176. package/resources/skills/skills/media/photo-pack-generator/scripts/generate-pack.sh +241 -0
  177. package/resources/skills/skills/media/product-ad-cinematic/SKILL.md +78 -0
  178. package/resources/skills/skills/media/product-campaign/SKILL.md +76 -0
  179. package/resources/skills/skills/media/product-showcase-video/SKILL.md +60 -0
  180. package/resources/skills/skills/media/product-video-ad-maker/SKILL.md +59 -0
  181. package/resources/skills/skills/media/rednote-cover/SKILL.md +57 -0
  182. package/resources/skills/skills/media/seedance-2/SKILL.md +632 -0
  183. package/resources/skills/skills/media/seedance-2/scripts/generate-seedance.sh +701 -0
  184. package/resources/skills/skills/media/selfie-with-celebrities/SKILL.md +64 -0
  185. package/resources/skills/skills/media/social-media-video/SKILL.md +277 -0
  186. package/resources/skills/skills/media/social-media-video/scripts/run-social-video.sh +316 -0
  187. package/resources/skills/skills/media/social-pack/SKILL.md +58 -0
  188. package/resources/skills/skills/media/storyboard/SKILL.md +57 -0
  189. package/resources/skills/skills/media/storyboard-to-cooking-video/SKILL.md +143 -0
  190. package/resources/skills/skills/media/talking-baby-video/SKILL.md +57 -0
  191. package/resources/skills/skills/media/ugc-ads-workflow/SKILL.md +70 -0
  192. package/resources/skills/skills/media/ugc-lifestyle-try-on/SKILL.md +65 -0
  193. package/resources/skills/skills/media/ugc-video-factory/SKILL.md +134 -0
  194. package/resources/skills/skills/media/ui-design/SKILL.md +81 -0
  195. package/resources/skills/skills/media/ui-design/scripts/generate-mockup.sh +49 -0
  196. package/resources/skills/skills/media/url-to-design/SKILL.md +61 -0
  197. package/resources/skills/skills/media/workflow/SKILL.md +197 -0
  198. package/resources/skills/skills/media/workflow/scripts/discover-workflow.sh +18 -0
  199. package/resources/skills/skills/media/workflow/scripts/generate-workflow.sh +33 -0
  200. package/resources/skills/skills/media/workflow/scripts/interactive-run.sh +16 -0
  201. package/resources/skills/skills/media/workflow/scripts/list-workflows.sh +20 -0
  202. package/resources/skills/skills/media/workflow/scripts/run-workflow.sh +34 -0
  203. package/resources/skills/skills/media/youtube-shorts/SKILL.md +173 -0
  204. package/resources/skills/skills/media/youtube-shorts/scripts/run-youtube-shorts.sh +141 -0
  205. package/resources/skills/skills/media/youtube-thumbnail/SKILL.md +66 -0
  206. package/resources/skills/skills/meta/cue-developer/references/architecture.md +2 -2
  207. package/resources/skills/skills/meta/cue-usage/SKILL.md +1 -1
  208. package/resources/skills/skills/meta/profile-fit-monitor/SKILL.md +2 -2
  209. package/resources/skills/skills/meta/profile-optimizer/SKILL.md +1 -1
  210. package/resources/skills/skills/meta/profile-suggest/SKILL.md +7 -7
  211. package/resources/skills/skills/meta/profile-summon/SKILL.md +159 -0
  212. package/resources/skills/skills/meta/profile-summon/evals/evals.json +53 -0
  213. package/resources/skills/skills/meta/save-profile/SKILL.md +1 -1
  214. package/resources/skills/skills/meta/skill-reviewer/SKILL.md +3 -0
  215. package/resources/skills/skills/meta/skill-reviewer/references/tdd-for-skills.md +55 -0
  216. package/resources/skills/skills/research/find-skills/SKILL.md +1 -1
  217. package/resources/skills/skills/review/code-review-deep/SKILL.md +20 -0
  218. package/resources/skills/skills/security/trivy-scan/SKILL.md +139 -0
  219. package/resources/skills/skills/security/trivy-scan/scripts/ensure-trivy.sh +21 -0
  220. package/resources/skills/skills/tools/ccusage/SKILL.md +142 -0
  221. package/src/commands/_index.ts +8 -0
  222. package/src/commands/ai.ts +2 -2
  223. package/src/commands/auto-detect.test.ts +74 -0
  224. package/src/commands/auto-detect.ts +9 -7
  225. package/src/commands/cli.test.ts +20 -4
  226. package/src/commands/cli.ts +36 -20
  227. package/src/commands/create-profile.ts +2 -2
  228. package/src/commands/debug.ts +2 -2
  229. package/src/commands/discover.ts +14 -4
  230. package/src/commands/export-docker.ts +1 -1
  231. package/src/commands/features-batch1.test.ts +1 -1
  232. package/src/commands/gates.ts +1 -1
  233. package/src/commands/import-profile.ts +1 -1
  234. package/src/commands/init.ts +15 -11
  235. package/src/commands/install.test.ts +192 -0
  236. package/src/commands/install.ts +610 -0
  237. package/src/commands/launch-handoff.e2e.test.ts +33 -1
  238. package/src/commands/launch.e2e.test.ts +15 -10
  239. package/src/commands/launch.ts +73 -116
  240. package/src/commands/materialize.ts +2 -2
  241. package/src/commands/prune.ts +1 -1
  242. package/src/commands/security-audit.ts +1 -1
  243. package/src/commands/shell.ts +7 -7
  244. package/src/commands/skill-report.ts +1 -1
  245. package/src/commands/skills.ts +3 -3
  246. package/src/commands/snapshot.ts +2 -2
  247. package/src/commands/summon.test.ts +116 -0
  248. package/src/commands/summon.ts +338 -0
  249. package/src/commands/trigger-gaps.ts +1 -1
  250. package/src/commands/use.ts +47 -3
  251. package/src/commands/watch-live.ts +5 -5
  252. package/src/commands/watch.ts +8 -8
  253. package/src/index.ts +2 -0
  254. package/src/lib/active-sessions.test.ts +3 -3
  255. package/src/lib/active-sessions.ts +4 -4
  256. package/src/lib/auto-detect.test.ts +172 -8
  257. package/src/lib/auto-detect.ts +191 -136
  258. package/src/lib/codex-persona-parity.test.ts +58 -0
  259. package/src/lib/companion-detect.test.ts +43 -1
  260. package/src/lib/companion-detect.ts +35 -0
  261. package/src/lib/credentials-sync.test.ts +121 -1
  262. package/src/lib/credentials-sync.ts +95 -1
  263. package/src/lib/cwd-resolver.test.ts +8 -8
  264. package/src/lib/cwd-resolver.ts +2 -2
  265. package/src/lib/dashboard-merge.test.ts +9 -4
  266. package/src/lib/dashboard-server.ts +1 -1
  267. package/src/lib/picker.test.ts +1 -1
  268. package/src/lib/picker.ts +5 -5
  269. package/src/lib/profile-merge.test.ts +8 -0
  270. package/src/lib/profile-names.test.ts +3 -3
  271. package/src/lib/runtime-install.ts +166 -0
  272. package/src/lib/runtime-materializer.test.ts +137 -0
  273. package/src/lib/runtime-materializer.ts +105 -2
  274. package/src/lib/skill-router.test.ts +38 -0
  275. package/src/lib/skill-router.ts +65 -4
  276. package/profiles/eu-tender-research/README.md +0 -48
  277. package/profiles/eu-tender-research/logo.png +0 -0
  278. package/profiles/eu-tender-research/profile.yaml +0 -108
@@ -0,0 +1,169 @@
1
+ #!/bin/bash
2
+ # muapi.ai Audio & Music Generation
3
+ # Usage: ./create-music.sh --op create --style "lo-fi" --prompt "chill beats"
4
+
5
+ set -e
6
+
7
+ MUAPI_BASE="https://api.muapi.ai/api/v1"
8
+
9
+ OP="create"
10
+ STYLE=""
11
+ PROMPT=""
12
+ SUNO_MODEL="V5"
13
+ AUDIO_URL=""
14
+ AUDIO_FILE=""
15
+ VIDEO_URL=""
16
+ VIDEO_FILE=""
17
+ DURATION=10
18
+ ASYNC=false
19
+ JSON_ONLY=false
20
+ MAX_WAIT=300
21
+ POLL_INTERVAL=5
22
+
23
+ for arg in "$@"; do
24
+ if [ "$arg" = "--add-key" ]; then
25
+ shift
26
+ KEY_VALUE=""
27
+ if [[ -n "$1" && ! "$1" =~ ^-- ]]; then KEY_VALUE="$1"; fi
28
+ if [ -z "$KEY_VALUE" ]; then echo "Enter your muapi.ai API key:" >&2; read -r KEY_VALUE; fi
29
+ if [ -n "$KEY_VALUE" ]; then
30
+ grep -v "^MUAPI_KEY=" .env > .env.tmp 2>/dev/null || true
31
+ mv .env.tmp .env 2>/dev/null || true
32
+ echo "MUAPI_KEY=$KEY_VALUE" >> .env
33
+ echo "MUAPI_KEY saved to .env" >&2
34
+ fi
35
+ exit 0
36
+ fi
37
+ done
38
+
39
+ if [ -f ".env" ]; then source .env 2>/dev/null || true; fi
40
+
41
+ while [[ $# -gt 0 ]]; do
42
+ case $1 in
43
+ --op) OP="$2"; shift 2 ;;
44
+ --style) STYLE="$2"; shift 2 ;;
45
+ --prompt|-p) PROMPT="$2"; shift 2 ;;
46
+ --suno-model) SUNO_MODEL="$2"; shift 2 ;;
47
+ --audio-url) AUDIO_URL="$2"; shift 2 ;;
48
+ --audio-file) AUDIO_FILE="$2"; shift 2 ;;
49
+ --video-url) VIDEO_URL="$2"; shift 2 ;;
50
+ --video-file) VIDEO_FILE="$2"; shift 2 ;;
51
+ --duration) DURATION="$2"; shift 2 ;;
52
+ --async) ASYNC=true; shift ;;
53
+ --timeout) MAX_WAIT="$2"; shift 2 ;;
54
+ --json) JSON_ONLY=true; shift ;;
55
+ --help|-h)
56
+ echo "muapi.ai Audio & Music Generation" >&2
57
+ echo "" >&2
58
+ echo "Operations (--op):" >&2
59
+ echo " create Suno music creation (default)" >&2
60
+ echo " remix Suno remix (requires --audio-url)" >&2
61
+ echo " extend Suno extend (requires --audio-url)" >&2
62
+ echo " text-to-audio MMAudio from text prompt" >&2
63
+ echo " video-to-audio MMAudio from video (requires --video-url)" >&2
64
+ echo "" >&2
65
+ echo "Examples:" >&2
66
+ echo " bash create-music.sh --style \"lo-fi hip hop\" --prompt \"chill beats\"" >&2
67
+ echo " bash create-music.sh --op text-to-audio --prompt \"thunderstorm\" --duration 15" >&2
68
+ echo " bash create-music.sh --op video-to-audio --video-url URL --prompt \"epic score\"" >&2
69
+ echo "" >&2
70
+ echo "File Inputs:" >&2
71
+ echo " --audio-file Local audio file for remix/extend" >&2
72
+ echo " --video-file Local video file for video-to-audio" >&2
73
+ exit 0 ;;
74
+ *) shift ;;
75
+ esac
76
+ done
77
+
78
+ if [ -z "$MUAPI_KEY" ]; then echo "Error: MUAPI_KEY not set" >&2; exit 1; fi
79
+
80
+ HEADERS=(-H "x-api-key: $MUAPI_KEY" -H "Content-Type: application/json")
81
+ PROMPT_JSON=$(echo "${PROMPT:-}" | python3 -c 'import json,sys; print(json.dumps(sys.stdin.read().rstrip()))')
82
+ STYLE_JSON=$(echo "${STYLE:-}" | python3 -c 'import json,sys; print(json.dumps(sys.stdin.read().rstrip()))')
83
+
84
+ # Auto-upload local files
85
+ upload_file() {
86
+ local FPATH="$1"
87
+ if [ ! -f "$FPATH" ]; then echo "Error: File not found: $FPATH" >&2; exit 1; fi
88
+ [ "$JSON_ONLY" = false ] && echo "Uploading $(basename "$FPATH")..." >&2
89
+ local RESP=$(curl -s -X POST "${MUAPI_BASE}/upload_file" -H "x-api-key: $MUAPI_KEY" -F "file=@${FPATH}")
90
+ local URL=$(echo "$RESP" | jq -r '.url // empty')
91
+ if [ -z "$URL" ]; then
92
+ local ERR=$(echo "$RESP" | jq -r '.error // .detail // "Upload failed"')
93
+ echo "Error: $ERR" >&2; exit 1
94
+ fi
95
+ echo "$URL"
96
+ }
97
+
98
+ if [ -n "$AUDIO_FILE" ]; then AUDIO_URL=$(upload_file "$AUDIO_FILE"); fi
99
+ if [ -n "$VIDEO_FILE" ]; then VIDEO_URL=$(upload_file "$VIDEO_FILE"); fi
100
+
101
+ case $OP in
102
+ create)
103
+ if [ -z "$STYLE" ]; then echo "Error: --style is required for create" >&2; exit 1; fi
104
+ ENDPOINT="suno-create-music"
105
+ PAYLOAD="{\"style\": $STYLE_JSON, \"prompt\": $PROMPT_JSON, \"model\": \"$SUNO_MODEL\"}" ;;
106
+ remix)
107
+ if [ -z "$AUDIO_URL" ]; then echo "Error: --audio-url is required for remix" >&2; exit 1; fi
108
+ AUDIO_CLEAN=$(echo "$AUDIO_URL" | tr -d '"')
109
+ ENDPOINT="suno-remix-music"
110
+ PAYLOAD="{\"audio_url\": \"$AUDIO_CLEAN\", \"style\": $STYLE_JSON, \"prompt\": $PROMPT_JSON, \"model\": \"$SUNO_MODEL\"}" ;;
111
+ extend)
112
+ if [ -z "$AUDIO_URL" ]; then echo "Error: --audio-url is required for extend" >&2; exit 1; fi
113
+ AUDIO_CLEAN=$(echo "$AUDIO_URL" | tr -d '"')
114
+ ENDPOINT="suno-extend-music"
115
+ PAYLOAD="{\"audio_url\": \"$AUDIO_CLEAN\", \"prompt\": $PROMPT_JSON, \"model\": \"$SUNO_MODEL\"}" ;;
116
+ text-to-audio)
117
+ if [ -z "$PROMPT" ]; then echo "Error: --prompt is required for text-to-audio" >&2; exit 1; fi
118
+ ENDPOINT="mmaudio-v2/text-to-audio"
119
+ PAYLOAD="{\"prompt\": $PROMPT_JSON, \"duration\": $DURATION}" ;;
120
+ video-to-audio)
121
+ if [ -z "$VIDEO_URL" ]; then echo "Error: --video-url is required for video-to-audio" >&2; exit 1; fi
122
+ VIDEO_CLEAN=$(echo "$VIDEO_URL" | tr -d '"')
123
+ ENDPOINT="mmaudio-v2/video-to-video"
124
+ PAYLOAD="{\"video_url\": \"$VIDEO_CLEAN\", \"prompt\": $PROMPT_JSON}" ;;
125
+ *)
126
+ echo "Error: Unknown operation '$OP'" >&2
127
+ echo "Valid: create, remix, extend, text-to-audio, video-to-audio" >&2
128
+ exit 1 ;;
129
+ esac
130
+
131
+ [ "$JSON_ONLY" = false ] && echo "Submitting $OP to $ENDPOINT..." >&2
132
+
133
+ SUBMIT=$(curl -s -X POST "${MUAPI_BASE}/${ENDPOINT}" "${HEADERS[@]}" -d "$PAYLOAD")
134
+
135
+ if echo "$SUBMIT" | grep -q '"error"\|"detail"'; then
136
+ ERR=$(echo "$SUBMIT" | grep -o '"detail":"[^"]*"' | head -1 | cut -d'"' -f4)
137
+ [ -z "$ERR" ] && ERR=$(echo "$SUBMIT" | grep -o '"error":"[^"]*"' | head -1 | cut -d'"' -f4)
138
+ echo "Error: ${ERR:-$SUBMIT}" >&2; exit 1
139
+ fi
140
+
141
+ REQUEST_ID=$(echo "$SUBMIT" | grep -oE '"request_id"[[:space:]]*:[[:space:]]*"[^"]*"' | sed 's/.*: *"//' | sed 's/"$//')
142
+ if [ -z "$REQUEST_ID" ]; then echo "Error: No request_id" >&2; echo "$SUBMIT" >&2; exit 1; fi
143
+ [ "$JSON_ONLY" = false ] && echo "Request ID: $REQUEST_ID" >&2
144
+
145
+ if [ "$ASYNC" = true ]; then
146
+ [ "$JSON_ONLY" = false ] && echo "Music generation takes 30–90s. Check: bash check-result.sh --id \"$REQUEST_ID\"" >&2
147
+ echo "$SUBMIT"; exit 0
148
+ fi
149
+
150
+ [ "$JSON_ONLY" = false ] && echo "Generating (30–90 seconds)..." >&2
151
+ ELAPSED=0; LAST_STATUS=""
152
+ while [ $ELAPSED -lt $MAX_WAIT ]; do
153
+ sleep $POLL_INTERVAL; ELAPSED=$((ELAPSED + POLL_INTERVAL))
154
+ RESULT=$(curl -s -X GET "${MUAPI_BASE}/predictions/${REQUEST_ID}/result" "${HEADERS[@]}")
155
+ STATUS=$(echo "$RESULT" | grep -oE '"status"[[:space:]]*:[[:space:]]*"[^"]*"' | sed 's/.*: *"//' | sed 's/"$//')
156
+ if [ "$STATUS" != "$LAST_STATUS" ] && [ "$JSON_ONLY" = false ]; then echo "Status: $STATUS (${ELAPSED}s)" >&2; LAST_STATUS="$STATUS"; fi
157
+ case $STATUS in
158
+ completed)
159
+ [ "$JSON_ONLY" = false ] && echo "" >&2
160
+ [ "$JSON_ONLY" = false ] && echo "Audio generation complete!" >&2
161
+ URL=$(echo "$RESULT" | grep -o '"outputs":\[[^]]*\]' | grep -o '"[^"]*\.\(mp3\|wav\|mp4\)"' | head -1 | tr -d '"')
162
+ [ -n "$URL" ] && [ "$JSON_ONLY" = false ] && echo "Audio URL: $URL" >&2
163
+ echo "$RESULT"; exit 0 ;;
164
+ failed)
165
+ ERR=$(echo "$RESULT" | grep -o '"error":"[^"]*"' | head -1 | cut -d'"' -f4)
166
+ echo "Error: ${ERR:-Generation failed}" >&2; echo "$RESULT"; exit 1 ;;
167
+ esac
168
+ done
169
+ echo "Error: Timeout after ${MAX_WAIT}s — Request ID: $REQUEST_ID" >&2; exit 1
@@ -0,0 +1,161 @@
1
+ #!/bin/bash
2
+ # muapi.ai Text-to-Image Generation
3
+ # Usage: ./generate-image.sh --prompt "..." [--model MODEL] [options]
4
+
5
+ set -e
6
+
7
+ MUAPI_BASE="https://api.muapi.ai/api/v1"
8
+ SCHEMA_FILE="$(dirname "$0")/schema_data.json"
9
+
10
+ # Defaults
11
+ PROMPT=""
12
+ IMAGE_URL=""
13
+ MODEL="flux-dev"
14
+ WIDTH=1024
15
+ HEIGHT=1024
16
+ ASPECT_RATIO=""
17
+ RESOLUTION="1k"
18
+ NUM_IMAGES=1
19
+ ASYNC=false
20
+ VIEW=false
21
+ JSON_ONLY=false
22
+ MAX_WAIT=300
23
+ POLL_INTERVAL=3
24
+
25
+ # Check for .env and setup
26
+ if [ -f ".env" ]; then source .env 2>/dev/null || true; fi
27
+
28
+ # Parse arguments
29
+ while [[ $# -gt 0 ]]; do
30
+ case $1 in
31
+ --prompt|-p) PROMPT="$2"; shift 2 ;;
32
+ --image-url) IMAGE_URL="$2"; shift 2 ;;
33
+ --model|-m) MODEL="$2"; shift 2 ;;
34
+ --width) WIDTH="$2"; shift 2 ;;
35
+ --height) HEIGHT="$2"; shift 2 ;;
36
+ --aspect-ratio) ASPECT_RATIO="$2"; shift 2 ;;
37
+ --resolution) RESOLUTION="$2"; shift 2 ;;
38
+ --num-images) NUM_IMAGES="$2"; shift 2 ;;
39
+ --async) ASYNC=true; shift ;;
40
+ --view) VIEW=true; shift ;;
41
+ --timeout) MAX_WAIT="$2"; shift 2 ;;
42
+ --json) JSON_ONLY=true; shift ;;
43
+ --help|-h)
44
+ echo "muapi.ai Text-to-Image" >&2
45
+ echo "" >&2
46
+ echo "Usage: ./generate-image.sh --prompt \"...\" [options]" >&2
47
+ echo "" >&2
48
+ echo "Options:" >&2
49
+ echo " --prompt, -p Text description (required)" >&2
50
+ echo " --image-url Reference image URL for img2img" >&2
51
+ echo " --model, -m Model name (default: flux-dev)" >&2
52
+ echo " --aspect-ratio 1:1, 16:9, 9:16, 4:3, 3:4, 21:9" >&2
53
+ echo " --resolution 1k, 2k, 4k (for supported models)" >&2
54
+ echo " --width/--height Manual pixel override" >&2
55
+ echo " --async Return request_id immediately" >&2
56
+ echo " --view Download and open image (macOS only)" >&2
57
+ echo " --json Raw JSON output only" >&2
58
+ exit 0 ;;
59
+ *) shift ;;
60
+ esac
61
+ done
62
+
63
+ if [ -z "$MUAPI_KEY" ]; then echo "Error: MUAPI_KEY not set" >&2; exit 1; fi
64
+ if [ -z "$PROMPT" ]; then echo "Error: --prompt is required" >&2; exit 1; fi
65
+
66
+ # --- DYNAMIC SCHEMA PARSING ---
67
+ if [ ! -f "$SCHEMA_FILE" ]; then echo "Error: schema_data.json not found at $SCHEMA_FILE" >&2; exit 1; fi
68
+
69
+ MODEL_DATA=$(jq -r ".[] | select(.name == \"$MODEL\")" "$SCHEMA_FILE")
70
+ if [ -z "$MODEL_DATA" ]; then
71
+ echo "Error: Model '$MODEL' not found in schema_data.json" >&2
72
+ echo "Available models: $(jq -r '.[] | .name' "$SCHEMA_FILE" | head -10)..." >&2
73
+ exit 1
74
+ fi
75
+
76
+ ENDPOINT=$(echo "$MODEL_DATA" | jq -r '.input_schema.schemas.input_data.endpoint_url')
77
+ PARAMS=$(echo "$MODEL_DATA" | jq -r '.input_schema.schemas.input_data.properties | keys[]')
78
+
79
+ # Auto-map aspect ratio to width/height if model doesn't support aspect_ratio field
80
+ SUPPORTS_AR=$(echo "$PARAMS" | grep -w "aspect_ratio" || true)
81
+ if [ -n "$ASPECT_RATIO" ] && [ -z "$SUPPORTS_AR" ]; then
82
+ case $ASPECT_RATIO in
83
+ "1:1") WIDTH=1024; HEIGHT=1024 ;;
84
+ "16:9") WIDTH=1344; HEIGHT=768 ;;
85
+ "9:16") WIDTH=768; HEIGHT=1344 ;;
86
+ "4:3") WIDTH=1152; HEIGHT=896 ;;
87
+ "3:4") WIDTH=896; HEIGHT=1152 ;;
88
+ "21:9") WIDTH=1536; HEIGHT=640 ;;
89
+ esac
90
+ fi
91
+
92
+ # Build Payload Dynamically
93
+ PROMPT_JSON=$(echo "$PROMPT" | python3 -c 'import json,sys; print(json.dumps(sys.stdin.read().rstrip()))')
94
+ PAYLOAD="{\"prompt\": $PROMPT_JSON"
95
+
96
+ # Add string parameters
97
+ if [ -n "$IMAGE_URL" ]; then
98
+ if echo "$PARAMS" | grep -w "image_url" >/dev/null; then
99
+ PAYLOAD="$PAYLOAD, \"image_url\": \"$IMAGE_URL\""
100
+ elif echo "$PARAMS" | grep -w "images_list" >/dev/null; then
101
+ PAYLOAD="$PAYLOAD, \"images_list\": [\"$IMAGE_URL\"]"
102
+ fi
103
+ fi
104
+
105
+ # Add numeric parameters
106
+ if echo "$PARAMS" | grep -w "num_images" >/dev/null; then PAYLOAD="$PAYLOAD, \"num_images\": $NUM_IMAGES"; fi
107
+ if echo "$PARAMS" | grep -w "width" >/dev/null && [ -z "$SUPPORTS_AR" ]; then PAYLOAD="$PAYLOAD, \"width\": $WIDTH, \"height\": $HEIGHT"; fi
108
+
109
+ # Add other string parameters
110
+ if [ -n "$SUPPORTS_AR" ]; then PAYLOAD="$PAYLOAD, \"aspect_ratio\": \"${ASPECT_RATIO:-1:1}\""; fi
111
+ if echo "$PARAMS" | grep -w "resolution" >/dev/null; then PAYLOAD="$PAYLOAD, \"resolution\": \"$RESOLUTION\""; fi
112
+
113
+ PAYLOAD="$PAYLOAD}"
114
+
115
+ # --- EXECUTION ---
116
+ HEADERS=(-H "x-api-key: $MUAPI_KEY" -H "Content-Type: application/json")
117
+ [ "$JSON_ONLY" = false ] && echo "Submitting to $ENDPOINT (Model: $MODEL)..." >&2
118
+
119
+ SUBMIT=$(curl -s -X POST "${MUAPI_BASE}/${ENDPOINT}" "${HEADERS[@]}" -d "$PAYLOAD")
120
+
121
+ if echo "$SUBMIT" | grep -q '"error"\|"detail"'; then
122
+ ERR=$(echo "$SUBMIT" | jq -r '.error // .detail // empty')
123
+ echo "Error: ${ERR:-$SUBMIT}" >&2; exit 1
124
+ fi
125
+
126
+ REQUEST_ID=$(echo "$SUBMIT" | jq -r '.request_id')
127
+ [ "$JSON_ONLY" = false ] && echo "Request ID: $REQUEST_ID" >&2
128
+
129
+ if [ "$ASYNC" = true ]; then echo "$SUBMIT"; exit 0; fi
130
+
131
+ # Polling
132
+ [ "$JSON_ONLY" = false ] && echo "Waiting for completion..." >&2
133
+ ELAPSED=0
134
+ while [ $ELAPSED -lt $MAX_WAIT ]; do
135
+ sleep $POLL_INTERVAL
136
+ ELAPSED=$((ELAPSED + POLL_INTERVAL))
137
+ RESULT=$(curl -s -X GET "${MUAPI_BASE}/predictions/${REQUEST_ID}/result" "${HEADERS[@]}")
138
+ STATUS=$(echo "$RESULT" | jq -r '.status')
139
+ if [ "$STATUS" = "completed" ]; then
140
+ URL=$(echo "$RESULT" | jq -r '.outputs[0]')
141
+ [ "$JSON_ONLY" = false ] && echo "Success! URL: $URL" >&2
142
+
143
+ if [ "$VIEW" = true ]; then
144
+ EXT="${URL##*.}"
145
+ [ -z "$EXT" ] || [[ "$EXT" == http* ]] && EXT="jpg"
146
+ OUTPUT_DIR="${PWD}/media_outputs"
147
+ mkdir -p "$OUTPUT_DIR"
148
+ TEMP_FILE="$OUTPUT_DIR/muapi_$(date +%s).$EXT"
149
+ [ "$JSON_ONLY" = false ] && echo "Downloading to $TEMP_FILE..." >&2
150
+ curl -s -o "$TEMP_FILE" "$URL"
151
+ if [[ "$OSTYPE" == "darwin"* ]]; then
152
+ open "$TEMP_FILE"
153
+ fi
154
+ fi
155
+
156
+ echo "$RESULT"; exit 0
157
+ elif [ "$STATUS" = "failed" ]; then
158
+ echo "Error: $(echo "$RESULT" | jq -r '.output.error')" >&2; exit 1
159
+ fi
160
+ done
161
+ exit 1
@@ -0,0 +1,137 @@
1
+ #!/bin/bash
2
+ # muapi.ai Text-to-Video Generation
3
+ # Usage: ./generate-video.sh --prompt "..." [--model MODEL] [options]
4
+
5
+ set -e
6
+
7
+ MUAPI_BASE="https://api.muapi.ai/api/v1"
8
+ SCHEMA_FILE="$(dirname "$0")/schema_data.json"
9
+
10
+ # Defaults
11
+ PROMPT=""
12
+ MODEL="minimax-pro"
13
+ ASPECT_RATIO="16:9"
14
+ DURATION=5
15
+ GENERATE_AUDIO=true
16
+ ASYNC=false
17
+ VIEW=false
18
+ JSON_ONLY=false
19
+ MAX_WAIT=600
20
+ POLL_INTERVAL=5
21
+ ACTION="generate"
22
+ REQUEST_ID=""
23
+
24
+ # Check for .env
25
+ if [ -f ".env" ]; then source .env 2>/dev/null || true; fi
26
+
27
+ # Parse arguments
28
+ while [[ $# -gt 0 ]]; do
29
+ case $1 in
30
+ --prompt|-p) PROMPT="$2"; shift 2 ;;
31
+ --model|-m) MODEL="$2"; shift 2 ;;
32
+ --aspect-ratio) ASPECT_RATIO="$2"; shift 2 ;;
33
+ --duration) DURATION="$2"; shift 2 ;;
34
+ --no-audio) GENERATE_AUDIO=false; shift ;;
35
+ --async) ASYNC=true; shift ;;
36
+ --view) VIEW=true; shift ;;
37
+ --status) ACTION="status"; REQUEST_ID="$2"; shift 2 ;;
38
+ --result) ACTION="result"; REQUEST_ID="$2"; shift 2 ;;
39
+ --timeout) MAX_WAIT="$2"; shift 2 ;;
40
+ --json) JSON_ONLY=true; shift ;;
41
+ --help|-h)
42
+ echo "muapi.ai Text-to-Video" >&2
43
+ echo "" >&2
44
+ echo "Usage: ./generate-video.sh --prompt \"...\" [options]" >&2
45
+ echo "" >&2
46
+ echo "Options:" >&2
47
+ echo " --prompt, -p Text description (required)" >&2
48
+ echo " --model, -m Model name (default: minimax-pro)" >&2
49
+ echo " --aspect-ratio 16:9, 9:16, 1:1" >&2
50
+ echo " --duration Length in seconds (3-15)" >&2
51
+ echo " --no-audio Disable audio generation" >&2
52
+ echo " --async Return request_id immediately" >&2
53
+ echo " --view Download and open video (macOS only)" >&2
54
+ echo " --status ID Check status of a request" >&2
55
+ echo " --json Raw JSON output only" >&2
56
+ exit 0 ;;
57
+ *) shift ;;
58
+ esac
59
+ done
60
+
61
+ if [ -z "$MUAPI_KEY" ]; then echo "Error: MUAPI_KEY not set" >&2; exit 1; fi
62
+
63
+ HEADERS=(-H "x-api-key: $MUAPI_KEY" -H "Content-Type: application/json")
64
+
65
+ # Handle status/result actions
66
+ if [ "$ACTION" = "status" ] || [ "$ACTION" = "result" ]; then
67
+ if [ -z "$REQUEST_ID" ]; then echo "Error: Request ID required" >&2; exit 1; fi
68
+ RESULT=$(curl -s -X GET "${MUAPI_BASE}/predictions/${REQUEST_ID}/result" "${HEADERS[@]}")
69
+ echo "$RESULT"; exit 0
70
+ fi
71
+
72
+ if [ -z "$PROMPT" ]; then echo "Error: --prompt is required" >&2; exit 1; fi
73
+
74
+ # --- DYNAMIC SCHEMA PARSING ---
75
+ if [ ! -f "$SCHEMA_FILE" ]; then echo "Error: schema_data.json not found" >&2; exit 1; fi
76
+
77
+ MODEL_DATA=$(jq -r ".[] | select(.name == \"$MODEL\")" "$SCHEMA_FILE")
78
+ if [ -z "$MODEL_DATA" ]; then
79
+ echo "Error: Model '$MODEL' not found in schema" >&2; exit 1
80
+ fi
81
+
82
+ ENDPOINT=$(echo "$MODEL_DATA" | jq -r '.input_schema.schemas.input_data.endpoint_url')
83
+ PARAMS=$(echo "$MODEL_DATA" | jq -r '.input_schema.schemas.input_data.properties | keys[]')
84
+
85
+ # Build Payload
86
+ PROMPT_JSON=$(echo "$PROMPT" | python3 -c 'import json,sys; print(json.dumps(sys.stdin.read().rstrip()))')
87
+ PAYLOAD="{\"prompt\": $PROMPT_JSON"
88
+
89
+ if echo "$PARAMS" | grep -w "aspect_ratio" >/dev/null; then PAYLOAD="$PAYLOAD, \"aspect_ratio\": \"$ASPECT_RATIO\""; fi
90
+ if echo "$PARAMS" | grep -w "duration" >/dev/null; then PAYLOAD="$PAYLOAD, \"duration\": $DURATION"; fi
91
+ if echo "$PARAMS" | grep -w "generate_audio" >/dev/null; then PAYLOAD="$PAYLOAD, \"generate_audio\": $GENERATE_AUDIO"; fi
92
+
93
+ PAYLOAD="$PAYLOAD}"
94
+
95
+ # --- EXECUTION ---
96
+ [ "$JSON_ONLY" = false ] && echo "Submitting to $ENDPOINT..." >&2
97
+ SUBMIT=$(curl -s -X POST "${MUAPI_BASE}/${ENDPOINT}" "${HEADERS[@]}" -d "$PAYLOAD")
98
+
99
+ if echo "$SUBMIT" | grep -q '"error"\|"detail"'; then
100
+ ERR=$(echo "$SUBMIT" | jq -r '.error // .detail // empty')
101
+ echo "Error: ${ERR:-$SUBMIT}" >&2; exit 1
102
+ fi
103
+
104
+ REQUEST_ID=$(echo "$SUBMIT" | jq -r '.request_id')
105
+ if [ "$ASYNC" = true ]; then echo "$SUBMIT"; exit 0; fi
106
+
107
+ # Polling
108
+ [ "$JSON_ONLY" = false ] && echo "Waiting for completion (Request ID: $REQUEST_ID)..." >&2
109
+ ELAPSED=0
110
+ while [ $ELAPSED -lt $MAX_WAIT ]; do
111
+ sleep $POLL_INTERVAL
112
+ ELAPSED=$((ELAPSED + POLL_INTERVAL))
113
+ RESULT=$(curl -s -X GET "${MUAPI_BASE}/predictions/${REQUEST_ID}/result" "${HEADERS[@]}")
114
+ STATUS=$(echo "$RESULT" | jq -r '.status')
115
+ if [ "$STATUS" = "completed" ]; then
116
+ URL=$(echo "$RESULT" | jq -r '.outputs[0]')
117
+ [ "$JSON_ONLY" = false ] && echo "Success! URL: $URL" >&2
118
+
119
+ if [ "$VIEW" = true ]; then
120
+ EXT="${URL##*.}"
121
+ [ -z "$EXT" ] || [[ "$EXT" == http* ]] && EXT="mp4"
122
+ OUTPUT_DIR="${PWD}/media_outputs"
123
+ mkdir -p "$OUTPUT_DIR"
124
+ TEMP_FILE="$OUTPUT_DIR/muapi_$(date +%s).$EXT"
125
+ [ "$JSON_ONLY" = false ] && echo "Downloading to $TEMP_FILE..." >&2
126
+ curl -s -o "$TEMP_FILE" "$URL"
127
+ if [[ "$OSTYPE" == "darwin"* ]]; then
128
+ open "$TEMP_FILE"
129
+ fi
130
+ fi
131
+
132
+ echo "$RESULT"; exit 0
133
+ elif [ "$STATUS" = "failed" ]; then
134
+ echo "Error: $(echo "$RESULT" | jq -r '.output.error')" >&2; exit 1
135
+ fi
136
+ done
137
+ exit 1