@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,177 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A project open in the studio. A local server (`studio/server/serve.ts` in the package) hands
|
|
3
|
+
* the page the project's registered profiles and tools as a workspace, and runs each profile's
|
|
4
|
+
* own code.
|
|
5
|
+
*/
|
|
6
|
+
import { createContext, useContext } from 'react';
|
|
7
|
+
import { filesPrint, providersAtStart, } from "../../mod.js";
|
|
8
|
+
import { READ_STEPS } from "../../read-steps.js";
|
|
9
|
+
import { projectEndpoint } from "./project-address.js";
|
|
10
|
+
import { getPref } from "./studio-prefs.js";
|
|
11
|
+
/**
|
|
12
|
+
* What the project's files hold that exported code names and does not write again. A provider the
|
|
13
|
+
* builder changed is left out, so the code writes it as the studio holds it.
|
|
14
|
+
*/
|
|
15
|
+
export function projectCode(project, workspace) {
|
|
16
|
+
if (!project)
|
|
17
|
+
return undefined;
|
|
18
|
+
const kept = new Set(providersAtStart(workspace));
|
|
19
|
+
return {
|
|
20
|
+
providers: project.providerPlaces.filter((place) => kept.has(place.id)),
|
|
21
|
+
origins: project.origins.profiles,
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
export const NO_ASKS = { asked: [], inside: [] };
|
|
25
|
+
const NO_ORIGINS = { profiles: {}, tools: {}, providers: {} };
|
|
26
|
+
/** Set while the page has a project open; `null` on the website's own page. */
|
|
27
|
+
export const ProjectContext = createContext(null);
|
|
28
|
+
export function useProject() {
|
|
29
|
+
return useContext(ProjectContext);
|
|
30
|
+
}
|
|
31
|
+
/** The session for a project already open: the run page names it in its address. */
|
|
32
|
+
export function projectSession(name) {
|
|
33
|
+
return {
|
|
34
|
+
endpoint: projectEndpoint(),
|
|
35
|
+
name,
|
|
36
|
+
profiles: [],
|
|
37
|
+
providers: [],
|
|
38
|
+
problems: [],
|
|
39
|
+
modelProblems: [],
|
|
40
|
+
differences: [],
|
|
41
|
+
unheld: [],
|
|
42
|
+
shared: [],
|
|
43
|
+
unregistered: [],
|
|
44
|
+
origins: NO_ORIGINS,
|
|
45
|
+
providerPlaces: [],
|
|
46
|
+
asks: NO_ASKS,
|
|
47
|
+
print: '',
|
|
48
|
+
people: undefined,
|
|
49
|
+
peopleProblem: undefined,
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
/** Where the local server runs the profile with this id. */
|
|
53
|
+
export function projectProfileEndpoint(project, profileId) {
|
|
54
|
+
return `${project.endpoint}/profiles/${encodeURIComponent(profileId)}`;
|
|
55
|
+
}
|
|
56
|
+
async function post(project, path, body) {
|
|
57
|
+
const response = await fetch(`${project.endpoint}${path}`, {
|
|
58
|
+
method: 'POST',
|
|
59
|
+
headers: { 'content-type': 'application/json' },
|
|
60
|
+
body: JSON.stringify(body),
|
|
61
|
+
});
|
|
62
|
+
if (!response.ok)
|
|
63
|
+
throw new Error(`The studio server answered ${String(response.status)}.`);
|
|
64
|
+
return response.json();
|
|
65
|
+
}
|
|
66
|
+
/** What Save would write for this workspace: each change, and the lines of each file. Writes nothing. */
|
|
67
|
+
export function reviewSave(project, workspace) {
|
|
68
|
+
return post(project, '/save', { workspace });
|
|
69
|
+
}
|
|
70
|
+
/** Writes the changes of a review the builder read. The server checks the project and reloads it. */
|
|
71
|
+
export function writeSave(project, workspace, stamp) {
|
|
72
|
+
return post(project, '/save', { workspace, stamp });
|
|
73
|
+
}
|
|
74
|
+
/** Puts the files of the last Save back. */
|
|
75
|
+
export function undoSave(project) {
|
|
76
|
+
return post(project, '/save/undo', {});
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Starts the load that runs this workspace's edits over the project's files, when it is not the
|
|
80
|
+
* one running. Writes nothing.
|
|
81
|
+
*/
|
|
82
|
+
export function openEdited(project, workspace) {
|
|
83
|
+
return post(project, '/edited', { workspace });
|
|
84
|
+
}
|
|
85
|
+
/** Where the local server runs the profile with this id as the builder's edits make it. */
|
|
86
|
+
export function editedProfileEndpoint(project, profileId) {
|
|
87
|
+
return `${project.endpoint}/edited/profiles/${encodeURIComponent(profileId)}`;
|
|
88
|
+
}
|
|
89
|
+
/** Shows a line of one of the project's files in the editor the builder chose, or the studio command's. */
|
|
90
|
+
export function openInEditor(project, place) {
|
|
91
|
+
const editor = getPref('editor');
|
|
92
|
+
return post(project, '/open', editor ? { ...place, editor } : place);
|
|
93
|
+
}
|
|
94
|
+
async function describe() {
|
|
95
|
+
const response = await fetch(projectEndpoint());
|
|
96
|
+
if (!response.ok)
|
|
97
|
+
throw new Error(`The studio server answered ${String(response.status)}.`);
|
|
98
|
+
return response.json();
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* The project as the server describes it, after each step of its read of the files: `said` hears
|
|
102
|
+
* each as it happens. The server sends a line of JSON for each, then one holding the project.
|
|
103
|
+
*/
|
|
104
|
+
async function describeSaying(said) {
|
|
105
|
+
const response = await fetch(`${projectEndpoint()}?${READ_STEPS}`);
|
|
106
|
+
if (!response.ok || !response.body) {
|
|
107
|
+
throw new Error(`The studio server answered ${String(response.status)}.`);
|
|
108
|
+
}
|
|
109
|
+
const lines = response.body.pipeThrough(new TextDecoderStream()).getReader();
|
|
110
|
+
let kept = '';
|
|
111
|
+
let opened;
|
|
112
|
+
const take = (line) => {
|
|
113
|
+
if (!line)
|
|
114
|
+
return;
|
|
115
|
+
const read = JSON.parse(line);
|
|
116
|
+
if ('opened' in read)
|
|
117
|
+
opened = read.opened;
|
|
118
|
+
else
|
|
119
|
+
said(read);
|
|
120
|
+
};
|
|
121
|
+
for (let next = await lines.read(); !next.done; next = await lines.read()) {
|
|
122
|
+
const whole = (kept + next.value).split('\n');
|
|
123
|
+
kept = whole.pop() ?? '';
|
|
124
|
+
whole.forEach(take);
|
|
125
|
+
}
|
|
126
|
+
take(kept);
|
|
127
|
+
if (!opened)
|
|
128
|
+
throw new Error('The studio server stopped before it sent the project.');
|
|
129
|
+
return opened;
|
|
130
|
+
}
|
|
131
|
+
/** What the files say, of a project as the server describes it. */
|
|
132
|
+
function filesOf(opened) {
|
|
133
|
+
return {
|
|
134
|
+
profiles: opened.workspace.agents.map((agent) => agent.identity.agentId),
|
|
135
|
+
providers: opened.workspace.providers.map((provider) => provider.id),
|
|
136
|
+
problems: opened.problems,
|
|
137
|
+
modelProblems: opened.modelProblems ?? [],
|
|
138
|
+
differences: opened.differences ?? [],
|
|
139
|
+
unheld: opened.unheld ?? [],
|
|
140
|
+
origins: opened.origins ?? NO_ORIGINS,
|
|
141
|
+
providerPlaces: opened.providerPlaces ?? [],
|
|
142
|
+
asks: opened.asks ?? NO_ASKS,
|
|
143
|
+
print: filesPrint(opened.workspace),
|
|
144
|
+
// Set even when absent, so a setup file that stops offering people stops being offered.
|
|
145
|
+
people: opened.people,
|
|
146
|
+
peopleProblem: opened.peopleProblem,
|
|
147
|
+
...(opened.unloaded === undefined ? {} : { unloaded: opened.unloaded }),
|
|
148
|
+
};
|
|
149
|
+
}
|
|
150
|
+
/**
|
|
151
|
+
* What the project's files say now that the page does not hold as edits: the profiles they hold
|
|
152
|
+
* and the ones the studio cannot run, the settings they set in code, whose lines a Save moves,
|
|
153
|
+
* and the tools the studio makes ask. With them, the workspace the files open as.
|
|
154
|
+
*/
|
|
155
|
+
export async function readFiles() {
|
|
156
|
+
const opened = await describe();
|
|
157
|
+
return { files: filesOf(opened), workspace: opened.workspace };
|
|
158
|
+
}
|
|
159
|
+
/**
|
|
160
|
+
* The project the local server has open. `said` hears each step of the server's read of the
|
|
161
|
+
* files. Throws when no server answers.
|
|
162
|
+
*/
|
|
163
|
+
export async function openProject(said) {
|
|
164
|
+
const opened = await (said ? describeSaying(said) : describe());
|
|
165
|
+
return {
|
|
166
|
+
project: {
|
|
167
|
+
endpoint: projectEndpoint(),
|
|
168
|
+
name: opened.project,
|
|
169
|
+
shared: opened.shared ?? [],
|
|
170
|
+
unregistered: opened.unregistered ?? [],
|
|
171
|
+
...(opened.editor === undefined ? {} : { editor: opened.editor }),
|
|
172
|
+
...(opened.setup === undefined ? {} : { setup: opened.setup }),
|
|
173
|
+
...filesOf(opened),
|
|
174
|
+
},
|
|
175
|
+
workspace: opened.workspace,
|
|
176
|
+
};
|
|
177
|
+
}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Reading the studio's workspace back from this tab's sessionStorage. A kept workspace that no
|
|
3
|
+
* longer fits the current shape is set aside, and a draft kept by the one-agent studio opens as
|
|
4
|
+
* a workspace holding it.
|
|
5
|
+
*/
|
|
6
|
+
import { type StudioWorkspace } from '../../mod.ts';
|
|
7
|
+
import { type RestoredStudio } from './studio-session.ts';
|
|
8
|
+
/**
|
|
9
|
+
* The workspace this tab last kept. `discarded` when one was there but could not be read back (an
|
|
10
|
+
* older shape after a deploy, or a broken write); it is removed so the next load starts clean.
|
|
11
|
+
*/
|
|
12
|
+
export declare function restoreStudio(): {
|
|
13
|
+
kind: 'restored';
|
|
14
|
+
value: RestoredStudio;
|
|
15
|
+
} | {
|
|
16
|
+
kind: 'none' | 'discarded';
|
|
17
|
+
};
|
|
18
|
+
/**
|
|
19
|
+
* Keeps edits the project's files changed under, masked as the tab keeps a workspace, until the
|
|
20
|
+
* builder brings them back or lets them go. A reload offers them again.
|
|
21
|
+
*/
|
|
22
|
+
export declare function setAside(key: string, edits: StudioWorkspace): void;
|
|
23
|
+
/** Forgets a project's set-aside edits: the builder brought them back or let them go. */
|
|
24
|
+
export declare function dropAside(key: string): void;
|
|
25
|
+
/** The edits set aside for a project and not yet answered for, over the files as `opened`. */
|
|
26
|
+
export declare function editsAside(key: string, opened: StudioWorkspace): StudioWorkspace | undefined;
|
|
27
|
+
/**
|
|
28
|
+
* Keeps the files as the studio read them, beside the edits that stand on that reading. It says
|
|
29
|
+
* which profiles the builder removed, so a merge after a reload leaves them removed.
|
|
30
|
+
*/
|
|
31
|
+
export declare function keepReading(key: string, print: string, read: StudioWorkspace): void;
|
|
32
|
+
/** The files as the studio read them when they printed as `print`, if this tab kept that reading. */
|
|
33
|
+
export declare function keptReading(key: string, print: string | undefined): StudioWorkspace | undefined;
|
|
34
|
+
/**
|
|
35
|
+
* The edits this tab kept for a project. `restored` with the reading of the files they stand on:
|
|
36
|
+
* when the files changed since, the studio merges the change into them as it does one the
|
|
37
|
+
* builder's editor writes while the page is open. `moved` when the edits stand on no reading, so
|
|
38
|
+
* nothing says what the files changed: the files open, and the edits are set aside and handed back
|
|
39
|
+
* to be offered. Kept edits that cannot be read back are removed.
|
|
40
|
+
*/
|
|
41
|
+
export declare function restoreProject(key: string, opened: StudioWorkspace, files: string): {
|
|
42
|
+
kind: 'restored';
|
|
43
|
+
value: RestoredStudio;
|
|
44
|
+
} | {
|
|
45
|
+
kind: 'moved';
|
|
46
|
+
workspace: StudioWorkspace;
|
|
47
|
+
} | {
|
|
48
|
+
kind: 'none' | 'discarded';
|
|
49
|
+
};
|
|
@@ -0,0 +1,251 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Reading the studio's workspace back from this tab's sessionStorage. A kept workspace that no
|
|
3
|
+
* longer fits the current shape is set aside, and a draft kept by the one-agent studio opens as
|
|
4
|
+
* a workspace holding it.
|
|
5
|
+
*/
|
|
6
|
+
import { agentDraft, createBlankDraft, editedSince, STUDIO_WORKSPACE_VERSION, workspaceFromDraft, } from "../../mod.js";
|
|
7
|
+
import { CHAT_PREFIX, isRecord, session, WORKSPACE_KEY, } from "./studio-session.js";
|
|
8
|
+
import { keptTool, keptWorkspace } from "./studio-store.js";
|
|
9
|
+
const V1_DRAFT_KEY = 'theorem.studio.v1';
|
|
10
|
+
const V1_CHAT_KEY = 'theorem.studio.v1.chat';
|
|
11
|
+
/**
|
|
12
|
+
* True when `value` has every section `shape` has, all the way down, and lists, text and
|
|
13
|
+
* switches where it has them. A draft kept before the draft changed shape fails it, so it is
|
|
14
|
+
* set aside rather than compiled.
|
|
15
|
+
*/
|
|
16
|
+
function hasShapeOf(value, shape) {
|
|
17
|
+
if (Array.isArray(shape))
|
|
18
|
+
return Array.isArray(value);
|
|
19
|
+
if (typeof shape === 'string' || typeof shape === 'boolean')
|
|
20
|
+
return typeof value === typeof shape;
|
|
21
|
+
if (!isRecord(shape))
|
|
22
|
+
return true;
|
|
23
|
+
if (!isRecord(value))
|
|
24
|
+
return false;
|
|
25
|
+
return Object.entries(shape).every(([key, part]) => hasShapeOf(value[key], part));
|
|
26
|
+
}
|
|
27
|
+
function isWorkspace(value) {
|
|
28
|
+
if (!isRecord(value) || value.v !== STUDIO_WORKSPACE_VERSION)
|
|
29
|
+
return false;
|
|
30
|
+
const { agents, toolSpecs, selected, chatWith } = value;
|
|
31
|
+
if (!Array.isArray(agents) || agents.length === 0 || !Array.isArray(toolSpecs))
|
|
32
|
+
return false;
|
|
33
|
+
if (!Array.isArray(value.providers))
|
|
34
|
+
return false;
|
|
35
|
+
if (typeof selected !== 'string' || typeof chatWith !== 'string')
|
|
36
|
+
return false;
|
|
37
|
+
const { starts } = value;
|
|
38
|
+
if (!isRecord(starts) || !isRecord(starts.agents) || !isRecord(starts.tools))
|
|
39
|
+
return false;
|
|
40
|
+
if (!isRecord(starts.providers))
|
|
41
|
+
return false;
|
|
42
|
+
const blank = createBlankDraft();
|
|
43
|
+
const workspace = value;
|
|
44
|
+
return agents.every((agent) => isRecord(agent) &&
|
|
45
|
+
typeof agent.key === 'string' &&
|
|
46
|
+
isRecord(agent.tools) &&
|
|
47
|
+
Array.isArray(agent.tools.allow) &&
|
|
48
|
+
hasShapeOf(agentDraft(workspace, agent.key), blank));
|
|
49
|
+
}
|
|
50
|
+
function isStoredWorkspace(value) {
|
|
51
|
+
return (isRecord(value) &&
|
|
52
|
+
value.v === STUDIO_WORKSPACE_VERSION &&
|
|
53
|
+
isWorkspace(value.workspace) &&
|
|
54
|
+
typeof value.revision === 'number');
|
|
55
|
+
}
|
|
56
|
+
/** A one-agent draft kept before workspaces, as the studio kept it. */
|
|
57
|
+
function isV1Draft(value) {
|
|
58
|
+
return (isRecord(value) &&
|
|
59
|
+
value.v === 1 &&
|
|
60
|
+
hasShapeOf(value.draft, createBlankDraft()) &&
|
|
61
|
+
typeof value.revision === 'number' &&
|
|
62
|
+
typeof value.selectedId === 'string');
|
|
63
|
+
}
|
|
64
|
+
function parsed(store, key) {
|
|
65
|
+
const raw = store.getItem(key);
|
|
66
|
+
if (!raw)
|
|
67
|
+
return undefined;
|
|
68
|
+
try {
|
|
69
|
+
return JSON.parse(raw);
|
|
70
|
+
}
|
|
71
|
+
catch {
|
|
72
|
+
return null;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* A one-agent draft from before workspaces, as a workspace holding it. Its conversation was kept
|
|
77
|
+
* whole, before conversations were sealed, so nothing can resume it. Either way the old keys go.
|
|
78
|
+
*/
|
|
79
|
+
function migrateV1(store) {
|
|
80
|
+
const kept = parsed(store, V1_DRAFT_KEY);
|
|
81
|
+
if (kept === undefined)
|
|
82
|
+
return undefined;
|
|
83
|
+
store.removeItem(V1_DRAFT_KEY);
|
|
84
|
+
store.removeItem(V1_CHAT_KEY);
|
|
85
|
+
if (!isV1Draft(kept))
|
|
86
|
+
return 'discarded';
|
|
87
|
+
const workspace = workspaceFromDraft(kept.draft, kept.selectedId);
|
|
88
|
+
return { workspace, revision: kept.revision };
|
|
89
|
+
}
|
|
90
|
+
function forgetAll(store) {
|
|
91
|
+
store.removeItem(WORKSPACE_KEY);
|
|
92
|
+
for (const key of Object.keys(store)) {
|
|
93
|
+
if (key.startsWith(CHAT_PREFIX))
|
|
94
|
+
store.removeItem(key);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* The workspace this tab last kept. `discarded` when one was there but could not be read back (an
|
|
99
|
+
* older shape after a deploy, or a broken write); it is removed so the next load starts clean.
|
|
100
|
+
*/
|
|
101
|
+
export function restoreStudio() {
|
|
102
|
+
const store = session();
|
|
103
|
+
if (!store)
|
|
104
|
+
return { kind: 'none' };
|
|
105
|
+
const kept = parsed(store, WORKSPACE_KEY);
|
|
106
|
+
if (kept === undefined) {
|
|
107
|
+
const migrated = migrateV1(store);
|
|
108
|
+
if (migrated === 'discarded')
|
|
109
|
+
return { kind: 'discarded' };
|
|
110
|
+
return migrated ? { kind: 'restored', value: migrated } : { kind: 'none' };
|
|
111
|
+
}
|
|
112
|
+
if (isStoredWorkspace(kept)) {
|
|
113
|
+
const { workspace, revision } = kept;
|
|
114
|
+
return { kind: 'restored', value: { workspace, revision } };
|
|
115
|
+
}
|
|
116
|
+
forgetAll(store);
|
|
117
|
+
return { kind: 'discarded' };
|
|
118
|
+
}
|
|
119
|
+
const MASKED = ['endpoint', 'serverUrl', 'headersJson'];
|
|
120
|
+
/**
|
|
121
|
+
* A kept workspace with what keeping it masked put back from the files: a tool's URLs and headers,
|
|
122
|
+
* in its start and wherever the builder had not changed them. One they did change stays masked.
|
|
123
|
+
*/
|
|
124
|
+
function withFilesCredentials(kept, files) {
|
|
125
|
+
const held = new Map(files.toolSpecs.map((tool) => [tool.toolName, tool]));
|
|
126
|
+
const starts = { ...kept.starts.tools };
|
|
127
|
+
const tools = new Map(kept.toolSpecs.map((tool) => [tool.key, tool]));
|
|
128
|
+
for (const [key, start] of Object.entries(kept.starts.tools)) {
|
|
129
|
+
const file = held.get(start.toolName);
|
|
130
|
+
if (!file)
|
|
131
|
+
continue;
|
|
132
|
+
const masked = keptTool(file);
|
|
133
|
+
const now = tools.get(key);
|
|
134
|
+
const back = { ...start };
|
|
135
|
+
const next = now && { ...now };
|
|
136
|
+
for (const field of MASKED) {
|
|
137
|
+
if (file[field] === undefined || start[field] !== masked[field])
|
|
138
|
+
continue;
|
|
139
|
+
back[field] = file[field];
|
|
140
|
+
if (next && now[field] === start[field])
|
|
141
|
+
next[field] = file[field];
|
|
142
|
+
}
|
|
143
|
+
starts[key] = back;
|
|
144
|
+
if (next)
|
|
145
|
+
tools.set(key, next);
|
|
146
|
+
}
|
|
147
|
+
return {
|
|
148
|
+
...kept,
|
|
149
|
+
toolSpecs: kept.toolSpecs.map((tool) => tools.get(tool.key) ?? tool),
|
|
150
|
+
starts: { ...kept.starts, tools: starts },
|
|
151
|
+
};
|
|
152
|
+
}
|
|
153
|
+
/** Where a project's set-aside edits wait for the builder's answer. */
|
|
154
|
+
const asideKey = (key) => `${key}.aside`;
|
|
155
|
+
/**
|
|
156
|
+
* Keeps edits the project's files changed under, masked as the tab keeps a workspace, until the
|
|
157
|
+
* builder brings them back or lets them go. A reload offers them again.
|
|
158
|
+
*/
|
|
159
|
+
export function setAside(key, edits) {
|
|
160
|
+
const record = {
|
|
161
|
+
v: STUDIO_WORKSPACE_VERSION,
|
|
162
|
+
workspace: keptWorkspace(edits),
|
|
163
|
+
revision: 0,
|
|
164
|
+
};
|
|
165
|
+
try {
|
|
166
|
+
session()?.setItem(asideKey(key), JSON.stringify(record));
|
|
167
|
+
}
|
|
168
|
+
catch {
|
|
169
|
+
// Quota or a blocked store: the offer on the page still holds the edits.
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
/** Forgets a project's set-aside edits: the builder brought them back or let them go. */
|
|
173
|
+
export function dropAside(key) {
|
|
174
|
+
session()?.removeItem(asideKey(key));
|
|
175
|
+
}
|
|
176
|
+
/** The edits set aside for a project and not yet answered for, over the files as `opened`. */
|
|
177
|
+
export function editsAside(key, opened) {
|
|
178
|
+
const store = session();
|
|
179
|
+
const kept = store ? parsed(store, asideKey(key)) : undefined;
|
|
180
|
+
if (kept === undefined)
|
|
181
|
+
return undefined;
|
|
182
|
+
if (isStoredWorkspace(kept))
|
|
183
|
+
return withFilesCredentials(kept.workspace, opened);
|
|
184
|
+
dropAside(key);
|
|
185
|
+
return undefined;
|
|
186
|
+
}
|
|
187
|
+
/** Where the files a project's kept edits stand on wait, as the studio read them. */
|
|
188
|
+
const readingKey = (key) => `${key}.read`;
|
|
189
|
+
/**
|
|
190
|
+
* Keeps the files as the studio read them, beside the edits that stand on that reading. It says
|
|
191
|
+
* which profiles the builder removed, so a merge after a reload leaves them removed.
|
|
192
|
+
*/
|
|
193
|
+
export function keepReading(key, print, read) {
|
|
194
|
+
const record = {
|
|
195
|
+
v: STUDIO_WORKSPACE_VERSION,
|
|
196
|
+
workspace: keptWorkspace(read),
|
|
197
|
+
revision: 0,
|
|
198
|
+
files: print,
|
|
199
|
+
};
|
|
200
|
+
try {
|
|
201
|
+
session()?.setItem(readingKey(key), JSON.stringify(record));
|
|
202
|
+
}
|
|
203
|
+
catch {
|
|
204
|
+
// Quota or a blocked store: a profile removed here comes back after a reload.
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
/** The files as the studio read them when they printed as `print`, if this tab kept that reading. */
|
|
208
|
+
export function keptReading(key, print) {
|
|
209
|
+
const store = session();
|
|
210
|
+
const kept = store ? parsed(store, readingKey(key)) : undefined;
|
|
211
|
+
return isStoredWorkspace(kept) && kept.files === print ? kept.workspace : undefined;
|
|
212
|
+
}
|
|
213
|
+
/**
|
|
214
|
+
* The edits this tab kept for a project. `restored` with the reading of the files they stand on:
|
|
215
|
+
* when the files changed since, the studio merges the change into them as it does one the
|
|
216
|
+
* builder's editor writes while the page is open. `moved` when the edits stand on no reading, so
|
|
217
|
+
* nothing says what the files changed: the files open, and the edits are set aside and handed back
|
|
218
|
+
* to be offered. Kept edits that cannot be read back are removed.
|
|
219
|
+
*/
|
|
220
|
+
export function restoreProject(key, opened, files) {
|
|
221
|
+
const store = session();
|
|
222
|
+
if (!store)
|
|
223
|
+
return { kind: 'none' };
|
|
224
|
+
const kept = parsed(store, key);
|
|
225
|
+
if (kept === undefined)
|
|
226
|
+
return { kind: 'none' };
|
|
227
|
+
if (!isStoredWorkspace(kept)) {
|
|
228
|
+
store.removeItem(key);
|
|
229
|
+
return { kind: 'discarded' };
|
|
230
|
+
}
|
|
231
|
+
const workspace = withFilesCredentials(kept.workspace, opened);
|
|
232
|
+
if (kept.files === files) {
|
|
233
|
+
return {
|
|
234
|
+
kind: 'restored',
|
|
235
|
+
value: { workspace, revision: kept.revision, project: { key, files } },
|
|
236
|
+
};
|
|
237
|
+
}
|
|
238
|
+
// With nothing edited the files open as they are.
|
|
239
|
+
const isEdited = kept.files === undefined || editedSince(kept.workspace, kept.files);
|
|
240
|
+
if (isEdited && kept.files !== undefined) {
|
|
241
|
+
return {
|
|
242
|
+
kind: 'restored',
|
|
243
|
+
value: { workspace, revision: kept.revision, project: { key, files: kept.files } },
|
|
244
|
+
};
|
|
245
|
+
}
|
|
246
|
+
store.removeItem(key);
|
|
247
|
+
if (!isEdited)
|
|
248
|
+
return { kind: 'none' };
|
|
249
|
+
setAside(key, kept.workspace);
|
|
250
|
+
return { kind: 'moved', workspace };
|
|
251
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { type StudioRunPayload } from '../../mod.ts';
|
|
2
|
+
import { type ProjectSession } from './studio-project.ts';
|
|
3
|
+
/** What a run tab opens on: the compiled agent, and the project it belongs to if it has one. */
|
|
4
|
+
export type StudioRunOpened = {
|
|
5
|
+
payload: StudioRunPayload;
|
|
6
|
+
project: ProjectSession | null;
|
|
7
|
+
};
|
|
8
|
+
/**
|
|
9
|
+
* What the run tab at `url` opens on, or `null` when its agent is gone. The compiled agent is kept
|
|
10
|
+
* in this browser's storage under the id in the address, so this runs in the browser. `project`
|
|
11
|
+
* says whether this host can have a project open; without it, the address's project is ignored.
|
|
12
|
+
*/
|
|
13
|
+
export declare function openStudioRun(url: string, options: {
|
|
14
|
+
project: boolean;
|
|
15
|
+
}): StudioRunOpened | null;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { clearStaleStudioRuns, loadStudioRunPayload, readStudioRunIdFromUrl, } from "../../mod.js";
|
|
2
|
+
import { projectSession } from "./studio-project.js";
|
|
3
|
+
/**
|
|
4
|
+
* What the run tab at `url` opens on, or `null` when its agent is gone. The compiled agent is kept
|
|
5
|
+
* in this browser's storage under the id in the address, so this runs in the browser. `project`
|
|
6
|
+
* says whether this host can have a project open; without it, the address's project is ignored.
|
|
7
|
+
*/
|
|
8
|
+
export function openStudioRun(url, options) {
|
|
9
|
+
clearStaleStudioRuns();
|
|
10
|
+
const runId = readStudioRunIdFromUrl(url);
|
|
11
|
+
const payload = runId ? loadStudioRunPayload(runId) : null;
|
|
12
|
+
if (!payload)
|
|
13
|
+
return null;
|
|
14
|
+
const name = options.project ? new URL(url).searchParams.get('project') : null;
|
|
15
|
+
return { payload, project: name ? projectSession(name) : null };
|
|
16
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Where the studio keeps itself: this tab's sessionStorage, under the keys and in the record
|
|
3
|
+
* shape the workspace store, its restore, and the kept conversations share.
|
|
4
|
+
*/
|
|
5
|
+
import type { STUDIO_WORKSPACE_VERSION, StudioWorkspace } from '../../mod.ts';
|
|
6
|
+
export declare const WORKSPACE_KEY = "theorem.studio.v2";
|
|
7
|
+
/** A project's workspace is kept under its own name, apart from the website's and other projects'. */
|
|
8
|
+
export declare const projectKey: (name: string) => string;
|
|
9
|
+
/** One conversation per agent, under this and the agent's key. */
|
|
10
|
+
export declare const CHAT_PREFIX = "theorem.studio.v2.chat:";
|
|
11
|
+
/** A kept workspace, read back with its revision. */
|
|
12
|
+
export interface RestoredStudio {
|
|
13
|
+
workspace: StudioWorkspace;
|
|
14
|
+
revision: number;
|
|
15
|
+
/**
|
|
16
|
+
* A project's workspace: the key it is kept under, and the print of the files its starts stand
|
|
17
|
+
* on. A reload brings the edits back while the files still print the same.
|
|
18
|
+
*/
|
|
19
|
+
project?: {
|
|
20
|
+
key: string;
|
|
21
|
+
files: string;
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
/** What sessionStorage holds. */
|
|
25
|
+
export interface StoredWorkspace {
|
|
26
|
+
v: typeof STUDIO_WORKSPACE_VERSION;
|
|
27
|
+
workspace: StudioWorkspace;
|
|
28
|
+
revision: number;
|
|
29
|
+
/** For a project's workspace: the print of the files its starts stand on. */
|
|
30
|
+
files?: string;
|
|
31
|
+
}
|
|
32
|
+
/** This tab's sessionStorage, or null where there is none or it is blocked. */
|
|
33
|
+
export declare function session(): Storage | null;
|
|
34
|
+
export declare function isRecord(value: unknown): value is Record<string, unknown>;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
export const WORKSPACE_KEY = 'theorem.studio.v2';
|
|
2
|
+
/** A project's workspace is kept under its own name, apart from the website's and other projects'. */
|
|
3
|
+
export const projectKey = (name) => `${WORKSPACE_KEY}.project:${name}`;
|
|
4
|
+
/** One conversation per agent, under this and the agent's key. */
|
|
5
|
+
export const CHAT_PREFIX = 'theorem.studio.v2.chat:';
|
|
6
|
+
/** This tab's sessionStorage, or null where there is none or it is blocked. */
|
|
7
|
+
export function session() {
|
|
8
|
+
try {
|
|
9
|
+
return typeof sessionStorage === 'undefined' ? null : sessionStorage;
|
|
10
|
+
}
|
|
11
|
+
catch {
|
|
12
|
+
return null;
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
export function isRecord(value) {
|
|
16
|
+
return typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
17
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export declare const SETTINGS_SECTIONS: readonly ["files", "confirmations", "keys", "people", "project", "about"];
|
|
2
|
+
export type SettingsSection = (typeof SETTINGS_SECTIONS)[number];
|
|
3
|
+
export interface SettingsDoor {
|
|
4
|
+
/** True once a screen that shows Settings is on the page: the door opens nothing before then. */
|
|
5
|
+
ready: boolean;
|
|
6
|
+
open: boolean;
|
|
7
|
+
section: SettingsSection;
|
|
8
|
+
}
|
|
9
|
+
/** Opens Settings, on `section` when one is named and where it was left otherwise. */
|
|
10
|
+
export declare function openSettings(section?: SettingsSection): void;
|
|
11
|
+
export declare function closeSettings(): void;
|
|
12
|
+
export declare function showSettingsSection(section: SettingsSection): void;
|
|
13
|
+
/** Says a screen that shows Settings is on the page; the answer says it left. */
|
|
14
|
+
export declare function settingsScreen(): () => void;
|
|
15
|
+
export declare function useSettingsDoor(): SettingsDoor;
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Whether Settings is open, and on which section. The door to it sits in the shell's rail, away
|
|
3
|
+
* from the screen that shows it, so both read the one place here.
|
|
4
|
+
*/
|
|
5
|
+
import { useSyncExternalStore } from 'react';
|
|
6
|
+
export const SETTINGS_SECTIONS = [
|
|
7
|
+
'files',
|
|
8
|
+
'confirmations',
|
|
9
|
+
'keys',
|
|
10
|
+
'people',
|
|
11
|
+
'project',
|
|
12
|
+
'about',
|
|
13
|
+
];
|
|
14
|
+
let door = { ready: false, open: false, section: 'files' };
|
|
15
|
+
const listeners = new Set();
|
|
16
|
+
function move(next) {
|
|
17
|
+
door = { ...door, ...next };
|
|
18
|
+
for (const listener of listeners)
|
|
19
|
+
listener();
|
|
20
|
+
}
|
|
21
|
+
/** Opens Settings, on `section` when one is named and where it was left otherwise. */
|
|
22
|
+
export function openSettings(section) {
|
|
23
|
+
if (door.ready)
|
|
24
|
+
move({ open: true, ...(section ? { section } : {}) });
|
|
25
|
+
}
|
|
26
|
+
export function closeSettings() {
|
|
27
|
+
move({ open: false });
|
|
28
|
+
}
|
|
29
|
+
export function showSettingsSection(section) {
|
|
30
|
+
move({ section });
|
|
31
|
+
}
|
|
32
|
+
/** Says a screen that shows Settings is on the page; the answer says it left. */
|
|
33
|
+
export function settingsScreen() {
|
|
34
|
+
move({ ready: true });
|
|
35
|
+
return () => {
|
|
36
|
+
move({ ready: false, open: false });
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
const subscribe = (listener) => {
|
|
40
|
+
listeners.add(listener);
|
|
41
|
+
return () => {
|
|
42
|
+
listeners.delete(listener);
|
|
43
|
+
};
|
|
44
|
+
};
|
|
45
|
+
const read = () => door;
|
|
46
|
+
export function useSettingsDoor() {
|
|
47
|
+
return useSyncExternalStore(subscribe, read, read);
|
|
48
|
+
}
|