@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,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The order the loader runs in: the mark draws, a project's read is mapped on the panel as it pulls
|
|
3
|
+
* in beside the rail, the map fades, and the panel pulls in to the page. What each step does on
|
|
4
|
+
* screen is the caller's; this only decides when.
|
|
5
|
+
*/
|
|
6
|
+
/**
|
|
7
|
+
* What the loader shows: the mark drawing, the map of a project's read on the panel as it pulls in
|
|
8
|
+
* beside the rail, the map fading out, and nothing once the page has the shell.
|
|
9
|
+
*/
|
|
10
|
+
export type BootPhase = 'draw' | 'map' | 'leave' | 'done';
|
|
11
|
+
export interface Boot {
|
|
12
|
+
/** Whether a project is read for the page, and so mapped. Never with reduced motion. */
|
|
13
|
+
reads: boolean;
|
|
14
|
+
reduced: boolean;
|
|
15
|
+
/** How long the map takes to fade. */
|
|
16
|
+
fadeMs: number;
|
|
17
|
+
/** Settles when the page under the loader is on screen with its fonts. */
|
|
18
|
+
settled: Promise<unknown>;
|
|
19
|
+
/** Settles when the map has drawn every step of a read that has ended. */
|
|
20
|
+
mapDrawn: Promise<void>;
|
|
21
|
+
markDrawn(): Promise<void>;
|
|
22
|
+
/** Whether the pen has begun. Until it does, the panel is blank and there is nothing to wait out. */
|
|
23
|
+
penHasStarted(): boolean;
|
|
24
|
+
/** Pulls the panel in beside the rail. */
|
|
25
|
+
pullIn(): Promise<unknown>;
|
|
26
|
+
sleep(ms: number): Promise<void>;
|
|
27
|
+
show(phase: 'map' | 'leave'): void;
|
|
28
|
+
/** Pulls the panel in to the page's shape. Called once. */
|
|
29
|
+
reveal(): void;
|
|
30
|
+
}
|
|
31
|
+
/** Runs the loader. The function returned stops it: nothing more is shown or revealed. */
|
|
32
|
+
export declare function runBoot(boot: Boot): () => void;
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The order the loader runs in: the mark draws, a project's read is mapped on the panel as it pulls
|
|
3
|
+
* in beside the rail, the map fades, and the panel pulls in to the page. What each step does on
|
|
4
|
+
* screen is the caller's; this only decides when.
|
|
5
|
+
*/
|
|
6
|
+
/** How long the drawn mark is held before it gives way. */
|
|
7
|
+
const HOLD_MS = 90;
|
|
8
|
+
const REDUCED_HOLD_MS = 200;
|
|
9
|
+
/** Runs the loader. The function returned stops it: nothing more is shown or revealed. */
|
|
10
|
+
export function runBoot(boot) {
|
|
11
|
+
let cancelled = false;
|
|
12
|
+
let revealed = false;
|
|
13
|
+
let pulling = false;
|
|
14
|
+
const reveal = () => {
|
|
15
|
+
if (cancelled || revealed)
|
|
16
|
+
return;
|
|
17
|
+
revealed = true;
|
|
18
|
+
boot.reveal();
|
|
19
|
+
};
|
|
20
|
+
/* A project's read is drawn once the mark is, loaded or not. The mark gives way as it does for
|
|
21
|
+
any page, and the map starts on the panel as it pulls in. Settles once the panel is in. */
|
|
22
|
+
const mapped = boot.reads
|
|
23
|
+
? boot
|
|
24
|
+
.markDrawn()
|
|
25
|
+
.then(() => boot.sleep(HOLD_MS))
|
|
26
|
+
.then(() => {
|
|
27
|
+
if (cancelled || revealed)
|
|
28
|
+
return false;
|
|
29
|
+
pulling = true;
|
|
30
|
+
boot.show('map');
|
|
31
|
+
return boot.pullIn().then(() => !cancelled);
|
|
32
|
+
})
|
|
33
|
+
: Promise.resolve(false);
|
|
34
|
+
/* If the page is ready before the pen starts, no mark was ever on screen and the panel pulls in
|
|
35
|
+
at once. Once the pen has started, it finishes, and so does a map. */
|
|
36
|
+
void boot.settled
|
|
37
|
+
.then(() => {
|
|
38
|
+
if (!boot.reduced && !pulling && !boot.penHasStarted())
|
|
39
|
+
return undefined;
|
|
40
|
+
if (!boot.reads)
|
|
41
|
+
return boot.markDrawn().then(() => boot.sleep(boot.reduced ? REDUCED_HOLD_MS : HOLD_MS));
|
|
42
|
+
return mapped.then((shown) => {
|
|
43
|
+
if (!shown || cancelled)
|
|
44
|
+
return undefined;
|
|
45
|
+
return boot.mapDrawn.then(() => {
|
|
46
|
+
if (cancelled)
|
|
47
|
+
return undefined;
|
|
48
|
+
boot.show('leave');
|
|
49
|
+
return boot.sleep(boot.fadeMs);
|
|
50
|
+
});
|
|
51
|
+
});
|
|
52
|
+
})
|
|
53
|
+
.then(reveal);
|
|
54
|
+
return () => {
|
|
55
|
+
cancelled = true;
|
|
56
|
+
};
|
|
57
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { type CompiledStudio, type CompiledWorkspace, type ProjectCode, type SourceFile } from '../../mod.ts';
|
|
2
|
+
/**
|
|
3
|
+
* The workspace as files: the README, the tools, one module per agent, and the
|
|
4
|
+
* registration, then the route and component for `agent`, the one being chatted with.
|
|
5
|
+
* On a project, `project` is what its files hold that the code names and does not write again.
|
|
6
|
+
*/
|
|
7
|
+
export declare function exportFiles(workspace: CompiledWorkspace, agent: CompiledStudio, project?: ProjectCode): SourceFile[];
|
|
8
|
+
/** The files as one text, each under its path, to paste or to hand to a coding agent. */
|
|
9
|
+
export declare function exportText(files: readonly SourceFile[]): string;
|
|
10
|
+
/** The files with a brief for a coding agent: what to ask, what to install, where each file goes. */
|
|
11
|
+
export declare function llmBrief(workspace: CompiledWorkspace, agent: CompiledStudio, project?: ProjectCode): string;
|
|
@@ -0,0 +1,335 @@
|
|
|
1
|
+
import { agentModulePath, importSpecifier, workspaceSource, } from "../../mod.js";
|
|
2
|
+
const PACKAGES = [
|
|
3
|
+
'@theoremjs/agents',
|
|
4
|
+
'@theoremjs/react',
|
|
5
|
+
'zod',
|
|
6
|
+
'react',
|
|
7
|
+
'react-dom',
|
|
8
|
+
'@astryxdesign/core',
|
|
9
|
+
'@stylexjs/stylex',
|
|
10
|
+
];
|
|
11
|
+
const INSTALL = `npm install ${PACKAGES.join(' ')}`;
|
|
12
|
+
/** Where the host mounts `createTheoremHandler`; `TheoremChat`'s default endpoint. */
|
|
13
|
+
const ENDPOINT = '/api/theorem';
|
|
14
|
+
/** Where the host mounts `createTheoremDecisionHandler`; `TheoremDecision`'s default endpoint. */
|
|
15
|
+
const DECISION_ENDPOINT = '/api/decision';
|
|
16
|
+
/** Where the host mounts `createTheoremHostHandler`; `TheoremHost`'s default endpoint. */
|
|
17
|
+
const HOST_ENDPOINT = '/api/host';
|
|
18
|
+
/** Where the host mounts `createTheoremEmbeddingHandler`; `TheoremEmbedding`'s default endpoint. */
|
|
19
|
+
const EMBEDDING_ENDPOINT = '/api/embedding';
|
|
20
|
+
/** Turn profiles run through `createTheoremHandler`; live profiles run through a relay. */
|
|
21
|
+
const NOT_TURNS = new Set(['live', 'decision', 'host', 'embedding']);
|
|
22
|
+
function servesTurns({ profile }) {
|
|
23
|
+
return !NOT_TURNS.has(profile.type);
|
|
24
|
+
}
|
|
25
|
+
/** The `keySlot` and `fallbackKeySlot` an object names, when they are strings. */
|
|
26
|
+
function slotsOn(value) {
|
|
27
|
+
if (!value || typeof value !== 'object')
|
|
28
|
+
return [];
|
|
29
|
+
const { keySlot, fallbackKeySlot } = value;
|
|
30
|
+
return [keySlot, fallbackKeySlot].filter((slot) => typeof slot === 'string' && slot !== '');
|
|
31
|
+
}
|
|
32
|
+
/** Every vault slot an agent names, on the profile or on a model. */
|
|
33
|
+
function keySlots({ profile }) {
|
|
34
|
+
const models = 'models' in profile ? profile.models : {};
|
|
35
|
+
const bindings = models && typeof models === 'object' ? Object.values(models) : [];
|
|
36
|
+
return [profile, ...bindings].flatMap(slotsOn);
|
|
37
|
+
}
|
|
38
|
+
/** The vault the route reads: each slot any agent names, from `THEOREM_VAULT_<SLOT>`. The agents it calls spend keys too. */
|
|
39
|
+
function vaultSource(workspace) {
|
|
40
|
+
const slots = [...new Set(workspace.agents.flatMap(keySlots))];
|
|
41
|
+
const entries = slots.map((slot) => `${JSON.stringify(slot)}: process.env.THEOREM_VAULT_${slot.toUpperCase().replaceAll('-', '_')}`);
|
|
42
|
+
return `{ ${entries.join(', ')} }`;
|
|
43
|
+
}
|
|
44
|
+
/** The provider options the route needs, each key read from the server's environment. */
|
|
45
|
+
function providerSource(workspace) {
|
|
46
|
+
const parts = [`vault: ${vaultSource(workspace)}`];
|
|
47
|
+
return `{\n${parts.map((part) => ` ${part},`).join('\n')}\n }`;
|
|
48
|
+
}
|
|
49
|
+
/** The route file: `factory` from the server entry, built from the agent's module with `options`. */
|
|
50
|
+
/** What a route imports from the agent's module: its profile, and a decision's questions and pictures. */
|
|
51
|
+
function moduleNames(agent) {
|
|
52
|
+
if (agent.profile.type !== 'decision')
|
|
53
|
+
return ['profile'];
|
|
54
|
+
return ['profile', 'questions', ...(agent.images ? ['images'] : [])];
|
|
55
|
+
}
|
|
56
|
+
function serverFile(agent, exportName, factory, mount, options) {
|
|
57
|
+
const module = importSpecifier(agentModulePath(agent.agentId));
|
|
58
|
+
return {
|
|
59
|
+
path: 'route.ts',
|
|
60
|
+
code: `${[
|
|
61
|
+
`import { ${factory} } from '@theoremjs/react/server';`,
|
|
62
|
+
"import './theorem';",
|
|
63
|
+
`import { ${moduleNames(agent).join(', ')} } from '${module}';`,
|
|
64
|
+
'',
|
|
65
|
+
`/** ${mount} */`,
|
|
66
|
+
`export const ${exportName} = ${factory}({`,
|
|
67
|
+
...options.map((option) => ` ${option},`),
|
|
68
|
+
'});',
|
|
69
|
+
].join('\n')}\n`,
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
/** The browser file: one component that renders `component` pointed at `endpoint`. */
|
|
73
|
+
function browserFile(path, name, component, endpoint, what, props = []) {
|
|
74
|
+
const element = props.length === 0
|
|
75
|
+
? [` return <${component} endpoint="${endpoint}" />;`]
|
|
76
|
+
: [
|
|
77
|
+
' return (',
|
|
78
|
+
` <${component}`,
|
|
79
|
+
` endpoint="${endpoint}"`,
|
|
80
|
+
...props.map((prop) => ` ${prop}`),
|
|
81
|
+
' />',
|
|
82
|
+
' );',
|
|
83
|
+
];
|
|
84
|
+
return {
|
|
85
|
+
path,
|
|
86
|
+
what,
|
|
87
|
+
code: `${[
|
|
88
|
+
`import { ${component} } from '@theoremjs/react/ui';`,
|
|
89
|
+
'',
|
|
90
|
+
`export function ${name}() {`,
|
|
91
|
+
...element,
|
|
92
|
+
'}',
|
|
93
|
+
].join('\n')}\n`,
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
/** What the agent takes from its page and its server: `inputs.slots` and `inputs.context`. */
|
|
97
|
+
function pageInputs({ profile }) {
|
|
98
|
+
const inputs = 'inputs' in profile ? profile.inputs : undefined;
|
|
99
|
+
const slots = inputs && 'slots' in inputs ? (inputs.slots ?? {}) : {};
|
|
100
|
+
const context = inputs && 'context' in inputs ? inputs.context : undefined;
|
|
101
|
+
return { slots: Object.entries(slots), from: context?.from ?? [] };
|
|
102
|
+
}
|
|
103
|
+
/** The chat's prop for the tools this page answers: a function per tool, returning its output. */
|
|
104
|
+
function pageToolsProp(agent) {
|
|
105
|
+
const names = agent.customTools.flatMap((tool) => tool.type === 'function' && tool.answeredBy === 'page' ? [tool.name] : []);
|
|
106
|
+
if (names.length === 0)
|
|
107
|
+
return [];
|
|
108
|
+
return [
|
|
109
|
+
'// What this page does for each tool it answers, and the output it returns.',
|
|
110
|
+
'pageTools={{',
|
|
111
|
+
...names.map((name) => ` ${JSON.stringify(name)}: (args) => ({ output: {} }),`),
|
|
112
|
+
'}}',
|
|
113
|
+
];
|
|
114
|
+
}
|
|
115
|
+
/** The chat's props for what the page supplies: a value per slot, and its context. */
|
|
116
|
+
function pageProps(agent) {
|
|
117
|
+
const { slots, from } = pageInputs(agent);
|
|
118
|
+
const picked = slots.map(([name, allowed]) => `${JSON.stringify(name)}: ${JSON.stringify(allowed.at(0) ?? '')}`);
|
|
119
|
+
return [
|
|
120
|
+
...slots.map(([name, allowed]) => `// ${name}: ${allowed.join(' | ')}`),
|
|
121
|
+
...(slots.length > 0 ? [`slots={{ ${picked.join(', ')} }}`] : []),
|
|
122
|
+
...(from.includes('client')
|
|
123
|
+
? ['// What this page tells the agent: any JSON.', 'context={{}}']
|
|
124
|
+
: []),
|
|
125
|
+
...pageToolsProp(agent),
|
|
126
|
+
];
|
|
127
|
+
}
|
|
128
|
+
/** The route's option for what the server tells the agent, when the profile takes it. */
|
|
129
|
+
function serverContext(agent) {
|
|
130
|
+
return pageInputs(agent).from.includes('server')
|
|
131
|
+
? ['// What your server tells the agent with each request: any JSON.\n context: () => ({})']
|
|
132
|
+
: [];
|
|
133
|
+
}
|
|
134
|
+
/** A decision agent's route and its state-and-answers component. */
|
|
135
|
+
function decisionEntry(workspace, agent) {
|
|
136
|
+
return {
|
|
137
|
+
endpoint: DECISION_ENDPOINT,
|
|
138
|
+
route: serverFile(agent, 'decision', 'createTheoremDecisionHandler', `Mount at ${DECISION_ENDPOINT} and ${DECISION_ENDPOINT}/decide. The questions stay here; the browser sends only the state.`, [...moduleNames(agent), `vault: ${vaultSource(workspace)}`]),
|
|
139
|
+
ui: browserFile('AgentDecision.tsx', 'AgentDecision', 'TheoremDecision', DECISION_ENDPOINT, 'the state field and the answers'),
|
|
140
|
+
};
|
|
141
|
+
}
|
|
142
|
+
/** A host agent's route and its form-per-tool component. */
|
|
143
|
+
function hostEntry(agent) {
|
|
144
|
+
return {
|
|
145
|
+
endpoint: HOST_ENDPOINT,
|
|
146
|
+
route: serverFile(agent, 'host', 'createTheoremHostHandler', `Mount at ${HOST_ENDPOINT}/*: it describes the tools, and answers /call and /invoke. No model runs.`, ['profile']),
|
|
147
|
+
ui: browserFile('AgentHost.tsx', 'AgentHost', 'TheoremHost', HOST_ENDPOINT, 'a form per tool and its result'),
|
|
148
|
+
};
|
|
149
|
+
}
|
|
150
|
+
/** An embedding agent's route and its inputs-and-vectors component. */
|
|
151
|
+
function embeddingEntry(workspace, agent) {
|
|
152
|
+
return {
|
|
153
|
+
endpoint: EMBEDDING_ENDPOINT,
|
|
154
|
+
route: serverFile(agent, 'embedding', 'createTheoremEmbeddingHandler', `Mount at ${EMBEDDING_ENDPOINT} and ${EMBEDDING_ENDPOINT}/embed.`, ['profile', `vault: ${vaultSource(workspace)}`]),
|
|
155
|
+
ui: browserFile('AgentEmbedding.tsx', 'AgentEmbedding', 'TheoremEmbedding', EMBEDDING_ENDPOINT, 'the inputs and their vectors'),
|
|
156
|
+
};
|
|
157
|
+
}
|
|
158
|
+
/** A turn agent's route and its chat. */
|
|
159
|
+
function turnEntry(workspace, agent) {
|
|
160
|
+
return {
|
|
161
|
+
endpoint: ENDPOINT,
|
|
162
|
+
route: serverFile(agent, 'theorem', 'createTheoremHandler', `Mount at ${ENDPOINT}/*: it answers /turn, /invoke and /steer.`, ['profile', `provider: ${providerSource(workspace)}`, ...serverContext(agent)]),
|
|
163
|
+
ui: browserFile('AgentChat.tsx', 'AgentChat', 'TheoremChat', ENDPOINT, 'the chat', pageProps(agent)),
|
|
164
|
+
};
|
|
165
|
+
}
|
|
166
|
+
function entryFiles(workspace, agent) {
|
|
167
|
+
if (agent.profile.type === 'decision')
|
|
168
|
+
return decisionEntry(workspace, agent);
|
|
169
|
+
if (agent.profile.type === 'host')
|
|
170
|
+
return hostEntry(agent);
|
|
171
|
+
if (agent.profile.type === 'embedding')
|
|
172
|
+
return embeddingEntry(workspace, agent);
|
|
173
|
+
if (!servesTurns(agent))
|
|
174
|
+
return {};
|
|
175
|
+
return turnEntry(workspace, agent);
|
|
176
|
+
}
|
|
177
|
+
/** The README: what each file is, which run only on the server, and what to install. */
|
|
178
|
+
function readme(files, agent, entry) {
|
|
179
|
+
const agents = files.filter((file) => file.path.startsWith('agents/'));
|
|
180
|
+
const rows = [
|
|
181
|
+
...(files.some((file) => file.path === 'tools.ts')
|
|
182
|
+
? ['- `tools.ts` (server only): the tools the agents share.']
|
|
183
|
+
: []),
|
|
184
|
+
...agents.map((file) => `- \`${file.path}\` (server only): one agent's profile. It registers nothing.`),
|
|
185
|
+
'- `theorem.ts` (server only): registers every tool and agent, each after the agents it names. Import it once.',
|
|
186
|
+
...(entry.route
|
|
187
|
+
? [
|
|
188
|
+
`- \`route.ts\` (server only): runs \`${agent.agentId}\`, mounted at \`${entry.endpoint ?? ''}\`.`,
|
|
189
|
+
]
|
|
190
|
+
: []),
|
|
191
|
+
...(entry.ui
|
|
192
|
+
? [`- \`${entry.ui.path}\` (browser): ${entry.ui.what}, pointed at that route.`]
|
|
193
|
+
: []),
|
|
194
|
+
];
|
|
195
|
+
return `${[
|
|
196
|
+
`# ${agent.agentId}`,
|
|
197
|
+
'',
|
|
198
|
+
`Exported from the Theorem Studio: ${agents.length === 1 ? 'one agent' : `${String(agents.length)} agents`}${entry.route
|
|
199
|
+
? `, and the route and ${entry.ui ? 'component' : 'files'} for \`${agent.agentId}\``
|
|
200
|
+
: ''}.`,
|
|
201
|
+
'',
|
|
202
|
+
...rows,
|
|
203
|
+
'',
|
|
204
|
+
entry.route
|
|
205
|
+
? 'The server-only files read your keys. Nothing in them may reach the browser.'
|
|
206
|
+
: `\`${agent.agentId}\` is a ${agent.profile.type} agent: register it on your server, then run it through your own relay (see @theoremjs/react/live).`,
|
|
207
|
+
'',
|
|
208
|
+
'```bash',
|
|
209
|
+
INSTALL,
|
|
210
|
+
'```',
|
|
211
|
+
].join('\n')}\n`;
|
|
212
|
+
}
|
|
213
|
+
/**
|
|
214
|
+
* The workspace as files: the README, the tools, one module per agent, and the
|
|
215
|
+
* registration, then the route and component for `agent`, the one being chatted with.
|
|
216
|
+
* On a project, `project` is what its files hold that the code names and does not write again.
|
|
217
|
+
*/
|
|
218
|
+
export function exportFiles(workspace, agent, project) {
|
|
219
|
+
const source = workspaceSource(workspace, project).map((file) => file.path !== 'theorem.ts'
|
|
220
|
+
? file
|
|
221
|
+
: {
|
|
222
|
+
...file,
|
|
223
|
+
code: file.code.replace("baseUrl: 'http://localhost:11434/v1'", "baseUrl: (process.env.LOCAL_MODEL_URL ?? 'http://127.0.0.1:11434').replace(/\\/$/, '') + '/v1'"),
|
|
224
|
+
});
|
|
225
|
+
const entry = entryFiles(workspace, agent);
|
|
226
|
+
return [
|
|
227
|
+
{ path: 'README.md', code: readme(source, agent, entry) },
|
|
228
|
+
...source,
|
|
229
|
+
...(entry.route ? [entry.route] : []),
|
|
230
|
+
...(entry.ui ? [{ path: entry.ui.path, code: entry.ui.code }] : []),
|
|
231
|
+
];
|
|
232
|
+
}
|
|
233
|
+
/** The files as one text, each under its path, to paste or to hand to a coding agent. */
|
|
234
|
+
export function exportText(files) {
|
|
235
|
+
return files.map((file) => `// ─── ${file.path} ───\n\n${file.code.trimEnd()}\n`).join('\n');
|
|
236
|
+
}
|
|
237
|
+
/** What the brief asks before code, by the chatted agent's type. */
|
|
238
|
+
function briefQuestions(agent, tools) {
|
|
239
|
+
const type = agent.profile.type;
|
|
240
|
+
if (type === 'decision') {
|
|
241
|
+
return [
|
|
242
|
+
'- Where the state comes from: typed by a person in `TheoremDecision` (`AgentDecision.tsx`), or built by my own code, which then calls `runDecision` from `@theoremjs/agents` on the server and drops `route.ts` and `AgentDecision.tsx`.',
|
|
243
|
+
`- Which framework this app uses, and where server routes live (so the handler mounts at \`${DECISION_ENDPOINT}\`, or the path you pick).`,
|
|
244
|
+
'- Where the model keys come from: environment variables or a secrets manager.',
|
|
245
|
+
'- Who may call the route, and how many decisions each caller may make: every decision spends a key.',
|
|
246
|
+
];
|
|
247
|
+
}
|
|
248
|
+
if (type === 'host') {
|
|
249
|
+
return [
|
|
250
|
+
'- Who calls the tools: a person in `TheoremHost` (`AgentHost.tsx`), an MCP client, or my own code, which then drops `AgentHost.tsx`.',
|
|
251
|
+
`- Which framework this app uses, and where server routes live (so the handler mounts at \`${HOST_ENDPOINT}\`, or the path you pick).`,
|
|
252
|
+
"- Where each tool's keys come from, if any need them.",
|
|
253
|
+
'- Who may call the route, and how often.',
|
|
254
|
+
];
|
|
255
|
+
}
|
|
256
|
+
if (type === 'embedding') {
|
|
257
|
+
return [
|
|
258
|
+
'- Where the inputs come from: typed by a person in `TheoremEmbedding` (`AgentEmbedding.tsx`), or sent by my own code, which then calls `runEmbedding` from `@theoremjs/agents` on the server and drops `route.ts` and `AgentEmbedding.tsx`.',
|
|
259
|
+
`- Which framework this app uses, and where server routes live (so the handler mounts at \`${EMBEDDING_ENDPOINT}\`, or the path you pick).`,
|
|
260
|
+
'- Where the model keys come from: environment variables or a secrets manager.',
|
|
261
|
+
'- Where the vectors go: the store or index that keeps them, and who may call the route: every request spends a key.',
|
|
262
|
+
];
|
|
263
|
+
}
|
|
264
|
+
const turns = servesTurns(agent);
|
|
265
|
+
return [
|
|
266
|
+
...(turns
|
|
267
|
+
? [
|
|
268
|
+
'- Whether I want a UI at all, since the answer decides what you install and build:',
|
|
269
|
+
' - The package-prepared user interface (`TheoremChat`, in `AgentChat.tsx`);',
|
|
270
|
+
' - my own UI on `useTheoremChat` from `@theoremjs/react`, which gives the conversation state without the styling;',
|
|
271
|
+
' - or none: my server code calls `runTurn` from `@theoremjs/agents` directly, and `route.ts` and `AgentChat.tsx` are dropped.',
|
|
272
|
+
]
|
|
273
|
+
: []),
|
|
274
|
+
`- Which framework this app uses, and where server routes live (so the handler mounts at \`${ENDPOINT}\`, or the path you pick).`,
|
|
275
|
+
"- Where model keys come from: environment variables, a secrets manager, or each user's own key.",
|
|
276
|
+
'- Who may use the agents: anyone, or only signed-in users (the handler takes a `session` resolver).',
|
|
277
|
+
'- Whether sessions must survive restarts or span several instances (then pass a shared atomic `sessionStore` with `load` and `compareAndSwap`; a separate read followed by a write is unsafe).',
|
|
278
|
+
...(tools.length
|
|
279
|
+
? [
|
|
280
|
+
`- What each tool should really do: ${tools.join(', ')} return stand-in data today. Where does the real data come from, and what credentials does each need?`,
|
|
281
|
+
]
|
|
282
|
+
: []),
|
|
283
|
+
'- If I want a UI: where it should appear, and whether it should match an existing theme.',
|
|
284
|
+
];
|
|
285
|
+
}
|
|
286
|
+
/** The files with a brief for a coding agent: what to ask, what to install, where each file goes. */
|
|
287
|
+
export function llmBrief(workspace, agent, project) {
|
|
288
|
+
const files = exportFiles(workspace, agent, project);
|
|
289
|
+
const stubs = [
|
|
290
|
+
...new Set(workspace.agents.flatMap((each) => each.customTools
|
|
291
|
+
.filter((tool) => tool.type === 'function')
|
|
292
|
+
.map((tool) => `\`${tool.name}\``))),
|
|
293
|
+
];
|
|
294
|
+
const turns = servesTurns(agent);
|
|
295
|
+
return `# Add the Theorem agents to this app
|
|
296
|
+
|
|
297
|
+
The files below were exported from the Theorem Studio: ${workspace.agents.map((each) => `\`${each.agentId}\``).join(', ')}, the tools they share, the registration that wires them together${files.some((file) => file.path === 'route.ts')
|
|
298
|
+
? `, and a server route and package-prepared user interface for \`${agent.agentId}\``
|
|
299
|
+
: ''}. The README says what each file is. Wire them into this codebase.
|
|
300
|
+
|
|
301
|
+
## Before you write code, ask me
|
|
302
|
+
${briefQuestions(agent, stubs).join('\n')}
|
|
303
|
+
|
|
304
|
+
## Install
|
|
305
|
+
${turns
|
|
306
|
+
? `Install only what my answer about the UI needs:
|
|
307
|
+
- No UI: \`npm install @theoremjs/agents zod\`
|
|
308
|
+
- My own UI: \`npm install @theoremjs/agents @theoremjs/react zod react react-dom\`
|
|
309
|
+
- The package-prepared user interface: \`${INSTALL}\``
|
|
310
|
+
: `\`\`\`bash
|
|
311
|
+
${INSTALL}
|
|
312
|
+
\`\`\``}
|
|
313
|
+
|
|
314
|
+
## Organise it
|
|
315
|
+
- Keep the layout: \`tools.ts\`, \`agents/\` and \`theorem.ts\` together in one server-only folder. Each agent has one module, so its profile has one source of truth.
|
|
316
|
+
- Import \`theorem.ts\` once, before anything runs an agent. Keep its order: an agent is registered after the agents it calls or that summarise for it, and an agent tool after the agent it runs.
|
|
317
|
+
|
|
318
|
+
## Do
|
|
319
|
+
- Read model keys on the server only, from the environment or a secrets manager.
|
|
320
|
+
- Keep \`registerProfile\`, \`registerTool\` and the handler in server-only modules; the browser imports only \`@theoremjs/react\`, \`/ui\` or \`/live\`.
|
|
321
|
+
- Replace each function tool's stand-in handler with the real call; its input is already checked against the Zod schema given.
|
|
322
|
+
- Change an agent's settings in its own module, or in the studio and export again.
|
|
323
|
+
|
|
324
|
+
## Don't
|
|
325
|
+
- Don't import \`tools.ts\`, \`agents/\`, \`theorem.ts\` or \`route.ts\` from browser code, or put a key in a \`VITE_\`, \`NEXT_PUBLIC_\` or other client variable.
|
|
326
|
+
- Don't log request bodies or tool credentials; the handler keeps credentials per session, off the wire.
|
|
327
|
+
- Don't copy a profile into several places.
|
|
328
|
+
- Don't turn off an agent's guardrails to make a test pass.
|
|
329
|
+
|
|
330
|
+
## The files
|
|
331
|
+
\`\`\`tsx
|
|
332
|
+
${exportText(files).trimEnd()}
|
|
333
|
+
\`\`\`
|
|
334
|
+
`;
|
|
335
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Studio tree icons for PROFILE_GRAPH facets. Docs chapters reuse this
|
|
3
|
+
* map so a section does not grow a second glyph.
|
|
4
|
+
*/
|
|
5
|
+
export declare const FACET_ICON: {
|
|
6
|
+
identity: import("react").ForwardRefExoticComponent<import("@tabler/icons-react").IconProps & import("react").RefAttributes<SVGSVGElement>>;
|
|
7
|
+
models: import("react").ForwardRefExoticComponent<import("@tabler/icons-react").IconProps & import("react").RefAttributes<SVGSVGElement>>;
|
|
8
|
+
modelBinding: import("react").ForwardRefExoticComponent<import("@tabler/icons-react").IconProps & import("react").RefAttributes<SVGSVGElement>>;
|
|
9
|
+
tools: import("react").ForwardRefExoticComponent<import("@tabler/icons-react").IconProps & import("react").RefAttributes<SVGSVGElement>>;
|
|
10
|
+
inputs: import("react").ForwardRefExoticComponent<import("@tabler/icons-react").IconProps & import("react").RefAttributes<SVGSVGElement>>;
|
|
11
|
+
outputs: import("react").ForwardRefExoticComponent<import("@tabler/icons-react").IconProps & import("react").RefAttributes<SVGSVGElement>>;
|
|
12
|
+
turnBehaviour: import("react").ForwardRefExoticComponent<import("@tabler/icons-react").IconProps & import("react").RefAttributes<SVGSVGElement>>;
|
|
13
|
+
guardrails: import("react").ForwardRefExoticComponent<import("@tabler/icons-react").IconProps & import("react").RefAttributes<SVGSVGElement>>;
|
|
14
|
+
observability: import("react").ForwardRefExoticComponent<import("@tabler/icons-react").IconProps & import("react").RefAttributes<SVGSVGElement>>;
|
|
15
|
+
labels: import("react").ForwardRefExoticComponent<import("@tabler/icons-react").IconProps & import("react").RefAttributes<SVGSVGElement>>;
|
|
16
|
+
image: import("react").ForwardRefExoticComponent<import("@tabler/icons-react").IconProps & import("react").RefAttributes<SVGSVGElement>>;
|
|
17
|
+
speech: import("react").ForwardRefExoticComponent<import("@tabler/icons-react").IconProps & import("react").RefAttributes<SVGSVGElement>>;
|
|
18
|
+
live: import("react").ForwardRefExoticComponent<import("@tabler/icons-react").IconProps & import("react").RefAttributes<SVGSVGElement>>;
|
|
19
|
+
decision: import("react").ForwardRefExoticComponent<import("@tabler/icons-react").IconProps & import("react").RefAttributes<SVGSVGElement>>;
|
|
20
|
+
};
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Studio tree icons for PROFILE_GRAPH facets. Docs chapters reuse this
|
|
3
|
+
* map so a section does not grow a second glyph.
|
|
4
|
+
*/
|
|
5
|
+
import { IconActivity, IconCpu, IconFileExport, IconFileImport, IconGavel, IconHeadset, IconId, IconPhoto, IconQuote, IconRepeat, IconShieldCheck, IconStack2, IconTool, IconVolume, } from '@tabler/icons-react';
|
|
6
|
+
export const FACET_ICON = {
|
|
7
|
+
identity: IconId,
|
|
8
|
+
models: IconStack2,
|
|
9
|
+
modelBinding: IconCpu,
|
|
10
|
+
tools: IconTool,
|
|
11
|
+
inputs: IconFileImport,
|
|
12
|
+
outputs: IconFileExport,
|
|
13
|
+
turnBehaviour: IconRepeat,
|
|
14
|
+
guardrails: IconShieldCheck,
|
|
15
|
+
observability: IconActivity,
|
|
16
|
+
labels: IconQuote,
|
|
17
|
+
image: IconPhoto,
|
|
18
|
+
speech: IconVolume,
|
|
19
|
+
live: IconHeadset,
|
|
20
|
+
decision: IconGavel,
|
|
21
|
+
};
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/** A phone's panel already takes the frame, and reduced motion moves nothing. */
|
|
2
|
+
export declare function panelCanMove(): boolean;
|
|
3
|
+
/**
|
|
4
|
+
* Move the panel around `swap`, which puts the next view on screen and must have drawn it by the
|
|
5
|
+
* time it returns. `widens` is the map or Settings opening; otherwise it is closing. Without a
|
|
6
|
+
* panel to move, the swap happens at once.
|
|
7
|
+
*/
|
|
8
|
+
export declare function movePanel(widens: boolean, swap: () => void): Promise<void>;
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The panel takes the whole frame for the map or Settings, and gives it back. The preview eases
|
|
3
|
+
* out, the panel's far edge moves over the room it gave up, and the map or Settings eases in as it
|
|
4
|
+
* is uncovered. The tree and the editor stay where they are.
|
|
5
|
+
*/
|
|
6
|
+
import { HOLD_MS, prefersReducedMotion, sleep } from "../shell-motion.js";
|
|
7
|
+
const MOVE_MS = 640;
|
|
8
|
+
const FADE_MS = 280;
|
|
9
|
+
const EASE = 'cubic-bezier(0.45, 0.02, 0.15, 1)';
|
|
10
|
+
/** What fades out before the move and back in after it: the preview and the panel's handle. */
|
|
11
|
+
const PARTS = '.studio-preview, .studio-side-handle';
|
|
12
|
+
/** What eases in as the panel extends over it: the map, or Settings' list and body under its headers. */
|
|
13
|
+
const INCOMING = '.studio-map-pane, .studio-settings-tree, .studio-settings-body';
|
|
14
|
+
/** A phone's panel already takes the frame, and reduced motion moves nothing. */
|
|
15
|
+
export function panelCanMove() {
|
|
16
|
+
return globalThis.matchMedia('(min-width: 768px)').matches && !prefersReducedMotion();
|
|
17
|
+
}
|
|
18
|
+
/** A tab in the background runs no animation, so each one is also given its time and no longer. */
|
|
19
|
+
function ended(animations, ms) {
|
|
20
|
+
const all = Promise.all(animations.map((each) => each.finished.catch(() => undefined)));
|
|
21
|
+
return Promise.race([all, sleep(ms + 200)]);
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Move the panel around `swap`, which puts the next view on screen and must have drawn it by the
|
|
25
|
+
* time it returns. `widens` is the map or Settings opening; otherwise it is closing. Without a
|
|
26
|
+
* panel to move, the swap happens at once.
|
|
27
|
+
*/
|
|
28
|
+
export async function movePanel(widens, swap) {
|
|
29
|
+
const frame = document.querySelector('.studio-frame');
|
|
30
|
+
const surface = frame?.querySelector('[data-shell-frame]');
|
|
31
|
+
if (!frame || !surface || !panelCanMove()) {
|
|
32
|
+
swap();
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
35
|
+
const parts = () => [...frame.querySelectorAll(PARTS)];
|
|
36
|
+
const hidden = parts().map((part) => part.animate({ opacity: [1, 0] }, { duration: HOLD_MS, easing: 'ease', fill: 'forwards' }));
|
|
37
|
+
await ended(hidden, HOLD_MS);
|
|
38
|
+
// The panel is drawn at its full width, cut back to the width it rests at: only the cut moves.
|
|
39
|
+
// The corners are the raised surface's own, which the frame wraps.
|
|
40
|
+
const drawn = surface.firstElementChild ?? surface;
|
|
41
|
+
const round = getComputedStyle(drawn).borderTopRightRadius || '0px';
|
|
42
|
+
const cut = (width) => `inset(0 calc(100% - ${String(width)}px) 0 0 round ${round})`;
|
|
43
|
+
const whole = `inset(0 0 0 0 round ${round})`;
|
|
44
|
+
if (widens) {
|
|
45
|
+
const narrow = surface.offsetWidth;
|
|
46
|
+
surface.dataset.rests = String(narrow);
|
|
47
|
+
const move = surface.animate({ clipPath: [cut(narrow), whole] }, { duration: MOVE_MS, easing: EASE, fill: 'both' });
|
|
48
|
+
swap();
|
|
49
|
+
const incoming = frame.querySelectorAll(INCOMING);
|
|
50
|
+
const fades = [...incoming].map((each) => each.animate({ opacity: [0, 1] }, { duration: MOVE_MS, easing: EASE, fill: 'both' }));
|
|
51
|
+
await ended([move, ...fades], MOVE_MS);
|
|
52
|
+
move.cancel();
|
|
53
|
+
for (const each of fades)
|
|
54
|
+
each.cancel();
|
|
55
|
+
}
|
|
56
|
+
else {
|
|
57
|
+
const narrow = Number(surface.dataset.rests);
|
|
58
|
+
delete surface.dataset.rests;
|
|
59
|
+
if (narrow > 0) {
|
|
60
|
+
const move = surface.animate({ clipPath: [whole, cut(narrow)] }, { duration: MOVE_MS, easing: EASE, fill: 'both' });
|
|
61
|
+
await ended([move], MOVE_MS);
|
|
62
|
+
swap();
|
|
63
|
+
move.cancel();
|
|
64
|
+
}
|
|
65
|
+
else {
|
|
66
|
+
swap();
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
for (const part of parts()) {
|
|
70
|
+
part.animate({ opacity: [0, 1] }, { duration: FADE_MS, easing: EASE });
|
|
71
|
+
}
|
|
72
|
+
for (const each of hidden)
|
|
73
|
+
each.cancel();
|
|
74
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Where the page finds the project's local server. The studio's own page is told in its document,
|
|
3
|
+
* by the command that started both; any other page looks where the first studio on this machine
|
|
4
|
+
* listens.
|
|
5
|
+
*/
|
|
6
|
+
export declare const PROJECT_META = "theorem-studio-project";
|
|
7
|
+
export declare const FIRST_PROJECT_ENDPOINT = "http://127.0.0.1:4983/api/studio";
|
|
8
|
+
export declare function projectEndpoint(): string;
|
|
9
|
+
/**
|
|
10
|
+
* Where the screen's own requests go: the guardrail probe and the key and connection tests. The
|
|
11
|
+
* studio's own page has no server of its own, so they go to the project's; any other page answers
|
|
12
|
+
* them itself, under `/api/studio`.
|
|
13
|
+
*/
|
|
14
|
+
export declare function screenEndpoint(): string;
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Where the page finds the project's local server. The studio's own page is told in its document,
|
|
3
|
+
* by the command that started both; any other page looks where the first studio on this machine
|
|
4
|
+
* listens.
|
|
5
|
+
*/
|
|
6
|
+
export const PROJECT_META = 'theorem-studio-project';
|
|
7
|
+
export const FIRST_PROJECT_ENDPOINT = 'http://127.0.0.1:4983/api/studio';
|
|
8
|
+
export function projectEndpoint() {
|
|
9
|
+
if (typeof document === 'undefined')
|
|
10
|
+
return FIRST_PROJECT_ENDPOINT;
|
|
11
|
+
return (document.querySelector(`meta[name="${PROJECT_META}"]`)?.content ??
|
|
12
|
+
FIRST_PROJECT_ENDPOINT);
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Where the screen's own requests go: the guardrail probe and the key and connection tests. The
|
|
16
|
+
* studio's own page has no server of its own, so they go to the project's; any other page answers
|
|
17
|
+
* them itself, under `/api/studio`.
|
|
18
|
+
*/
|
|
19
|
+
export function screenEndpoint() {
|
|
20
|
+
if (typeof document === 'undefined')
|
|
21
|
+
return '/api/studio';
|
|
22
|
+
return (document.querySelector(`meta[name="${PROJECT_META}"]`)?.content ??
|
|
23
|
+
'/api/studio');
|
|
24
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The studio's page can be opened a moment before the project's server listens: one command starts
|
|
3
|
+
* both. Nothing answering is then a server still starting, so the page asks again until one does.
|
|
4
|
+
*/
|
|
5
|
+
export interface Clock {
|
|
6
|
+
now(): number;
|
|
7
|
+
wait(ms: number): Promise<void>;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* What `open` resolves to, asking again while nothing answers. Throws what `open` last threw when
|
|
11
|
+
* a server answers badly, or when none has answered by the time one would have started.
|
|
12
|
+
*/
|
|
13
|
+
export declare function onceAnswering<T>(open: () => Promise<T>, clock?: Clock): Promise<T>;
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The studio's page can be opened a moment before the project's server listens: one command starts
|
|
3
|
+
* both. Nothing answering is then a server still starting, so the page asks again until one does.
|
|
4
|
+
*/
|
|
5
|
+
/** How long a server has to start listening, and how often the page asks. */
|
|
6
|
+
const STARTING_MS = 10_000;
|
|
7
|
+
const EVERY_MS = 200;
|
|
8
|
+
const CLOCK = {
|
|
9
|
+
now: () => performance.now(),
|
|
10
|
+
wait: (ms) => new Promise((resolve) => setTimeout(resolve, ms)),
|
|
11
|
+
};
|
|
12
|
+
/** A fetch that reached nothing throws a TypeError; a server that answered badly throws something else. */
|
|
13
|
+
const nothingAnswered = (error) => error instanceof TypeError;
|
|
14
|
+
/**
|
|
15
|
+
* What `open` resolves to, asking again while nothing answers. Throws what `open` last threw when
|
|
16
|
+
* a server answers badly, or when none has answered by the time one would have started.
|
|
17
|
+
*/
|
|
18
|
+
export async function onceAnswering(open, clock = CLOCK) {
|
|
19
|
+
const until = clock.now() + STARTING_MS;
|
|
20
|
+
for (;;) {
|
|
21
|
+
try {
|
|
22
|
+
return await open();
|
|
23
|
+
}
|
|
24
|
+
catch (error) {
|
|
25
|
+
if (!nothingAnswered(error) || clock.now() >= until)
|
|
26
|
+
throw error;
|
|
27
|
+
await clock.wait(EVERY_MS);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
}
|