@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,21 @@
1
+ /**
2
+ * Takes a profile or a tool the studio removed out of the project's files: the statement that
3
+ * registers it, and what only that statement used. A definition something else still reads stays.
4
+ * Whatever the files do that the studio cannot follow is named, and nothing is planned for it.
5
+ *
6
+ * @module
7
+ */
8
+ import { type ProjectSource } from './project-source.ts';
9
+ import type { SavePlan } from './save-plan.ts';
10
+ /** What the studio took away: the ids of profiles and providers and the names of tools the project has. */
11
+ export interface Removed {
12
+ profiles: readonly string[];
13
+ tools: readonly string[];
14
+ providers: readonly string[];
15
+ }
16
+ export interface RemovalPlan extends SavePlan {
17
+ /** The files left with nothing of their own, which Save takes away. */
18
+ gone: string[];
19
+ }
20
+ /** Plans the removal of each profile, tool, and provider the studio took away. */
21
+ export declare function planRemoved(project: ProjectSource, removed: Removed): RemovalPlan;
@@ -0,0 +1,528 @@
1
+ /**
2
+ * Takes a profile or a tool the studio removed out of the project's files: the statement that
3
+ * registers it, and what only that statement used. A definition something else still reads stays.
4
+ * Whatever the files do that the studio cannot follow is named, and nothing is planned for it.
5
+ *
6
+ * @module
7
+ */
8
+ import ts from 'typescript';
9
+ import { calleeName, isRead, propertyName, setupExport, sourceOf, unwrapped, } from "./project-source.js";
10
+ /** The calls that register what a profile's or a provider's module holds. */
11
+ const REGISTERS = new Set([
12
+ 'registerProfile',
13
+ 'registerStructured',
14
+ 'registerProvider',
15
+ 'registerTool',
16
+ ]);
17
+ /** `node` with the wrappers around it that do not change what it is. */
18
+ function wrapped(node) {
19
+ let at = node;
20
+ while (ts.isParenthesizedExpression(at.parent) ||
21
+ ts.isAsExpression(at.parent) ||
22
+ ts.isSatisfiesExpression(at.parent) ||
23
+ ts.isNonNullExpression(at.parent) ||
24
+ ts.isAwaitExpression(at.parent))
25
+ at = at.parent;
26
+ return at;
27
+ }
28
+ /** The statement an expression is the whole of, when it stands in a file or a block. */
29
+ function statementOf(expression) {
30
+ const { parent } = wrapped(expression);
31
+ if (!ts.isExpressionStatement(parent))
32
+ return undefined;
33
+ return ts.isSourceFile(parent.parent) || ts.isBlock(parent.parent) ? parent : undefined;
34
+ }
35
+ /** A file's top-level declaration that `value` is the whole value of: one `const`, alone in its statement. */
36
+ function declared(value, source) {
37
+ const { parent } = wrapped(value);
38
+ if (!ts.isVariableDeclaration(parent) || !ts.isIdentifier(parent.name))
39
+ return undefined;
40
+ const statement = parent.parent.parent;
41
+ if (!ts.isVariableStatement(statement) || statement.parent !== source)
42
+ return undefined;
43
+ if (!(statement.declarationList.flags & ts.NodeFlags.Const))
44
+ return undefined;
45
+ if (statement.declarationList.declarations.length !== 1)
46
+ return undefined;
47
+ return { name: parent.name.text, source, statement };
48
+ }
49
+ /** The top-level function a statement is the whole body of. */
50
+ function wholeBodyOf(statement, source) {
51
+ const block = statement.parent;
52
+ if (!ts.isBlock(block) || block.statements.length !== 1)
53
+ return undefined;
54
+ const held = block.parent;
55
+ if (!ts.isFunctionDeclaration(held) || held.parent !== source || !held.name)
56
+ return undefined;
57
+ return { name: held.name.text, source, statement: held };
58
+ }
59
+ function readsIn(source, name, declaration) {
60
+ const reads = [];
61
+ const visit = (node) => {
62
+ if (ts.isImportDeclaration(node))
63
+ return;
64
+ if (ts.isIdentifier(node) && node.text === name && node.parent !== declaration && isRead(node))
65
+ reads.push(node);
66
+ ts.forEachChild(node, visit);
67
+ };
68
+ visit(source);
69
+ return reads;
70
+ }
71
+ /** Each import and re-export of `home` the project's other files write. */
72
+ function* importsOf(project, home) {
73
+ for (const source of project.files.values()) {
74
+ if (source === home)
75
+ continue;
76
+ for (const statement of source.statements) {
77
+ if (!ts.isImportDeclaration(statement) && !ts.isExportDeclaration(statement))
78
+ continue;
79
+ const specifier = statement.moduleSpecifier;
80
+ if (!specifier || !ts.isStringLiteralLike(specifier))
81
+ continue;
82
+ if (sourceOf(project, source, specifier.text) === home)
83
+ yield { source, statement };
84
+ }
85
+ }
86
+ }
87
+ /** How one import of a definition's file reads the definition, when it brings it in. */
88
+ function importReader(source, statement, named) {
89
+ const bindings = statement.importClause?.namedBindings;
90
+ if (!bindings)
91
+ return undefined;
92
+ if (ts.isNamespaceImport(bindings)) {
93
+ const all = readsIn(source, bindings.name.text);
94
+ const own = (read) => ts.isPropertyAccessExpression(read.parent) &&
95
+ read.parent.expression === read &&
96
+ read.parent.name.text === named.name;
97
+ return {
98
+ source,
99
+ reads: all.filter(own),
100
+ others: all.filter((read) => !own(read)),
101
+ imported: statement,
102
+ passesOn: false,
103
+ };
104
+ }
105
+ const element = bindings.elements.find((each) => (each.propertyName ?? each.name).text === named.name);
106
+ return (element && {
107
+ source,
108
+ reads: readsIn(source, element.name.text),
109
+ others: [],
110
+ imported: element,
111
+ passesOn: false,
112
+ });
113
+ }
114
+ /** Every file of the project that reads `named`, by its own name or through an import of its file. */
115
+ function readersOf(project, named) {
116
+ const declaration = ts.isVariableStatement(named.statement)
117
+ ? named.statement.declarationList.declarations[0]
118
+ : named.statement;
119
+ const readers = [
120
+ {
121
+ source: named.source,
122
+ reads: readsIn(named.source, named.name, declaration),
123
+ others: [],
124
+ passesOn: false,
125
+ },
126
+ ];
127
+ for (const { source, statement } of importsOf(project, named.source)) {
128
+ const reader = ts.isImportDeclaration(statement)
129
+ ? importReader(source, statement, named)
130
+ : { source, reads: [], others: [], passesOn: true };
131
+ if (reader)
132
+ readers.push(reader);
133
+ }
134
+ return readers;
135
+ }
136
+ /** One plan in the making: what goes, and what could not be followed. */
137
+ /** The statement a call is, when it registers `value` or, for a function, calls it. */
138
+ function callPart(call, value, callable) {
139
+ const registers = call.arguments.includes(value) && REGISTERS.has(calleeName(call) ?? '');
140
+ const called = callable && call.expression === value;
141
+ return registers || called ? statementOf(call) : undefined;
142
+ }
143
+ const SETUP_EXPORTS = ['questions', 'images'];
144
+ /** `value`'s entry in the setup's `questions` or `images`, when that is where it sits. */
145
+ function setupEntry(parent, value, source) {
146
+ const entry = ts.isShorthandPropertyAssignment(parent) ||
147
+ (ts.isPropertyAssignment(parent) && parent.initializer === value);
148
+ if (!entry)
149
+ return undefined;
150
+ const held = SETUP_EXPORTS.some((name) => {
151
+ const value = setupExport(source, name)?.initializer;
152
+ return value && parent.parent === unwrapped(value);
153
+ });
154
+ return held ? parent : undefined;
155
+ }
156
+ class Removal {
157
+ project;
158
+ changes = [];
159
+ cut = new Map();
160
+ /** The files that define what was removed. */
161
+ homes = new Set();
162
+ constructor(project) {
163
+ this.project = project;
164
+ }
165
+ lineOf(node, source) {
166
+ return source.getLineAndCharacterOfPosition(node.getStart(source)).line + 1;
167
+ }
168
+ note(kind, of, status, at) {
169
+ this.changes.push({
170
+ kind,
171
+ of,
172
+ setting: '',
173
+ status,
174
+ ...(at ? { file: at.source.fileName, line: this.lineOf(at.node, at.source) } : {}),
175
+ });
176
+ }
177
+ /**
178
+ * What a read of a name is there for, when taking it out leaves nothing behind: a statement
179
+ * that registers it, a statement that calls it when it is a function, or its entry in the
180
+ * setup's `questions` or `images`.
181
+ */
182
+ partOf(read, source, callable = false) {
183
+ let value = read;
184
+ // `module.profile` and `module.structured.id` are reads of what the module holds.
185
+ while (ts.isPropertyAccessExpression(value.parent) && value.parent.expression === value)
186
+ value = value.parent;
187
+ value = wrapped(value);
188
+ const { parent } = value;
189
+ if (ts.isCallExpression(parent))
190
+ return callPart(parent, value, callable);
191
+ return setupEntry(parent, value, source);
192
+ }
193
+ /**
194
+ * Takes a named definition out of every file that only registers it. True when a statement that
195
+ * registers it was found. The definition itself goes when nothing else reads it.
196
+ */
197
+ named(named) {
198
+ const readers = readersOf(this.project, named);
199
+ const callable = ts.isFunctionDeclaration(named.statement);
200
+ const uses = readers.map((reader) => reader.reads.map((read) => this.partOf(read, reader.source, callable)));
201
+ const registering = uses
202
+ .flat()
203
+ .filter((use) => use !== undefined && ts.isExpressionStatement(use));
204
+ if (!registering.length)
205
+ return false;
206
+ // A module that defines one profile holds what goes with it: its reply's shape, its questions.
207
+ const alone = !callable && this.definedIn(named.source) === 1;
208
+ let kept = false;
209
+ readers.forEach((reader, index) => {
210
+ const held = uses[index] ?? [];
211
+ for (const use of held)
212
+ if (use)
213
+ this.cut.set(use, reader.source);
214
+ const beside = reader.others.map((read) => alone ? this.partOf(read, reader.source) : undefined);
215
+ const whole = !reader.passesOn && [...held, ...beside].every((use) => use !== undefined);
216
+ if (whole)
217
+ for (const use of beside)
218
+ if (use)
219
+ this.cut.set(use, reader.source);
220
+ if (whole && reader.imported)
221
+ this.unimport(reader.imported, reader.source);
222
+ if (!held.every((use) => use !== undefined) || reader.passesOn)
223
+ kept = true;
224
+ });
225
+ if (!kept)
226
+ this.cut.set(named.statement, named.source);
227
+ return true;
228
+ }
229
+ /** How many profiles a file defines. */
230
+ definedIn(source) {
231
+ let count = 0;
232
+ for (const targets of this.project.profiles.values())
233
+ count += targets.filter((target) => target.source === source).length;
234
+ return count;
235
+ }
236
+ /** An import's name goes, and the import with it when that was all it brought in. */
237
+ unimport(imported, source) {
238
+ if (ts.isImportDeclaration(imported)) {
239
+ this.cut.set(imported, source);
240
+ return;
241
+ }
242
+ this.cut.set(imported, source);
243
+ const names = imported.parent;
244
+ const statement = names.parent.parent;
245
+ if (!ts.isImportDeclaration(statement))
246
+ return;
247
+ const alone = !statement.importClause?.name && names.elements.every((element) => this.cut.has(element));
248
+ if (alone)
249
+ this.cut.set(statement, source);
250
+ }
251
+ /**
252
+ * Takes out a profile `register` registers: the statement that registers it where it is written,
253
+ * or its named definition and each statement that registers the name. True when it went; a way of
254
+ * registering the studio cannot follow is noted instead.
255
+ */
256
+ defined(id, register) {
257
+ const kind = 'profile';
258
+ const targets = this.project.profiles.get(id) ?? [];
259
+ const [target] = targets;
260
+ const unfollowed = (place) => {
261
+ this.note(kind, id, 'removed', place);
262
+ return false;
263
+ };
264
+ if (!target)
265
+ return unfollowed();
266
+ const at = { node: target.options, source: target.source };
267
+ // Written twice: the studio cannot tell which one runs.
268
+ if (targets.length > 1)
269
+ return unfollowed(at);
270
+ const defined = wrapped(target.options).parent;
271
+ const outer = wrapped(defined).parent;
272
+ // Registered where it is written: with its `define` call inside the call, or without it.
273
+ const registers = [defined, outer].find((call) => ts.isCallExpression(call) && calleeName(call) === register);
274
+ const inline = registers && statementOf(registers);
275
+ const named = inline ? undefined : declared(defined, target.source);
276
+ if (inline)
277
+ this.cut.set(inline, target.source);
278
+ else if (!named || !this.named(named))
279
+ return unfollowed(at);
280
+ this.homes.add(target.source);
281
+ this.note(kind, id, 'written', at);
282
+ return true;
283
+ }
284
+ profile(id) {
285
+ if (this.defined(id, 'registerProfile'))
286
+ this.unasked(id);
287
+ }
288
+ provider(id) {
289
+ // Registered under a name, it goes with each statement that reads the name.
290
+ this.registration('provider', id, this.project.providers, (target) => wrapped(target.options).parent);
291
+ }
292
+ /** A removed decision's entries in the setup's `questions` and `images`, under its id. */
293
+ unasked(id) {
294
+ for (const source of this.project.files.values()) {
295
+ for (const name of SETUP_EXPORTS) {
296
+ const held = setupExport(source, name)?.initializer;
297
+ const named = held && unwrapped(held);
298
+ if (!named || !ts.isObjectLiteralExpression(named))
299
+ continue;
300
+ const entry = named.properties.find((property) => propertyName(property) === id);
301
+ if (entry)
302
+ this.cut.set(entry, source);
303
+ }
304
+ }
305
+ }
306
+ tool(name) {
307
+ // Written as a constant: it goes with each statement that registers it.
308
+ this.registration('tool', name, this.project.tools, (target) => target.options);
309
+ }
310
+ /**
311
+ * Takes out the call that registers a tool or a provider. A function that only makes the call
312
+ * goes with its calls; one nothing here calls is the setup's own, and keeps its name. A call that
313
+ * is not a statement of its own goes with the name `named` gives it, and each statement that reads it.
314
+ */
315
+ registration(kind, id, held, named) {
316
+ const targets = held.get(id) ?? [];
317
+ const [target] = targets;
318
+ if (!target)
319
+ return this.note(kind, id, 'removed');
320
+ const at = { node: target.options, source: target.source };
321
+ if (targets.length > 1)
322
+ return this.note(kind, id, 'removed', at);
323
+ const statement = statementOf(wrapped(target.options).parent);
324
+ if (statement) {
325
+ const register = wholeBodyOf(statement, target.source);
326
+ if (!register || !this.named(register))
327
+ this.cut.set(statement, target.source);
328
+ }
329
+ else {
330
+ const name = declared(named(target), target.source);
331
+ if (!name || !this.named(name))
332
+ return this.note(kind, id, 'removed', at);
333
+ }
334
+ this.homes.add(target.source);
335
+ this.note(kind, id, 'written', at);
336
+ }
337
+ within(part) {
338
+ for (let at = part.parent; at; at = at.parent)
339
+ if (this.cut.has(at))
340
+ return true;
341
+ return false;
342
+ }
343
+ /**
344
+ * A file that defined what was removed and that the project no longer reads: nothing imports it
345
+ * now, and all that is left in it are declarations. Each one it exports was read in the setup, and
346
+ * only by what is cut. An export the setup never reads, which a test or a server may import, or a
347
+ * statement that runs, keeps the file.
348
+ */
349
+ isGone(source) {
350
+ if (source.fileName === this.project.entry || !this.homes.has(source))
351
+ return false;
352
+ for (const { statement } of importsOf(this.project, source))
353
+ if (!this.cut.has(statement))
354
+ return false;
355
+ const own = source.statements.filter((statement) => !ts.isImportDeclaration(statement));
356
+ const left = own.filter((statement) => !this.cut.has(statement));
357
+ return (own.length > left.length &&
358
+ left.every((statement) => {
359
+ const names = declaredNames(statement);
360
+ if (!names)
361
+ return false;
362
+ if (!isExported(statement))
363
+ return true;
364
+ return names.every((name) => this.readOnlyByCut({ name, source, statement }));
365
+ }));
366
+ }
367
+ /** Whether the setup reads `named`, and only in what is cut. */
368
+ readOnlyByCut(named) {
369
+ const readers = readersOf(this.project, named);
370
+ const reads = readers.flatMap((reader) => reader.reads);
371
+ return (!readers.some((reader) => reader.passesOn) &&
372
+ reads.length > 0 &&
373
+ reads.every((read) => this.isCut(read)));
374
+ }
375
+ isCut(node) {
376
+ for (let at = node; at; at = at.parent)
377
+ if (this.cut.has(at))
378
+ return true;
379
+ return false;
380
+ }
381
+ /** An import of a file only for what running it registers goes when the file registers nothing now. */
382
+ unrun() {
383
+ for (const home of this.homes) {
384
+ const own = home.statements.filter((statement) => !ts.isImportDeclaration(statement));
385
+ if (!own.length || !own.every((statement) => this.cut.has(statement)))
386
+ continue;
387
+ for (const { source, statement } of importsOf(this.project, home)) {
388
+ if (ts.isImportDeclaration(statement) && !statement.importClause)
389
+ this.cut.set(statement, source);
390
+ }
391
+ }
392
+ }
393
+ build() {
394
+ this.unrun();
395
+ const gone = [...this.project.files.values()].filter((source) => this.isGone(source));
396
+ const parts = new Map();
397
+ for (const [part, source] of this.cut) {
398
+ if (gone.includes(source) || this.within(part))
399
+ continue;
400
+ parts.set(source, [...(parts.get(source) ?? []), part]);
401
+ }
402
+ const edits = [...parts].flatMap(([source, held]) => cutsOf(held, source).map(({ start, end }) => ({ file: source.fileName, start, end, text: '' })));
403
+ return { changes: this.changes, edits, gone: gone.map((source) => source.fileName) };
404
+ }
405
+ }
406
+ /** The names a top-level declaration declares, or undefined for a statement that is not one. */
407
+ function declaredNames(statement) {
408
+ if (ts.isVariableStatement(statement)) {
409
+ const names = statement.declarationList.declarations.map((each) => ts.isIdentifier(each.name) ? each.name.text : undefined);
410
+ return names.every((name) => name !== undefined) ? names : undefined;
411
+ }
412
+ const declares = ts.isFunctionDeclaration(statement) ||
413
+ ts.isClassDeclaration(statement) ||
414
+ ts.isInterfaceDeclaration(statement) ||
415
+ ts.isTypeAliasDeclaration(statement) ||
416
+ ts.isEnumDeclaration(statement);
417
+ return declares && statement.name ? [statement.name.text] : undefined;
418
+ }
419
+ function isExported(statement) {
420
+ return (ts.canHaveModifiers(statement) &&
421
+ (ts
422
+ .getModifiers(statement)
423
+ ?.some((modifier) => modifier.kind === ts.SyntaxKind.ExportKeyword) ??
424
+ false));
425
+ }
426
+ const BLANK = /^[ \t]*$/;
427
+ /** The comments right above a part, with no blank line between: they are about it, and go with it. */
428
+ function withComments(part, source) {
429
+ let start = part.getStart(source);
430
+ const comments = ts.getLeadingCommentRanges(source.text, part.getFullStart()) ?? [];
431
+ for (const comment of comments.toReversed()) {
432
+ const between = source.text.slice(comment.end, start);
433
+ if (between.trim() !== '' || between.split('\n').length > 2)
434
+ break;
435
+ start = comment.pos;
436
+ }
437
+ return start;
438
+ }
439
+ /** The lines a part fills, when nothing else is written on them. A listed part's comma is its own. */
440
+ function ownLines(part, source) {
441
+ const { text } = source;
442
+ const start = withComments(part, source);
443
+ const end = !ts.isStatement(part) && text[part.end] === ',' ? part.end + 1 : part.end;
444
+ const lineStart = text.lastIndexOf('\n', start - 1) + 1;
445
+ const next = text.indexOf('\n', end);
446
+ const lineEnd = next === -1 ? text.length : next;
447
+ if (!BLANK.test(text.slice(lineStart, start)) || !BLANK.test(text.slice(end, lineEnd)))
448
+ return undefined;
449
+ return { start: lineStart, end: next === -1 ? text.length : next + 1, lines: true };
450
+ }
451
+ /** The list a part is one entry of: an object's properties, or an import's names. */
452
+ function listOf(part) {
453
+ if (ts.isImportSpecifier(part))
454
+ return part.parent.elements;
455
+ if (ts.isStatement(part))
456
+ return undefined;
457
+ return ts.isObjectLiteralExpression(part.parent) ? part.parent.properties : undefined;
458
+ }
459
+ /**
460
+ * The cut for entries that share their line with others: up to the entry that follows them, or
461
+ * back to the one before when they are last, so the commas left are the ones the list needs.
462
+ */
463
+ function inList(list, first, last, source) {
464
+ const [from, to, after, before] = [list[first], list[last], list[last + 1], list[first - 1]];
465
+ if (!from || !to)
466
+ throw new Error('A cut names an entry its list does not hold.');
467
+ if (after)
468
+ return { start: from.getStart(source), end: after.getStart(source), lines: false };
469
+ if (before)
470
+ return { start: before.end, end: to.end, lines: false };
471
+ const end = source.text[to.end] === ',' ? to.end + 1 : to.end;
472
+ return { start: from.getStart(source), end, lines: false };
473
+ }
474
+ /** One blank line stays between what was above a cut and what was below it, not two. */
475
+ function closed(cut, text) {
476
+ if (!cut.lines)
477
+ return cut;
478
+ const above = cut.start === 0 ||
479
+ BLANK.test(text.slice(text.lastIndexOf('\n', cut.start - 2) + 1, cut.start - 1));
480
+ const next = text.indexOf('\n', cut.end);
481
+ const below = next !== -1 && BLANK.test(text.slice(cut.end, next));
482
+ return above && below ? { ...cut, end: next + 1 } : cut;
483
+ }
484
+ /** What to take out of one file for the parts cut from it: no two cuts touch. */
485
+ function cutsOf(parts, source) {
486
+ const cuts = [];
487
+ const listed = new Map();
488
+ for (const part of parts) {
489
+ const own = ownLines(part, source);
490
+ const list = own ? undefined : listOf(part);
491
+ if (own)
492
+ cuts.push(own);
493
+ else if (list)
494
+ listed.set(list, [...(listed.get(list) ?? []), part]);
495
+ else
496
+ cuts.push({ start: withComments(part, source), end: part.end, lines: false });
497
+ }
498
+ for (const [list, held] of listed) {
499
+ const at = held.map((part) => list.indexOf(part)).sort((a, b) => a - b);
500
+ for (let index = 0; index < at.length; index++) {
501
+ const first = at[index] ?? 0;
502
+ while (at[index + 1] === (at[index] ?? 0) + 1)
503
+ index++;
504
+ cuts.push(inList(list, first, at[index] ?? first, source));
505
+ }
506
+ }
507
+ cuts.sort((a, b) => a.start - b.start);
508
+ const joined = [];
509
+ for (const cut of cuts) {
510
+ const last = joined.at(-1);
511
+ if (last && cut.start <= last.end)
512
+ last.end = Math.max(last.end, cut.end);
513
+ else
514
+ joined.push({ ...cut });
515
+ }
516
+ return joined.map((cut) => closed(cut, source.text));
517
+ }
518
+ /** Plans the removal of each profile, tool, and provider the studio took away. */
519
+ export function planRemoved(project, removed) {
520
+ const removal = new Removal(project);
521
+ for (const id of removed.profiles)
522
+ removal.profile(id);
523
+ for (const name of removed.tools)
524
+ removal.tool(name);
525
+ for (const id of removed.providers)
526
+ removal.provider(id);
527
+ return removal.build();
528
+ }
@@ -0,0 +1,96 @@
1
+ /**
2
+ * Save for one open project: the review of what would change, the write with
3
+ * its three proofs, and the undo. It reaches the disk and the project's process
4
+ * only through the host it is given, so the rules can be run without either.
5
+ *
6
+ * @module
7
+ */
8
+ import type { ReadStep } from '../read-steps.ts';
9
+ import type { StudioWorkspace } from '../workspace.ts';
10
+ import { type ProjectSource } from './project-source.ts';
11
+ import { type ProjectNames } from './save.ts';
12
+ import type { ProjectOrigins, ProviderPlace, SaveDone, SaveRefusal, SaveRequest, SaveReview, SharedSetting, Unregistered } from './save-wire.ts';
13
+ /** What Save needs from the machine. `Loaded` is one load of the project. */
14
+ export interface SaveHost<Loaded> {
15
+ /** The folder Save may write in. */
16
+ root: string;
17
+ /** The project's setup module, inside `root`. */
18
+ setupFile: string;
19
+ /** A project file's text, or undefined when it is missing or leads outside the project. */
20
+ read(path: string): string | undefined;
21
+ /** Whether a write to this path lands inside `root`: no link on the way, or at it, leads out. */
22
+ landsInside(path: string): boolean;
23
+ /** Writes a file, with the folders that lead to it. */
24
+ write(path: string, text: string): void;
25
+ /** Takes away a file: one Save created, or one a removal left with nothing of its own. */
26
+ remove(path: string): void;
27
+ /** Whether the project type-checks as it is on disk, and what the checker printed. */
28
+ typeChecks(): Promise<{
29
+ ok: boolean;
30
+ output: string;
31
+ }>;
32
+ /** Loads the project from disk. Throws what it printed when it does not start. */
33
+ load(): Promise<Loaded>;
34
+ stop(loaded: Loaded): Promise<void>;
35
+ /** The workspace a load opened as. */
36
+ opened(loaded: Loaded): StudioWorkspace;
37
+ }
38
+ /** What one read of the project's files says. Each file is named from the project's folder. */
39
+ export interface FilesRead {
40
+ /** The project's shared settings. */
41
+ shared: SharedSetting[];
42
+ /** The settings the files set in code. */
43
+ origins: ProjectOrigins;
44
+ /** The profiles and tools the files define that the project did not register. */
45
+ unregistered: Unregistered[];
46
+ /** Where the files define each provider the project registered. */
47
+ providerPlaces: ProviderPlace[];
48
+ /** What the project printed when the files did not load. */
49
+ unloaded?: string;
50
+ }
51
+ /** Save for one project, and the load of it that answers requests now. */
52
+ export interface SaveSession<Loaded> {
53
+ project(): Loaded;
54
+ /** The absolute path of a file named from the project's folder, when the project's setup reads it. */
55
+ place(file: string): string | undefined;
56
+ /** The review when the request has no stamp; the write when it has the review's. */
57
+ save(request: SaveRequest): Promise<SaveReview | SaveDone | SaveRefusal>;
58
+ /** Puts the last Save's files back, when they still hold what it wrote. */
59
+ undo(): Promise<SaveDone | SaveRefusal>;
60
+ /**
61
+ * What the project's files say now, from one read of them. Loads the project again first when
62
+ * they changed outside the studio; when they do not load, the last load that did answers
63
+ * requests until they do. `said` hears each step of the read as it happens.
64
+ */
65
+ read(said?: (step: ReadStep) => void): Promise<FilesRead>;
66
+ /** Every file the project's setup reads, by absolute path. */
67
+ watched(): string[];
68
+ /**
69
+ * The files that hold something other than what the load that answers was read from, each from
70
+ * the project's folder. None after a Save or an undo: those are the studio's own writes.
71
+ */
72
+ changed(): Promise<string[]>;
73
+ }
74
+ /** Why nothing was done, with what to show for it. */
75
+ export declare const refusal: (reason: SaveRefusal["reason"], detail?: string[]) => SaveRefusal;
76
+ /** What a thrown value says. */
77
+ export declare const message: (error: unknown) => string;
78
+ /** A name for a value that changes when the value does. */
79
+ export declare function stampOf(value: unknown): Promise<string>;
80
+ /** Whether a body is a Save request, or one for the edited load: a workspace with its starts. */
81
+ export declare function isSaveRequest(body: unknown): body is SaveRequest;
82
+ /**
83
+ * What Save answers a request with, as a status and a body: the review or the write at `base`, and
84
+ * the undo at `base/undo`. Undefined when the request is not Save's.
85
+ */
86
+ export declare function answerSave<Loaded>(session: Pick<SaveSession<Loaded>, 'save' | 'undo'>, base: string, request: Request): Promise<{
87
+ status: number;
88
+ body: unknown;
89
+ } | undefined>;
90
+ /**
91
+ * A project's origins as the page reads them: each file from the project's folder, and each
92
+ * profile and tool the project registers that no file defines marked as one the studio cannot find.
93
+ */
94
+ export declare function pageOrigins(found: ProjectOrigins, names: ProjectNames, source: Pick<ProjectSource, 'profiles' | 'tools' | 'providers'>, inRoot: (file: string) => string): ProjectOrigins;
95
+ /** Starts Save for a project that `first` loaded. */
96
+ export declare function createSaveSession<Loaded>(host: SaveHost<Loaded>, first: Loaded): SaveSession<Loaded>;