@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,45 @@
1
+ import { TheoremChat } from '@theoremjs/react/ui';
2
+ import { type ComponentProps } from 'react';
3
+ import { type StudioBrowserRuntime } from '../browser.ts';
4
+ import { type StudioConnectionMode, type StudioRunPayload, type StudioWorkspace } from '../mod.ts';
5
+ export interface StudioRunnerProps {
6
+ payload: StudioRunPayload;
7
+ mode: StudioConnectionMode;
8
+ runtime: StudioBrowserRuntime | null;
9
+ trace?: boolean;
10
+ className?: string;
11
+ /** The run page is already the shell. A decision or host sits in it, rather than on its own ground. */
12
+ flush?: boolean;
13
+ /** A decision or host puts the request on the left and the response on the right. */
14
+ columns?: boolean;
15
+ /** Called on each request the conversation sends: a turn, call, decision, or live session. */
16
+ onActivity?: () => void;
17
+ /**
18
+ * The ref of a chat conversation to resume, as `onConversationChange` reported it (text and
19
+ * image agents run in the page). A project's chat is not resumed: its key is the run's.
20
+ */
21
+ conversation?: ChatProps['conversation'];
22
+ /** The conversation under `conversation` as the server showed it, drawn at once. */
23
+ conversationView?: ChatProps['conversationView'];
24
+ /** The text a chat's composer starts with. */
25
+ initialText?: ChatProps['initialText'];
26
+ onConversationChange?: ChatProps['onConversationChange'];
27
+ chatRef?: ChatProps['chatRef'];
28
+ /** The value the page picked for each slot, for a chat's turns and a call's start. */
29
+ slots?: ChatProps['slots'];
30
+ /** What the page tells the agent. */
31
+ context?: ChatProps['context'];
32
+ /**
33
+ * The workspace the payload was compiled from, when the page edits one. A project's chat then
34
+ * answers twice while it holds edits the files do not: as the files, and as the edits.
35
+ */
36
+ tested?: StudioWorkspace;
37
+ }
38
+ /**
39
+ * The builder preview and existing run page select transports under the same runner UI.
40
+ *
41
+ * A runner is one conversation. The chat keeps its transcript when an edit recompiles the draft,
42
+ * so its trace feed outlives each transport too; remount the runner (a new `key`) to start over.
43
+ */
44
+ export declare function StudioRunner({ payload, mode, runtime, trace, className, flush, columns, onActivity, conversation, conversationView, initialText, onConversationChange, chatRef, slots, context, tested, }: StudioRunnerProps): import("react").JSX.Element;
45
+ export type ChatProps = ComponentProps<typeof TheoremChat>;
@@ -0,0 +1,187 @@
1
+ import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { Button } from '@astryxdesign/core/Button';
3
+ import { HStack } from '@astryxdesign/core/HStack';
4
+ import { Icon } from '@astryxdesign/core/Icon';
5
+ import { Token } from '@astryxdesign/core/Token';
6
+ import { IconKey } from '@tabler/icons-react';
7
+ import { createDecisionTransport, createEmbeddingTransport, createHostTransport, createHttpTransport, createTraceFeed, } from '@theoremjs/react/client';
8
+ import { PaneLoading, PaneState, TheoremChat, useLabels } from '@theoremjs/react/ui';
9
+ import { lazy, Suspense, useContext, useEffect, useMemo, useRef, useState, } from 'react';
10
+ import { createBrowserStudioTransport } from "../browser.js";
11
+ import { compileWorkspace, createStudioTransport, ON_OWN_KEYS, studioInterface, studioPageTools, workspaceRunAgent, } from "../mod.js";
12
+ import { useActingAs } from "./lib/acting-as.js";
13
+ import { tracedTransport } from "./lib/project-traces.js";
14
+ import { noting } from "./lib/studio-activity.js";
15
+ import { pageConversationKey } from "./lib/studio-conversation.js";
16
+ import { STUDIO_LABELS } from "./lib/studio-labels.js";
17
+ import { editedProfileEndpoint, projectProfileEndpoint, useProject, } from "./lib/studio-project.js";
18
+ import { warmWhenIdle } from "./lib/when-idle.js";
19
+ import { EditedSide, ProjectChat, SavedSide, SavedSlot, unsavedEdits, useEditedLoad, useLoadedStamp, useSavedHidden, } from "./studio-compare.js";
20
+ import { ChooseConflictsContext } from "./studio-conflicts.js";
21
+ import { clearRemoves, useProjectSave } from "./studio-save.js";
22
+ // Each type that is not a chat loads when an agent of it first runs, or once the page is idle.
23
+ const decisionRun = () => import("./studio-decision.js");
24
+ const embeddingRun = () => import("./studio-embedding.js");
25
+ const hostRun = () => import("./studio-host-console.js");
26
+ const liveRun = () => import("./studio-live.js");
27
+ const StudioDecision = lazy(() => decisionRun().then((run) => ({ default: run.StudioDecision })));
28
+ const DecisionView = lazy(() => decisionRun().then((run) => ({ default: run.DecisionView })));
29
+ const StudioEmbedding = lazy(() => embeddingRun().then((run) => ({ default: run.StudioEmbedding })));
30
+ const EmbeddingView = lazy(() => embeddingRun().then((run) => ({ default: run.EmbeddingView })));
31
+ const StudioHostConsole = lazy(() => hostRun().then((run) => ({ default: run.StudioHostConsole })));
32
+ const HostView = lazy(() => hostRun().then((run) => ({ default: run.HostView })));
33
+ const StudioLive = lazy(() => liveRun().then((run) => ({ default: run.StudioLive })));
34
+ const ProjectLive = lazy(() => liveRun().then((run) => ({ default: run.ProjectLive })));
35
+ /** While a type's runner loads: blank, then the chat's own loading pane if it takes a while. */
36
+ function RunLoading() {
37
+ const t = useLabels();
38
+ return _jsx(PaneLoading, { label: t('@theorem.chat.loading') });
39
+ }
40
+ /**
41
+ * The builder preview and existing run page select transports under the same runner UI.
42
+ *
43
+ * A runner is one conversation. The chat keeps its transcript when an edit recompiles the draft,
44
+ * so its trace feed outlives each transport too; remount the runner (a new `key`) to start over.
45
+ */
46
+ export function StudioRunner({ payload, mode, runtime, trace, className, flush, columns, onActivity, conversation, conversationView, initialText, onConversationChange, chatRef, slots, context, tested, }) {
47
+ const [traces] = useState(createTraceFeed);
48
+ const activity = useRef(onActivity);
49
+ activity.current = onActivity;
50
+ const [note] = useState(() => () => activity.current?.());
51
+ const project = useProject();
52
+ useEffect(() => {
53
+ warmWhenIdle(decisionRun, embeddingRun, hostRun, liveRun);
54
+ }, []);
55
+ return (_jsx(Suspense, { fallback: _jsx(RunLoading, {}), children: _jsx(Run, { payload: payload, mode: mode, runtime: runtime, trace: trace, className: className, flush: flush, columns: columns, conversation: conversation, conversationView: conversationView, initialText: initialText, onConversationChange: onConversationChange, chatRef: chatRef, slots: slots, context: context, tested: tested, project: project, traces: traces, note: note }) }));
56
+ }
57
+ function Run({ payload, mode, runtime, trace, className, flush, columns, conversation, conversationView, initialText, onConversationChange, chatRef, slots, context, tested, project, traces, note, }) {
58
+ if (project)
59
+ return (_jsx(ProjectRun, { project: project, payload: payload, traces: traces, trace: trace, className: className, flush: flush, columns: columns, note: note, chatRef: chatRef, slots: slots, context: context, tested: tested }));
60
+ if (mode !== 'demo' && !runtime)
61
+ return (_jsx(PaneState, { icon: _jsx(Icon, { icon: IconKey, size: "lg", color: "secondary" }), title: "Connect to run", description: "Add your provider keys or local endpoint under Keys." }));
62
+ if (payload.profile.type === 'decision')
63
+ return (_jsx(StudioDecision, { payload: payload, runtime: runtime, traces: traces, trace: trace, className: className, onActivity: note, flush: flush, columns: columns }));
64
+ if (payload.profile.type === 'host')
65
+ return (_jsx(StudioHostConsole, { payload: payload, runtime: runtime, traces: traces, trace: trace, className: className, onActivity: note, flush: flush, columns: columns }));
66
+ if (payload.profile.type === 'embedding')
67
+ return (_jsx(StudioEmbedding, { payload: payload, runtime: runtime, traces: traces, trace: trace, className: className, onActivity: note, flush: flush, columns: columns }));
68
+ return (_jsx(TurnRun, { payload: payload, runtime: runtime, traces: traces, trace: trace, className: className, note: note, conversation: conversation, conversationView: conversationView, initialText: initialText, onConversationChange: onConversationChange, chatRef: chatRef, slots: slots, context: context }));
69
+ }
70
+ /**
71
+ * The two ways out of a run that waits on a Save: write the edits, or drop them. Dropping an
72
+ * agent the files never held removes it.
73
+ */
74
+ function UnsavedActions({ agentId, isNew }) {
75
+ const save = useProjectSave();
76
+ const choose = useContext(ChooseConflictsContext);
77
+ if (!save)
78
+ return null;
79
+ return (_jsxs(_Fragment, { children: [choose ? (_jsx(Token, { label: "Choose", color: "orange", description: "Choose between studio edits and source code, then save", onClick: choose })) : (_jsx(Token, { label: "Save", color: "blue", description: save.review ? 'Review the diff, then save' : 'Fix the issues in the editor first', onClick: save.review })), _jsx(Button, { label: isNew ? 'Remove agent' : 'Clear changes', variant: "ghost", size: "sm", onClick: () => {
80
+ save.clear(agentId);
81
+ } })] }));
82
+ }
83
+ /** The types that are not a conversation: a chat cannot sit beside one of these. */
84
+ const NOT_A_CHAT = new Set(['decision', 'host', 'live']);
85
+ const isChat = (payload) => !NOT_A_CHAT.has(payload.profile.type);
86
+ /**
87
+ * The agent as the files hold it, compiled from where the workspace started: an edit may have
88
+ * renamed it or made it another type. Undefined for an agent the files do not hold.
89
+ */
90
+ function savedPayload(edits, payload, profiles) {
91
+ const inFiles = (agent) => profiles.includes(agent.identity.agentId.trim());
92
+ const key = edits.agents.find((agent) => agent.identity.agentId.trim() === payload.agentId)?.key;
93
+ const start = key === undefined ? undefined : edits.starts.agents[key];
94
+ if (!start || !inFiles(start))
95
+ return undefined;
96
+ const agents = Object.values(edits.starts.agents).filter(inFiles);
97
+ const here = new Set(agents.map((agent) => agent.key));
98
+ // A tool that ran an agent the edits removed has no agent here to run.
99
+ const toolSpecs = Object.values(edits.starts.tools).filter((tool) => tool.toolType !== 'agent' || here.has(tool.agentKey ?? ''));
100
+ const held = new Set(toolSpecs.map((tool) => tool.key));
101
+ const files = {
102
+ ...edits,
103
+ agents: agents.map((agent) => ({
104
+ ...agent,
105
+ tools: { ...agent.tools, allow: agent.tools.allow.filter((toolKey) => held.has(toolKey)) },
106
+ })),
107
+ toolSpecs,
108
+ };
109
+ // The files run in the project, on its own setup.
110
+ const compiled = compileWorkspace(files, ON_OWN_KEYS);
111
+ const run = compiled.ok ? workspaceRunAgent(compiled, start.identity.agentId.trim()) : undefined;
112
+ if (!run)
113
+ return undefined;
114
+ const { agentId, profile, customTools, structured, questions, dependencies } = run;
115
+ return { ...payload, agentId, profile, customTools, structured, questions, dependencies };
116
+ }
117
+ /** One profile on one endpoint, as its type runs: a chat, a decision, an embedding, a tool console, or a call. */
118
+ function SideRun({ payload, endpoint, load, traces, note, trace, className, flush, columns, chatRef, slots, context, }) {
119
+ const { type } = payload.profile;
120
+ // One per load, so each transport below is made again when the edits load again.
121
+ const at = useMemo(() => ({ endpoint, load }), [endpoint, load]);
122
+ const pageTools = useMemo(() => studioPageTools(payload), [payload]);
123
+ const chats = isChat(payload);
124
+ const { actingAs } = useActingAs();
125
+ const chat = useMemo(() => chats
126
+ ? noting(tracedTransport(createHttpTransport, at.endpoint, traces, actingAs), note)
127
+ : null, [chats, at, traces, actingAs, note]);
128
+ const host = useMemo(() => type === 'host'
129
+ ? noting(tracedTransport(createHostTransport, at.endpoint, traces, actingAs), note)
130
+ : null, [type, at, traces, actingAs, note]);
131
+ const decision = useMemo(() => type === 'decision'
132
+ ? noting({ ...createDecisionTransport({ endpoint: at.endpoint }), traces }, note)
133
+ : null, [type, at, traces, note]);
134
+ const embedding = useMemo(() => type === 'embedding'
135
+ ? noting({ ...createEmbeddingTransport({ endpoint: at.endpoint }), traces }, note)
136
+ : null, [type, at, traces, note]);
137
+ if (chat)
138
+ return (_jsx(TheoremChat, { detectCodeLanguage: true, labels: STUDIO_LABELS, transport: chat, pageTools: pageTools, trace: trace, className: className, chatRef: chatRef, slots: slots, context: context }));
139
+ const view = { payload, trace, flush, columns, className };
140
+ if (decision)
141
+ return _jsx(DecisionView, { ...view, transport: decision });
142
+ if (embedding)
143
+ return _jsx(EmbeddingView, { ...view, transport: embedding });
144
+ if (host)
145
+ return _jsx(HostView, { ...view, transport: host });
146
+ return (_jsx(ProjectLive, { payload: payload, endpoint: endpoint, note: note, trace: trace, slots: slots, context: context }));
147
+ }
148
+ /**
149
+ * A project's profile with edits the files do not hold, where either side is not a chat: the
150
+ * files' run and the edits' run side by side, each its own. The files' side can be put away.
151
+ */
152
+ function ProjectSides({ project, payload, saved, edits, traces, chatRef, ...shared }) {
153
+ const { answer, pending } = useEditedLoad(project, edits, false);
154
+ const stamp = useLoadedStamp(answer);
155
+ const refused = answer && !answer.ok && !pending ? answer : undefined;
156
+ const isSavedHidden = useSavedHidden();
157
+ // The edited side's own feed, so its traces are not the files' side's.
158
+ const [editedTraces] = useState(createTraceFeed);
159
+ return (_jsxs(HStack, { height: "100%", children: [_jsx(SavedSlot, { isShown: !isSavedHidden, hasDivider: true, children: saved && (_jsx(SavedSide, { children: _jsx(SideRun, { ...shared, payload: saved, endpoint: projectProfileEndpoint(project, saved.agentId), traces: traces }) })) }), _jsx("div", { className: "studio-edited-slot", children: _jsx(EditedSide, { refused: refused, isLoading: stamp === undefined && !refused, hasSaved: saved !== undefined, actions: _jsx(UnsavedActions, { agentId: payload.agentId, isNew: clearRemoves(edits, payload.agentId, project.profiles) }), children: stamp !== undefined && (_jsx(SideRun, { ...shared, load: stamp, payload: payload, endpoint: editedProfileEndpoint(project, payload.agentId), traces: editedTraces, chatRef: chatRef })) }) }, "edited")] }));
160
+ }
161
+ /**
162
+ * A project's profile, run by the studio's local server: the project's own tools and models.
163
+ * While the builder has edits the files do not hold, it runs twice, side by side: as the files,
164
+ * and as the files with the edits laid over them. Two chats share one message.
165
+ */
166
+ function ProjectRun({ project, tested, ...run }) {
167
+ const { payload } = run;
168
+ const edits = useMemo(() => unsavedEdits(tested, project.profiles), [tested, project.profiles]);
169
+ const saved = useMemo(() => (edits ? savedPayload(edits, payload, project.profiles) : undefined), [edits, payload, project.profiles]);
170
+ if (isChat(payload) && (!saved || isChat(saved)))
171
+ return (_jsx(ProjectChat, { project: project, profileId: payload.agentId, tested: tested, note: run.note, traces: run.traces, trace: run.trace, className: run.className, chatRef: run.chatRef, slots: run.slots, context: run.context }));
172
+ if (!edits)
173
+ return _jsx(SideRun, { ...run, endpoint: projectProfileEndpoint(project, payload.agentId) });
174
+ return _jsx(ProjectSides, { ...run, project: project, saved: saved, edits: edits });
175
+ }
176
+ function TurnRun({ payload, runtime, traces, trace, className, note, conversation, conversationView, initialText, onConversationChange, chatRef, slots, context, }) {
177
+ const iface = useMemo(() => studioInterface(payload), [payload]);
178
+ /** The studio's page answers each page tool with the tool's stub. */
179
+ const pageTools = useMemo(() => studioPageTools(payload), [payload]);
180
+ const transport = useMemo(() => noting(runtime
181
+ ? createBrowserStudioTransport(payload, runtime, {
182
+ conversationKey: pageConversationKey(),
183
+ traces,
184
+ })
185
+ : createStudioTransport(payload, { traces }), note), [payload, runtime, traces, note]);
186
+ return iface.type === 'live' ? (_jsx(StudioLive, { payload: payload, runtime: runtime, note: note, trace: trace, slots: slots, context: context })) : (_jsx(TheoremChat, { detectCodeLanguage: true, labels: STUDIO_LABELS, transport: transport, trace: trace, className: className, conversation: conversation, conversationView: conversationView, initialText: initialText, onConversationChange: onConversationChange, chatRef: chatRef, slots: slots, context: context, pageTools: pageTools }));
187
+ }
@@ -0,0 +1,49 @@
1
+ import { type ReactNode } from 'react';
2
+ import { type StudioWorkspace } from '../mod.ts';
3
+ import { type ProjectSession } from './lib/studio-project.ts';
4
+ export type Update = (change: (current: StudioWorkspace) => StudioWorkspace) => void;
5
+ /** Save, for whatever on the page offers it. */
6
+ export interface ProjectSaveActions {
7
+ /** Whether the studio holds edits the project's files do not. */
8
+ unsaved: boolean;
9
+ /** Opens the review of the lines a Save writes. Absent while Save cannot start. */
10
+ review: (() => void) | undefined;
11
+ /** Puts one profile back as the files hold it. One the files do not hold leaves the studio. */
12
+ clear: (agentId: string) => void;
13
+ /**
14
+ * Asks once, then drops every unsaved edit and opens the files as they are. Absent while the
15
+ * studio holds no edits.
16
+ */
17
+ discard: (() => void) | undefined;
18
+ }
19
+ /** Save for the open project, or null on a page that has none. */
20
+ export declare function useProjectSave(): ProjectSaveActions | null;
21
+ /**
22
+ * Whether clearing a profile removes it: it was added here, the files do not hold it, and it has
23
+ * no changes of its own left to drop.
24
+ */
25
+ export declare function clearRemoves(workspace: StudioWorkspace, agentId: string, profiles: readonly string[]): boolean;
26
+ /**
27
+ * Save for a project: the review of the lines that change before anything is written, and the
28
+ * write. Whatever it wraps opens that review through `useProjectSave`.
29
+ */
30
+ export declare function ProjectSave({ project, workspace, update, onFilesChanged, onDiscard, blocked, children, }: {
31
+ project: ProjectSession;
32
+ workspace: StudioWorkspace;
33
+ update: Update;
34
+ /** Called once a Save or an undo has changed the project's files. */
35
+ onFilesChanged: () => void;
36
+ /** Drops every unsaved edit and opens the files as they are. The builder has said yes. */
37
+ onDiscard: () => void;
38
+ /** Whether Save cannot start: the editor has issues. */
39
+ blocked: boolean;
40
+ children: ReactNode;
41
+ }): import("react").JSX.Element;
42
+ /**
43
+ * A project's tokens in the editor's toolbar: Save while the studio holds edits the files do not,
44
+ * and what the studio cannot run. Nothing while there is neither.
45
+ */
46
+ export declare function ProjectTokens({ project, unloaded, }: {
47
+ project: ProjectSession;
48
+ unloaded?: string;
49
+ }): import("react").JSX.Element;
@@ -0,0 +1,307 @@
1
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
+ import { AlertDialog } from '@astryxdesign/core/AlertDialog';
3
+ import { Banner } from '@astryxdesign/core/Banner';
4
+ import { Button } from '@astryxdesign/core/Button';
5
+ import { CodeBlock } from '@astryxdesign/core/CodeBlock';
6
+ import { Dialog, DialogHeader } from '@astryxdesign/core/Dialog';
7
+ import { HoverCard } from '@astryxdesign/core/HoverCard';
8
+ import { HStack } from '@astryxdesign/core/HStack';
9
+ import { Icon } from '@astryxdesign/core/Icon';
10
+ import { IconButton } from '@astryxdesign/core/IconButton';
11
+ import { Layout, LayoutContent, LayoutFooter } from '@astryxdesign/core/Layout';
12
+ import { ScrollableArea } from '@astryxdesign/core/ScrollableArea';
13
+ import { Tab, TabList } from '@astryxdesign/core/TabList';
14
+ import { Text } from '@astryxdesign/core/Text';
15
+ import { useToast } from '@astryxdesign/core/Toast';
16
+ import { Token } from '@astryxdesign/core/Token';
17
+ import { VStack } from '@astryxdesign/core/VStack';
18
+ import { IconFiles, IconListDetails } from '@tabler/icons-react';
19
+ import { createContext, useCallback, useContext, useEffect, useMemo, useRef, useState, } from 'react';
20
+ import { atStart, removeAgent, resetAgent, startedHere, } from "../mod.js";
21
+ import { DiffBlock } from "./diff-block.js";
22
+ import { reviewSave, undoSave, writeSave } from "./lib/studio-project.js";
23
+ import { RefusalDetail } from "./refusal-detail.js";
24
+ /** Wide enough for a reason's sentence to read in a few lines. */
25
+ const ALERTS_WIDTH = 320;
26
+ /** The most of the alerts a hover shows before it scrolls: a project can have one for every agent. */
27
+ const ALERTS_MAX_HEIGHT = 'min(24rem, 60vh)';
28
+ const DIALOG_WIDTH = 720;
29
+ /** How long the saved line stays, in milliseconds: long enough to reach Undo. */
30
+ const UNDO_WINDOW = 15_000;
31
+ /** Why nothing was written, as the builder reads it. */
32
+ const REFUSED = {
33
+ issues: 'Fix the issues in the editor first.',
34
+ stale: 'Your files changed after this review was made. Close it and review again.',
35
+ unwritable: 'Some changes cannot be written to your files.',
36
+ write: 'A file could not be written, so your files were put back.',
37
+ check: 'The project did not type-check with these changes, so your files were put back.',
38
+ load: 'The project did not start with these changes, so your files were put back.',
39
+ differs: 'The files did not load as what you tested, so they were put back.',
40
+ nothing: 'There is no save to undo.',
41
+ unanswered: 'The studio did not answer, so it is not known whether your files changed. Check them in your editor.',
42
+ };
43
+ /** A server that did not answer, as a refusal the dialog can show. */
44
+ function unreachable(error) {
45
+ return {
46
+ ok: false,
47
+ reason: 'unanswered',
48
+ detail: [error instanceof Error ? error.message : String(error)],
49
+ };
50
+ }
51
+ /** Where a change is set, as `file:line`. */
52
+ function place(change) {
53
+ if (!change.file)
54
+ return 'your files';
55
+ return change.line ? `${change.file}:${String(change.line)}` : change.file;
56
+ }
57
+ /** Why a change inside a constant is not written: who else reads the constant, and the way through. */
58
+ function constantReason(change) {
59
+ const name = change.name ?? 'a constant';
60
+ const also = change.readByCode ? ' Other code reads it too.' : '';
61
+ if (!change.sharedWith?.length)
62
+ return `Set by ${name} in ${place(change)}. Change it there.${also}`;
63
+ const others = change.sharedWith.join(', ');
64
+ const hold = change.sharedWith.length > 1 ? 'do' : 'does';
65
+ return `${name} in ${place(change)} is shared with ${others}, which ${hold} not hold this change. Make it on each, or change it there.${also}`;
66
+ }
67
+ /** The values Save writes that other code reads too, each once: `resultSchema in result.ts:3`. */
68
+ function readElsewhere(changes) {
69
+ const held = changes
70
+ .filter((change) => change.status === 'written' && change.readByCode)
71
+ .map((change) => `${change.name ? `${change.name} in ` : ''}${place(change)}`);
72
+ return [...new Set(held)];
73
+ }
74
+ /** Why one change is not written, and what the builder does about it. */
75
+ function reason(change) {
76
+ switch (change.status) {
77
+ case 'constant':
78
+ return constantReason(change);
79
+ case 'code':
80
+ return `Set in code at ${place(change)}. Change it there.`;
81
+ case 'changed':
82
+ return `${place(change)} changed after the studio opened it. Reload the studio.`;
83
+ case 'unused':
84
+ return 'No agent allows this tool yet. Allow it on an agent, or remove it.';
85
+ case 'taken':
86
+ return `A file is already at ${place(change)}. Rename the ${change.kind}, or move that file.`;
87
+ case 'owed':
88
+ return 'This agent checks each item of a list with code the studio does not hold. Add the agent in your code.';
89
+ case 'setup':
90
+ return `The studio cannot tell where ${place(change)} would register a new ${change.kind}. Add it in your code.`;
91
+ case 'removed':
92
+ return change.file
93
+ ? `The studio cannot tell how ${place(change)} registers this ${change.kind}. Remove it in your code.`
94
+ : `The studio could not find where your files register this ${change.kind}. Remove it in your code.`;
95
+ default:
96
+ return 'The studio could not find where your files set this.';
97
+ }
98
+ }
99
+ /** One run of changed lines: the lines taken out marked `-`, the lines put in marked `+`. */
100
+ function HunkBlock({ file, hunk }) {
101
+ const signed = (sign) => (text) => ({ sign, text });
102
+ return (_jsx(DiffBlock, { title: file.created || file.removed
103
+ ? `${fileNote(file)} · ${file.file}`
104
+ : `${file.file}:${String(hunk.line)}`, start: hunk.line - hunk.lead.length, lines: [
105
+ ...hunk.lead.map(signed(' ')),
106
+ ...hunk.removed.map(signed('-')),
107
+ ...hunk.added.map(signed('+')),
108
+ ...hunk.trail.map(signed(' ')),
109
+ ] }));
110
+ }
111
+ /** What happens to a file: it is new, it goes, or how many places in it change. */
112
+ function fileNote(file) {
113
+ if (file.created)
114
+ return 'New file';
115
+ if (file.removed)
116
+ return 'Removed file';
117
+ return file.hunks.length === 1 ? '1 change' : `${String(file.hunks.length)} changes`;
118
+ }
119
+ function FileHunks({ file }) {
120
+ return (_jsx(VStack, { gap: 3, children: file.hunks.map((hunk) => (_jsx(HunkBlock, { file: file, hunk: hunk }, hunk.line))) }));
121
+ }
122
+ /** The changes Save cannot write, each with what the builder does about it. */
123
+ function BlockedChanges({ changes }) {
124
+ if (!changes.length)
125
+ return null;
126
+ return (_jsxs(VStack, { gap: 4, children: [_jsx(Banner, { status: "warning", title: "Save writes every change or none, so your files hold exactly what you tested.", description: "Reset the changes below in the studio, or make them in your code." }), changes.map((change) => (_jsxs(VStack, { gap: 1, children: [_jsx(Text, { weight: "semibold", children: change.setting ? `${change.of} · ${change.setting}` : change.of }), _jsx(Text, { type: "supporting", color: "secondary", children: reason(change) })] }, `${change.kind}:${change.of}:${change.setting}`)))] }));
127
+ }
128
+ /** The button that flips the review's view: it names the view it goes to. */
129
+ const VIEW_FLIP = {
130
+ all: { label: 'By file', icon: IconFiles, tooltip: 'Show one file at a time', next: 'file' },
131
+ file: {
132
+ label: 'All changes',
133
+ icon: IconListDetails,
134
+ tooltip: 'Show every change in one scroll',
135
+ next: 'all',
136
+ },
137
+ };
138
+ /**
139
+ * The lines Save changes. Down one scroll, each file's name stays at the top while its changes
140
+ * pass. By file, a tab for each file stays there and shows that file alone.
141
+ */
142
+ function ReviewBody({ review, view }) {
143
+ const [picked, setPicked] = useState();
144
+ const { files } = review;
145
+ const blocked = review.changes.filter((change) => change.status !== 'written');
146
+ const elsewhere = readElsewhere(review.changes);
147
+ const shown = files.find((file) => file.file === picked) ?? files[0];
148
+ // One file reads the same either way.
149
+ const byFile = view === 'file' && files.length > 1;
150
+ return (_jsxs(_Fragment, { children: [review.changes.length === 0 && (_jsx(Text, { color: "secondary", children: "Nothing here changes what your files set." })), _jsx(BlockedChanges, { changes: blocked }), elsewhere.length > 0 && (_jsx(Banner, { status: "info", title: "Other code in your project reads what this changes.", description: `${elsewhere.join(', ')}. That code runs on the new value once you save.` })), byFile
151
+ ? shown && (_jsxs(VStack, { gap: 2, children: [_jsx("div", { className: "save-file", children: _jsx(TabList, { value: shown.file, size: "sm", onChange: setPicked, children: files.map((file) => (_jsx(Tab, { value: file.file, label: file.file }, file.file))) }) }), _jsx(FileHunks, { file: shown })] }))
152
+ : files.map((file) => (_jsxs(VStack, { gap: 2, children: [_jsx("div", { className: "save-file", children: _jsxs(HStack, { gap: 2, vAlign: "center", children: [_jsx(Text, { weight: "semibold", children: file.file }), _jsx(Text, { type: "supporting", color: "secondary", children: fileNote(file) })] }) }), _jsx(FileHunks, { file: file })] }, file.file)))] }));
153
+ }
154
+ function RefusalBody({ refusal }) {
155
+ return (_jsxs(VStack, { gap: 3, children: [_jsx(Banner, { status: "error", title: REFUSED[refusal.reason] }), refusal.kept?.length ? (_jsx(Banner, { status: "warning", title: `Left as they are now, because they changed while Save checked them: ${refusal.kept.join(', ')}` })) : null, _jsx(RefusalDetail, { refusal: refusal })] }));
156
+ }
157
+ /**
158
+ * What the studio cannot run: files that stopped loading, and the profiles a project registers
159
+ * that it cannot run. A count that shows each one's reason on hover. Nothing while there are none.
160
+ */
161
+ function ProjectProblems({ project, unloaded }) {
162
+ const { problems, modelProblems, differences, unheld, unregistered } = project;
163
+ const count = problems.length +
164
+ modelProblems.length +
165
+ differences.length +
166
+ (unheld.length ? 1 : 0) +
167
+ (unregistered.length ? 1 : 0) +
168
+ (unloaded === undefined ? 0 : 1);
169
+ if (!count)
170
+ return null;
171
+ return (_jsx(HoverCard, { label: "What the studio cannot run or shows differently", touchTrigger: "tap", content: _jsx(ScrollableArea, { label: "What the studio cannot run or shows differently", width: ALERTS_WIDTH, style: { maxHeight: ALERTS_MAX_HEIGHT }, children: _jsxs(VStack, { gap: 3, children: [unloaded !== undefined && (_jsxs(VStack, { gap: 1, children: [_jsx(Text, { weight: "semibold", children: "The studio cannot load your files." }), _jsx(Text, { type: "supporting", color: "secondary", children: "It runs them as they last loaded, until they load again." }), _jsx(CodeBlock, { code: unloaded.trim(), size: "sm", isWrapped: true, maxHeight: 240 })] })), problems.map((problem) => (_jsxs(VStack, { gap: 1, children: [_jsx(Text, { weight: "semibold", children: `The studio cannot run ${problem.profile}.` }), _jsx(Text, { type: "supporting", color: "secondary", children: problem.message })] }, problem.profile))), modelProblems.map((problem) => (_jsxs(VStack, { gap: 1, children: [_jsx(Text, { weight: "semibold", children: `As your files set it, ${problem.profile}'s model '${problem.model}' cannot run.` }), _jsx(Text, { type: "supporting", color: "secondary", children: problem.message })] }, `${problem.profile}:${problem.model}`))), unregistered.length > 0 && (_jsxs(VStack, { gap: 1, children: [_jsx(Text, { weight: "semibold", children: "Your project did not register everything its files define." }), _jsx(Text, { type: "supporting", color: "secondary", children: `Not loaded, so not shown: ${unregistered.map((each) => each.name).join(', ')}. The studio shows what your project registers when it starts.` })] })), unheld.length > 0 && (_jsxs(VStack, { gap: 1, children: [_jsx(Text, { weight: "semibold", children: "The studio cannot check what it shows against your files." }), _jsx(Text, { type: "supporting", color: "secondary", children: `A run and Save still use your files. ${unheld.join(' ')}` })] })), differences.map((difference) => (_jsxs(VStack, { gap: 1, children: [_jsx(Text, { weight: "semibold", children: `The studio shows ${difference.of} differently from your files.` }), _jsx(Text, { type: "supporting", color: "secondary", children: `A run and Save still use your files for: ${difference.settings.join(', ')}.` })] }, `${difference.kind}:${difference.of}`)))] }) }), children: _jsx(Token, { label: count === 1 ? '1 alert' : `${String(count)} alerts`, color: "orange" }) }));
172
+ }
173
+ const ProjectSaveContext = createContext(null);
174
+ /** Save for the open project, or null on a page that has none. */
175
+ export function useProjectSave() {
176
+ return useContext(ProjectSaveContext);
177
+ }
178
+ /**
179
+ * Whether clearing a profile removes it: it was added here, the files do not hold it, and it has
180
+ * no changes of its own left to drop.
181
+ */
182
+ export function clearRemoves(workspace, agentId, profiles) {
183
+ const agent = workspace.agents.find((each) => each.identity.agentId === agentId);
184
+ const start = agent && workspace.starts.agents[agent.key];
185
+ if (!agent || !start || profiles.includes(start.identity.agentId))
186
+ return false;
187
+ return resetAgent(workspace, agent.key) === workspace;
188
+ }
189
+ /** One profile as the files hold it: back to its start, or gone when it was added here. */
190
+ function clearProfile(workspace, agentId, profiles) {
191
+ const agent = workspace.agents.find((each) => each.identity.agentId === agentId);
192
+ if (!agent)
193
+ return workspace;
194
+ return clearRemoves(workspace, agentId, profiles)
195
+ ? removeAgent(workspace, agent.key)
196
+ : resetAgent(workspace, agent.key);
197
+ }
198
+ /**
199
+ * Save for a project: the review of the lines that change before anything is written, and the
200
+ * write. Whatever it wraps opens that review through `useProjectSave`.
201
+ */
202
+ export function ProjectSave({ project, workspace, update, onFilesChanged, onDiscard, blocked, children, }) {
203
+ const toast = useToast();
204
+ const [step, setStep] = useState({ at: 'closed' });
205
+ const [view, setView] = useState('all');
206
+ const [asking, setAsking] = useState(false);
207
+ // An agent or provider added here is at its own start, and still one the files do not hold.
208
+ // One removed here has no start left, and is still one the files hold.
209
+ const clean = useMemo(() => atStart(workspace) &&
210
+ workspace.agents.length === project.profiles.length &&
211
+ workspace.agents.every((agent) => project.profiles.includes(agent.identity.agentId)) &&
212
+ workspace.providers.length === project.providers.length &&
213
+ workspace.providers.every((provider) => project.providers.includes(provider.id)), [workspace, project.profiles, project.providers]);
214
+ // The review reads the workspace as it is when asked for, so a keystroke does not remake Save.
215
+ const held = useRef({ project, workspace });
216
+ useEffect(() => {
217
+ held.current = { project, workspace };
218
+ });
219
+ const open = useCallback(() => {
220
+ setStep({ at: 'reading' });
221
+ reviewSave(held.current.project, held.current.workspace)
222
+ .catch(unreachable)
223
+ .then((answer) => {
224
+ setStep(answer.ok
225
+ ? { at: 'review', review: answer, writing: false }
226
+ : { at: 'refused', refusal: answer });
227
+ });
228
+ }, []);
229
+ const clear = useCallback((agentId) => {
230
+ update((current) => clearProfile(current, agentId, held.current.project.profiles));
231
+ }, [update]);
232
+ const undo = (starts) => {
233
+ undoSave(project)
234
+ .catch(unreachable)
235
+ .then((answer) => {
236
+ if (!answer.ok) {
237
+ toast({ type: 'error', body: REFUSED[answer.reason] });
238
+ return;
239
+ }
240
+ // The edits stay in the studio, unsaved again.
241
+ update((current) => ({ ...current, starts }));
242
+ onFilesChanged();
243
+ toast({ body: `Put ${answer.written.join(', ')} back.` });
244
+ });
245
+ };
246
+ const write = (review) => {
247
+ setStep({ at: 'review', review, writing: true });
248
+ writeSave(project, workspace, review.stamp)
249
+ .catch(unreachable)
250
+ .then((answer) => {
251
+ if (!answer.ok) {
252
+ setStep({ at: 'review', review, writing: false, refusal: answer });
253
+ return;
254
+ }
255
+ const { starts } = workspace;
256
+ update(() => startedHere(workspace));
257
+ onFilesChanged();
258
+ setStep({ at: 'closed' });
259
+ const dismiss = toast({
260
+ body: `Saved to ${answer.written.join(', ')}.`,
261
+ autoHideDuration: UNDO_WINDOW,
262
+ endContent: (_jsx(Button, { label: "Undo", variant: "ghost", size: "sm", onClick: () => {
263
+ undo(starts);
264
+ dismiss();
265
+ } })),
266
+ });
267
+ });
268
+ };
269
+ const ask = useCallback(() => {
270
+ setAsking(true);
271
+ }, []);
272
+ const unsaved = !clean || step.at !== 'closed';
273
+ const actions = useMemo(() => ({
274
+ unsaved,
275
+ review: blocked ? undefined : open,
276
+ clear,
277
+ discard: clean ? undefined : ask,
278
+ }), [unsaved, blocked, open, clear, clean, ask]);
279
+ const writing = step.at === 'review' && step.writing;
280
+ const refusal = step.at === 'refused' || step.at === 'review' ? step.refusal : undefined;
281
+ const flip = VIEW_FLIP[view];
282
+ return (_jsxs(ProjectSaveContext.Provider, { value: actions, children: [children, _jsx(Dialog, { isOpen: step.at === 'review' || step.at === 'refused', purpose: writing ? 'required' : 'form', width: DIALOG_WIDTH, maxHeight: "80vh", onOpenChange: (isOpen) => {
283
+ if (!isOpen && !writing)
284
+ setStep({ at: 'closed' });
285
+ }, children: _jsx(Layout, { header: _jsx(DialogHeader, { title: `Save to ${project.name}`, subtitle: writing
286
+ ? 'Checking that the project still loads with these lines.'
287
+ : 'Save writes all of these lines or none. It then type-checks and loads the project, and puts your files back unless it runs as what you tested.', endContent: step.at === 'review' &&
288
+ step.review.files.length > 1 && (_jsx(IconButton, { label: flip.label, variant: "ghost", icon: _jsx(Icon, { icon: flip.icon, size: "sm" }), tooltip: flip.tooltip, onClick: () => {
289
+ setView(flip.next);
290
+ } })), onOpenChange: writing ? undefined : () => setStep({ at: 'closed' }) }), content: _jsx(LayoutContent, { isScrollable: false, padding: 0, children: _jsx(ScrollableArea, { label: "Changes", height: "100%", paddingInline: 4, children: _jsxs(VStack, { gap: 4, children: [refusal && _jsx(RefusalBody, { refusal: refusal }), step.at === 'review' && _jsx(ReviewBody, { review: step.review, view: view })] }) }) }), footer: _jsx(LayoutFooter, { children: _jsxs(HStack, { gap: 2, justify: "between", children: [_jsx(Button, { label: "Discard all", variant: "ghost", isDisabled: writing || clean, onClick: ask }), _jsxs(HStack, { gap: 2, children: [_jsx(Button, { label: "Cancel", variant: "ghost", isDisabled: writing, onClick: () => {
291
+ setStep({ at: 'closed' });
292
+ } }), step.at === 'review' && (_jsx(Button, { label: "Save", variant: "primary", isDisabled: !step.review.writable, isLoading: writing, onClick: () => {
293
+ write(step.review);
294
+ } }))] })] }) }) }) }), _jsx(AlertDialog, { isOpen: asking, onOpenChange: setAsking, title: "Discard every unsaved edit?", description: "All unsaved edits will be lost. This action cannot be reversed.", actionLabel: "Discard all", actionVariant: "destructive", onAction: () => {
295
+ setAsking(false);
296
+ setStep({ at: 'closed' });
297
+ onDiscard();
298
+ } })] }));
299
+ }
300
+ /**
301
+ * A project's tokens in the editor's toolbar: Save while the studio holds edits the files do not,
302
+ * and what the studio cannot run. Nothing while there is neither.
303
+ */
304
+ export function ProjectTokens({ project, unloaded, }) {
305
+ const save = useProjectSave();
306
+ return (_jsxs(_Fragment, { children: [save?.unsaved && save.review && (_jsx(Token, { label: "Save", color: "blue", description: "Review the diff, then save", onClick: save.review })), _jsx(ProjectProblems, { project: project, unloaded: unloaded })] }));
307
+ }