@crievo/omni 0.0.0-stage → 0.1.1

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 (708) hide show
  1. package/.env.example +41 -0
  2. package/README.md +2 -2
  3. package/bin/omni.mjs +18 -0
  4. package/docs/onboarding/clone-voice.png +0 -0
  5. package/docs/onboarding/getting-started.png +0 -0
  6. package/docs/onboarding/new-video.png +0 -0
  7. package/docs/onboarding/providers.png +0 -0
  8. package/docs/onboarding/publish.png +0 -0
  9. package/docs/onboarding/references.png +0 -0
  10. package/docs/onboarding.md +212 -0
  11. package/omnivideo.config.example.json +437 -0
  12. package/package.json +40 -4
  13. package/reference/captions.md +156 -0
  14. package/reference/carousel-contract.md +91 -0
  15. package/reference/cloud.md +96 -0
  16. package/reference/learnings.md +792 -0
  17. package/reference/omnichat.md +305 -0
  18. package/reference/premiere-mcp.md +91 -0
  19. package/reference/publish.md +305 -0
  20. package/reference/scenes-contract.md +109 -0
  21. package/reference/studio.md +666 -0
  22. package/reference/voicestudio.md +81 -0
  23. package/reference/writing-for-voice.md +67 -0
  24. package/requirements.txt +3 -0
  25. package/studio/api/app.ts +87 -0
  26. package/studio/api/lib/errors.ts +33 -0
  27. package/studio/api/lib/files.ts +41 -0
  28. package/studio/api/lib/hono.ts +9 -0
  29. package/studio/api/lib/result.ts +14 -0
  30. package/studio/api/lib/validate.ts +31 -0
  31. package/studio/api/lib/video.ts +10 -0
  32. package/studio/api/middleware/json-charset.ts +11 -0
  33. package/studio/api/middleware/local-only.ts +32 -0
  34. package/studio/api/middleware/no-timeout.ts +10 -0
  35. package/studio/api/routes/admin.ts +18 -0
  36. package/studio/api/routes/agent-cascade.ts +100 -0
  37. package/studio/api/routes/agent-history.ts +23 -0
  38. package/studio/api/routes/agent.ts +162 -0
  39. package/studio/api/routes/analytics.ts +31 -0
  40. package/studio/api/routes/approval.ts +60 -0
  41. package/studio/api/routes/archive.ts +12 -0
  42. package/studio/api/routes/captions.ts +28 -0
  43. package/studio/api/routes/carousel.ts +38 -0
  44. package/studio/api/routes/clone.ts +27 -0
  45. package/studio/api/routes/create.ts +19 -0
  46. package/studio/api/routes/events.ts +11 -0
  47. package/studio/api/routes/export.ts +14 -0
  48. package/studio/api/routes/media.ts +30 -0
  49. package/studio/api/routes/omnichat.ts +113 -0
  50. package/studio/api/routes/onboarding.ts +14 -0
  51. package/studio/api/routes/publish.ts +40 -0
  52. package/studio/api/routes/queue.ts +14 -0
  53. package/studio/api/routes/references.ts +40 -0
  54. package/studio/api/routes/runner.ts +17 -0
  55. package/studio/api/routes/schedule.ts +47 -0
  56. package/studio/api/routes/services.ts +11 -0
  57. package/studio/api/routes/sessions.ts +27 -0
  58. package/studio/api/routes/settings.ts +102 -0
  59. package/studio/api/routes/sound.ts +45 -0
  60. package/studio/api/routes/thumbnail.ts +18 -0
  61. package/studio/api/routes/usage.ts +13 -0
  62. package/studio/api/routes/videos.ts +41 -0
  63. package/studio/api/routes/voices.ts +71 -0
  64. package/studio/api/services/admin.ts +113 -0
  65. package/studio/api/services/agent-cascade.ts +975 -0
  66. package/studio/api/services/agent-claude.ts +47 -0
  67. package/studio/api/services/agent-history.ts +103 -0
  68. package/studio/api/services/agent-persona.ts +77 -0
  69. package/studio/api/services/agent-tools.ts +2237 -0
  70. package/studio/api/services/agent-ui-tools.ts +259 -0
  71. package/studio/api/services/agent-wait.ts +32 -0
  72. package/studio/api/services/agent.ts +553 -0
  73. package/studio/api/services/analytics.ts +92 -0
  74. package/studio/api/services/approval.ts +134 -0
  75. package/studio/api/services/archive.ts +38 -0
  76. package/studio/api/services/captions.ts +268 -0
  77. package/studio/api/services/carousel.ts +206 -0
  78. package/studio/api/services/classify.ts +196 -0
  79. package/studio/api/services/clone-phrases.ts +75 -0
  80. package/studio/api/services/clone.ts +722 -0
  81. package/studio/api/services/create.ts +421 -0
  82. package/studio/api/services/events.ts +215 -0
  83. package/studio/api/services/media.ts +32 -0
  84. package/studio/api/services/omnichat.ts +624 -0
  85. package/studio/api/services/onboarding.ts +77 -0
  86. package/studio/api/services/publish.ts +287 -0
  87. package/studio/api/services/queue.ts +150 -0
  88. package/studio/api/services/references.ts +269 -0
  89. package/studio/api/services/root.ts +60 -0
  90. package/studio/api/services/services.ts +114 -0
  91. package/studio/api/services/sessions.ts +1007 -0
  92. package/studio/api/services/settings.ts +983 -0
  93. package/studio/api/services/sound.ts +311 -0
  94. package/studio/api/services/thumbnail.ts +133 -0
  95. package/studio/api/services/usage.ts +27 -0
  96. package/studio/api/services/videos.ts +418 -0
  97. package/studio/api/services/voice-pause.ts +98 -0
  98. package/studio/api/services/voices.ts +324 -0
  99. package/studio/runner/runner.ts +244 -0
  100. package/studio/shared/omni-actions.ts +68 -0
  101. package/studio/shared/omni-admin.ts +52 -0
  102. package/studio/shared/omni-farewell.ts +48 -0
  103. package/studio/shared/omni-hotword.ts +20 -0
  104. package/studio/shared/omni-screens.ts +228 -0
  105. package/studio/shared/schemas/admin.ts +15 -0
  106. package/studio/shared/schemas/agent-cascade.ts +58 -0
  107. package/studio/shared/schemas/agent-history.ts +73 -0
  108. package/studio/shared/schemas/agent.ts +50 -0
  109. package/studio/shared/schemas/analytics.ts +6 -0
  110. package/studio/shared/schemas/approval.ts +22 -0
  111. package/studio/shared/schemas/captions.ts +19 -0
  112. package/studio/shared/schemas/carousel.ts +26 -0
  113. package/studio/shared/schemas/clone.ts +40 -0
  114. package/studio/shared/schemas/common.ts +16 -0
  115. package/studio/shared/schemas/omnichat.ts +54 -0
  116. package/studio/shared/schemas/onboarding.ts +5 -0
  117. package/studio/shared/schemas/publish.ts +45 -0
  118. package/studio/shared/schemas/references.ts +20 -0
  119. package/studio/shared/schemas/settings.ts +82 -0
  120. package/studio/shared/schemas/sound.ts +22 -0
  121. package/studio/shared/schemas/videos.ts +38 -0
  122. package/studio/shared/schemas/voices.ts +23 -0
  123. package/studio/shared/types/api.ts +1290 -0
  124. package/studio/studio.ts +148 -0
  125. package/studio/tsconfig.json +15 -0
  126. package/studio/web/assets/logos/cartesia.svg +4 -0
  127. package/studio/web/assets/logos/elevenlabs.svg +12 -0
  128. package/studio/web/assets/logos/fish.svg +24 -0
  129. package/studio/web/assets/logos/omni-black.png +0 -0
  130. package/studio/web/assets/logos/omni-white.png +0 -0
  131. package/studio/web/assets/logos/voicestudio.svg +21 -0
  132. package/studio/web/components/AgentMark.tsx +7 -0
  133. package/studio/web/components/AgentWalking.tsx +11 -0
  134. package/studio/web/components/ApiKeyField.tsx +104 -0
  135. package/studio/web/components/AppShell.tsx +64 -0
  136. package/studio/web/components/ApprovalNotice.tsx +65 -0
  137. package/studio/web/components/AvatarGroupIcon.tsx +22 -0
  138. package/studio/web/components/AvatarNameField.tsx +86 -0
  139. package/studio/web/components/AvatarPicker.tsx +84 -0
  140. package/studio/web/components/BrandLogo.tsx +16 -0
  141. package/studio/web/components/CartesiaPlanSetting.tsx +90 -0
  142. package/studio/web/components/ClaudeWalking.tsx +32 -0
  143. package/studio/web/components/CloneVoiceDialog/GuidedScript.tsx +39 -0
  144. package/studio/web/components/CloneVoiceDialog/LanguageBar.tsx +37 -0
  145. package/studio/web/components/CloneVoiceDialog/LevelMeter.tsx +31 -0
  146. package/studio/web/components/CloneVoiceDialog/ProviderChoice.tsx +81 -0
  147. package/studio/web/components/CloneVoiceDialog/QualityPanel.tsx +62 -0
  148. package/studio/web/components/CloneVoiceDialog/RecordStep.tsx +50 -0
  149. package/studio/web/components/CloneVoiceDialog/RecorderBar.tsx +79 -0
  150. package/studio/web/components/CloneVoiceDialog/RedoSummary.tsx +54 -0
  151. package/studio/web/components/CloneVoiceDialog/SaveStep.tsx +91 -0
  152. package/studio/web/components/CloneVoiceDialog/SourceBar.tsx +30 -0
  153. package/studio/web/components/CloneVoiceDialog/index.tsx +141 -0
  154. package/studio/web/components/CloneVoiceDialog/types.ts +28 -0
  155. package/studio/web/components/CloneVoiceDialog/useCloneVoice.ts +528 -0
  156. package/studio/web/components/ConnectionSignals.tsx +51 -0
  157. package/studio/web/components/EditVoiceDialog/EditVoiceFooter.tsx +72 -0
  158. package/studio/web/components/EditVoiceDialog/ProviderCards.tsx +81 -0
  159. package/studio/web/components/EditVoiceDialog/index.tsx +256 -0
  160. package/studio/web/components/ErrorBanner.tsx +115 -0
  161. package/studio/web/components/FinishedTask.tsx +41 -0
  162. package/studio/web/components/FishModelSetting.tsx +69 -0
  163. package/studio/web/components/FishPriceSetting.tsx +44 -0
  164. package/studio/web/components/HumanBanner.tsx +64 -0
  165. package/studio/web/components/Lightbox.tsx +41 -0
  166. package/studio/web/components/LogStream.tsx +42 -0
  167. package/studio/web/components/Markdown.tsx +21 -0
  168. package/studio/web/components/MissingDmsPanel/BatchSend.tsx +137 -0
  169. package/studio/web/components/MissingDmsPanel/CommentCard.tsx +168 -0
  170. package/studio/web/components/MissingDmsPanel/CommentFeed.tsx +45 -0
  171. package/studio/web/components/MissingDmsPanel/DmBubble.tsx +38 -0
  172. package/studio/web/components/MissingDmsPanel/ReplyComposer.tsx +63 -0
  173. package/studio/web/components/MissingDmsPanel/index.tsx +98 -0
  174. package/studio/web/components/NotFound.tsx +48 -0
  175. package/studio/web/components/Omni/OmniAvatarPicker.tsx +92 -0
  176. package/studio/web/components/Omni/OmniCards.tsx +202 -0
  177. package/studio/web/components/Omni/OmniGlow.tsx +183 -0
  178. package/studio/web/components/Omni/OmniHistory.tsx +119 -0
  179. package/studio/web/components/Omni/OmniHotword.tsx +40 -0
  180. package/studio/web/components/Omni/OmniMicSelect.tsx +92 -0
  181. package/studio/web/components/Omni/OmniVoiceSample.tsx +81 -0
  182. package/studio/web/components/Omni/OmniWidget.tsx +743 -0
  183. package/studio/web/components/Omni/PendingActions.tsx +200 -0
  184. package/studio/web/components/Omni/Transcript.tsx +127 -0
  185. package/studio/web/components/OmnichatAccountStatus.tsx +87 -0
  186. package/studio/web/components/OmnichatRulePanel/RuleConfig.tsx +150 -0
  187. package/studio/web/components/OmnichatRulePanel/RuleDryRun.tsx +15 -0
  188. package/studio/web/components/OmnichatRulePanel/RuleEnableConfirm.tsx +42 -0
  189. package/studio/web/components/OmnichatRulePanel/RuleSkeleton.tsx +18 -0
  190. package/studio/web/components/OmnichatRulePanel/RuleStatus.tsx +55 -0
  191. package/studio/web/components/OmnichatRulePanel/index.tsx +115 -0
  192. package/studio/web/components/OmnichatRulePanel/rule-steps.ts +67 -0
  193. package/studio/web/components/OmnichatRulePanel/steps/MessageStep.tsx +91 -0
  194. package/studio/web/components/OmnichatRulePanel/steps/RepliesStep.tsx +201 -0
  195. package/studio/web/components/OmnichatRulePanel/steps/TriggerStep.tsx +76 -0
  196. package/studio/web/components/OmnichatRulePanel/steps/types.ts +11 -0
  197. package/studio/web/components/Palette.tsx +17 -0
  198. package/studio/web/components/PlatformCard.tsx +109 -0
  199. package/studio/web/components/PlatformIcon.tsx +19 -0
  200. package/studio/web/components/ProviderCard.tsx +80 -0
  201. package/studio/web/components/ProviderDetail.tsx +367 -0
  202. package/studio/web/components/ProviderLogo.tsx +20 -0
  203. package/studio/web/components/QueuePanel.tsx +77 -0
  204. package/studio/web/components/ReferenceActions.tsx +89 -0
  205. package/studio/web/components/ReferencePicker.tsx +136 -0
  206. package/studio/web/components/ResultMessage.tsx +7 -0
  207. package/studio/web/components/RuleForm.tsx +138 -0
  208. package/studio/web/components/RuleLog.tsx +151 -0
  209. package/studio/web/components/RunningTask.tsx +23 -0
  210. package/studio/web/components/SampleList.tsx +55 -0
  211. package/studio/web/components/SessionPanel.tsx +352 -0
  212. package/studio/web/components/SettingRow.tsx +14 -0
  213. package/studio/web/components/SettingsCategorySkeleton.tsx +25 -0
  214. package/studio/web/components/SidePanel.tsx +77 -0
  215. package/studio/web/components/Sidebar.tsx +289 -0
  216. package/studio/web/components/StageStepper.tsx +87 -0
  217. package/studio/web/components/StudioOffline.tsx +80 -0
  218. package/studio/web/components/TaskName.tsx +17 -0
  219. package/studio/web/components/TopBanners.tsx +30 -0
  220. package/studio/web/components/VideoOmnichatPanel.tsx +287 -0
  221. package/studio/web/components/VoiceAvatar.tsx +33 -0
  222. package/studio/web/components/VoiceCarousel.tsx +196 -0
  223. package/studio/web/components/VoiceCategory.tsx +9 -0
  224. package/studio/web/components/VoiceModal.tsx +39 -0
  225. package/studio/web/components/VoiceProfileCard.tsx +75 -0
  226. package/studio/web/components/VoiceProfilePicker.tsx +107 -0
  227. package/studio/web/components/VoiceProfilesSettings.tsx +150 -0
  228. package/studio/web/components/VoiceProviderCard.tsx +118 -0
  229. package/studio/web/components/VoiceProvidersCard.tsx +26 -0
  230. package/studio/web/components/WaitList.tsx +21 -0
  231. package/studio/web/components/icons.tsx +247 -0
  232. package/studio/web/components/ui/accordion.tsx +47 -0
  233. package/studio/web/components/ui/badge.tsx +18 -0
  234. package/studio/web/components/ui/calendar.tsx +43 -0
  235. package/studio/web/components/ui/chart.tsx +229 -0
  236. package/studio/web/components/ui/checkbox.tsx +26 -0
  237. package/studio/web/components/ui/cx.ts +2 -0
  238. package/studio/web/components/ui/date-time-picker.tsx +84 -0
  239. package/studio/web/components/ui/panel.tsx +23 -0
  240. package/studio/web/components/ui/picker.tsx +58 -0
  241. package/studio/web/components/ui/popover.tsx +24 -0
  242. package/studio/web/components/ui/select.tsx +89 -0
  243. package/studio/web/components/ui/skeleton.tsx +10 -0
  244. package/studio/web/components/ui/slider.tsx +68 -0
  245. package/studio/web/components/ui/switch.tsx +13 -0
  246. package/studio/web/components/ui/tooltip.tsx +59 -0
  247. package/studio/web/hooks/useAccounts.ts +27 -0
  248. package/studio/web/hooks/useAdmin.ts +12 -0
  249. package/studio/web/hooks/useAnalytics.ts +21 -0
  250. package/studio/web/hooks/useAvatarAudioReactive.ts +87 -0
  251. package/studio/web/hooks/useBrowserConnect.ts +48 -0
  252. package/studio/web/hooks/useClonePlan.ts +14 -0
  253. package/studio/web/hooks/useConnected.ts +7 -0
  254. package/studio/web/hooks/useLiveQuery.ts +29 -0
  255. package/studio/web/hooks/useMenuCollapsed.ts +32 -0
  256. package/studio/web/hooks/useMicDevices.ts +53 -0
  257. package/studio/web/hooks/useMissingDms.ts +211 -0
  258. package/studio/web/hooks/useMissingSetupSteps.ts +26 -0
  259. package/studio/web/hooks/useNow.ts +11 -0
  260. package/studio/web/hooks/useOmniAgent.ts +278 -0
  261. package/studio/web/hooks/useOmniClaude.ts +124 -0
  262. package/studio/web/hooks/useOmniDock.ts +142 -0
  263. package/studio/web/hooks/useOmniGreeting.ts +60 -0
  264. package/studio/web/hooks/useOmniHotword.ts +128 -0
  265. package/studio/web/hooks/useOmnichat.ts +26 -0
  266. package/studio/web/hooks/useOnboarding.ts +27 -0
  267. package/studio/web/hooks/usePost.ts +23 -0
  268. package/studio/web/hooks/useQueue.ts +10 -0
  269. package/studio/web/hooks/useReferences.ts +20 -0
  270. package/studio/web/hooks/useRuleEditor.ts +101 -0
  271. package/studio/web/hooks/useRunner.ts +24 -0
  272. package/studio/web/hooks/useSaveAction.ts +23 -0
  273. package/studio/web/hooks/useSchedule.ts +11 -0
  274. package/studio/web/hooks/useServices.ts +10 -0
  275. package/studio/web/hooks/useSessions.ts +15 -0
  276. package/studio/web/hooks/useSettings.ts +11 -0
  277. package/studio/web/hooks/useSettingsSection.ts +30 -0
  278. package/studio/web/hooks/useSidePanel.ts +23 -0
  279. package/studio/web/hooks/useSound.ts +30 -0
  280. package/studio/web/hooks/useUsage.ts +11 -0
  281. package/studio/web/hooks/useVideoVoice.ts +36 -0
  282. package/studio/web/hooks/useVideos.ts +21 -0
  283. package/studio/web/hooks/useVoiceProfilePreview.ts +52 -0
  284. package/studio/web/hooks/useVoiceProfiles.ts +7 -0
  285. package/studio/web/hooks/useVoiceRunning.ts +10 -0
  286. package/studio/web/hooks/useVoiceStudioClosed.ts +8 -0
  287. package/studio/web/index.html +19 -0
  288. package/studio/web/lib/agent.ts +7 -0
  289. package/studio/web/lib/alerts.ts +210 -0
  290. package/studio/web/lib/analytics-metrics.ts +351 -0
  291. package/studio/web/lib/api.ts +70 -0
  292. package/studio/web/lib/audio.ts +39 -0
  293. package/studio/web/lib/avatars.ts +41 -0
  294. package/studio/web/lib/calendar.ts +218 -0
  295. package/studio/web/lib/caption-position.ts +249 -0
  296. package/studio/web/lib/carousel.ts +24 -0
  297. package/studio/web/lib/chime.ts +42 -0
  298. package/studio/web/lib/clone-voice.ts +55 -0
  299. package/studio/web/lib/export.ts +11 -0
  300. package/studio/web/lib/files.ts +8 -0
  301. package/studio/web/lib/format.ts +93 -0
  302. package/studio/web/lib/media.ts +29 -0
  303. package/studio/web/lib/mic-device.ts +72 -0
  304. package/studio/web/lib/missing-dms.ts +70 -0
  305. package/studio/web/lib/omni-cards.ts +42 -0
  306. package/studio/web/lib/omni-cascade.ts +1067 -0
  307. package/studio/web/lib/omni-greeting-audio.ts +24 -0
  308. package/studio/web/lib/omni-hotword.ts +231 -0
  309. package/studio/web/lib/omni-panel.ts +67 -0
  310. package/studio/web/lib/omni-realtime.ts +811 -0
  311. package/studio/web/lib/omni-ui.ts +402 -0
  312. package/studio/web/lib/omni-wait.ts +174 -0
  313. package/studio/web/lib/omnichat-api.ts +44 -0
  314. package/studio/web/lib/orb.ts +270 -0
  315. package/studio/web/lib/pcm-recorder.ts +115 -0
  316. package/studio/web/lib/platforms.ts +17 -0
  317. package/studio/web/lib/providers.ts +27 -0
  318. package/studio/web/lib/publish-draft.ts +52 -0
  319. package/studio/web/lib/publish-settings.ts +81 -0
  320. package/studio/web/lib/query-client.ts +122 -0
  321. package/studio/web/lib/references.ts +13 -0
  322. package/studio/web/lib/services.ts +40 -0
  323. package/studio/web/lib/sessions.ts +103 -0
  324. package/studio/web/lib/settings-categories.ts +58 -0
  325. package/studio/web/lib/sound-audio.ts +33 -0
  326. package/studio/web/lib/sound-timeline.ts +291 -0
  327. package/studio/web/lib/sse.ts +86 -0
  328. package/studio/web/lib/stage-history.ts +141 -0
  329. package/studio/web/lib/stages.ts +344 -0
  330. package/studio/web/lib/studio-offline.ts +60 -0
  331. package/studio/web/lib/upload.ts +24 -0
  332. package/studio/web/lib/video-tabs.ts +118 -0
  333. package/studio/web/lib/voice-profile-draft.ts +34 -0
  334. package/studio/web/lib/voice-profiles.ts +3 -0
  335. package/studio/web/main.tsx +14 -0
  336. package/studio/web/pages/AdminPage/index.tsx +123 -0
  337. package/studio/web/pages/AgentPage/components/Measurements.tsx +102 -0
  338. package/studio/web/pages/AgentPage/index.tsx +28 -0
  339. package/studio/web/pages/AnalyticsPage/components/About.tsx +52 -0
  340. package/studio/web/pages/AnalyticsPage/components/ChannelCards.tsx +106 -0
  341. package/studio/web/pages/AnalyticsPage/components/ChannelView.tsx +137 -0
  342. package/studio/web/pages/AnalyticsPage/components/CollectionStatus.tsx +46 -0
  343. package/studio/web/pages/AnalyticsPage/components/Comparison.tsx +68 -0
  344. package/studio/web/pages/AnalyticsPage/components/Diagnosis.tsx +50 -0
  345. package/studio/web/pages/AnalyticsPage/components/Highlights.tsx +49 -0
  346. package/studio/web/pages/AnalyticsPage/components/Hint.tsx +11 -0
  347. package/studio/web/pages/AnalyticsPage/components/HookVsBody.tsx +100 -0
  348. package/studio/web/pages/AnalyticsPage/components/HourlyWave.tsx +133 -0
  349. package/studio/web/pages/AnalyticsPage/components/Insights.tsx +70 -0
  350. package/studio/web/pages/AnalyticsPage/components/MetricCard.tsx +46 -0
  351. package/studio/web/pages/AnalyticsPage/components/PlanSection.tsx +40 -0
  352. package/studio/web/pages/AnalyticsPage/components/ProgressionChart.tsx +155 -0
  353. package/studio/web/pages/AnalyticsPage/components/ReelBarsChart.tsx +154 -0
  354. package/studio/web/pages/AnalyticsPage/components/ReelThumb.tsx +19 -0
  355. package/studio/web/pages/AnalyticsPage/components/ReelView.tsx +290 -0
  356. package/studio/web/pages/AnalyticsPage/components/ReelsTable.tsx +269 -0
  357. package/studio/web/pages/AnalyticsPage/components/RequestWithFocus.tsx +38 -0
  358. package/studio/web/pages/AnalyticsPage/components/SegmentedControl.tsx +35 -0
  359. package/studio/web/pages/AnalyticsPage/components/VsMedian.tsx +31 -0
  360. package/studio/web/pages/AnalyticsPage/index.tsx +17 -0
  361. package/studio/web/pages/GettingStartedPage/index.tsx +174 -0
  362. package/studio/web/pages/NewVideoPage/components/DeliverablesPicker.tsx +62 -0
  363. package/studio/web/pages/NewVideoPage/components/FormatPicker.tsx +33 -0
  364. package/studio/web/pages/NewVideoPage/index.tsx +133 -0
  365. package/studio/web/pages/NotFoundPage/index.tsx +9 -0
  366. package/studio/web/pages/OmnichatPage/components/NewFromLink.tsx +59 -0
  367. package/studio/web/pages/OmnichatPage/components/RuleListItem.tsx +64 -0
  368. package/studio/web/pages/OmnichatPage/components/RulePreview.tsx +14 -0
  369. package/studio/web/pages/OmnichatPage/components/RuleView.tsx +88 -0
  370. package/studio/web/pages/OmnichatPage/index.tsx +153 -0
  371. package/studio/web/pages/QueuePage/index.tsx +22 -0
  372. package/studio/web/pages/ReferencePage/components/ReferenceTexts.tsx +131 -0
  373. package/studio/web/pages/ReferencePage/index.tsx +216 -0
  374. package/studio/web/pages/ReferencesPage/components/NewReferenceForm.tsx +150 -0
  375. package/studio/web/pages/ReferencesPage/components/ReferenceCard.tsx +42 -0
  376. package/studio/web/pages/ReferencesPage/components/ReferenceGridSkeleton.tsx +31 -0
  377. package/studio/web/pages/ReferencesPage/index.tsx +67 -0
  378. package/studio/web/pages/SchedulePage/components/CalendarSkeleton.tsx +18 -0
  379. package/studio/web/pages/SchedulePage/components/DayView.tsx +177 -0
  380. package/studio/web/pages/SchedulePage/components/HourPicker.tsx +103 -0
  381. package/studio/web/pages/SchedulePage/components/MonthDayCell.tsx +111 -0
  382. package/studio/web/pages/SchedulePage/components/MonthView.tsx +47 -0
  383. package/studio/web/pages/SchedulePage/components/PlatformIcons.tsx +12 -0
  384. package/studio/web/pages/SchedulePage/components/PostThumb.tsx +15 -0
  385. package/studio/web/pages/SchedulePage/components/WeekColumn.tsx +75 -0
  386. package/studio/web/pages/SchedulePage/components/WeekView.tsx +35 -0
  387. package/studio/web/pages/SchedulePage/index.tsx +285 -0
  388. package/studio/web/pages/SettingsPage/components/AgentAccounts.tsx +263 -0
  389. package/studio/web/pages/SettingsPage/components/AgentCategory.tsx +20 -0
  390. package/studio/web/pages/SettingsPage/components/ModelPicker.tsx +49 -0
  391. package/studio/web/pages/SettingsPage/components/ModelsSettings.tsx +138 -0
  392. package/studio/web/pages/SettingsPage/components/PlatformsCategory.tsx +23 -0
  393. package/studio/web/pages/SettingsPage/components/PublishingCategory/AccountStatus.tsx +29 -0
  394. package/studio/web/pages/SettingsPage/components/PublishingCategory/AutoPublishPanel.tsx +90 -0
  395. package/studio/web/pages/SettingsPage/components/PublishingCategory/BrowserConnect.tsx +62 -0
  396. package/studio/web/pages/SettingsPage/components/PublishingCategory/CheckField.tsx +19 -0
  397. package/studio/web/pages/SettingsPage/components/PublishingCategory/InstagramPanel.tsx +113 -0
  398. package/studio/web/pages/SettingsPage/components/PublishingCategory/OmnichatSettingsPanel.tsx +146 -0
  399. package/studio/web/pages/SettingsPage/components/PublishingCategory/SaveBar.tsx +33 -0
  400. package/studio/web/pages/SettingsPage/components/PublishingCategory/SchedulePanel.tsx +132 -0
  401. package/studio/web/pages/SettingsPage/components/PublishingCategory/SettingsCard.tsx +47 -0
  402. package/studio/web/pages/SettingsPage/components/PublishingCategory/SettingsCardGroup.tsx +19 -0
  403. package/studio/web/pages/SettingsPage/components/PublishingCategory/TextPanel.tsx +55 -0
  404. package/studio/web/pages/SettingsPage/components/PublishingCategory/TiktokPanel.tsx +123 -0
  405. package/studio/web/pages/SettingsPage/components/PublishingCategory/YoutubePanel.tsx +100 -0
  406. package/studio/web/pages/SettingsPage/components/PublishingCategory/badges.tsx +15 -0
  407. package/studio/web/pages/SettingsPage/components/PublishingCategory/index.tsx +40 -0
  408. package/studio/web/pages/SettingsPage/components/PublishingCategory/types.ts +10 -0
  409. package/studio/web/pages/SettingsPage/components/UsageCategory.tsx +389 -0
  410. package/studio/web/pages/SettingsPage/components/VoiceProvidersCategory.tsx +97 -0
  411. package/studio/web/pages/SettingsPage/index.tsx +85 -0
  412. package/studio/web/pages/VideoPage/components/AudioPlayer.tsx +113 -0
  413. package/studio/web/pages/VideoPage/components/CaptionPositionEditor/AxisField.tsx +50 -0
  414. package/studio/web/pages/VideoPage/components/CaptionPositionEditor/CaptionList.tsx +56 -0
  415. package/studio/web/pages/VideoPage/components/CaptionPositionEditor/CaptionListItem.tsx +92 -0
  416. package/studio/web/pages/VideoPage/components/CaptionPositionEditor/CaptionMargins.tsx +57 -0
  417. package/studio/web/pages/VideoPage/components/CaptionPositionEditor/CaptionStyleFields.tsx +70 -0
  418. package/studio/web/pages/VideoPage/components/CaptionPositionEditor/CaptionTextForm.tsx +87 -0
  419. package/studio/web/pages/VideoPage/components/CaptionPositionEditor/ColorField.tsx +37 -0
  420. package/studio/web/pages/VideoPage/components/CaptionPositionEditor/MarginField.tsx +59 -0
  421. package/studio/web/pages/VideoPage/components/CaptionPositionEditor/NumberField.tsx +57 -0
  422. package/studio/web/pages/VideoPage/components/CaptionPositionEditor/PositionControls.tsx +140 -0
  423. package/studio/web/pages/VideoPage/components/CaptionPositionEditor/captionEditor.ts +215 -0
  424. package/studio/web/pages/VideoPage/components/CaptionPositionEditor/useCaptionPosition.ts +154 -0
  425. package/studio/web/pages/VideoPage/components/CarouselChangeRequest.tsx +72 -0
  426. package/studio/web/pages/VideoPage/components/CarouselCompositionStage.tsx +80 -0
  427. package/studio/web/pages/VideoPage/components/CarouselCreate.tsx +63 -0
  428. package/studio/web/pages/VideoPage/components/CarouselMissing.tsx +19 -0
  429. package/studio/web/pages/VideoPage/components/CarouselPublishStage.tsx +173 -0
  430. package/studio/web/pages/VideoPage/components/CarouselScriptStage.tsx +82 -0
  431. package/studio/web/pages/VideoPage/components/CarouselSlideCard.tsx +49 -0
  432. package/studio/web/pages/VideoPage/components/CarouselViewer.tsx +55 -0
  433. package/studio/web/pages/VideoPage/components/ChangedVoices.tsx +53 -0
  434. package/studio/web/pages/VideoPage/components/CompositionStage.tsx +78 -0
  435. package/studio/web/pages/VideoPage/components/CoverPicker.tsx +32 -0
  436. package/studio/web/pages/VideoPage/components/EditorStage.tsx +53 -0
  437. package/studio/web/pages/VideoPage/components/LineTakes.tsx +160 -0
  438. package/studio/web/pages/VideoPage/components/LineTextEditor.tsx +124 -0
  439. package/studio/web/pages/VideoPage/components/LineVoicePicker.tsx +37 -0
  440. package/studio/web/pages/VideoPage/components/MediaImage.tsx +25 -0
  441. package/studio/web/pages/VideoPage/components/MotionScriptStage.tsx +39 -0
  442. package/studio/web/pages/VideoPage/components/NarrationStage.tsx +70 -0
  443. package/studio/web/pages/VideoPage/components/PublishForm.tsx +387 -0
  444. package/studio/web/pages/VideoPage/components/PublishStage.tsx +76 -0
  445. package/studio/web/pages/VideoPage/components/PublishText.tsx +149 -0
  446. package/studio/web/pages/VideoPage/components/ScenesApprovalPanel.tsx +278 -0
  447. package/studio/web/pages/VideoPage/components/ScheduledInfo.tsx +72 -0
  448. package/studio/web/pages/VideoPage/components/ScriptApprovalPanel.tsx +189 -0
  449. package/studio/web/pages/VideoPage/components/ScriptStage.tsx +17 -0
  450. package/studio/web/pages/VideoPage/components/SequencePlayer.tsx +146 -0
  451. package/studio/web/pages/VideoPage/components/SoundTimeline/AddSound.tsx +117 -0
  452. package/studio/web/pages/VideoPage/components/SoundTimeline/AreaSelection.tsx +74 -0
  453. package/studio/web/pages/VideoPage/components/SoundTimeline/BedPanel.tsx +94 -0
  454. package/studio/web/pages/VideoPage/components/SoundTimeline/BedRow.tsx +45 -0
  455. package/studio/web/pages/VideoPage/components/SoundTimeline/CaptionOverlay.tsx +44 -0
  456. package/studio/web/pages/VideoPage/components/SoundTimeline/CaptionSaveBar.tsx +32 -0
  457. package/studio/web/pages/VideoPage/components/SoundTimeline/CaptionsPanel.tsx +22 -0
  458. package/studio/web/pages/VideoPage/components/SoundTimeline/ClipBlock.tsx +111 -0
  459. package/studio/web/pages/VideoPage/components/SoundTimeline/ClipPanel.tsx +76 -0
  460. package/studio/web/pages/VideoPage/components/SoundTimeline/CutsPanel.tsx +44 -0
  461. package/studio/web/pages/VideoPage/components/SoundTimeline/EditorTabBar.tsx +73 -0
  462. package/studio/web/pages/VideoPage/components/SoundTimeline/EffectChoice.tsx +46 -0
  463. package/studio/web/pages/VideoPage/components/SoundTimeline/EffectItem.tsx +89 -0
  464. package/studio/web/pages/VideoPage/components/SoundTimeline/EffectPanel.tsx +232 -0
  465. package/studio/web/pages/VideoPage/components/SoundTimeline/EffectsRow.tsx +21 -0
  466. package/studio/web/pages/VideoPage/components/SoundTimeline/Lane.tsx +39 -0
  467. package/studio/web/pages/VideoPage/components/SoundTimeline/MarkerRow.tsx +40 -0
  468. package/studio/web/pages/VideoPage/components/SoundTimeline/MuteButton.tsx +36 -0
  469. package/studio/web/pages/VideoPage/components/SoundTimeline/NumberInput.tsx +37 -0
  470. package/studio/web/pages/VideoPage/components/SoundTimeline/PlanWarnings.tsx +19 -0
  471. package/studio/web/pages/VideoPage/components/SoundTimeline/PlayerResizeHandle.tsx +50 -0
  472. package/studio/web/pages/VideoPage/components/SoundTimeline/PreviewControls.tsx +51 -0
  473. package/studio/web/pages/VideoPage/components/SoundTimeline/SceneRow.tsx +54 -0
  474. package/studio/web/pages/VideoPage/components/SoundTimeline/SettingsPanel.tsx +65 -0
  475. package/studio/web/pages/VideoPage/components/SoundTimeline/SoundLibrary.tsx +99 -0
  476. package/studio/web/pages/VideoPage/components/SoundTimeline/SoundPreview.tsx +82 -0
  477. package/studio/web/pages/VideoPage/components/SoundTimeline/SpeedPanel.tsx +128 -0
  478. package/studio/web/pages/VideoPage/components/SoundTimeline/TimelineDock.tsx +56 -0
  479. package/studio/web/pages/VideoPage/components/SoundTimeline/TimelineFooter.tsx +26 -0
  480. package/studio/web/pages/VideoPage/components/SoundTimeline/TimelineSkeleton.tsx +21 -0
  481. package/studio/web/pages/VideoPage/components/SoundTimeline/TimelineToolbar.tsx +160 -0
  482. package/studio/web/pages/VideoPage/components/SoundTimeline/TimelineTracks.tsx +121 -0
  483. package/studio/web/pages/VideoPage/components/SoundTimeline/TrackSidebar.tsx +30 -0
  484. package/studio/web/pages/VideoPage/components/SoundTimeline/VoiceRow.tsx +53 -0
  485. package/studio/web/pages/VideoPage/components/SoundTimeline/Waveform.tsx +97 -0
  486. package/studio/web/pages/VideoPage/components/SoundTimeline/clipActions.ts +50 -0
  487. package/studio/web/pages/VideoPage/components/SoundTimeline/effectActions.ts +161 -0
  488. package/studio/web/pages/VideoPage/components/SoundTimeline/index.tsx +161 -0
  489. package/studio/web/pages/VideoPage/components/SoundTimeline/timelineGeometry.ts +45 -0
  490. package/studio/web/pages/VideoPage/components/SoundTimeline/types.ts +43 -0
  491. package/studio/web/pages/VideoPage/components/SoundTimeline/useAutosave.ts +107 -0
  492. package/studio/web/pages/VideoPage/components/SoundTimeline/useEditorShortcuts.ts +168 -0
  493. package/studio/web/pages/VideoPage/components/SoundTimeline/useFitHeight.ts +40 -0
  494. package/studio/web/pages/VideoPage/components/SoundTimeline/useFollowPlayhead.ts +21 -0
  495. package/studio/web/pages/VideoPage/components/SoundTimeline/useListenMix.ts +43 -0
  496. package/studio/web/pages/VideoPage/components/SoundTimeline/usePlayback.ts +231 -0
  497. package/studio/web/pages/VideoPage/components/SoundTimeline/usePlayerWidth.ts +27 -0
  498. package/studio/web/pages/VideoPage/components/SoundTimeline/useSoundData.ts +124 -0
  499. package/studio/web/pages/VideoPage/components/SoundTimeline/useSoundTimeline.ts +511 -0
  500. package/studio/web/pages/VideoPage/components/StageDrawer/CompareVersions.tsx +111 -0
  501. package/studio/web/pages/VideoPage/components/StageDrawer/VersionCard.tsx +81 -0
  502. package/studio/web/pages/VideoPage/components/StageDrawer/VersionMedia.tsx +24 -0
  503. package/studio/web/pages/VideoPage/components/StageDrawer/VersionText.tsx +15 -0
  504. package/studio/web/pages/VideoPage/components/StageDrawer/index.tsx +109 -0
  505. package/studio/web/pages/VideoPage/components/StageProcess.tsx +126 -0
  506. package/studio/web/pages/VideoPage/components/StageResult.tsx +69 -0
  507. package/studio/web/pages/VideoPage/components/SwapReference.tsx +92 -0
  508. package/studio/web/pages/VideoPage/components/ThumbnailPanel.tsx +252 -0
  509. package/studio/web/pages/VideoPage/components/TimingPanel.tsx +89 -0
  510. package/studio/web/pages/VideoPage/components/VideoPlayer.tsx +18 -0
  511. package/studio/web/pages/VideoPage/components/VideoSkeleton.tsx +50 -0
  512. package/studio/web/pages/VideoPage/components/VideoVoiceInfo.tsx +33 -0
  513. package/studio/web/pages/VideoPage/components/VideoVoicePicker.tsx +165 -0
  514. package/studio/web/pages/VideoPage/components/VoicePauseBanner.tsx +56 -0
  515. package/studio/web/pages/VideoPage/components/WithLogo.tsx +10 -0
  516. package/studio/web/pages/VideoPage/index.tsx +295 -0
  517. package/studio/web/pages/VideosPage/components/PublishedOn.tsx +85 -0
  518. package/studio/web/pages/VideosPage/components/ServicesPanel.tsx +81 -0
  519. package/studio/web/pages/VideosPage/components/SessionsPanel.tsx +62 -0
  520. package/studio/web/pages/VideosPage/components/VideoListSkeleton.tsx +25 -0
  521. package/studio/web/pages/VideosPage/components/VideoRow.tsx +122 -0
  522. package/studio/web/pages/VideosPage/index.tsx +134 -0
  523. package/studio/web/pages/VoicePage/index.tsx +28 -0
  524. package/studio/web/router.tsx +201 -0
  525. package/studio/web/styles/base/elements.css +55 -0
  526. package/studio/web/styles/base/utilities.css +25 -0
  527. package/studio/web/styles/components/badge.css +33 -0
  528. package/studio/web/styles/components/claude-running.css +27 -0
  529. package/studio/web/styles/components/claude-session.css +212 -0
  530. package/studio/web/styles/components/claude-walking.css +92 -0
  531. package/studio/web/styles/components/clone-voice-save.css +136 -0
  532. package/studio/web/styles/components/clone-voice.css +379 -0
  533. package/studio/web/styles/components/controls.css +70 -0
  534. package/studio/web/styles/components/data-and-image.css +54 -0
  535. package/studio/web/styles/components/forms.css +132 -0
  536. package/studio/web/styles/components/human-banner.css +99 -0
  537. package/studio/web/styles/components/lightbox.css +50 -0
  538. package/studio/web/styles/components/markdown.css +68 -0
  539. package/studio/web/styles/components/modal.css +70 -0
  540. package/studio/web/styles/components/omni-cards.css +105 -0
  541. package/studio/web/styles/components/omni.css +859 -0
  542. package/studio/web/styles/components/omnichat.css +538 -0
  543. package/studio/web/styles/components/panel.css +115 -0
  544. package/studio/web/styles/components/platform-card.css +140 -0
  545. package/studio/web/styles/components/provider-card.css +132 -0
  546. package/studio/web/styles/components/queue.css +185 -0
  547. package/studio/web/styles/components/reference-actions.css +133 -0
  548. package/studio/web/styles/components/reference-picker.css +146 -0
  549. package/studio/web/styles/components/results-drawer.css +224 -0
  550. package/studio/web/styles/components/segmented.css +115 -0
  551. package/studio/web/styles/components/side-panel-tab.css +23 -0
  552. package/studio/web/styles/components/status-signals.css +66 -0
  553. package/studio/web/styles/components/stepper.css +208 -0
  554. package/studio/web/styles/components/table.css +19 -0
  555. package/studio/web/styles/components/tabs.css +24 -0
  556. package/studio/web/styles/components/ui/accordion.css +71 -0
  557. package/studio/web/styles/components/ui/chart.css +162 -0
  558. package/studio/web/styles/components/ui/checkbox.css +37 -0
  559. package/studio/web/styles/components/ui/date-picker.css +153 -0
  560. package/studio/web/styles/components/ui/select.css +110 -0
  561. package/studio/web/styles/components/ui/skeleton.css +25 -0
  562. package/studio/web/styles/components/ui/slider.css +81 -0
  563. package/studio/web/styles/components/ui/switch.css +41 -0
  564. package/studio/web/styles/components/ui/tooltip.css +24 -0
  565. package/studio/web/styles/components/voice-carousel.css +255 -0
  566. package/studio/web/styles/components/voice-editor.css +179 -0
  567. package/studio/web/styles/components/voice-grid.css +56 -0
  568. package/studio/web/styles/components/voice-profiles.css +192 -0
  569. package/studio/web/styles/design-system.md +136 -0
  570. package/studio/web/styles/index.css +116 -0
  571. package/studio/web/styles/layout/page.css +41 -0
  572. package/studio/web/styles/layout/sidebar-groups.css +39 -0
  573. package/studio/web/styles/layout/sidebar.css +111 -0
  574. package/studio/web/styles/pages/agent.css +26 -0
  575. package/studio/web/styles/pages/analytics/dashboard.css +614 -0
  576. package/studio/web/styles/pages/analytics/insights.css +48 -0
  577. package/studio/web/styles/pages/getting-started.css +166 -0
  578. package/studio/web/styles/pages/new-video/form.css +32 -0
  579. package/studio/web/styles/pages/not-found.css +59 -0
  580. package/studio/web/styles/pages/references.css +204 -0
  581. package/studio/web/styles/pages/schedule/calendar.css +541 -0
  582. package/studio/web/styles/pages/schedule/chip-states.css +60 -0
  583. package/studio/web/styles/pages/settings/models.css +72 -0
  584. package/studio/web/styles/pages/settings/shell.css +361 -0
  585. package/studio/web/styles/pages/settings/usage.css +63 -0
  586. package/studio/web/styles/pages/studio-offline.css +105 -0
  587. package/studio/web/styles/pages/video/caption-controls.css +194 -0
  588. package/studio/web/styles/pages/video/captions-grid.css +70 -0
  589. package/studio/web/styles/pages/video/captions.css +79 -0
  590. package/studio/web/styles/pages/video/editor-chat.css +103 -0
  591. package/studio/web/styles/pages/video/export.css +50 -0
  592. package/studio/web/styles/pages/video/frames.css +29 -0
  593. package/studio/web/styles/pages/video/fullscreen-stage.css +400 -0
  594. package/studio/web/styles/pages/video/instagram-carousel.css +309 -0
  595. package/studio/web/styles/pages/video/layout.css +285 -0
  596. package/studio/web/styles/pages/video/narration.css +138 -0
  597. package/studio/web/styles/pages/video/preview-overview.css +11 -0
  598. package/studio/web/styles/pages/video/processing-notice.css +34 -0
  599. package/studio/web/styles/pages/video/publish-when.css +76 -0
  600. package/studio/web/styles/pages/video/publish.css +97 -0
  601. package/studio/web/styles/pages/video/result.css +96 -0
  602. package/studio/web/styles/pages/video/scenes.css +167 -0
  603. package/studio/web/styles/pages/video/sound-timeline.css +672 -0
  604. package/studio/web/styles/pages/video/sound-toolbar.css +149 -0
  605. package/studio/web/styles/pages/video/take-player.css +100 -0
  606. package/studio/web/styles/pages/video/thumbnail.css +157 -0
  607. package/studio/web/styles/pages/video/timeline.css +117 -0
  608. package/studio/web/styles/pages/video/voice-picker.css +14 -0
  609. package/studio/web/styles/pages/video-list/active-row.css +27 -0
  610. package/studio/web/styles/pages/video-list/card-link.css +49 -0
  611. package/studio/web/styles/pages/video-list/list.css +86 -0
  612. package/studio/web/styles/theme/identity/details.css +204 -0
  613. package/studio/web/styles/theme/identity/shell.css +249 -0
  614. package/studio/web/styles/theme/identity/surfaces.css +183 -0
  615. package/studio/web/styles/theme/identity/titles-and-buttons.css +120 -0
  616. package/studio/web/styles/theme/no-borders/blocks.css +208 -0
  617. package/studio/web/styles/theme/no-borders/controls.css +256 -0
  618. package/studio/web/styles/tokens.css +245 -0
  619. package/studio/web/types/api.ts +2 -0
  620. package/studio/web/types/assets.d.ts +9 -0
  621. package/templates/brief.md +27 -0
  622. package/templates/captions.html +204 -0
  623. package/templates/carousel-composition.md +47 -0
  624. package/templates/carousel-script.md +60 -0
  625. package/templates/components/voiceavatar/README.md +87 -0
  626. package/templates/components/voiceavatar/demo.html +50 -0
  627. package/templates/components/voiceavatar/voiceavatar.js +415 -0
  628. package/templates/motion.md +80 -0
  629. package/templates/playbook.md +43 -0
  630. package/templates/reference.md +123 -0
  631. package/templates/scene.html +112 -0
  632. package/templates/scenes.example.json +96 -0
  633. package/templates/script.md +63 -0
  634. package/templates/slide.html +71 -0
  635. package/templates/wireframe.html +91 -0
  636. package/tools/analysis.mjs +300 -0
  637. package/tools/approval.mjs +442 -0
  638. package/tools/assemble.mjs +942 -0
  639. package/tools/build-motion.mjs +437 -0
  640. package/tools/captions.mjs +246 -0
  641. package/tools/carousel.mjs +558 -0
  642. package/tools/compose.mjs +307 -0
  643. package/tools/cuts.mjs +74 -0
  644. package/tools/editor.mjs +419 -0
  645. package/tools/epidemic-capture.js +54 -0
  646. package/tools/fanout.mjs +69 -0
  647. package/tools/history.mjs +70 -0
  648. package/tools/history.py +61 -0
  649. package/tools/job-queue.mjs +180 -0
  650. package/tools/job_queue.py +430 -0
  651. package/tools/lib/agents.mjs +412 -0
  652. package/tools/lib/channel.mjs +399 -0
  653. package/tools/lib/claude-settings.mjs +67 -0
  654. package/tools/lib/cli.mjs +9 -0
  655. package/tools/lib/fanout.mjs +234 -0
  656. package/tools/lib/http.mjs +94 -0
  657. package/tools/lib/index.js +14 -0
  658. package/tools/lib/mcp-server.mjs +69 -0
  659. package/tools/lib/metrics/metrics.mjs +204 -0
  660. package/tools/lib/narration.mjs +15 -0
  661. package/tools/lib/oauth-client.mjs +295 -0
  662. package/tools/lib/omnichat/config.mjs +139 -0
  663. package/tools/lib/omnichat/errors.mjs +42 -0
  664. package/tools/lib/omnichat/extract.mjs +82 -0
  665. package/tools/lib/omnichat/gate.mjs +151 -0
  666. package/tools/lib/omnichat/manual.mjs +166 -0
  667. package/tools/lib/omnichat/match.mjs +78 -0
  668. package/tools/lib/omnichat/pass.mjs +393 -0
  669. package/tools/lib/omnichat/record.mjs +208 -0
  670. package/tools/lib/omnichat/text.mjs +315 -0
  671. package/tools/lib/omnichat/webhook.mjs +166 -0
  672. package/tools/lib/pairing.mjs +99 -0
  673. package/tools/lib/paths.mjs +41 -0
  674. package/tools/lib/platforms/instagram.mjs +469 -0
  675. package/tools/lib/platforms/tiktok.mjs +343 -0
  676. package/tools/lib/platforms/youtube.mjs +228 -0
  677. package/tools/lib/publish/publish.mjs +244 -0
  678. package/tools/lib/schedule/schedule.mjs +191 -0
  679. package/tools/lib/service.mjs +134 -0
  680. package/tools/lib/skill-client.mjs +126 -0
  681. package/tools/lib/skills-release.mjs +196 -0
  682. package/tools/lib/testing.mjs +52 -0
  683. package/tools/lib/up.mjs +187 -0
  684. package/tools/metrics.mjs +415 -0
  685. package/tools/models.mjs +134 -0
  686. package/tools/narrate.mjs +257 -0
  687. package/tools/omni.mjs +298 -0
  688. package/tools/omni_paths.py +12 -0
  689. package/tools/omnichat.mjs +1577 -0
  690. package/tools/omnivideo.py +1122 -0
  691. package/tools/package.mjs +130 -0
  692. package/tools/platforms.mjs +236 -0
  693. package/tools/premiere.mjs +533 -0
  694. package/tools/publish.mjs +1496 -0
  695. package/tools/reference.mjs +1408 -0
  696. package/tools/render.mjs +426 -0
  697. package/tools/runner.mjs +156 -0
  698. package/tools/setup.mjs +466 -0
  699. package/tools/skills-release.mjs +93 -0
  700. package/tools/sound.mjs +1323 -0
  701. package/tools/soundtrack.mjs +217 -0
  702. package/tools/thumbnail.mjs +271 -0
  703. package/tools/timing.mjs +108 -0
  704. package/tools/usage.py +628 -0
  705. package/tools/voice-envelope.mjs +185 -0
  706. package/tools/voice.py +448 -0
  707. package/tools/voice_sample.py +75 -0
  708. package/tools/wireframe.mjs +230 -0
@@ -0,0 +1,426 @@
1
+ #!/usr/bin/env node
2
+ /* ============================================================================
3
+ Seek-safe scene renderer: HTML → PNG, contact sheet or video.
4
+
5
+ node tools/render.mjs scene.html out.mp4 --dur 5.4 --fps 30 --w 1080 --h 1920
6
+ node tools/render.mjs scene.html --still f.png --at 3.2
7
+ node tools/render.mjs scene.html --still f.png --at 3.2 --measure # + box of each [data-continues]
8
+ node tools/render.mjs scene.html --sheet s.png --at 0,0.7,1.4,2.4
9
+ node tools/render.mjs scene.html out.webm --format webm # with alpha
10
+ node tools/render.mjs scene.html frames/ --format png-sequence
11
+ node tools/render.mjs scene.html --frames dir/ --at 0.5,2.1 --alpha # one PNG per t (q000.png…)
12
+ node tools/render.mjs scene.html --still f.png --eval "window.__warnings" # + EVAL <json>
13
+ --alpha transparent background in still and frames (the scene must not paint the body)
14
+ --jobs N Chromes in parallel for video (default 3)
15
+ --gl software WebGL2 for the scene (SwiftShader). Automatic when the source
16
+ mentions webgl or VoiceAvatar; without it Chrome runs with --disable-gpu,
17
+ which has no WebGL at all
18
+ --from S the video starts at second S of the scene (default 0)
19
+
20
+ The scene contract: the frame at t depends only on t. The renderer writes
21
+ `--t` on the <html> style and waits two frames before capturing. The scene
22
+ signals it is mounted with `window.__ready = true` (after fonts, GSAP etc.).
23
+ CSS animation uses the [data-anim] rule; GSAP/Motion stay paused and are
24
+ positioned by a MutationObserver on that style. Base: templates/scene.html.
25
+
26
+ Requires Chrome/Chromium and ffmpeg.
27
+ ============================================================================ */
28
+
29
+ import { spawn } from "node:child_process";
30
+ import { mkdir, writeFile, rm, access, readdir } from "node:fs/promises";
31
+ import { readFileSync } from "node:fs";
32
+ import { join, resolve } from "node:path";
33
+ import { tmpdir } from "node:os";
34
+
35
+ /* --- arguments ------------------------------------------------------------- */
36
+ const argv = process.argv.slice(2);
37
+ const flag = (n, d) => {
38
+ const i = argv.indexOf(`--${n}`);
39
+ return i < 0 ? d : argv[i + 1];
40
+ };
41
+ const has = n => argv.includes(`--${n}`);
42
+ const positional = [];
43
+ for (let i = 0; i < argv.length; i++) {
44
+ if (argv[i].startsWith("--")) {
45
+ if (flag(argv[i].slice(2), null) !== null) i++;
46
+ continue;
47
+ }
48
+ positional.push(argv[i]);
49
+ }
50
+
51
+ if (!positional[0]) {
52
+ console.error("uso: node render.mjs <scene.html> <out> [--dur N] [--fps N] [--w N] [--h N] [--jobs N]");
53
+ console.error(" node render.mjs <scene.html> --still f.png --at 3.2");
54
+ console.error(" node render.mjs <scene.html> --sheet s.png --at 0,1,2,3");
55
+ process.exit(1);
56
+ }
57
+
58
+ const SRC = resolve(positional[0]);
59
+ const FMT = flag("format", "mp4");
60
+ const FPS = +flag("fps", 30);
61
+ const W = +flag("w", 1920),
62
+ H = +flag("h", 1080);
63
+ const DUR = +flag("dur", 5);
64
+ const FROM = +flag("from", 0);
65
+ const JOBS = Math.max(1, +flag("jobs", 3));
66
+ const AT = (flag("at", "") || "").split(",").filter(Boolean).map(Number);
67
+ const MODE = has("still") ? "still" : has("sheet") ? "sheet" : has("frames") ? "frames" : "video";
68
+ const OUT = resolve(
69
+ MODE === "still"
70
+ ? flag("still", "still.png")
71
+ : MODE === "sheet"
72
+ ? flag("sheet", "sheet.png")
73
+ : MODE === "frames"
74
+ ? flag("frames", "frames")
75
+ : (positional[1] ?? "out.mp4"),
76
+ );
77
+ const TMP = join(tmpdir(), `render-${process.pid}`);
78
+ /* A WebGL scene needs a GL backend; the plain --disable-gpu Chrome has none. */
79
+ const GL = has("gl") || /webgl|VoiceAvatar/i.test(readFileSync(SRC, "utf8"));
80
+
81
+ /* --- Chrome ---------------------------------------------------------------- */
82
+ async function findChrome() {
83
+ const fixed = [
84
+ process.env.CHROME_PATH,
85
+ "/Applications/Google Chrome.app/Contents/MacOS/Google Chrome",
86
+ "/Applications/Chromium.app/Contents/MacOS/Chromium",
87
+ "/Applications/Brave Browser.app/Contents/MacOS/Brave Browser",
88
+ "/usr/bin/google-chrome",
89
+ "/usr/bin/chromium",
90
+ ].filter(Boolean);
91
+ for (const p of fixed) {
92
+ try {
93
+ await access(p);
94
+ return p;
95
+ } catch {
96
+ /* next */
97
+ }
98
+ }
99
+ /* any Chromium in the Playwright cache, newest first */
100
+ const cache = `${process.env.HOME}/Library/Caches/ms-playwright`;
101
+ try {
102
+ const dirs = (await readdir(cache))
103
+ .filter(d => d.startsWith("chromium-"))
104
+ .sort()
105
+ .reverse();
106
+ for (const d of dirs) {
107
+ for (const sub of ["chrome-mac-arm64", "chrome-mac", "chrome-linux"]) {
108
+ for (const bin of [
109
+ "Google Chrome for Testing.app/Contents/MacOS/Google Chrome for Testing",
110
+ "Chromium.app/Contents/MacOS/Chromium",
111
+ "chrome",
112
+ ]) {
113
+ const p = join(cache, d, sub, bin);
114
+ try {
115
+ await access(p);
116
+ return p;
117
+ } catch {
118
+ /* next */
119
+ }
120
+ }
121
+ }
122
+ }
123
+ } catch {
124
+ /* no cache */
125
+ }
126
+ throw new Error("Chrome não encontrado. Defina CHROME_PATH=/caminho/para/chrome");
127
+ }
128
+
129
+ /* One session = one Chrome process with one page. Parallel tabs in the same
130
+ Chrome don't work: a background tab has requestAnimationFrame throttled,
131
+ and the two-frame wait hangs. */
132
+ async function openSession(chromePath, n) {
133
+ /* a truly free port: another session rendering at the same time may have a Chrome
134
+ on the PID-derived port, and connecting to it captures its page (learnings.md) */
135
+ let port = 9300 + ((process.pid * 7 + n * 31) % 600);
136
+ for (let t = 0; t < 50; t++) {
137
+ const taken = await fetch(`http://127.0.0.1:${port}/json/version`).then(
138
+ () => true,
139
+ () => false,
140
+ );
141
+ if (!taken) break;
142
+ port = 9300 + Math.floor(Math.random() * 6000);
143
+ }
144
+ const profile = join(TMP, `profile-${n}`);
145
+ const proc = spawn(
146
+ chromePath,
147
+ [
148
+ "--headless=new",
149
+ ...(GL
150
+ ? ["--use-angle=swiftshader", "--enable-unsafe-swiftshader", "--ignore-gpu-blocklist"]
151
+ : ["--disable-gpu"]),
152
+ "--hide-scrollbars",
153
+ "--force-device-scale-factor=1",
154
+ "--force-color-profile=srgb" /* no display profile leaking into the frame */,
155
+ "--disable-lcd-text" /* grayscale AA: subpixel flickers between frames */,
156
+ "--allow-file-access-from-files",
157
+ "--disable-background-timer-throttling",
158
+ "--disable-renderer-backgrounding",
159
+ `--window-size=${W},${H + 400}` /* the viewport opens ~140 px shorter: without slack, the bottom of the frame isn't painted (learnings.md) */,
160
+ `--remote-debugging-port=${port}`,
161
+ `--user-data-dir=${profile}`,
162
+ `file://${SRC}`,
163
+ ],
164
+ { stdio: "ignore" },
165
+ );
166
+
167
+ let ws;
168
+ for (let i = 0; i < 100 && !ws; i++) {
169
+ try {
170
+ const page = (await (await fetch(`http://127.0.0.1:${port}/json/list`)).json()).find(
171
+ t => t.type === "page" && t.url.startsWith(`file://${SRC}`),
172
+ );
173
+ if (page) ws = new WebSocket(page.webSocketDebuggerUrl);
174
+ } catch {
175
+ /* still starting */
176
+ }
177
+ if (!ws) await new Promise(r => setTimeout(r, 120));
178
+ }
179
+ if (!ws) {
180
+ proc.kill();
181
+ throw new Error("Chrome não expôs alvo de depuração");
182
+ }
183
+ await new Promise((ok, no) => {
184
+ ws.onopen = ok;
185
+ ws.onerror = no;
186
+ });
187
+
188
+ let id = 0;
189
+ const pending = new Map();
190
+ ws.onmessage = e => {
191
+ const m = JSON.parse(e.data);
192
+ if (m.id && pending.has(m.id)) {
193
+ pending.get(m.id)(m);
194
+ pending.delete(m.id);
195
+ }
196
+ };
197
+ const cmd = (method, params = {}) =>
198
+ new Promise((ok, no) => {
199
+ const k = ++id;
200
+ pending.set(k, m => (m.error ? no(new Error(`${method}: ${m.error.message}`)) : ok(m.result)));
201
+ ws.send(JSON.stringify({ id: k, method, params }));
202
+ });
203
+ const evaluate = async expression => {
204
+ const r = await cmd("Runtime.evaluate", { expression, awaitPromise: true, returnByValue: true });
205
+ if (r.exceptionDetails) throw new Error(r.exceptionDetails.exception?.description ?? r.exceptionDetails.text);
206
+ return r.result.value;
207
+ };
208
+
209
+ await cmd("Page.enable");
210
+ await cmd("Emulation.setDeviceMetricsOverride", { width: W, height: H, deviceScaleFactor: 1, mobile: false });
211
+ if (FMT === "webm" || FMT === "png-sequence" || has("alpha")) {
212
+ /* transparent background: only works if the scene doesn't paint the body */
213
+ await cmd("Emulation.setDefaultBackgroundColorOverride", { color: { r: 0, g: 0, b: 0, a: 0 } });
214
+ }
215
+
216
+ /* wait for the scene to really mount: fonts and its flag */
217
+ const ready = await evaluate(`(async () => {
218
+ await document.fonts.ready;
219
+ for (let i = 0; i < 200; i++) {
220
+ if (window.__ready === true) return true;
221
+ await new Promise(r => setTimeout(r, 100));
222
+ }
223
+ return false;
224
+ })()`);
225
+
226
+ return {
227
+ ready,
228
+ evaluate,
229
+ async grab(t) {
230
+ /* write the timeline head and let the compositor settle for TWO
231
+ frames: with only one, filter/backdrop-filter layers lag behind */
232
+ await evaluate(`(() => {
233
+ document.documentElement.style.setProperty("--t", ${t} + "s");
234
+ return new Promise(r => requestAnimationFrame(() => requestAnimationFrame(() => r(true))));
235
+ })()`);
236
+ const { data } = await cmd("Page.captureScreenshot", {
237
+ format: "png",
238
+ fromSurface: true,
239
+ optimizeForSpeed: true,
240
+ });
241
+ return Buffer.from(data, "base64");
242
+ },
243
+ close() {
244
+ try {
245
+ ws.close();
246
+ } catch {
247
+ /* already closed */
248
+ }
249
+ proc.kill();
250
+ },
251
+ };
252
+ }
253
+
254
+ /* An inline animation-delay or play-state beats calc(--start − --t) and hands
255
+ the animation back to the wall clock. Frames still look plausible, they just
256
+ start depending on capture speed. Neutralize and warn. */
257
+ async function determinismGate(s) {
258
+ const { fixed, running } = await s.evaluate(`(() => {
259
+ let fixed = 0, running = 0;
260
+ document.querySelectorAll("[data-anim]").forEach(el => {
261
+ const d = el.style.animationDelay; /* an inline delay with --t is legit */
262
+ if (d && !d.includes("--t")) { el.style.animationDelay = ""; fixed++; }
263
+ if (el.style.animationPlayState && el.style.animationPlayState !== "paused") { el.style.animationPlayState = ""; fixed++; }
264
+ });
265
+ document.querySelectorAll("[data-anim]").forEach(el => { if (getComputedStyle(el).animationPlayState !== "paused") running++; });
266
+ return { fixed, running };
267
+ })()`);
268
+ if (fixed)
269
+ console.warn(`aviso: ${fixed} estilo(s) inline de animação removidos — a cena estava presa ao relógio, não a --t`);
270
+ if (running)
271
+ console.warn(
272
+ `aviso: ${running} elemento(s) com animation-play-state != paused — o render pode não ser determinístico`,
273
+ );
274
+ }
275
+
276
+ const sh = (bin, args) =>
277
+ new Promise((ok, no) => {
278
+ const p = spawn(bin, args, { stdio: ["ignore", "inherit", "inherit"] });
279
+ p.on("exit", c => (c === 0 ? ok() : no(new Error(`${bin} saiu com ${c}`))));
280
+ });
281
+
282
+ /* --- run ------------------------------------------------------------------ */
283
+ await mkdir(TMP, { recursive: true });
284
+ const chromePath = await findChrome();
285
+ const sessions = [];
286
+ try {
287
+ const n = MODE === "video" ? JOBS : 1;
288
+ sessions.push(...(await Promise.all(Array.from({ length: n }, (_, i) => openSession(chromePath, i)))));
289
+ if (!sessions[0].ready)
290
+ console.warn("aviso: a cena não sinalizou window.__ready = true em 20 s; seguindo assim mesmo");
291
+ for (const s of sessions) await determinismGate(s);
292
+
293
+ if (MODE === "still") {
294
+ const t = AT[0] ?? 0;
295
+ await writeFile(OUT, await sessions[0].grab(t));
296
+ console.log(`still em t=${t}s -> ${OUT}`);
297
+ if (has("measure")) {
298
+ /* on-screen box (with transform) and effective opacity, including the
299
+ ancestors': that is what shows at the cut between two scenes.
300
+ data-continua = legacy name of data-continues */
301
+ const measurements =
302
+ await sessions[0].evaluate(`[...document.querySelectorAll("[data-continues],[data-continua]")].map(el => {
303
+ const r = el.getBoundingClientRect();
304
+ let opacity = 1;
305
+ for (let e = el; e; e = e.parentElement) opacity *= +getComputedStyle(e).opacity;
306
+ return { name: el.dataset.continues ?? el.dataset.continua, x: r.x, y: r.y, w: r.width, h: r.height, opacity };
307
+ })`);
308
+ console.log(`MEASUREMENTS ${JSON.stringify(measurements)}`);
309
+ }
310
+ /* a page expression, after the still: the caller reads the EVAL line */
311
+ if (flag("eval", null))
312
+ console.log(`EVAL ${JSON.stringify((await sessions[0].evaluate(flag("eval", null))) ?? null)}`);
313
+ } else if (MODE === "frames") {
314
+ await mkdir(OUT, { recursive: true });
315
+ for (const [i, t] of AT.entries()) {
316
+ await writeFile(join(OUT, `q${String(i).padStart(3, "0")}.png`), await sessions[0].grab(t));
317
+ }
318
+ console.log(`${AT.length} quadro(s) -> ${OUT}/`);
319
+ } else if (MODE === "sheet") {
320
+ const times = AT.length ? AT : [0, 1, 2, 3, 4, 5];
321
+ for (const [i, t] of times.entries()) {
322
+ await writeFile(join(TMP, `s${String(i).padStart(3, "0")}.png`), await sessions[0].grab(t));
323
+ }
324
+ const cols = Math.min(3, times.length),
325
+ rows = Math.ceil(times.length / cols);
326
+ /* tile builds the grid and pads the last row by itself */
327
+ await sh("ffmpeg", [
328
+ "-y",
329
+ "-loglevel",
330
+ "error",
331
+ "-framerate",
332
+ "1",
333
+ "-i",
334
+ join(TMP, "s%03d.png"),
335
+ "-vf",
336
+ `scale=640:-1,tile=${cols}x${rows}:padding=8:margin=8:color=white`,
337
+ "-frames:v",
338
+ "1",
339
+ OUT,
340
+ ]);
341
+ console.log(`folha de contatos (${times.join(", ")}s) -> ${OUT}`);
342
+ } else {
343
+ const total = Math.round(DUR * FPS);
344
+ const seq = FMT === "png-sequence";
345
+ const frameDir = seq ? OUT : TMP;
346
+ if (seq) await mkdir(frameDir, { recursive: true });
347
+ const started = Date.now();
348
+ let next = 0,
349
+ done = 0;
350
+ process.stdout.write(`${total} quadros @ ${FPS}fps, ${sessions.length} Chrome(s) `);
351
+ await Promise.all(
352
+ sessions.map(async s => {
353
+ while (next < total) {
354
+ const f = next++;
355
+ await writeFile(
356
+ join(frameDir, `f${String(f).padStart(5, "0")}.png`),
357
+ await s.grab(+(FROM + f / FPS).toFixed(6)),
358
+ );
359
+ if (++done % 15 === 0) process.stdout.write(".");
360
+ }
361
+ }),
362
+ );
363
+ console.log(` ok em ${((Date.now() - started) / 1000).toFixed(1)}s`);
364
+ sessions.forEach(s => s.close());
365
+ sessions.length = 0;
366
+
367
+ if (seq) {
368
+ console.log(`sequência PNG -> ${OUT}/`);
369
+ } else if (FMT === "webm") {
370
+ /* VP9 with alpha: yuva420p keeps transparency */
371
+ await sh("ffmpeg", [
372
+ "-y",
373
+ "-loglevel",
374
+ "error",
375
+ "-framerate",
376
+ String(FPS),
377
+ "-i",
378
+ join(TMP, "f%05d.png"),
379
+ "-c:v",
380
+ "libvpx-vp9",
381
+ "-pix_fmt",
382
+ "yuva420p",
383
+ "-crf",
384
+ "24",
385
+ "-b:v",
386
+ "0",
387
+ "-auto-alt-ref",
388
+ "0",
389
+ OUT,
390
+ ]);
391
+ console.log(`escrito ${OUT}`);
392
+ } else {
393
+ /* Top-level -color_* flags are dropped before the H.264 VUI and the
394
+ file comes out `unknown`; setparams is what writes the bt709 tag. */
395
+ await sh("ffmpeg", [
396
+ "-y",
397
+ "-loglevel",
398
+ "error",
399
+ "-framerate",
400
+ String(FPS),
401
+ "-i",
402
+ join(TMP, "f%05d.png"),
403
+ "-vf",
404
+ "scale=out_color_matrix=bt709:out_range=tv,format=yuv420p," +
405
+ "setparams=color_primaries=bt709:color_trc=bt709:colorspace=bt709:range=tv",
406
+ "-c:v",
407
+ "libx264",
408
+ "-crf",
409
+ "16",
410
+ "-preset",
411
+ "slow",
412
+ "-movflags",
413
+ "+faststart",
414
+ OUT,
415
+ ]);
416
+ console.log(`escrito ${OUT}`);
417
+ }
418
+ }
419
+ } finally {
420
+ sessions.forEach(s => s.close());
421
+ /* Chrome may still be writing the profile when it exits: cleanup retries
422
+ and never fails a render that already finished */
423
+ await rm(TMP, { recursive: true, force: true, maxRetries: 10, retryDelay: 200 }).catch(e =>
424
+ console.warn(`aviso: não deu para limpar ${TMP}: ${e.code ?? e.message}`),
425
+ );
426
+ }
@@ -0,0 +1,156 @@
1
+ #!/usr/bin/env node
2
+ /* ============================================================================
3
+ This Mac as the hosted studio's runner (cloud/studio, docs/specs/phase-1-split-api.md): pairing,
4
+ status, unpairing and the service that keeps the studio on. The studio (`bun studio.ts`, with
5
+ cloud.studio in the config) connects with the key this writes into .env (OMNIVIDEO_RUNNER_TOKEN) and
6
+ picks a new one up within 30 s, no restart. When the cloud refuses its key (not a "Desconectar"), the
7
+ studio pairs again by itself: it opens the approval page on this Mac.
8
+
9
+ node tools/runner.mjs login [--name <nome>] [--no-open]
10
+ pairs this Mac: shows a code, opens the approval page, waits
11
+ node tools/runner.mjs status [--json] paired? which Mac? connected now? the service on?
12
+ node tools/runner.mjs logout deletes this Mac's key in the cloud and here
13
+ node tools/runner.mjs service install the studio as a macOS service: starts at login, restarts if it
14
+ stops, no terminal (log in .runner/studio.log)
15
+ node tools/runner.mjs service uninstall | restart | status
16
+
17
+ Pairing is the device authorization flow (RFC 8628) of the studio's Better Auth: the code lasts
18
+ 10 minutes and is approved by the signed-in user at <studio>/runner/pair. The paired Macs, with
19
+ "Desconectar", are at <studio>/runner.
20
+ ============================================================================ */
21
+
22
+ import { hostname } from "node:os";
23
+ import { spawn } from "node:child_process";
24
+ import { finishPairing, startPairing } from "./lib/pairing.mjs";
25
+ import { cloudSettings, env, runnerStatus, writeEnv } from "./platforms.mjs";
26
+ import { service, serviceInstall, serviceRestart, serviceUninstall } from "./lib/service.mjs";
27
+
28
+ const KEY = "OMNIVIDEO_RUNNER_TOKEN";
29
+ const args = process.argv.slice(2);
30
+ const flag = (/** @type {string} */ name) => {
31
+ const i = args.indexOf(`--${name}`);
32
+ return i < 0 ? undefined : (args[i + 1] ?? "");
33
+ };
34
+
35
+ const fail = (/** @type {string} */ m) => {
36
+ console.error(`erro: ${m}`);
37
+ process.exit(1);
38
+ };
39
+
40
+ function studioUrl() {
41
+ const { url } = cloudSettings().studio;
42
+ if (!url) fail("falta cloud.studio_url no omnivideo.config.json (o endereço do studio hospedado)");
43
+ return url;
44
+ }
45
+
46
+ /** @param {string} url @param {string} path @param {{ method?: string, body?: unknown, token?: string }} [o] */
47
+ async function call(url, path, { method = "POST", body, token } = {}) {
48
+ const r = await fetch(`${url}${path}`, {
49
+ method,
50
+ headers: { "content-type": "application/json", ...(token ? { authorization: `Bearer ${token}` } : {}) },
51
+ body: body === undefined ? undefined : JSON.stringify(body),
52
+ });
53
+ const j = await r.json().catch(() => ({}));
54
+ return { status: r.status, ok: r.ok, body: /** @type {any} */ (j) };
55
+ }
56
+
57
+ async function login() {
58
+ const url = studioUrl();
59
+ const name = flag("name") || hostname().replace(/\.local$/, "");
60
+ const code = await startPairing(url).catch(e => fail(e.message));
61
+ console.log(`Código do pareamento: ${code.user_code}`);
62
+ console.log(`Aprove em: ${code.verification_uri_complete}`);
63
+ console.log(`(vale ${Math.round(code.expires_in / 60)} min; confira se o código na página é o mesmo)`);
64
+ if (!args.includes("--no-open") && process.platform === "darwin")
65
+ spawn("open", [code.verification_uri_complete], { stdio: "ignore", detached: true }).unref();
66
+ const paired = await finishPairing(url, code, name).catch(e =>
67
+ fail(`${e.message}; rode de novo node tools/runner.mjs login`),
68
+ );
69
+ writeEnv({ [KEY]: paired.key });
70
+ console.log(`Mac pareado como "${paired.name}". A chave ficou no .env (${KEY}).`);
71
+ console.log(
72
+ service().loaded
73
+ ? "O studio (serviço) conecta sozinho em até 30 s."
74
+ : "O studio aberto conecta sozinho em até 30 s; para deixá-lo sempre ligado: node tools/runner.mjs service install",
75
+ );
76
+ }
77
+
78
+ /* --- the service: the studio kept on by launchd (tools/lib/service.mjs) ------------------ */
79
+ function install() {
80
+ try {
81
+ serviceInstall({ log: line => console.log(line) });
82
+ } catch (e) {
83
+ fail(String(/** @type {Error} */ (e).message));
84
+ }
85
+ console.log("studio ligado como serviço: abre no login e volta sozinho se parar (log em .runner/studio.log)");
86
+ }
87
+
88
+ function uninstall() {
89
+ serviceUninstall();
90
+ console.log(
91
+ "serviço do studio desligado: o studio hospedado só funciona com o studio aberto à mão (cd studio && bun start)",
92
+ );
93
+ }
94
+
95
+ function restart() {
96
+ if (!service().loaded) fail("o serviço não está ligado: node tools/runner.mjs service install");
97
+ try {
98
+ serviceRestart();
99
+ } catch (e) {
100
+ fail(String(/** @type {Error} */ (e).message));
101
+ }
102
+ console.log("studio reiniciado (depois de um git pull, é assim que o código novo entra)");
103
+ }
104
+
105
+ const serviceLine = () => {
106
+ const s = service();
107
+ if (!s.installed)
108
+ return "Serviço: desligado (para manter o studio sempre aberto: node tools/runner.mjs service install).";
109
+ if (!s.loaded) return "Serviço: instalado, mas não carregado: node tools/runner.mjs service install";
110
+ return `Serviço: ligado${s.pid ? `, studio rodando (pid ${s.pid})` : ", esperando para abrir o studio (veja .runner/studio.log)"}.`;
111
+ };
112
+
113
+ async function status() {
114
+ const out = await runnerStatus();
115
+ if (args.includes("--json")) {
116
+ const { url, paired, name, online, error } = out;
117
+ return console.log(JSON.stringify({ url, paired, name, online, error, service: service() }, null, 2));
118
+ }
119
+ if (!out.url) return console.log("Studio hospedado: não configurado (cloud.studio_url no config).");
120
+ console.log(`Studio hospedado: ${out.url}`);
121
+ console.log(serviceLine());
122
+ if (!out.hasKey) return console.log("Este Mac: não pareado (node tools/runner.mjs login).");
123
+ if (!out.paired)
124
+ return console.log(
125
+ `Este Mac: a chave não vale mais (${out.error}). O studio aberto pareia de novo sozinho (aprove na página que ele abre), ou: node tools/runner.mjs login`,
126
+ );
127
+ console.log(
128
+ `Este Mac: pareado como "${out.name}", ${out.online ? "conectado agora" : "desconectado (o studio está aberto? veja o serviço acima)"}.`,
129
+ );
130
+ }
131
+
132
+ async function logout() {
133
+ const url = studioUrl();
134
+ const token = env(KEY);
135
+ if (!token) return console.log("Este Mac já não está pareado.");
136
+ const r = await call(url, "/runner/logout", { token });
137
+ writeEnv({ [KEY]: "" });
138
+ if (!r.ok && r.status !== 401)
139
+ fail(`a chave saiu do .env, mas o studio não confirmou (${r.status}: ${r.body?.error ?? "?"})`);
140
+ console.log("Mac desconectado do studio hospedado. Para voltar: node tools/runner.mjs login");
141
+ }
142
+
143
+ const [cmd, sub] = args;
144
+ if (cmd === "login") await login();
145
+ else if (cmd === "status") await status();
146
+ else if (cmd === "logout") await logout();
147
+ else if (cmd === "service" && sub === "install") install();
148
+ else if (cmd === "service" && sub === "uninstall") uninstall();
149
+ else if (cmd === "service" && sub === "restart") restart();
150
+ else if (cmd === "service" && (!sub || sub === "status")) console.log(serviceLine());
151
+ else {
152
+ console.error(
153
+ "uso: node tools/runner.mjs login [--name <nome>] [--no-open] | status [--json] | logout | service install|uninstall|restart|status",
154
+ );
155
+ process.exit(cmd ? 1 : 0);
156
+ }