@engenty/wizards-runtime 0.0.0-stage → 0.7.5

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 (518) hide show
  1. package/LICENSE +110 -0
  2. package/README.md +214 -2
  3. package/apps/runtime/dist/agents/architect.js +444 -0
  4. package/apps/runtime/dist/agents/studio-assistant.js +883 -0
  5. package/apps/runtime/dist/agents/subscription.js +207 -0
  6. package/apps/runtime/dist/agents/thought.js +21 -0
  7. package/apps/runtime/dist/agents/website.js +480 -0
  8. package/apps/runtime/dist/app.js +359 -0
  9. package/apps/runtime/dist/apple/wizards-apple +0 -0
  10. package/apps/runtime/dist/assistant/browser.js +26 -0
  11. package/apps/runtime/dist/assistant/docs.js +158 -0
  12. package/apps/runtime/dist/assistant/knows.js +353 -0
  13. package/apps/runtime/dist/assistant/primer.js +26 -0
  14. package/apps/runtime/dist/assistant/runs.js +24 -0
  15. package/apps/runtime/dist/auth/account.js +175 -0
  16. package/apps/runtime/dist/auth/device.js +112 -0
  17. package/apps/runtime/dist/auth/index.js +358 -0
  18. package/apps/runtime/dist/auth/keys.js +55 -0
  19. package/apps/runtime/dist/auth/local-ticket.js +26 -0
  20. package/apps/runtime/dist/authoring/example.js +74 -0
  21. package/apps/runtime/dist/authoring/guide.js +433 -0
  22. package/apps/runtime/dist/authoring/ops.js +117 -0
  23. package/apps/runtime/dist/browser/fast/action-space.js +160 -0
  24. package/apps/runtime/dist/browser/fast/classifier.js +91 -0
  25. package/apps/runtime/dist/browser/fast/decide.js +171 -0
  26. package/apps/runtime/dist/browser/fast/driver.js +141 -0
  27. package/apps/runtime/dist/browser/fast/instructions.js +33 -0
  28. package/apps/runtime/dist/browser/fast/run.js +249 -0
  29. package/apps/runtime/dist/browser/fast/span-picker.js +153 -0
  30. package/apps/runtime/dist/browser/fast/text-helper.js +178 -0
  31. package/apps/runtime/dist/browser/snapshot.js +335 -0
  32. package/apps/runtime/dist/cli/account.js +385 -0
  33. package/apps/runtime/dist/cli/autostart.js +182 -0
  34. package/apps/runtime/dist/cli/autoupdate.js +221 -0
  35. package/apps/runtime/dist/cli/clients.js +44 -0
  36. package/apps/runtime/dist/cli/connect.js +540 -0
  37. package/apps/runtime/dist/cli/environment.js +93 -0
  38. package/apps/runtime/dist/cli/exec.js +45 -0
  39. package/apps/runtime/dist/cli/features.js +50 -0
  40. package/apps/runtime/dist/cli/home.js +88 -0
  41. package/apps/runtime/dist/cli/install-env.js +33 -0
  42. package/apps/runtime/dist/cli/machine.js +107 -0
  43. package/apps/runtime/dist/cli/main.js +222 -0
  44. package/apps/runtime/dist/cli/mcp.js +136 -0
  45. package/apps/runtime/dist/cli/menu.js +202 -0
  46. package/apps/runtime/dist/cli/processes.js +72 -0
  47. package/apps/runtime/dist/cli/report.js +66 -0
  48. package/apps/runtime/dist/cli/setup.js +335 -0
  49. package/apps/runtime/dist/cli/start.js +276 -0
  50. package/apps/runtime/dist/cli/status.js +203 -0
  51. package/apps/runtime/dist/cli/ui.js +59 -0
  52. package/apps/runtime/dist/cli/uninstall-main.js +20 -0
  53. package/apps/runtime/dist/cli/uninstall.js +231 -0
  54. package/apps/runtime/dist/cli/update.js +86 -0
  55. package/apps/runtime/dist/cli/validate.js +75 -0
  56. package/apps/runtime/dist/cli/versions.js +123 -0
  57. package/apps/runtime/dist/connectors/builtin.js +86 -0
  58. package/apps/runtime/dist/connectors/external.js +409 -0
  59. package/apps/runtime/dist/connectors/gmail.js +107 -0
  60. package/apps/runtime/dist/connectors/imap.js +261 -0
  61. package/apps/runtime/dist/connectors/index.js +325 -0
  62. package/apps/runtime/dist/connectors/mail.js +72 -0
  63. package/apps/runtime/dist/connectors/outlook.js +90 -0
  64. package/apps/runtime/dist/connectors/plugin-connections.js +343 -0
  65. package/apps/runtime/dist/connectors/via-account.js +65 -0
  66. package/apps/runtime/dist/credits/credits.js +100 -0
  67. package/apps/runtime/dist/credits/estimate.js +152 -0
  68. package/apps/runtime/dist/db/adopt.js +149 -0
  69. package/apps/runtime/dist/db/client.js +173 -0
  70. package/apps/runtime/dist/db/control-schema.js +133 -0
  71. package/apps/runtime/dist/db/migrations/control/0000_last_absorbing_man.sql +47 -0
  72. package/apps/runtime/dist/db/migrations/control/0001_gorgeous_nicolaos.sql +41 -0
  73. package/apps/runtime/dist/db/migrations/control/0002_secret_penance.sql +1 -0
  74. package/apps/runtime/dist/db/migrations/control/0003_nasty_mordo.sql +3 -0
  75. package/apps/runtime/dist/db/migrations/control/0004_breezy_eddie_brock.sql +6 -0
  76. package/apps/runtime/dist/db/migrations/control/0005_chilly_oracle.sql +1 -0
  77. package/apps/runtime/dist/db/migrations/control/0006_sleepy_mojo.sql +1 -0
  78. package/apps/runtime/dist/db/migrations/control/0007_common_the_hand.sql +15 -0
  79. package/apps/runtime/dist/db/migrations/control/0008_runner.sql +8 -0
  80. package/apps/runtime/dist/db/migrations/control/0009_plugin_claim.sql +9 -0
  81. package/apps/runtime/dist/db/migrations/control/0010_tan_snowbird.sql +6 -0
  82. package/apps/runtime/dist/db/migrations/control/meta/0000_snapshot.json +311 -0
  83. package/apps/runtime/dist/db/migrations/control/meta/0001_snapshot.json +599 -0
  84. package/apps/runtime/dist/db/migrations/control/meta/0002_snapshot.json +607 -0
  85. package/apps/runtime/dist/db/migrations/control/meta/0003_snapshot.json +311 -0
  86. package/apps/runtime/dist/db/migrations/control/meta/0004_snapshot.json +350 -0
  87. package/apps/runtime/dist/db/migrations/control/meta/0005_snapshot.json +358 -0
  88. package/apps/runtime/dist/db/migrations/control/meta/0006_snapshot.json +365 -0
  89. package/apps/runtime/dist/db/migrations/control/meta/0007_snapshot.json +460 -0
  90. package/apps/runtime/dist/db/migrations/control/meta/0008_snapshot.json +505 -0
  91. package/apps/runtime/dist/db/migrations/control/meta/0009_snapshot.json +561 -0
  92. package/apps/runtime/dist/db/migrations/control/meta/0010_snapshot.json +600 -0
  93. package/apps/runtime/dist/db/migrations/control/meta/_journal.json +83 -0
  94. package/apps/runtime/dist/db/migrations/tenant/0000_eminent_freak.sql +188 -0
  95. package/apps/runtime/dist/db/migrations/tenant/0001_salty_master_chief.sql +1 -0
  96. package/apps/runtime/dist/db/migrations/tenant/0002_cloudy_firebird.sql +1 -0
  97. package/apps/runtime/dist/db/migrations/tenant/0003_brown_warbound.sql +52 -0
  98. package/apps/runtime/dist/db/migrations/tenant/0004_romantic_nocturne.sql +6 -0
  99. package/apps/runtime/dist/db/migrations/tenant/0005_reflective_forgotten_one.sql +2 -0
  100. package/apps/runtime/dist/db/migrations/tenant/0006_hard_war_machine.sql +30 -0
  101. package/apps/runtime/dist/db/migrations/tenant/0007_space_data.sql +43 -0
  102. package/apps/runtime/dist/db/migrations/tenant/0008_run_event_note.sql +1 -0
  103. package/apps/runtime/dist/db/migrations/tenant/0009_knowledge.sql +104 -0
  104. package/apps/runtime/dist/db/migrations/tenant/0010_plugin_connection.sql +15 -0
  105. package/apps/runtime/dist/db/migrations/tenant/0011_runners.sql +2 -0
  106. package/apps/runtime/dist/db/migrations/tenant/0012_assistant_chat.sql +40 -0
  107. package/apps/runtime/dist/db/migrations/tenant/0013_run_origin.sql +1 -0
  108. package/apps/runtime/dist/db/migrations/tenant/0014_run_answer.sql +2 -0
  109. package/apps/runtime/dist/db/migrations/tenant/0015_device_calls.sql +13 -0
  110. package/apps/runtime/dist/db/migrations/tenant/0016_even_trish_tilby.sql +12 -0
  111. package/apps/runtime/dist/db/migrations/tenant/meta/0000_snapshot.json +1323 -0
  112. package/apps/runtime/dist/db/migrations/tenant/meta/0001_snapshot.json +1330 -0
  113. package/apps/runtime/dist/db/migrations/tenant/meta/0002_snapshot.json +1337 -0
  114. package/apps/runtime/dist/db/migrations/tenant/meta/0003_snapshot.json +1605 -0
  115. package/apps/runtime/dist/db/migrations/tenant/meta/0004_snapshot.json +1645 -0
  116. package/apps/runtime/dist/db/migrations/tenant/meta/0005_snapshot.json +1659 -0
  117. package/apps/runtime/dist/db/migrations/tenant/meta/0006_snapshot.json +1696 -0
  118. package/apps/runtime/dist/db/migrations/tenant/meta/0007_snapshot.json +2012 -0
  119. package/apps/runtime/dist/db/migrations/tenant/meta/0008_snapshot.json +2019 -0
  120. package/apps/runtime/dist/db/migrations/tenant/meta/0009_snapshot.json +2837 -0
  121. package/apps/runtime/dist/db/migrations/tenant/meta/0010_snapshot.json +2942 -0
  122. package/apps/runtime/dist/db/migrations/tenant/meta/0011_snapshot.json +2956 -0
  123. package/apps/runtime/dist/db/migrations/tenant/meta/0012_snapshot.json +3132 -0
  124. package/apps/runtime/dist/db/migrations/tenant/meta/0013_snapshot.json +3139 -0
  125. package/apps/runtime/dist/db/migrations/tenant/meta/0014_snapshot.json +3154 -0
  126. package/apps/runtime/dist/db/migrations/tenant/meta/0015_snapshot.json +3243 -0
  127. package/apps/runtime/dist/db/migrations/tenant/meta/0016_snapshot.json +3326 -0
  128. package/apps/runtime/dist/db/migrations/tenant/meta/_journal.json +125 -0
  129. package/apps/runtime/dist/db/schema.js +602 -0
  130. package/apps/runtime/dist/debug.js +196 -0
  131. package/apps/runtime/dist/docs/dev/index.md +41 -0
  132. package/apps/runtime/dist/docs/dev/meta.json +7 -0
  133. package/apps/runtime/dist/docs/dev/plugins/connections.md +74 -0
  134. package/apps/runtime/dist/docs/dev/plugins/events.md +89 -0
  135. package/apps/runtime/dist/docs/dev/plugins/examples.md +101 -0
  136. package/apps/runtime/dist/docs/dev/plugins/index.md +78 -0
  137. package/apps/runtime/dist/docs/dev/plugins/layout.md +90 -0
  138. package/apps/runtime/dist/docs/dev/plugins/meta.json +28 -0
  139. package/apps/runtime/dist/docs/dev/plugins/quick-start.md +94 -0
  140. package/apps/runtime/dist/docs/dev/plugins/reference.md +348 -0
  141. package/apps/runtime/dist/docs/dev/plugins/reloading.md +76 -0
  142. package/apps/runtime/dist/docs/dev/plugins/routes.md +185 -0
  143. package/apps/runtime/dist/docs/dev/plugins/runners.md +230 -0
  144. package/apps/runtime/dist/docs/dev/plugins/server.md +281 -0
  145. package/apps/runtime/dist/docs/dev/plugins/shipping.md +79 -0
  146. package/apps/runtime/dist/docs/dev/plugins/space.md +297 -0
  147. package/apps/runtime/dist/docs/dev/plugins/starters.md +70 -0
  148. package/apps/runtime/dist/docs/dev/plugins/studio.md +363 -0
  149. package/apps/runtime/dist/docs/dev/plugins/styling.md +129 -0
  150. package/apps/runtime/dist/docs/dev/plugins/tables.md +104 -0
  151. package/apps/runtime/dist/docs/dev/plugins/tools.md +139 -0
  152. package/apps/runtime/dist/docs/dev/wizard-format.md +125 -0
  153. package/apps/runtime/dist/docs/meta.json +3 -0
  154. package/apps/runtime/dist/docs/user/ai-apps.md +112 -0
  155. package/apps/runtime/dist/docs/user/assistant.md +77 -0
  156. package/apps/runtime/dist/docs/user/build-a-wizard.md +116 -0
  157. package/apps/runtime/dist/docs/user/command-line.md +83 -0
  158. package/apps/runtime/dist/docs/user/connectors.md +90 -0
  159. package/apps/runtime/dist/docs/user/create-account.md +52 -0
  160. package/apps/runtime/dist/docs/user/data.md +66 -0
  161. package/apps/runtime/dist/docs/user/first-start.md +60 -0
  162. package/apps/runtime/dist/docs/user/index.md +49 -0
  163. package/apps/runtime/dist/docs/user/install.md +123 -0
  164. package/apps/runtime/dist/docs/user/local-only.md +42 -0
  165. package/apps/runtime/dist/docs/user/meta.json +32 -0
  166. package/apps/runtime/dist/docs/user/models.md +156 -0
  167. package/apps/runtime/dist/docs/user/plugins.md +71 -0
  168. package/apps/runtime/dist/docs/user/run.md +98 -0
  169. package/apps/runtime/dist/docs/user/server.md +52 -0
  170. package/apps/runtime/dist/docs/user/space.md +126 -0
  171. package/apps/runtime/dist/docs/user/steps.md +220 -0
  172. package/apps/runtime/dist/docs/user/test-and-share.md +224 -0
  173. package/apps/runtime/dist/docs/user/troubleshooting.md +67 -0
  174. package/apps/runtime/dist/docs/user/wordpress.md +121 -0
  175. package/apps/runtime/dist/documents/parse.js +246 -0
  176. package/apps/runtime/dist/engenty/connections-external/build-connector.js +193 -0
  177. package/apps/runtime/dist/engenty/connections-external/errors.js +11 -0
  178. package/apps/runtime/dist/engenty/connections-external/import-service.js +270 -0
  179. package/apps/runtime/dist/engenty/connections-external/importer/classify.js +34 -0
  180. package/apps/runtime/dist/engenty/connections-external/importer/map-auth.js +185 -0
  181. package/apps/runtime/dist/engenty/connections-external/importer/normalize-mcp.js +63 -0
  182. package/apps/runtime/dist/engenty/connections-external/importer/normalize-openapi.js +130 -0
  183. package/apps/runtime/dist/engenty/connections-external/invoke/http-invoker.js +143 -0
  184. package/apps/runtime/dist/engenty/connections-external/invoke/mcp-client.js +143 -0
  185. package/apps/runtime/dist/engenty/connections-external/net/guarded-fetch.js +119 -0
  186. package/apps/runtime/dist/engenty/connections-external/oauth-dcr.js +88 -0
  187. package/apps/runtime/dist/engenty/connections-external/registry-client.js +336 -0
  188. package/apps/runtime/dist/engenty/connections-external/registry-source.js +82 -0
  189. package/apps/runtime/dist/engenty/connections-external/types.js +7 -0
  190. package/apps/runtime/dist/engenty/connections-github/connector.js +209 -0
  191. package/apps/runtime/dist/engenty/connections-google/connectors/calendar.js +381 -0
  192. package/apps/runtime/dist/engenty/connections-google/connectors/contacts.js +94 -0
  193. package/apps/runtime/dist/engenty/connections-google/connectors/drive.js +290 -0
  194. package/apps/runtime/dist/engenty/connections-google/connectors/gmail.js +567 -0
  195. package/apps/runtime/dist/engenty/connections-google/definitions.js +11 -0
  196. package/apps/runtime/dist/engenty/connections-google/shared.js +73 -0
  197. package/apps/runtime/dist/engenty/connections-hubspot/connector.js +140 -0
  198. package/apps/runtime/dist/engenty/connections-microsoft/action.js +17 -0
  199. package/apps/runtime/dist/engenty/connections-microsoft/graph.js +114 -0
  200. package/apps/runtime/dist/engenty/connections-microsoft/onedrive.js +286 -0
  201. package/apps/runtime/dist/engenty/connections-microsoft/outlook.js +492 -0
  202. package/apps/runtime/dist/engenty/connections-s3/s3.js +328 -0
  203. package/apps/runtime/dist/engenty/connections-sdk/files-capability.js +86 -0
  204. package/apps/runtime/dist/engenty/connections-sdk/oauth2.js +150 -0
  205. package/apps/runtime/dist/engenty/connections-sdk/registry.js +89 -0
  206. package/apps/runtime/dist/engenty/connections-sdk/storage-capability.js +84 -0
  207. package/apps/runtime/dist/engenty/connections-sdk/types.js +30 -0
  208. package/apps/runtime/dist/engenty/connections-slack/connector.js +360 -0
  209. package/apps/runtime/dist/engenty/csv-import/csv-matrix.js +178 -0
  210. package/apps/runtime/dist/engenty/csv-import/import-sources.js +87 -0
  211. package/apps/runtime/dist/engenty/csv-import/parse-csv.js +129 -0
  212. package/apps/runtime/dist/engenty/csv-import/serialize-csv.js +20 -0
  213. package/apps/runtime/dist/engenty/csv-import/types.js +1 -0
  214. package/apps/runtime/dist/engenty/csv-import/xlsx-workbook.js +159 -0
  215. package/apps/runtime/dist/engenty/doc-converter/interface.js +9 -0
  216. package/apps/runtime/dist/engenty/doc-converter/page-break.js +92 -0
  217. package/apps/runtime/dist/engenty/doc-converter/providers/local/index.js +72 -0
  218. package/apps/runtime/dist/engenty/document-scanner/schemas/classifier.js +30 -0
  219. package/apps/runtime/dist/engenty/document-scanner/schemas/index.js +4 -0
  220. package/apps/runtime/dist/engenty/document-scanner/schemas/invoice.js +73 -0
  221. package/apps/runtime/dist/engenty/document-scanner/schemas/receipt.js +63 -0
  222. package/apps/runtime/dist/engenty/document-scanner/schemas/shared.js +40 -0
  223. package/apps/runtime/dist/engenty/search-index/chunks.js +164 -0
  224. package/apps/runtime/dist/engenty/search-index/contracts.js +9 -0
  225. package/apps/runtime/dist/engenty/shims/connections-sdk.js +39 -0
  226. package/apps/runtime/dist/engenty/shims/plugin-sdk.js +1 -0
  227. package/apps/runtime/dist/engenty/shims/web-ingest.js +19 -0
  228. package/apps/runtime/dist/engenty/web-ingest/ssrf.js +277 -0
  229. package/apps/runtime/dist/engine/asks.js +82 -0
  230. package/apps/runtime/dist/engine/decide.js +82 -0
  231. package/apps/runtime/dist/engine/device.js +194 -0
  232. package/apps/runtime/dist/engine/events.js +128 -0
  233. package/apps/runtime/dist/engine/input.js +208 -0
  234. package/apps/runtime/dist/engine/owner.js +32 -0
  235. package/apps/runtime/dist/engine/prepare.js +90 -0
  236. package/apps/runtime/dist/engine/push.js +58 -0
  237. package/apps/runtime/dist/engine/requirements.js +355 -0
  238. package/apps/runtime/dist/engine/resources.js +198 -0
  239. package/apps/runtime/dist/engine/runner.js +970 -0
  240. package/apps/runtime/dist/engine/steps.js +1000 -0
  241. package/apps/runtime/dist/engine/surface.js +91 -0
  242. package/apps/runtime/dist/engine/template.js +240 -0
  243. package/apps/runtime/dist/engine/types.js +4 -0
  244. package/apps/runtime/dist/env.js +295 -0
  245. package/apps/runtime/dist/features.js +123 -0
  246. package/apps/runtime/dist/files/blobs.js +22 -0
  247. package/apps/runtime/dist/files/objects.js +86 -0
  248. package/apps/runtime/dist/files/storage.js +120 -0
  249. package/apps/runtime/dist/files/web-images.js +101 -0
  250. package/apps/runtime/dist/film/project.js +257 -0
  251. package/apps/runtime/dist/film/skills.js +91 -0
  252. package/apps/runtime/dist/film/sounds.js +122 -0
  253. package/apps/runtime/dist/film/step.js +289 -0
  254. package/apps/runtime/dist/film/tools.js +99 -0
  255. package/apps/runtime/dist/geocode.js +58 -0
  256. package/apps/runtime/dist/harness/antigravity.js +129 -0
  257. package/apps/runtime/dist/harness/apple.js +270 -0
  258. package/apps/runtime/dist/harness/claude.js +147 -0
  259. package/apps/runtime/dist/harness/codex.js +229 -0
  260. package/apps/runtime/dist/harness/cursor.js +93 -0
  261. package/apps/runtime/dist/harness/env.js +124 -0
  262. package/apps/runtime/dist/harness/index.js +95 -0
  263. package/apps/runtime/dist/harness/model.js +279 -0
  264. package/apps/runtime/dist/harness/prompt.js +121 -0
  265. package/apps/runtime/dist/harness/terminal.js +194 -0
  266. package/apps/runtime/dist/harness/types.js +7 -0
  267. package/apps/runtime/dist/index.js +113 -0
  268. package/apps/runtime/dist/limits.js +81 -0
  269. package/apps/runtime/dist/link-preview.js +60 -0
  270. package/apps/runtime/dist/log.js +106 -0
  271. package/apps/runtime/dist/manage.js +249 -0
  272. package/apps/runtime/dist/mcp/auth.js +161 -0
  273. package/apps/runtime/dist/mcp/bridge.js +59 -0
  274. package/apps/runtime/dist/mcp/flow-app.js +97 -0
  275. package/apps/runtime/dist/mcp/handler.js +54 -0
  276. package/apps/runtime/dist/mcp/scopes.js +14 -0
  277. package/apps/runtime/dist/mcp/seen.js +65 -0
  278. package/apps/runtime/dist/mcp/tools.js +572 -0
  279. package/apps/runtime/dist/media/conversation.js +167 -0
  280. package/apps/runtime/dist/media/ffmpeg.js +121 -0
  281. package/apps/runtime/dist/media/generate.js +120 -0
  282. package/apps/runtime/dist/media/marking.js +121 -0
  283. package/apps/runtime/dist/media/transcribe.js +198 -0
  284. package/apps/runtime/dist/model-errors.js +42 -0
  285. package/apps/runtime/dist/models.js +1164 -0
  286. package/apps/runtime/dist/plugin.js +61 -0
  287. package/apps/runtime/dist/plugins/channels.js +78 -0
  288. package/apps/runtime/dist/plugins/claims.js +56 -0
  289. package/apps/runtime/dist/plugins/discovery.js +155 -0
  290. package/apps/runtime/dist/plugins/events.js +63 -0
  291. package/apps/runtime/dist/plugins/jobs.js +64 -0
  292. package/apps/runtime/dist/plugins/loader.js +508 -0
  293. package/apps/runtime/dist/plugins/migrations.js +69 -0
  294. package/apps/runtime/dist/plugins/pro-keys.js +34 -0
  295. package/apps/runtime/dist/plugins/pro-state.js +83 -0
  296. package/apps/runtime/dist/plugins/pro.js +310 -0
  297. package/apps/runtime/dist/plugins/public.js +44 -0
  298. package/apps/runtime/dist/plugins/registry.js +122 -0
  299. package/apps/runtime/dist/plugins/runs.js +210 -0
  300. package/apps/runtime/dist/render/browser-path.js +54 -0
  301. package/apps/runtime/dist/render/chromium.js +98 -0
  302. package/apps/runtime/dist/render/convert.js +158 -0
  303. package/apps/runtime/dist/render/downloads.js +299 -0
  304. package/apps/runtime/dist/render/guard.js +25 -0
  305. package/apps/runtime/dist/render/shaped.js +137 -0
  306. package/apps/runtime/dist/routes/api.js +440 -0
  307. package/apps/runtime/dist/routes/debug.js +42 -0
  308. package/apps/runtime/dist/routes/delivery.js +90 -0
  309. package/apps/runtime/dist/routes/internal.js +81 -0
  310. package/apps/runtime/dist/routes/lang.js +25 -0
  311. package/apps/runtime/dist/routes/marketplace.js +43 -0
  312. package/apps/runtime/dist/routes/plugin-public.js +113 -0
  313. package/apps/runtime/dist/routes/plugins.js +212 -0
  314. package/apps/runtime/dist/routes/runs.js +1422 -0
  315. package/apps/runtime/dist/routes/studio.js +1629 -0
  316. package/apps/runtime/dist/routes/wizard-stream.js +30 -0
  317. package/apps/runtime/dist/running.js +39 -0
  318. package/apps/runtime/dist/sandbox/docker.js +75 -0
  319. package/apps/runtime/dist/sandbox/index.js +23 -0
  320. package/apps/runtime/dist/sandbox/types.js +1 -0
  321. package/apps/runtime/dist/secrets/crypto.js +28 -0
  322. package/apps/runtime/dist/secrets/signing.js +52 -0
  323. package/apps/runtime/dist/secrets/vault.js +59 -0
  324. package/apps/runtime/dist/services/access.js +88 -0
  325. package/apps/runtime/dist/services/api.js +248 -0
  326. package/apps/runtime/dist/services/architect.js +95 -0
  327. package/apps/runtime/dist/services/assistant-chats.js +311 -0
  328. package/apps/runtime/dist/services/brand.js +85 -0
  329. package/apps/runtime/dist/services/cloud.js +456 -0
  330. package/apps/runtime/dist/services/draft-events.js +27 -0
  331. package/apps/runtime/dist/services/engenty-shapes.js +71 -0
  332. package/apps/runtime/dist/services/errors.js +29 -0
  333. package/apps/runtime/dist/services/files.js +178 -0
  334. package/apps/runtime/dist/services/knowledge-model.js +559 -0
  335. package/apps/runtime/dist/services/knowledge.js +721 -0
  336. package/apps/runtime/dist/services/links.js +16 -0
  337. package/apps/runtime/dist/services/marketplace.js +492 -0
  338. package/apps/runtime/dist/services/onboarding.js +152 -0
  339. package/apps/runtime/dist/services/package-file.js +82 -0
  340. package/apps/runtime/dist/services/package.js +170 -0
  341. package/apps/runtime/dist/services/profile.js +51 -0
  342. package/apps/runtime/dist/services/project-files.js +439 -0
  343. package/apps/runtime/dist/services/project-index.js +707 -0
  344. package/apps/runtime/dist/services/projects.js +387 -0
  345. package/apps/runtime/dist/services/relevance.js +58 -0
  346. package/apps/runtime/dist/services/runners.js +178 -0
  347. package/apps/runtime/dist/services/runs.js +524 -0
  348. package/apps/runtime/dist/services/shares.js +130 -0
  349. package/apps/runtime/dist/services/site.js +270 -0
  350. package/apps/runtime/dist/services/space-categories.js +861 -0
  351. package/apps/runtime/dist/services/space-data.js +792 -0
  352. package/apps/runtime/dist/services/space-origin.js +207 -0
  353. package/apps/runtime/dist/services/spaces.js +656 -0
  354. package/apps/runtime/dist/services/translations.js +306 -0
  355. package/apps/runtime/dist/services/widgets.js +34 -0
  356. package/apps/runtime/dist/services/wizard-icon.js +157 -0
  357. package/apps/runtime/dist/services/wizards.js +420 -0
  358. package/apps/runtime/dist/settings.js +16 -0
  359. package/apps/runtime/dist/store/errors.js +4 -0
  360. package/apps/runtime/dist/store/index.js +299 -0
  361. package/apps/runtime/dist/store/shared-lists.js +123 -0
  362. package/apps/runtime/dist/tenants/control.js +238 -0
  363. package/apps/runtime/dist/tenants/tenant.js +26 -0
  364. package/apps/runtime/dist/texts.js +207 -0
  365. package/apps/runtime/dist/tools/browser.js +703 -0
  366. package/apps/runtime/dist/tools/connector.js +204 -0
  367. package/apps/runtime/dist/tools/index.js +291 -0
  368. package/apps/runtime/dist/tools/mail.js +104 -0
  369. package/apps/runtime/dist/tools/net-guard.js +170 -0
  370. package/apps/runtime/dist/tools/pages.js +81 -0
  371. package/apps/runtime/dist/tools/plugin.js +180 -0
  372. package/apps/runtime/dist/tools/project.js +154 -0
  373. package/apps/runtime/dist/tools/shared.js +69 -0
  374. package/apps/runtime/dist/tools/store.js +238 -0
  375. package/apps/runtime/dist/update.js +113 -0
  376. package/apps/runtime/dist/widgets/bundle.js +99 -0
  377. package/apps/runtime/dist/widgets/render.js +329 -0
  378. package/apps/runtime/dist/widgets/runtime.js +108 -0
  379. package/apps/runtime/dist/widgets/script.js +30 -0
  380. package/apps/runtime/dist/widgets/step.js +223 -0
  381. package/apps/web/dist/ai-labels/ai-black.svg +20 -0
  382. package/apps/web/dist/ai-labels/ai-generated-black.svg +31 -0
  383. package/apps/web/dist/ai-labels/ai-generated-white.svg +32 -0
  384. package/apps/web/dist/ai-labels/ai-modified-black.svg +30 -0
  385. package/apps/web/dist/ai-labels/ai-modified-white.svg +31 -0
  386. package/apps/web/dist/ai-labels/ai-white.svg +21 -0
  387. package/apps/web/dist/assets/AboutDialog-D4mvc-zu.js +1 -0
  388. package/apps/web/dist/assets/ChangelogDialog-DLqpJsF6.js +1 -0
  389. package/apps/web/dist/assets/ChatView-3laypRcE.js +10 -0
  390. package/apps/web/dist/assets/EditorPage-BalA5U2Y.js +3 -0
  391. package/apps/web/dist/assets/FlowPreview-CusP7ci9.js +1 -0
  392. package/apps/web/dist/assets/Harness-BrP-ENHg.css +1 -0
  393. package/apps/web/dist/assets/Harness-iYLtOLaK.js +16 -0
  394. package/apps/web/dist/assets/NewWizardChannels-CbwJ9A56.js +1 -0
  395. package/apps/web/dist/assets/NewWizardPage-BOBYiB9i.js +7 -0
  396. package/apps/web/dist/assets/OnboardingPage-CUwCiVIr.js +1 -0
  397. package/apps/web/dist/assets/ProjectPage-Bb16MdYG.js +1 -0
  398. package/apps/web/dist/assets/PublicRunner-BCt7Q6C-.js +1 -0
  399. package/apps/web/dist/assets/ReadOnly-kIHX2TEy.js +1 -0
  400. package/apps/web/dist/assets/RunDrawer-hZ9oeSXu.js +4 -0
  401. package/apps/web/dist/assets/RunnerView-DUS9fPmx.js +1 -0
  402. package/apps/web/dist/assets/SettingsPage-BzwR50fi.js +1 -0
  403. package/apps/web/dist/assets/SetupPage-gAp7rPxp.js +1 -0
  404. package/apps/web/dist/assets/SharePage-DqZWHva_.js +1 -0
  405. package/apps/web/dist/assets/changelog-DugmCNSf.js +1 -0
  406. package/apps/web/dist/assets/engenty-eXZ-EAwd.js +1 -0
  407. package/apps/web/dist/assets/esm-DXeMu8Lb.js +7 -0
  408. package/apps/web/dist/assets/fluffy-engenty-ClRou7yu.js +456 -0
  409. package/apps/web/dist/assets/index-AfUa8xKD.css +1 -0
  410. package/apps/web/dist/assets/index-C5Sm7tTR.js +14 -0
  411. package/apps/web/dist/assets/jsx-runtime-BNakU3Ej.js +1 -0
  412. package/apps/web/dist/assets/lock-R_CfU0Xo.js +1 -0
  413. package/apps/web/dist/assets/oss-credits-cZ9NUaLZ.js +1 -0
  414. package/apps/web/dist/assets/pdfmake-Cx9scTbD.js +228 -0
  415. package/apps/web/dist/assets/phone-CgrIS4_-.js +1 -0
  416. package/apps/web/dist/assets/preload-helper-CNEI7N0N.js +1 -0
  417. package/apps/web/dist/assets/qr-scanner-worker.min-CJaXo3yu.js +98 -0
  418. package/apps/web/dist/assets/qr-scanner.min-C_UI0gH-.js +1 -0
  419. package/apps/web/dist/assets/rolldown-runtime-hePW80VL.js +1 -0
  420. package/apps/web/dist/assets/settings-menu-2IMOOlLl.js +1 -0
  421. package/apps/web/dist/assets/ui-dzGvc3xk.js +137 -0
  422. package/apps/web/dist/assets/upload-BSuTilFF.js +1 -0
  423. package/apps/web/dist/assets/vfs_fonts-DllDSYt1.js +1 -0
  424. package/apps/web/dist/embed.js +266 -0
  425. package/apps/web/dist/favicon.svg +1 -0
  426. package/apps/web/dist/icons/apple-touch-icon.png +0 -0
  427. package/apps/web/dist/icons/icon-192.png +0 -0
  428. package/apps/web/dist/icons/icon-512.png +0 -0
  429. package/apps/web/dist/icons/icon-maskable-512.png +0 -0
  430. package/apps/web/dist/index.html +48 -0
  431. package/apps/web/dist/install.sh +577 -0
  432. package/apps/web/dist/manifest.webmanifest +21 -0
  433. package/apps/web/dist/mcp/flow.html +980 -0
  434. package/apps/web/dist/sw.js +15 -0
  435. package/bin/wizards.mjs +288 -0
  436. package/modules/README.md +15 -0
  437. package/node_modules/@engenty/wizards/dist/plugin/index.d.ts +1150 -0
  438. package/node_modules/@engenty/wizards/dist/plugin/index.js +4 -0
  439. package/node_modules/@engenty/wizards/dist/plugin/studio.d.ts +322 -0
  440. package/node_modules/@engenty/wizards/dist/plugin/studio.js +4 -0
  441. package/node_modules/@engenty/wizards/dist/plugin/thread.d.ts +174 -0
  442. package/node_modules/@engenty/wizards/dist/plugin/thread.js +821 -0
  443. package/node_modules/@engenty/wizards/package.json +11 -0
  444. package/node_modules/@engenty-wizards/shared/dist/assistant.d.ts +174 -0
  445. package/node_modules/@engenty-wizards/shared/dist/assistant.js +65 -0
  446. package/node_modules/@engenty-wizards/shared/dist/changes.d.ts +22 -0
  447. package/node_modules/@engenty-wizards/shared/dist/changes.js +61 -0
  448. package/node_modules/@engenty-wizards/shared/dist/connectors.d.ts +77 -0
  449. package/node_modules/@engenty-wizards/shared/dist/connectors.js +2 -0
  450. package/node_modules/@engenty-wizards/shared/dist/decision.d.ts +76 -0
  451. package/node_modules/@engenty-wizards/shared/dist/decision.js +147 -0
  452. package/node_modules/@engenty-wizards/shared/dist/definition.d.ts +2922 -0
  453. package/node_modules/@engenty-wizards/shared/dist/definition.js +1920 -0
  454. package/node_modules/@engenty-wizards/shared/dist/engenty/data-tables/columns-format.d.ts +5 -0
  455. package/node_modules/@engenty-wizards/shared/dist/engenty/data-tables/columns-format.js +132 -0
  456. package/node_modules/@engenty-wizards/shared/dist/engenty/data-tables/columns-value.d.ts +11 -0
  457. package/node_modules/@engenty-wizards/shared/dist/engenty/data-tables/columns-value.js +209 -0
  458. package/node_modules/@engenty-wizards/shared/dist/engenty/data-tables/columns.d.ts +532 -0
  459. package/node_modules/@engenty-wizards/shared/dist/engenty/data-tables/columns.js +217 -0
  460. package/node_modules/@engenty-wizards/shared/dist/engenty/data-tables/index.d.ts +3 -0
  461. package/node_modules/@engenty-wizards/shared/dist/engenty/data-tables/index.js +3 -0
  462. package/node_modules/@engenty-wizards/shared/dist/engenty/search-index/catalog-lexical.d.ts +14 -0
  463. package/node_modules/@engenty-wizards/shared/dist/engenty/search-index/catalog-lexical.js +166 -0
  464. package/node_modules/@engenty-wizards/shared/dist/engenty/search-index/catalog-rank.d.ts +33 -0
  465. package/node_modules/@engenty-wizards/shared/dist/engenty/search-index/catalog-rank.js +99 -0
  466. package/node_modules/@engenty-wizards/shared/dist/feature-flags.d.ts +78 -0
  467. package/node_modules/@engenty-wizards/shared/dist/feature-flags.js +70 -0
  468. package/node_modules/@engenty-wizards/shared/dist/features.d.ts +41 -0
  469. package/node_modules/@engenty-wizards/shared/dist/features.js +89 -0
  470. package/node_modules/@engenty-wizards/shared/dist/fit.d.ts +71 -0
  471. package/node_modules/@engenty-wizards/shared/dist/fit.js +382 -0
  472. package/node_modules/@engenty-wizards/shared/dist/json-schema.d.ts +14 -0
  473. package/node_modules/@engenty-wizards/shared/dist/json-schema.js +66 -0
  474. package/node_modules/@engenty-wizards/shared/dist/knowledge.d.ts +199 -0
  475. package/node_modules/@engenty-wizards/shared/dist/knowledge.js +68 -0
  476. package/node_modules/@engenty-wizards/shared/dist/marketplace-entry.d.ts +35 -0
  477. package/node_modules/@engenty-wizards/shared/dist/marketplace-entry.js +107 -0
  478. package/node_modules/@engenty-wizards/shared/dist/marketplace-search.d.ts +20 -0
  479. package/node_modules/@engenty-wizards/shared/dist/marketplace-search.js +136 -0
  480. package/node_modules/@engenty-wizards/shared/dist/marketplace.d.ts +227 -0
  481. package/node_modules/@engenty-wizards/shared/dist/marketplace.js +354 -0
  482. package/node_modules/@engenty-wizards/shared/dist/merge.d.ts +7 -0
  483. package/node_modules/@engenty-wizards/shared/dist/merge.js +40 -0
  484. package/node_modules/@engenty-wizards/shared/dist/numbers.d.ts +24 -0
  485. package/node_modules/@engenty-wizards/shared/dist/numbers.js +54 -0
  486. package/node_modules/@engenty-wizards/shared/dist/projects.d.ts +224 -0
  487. package/node_modules/@engenty-wizards/shared/dist/projects.js +319 -0
  488. package/node_modules/@engenty-wizards/shared/dist/providers.d.ts +101 -0
  489. package/node_modules/@engenty-wizards/shared/dist/providers.js +390 -0
  490. package/node_modules/@engenty-wizards/shared/dist/run.d.ts +680 -0
  491. package/node_modules/@engenty-wizards/shared/dist/run.js +620 -0
  492. package/node_modules/@engenty-wizards/shared/dist/runner-texts.d.ts +546 -0
  493. package/node_modules/@engenty-wizards/shared/dist/runner-texts.js +523 -0
  494. package/node_modules/@engenty-wizards/shared/dist/runners.d.ts +93 -0
  495. package/node_modules/@engenty-wizards/shared/dist/runners.js +146 -0
  496. package/node_modules/@engenty-wizards/shared/dist/shape.d.ts +102 -0
  497. package/node_modules/@engenty-wizards/shared/dist/shape.js +318 -0
  498. package/node_modules/@engenty-wizards/shared/dist/space-data.d.ts +89 -0
  499. package/node_modules/@engenty-wizards/shared/dist/space-data.js +47 -0
  500. package/node_modules/@engenty-wizards/shared/dist/store.d.ts +117 -0
  501. package/node_modules/@engenty-wizards/shared/dist/store.js +81 -0
  502. package/node_modules/@engenty-wizards/shared/dist/surface.d.ts +115 -0
  503. package/node_modules/@engenty-wizards/shared/dist/surface.js +442 -0
  504. package/node_modules/@engenty-wizards/shared/dist/texts.d.ts +45 -0
  505. package/node_modules/@engenty-wizards/shared/dist/texts.js +54 -0
  506. package/node_modules/@engenty-wizards/shared/dist/translation.d.ts +23 -0
  507. package/node_modules/@engenty-wizards/shared/dist/translation.js +154 -0
  508. package/node_modules/@engenty-wizards/shared/dist/wizard-package.d.ts +48 -0
  509. package/node_modules/@engenty-wizards/shared/dist/wizard-package.js +49 -0
  510. package/node_modules/@engenty-wizards/shared/dist/workspace.d.ts +16 -0
  511. package/node_modules/@engenty-wizards/shared/dist/workspace.js +51 -0
  512. package/node_modules/@engenty-wizards/shared/package.json +10 -0
  513. package/package.json +77 -4
  514. package/plugin/.claude-plugin/plugin.json +9 -0
  515. package/plugin/.mcp.json +8 -0
  516. package/plugin/commands/wizard.md +8 -0
  517. package/plugin/skills/build-wizard/SKILL.md +27 -0
  518. package/plugin/skills/use-wizard/SKILL.md +18 -0
@@ -0,0 +1,167 @@
1
+ import { langNameEn } from "@engenty-wizards/shared/definition";
2
+ import { NotedError } from "../model-errors.js";
3
+ import { conversationAccess } from "../models.js";
4
+ /**
5
+ * A live conversation with a wizard: the browser talks to a realtime speech model directly
6
+ * (audio both ways over WebRTC); this runtime only mints the short-lived secret the browser
7
+ * connects with, and writes the instructions and the tools the model drives the run with. The
8
+ * tools run in the browser against the run's own routes, so audio never touches the runtime.
9
+ */
10
+ const SECRETS_URL = "https://api.openai.com/v1/realtime/client_secrets";
11
+ const CALLS_URL = "https://api.openai.com/v1/realtime/calls";
12
+ /** How long a minted secret opens a session; the session itself goes on until it ends. */
13
+ const SECRET_TTL_SECONDS = 600;
14
+ /** The voice the wizard speaks with: one that speaks every language engenty does. */
15
+ const VOICE = "marin";
16
+ /** What the model may do: one tool per command of the run page, run by the browser. */
17
+ export const CONVERSATION_TOOLS = [
18
+ {
19
+ type: "function",
20
+ name: "get_state",
21
+ description: "What the run waits for right now: the page with its fields (which are answered, which are still open, which need the screen), the review, or what the wizard is working on. Call it when unsure, and after the state changed.",
22
+ parameters: { type: "object", properties: {}, additionalProperties: false },
23
+ },
24
+ {
25
+ type: "function",
26
+ name: "set_field",
27
+ description: "Keeps the person's answer to one field of the current page. Call it once per field as soon as the person answered; for a choice give one of the options exactly.",
28
+ parameters: {
29
+ type: "object",
30
+ properties: {
31
+ field: { type: "string", description: "The field's id from the state." },
32
+ value: {
33
+ description: "The answer: a string, a number, true/false for a toggle, or an array of options for a multiple choice.",
34
+ },
35
+ },
36
+ required: ["field", "value"],
37
+ additionalProperties: false,
38
+ },
39
+ },
40
+ {
41
+ type: "function",
42
+ name: "submit_page",
43
+ description: "Sends the current page once every required field that can be answered by voice has a value. Fields that need the screen are filled there by the person; say so and wait.",
44
+ parameters: { type: "object", properties: {}, additionalProperties: false },
45
+ },
46
+ {
47
+ type: "function",
48
+ name: "accept_review",
49
+ description: "Accepts what the wizard made, when the person is happy with it.",
50
+ parameters: { type: "object", properties: {}, additionalProperties: false },
51
+ },
52
+ {
53
+ type: "function",
54
+ name: "regenerate",
55
+ description: "Asks the wizard to make one of the shown outputs again, with what should change.",
56
+ parameters: {
57
+ type: "object",
58
+ properties: {
59
+ target: { type: "string", description: "The step id of the output, from the state." },
60
+ note: { type: "string", description: "What should change, in the person's words." },
61
+ },
62
+ required: ["target", "note"],
63
+ additionalProperties: false,
64
+ },
65
+ },
66
+ {
67
+ type: "function",
68
+ name: "answer_ask",
69
+ description: "Answers the question a running step asks before it changes something in a connected account: allow it, or skip it.",
70
+ parameters: {
71
+ type: "object",
72
+ properties: { allow: { type: "boolean" } },
73
+ required: ["allow"],
74
+ additionalProperties: false,
75
+ },
76
+ },
77
+ {
78
+ type: "function",
79
+ name: "look",
80
+ description: "Takes a look through the person's camera right now: a picture of what they are showing arrives as the next message. Only while the camera is on; otherwise ask them to switch it on.",
81
+ parameters: { type: "object", properties: {}, additionalProperties: false },
82
+ },
83
+ {
84
+ type: "function",
85
+ name: "take_photo",
86
+ description: "Takes a photo with the person's camera and puts it into a photo field of the current page. Say 'hold it still' first. Only while the camera is on.",
87
+ parameters: {
88
+ type: "object",
89
+ properties: { field: { type: "string", description: "The id of the image field." } },
90
+ required: ["field"],
91
+ additionalProperties: false,
92
+ },
93
+ },
94
+ {
95
+ type: "function",
96
+ name: "go_back",
97
+ description: "Goes back to the page before, when the person wants to change an earlier answer.",
98
+ parameters: { type: "object", properties: {}, additionalProperties: false },
99
+ },
100
+ ];
101
+ /** The rules the model speaks by: written in English, it speaks the wizard's language. */
102
+ export function conversationInstructions(view) {
103
+ const about = [`You are ${view.wizard.title}.`, view.wizard.description, view.wizard.intro]
104
+ .filter(Boolean)
105
+ .join(" ");
106
+ const rules = [
107
+ "You hold a conversation that fills in a wizard step by step. The person also sees the wizard on the screen.",
108
+ `Speak ${langNameEn(view.lang)} (${view.lang}), short and friendly, as on the phone. One sentence, then the next question.`,
109
+ "Ask one field at a time, in the order of the state. After each answer call set_field. When every field you can fill by voice is answered, call submit_page.",
110
+ "For a choice, name the options (at most four at a time) and pass exactly one of them on.",
111
+ "Read e-mail addresses, links and numbers back before passing them on.",
112
+ "A field that needs the screen (a photo, a file, a signature, a connection) is filled there by the person: say so in one sentence and wait for the next state.",
113
+ "While the wizard works, say in one sentence what it is doing and wait. Never make anything up.",
114
+ "At a review, sum the text up in a few words and ask whether it fits. Then accept_review, or regenerate with what the person wants changed.",
115
+ "At the end, say what was made and that it is on the screen.",
116
+ "With the camera on you can see what the person shows with look, and put a photo into a photo field with take_photo; ask for a photo field like this: 'Hold it to the camera, I will take the picture.' With the camera off, ask the person to switch it on, or leave the field to the screen.",
117
+ ];
118
+ return `${about}\n\n${rules.join("\n")}`;
119
+ }
120
+ /** Mints the secret a browser opens a session with; a failure carries a note for the run's language. */
121
+ export async function mintConversation(view) {
122
+ const { apiKey, model } = await conversationAccess();
123
+ const res = await fetch(SECRETS_URL, {
124
+ method: "POST",
125
+ headers: { authorization: `Bearer ${apiKey}`, "content-type": "application/json" },
126
+ body: JSON.stringify({
127
+ expires_after: { anchor: "created_at", seconds: SECRET_TTL_SECONDS },
128
+ session: {
129
+ type: "realtime",
130
+ model,
131
+ instructions: conversationInstructions(view),
132
+ tools: CONVERSATION_TOOLS,
133
+ tool_choice: "auto",
134
+ audio: {
135
+ // What the person said, written down: the call screen shows it as captions.
136
+ input: {
137
+ transcription: { model: "gpt-4o-mini-transcribe" },
138
+ // Phones and laptops play the wizard's voice through their own speakers, which the mic
139
+ // picks up: far-field filtering and a higher bar for speech keep it from interrupting itself.
140
+ noise_reduction: { type: "far_field" },
141
+ turn_detection: { type: "server_vad", threshold: 0.7, silence_duration_ms: 600 },
142
+ },
143
+ output: { voice: VOICE },
144
+ },
145
+ },
146
+ }),
147
+ signal: AbortSignal.timeout(15_000),
148
+ });
149
+ if (!res.ok) {
150
+ // The provider's answer goes to the log; the page hears only that it did not work, and why in a word.
151
+ const detail = (await res.text()).slice(0, 500);
152
+ console.error(`[talk] the provider refused the session (${res.status}):`, detail);
153
+ throw new NotedError(res.status === 401 || res.status === 403
154
+ ? { code: "talkKeyRefused" }
155
+ : { code: "talkFailed", params: { status: res.status } });
156
+ }
157
+ const body = (await res.json());
158
+ if (!body.value) {
159
+ throw new NotedError({ code: "talkNoSecret" });
160
+ }
161
+ return {
162
+ clientSecret: body.value,
163
+ expiresAt: new Date((body.expires_at ?? Date.now() / 1000 + SECRET_TTL_SECONDS) * 1000).toISOString(),
164
+ model,
165
+ endpoint: `${CALLS_URL}?model=${encodeURIComponent(model)}`,
166
+ };
167
+ }
@@ -0,0 +1,121 @@
1
+ import { spawn } from "node:child_process";
2
+ import { mkdtemp, readFile, rm, writeFile } from "node:fs/promises";
3
+ import { tmpdir } from "node:os";
4
+ import { join } from "node:path";
5
+ import { env } from "../env.js";
6
+ let ffmpegCheck = null;
7
+ export function hasFfmpeg() {
8
+ ffmpegCheck ??= new Promise((resolve) => {
9
+ const p = spawn(env.ffmpegPath, ["-version"], { stdio: "ignore" });
10
+ p.on("error", () => resolve(false));
11
+ p.on("exit", (code) => resolve(code === 0));
12
+ });
13
+ return ffmpegCheck;
14
+ }
15
+ /** Runs ffmpeg to its end; what it wrote to stderr comes back either way. */
16
+ export function ffmpeg(args) {
17
+ return new Promise((resolve, reject) => {
18
+ const p = spawn(env.ffmpegPath, ["-hide_banner", ...args], {
19
+ stdio: ["ignore", "ignore", "pipe"],
20
+ });
21
+ let stderr = "";
22
+ p.stderr.on("data", (d) => {
23
+ stderr = (stderr + String(d)).slice(-20_000);
24
+ });
25
+ p.on("error", reject);
26
+ p.on("exit", (code) => resolve({ code: code ?? 1, stderr }));
27
+ });
28
+ }
29
+ /** A folder for one job's files, removed when the job is over. */
30
+ export async function withTempDir(use) {
31
+ const dir = await mkdtemp(join(tmpdir(), "wizard-media-"));
32
+ try {
33
+ return await use(dir);
34
+ }
35
+ finally {
36
+ await rm(dir, { recursive: true, force: true });
37
+ }
38
+ }
39
+ /** What ffmpeg says about a media file: how long it is, whether it carries sound, its picture size. */
40
+ export async function probeMedia(path) {
41
+ // Without an output ffmpeg prints the streams and exits with an error; the print is the answer.
42
+ const { stderr } = await ffmpeg(["-i", path]);
43
+ const m = stderr.match(/Duration:\s*(\d+):(\d+):(\d+(?:\.\d+)?)/);
44
+ const seconds = m ? Number(m[1]) * 3600 + Number(m[2]) * 60 + Number(m[3]) : 0;
45
+ const size = stderr.match(/Stream #\d+:\d+.*Video:.*?, (\d{2,5})x(\d{2,5})/);
46
+ return {
47
+ seconds,
48
+ audio: /Stream #\d+:\d+.*Audio:/.test(stderr),
49
+ width: size ? Number(size[1]) : 0,
50
+ height: size ? Number(size[2]) : 0,
51
+ };
52
+ }
53
+ /**
54
+ * A video no larger than `short` pixels on its short side (720 for 720p), sound kept. One that
55
+ * fits already comes back as it is; without ffmpeg too.
56
+ */
57
+ export async function capVideo(bytes, short) {
58
+ if (!(await hasFfmpeg())) {
59
+ return bytes;
60
+ }
61
+ return withTempDir(async (dir) => {
62
+ const input = join(dir, "in.mp4");
63
+ const out = join(dir, "out.mp4");
64
+ await writeFile(input, bytes);
65
+ const { width, height } = await probeMedia(input);
66
+ if (!(width && height) || Math.min(width, height) <= short) {
67
+ return bytes;
68
+ }
69
+ const scale = width >= height ? `scale=-2:${short}` : `scale=${short}:-2`;
70
+ const { code } = await ffmpeg([
71
+ "-y",
72
+ "-loglevel",
73
+ "error",
74
+ "-i",
75
+ input,
76
+ "-vf",
77
+ scale,
78
+ "-c:v",
79
+ "libx264",
80
+ "-preset",
81
+ "veryfast",
82
+ "-crf",
83
+ "21",
84
+ "-pix_fmt",
85
+ "yuv420p",
86
+ "-c:a",
87
+ "copy",
88
+ "-movflags",
89
+ "+faststart",
90
+ out,
91
+ ]);
92
+ return code === 0 ? new Uint8Array(await readFile(out)) : bytes;
93
+ });
94
+ }
95
+ /**
96
+ * Any audio as MP3 — what every phone and browser plays — with `tags` written into the file
97
+ * (ID3). An MP3 is not encoded again, only tagged. `null` without ffmpeg.
98
+ */
99
+ export async function toMp3(bytes, ext, tags = {}) {
100
+ if (!(await hasFfmpeg())) {
101
+ return null;
102
+ }
103
+ return withTempDir(async (dir) => {
104
+ const input = join(dir, `in.${ext}`);
105
+ const out = join(dir, "out.mp3");
106
+ await writeFile(input, bytes);
107
+ const { code } = await ffmpeg([
108
+ "-y",
109
+ "-loglevel",
110
+ "error",
111
+ "-i",
112
+ input,
113
+ ...(ext === "mp3" ? ["-codec:a", "copy"] : ["-codec:a", "libmp3lame", "-q:a", "3"]),
114
+ "-id3v2_version",
115
+ "3",
116
+ ...Object.entries(tags).flatMap(([key, value]) => ["-metadata", `${key}=${value}`]),
117
+ out,
118
+ ]);
119
+ return code === 0 ? new Uint8Array(await readFile(out)) : null;
120
+ });
121
+ }
@@ -0,0 +1,120 @@
1
+ import { experimental_generateVideo, generateImage, generateSpeech, generateText } from "ai";
2
+ import { extFor } from "../files/storage.js";
3
+ import { imageCostUsd, imageModel, isHarnessVendor, speechCostUsd, speechModel, textModel, videoCostUsd, videoModel, } from "../models.js";
4
+ import { capVideo, toMp3 } from "./ffmpeg.js";
5
+ import { speechTags } from "./marking.js";
6
+ /** One image. Gemini image models answer through chat with an image file; the rest through generateImage. */
7
+ export async function generateImageMedia(input) {
8
+ const { prompt, reference, abortSignal } = input;
9
+ const aspect = (input.aspectRatio ?? "1:1");
10
+ const image = await imageModel(input.call);
11
+ // The gateway books its own calls; a client's images are part of the person's subscription.
12
+ const costUsd = image.metered || isHarnessVendor(image.vendor) ? 0 : imageCostUsd(image.ref);
13
+ if (image.chat) {
14
+ const chat = await textModel("image", input.call);
15
+ const text = `${prompt}\n\nAspect ratio: ${aspect}. Return exactly one image.`;
16
+ const result = await generateText({
17
+ model: chat.model,
18
+ abortSignal,
19
+ providerOptions: {
20
+ google: { responseModalities: ["IMAGE", "TEXT"], imageConfig: { aspectRatio: aspect } },
21
+ },
22
+ messages: [
23
+ {
24
+ role: "user",
25
+ content: reference
26
+ ? [
27
+ { type: "text", text },
28
+ { type: "image", image: reference.bytes, mediaType: reference.mediaType },
29
+ ]
30
+ : text,
31
+ },
32
+ ],
33
+ });
34
+ const file = result.files?.find((f) => (f.mediaType ?? "").startsWith("image/"));
35
+ if (!file?.uint8Array?.byteLength) {
36
+ throw new Error("The image model returned no image.");
37
+ }
38
+ return {
39
+ bytes: file.uint8Array,
40
+ mime: file.mediaType ?? "image/png",
41
+ costUsd,
42
+ system: image.ref,
43
+ };
44
+ }
45
+ const result = await generateImage({
46
+ model: image.model,
47
+ n: 1,
48
+ abortSignal,
49
+ prompt: reference ? { images: [reference.bytes], text: prompt } : prompt,
50
+ aspectRatio: aspect,
51
+ });
52
+ const img = result.image ?? result.images?.[0];
53
+ if (!img?.uint8Array?.byteLength) {
54
+ throw new Error("The image model returned no image.");
55
+ }
56
+ return {
57
+ bytes: img.uint8Array,
58
+ mime: img.mediaType ?? "image/png",
59
+ costUsd,
60
+ system: image.ref,
61
+ };
62
+ }
63
+ /** The short side of a video in pixels, per resolution. */
64
+ const VIDEO_SHORT_SIDE = { "720p": 720, "480p": 480 };
65
+ /** The pixel size a model is asked for: the short side as the resolution says, the long one as the aspect. */
66
+ function videoSize(aspect, resolution) {
67
+ const short = VIDEO_SHORT_SIDE[resolution];
68
+ const [w, h] = aspect.split(":").map(Number);
69
+ const long = Math.round((short * Math.max(w, h)) / Math.min(w, h) / 2) * 2;
70
+ return w >= h ? `${long}x${short}` : `${short}x${long}`;
71
+ }
72
+ /**
73
+ * One video clip. Text-to-video, or image-to-video when a reference is given. Rendered at 720p,
74
+ * or 480p when the step asks: a model that gives more anyway is scaled down to it.
75
+ */
76
+ export async function generateVideoMedia(input) {
77
+ const duration = Math.min(Math.max(Math.round(input.duration ?? 8), 4), 10);
78
+ const aspect = (input.aspectRatio === "1:1" ? "16:9" : (input.aspectRatio ?? "16:9"));
79
+ const resolution = input.resolution ?? "720p";
80
+ const videoClass = await videoModel(input.call);
81
+ const result = await experimental_generateVideo({
82
+ model: videoClass.model,
83
+ prompt: input.reference ? { image: input.reference.bytes, text: input.prompt } : input.prompt,
84
+ aspectRatio: aspect,
85
+ resolution: videoSize(aspect, resolution),
86
+ duration,
87
+ abortSignal: input.abortSignal,
88
+ });
89
+ const video = result.video ?? result.videos?.[0];
90
+ if (!video?.uint8Array?.byteLength) {
91
+ throw new Error("The video model returned no video.");
92
+ }
93
+ return {
94
+ bytes: await capVideo(video.uint8Array, VIDEO_SHORT_SIDE[resolution]),
95
+ mime: video.mediaType ?? "video/mp4",
96
+ costUsd: videoClass.metered ? 0 : videoCostUsd(videoClass.ref, duration, resolution),
97
+ system: videoClass.ref,
98
+ };
99
+ }
100
+ /** A text read aloud, as MP3 where ffmpeg is at hand (else as the model gave it). */
101
+ export async function generateSpeechMedia(input) {
102
+ const speech = await speechModel(input.call);
103
+ const result = await generateSpeech({
104
+ model: speech.model,
105
+ text: input.text,
106
+ instructions: input.style || undefined,
107
+ abortSignal: input.abortSignal,
108
+ });
109
+ const audio = result.audio;
110
+ if (!audio?.uint8Array?.byteLength) {
111
+ throw new Error("The speech model returned no audio.");
112
+ }
113
+ const mime = audio.mediaType ?? "audio/mpeg";
114
+ const costUsd = speech.metered ? 0 : speechCostUsd(speech.ref, input.text.length);
115
+ // As MP3, and saying in its tags that a model speaks here.
116
+ const mp3 = await toMp3(audio.uint8Array, extFor(mime) === "bin" ? "wav" : extFor(mime), speechTags({ origin: "generated", system: speech.ref }));
117
+ return mp3
118
+ ? { bytes: mp3, mime: "audio/mpeg", costUsd, system: speech.ref }
119
+ : { bytes: audio.uint8Array, mime, costUsd, system: speech.ref };
120
+ }
@@ -0,0 +1,121 @@
1
+ import { crc32 } from "node:zlib";
2
+ const SOURCE_TYPE = {
3
+ generated: "http://cv.iptc.org/newscodes/digitalsourcetype/trainedAlgorithmicMedia",
4
+ edited: "http://cv.iptc.org/newscodes/digitalsourcetype/compositeWithTrainedAlgorithmicMedia",
5
+ };
6
+ function xml(s) {
7
+ return s
8
+ .replace(/&/g, "&amp;")
9
+ .replace(/</g, "&lt;")
10
+ .replace(/>/g, "&gt;")
11
+ .replace(/"/g, "&quot;");
12
+ }
13
+ /** The XMP packet that says how the file came to be. */
14
+ export function xmpPacket(marking) {
15
+ const system = marking.system ? `\n Iptc4xmpExt:AISystemUsed="${xml(marking.system)}"` : "";
16
+ return `<?xpacket begin="" id="W5M0MpCehiHzreSzNTczkc9d"?>
17
+ <x:xmpmeta xmlns:x="adobe:ns:meta/">
18
+ <rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
19
+ <rdf:Description rdf:about=""
20
+ xmlns:Iptc4xmpExt="http://iptc.org/std/Iptc4xmpExt/2008-02-29/"
21
+ xmlns:xmp="http://ns.adobe.com/xap/1.0/"
22
+ Iptc4xmpExt:DigitalSourceType="${SOURCE_TYPE[marking.origin]}"${system}
23
+ xmp:CreatorTool="engenty wizards"/>
24
+ </rdf:RDF>
25
+ </x:xmpmeta>
26
+ <?xpacket end="w"?>`;
27
+ }
28
+ /** Whether the file already says it is AI media: signed Content Credentials, or a source type in its XMP. */
29
+ export function isMarked(bytes) {
30
+ const data = Buffer.from(bytes.buffer, bytes.byteOffset, bytes.byteLength);
31
+ return data.includes("c2pa") || data.includes("DigitalSourceType");
32
+ }
33
+ const PNG_SIGNATURE = Buffer.from([0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a]);
34
+ /** PNG: an iTXt chunk "XML:com.adobe.xmp" right after the header chunk. */
35
+ function markPng(data, xmp) {
36
+ if (!data.subarray(0, 8).equals(PNG_SIGNATURE) || data.toString("latin1", 12, 16) !== "IHDR") {
37
+ return null;
38
+ }
39
+ const headerEnd = 8 + 12 + data.readUInt32BE(8);
40
+ const body = Buffer.concat([
41
+ Buffer.from("XML:com.adobe.xmp\0\0\0\0\0", "latin1"),
42
+ Buffer.from(xmp, "utf8"),
43
+ ]);
44
+ const type = Buffer.from("iTXt", "latin1");
45
+ const length = Buffer.alloc(4);
46
+ length.writeUInt32BE(body.length);
47
+ const check = Buffer.alloc(4);
48
+ check.writeUInt32BE(crc32(Buffer.concat([type, body])) >>> 0);
49
+ return Buffer.concat([
50
+ data.subarray(0, headerEnd),
51
+ length,
52
+ type,
53
+ body,
54
+ check,
55
+ data.subarray(headerEnd),
56
+ ]);
57
+ }
58
+ /** JPEG: an APP1 segment with the XMP, after the start marker and the JFIF/Exif segments. */
59
+ function markJpeg(data, xmp) {
60
+ if (data[0] !== 0xff || data[1] !== 0xd8) {
61
+ return null;
62
+ }
63
+ let at = 2;
64
+ // Skip APP0 (JFIF) and an APP1 that holds Exif: readers expect them first.
65
+ while (at + 4 <= data.length &&
66
+ data[at] === 0xff &&
67
+ (data[at + 1] === 0xe0 || data[at + 1] === 0xe1)) {
68
+ at += 2 + data.readUInt16BE(at + 2);
69
+ }
70
+ const body = Buffer.concat([
71
+ Buffer.from("http://ns.adobe.com/xap/1.0/\0", "latin1"),
72
+ Buffer.from(xmp, "utf8"),
73
+ ]);
74
+ if (body.length + 2 > 0xffff) {
75
+ return null;
76
+ }
77
+ const head = Buffer.from([0xff, 0xe1, 0, 0]);
78
+ head.writeUInt16BE(body.length + 2, 2);
79
+ return Buffer.concat([data.subarray(0, at), head, body, data.subarray(at)]);
80
+ }
81
+ /** The id of the box that holds XMP in an MP4 or QuickTime file. */
82
+ const XMP_BOX = Buffer.from("be7acfcb97a942e89c71999491e3afac", "hex");
83
+ /** MP4 / MOV: a top-level `uuid` box with the XMP, at the end of the file. */
84
+ function markMp4(data, xmp) {
85
+ if (data.toString("latin1", 4, 8) !== "ftyp") {
86
+ return null;
87
+ }
88
+ const body = Buffer.from(xmp, "utf8");
89
+ const head = Buffer.alloc(8);
90
+ head.writeUInt32BE(8 + XMP_BOX.length + body.length);
91
+ head.write("uuid", 4, "latin1");
92
+ return Buffer.concat([data, head, XMP_BOX, body]);
93
+ }
94
+ /**
95
+ * The file with its marking. Returned unchanged when it is already marked, or of a kind this
96
+ * cannot write (audio is tagged where it is encoded, see `speechTags`).
97
+ */
98
+ export function markMedia(bytes, mime, marking) {
99
+ if (isMarked(bytes)) {
100
+ return bytes;
101
+ }
102
+ const data = Buffer.from(bytes.buffer, bytes.byteOffset, bytes.byteLength);
103
+ const xmp = xmpPacket(marking);
104
+ const marked = mime === "image/png"
105
+ ? markPng(data, xmp)
106
+ : mime === "image/jpeg"
107
+ ? markJpeg(data, xmp)
108
+ : mime === "video/mp4" || mime === "video/quicktime"
109
+ ? markMp4(data, xmp)
110
+ : null;
111
+ return marked ? new Uint8Array(marked) : bytes;
112
+ }
113
+ /** What an audio file says about itself, as the tags ffmpeg writes (ID3 for MP3). */
114
+ export function speechTags(marking) {
115
+ return {
116
+ comment: "AI-generated voice",
117
+ DigitalSourceType: SOURCE_TYPE[marking.origin],
118
+ ...(marking.system ? { AISystemUsed: marking.system } : {}),
119
+ encoded_by: "engenty wizards",
120
+ };
121
+ }