@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,1290 @@
1
+ /* What the studio API returns (api/services/*.ts), shared by api/routes and web/. */
2
+
3
+ import type { NavigateArgs } from "../omni-screens";
4
+
5
+ /* voice-pause.json: voice swapped from the UI and being chosen; what comes after waits for "Seguir" */
6
+ export type VoicePause = {
7
+ since: string;
8
+ lines: string[];
9
+ interrupted: string[];
10
+ claude_stopped: boolean;
11
+ removed?: string[];
12
+ };
13
+
14
+ export type StatusStage = {
15
+ id: string;
16
+ number: string;
17
+ name: string;
18
+ ok: boolean;
19
+ detail: string | null;
20
+ stale?: string[];
21
+ outdated?: boolean;
22
+ /* export: what changed after the export (captions, scenes, motion, voice) */
23
+ changed?: string[];
24
+ pause?: VoicePause | null;
25
+ };
26
+
27
+ export type PipelineStatus = {
28
+ video: string;
29
+ stages: StatusStage[];
30
+ next: { id: string; name: string } | null;
31
+ ready: boolean;
32
+ total_duration: number | null;
33
+ scenes: number;
34
+ lines: number;
35
+ warnings: string[];
36
+ };
37
+
38
+ /* reference swap requested from the UI (motion/reference-swap.json) */
39
+ export type ReferenceSwap = {
40
+ from: string[];
41
+ to: string | null;
42
+ note: string | null;
43
+ requested_at: string;
44
+ applied: boolean;
45
+ };
46
+
47
+ /* approval of the motion script scenes (tools/approval.mjs, motion/approval.json)
48
+ and of the content script (script-approval.json, one item only: "script") */
49
+ export type ApprovalItem = {
50
+ state: "pending" | "approved" | "change_requested";
51
+ comment: string;
52
+ at: string | null;
53
+ by: "user" | "auto" | "literal" | null;
54
+ edited?: boolean;
55
+ };
56
+ export type ApprovalRound = {
57
+ round: number;
58
+ opened_at: string;
59
+ deadline: string;
60
+ /* paused: the user is editing a change request; what is left is in remaining_ms */
61
+ mode: "auto" | "paused";
62
+ paused_at: string | null;
63
+ remaining_ms: number | null;
64
+ completed_at: string | null;
65
+ status: "pending" | "change_requested" | "approved";
66
+ pending_count: number;
67
+ change_requests: { id: string; comment: string }[];
68
+ auto_count: number;
69
+ };
70
+ export type ScenesApproval = ApprovalRound & { scenes: Record<string, ApprovalItem> };
71
+ /* an edit made in the UI writes script.md and approves: `edited` on the item */
72
+ export type ScriptApproval = ApprovalRound & { items: { script: ApprovalItem } };
73
+
74
+ /* --- queue ----------------------------------------------------------------------- */
75
+ export type TicketState = "waiting" | "running" | "ok" | "error" | "interrupted";
76
+
77
+ export type Ticket = {
78
+ id: string;
79
+ tool: string;
80
+ video: string | null;
81
+ dir: string | null;
82
+ command: string;
83
+ pid: number;
84
+ origin: string;
85
+ session: string | null;
86
+ state: TicketState;
87
+ effective: TicketState;
88
+ arrived_at: string;
89
+ started_at: string | null;
90
+ ended_at: string | null;
91
+ exit_code: number | null;
92
+ };
93
+
94
+ export type Queue = { running: Ticket[]; waiting: Ticket[]; recent: Ticket[] };
95
+
96
+ /* --- video summary / detail -------------------------------------------------------- */
97
+ export type VideoFormat = { aspect: string; w: number; h: number; fps: number };
98
+
99
+ export type FileEntry = { path: string; size: number; mtime: number };
100
+
101
+ /* a content's Instagram carousel (api/services/carousel.ts, tools/carousel.mjs) */
102
+ export type Deliverable = "video" | "carousel";
103
+ export type CarouselStage = {
104
+ id: "script" | "composition" | "export" | "publish";
105
+ name: string;
106
+ ok: boolean;
107
+ missing: string | null;
108
+ };
109
+ export type CarouselPublication = {
110
+ caption?: string;
111
+ instagram?: {
112
+ id?: string;
113
+ url?: string | null;
114
+ published_at?: string;
115
+ slides?: number;
116
+ last_error?: { at: string; message: string };
117
+ };
118
+ };
119
+ export type CarouselSummary = {
120
+ title: string | null;
121
+ format: { ratio: string; w: number; h: number } | null;
122
+ slides: number;
123
+ stages: CarouselStage[];
124
+ warnings: string[];
125
+ next: string | null;
126
+ cover: FileEntry | null;
127
+ publication: CarouselPublication | null;
128
+ error?: string;
129
+ };
130
+ export type CarouselSlide = {
131
+ id: string;
132
+ role: "cover" | "content" | "payoff" | "cta" | null;
133
+ title: string | null;
134
+ text: string | null;
135
+ hero: string | null;
136
+ png: FileEntry | null;
137
+ warnings: string[];
138
+ generated_at: string | null;
139
+ };
140
+ export type CarouselDetail = CarouselSummary & {
141
+ goal: string | null;
142
+ caption: string;
143
+ origin: "script" | "video" | null;
144
+ references: string[];
145
+ slide_list: CarouselSlide[];
146
+ sheet: FileEntry | null;
147
+ export: { at: string; jpgs: FileEntry[] } | null;
148
+ texts: { script: string | null; composition: string | null };
149
+ };
150
+
151
+ /* the queue tasks of this video (server summary) */
152
+ export type VideoTasks = { running: Ticket[]; waiting: (Ticket & { position: number })[] };
153
+
154
+ export type VideoSummary = {
155
+ slug: string;
156
+ dir: string;
157
+ /* what the content delivers: video, carousel or both */
158
+ deliverables: Deliverable[];
159
+ /* false: "Sem narração e voz" (no spoken script, narration, voice or captions) */
160
+ narration: boolean;
161
+ carousel: CarouselSummary | null;
162
+ title: string;
163
+ format: VideoFormat | null;
164
+ status: PipelineStatus | null;
165
+ statusError: string | null;
166
+ scenes_approval: ScenesApproval | null;
167
+ script_approval: ScriptApproval | null;
168
+ reference_swap: ReferenceSwap | null;
169
+ tasks?: VideoTasks;
170
+ cover: FileEntry | null;
171
+ /* thumbnail/thumbnail.png, when one is selected (the publication cover) */
172
+ thumbnail: FileEntry | null;
173
+ created: number;
174
+ updated: number;
175
+ publication: Publication | null;
176
+ /* when it was archived; null = in the work list */
177
+ archived: string | null;
178
+ };
179
+
180
+ export type Clip = { from: number; to: number; offset?: number };
181
+ export type Word = { w: string; s: number; e: number };
182
+
183
+ export type Line = {
184
+ id: string;
185
+ text: string;
186
+ wav?: string;
187
+ dur?: number;
188
+ start?: number;
189
+ end?: number;
190
+ provider?: string;
191
+ provider_requested?: string;
192
+ /* the voice (profile) id that spoke the line */
193
+ voice_profile?: string;
194
+ /* the line has its own provider (chosen next to "Gerar outra fala"): the video's does not change it */
195
+ provider_pinned?: boolean;
196
+ instruct?: string | null;
197
+ clips?: Clip[];
198
+ words?: Word[];
199
+ };
200
+
201
+ /* one effect in scenes.json (tools/sound.mjs) */
202
+ export type SoundCue =
203
+ | string
204
+ | {
205
+ name: string;
206
+ offset?: number;
207
+ db?: number;
208
+ anchor?: "peak" | "start";
209
+ trim?: [number, number | null];
210
+ fade?: [number, number];
211
+ dur?: number;
212
+ speed?: number;
213
+ pitch?: number;
214
+ duck?: number | false;
215
+ };
216
+
217
+ export type Beat = {
218
+ element: string;
219
+ t?: number;
220
+ enters_with?: string;
221
+ sound?: SoundCue | SoundCue[];
222
+ };
223
+
224
+ export type Scene = {
225
+ id: string;
226
+ title?: string;
227
+ goal?: string;
228
+ visual?: string;
229
+ hero?: string;
230
+ min_duration?: number;
231
+ duration?: number;
232
+ start?: number;
233
+ html?: string;
234
+ mp4?: string;
235
+ transition?: "cut" | { continues?: string[]; sound?: SoundCue | SoundCue[] };
236
+ beats?: Beat[];
237
+ lines?: Line[];
238
+ lead_in?: number;
239
+ clips?: Clip[];
240
+ /* legacy */
241
+ video_offset?: number;
242
+ };
243
+
244
+ export type HistoryVersion = {
245
+ stage: string;
246
+ key: string | null;
247
+ at: string;
248
+ files: FileEntry[];
249
+ data: Record<string, any>;
250
+ };
251
+
252
+ /* scenes.json, whole */
253
+ export type ScenesFile = {
254
+ title?: string;
255
+ format?: VideoFormat;
256
+ references?: string[];
257
+ scenes: Scene[];
258
+ total_duration?: number;
259
+ voice?: { provider?: string; voice_profile?: string };
260
+ captions?: Record<string, unknown>;
261
+ captions_in_motion?: boolean;
262
+ bed?: unknown;
263
+ cuts?: unknown;
264
+ };
265
+
266
+ export type ResolvedTiming = {
267
+ provisional: boolean;
268
+ total_duration: number;
269
+ scenes: {
270
+ id: string;
271
+ start: number;
272
+ duration: number;
273
+ beats: { element: string; t?: number; error?: string }[];
274
+ lines: { id: string; start: number; end: number }[];
275
+ }[];
276
+ };
277
+
278
+ export type ThumbnailRequest = {
279
+ random: { at: string } | null;
280
+ manual: { at: string; instruction: string } | null;
281
+ changes: Record<string, { at: string; instruction: string }>;
282
+ };
283
+
284
+ export type SoundPlan = {
285
+ items: {
286
+ id: string;
287
+ scene: string;
288
+ element: string;
289
+ name: string;
290
+ start: number;
291
+ peak: number;
292
+ gain_db: number;
293
+ duration?: number;
294
+ anchor?: "peak" | "start";
295
+ }[];
296
+ bed?: { name: string; start: number; duration: number; gain_db: number; duck_db: number } | null;
297
+ voice_lufs?: number;
298
+ warnings: string[];
299
+ };
300
+
301
+ /* --- sound timeline (GET /videos/:slug/sound, api/services/sound.ts getSoundData) ---------- */
302
+
303
+ /* one layer of a place's sound, as the timeline edits it (SoundCue's object form) */
304
+ export type SoundLayer = {
305
+ name: string;
306
+ anchor?: "peak" | "start";
307
+ offset?: number;
308
+ db?: number;
309
+ trim?: [number, number | null];
310
+ fade?: [number, number];
311
+ dur?: number;
312
+ speed?: number;
313
+ pitch?: number;
314
+ duck?: number | false;
315
+ };
316
+ /* a beat or a scene transition that can carry sounds; `instant` in voice time */
317
+ export type SoundPlace = {
318
+ type: "beat" | "transition";
319
+ scene: string;
320
+ element: string;
321
+ instant: number | null;
322
+ error?: string | null;
323
+ sounds: SoundLayer[];
324
+ };
325
+ /* the video's background music (bed) */
326
+ export type SoundBed = {
327
+ name: string;
328
+ db?: number;
329
+ from?: number;
330
+ to?: number;
331
+ trim?: [number, number | null];
332
+ fade?: [number, number];
333
+ loop?: boolean;
334
+ duck?: number | false;
335
+ /* 0.5–2: the music alone, faster or slower, its pitch kept (the export speed never touches it) */
336
+ speed?: number;
337
+ } | null;
338
+ /* an area cut (tools/cuts.mjs), in scenes.json time */
339
+ export type SoundCut = { from: number; to: number };
340
+ /* a sound of the kit or of the video's sfx/ */
341
+ export type SoundEffectInfo = {
342
+ name: string;
343
+ origin: "kit" | "video";
344
+ role: string | null;
345
+ title: string;
346
+ music: boolean;
347
+ duration: number;
348
+ peak_s: number | null;
349
+ useful_end_s: number | null;
350
+ volume_lufs: number | null;
351
+ };
352
+ /* clips (tools/soundtrack.mjs): pieces of a scene's MP4 or of a line's WAV, `from`/`to` in the file and
353
+ `offset` how far the piece moves; `scene_clips` { <scene>: clips } and `line_clips` { <line>: clips } */
354
+ /* `speed` (0.5–2, absent = 1): the piece plays faster and lasts (to − from) / speed (tools/soundtrack.mjs) */
355
+ export type SoundClip = { from: number; to: number; offset: number; speed?: number };
356
+ export type SoundCatalog = {
357
+ kit: SoundEffectInfo[];
358
+ video: SoundEffectInfo[];
359
+ roles: Record<string, { db: number; stretchable?: boolean }>;
360
+ level_db: number;
361
+ ducking: { db: number };
362
+ bed: { level_db: number; ducking_db: number; fade: [number, number] };
363
+ };
364
+ export type SoundData = {
365
+ total: number;
366
+ provisional: boolean;
367
+ format: { w: number; h: number; fps: number };
368
+ scenes: {
369
+ id: string;
370
+ title: string | null;
371
+ start: number;
372
+ duration: number;
373
+ clips: SoundClip[];
374
+ mp4: { path: string; mtime: number } | null;
375
+ }[];
376
+ lines: {
377
+ id: string;
378
+ scene: string;
379
+ start: number;
380
+ end: number;
381
+ dur: number;
382
+ clips: SoundClip[];
383
+ wav: string | null;
384
+ text: string;
385
+ }[];
386
+ places: SoundPlace[];
387
+ bed: SoundBed;
388
+ cuts: SoundCut[];
389
+ /* the export speed, 1 to 1.5: picture, voice and effects; never the bed */
390
+ speed: number;
391
+ catalog: SoundCatalog;
392
+ export: { path: string; mtime: number; cuts: SoundCut[]; scene_clips: Record<string, SoundClip[] | number> } | null;
393
+ /* the export at the chosen speed (export/<slug>-speed-<pct>.mp4), when there is one */
394
+ speed_export: { path: string; mtime: number; speed: number } | null;
395
+ export_outdated: boolean;
396
+ error?: string;
397
+ };
398
+ /* one effect of a draft's plan (POST /videos/:slug/sound/plan, tools/sound.mjs) */
399
+ export type SoundPlanItem = {
400
+ id: string;
401
+ group: string;
402
+ type: "beat" | "transition";
403
+ layer: number;
404
+ scene: string;
405
+ element: string;
406
+ name: string;
407
+ url: string;
408
+ start: number;
409
+ duration: number;
410
+ peak: number;
411
+ beat: number;
412
+ anchor: string;
413
+ gain_db: number;
414
+ volume_lufs: number;
415
+ duck_db: number;
416
+ role: string | null;
417
+ origin: string;
418
+ };
419
+ export type SoundBedItem = {
420
+ name: string;
421
+ url: string;
422
+ start: number;
423
+ duration: number;
424
+ gain_db: number;
425
+ duck_db: number;
426
+ };
427
+ /* a draft's plan: the ready WAVs, the warnings, the voice level and the ducking spans */
428
+ export type SoundDraftPlan = {
429
+ items: SoundPlanItem[];
430
+ bed: SoundBedItem | null;
431
+ warnings: string[];
432
+ voice: { lufs: number; measured: boolean };
433
+ ducking: { db: number; segments: [number, number][] };
434
+ };
435
+ /* the timeline's whole edit: what plan and save receive */
436
+ export type SoundDraft = {
437
+ places: SoundPlace[];
438
+ bed: SoundBed;
439
+ cuts: SoundCut[];
440
+ speed: number;
441
+ scene_clips: Record<string, SoundClip[]>;
442
+ line_clips: Record<string, SoundClip[]>;
443
+ };
444
+
445
+ export type VideoDetail = VideoSummary & {
446
+ root: string;
447
+ history: HistoryVersion[];
448
+ runs: Ticket[];
449
+ scenes: ScenesFile | null;
450
+ resolved: ResolvedTiming | null;
451
+ resolvedError: string | null;
452
+ texts: { script: string | null; motion: string | null; brief: string | null; captions: string | null };
453
+ files: FileEntry[];
454
+ premiere: Record<string, any> | null;
455
+ assembly: Record<string, any> | null;
456
+ thumbnail: ThumbnailManifest | null;
457
+ thumbnailRequest: ThumbnailRequest | null;
458
+ sound: SoundPlan | null;
459
+ renders: Record<string, { start: number; duration: number; video_time: boolean } | null>;
460
+ carousel: CarouselDetail | null;
461
+ };
462
+
463
+ /* thumbnail/thumbnail.json (tools/thumbnail.mjs): the three random ones (v1–v3), the
464
+ user-instructed one (v4) and the one the user picked */
465
+ export type ThumbnailManifest = {
466
+ format: { aspect: string; w: number; h: number };
467
+ generated_at: string;
468
+ versions: {
469
+ id: string;
470
+ name: string;
471
+ description: string | null;
472
+ html: string;
473
+ png: string;
474
+ generated_at?: string;
475
+ instruction?: string | null;
476
+ change?: { at: string; instruction: string };
477
+ }[];
478
+ selected: string | null;
479
+ selected_at?: string;
480
+ };
481
+
482
+ /* --- publication / schedule / accounts ----------------------------------------------- */
483
+ /* publication.json (tools/publish.mjs): the text and the result per platform */
484
+ export type PlatformPublication = {
485
+ id?: string;
486
+ url?: string | null;
487
+ studio?: string;
488
+ privacy?: string | null;
489
+ /* TikTok in draft mode: went to the app inbox */
490
+ draft?: boolean;
491
+ published_at?: string;
492
+ mp4?: string;
493
+ mp4_mtime?: number;
494
+ /* published by the scheduler: the time it was set for */
495
+ scheduled_for?: string;
496
+ /* the selected thumbnail used as cover (YouTube and Instagram) */
497
+ cover?: { version: string; applied: boolean; error?: string };
498
+ last_error?: { at: string; message: string };
499
+ };
500
+ /* `publish.mjs schedule`: the request kept for the day and time; leaves the file once published */
501
+ export type ScheduledPost = {
502
+ when: string;
503
+ platforms: string[];
504
+ privacy: string;
505
+ tiktok_privacy: string;
506
+ republish?: boolean;
507
+ state: "scheduled" | "publishing" | "failed" | "missed";
508
+ attempts: number;
509
+ created_at?: string;
510
+ origin?: string;
511
+ started_at?: string;
512
+ pid?: number;
513
+ next_attempt?: string;
514
+ rescheduled_at?: string;
515
+ last_error?: { at: string; message: string };
516
+ };
517
+ export type LaunchdAgent = {
518
+ installed: boolean;
519
+ loaded: boolean;
520
+ node_ok: boolean;
521
+ log: string;
522
+ /* omnichat only: the cloud answers instead of the agent (omnichat.cloud.owns) */
523
+ cloud?: CloudHealth;
524
+ };
525
+ export type CloudHealth =
526
+ | {
527
+ owns: true;
528
+ ready: true;
529
+ active: boolean;
530
+ expires: string | null;
531
+ pause: { until: string; reason: string } | null;
532
+ }
533
+ | { owns: true; ready: false; reason: string };
534
+ /* GET /api/publish/schedule: `publish.mjs scheduler --json` */
535
+ export type Schedule = {
536
+ error?: string;
537
+ agent?: LaunchdAgent;
538
+ items?: (ScheduledPost & { slug: string; dir: string })[];
539
+ };
540
+ export type Publication = {
541
+ title?: string;
542
+ description?: string;
543
+ /* the same on Instagram and TikTok; caption_instagram is the old name */
544
+ caption?: string;
545
+ caption_instagram?: string;
546
+ tags?: string[];
547
+ text_generated?: { at: string; by: "claude" | "script" };
548
+ youtube?: PlatformPublication;
549
+ instagram?: PlatformPublication;
550
+ tiktok?: PlatformPublication;
551
+ schedule?: ScheduledPost;
552
+ };
553
+ /* GET /api/publish/accounts: `publish.mjs status --json` */
554
+ /* the connected account: `account` is the text line; username (@), name and avatar go to the card */
555
+ export type PlatformAccount = {
556
+ ready: boolean;
557
+ account?: string;
558
+ username?: string | null;
559
+ name?: string | null;
560
+ avatar?: string | null;
561
+ reason?: string;
562
+ };
563
+ export type PlatformAccounts = {
564
+ error?: string;
565
+ youtube?: PlatformAccount & { privacy?: string; audited?: boolean };
566
+ instagram?: PlatformAccount & { expires?: string | null };
567
+ tiktok?: PlatformAccount & { expires?: string | null; mode?: string; privacy?: string; audited?: boolean };
568
+ auto?: { approved: boolean; platforms: string[] };
569
+ scheduler?: LaunchdAgent;
570
+ };
571
+
572
+ /* --- omnichat on Instagram (tools/omnichat.mjs, api/services/omnichat.ts) ------------------ */
573
+ /* <dir>/omnichat.json, key instagram: the rule. Born disabled */
574
+ export type OmnichatRule = {
575
+ enabled: boolean;
576
+ keywords: string[];
577
+ /* any comment triggers */
578
+ any_comment: boolean;
579
+ link: string;
580
+ /* {username} and {link} are replaced; without {link}, it goes at the end */
581
+ dm: string;
582
+ /* one drawn per comment; empty = DM only; without the key, the config ones */
583
+ public_replies?: string[];
584
+ /* comment the account already answered by hand: skip, or send anyway (only if the
585
+ account's reply contains one of already_replied_if, when set) */
586
+ already_replied?: "skip" | "send";
587
+ already_replied_if?: string[];
588
+ /* generic requests ("quero", "me manda", "link"…, config omnichat.instagram.generic_phrases)
589
+ also trigger; mid-sentence, the agent reads the post context first. Without the key, true */
590
+ generic_phrases?: boolean;
591
+ /* what the DM delivers, in words, for Claude to read the context; empty, the caption and the link */
592
+ offer?: string;
593
+ /* the commented Reel link on the DM's first line (without {post} in the text): Instagram shows the
594
+ Reel card and the message reads as a reply to it. Without the key, false */
595
+ quote_post?: boolean;
596
+ /* the DM opens with a button and the link goes out when the person taps it (needs the webhook) */
597
+ button?: boolean;
598
+ /* the tap only delivers if the person follows the account (implies the button) */
599
+ require_follow?: boolean;
600
+ /* text above the button, the button, what goes to someone who taps without following and its button;
601
+ empty = the config's */
602
+ opening_dm?: string;
603
+ button_label?: string;
604
+ not_following_dm?: string;
605
+ retry_label?: string;
606
+ /* the link goes in a button that opens it ("Abrir link"), not in the DM's text */
607
+ link_button?: boolean;
608
+ link_label?: string;
609
+ /* false: whoever says they follow without following never gets "Receber sem seguir" (on without the key) */
610
+ follow_skip?: boolean;
611
+ skip_label?: string;
612
+ /* the DM of whoever got the link through that button; empty = the config's */
613
+ skip_dm?: string;
614
+ updated_at?: string;
615
+ enabled_at?: string;
616
+ disabled_at?: string;
617
+ };
618
+ export type OmnichatTotals = {
619
+ triggers: number;
620
+ dms: number;
621
+ public_replies: number;
622
+ queued: number;
623
+ uncertain?: number;
624
+ failures: number;
625
+ /* gated rules: opener sent, waiting for the tap or the follow / link delivered */
626
+ awaiting?: number;
627
+ delivered?: number;
628
+ };
629
+ export type OmnichatCommentState = "queued" | "retry" | "done" | "failed" | "skipped" | "uncertain";
630
+ /* one comment of omnichat-record.json, as `log --json` returns it */
631
+ export type OmnichatComment = {
632
+ id: string;
633
+ username: string | null;
634
+ text: string;
635
+ commented_at: string;
636
+ /* uncertain: generic request that Claude has not read in context yet */
637
+ state: OmnichatCommentState;
638
+ attempts?: number;
639
+ pauses?: number;
640
+ uncertain_count?: number;
641
+ error?: string;
642
+ reason?: string;
643
+ account_reply?: string | null;
644
+ context?: string | null;
645
+ manual?: boolean;
646
+ manual_at?: string;
647
+ dm?:
648
+ | { at: string; id: string | null; text?: string; error?: undefined }
649
+ | { error: string; failed_at: string; at?: undefined; text?: undefined };
650
+ /* rule with a button: where the person is after the opener */
651
+ gate?: {
652
+ state: "awaiting_tap" | "awaiting_follow" | "delivered";
653
+ via?: "button" | "quick_reply";
654
+ taps?: number;
655
+ last_tap_at?: string;
656
+ delivered_at?: string;
657
+ skipped_follow?: boolean;
658
+ };
659
+ /* manual: written in the UI and sent only as a comment, no DM (`send --public-only`) */
660
+ public_reply?:
661
+ | { at: string; id: string | null; text: string; manual?: boolean; error?: undefined }
662
+ | { error: string; failed_at: string; at?: undefined };
663
+ };
664
+ /* POST …/omnichat/comments: the Reel read now, and who did not get the DM */
665
+ export type MissingDmItem = {
666
+ id: string;
667
+ username: string | null;
668
+ text: string;
669
+ commented_at: string;
670
+ /* what the agent already did with it; null: did not trigger, or not read yet */
671
+ state: OmnichatCommentState | null;
672
+ reason: string | null;
673
+ triggers: "yes" | "uncertain" | false;
674
+ account_reply: string | null;
675
+ /* Meta only accepts the DM up to 7 days after the comment */
676
+ within_deadline: boolean;
677
+ };
678
+ /* a reply nested in a comment: a person's, the account's own, or the account's loose "@person" comment */
679
+ export type ThreadReply = {
680
+ id: string;
681
+ username: string | null;
682
+ text: string;
683
+ at: string;
684
+ own: boolean;
685
+ loose?: boolean;
686
+ };
687
+ /* a top-level comment of the post as a chat card, with what is nested in it */
688
+ export type ThreadComment = ThreadReply & {
689
+ replies: ThreadReply[];
690
+ /* the DM that went; `exact` false: the rule's text as it reads today (older records did not keep it) */
691
+ dm: { at: string; text: string | null; exact: boolean; gate: string | null } | null;
692
+ state: OmnichatCommentState | null;
693
+ reason: string | null;
694
+ triggers: "yes" | "uncertain" | false;
695
+ within_deadline: boolean;
696
+ };
697
+ export type MissingDmList = {
698
+ checked_at: string;
699
+ read: number;
700
+ truncated: boolean;
701
+ without_dm: number;
702
+ items: MissingDmItem[];
703
+ /* every comment with its replies nested (the chat); `items` is the ones without the DM */
704
+ thread: ThreadComment[];
705
+ };
706
+ /* POST …/omnichat/comments/delete: one per comment */
707
+ export type DeletedComment = { id: string; state: string; reason: string | null };
708
+ /* POST …/omnichat/send: one per chosen comment */
709
+ export type ManualSend = {
710
+ id: string;
711
+ username?: string | null;
712
+ state: string;
713
+ public_reply?: boolean;
714
+ reason: string | null;
715
+ };
716
+ export type OmnichatLog = {
717
+ totals: OmnichatTotals;
718
+ checked_at: string | null;
719
+ warning: string | null;
720
+ items: OmnichatComment[];
721
+ };
722
+ /* one item of the rule list (GET /api/omnichat) */
723
+ export type OmnichatRuleSummary = {
724
+ /* a video's Reel, a content's carousel (videos/<slug>/carousel) or an outside post */
725
+ type: "video" | "post" | "carousel";
726
+ /* video slug (also the carousel's) or post code */
727
+ id: string;
728
+ dir: string;
729
+ enabled: boolean;
730
+ published: boolean;
731
+ post: string | null;
732
+ published_at: string | null;
733
+ /* null: any comment */
734
+ keywords: string[] | null;
735
+ updated_at: string | null;
736
+ totals: OmnichatTotals | null;
737
+ checked_at: string | null;
738
+ warning: string | null;
739
+ log_error: string | null;
740
+ };
741
+ /* GET /api/videos/<slug>/omnichat, /api/videos/<slug>/carousel/omnichat and /api/omnichat/posts/<code> */
742
+ export type OmnichatRuleDetail = Omit<
743
+ OmnichatRuleSummary,
744
+ "enabled" | "keywords" | "updated_at" | "totals" | "checked_at" | "warning"
745
+ > & {
746
+ rule: OmnichatRule | null;
747
+ /* what a new rule gets and how many go per pass (config omnichat.instagram) */
748
+ defaults: {
749
+ dm: string | null;
750
+ public_replies: string[] | null;
751
+ max_per_pass: number | null;
752
+ quote_post: boolean;
753
+ opening_dm: string | null;
754
+ button_label: string | null;
755
+ not_following_dm: string | null;
756
+ retry_label: string | null;
757
+ link_label: string | null;
758
+ skip_label: string | null;
759
+ skip_dm: string | null;
760
+ };
761
+ /* video: the first URL of the description, brief.md or source/request.md (social networks don't
762
+ count), which a new rule gets as link; `found_in` says where ("no brief.md") */
763
+ found_link: { link: string; found_in: string } | null;
764
+ /* video: with `enable` (omnichat.instagram.enable_on_publish), a rule not enabled yet turns on
765
+ when the Reel goes up; without a rule, `term` is what the narration asks ("comenta REA…") */
766
+ on_publish: { enable: boolean; term: string | null } | null;
767
+ log: OmnichatLog | null;
768
+ };
769
+ /* GET /api/omnichat: account and comments permission (cached 2 min), agent, pause and rules */
770
+ export type OmnichatState = {
771
+ agent: LaunchdAgent | null;
772
+ pause: { until: string; reason: string; at: string } | null;
773
+ account:
774
+ | { ready: true; username: string; expires: string | null }
775
+ | { ready: false; reason: string; username?: undefined };
776
+ /* ready null: no recent post with a comment to check */
777
+ comments: { ready: boolean | null; reason?: string } | null;
778
+ checked_at: string;
779
+ rules?: OmnichatRuleSummary[];
780
+ };
781
+
782
+ /* --- sessions -------------------------------------------------------------------------- */
783
+ export type TurnResult = {
784
+ duration_ms: number | null;
785
+ cost: number | null;
786
+ text: string;
787
+ error: boolean;
788
+ denied: string[];
789
+ };
790
+
791
+ export type SessionType = "video" | "reference" | "analysis" | "edit" | "omni";
792
+ export type SessionState = "running" | "stopped" | "error" | "interrupted";
793
+
794
+ export type Session = {
795
+ id: string;
796
+ /* "analysis": the Analytics page session (target "channel"), with the av-analysis skill */
797
+ type: SessionType;
798
+ target: string;
799
+ title: string;
800
+ created_at: string;
801
+ state: SessionState;
802
+ activity: number;
803
+ turns: number;
804
+ turn: {
805
+ n: number;
806
+ origin: string;
807
+ prompt: string;
808
+ started_at: string;
809
+ pid: number;
810
+ result: TurnResult | null;
811
+ } | null;
812
+ now: string | null;
813
+ total_cost: number;
814
+ };
815
+ /* server name for the same shape */
816
+ export type SessionSummary = Session;
817
+
818
+ /* --- references -------------------------------------------------------------------------- */
819
+ export type Color = { hex: string; name: string };
820
+
821
+ export type ReferenceSummary = {
822
+ name: string;
823
+ enabled: boolean;
824
+ title: string;
825
+ essence: string | null;
826
+ guide: string | null;
827
+ measurements: {
828
+ duration: number;
829
+ w: number;
830
+ h: number;
831
+ fps: number;
832
+ shots: number | null;
833
+ hold_pct: number | null;
834
+ strip: string | null;
835
+ step: number | null;
836
+ bpm: number | null;
837
+ source: string | null;
838
+ } | null;
839
+ palette: Color[];
840
+ cover: FileEntry | null;
841
+ frame: FileEntry | null;
842
+ video: FileEntry | null;
843
+ images: number;
844
+ videos: number;
845
+ updated: number;
846
+ };
847
+
848
+ export type ReferenceDetail = ReferenceSummary & {
849
+ dir: string;
850
+ files: FileEntry[];
851
+ texts: { path: string; type: string; text: string }[];
852
+ used_in: { slug: string; title: string }[];
853
+ };
854
+
855
+ /* --- services / usage -------------------------------------------------------------------- */
856
+ export type VoiceProviderStatus = { id: string; name: string; default: boolean; ready: boolean; reason: string | null };
857
+
858
+ export type Services = {
859
+ voicestudio: { ok: boolean; url: string; version: string | null; device: string | null };
860
+ voices: VoiceProviderStatus[];
861
+ premiere: { ok: boolean; started: boolean; age_ms: number | null };
862
+ /* pressure is shown to the user as is: "normal" | "atenção" | "crítica" */
863
+ memory: { swap_total_mb: number; swap_used_mb: number; free_pct: number; pressure: string; total_gb: number };
864
+ at: number;
865
+ };
866
+
867
+ /* voice usage (tools/usage.py summary --json) */
868
+ export type UsageProviderRun = {
869
+ lines: number;
870
+ bytes: number;
871
+ chars: number;
872
+ audio_s: number;
873
+ lines_free?: number;
874
+ bytes_paid?: number;
875
+ estimated_usd?: number;
876
+ platform?: number;
877
+ estimated_credits?: number;
878
+ };
879
+
880
+ export type UsageRun = {
881
+ run: string;
882
+ at: string;
883
+ video: string | null;
884
+ providers: Record<string, UsageProviderRun>;
885
+ failures: { provider: string; line: string | null; reason: string | null }[];
886
+ };
887
+
888
+ export type UsageData = {
889
+ generated_at: string;
890
+ cycle: { start: string; end: string };
891
+ fish: {
892
+ name: string;
893
+ key: boolean;
894
+ voice_id: string | null;
895
+ model: string;
896
+ fallback_model: string | null;
897
+ balance: { credit: number | null; cumulative_top_up: number | null; at: string | null };
898
+ cycle: {
899
+ lines: number;
900
+ lines_free: number;
901
+ chars: number;
902
+ bytes: number;
903
+ bytes_paid: number;
904
+ estimated_usd: number;
905
+ platform: number | null;
906
+ platform_since: string | null;
907
+ };
908
+ price_usd_per_million_bytes: number;
909
+ };
910
+ cartesia: {
911
+ name: string;
912
+ key: boolean;
913
+ admin_key: boolean;
914
+ voice_id: string | null;
915
+ plan: string;
916
+ cycle_day: number;
917
+ quota: number;
918
+ used: number;
919
+ source: "platform" | "estimated";
920
+ read_at: string | null;
921
+ estimated: number;
922
+ remaining: number;
923
+ fraction: number;
924
+ cycle: { lines: number; chars: number };
925
+ };
926
+ voicestudio: { name: string; lines: number; audio_s: number };
927
+ by_video: {
928
+ video: string;
929
+ lines: number;
930
+ fish_usd: number;
931
+ cartesia_credits: number;
932
+ audio_s: number;
933
+ providers: string[];
934
+ }[];
935
+ runs: UsageRun[];
936
+ warnings: string[];
937
+ refresh: { live: boolean; errors: string[] };
938
+ };
939
+
940
+ export type Usage = UsageData | { error: string };
941
+
942
+ /* --- settings ---------------------------------------------------------------------------- */
943
+ export type KeyStatus = { name: string; masked: string | null; in_env: boolean };
944
+
945
+ export type ModelChoice = { model: string; effort?: string };
946
+
947
+ /* one voice: what it has on each provider and the try order (the first is preferred) */
948
+ export type VoiceProfile = {
949
+ id: string;
950
+ name: string;
951
+ order: string[];
952
+ fish: string | null;
953
+ cartesia: string | null;
954
+ voicestudio: string | null;
955
+ elevenlabs: string | null;
956
+ avatar?: string | null;
957
+ };
958
+
959
+ export type Settings = {
960
+ voice: {
961
+ /* voice.order: the first is the default, the others are fallback */
962
+ order: string[];
963
+ /* voice profiles: the Fish and Cartesia voice_id under one name; default_profile is the id checked on a new video */
964
+ profiles: VoiceProfile[];
965
+ default_profile: string | null;
966
+ voicestudio: { profile: string | null };
967
+ fish: {
968
+ key: KeyStatus;
969
+ voice_id: string | null;
970
+ model: string;
971
+ fallback_model: string | null;
972
+ usd_per_million_bytes: number | null;
973
+ };
974
+ cartesia: {
975
+ key: KeyStatus;
976
+ admin_key: KeyStatus;
977
+ voice_id: string | null;
978
+ plan: string;
979
+ monthly_quota: number;
980
+ cycle_day: number;
981
+ };
982
+ elevenlabs: { key: KeyStatus; voice_id: string | null; model: string };
983
+ };
984
+ publish: {
985
+ auto: { approved: boolean; platforms: string[] };
986
+ text: { footer_youtube: string; footer_instagram: string; footer_tiktok: string; hashtags: string[] };
987
+ youtube: {
988
+ privacy: string;
989
+ audited: boolean;
990
+ category: string;
991
+ language: string;
992
+ made_for_kids: boolean;
993
+ synthetic_content: boolean;
994
+ };
995
+ instagram: { api_version: string; share_to_feed: boolean; cover_at_s: number | null };
996
+ tiktok: {
997
+ mode: "direct" | "draft";
998
+ privacy: string;
999
+ audited: boolean;
1000
+ comments: boolean;
1001
+ duet: boolean;
1002
+ stitch: boolean;
1003
+ ai_content: boolean;
1004
+ cover_at_s: number | null;
1005
+ };
1006
+ schedule: { max_delay_h: number; attempts: number; interval_min: number };
1007
+ keys: {
1008
+ youtube_client_id: KeyStatus;
1009
+ youtube_client_secret: KeyStatus;
1010
+ youtube_connected: boolean;
1011
+ instagram_connected: boolean;
1012
+ tiktok_client_key: KeyStatus;
1013
+ tiktok_client_secret: KeyStatus;
1014
+ tiktok_connected: boolean;
1015
+ };
1016
+ };
1017
+ models: {
1018
+ orchestrator: ModelChoice | null;
1019
+ reference: ModelChoice | null;
1020
+ stages: (ModelChoice & {
1021
+ stage: string;
1022
+ in_skill: { model: string | null; effort: string | null; fork: boolean } | null;
1023
+ })[];
1024
+ options: { models: string[]; efforts: string[] };
1025
+ };
1026
+ /* omnichat.instagram: the rule turns on by itself when the Reel goes up; a new rule quotes the Reel in the DM */
1027
+ omnichat: { enable_on_publish: boolean; quote_post: boolean };
1028
+ agents: AgentsSettings;
1029
+ };
1030
+
1031
+ /* the agent accounts (agents in the config; tools/lib/agents.mjs): N Claude dirs and N Codex homes,
1032
+ in rotation order */
1033
+ export type AgentProvider = "claude" | "codex";
1034
+ export type AgentAccount = {
1035
+ id: string;
1036
+ provider: AgentProvider;
1037
+ dir: string;
1038
+ label: string;
1039
+ enabled: boolean;
1040
+ login: { email: string | null; detail: string | null } | null;
1041
+ /* over its usage limit until then (ms) */
1042
+ limited_until: number | null;
1043
+ login_command: string;
1044
+ logging_in: { state: "waiting" | "ok" | "error"; url: string | null; output: string; at: number } | null;
1045
+ };
1046
+ export type AgentsSettings = {
1047
+ accounts: AgentAccount[];
1048
+ next: string | null;
1049
+ codex: {
1050
+ model: string;
1051
+ effort?: string;
1052
+ sandbox: string;
1053
+ bin: string;
1054
+ installed: boolean;
1055
+ options: { models: { id: string; label: string; efforts: string[] }[]; sandboxes: string[] };
1056
+ };
1057
+ };
1058
+
1059
+ /* --- getting started (/api/onboarding): the guide (docs/onboarding.md) in steps, each with the
1060
+ tools/setup.mjs check -------------------------------------------------------------------- */
1061
+ export type OnboardingCheck = { id: string; title: string; state: "ok" | "missing" | "warning"; detail: string };
1062
+ export type OnboardingStep = {
1063
+ id: string;
1064
+ title: string;
1065
+ markdown: string;
1066
+ state: OnboardingCheck["state"] | null;
1067
+ optional: boolean;
1068
+ items: OnboardingCheck[];
1069
+ };
1070
+ export type Onboarding = { ready: boolean; checked: boolean; intro: string; steps: OnboardingStep[]; error?: string };
1071
+
1072
+ /* --- analytics (tools/analysis.mjs context; metrics from tools/metrics.mjs) ----------------- */
1073
+ export type MetricsSnapshot = {
1074
+ milestone?: string;
1075
+ at: string;
1076
+ age_h: number;
1077
+ views: number | null;
1078
+ reach: number | null;
1079
+ likes: number | null;
1080
+ comments: number | null;
1081
+ saves: number | null;
1082
+ shares: number | null;
1083
+ interactions: number | null;
1084
+ avg_watch_s: number | null;
1085
+ watched_pct: number | null;
1086
+ skip_3s_pct: number | null;
1087
+ total_watch_h: number | null;
1088
+ };
1089
+ export type ComparableMetric =
1090
+ | "views"
1091
+ | "reach"
1092
+ | "skip_3s_pct"
1093
+ | "watched_pct"
1094
+ | "avg_watch_s"
1095
+ | "saves"
1096
+ | "shares"
1097
+ | "comments"
1098
+ | "likes"
1099
+ | "saves_per_k"
1100
+ | "shares_per_k"
1101
+ | "comments_per_k";
1102
+ export type Medians = { n: number } & Record<ComparableMetric, number | null>;
1103
+ export type MediansByMilestone = Record<"current" | "24h" | "72h", Medians>;
1104
+ export type ReelMetrics = {
1105
+ slug: string;
1106
+ title: string | null;
1107
+ cover: FileEntry | null;
1108
+ published_at: string;
1109
+ url: string | null;
1110
+ duration_s: number | null;
1111
+ current: MetricsSnapshot | null;
1112
+ snapshots: MetricsSnapshot[];
1113
+ error: { at: string; message: string } | null;
1114
+ removed: boolean;
1115
+ pillar: string | null;
1116
+ goal: string | null;
1117
+ promise: string | null;
1118
+ hook: { line: string | null; frame0: string | null; text: string | null; type: string | null } | null;
1119
+ first_line: string | null;
1120
+ analysis: { at: string } | null;
1121
+ opening: boolean;
1122
+ /* readings kept every 4 hours (the series comes only in the Reel detail) */
1123
+ n_hourly: number;
1124
+ };
1125
+ export type AccountSnapshot = {
1126
+ day: string;
1127
+ at: string;
1128
+ username: string;
1129
+ followers: number | null;
1130
+ following: number | null;
1131
+ posts: number | null;
1132
+ profile_visits_day: number | null;
1133
+ };
1134
+ export type Analytics =
1135
+ | {
1136
+ generated_at: string;
1137
+ account: AccountSnapshot[];
1138
+ medians: MediansByMilestone;
1139
+ /* the hourly sum of the Reels (last 30 days) and the Reels published in that range */
1140
+ progression: { t: number; views: number; comments: number; saves: number; followers: number | null }[];
1141
+ publications: { t: number; slug: string; title: string | null }[];
1142
+ /* the 3 s skip range before OmniVideo, if the playbook says so */
1143
+ before: { skip_3s_pct: [number, number] } | null;
1144
+ videos: ReelMetrics[];
1145
+ agent: { installed: boolean; loaded: boolean; log: string };
1146
+ last_analysis: { file: string; day: string; at: string; text: string | null } | null;
1147
+ playbook: boolean;
1148
+ }
1149
+ | { error: string };
1150
+ export type ReelDetail =
1151
+ | (ReelMetrics & { hourly: MetricsSnapshot[]; medians: MediansByMilestone; analysis_text: string | null })
1152
+ | { error: string };
1153
+
1154
+ /* --- the hosted studio's runner (GET /api/runner; the hub answers it in cloud/studio) -------------- */
1155
+ /* what kept the Mac out (cloud/studio/src/presence.mjs): its key refused (it pairs again by itself), the
1156
+ protocol versions apart (`side` is the one to update), or disconnected by the user at /runner */
1157
+ export type RunnerProblem =
1158
+ | { reason: "key"; at: string; host?: string }
1159
+ | { reason: "protocol"; at: string; side: "mac" | "cloud"; host?: string }
1160
+ | { reason: "revoked"; at: string; name?: string };
1161
+
1162
+ /* --- the admin panel (GET /api/admin) ------------------------------------------------------------ */
1163
+ export type OmniAdminSettings = {
1164
+ enabled: boolean;
1165
+ engine: "grok" | "stream" | "chunks";
1166
+ voice: string;
1167
+ fish_model: string;
1168
+ llm: string;
1169
+ };
1170
+ export type AdminInfo = {
1171
+ /* this studio on the Mac is always admin; the hosted one, the emails in admin.emails */
1172
+ admin: boolean;
1173
+ email: string | null;
1174
+ hosted: boolean;
1175
+ omni: OmniAdminSettings | null;
1176
+ };
1177
+
1178
+ /* --- Omni, the voice agent (GET /api/agent, POST /api/agent/session) --------------------------- */
1179
+ export type AgentGender = "female" | "male";
1180
+ export type AgentConfig = {
1181
+ /* false: Omni is off (the widget hides) */
1182
+ enabled: boolean;
1183
+ /* the agent saved in console.x.ai (persona, greeting, keyterms, silence); null = the app's own */
1184
+ xai_agent_id: string | null;
1185
+ /* what Omni runs on, for every user (the admin panel, agent.engine) */
1186
+ engine: "grok" | "stream" | "chunks";
1187
+ gender: AgentGender;
1188
+ /* Omni's face: the seed of its avatar */
1189
+ avatar: string;
1190
+ voices: Record<AgentGender, string>;
1191
+ model: string;
1192
+ language: string;
1193
+ /* Grok asks "Ainda tá aí?" after nudge_s of silence; the page hangs up after hangup_s */
1194
+ idle: { nudge_s: number; hangup_s: number };
1195
+ /* a session can't start once today's spend reaches daily_usd; the page hangs up at max_session_min */
1196
+ limits: {
1197
+ /* Grok voice minutes per day; past it, Omni goes on in Claude mode */
1198
+ daily_voice_min: number;
1199
+ daily_usd: number;
1200
+ max_session_min: number;
1201
+ max_actions: number;
1202
+ max_tool_calls: number;
1203
+ };
1204
+ /* waiting for the studio's work (wait_for_work): past this many minutes asleep, the call hangs up */
1205
+ wait_max_min: number;
1206
+ };
1207
+ export type AgentStats = {
1208
+ sessions: number;
1209
+ minutes: number;
1210
+ turns: number;
1211
+ latency_p50_ms: number | null;
1212
+ latency_p90_ms: number | null;
1213
+ tool_calls: number;
1214
+ tool_errors: number;
1215
+ classify_cost_usd: number;
1216
+ voice_cost_usd: number;
1217
+ thumbs_up: number;
1218
+ thumbs_down: number;
1219
+ /* the same, per way of talking: Grok, or the cascade by streamed or whole-utterance STT */
1220
+ by_mode: AgentModeStats[];
1221
+ };
1222
+ export type AgentModeStats = {
1223
+ mode: "grok" | "stream" | "chunks";
1224
+ sessions: number;
1225
+ minutes: number;
1226
+ turns: number;
1227
+ latency_p50_ms: number | null;
1228
+ latency_p90_ms: number | null;
1229
+ cost_usd: number;
1230
+ /* cost over the minutes the conversations lasted (null with no minutes yet) */
1231
+ cost_per_min_usd: number | null;
1232
+ thumbs_up: number;
1233
+ thumbs_down: number;
1234
+ };
1235
+ /* voice_left_s <= 0: today's voice quota is used up and the widget is in Claude mode */
1236
+ export type AgentInfo = { config: AgentConfig; stats: AgentStats; error: string | null; voice_left_s: number };
1237
+ export type AgentSessionStart = {
1238
+ ok: true;
1239
+ id: string;
1240
+ /* the xAI ephemeral token: only opens the WebSocket */
1241
+ token: string;
1242
+ expires_at: number;
1243
+ url: string;
1244
+ /* the session.update the browser sends right after connecting */
1245
+ session: Record<string, unknown>;
1246
+ /* the system message sent after it: the time and the studio's state */
1247
+ context: string;
1248
+ config: AgentConfig;
1249
+ voice_remaining_s: number;
1250
+ };
1251
+ /* GET /api/agent/claude/:id: Omni's Claude mode, the turn's state and the answer once it ended */
1252
+ export type AgentClaudeReply = { state: string; text: string | null; now: string | null };
1253
+ /* an action staged by the agent, waiting for the screen's "Confirmar" */
1254
+ /* a card decided by voice (confirm_action, cancel_action): the page takes it away and opens `open` */
1255
+ export type AgentResolvedAction = {
1256
+ id: string;
1257
+ kind: string;
1258
+ slug: string | null;
1259
+ summary: string;
1260
+ state: "confirmed" | "canceled" | "failed";
1261
+ open: NavigateArgs | null;
1262
+ };
1263
+
1264
+ export type AgentPendingAction = {
1265
+ id: string;
1266
+ session: string;
1267
+ kind:
1268
+ | "change"
1269
+ | "create"
1270
+ | "thumbnail"
1271
+ | "publish"
1272
+ | "schedule"
1273
+ | "approval"
1274
+ | "reference"
1275
+ | "new_reference"
1276
+ | "choose_thumbnail"
1277
+ | "analysis"
1278
+ | "omnichat"
1279
+ | "omnichat_send";
1280
+ slug: string | null;
1281
+ title: string;
1282
+ /* what will happen, in Portuguese */
1283
+ summary: string;
1284
+ created: string;
1285
+ payload: Record<string, unknown>;
1286
+ /* the cards this one replaced (a corrected request): the screen takes them away */
1287
+ replaces?: string[];
1288
+ /* the screen where its result shows: the page opens it with the card (shared/omni-actions) */
1289
+ open?: NavigateArgs | null;
1290
+ };