@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
package/runtime.js
ADDED
|
@@ -0,0 +1,387 @@
|
|
|
1
|
+
import { labelText, registerTraceDestination, resolveObservabilityPolicy, TheoremError, z, } from '@theoremjs/agents';
|
|
2
|
+
import { gatedToolsFromEvents, interfaceFromProfile, promotedToolIdsFromEvents, toolSnapshotFromEvents, } from '@theoremjs/agents/interface';
|
|
3
|
+
import { answerGatedCall, memoryCredentialSource, } from '@theoremjs/agents/kernel';
|
|
4
|
+
import { decisionAssets, withFailedTraces, } from '@theoremjs/react/client';
|
|
5
|
+
import { answerReply, checkRequest, conversationView, messageReply, openConversation, postedMessage, readerConversationHost, rewindConversation, startConversation, statelessRefusal, steerStage, waitingCalls, } from '@theoremjs/react/server';
|
|
6
|
+
import { STUDIO_TRACE_DESTINATION } from "./policy.js";
|
|
7
|
+
import { studioReader } from "./reader.js";
|
|
8
|
+
import { agentCallHook, runtimeProvider, studioScope, } from "./runtime-scope.js";
|
|
9
|
+
import { createStudioTraceRouter } from "./traces.js";
|
|
10
|
+
// Profiles that write to the studio destination get their records back on the run's own stream.
|
|
11
|
+
export const studioTraces = createStudioTraceRouter();
|
|
12
|
+
registerTraceDestination(STUDIO_TRACE_DESTINATION, studioTraces.sink);
|
|
13
|
+
/**
|
|
14
|
+
* Streams one run's lines, then the trace records it wrote. The kernel writes
|
|
15
|
+
* a run's records before the run returns or throws, so a failed run still
|
|
16
|
+
* delivers them ahead of its failure.
|
|
17
|
+
*/
|
|
18
|
+
async function* withRunTraces(run) {
|
|
19
|
+
const records = [];
|
|
20
|
+
const traces = studioTraces.route((record) => records.push(record));
|
|
21
|
+
let failure;
|
|
22
|
+
try {
|
|
23
|
+
yield* run(traces.metadata);
|
|
24
|
+
}
|
|
25
|
+
catch (error) {
|
|
26
|
+
failure = { error };
|
|
27
|
+
}
|
|
28
|
+
finally {
|
|
29
|
+
traces.close();
|
|
30
|
+
}
|
|
31
|
+
for (const record of records)
|
|
32
|
+
yield { type: 'trace', record };
|
|
33
|
+
if (failure)
|
|
34
|
+
throw failure.error;
|
|
35
|
+
}
|
|
36
|
+
function assertNotLiveProfile(profileType, action) {
|
|
37
|
+
if (profileType === 'live') {
|
|
38
|
+
throw new TheoremError('request', `Studio ${action} does not support live profiles.`);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
export { newConversationKey } from "./conversation-key.js";
|
|
42
|
+
/** The draft's scope and its chat: the conversation host, or none for a stateless profile. */
|
|
43
|
+
async function studioChat(draft, conversations) {
|
|
44
|
+
const { scope, profile } = await studioScope(draft.profile, draft.customTools, draft.structured, draft.runtime, draft.dependencies);
|
|
45
|
+
assertNotLiveProfile(profile.type, 'turn runner — use runSession');
|
|
46
|
+
const iface = interfaceFromProfile(profile, scope.tools);
|
|
47
|
+
if (iface.type === 'live') {
|
|
48
|
+
// labels-exempt: internal diagnostic; the user reads error.request
|
|
49
|
+
throw new TheoremError('request', 'A studio chat does not run a live profile.');
|
|
50
|
+
}
|
|
51
|
+
const host = iface.providerContinuation?.history === 'stateless'
|
|
52
|
+
? undefined
|
|
53
|
+
: readerConversationHost({
|
|
54
|
+
...conversations,
|
|
55
|
+
profile,
|
|
56
|
+
clientEvents: studioReader(draft.runtime),
|
|
57
|
+
});
|
|
58
|
+
return { scope, profile, iface, host };
|
|
59
|
+
}
|
|
60
|
+
/** How a chat request runs the model for a reply, on the draft's scope. */
|
|
61
|
+
function studioRunner(args) {
|
|
62
|
+
const { scope, profile, runtime, metadata, signal } = args;
|
|
63
|
+
return {
|
|
64
|
+
run: (turn) => scope.runTurn({
|
|
65
|
+
profile: profile.id,
|
|
66
|
+
execution: runtime.execution,
|
|
67
|
+
pageExecution: runtime.pageExecution,
|
|
68
|
+
metadata,
|
|
69
|
+
input: turn.input,
|
|
70
|
+
providerState: turn.providerState,
|
|
71
|
+
sessionPermissions: args.sessionPermissions,
|
|
72
|
+
resolveHost: runtime.resolveHost,
|
|
73
|
+
signal,
|
|
74
|
+
...(turn.model ? { model: turn.model } : {}),
|
|
75
|
+
...(turn.effort ? { effort: turn.effort } : {}),
|
|
76
|
+
...(args.onStage ? { onStage: args.onStage } : {}),
|
|
77
|
+
onAgentCall: agentCallHook(scope, runtime),
|
|
78
|
+
}, runtimeProvider(runtime, scope, profile, turn.model)),
|
|
79
|
+
async compact(history, tokens, model) {
|
|
80
|
+
const compacted = await scope.compactHistory({ profile: profile.id, history, tokens, signal, ...(model ? { model } : {}) }, runtimeProvider(runtime, scope, profile, model));
|
|
81
|
+
return compacted?.history;
|
|
82
|
+
},
|
|
83
|
+
...(args.model ? { model: args.model } : {}),
|
|
84
|
+
...(args.effort ? { effort: args.effort } : {}),
|
|
85
|
+
signal,
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* The paused call as the stored reply holds it, answered. The studio keeps no
|
|
90
|
+
* session, so the call's gate comes from the draft's registered tool; only the
|
|
91
|
+
* permissions the page granted come from the browser.
|
|
92
|
+
*/
|
|
93
|
+
function answerPaused(scope, profile, opened, request, sessionPermissions, runtime) {
|
|
94
|
+
const events = opened.conversation.paused?.events ?? [];
|
|
95
|
+
const call = gatedToolsFromEvents(events).find((gated) => gated.callId === request.callId && gated.operationId === request.operationId);
|
|
96
|
+
// labels-exempt: internal diagnostic; the user reads error.internal
|
|
97
|
+
if (!call)
|
|
98
|
+
throw new TheoremError('internal', `the paused reply holds no call ${request.callId}`);
|
|
99
|
+
return answerReplayed(scope, profile, request, {
|
|
100
|
+
name: call.name,
|
|
101
|
+
input: call.arguments,
|
|
102
|
+
gateKind: call.gateKind,
|
|
103
|
+
snapshot: toolSnapshotFromEvents(events),
|
|
104
|
+
promoted: promotedToolIdsFromEvents(events),
|
|
105
|
+
...(opened.conversation.paused?.model ? { model: opened.conversation.paused.model } : {}),
|
|
106
|
+
...(sessionPermissions ? { sessionPermissions } : {}),
|
|
107
|
+
}, runtime);
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* One message, run against the conversation the host keeps: the paused calls it
|
|
111
|
+
* walks away from settle first, then the reply runs.
|
|
112
|
+
*/
|
|
113
|
+
export async function* streamStudioTurn(args) {
|
|
114
|
+
const { request, runtime, signal } = args;
|
|
115
|
+
const { scope, profile, iface, host } = await studioChat(args, args.conversations);
|
|
116
|
+
const message = postedMessage(iface, request.input);
|
|
117
|
+
const sessionPermissions = request.replay?.sessionPermissions;
|
|
118
|
+
if (!host && request.conversation !== undefined)
|
|
119
|
+
throw statelessRefusal('continue');
|
|
120
|
+
if (!host && request.abandon)
|
|
121
|
+
throw statelessRefusal('walk away from');
|
|
122
|
+
const opened = host
|
|
123
|
+
? await openConversation(host, request.conversation, { kind: 'message', ...(request.abandon ? { abandon: request.abandon } : {}) },
|
|
124
|
+
// why: The draft is the visitor's own, so the page's transcript is as much theirs as the store's copy.
|
|
125
|
+
request.transcript ? { profile, blocks: request.transcript } : undefined)
|
|
126
|
+
: undefined;
|
|
127
|
+
// Answered up front, so a refused call starts nothing.
|
|
128
|
+
const walked = opened
|
|
129
|
+
? (request.abandon ?? []).map((reference) => ({
|
|
130
|
+
reference,
|
|
131
|
+
invoke: answerPaused(scope, profile.id, opened, { ...reference, decision: 'abandon' }, sessionPermissions, runtime),
|
|
132
|
+
}))
|
|
133
|
+
: [];
|
|
134
|
+
// Random and picked here, so only the run's own browser can steer it.
|
|
135
|
+
const inbox = globalThis.crypto.randomUUID();
|
|
136
|
+
await args.steer.open(inbox);
|
|
137
|
+
const steerLine = { type: 'steer_inbox', inbox };
|
|
138
|
+
yield steerLine;
|
|
139
|
+
try {
|
|
140
|
+
yield* withRunTraces((metadata) => {
|
|
141
|
+
const runner = studioRunner({
|
|
142
|
+
scope,
|
|
143
|
+
profile,
|
|
144
|
+
runtime,
|
|
145
|
+
metadata,
|
|
146
|
+
sessionPermissions,
|
|
147
|
+
...(request.model ? { model: request.model } : {}),
|
|
148
|
+
...(request.effort ? { effort: request.effort } : {}),
|
|
149
|
+
signal,
|
|
150
|
+
onStage: steerStage(args.steer, inbox),
|
|
151
|
+
});
|
|
152
|
+
if (!host || !opened) {
|
|
153
|
+
return runner.run({ input: message.input, model: request.model, effort: request.effort });
|
|
154
|
+
}
|
|
155
|
+
const walkAway = walked.map(({ reference, invoke }) => ({
|
|
156
|
+
...reference,
|
|
157
|
+
events: scope.invokeTool({ ...invoke, metadata, signal }),
|
|
158
|
+
}));
|
|
159
|
+
return messageReply({ host, opened, message, walkAway, runner });
|
|
160
|
+
});
|
|
161
|
+
}
|
|
162
|
+
finally {
|
|
163
|
+
await args.steer.close(inbox);
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
/** The model's input to the paused call, as the browser replays it. */
|
|
167
|
+
const modelArguments = z.record(z.string(), z.unknown());
|
|
168
|
+
/** The gate a tool waits on: its permission tier, and the slot a sign-in gate fills. */
|
|
169
|
+
function heldGate(tool) {
|
|
170
|
+
const auth = 'auth' in tool ? tool.auth : undefined;
|
|
171
|
+
return {
|
|
172
|
+
permission: tool.permission,
|
|
173
|
+
...(auth
|
|
174
|
+
? {
|
|
175
|
+
auth: { slot: auth.slot, authType: auth.type, service: auth.service },
|
|
176
|
+
}
|
|
177
|
+
: {}),
|
|
178
|
+
};
|
|
179
|
+
}
|
|
180
|
+
/**
|
|
181
|
+
* The user's answer to a paused call, as `replay` holds it. The studio keeps no
|
|
182
|
+
* session; its gate comes from the draft's registered tool, and the answer
|
|
183
|
+
* settles it by the rule every Theorem host uses. Returns the run that settles
|
|
184
|
+
* it, less its trace metadata.
|
|
185
|
+
*/
|
|
186
|
+
function answerReplayed(scope, profile, request, replay, runtime) {
|
|
187
|
+
const tool = replay.name === undefined ? undefined : scope.tools.get(replay.name);
|
|
188
|
+
if (!tool) {
|
|
189
|
+
// labels-exempt: internal diagnostic; the user reads error.request
|
|
190
|
+
throw new TheoremError('request', 'invoke: the paused call names no tool in this draft');
|
|
191
|
+
}
|
|
192
|
+
const answered = answerGatedCall(request, {
|
|
193
|
+
name: tool.name,
|
|
194
|
+
arguments: checkRequest(modelArguments, replay.input, 'replayed call input'),
|
|
195
|
+
gateKind: replay.gateKind,
|
|
196
|
+
...heldGate(tool),
|
|
197
|
+
}, replay.sessionPermissions ?? []);
|
|
198
|
+
return {
|
|
199
|
+
profile,
|
|
200
|
+
name: tool.name,
|
|
201
|
+
callId: request.callId,
|
|
202
|
+
operationId: request.operationId,
|
|
203
|
+
input: answered.input,
|
|
204
|
+
resume: answered.resume,
|
|
205
|
+
...(answered.page ? { page: answered.page } : {}),
|
|
206
|
+
sessionPermissions: answered.sessionPermissions,
|
|
207
|
+
...(answered.typed
|
|
208
|
+
? {
|
|
209
|
+
credentials: memoryCredentialSource({
|
|
210
|
+
[answered.typed.slot]: answered.typed.credential,
|
|
211
|
+
}),
|
|
212
|
+
}
|
|
213
|
+
: {}),
|
|
214
|
+
snapshot: replay.snapshot,
|
|
215
|
+
promoted: replay.promoted,
|
|
216
|
+
model: replay.model,
|
|
217
|
+
resolveHost: runtime.resolveHost,
|
|
218
|
+
execution: runtime.execution,
|
|
219
|
+
pageExecution: runtime.pageExecution,
|
|
220
|
+
onAgentCall: agentCallHook(scope, runtime),
|
|
221
|
+
};
|
|
222
|
+
}
|
|
223
|
+
function answerOf(answer) {
|
|
224
|
+
const { gateId, operationId, decision, input, secret, page } = answer;
|
|
225
|
+
return { callId: gateId, operationId, decision, input, secret, page };
|
|
226
|
+
}
|
|
227
|
+
/** A paused call the browser replays, answered: a host draft's call, or a stateless chat's. */
|
|
228
|
+
function replayedInvoke(scope, profile, answer, runtime, signal) {
|
|
229
|
+
const invoke = answerReplayed(scope, profile, answerOf(answer), answer.replay ?? {}, runtime);
|
|
230
|
+
return withRunTraces((metadata) => scope.invokeTool({ ...invoke, metadata, signal }));
|
|
231
|
+
}
|
|
232
|
+
/**
|
|
233
|
+
* The user's answer to a paused call. In a kept conversation the reply goes on
|
|
234
|
+
* in the same stream once no call waits; otherwise the stream is the call's.
|
|
235
|
+
*/
|
|
236
|
+
export async function* streamStudioInvoke(args) {
|
|
237
|
+
const { answer, runtime, signal } = args;
|
|
238
|
+
const { scope, profile, host } = await studioChat(args, args.conversations);
|
|
239
|
+
const request = answerOf(answer);
|
|
240
|
+
const sessionPermissions = answer.replay?.sessionPermissions;
|
|
241
|
+
if (!host) {
|
|
242
|
+
if (answer.conversation !== undefined)
|
|
243
|
+
throw statelessRefusal('continue');
|
|
244
|
+
yield* replayedInvoke(scope, profile.id, answer, runtime, signal);
|
|
245
|
+
return;
|
|
246
|
+
}
|
|
247
|
+
if (answer.conversation === undefined)
|
|
248
|
+
throw statelessRefusal('continue');
|
|
249
|
+
const opened = await openConversation(host, answer.conversation, {
|
|
250
|
+
kind: 'answer',
|
|
251
|
+
call: { callId: request.callId, operationId: request.operationId },
|
|
252
|
+
});
|
|
253
|
+
const invoke = answerPaused(scope, profile.id, opened, request, sessionPermissions, runtime);
|
|
254
|
+
yield* withRunTraces((metadata) => answerReply({
|
|
255
|
+
host,
|
|
256
|
+
opened,
|
|
257
|
+
call: { callId: request.callId, operationId: request.operationId },
|
|
258
|
+
settling: scope.invokeTool({ ...invoke, metadata, signal }),
|
|
259
|
+
runner: studioRunner({
|
|
260
|
+
scope,
|
|
261
|
+
profile,
|
|
262
|
+
runtime,
|
|
263
|
+
metadata,
|
|
264
|
+
sessionPermissions,
|
|
265
|
+
signal,
|
|
266
|
+
}),
|
|
267
|
+
}));
|
|
268
|
+
}
|
|
269
|
+
/** A conversation that opens on blocks the page wrote, read first by the draft's guardrails: its ref and view. */
|
|
270
|
+
export async function startStudioConversation(draft, conversations, blocks) {
|
|
271
|
+
const { profile, host } = await studioChat(draft, conversations);
|
|
272
|
+
if (!host)
|
|
273
|
+
throw statelessRefusal('start');
|
|
274
|
+
const { ref, view } = await startConversation(host, profile, blocks);
|
|
275
|
+
return { conversation: ref, view };
|
|
276
|
+
}
|
|
277
|
+
/** The conversation under a ref, as the page draws it. */
|
|
278
|
+
export async function studioConversation(draft, conversations, request) {
|
|
279
|
+
const { host } = await studioChat(draft, conversations);
|
|
280
|
+
if (!host)
|
|
281
|
+
throw statelessRefusal('read');
|
|
282
|
+
const opened = await openConversation(host, request.conversation, { kind: 'read' });
|
|
283
|
+
return conversationView(host, opened.conversation);
|
|
284
|
+
}
|
|
285
|
+
/** The conversation cut after one block; a reply that waits on gates is walked away from first. */
|
|
286
|
+
export async function rewindStudio(draft, conversations, request, signal) {
|
|
287
|
+
const { scope, profile, host } = await studioChat(draft, conversations);
|
|
288
|
+
if (!host)
|
|
289
|
+
throw statelessRefusal('rewind');
|
|
290
|
+
const opened = await openConversation(host, request.conversation, {
|
|
291
|
+
kind: 'rewind',
|
|
292
|
+
at: request.at,
|
|
293
|
+
});
|
|
294
|
+
const walkAway = waitingCalls(opened.conversation).map((reference) => {
|
|
295
|
+
const invoke = answerPaused(scope, profile.id, opened, { ...reference, decision: 'abandon' }, undefined, draft.runtime);
|
|
296
|
+
return { ...reference, events: scope.invokeTool({ ...invoke, signal }) };
|
|
297
|
+
});
|
|
298
|
+
const next = await rewindConversation({ host, opened, at: request.at, walkAway });
|
|
299
|
+
if (next.ref === null)
|
|
300
|
+
throw new TheoremError('internal', labelText('error.internal'));
|
|
301
|
+
return { conversation: next.ref, view: conversationView(host, next.conversation) };
|
|
302
|
+
}
|
|
303
|
+
/** The user's answer to a host draft's paused call: the studio keeps no session, so the browser replays it. */
|
|
304
|
+
export async function* streamStudioHostInvoke(args) {
|
|
305
|
+
const { scope, profile } = await hostScope(args);
|
|
306
|
+
yield* replayedInvoke(scope, profile.id, args.answer, args.runtime, args.signal);
|
|
307
|
+
}
|
|
308
|
+
/** A host draft's scope; any other profile is refused. */
|
|
309
|
+
async function hostScope(draft) {
|
|
310
|
+
const opened = await studioScope(draft.profile, draft.customTools, undefined, draft.runtime, draft.dependencies);
|
|
311
|
+
if (opened.profile.type !== 'host') {
|
|
312
|
+
// labels-exempt: internal diagnostic; the user reads error.request
|
|
313
|
+
throw new TheoremError('request', 'Studio calls run host profiles only.');
|
|
314
|
+
}
|
|
315
|
+
return opened;
|
|
316
|
+
}
|
|
317
|
+
/** One call of a host draft's tool, streamed. */
|
|
318
|
+
export async function* streamStudioCall(args) {
|
|
319
|
+
const { scope, profile } = await hostScope(args);
|
|
320
|
+
yield* withRunTraces((metadata) => scope.invokeTool({
|
|
321
|
+
profile: profile.id,
|
|
322
|
+
execution: args.runtime.execution,
|
|
323
|
+
pageExecution: args.runtime.pageExecution,
|
|
324
|
+
name: args.call.name,
|
|
325
|
+
input: args.call.input,
|
|
326
|
+
sessionPermissions: args.sessionPermissions,
|
|
327
|
+
resolveHost: args.runtime.resolveHost,
|
|
328
|
+
onAgentCall: agentCallHook(scope, args.runtime),
|
|
329
|
+
signal: args.signal,
|
|
330
|
+
metadata,
|
|
331
|
+
}));
|
|
332
|
+
}
|
|
333
|
+
export { studioScope } from "./runtime-scope.js";
|
|
334
|
+
/** The records a preview writes, and the sink that keeps them when its profile records traces. */
|
|
335
|
+
function collectTraces(observability) {
|
|
336
|
+
const traces = [];
|
|
337
|
+
if (!observability || !resolveObservabilityPolicy(observability).record)
|
|
338
|
+
return { traces };
|
|
339
|
+
const sink = {
|
|
340
|
+
write: (record) => {
|
|
341
|
+
traces.push(record);
|
|
342
|
+
return Promise.resolve();
|
|
343
|
+
},
|
|
344
|
+
};
|
|
345
|
+
return { traces, sink };
|
|
346
|
+
}
|
|
347
|
+
/** Both hosts run decisions through the kernel; the browser supplies its provider vault. */
|
|
348
|
+
export async function runStudioDecision(payload, state, options, signal, assets) {
|
|
349
|
+
const { scope, profile } = await studioScope(payload.profile, [], undefined, {
|
|
350
|
+
mode: 'byok',
|
|
351
|
+
});
|
|
352
|
+
const { traces, sink } = collectTraces(profile.observability);
|
|
353
|
+
try {
|
|
354
|
+
const result = await scope.runDecision({
|
|
355
|
+
profile: profile.id,
|
|
356
|
+
state,
|
|
357
|
+
questions: payload.questions ?? {},
|
|
358
|
+
assets: decisionAssets(payload.images, assets),
|
|
359
|
+
signal,
|
|
360
|
+
}, { ...options, ...(sink ? { sink } : {}) });
|
|
361
|
+
return { result, traces };
|
|
362
|
+
}
|
|
363
|
+
catch (err) {
|
|
364
|
+
// The kernel traces a decision however it ends; the failure carries what it left.
|
|
365
|
+
throw withFailedTraces(err, traces);
|
|
366
|
+
}
|
|
367
|
+
}
|
|
368
|
+
/** Runs one embedding preview and returns its normalized result with the records it wrote. */
|
|
369
|
+
export async function runStudioEmbedding(payload, request, runtime) {
|
|
370
|
+
const { scope, profile } = await studioScope(payload.profile, payload.customTools, payload.structured, runtime, payload.dependencies);
|
|
371
|
+
if (profile.type !== 'embedding') {
|
|
372
|
+
throw new TheoremError('request', 'Studio embedding runs require an embedding profile.');
|
|
373
|
+
}
|
|
374
|
+
const { traces, sink } = collectTraces(profile.observability);
|
|
375
|
+
try {
|
|
376
|
+
const result = await scope.runEmbedding({ ...request, profile: profile.id }, {
|
|
377
|
+
...runtimeProvider(runtime, scope, profile, request.model),
|
|
378
|
+
...(sink ? { sink } : {}),
|
|
379
|
+
});
|
|
380
|
+
return { result, traces };
|
|
381
|
+
}
|
|
382
|
+
catch (err) {
|
|
383
|
+
throw withFailedTraces(err, traces);
|
|
384
|
+
}
|
|
385
|
+
}
|
|
386
|
+
export { failedDecisionTraces, withFailedTraces } from '@theoremjs/react/client';
|
|
387
|
+
export { studioKeySlots } from "./browser-connection.js";
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* What a section of the studio's profile editor says that the catalog doc
|
|
3
|
+
* of the field it edits does not: how the editor works, and what the
|
|
4
|
+
* studio does. The catalog doc is on the field's hover; a note never repeats it.
|
|
5
|
+
*/
|
|
6
|
+
declare const SECTION_NOTES: {
|
|
7
|
+
readonly models: "Add a model here, then select its binding in the tree to configure it.";
|
|
8
|
+
readonly 'models.decision': "A decision uses one model. Select its binding in the tree to configure it.";
|
|
9
|
+
readonly decisionModel: "This binding answers the questions configured under Decision.";
|
|
10
|
+
readonly slots: "Each slot's picker sets what the preview sends. It is not saved in the profile.";
|
|
11
|
+
readonly context: "Preview is what the studio sends as the page. It is not saved in the profile.";
|
|
12
|
+
readonly compaction: "The studio's chat compacts only before a turn.";
|
|
13
|
+
readonly quota: "Studio runs are not counted.";
|
|
14
|
+
readonly 'detect.mixed': "Actions differ by boundary.";
|
|
15
|
+
readonly 'detect.source.theorem': "Theorem's patterns only.";
|
|
16
|
+
readonly 'detect.source.mine': "Your patterns only.";
|
|
17
|
+
readonly 'detect.source.both': "Theorem's patterns and yours.";
|
|
18
|
+
readonly 'detect.own': "Detectors you define.";
|
|
19
|
+
readonly 'detect.try': "Sample text is not saved.";
|
|
20
|
+
readonly 'detect.try.off': "Set to Ignore at every boundary tested. Nothing reads the sample.";
|
|
21
|
+
readonly 'traces.storage': "Your host's trace store uses these. The studio's stores nothing.";
|
|
22
|
+
readonly 'tools.host': "What the host runs. Each call names one.";
|
|
23
|
+
readonly 'tool.test.http': "Sends one real {method} request with the sample input.";
|
|
24
|
+
readonly 'tool.test.mcp': "Asks the server which tools it has.";
|
|
25
|
+
readonly 'tool.host': "What a call runs, and what the console says it does.";
|
|
26
|
+
readonly 'tool.headers': "Headers are saved in the profile, so keep secrets under Auth.";
|
|
27
|
+
readonly 'tool.auth': "The studio stores no credential: at a sign-in gate you type one for that call only.";
|
|
28
|
+
readonly 'decision.questions': "Asked together in one call, answered in this order.";
|
|
29
|
+
readonly connection: "Kept in this tab. Sent directly to the provider.";
|
|
30
|
+
};
|
|
31
|
+
/** The note for `id`, each `{name}` in `fill` replaced by its value. */
|
|
32
|
+
declare function sectionNote(id: keyof typeof SECTION_NOTES, fill?: Readonly<Record<string, string>>): string;
|
|
33
|
+
export { sectionNote };
|
package/section-notes.js
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* What a section of the studio's profile editor says that the catalog doc
|
|
3
|
+
* of the field it edits does not: how the editor works, and what the
|
|
4
|
+
* studio does. The catalog doc is on the field's hover; a note never repeats it.
|
|
5
|
+
*/
|
|
6
|
+
const SECTION_NOTES = {
|
|
7
|
+
models: 'Add a model here, then select its binding in the tree to configure it.',
|
|
8
|
+
'models.decision': 'A decision uses one model. Select its binding in the tree to configure it.',
|
|
9
|
+
decisionModel: 'This binding answers the questions configured under Decision.',
|
|
10
|
+
slots: "Each slot's picker sets what the preview sends. It is not saved in the profile.",
|
|
11
|
+
context: 'Preview is what the studio sends as the page. It is not saved in the profile.',
|
|
12
|
+
compaction: "The studio's chat compacts only before a turn.",
|
|
13
|
+
quota: 'Studio runs are not counted.',
|
|
14
|
+
'detect.mixed': 'Actions differ by boundary.',
|
|
15
|
+
'detect.source.theorem': "Theorem's patterns only.",
|
|
16
|
+
'detect.source.mine': 'Your patterns only.',
|
|
17
|
+
'detect.source.both': "Theorem's patterns and yours.",
|
|
18
|
+
'detect.own': 'Detectors you define.',
|
|
19
|
+
'detect.try': 'Sample text is not saved.',
|
|
20
|
+
'detect.try.off': 'Set to Ignore at every boundary tested. Nothing reads the sample.',
|
|
21
|
+
'traces.storage': "Your host's trace store uses these. The studio's stores nothing.",
|
|
22
|
+
'tools.host': 'What the host runs. Each call names one.',
|
|
23
|
+
'tool.test.http': 'Sends one real {method} request with the sample input.',
|
|
24
|
+
'tool.test.mcp': 'Asks the server which tools it has.',
|
|
25
|
+
'tool.host': 'What a call runs, and what the console says it does.',
|
|
26
|
+
'tool.headers': 'Headers are saved in the profile, so keep secrets under Auth.',
|
|
27
|
+
'tool.auth': 'The studio stores no credential: at a sign-in gate you type one for that call only.',
|
|
28
|
+
'decision.questions': 'Asked together in one call, answered in this order.',
|
|
29
|
+
connection: 'Kept in this tab. Sent directly to the provider.',
|
|
30
|
+
};
|
|
31
|
+
/** The note for `id`, each `{name}` in `fill` replaced by its value. */
|
|
32
|
+
function sectionNote(id, fill = {}) {
|
|
33
|
+
let note = SECTION_NOTES[id];
|
|
34
|
+
for (const [name, value] of Object.entries(fill))
|
|
35
|
+
note = note.replaceAll(`{${name}}`, value);
|
|
36
|
+
return note;
|
|
37
|
+
}
|
|
38
|
+
export { sectionNote };
|
package/serve-page.mjs
ADDED
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Serves the installed package's built page, as Vite serves the sources in the repo:
|
|
3
|
+
*
|
|
4
|
+
* node serve-page.mjs --port <port> --project <the project server's /api/studio address>
|
|
5
|
+
*
|
|
6
|
+
* Only this machine reaches it. Every response carries the page's headers (`page.mjs`). A path
|
|
7
|
+
* that names no file is the page itself, so a run tab's address opens the screen.
|
|
8
|
+
*/
|
|
9
|
+
import { readdirSync, readFileSync } from 'node:fs';
|
|
10
|
+
import { createServer } from 'node:http';
|
|
11
|
+
import path from 'node:path';
|
|
12
|
+
import { fileURLToPath } from 'node:url';
|
|
13
|
+
import { BUILT_PAGE, PAGE_BASE, PAGE_HEADERS, PROJECT_PLACEHOLDER } from './page.mjs';
|
|
14
|
+
|
|
15
|
+
const root = path.join(path.dirname(fileURLToPath(import.meta.url)), BUILT_PAGE);
|
|
16
|
+
const PAGE_FILE = path.join(root, 'index.html');
|
|
17
|
+
|
|
18
|
+
const TYPES = {
|
|
19
|
+
'.html': 'text/html; charset=utf-8',
|
|
20
|
+
'.js': 'text/javascript; charset=utf-8',
|
|
21
|
+
'.css': 'text/css; charset=utf-8',
|
|
22
|
+
'.json': 'application/json',
|
|
23
|
+
'.svg': 'image/svg+xml',
|
|
24
|
+
'.png': 'image/png',
|
|
25
|
+
'.woff': 'font/woff',
|
|
26
|
+
'.woff2': 'font/woff2',
|
|
27
|
+
'.ttf': 'font/ttf',
|
|
28
|
+
'.wasm': 'application/wasm',
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
const args = process.argv.slice(2);
|
|
32
|
+
const flag = (name) => {
|
|
33
|
+
const at = args.indexOf(`--${name}`);
|
|
34
|
+
return at === -1 ? undefined : args[at + 1];
|
|
35
|
+
};
|
|
36
|
+
const port = Number(flag('port'));
|
|
37
|
+
const project = flag('project');
|
|
38
|
+
if (!Number.isInteger(port) || !project) {
|
|
39
|
+
console.error('usage: node serve-page.mjs --port <port> --project <address>');
|
|
40
|
+
process.exit(2);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
const page = readFileSync(PAGE_FILE, 'utf8').replaceAll(PROJECT_PLACEHOLDER, project);
|
|
44
|
+
|
|
45
|
+
/** The build's files, each with the path a request names it by, less the page (served with its project filled in). Nothing else is ever read. */
|
|
46
|
+
const FILES = [];
|
|
47
|
+
(function list(dir, named) {
|
|
48
|
+
for (const entry of readdirSync(dir, { withFileTypes: true })) {
|
|
49
|
+
const file = path.join(dir, entry.name);
|
|
50
|
+
if (entry.isDirectory()) list(file, `${named}${entry.name}/`);
|
|
51
|
+
else if (entry.isFile() && file !== PAGE_FILE) FILES.push([`${named}${entry.name}`, file]);
|
|
52
|
+
}
|
|
53
|
+
})(root, '');
|
|
54
|
+
|
|
55
|
+
/** The built file a request names, or undefined for the page itself (a malformed path too). */
|
|
56
|
+
function fileFor(pathname) {
|
|
57
|
+
let relative;
|
|
58
|
+
try {
|
|
59
|
+
relative = decodeURIComponent(pathname.slice(PAGE_BASE.length));
|
|
60
|
+
} catch {
|
|
61
|
+
return undefined;
|
|
62
|
+
}
|
|
63
|
+
// why: the request only picks among the build's own files; what is read comes from the list, never from the address.
|
|
64
|
+
for (const [name, file] of FILES) {
|
|
65
|
+
if (name === relative) return { body: readFileSync(file), type: TYPES[path.extname(file)] };
|
|
66
|
+
}
|
|
67
|
+
return undefined;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/** What a request is answered: the way to the page, nothing, or a built file or the page. */
|
|
71
|
+
function answerFor(method, pathname) {
|
|
72
|
+
if (pathname === '/' || `${pathname}/` === PAGE_BASE) {
|
|
73
|
+
return { status: 302, headers: { ...PAGE_HEADERS, Location: PAGE_BASE } };
|
|
74
|
+
}
|
|
75
|
+
if (!readsPage(method, pathname)) return { status: 404, headers: PAGE_HEADERS };
|
|
76
|
+
return served(method, pathname);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/** Whether a request reads something of the page's. */
|
|
80
|
+
function readsPage(method, pathname) {
|
|
81
|
+
return (method === 'GET' || method === 'HEAD') && pathname.startsWith(PAGE_BASE);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/** The built file a read names, or the page itself; a HEAD has no body. */
|
|
85
|
+
function served(method, pathname) {
|
|
86
|
+
const file = fileFor(pathname);
|
|
87
|
+
const type = file ? (file.type ?? 'application/octet-stream') : TYPES['.html'];
|
|
88
|
+
const body = method === 'HEAD' ? undefined : (file?.body ?? page);
|
|
89
|
+
return { status: 200, headers: { ...PAGE_HEADERS, 'Content-Type': type }, body };
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
createServer((request, response) => {
|
|
93
|
+
const { pathname } = new URL(request.url ?? '/', 'http://localhost');
|
|
94
|
+
const { status, headers, body } = answerFor(request.method, pathname);
|
|
95
|
+
response.writeHead(status, headers).end(body);
|
|
96
|
+
}).listen(port, '127.0.0.1');
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `POST <base>/decide`: one decision on lent keys. The browser authors the profile and its
|
|
3
|
+
* questions, so the server takes only the fields a studio decision compiles to, within the keys'
|
|
4
|
+
* decision limits, and checks the model, the state, and each question against the keys before it
|
|
5
|
+
* spends anything.
|
|
6
|
+
*
|
|
7
|
+
* @module
|
|
8
|
+
*/
|
|
9
|
+
import { z } from '@theoremjs/agents';
|
|
10
|
+
import type { LentDecisionLimits } from '../lent-keys.ts';
|
|
11
|
+
import type { LentRuntime } from './draft-handler.ts';
|
|
12
|
+
/** The decision request lent keys answer: only the fields a studio decision compiles to, within `limits`. A setting left out stays out. */
|
|
13
|
+
export declare function decisionRequestSchema(limits: LentDecisionLimits): z.ZodObject<{
|
|
14
|
+
profile: z.ZodObject<{
|
|
15
|
+
type: z.ZodLiteral<"decision">;
|
|
16
|
+
id: z.ZodString;
|
|
17
|
+
identity: z.ZodObject<{
|
|
18
|
+
handle: z.ZodString;
|
|
19
|
+
}, z.core.$strip>;
|
|
20
|
+
models: z.ZodRecord<z.ZodString, z.ZodObject<{
|
|
21
|
+
protocol: z.ZodLiteral<"systemOne">;
|
|
22
|
+
provider: z.ZodString;
|
|
23
|
+
apiId: z.ZodString;
|
|
24
|
+
keySlot: z.ZodOptional<z.ZodString>;
|
|
25
|
+
fallbackKeySlot: z.ZodOptional<z.ZodString>;
|
|
26
|
+
options: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodJSONSchema>>;
|
|
27
|
+
timeoutMs: z.ZodOptional<z.ZodNumber>;
|
|
28
|
+
}, z.core.$strip>>;
|
|
29
|
+
inputs: z.ZodObject<{
|
|
30
|
+
state: z.ZodLiteral<"json">;
|
|
31
|
+
maxStateBytes: z.ZodOptional<z.ZodNumber>;
|
|
32
|
+
}, z.core.$strip>;
|
|
33
|
+
decision: z.ZodObject<{
|
|
34
|
+
contract: z.ZodString;
|
|
35
|
+
}, z.core.$strip>;
|
|
36
|
+
observability: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
|
|
37
|
+
labels: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
|
|
38
|
+
}, z.core.$strip>;
|
|
39
|
+
questions: z.ZodRecord<z.ZodString, z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
40
|
+
type: z.ZodLiteral<"choice">;
|
|
41
|
+
instructions: z.ZodString;
|
|
42
|
+
criteria: z.ZodRecord<z.ZodString, z.ZodString>;
|
|
43
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
44
|
+
type: z.ZodLiteral<"score">;
|
|
45
|
+
instructions: z.ZodString;
|
|
46
|
+
criteria: z.ZodArray<z.ZodString>;
|
|
47
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
48
|
+
type: z.ZodLiteral<"noul">;
|
|
49
|
+
instructions: z.ZodString;
|
|
50
|
+
criteria: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
|
|
51
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
52
|
+
type: z.ZodLiteral<"box">;
|
|
53
|
+
instructions: z.ZodString;
|
|
54
|
+
image: z.ZodOptional<z.ZodString>;
|
|
55
|
+
}, z.core.$strip>], "type">>;
|
|
56
|
+
state: z.ZodUnknown;
|
|
57
|
+
assets: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodObject<{
|
|
58
|
+
mimeType: z.ZodEnum<{
|
|
59
|
+
"image/jpeg": "image/jpeg";
|
|
60
|
+
"image/png": "image/png";
|
|
61
|
+
}>;
|
|
62
|
+
data: z.ZodString;
|
|
63
|
+
}, z.core.$strip>>>;
|
|
64
|
+
}, z.core.$strip>;
|
|
65
|
+
/** What a decision on lent keys runs with. */
|
|
66
|
+
export type DraftDecideOptions = {
|
|
67
|
+
runtime: LentRuntime;
|
|
68
|
+
/** Spends the decision once the request is one the keys would answer; throws to refuse it. */
|
|
69
|
+
spend: (request: Request) => Promise<void>;
|
|
70
|
+
};
|
|
71
|
+
/** Answers one decision on the lent keys, with the records it wrote; a failed one is traced too. */
|
|
72
|
+
export declare function draftDecide(request: Request, options: DraftDecideOptions): Promise<Response>;
|