@crievo/omni 0.0.0-stage → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (709) hide show
  1. package/.env.example +41 -0
  2. package/README.md +2 -2
  3. package/bin/omni.mjs +14 -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.test.tsx +30 -0
  247. package/studio/web/components/ui/tooltip.tsx +59 -0
  248. package/studio/web/hooks/useAccounts.ts +27 -0
  249. package/studio/web/hooks/useAdmin.ts +12 -0
  250. package/studio/web/hooks/useAnalytics.ts +21 -0
  251. package/studio/web/hooks/useAvatarAudioReactive.ts +87 -0
  252. package/studio/web/hooks/useBrowserConnect.ts +48 -0
  253. package/studio/web/hooks/useClonePlan.ts +14 -0
  254. package/studio/web/hooks/useConnected.ts +7 -0
  255. package/studio/web/hooks/useLiveQuery.ts +29 -0
  256. package/studio/web/hooks/useMenuCollapsed.ts +32 -0
  257. package/studio/web/hooks/useMicDevices.ts +53 -0
  258. package/studio/web/hooks/useMissingDms.ts +211 -0
  259. package/studio/web/hooks/useMissingSetupSteps.ts +26 -0
  260. package/studio/web/hooks/useNow.ts +11 -0
  261. package/studio/web/hooks/useOmniAgent.ts +278 -0
  262. package/studio/web/hooks/useOmniClaude.ts +124 -0
  263. package/studio/web/hooks/useOmniDock.ts +142 -0
  264. package/studio/web/hooks/useOmniGreeting.ts +60 -0
  265. package/studio/web/hooks/useOmniHotword.ts +128 -0
  266. package/studio/web/hooks/useOmnichat.ts +26 -0
  267. package/studio/web/hooks/useOnboarding.ts +27 -0
  268. package/studio/web/hooks/usePost.ts +23 -0
  269. package/studio/web/hooks/useQueue.ts +10 -0
  270. package/studio/web/hooks/useReferences.ts +20 -0
  271. package/studio/web/hooks/useRuleEditor.ts +101 -0
  272. package/studio/web/hooks/useRunner.ts +24 -0
  273. package/studio/web/hooks/useSaveAction.ts +23 -0
  274. package/studio/web/hooks/useSchedule.ts +11 -0
  275. package/studio/web/hooks/useServices.ts +10 -0
  276. package/studio/web/hooks/useSessions.ts +15 -0
  277. package/studio/web/hooks/useSettings.ts +11 -0
  278. package/studio/web/hooks/useSettingsSection.ts +30 -0
  279. package/studio/web/hooks/useSidePanel.ts +23 -0
  280. package/studio/web/hooks/useSound.ts +30 -0
  281. package/studio/web/hooks/useUsage.ts +11 -0
  282. package/studio/web/hooks/useVideoVoice.ts +36 -0
  283. package/studio/web/hooks/useVideos.ts +21 -0
  284. package/studio/web/hooks/useVoiceProfilePreview.ts +52 -0
  285. package/studio/web/hooks/useVoiceProfiles.ts +7 -0
  286. package/studio/web/hooks/useVoiceRunning.ts +10 -0
  287. package/studio/web/hooks/useVoiceStudioClosed.ts +8 -0
  288. package/studio/web/index.html +19 -0
  289. package/studio/web/lib/agent.ts +7 -0
  290. package/studio/web/lib/alerts.ts +210 -0
  291. package/studio/web/lib/analytics-metrics.ts +351 -0
  292. package/studio/web/lib/api.ts +70 -0
  293. package/studio/web/lib/audio.ts +39 -0
  294. package/studio/web/lib/avatars.ts +41 -0
  295. package/studio/web/lib/calendar.ts +218 -0
  296. package/studio/web/lib/caption-position.ts +249 -0
  297. package/studio/web/lib/carousel.ts +24 -0
  298. package/studio/web/lib/chime.ts +42 -0
  299. package/studio/web/lib/clone-voice.ts +55 -0
  300. package/studio/web/lib/export.ts +11 -0
  301. package/studio/web/lib/files.ts +8 -0
  302. package/studio/web/lib/format.ts +93 -0
  303. package/studio/web/lib/media.ts +29 -0
  304. package/studio/web/lib/mic-device.ts +72 -0
  305. package/studio/web/lib/missing-dms.ts +70 -0
  306. package/studio/web/lib/omni-cards.ts +42 -0
  307. package/studio/web/lib/omni-cascade.ts +1067 -0
  308. package/studio/web/lib/omni-greeting-audio.ts +24 -0
  309. package/studio/web/lib/omni-hotword.ts +231 -0
  310. package/studio/web/lib/omni-panel.ts +67 -0
  311. package/studio/web/lib/omni-realtime.ts +811 -0
  312. package/studio/web/lib/omni-ui.ts +402 -0
  313. package/studio/web/lib/omni-wait.ts +174 -0
  314. package/studio/web/lib/omnichat-api.ts +44 -0
  315. package/studio/web/lib/orb.ts +270 -0
  316. package/studio/web/lib/pcm-recorder.ts +115 -0
  317. package/studio/web/lib/platforms.ts +17 -0
  318. package/studio/web/lib/providers.ts +27 -0
  319. package/studio/web/lib/publish-draft.ts +52 -0
  320. package/studio/web/lib/publish-settings.ts +81 -0
  321. package/studio/web/lib/query-client.ts +122 -0
  322. package/studio/web/lib/references.ts +13 -0
  323. package/studio/web/lib/services.ts +40 -0
  324. package/studio/web/lib/sessions.ts +103 -0
  325. package/studio/web/lib/settings-categories.ts +58 -0
  326. package/studio/web/lib/sound-audio.ts +33 -0
  327. package/studio/web/lib/sound-timeline.ts +291 -0
  328. package/studio/web/lib/sse.ts +86 -0
  329. package/studio/web/lib/stage-history.ts +141 -0
  330. package/studio/web/lib/stages.ts +344 -0
  331. package/studio/web/lib/studio-offline.ts +60 -0
  332. package/studio/web/lib/upload.ts +24 -0
  333. package/studio/web/lib/video-tabs.ts +118 -0
  334. package/studio/web/lib/voice-profile-draft.ts +34 -0
  335. package/studio/web/lib/voice-profiles.ts +3 -0
  336. package/studio/web/main.tsx +14 -0
  337. package/studio/web/pages/AdminPage/index.tsx +123 -0
  338. package/studio/web/pages/AgentPage/components/Measurements.tsx +102 -0
  339. package/studio/web/pages/AgentPage/index.tsx +28 -0
  340. package/studio/web/pages/AnalyticsPage/components/About.tsx +52 -0
  341. package/studio/web/pages/AnalyticsPage/components/ChannelCards.tsx +106 -0
  342. package/studio/web/pages/AnalyticsPage/components/ChannelView.tsx +137 -0
  343. package/studio/web/pages/AnalyticsPage/components/CollectionStatus.tsx +46 -0
  344. package/studio/web/pages/AnalyticsPage/components/Comparison.tsx +68 -0
  345. package/studio/web/pages/AnalyticsPage/components/Diagnosis.tsx +50 -0
  346. package/studio/web/pages/AnalyticsPage/components/Highlights.tsx +49 -0
  347. package/studio/web/pages/AnalyticsPage/components/Hint.tsx +11 -0
  348. package/studio/web/pages/AnalyticsPage/components/HookVsBody.tsx +100 -0
  349. package/studio/web/pages/AnalyticsPage/components/HourlyWave.tsx +133 -0
  350. package/studio/web/pages/AnalyticsPage/components/Insights.tsx +70 -0
  351. package/studio/web/pages/AnalyticsPage/components/MetricCard.tsx +46 -0
  352. package/studio/web/pages/AnalyticsPage/components/PlanSection.tsx +40 -0
  353. package/studio/web/pages/AnalyticsPage/components/ProgressionChart.tsx +155 -0
  354. package/studio/web/pages/AnalyticsPage/components/ReelBarsChart.tsx +154 -0
  355. package/studio/web/pages/AnalyticsPage/components/ReelThumb.tsx +19 -0
  356. package/studio/web/pages/AnalyticsPage/components/ReelView.tsx +290 -0
  357. package/studio/web/pages/AnalyticsPage/components/ReelsTable.tsx +269 -0
  358. package/studio/web/pages/AnalyticsPage/components/RequestWithFocus.tsx +38 -0
  359. package/studio/web/pages/AnalyticsPage/components/SegmentedControl.tsx +35 -0
  360. package/studio/web/pages/AnalyticsPage/components/VsMedian.tsx +31 -0
  361. package/studio/web/pages/AnalyticsPage/index.tsx +17 -0
  362. package/studio/web/pages/GettingStartedPage/index.tsx +174 -0
  363. package/studio/web/pages/NewVideoPage/components/DeliverablesPicker.tsx +62 -0
  364. package/studio/web/pages/NewVideoPage/components/FormatPicker.tsx +33 -0
  365. package/studio/web/pages/NewVideoPage/index.tsx +133 -0
  366. package/studio/web/pages/NotFoundPage/index.tsx +9 -0
  367. package/studio/web/pages/OmnichatPage/components/NewFromLink.tsx +59 -0
  368. package/studio/web/pages/OmnichatPage/components/RuleListItem.tsx +64 -0
  369. package/studio/web/pages/OmnichatPage/components/RulePreview.tsx +14 -0
  370. package/studio/web/pages/OmnichatPage/components/RuleView.tsx +88 -0
  371. package/studio/web/pages/OmnichatPage/index.tsx +153 -0
  372. package/studio/web/pages/QueuePage/index.tsx +22 -0
  373. package/studio/web/pages/ReferencePage/components/ReferenceTexts.tsx +131 -0
  374. package/studio/web/pages/ReferencePage/index.tsx +216 -0
  375. package/studio/web/pages/ReferencesPage/components/NewReferenceForm.tsx +150 -0
  376. package/studio/web/pages/ReferencesPage/components/ReferenceCard.tsx +42 -0
  377. package/studio/web/pages/ReferencesPage/components/ReferenceGridSkeleton.tsx +31 -0
  378. package/studio/web/pages/ReferencesPage/index.tsx +67 -0
  379. package/studio/web/pages/SchedulePage/components/CalendarSkeleton.tsx +18 -0
  380. package/studio/web/pages/SchedulePage/components/DayView.tsx +177 -0
  381. package/studio/web/pages/SchedulePage/components/HourPicker.tsx +103 -0
  382. package/studio/web/pages/SchedulePage/components/MonthDayCell.tsx +111 -0
  383. package/studio/web/pages/SchedulePage/components/MonthView.tsx +47 -0
  384. package/studio/web/pages/SchedulePage/components/PlatformIcons.tsx +12 -0
  385. package/studio/web/pages/SchedulePage/components/PostThumb.tsx +15 -0
  386. package/studio/web/pages/SchedulePage/components/WeekColumn.tsx +75 -0
  387. package/studio/web/pages/SchedulePage/components/WeekView.tsx +35 -0
  388. package/studio/web/pages/SchedulePage/index.tsx +285 -0
  389. package/studio/web/pages/SettingsPage/components/AgentAccounts.tsx +263 -0
  390. package/studio/web/pages/SettingsPage/components/AgentCategory.tsx +20 -0
  391. package/studio/web/pages/SettingsPage/components/ModelPicker.tsx +49 -0
  392. package/studio/web/pages/SettingsPage/components/ModelsSettings.tsx +138 -0
  393. package/studio/web/pages/SettingsPage/components/PlatformsCategory.tsx +23 -0
  394. package/studio/web/pages/SettingsPage/components/PublishingCategory/AccountStatus.tsx +29 -0
  395. package/studio/web/pages/SettingsPage/components/PublishingCategory/AutoPublishPanel.tsx +90 -0
  396. package/studio/web/pages/SettingsPage/components/PublishingCategory/BrowserConnect.tsx +62 -0
  397. package/studio/web/pages/SettingsPage/components/PublishingCategory/CheckField.tsx +19 -0
  398. package/studio/web/pages/SettingsPage/components/PublishingCategory/InstagramPanel.tsx +113 -0
  399. package/studio/web/pages/SettingsPage/components/PublishingCategory/OmnichatSettingsPanel.tsx +146 -0
  400. package/studio/web/pages/SettingsPage/components/PublishingCategory/SaveBar.tsx +33 -0
  401. package/studio/web/pages/SettingsPage/components/PublishingCategory/SchedulePanel.tsx +132 -0
  402. package/studio/web/pages/SettingsPage/components/PublishingCategory/SettingsCard.tsx +47 -0
  403. package/studio/web/pages/SettingsPage/components/PublishingCategory/SettingsCardGroup.tsx +19 -0
  404. package/studio/web/pages/SettingsPage/components/PublishingCategory/TextPanel.tsx +55 -0
  405. package/studio/web/pages/SettingsPage/components/PublishingCategory/TiktokPanel.tsx +123 -0
  406. package/studio/web/pages/SettingsPage/components/PublishingCategory/YoutubePanel.tsx +100 -0
  407. package/studio/web/pages/SettingsPage/components/PublishingCategory/badges.tsx +15 -0
  408. package/studio/web/pages/SettingsPage/components/PublishingCategory/index.tsx +40 -0
  409. package/studio/web/pages/SettingsPage/components/PublishingCategory/types.ts +10 -0
  410. package/studio/web/pages/SettingsPage/components/UsageCategory.tsx +389 -0
  411. package/studio/web/pages/SettingsPage/components/VoiceProvidersCategory.tsx +97 -0
  412. package/studio/web/pages/SettingsPage/index.tsx +85 -0
  413. package/studio/web/pages/VideoPage/components/AudioPlayer.tsx +113 -0
  414. package/studio/web/pages/VideoPage/components/CaptionPositionEditor/AxisField.tsx +50 -0
  415. package/studio/web/pages/VideoPage/components/CaptionPositionEditor/CaptionList.tsx +56 -0
  416. package/studio/web/pages/VideoPage/components/CaptionPositionEditor/CaptionListItem.tsx +92 -0
  417. package/studio/web/pages/VideoPage/components/CaptionPositionEditor/CaptionMargins.tsx +57 -0
  418. package/studio/web/pages/VideoPage/components/CaptionPositionEditor/CaptionStyleFields.tsx +70 -0
  419. package/studio/web/pages/VideoPage/components/CaptionPositionEditor/CaptionTextForm.tsx +87 -0
  420. package/studio/web/pages/VideoPage/components/CaptionPositionEditor/ColorField.tsx +37 -0
  421. package/studio/web/pages/VideoPage/components/CaptionPositionEditor/MarginField.tsx +59 -0
  422. package/studio/web/pages/VideoPage/components/CaptionPositionEditor/NumberField.tsx +57 -0
  423. package/studio/web/pages/VideoPage/components/CaptionPositionEditor/PositionControls.tsx +140 -0
  424. package/studio/web/pages/VideoPage/components/CaptionPositionEditor/captionEditor.ts +215 -0
  425. package/studio/web/pages/VideoPage/components/CaptionPositionEditor/useCaptionPosition.ts +154 -0
  426. package/studio/web/pages/VideoPage/components/CarouselChangeRequest.tsx +72 -0
  427. package/studio/web/pages/VideoPage/components/CarouselCompositionStage.tsx +80 -0
  428. package/studio/web/pages/VideoPage/components/CarouselCreate.tsx +63 -0
  429. package/studio/web/pages/VideoPage/components/CarouselMissing.tsx +19 -0
  430. package/studio/web/pages/VideoPage/components/CarouselPublishStage.tsx +173 -0
  431. package/studio/web/pages/VideoPage/components/CarouselScriptStage.tsx +82 -0
  432. package/studio/web/pages/VideoPage/components/CarouselSlideCard.tsx +49 -0
  433. package/studio/web/pages/VideoPage/components/CarouselViewer.tsx +55 -0
  434. package/studio/web/pages/VideoPage/components/ChangedVoices.tsx +53 -0
  435. package/studio/web/pages/VideoPage/components/CompositionStage.tsx +78 -0
  436. package/studio/web/pages/VideoPage/components/CoverPicker.tsx +32 -0
  437. package/studio/web/pages/VideoPage/components/EditorStage.tsx +53 -0
  438. package/studio/web/pages/VideoPage/components/LineTakes.tsx +160 -0
  439. package/studio/web/pages/VideoPage/components/LineTextEditor.tsx +124 -0
  440. package/studio/web/pages/VideoPage/components/LineVoicePicker.tsx +37 -0
  441. package/studio/web/pages/VideoPage/components/MediaImage.tsx +25 -0
  442. package/studio/web/pages/VideoPage/components/MotionScriptStage.tsx +39 -0
  443. package/studio/web/pages/VideoPage/components/NarrationStage.tsx +70 -0
  444. package/studio/web/pages/VideoPage/components/PublishForm.tsx +387 -0
  445. package/studio/web/pages/VideoPage/components/PublishStage.tsx +76 -0
  446. package/studio/web/pages/VideoPage/components/PublishText.tsx +149 -0
  447. package/studio/web/pages/VideoPage/components/ScenesApprovalPanel.tsx +278 -0
  448. package/studio/web/pages/VideoPage/components/ScheduledInfo.tsx +72 -0
  449. package/studio/web/pages/VideoPage/components/ScriptApprovalPanel.tsx +189 -0
  450. package/studio/web/pages/VideoPage/components/ScriptStage.tsx +17 -0
  451. package/studio/web/pages/VideoPage/components/SequencePlayer.tsx +146 -0
  452. package/studio/web/pages/VideoPage/components/SoundTimeline/AddSound.tsx +117 -0
  453. package/studio/web/pages/VideoPage/components/SoundTimeline/AreaSelection.tsx +74 -0
  454. package/studio/web/pages/VideoPage/components/SoundTimeline/BedPanel.tsx +94 -0
  455. package/studio/web/pages/VideoPage/components/SoundTimeline/BedRow.tsx +45 -0
  456. package/studio/web/pages/VideoPage/components/SoundTimeline/CaptionOverlay.tsx +44 -0
  457. package/studio/web/pages/VideoPage/components/SoundTimeline/CaptionSaveBar.tsx +32 -0
  458. package/studio/web/pages/VideoPage/components/SoundTimeline/CaptionsPanel.tsx +22 -0
  459. package/studio/web/pages/VideoPage/components/SoundTimeline/ClipBlock.tsx +111 -0
  460. package/studio/web/pages/VideoPage/components/SoundTimeline/ClipPanel.tsx +76 -0
  461. package/studio/web/pages/VideoPage/components/SoundTimeline/CutsPanel.tsx +44 -0
  462. package/studio/web/pages/VideoPage/components/SoundTimeline/EditorTabBar.tsx +73 -0
  463. package/studio/web/pages/VideoPage/components/SoundTimeline/EffectChoice.tsx +46 -0
  464. package/studio/web/pages/VideoPage/components/SoundTimeline/EffectItem.tsx +89 -0
  465. package/studio/web/pages/VideoPage/components/SoundTimeline/EffectPanel.tsx +232 -0
  466. package/studio/web/pages/VideoPage/components/SoundTimeline/EffectsRow.tsx +21 -0
  467. package/studio/web/pages/VideoPage/components/SoundTimeline/Lane.tsx +39 -0
  468. package/studio/web/pages/VideoPage/components/SoundTimeline/MarkerRow.tsx +40 -0
  469. package/studio/web/pages/VideoPage/components/SoundTimeline/MuteButton.tsx +36 -0
  470. package/studio/web/pages/VideoPage/components/SoundTimeline/NumberInput.tsx +37 -0
  471. package/studio/web/pages/VideoPage/components/SoundTimeline/PlanWarnings.tsx +19 -0
  472. package/studio/web/pages/VideoPage/components/SoundTimeline/PlayerResizeHandle.tsx +50 -0
  473. package/studio/web/pages/VideoPage/components/SoundTimeline/PreviewControls.tsx +51 -0
  474. package/studio/web/pages/VideoPage/components/SoundTimeline/SceneRow.tsx +54 -0
  475. package/studio/web/pages/VideoPage/components/SoundTimeline/SettingsPanel.tsx +65 -0
  476. package/studio/web/pages/VideoPage/components/SoundTimeline/SoundLibrary.tsx +99 -0
  477. package/studio/web/pages/VideoPage/components/SoundTimeline/SoundPreview.tsx +82 -0
  478. package/studio/web/pages/VideoPage/components/SoundTimeline/SpeedPanel.tsx +128 -0
  479. package/studio/web/pages/VideoPage/components/SoundTimeline/TimelineDock.tsx +56 -0
  480. package/studio/web/pages/VideoPage/components/SoundTimeline/TimelineFooter.tsx +26 -0
  481. package/studio/web/pages/VideoPage/components/SoundTimeline/TimelineSkeleton.tsx +21 -0
  482. package/studio/web/pages/VideoPage/components/SoundTimeline/TimelineToolbar.tsx +160 -0
  483. package/studio/web/pages/VideoPage/components/SoundTimeline/TimelineTracks.tsx +121 -0
  484. package/studio/web/pages/VideoPage/components/SoundTimeline/TrackSidebar.tsx +30 -0
  485. package/studio/web/pages/VideoPage/components/SoundTimeline/VoiceRow.tsx +53 -0
  486. package/studio/web/pages/VideoPage/components/SoundTimeline/Waveform.tsx +97 -0
  487. package/studio/web/pages/VideoPage/components/SoundTimeline/clipActions.ts +50 -0
  488. package/studio/web/pages/VideoPage/components/SoundTimeline/effectActions.ts +161 -0
  489. package/studio/web/pages/VideoPage/components/SoundTimeline/index.tsx +161 -0
  490. package/studio/web/pages/VideoPage/components/SoundTimeline/timelineGeometry.ts +45 -0
  491. package/studio/web/pages/VideoPage/components/SoundTimeline/types.ts +43 -0
  492. package/studio/web/pages/VideoPage/components/SoundTimeline/useAutosave.ts +107 -0
  493. package/studio/web/pages/VideoPage/components/SoundTimeline/useEditorShortcuts.ts +168 -0
  494. package/studio/web/pages/VideoPage/components/SoundTimeline/useFitHeight.ts +40 -0
  495. package/studio/web/pages/VideoPage/components/SoundTimeline/useFollowPlayhead.ts +21 -0
  496. package/studio/web/pages/VideoPage/components/SoundTimeline/useListenMix.ts +43 -0
  497. package/studio/web/pages/VideoPage/components/SoundTimeline/usePlayback.ts +231 -0
  498. package/studio/web/pages/VideoPage/components/SoundTimeline/usePlayerWidth.ts +27 -0
  499. package/studio/web/pages/VideoPage/components/SoundTimeline/useSoundData.ts +124 -0
  500. package/studio/web/pages/VideoPage/components/SoundTimeline/useSoundTimeline.ts +511 -0
  501. package/studio/web/pages/VideoPage/components/StageDrawer/CompareVersions.tsx +111 -0
  502. package/studio/web/pages/VideoPage/components/StageDrawer/VersionCard.tsx +81 -0
  503. package/studio/web/pages/VideoPage/components/StageDrawer/VersionMedia.tsx +24 -0
  504. package/studio/web/pages/VideoPage/components/StageDrawer/VersionText.tsx +15 -0
  505. package/studio/web/pages/VideoPage/components/StageDrawer/index.tsx +109 -0
  506. package/studio/web/pages/VideoPage/components/StageProcess.tsx +126 -0
  507. package/studio/web/pages/VideoPage/components/StageResult.tsx +69 -0
  508. package/studio/web/pages/VideoPage/components/SwapReference.tsx +92 -0
  509. package/studio/web/pages/VideoPage/components/ThumbnailPanel.tsx +252 -0
  510. package/studio/web/pages/VideoPage/components/TimingPanel.tsx +89 -0
  511. package/studio/web/pages/VideoPage/components/VideoPlayer.tsx +18 -0
  512. package/studio/web/pages/VideoPage/components/VideoSkeleton.tsx +50 -0
  513. package/studio/web/pages/VideoPage/components/VideoVoiceInfo.tsx +33 -0
  514. package/studio/web/pages/VideoPage/components/VideoVoicePicker.tsx +165 -0
  515. package/studio/web/pages/VideoPage/components/VoicePauseBanner.tsx +56 -0
  516. package/studio/web/pages/VideoPage/components/WithLogo.tsx +10 -0
  517. package/studio/web/pages/VideoPage/index.tsx +295 -0
  518. package/studio/web/pages/VideosPage/components/PublishedOn.tsx +85 -0
  519. package/studio/web/pages/VideosPage/components/ServicesPanel.tsx +81 -0
  520. package/studio/web/pages/VideosPage/components/SessionsPanel.tsx +62 -0
  521. package/studio/web/pages/VideosPage/components/VideoListSkeleton.tsx +25 -0
  522. package/studio/web/pages/VideosPage/components/VideoRow.tsx +122 -0
  523. package/studio/web/pages/VideosPage/index.tsx +134 -0
  524. package/studio/web/pages/VoicePage/index.tsx +28 -0
  525. package/studio/web/router.tsx +201 -0
  526. package/studio/web/styles/base/elements.css +55 -0
  527. package/studio/web/styles/base/utilities.css +25 -0
  528. package/studio/web/styles/components/badge.css +33 -0
  529. package/studio/web/styles/components/claude-running.css +27 -0
  530. package/studio/web/styles/components/claude-session.css +212 -0
  531. package/studio/web/styles/components/claude-walking.css +92 -0
  532. package/studio/web/styles/components/clone-voice-save.css +136 -0
  533. package/studio/web/styles/components/clone-voice.css +379 -0
  534. package/studio/web/styles/components/controls.css +70 -0
  535. package/studio/web/styles/components/data-and-image.css +54 -0
  536. package/studio/web/styles/components/forms.css +132 -0
  537. package/studio/web/styles/components/human-banner.css +99 -0
  538. package/studio/web/styles/components/lightbox.css +50 -0
  539. package/studio/web/styles/components/markdown.css +68 -0
  540. package/studio/web/styles/components/modal.css +70 -0
  541. package/studio/web/styles/components/omni-cards.css +105 -0
  542. package/studio/web/styles/components/omni.css +859 -0
  543. package/studio/web/styles/components/omnichat.css +538 -0
  544. package/studio/web/styles/components/panel.css +115 -0
  545. package/studio/web/styles/components/platform-card.css +140 -0
  546. package/studio/web/styles/components/provider-card.css +132 -0
  547. package/studio/web/styles/components/queue.css +185 -0
  548. package/studio/web/styles/components/reference-actions.css +133 -0
  549. package/studio/web/styles/components/reference-picker.css +146 -0
  550. package/studio/web/styles/components/results-drawer.css +224 -0
  551. package/studio/web/styles/components/segmented.css +115 -0
  552. package/studio/web/styles/components/side-panel-tab.css +23 -0
  553. package/studio/web/styles/components/status-signals.css +66 -0
  554. package/studio/web/styles/components/stepper.css +208 -0
  555. package/studio/web/styles/components/table.css +19 -0
  556. package/studio/web/styles/components/tabs.css +24 -0
  557. package/studio/web/styles/components/ui/accordion.css +71 -0
  558. package/studio/web/styles/components/ui/chart.css +162 -0
  559. package/studio/web/styles/components/ui/checkbox.css +37 -0
  560. package/studio/web/styles/components/ui/date-picker.css +153 -0
  561. package/studio/web/styles/components/ui/select.css +110 -0
  562. package/studio/web/styles/components/ui/skeleton.css +25 -0
  563. package/studio/web/styles/components/ui/slider.css +81 -0
  564. package/studio/web/styles/components/ui/switch.css +41 -0
  565. package/studio/web/styles/components/ui/tooltip.css +24 -0
  566. package/studio/web/styles/components/voice-carousel.css +255 -0
  567. package/studio/web/styles/components/voice-editor.css +179 -0
  568. package/studio/web/styles/components/voice-grid.css +56 -0
  569. package/studio/web/styles/components/voice-profiles.css +192 -0
  570. package/studio/web/styles/design-system.md +136 -0
  571. package/studio/web/styles/index.css +116 -0
  572. package/studio/web/styles/layout/page.css +41 -0
  573. package/studio/web/styles/layout/sidebar-groups.css +39 -0
  574. package/studio/web/styles/layout/sidebar.css +111 -0
  575. package/studio/web/styles/pages/agent.css +26 -0
  576. package/studio/web/styles/pages/analytics/dashboard.css +614 -0
  577. package/studio/web/styles/pages/analytics/insights.css +48 -0
  578. package/studio/web/styles/pages/getting-started.css +166 -0
  579. package/studio/web/styles/pages/new-video/form.css +32 -0
  580. package/studio/web/styles/pages/not-found.css +59 -0
  581. package/studio/web/styles/pages/references.css +204 -0
  582. package/studio/web/styles/pages/schedule/calendar.css +541 -0
  583. package/studio/web/styles/pages/schedule/chip-states.css +60 -0
  584. package/studio/web/styles/pages/settings/models.css +72 -0
  585. package/studio/web/styles/pages/settings/shell.css +361 -0
  586. package/studio/web/styles/pages/settings/usage.css +63 -0
  587. package/studio/web/styles/pages/studio-offline.css +105 -0
  588. package/studio/web/styles/pages/video/caption-controls.css +194 -0
  589. package/studio/web/styles/pages/video/captions-grid.css +70 -0
  590. package/studio/web/styles/pages/video/captions.css +79 -0
  591. package/studio/web/styles/pages/video/editor-chat.css +103 -0
  592. package/studio/web/styles/pages/video/export.css +50 -0
  593. package/studio/web/styles/pages/video/frames.css +29 -0
  594. package/studio/web/styles/pages/video/fullscreen-stage.css +400 -0
  595. package/studio/web/styles/pages/video/instagram-carousel.css +309 -0
  596. package/studio/web/styles/pages/video/layout.css +285 -0
  597. package/studio/web/styles/pages/video/narration.css +138 -0
  598. package/studio/web/styles/pages/video/preview-overview.css +11 -0
  599. package/studio/web/styles/pages/video/processing-notice.css +34 -0
  600. package/studio/web/styles/pages/video/publish-when.css +76 -0
  601. package/studio/web/styles/pages/video/publish.css +97 -0
  602. package/studio/web/styles/pages/video/result.css +96 -0
  603. package/studio/web/styles/pages/video/scenes.css +167 -0
  604. package/studio/web/styles/pages/video/sound-timeline.css +672 -0
  605. package/studio/web/styles/pages/video/sound-toolbar.css +149 -0
  606. package/studio/web/styles/pages/video/take-player.css +100 -0
  607. package/studio/web/styles/pages/video/thumbnail.css +157 -0
  608. package/studio/web/styles/pages/video/timeline.css +117 -0
  609. package/studio/web/styles/pages/video/voice-picker.css +14 -0
  610. package/studio/web/styles/pages/video-list/active-row.css +27 -0
  611. package/studio/web/styles/pages/video-list/card-link.css +49 -0
  612. package/studio/web/styles/pages/video-list/list.css +86 -0
  613. package/studio/web/styles/theme/identity/details.css +204 -0
  614. package/studio/web/styles/theme/identity/shell.css +249 -0
  615. package/studio/web/styles/theme/identity/surfaces.css +183 -0
  616. package/studio/web/styles/theme/identity/titles-and-buttons.css +120 -0
  617. package/studio/web/styles/theme/no-borders/blocks.css +208 -0
  618. package/studio/web/styles/theme/no-borders/controls.css +256 -0
  619. package/studio/web/styles/tokens.css +245 -0
  620. package/studio/web/types/api.ts +2 -0
  621. package/studio/web/types/assets.d.ts +9 -0
  622. package/templates/brief.md +27 -0
  623. package/templates/captions.html +204 -0
  624. package/templates/carousel-composition.md +47 -0
  625. package/templates/carousel-script.md +60 -0
  626. package/templates/components/voiceavatar/README.md +87 -0
  627. package/templates/components/voiceavatar/demo.html +50 -0
  628. package/templates/components/voiceavatar/voiceavatar.js +415 -0
  629. package/templates/motion.md +80 -0
  630. package/templates/playbook.md +43 -0
  631. package/templates/reference.md +123 -0
  632. package/templates/scene.html +112 -0
  633. package/templates/scenes.example.json +96 -0
  634. package/templates/script.md +63 -0
  635. package/templates/slide.html +71 -0
  636. package/templates/wireframe.html +91 -0
  637. package/tools/analysis.mjs +300 -0
  638. package/tools/approval.mjs +442 -0
  639. package/tools/assemble.mjs +942 -0
  640. package/tools/build-motion.mjs +437 -0
  641. package/tools/captions.mjs +246 -0
  642. package/tools/carousel.mjs +558 -0
  643. package/tools/compose.mjs +307 -0
  644. package/tools/cuts.mjs +74 -0
  645. package/tools/editor.mjs +419 -0
  646. package/tools/epidemic-capture.js +54 -0
  647. package/tools/fanout.mjs +69 -0
  648. package/tools/history.mjs +70 -0
  649. package/tools/history.py +61 -0
  650. package/tools/job-queue.mjs +180 -0
  651. package/tools/job_queue.py +430 -0
  652. package/tools/lib/agents.mjs +412 -0
  653. package/tools/lib/channel.mjs +399 -0
  654. package/tools/lib/claude-settings.mjs +67 -0
  655. package/tools/lib/cli.mjs +9 -0
  656. package/tools/lib/fanout.mjs +234 -0
  657. package/tools/lib/http.mjs +94 -0
  658. package/tools/lib/index.js +14 -0
  659. package/tools/lib/mcp-server.mjs +69 -0
  660. package/tools/lib/metrics/metrics.mjs +204 -0
  661. package/tools/lib/narration.mjs +15 -0
  662. package/tools/lib/oauth-client.mjs +295 -0
  663. package/tools/lib/omnichat/config.mjs +139 -0
  664. package/tools/lib/omnichat/errors.mjs +42 -0
  665. package/tools/lib/omnichat/extract.mjs +82 -0
  666. package/tools/lib/omnichat/gate.mjs +151 -0
  667. package/tools/lib/omnichat/manual.mjs +166 -0
  668. package/tools/lib/omnichat/match.mjs +78 -0
  669. package/tools/lib/omnichat/pass.mjs +393 -0
  670. package/tools/lib/omnichat/record.mjs +208 -0
  671. package/tools/lib/omnichat/text.mjs +315 -0
  672. package/tools/lib/omnichat/webhook.mjs +166 -0
  673. package/tools/lib/pairing.mjs +99 -0
  674. package/tools/lib/paths.mjs +41 -0
  675. package/tools/lib/platforms/instagram.mjs +469 -0
  676. package/tools/lib/platforms/tiktok.mjs +343 -0
  677. package/tools/lib/platforms/youtube.mjs +228 -0
  678. package/tools/lib/publish/publish.mjs +244 -0
  679. package/tools/lib/schedule/schedule.mjs +191 -0
  680. package/tools/lib/service.mjs +134 -0
  681. package/tools/lib/skill-client.mjs +126 -0
  682. package/tools/lib/skills-release.mjs +196 -0
  683. package/tools/lib/testing.mjs +52 -0
  684. package/tools/lib/up.mjs +187 -0
  685. package/tools/metrics.mjs +415 -0
  686. package/tools/models.mjs +134 -0
  687. package/tools/narrate.mjs +257 -0
  688. package/tools/omni.mjs +298 -0
  689. package/tools/omni_paths.py +12 -0
  690. package/tools/omnichat.mjs +1577 -0
  691. package/tools/omnivideo.py +1122 -0
  692. package/tools/package.mjs +130 -0
  693. package/tools/platforms.mjs +236 -0
  694. package/tools/premiere.mjs +533 -0
  695. package/tools/publish.mjs +1496 -0
  696. package/tools/reference.mjs +1408 -0
  697. package/tools/render.mjs +426 -0
  698. package/tools/runner.mjs +156 -0
  699. package/tools/setup.mjs +466 -0
  700. package/tools/skills-release.mjs +93 -0
  701. package/tools/sound.mjs +1323 -0
  702. package/tools/soundtrack.mjs +217 -0
  703. package/tools/thumbnail.mjs +271 -0
  704. package/tools/timing.mjs +108 -0
  705. package/tools/usage.py +628 -0
  706. package/tools/voice-envelope.mjs +185 -0
  707. package/tools/voice.py +448 -0
  708. package/tools/voice_sample.py +75 -0
  709. package/tools/wireframe.mjs +230 -0
@@ -0,0 +1,200 @@
1
+ /* An action Omni staged: nothing runs until the user presses Confirmar here, or says yes to Omni, who
2
+ then presses it (confirm_action; the server only takes a card the user has spoken after). */
3
+
4
+ import { useEffect, useRef, useState } from "react";
5
+ import { CaretLeft, CaretRight } from "../icons";
6
+ import type { AgentPendingAction } from "../../types/api";
7
+
8
+ const KIND_TITLE: Record<AgentPendingAction["kind"], string> = {
9
+ change: "Pedir alteração ao Claude",
10
+ create: "Criar conteúdo",
11
+ thumbnail: "Pedir thumbnails",
12
+ publish: "Publicar agora",
13
+ schedule: "Agendar publicação",
14
+ approval: "Responder a aprovação",
15
+ reference: "Pedir edição no estilo visual",
16
+ new_reference: "Criar estilo visual",
17
+ choose_thumbnail: "Escolher a thumbnail",
18
+ analysis: "Pedir análise",
19
+ omnichat: "Mudar o Omnichat",
20
+ omnichat_send: "Mandar o Omnichat",
21
+ };
22
+ const KIND_BUSY: Record<AgentPendingAction["kind"], string> = {
23
+ change: "Enviando…",
24
+ create: "Criando…",
25
+ thumbnail: "Enviando…",
26
+ publish: "Publicando…",
27
+ schedule: "Agendando…",
28
+ approval: "Enviando…",
29
+ reference: "Enviando…",
30
+ new_reference: "Criando…",
31
+ choose_thumbnail: "Aplicando…",
32
+ analysis: "Enviando…",
33
+ omnichat: "Gravando…",
34
+ omnichat_send: "Mandando…",
35
+ };
36
+
37
+ /* a summary past three lines folds, with a "Mostrar tudo" that opens it */
38
+ function Summary({ text }: { text: string }) {
39
+ const ref = useRef<HTMLParagraphElement>(null);
40
+ const [open, setOpen] = useState(false);
41
+ const [long, setLong] = useState(false);
42
+ useEffect(() => {
43
+ const el = ref.current;
44
+ if (!el) return;
45
+ const measure = () => {
46
+ if (!open) setLong(el.scrollHeight > el.clientHeight + 1);
47
+ };
48
+ measure();
49
+ const ro = new ResizeObserver(measure);
50
+ ro.observe(el);
51
+ return () => ro.disconnect();
52
+ }, [text, open]);
53
+ return (
54
+ <>
55
+ <p ref={ref} className={`omni-pending-summary${open ? "" : " clamped"}`}>
56
+ {text}
57
+ </p>
58
+ {(long || open) && (
59
+ <button type="button" className="omni-pending-more" onClick={() => setOpen(o => !o)}>
60
+ {open ? "Mostrar menos" : "Mostrar tudo"}
61
+ </button>
62
+ )}
63
+ </>
64
+ );
65
+ }
66
+
67
+ export function PendingActions({
68
+ actions,
69
+ onResolve,
70
+ }: {
71
+ actions: AgentPendingAction[];
72
+ onResolve: (a: AgentPendingAction, confirm: boolean) => Promise<{ ok: boolean; error?: string }>;
73
+ }) {
74
+ const [busy, setBusy] = useState<string | null>(null);
75
+ const [dragging, setDragging] = useState(false);
76
+ const drag = useRef<{ x: number; left: number; moved: boolean } | null>(null);
77
+ const scroller = useRef<HTMLDivElement>(null);
78
+ const [index, setIndex] = useState(0);
79
+ const [errors, setErrors] = useState<Record<string, string>>({});
80
+ if (!actions.length) return null;
81
+ const act = async (a: AgentPendingAction, confirm: boolean) => {
82
+ setBusy(a.id);
83
+ const r = await onResolve(a, confirm);
84
+ setBusy(null);
85
+ setErrors(e => ({ ...e, [a.id]: r.ok ? "" : (r.error ?? "falhou") }));
86
+ };
87
+ /* mouse drag scrolls the carousel (touch scrolls natively); a drag never presses a button */
88
+ const onPointerDown = (e: React.PointerEvent<HTMLDivElement>) => {
89
+ if (e.pointerType !== "mouse" || e.button !== 0 || actions.length < 2) return;
90
+ if ((e.target as HTMLElement).closest("button")) return;
91
+ drag.current = {
92
+ x: e.clientX,
93
+ left: e.currentTarget.scrollLeft,
94
+ moved: false,
95
+ };
96
+ };
97
+ const onPointerMove = (e: React.PointerEvent<HTMLDivElement>) => {
98
+ const d = drag.current;
99
+ if (!d) return;
100
+ const dx = e.clientX - d.x;
101
+ if (!d.moved && Math.abs(dx) < 4) return;
102
+ if (!d.moved) {
103
+ d.moved = true;
104
+ setDragging(true);
105
+ e.currentTarget.setPointerCapture(e.pointerId);
106
+ }
107
+ e.currentTarget.scrollLeft = d.left - dx;
108
+ };
109
+ const onPointerUp = (e: React.PointerEvent<HTMLDivElement>) => {
110
+ if (!drag.current) return;
111
+ drag.current = null;
112
+ setDragging(false);
113
+ /* snap to the nearest card once released */
114
+ const el = e.currentTarget;
115
+ const card = el.querySelector<HTMLElement>(".omni-pending-card");
116
+ if (!card) return;
117
+ const step = card.offsetWidth + 8;
118
+ el.scrollTo({
119
+ left: Math.round(el.scrollLeft / step) * step,
120
+ behavior: "smooth",
121
+ });
122
+ };
123
+ const stepWidth = () => (scroller.current?.querySelector<HTMLElement>(".omni-pending-card")?.offsetWidth ?? 0) + 8;
124
+ const goTo = (i: number) => {
125
+ const n = Math.max(0, Math.min(actions.length - 1, i));
126
+ scroller.current?.scrollTo({ left: n * stepWidth(), behavior: "smooth" });
127
+ };
128
+ /* the active card follows the scroll (drag, swipe, arrows or dots) */
129
+ const onScroll = (e: React.UIEvent<HTMLDivElement>) => {
130
+ const w = stepWidth();
131
+ if (w > 8) setIndex(Math.round(e.currentTarget.scrollLeft / w));
132
+ };
133
+ const active = Math.min(index, actions.length - 1);
134
+ return (
135
+ <div className="omni-pending-carousel">
136
+ <div
137
+ ref={scroller}
138
+ className={`omni-pending${dragging ? " dragging" : ""}`}
139
+ onPointerDown={onPointerDown}
140
+ onPointerMove={onPointerMove}
141
+ onPointerUp={onPointerUp}
142
+ onPointerCancel={onPointerUp}
143
+ onScroll={onScroll}
144
+ >
145
+ {actions.map(a => (
146
+ <div key={a.id} className="omni-pending-card" role="alert">
147
+ <div className="omni-pending-body">
148
+ <strong>{KIND_TITLE[a.kind]}</strong>
149
+ <Summary text={a.summary} />
150
+ {errors[a.id] && <p className="response error">{errors[a.id]}</p>}
151
+ </div>
152
+ <div className="omni-pending-actions">
153
+ <button type="button" className="button" disabled={busy === a.id} onClick={() => act(a, false)}>
154
+ Cancelar
155
+ </button>
156
+ <button type="button" className="button primary" disabled={busy === a.id} onClick={() => act(a, true)}>
157
+ {busy === a.id ? KIND_BUSY[a.kind] : "Confirmar"}
158
+ </button>
159
+ </div>
160
+ </div>
161
+ ))}
162
+ </div>
163
+ {actions.length > 1 && (
164
+ <div className="omni-pending-nav">
165
+ <button
166
+ type="button"
167
+ className="mini-button omni-icon-button ghost"
168
+ aria-label="Pedido anterior"
169
+ disabled={active === 0}
170
+ onClick={() => goTo(active - 1)}
171
+ >
172
+ <CaretLeft />
173
+ </button>
174
+ <div className="omni-pending-dots" role="tablist" aria-label="Pedidos pendentes">
175
+ {actions.map((a, i) => (
176
+ <button
177
+ key={a.id}
178
+ type="button"
179
+ role="tab"
180
+ aria-selected={i === active}
181
+ aria-label={`Pedido ${i + 1} de ${actions.length}`}
182
+ className={i === active ? "active" : ""}
183
+ onClick={() => goTo(i)}
184
+ />
185
+ ))}
186
+ </div>
187
+ <button
188
+ type="button"
189
+ className="mini-button omni-icon-button ghost"
190
+ aria-label="Próximo pedido"
191
+ disabled={active === actions.length - 1}
192
+ onClick={() => goTo(active + 1)}
193
+ >
194
+ <CaretRight />
195
+ </button>
196
+ </div>
197
+ )}
198
+ </div>
199
+ );
200
+ }
@@ -0,0 +1,127 @@
1
+ /* The conversation as text: what the user said, Omni's replies (with the latency to the first audio
2
+ and 👍/👎) and each tool Omni called, in order. */
3
+
4
+ import { useEffect, useRef } from "react";
5
+ import { Check, ThumbsDown, ThumbsUp, X } from "../icons";
6
+ import type { OmniEntry } from "../../lib/omni-realtime";
7
+
8
+ const TOOL_LABELS: Record<string, string> = {
9
+ list_videos: "Lendo seus conteúdos",
10
+ get_video: "Abrindo o vídeo",
11
+ channel_metrics: "Lendo as métricas do canal",
12
+ queue_status: "Olhando a fila da máquina",
13
+ inspect_content: "Analisando o conteúdo",
14
+ request_change: "Preparando a alteração",
15
+ create_content: "Preparando o conteúdo novo",
16
+ request_thumbnail: "Preparando o pedido de thumbnails",
17
+ prepare_publish: "Preparando a publicação",
18
+ navigate: "Abrindo a tela",
19
+ pending_approvals: "Vendo o que espera você",
20
+ get_motion_script: "Lendo o roteiro de motion",
21
+ answer_approval: "Preparando a resposta da aprovação",
22
+ list_references: "Lendo os estilos visuais",
23
+ get_reference: "Abrindo o estilo visual",
24
+ inspect_reference: "Olhando o estilo visual",
25
+ request_reference_change: "Preparando o pedido para o estilo visual",
26
+ open_claude: "Abrindo o processo do Claude",
27
+ stop_claude: "Parando o Claude",
28
+ write_to_claude: "Escrevendo para o Claude",
29
+ send_to_claude: "Enviando ao Claude",
30
+ create_reference: "Preparando o estilo visual novo",
31
+ choose_thumbnail: "Preparando a escolha da thumbnail",
32
+ request_analysis: "Preparando o pedido de análise",
33
+ omnichat_status: "Lendo o Omnichat",
34
+ set_omnichat: "Configurando o Omnichat",
35
+ omnichat_comments: "Lendo os comentários sem DM",
36
+ send_omnichat: "Preparando o envio do Omnichat",
37
+ confirm_action: "Confirmando",
38
+ cancel_action: "Cancelando",
39
+ control_editor: "Mexendo no player do editor",
40
+ add_epidemic_sound: "Buscando na Epidemic",
41
+ show_card: "Mostrando no painel",
42
+ ask_in_chat: "Abrindo o chat",
43
+ wait_for_work: "Pondo a conversa em espera",
44
+ };
45
+
46
+ export function Transcript({
47
+ entries,
48
+ onFeedback,
49
+ }: {
50
+ entries: OmniEntry[];
51
+ onFeedback: (item: string, value: "up" | "down" | null) => void;
52
+ }) {
53
+ const end = useRef<HTMLDivElement>(null);
54
+ /* follows the reply as it is written, not only when a new message arrives */
55
+ const last = entries.at(-1);
56
+ const tail = last && "text" in last ? last.text.length : 0;
57
+ // biome-ignore lint/correctness/useExhaustiveDependencies: re-runs on purpose when a message arrives or grows
58
+ useEffect(() => {
59
+ end.current?.scrollIntoView({ block: "nearest" });
60
+ }, [entries.length, tail]);
61
+ if (!entries.length) return null;
62
+ return (
63
+ <div className="omni-transcript" aria-live="polite">
64
+ {entries.map(e => {
65
+ if (e.kind === "user")
66
+ return (
67
+ <p key={`u-${e.id}`} className={`omni-msg user${e.pending ? " pending" : ""}`}>
68
+ {e.pending ? "…" : e.text}
69
+ </p>
70
+ );
71
+ if (e.kind === "tool")
72
+ return (
73
+ <p key={e.id} className={`omni-tool ${e.state}`}>
74
+ {e.state === "ok" ? (
75
+ <Check className="ic" />
76
+ ) : e.state === "error" ? (
77
+ <X className="ic" />
78
+ ) : (
79
+ <span className="omni-spinner" aria-hidden="true" />
80
+ )}
81
+ {TOOL_LABELS[e.name] ?? e.name}
82
+ {e.ms != null && <span className="subtle"> · {(e.ms / 1000).toFixed(1)} s</span>}
83
+ {e.detail && <span className="omni-tool-error"> · {e.detail}</span>}
84
+ </p>
85
+ );
86
+ if (e.kind === "note")
87
+ return (
88
+ <p key={e.id} className="omni-note subtle">
89
+ {e.text}
90
+ </p>
91
+ );
92
+ return (
93
+ <div key={`a-${e.id}`} className="omni-msg assistant">
94
+ <p>{e.text || "…"}</p>
95
+ <div className="omni-msg-meta">
96
+ {e.latency_ms != null && (
97
+ <span className="subtle" title={e.breakdown}>
98
+ {(e.latency_ms / 1000).toFixed(2)} s
99
+ </span>
100
+ )}
101
+ {e.breakdown && <span className="subtle omni-breakdown">{e.breakdown}</span>}
102
+ <button
103
+ type="button"
104
+ className={`omni-vote${e.feedback === "up" ? " on" : ""}`}
105
+ onClick={() => onFeedback(e.id, e.feedback === "up" ? null : "up")}
106
+ aria-label="Resposta boa"
107
+ aria-pressed={e.feedback === "up"}
108
+ >
109
+ <ThumbsUp />
110
+ </button>
111
+ <button
112
+ type="button"
113
+ className={`omni-vote${e.feedback === "down" ? " on" : ""}`}
114
+ onClick={() => onFeedback(e.id, e.feedback === "down" ? null : "down")}
115
+ aria-label="Resposta ruim"
116
+ aria-pressed={e.feedback === "down"}
117
+ >
118
+ <ThumbsDown />
119
+ </button>
120
+ </div>
121
+ </div>
122
+ );
123
+ })}
124
+ <div ref={end} />
125
+ </div>
126
+ );
127
+ }
@@ -0,0 +1,87 @@
1
+ /* The account, the comments permission, the agent and the pause. `enabled`: some rule is on
2
+ (then a stopped agent is a warning, not a hint). */
3
+
4
+ import { Link } from "@tanstack/react-router";
5
+ import { formatDayTime } from "../lib/format";
6
+ import type { OmnichatState } from "../types/api";
7
+ import { Skeleton } from "./ui/skeleton";
8
+
9
+ export function OmnichatAccountStatus({ state, enabled = false }: { state: OmnichatState | null; enabled?: boolean }) {
10
+ if (!state) return <Skeleton className="row" aria-busy="true" style={{ width: 240 }} />;
11
+ const { account, comments, agent, pause } = state;
12
+ return (
13
+ <div className="omnichat-account">
14
+ {!account.ready ? (
15
+ <p className="warning">
16
+ Instagram não conectado: {account.reason}. Conecte em{" "}
17
+ <Link to="/settings/$category" params={{ category: "platforms" }} className="link">
18
+ Configurações → Plataformas
19
+ </Link>
20
+ .
21
+ </p>
22
+ ) : comments?.ready === false ? (
23
+ <div className="omnichat-token">
24
+ <p className="warning">
25
+ <strong>A API não lê os comentários de {account.username}.</strong> {comments.reason}
26
+ </p>
27
+ <ol>
28
+ <li>
29
+ Em{" "}
30
+ <a className="link" href="https://developers.facebook.com/apps" target="_blank" rel="noreferrer">
31
+ developers.facebook.com/apps
32
+ </a>{" "}
33
+ → seu app → Instagram → API setup with Instagram login → Generate access tokens, gere o token marcando{" "}
34
+ <code>instagram_business_basic</code>, <code>instagram_business_content_publish</code>,{" "}
35
+ <code>instagram_business_manage_comments</code> e <code>instagram_business_manage_messages</code>.
36
+ </li>
37
+ <li>
38
+ Cole em{" "}
39
+ <Link to="/settings/$category" params={{ category: "platforms" }} className="link">
40
+ Configurações → Plataformas → Instagram
41
+ </Link>
42
+ .
43
+ </li>
44
+ <li>
45
+ Se a DM der erro de permissão: no app do Instagram, Configurações → Mensagens e respostas ao story →
46
+ Controles de mensagens → Ferramentas conectadas → permitir acesso às mensagens.
47
+ </li>
48
+ </ol>
49
+ <p className="hint">
50
+ Passo a passo em <code>reference/omnichat.md</code>.
51
+ </p>
52
+ </div>
53
+ ) : comments && !comments.ready && comments.reason ? (
54
+ <p className="hint">Permissão de comentários sem conferir: {comments.reason}</p>
55
+ ) : null}
56
+ {pause && (
57
+ <p className="warning">
58
+ Em pausa até {formatDayTime(pause.until)}: {pause.reason}
59
+ </p>
60
+ )}
61
+ {agent?.cloud ? (
62
+ agent.cloud.ready ? (
63
+ agent.cloud.active ? null : (
64
+ <p className="warning">
65
+ A cloud está configurada para responder, mas está desligada lá: rode{" "}
66
+ <code>node tools/omnichat.mjs cloud push</code>.
67
+ </p>
68
+ )
69
+ ) : (
70
+ <p className="warning">Não deu para falar com a cloud: {agent.cloud.reason}</p>
71
+ )
72
+ ) : null}
73
+ {agent && !agent.cloud && !agent.loaded && (
74
+ <p className={enabled ? "warning" : "hint"}>
75
+ O agente do omnichat está desligado: nada é respondido sozinho. Ligue em{" "}
76
+ <Link to="/settings/$category" params={{ category: "publishing" }} className="link">
77
+ Configurações → Publicação → Omnichat
78
+ </Link>
79
+ .
80
+ </p>
81
+ )}
82
+ {agent?.installed && !agent.node_ok && (
83
+ <p className="warning">O node que o agente usa não existe mais: desligue e ligue o agente de novo.</p>
84
+ )}
85
+ </div>
86
+ );
87
+ }
@@ -0,0 +1,150 @@
1
+ /* the rule config (collapsed when the rule exists; without a rule, it opens to create one), in steps:
2
+ trigger, message and replies (which also holds how the link is delivered). A new rule walks them with
3
+ Next (the defaults already fill the texts); a saved one jumps straight to the step to change. Save, discard and dry run stay in the
4
+ footer of every step. */
5
+
6
+ import { useState } from "react";
7
+ import type { RuleEditor } from "../../hooks/useRuleEditor";
8
+ import type { OmnichatRuleDetail } from "../../types/api";
9
+ import { ArrowCounterClockwise, ArrowLeft, ArrowRight, Check, FloppyDisk, Play, SlidersHorizontal, X } from "../icons";
10
+ import { Accordion, AccordionContent, AccordionItem, AccordionTrigger } from "../ui/accordion";
11
+ import { STEPS, stepInfo, type StepId } from "./rule-steps";
12
+ import { MessageStep } from "./steps/MessageStep";
13
+ import { RepliesStep } from "./steps/RepliesStep";
14
+ import { TriggerStep } from "./steps/TriggerStep";
15
+ import type { StepProps } from "./steps/types";
16
+
17
+ const BODIES: Record<StepId, (p: StepProps) => React.ReactNode> = {
18
+ trigger: p => <TriggerStep {...p} />,
19
+ message: p => <MessageStep {...p} />,
20
+ replies: p => <RepliesStep {...p} />,
21
+ };
22
+
23
+ export function RuleConfig({
24
+ editor,
25
+ detail: d,
26
+ enabled,
27
+ onBehalf,
28
+ post,
29
+ thePost,
30
+ defaultOpen = false,
31
+ }: {
32
+ editor: RuleEditor;
33
+ detail: OmnichatRuleDetail;
34
+ enabled: boolean;
35
+ onBehalf: string;
36
+ post: string;
37
+ thePost: string;
38
+ /* open from the start even when the rule exists (the rule's own screen) */
39
+ defaultOpen?: boolean;
40
+ }) {
41
+ const { rule, initial, changed, form, setForm, busy, confirmSave, setConfirmSave, save, runDry } = editor;
42
+ const [index, setIndex] = useState(0);
43
+ /* how far a new rule has walked: a step it has not reached shows its number, not a check */
44
+ const [reached, setReached] = useState(0);
45
+ const go = (i: number) => {
46
+ setIndex(i);
47
+ setReached(r => Math.max(r, i));
48
+ };
49
+ const last = index === STEPS.length - 1;
50
+ const step = STEPS[index];
51
+ const infos = STEPS.map(s => stepInfo(s.id, form, d, post));
52
+ /* a saved rule has been through every step; a new one only the ones it walked */
53
+ const seen = (i: number) => !!rule || i <= reached;
54
+ const saveFirst = last || !!rule;
55
+
56
+ return (
57
+ <Accordion
58
+ type="single"
59
+ collapsible
60
+ defaultValue={rule && !defaultOpen ? undefined : "config"}
61
+ className="auto-rule-config"
62
+ >
63
+ <AccordionItem value="config">
64
+ <AccordionTrigger>
65
+ <SlidersHorizontal className="ic" />
66
+ <span>Configuração do chat</span>
67
+ <span className="subtle auto-rule-config-summary">
68
+ {infos[0].summary}
69
+ {changed ? " · não gravado" : ""}
70
+ </span>
71
+ </AccordionTrigger>
72
+ <AccordionContent className="auto-rule-config-fields">
73
+ <ol className="stepper compact rule-steps">
74
+ {STEPS.map((s, i) => {
75
+ const { missing, summary } = infos[i];
76
+ const kind = !seen(i) ? "" : missing ? "warning" : "done";
77
+ return (
78
+ <li key={s.id} className={`step ${kind}${i === index ? " chosen" : ""}`}>
79
+ <button type="button" onClick={() => go(i)} aria-current={i === index ? "step" : undefined}>
80
+ <span className="step-mark">{kind === "done" ? <Check weight="bold" /> : kind ? "!" : i + 1}</span>
81
+ <span className="step-name">{s.name}</span>
82
+ <span className="step-status">{summary}</span>
83
+ </button>
84
+ </li>
85
+ );
86
+ })}
87
+ </ol>
88
+
89
+ <div className="auto-rule-step">{BODIES[step.id]({ editor, detail: d, post, thePost })}</div>
90
+
91
+ {confirmSave && enabled && (
92
+ <p className="warning">
93
+ A regra está ligada: a nova vale na próxima passada e relê os comentários dos últimos 7 dias, respondendo{" "}
94
+ {onBehalf} os que passarem a disparar.
95
+ </p>
96
+ )}
97
+ <div className="actions">
98
+ {index > 0 && !confirmSave && (
99
+ <button className="button" disabled={!!busy} onClick={() => go(index - 1)}>
100
+ <ArrowLeft className="ic" /> Voltar
101
+ </button>
102
+ )}
103
+ {!last && !confirmSave && (
104
+ <button
105
+ className={`button${saveFirst ? "" : " primary"}`}
106
+ disabled={!!busy}
107
+ onClick={() => go(index + 1)}
108
+ >
109
+ Próximo <ArrowRight className="ic" />
110
+ </button>
111
+ )}
112
+ {confirmSave && enabled ? (
113
+ <>
114
+ <button className="button approve" disabled={!!busy} onClick={save}>
115
+ <Check className="ic" /> {busy === "save" ? "Gravando…" : "Confirmar: gravar com a regra ligada"}
116
+ </button>
117
+ <button className="button" disabled={!!busy} onClick={() => setConfirmSave(false)}>
118
+ <X className="ic" /> Cancelar
119
+ </button>
120
+ </>
121
+ ) : (
122
+ <button
123
+ className={`button${saveFirst ? " primary" : ""}`}
124
+ disabled={!!busy || (!changed && !!rule)}
125
+ onClick={() => (enabled ? setConfirmSave(true) : save())}
126
+ >
127
+ <FloppyDisk className="ic" /> {busy === "save" ? "Gravando…" : "Gravar"}
128
+ </button>
129
+ )}
130
+ {changed && rule && !confirmSave && (
131
+ <button className="button" disabled={!!busy} onClick={() => setForm(initial)}>
132
+ <ArrowCounterClockwise className="ic" /> Descartar
133
+ </button>
134
+ )}
135
+ <button
136
+ className="button"
137
+ disabled={!!busy || !rule || changed}
138
+ onClick={runDry}
139
+ title={
140
+ changed ? "Grave antes: a simulação usa a regra gravada" : "Mostra o que mandaria, sem mandar nada"
141
+ }
142
+ >
143
+ <Play className="ic" /> {busy === "dry-run" ? "Simulando…" : "Simular"}
144
+ </button>
145
+ </div>
146
+ </AccordionContent>
147
+ </AccordionItem>
148
+ </Accordion>
149
+ );
150
+ }
@@ -0,0 +1,15 @@
1
+ /* the dry run's output: what the rule would send now, sending nothing */
2
+
3
+ export function RuleDryRun({ output, onClose }: { output: string; onClose: () => void }) {
4
+ return (
5
+ <div className="auto-rule-dry-run">
6
+ <h3>
7
+ Simulação <span className="subtle">o que mandaria agora, sem mandar nada</span>
8
+ <button className="subtle-link" onClick={onClose}>
9
+ Fechar
10
+ </button>
11
+ </h3>
12
+ <pre className="log">{output}</pre>
13
+ </div>
14
+ );
15
+ }
@@ -0,0 +1,42 @@
1
+ /* the second click of turning the rule on: it answers outside, on behalf of the account */
2
+
3
+ import { capitalize } from "../../lib/format";
4
+ import type { RuleEditor } from "../../hooks/useRuleEditor";
5
+ import type { OmnichatRuleDetail } from "../../types/api";
6
+ import { Power, X } from "../icons";
7
+ import { triggerLabel } from "../RuleForm";
8
+
9
+ export function RuleEnableConfirm({
10
+ editor: { form, busy, setConfirm, enable },
11
+ detail: d,
12
+ onBehalf,
13
+ thePost,
14
+ publicReplies,
15
+ }: {
16
+ editor: RuleEditor;
17
+ detail: OmnichatRuleDetail;
18
+ onBehalf: string;
19
+ thePost: string;
20
+ publicReplies: string[];
21
+ }) {
22
+ return (
23
+ <div className="auto-rule-confirm">
24
+ <p>
25
+ <strong>Ligar responde para fora, {onBehalf}.</strong> Quem comentar{" "}
26
+ {triggerLabel({ any_comment: form.any_comment, keywords: form.keywords })} recebe a DM
27
+ {publicReplies.length ? " e uma resposta pública no comentário" : ""}.
28
+ {d.published
29
+ ? ` Os comentários dos últimos 7 dias que disparam também entram${d.defaults.max_per_pass ? `, até ${d.defaults.max_per_pass} por passada` : ""}.`
30
+ : ` ${capitalize(thePost)} ainda não subiu: começa quando ele for publicado.`}
31
+ </p>
32
+ <div className="actions">
33
+ <button className="button approve" disabled={!!busy} onClick={() => enable(true)}>
34
+ <Power className="ic" /> {busy === "enable" ? "Ligando…" : `Confirmar: responder ${onBehalf}`}
35
+ </button>
36
+ <button className="button" disabled={!!busy} onClick={() => setConfirm(false)}>
37
+ <X className="ic" /> Cancelar
38
+ </button>
39
+ </div>
40
+ </div>
41
+ );
42
+ }
@@ -0,0 +1,18 @@
1
+ import { Skeleton } from "../ui/skeleton";
2
+
3
+ /* the rule has not arrived yet: the state, the term, the message and the button, in form order */
4
+ export function RuleSkeleton() {
5
+ return (
6
+ <div
7
+ className="omnichat-rule-skeleton"
8
+ aria-busy="true"
9
+ aria-label="Lendo a regra"
10
+ style={{ display: "flex", flexDirection: "column", gap: 10 }}
11
+ >
12
+ <Skeleton className="row" style={{ width: 200 }} />
13
+ <Skeleton style={{ height: 36, width: "100%", maxWidth: 360 }} />
14
+ <Skeleton style={{ height: 72, width: "100%" }} />
15
+ <Skeleton style={{ height: 32, width: 120 }} />
16
+ </div>
17
+ );
18
+ }