@theoremjs/studio 0.0.0-stage → 0.3.2

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 (473) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +295 -2
  3. package/agreement.d.ts +14 -0
  4. package/agreement.js +80 -0
  5. package/asks.d.ts +47 -0
  6. package/asks.js +54 -0
  7. package/browser-connection.d.ts +49 -0
  8. package/browser-connection.js +215 -0
  9. package/browser-engine.d.ts +11 -0
  10. package/browser-engine.js +11 -0
  11. package/browser-execution.d.ts +6 -0
  12. package/browser-execution.js +18 -0
  13. package/browser-live.d.ts +4 -0
  14. package/browser-live.js +132 -0
  15. package/browser-transport.d.ts +33 -0
  16. package/browser-transport.js +229 -0
  17. package/browser.d.ts +4 -0
  18. package/browser.js +4 -0
  19. package/canonical.d.ts +10 -0
  20. package/canonical.js +25 -0
  21. package/compile-workspace.d.ts +28 -0
  22. package/compile-workspace.js +295 -0
  23. package/compile.d.ts +65 -0
  24. package/compile.js +1605 -0
  25. package/concierge-demo.d.ts +17 -0
  26. package/concierge-demo.js +1230 -0
  27. package/conversation-key.d.ts +5 -0
  28. package/conversation-key.js +10 -0
  29. package/decision-example-images.d.ts +30 -0
  30. package/decision-example-images.js +30 -0
  31. package/deno.json +3 -0
  32. package/draft.d.ts +407 -0
  33. package/draft.js +505 -0
  34. package/editors.d.ts +29 -0
  35. package/editors.js +51 -0
  36. package/example-embedding-files.d.ts +11 -0
  37. package/example-embedding-files.js +20 -0
  38. package/example.d.ts +36 -0
  39. package/example.js +357 -0
  40. package/guardrail-probe.d.ts +100 -0
  41. package/guardrail-probe.js +722 -0
  42. package/held-credentials.d.ts +28 -0
  43. package/held-credentials.js +87 -0
  44. package/installed.mjs +40 -0
  45. package/lent-keys.d.ts +122 -0
  46. package/lent-keys.js +47 -0
  47. package/line-diff.d.ts +15 -0
  48. package/line-diff.js +41 -0
  49. package/live-connection.d.ts +22 -0
  50. package/live-connection.js +27 -0
  51. package/live-session-bridge.d.ts +15 -0
  52. package/live-session-bridge.js +202 -0
  53. package/map-line.d.ts +19 -0
  54. package/map-line.js +42 -0
  55. package/map.d.ts +154 -0
  56. package/map.js +525 -0
  57. package/media-accept.d.ts +19 -0
  58. package/media-accept.js +65 -0
  59. package/mod.d.ts +39 -0
  60. package/mod.js +33 -0
  61. package/origins.d.ts +52 -0
  62. package/origins.js +165 -0
  63. package/package.json +85 -4
  64. package/page/assets/Banner-BISz3nXA.js +2 -0
  65. package/page/assets/BottomSheet-BwfBDtje.js +1 -0
  66. package/page/assets/Card-Lp-0P5eL.js +1 -0
  67. package/page/assets/CardWall-CBRLdDZW.js +1 -0
  68. package/page/assets/Center-nHS1JSux.js +1 -0
  69. package/page/assets/CheckboxInput-Cj5pk-KI.js +2 -0
  70. package/page/assets/CodeBlock-C7XJ4ioE.js +51 -0
  71. package/page/assets/CollapsibleGroup-N7_SOjbm.js +2 -0
  72. package/page/assets/ContextMenu-CBu9H-9H.js +2 -0
  73. package/page/assets/DateInput-BGrQ5tPC.js +1 -0
  74. package/page/assets/Dialog-DELWQo-v.js +1 -0
  75. package/page/assets/EmptyState-C8W4JKBZ.js +1 -0
  76. package/page/assets/HoverCard-D1Y1ltWQ.js +1 -0
  77. package/page/assets/Icon-JrysT8aU.js +3 -0
  78. package/page/assets/IconAlertTriangle-BqAEqqdU.js +1 -0
  79. package/page/assets/IconButton-DlOGzJIX.js +1 -0
  80. package/page/assets/IconEye-BB5aY-wQ.js +1 -0
  81. package/page/assets/IconFileText-6zOFKKrF.js +1 -0
  82. package/page/assets/IconSearch-BTx66a40.js +1 -0
  83. package/page/assets/IconShield-DDOh7Gr5.js +1 -0
  84. package/page/assets/ItemSwipeLayer-Ckn4X6h9.js +1 -0
  85. package/page/assets/PaneState-BvA2tLQg.js +1 -0
  86. package/page/assets/PaneState-eUzUkNE8.css +1 -0
  87. package/page/assets/ScrollableArea-Ckugdj1N.js +1 -0
  88. package/page/assets/Section-DJ97F7QE.js +1 -0
  89. package/page/assets/SegmentedControlItem-h-aaXzyS.js +1 -0
  90. package/page/assets/SidePanel-BL32abk8.js +1 -0
  91. package/page/assets/StackItem-CQviqAfM.js +1 -0
  92. package/page/assets/Text-bum6zWWx.js +2 -0
  93. package/page/assets/TimestampHoverCard-DQIG0RZF.js +1 -0
  94. package/page/assets/ToolResultCharts-CgshSv9Q.js +1 -0
  95. package/page/assets/Tooltip-BH9xiRMl.js +1 -0
  96. package/page/assets/TraceInspector-_yZiz05W.js +1 -0
  97. package/page/assets/TraceOverview-BPO-HIYK.js +57 -0
  98. package/page/assets/VStack-CkVMcNiK.js +1 -0
  99. package/page/assets/_virtual_studio-type-sources-ByxqQaOG.js +12936 -0
  100. package/page/assets/arrive-DvbqpeRS.js +1 -0
  101. package/page/assets/browser-engine-CYq9DQAM.js +9 -0
  102. package/page/assets/browser-transport-D-2jDYe7.js +47 -0
  103. package/page/assets/codicon-DF1abBS2.ttf +0 -0
  104. package/page/assets/compile-egress-BSxOdX4K.js +23 -0
  105. package/page/assets/container.stylex-BmOi-8DQ.js +1 -0
  106. package/page/assets/createReactComponent-CZwsv6DD.js +1 -0
  107. package/page/assets/decision-example-images-CZGr7YIT.js +1 -0
  108. package/page/assets/devWarning-DxuplmRl.js +1 -0
  109. package/page/assets/editor-DjpsE8to.css +1 -0
  110. package/page/assets/editor.api-Cd3ViPQa.js +908 -0
  111. package/page/assets/editor.worker-6GY8RhDc.js +1 -0
  112. package/page/assets/editor.worker-BmdWdrHZ.js +33 -0
  113. package/page/assets/editors-BJX_S59A.js +1 -0
  114. package/page/assets/egress-automata-B5ZGE1mT.js +1 -0
  115. package/page/assets/embedding-space-view-CfQBPDxD.js +140 -0
  116. package/page/assets/encode-files-Bc3HJyAh.js +1 -0
  117. package/page/assets/export-agent-C3yyzXH8.js +43 -0
  118. package/page/assets/figtree-latin-400-normal-BD4aNku5.woff +0 -0
  119. package/page/assets/figtree-latin-400-normal-g7Dtegnw.woff2 +0 -0
  120. package/page/assets/figtree-latin-500-normal-BWnGEVsr.woff2 +0 -0
  121. package/page/assets/figtree-latin-500-normal-B_yy1phn.woff +0 -0
  122. package/page/assets/figtree-latin-600-normal-BM_oTo4n.woff +0 -0
  123. package/page/assets/figtree-latin-600-normal-Cv_xCTDl.woff2 +0 -0
  124. package/page/assets/figtree-latin-700-normal-BCCt2T1q.woff +0 -0
  125. package/page/assets/figtree-latin-700-normal-th6qEP7c.woff2 +0 -0
  126. package/page/assets/focusOutline.stylex-BT0kfa4t.js +1 -0
  127. package/page/assets/focusableSelector-DXZeMU85.js +1 -0
  128. package/page/assets/groupStyles-C7Ter7zC.js +1 -0
  129. package/page/assets/guardrail-tester-Gut5xK4a.js +9 -0
  130. package/page/assets/host-patterns-C9RMP16Q.js +1 -0
  131. package/page/assets/index-CvvmFKgS.js +105 -0
  132. package/page/assets/index-DOaHlqBo.css +1 -0
  133. package/page/assets/isRtlElement-BG33-k_H.js +1 -0
  134. package/page/assets/labels-provider-4TIWDvsE.js +3 -0
  135. package/page/assets/lent-keys-C32ems-I.js +1 -0
  136. package/page/assets/live-ingress-lDUGPwth.js +1 -0
  137. package/page/assets/live-messages-CnkL4GWi.js +1 -0
  138. package/page/assets/mergeProps-ptS-gIMz.js +1 -0
  139. package/page/assets/padding.stylex-B76907Zf.js +1 -0
  140. package/page/assets/preload-helper-DpV6A1kQ.js +1 -0
  141. package/page/assets/reader-BOCCYaRp.js +7 -0
  142. package/page/assets/register-CDgivxvX.js +2 -0
  143. package/page/assets/rolldown-runtime-hePW80VL.js +1 -0
  144. package/page/assets/schemas-BQ9Jydzb.js +56 -0
  145. package/page/assets/shaped-data-BcarWqd5.js +16 -0
  146. package/page/assets/sharedResizeObserver-4U9Xq5Oq.js +1 -0
  147. package/page/assets/stub-DhdcU_Ew.js +471 -0
  148. package/page/assets/studio-code-pane-C_SAbcOa.js +8 -0
  149. package/page/assets/studio-console-DZwlEsvr.js +3 -0
  150. package/page/assets/studio-decision-B0FnCAXA.js +1 -0
  151. package/page/assets/studio-embedding-CmA51HVo.js +2 -0
  152. package/page/assets/studio-host-console-By7hqu2l.js +2 -0
  153. package/page/assets/studio-live-BrcVQcyV.js +1 -0
  154. package/page/assets/studio-map-B_xSia-z.js +1 -0
  155. package/page/assets/studio-map-Bb06Tw1F.css +1 -0
  156. package/page/assets/studio-monaco-CbKf90i6.css +1 -0
  157. package/page/assets/studio-monaco-xfyfezQS.js +34 -0
  158. package/page/assets/studio-ts.worker-B-EXG4Sv.js +67741 -0
  159. package/page/assets/studio-ts.worker-BXtW3z-O.js +1 -0
  160. package/page/assets/studio-type-checker-BOvxudki.js +23 -0
  161. package/page/assets/themeProps-3IqahpCr.js +1 -0
  162. package/page/assets/tokens.stylex-DkHf0P9C.js +1 -0
  163. package/page/assets/tool-schema-idaOe2nI.js +18 -0
  164. package/page/assets/trace-patterns-DnYJa0nI.js +1 -0
  165. package/page/assets/trace-record-C3zNksA_.js +1 -0
  166. package/page/assets/trace-schema-9CdEyG6Q.js +1 -0
  167. package/page/assets/tree-DqyAMsbI.js +3 -0
  168. package/page/assets/turn-client-Du3Um3Mg.js +2 -0
  169. package/page/assets/types-BhfXQCLx.js +1 -0
  170. package/page/assets/typescript-20GgZ8PJ.js +1 -0
  171. package/page/assets/use-one-call-Hcs8YBp1.js +1 -0
  172. package/page/assets/useAdaptivePresentation-BzmPCddb.js +1 -0
  173. package/page/assets/useClipboard-BgGRxRMJ.js +1 -0
  174. package/page/assets/useContainerReveal-BFy8N_QU.js +1 -0
  175. package/page/assets/useDevWarning-Z9SoixOP.js +1 -0
  176. package/page/assets/useLayerDismissal-B_G7IWpC.js +1 -0
  177. package/page/assets/useMediaQuery-BCT0NUeZ.js +1 -0
  178. package/page/assets/useScrollLock-Dyf6PHJt.js +1 -0
  179. package/page/assets/useScrollableArea-0NzdiBCq.js +1 -0
  180. package/page/assets/useTooltip-CJM_xhLB.js +1 -0
  181. package/page/assets/workspace-DZALqEDX.js +1 -0
  182. package/page/assets/zip-DTcEfps6.js +1 -0
  183. package/page/index.html +90 -0
  184. package/page.mjs +49 -0
  185. package/people.d.ts +87 -0
  186. package/people.js +110 -0
  187. package/policy.d.ts +43 -0
  188. package/policy.js +102 -0
  189. package/ports.d.mts +32 -0
  190. package/ports.mjs +85 -0
  191. package/probe-battery.d.ts +13 -0
  192. package/probe-battery.js +404 -0
  193. package/providers.d.ts +149 -0
  194. package/providers.js +306 -0
  195. package/read-source.d.ts +48 -0
  196. package/read-source.js +1301 -0
  197. package/read-steps.d.ts +23 -0
  198. package/read-steps.js +2 -0
  199. package/reader.d.ts +11 -0
  200. package/reader.js +11 -0
  201. package/registrations.d.ts +83 -0
  202. package/registrations.js +1 -0
  203. package/requirements.d.ts +22 -0
  204. package/requirements.js +38 -0
  205. package/run-payload-core.d.ts +28 -0
  206. package/run-payload-core.js +123 -0
  207. package/run-payload.d.ts +32 -0
  208. package/run-payload.js +26 -0
  209. package/runtime-scope.d.ts +84 -0
  210. package/runtime-scope.js +308 -0
  211. package/runtime.d.ts +84 -0
  212. package/runtime.js +387 -0
  213. package/section-notes.d.ts +33 -0
  214. package/section-notes.js +38 -0
  215. package/serve-page.mjs +96 -0
  216. package/server/draft-decide.d.ts +72 -0
  217. package/server/draft-decide.js +111 -0
  218. package/server/draft-embedding.d.ts +3 -0
  219. package/server/draft-embedding.js +35 -0
  220. package/server/draft-handler.d.ts +82 -0
  221. package/server/draft-handler.js +213 -0
  222. package/server/draft-probe.d.ts +14 -0
  223. package/server/draft-probe.js +61 -0
  224. package/server/draft-replies.d.ts +22 -0
  225. package/server/draft-replies.js +46 -0
  226. package/server/edited-session.d.ts +28 -0
  227. package/server/edited-session.js +83 -0
  228. package/server/edits.d.ts +38 -0
  229. package/server/edits.js +195 -0
  230. package/server/handler.d.ts +133 -0
  231. package/server/handler.js +598 -0
  232. package/server/lent-draft.d.ts +19 -0
  233. package/server/lent-draft.js +23 -0
  234. package/server/live.d.ts +15 -0
  235. package/server/live.js +96 -0
  236. package/server/open-editor.d.ts +63 -0
  237. package/server/open-editor.js +115 -0
  238. package/server/origins.d.ts +18 -0
  239. package/server/origins.js +330 -0
  240. package/server/project-source.d.ts +208 -0
  241. package/server/project-source.js +1042 -0
  242. package/server/project.d.ts +22 -0
  243. package/server/project.js +56 -0
  244. package/server/run-traces.d.ts +20 -0
  245. package/server/run-traces.js +96 -0
  246. package/server/save-new.d.ts +29 -0
  247. package/server/save-new.js +514 -0
  248. package/server/save-plan.d.ts +46 -0
  249. package/server/save-plan.js +1134 -0
  250. package/server/save-remove.d.ts +21 -0
  251. package/server/save-remove.js +528 -0
  252. package/server/save-session.d.ts +96 -0
  253. package/server/save-session.js +418 -0
  254. package/server/save-wire.d.ts +235 -0
  255. package/server/save-wire.js +8 -0
  256. package/server/save.d.ts +52 -0
  257. package/server/save.js +209 -0
  258. package/server/serve.d.ts +23 -0
  259. package/server/serve.js +413 -0
  260. package/server/test-connection.d.ts +17 -0
  261. package/server/test-connection.js +362 -0
  262. package/server/test-key.d.ts +2 -0
  263. package/server/test-key.js +83 -0
  264. package/server/watch.d.ts +28 -0
  265. package/server/watch.js +93 -0
  266. package/server/zod-edit.d.ts +74 -0
  267. package/server/zod-edit.js +558 -0
  268. package/server.d.ts +8 -0
  269. package/server.js +8 -0
  270. package/setups.mjs +170 -0
  271. package/shared-carry.d.ts +114 -0
  272. package/shared-carry.js +523 -0
  273. package/shared-settings.d.ts +34 -0
  274. package/shared-settings.js +70 -0
  275. package/source.d.ts +75 -0
  276. package/source.js +414 -0
  277. package/start.mjs +169 -0
  278. package/stream-lines.d.ts +9 -0
  279. package/stream-lines.js +27 -0
  280. package/stub.d.ts +6 -0
  281. package/stub.js +33 -0
  282. package/surface.d.ts +53 -0
  283. package/surface.js +631 -0
  284. package/system-markup.d.ts +20 -0
  285. package/system-markup.js +51 -0
  286. package/tool-schema.d.ts +23 -0
  287. package/tool-schema.js +69 -0
  288. package/tools.d.ts +16 -0
  289. package/tools.js +91 -0
  290. package/traces.d.ts +24 -0
  291. package/traces.js +29 -0
  292. package/transport.d.ts +57 -0
  293. package/transport.js +187 -0
  294. package/tree.d.ts +32 -0
  295. package/tree.js +83 -0
  296. package/types.d.ts +62 -0
  297. package/types.js +6 -0
  298. package/ui/acting-as-button.d.ts +2 -0
  299. package/ui/acting-as-button.js +16 -0
  300. package/ui/add-provider.d.ts +13 -0
  301. package/ui/add-provider.js +20 -0
  302. package/ui/boot-mark.css +53 -0
  303. package/ui/boot-mark.d.ts +19 -0
  304. package/ui/boot-mark.js +128 -0
  305. package/ui/boot-paint.d.ts +8 -0
  306. package/ui/boot-paint.js +8 -0
  307. package/ui/brand-icons.d.ts +57 -0
  308. package/ui/brand-icons.js +148 -0
  309. package/ui/built/theme.css +830 -0
  310. package/ui/built/theme.css.d.ts +9 -0
  311. package/ui/built/theorem-studio.d.ts +13 -0
  312. package/ui/built/theorem-studio.js +705 -0
  313. package/ui/built/theorem-studio.variants.d.ts +28 -0
  314. package/ui/code/monaco-contributions.d.ts +45 -0
  315. package/ui/code/studio-code.d.ts +7 -0
  316. package/ui/code/studio-code.js +253 -0
  317. package/ui/code/studio-monaco.d.ts +44 -0
  318. package/ui/code/studio-monaco.js +48 -0
  319. package/ui/code/studio-ts.worker.d.ts +1 -0
  320. package/ui/code/studio-ts.worker.js +16 -0
  321. package/ui/code/studio-type-checker.d.ts +12 -0
  322. package/ui/code/studio-type-checker.js +308 -0
  323. package/ui/code/studio-type-sources.d.ts +26 -0
  324. package/ui/confirm-write.d.ts +12 -0
  325. package/ui/confirm-write.js +45 -0
  326. package/ui/diff-block.d.ts +21 -0
  327. package/ui/diff-block.js +17 -0
  328. package/ui/figtree.css +59 -0
  329. package/ui/file-place.d.ts +4 -0
  330. package/ui/file-place.js +26 -0
  331. package/ui/guardrail-tester.d.ts +18 -0
  332. package/ui/guardrail-tester.js +248 -0
  333. package/ui/inspector-context.d.ts +119 -0
  334. package/ui/inspector-context.js +84 -0
  335. package/ui/inspector.d.ts +247 -0
  336. package/ui/inspector.js +284 -0
  337. package/ui/lib/acting-as.d.ts +25 -0
  338. package/ui/lib/acting-as.js +90 -0
  339. package/ui/lib/boot-sequence.d.ts +32 -0
  340. package/ui/lib/boot-sequence.js +57 -0
  341. package/ui/lib/export-agent.d.ts +11 -0
  342. package/ui/lib/export-agent.js +335 -0
  343. package/ui/lib/facet-icons.d.ts +20 -0
  344. package/ui/lib/facet-icons.js +21 -0
  345. package/ui/lib/panel-motion.d.ts +8 -0
  346. package/ui/lib/panel-motion.js +74 -0
  347. package/ui/lib/project-address.d.ts +14 -0
  348. package/ui/lib/project-address.js +24 -0
  349. package/ui/lib/project-starting.d.ts +13 -0
  350. package/ui/lib/project-starting.js +30 -0
  351. package/ui/lib/project-traces.d.ts +17 -0
  352. package/ui/lib/project-traces.js +54 -0
  353. package/ui/lib/read-map.d.ts +30 -0
  354. package/ui/lib/read-map.js +173 -0
  355. package/ui/lib/read-progress.d.ts +14 -0
  356. package/ui/lib/read-progress.js +12 -0
  357. package/ui/lib/refusal-lines.d.ts +3 -0
  358. package/ui/lib/refusal-lines.js +8 -0
  359. package/ui/lib/studio-activity.d.ts +5 -0
  360. package/ui/lib/studio-activity.js +17 -0
  361. package/ui/lib/studio-console.d.ts +27 -0
  362. package/ui/lib/studio-console.js +9 -0
  363. package/ui/lib/studio-conversation.d.ts +20 -0
  364. package/ui/lib/studio-conversation.js +130 -0
  365. package/ui/lib/studio-examples.d.ts +31 -0
  366. package/ui/lib/studio-examples.js +25 -0
  367. package/ui/lib/studio-labels.d.ts +6 -0
  368. package/ui/lib/studio-labels.js +13 -0
  369. package/ui/lib/studio-map-kept.d.ts +17 -0
  370. package/ui/lib/studio-map-kept.js +48 -0
  371. package/ui/lib/studio-open.d.ts +22 -0
  372. package/ui/lib/studio-open.js +54 -0
  373. package/ui/lib/studio-page.d.ts +33 -0
  374. package/ui/lib/studio-page.js +121 -0
  375. package/ui/lib/studio-prefs.d.ts +26 -0
  376. package/ui/lib/studio-prefs.js +87 -0
  377. package/ui/lib/studio-project.d.ts +106 -0
  378. package/ui/lib/studio-project.js +177 -0
  379. package/ui/lib/studio-restore.d.ts +49 -0
  380. package/ui/lib/studio-restore.js +251 -0
  381. package/ui/lib/studio-run-open.d.ts +15 -0
  382. package/ui/lib/studio-run-open.js +16 -0
  383. package/ui/lib/studio-session.d.ts +34 -0
  384. package/ui/lib/studio-session.js +17 -0
  385. package/ui/lib/studio-settings.d.ts +15 -0
  386. package/ui/lib/studio-settings.js +48 -0
  387. package/ui/lib/studio-store.d.ts +64 -0
  388. package/ui/lib/studio-store.js +391 -0
  389. package/ui/lib/studio-watch.d.ts +12 -0
  390. package/ui/lib/studio-watch.js +27 -0
  391. package/ui/lib/tab-fills.d.ts +6 -0
  392. package/ui/lib/tab-fills.js +14 -0
  393. package/ui/lib/tool-credentials.d.ts +3 -0
  394. package/ui/lib/tool-credentials.js +23 -0
  395. package/ui/lib/tool-probe.d.ts +19 -0
  396. package/ui/lib/tool-probe.js +104 -0
  397. package/ui/lib/type-icons.d.ts +35 -0
  398. package/ui/lib/type-icons.js +38 -0
  399. package/ui/lib/when-idle.d.ts +5 -0
  400. package/ui/lib/when-idle.js +14 -0
  401. package/ui/lib/zip.d.ts +5 -0
  402. package/ui/lib/zip.js +8 -0
  403. package/ui/map-token.css +11 -0
  404. package/ui/map-token.d.ts +17 -0
  405. package/ui/map-token.js +29 -0
  406. package/ui/mcp-icon.d.ts +6 -0
  407. package/ui/mcp-icon.js +8 -0
  408. package/ui/motion.css +113 -0
  409. package/ui/pan.d.ts +32 -0
  410. package/ui/pan.js +90 -0
  411. package/ui/profile-editor.d.ts +33 -0
  412. package/ui/profile-editor.js +2638 -0
  413. package/ui/provider-editor.d.ts +15 -0
  414. package/ui/provider-editor.js +92 -0
  415. package/ui/read-map.css +48 -0
  416. package/ui/read-map.d.ts +7 -0
  417. package/ui/read-map.js +163 -0
  418. package/ui/refusal-detail.d.ts +4 -0
  419. package/ui/refusal-detail.js +21 -0
  420. package/ui/shared-change.d.ts +9 -0
  421. package/ui/shared-change.js +28 -0
  422. package/ui/shell-motion.css +121 -0
  423. package/ui/shell-motion.d.ts +73 -0
  424. package/ui/shell-motion.js +194 -0
  425. package/ui/studio-code-pane.d.ts +19 -0
  426. package/ui/studio-code-pane.js +44 -0
  427. package/ui/studio-compare.d.ts +80 -0
  428. package/ui/studio-compare.js +326 -0
  429. package/ui/studio-conflicts.d.ts +17 -0
  430. package/ui/studio-conflicts.js +87 -0
  431. package/ui/studio-connection.d.ts +64 -0
  432. package/ui/studio-connection.js +286 -0
  433. package/ui/studio-decision.d.ts +6 -0
  434. package/ui/studio-decision.js +49 -0
  435. package/ui/studio-embedding.d.ts +6 -0
  436. package/ui/studio-embedding.js +30 -0
  437. package/ui/studio-host-console.d.ts +6 -0
  438. package/ui/studio-host-console.js +17 -0
  439. package/ui/studio-host.d.ts +73 -0
  440. package/ui/studio-host.js +12 -0
  441. package/ui/studio-live.d.ts +17 -0
  442. package/ui/studio-live.js +26 -0
  443. package/ui/studio-map.css +273 -0
  444. package/ui/studio-map.d.ts +17 -0
  445. package/ui/studio-map.js +397 -0
  446. package/ui/studio-nav.d.ts +24 -0
  447. package/ui/studio-nav.js +17 -0
  448. package/ui/studio-no-project.d.ts +5 -0
  449. package/ui/studio-no-project.js +9 -0
  450. package/ui/studio-run.css +76 -0
  451. package/ui/studio-run.d.ts +14 -0
  452. package/ui/studio-run.js +119 -0
  453. package/ui/studio-runner.d.ts +45 -0
  454. package/ui/studio-runner.js +187 -0
  455. package/ui/studio-save.d.ts +49 -0
  456. package/ui/studio-save.js +307 -0
  457. package/ui/studio-screen.d.ts +61 -0
  458. package/ui/studio-screen.js +2078 -0
  459. package/ui/studio-settings.d.ts +31 -0
  460. package/ui/studio-settings.js +288 -0
  461. package/ui/studio-shell.css +27 -0
  462. package/ui/studio-shell.d.ts +43 -0
  463. package/ui/studio-shell.js +87 -0
  464. package/ui/studio-theme.d.ts +7 -0
  465. package/ui/studio-theme.js +94 -0
  466. package/ui/studio.css +427 -0
  467. package/ui/theorem-mark.css +84 -0
  468. package/ui/theorem-mark.d.ts +22 -0
  469. package/ui/theorem-mark.js +21 -0
  470. package/vite.d.mts +30 -0
  471. package/vite.mjs +277 -0
  472. package/workspace.d.ts +230 -0
  473. package/workspace.js +1054 -0
@@ -0,0 +1,598 @@
1
+ /**
2
+ * The studio's local server: a project's registered profiles and tools, as the
3
+ * studio's workspace, and each profile served to run.
4
+ *
5
+ * The page is the studio. It reads its workspace from `GET <base>` and runs
6
+ * the open profile at `<base>/profiles/<id>`, so a run is the project's own
7
+ * code, not the page's draft.
8
+ *
9
+ * It reads and runs. Writing an edit back to the project is the server's
10
+ * (`serve.ts`), which starts this in a process of its own and starts it again
11
+ * after a Save, so a run is always the code on disk.
12
+ *
13
+ * @module
14
+ */
15
+ import { defineProfile, getStructured, listProfiles, listProviders, listTools, registerTool, } from '@theoremjs/agents';
16
+ import { compileDetect } from '@theoremjs/agents/guardrails/compile';
17
+ import { createProviderRegistry } from '@theoremjs/agents/kernel';
18
+ import { createSealedConversationStore, createTheoremDecisionHandler, createTheoremEmbeddingHandler, createTheoremHandler, createTheoremHostHandler, } from '@theoremjs/react/server';
19
+ import { differingSettings } from "../agreement.js";
20
+ import { studioAsks } from "../asks.js";
21
+ import { compileWorkspace } from "../compile-workspace.js";
22
+ import { createBlankDraft } from "../draft.js";
23
+ import { shownConnection, withoutCredentials } from "../held-credentials.js";
24
+ import { ON_OWN_KEYS } from "../lent-keys.js";
25
+ import { ACTING_AS_HEADER, actingAsSession, peopleFault, peopleOffer, readActingAs, readPerson, readPlace, } from "../people.js";
26
+ import { STUDIO_TRACE_DESTINATION } from "../policy.js";
27
+ import { kernelDefinition, registerStudioProvider } from "../providers.js";
28
+ import { readStudioSource } from "../read-source.js";
29
+ import { STUDIO_READER } from "../reader.js";
30
+ import { withPatterns } from "../runtime-scope.js";
31
+ import { studioSource } from "../source.js";
32
+ import { createStudioDraftHandler, STUDIO_BASE } from "./draft-handler.js";
33
+ import { createStudioLiveHandler } from "./live.js";
34
+ export { STUDIO_BASE } from "./draft-handler.js";
35
+ import { addAgent, agentNodeId, createBlankWorkspace, workspaceFromDraft, } from "../workspace.js";
36
+ import { tracedToPage, withJsonTraces, withRunTraces } from "./run-traces.js";
37
+ /** The registered tools as the studio's printer takes them: their fields and JSON schemas. */
38
+ function registeredTools() {
39
+ return (listTools()
40
+ // A provider's built-in tool is a model's setting, not a tool the project registers.
41
+ .filter((tool) => tool.type !== 'builtin')
42
+ .map((tool) => {
43
+ const fields = { ...tool };
44
+ for (const own of ['handler', 'input', 'output'])
45
+ delete fields[own];
46
+ // What the file writes as code (a hook before the call, its sources) is left to the file.
47
+ // A credential in its URL or headers stays in this load: the page gets a mask.
48
+ return withoutCredentials(plainSetting(fields));
49
+ }));
50
+ }
51
+ /** A setting with what only code can say taken out, or nothing when it is code itself. */
52
+ function plainSetting(value) {
53
+ if (typeof value === 'function')
54
+ return undefined;
55
+ if (Array.isArray(value))
56
+ return value.map(plainSetting).filter((item) => item !== undefined);
57
+ if (!isRecord(value))
58
+ return value;
59
+ const kept = Object.entries(value)
60
+ .map(([key, item]) => [key, plainSetting(item)])
61
+ .filter(([, item]) => item !== undefined);
62
+ // A setting that was all code is left out whole, not shown as an empty one.
63
+ return kept.length || !Object.keys(value).length ? Object.fromEntries(kept) : undefined;
64
+ }
65
+ /**
66
+ * A profile as the studio can print it. What a file writes as code (a validator, a trigger, a
67
+ * trace sink of its own) cannot be shown as a setting, so it is left to the file: the editor
68
+ * says where it is set, Save does not touch it, and a run is still the profile as registered.
69
+ */
70
+ export function printableProfile(profile) {
71
+ const { observability } = profile;
72
+ // A sink of the project's own still records, so the studio shows the profile as one that does.
73
+ const recording = isRecord(observability?.writeTo)
74
+ ? { ...profile, observability: { ...observability, writeTo: STUDIO_TRACE_DESTINATION } }
75
+ : profile;
76
+ return plainSetting(recording);
77
+ }
78
+ /**
79
+ * The schema a profile's replies take, as registered. None when the profile names one nothing
80
+ * registers, or one for each slot: the editor holds a single schema.
81
+ */
82
+ function replySchema(profile) {
83
+ const id = 'outputs' in profile ? profile.outputs?.structured : undefined;
84
+ if (typeof id !== 'string')
85
+ return undefined;
86
+ try {
87
+ return { id, spec: { jsonSchema: getStructured(id).jsonSchema } };
88
+ }
89
+ catch {
90
+ return undefined;
91
+ }
92
+ }
93
+ /** Whether `provider` is registered from one of the kernel's own definitions, whose connection the page edits. */
94
+ function onKernelDefinition(provider) {
95
+ return kernelDefinition(provider.definition.id) !== undefined;
96
+ }
97
+ /**
98
+ * The project's providers as the page gets them: the definition each is registered from, its key
99
+ * slots, and what it connects with when its definition is the kernel's. What a project's own
100
+ * definition connects with is its own to say, so it stays here.
101
+ */
102
+ function registeredProviders() {
103
+ return listProviders().map((provider) => {
104
+ const connection = onKernelDefinition(provider)
105
+ ? shownConnection(provider.connection)
106
+ : undefined;
107
+ return {
108
+ id: provider.id,
109
+ definition: provider.definition.id,
110
+ ...(connection ? { connection } : {}),
111
+ ...(provider.keySlot ? { keySlot: provider.keySlot } : {}),
112
+ ...(provider.fallbackKeySlot ? { fallbackKeySlot: provider.fallbackKeySlot } : {}),
113
+ };
114
+ });
115
+ }
116
+ /** One registered profile as the draft the editor shows, read from the source the studio prints for it. */
117
+ function readProfile(profile, tools, questions, images) {
118
+ try {
119
+ const structured = replySchema(profile);
120
+ const source = studioSource({
121
+ ...(questions ? { questions } : {}),
122
+ ...(images ? { images } : {}),
123
+ agentId: profile.id,
124
+ profile: printableProfile(profile),
125
+ customTools: [...tools],
126
+ providers: registeredProviders(),
127
+ ...(structured ? { structured } : {}),
128
+ });
129
+ const read = readStudioSource(source, createBlankDraft());
130
+ if (!read.ok)
131
+ return { ok: false, message: read.errors.map((error) => error.message).join(' ') };
132
+ return { ok: true, draft: read.draft, registered: read.registered };
133
+ }
134
+ catch (error) {
135
+ return { ok: false, message: error instanceof Error ? error.message : String(error) };
136
+ }
137
+ }
138
+ /**
139
+ * Each opened profile that is not the one the project registered: what the workspace compiles to
140
+ * for it, beside the registered profile. A workspace that does not compile holds something the
141
+ * kernel took and the studio does not: that is said whole, in the studio's own words.
142
+ */
143
+ function disagreements(workspace) {
144
+ const compiled = compileWorkspace(workspace, ON_OWN_KEYS);
145
+ if (!compiled.ok)
146
+ return { differences: [], unheld: compiled.issues.map((issue) => issue.message) };
147
+ const registered = new Map(listProfiles().map((profile) => [profile.id, profile]));
148
+ const differences = compiled.agents.flatMap((agent) => {
149
+ const profile = registered.get(agent.agentId);
150
+ if (!profile)
151
+ return [];
152
+ const shown = plainSetting(defineProfile(withPatterns(agent.profile, compileDetect)));
153
+ const settings = differingSettings(plainSetting(printableProfile(profile)), shown);
154
+ return settings.length ? [{ kind: 'profile', of: agent.agentId, settings }] : [];
155
+ });
156
+ return { differences: [...differences, ...providerDifferences(workspace)], unheld: [] };
157
+ }
158
+ /**
159
+ * Each opened provider that is not the one the project registered: the provider the kernel registers
160
+ * from what the studio holds, beside the registered one. What a project's own definition connects
161
+ * with stays with the project, so only its definition and its slots are compared.
162
+ */
163
+ function providerDifferences(workspace) {
164
+ const registered = new Map(listProviders().map((provider) => [provider.id, provider]));
165
+ const read = (provider, connects) => plainSetting({
166
+ definition: provider.definition.id,
167
+ ...(connects ? { connection: provider.connection } : {}),
168
+ keySlot: provider.keySlot,
169
+ fallbackKeySlot: provider.fallbackKeySlot,
170
+ });
171
+ return workspace.providers.flatMap((provider) => {
172
+ const held = registered.get(provider.id);
173
+ if (!held)
174
+ return [];
175
+ const kernel = kernelDefinition(provider.definition);
176
+ const definition = kernel ?? (held.definition.id === provider.definition ? held.definition : undefined);
177
+ if (!definition)
178
+ return [{ kind: 'provider', of: provider.id, settings: ['definition'] }];
179
+ let shown;
180
+ try {
181
+ shown = kernel
182
+ ? registerStudioProvider(createProviderRegistry(), provider, kernel)
183
+ : createProviderRegistry().register(definition, {
184
+ id: provider.id,
185
+ connection: held.connection,
186
+ ...(provider.keySlot ? { keySlot: provider.keySlot } : {}),
187
+ ...(provider.fallbackKeySlot ? { fallbackKeySlot: provider.fallbackKeySlot } : {}),
188
+ });
189
+ }
190
+ catch {
191
+ // The kernel took a connection the studio cannot register again: all of it is shown differently.
192
+ return [{ kind: 'provider', of: provider.id, settings: ['connection'] }];
193
+ }
194
+ const settings = differingSettings(read(held, kernel !== undefined), read(shown, kernel !== undefined));
195
+ return settings.length ? [{ kind: 'provider', of: provider.id, settings }] : [];
196
+ });
197
+ }
198
+ /** The agent that writes each model's summaries, by the model's name, where a profile names one. */
199
+ function compactors(profile) {
200
+ const models = 'models' in profile && isRecord(profile.models) ? profile.models : {};
201
+ return Object.fromEntries(Object.entries(models).flatMap(([name, model]) => {
202
+ const writer = isRecord(model) && isRecord(model.compaction) ? model.compaction.profile : undefined;
203
+ return typeof writer === 'string' ? [[name, writer]] : [];
204
+ }));
205
+ }
206
+ /** The tools of `registered` the workspace does not hold yet, by name. */
207
+ function unlisted(workspace, registered) {
208
+ const held = new Set(workspace.toolSpecs.map((tool) => tool.toolName));
209
+ return registered.filter((tool) => !held.has(tool.toolName));
210
+ }
211
+ /** The registered profiles and tools, as the workspace the studio opens. */
212
+ function describeStudio(project, questions, images) {
213
+ const tools = registeredTools();
214
+ const problems = [];
215
+ const modelProblems = [];
216
+ let workspace;
217
+ let library = [];
218
+ for (const profile of listProfiles()) {
219
+ const asked = questions[profile.id];
220
+ // A decision the studio cannot ask is left out, with why: a draft with no questions would not compile.
221
+ const fault = profile.type === 'decision' ? questionsFault(profile.id, asked) : undefined;
222
+ if (fault) {
223
+ problems.push({ profile: profile.id, message: fault });
224
+ continue;
225
+ }
226
+ const read = readProfile(profile, tools, asked, images[profile.id]);
227
+ if (!read.ok) {
228
+ problems.push({ profile: profile.id, message: read.message });
229
+ continue;
230
+ }
231
+ workspace = workspace ? addAgent(workspace, read.draft) : workspaceFromDraft(read.draft);
232
+ library = read.registered;
233
+ }
234
+ const opened = workspace ?? createBlankWorkspace();
235
+ // A tool no profile allows is still the project's: it joins the library.
236
+ const extra = unlisted(opened, library);
237
+ const first = opened.agents[0];
238
+ // A tool that runs an agent names it by id. Each profile is read alone, so the agent is found once all are.
239
+ const runs = new Map(tools.flatMap((tool) => (tool.type === 'agent' ? [[tool.name, tool.profile]] : [])));
240
+ const linked = (tool) => {
241
+ const id = tool.toolType === 'agent' && !tool.agentKey ? runs.get(tool.toolName) : undefined;
242
+ const agentKey = id && opened.agents.find((agent) => agent.identity.agentId === id)?.key;
243
+ return agentKey ? { ...tool, agentKey } : tool;
244
+ };
245
+ const toolSpecs = [...opened.toolSpecs, ...extra].map(linked);
246
+ // A model's summaries are written by an agent it names by id, found the same way.
247
+ const writers = new Map(listProfiles().map((profile) => [profile.id, compactors(profile)]));
248
+ const agents = opened.agents.map((agent) => {
249
+ const named = writers.get(agent.identity.agentId);
250
+ const modelBindings = agent.modelBindings.map((binding) => {
251
+ const id = binding.compactWith ? undefined : named?.[binding.modelId];
252
+ if (!id)
253
+ return binding;
254
+ const key = opened.agents.find((each) => each.identity.agentId === id)?.key;
255
+ // A blank writer is the agent itself, so a writer this project does not open is said, not dropped.
256
+ if (!key) {
257
+ modelProblems.push({
258
+ profile: agent.identity.agentId,
259
+ model: binding.modelId,
260
+ message: `It has '${id}' write its summaries, and this project registers no agent '${id}'.`,
261
+ });
262
+ return binding;
263
+ }
264
+ return { ...binding, compactWith: key };
265
+ });
266
+ return modelBindings.some((binding, index) => binding !== agent.modelBindings[index])
267
+ ? { ...agent, modelBindings }
268
+ : agent;
269
+ });
270
+ // The project's own providers are the ones a model here can name.
271
+ const registered = registeredProviders();
272
+ const providers = registered.length > 0 ? registered : opened.providers;
273
+ const whole = {
274
+ ...opened,
275
+ providers,
276
+ agents,
277
+ toolSpecs,
278
+ // What opened is what the files hold: nothing here is a change yet.
279
+ starts: {
280
+ ...opened.starts,
281
+ agents: Object.fromEntries(agents.map((agent) => [agent.key, agent])),
282
+ tools: Object.fromEntries(toolSpecs.map((tool) => [tool.key, tool])),
283
+ providers: Object.fromEntries(providers.map((provider) => [provider.id, provider])),
284
+ },
285
+ ...(first ? { selected: agentNodeId(first.key), chatWith: first.key } : {}),
286
+ };
287
+ const { differences, unheld } = disagreements(whole);
288
+ return {
289
+ project,
290
+ workspace: whole,
291
+ problems,
292
+ ...(modelProblems.length ? { modelProblems } : {}),
293
+ ...(differences.length ? { differences } : {}),
294
+ ...(unheld.length ? { unheld } : {}),
295
+ asks: { asked: [], inside: [] },
296
+ };
297
+ }
298
+ /**
299
+ * Makes every registered tool that writes ask the builder before each run, whatever its own
300
+ * setting: a run in the studio is the project's real code, on whatever it reaches. The project's
301
+ * files are not touched, and the editor shows what they say.
302
+ */
303
+ function askBeforeWrites() {
304
+ const tools = listTools();
305
+ const profiles = new Map(listProfiles().map((profile) => [profile.id, profile]));
306
+ const asks = studioAsks(tools, (id) => {
307
+ const profile = profiles.get(id);
308
+ return profile && 'tools' in profile ? profile.tools.allow : [];
309
+ });
310
+ for (const tool of tools) {
311
+ if (asks.asked.includes(tool.name))
312
+ registerTool({ ...tool, permission: 'always_confirm' });
313
+ }
314
+ return asks;
315
+ }
316
+ export function json(status, body, headers) {
317
+ return new Response(JSON.stringify(body), {
318
+ status,
319
+ headers: { 'content-type': 'application/json; charset=utf-8', ...headers },
320
+ });
321
+ }
322
+ /**
323
+ * Whether a request comes from somewhere other than the studio's own page.
324
+ * A page on another site can reach 127.0.0.1 through the builder's browser: the
325
+ * origin check stops its requests, and the host check stops a name it pointed at
326
+ * this machine. A browser's request that names no page at all (an image or a script tag, an
327
+ * address typed in) is refused too: the studio's page always names itself.
328
+ */
329
+ export function isForeign(request, options) {
330
+ if (request.headers.get('host') !== options.listenHost)
331
+ return true;
332
+ const origin = request.headers.get('origin');
333
+ // Only a browser says where a request was fetched from; the studio's command and server say nothing.
334
+ if (origin === null)
335
+ return request.headers.has('sec-fetch-site');
336
+ return !options.pageOrigins.includes(origin);
337
+ }
338
+ /** What the application answered when it was asked for people and could not say. */
339
+ function applicationFailed(error, cors) {
340
+ // why: only an Error's own message reaches the page, never whatever else was thrown, which may carry a stack.
341
+ const message = error instanceof Error ? error.message : 'The application did not say why.'; // labels-exempt: builder diagnostic
342
+ return json(502, { message }, cors);
343
+ }
344
+ /** `GET <base>/people?place=<id>`: the people the application offers in a place. */
345
+ async function existingPeople(people, request, cors) {
346
+ if (!people?.existing)
347
+ return json(404, {}, cors);
348
+ const read = readPlace(new URL(request.url).searchParams.get('place'), people.places);
349
+ if (!read.ok)
350
+ return json(400, { message: read.message }, cors);
351
+ const { place } = read;
352
+ try {
353
+ const found = await people.existing(place);
354
+ return json(200, { people: found.map((person) => readPerson(person, 'existing')) }, cors);
355
+ }
356
+ catch (error) {
357
+ return applicationFailed(error, cors);
358
+ }
359
+ }
360
+ /** `POST <base>/people/fresh` with `{ place }`: a new person the application made in a place. */
361
+ async function freshPerson(people, request, cors) {
362
+ if (!people?.fresh)
363
+ return json(404, {}, cors);
364
+ const body = await request.json().catch(() => undefined);
365
+ const read = readPlace(isRecord(body) ? body.place : undefined, people.places);
366
+ if (!read.ok)
367
+ return json(400, { message: read.message }, cors);
368
+ const { place } = read;
369
+ try {
370
+ return json(200, { person: readPerson(await people.fresh(place), 'fresh') }, cors);
371
+ }
372
+ catch (error) {
373
+ return applicationFailed(error, cors);
374
+ }
375
+ }
376
+ /** The page's own origin, echoed: a request from any other was refused before this. */
377
+ export function corsHeaders(request, pageOrigins) {
378
+ return {
379
+ 'access-control-allow-origin': request.headers.get('origin') ?? pageOrigins[0] ?? '',
380
+ 'access-control-allow-headers': `content-type, ${ACTING_AS_HEADER}`,
381
+ 'access-control-allow-methods': 'GET, POST, OPTIONS',
382
+ vary: 'origin',
383
+ };
384
+ }
385
+ /** Why a decision profile is not run: the setup file does not name its questions. */
386
+ export function noQuestions(profileId) {
387
+ return `The studio does not know what ${profileId} asks. Export the questions your application passes it from the setup file: export const questions = { '${profileId}': { ... } }.`;
388
+ }
389
+ const isRecord = (value) => typeof value === 'object' && value !== null && !Array.isArray(value);
390
+ /** What each kind of question needs of its criteria, and what is wrong when it lacks it. */
391
+ const CRITERIA = new Map([
392
+ [
393
+ 'choice',
394
+ {
395
+ fits: (criteria) => isRecord(criteria) && Object.keys(criteria).length > 0,
396
+ fault: 'needs criteria: an object of the labels it picks from',
397
+ },
398
+ ],
399
+ [
400
+ 'score',
401
+ {
402
+ fits: (criteria) => Array.isArray(criteria) && criteria.length > 0,
403
+ fault: 'needs criteria: a list, lowest score first',
404
+ },
405
+ ],
406
+ [
407
+ 'noul',
408
+ {
409
+ fits: (criteria) => criteria === undefined || isRecord(criteria),
410
+ fault: 'has criteria that are not an object',
411
+ },
412
+ ],
413
+ [
414
+ 'box',
415
+ {
416
+ fits: (criteria) => criteria === undefined,
417
+ fault: 'has criteria, and a box takes none',
418
+ },
419
+ ],
420
+ ]);
421
+ /** What is wrong with one question as the setup wrote it, or nothing. */
422
+ function questionFault(question) {
423
+ if (!isRecord(question))
424
+ return 'is not a question';
425
+ const kind = CRITERIA.get(question.type);
426
+ if (!kind)
427
+ return "needs a type: 'choice', 'noul', 'score', or 'box'";
428
+ if (question.instructions === undefined)
429
+ return 'needs instructions';
430
+ return kind.fits(question.criteria) ? undefined : kind.fault;
431
+ }
432
+ /**
433
+ * Why a decision profile's questions cannot be asked, or nothing. A setup file is not always
434
+ * type-checked, so the studio reads what it exports before it trusts it.
435
+ */
436
+ export function questionsFault(profileId, questions) {
437
+ if (!isRecord(questions) || !Object.keys(questions).length)
438
+ return noQuestions(profileId);
439
+ for (const [id, question] of Object.entries(questions)) {
440
+ const fault = questionFault(question);
441
+ if (fault)
442
+ return `The question '${id}' the setup file exports for ${profileId} ${fault}.`;
443
+ }
444
+ return undefined;
445
+ }
446
+ /** Why a live profile is not run: a voice call needs a socket, and the server was given no way to take one. */
447
+ const NO_SOCKET = 'A live profile runs over a socket, and this server was not given a way to take one (`upgrade`).';
448
+ /** Each registered profile's own handler, by id; a profile that cannot be served is a problem. */
449
+ function profileHandlers(options, problems) {
450
+ const served = new Map();
451
+ // `run` refused a pick it cannot read before any handler is reached, so here it reads.
452
+ const actingAs = (request) => {
453
+ const read = readActingAs(request, options.people);
454
+ return read.ok ? read.actingAs : undefined;
455
+ };
456
+ const host = options.host;
457
+ const shared = {
458
+ // Each person is a session of their own: their chats and held calls are theirs alone.
459
+ session: (request) => actingAsSession(actingAs(request)),
460
+ clientEvents: STUDIO_READER,
461
+ ...(host ? { host: (request) => host(request, actingAs(request)) } : {}),
462
+ };
463
+ // One store for every chat profile: one key, so any of them opens a ref its session holds.
464
+ let conversationStore;
465
+ const chatStore = () => (conversationStore ??= createSealedConversationStore({
466
+ keys: { 1: options.conversationKey },
467
+ keyVersion: 1,
468
+ }));
469
+ /** A decision is asked the project's questions. The profile does not hold them, so the setup names them. */
470
+ const decision = (profile) => {
471
+ const questions = options.questions?.[profile.id];
472
+ // The description already says why a decision with no questions to ask is left out.
473
+ if (!questions || questionsFault(profile.id, questions))
474
+ return undefined;
475
+ const { vault, fetch } = options.provider ?? {};
476
+ // The page shows a decision's trace, so the profile is served writing its records to the reply.
477
+ return withJsonTraces(createTheoremDecisionHandler({
478
+ profile: tracedToPage(profile),
479
+ questions,
480
+ images: options.images?.[profile.id],
481
+ vault,
482
+ fetch,
483
+ clientEvents: STUDIO_READER,
484
+ }));
485
+ };
486
+ for (const profile of listProfiles()) {
487
+ try {
488
+ if (profile.type === 'decision') {
489
+ const serve = decision(profile);
490
+ if (serve)
491
+ served.set(profile.id, serve);
492
+ continue;
493
+ }
494
+ if (profile.type === 'live') {
495
+ if (options.upgrade) {
496
+ served.set(profile.id, createStudioLiveHandler(profile, options.provider ?? {}, options.upgrade));
497
+ }
498
+ else
499
+ problems.push({ profile: profile.id, message: NO_SOCKET });
500
+ continue;
501
+ }
502
+ if (profile.type === 'embedding') {
503
+ // The page shows an embedding's trace, so its records ride in the reply as a decision's do.
504
+ served.set(profile.id, withJsonTraces(createTheoremEmbeddingHandler({
505
+ profile: tracedToPage(profile),
506
+ provider: options.provider,
507
+ clientEvents: STUDIO_READER,
508
+ })));
509
+ continue;
510
+ }
511
+ // The page shows a run's trace, so the profile is served writing its records to the run.
512
+ served.set(profile.id, withRunTraces(profile.type === 'host'
513
+ ? createTheoremHostHandler({ profile: tracedToPage(profile), ...shared })
514
+ : createTheoremHandler({
515
+ profile: tracedToPage(profile),
516
+ provider: options.provider ?? {},
517
+ // A stateless profile keeps no conversation, so it takes no store.
518
+ ...(profile.providerContinuation?.history === 'stateless'
519
+ ? {}
520
+ : { conversationStore: chatStore() }),
521
+ ...shared,
522
+ })));
523
+ }
524
+ catch (error) {
525
+ problems.push({
526
+ profile: profile.id,
527
+ message: error instanceof Error ? error.message : String(error),
528
+ });
529
+ }
530
+ }
531
+ return served;
532
+ }
533
+ /** `answer` with the page's CORS headers on it. */
534
+ async function withCors(answer, cors) {
535
+ const response = await answer;
536
+ const headers = new Headers(response.headers);
537
+ for (const [key, value] of Object.entries(cors))
538
+ headers.set(key, value);
539
+ return new Response(response.body, { status: response.status, headers });
540
+ }
541
+ /**
542
+ * Serves the studio for the tools and profiles registered when it is called.
543
+ * Register the project first.
544
+ */
545
+ export function createStudioHandler(options) {
546
+ const base = STUDIO_BASE;
547
+ const corsFor = (request) => corsHeaders(request, options.pageOrigins);
548
+ // The page reads the tools as the files set them, then they are made to ask.
549
+ const description = describeStudio(options.project, options.questions ?? {}, options.images ?? {});
550
+ description.asks = askBeforeWrites();
551
+ const peopleProblem = options.people === undefined ? undefined : peopleFault(options.people);
552
+ // People the page cannot be offered are not offered: every run acts as no one, and the page says why.
553
+ const people = options.people && !peopleProblem ? options.people : undefined;
554
+ if (people)
555
+ description.people = peopleOffer(people);
556
+ if (peopleProblem)
557
+ description.peopleProblem = peopleProblem;
558
+ const handlerOptions = { ...options, people };
559
+ const served = profileHandlers(handlerOptions, description.problems);
560
+ const prefix = `${base}/profiles/`;
561
+ const peoplePath = `${base}/people`;
562
+ // The screen's own requests (the guardrail probe, the key and connection tests) need no project.
563
+ // This server is the builder's alone, so a connection test reaches what the draft's runs reach.
564
+ const draft = createStudioDraftHandler({ draftNetwork: true });
565
+ const run = async (request, path) => {
566
+ const cors = corsFor(request);
567
+ const id = decodeURIComponent(path.slice(prefix.length).split('/')[0] ?? '');
568
+ const serve = served.get(id);
569
+ if (!serve)
570
+ return json(404, {}, cors);
571
+ const read = readActingAs(request, people);
572
+ if (!read.ok)
573
+ return json(400, { message: read.message }, cors);
574
+ const response = await serve(request);
575
+ // A socket's answer goes back as it is: it is not a response the page reads.
576
+ if (response.status === 101)
577
+ return response;
578
+ return withCors(Promise.resolve(response), cors);
579
+ };
580
+ const answer = (request) => {
581
+ if (isForeign(request, options))
582
+ return json(403, {}, {});
583
+ const cors = corsFor(request);
584
+ if (request.method === 'OPTIONS')
585
+ return new Response(null, { status: 204, headers: cors });
586
+ const path = new URL(request.url).pathname;
587
+ if (path === base && request.method === 'GET')
588
+ return json(200, description, cors);
589
+ if (path.startsWith(prefix))
590
+ return run(request, path);
591
+ if (path === peoplePath && request.method === 'GET')
592
+ return existingPeople(people, request, cors);
593
+ if (path === `${peoplePath}/fresh` && request.method === 'POST')
594
+ return freshPerson(people, request, cors);
595
+ return withCors(draft(request), cors);
596
+ };
597
+ return (request) => Promise.resolve(answer(request));
598
+ }
@@ -0,0 +1,19 @@
1
+ /**
2
+ * What a decision and an embedding on lent keys share: the model the keys judge, and the vault
3
+ * the run takes from the host.
4
+ *
5
+ * @module
6
+ */
7
+ import { type Profile, type ProviderHostOptions } from '@theoremjs/agents';
8
+ import type { LentBinding, ModelProfileType } from '../lent-keys.ts';
9
+ import type { LentRuntime } from './draft-handler.ts';
10
+ /** The route of `profile`'s first model, as the keys judge it. */
11
+ export declare function lentRoute(type: ModelProfileType, profile: {
12
+ models: Record<string, {
13
+ protocol: string;
14
+ provider: string;
15
+ apiId: string;
16
+ }>;
17
+ }): LentBinding;
18
+ /** The vault the host lends `profile`, refused as `auth` when it holds no key. */
19
+ export declare function lentVault(runtime: LentRuntime, profile: Profile, route: string): NonNullable<ProviderHostOptions['vault']>;
@@ -0,0 +1,23 @@
1
+ /**
2
+ * What a decision and an embedding on lent keys share: the model the keys judge, and the vault
3
+ * the run takes from the host.
4
+ *
5
+ * @module
6
+ */
7
+ import { TheoremError } from '@theoremjs/agents';
8
+ import { modelRoute, STUDIO_PROVIDERS } from "../providers.js";
9
+ /** The route of `profile`'s first model, as the keys judge it. */
10
+ export function lentRoute(type, profile) {
11
+ return {
12
+ ...modelRoute(STUDIO_PROVIDERS, type, Object.values(profile.models)[0]),
13
+ builtInTools: [],
14
+ };
15
+ }
16
+ /** The vault the host lends `profile`, refused as `auth` when it holds no key. */
17
+ export function lentVault(runtime, profile, route) {
18
+ const vault = runtime.hostOptions?.(profile).vault ?? {};
19
+ if (!Object.values(vault).some(Boolean)) {
20
+ throw new TheoremError('auth', `studio ${route}: provider key is missing`); // labels-exempt: internal diagnostic
21
+ }
22
+ return vault;
23
+ }
@@ -0,0 +1,15 @@
1
+ /**
2
+ * A voice call with one of the project's live profiles: the page's socket on one side, the
3
+ * project's own session on the other. The call opens with the page's open message, as a call to
4
+ * the application's relay does.
5
+ *
6
+ * @module
7
+ */
8
+ import { type Profile, type ProviderHostOptions } from '@theoremjs/agents';
9
+ /** The server's end of the page's socket, and the answer that completes the upgrade. */
10
+ export type StudioUpgrade = (request: Request) => {
11
+ socket: WebSocket;
12
+ response: Response;
13
+ };
14
+ /** Serves a live profile: a socket upgrade starts a call, and anything else is told to upgrade. */
15
+ export declare function createStudioLiveHandler(profile: Profile, provider: ProviderHostOptions, upgrade: StudioUpgrade): (request: Request) => Promise<Response>;