@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
package/read-source.js ADDED
@@ -0,0 +1,1301 @@
1
+ /**
2
+ * The inverse of `studioSource`: the file it prints, read back into the draft
3
+ * the form stores. Plain values come back as themselves. The printer's own
4
+ * wrappers (`z.fromJSONSchema`, a canned `handler`, `compileDetect`, `.join('\\n')`)
5
+ * come back through the same shapes that printer writes. Anything else is an
6
+ * error at that spot, and the draft is left alone.
7
+ */
8
+ import { DEFAULT_ALLOW_CONTINUE, DEFAULT_AUTO_CONTINUE, liveIngressChannelDefault, } from '@theoremjs/agents';
9
+ import { BOUNDARIES, DETECTORS, recordOf, } from '@theoremjs/agents/guardrails';
10
+ import { PROFILE_GRAPH } from '@theoremjs/agents/kernel';
11
+ import { CONTEXT_SENDERS, fieldMeta, } from '@theoremjs/agents/schema';
12
+ import { canonical } from "./canonical.js";
13
+ import { createBlankDraft, defaultModelBinding, defaultToolSpec, draftKey, INLINE_LABELS, STUDIO_PROFILE_TYPES, } from "./draft.js";
14
+ import { definitionFactory, definitionOfFactory, kernelDefinitions, } from "./providers.js";
15
+ import { stubOutputFromSchema } from "./stub.js";
16
+ import { STUDIO_TOOL_TYPE_MESSAGE, STUDIO_TOOL_TYPES } from "./types.js";
17
+ class ReadFail extends Error {
18
+ line;
19
+ column;
20
+ constructor(message, line, column) {
21
+ super(message);
22
+ this.line = line;
23
+ this.column = column;
24
+ }
25
+ }
26
+ class Src {
27
+ text;
28
+ of;
29
+ i = 0;
30
+ line = 1;
31
+ column = 1;
32
+ /** A provider's file holds its definition and nothing else; an agent's file holds no provider. */
33
+ constructor(text, of = 'profile') {
34
+ this.text = text;
35
+ this.of = of;
36
+ }
37
+ get done() {
38
+ return this.i >= this.text.length;
39
+ }
40
+ pos() {
41
+ return { line: this.line, column: this.column };
42
+ }
43
+ fail(message) {
44
+ throw new ReadFail(message, this.line, this.column);
45
+ }
46
+ peek(n = 0) {
47
+ return this.text[this.i + n] ?? '';
48
+ }
49
+ bump() {
50
+ const ch = this.text[this.i] ?? '';
51
+ this.i += 1;
52
+ if (ch === '\n') {
53
+ this.line += 1;
54
+ this.column = 1;
55
+ }
56
+ else {
57
+ this.column += 1;
58
+ }
59
+ return ch;
60
+ }
61
+ skip() {
62
+ for (;;) {
63
+ const ch = this.peek();
64
+ if (ch === ' ' || ch === '\t' || ch === '\n' || ch === '\r' || ch === '\ufeff') {
65
+ this.bump();
66
+ continue;
67
+ }
68
+ if (ch === '/' && this.peek(1) === '/') {
69
+ while (!this.done && this.peek() !== '\n')
70
+ this.bump();
71
+ continue;
72
+ }
73
+ if (ch === '/' && this.peek(1) === '*') {
74
+ this.bump();
75
+ this.bump();
76
+ while (!this.done && !(this.peek() === '*' && this.peek(1) === '/'))
77
+ this.bump();
78
+ if (this.done)
79
+ this.fail('This comment never closes.');
80
+ this.bump();
81
+ this.bump();
82
+ continue;
83
+ }
84
+ return;
85
+ }
86
+ }
87
+ starts(token) {
88
+ this.skip();
89
+ return this.text.startsWith(token, this.i);
90
+ }
91
+ eat(token) {
92
+ if (!this.starts(token))
93
+ return false;
94
+ for (let n = 0; n < token.length; n += 1)
95
+ this.bump();
96
+ return true;
97
+ }
98
+ expect(token) {
99
+ if (!this.eat(token))
100
+ this.fail(`Expected '${token}'.`);
101
+ }
102
+ /** The next identifier, or `undefined` when the next token is something else. */
103
+ ident() {
104
+ this.skip();
105
+ const ch = this.peek();
106
+ if (!/^[A-Za-z_$]/.test(ch))
107
+ return undefined;
108
+ let name = '';
109
+ while (/^[A-Za-z0-9_$]/.test(this.peek()))
110
+ name += this.bump();
111
+ return name;
112
+ }
113
+ expectIdent() {
114
+ const name = this.ident();
115
+ if (name === undefined)
116
+ this.fail('Expected a name.');
117
+ return name;
118
+ }
119
+ /** The next identifier, without consuming it. */
120
+ peekIdent() {
121
+ this.skip();
122
+ return /^[A-Za-z_$][A-Za-z0-9_$]*/.exec(this.text.slice(this.i))?.[0];
123
+ }
124
+ /** The text from the next token, for a short lookahead. */
125
+ rest() {
126
+ this.skip();
127
+ return this.text.slice(this.i);
128
+ }
129
+ }
130
+ function isRecord(value) {
131
+ return value !== null && typeof value === 'object' && !Array.isArray(value);
132
+ }
133
+ function parseString(src) {
134
+ src.skip();
135
+ const quote = src.peek();
136
+ if (quote !== "'" && quote !== '"')
137
+ src.fail('Expected a string.');
138
+ src.bump();
139
+ let out = '';
140
+ while (!src.done && src.peek() !== quote) {
141
+ const ch = src.bump();
142
+ if (ch !== '\\') {
143
+ out += ch;
144
+ continue;
145
+ }
146
+ const esc = src.bump();
147
+ const simple = {
148
+ n: '\n',
149
+ r: '\r',
150
+ t: '\t',
151
+ '\\': '\\',
152
+ "'": "'",
153
+ '"': '"',
154
+ };
155
+ if (esc in simple) {
156
+ out += simple[esc];
157
+ continue;
158
+ }
159
+ if (esc === 'u') {
160
+ let hex = '';
161
+ for (let n = 0; n < 4; n += 1)
162
+ hex += src.bump();
163
+ out += String.fromCharCode(Number.parseInt(hex, 16));
164
+ continue;
165
+ }
166
+ out += esc;
167
+ }
168
+ if (src.peek() !== quote)
169
+ src.fail('This string never closes.');
170
+ src.bump();
171
+ return out;
172
+ }
173
+ function parseNumber(src) {
174
+ src.skip();
175
+ const start = src.pos();
176
+ let raw = '';
177
+ if (src.peek() === '-')
178
+ raw += src.bump();
179
+ while (/^[0-9.eE+-]/.test(src.peek()) && raw.length < 64)
180
+ raw += src.bump();
181
+ const value = Number(raw);
182
+ if (!Number.isFinite(value)) {
183
+ throw new ReadFail(`'${raw}' is not a number.`, start.line, start.column);
184
+ }
185
+ return value;
186
+ }
187
+ /** Skip `satisfies …` or `as …` up to the end of the statement. */
188
+ /** Skips to where `ended` says so, outside every bracket. A string is skipped whole. */
189
+ function skipBalanced(src, open, close, ended) {
190
+ let depth = 0;
191
+ while (!src.done) {
192
+ const end = ended();
193
+ if (end && depth === 0)
194
+ return;
195
+ const ch = src.peek();
196
+ if (ch === "'" || ch === '"') {
197
+ parseString(src);
198
+ continue;
199
+ }
200
+ if (ch !== '' && open.includes(ch))
201
+ depth += 1;
202
+ else if (ch !== '' && close.includes(ch))
203
+ depth -= 1;
204
+ src.bump();
205
+ }
206
+ }
207
+ function skipTypeClause(src) {
208
+ skipBalanced(src, '<([{', '>)]}', () => {
209
+ src.skip();
210
+ return src.peek() === ';' || src.peek() === '\n';
211
+ });
212
+ }
213
+ function skipImport(src) {
214
+ skipBalanced(src, '{([', '})]', () => src.peek() === ';');
215
+ if (src.peek() === ';')
216
+ src.bump();
217
+ }
218
+ function parseObject(src, path, spans) {
219
+ src.expect('{');
220
+ const out = {};
221
+ while (!src.eat('}')) {
222
+ if (src.eat('...'))
223
+ src.fail("This file doesn't use spreads.");
224
+ const at = src.pos();
225
+ let key;
226
+ if (src.peek() === "'" || src.peek() === '"')
227
+ key = parseString(src);
228
+ else
229
+ key = src.expectIdent();
230
+ // JavaScript sets an object's prototype from `__proto__`, and TypeScript refuses a key set twice.
231
+ if (key === '__proto__') {
232
+ throw new ReadFail("'__proto__' sets what an object inherits, not a setting.", at.line, at.column);
233
+ }
234
+ if (Object.hasOwn(out, key))
235
+ throw new ReadFail(`'${key}' is set twice.`, at.line, at.column);
236
+ const next = path ? `${path}.${key}` : key;
237
+ spans.push({ path: next, line: at.line, column: at.column });
238
+ src.expect(':');
239
+ out[key] = parseValue(src, next, spans);
240
+ src.eat(',');
241
+ if (src.done)
242
+ src.fail('This object never closes.');
243
+ }
244
+ return out;
245
+ }
246
+ function parseArray(src, path, spans) {
247
+ src.expect('[');
248
+ const out = [];
249
+ let index = 0;
250
+ while (!src.eat(']')) {
251
+ if (src.eat('...'))
252
+ src.fail("This file doesn't use spreads.");
253
+ src.skip();
254
+ const at = src.pos();
255
+ const itemPath = path ? `${path}.${String(index)}` : String(index);
256
+ spans.push({ path: itemPath, line: at.line, column: at.column });
257
+ out.push(parseValue(src, itemPath, spans));
258
+ index += 1;
259
+ src.eat(',');
260
+ if (src.done)
261
+ src.fail('This array never closes.');
262
+ }
263
+ return out;
264
+ }
265
+ function zodSchema(head, args, src) {
266
+ const [schema] = args;
267
+ if (head !== 'z.fromJSONSchema') {
268
+ src.fail(`The studio reads a schema as JSON Schema: z.fromJSONSchema({ ... }), not '${head}'.`);
269
+ }
270
+ if (!isRecord(schema))
271
+ src.fail('z.fromJSONSchema() needs a schema.');
272
+ return schema;
273
+ }
274
+ function isMember(value) {
275
+ return isRecord(value) && value.kind === 'member';
276
+ }
277
+ function asMember(object, name) {
278
+ return { kind: 'member', object, name };
279
+ }
280
+ function memberHead(value) {
281
+ if (typeof value.object === 'string')
282
+ return `${value.object}.${value.name}`;
283
+ if (isMember(value.object)) {
284
+ const parent = memberHead(value.object);
285
+ return parent ? `${parent}.${value.name}` : undefined;
286
+ }
287
+ return undefined;
288
+ }
289
+ function objectArg(args, src, message) {
290
+ const value = args[0];
291
+ if (!isRecord(value))
292
+ src.fail(message);
293
+ return value;
294
+ }
295
+ function registerToolCall(args, src, spans) {
296
+ const tool = objectArg(args, src, 'registerTool() needs the tool object.');
297
+ const type = tool.type;
298
+ const known = typeof type === 'string' && STUDIO_TOOL_TYPES.includes(type);
299
+ if (type !== undefined && !known) {
300
+ const at = spans.findLast((span) => span.path === 'type') ?? src.pos();
301
+ throw new ReadFail(STUDIO_TOOL_TYPE_MESSAGE, at.line, at.column);
302
+ }
303
+ return { kind: 'registerTool', tool };
304
+ }
305
+ function namedCall(callee, args, src, spans) {
306
+ if (src.of === 'provider') {
307
+ if (callee !== 'registerProvider')
308
+ return src.fail(`'${callee}' isn't part of a provider's code.`);
309
+ const [definition, spec = {}] = args;
310
+ if (typeof definition !== 'string')
311
+ src.fail('registerProvider() needs the definition it registers from.');
312
+ if (!isRecord(spec) || args.length > 2)
313
+ src.fail('registerProvider() takes the definition and its settings.');
314
+ return { kind: 'provider', definition, spec };
315
+ }
316
+ if (callee === 'compileDetect') {
317
+ return objectArg(args, src, 'compileDetect() needs the detect object.');
318
+ }
319
+ if (callee === 'defineProfile') {
320
+ return objectArg(args, src, 'defineProfile() needs the profile object.');
321
+ }
322
+ if (callee === 'registerTool')
323
+ return registerToolCall(args, src, spans);
324
+ if (callee === 'registerStructured')
325
+ return { kind: 'registerStructured', args };
326
+ if (callee === 'registerProfile' || callee === 'registerProvider')
327
+ return { kind: callee };
328
+ return src.fail(`'${callee}' isn't part of this file.`);
329
+ }
330
+ function joinedLines(parts, sep, src) {
331
+ if (typeof sep !== 'string' || parts.some((part) => typeof part !== 'string')) {
332
+ src.fail('.join() here joins lines of one string.');
333
+ }
334
+ return parts.join(sep);
335
+ }
336
+ function memberCall(callee, args, src) {
337
+ if (callee.name === 'join' && Array.isArray(callee.object)) {
338
+ return joinedLines(callee.object, args[0], src);
339
+ }
340
+ if (callee.name === 'resolve' && callee.object === 'Promise')
341
+ return args[0];
342
+ const head = memberHead(callee);
343
+ if (head?.startsWith('z.'))
344
+ return zodSchema(head, args, src);
345
+ return src.fail("This call isn't part of this file.");
346
+ }
347
+ function callExpr(callee, args, src, spans) {
348
+ if (typeof callee === 'string')
349
+ return namedCall(callee, args, src, spans);
350
+ if (!isMember(callee))
351
+ src.fail("This call isn't part of this file.");
352
+ return memberCall(callee, args, src);
353
+ }
354
+ function looksLikeArrow(src) {
355
+ return /^(async\s*)?\(\s*\)\s*=>/.test(src.rest());
356
+ }
357
+ function parseArrow(src, path, spans) {
358
+ if (src.peekIdent() === 'async')
359
+ src.expectIdent();
360
+ src.expect('(');
361
+ if (!src.eat(')'))
362
+ src.fail('A handler here takes no arguments. It returns a fixed value.');
363
+ src.expect('=>');
364
+ return parseValue(src, path, spans);
365
+ }
366
+ /** A name as written: what is called or read from, or, standing alone, a value set elsewhere. */
367
+ class Name {
368
+ name;
369
+ constructor(name) {
370
+ this.name = name;
371
+ }
372
+ }
373
+ /** `value`, with a name in it read as the text of the name. */
374
+ function named(value) {
375
+ return value instanceof Name ? value.name : value;
376
+ }
377
+ function parseExpr(src, path, spans) {
378
+ if (looksLikeArrow(src))
379
+ return parseArrow(src, path, spans);
380
+ return parsePostfix(parseAtom(src, path, spans), src, path, spans);
381
+ }
382
+ function parseAtom(src, path, spans) {
383
+ src.skip();
384
+ const ch = src.peek();
385
+ if (ch === "'" || ch === '"')
386
+ return parseString(src);
387
+ if (ch === '`')
388
+ src.fail("This file doesn't use template strings.");
389
+ if (ch === '-' || /^[0-9]/.test(ch))
390
+ return parseNumber(src);
391
+ if (ch === '{')
392
+ return parseObject(src, path, spans);
393
+ if (ch === '[')
394
+ return parseArray(src, path, spans);
395
+ if (ch === '(') {
396
+ src.bump();
397
+ const inner = parseExpr(src, path, spans);
398
+ src.expect(')');
399
+ return inner;
400
+ }
401
+ const name = src.ident();
402
+ if (name === 'true')
403
+ return true;
404
+ if (name === 'false')
405
+ return false;
406
+ if (name === 'null')
407
+ return null;
408
+ if (name === undefined)
409
+ src.fail('Expected a value.');
410
+ return new Name(name);
411
+ }
412
+ /**
413
+ * A setting's value, as written in an object or a list. A name standing alone there is a value
414
+ * written somewhere else, which this file does not show; `undefined` is no value.
415
+ */
416
+ function parseValue(src, path, spans) {
417
+ src.skip();
418
+ const at = src.pos();
419
+ const value = parseExpr(src, path, spans);
420
+ if (!(value instanceof Name))
421
+ return value;
422
+ if (value.name === 'undefined')
423
+ return undefined;
424
+ throw new ReadFail(`'${value.name}' is set somewhere else. Write its value here.`, at.line, at.column);
425
+ }
426
+ function parsePostfix(value, src, path, spans) {
427
+ let current = value;
428
+ for (;;) {
429
+ if (src.eat('.')) {
430
+ const name = src.expectIdent();
431
+ current = asMember(named(current), name);
432
+ continue;
433
+ }
434
+ if (src.eat('(')) {
435
+ const from = spans.length;
436
+ const args = [];
437
+ while (!src.eat(')')) {
438
+ args.push(named(parseExpr(src, path, spans)));
439
+ src.eat(',');
440
+ if (src.done)
441
+ src.fail('This call never closes.');
442
+ }
443
+ current = callExpr(named(current), args, src, spans.slice(from));
444
+ continue;
445
+ }
446
+ if (isMember(current))
447
+ src.fail("This file doesn't stop on a property.");
448
+ return current;
449
+ }
450
+ }
451
+ function readConst(src, parsed) {
452
+ src.expectIdent();
453
+ const name = src.expectIdent();
454
+ src.expect('=');
455
+ const value = parseExpr(src, '', parsed.spans);
456
+ if (src.eat('satisfies') || src.eat('as'))
457
+ skipTypeClause(src);
458
+ src.eat(';');
459
+ if (src.of === 'provider') {
460
+ src.fail("A provider's code is its registerProvider() call and nothing else.");
461
+ }
462
+ else if (name === 'profile') {
463
+ if (!isRecord(value))
464
+ src.fail('profile has to be the defineProfile() object.');
465
+ if (parsed.profile)
466
+ src.fail('This file defines two profiles.');
467
+ parsed.profile = value;
468
+ }
469
+ else if (name === 'questions') {
470
+ if (!isRecord(value))
471
+ src.fail('questions has to be an object.');
472
+ parsed.questions = value;
473
+ }
474
+ else if (name === 'images') {
475
+ if (!isRecord(value))
476
+ src.fail('images has to be an object.');
477
+ parsed.images = value;
478
+ }
479
+ }
480
+ function readCall(src, parsed) {
481
+ const value = parseExpr(src, '', parsed.spans);
482
+ src.eat(';');
483
+ if (!isRecord(value))
484
+ return;
485
+ if (value.kind === 'provider' && typeof value.definition === 'string' && isRecord(value.spec)) {
486
+ if (parsed.provider)
487
+ src.fail('This code registers two providers.');
488
+ parsed.provider = { definition: value.definition, spec: value.spec };
489
+ return;
490
+ }
491
+ if (value.kind === 'registerTool') {
492
+ const tool = value.tool;
493
+ if (!isRecord(tool))
494
+ src.fail('registerTool() needs the tool object.');
495
+ parsed.tools.push(tool);
496
+ }
497
+ else if (value.kind === 'registerStructured') {
498
+ const args = Array.isArray(value.args) ? value.args : [];
499
+ const [id, spec] = args;
500
+ if (typeof id !== 'string' || !isRecord(spec)) {
501
+ src.fail('registerStructured() needs an id and a spec.');
502
+ }
503
+ parsed.structured = { id, spec };
504
+ }
505
+ }
506
+ function parseModule(text, of = 'profile') {
507
+ const src = new Src(text, of);
508
+ const parsed = { tools: [], spans: [] };
509
+ for (src.skip(); !src.done; src.skip()) {
510
+ if (src.peekIdent() === 'import') {
511
+ src.expectIdent();
512
+ skipImport(src);
513
+ continue;
514
+ }
515
+ if (src.peekIdent() === 'export')
516
+ src.expectIdent();
517
+ if (src.peekIdent() === 'const')
518
+ readConst(src, parsed);
519
+ else
520
+ readCall(src, parsed);
521
+ }
522
+ if (of === 'provider') {
523
+ if (!parsed.provider)
524
+ src.fail('This code needs registerProvider().');
525
+ }
526
+ else if (!parsed.profile)
527
+ src.fail('This file needs defineProfile().');
528
+ return parsed;
529
+ }
530
+ function text(value, fallback = '') {
531
+ return typeof value === 'string' ? value : fallback;
532
+ }
533
+ function whole(value) {
534
+ return typeof value === 'number' ? value : null;
535
+ }
536
+ function markup(value, srcMessage) {
537
+ if (value === undefined)
538
+ return '';
539
+ if (typeof value === 'string')
540
+ return value;
541
+ if (!Array.isArray(value))
542
+ throw new ReadFail(srcMessage, 1, 1);
543
+ return value
544
+ .map((part) => {
545
+ if (typeof part === 'string')
546
+ return part;
547
+ if (isRecord(part) && typeof part.private === 'string')
548
+ return `{private: ${part.private}}`;
549
+ throw new ReadFail(srcMessage, 1, 1);
550
+ })
551
+ .join('');
552
+ }
553
+ function jsonText(value) {
554
+ if (value === undefined)
555
+ return '';
556
+ return JSON.stringify(value, null, 2);
557
+ }
558
+ function sameValue(a, b) {
559
+ return canonical(a) === canonical(b);
560
+ }
561
+ function schemaText(schema) {
562
+ return isRecord(schema) ? JSON.stringify(schema, null, 2) : JSON.stringify(schema);
563
+ }
564
+ function patternsOf(value) {
565
+ if (!Array.isArray(value))
566
+ return [];
567
+ return value.map((pattern) => {
568
+ if (!isRecord(pattern) || typeof pattern.name !== 'string') {
569
+ throw new ReadFail('A pattern needs a name.', 1, 1);
570
+ }
571
+ if (Array.isArray(pattern.words)) {
572
+ return {
573
+ name: pattern.name,
574
+ kind: 'words',
575
+ pattern: '',
576
+ flags: '',
577
+ words: pattern.words.filter((word) => typeof word === 'string'),
578
+ };
579
+ }
580
+ return {
581
+ name: pattern.name,
582
+ kind: 'pattern',
583
+ pattern: text(pattern.pattern),
584
+ flags: text(pattern.flags),
585
+ words: [],
586
+ };
587
+ });
588
+ }
589
+ function record(value) {
590
+ return isRecord(value) ? value : undefined;
591
+ }
592
+ function strings(value) {
593
+ if (!Array.isArray(value))
594
+ return [];
595
+ return value.filter((entry) => typeof entry === 'string');
596
+ }
597
+ /** The strings of a list the file wrote, or `undefined` when it wrote none. */
598
+ function listed(value) {
599
+ return Array.isArray(value) ? strings(value) : undefined;
600
+ }
601
+ function filled(value) {
602
+ return text(value) || undefined;
603
+ }
604
+ /** A label as its box holds it: a list the file wrote has a line each. */
605
+ function labelText(value) {
606
+ return Array.isArray(value) ? strings(value).join('\n') || undefined : filled(value);
607
+ }
608
+ /** A section of the profile, read when the file has it and kept as it was when not. */
609
+ function section(value, read, kept) {
610
+ return isRecord(value) ? read(value) : kept;
611
+ }
612
+ function readAllow(into, detector, spec) {
613
+ if (!isRecord(spec))
614
+ return;
615
+ if (Array.isArray(spec.names)) {
616
+ into.innocentNames = strings(spec.names);
617
+ return;
618
+ }
619
+ if (!(detector in into.allow))
620
+ return;
621
+ const url = into.allow[detector];
622
+ url.hosts = strings(spec.hosts);
623
+ url.fromTools = spec.fromTools !== false;
624
+ }
625
+ function readDetector(into, detector, rule) {
626
+ const at = record(rule.at) ?? {};
627
+ into.detect[detector] = { ...into.detect[detector], ...at };
628
+ const source = into.sources[detector];
629
+ if (source) {
630
+ if (rule.theorem === false)
631
+ source.theorem = false;
632
+ source.patterns = patternsOf(rule.patterns);
633
+ source.hint = text(rule.hint);
634
+ }
635
+ readAllow(into, detector, rule.allow);
636
+ }
637
+ function ownDetector(key, rule) {
638
+ const at = recordOf(BOUNDARIES, () => 'ignore');
639
+ if (isRecord(rule.at))
640
+ Object.assign(at, rule.at);
641
+ return {
642
+ key,
643
+ label: text(rule.label),
644
+ at,
645
+ patterns: patternsOf(rule.patterns),
646
+ hint: text(rule.hint),
647
+ };
648
+ }
649
+ function guardrailsOf(spec) {
650
+ const blank = createBlankDraft().guardrails;
651
+ if (!isRecord(spec))
652
+ return blank;
653
+ const read = {
654
+ detect: structuredClone(blank.detect),
655
+ sources: structuredClone(blank.sources),
656
+ allow: structuredClone(blank.allow),
657
+ innocentNames: [...blank.innocentNames],
658
+ };
659
+ const own = [];
660
+ const known = new Set(DETECTORS);
661
+ for (const [key, rule] of Object.entries(record(spec.detect) ?? {})) {
662
+ if (!isRecord(rule))
663
+ continue;
664
+ if (known.has(key))
665
+ readDetector(read, key, rule);
666
+ else
667
+ own.push(ownDetector(key, rule));
668
+ }
669
+ const quota = record(spec.quota);
670
+ const blocked = record(spec.blockedReply);
671
+ const network = record(spec.network);
672
+ const taint = record(spec.taint);
673
+ return {
674
+ ...blank,
675
+ ...read,
676
+ own,
677
+ quotaEnabled: quota !== undefined,
678
+ quotaPerDay: whole(quota?.perDay),
679
+ blockedReplyOnBlock: text(blocked?.onBlock),
680
+ blockedReplyMaxRetries: whole(blocked?.maxRetries),
681
+ allowPrivateNetworks: network?.allowPrivateNetworks === true,
682
+ allowedHosts: strings(network?.allowedHosts),
683
+ allowedSchemes: strings(network?.allowedSchemes),
684
+ taintAfterRemoteRead: text(taint?.afterRemoteRead),
685
+ taintRemoteDestination: text(taint?.remoteDestination),
686
+ };
687
+ }
688
+ /** The wording a section's own field holds, and the field it goes back into. */
689
+ const LABEL_FIELDS = {
690
+ 'continue.instruction': (draft, value) => {
691
+ draft.turnBehaviour.continueInstruction = value;
692
+ },
693
+ 'canary.bind_note': (draft, value) => {
694
+ draft.guardrails.canaryBindNote = value;
695
+ },
696
+ 'quota.exhausted': (draft, value) => {
697
+ draft.guardrails.quotaMessage = value;
698
+ },
699
+ 'repair.default_guidance': (draft, value) => {
700
+ draft.outputs.repairGuidance = value;
701
+ },
702
+ 'egress.default_repair_guidance': (draft, value) => {
703
+ draft.guardrails.egressRepairGuidance = value;
704
+ },
705
+ 'egress.refusal': (draft, value) => {
706
+ draft.guardrails.egressRefusal = value;
707
+ },
708
+ };
709
+ function applyLabels(draft, labels) {
710
+ if (!isRecord(labels))
711
+ return;
712
+ const entries = {};
713
+ for (const [key, value] of Object.entries(labels)) {
714
+ if (typeof value !== 'string')
715
+ continue;
716
+ const field = LABEL_FIELDS[key];
717
+ if (field)
718
+ field(draft, value);
719
+ else if (!INLINE_LABELS[key])
720
+ entries[key] = value;
721
+ }
722
+ draft.labels = entries;
723
+ }
724
+ function bindingOf(modelId, spec, current, agentKeyOf, spans) {
725
+ const base = current ?? defaultModelBinding({ modelId });
726
+ if (!isRecord(spec))
727
+ return { ...base, modelId };
728
+ const efforts = isRecord(spec.efforts)
729
+ ? Object.entries(spec.efforts).map(([alias, level]) => ({
730
+ alias,
731
+ level: level,
732
+ }))
733
+ : [];
734
+ const compaction = isRecord(spec.compaction) ? spec.compaction : undefined;
735
+ const compactWith = text(compaction?.profile);
736
+ const timeout = whole(spec.timeoutMs);
737
+ return {
738
+ ...base,
739
+ modelId,
740
+ protocol: text(spec.protocol, base.protocol),
741
+ provider: text(spec.provider, base.provider),
742
+ apiId: text(spec.apiId),
743
+ options: (record(spec.options) ?? {}),
744
+ timeoutMs: timeout,
745
+ efforts,
746
+ defaultEffort: text(spec.defaultEffort),
747
+ allowEffortSelect: spec.allowEffortSelect === true,
748
+ summaries: typeof spec.summaries === 'boolean' ? spec.summaries : null,
749
+ maxOutputTokens: whole(spec.maxOutputTokens),
750
+ temperature: typeof spec.temperature === 'number' ? spec.temperature : null,
751
+ builtInTools: Array.isArray(spec.builtInTools)
752
+ ? spec.builtInTools.filter((tool) => typeof tool === 'string')
753
+ : [],
754
+ keySlot: text(spec.keySlot),
755
+ fallbackKeySlot: text(spec.fallbackKeySlot),
756
+ compactTiming: text(compaction?.timing),
757
+ compactMaxTokens: whole(compaction?.maxTokens),
758
+ compactAt: typeof compaction?.compactAt === 'number' ? compaction.compactAt : undefined,
759
+ compactKeep: whole(compaction?.previousExchanges),
760
+ compactMeter: text(compaction?.meter),
761
+ compactWith: compactWith
762
+ ? compactorKey(compactWith, agentKeyOf, `models.${modelId}.compaction.profile`, spans)
763
+ : '',
764
+ };
765
+ }
766
+ /**
767
+ * The key of the agent `id` names to write a model's summaries. Without `agentKeyOf` the caller
768
+ * links it once every agent is read, so it is left blank here; with it, an id no agent has is
769
+ * refused where it is written, since a blank one means the agent itself.
770
+ */
771
+ function compactorKey(id, agentKeyOf, path, spans) {
772
+ if (!agentKeyOf)
773
+ return '';
774
+ return (agentKeyOf(id) ??
775
+ failAt(spans, path, `'${id}' is not an agent here, so it can't write this model's summaries.`));
776
+ }
777
+ /** The canned reply a function tool returns, when the file wrote its own. */
778
+ function stubOf(type, spec) {
779
+ const schema = spec.output;
780
+ if (type !== 'function' || !isRecord(spec.handler) || !isRecord(schema))
781
+ return undefined;
782
+ if (sameValue(spec.handler, stubOutputFromSchema(schema)))
783
+ return undefined;
784
+ return jsonText(spec.handler);
785
+ }
786
+ function toolRoute(spec) {
787
+ const mapping = record(spec.mapping) ?? {};
788
+ return {
789
+ endpoint: filled(spec.endpoint),
790
+ method: filled(spec.method),
791
+ headersJson: isRecord(spec.headers) ? jsonText(spec.headers) : undefined,
792
+ pathParams: listed(mapping.pathParams),
793
+ queryParams: listed(mapping.queryParams),
794
+ bodyParam: filled(mapping.bodyParam),
795
+ serverUrl: filled(spec.serverUrl),
796
+ mcpToolName: filled(spec.mcpToolName),
797
+ };
798
+ }
799
+ function toolAuth(spec) {
800
+ const auth = record(spec.auth) ?? {};
801
+ return {
802
+ authType: text(auth.type),
803
+ authSlot: filled(auth.slot),
804
+ authService: filled(auth.service),
805
+ authHeaderName: filled(auth.headerName),
806
+ authHeaderPrefix: typeof auth.headerPrefix === 'string' ? auth.headerPrefix : undefined,
807
+ authQueryParam: filled(auth.queryParam),
808
+ authUnauthenticated: text(auth.onUnauthenticated),
809
+ authScopes: listed(auth.scopes),
810
+ authClientId: filled(auth.clientId),
811
+ authRedirectUri: filled(auth.redirectUri),
812
+ };
813
+ }
814
+ function toolOf(spec, current, agentKeyOf) {
815
+ const base = current ?? defaultToolSpec();
816
+ const type = text(spec.type, base.toolType);
817
+ const labels = record(spec.labels) ?? {};
818
+ const agentId = text(spec.profile);
819
+ const page = spec.answeredBy === 'page';
820
+ return {
821
+ ...base,
822
+ key: current?.key ?? draftKey('tool'),
823
+ toolName: text(spec.name, base.toolName),
824
+ toolType: type,
825
+ description: text(spec.description),
826
+ category: text(spec.category, 'studio'),
827
+ access: text(spec.access, base.access),
828
+ permission: text(spec.permission, base.permission),
829
+ loadTier: text(spec.loadTier, base.loadTier),
830
+ paths: listed(spec.paths) ?? ['*'],
831
+ inputJson: spec.input === undefined ? base.inputJson : schemaText(spec.input),
832
+ outputJson: spec.output === undefined ? base.outputJson : schemaText(spec.output),
833
+ activity: labelText(labels.activity),
834
+ activityPast: labelText(labels.activityPast),
835
+ activityFailed: labelText(labels.activityFailed),
836
+ request: labelText(labels.request),
837
+ // A page tool's source has no handler: its stub is the studio's own, so it is kept.
838
+ stubOutputJson: page ? current?.stubOutputJson : stubOf(type, spec),
839
+ answeredBy: page ? 'page' : undefined,
840
+ ...toolRoute(spec),
841
+ agentKey: agentId ? agentKeyOf?.(agentId) : undefined,
842
+ maxCallsPerTurn: whole(spec.maxCallsPerTurn),
843
+ ...toolAuth(spec),
844
+ };
845
+ }
846
+ function questionsOf(spec, current) {
847
+ const byId = new Map(current.map((question) => [question.id, question]));
848
+ return Object.entries(spec).map(([id, value]) => {
849
+ const previous = byId.get(id);
850
+ const question = isRecord(value) ? value : {};
851
+ const type = text(question.type, 'choice');
852
+ const criteria = question.criteria;
853
+ const rows = Array.isArray(criteria)
854
+ ? criteria.map((entry, index) => ({
855
+ key: previous?.criteria[index]?.key ?? draftKey('criterion'),
856
+ label: '',
857
+ text: text(entry),
858
+ }))
859
+ : isRecord(criteria)
860
+ ? Object.entries(criteria).map(([label, entry], index) => ({
861
+ key: previous?.criteria[index]?.key ?? draftKey('criterion'),
862
+ label,
863
+ text: text(entry),
864
+ }))
865
+ : [];
866
+ return {
867
+ key: previous?.key ?? draftKey('question'),
868
+ id,
869
+ type,
870
+ instructions: text(question.instructions),
871
+ criteria: rows,
872
+ ...(type === 'box' && text(question.image) ? { image: text(question.image) } : {}),
873
+ };
874
+ });
875
+ }
876
+ function referencesOf(value) {
877
+ if (!Array.isArray(value))
878
+ return [];
879
+ const references = [];
880
+ for (const reference of value) {
881
+ if (!isRecord(reference))
882
+ continue;
883
+ if (typeof reference.uri === 'string') {
884
+ const name = text(reference.name);
885
+ references.push({
886
+ key: draftKey('reference'),
887
+ uri: reference.uri,
888
+ ...(name ? { name } : {}),
889
+ });
890
+ }
891
+ else if (typeof reference.data === 'string') {
892
+ references.push({
893
+ key: draftKey('reference'),
894
+ name: text(reference.name),
895
+ mimeType: text(reference.mimeType),
896
+ data: reference.data,
897
+ });
898
+ }
899
+ }
900
+ return references;
901
+ }
902
+ function includedOf(type, profile) {
903
+ if (!type)
904
+ return createBlankDraft().included;
905
+ return PROFILE_GRAPH.filter((facet) => {
906
+ if (!facet.optional || facet.role === 'branch')
907
+ return false;
908
+ if (!facet.profileTypes.includes(type))
909
+ return false;
910
+ return facet.profilePath in profile;
911
+ }).map((facet) => facet.id);
912
+ }
913
+ /**
914
+ * `registerTool` calls define the tools. `tools.allow` chooses which of those
915
+ * this agent uses. A call left out of `allow` stays defined and is not used.
916
+ * A name in `allow` with no call is an error at that name: the file would be
917
+ * allowing a tool it does not define.
918
+ */
919
+ function registerTools(calls, byToolName, agentKeyOf, spans) {
920
+ const registered = [];
921
+ const seen = new Set();
922
+ for (const call of calls) {
923
+ const tool = toolOf(call, byToolName.get(text(call.name)), agentKeyOf);
924
+ if (tool.toolName && seen.has(tool.toolName)) {
925
+ const names = spans.filter((span) => span.path === 'name');
926
+ const at = names[registered.length] ?? { line: 1, column: 1 };
927
+ throw new ReadFail(`'${tool.toolName}' is registered twice.`, at.line, at.column);
928
+ }
929
+ if (tool.toolName)
930
+ seen.add(tool.toolName);
931
+ registered.push(tool);
932
+ }
933
+ return registered;
934
+ }
935
+ function allowTools(registered, allow, spans) {
936
+ // A profile with no `tools` allows none: the kernel reads it so.
937
+ if (allow === undefined)
938
+ return [];
939
+ const atAllow = spans.findLast((span) => span.path === 'tools.allow') ?? { line: 1, column: 1 };
940
+ if (!Array.isArray(allow)) {
941
+ throw new ReadFail('tools.allow has to be a list of tool names.', atAllow.line, atAllow.column);
942
+ }
943
+ const byName = new Map(registered.map((tool) => [tool.toolName, tool]));
944
+ const allowed = [];
945
+ const seen = new Set();
946
+ for (const [index, name] of allow.entries()) {
947
+ const at = spans.find((span) => span.path === `tools.allow.${String(index)}`) ?? atAllow;
948
+ if (typeof name !== 'string' || name.trim() === '') {
949
+ throw new ReadFail('tools.allow names tools.', at.line, at.column);
950
+ }
951
+ if (seen.has(name))
952
+ throw new ReadFail(`'${name}' is listed twice in tools.allow.`, at.line, at.column);
953
+ seen.add(name);
954
+ const tool = byName.get(name);
955
+ if (!tool) {
956
+ throw new ReadFail(`'${name}' is in tools.allow, and this file has no registerTool for it.`, at.line, at.column);
957
+ }
958
+ allowed.push(tool);
959
+ }
960
+ return allowed;
961
+ }
962
+ function identityOf(current, profile, type) {
963
+ const identity = record(profile.identity) ?? {};
964
+ const byRole = identity.systemByRole;
965
+ return {
966
+ ...current,
967
+ agentId: text(profile.id),
968
+ profileType: type,
969
+ handle: text(identity.handle),
970
+ system: markup(identity.system, 'The system prompt has to be text.'),
971
+ systemByRoleJson: isRecord(byRole) || Array.isArray(byRole) ? jsonText(byRole) : '',
972
+ };
973
+ }
974
+ function modelsOf(profile) {
975
+ return {
976
+ ...(isRecord(profile.providerContinuation) &&
977
+ (profile.providerContinuation.history === 'provider' ||
978
+ profile.providerContinuation.history === 'stateless')
979
+ ? { providerHistory: profile.providerContinuation.history }
980
+ : {}),
981
+ defaultModel: text(profile.defaultModel),
982
+ allowModelSelect: profile.allowModelSelect === true,
983
+ maxSteps: whole(profile.maxSteps),
984
+ key: text(profile.key),
985
+ fallbackKey: text(profile.fallbackKey),
986
+ };
987
+ }
988
+ function isContextSender(value) {
989
+ return CONTEXT_SENDERS.includes(value);
990
+ }
991
+ function inputsOf(inputs) {
992
+ const context = record(inputs.context);
993
+ return {
994
+ text: inputs.text !== false,
995
+ attachmentsAccept: strings(record(inputs.attachments)?.accept),
996
+ voiceAccept: strings(record(inputs.voice)?.accept),
997
+ maxFiles: whole(inputs.maxFiles),
998
+ maxBytes: whole(inputs.maxBytes),
999
+ maxTurnBytes: whole(inputs.maxTurnBytes),
1000
+ limitsByMimeJson: jsonText(inputs.limitsByMime),
1001
+ slotsJson: jsonText(inputs.slots),
1002
+ contextFrom: strings(context?.from).filter(isContextSender),
1003
+ contextMaxChars: whole(context?.maxChars),
1004
+ };
1005
+ }
1006
+ function itemRulesOf(items) {
1007
+ return Object.fromEntries(Object.entries(items ?? {}).map(([list, rule]) => [
1008
+ list,
1009
+ record(rule)?.onFail === 'fix' ? 'fix' : 'drop',
1010
+ ]));
1011
+ }
1012
+ function outputsOf(outputs, structured) {
1013
+ const schemaId = structured?.id ?? text(outputs?.structured);
1014
+ const streaming = record(outputs?.streaming);
1015
+ const validation = record(outputs?.validation);
1016
+ return {
1017
+ mode: schemaId ? 'structured' : 'text',
1018
+ schemaId,
1019
+ schemaJson: jsonText(structured?.spec.jsonSchema),
1020
+ streamMode: text(streaming?.mode),
1021
+ streamThoughts: streaming?.streamThoughts !== false,
1022
+ validationEnabled: validation !== undefined,
1023
+ maxRetries: whole(validation?.maxRetries),
1024
+ itemRules: itemRulesOf(record(validation?.items)),
1025
+ repairGuidance: '',
1026
+ };
1027
+ }
1028
+ function turnOf(turn) {
1029
+ const resumption = record(turn.resumption);
1030
+ // A list left out is the kernel's own, not none.
1031
+ const allowContinue = Array.isArray(resumption?.allowContinue)
1032
+ ? resumption.allowContinue
1033
+ : [...DEFAULT_ALLOW_CONTINUE];
1034
+ const autoContinue = Array.isArray(resumption?.autoContinue)
1035
+ ? resumption.autoContinue
1036
+ : [...DEFAULT_AUTO_CONTINUE];
1037
+ return {
1038
+ resumeEnabled: allowContinue.length > 0 || autoContinue.length > 0,
1039
+ allowContinue: allowContinue,
1040
+ autoContinue: autoContinue,
1041
+ maxContinues: whole(resumption?.maxContinues),
1042
+ continueInstruction: '',
1043
+ allowSteering: turn.allowSteering !== false,
1044
+ atStepLimit: turn.atStepLimit === 'answer' ? 'answer' : 'stop',
1045
+ };
1046
+ }
1047
+ function observabilityOf(spec) {
1048
+ const blank = createBlankDraft().observability;
1049
+ // A project's profile names its own store. It stays the one traces go to when they are on.
1050
+ const destination = typeof spec.writeTo === 'string' && spec.writeTo ? spec.writeTo : blank.destination;
1051
+ return {
1052
+ ...blank,
1053
+ writeTo: spec.writeTo === false ? false : destination,
1054
+ destination,
1055
+ sampleRate: typeof spec.sampleRate === 'number' ? spec.sampleRate : blank.sampleRate,
1056
+ include: { ...blank.include, ...record(spec.include) },
1057
+ scrub: { ...blank.scrub, ...record(spec.scrub) },
1058
+ retainForDays: whole(spec.retainForDays),
1059
+ rotateAfterMiB: whole(spec.rotateAfterMiB),
1060
+ resourceJson: jsonText(spec.resource),
1061
+ };
1062
+ }
1063
+ function imageOf(image) {
1064
+ return {
1065
+ aspectRatio: text(image.aspectRatio),
1066
+ resolution: text(image.resolution),
1067
+ mimeType: text(image.mimeType),
1068
+ quality: text(image.quality),
1069
+ background: text(image.background),
1070
+ n: whole(image.n),
1071
+ seed: whole(image.seed),
1072
+ outputCompression: whole(image.outputCompression),
1073
+ includeText: image.includeText === true,
1074
+ references: referencesOf(image.references),
1075
+ };
1076
+ }
1077
+ function speechOf(speech) {
1078
+ return {
1079
+ voice: text(speech.voice),
1080
+ style: text(speech.style),
1081
+ speed: whole(speech.speed),
1082
+ format: text(speech.format),
1083
+ };
1084
+ }
1085
+ function ingressOf(ingress, channel) {
1086
+ const value = ingress[channel];
1087
+ return typeof value === 'boolean' ? value : liveIngressChannelDefault(channel);
1088
+ }
1089
+ function liveOf(live) {
1090
+ const ingress = record(live.ingress) ?? {};
1091
+ const vad = record(live.vad) ?? {};
1092
+ const compression = record(live.contextCompression);
1093
+ const sliding = record(compression?.slidingWindow);
1094
+ const transcription = record(live.transcription);
1095
+ return {
1096
+ ingressAudio: ingressOf(ingress, 'audio'),
1097
+ ingressVideo: ingressOf(ingress, 'video'),
1098
+ ingressText: ingressOf(ingress, 'text'),
1099
+ voice: text(live.voice),
1100
+ sessionResumption: live.sessionResumption === true,
1101
+ greeting: text(live.greeting),
1102
+ resumedPrompt: text(record(live.resumed)?.prompt),
1103
+ resumedAfterMs: whole(record(live.resumed)?.afterMs),
1104
+ contextCompression: compression !== undefined,
1105
+ compressionTriggerTokens: whole(compression?.triggerTokens),
1106
+ compressionTargetTokens: whole(sliding?.targetTokens),
1107
+ transcriptionInput: transcription?.input === true,
1108
+ transcriptionOutput: transcription?.output === true,
1109
+ vadActivityHandling: text(vad.activityHandling),
1110
+ vadStartSensitivity: text(vad.startSensitivity),
1111
+ vadEndSensitivity: text(vad.endSensitivity),
1112
+ vadPrefixPaddingMs: whole(vad.prefixPaddingMs),
1113
+ vadSilenceDurationMs: whole(vad.silenceDurationMs),
1114
+ };
1115
+ }
1116
+ function decisionOf(decision, parsed, current) {
1117
+ const maxState = whole(record(parsed.profile?.inputs)?.maxStateBytes);
1118
+ return {
1119
+ contract: text(decision.contract),
1120
+ maxStateBytes: maxState,
1121
+ questions: parsed.questions ? questionsOf(parsed.questions, current.questions) : [],
1122
+ images: parsed.images ? decisionImagesOf(parsed.images, current.images) : [],
1123
+ };
1124
+ }
1125
+ /** The module's pictures, each keeping the key of the one it replaces by name. */
1126
+ function decisionImagesOf(spec, current) {
1127
+ const byName = new Map(current.map((image) => [image.name, image]));
1128
+ return Object.entries(spec).map(([reference, value]) => {
1129
+ const name = reference.replace(/^<|>$/g, '');
1130
+ const image = isRecord(value) ? value : {};
1131
+ return {
1132
+ key: byName.get(name)?.key ?? draftKey('image'),
1133
+ name,
1134
+ mimeType: text(image.mimeType),
1135
+ data: text(image.data),
1136
+ };
1137
+ });
1138
+ }
1139
+ function profileTypeOf(profile) {
1140
+ const type = text(profile.type);
1141
+ if (type && !STUDIO_PROFILE_TYPES.includes(type)) {
1142
+ throw new ReadFail(`'${type}' is not a profile type.`, 1, 1);
1143
+ }
1144
+ return type;
1145
+ }
1146
+ /** The settings a reader below would otherwise take as their default when set to anything else. */
1147
+ const LISTED_SETTINGS = ['turnBehaviour.atStepLimit', 'outputs.validation.items.*.onFail'];
1148
+ /** Refuses, where it is written, a listed setting set to a value the kernel's table does not list. */
1149
+ function refuseUnlisted(profile, spans) {
1150
+ for (const setting of LISTED_SETTINGS) {
1151
+ const options = fieldMeta(setting)?.options ?? [];
1152
+ for (const [path, value] of valuesAt(profile, setting.split('.'), [])) {
1153
+ if (value !== undefined && !options.includes(value)) {
1154
+ failAt(spans, path, `${JSON.stringify(value)} is not one of ${options.map((option) => `'${option}'`).join(', ')}.`);
1155
+ }
1156
+ }
1157
+ }
1158
+ }
1159
+ /** Each value at `keys` in `value`, `*` standing for every key, with its path as written. */
1160
+ function valuesAt(value, keys, at) {
1161
+ const [key, ...rest] = keys;
1162
+ if (key === undefined)
1163
+ return [[at.join('.'), value]];
1164
+ if (!isRecord(value))
1165
+ return [];
1166
+ const next = key === '*' ? Object.keys(value) : [key];
1167
+ return next.flatMap((each) => valuesAt(value[each], rest, [...at, each]));
1168
+ }
1169
+ function draftFrom(parsed, current, agentKeyOf) {
1170
+ const profile = parsed.profile ?? {};
1171
+ const type = profileTypeOf(profile);
1172
+ refuseUnlisted(profile, parsed.spans);
1173
+ const byModelId = new Map(current.modelBindings.map((binding) => [binding.modelId, binding]));
1174
+ const byToolName = new Map(current.toolSpecs.map((tool) => [tool.toolName, tool]));
1175
+ const tools = record(profile.tools) ?? {};
1176
+ const inputs = record(profile.inputs);
1177
+ const outputs = record(profile.outputs);
1178
+ const draft = {
1179
+ ...current,
1180
+ identity: identityOf(current.identity, profile, type),
1181
+ included: includedOf(type, profile),
1182
+ models: modelsOf(profile),
1183
+ modelBindings: Object.entries(record(profile.models) ?? {}).map(([modelId, spec]) => bindingOf(modelId, spec, byModelId.get(modelId), agentKeyOf, parsed.spans)),
1184
+ tools: { t2Loader: text(tools.t2Loader), parallel: tools.parallel === true },
1185
+ toolSpecs: [],
1186
+ inputs: inputs && type !== 'decision' ? inputsOf(inputs) : current.inputs,
1187
+ outputs: outputs || parsed.structured ? outputsOf(outputs, parsed.structured) : current.outputs,
1188
+ turnBehaviour: section(profile.turnBehaviour, turnOf, current.turnBehaviour),
1189
+ guardrails: section(profile.guardrails, guardrailsOf, current.guardrails),
1190
+ observability: section(profile.observability, observabilityOf, current.observability),
1191
+ image: section(profile.image, imageOf, current.image),
1192
+ speech: section(profile.speech, speechOf, current.speech),
1193
+ live: section(profile.live, liveOf, current.live),
1194
+ decision: section(profile.decision, (spec) => decisionOf(spec, parsed, current.decision), current.decision),
1195
+ labels: {},
1196
+ };
1197
+ const registered = registerTools(parsed.tools, byToolName, agentKeyOf, parsed.spans);
1198
+ const allowed = allowTools(registered, tools.allow, parsed.spans);
1199
+ draft.toolSpecs = allowed;
1200
+ const allowedNames = new Set(allowed.map((tool) => tool.toolName));
1201
+ if (draft.tools.t2Loader && !allowedNames.has(draft.tools.t2Loader)) {
1202
+ draft.tools = { ...draft.tools, t2Loader: '' };
1203
+ }
1204
+ applyLabels(draft, profile.labels);
1205
+ return { draft, registered };
1206
+ }
1207
+ /**
1208
+ * The open agent's file, as a draft. `current` keeps the row keys of models and
1209
+ * tools the file still has. `agentKeyOf` resolves an agent id named in the file.
1210
+ */
1211
+ export function readStudioSource(source, current, agentKeyOf) {
1212
+ try {
1213
+ const parsed = parseModule(source);
1214
+ const { draft, registered } = draftFrom(parsed, current, agentKeyOf);
1215
+ return { ok: true, draft, spans: parsed.spans, registered };
1216
+ }
1217
+ catch (error) {
1218
+ if (error instanceof ReadFail) {
1219
+ return {
1220
+ ok: false,
1221
+ errors: [{ message: error.message, line: error.line, column: error.column }],
1222
+ };
1223
+ }
1224
+ throw error;
1225
+ }
1226
+ }
1227
+ /** Fails at where `path` was written, or at the file's start. */
1228
+ function failAt(spans, path, message) {
1229
+ const at = spans.findLast((span) => span.path === path) ?? { line: 1, column: 1 };
1230
+ throw new ReadFail(message, at.line, at.column);
1231
+ }
1232
+ const PROVIDER_SETTINGS = new Set(['id', 'connection', 'keySlot', 'fallbackKeySlot']);
1233
+ function providerFrom(written, current, spans) {
1234
+ const { spec } = written;
1235
+ for (const key of Object.keys(spec)) {
1236
+ if (!PROVIDER_SETTINGS.has(key))
1237
+ failAt(spans, key, `'${key}' isn't a provider setting the studio holds.`);
1238
+ }
1239
+ if (spec.id !== current.id) {
1240
+ failAt(spans, 'id', `The id stays '${current.id}': models and code name the provider by it.`);
1241
+ }
1242
+ const definition = definitionOfFactory(written.definition);
1243
+ if (!definition) {
1244
+ const named = kernelDefinitions()
1245
+ .flatMap((id) => definitionFactory(id) ?? [])
1246
+ .join(', ');
1247
+ failAt(spans, '', `'${written.definition}' isn't one of the kernel's providers: ${named}.`);
1248
+ }
1249
+ const held = spec.connection === undefined ? {} : connectionFrom(spec.connection, spans);
1250
+ // An empty connection is what the code has to say for one that opened with none.
1251
+ const empty = Object.keys(held).length === 0 && current.connection === undefined;
1252
+ const provider = {
1253
+ id: current.id,
1254
+ definition,
1255
+ ...(empty ? {} : { connection: held }),
1256
+ };
1257
+ for (const slot of ['keySlot', 'fallbackKeySlot']) {
1258
+ const value = spec[slot];
1259
+ if (value === undefined)
1260
+ continue;
1261
+ if (typeof value !== 'string')
1262
+ failAt(spans, slot, `${slot} names a key slot.`);
1263
+ provider[slot] = value;
1264
+ }
1265
+ return provider;
1266
+ }
1267
+ /** A provider's connection: text settings, by name. */
1268
+ function connectionFrom(connection, spans) {
1269
+ const wrong = 'connection holds text settings here.';
1270
+ const held = {};
1271
+ if (!isRecord(connection))
1272
+ failAt(spans, 'connection', wrong);
1273
+ for (const [name, value] of Object.entries(connection)) {
1274
+ if (typeof value !== 'string')
1275
+ failAt(spans, 'connection', wrong);
1276
+ held[name] = value;
1277
+ }
1278
+ return held;
1279
+ }
1280
+ /** A provider's file, as the provider it defines. Its id has to stay `current`'s. */
1281
+ export function readProviderSource(source, current) {
1282
+ try {
1283
+ const parsed = parseModule(source, 'provider');
1284
+ if (!parsed.provider)
1285
+ throw new ReadFail('This code needs registerProvider().', 1, 1);
1286
+ return {
1287
+ ok: true,
1288
+ provider: providerFrom(parsed.provider, current, parsed.spans),
1289
+ spans: parsed.spans,
1290
+ };
1291
+ }
1292
+ catch (error) {
1293
+ if (error instanceof ReadFail) {
1294
+ return {
1295
+ ok: false,
1296
+ errors: [{ message: error.message, line: error.line, column: error.column }],
1297
+ };
1298
+ }
1299
+ throw error;
1300
+ }
1301
+ }