@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.
- package/LICENSE +21 -0
- package/README.md +295 -2
- package/agreement.d.ts +14 -0
- package/agreement.js +80 -0
- package/asks.d.ts +47 -0
- package/asks.js +54 -0
- package/browser-connection.d.ts +49 -0
- package/browser-connection.js +215 -0
- package/browser-engine.d.ts +11 -0
- package/browser-engine.js +11 -0
- package/browser-execution.d.ts +6 -0
- package/browser-execution.js +18 -0
- package/browser-live.d.ts +4 -0
- package/browser-live.js +132 -0
- package/browser-transport.d.ts +33 -0
- package/browser-transport.js +229 -0
- package/browser.d.ts +4 -0
- package/browser.js +4 -0
- package/canonical.d.ts +10 -0
- package/canonical.js +25 -0
- package/compile-workspace.d.ts +28 -0
- package/compile-workspace.js +295 -0
- package/compile.d.ts +65 -0
- package/compile.js +1605 -0
- package/concierge-demo.d.ts +17 -0
- package/concierge-demo.js +1230 -0
- package/conversation-key.d.ts +5 -0
- package/conversation-key.js +10 -0
- package/decision-example-images.d.ts +30 -0
- package/decision-example-images.js +30 -0
- package/deno.json +3 -0
- package/draft.d.ts +407 -0
- package/draft.js +505 -0
- package/editors.d.ts +29 -0
- package/editors.js +51 -0
- package/example-embedding-files.d.ts +11 -0
- package/example-embedding-files.js +20 -0
- package/example.d.ts +36 -0
- package/example.js +357 -0
- package/guardrail-probe.d.ts +100 -0
- package/guardrail-probe.js +722 -0
- package/held-credentials.d.ts +28 -0
- package/held-credentials.js +87 -0
- package/installed.mjs +40 -0
- package/lent-keys.d.ts +122 -0
- package/lent-keys.js +47 -0
- package/line-diff.d.ts +15 -0
- package/line-diff.js +41 -0
- package/live-connection.d.ts +22 -0
- package/live-connection.js +27 -0
- package/live-session-bridge.d.ts +15 -0
- package/live-session-bridge.js +202 -0
- package/map-line.d.ts +19 -0
- package/map-line.js +42 -0
- package/map.d.ts +154 -0
- package/map.js +525 -0
- package/media-accept.d.ts +19 -0
- package/media-accept.js +65 -0
- package/mod.d.ts +39 -0
- package/mod.js +33 -0
- package/origins.d.ts +52 -0
- package/origins.js +165 -0
- package/package.json +85 -4
- package/page/assets/Banner-BISz3nXA.js +2 -0
- package/page/assets/BottomSheet-BwfBDtje.js +1 -0
- package/page/assets/Card-Lp-0P5eL.js +1 -0
- package/page/assets/CardWall-CBRLdDZW.js +1 -0
- package/page/assets/Center-nHS1JSux.js +1 -0
- package/page/assets/CheckboxInput-Cj5pk-KI.js +2 -0
- package/page/assets/CodeBlock-C7XJ4ioE.js +51 -0
- package/page/assets/CollapsibleGroup-N7_SOjbm.js +2 -0
- package/page/assets/ContextMenu-CBu9H-9H.js +2 -0
- package/page/assets/DateInput-BGrQ5tPC.js +1 -0
- package/page/assets/Dialog-DELWQo-v.js +1 -0
- package/page/assets/EmptyState-C8W4JKBZ.js +1 -0
- package/page/assets/HoverCard-D1Y1ltWQ.js +1 -0
- package/page/assets/Icon-JrysT8aU.js +3 -0
- package/page/assets/IconAlertTriangle-BqAEqqdU.js +1 -0
- package/page/assets/IconButton-DlOGzJIX.js +1 -0
- package/page/assets/IconEye-BB5aY-wQ.js +1 -0
- package/page/assets/IconFileText-6zOFKKrF.js +1 -0
- package/page/assets/IconSearch-BTx66a40.js +1 -0
- package/page/assets/IconShield-DDOh7Gr5.js +1 -0
- package/page/assets/ItemSwipeLayer-Ckn4X6h9.js +1 -0
- package/page/assets/PaneState-BvA2tLQg.js +1 -0
- package/page/assets/PaneState-eUzUkNE8.css +1 -0
- package/page/assets/ScrollableArea-Ckugdj1N.js +1 -0
- package/page/assets/Section-DJ97F7QE.js +1 -0
- package/page/assets/SegmentedControlItem-h-aaXzyS.js +1 -0
- package/page/assets/SidePanel-BL32abk8.js +1 -0
- package/page/assets/StackItem-CQviqAfM.js +1 -0
- package/page/assets/Text-bum6zWWx.js +2 -0
- package/page/assets/TimestampHoverCard-DQIG0RZF.js +1 -0
- package/page/assets/ToolResultCharts-CgshSv9Q.js +1 -0
- package/page/assets/Tooltip-BH9xiRMl.js +1 -0
- package/page/assets/TraceInspector-_yZiz05W.js +1 -0
- package/page/assets/TraceOverview-BPO-HIYK.js +57 -0
- package/page/assets/VStack-CkVMcNiK.js +1 -0
- package/page/assets/_virtual_studio-type-sources-ByxqQaOG.js +12936 -0
- package/page/assets/arrive-DvbqpeRS.js +1 -0
- package/page/assets/browser-engine-CYq9DQAM.js +9 -0
- package/page/assets/browser-transport-D-2jDYe7.js +47 -0
- package/page/assets/codicon-DF1abBS2.ttf +0 -0
- package/page/assets/compile-egress-BSxOdX4K.js +23 -0
- package/page/assets/container.stylex-BmOi-8DQ.js +1 -0
- package/page/assets/createReactComponent-CZwsv6DD.js +1 -0
- package/page/assets/decision-example-images-CZGr7YIT.js +1 -0
- package/page/assets/devWarning-DxuplmRl.js +1 -0
- package/page/assets/editor-DjpsE8to.css +1 -0
- package/page/assets/editor.api-Cd3ViPQa.js +908 -0
- package/page/assets/editor.worker-6GY8RhDc.js +1 -0
- package/page/assets/editor.worker-BmdWdrHZ.js +33 -0
- package/page/assets/editors-BJX_S59A.js +1 -0
- package/page/assets/egress-automata-B5ZGE1mT.js +1 -0
- package/page/assets/embedding-space-view-CfQBPDxD.js +140 -0
- package/page/assets/encode-files-Bc3HJyAh.js +1 -0
- package/page/assets/export-agent-C3yyzXH8.js +43 -0
- package/page/assets/figtree-latin-400-normal-BD4aNku5.woff +0 -0
- package/page/assets/figtree-latin-400-normal-g7Dtegnw.woff2 +0 -0
- package/page/assets/figtree-latin-500-normal-BWnGEVsr.woff2 +0 -0
- package/page/assets/figtree-latin-500-normal-B_yy1phn.woff +0 -0
- package/page/assets/figtree-latin-600-normal-BM_oTo4n.woff +0 -0
- package/page/assets/figtree-latin-600-normal-Cv_xCTDl.woff2 +0 -0
- package/page/assets/figtree-latin-700-normal-BCCt2T1q.woff +0 -0
- package/page/assets/figtree-latin-700-normal-th6qEP7c.woff2 +0 -0
- package/page/assets/focusOutline.stylex-BT0kfa4t.js +1 -0
- package/page/assets/focusableSelector-DXZeMU85.js +1 -0
- package/page/assets/groupStyles-C7Ter7zC.js +1 -0
- package/page/assets/guardrail-tester-Gut5xK4a.js +9 -0
- package/page/assets/host-patterns-C9RMP16Q.js +1 -0
- package/page/assets/index-CvvmFKgS.js +105 -0
- package/page/assets/index-DOaHlqBo.css +1 -0
- package/page/assets/isRtlElement-BG33-k_H.js +1 -0
- package/page/assets/labels-provider-4TIWDvsE.js +3 -0
- package/page/assets/lent-keys-C32ems-I.js +1 -0
- package/page/assets/live-ingress-lDUGPwth.js +1 -0
- package/page/assets/live-messages-CnkL4GWi.js +1 -0
- package/page/assets/mergeProps-ptS-gIMz.js +1 -0
- package/page/assets/padding.stylex-B76907Zf.js +1 -0
- package/page/assets/preload-helper-DpV6A1kQ.js +1 -0
- package/page/assets/reader-BOCCYaRp.js +7 -0
- package/page/assets/register-CDgivxvX.js +2 -0
- package/page/assets/rolldown-runtime-hePW80VL.js +1 -0
- package/page/assets/schemas-BQ9Jydzb.js +56 -0
- package/page/assets/shaped-data-BcarWqd5.js +16 -0
- package/page/assets/sharedResizeObserver-4U9Xq5Oq.js +1 -0
- package/page/assets/stub-DhdcU_Ew.js +471 -0
- package/page/assets/studio-code-pane-C_SAbcOa.js +8 -0
- package/page/assets/studio-console-DZwlEsvr.js +3 -0
- package/page/assets/studio-decision-B0FnCAXA.js +1 -0
- package/page/assets/studio-embedding-CmA51HVo.js +2 -0
- package/page/assets/studio-host-console-By7hqu2l.js +2 -0
- package/page/assets/studio-live-BrcVQcyV.js +1 -0
- package/page/assets/studio-map-B_xSia-z.js +1 -0
- package/page/assets/studio-map-Bb06Tw1F.css +1 -0
- package/page/assets/studio-monaco-CbKf90i6.css +1 -0
- package/page/assets/studio-monaco-xfyfezQS.js +34 -0
- package/page/assets/studio-ts.worker-B-EXG4Sv.js +67741 -0
- package/page/assets/studio-ts.worker-BXtW3z-O.js +1 -0
- package/page/assets/studio-type-checker-BOvxudki.js +23 -0
- package/page/assets/themeProps-3IqahpCr.js +1 -0
- package/page/assets/tokens.stylex-DkHf0P9C.js +1 -0
- package/page/assets/tool-schema-idaOe2nI.js +18 -0
- package/page/assets/trace-patterns-DnYJa0nI.js +1 -0
- package/page/assets/trace-record-C3zNksA_.js +1 -0
- package/page/assets/trace-schema-9CdEyG6Q.js +1 -0
- package/page/assets/tree-DqyAMsbI.js +3 -0
- package/page/assets/turn-client-Du3Um3Mg.js +2 -0
- package/page/assets/types-BhfXQCLx.js +1 -0
- package/page/assets/typescript-20GgZ8PJ.js +1 -0
- package/page/assets/use-one-call-Hcs8YBp1.js +1 -0
- package/page/assets/useAdaptivePresentation-BzmPCddb.js +1 -0
- package/page/assets/useClipboard-BgGRxRMJ.js +1 -0
- package/page/assets/useContainerReveal-BFy8N_QU.js +1 -0
- package/page/assets/useDevWarning-Z9SoixOP.js +1 -0
- package/page/assets/useLayerDismissal-B_G7IWpC.js +1 -0
- package/page/assets/useMediaQuery-BCT0NUeZ.js +1 -0
- package/page/assets/useScrollLock-Dyf6PHJt.js +1 -0
- package/page/assets/useScrollableArea-0NzdiBCq.js +1 -0
- package/page/assets/useTooltip-CJM_xhLB.js +1 -0
- package/page/assets/workspace-DZALqEDX.js +1 -0
- package/page/assets/zip-DTcEfps6.js +1 -0
- package/page/index.html +90 -0
- package/page.mjs +49 -0
- package/people.d.ts +87 -0
- package/people.js +110 -0
- package/policy.d.ts +43 -0
- package/policy.js +102 -0
- package/ports.d.mts +32 -0
- package/ports.mjs +85 -0
- package/probe-battery.d.ts +13 -0
- package/probe-battery.js +404 -0
- package/providers.d.ts +149 -0
- package/providers.js +306 -0
- package/read-source.d.ts +48 -0
- package/read-source.js +1301 -0
- package/read-steps.d.ts +23 -0
- package/read-steps.js +2 -0
- package/reader.d.ts +11 -0
- package/reader.js +11 -0
- package/registrations.d.ts +83 -0
- package/registrations.js +1 -0
- package/requirements.d.ts +22 -0
- package/requirements.js +38 -0
- package/run-payload-core.d.ts +28 -0
- package/run-payload-core.js +123 -0
- package/run-payload.d.ts +32 -0
- package/run-payload.js +26 -0
- package/runtime-scope.d.ts +84 -0
- package/runtime-scope.js +308 -0
- package/runtime.d.ts +84 -0
- package/runtime.js +387 -0
- package/section-notes.d.ts +33 -0
- package/section-notes.js +38 -0
- package/serve-page.mjs +96 -0
- package/server/draft-decide.d.ts +72 -0
- package/server/draft-decide.js +111 -0
- package/server/draft-embedding.d.ts +3 -0
- package/server/draft-embedding.js +35 -0
- package/server/draft-handler.d.ts +82 -0
- package/server/draft-handler.js +213 -0
- package/server/draft-probe.d.ts +14 -0
- package/server/draft-probe.js +61 -0
- package/server/draft-replies.d.ts +22 -0
- package/server/draft-replies.js +46 -0
- package/server/edited-session.d.ts +28 -0
- package/server/edited-session.js +83 -0
- package/server/edits.d.ts +38 -0
- package/server/edits.js +195 -0
- package/server/handler.d.ts +133 -0
- package/server/handler.js +598 -0
- package/server/lent-draft.d.ts +19 -0
- package/server/lent-draft.js +23 -0
- package/server/live.d.ts +15 -0
- package/server/live.js +96 -0
- package/server/open-editor.d.ts +63 -0
- package/server/open-editor.js +115 -0
- package/server/origins.d.ts +18 -0
- package/server/origins.js +330 -0
- package/server/project-source.d.ts +208 -0
- package/server/project-source.js +1042 -0
- package/server/project.d.ts +22 -0
- package/server/project.js +56 -0
- package/server/run-traces.d.ts +20 -0
- package/server/run-traces.js +96 -0
- package/server/save-new.d.ts +29 -0
- package/server/save-new.js +514 -0
- package/server/save-plan.d.ts +46 -0
- package/server/save-plan.js +1134 -0
- package/server/save-remove.d.ts +21 -0
- package/server/save-remove.js +528 -0
- package/server/save-session.d.ts +96 -0
- package/server/save-session.js +418 -0
- package/server/save-wire.d.ts +235 -0
- package/server/save-wire.js +8 -0
- package/server/save.d.ts +52 -0
- package/server/save.js +209 -0
- package/server/serve.d.ts +23 -0
- package/server/serve.js +413 -0
- package/server/test-connection.d.ts +17 -0
- package/server/test-connection.js +362 -0
- package/server/test-key.d.ts +2 -0
- package/server/test-key.js +83 -0
- package/server/watch.d.ts +28 -0
- package/server/watch.js +93 -0
- package/server/zod-edit.d.ts +74 -0
- package/server/zod-edit.js +558 -0
- package/server.d.ts +8 -0
- package/server.js +8 -0
- package/setups.mjs +170 -0
- package/shared-carry.d.ts +114 -0
- package/shared-carry.js +523 -0
- package/shared-settings.d.ts +34 -0
- package/shared-settings.js +70 -0
- package/source.d.ts +75 -0
- package/source.js +414 -0
- package/start.mjs +169 -0
- package/stream-lines.d.ts +9 -0
- package/stream-lines.js +27 -0
- package/stub.d.ts +6 -0
- package/stub.js +33 -0
- package/surface.d.ts +53 -0
- package/surface.js +631 -0
- package/system-markup.d.ts +20 -0
- package/system-markup.js +51 -0
- package/tool-schema.d.ts +23 -0
- package/tool-schema.js +69 -0
- package/tools.d.ts +16 -0
- package/tools.js +91 -0
- package/traces.d.ts +24 -0
- package/traces.js +29 -0
- package/transport.d.ts +57 -0
- package/transport.js +187 -0
- package/tree.d.ts +32 -0
- package/tree.js +83 -0
- package/types.d.ts +62 -0
- package/types.js +6 -0
- package/ui/acting-as-button.d.ts +2 -0
- package/ui/acting-as-button.js +16 -0
- package/ui/add-provider.d.ts +13 -0
- package/ui/add-provider.js +20 -0
- package/ui/boot-mark.css +53 -0
- package/ui/boot-mark.d.ts +19 -0
- package/ui/boot-mark.js +128 -0
- package/ui/boot-paint.d.ts +8 -0
- package/ui/boot-paint.js +8 -0
- package/ui/brand-icons.d.ts +57 -0
- package/ui/brand-icons.js +148 -0
- package/ui/built/theme.css +830 -0
- package/ui/built/theme.css.d.ts +9 -0
- package/ui/built/theorem-studio.d.ts +13 -0
- package/ui/built/theorem-studio.js +705 -0
- package/ui/built/theorem-studio.variants.d.ts +28 -0
- package/ui/code/monaco-contributions.d.ts +45 -0
- package/ui/code/studio-code.d.ts +7 -0
- package/ui/code/studio-code.js +253 -0
- package/ui/code/studio-monaco.d.ts +44 -0
- package/ui/code/studio-monaco.js +48 -0
- package/ui/code/studio-ts.worker.d.ts +1 -0
- package/ui/code/studio-ts.worker.js +16 -0
- package/ui/code/studio-type-checker.d.ts +12 -0
- package/ui/code/studio-type-checker.js +308 -0
- package/ui/code/studio-type-sources.d.ts +26 -0
- package/ui/confirm-write.d.ts +12 -0
- package/ui/confirm-write.js +45 -0
- package/ui/diff-block.d.ts +21 -0
- package/ui/diff-block.js +17 -0
- package/ui/figtree.css +59 -0
- package/ui/file-place.d.ts +4 -0
- package/ui/file-place.js +26 -0
- package/ui/guardrail-tester.d.ts +18 -0
- package/ui/guardrail-tester.js +248 -0
- package/ui/inspector-context.d.ts +119 -0
- package/ui/inspector-context.js +84 -0
- package/ui/inspector.d.ts +247 -0
- package/ui/inspector.js +284 -0
- package/ui/lib/acting-as.d.ts +25 -0
- package/ui/lib/acting-as.js +90 -0
- package/ui/lib/boot-sequence.d.ts +32 -0
- package/ui/lib/boot-sequence.js +57 -0
- package/ui/lib/export-agent.d.ts +11 -0
- package/ui/lib/export-agent.js +335 -0
- package/ui/lib/facet-icons.d.ts +20 -0
- package/ui/lib/facet-icons.js +21 -0
- package/ui/lib/panel-motion.d.ts +8 -0
- package/ui/lib/panel-motion.js +74 -0
- package/ui/lib/project-address.d.ts +14 -0
- package/ui/lib/project-address.js +24 -0
- package/ui/lib/project-starting.d.ts +13 -0
- package/ui/lib/project-starting.js +30 -0
- package/ui/lib/project-traces.d.ts +17 -0
- package/ui/lib/project-traces.js +54 -0
- package/ui/lib/read-map.d.ts +30 -0
- package/ui/lib/read-map.js +173 -0
- package/ui/lib/read-progress.d.ts +14 -0
- package/ui/lib/read-progress.js +12 -0
- package/ui/lib/refusal-lines.d.ts +3 -0
- package/ui/lib/refusal-lines.js +8 -0
- package/ui/lib/studio-activity.d.ts +5 -0
- package/ui/lib/studio-activity.js +17 -0
- package/ui/lib/studio-console.d.ts +27 -0
- package/ui/lib/studio-console.js +9 -0
- package/ui/lib/studio-conversation.d.ts +20 -0
- package/ui/lib/studio-conversation.js +130 -0
- package/ui/lib/studio-examples.d.ts +31 -0
- package/ui/lib/studio-examples.js +25 -0
- package/ui/lib/studio-labels.d.ts +6 -0
- package/ui/lib/studio-labels.js +13 -0
- package/ui/lib/studio-map-kept.d.ts +17 -0
- package/ui/lib/studio-map-kept.js +48 -0
- package/ui/lib/studio-open.d.ts +22 -0
- package/ui/lib/studio-open.js +54 -0
- package/ui/lib/studio-page.d.ts +33 -0
- package/ui/lib/studio-page.js +121 -0
- package/ui/lib/studio-prefs.d.ts +26 -0
- package/ui/lib/studio-prefs.js +87 -0
- package/ui/lib/studio-project.d.ts +106 -0
- package/ui/lib/studio-project.js +177 -0
- package/ui/lib/studio-restore.d.ts +49 -0
- package/ui/lib/studio-restore.js +251 -0
- package/ui/lib/studio-run-open.d.ts +15 -0
- package/ui/lib/studio-run-open.js +16 -0
- package/ui/lib/studio-session.d.ts +34 -0
- package/ui/lib/studio-session.js +17 -0
- package/ui/lib/studio-settings.d.ts +15 -0
- package/ui/lib/studio-settings.js +48 -0
- package/ui/lib/studio-store.d.ts +64 -0
- package/ui/lib/studio-store.js +391 -0
- package/ui/lib/studio-watch.d.ts +12 -0
- package/ui/lib/studio-watch.js +27 -0
- package/ui/lib/tab-fills.d.ts +6 -0
- package/ui/lib/tab-fills.js +14 -0
- package/ui/lib/tool-credentials.d.ts +3 -0
- package/ui/lib/tool-credentials.js +23 -0
- package/ui/lib/tool-probe.d.ts +19 -0
- package/ui/lib/tool-probe.js +104 -0
- package/ui/lib/type-icons.d.ts +35 -0
- package/ui/lib/type-icons.js +38 -0
- package/ui/lib/when-idle.d.ts +5 -0
- package/ui/lib/when-idle.js +14 -0
- package/ui/lib/zip.d.ts +5 -0
- package/ui/lib/zip.js +8 -0
- package/ui/map-token.css +11 -0
- package/ui/map-token.d.ts +17 -0
- package/ui/map-token.js +29 -0
- package/ui/mcp-icon.d.ts +6 -0
- package/ui/mcp-icon.js +8 -0
- package/ui/motion.css +113 -0
- package/ui/pan.d.ts +32 -0
- package/ui/pan.js +90 -0
- package/ui/profile-editor.d.ts +33 -0
- package/ui/profile-editor.js +2638 -0
- package/ui/provider-editor.d.ts +15 -0
- package/ui/provider-editor.js +92 -0
- package/ui/read-map.css +48 -0
- package/ui/read-map.d.ts +7 -0
- package/ui/read-map.js +163 -0
- package/ui/refusal-detail.d.ts +4 -0
- package/ui/refusal-detail.js +21 -0
- package/ui/shared-change.d.ts +9 -0
- package/ui/shared-change.js +28 -0
- package/ui/shell-motion.css +121 -0
- package/ui/shell-motion.d.ts +73 -0
- package/ui/shell-motion.js +194 -0
- package/ui/studio-code-pane.d.ts +19 -0
- package/ui/studio-code-pane.js +44 -0
- package/ui/studio-compare.d.ts +80 -0
- package/ui/studio-compare.js +326 -0
- package/ui/studio-conflicts.d.ts +17 -0
- package/ui/studio-conflicts.js +87 -0
- package/ui/studio-connection.d.ts +64 -0
- package/ui/studio-connection.js +286 -0
- package/ui/studio-decision.d.ts +6 -0
- package/ui/studio-decision.js +49 -0
- package/ui/studio-embedding.d.ts +6 -0
- package/ui/studio-embedding.js +30 -0
- package/ui/studio-host-console.d.ts +6 -0
- package/ui/studio-host-console.js +17 -0
- package/ui/studio-host.d.ts +73 -0
- package/ui/studio-host.js +12 -0
- package/ui/studio-live.d.ts +17 -0
- package/ui/studio-live.js +26 -0
- package/ui/studio-map.css +273 -0
- package/ui/studio-map.d.ts +17 -0
- package/ui/studio-map.js +397 -0
- package/ui/studio-nav.d.ts +24 -0
- package/ui/studio-nav.js +17 -0
- package/ui/studio-no-project.d.ts +5 -0
- package/ui/studio-no-project.js +9 -0
- package/ui/studio-run.css +76 -0
- package/ui/studio-run.d.ts +14 -0
- package/ui/studio-run.js +119 -0
- package/ui/studio-runner.d.ts +45 -0
- package/ui/studio-runner.js +187 -0
- package/ui/studio-save.d.ts +49 -0
- package/ui/studio-save.js +307 -0
- package/ui/studio-screen.d.ts +61 -0
- package/ui/studio-screen.js +2078 -0
- package/ui/studio-settings.d.ts +31 -0
- package/ui/studio-settings.js +288 -0
- package/ui/studio-shell.css +27 -0
- package/ui/studio-shell.d.ts +43 -0
- package/ui/studio-shell.js +87 -0
- package/ui/studio-theme.d.ts +7 -0
- package/ui/studio-theme.js +94 -0
- package/ui/studio.css +427 -0
- package/ui/theorem-mark.css +84 -0
- package/ui/theorem-mark.d.ts +22 -0
- package/ui/theorem-mark.js +21 -0
- package/vite.d.mts +30 -0
- package/vite.mjs +277 -0
- package/workspace.d.ts +230 -0
- package/workspace.js +1054 -0
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `POST <base>/decide`: one decision on lent keys. The browser authors the profile and its
|
|
3
|
+
* questions, so the server takes only the fields a studio decision compiles to, within the keys'
|
|
4
|
+
* decision limits, and checks the model, the state, and each question against the keys before it
|
|
5
|
+
* spends anything.
|
|
6
|
+
*
|
|
7
|
+
* @module
|
|
8
|
+
*/
|
|
9
|
+
import { TheoremError, validateDecisionRequest, z } from '@theoremjs/agents';
|
|
10
|
+
import { KEY_SLOT_NAME } from '@theoremjs/agents/schema';
|
|
11
|
+
import { readBody } from '@theoremjs/react/server';
|
|
12
|
+
import { runStudioDecision } from "../runtime.js";
|
|
13
|
+
import { defineDraft } from "../runtime-scope.js";
|
|
14
|
+
import { errorJson, noStoreJson } from "./draft-replies.js";
|
|
15
|
+
import { lentRoute, lentVault } from "./lent-draft.js";
|
|
16
|
+
/** The decision request lent keys answer: only the fields a studio decision compiles to, within `limits`. A setting left out stays out. */
|
|
17
|
+
export function decisionRequestSchema(limits) {
|
|
18
|
+
const name = z.string().trim().min(1).max(limits.nameChars);
|
|
19
|
+
const id = z.string().trim().min(1).max(limits.idChars);
|
|
20
|
+
const entry = z.string().trim().min(1).max(limits.criterionChars);
|
|
21
|
+
const slot = z.string().regex(KEY_SLOT_NAME);
|
|
22
|
+
const labelled = z
|
|
23
|
+
.record(name, entry)
|
|
24
|
+
.refine((record) => Object.keys(record).length > 0 && Object.keys(record).length <= limits.criteria);
|
|
25
|
+
const instructions = z.string().trim().min(1).max(limits.instructionsChars);
|
|
26
|
+
const question = z.discriminatedUnion('type', [
|
|
27
|
+
z.object({ type: z.literal('choice'), instructions, criteria: labelled }),
|
|
28
|
+
z.object({
|
|
29
|
+
type: z.literal('score'),
|
|
30
|
+
instructions,
|
|
31
|
+
criteria: z.array(entry).min(2).max(limits.criteria),
|
|
32
|
+
}),
|
|
33
|
+
z.object({ type: z.literal('noul'), instructions, criteria: labelled.optional() }),
|
|
34
|
+
z.object({
|
|
35
|
+
type: z.literal('box'),
|
|
36
|
+
instructions,
|
|
37
|
+
image: z.string().trim().min(1).max(limits.instructionsChars).optional(),
|
|
38
|
+
}),
|
|
39
|
+
]);
|
|
40
|
+
// why: Base64 is four characters for every three bytes, so the byte limit bounds the text before it is decoded.
|
|
41
|
+
const image = z.object({
|
|
42
|
+
mimeType: z.enum(['image/png', 'image/jpeg']),
|
|
43
|
+
data: z.string().max(Math.ceil(limits.imageBytes / 3) * 4),
|
|
44
|
+
});
|
|
45
|
+
return z.object({
|
|
46
|
+
profile: z.object({
|
|
47
|
+
type: z.literal('decision'),
|
|
48
|
+
id,
|
|
49
|
+
identity: z.object({ handle: name }),
|
|
50
|
+
models: z
|
|
51
|
+
.record(name, z.object({
|
|
52
|
+
protocol: z.literal('systemOne'),
|
|
53
|
+
provider: name,
|
|
54
|
+
apiId: id,
|
|
55
|
+
keySlot: slot.optional(),
|
|
56
|
+
fallbackKeySlot: slot.optional(),
|
|
57
|
+
options: z.record(z.string(), z.json()).optional(),
|
|
58
|
+
timeoutMs: z.number().int().min(1).max(limits.timeoutMs).optional(),
|
|
59
|
+
}))
|
|
60
|
+
.refine((models) => Object.keys(models).length === 1),
|
|
61
|
+
inputs: z.object({
|
|
62
|
+
state: z.literal('json'),
|
|
63
|
+
maxStateBytes: z.number().int().min(1).max(limits.stateBytes).optional(),
|
|
64
|
+
}),
|
|
65
|
+
decision: z.object({ contract: id }),
|
|
66
|
+
observability: z.record(z.string(), z.unknown()).optional(),
|
|
67
|
+
labels: z.record(z.string(), z.unknown()).optional(),
|
|
68
|
+
}),
|
|
69
|
+
questions: z
|
|
70
|
+
.record(name, question)
|
|
71
|
+
.refine((record) => Object.keys(record).length > 0 && Object.keys(record).length <= limits.questions),
|
|
72
|
+
state: z.unknown(),
|
|
73
|
+
assets: z
|
|
74
|
+
.record(name, image)
|
|
75
|
+
.refine((record) => Object.keys(record).length <= limits.images)
|
|
76
|
+
.optional(),
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
/** Answers one decision on the lent keys, with the records it wrote; a failed one is traced too. */
|
|
80
|
+
export async function draftDecide(request, options) {
|
|
81
|
+
let labels;
|
|
82
|
+
try {
|
|
83
|
+
const body = await readBody(request, decisionRequestSchema(options.runtime.keys.decision));
|
|
84
|
+
const profile = defineDraft(body.profile);
|
|
85
|
+
labels = profile.labels;
|
|
86
|
+
const selected = lentRoute('decision', profile);
|
|
87
|
+
const { keys } = options.runtime;
|
|
88
|
+
const refused = keys.violation(selected)?.message ??
|
|
89
|
+
keys.stateViolation(selected, body.state) ??
|
|
90
|
+
Object.values(body.questions)
|
|
91
|
+
.map((question) => keys.questionViolation(selected, question))
|
|
92
|
+
.find(Boolean);
|
|
93
|
+
if (refused)
|
|
94
|
+
throw new TheoremError('request', `studio decide: ${refused}`);
|
|
95
|
+
validateDecisionRequest({
|
|
96
|
+
profile: profile.id,
|
|
97
|
+
state: body.state,
|
|
98
|
+
questions: body.questions,
|
|
99
|
+
assets: body.assets,
|
|
100
|
+
signal: request.signal,
|
|
101
|
+
}, profile);
|
|
102
|
+
const vault = lentVault(options.runtime, profile, 'decide');
|
|
103
|
+
await options.spend(request);
|
|
104
|
+
const { result, traces } = await runStudioDecision({ agentId: profile.id, profile: body.profile, customTools: [], questions: body.questions }, body.state, { vault }, request.signal, body.assets);
|
|
105
|
+
return noStoreJson({ result, traces });
|
|
106
|
+
}
|
|
107
|
+
catch (err) {
|
|
108
|
+
// A failed decision is traced too; the page shows what it left.
|
|
109
|
+
return errorJson(err, labels);
|
|
110
|
+
}
|
|
111
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `POST <base>/embedding/embed`: one embedding on lent keys, with the records it wrote.
|
|
3
|
+
*
|
|
4
|
+
* @module
|
|
5
|
+
*/
|
|
6
|
+
import { TheoremError, z } from '@theoremjs/agents';
|
|
7
|
+
import { embedBodySchema, embedRequest, readBody } from '@theoremjs/react/server';
|
|
8
|
+
import { runStudioEmbedding } from "../runtime.js";
|
|
9
|
+
import { defineDraft } from "../runtime-scope.js";
|
|
10
|
+
import { errorJson, noStoreJson } from "./draft-replies.js";
|
|
11
|
+
import { lentRoute, lentVault } from "./lent-draft.js";
|
|
12
|
+
const embeddingRequestSchema = embedBodySchema.extend({
|
|
13
|
+
profile: z.record(z.string(), z.unknown()),
|
|
14
|
+
});
|
|
15
|
+
/** Embeds the input on the lent keys, once the keys allow the profile's model. */
|
|
16
|
+
export async function draftEmbedding(request, runtime) {
|
|
17
|
+
let labels;
|
|
18
|
+
try {
|
|
19
|
+
const body = await readBody(request, embeddingRequestSchema);
|
|
20
|
+
const profile = defineDraft(body.profile);
|
|
21
|
+
if (profile.type !== 'embedding') {
|
|
22
|
+
throw new TheoremError('request', 'studio embedding requires an embedding profile.');
|
|
23
|
+
}
|
|
24
|
+
labels = profile.labels;
|
|
25
|
+
const violation = runtime.keys.violation(lentRoute('embedding', profile));
|
|
26
|
+
if (violation)
|
|
27
|
+
throw new TheoremError('request', `studio embedding: ${violation.message}`);
|
|
28
|
+
lentVault(runtime, profile, 'embedding');
|
|
29
|
+
const { result, traces } = await runStudioEmbedding({ agentId: profile.id, profile: body.profile, customTools: [] }, embedRequest(body), runtime);
|
|
30
|
+
return noStoreJson({ result, traces });
|
|
31
|
+
}
|
|
32
|
+
catch (err) {
|
|
33
|
+
return errorJson(err, labels);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The studio screen's server: everything the screen asks a server for, from one handler.
|
|
3
|
+
*
|
|
4
|
+
* The screen authors each draft in the browser and sends it with every request, so this serves
|
|
5
|
+
* no project. It always answers the guardrail probe, the key test, and the tool connection test.
|
|
6
|
+
* Given lent keys, it also runs drafts on them: chats, calls, decisions, and embeddings. Without
|
|
7
|
+
* them, the screen runs on the builder's own keys in the browser, and those routes answer 404.
|
|
8
|
+
*
|
|
9
|
+
* The host keeps its own policy: which keys it lends and how much anyone may spend on them
|
|
10
|
+
* (`spend`). The handler keeps the plumbing.
|
|
11
|
+
*
|
|
12
|
+
* @module
|
|
13
|
+
*/
|
|
14
|
+
import { type ResolveHost } from '@theoremjs/agents';
|
|
15
|
+
import type { TranscriptBlock } from '@theoremjs/agents/interface';
|
|
16
|
+
import { type PageToolBroker, type SteerInbox, type TheoremSessionStore } from '@theoremjs/react/server';
|
|
17
|
+
import type { LentKeys } from '../lent-keys.ts';
|
|
18
|
+
import type { StudioRuntime } from '../runtime-scope.ts';
|
|
19
|
+
import { type ProbeEntry } from './draft-probe.ts';
|
|
20
|
+
export type { ProbeEntry } from './draft-probe.ts';
|
|
21
|
+
/** Runs on keys the host lends, and what they are held to. */
|
|
22
|
+
export type LentRuntime = StudioRuntime & {
|
|
23
|
+
mode: 'demo';
|
|
24
|
+
keys: LentKeys;
|
|
25
|
+
};
|
|
26
|
+
/** What a request spends of the host's allowance: a decision, a host tool call, or an agent tool's model turn. */
|
|
27
|
+
export type StudioSpend = 'decision' | 'call' | 'agent';
|
|
28
|
+
export type StudioDraftHandlerOptions = {
|
|
29
|
+
/**
|
|
30
|
+
* Runs on the keys the host lends: `{ mode: 'demo', keys }`, with `hostOptions` filling each
|
|
31
|
+
* profile's key slots, and the host's tool handlers. Without it, no draft runs on the server.
|
|
32
|
+
*/
|
|
33
|
+
lent?: LentRuntime;
|
|
34
|
+
/**
|
|
35
|
+
* Spends one of `kind` for whoever sent `request`, before it runs. Throw a `TheoremError` to refuse
|
|
36
|
+
* it: the screen reads the error's wording. Every decision, host tool call, and agent tool turn on
|
|
37
|
+
* the lent keys passes through it. Default: nothing is counted.
|
|
38
|
+
*/
|
|
39
|
+
spend?: (kind: StudioSpend, request: Request) => void | Promise<void>;
|
|
40
|
+
/**
|
|
41
|
+
* Resolves the names the tool connection test calls, so the network guard refuses one that
|
|
42
|
+
* answers a private address. Workers have no DNS lookup: pass `dnsOverHttpsResolver(...)`.
|
|
43
|
+
* Default: `lent.resolveHost`.
|
|
44
|
+
*/
|
|
45
|
+
resolveHost?: ResolveHost;
|
|
46
|
+
/** Gets each probed text some guardrail boundary let through, after the answer. */
|
|
47
|
+
onProbePassed?: (entry: ProbeEntry, at: Date) => Promise<void>;
|
|
48
|
+
/** Where visitor sessions are kept. Default: in memory, for this handler's lifetime. */
|
|
49
|
+
sessionStore?: TheoremSessionStore;
|
|
50
|
+
/** Where page tool results wait for their run. Default: in memory. */
|
|
51
|
+
pageToolBroker?: PageToolBroker;
|
|
52
|
+
/**
|
|
53
|
+
* Where a running chat's steers queue, by the inbox id the run sends its page. A host on several
|
|
54
|
+
* isolates needs one store they all reach. Default: in memory.
|
|
55
|
+
*/
|
|
56
|
+
steer?: SteerInbox;
|
|
57
|
+
/** The key chat conversations are sealed with. Default: a new one, for this handler's lifetime. */
|
|
58
|
+
conversationKey?: string;
|
|
59
|
+
/**
|
|
60
|
+
* True only when the handler serves the builder alone, on their own machine, as the command's
|
|
61
|
+
* does: a connection test then keeps to the draft's network guardrail, as the draft's runs do,
|
|
62
|
+
* private addresses included when it allows them. Otherwise a test reaches public hosts only,
|
|
63
|
+
* whatever the draft says, so no visitor reaches the host's own network.
|
|
64
|
+
*/
|
|
65
|
+
draftNetwork?: boolean;
|
|
66
|
+
};
|
|
67
|
+
/**
|
|
68
|
+
* Answers a request under `STUDIO_BASE`; `defer` keeps work running after the reply (a Worker's
|
|
69
|
+
* `ctx.waitUntil`). A path it does not serve answers 404.
|
|
70
|
+
*/
|
|
71
|
+
export type StudioDraftHandler = {
|
|
72
|
+
(request: Request, defer?: (work: Promise<unknown>) => void): Promise<Response>;
|
|
73
|
+
/**
|
|
74
|
+
* Opens a chat on `blocks` the host wrote, in the asking visitor's session, read first by the
|
|
75
|
+
* draft's guardrails: `{ conversation, view }`. The request body is the draft. Needs `lent`.
|
|
76
|
+
*/
|
|
77
|
+
startConversation(request: Request, blocks: readonly TranscriptBlock[]): Promise<Response>;
|
|
78
|
+
};
|
|
79
|
+
/** Where the screen sends every request: mount the handler here. */
|
|
80
|
+
export declare const STUDIO_BASE = "/api/studio";
|
|
81
|
+
/** Serves the studio screen's requests. */
|
|
82
|
+
export declare function createStudioDraftHandler(options?: StudioDraftHandlerOptions): StudioDraftHandler;
|
|
@@ -0,0 +1,213 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The studio screen's server: everything the screen asks a server for, from one handler.
|
|
3
|
+
*
|
|
4
|
+
* The screen authors each draft in the browser and sends it with every request, so this serves
|
|
5
|
+
* no project. It always answers the guardrail probe, the key test, and the tool connection test.
|
|
6
|
+
* Given lent keys, it also runs drafts on them: chats, calls, decisions, and embeddings. Without
|
|
7
|
+
* them, the screen runs on the builder's own keys in the browser, and those routes answer 404.
|
|
8
|
+
*
|
|
9
|
+
* The host keeps its own policy: which keys it lends and how much anyone may spend on them
|
|
10
|
+
* (`spend`). The handler keeps the plumbing.
|
|
11
|
+
*
|
|
12
|
+
* @module
|
|
13
|
+
*/
|
|
14
|
+
import { TheoremError, z } from '@theoremjs/agents';
|
|
15
|
+
import { clientError } from '@theoremjs/agents/host';
|
|
16
|
+
import { checkRequest, createMemoryPageToolBroker, createMemorySessionStore, createMemorySteerInbox, createSealedConversationStore, createTheoremSessionBoundary, pageToolResultSchema, readBody, steerUnitOf, theoremConversationRequestSchema, theoremHostCallRequestSchema, theoremInvokeRequestSchema, theoremRewindRequestSchema, theoremSteerRequestSchema, theoremTurnRequestSchema, } from '@theoremjs/react/server';
|
|
17
|
+
import { newConversationKey } from "../conversation-key.js";
|
|
18
|
+
import { rewindStudio, startStudioConversation, streamStudioCall, streamStudioHostInvoke, streamStudioInvoke, streamStudioTurn, studioConversation, } from "../runtime.js";
|
|
19
|
+
import { draftDecide } from "./draft-decide.js";
|
|
20
|
+
import { draftEmbedding } from "./draft-embedding.js";
|
|
21
|
+
import { draftProbe } from "./draft-probe.js";
|
|
22
|
+
import { errorJson, ndjsonEventStream } from "./draft-replies.js";
|
|
23
|
+
import { testConnection } from "./test-connection.js";
|
|
24
|
+
import { testKey } from "./test-key.js";
|
|
25
|
+
/** A draft's outline: whatever else it holds, `defineProfile` and the tool registry check when the run opens. */
|
|
26
|
+
const record = z.record(z.string(), z.unknown());
|
|
27
|
+
const structuredOutline = z.object({ id: z.string(), spec: record });
|
|
28
|
+
const draftOutline = z.looseObject({
|
|
29
|
+
profile: record,
|
|
30
|
+
customTools: z.array(record).optional(),
|
|
31
|
+
structured: structuredOutline.optional(),
|
|
32
|
+
dependencies: z
|
|
33
|
+
.array(z.looseObject({
|
|
34
|
+
profile: record,
|
|
35
|
+
customTools: z.array(record),
|
|
36
|
+
structured: structuredOutline.optional(),
|
|
37
|
+
}))
|
|
38
|
+
.optional(),
|
|
39
|
+
});
|
|
40
|
+
/** The tools a page allowed for the rest of its visit, as the browser holds them. */
|
|
41
|
+
const pagePermissions = z.array(z.string().min(1).max(128)).max(256).optional();
|
|
42
|
+
/** The labels a failed request's reply is worded with: its draft's, once the body is read. */
|
|
43
|
+
function draftLabels(draft) {
|
|
44
|
+
// The body is unchecked when most failures are caught, so the draft may hold anything.
|
|
45
|
+
return draft?.profile?.labels;
|
|
46
|
+
}
|
|
47
|
+
const notFound = () => Response.json({}, { status: 404 });
|
|
48
|
+
/** Where the screen sends every request: mount the handler here. */
|
|
49
|
+
export const STUDIO_BASE = '/api/studio';
|
|
50
|
+
/** Serves the studio screen's requests. */
|
|
51
|
+
export function createStudioDraftHandler(options = {}) {
|
|
52
|
+
const { lent, spend } = options;
|
|
53
|
+
const resolveHost = options.resolveHost ?? lent?.resolveHost;
|
|
54
|
+
const sessionStore = options.sessionStore ?? createMemorySessionStore();
|
|
55
|
+
const pageToolBroker = options.pageToolBroker ?? createMemoryPageToolBroker();
|
|
56
|
+
const steer = options.steer ?? createMemorySteerInbox();
|
|
57
|
+
const conversationStore = createSealedConversationStore({
|
|
58
|
+
keys: { 1: options.conversationKey ?? newConversationKey() },
|
|
59
|
+
keyVersion: 1,
|
|
60
|
+
});
|
|
61
|
+
const conversationsOf = (boundary) => ({
|
|
62
|
+
sessionId: boundary.sessionId,
|
|
63
|
+
store: conversationStore,
|
|
64
|
+
});
|
|
65
|
+
/** Each agent tool call runs a model turn on the lent keys, so it spends first; a refusal is what the calling model reads. */
|
|
66
|
+
const agentCall = (request) => spend &&
|
|
67
|
+
(async () => {
|
|
68
|
+
try {
|
|
69
|
+
await spend('agent', request);
|
|
70
|
+
return undefined;
|
|
71
|
+
}
|
|
72
|
+
catch (err) {
|
|
73
|
+
return { refuse: clientError(err).error };
|
|
74
|
+
}
|
|
75
|
+
});
|
|
76
|
+
/** The run's runtime: the lent keys, on this session's tool execution. */
|
|
77
|
+
const runtimeOf = (lent, boundary, request) => ({
|
|
78
|
+
...lent,
|
|
79
|
+
execution: boundary.toolExecution,
|
|
80
|
+
pageExecution: boundary.pageExecution,
|
|
81
|
+
onAgentCall: agentCall(request),
|
|
82
|
+
});
|
|
83
|
+
/** A draft as a run takes it. */
|
|
84
|
+
const draftRun = (lent, draft, boundary, request) => ({
|
|
85
|
+
profile: draft.profile,
|
|
86
|
+
customTools: draft.customTools ?? [],
|
|
87
|
+
structured: draft.structured,
|
|
88
|
+
dependencies: draft.dependencies,
|
|
89
|
+
runtime: runtimeOf(lent, boundary, request),
|
|
90
|
+
});
|
|
91
|
+
/** A draft request: its body read, its session opened, the cookie set, and a failure worded with the draft's labels. */
|
|
92
|
+
const draftRequest = async (request, handle) => {
|
|
93
|
+
let draft;
|
|
94
|
+
try {
|
|
95
|
+
draft = (await readBody(request, draftOutline));
|
|
96
|
+
const boundary = await createTheoremSessionBoundary({
|
|
97
|
+
request,
|
|
98
|
+
sessionStore,
|
|
99
|
+
pageToolBroker,
|
|
100
|
+
});
|
|
101
|
+
const response = await handle(draft, boundary);
|
|
102
|
+
if (boundary.setCookie)
|
|
103
|
+
response.headers.append('set-cookie', boundary.setCookie);
|
|
104
|
+
return response;
|
|
105
|
+
}
|
|
106
|
+
catch (err) {
|
|
107
|
+
return errorJson(err, draftLabels(draft));
|
|
108
|
+
}
|
|
109
|
+
};
|
|
110
|
+
/** A run's events, streamed, with each checkpoint the run reaches kept in the session. */
|
|
111
|
+
const stream = (boundary, draft, events) => ndjsonEventStream(recorded(boundary, events), draft.profile.labels);
|
|
112
|
+
const lentRoutes = (lent) => ({
|
|
113
|
+
turn: (request) => draftRequest(request, (draft, boundary) => stream(boundary, draft, streamStudioTurn({
|
|
114
|
+
...draftRun(lent, draft, boundary, request),
|
|
115
|
+
request: checkRequest(theoremTurnRequestSchema, draft, 'request body'),
|
|
116
|
+
conversations: conversationsOf(boundary),
|
|
117
|
+
signal: request.signal,
|
|
118
|
+
steer,
|
|
119
|
+
}))),
|
|
120
|
+
invoke: (request) => draftRequest(request, (draft, boundary) => {
|
|
121
|
+
const answer = checkRequest(theoremInvokeRequestSchema, draft, 'request body');
|
|
122
|
+
const run = draftRun(lent, draft, boundary, request);
|
|
123
|
+
return stream(boundary, draft, draft.profile.type === 'host'
|
|
124
|
+
? streamStudioHostInvoke({ ...run, answer, signal: request.signal })
|
|
125
|
+
: streamStudioInvoke({
|
|
126
|
+
...run,
|
|
127
|
+
answer,
|
|
128
|
+
conversations: conversationsOf(boundary),
|
|
129
|
+
signal: request.signal,
|
|
130
|
+
}));
|
|
131
|
+
}),
|
|
132
|
+
conversation: (request) => draftRequest(request, async (draft, boundary) => Response.json(await studioConversation(draftRun(lent, draft, boundary, request), conversationsOf(boundary), checkRequest(theoremConversationRequestSchema, draft, 'request body')))),
|
|
133
|
+
rewind: (request) => draftRequest(request, async (draft, boundary) => Response.json(await rewindStudio(draftRun(lent, draft, boundary, request), conversationsOf(boundary), checkRequest(theoremRewindRequestSchema, draft, 'request body'), request.signal))),
|
|
134
|
+
call: (request) => draftRequest(request, async (draft, boundary) => {
|
|
135
|
+
const call = checkRequest(theoremHostCallRequestSchema, draft, 'request body');
|
|
136
|
+
const sessionPermissions = checkRequest(pagePermissions, draft.sessionPermissions, 'session permissions');
|
|
137
|
+
// Counted only once the request is one a host would run.
|
|
138
|
+
await spend?.('call', request);
|
|
139
|
+
const { structured: _structured, ...run } = draftRun(lent, draft, boundary, request);
|
|
140
|
+
return stream(boundary, draft, streamStudioCall({ ...run, call, sessionPermissions, signal: request.signal }));
|
|
141
|
+
}),
|
|
142
|
+
'turn/steer': async (request) => {
|
|
143
|
+
try {
|
|
144
|
+
// The inbox the server opened for the turn is the turn id the browser steers.
|
|
145
|
+
const asked = checkRequest(theoremSteerRequestSchema, await readBody(request, z.unknown()), 'request body');
|
|
146
|
+
if (!(await steer.enqueue(asked.turnId, steerUnitOf(asked)))) {
|
|
147
|
+
// labels-exempt: internal diagnostic; the user reads session.turn_ended
|
|
148
|
+
throw new TheoremError('request', 'steer: no open run has this inbox', {
|
|
149
|
+
copy: { key: 'session.turn_ended' },
|
|
150
|
+
});
|
|
151
|
+
}
|
|
152
|
+
return Response.json({ ok: true });
|
|
153
|
+
}
|
|
154
|
+
catch (err) {
|
|
155
|
+
return errorJson(err);
|
|
156
|
+
}
|
|
157
|
+
},
|
|
158
|
+
'page-result': async (request) => {
|
|
159
|
+
try {
|
|
160
|
+
const boundary = await createTheoremSessionBoundary({
|
|
161
|
+
request,
|
|
162
|
+
sessionStore,
|
|
163
|
+
pageToolBroker,
|
|
164
|
+
});
|
|
165
|
+
await boundary.answerPageResult(await readBody(request, pageToolResultSchema));
|
|
166
|
+
const response = Response.json({ accepted: true });
|
|
167
|
+
if (boundary.setCookie)
|
|
168
|
+
response.headers.append('set-cookie', boundary.setCookie);
|
|
169
|
+
return response;
|
|
170
|
+
}
|
|
171
|
+
catch (err) {
|
|
172
|
+
return errorJson(err);
|
|
173
|
+
}
|
|
174
|
+
},
|
|
175
|
+
decide: (request) => draftDecide(request, {
|
|
176
|
+
runtime: lent,
|
|
177
|
+
spend: async (asked) => await spend?.('decision', asked),
|
|
178
|
+
}),
|
|
179
|
+
'embedding/embed': (request) => draftEmbedding(request, lent),
|
|
180
|
+
});
|
|
181
|
+
const handler = ((request, defer) => {
|
|
182
|
+
const path = new URL(request.url).pathname;
|
|
183
|
+
const route = path.startsWith(`${STUDIO_BASE}/`) ? path.slice(STUDIO_BASE.length + 1) : '';
|
|
184
|
+
const routes = {
|
|
185
|
+
probe: (asked) => draftProbe(asked, options.onProbePassed, defer ?? (() => { })),
|
|
186
|
+
'test-key': testKey,
|
|
187
|
+
'test-connection': (asked) => testConnection(asked, { resolveHost, draftNetwork: options.draftNetwork }),
|
|
188
|
+
...(lent ? lentRoutes(lent) : {}),
|
|
189
|
+
};
|
|
190
|
+
if (!Object.hasOwn(routes, route))
|
|
191
|
+
return Promise.resolve(notFound());
|
|
192
|
+
if (request.method !== 'POST')
|
|
193
|
+
return Promise.resolve(new Response(null, { status: 405 }));
|
|
194
|
+
return routes[route](request);
|
|
195
|
+
});
|
|
196
|
+
handler.startConversation = (request, blocks) => {
|
|
197
|
+
if (!lent)
|
|
198
|
+
return Promise.resolve(notFound());
|
|
199
|
+
return draftRequest(request, async (draft, boundary) => Response.json(await startStudioConversation(draftRun(lent, draft, boundary, request), conversationsOf(boundary), blocks)));
|
|
200
|
+
};
|
|
201
|
+
return handler;
|
|
202
|
+
}
|
|
203
|
+
/** The run's events, with each checkpoint it reaches kept in the visitor's session. */
|
|
204
|
+
async function* recorded(boundary, events) {
|
|
205
|
+
for await (const event of events) {
|
|
206
|
+
if (event.type === 'done' || event.type === 'provider_checkpoint') {
|
|
207
|
+
const state = event.providerState;
|
|
208
|
+
if (state)
|
|
209
|
+
await boundary.recordCheckpoint(state);
|
|
210
|
+
}
|
|
211
|
+
yield event;
|
|
212
|
+
}
|
|
213
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { type GuardrailProbeAnswer } from '../guardrail-probe.ts';
|
|
2
|
+
/** A probed text some boundary let through, and what each boundary's guardrails did with it. */
|
|
3
|
+
export type ProbeEntry = {
|
|
4
|
+
text: string;
|
|
5
|
+
/** The draft's guardrails as written. */
|
|
6
|
+
guardrails: unknown;
|
|
7
|
+
answers: readonly Pick<GuardrailProbeAnswer, 'boundary' | 'status' | 'taint' | 'guardrails' | 'passed'>[];
|
|
8
|
+
};
|
|
9
|
+
/**
|
|
10
|
+
* Runs the text across every boundary and answers with what the guardrails did at each. A text
|
|
11
|
+
* some boundary passed, run with every detector and not one of the battery's, goes to `onPassed`
|
|
12
|
+
* through `defer`, after the answer: one that fails never fails a probe.
|
|
13
|
+
*/
|
|
14
|
+
export declare function draftProbe(request: Request, onPassed: ((entry: ProbeEntry, at: Date) => Promise<void>) | undefined, defer: (work: Promise<unknown>) => void): Promise<Response>;
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `POST <base>/probe`: one text sent across every guardrail boundary of the draft, each on a
|
|
3
|
+
* scripted model, so no key is spent and no host is reached. With `only`, the draft reads with that
|
|
4
|
+
* detector alone: what the others would catch passes there.
|
|
5
|
+
*
|
|
6
|
+
* @module
|
|
7
|
+
*/
|
|
8
|
+
import { z } from '@theoremjs/agents';
|
|
9
|
+
import { readBody } from '@theoremjs/react/server';
|
|
10
|
+
import { PROBE_TEXT_LIMIT, runGuardrailProbes, } from "../guardrail-probe.js";
|
|
11
|
+
import { PROBE_BATTERY } from "../probe-battery.js";
|
|
12
|
+
import { errorJson, noStoreJson } from "./draft-replies.js";
|
|
13
|
+
function part() {
|
|
14
|
+
return z.custom((value) => typeof value === 'object' && value !== null);
|
|
15
|
+
}
|
|
16
|
+
/** The draft as every studio request carries it, and the text to probe with. The kernel checks the draft when it registers it. */
|
|
17
|
+
const probeRequestSchema = z.object({
|
|
18
|
+
profile: part(),
|
|
19
|
+
customTools: z.array(part()).optional(),
|
|
20
|
+
structured: part().optional(),
|
|
21
|
+
dependencies: z.array(part()).optional(),
|
|
22
|
+
text: z.string().min(1).max(PROBE_TEXT_LIMIT),
|
|
23
|
+
only: z.string().min(1).max(200).optional(),
|
|
24
|
+
});
|
|
25
|
+
/** A battery text is known already: what passes it is no news to a reviewer. */
|
|
26
|
+
function isBatteryText(text) {
|
|
27
|
+
return PROBE_BATTERY.some((entry) => entry.text === text);
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Runs the text across every boundary and answers with what the guardrails did at each. A text
|
|
31
|
+
* some boundary passed, run with every detector and not one of the battery's, goes to `onPassed`
|
|
32
|
+
* through `defer`, after the answer: one that fails never fails a probe.
|
|
33
|
+
*/
|
|
34
|
+
export async function draftProbe(request, onPassed, defer) {
|
|
35
|
+
let labels;
|
|
36
|
+
try {
|
|
37
|
+
const body = await readBody(request, probeRequestSchema);
|
|
38
|
+
labels = body.profile.labels;
|
|
39
|
+
const answers = await runGuardrailProbes({
|
|
40
|
+
profile: body.profile,
|
|
41
|
+
customTools: body.customTools ?? [],
|
|
42
|
+
structured: body.structured,
|
|
43
|
+
dependencies: body.dependencies,
|
|
44
|
+
text: body.text,
|
|
45
|
+
only: body.only,
|
|
46
|
+
signal: request.signal,
|
|
47
|
+
});
|
|
48
|
+
const isNews = body.only === undefined &&
|
|
49
|
+
answers.some((answer) => answer.status === 'passed') &&
|
|
50
|
+
!isBatteryText(body.text);
|
|
51
|
+
if (onPassed && isNews) {
|
|
52
|
+
defer(onPassed({ text: body.text, guardrails: body.profile.guardrails, answers }, new Date()).catch((error) => {
|
|
53
|
+
console.error('studio probe: onPassed failed', error);
|
|
54
|
+
}));
|
|
55
|
+
}
|
|
56
|
+
return noStoreJson({ answers });
|
|
57
|
+
}
|
|
58
|
+
catch (err) {
|
|
59
|
+
return errorJson(err, labels);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* How the draft server answers: a run's events as NDJSON, and a failure as JSON, each worded
|
|
3
|
+
* for a visitor.
|
|
4
|
+
*
|
|
5
|
+
* @module
|
|
6
|
+
*/
|
|
7
|
+
import type { ProfileDefinition } from '@theoremjs/agents';
|
|
8
|
+
/**
|
|
9
|
+
* NDJSON response that streams a run's events, each as a visitor may have it. A failure the run didn't turn into an event itself
|
|
10
|
+
* (one thrown before the kernel's turn starts, such as registering the profile or creating its
|
|
11
|
+
* provider) ends the stream as the kernel's own error event, as a visitor may have it: its kind's
|
|
12
|
+
* wording, from the profile's `labels` when it has one, and never the raw detail.
|
|
13
|
+
*/
|
|
14
|
+
export declare function ndjsonEventStream(source: AsyncIterable<unknown>, labels?: ProfileDefinition['labels']): Response;
|
|
15
|
+
/** A JSON reply the browser never caches. */
|
|
16
|
+
export declare function noStoreJson(body: unknown, status?: number): Response;
|
|
17
|
+
/**
|
|
18
|
+
* The reply for a failure caught before a route had anything to stream: the status of its kind,
|
|
19
|
+
* the wording a visitor may read, from the profile's `labels` when the request carried one, and
|
|
20
|
+
* the traces the failed run left, when it left any.
|
|
21
|
+
*/
|
|
22
|
+
export declare function errorJson(err: unknown, labels?: ProfileDefinition['labels']): Response;
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { toErrorEvent, withPublicLabels } from '@theoremjs/agents/guardrails';
|
|
2
|
+
import { caughtStatus, clientError, forClient } from '@theoremjs/agents/host';
|
|
3
|
+
import { failedDecisionTraces } from "../runtime.js";
|
|
4
|
+
const NDJSON_HEADERS = {
|
|
5
|
+
'content-type': 'application/x-ndjson; charset=utf-8',
|
|
6
|
+
'cache-control': 'no-store',
|
|
7
|
+
};
|
|
8
|
+
/**
|
|
9
|
+
* NDJSON response that streams a run's events, each as a visitor may have it. A failure the run didn't turn into an event itself
|
|
10
|
+
* (one thrown before the kernel's turn starts, such as registering the profile or creating its
|
|
11
|
+
* provider) ends the stream as the kernel's own error event, as a visitor may have it: its kind's
|
|
12
|
+
* wording, from the profile's `labels` when it has one, and never the raw detail.
|
|
13
|
+
*/
|
|
14
|
+
export function ndjsonEventStream(source, labels) {
|
|
15
|
+
const encoder = new TextEncoder();
|
|
16
|
+
const stream = new ReadableStream({
|
|
17
|
+
async start(controller) {
|
|
18
|
+
try {
|
|
19
|
+
for await (const event of source) {
|
|
20
|
+
const line = event.type === 'conversation'
|
|
21
|
+
? event
|
|
22
|
+
: forClient(event);
|
|
23
|
+
controller.enqueue(encoder.encode(`${JSON.stringify(line)}\n`));
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
catch (err) {
|
|
27
|
+
controller.enqueue(encoder.encode(`${JSON.stringify(forClient(withPublicLabels(toErrorEvent(err), labels)))}\n`));
|
|
28
|
+
}
|
|
29
|
+
controller.close();
|
|
30
|
+
},
|
|
31
|
+
});
|
|
32
|
+
return new Response(stream, { headers: NDJSON_HEADERS });
|
|
33
|
+
}
|
|
34
|
+
/** A JSON reply the browser never caches. */
|
|
35
|
+
export function noStoreJson(body, status = 200) {
|
|
36
|
+
return Response.json(body, { status, headers: { 'cache-control': 'no-store' } });
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* The reply for a failure caught before a route had anything to stream: the status of its kind,
|
|
40
|
+
* the wording a visitor may read, from the profile's `labels` when the request carried one, and
|
|
41
|
+
* the traces the failed run left, when it left any.
|
|
42
|
+
*/
|
|
43
|
+
export function errorJson(err, labels) {
|
|
44
|
+
const traces = failedDecisionTraces(err);
|
|
45
|
+
return noStoreJson({ ...clientError(err, labels), ...(traces.length > 0 ? { traces } : {}) }, caughtStatus(err));
|
|
46
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The second load of an open project: the files with the builder's unsaved edits laid over them,
|
|
3
|
+
* so one message can be answered by both. It starts when the page asks for it, is replaced when
|
|
4
|
+
* the edits change, and ends when the files do. It reaches the project's process only through the
|
|
5
|
+
* host it is given, so the rules can be run without one.
|
|
6
|
+
*
|
|
7
|
+
* @module
|
|
8
|
+
*/
|
|
9
|
+
import type { StudioWorkspace } from '../workspace.ts';
|
|
10
|
+
import type { ProjectEdits } from './edits.ts';
|
|
11
|
+
import type { EditedAnswer } from './save-wire.ts';
|
|
12
|
+
/** What the edited load needs from the machine. `Loaded` is one load of the project. */
|
|
13
|
+
export interface EditedHost<Loaded> {
|
|
14
|
+
/** Loads the project from disk with the edits laid over it. Throws what it printed when it does not start. */
|
|
15
|
+
load(edits: ProjectEdits): Promise<Loaded>;
|
|
16
|
+
stop(loaded: Loaded): Promise<void>;
|
|
17
|
+
/** The workspace a load opened as. */
|
|
18
|
+
opened(loaded: Loaded): StudioWorkspace;
|
|
19
|
+
}
|
|
20
|
+
export interface EditedSession<Loaded> {
|
|
21
|
+
/** Makes the running load the one that holds this workspace's edits. `saved` is the files' load. */
|
|
22
|
+
open(workspace: StudioWorkspace, saved: Loaded): Promise<EditedAnswer>;
|
|
23
|
+
/** The load that answers now, when there is one. */
|
|
24
|
+
running(): Loaded | undefined;
|
|
25
|
+
/** Ends the load: the files changed, so its edits lie over files that are gone. */
|
|
26
|
+
close(): Promise<void>;
|
|
27
|
+
}
|
|
28
|
+
export declare function createEditedSession<Loaded>(host: EditedHost<Loaded>): EditedSession<Loaded>;
|