@tianshu-ai/tianshu 0.3.0
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 +200 -0
- package/README.md +284 -0
- package/README.zh-CN.md +136 -0
- package/bin/tianshu.mjs +32 -0
- package/package.json +60 -0
- package/packages/plugin-sdk/dist/agent-loop.d.ts +96 -0
- package/packages/plugin-sdk/dist/agent-loop.d.ts.map +1 -0
- package/packages/plugin-sdk/dist/agent-loop.js +11 -0
- package/packages/plugin-sdk/dist/agent-loop.js.map +1 -0
- package/packages/plugin-sdk/dist/capabilities.d.ts +48 -0
- package/packages/plugin-sdk/dist/capabilities.d.ts.map +1 -0
- package/packages/plugin-sdk/dist/capabilities.js +61 -0
- package/packages/plugin-sdk/dist/capabilities.js.map +1 -0
- package/packages/plugin-sdk/dist/catalog.d.ts +60 -0
- package/packages/plugin-sdk/dist/catalog.d.ts.map +1 -0
- package/packages/plugin-sdk/dist/catalog.js +11 -0
- package/packages/plugin-sdk/dist/catalog.js.map +1 -0
- package/packages/plugin-sdk/dist/client.d.ts +171 -0
- package/packages/plugin-sdk/dist/client.d.ts.map +1 -0
- package/packages/plugin-sdk/dist/client.js +96 -0
- package/packages/plugin-sdk/dist/client.js.map +1 -0
- package/packages/plugin-sdk/dist/index.d.ts +9 -0
- package/packages/plugin-sdk/dist/index.d.ts.map +1 -0
- package/packages/plugin-sdk/dist/index.js +19 -0
- package/packages/plugin-sdk/dist/index.js.map +1 -0
- package/packages/plugin-sdk/dist/lsp.d.ts +32 -0
- package/packages/plugin-sdk/dist/lsp.d.ts.map +1 -0
- package/packages/plugin-sdk/dist/lsp.js +19 -0
- package/packages/plugin-sdk/dist/lsp.js.map +1 -0
- package/packages/plugin-sdk/dist/manifest.d.ts +423 -0
- package/packages/plugin-sdk/dist/manifest.d.ts.map +1 -0
- package/packages/plugin-sdk/dist/manifest.js +7 -0
- package/packages/plugin-sdk/dist/manifest.js.map +1 -0
- package/packages/plugin-sdk/dist/mcp-client.d.ts +74 -0
- package/packages/plugin-sdk/dist/mcp-client.d.ts.map +1 -0
- package/packages/plugin-sdk/dist/mcp-client.js +226 -0
- package/packages/plugin-sdk/dist/mcp-client.js.map +1 -0
- package/packages/plugin-sdk/dist/mcp-fetch.d.ts +10 -0
- package/packages/plugin-sdk/dist/mcp-fetch.d.ts.map +1 -0
- package/packages/plugin-sdk/dist/mcp-fetch.js +130 -0
- package/packages/plugin-sdk/dist/mcp-fetch.js.map +1 -0
- package/packages/plugin-sdk/dist/mcp-toolset.d.ts +128 -0
- package/packages/plugin-sdk/dist/mcp-toolset.d.ts.map +1 -0
- package/packages/plugin-sdk/dist/mcp-toolset.js +246 -0
- package/packages/plugin-sdk/dist/mcp-toolset.js.map +1 -0
- package/packages/plugin-sdk/dist/server.d.ts +486 -0
- package/packages/plugin-sdk/dist/server.d.ts.map +1 -0
- package/packages/plugin-sdk/dist/server.js +10 -0
- package/packages/plugin-sdk/dist/server.js.map +1 -0
- package/packages/plugin-sdk/dist/session-inbox.d.ts +56 -0
- package/packages/plugin-sdk/dist/session-inbox.d.ts.map +1 -0
- package/packages/plugin-sdk/dist/session-inbox.js +12 -0
- package/packages/plugin-sdk/dist/session-inbox.js.map +1 -0
- package/packages/plugin-sdk/package.json +36 -0
- package/packages/server/builtinConfig/plugins/README.md +1 -0
- package/packages/server/builtinConfig/plugins/files/manifest.json +100 -0
- package/packages/server/builtinConfig/plugins/files/skills/files-workspace-layout.md +29 -0
- package/packages/server/builtinConfig/plugins/microsandbox/manifest.json +177 -0
- package/packages/server/builtinConfig/plugins/microsandbox/skills/microsandbox-browser-howto.md +155 -0
- package/packages/server/builtinConfig/plugins/microsandbox/skills/microsandbox-build-use.md +201 -0
- package/packages/server/builtinConfig/plugins/microsandbox/skills/microsandbox-config.md +38 -0
- package/packages/server/builtinConfig/plugins/microsandbox/skills/microsandbox-exec-howto.md +144 -0
- package/packages/server/builtinConfig/plugins/microsandbox/skills/microsandbox-libreoffice.md +159 -0
- package/packages/server/builtinConfig/plugins/microsandbox/skills/microsandbox-main-orchestration.md +75 -0
- package/packages/server/builtinConfig/plugins/microsandbox/templates/README.md +26 -0
- package/packages/server/builtinConfig/plugins/microsandbox/templates/browser.yaml +105 -0
- package/packages/server/builtinConfig/plugins/microsandbox/templates/task-runner-with-browser.yaml +80 -0
- package/packages/server/builtinConfig/plugins/microsandbox/templates/task-runner.yaml +80 -0
- package/packages/server/builtinConfig/plugins/web-search/manifest.json +65 -0
- package/packages/server/builtinConfig/plugins/web-search/skills/web-search-howto.md +69 -0
- package/packages/server/builtinConfig/plugins/workboard/agent-seeds/echo-demo/agent.json +7 -0
- package/packages/server/builtinConfig/plugins/workboard/agent-seeds/llm-default/SOUL.md +53 -0
- package/packages/server/builtinConfig/plugins/workboard/agent-seeds/llm-default/agent.json +7 -0
- package/packages/server/builtinConfig/plugins/workboard/manifest.json +180 -0
- package/packages/server/builtinConfig/plugins/workboard/skills/large-input-large-output.md +185 -0
- package/packages/server/builtinConfig/plugins/workboard/skills/workboard-howto.md +166 -0
- package/packages/server/builtinConfig/plugins/workboard/skills/worker-creator.md +267 -0
- package/packages/server/builtinConfig/plugins/workboard/skills/worker-fleet.md +431 -0
- package/packages/server/dist/catalog.d.ts +52 -0
- package/packages/server/dist/catalog.d.ts.map +1 -0
- package/packages/server/dist/catalog.js +189 -0
- package/packages/server/dist/catalog.js.map +1 -0
- package/packages/server/dist/chat/active-harnesses.d.ts +34 -0
- package/packages/server/dist/chat/active-harnesses.d.ts.map +1 -0
- package/packages/server/dist/chat/active-harnesses.js +118 -0
- package/packages/server/dist/chat/active-harnesses.js.map +1 -0
- package/packages/server/dist/chat/agent-loop.d.ts +64 -0
- package/packages/server/dist/chat/agent-loop.d.ts.map +1 -0
- package/packages/server/dist/chat/agent-loop.js +597 -0
- package/packages/server/dist/chat/agent-loop.js.map +1 -0
- package/packages/server/dist/chat/agent-tool-adapter.d.ts +33 -0
- package/packages/server/dist/chat/agent-tool-adapter.d.ts.map +1 -0
- package/packages/server/dist/chat/agent-tool-adapter.js +260 -0
- package/packages/server/dist/chat/agent-tool-adapter.js.map +1 -0
- package/packages/server/dist/chat/compact.d.ts +52 -0
- package/packages/server/dist/chat/compact.d.ts.map +1 -0
- package/packages/server/dist/chat/compact.js +248 -0
- package/packages/server/dist/chat/compact.js.map +1 -0
- package/packages/server/dist/chat/dump-system-prompt.d.ts +17 -0
- package/packages/server/dist/chat/dump-system-prompt.d.ts.map +1 -0
- package/packages/server/dist/chat/dump-system-prompt.js +58 -0
- package/packages/server/dist/chat/dump-system-prompt.js.map +1 -0
- package/packages/server/dist/chat/handler.d.ts +186 -0
- package/packages/server/dist/chat/handler.d.ts.map +1 -0
- package/packages/server/dist/chat/handler.js +1248 -0
- package/packages/server/dist/chat/handler.js.map +1 -0
- package/packages/server/dist/chat/image-fit.d.ts +34 -0
- package/packages/server/dist/chat/image-fit.d.ts.map +1 -0
- package/packages/server/dist/chat/image-fit.js +157 -0
- package/packages/server/dist/chat/image-fit.js.map +1 -0
- package/packages/server/dist/chat/messages.d.ts +118 -0
- package/packages/server/dist/chat/messages.d.ts.map +1 -0
- package/packages/server/dist/chat/messages.js +341 -0
- package/packages/server/dist/chat/messages.js.map +1 -0
- package/packages/server/dist/chat/session-inbox.d.ts +114 -0
- package/packages/server/dist/chat/session-inbox.d.ts.map +1 -0
- package/packages/server/dist/chat/session-inbox.js +418 -0
- package/packages/server/dist/chat/session-inbox.js.map +1 -0
- package/packages/server/dist/chat/sqlite-session-repo.d.ts +26 -0
- package/packages/server/dist/chat/sqlite-session-repo.d.ts.map +1 -0
- package/packages/server/dist/chat/sqlite-session-repo.js +132 -0
- package/packages/server/dist/chat/sqlite-session-repo.js.map +1 -0
- package/packages/server/dist/chat/sqlite-session-storage.d.ts +83 -0
- package/packages/server/dist/chat/sqlite-session-storage.d.ts.map +1 -0
- package/packages/server/dist/chat/sqlite-session-storage.js +418 -0
- package/packages/server/dist/chat/sqlite-session-storage.js.map +1 -0
- package/packages/server/dist/chat/stub-execution-env.d.ts +3 -0
- package/packages/server/dist/chat/stub-execution-env.d.ts.map +1 -0
- package/packages/server/dist/chat/stub-execution-env.js +87 -0
- package/packages/server/dist/chat/stub-execution-env.js.map +1 -0
- package/packages/server/dist/chat/token-estimate.d.ts +11 -0
- package/packages/server/dist/chat/token-estimate.d.ts.map +1 -0
- package/packages/server/dist/chat/token-estimate.js +67 -0
- package/packages/server/dist/chat/token-estimate.js.map +1 -0
- package/packages/server/dist/chat/ws-protocol.d.ts +244 -0
- package/packages/server/dist/chat/ws-protocol.d.ts.map +1 -0
- package/packages/server/dist/chat/ws-protocol.js +193 -0
- package/packages/server/dist/chat/ws-protocol.js.map +1 -0
- package/packages/server/dist/cli.d.ts +9 -0
- package/packages/server/dist/cli.d.ts.map +1 -0
- package/packages/server/dist/cli.js +329 -0
- package/packages/server/dist/cli.js.map +1 -0
- package/packages/server/dist/core/agent-seeds.d.ts +25 -0
- package/packages/server/dist/core/agent-seeds.d.ts.map +1 -0
- package/packages/server/dist/core/agent-seeds.js +69 -0
- package/packages/server/dist/core/agent-seeds.js.map +1 -0
- package/packages/server/dist/core/config.d.ts +172 -0
- package/packages/server/dist/core/config.d.ts.map +1 -0
- package/packages/server/dist/core/config.js +155 -0
- package/packages/server/dist/core/config.js.map +1 -0
- package/packages/server/dist/core/db-pool.d.ts +32 -0
- package/packages/server/dist/core/db-pool.d.ts.map +1 -0
- package/packages/server/dist/core/db-pool.js +108 -0
- package/packages/server/dist/core/db-pool.js.map +1 -0
- package/packages/server/dist/core/dev-mode.d.ts +13 -0
- package/packages/server/dist/core/dev-mode.d.ts.map +1 -0
- package/packages/server/dist/core/dev-mode.js +51 -0
- package/packages/server/dist/core/dev-mode.js.map +1 -0
- package/packages/server/dist/core/global-ops.d.ts +54 -0
- package/packages/server/dist/core/global-ops.d.ts.map +1 -0
- package/packages/server/dist/core/global-ops.js +143 -0
- package/packages/server/dist/core/global-ops.js.map +1 -0
- package/packages/server/dist/core/identity-resolvers.d.ts +102 -0
- package/packages/server/dist/core/identity-resolvers.d.ts.map +1 -0
- package/packages/server/dist/core/identity-resolvers.js +176 -0
- package/packages/server/dist/core/identity-resolvers.js.map +1 -0
- package/packages/server/dist/core/index.d.ts +13 -0
- package/packages/server/dist/core/index.d.ts.map +1 -0
- package/packages/server/dist/core/index.js +18 -0
- package/packages/server/dist/core/index.js.map +1 -0
- package/packages/server/dist/core/llm.d.ts +45 -0
- package/packages/server/dist/core/llm.d.ts.map +1 -0
- package/packages/server/dist/core/llm.js +140 -0
- package/packages/server/dist/core/llm.js.map +1 -0
- package/packages/server/dist/core/mcp-manager.d.ts +47 -0
- package/packages/server/dist/core/mcp-manager.d.ts.map +1 -0
- package/packages/server/dist/core/mcp-manager.js +129 -0
- package/packages/server/dist/core/mcp-manager.js.map +1 -0
- package/packages/server/dist/core/middleware.d.ts +31 -0
- package/packages/server/dist/core/middleware.d.ts.map +1 -0
- package/packages/server/dist/core/middleware.js +102 -0
- package/packages/server/dist/core/middleware.js.map +1 -0
- package/packages/server/dist/core/migrations/001-initial.d.ts +4 -0
- package/packages/server/dist/core/migrations/001-initial.d.ts.map +1 -0
- package/packages/server/dist/core/migrations/001-initial.js +66 -0
- package/packages/server/dist/core/migrations/001-initial.js.map +1 -0
- package/packages/server/dist/core/migrations/002-task-dependencies.d.ts +4 -0
- package/packages/server/dist/core/migrations/002-task-dependencies.d.ts.map +1 -0
- package/packages/server/dist/core/migrations/002-task-dependencies.js +20 -0
- package/packages/server/dist/core/migrations/002-task-dependencies.js.map +1 -0
- package/packages/server/dist/core/migrations/003-session-tree.d.ts +4 -0
- package/packages/server/dist/core/migrations/003-session-tree.d.ts.map +1 -0
- package/packages/server/dist/core/migrations/003-session-tree.js +96 -0
- package/packages/server/dist/core/migrations/003-session-tree.js.map +1 -0
- package/packages/server/dist/core/migrations/003-worker-agents.d.ts +4 -0
- package/packages/server/dist/core/migrations/003-worker-agents.d.ts.map +1 -0
- package/packages/server/dist/core/migrations/003-worker-agents.js +65 -0
- package/packages/server/dist/core/migrations/003-worker-agents.js.map +1 -0
- package/packages/server/dist/core/migrations/004-rebuild-message-chain.d.ts +4 -0
- package/packages/server/dist/core/migrations/004-rebuild-message-chain.d.ts.map +1 -0
- package/packages/server/dist/core/migrations/004-rebuild-message-chain.js +52 -0
- package/packages/server/dist/core/migrations/004-rebuild-message-chain.js.map +1 -0
- package/packages/server/dist/core/migrations/005-task-status-rename.d.ts +4 -0
- package/packages/server/dist/core/migrations/005-task-status-rename.d.ts.map +1 -0
- package/packages/server/dist/core/migrations/005-task-status-rename.js +64 -0
- package/packages/server/dist/core/migrations/005-task-status-rename.js.map +1 -0
- package/packages/server/dist/core/migrations/006-task-labels.d.ts +4 -0
- package/packages/server/dist/core/migrations/006-task-labels.d.ts.map +1 -0
- package/packages/server/dist/core/migrations/006-task-labels.js +43 -0
- package/packages/server/dist/core/migrations/006-task-labels.js.map +1 -0
- package/packages/server/dist/core/migrations/007-session-inbox.d.ts +4 -0
- package/packages/server/dist/core/migrations/007-session-inbox.d.ts.map +1 -0
- package/packages/server/dist/core/migrations/007-session-inbox.js +67 -0
- package/packages/server/dist/core/migrations/007-session-inbox.js.map +1 -0
- package/packages/server/dist/core/migrations/008-task-intervention.d.ts +4 -0
- package/packages/server/dist/core/migrations/008-task-intervention.d.ts.map +1 -0
- package/packages/server/dist/core/migrations/008-task-intervention.js +60 -0
- package/packages/server/dist/core/migrations/008-task-intervention.js.map +1 -0
- package/packages/server/dist/core/migrations/index.d.ts +12 -0
- package/packages/server/dist/core/migrations/index.d.ts.map +1 -0
- package/packages/server/dist/core/migrations/index.js +58 -0
- package/packages/server/dist/core/migrations/index.js.map +1 -0
- package/packages/server/dist/core/paths.d.ts +53 -0
- package/packages/server/dist/core/paths.d.ts.map +1 -0
- package/packages/server/dist/core/paths.js +125 -0
- package/packages/server/dist/core/paths.js.map +1 -0
- package/packages/server/dist/core/plugins/builtin-loader.d.ts +56 -0
- package/packages/server/dist/core/plugins/builtin-loader.d.ts.map +1 -0
- package/packages/server/dist/core/plugins/builtin-loader.js +153 -0
- package/packages/server/dist/core/plugins/builtin-loader.js.map +1 -0
- package/packages/server/dist/core/plugins/discovery.d.ts +28 -0
- package/packages/server/dist/core/plugins/discovery.d.ts.map +1 -0
- package/packages/server/dist/core/plugins/discovery.js +97 -0
- package/packages/server/dist/core/plugins/discovery.js.map +1 -0
- package/packages/server/dist/core/plugins/index.d.ts +6 -0
- package/packages/server/dist/core/plugins/index.d.ts.map +1 -0
- package/packages/server/dist/core/plugins/index.js +6 -0
- package/packages/server/dist/core/plugins/index.js.map +1 -0
- package/packages/server/dist/core/plugins/manifest.d.ts +9 -0
- package/packages/server/dist/core/plugins/manifest.d.ts.map +1 -0
- package/packages/server/dist/core/plugins/manifest.js +584 -0
- package/packages/server/dist/core/plugins/manifest.js.map +1 -0
- package/packages/server/dist/core/plugins/registry.d.ts +269 -0
- package/packages/server/dist/core/plugins/registry.d.ts.map +1 -0
- package/packages/server/dist/core/plugins/registry.js +1003 -0
- package/packages/server/dist/core/plugins/registry.js.map +1 -0
- package/packages/server/dist/core/plugins/secrets.d.ts +46 -0
- package/packages/server/dist/core/plugins/secrets.d.ts.map +1 -0
- package/packages/server/dist/core/plugins/secrets.js +174 -0
- package/packages/server/dist/core/plugins/secrets.js.map +1 -0
- package/packages/server/dist/core/plugins/skills.d.ts +131 -0
- package/packages/server/dist/core/plugins/skills.d.ts.map +1 -0
- package/packages/server/dist/core/plugins/skills.js +389 -0
- package/packages/server/dist/core/plugins/skills.js.map +1 -0
- package/packages/server/dist/core/templates.d.ts +28 -0
- package/packages/server/dist/core/templates.d.ts.map +1 -0
- package/packages/server/dist/core/templates.js +103 -0
- package/packages/server/dist/core/templates.js.map +1 -0
- package/packages/server/dist/core/tenant-context.d.ts +18 -0
- package/packages/server/dist/core/tenant-context.d.ts.map +1 -0
- package/packages/server/dist/core/tenant-context.js +42 -0
- package/packages/server/dist/core/tenant-context.js.map +1 -0
- package/packages/server/dist/core/tenant-id.d.ts +8 -0
- package/packages/server/dist/core/tenant-id.d.ts.map +1 -0
- package/packages/server/dist/core/tenant-id.js +53 -0
- package/packages/server/dist/core/tenant-id.js.map +1 -0
- package/packages/server/dist/core/tenant-skills.d.ts +29 -0
- package/packages/server/dist/core/tenant-skills.d.ts.map +1 -0
- package/packages/server/dist/core/tenant-skills.js +77 -0
- package/packages/server/dist/core/tenant-skills.js.map +1 -0
- package/packages/server/dist/core/worker-agents-fs.d.ts +44 -0
- package/packages/server/dist/core/worker-agents-fs.d.ts.map +1 -0
- package/packages/server/dist/core/worker-agents-fs.js +86 -0
- package/packages/server/dist/core/worker-agents-fs.js.map +1 -0
- package/packages/server/dist/core/worker-agents.d.ts +77 -0
- package/packages/server/dist/core/worker-agents.d.ts.map +1 -0
- package/packages/server/dist/core/worker-agents.js +191 -0
- package/packages/server/dist/core/worker-agents.js.map +1 -0
- package/packages/server/dist/index.d.ts +2 -0
- package/packages/server/dist/index.d.ts.map +1 -0
- package/packages/server/dist/index.js +623 -0
- package/packages/server/dist/index.js.map +1 -0
- package/packages/server/dist/lsp/client.d.ts +53 -0
- package/packages/server/dist/lsp/client.d.ts.map +1 -0
- package/packages/server/dist/lsp/client.js +258 -0
- package/packages/server/dist/lsp/client.js.map +1 -0
- package/packages/server/dist/lsp/format.d.ts +13 -0
- package/packages/server/dist/lsp/format.d.ts.map +1 -0
- package/packages/server/dist/lsp/format.js +55 -0
- package/packages/server/dist/lsp/format.js.map +1 -0
- package/packages/server/dist/lsp/index.d.ts +20 -0
- package/packages/server/dist/lsp/index.d.ts.map +1 -0
- package/packages/server/dist/lsp/index.js +32 -0
- package/packages/server/dist/lsp/index.js.map +1 -0
- package/packages/server/dist/lsp/language-registry.d.ts +29 -0
- package/packages/server/dist/lsp/language-registry.d.ts.map +1 -0
- package/packages/server/dist/lsp/language-registry.js +62 -0
- package/packages/server/dist/lsp/language-registry.js.map +1 -0
- package/packages/server/dist/lsp/manager.d.ts +77 -0
- package/packages/server/dist/lsp/manager.d.ts.map +1 -0
- package/packages/server/dist/lsp/manager.js +300 -0
- package/packages/server/dist/lsp/manager.js.map +1 -0
- package/packages/server/dist/plugins-routes.d.ts +96 -0
- package/packages/server/dist/plugins-routes.d.ts.map +1 -0
- package/packages/server/dist/plugins-routes.js +627 -0
- package/packages/server/dist/plugins-routes.js.map +1 -0
- package/packages/server/dist/setup/checks/config.d.ts +9 -0
- package/packages/server/dist/setup/checks/config.d.ts.map +1 -0
- package/packages/server/dist/setup/checks/config.js +66 -0
- package/packages/server/dist/setup/checks/config.js.map +1 -0
- package/packages/server/dist/setup/checks/db.d.ts +6 -0
- package/packages/server/dist/setup/checks/db.d.ts.map +1 -0
- package/packages/server/dist/setup/checks/db.js +79 -0
- package/packages/server/dist/setup/checks/db.js.map +1 -0
- package/packages/server/dist/setup/checks/known-models.d.ts +18 -0
- package/packages/server/dist/setup/checks/known-models.d.ts.map +1 -0
- package/packages/server/dist/setup/checks/known-models.js +119 -0
- package/packages/server/dist/setup/checks/known-models.js.map +1 -0
- package/packages/server/dist/setup/checks/network.d.ts +11 -0
- package/packages/server/dist/setup/checks/network.d.ts.map +1 -0
- package/packages/server/dist/setup/checks/network.js +176 -0
- package/packages/server/dist/setup/checks/network.js.map +1 -0
- package/packages/server/dist/setup/checks/plugins.d.ts +9 -0
- package/packages/server/dist/setup/checks/plugins.d.ts.map +1 -0
- package/packages/server/dist/setup/checks/plugins.js +194 -0
- package/packages/server/dist/setup/checks/plugins.js.map +1 -0
- package/packages/server/dist/setup/checks/providers.d.ts +12 -0
- package/packages/server/dist/setup/checks/providers.d.ts.map +1 -0
- package/packages/server/dist/setup/checks/providers.js +368 -0
- package/packages/server/dist/setup/checks/providers.js.map +1 -0
- package/packages/server/dist/setup/checks/runtime.d.ts +3 -0
- package/packages/server/dist/setup/checks/runtime.d.ts.map +1 -0
- package/packages/server/dist/setup/checks/runtime.js +44 -0
- package/packages/server/dist/setup/checks/runtime.js.map +1 -0
- package/packages/server/dist/setup/checks/sandbox.d.ts +9 -0
- package/packages/server/dist/setup/checks/sandbox.d.ts.map +1 -0
- package/packages/server/dist/setup/checks/sandbox.js +110 -0
- package/packages/server/dist/setup/checks/sandbox.js.map +1 -0
- package/packages/server/dist/setup/checks/tenants.d.ts +9 -0
- package/packages/server/dist/setup/checks/tenants.d.ts.map +1 -0
- package/packages/server/dist/setup/checks/tenants.js +509 -0
- package/packages/server/dist/setup/checks/tenants.js.map +1 -0
- package/packages/server/dist/setup/cli-agent.d.ts +39 -0
- package/packages/server/dist/setup/cli-agent.d.ts.map +1 -0
- package/packages/server/dist/setup/cli-agent.js +1353 -0
- package/packages/server/dist/setup/cli-agent.js.map +1 -0
- package/packages/server/dist/setup/doctor.d.ts +32 -0
- package/packages/server/dist/setup/doctor.d.ts.map +1 -0
- package/packages/server/dist/setup/doctor.js +80 -0
- package/packages/server/dist/setup/doctor.js.map +1 -0
- package/packages/server/dist/setup/launchd.d.ts +107 -0
- package/packages/server/dist/setup/launchd.d.ts.map +1 -0
- package/packages/server/dist/setup/launchd.js +309 -0
- package/packages/server/dist/setup/launchd.js.map +1 -0
- package/packages/server/dist/setup/load-env.d.ts +21 -0
- package/packages/server/dist/setup/load-env.d.ts.map +1 -0
- package/packages/server/dist/setup/load-env.js +88 -0
- package/packages/server/dist/setup/load-env.js.map +1 -0
- package/packages/server/dist/setup/probe-default-model.d.ts +28 -0
- package/packages/server/dist/setup/probe-default-model.d.ts.map +1 -0
- package/packages/server/dist/setup/probe-default-model.js +133 -0
- package/packages/server/dist/setup/probe-default-model.js.map +1 -0
- package/packages/server/dist/setup/render.d.ts +28 -0
- package/packages/server/dist/setup/render.d.ts.map +1 -0
- package/packages/server/dist/setup/render.js +60 -0
- package/packages/server/dist/setup/render.js.map +1 -0
- package/packages/server/dist/setup/repo-root.d.ts +3 -0
- package/packages/server/dist/setup/repo-root.d.ts.map +1 -0
- package/packages/server/dist/setup/repo-root.js +43 -0
- package/packages/server/dist/setup/repo-root.js.map +1 -0
- package/packages/server/dist/setup/service.d.ts +60 -0
- package/packages/server/dist/setup/service.d.ts.map +1 -0
- package/packages/server/dist/setup/service.js +345 -0
- package/packages/server/dist/setup/service.js.map +1 -0
- package/packages/server/dist/setup/start-server.d.ts +23 -0
- package/packages/server/dist/setup/start-server.d.ts.map +1 -0
- package/packages/server/dist/setup/start-server.js +465 -0
- package/packages/server/dist/setup/start-server.js.map +1 -0
- package/packages/server/dist/setup/wizard.d.ts +59 -0
- package/packages/server/dist/setup/wizard.d.ts.map +1 -0
- package/packages/server/dist/setup/wizard.js +556 -0
- package/packages/server/dist/setup/wizard.js.map +1 -0
- package/packages/server/dist/tools/edit-file.d.ts +13 -0
- package/packages/server/dist/tools/edit-file.d.ts.map +1 -0
- package/packages/server/dist/tools/edit-file.js +90 -0
- package/packages/server/dist/tools/edit-file.js.map +1 -0
- package/packages/server/dist/tools/glob.d.ts +12 -0
- package/packages/server/dist/tools/glob.d.ts.map +1 -0
- package/packages/server/dist/tools/glob.js +82 -0
- package/packages/server/dist/tools/glob.js.map +1 -0
- package/packages/server/dist/tools/index.d.ts +82 -0
- package/packages/server/dist/tools/index.d.ts.map +1 -0
- package/packages/server/dist/tools/index.js +72 -0
- package/packages/server/dist/tools/index.js.map +1 -0
- package/packages/server/dist/tools/list-dir.d.ts +24 -0
- package/packages/server/dist/tools/list-dir.d.ts.map +1 -0
- package/packages/server/dist/tools/list-dir.js +99 -0
- package/packages/server/dist/tools/list-dir.js.map +1 -0
- package/packages/server/dist/tools/path-helper.d.ts +15 -0
- package/packages/server/dist/tools/path-helper.d.ts.map +1 -0
- package/packages/server/dist/tools/path-helper.js +72 -0
- package/packages/server/dist/tools/path-helper.js.map +1 -0
- package/packages/server/dist/tools/read-file.d.ts +17 -0
- package/packages/server/dist/tools/read-file.d.ts.map +1 -0
- package/packages/server/dist/tools/read-file.js +94 -0
- package/packages/server/dist/tools/read-file.js.map +1 -0
- package/packages/server/dist/tools/sandbox.d.ts +57 -0
- package/packages/server/dist/tools/sandbox.d.ts.map +1 -0
- package/packages/server/dist/tools/sandbox.js +291 -0
- package/packages/server/dist/tools/sandbox.js.map +1 -0
- package/packages/server/dist/tools/write-file.d.ts +12 -0
- package/packages/server/dist/tools/write-file.d.ts.map +1 -0
- package/packages/server/dist/tools/write-file.js +67 -0
- package/packages/server/dist/tools/write-file.js.map +1 -0
- package/packages/server/dist/worker-agents-routes.d.ts +11 -0
- package/packages/server/dist/worker-agents-routes.d.ts.map +1 -0
- package/packages/server/dist/worker-agents-routes.js +253 -0
- package/packages/server/dist/worker-agents-routes.js.map +1 -0
- package/packages/server/package.json +41 -0
- package/packages/web/dist/assets/index-DH-gJ09_.js +60 -0
- package/packages/web/dist/assets/index-xU4lYYqY.css +2 -0
- package/packages/web/dist/index.html +14 -0
- package/packages/web/package.json +36 -0
- package/plugins/README.md +64 -0
- package/plugins/files/dist/client.d.ts +5 -0
- package/plugins/files/dist/client.d.ts.map +1 -0
- package/plugins/files/dist/client.js +354 -0
- package/plugins/files/dist/client.js.map +1 -0
- package/plugins/files/dist/server.d.ts +32 -0
- package/plugins/files/dist/server.d.ts.map +1 -0
- package/plugins/files/dist/server.js +514 -0
- package/plugins/files/dist/server.js.map +1 -0
- package/plugins/files/dist/tools/edit-file.d.ts +29 -0
- package/plugins/files/dist/tools/edit-file.d.ts.map +1 -0
- package/plugins/files/dist/tools/edit-file.js +230 -0
- package/plugins/files/dist/tools/edit-file.js.map +1 -0
- package/plugins/files/dist/tools/edit-file.prompt.md +36 -0
- package/plugins/files/dist/tools/glob.d.ts +12 -0
- package/plugins/files/dist/tools/glob.d.ts.map +1 -0
- package/plugins/files/dist/tools/glob.js +84 -0
- package/plugins/files/dist/tools/glob.js.map +1 -0
- package/plugins/files/dist/tools/index.d.ts +13 -0
- package/plugins/files/dist/tools/index.d.ts.map +1 -0
- package/plugins/files/dist/tools/index.js +158 -0
- package/plugins/files/dist/tools/index.js.map +1 -0
- package/plugins/files/dist/tools/list-dir.d.ts +24 -0
- package/plugins/files/dist/tools/list-dir.d.ts.map +1 -0
- package/plugins/files/dist/tools/list-dir.js +104 -0
- package/plugins/files/dist/tools/list-dir.js.map +1 -0
- package/plugins/files/dist/tools/load-prompt.d.ts +5 -0
- package/plugins/files/dist/tools/load-prompt.d.ts.map +1 -0
- package/plugins/files/dist/tools/load-prompt.js +39 -0
- package/plugins/files/dist/tools/load-prompt.js.map +1 -0
- package/plugins/files/dist/tools/path-helper.d.ts +32 -0
- package/plugins/files/dist/tools/path-helper.d.ts.map +1 -0
- package/plugins/files/dist/tools/path-helper.js +113 -0
- package/plugins/files/dist/tools/path-helper.js.map +1 -0
- package/plugins/files/dist/tools/read-file.d.ts +17 -0
- package/plugins/files/dist/tools/read-file.d.ts.map +1 -0
- package/plugins/files/dist/tools/read-file.js +109 -0
- package/plugins/files/dist/tools/read-file.js.map +1 -0
- package/plugins/files/dist/tools/read-tracker.d.ts +28 -0
- package/plugins/files/dist/tools/read-tracker.d.ts.map +1 -0
- package/plugins/files/dist/tools/read-tracker.js +135 -0
- package/plugins/files/dist/tools/read-tracker.js.map +1 -0
- package/plugins/files/dist/tools/replacers.d.ts +27 -0
- package/plugins/files/dist/tools/replacers.d.ts.map +1 -0
- package/plugins/files/dist/tools/replacers.js +221 -0
- package/plugins/files/dist/tools/replacers.js.map +1 -0
- package/plugins/files/dist/tools/tenant-config-delete.d.ts +12 -0
- package/plugins/files/dist/tools/tenant-config-delete.d.ts.map +1 -0
- package/plugins/files/dist/tools/tenant-config-delete.js +70 -0
- package/plugins/files/dist/tools/tenant-config-delete.js.map +1 -0
- package/plugins/files/dist/tools/tenant-config-edit.d.ts +25 -0
- package/plugins/files/dist/tools/tenant-config-edit.d.ts.map +1 -0
- package/plugins/files/dist/tools/tenant-config-edit.js +142 -0
- package/plugins/files/dist/tools/tenant-config-edit.js.map +1 -0
- package/plugins/files/dist/tools/tenant-config-glob.d.ts +12 -0
- package/plugins/files/dist/tools/tenant-config-glob.d.ts.map +1 -0
- package/plugins/files/dist/tools/tenant-config-glob.js +64 -0
- package/plugins/files/dist/tools/tenant-config-glob.js.map +1 -0
- package/plugins/files/dist/tools/tenant-config-helper.d.ts +64 -0
- package/plugins/files/dist/tools/tenant-config-helper.d.ts.map +1 -0
- package/plugins/files/dist/tools/tenant-config-helper.js +162 -0
- package/plugins/files/dist/tools/tenant-config-helper.js.map +1 -0
- package/plugins/files/dist/tools/tenant-config-list.d.ts +20 -0
- package/plugins/files/dist/tools/tenant-config-list.d.ts.map +1 -0
- package/plugins/files/dist/tools/tenant-config-list.js +95 -0
- package/plugins/files/dist/tools/tenant-config-list.js.map +1 -0
- package/plugins/files/dist/tools/tenant-config-read.d.ts +17 -0
- package/plugins/files/dist/tools/tenant-config-read.d.ts.map +1 -0
- package/plugins/files/dist/tools/tenant-config-read.js +87 -0
- package/plugins/files/dist/tools/tenant-config-read.js.map +1 -0
- package/plugins/files/dist/tools/tenant-config-write.d.ts +14 -0
- package/plugins/files/dist/tools/tenant-config-write.d.ts.map +1 -0
- package/plugins/files/dist/tools/tenant-config-write.js +78 -0
- package/plugins/files/dist/tools/tenant-config-write.js.map +1 -0
- package/plugins/files/dist/tools/text-shape.d.ts +20 -0
- package/plugins/files/dist/tools/text-shape.d.ts.map +1 -0
- package/plugins/files/dist/tools/text-shape.js +57 -0
- package/plugins/files/dist/tools/text-shape.js.map +1 -0
- package/plugins/files/dist/tools/write-file.d.ts +12 -0
- package/plugins/files/dist/tools/write-file.d.ts.map +1 -0
- package/plugins/files/dist/tools/write-file.js +89 -0
- package/plugins/files/dist/tools/write-file.js.map +1 -0
- package/plugins/files/dist/tools/write-file.prompt.md +14 -0
- package/plugins/files/manifest.json +100 -0
- package/plugins/files/package.json +39 -0
- package/plugins/files/skills/files-workspace-layout.md +29 -0
- package/plugins/microsandbox/dist/admin/browser-routes.d.ts +41 -0
- package/plugins/microsandbox/dist/admin/browser-routes.d.ts.map +1 -0
- package/plugins/microsandbox/dist/admin/browser-routes.js +208 -0
- package/plugins/microsandbox/dist/admin/browser-routes.js.map +1 -0
- package/plugins/microsandbox/dist/admin/preview-exec.d.ts +38 -0
- package/plugins/microsandbox/dist/admin/preview-exec.d.ts.map +1 -0
- package/plugins/microsandbox/dist/admin/preview-exec.js +185 -0
- package/plugins/microsandbox/dist/admin/preview-exec.js.map +1 -0
- package/plugins/microsandbox/dist/admin/routes.d.ts +35 -0
- package/plugins/microsandbox/dist/admin/routes.d.ts.map +1 -0
- package/plugins/microsandbox/dist/admin/routes.js +728 -0
- package/plugins/microsandbox/dist/admin/routes.js.map +1 -0
- package/plugins/microsandbox/dist/admin/sandboxfile-io.d.ts +11 -0
- package/plugins/microsandbox/dist/admin/sandboxfile-io.d.ts.map +1 -0
- package/plugins/microsandbox/dist/admin/sandboxfile-io.js +72 -0
- package/plugins/microsandbox/dist/admin/sandboxfile-io.js.map +1 -0
- package/plugins/microsandbox/dist/admin/templates.d.ts +16 -0
- package/plugins/microsandbox/dist/admin/templates.d.ts.map +1 -0
- package/plugins/microsandbox/dist/admin/templates.js +66 -0
- package/plugins/microsandbox/dist/admin/templates.js.map +1 -0
- package/plugins/microsandbox/dist/admin.d.ts +5 -0
- package/plugins/microsandbox/dist/admin.d.ts.map +1 -0
- package/plugins/microsandbox/dist/admin.js +256 -0
- package/plugins/microsandbox/dist/admin.js.map +1 -0
- package/plugins/microsandbox/dist/build/builder.d.ts +69 -0
- package/plugins/microsandbox/dist/build/builder.d.ts.map +1 -0
- package/plugins/microsandbox/dist/build/builder.js +257 -0
- package/plugins/microsandbox/dist/build/builder.js.map +1 -0
- package/plugins/microsandbox/dist/build/metadata.d.ts +27 -0
- package/plugins/microsandbox/dist/build/metadata.d.ts.map +1 -0
- package/plugins/microsandbox/dist/build/metadata.js +55 -0
- package/plugins/microsandbox/dist/build/metadata.js.map +1 -0
- package/plugins/microsandbox/dist/build/pointer.d.ts +51 -0
- package/plugins/microsandbox/dist/build/pointer.d.ts.map +1 -0
- package/plugins/microsandbox/dist/build/pointer.js +130 -0
- package/plugins/microsandbox/dist/build/pointer.js.map +1 -0
- package/plugins/microsandbox/dist/build/sandboxfile.d.ts +15 -0
- package/plugins/microsandbox/dist/build/sandboxfile.d.ts.map +1 -0
- package/plugins/microsandbox/dist/build/sandboxfile.js +176 -0
- package/plugins/microsandbox/dist/build/sandboxfile.js.map +1 -0
- package/plugins/microsandbox/dist/client.d.ts +5 -0
- package/plugins/microsandbox/dist/client.d.ts.map +1 -0
- package/plugins/microsandbox/dist/client.js +941 -0
- package/plugins/microsandbox/dist/client.js.map +1 -0
- package/plugins/microsandbox/dist/runner/browser.d.ts +50 -0
- package/plugins/microsandbox/dist/runner/browser.d.ts.map +1 -0
- package/plugins/microsandbox/dist/runner/browser.js +142 -0
- package/plugins/microsandbox/dist/runner/browser.js.map +1 -0
- package/plugins/microsandbox/dist/runner/free-port.d.ts +6 -0
- package/plugins/microsandbox/dist/runner/free-port.d.ts.map +1 -0
- package/plugins/microsandbox/dist/runner/free-port.js +53 -0
- package/plugins/microsandbox/dist/runner/free-port.js.map +1 -0
- package/plugins/microsandbox/dist/runner/index.d.ts +28 -0
- package/plugins/microsandbox/dist/runner/index.d.ts.map +1 -0
- package/plugins/microsandbox/dist/runner/index.js +72 -0
- package/plugins/microsandbox/dist/runner/index.js.map +1 -0
- package/plugins/microsandbox/dist/runner/microsandbox.d.ts +64 -0
- package/plugins/microsandbox/dist/runner/microsandbox.d.ts.map +1 -0
- package/plugins/microsandbox/dist/runner/microsandbox.js +668 -0
- package/plugins/microsandbox/dist/runner/microsandbox.js.map +1 -0
- package/plugins/microsandbox/dist/runner/nullable.d.ts +36 -0
- package/plugins/microsandbox/dist/runner/nullable.d.ts.map +1 -0
- package/plugins/microsandbox/dist/runner/nullable.js +82 -0
- package/plugins/microsandbox/dist/runner/nullable.js.map +1 -0
- package/plugins/microsandbox/dist/runner/pool.d.ts +97 -0
- package/plugins/microsandbox/dist/runner/pool.d.ts.map +1 -0
- package/plugins/microsandbox/dist/runner/pool.js +494 -0
- package/plugins/microsandbox/dist/runner/pool.js.map +1 -0
- package/plugins/microsandbox/dist/runner/types.d.ts +33 -0
- package/plugins/microsandbox/dist/runner/types.d.ts.map +1 -0
- package/plugins/microsandbox/dist/runner/types.js +79 -0
- package/plugins/microsandbox/dist/runner/types.js.map +1 -0
- package/plugins/microsandbox/dist/server.d.ts +7 -0
- package/plugins/microsandbox/dist/server.d.ts.map +1 -0
- package/plugins/microsandbox/dist/server.js +276 -0
- package/plugins/microsandbox/dist/server.js.map +1 -0
- package/plugins/microsandbox/dist/tools/browser.d.ts +25 -0
- package/plugins/microsandbox/dist/tools/browser.d.ts.map +1 -0
- package/plugins/microsandbox/dist/tools/browser.js +78 -0
- package/plugins/microsandbox/dist/tools/browser.js.map +1 -0
- package/plugins/microsandbox/dist/tools/build.d.ts +5 -0
- package/plugins/microsandbox/dist/tools/build.d.ts.map +1 -0
- package/plugins/microsandbox/dist/tools/build.js +243 -0
- package/plugins/microsandbox/dist/tools/build.js.map +1 -0
- package/plugins/microsandbox/dist/tools/index.d.ts +9 -0
- package/plugins/microsandbox/dist/tools/index.d.ts.map +1 -0
- package/plugins/microsandbox/dist/tools/index.js +430 -0
- package/plugins/microsandbox/dist/tools/index.js.map +1 -0
- package/plugins/microsandbox/dist/tools/mcp-client.d.ts +63 -0
- package/plugins/microsandbox/dist/tools/mcp-client.d.ts.map +1 -0
- package/plugins/microsandbox/dist/tools/mcp-client.js +226 -0
- package/plugins/microsandbox/dist/tools/mcp-client.js.map +1 -0
- package/plugins/microsandbox/manifest.json +177 -0
- package/plugins/microsandbox/package.json +38 -0
- package/plugins/microsandbox/skills/microsandbox-browser-howto.md +155 -0
- package/plugins/microsandbox/skills/microsandbox-build-use.md +201 -0
- package/plugins/microsandbox/skills/microsandbox-config.md +38 -0
- package/plugins/microsandbox/skills/microsandbox-exec-howto.md +144 -0
- package/plugins/microsandbox/skills/microsandbox-libreoffice.md +159 -0
- package/plugins/microsandbox/templates/README.md +26 -0
- package/plugins/web-search/dist/server.d.ts +4 -0
- package/plugins/web-search/dist/server.d.ts.map +1 -0
- package/plugins/web-search/dist/server.js +73 -0
- package/plugins/web-search/dist/server.js.map +1 -0
- package/plugins/web-search/dist/tools/health.d.ts +31 -0
- package/plugins/web-search/dist/tools/health.d.ts.map +1 -0
- package/plugins/web-search/dist/tools/health.js +59 -0
- package/plugins/web-search/dist/tools/health.js.map +1 -0
- package/plugins/web-search/dist/tools/index.d.ts +3 -0
- package/plugins/web-search/dist/tools/index.d.ts.map +1 -0
- package/plugins/web-search/dist/tools/index.js +2 -0
- package/plugins/web-search/dist/tools/index.js.map +1 -0
- package/plugins/web-search/dist/tools/providers.d.ts +43 -0
- package/plugins/web-search/dist/tools/providers.d.ts.map +1 -0
- package/plugins/web-search/dist/tools/providers.js +140 -0
- package/plugins/web-search/dist/tools/providers.js.map +1 -0
- package/plugins/web-search/dist/tools/web-search.d.ts +15 -0
- package/plugins/web-search/dist/tools/web-search.d.ts.map +1 -0
- package/plugins/web-search/dist/tools/web-search.js +244 -0
- package/plugins/web-search/dist/tools/web-search.js.map +1 -0
- package/plugins/web-search/manifest.json +65 -0
- package/plugins/web-search/node_modules/@esbuild/darwin-arm64/README.md +3 -0
- package/plugins/web-search/node_modules/@esbuild/darwin-arm64/package.json +20 -0
- package/plugins/web-search/node_modules/@vitest/expect/LICENSE +21 -0
- package/plugins/web-search/node_modules/@vitest/expect/README.md +21 -0
- package/plugins/web-search/node_modules/@vitest/expect/dist/index.d.ts +808 -0
- package/plugins/web-search/node_modules/@vitest/expect/dist/index.js +1799 -0
- package/plugins/web-search/node_modules/@vitest/expect/package.json +46 -0
- package/plugins/web-search/node_modules/@vitest/mocker/LICENSE +21 -0
- package/plugins/web-search/node_modules/@vitest/mocker/README.md +5 -0
- package/plugins/web-search/node_modules/@vitest/mocker/dist/auto-register.d.ts +2 -0
- package/plugins/web-search/node_modules/@vitest/mocker/dist/auto-register.js +9 -0
- package/plugins/web-search/node_modules/@vitest/mocker/dist/browser.d.ts +53 -0
- package/plugins/web-search/node_modules/@vitest/mocker/dist/browser.js +91 -0
- package/plugins/web-search/node_modules/@vitest/mocker/dist/chunk-interceptor-native.js +15 -0
- package/plugins/web-search/node_modules/@vitest/mocker/dist/chunk-mocker.js +1602 -0
- package/plugins/web-search/node_modules/@vitest/mocker/dist/chunk-pathe.M-eThtNZ.js +174 -0
- package/plugins/web-search/node_modules/@vitest/mocker/dist/chunk-registry.js +182 -0
- package/plugins/web-search/node_modules/@vitest/mocker/dist/chunk-utils.js +16 -0
- package/plugins/web-search/node_modules/@vitest/mocker/dist/index.d.ts +21 -0
- package/plugins/web-search/node_modules/@vitest/mocker/dist/index.js +174 -0
- package/plugins/web-search/node_modules/@vitest/mocker/dist/mocker.d-Ce9_ySj5.d.ts +83 -0
- package/plugins/web-search/node_modules/@vitest/mocker/dist/node.d.ts +821 -0
- package/plugins/web-search/node_modules/@vitest/mocker/dist/node.js +1306 -0
- package/plugins/web-search/node_modules/@vitest/mocker/dist/redirect.d.ts +3 -0
- package/plugins/web-search/node_modules/@vitest/mocker/dist/redirect.js +75 -0
- package/plugins/web-search/node_modules/@vitest/mocker/dist/register.d.ts +9 -0
- package/plugins/web-search/node_modules/@vitest/mocker/dist/register.js +41 -0
- package/plugins/web-search/node_modules/@vitest/mocker/dist/registry.d-D765pazg.d.ts +87 -0
- package/plugins/web-search/node_modules/@vitest/mocker/dist/types.d-D_aRZRdy.d.ts +8 -0
- package/plugins/web-search/node_modules/@vitest/mocker/package.json +82 -0
- package/plugins/web-search/node_modules/@vitest/pretty-format/LICENSE +21 -0
- package/plugins/web-search/node_modules/@vitest/pretty-format/dist/index.d.ts +119 -0
- package/plugins/web-search/node_modules/@vitest/pretty-format/dist/index.js +1387 -0
- package/plugins/web-search/node_modules/@vitest/pretty-format/package.json +44 -0
- package/plugins/web-search/node_modules/@vitest/runner/LICENSE +21 -0
- package/plugins/web-search/node_modules/@vitest/runner/README.md +5 -0
- package/plugins/web-search/node_modules/@vitest/runner/dist/chunk-hooks.js +2254 -0
- package/plugins/web-search/node_modules/@vitest/runner/dist/index.d.ts +261 -0
- package/plugins/web-search/node_modules/@vitest/runner/dist/index.js +6 -0
- package/plugins/web-search/node_modules/@vitest/runner/dist/tasks.d-CkscK4of.d.ts +558 -0
- package/plugins/web-search/node_modules/@vitest/runner/dist/types.d.ts +163 -0
- package/plugins/web-search/node_modules/@vitest/runner/dist/types.js +1 -0
- package/plugins/web-search/node_modules/@vitest/runner/dist/utils.d.ts +47 -0
- package/plugins/web-search/node_modules/@vitest/runner/dist/utils.js +6 -0
- package/plugins/web-search/node_modules/@vitest/runner/package.json +49 -0
- package/plugins/web-search/node_modules/@vitest/snapshot/LICENSE +21 -0
- package/plugins/web-search/node_modules/@vitest/snapshot/README.md +84 -0
- package/plugins/web-search/node_modules/@vitest/snapshot/dist/environment.d-DHdQ1Csl.d.ts +22 -0
- package/plugins/web-search/node_modules/@vitest/snapshot/dist/environment.d.ts +16 -0
- package/plugins/web-search/node_modules/@vitest/snapshot/dist/environment.js +40 -0
- package/plugins/web-search/node_modules/@vitest/snapshot/dist/index.d.ts +137 -0
- package/plugins/web-search/node_modules/@vitest/snapshot/dist/index.js +2305 -0
- package/plugins/web-search/node_modules/@vitest/snapshot/dist/manager.d.ts +18 -0
- package/plugins/web-search/node_modules/@vitest/snapshot/dist/manager.js +73 -0
- package/plugins/web-search/node_modules/@vitest/snapshot/dist/rawSnapshot.d-lFsMJFUd.d.ts +61 -0
- package/plugins/web-search/node_modules/@vitest/snapshot/package.json +54 -0
- package/plugins/web-search/node_modules/@vitest/spy/LICENSE +21 -0
- package/plugins/web-search/node_modules/@vitest/spy/README.md +3 -0
- package/plugins/web-search/node_modules/@vitest/spy/dist/index.d.ts +356 -0
- package/plugins/web-search/node_modules/@vitest/spy/dist/index.js +191 -0
- package/plugins/web-search/node_modules/@vitest/spy/package.json +38 -0
- package/plugins/web-search/node_modules/@vitest/utils/LICENSE +21 -0
- package/plugins/web-search/node_modules/@vitest/utils/dist/chunk-_commonjsHelpers.js +158 -0
- package/plugins/web-search/node_modules/@vitest/utils/dist/diff.d.ts +104 -0
- package/plugins/web-search/node_modules/@vitest/utils/dist/diff.js +2185 -0
- package/plugins/web-search/node_modules/@vitest/utils/dist/error.d.ts +9 -0
- package/plugins/web-search/node_modules/@vitest/utils/dist/error.js +162 -0
- package/plugins/web-search/node_modules/@vitest/utils/dist/helpers.d.ts +56 -0
- package/plugins/web-search/node_modules/@vitest/utils/dist/helpers.js +251 -0
- package/plugins/web-search/node_modules/@vitest/utils/dist/index.d.ts +57 -0
- package/plugins/web-search/node_modules/@vitest/utils/dist/index.js +633 -0
- package/plugins/web-search/node_modules/@vitest/utils/dist/source-map.d.ts +139 -0
- package/plugins/web-search/node_modules/@vitest/utils/dist/source-map.js +996 -0
- package/plugins/web-search/node_modules/@vitest/utils/dist/types.d-BCElaP-c.d.ts +53 -0
- package/plugins/web-search/node_modules/@vitest/utils/dist/types.d.ts +53 -0
- package/plugins/web-search/node_modules/@vitest/utils/dist/types.js +1 -0
- package/plugins/web-search/node_modules/@vitest/utils/package.json +77 -0
- package/plugins/web-search/node_modules/chai/LICENSE +21 -0
- package/plugins/web-search/node_modules/chai/README.md +162 -0
- package/plugins/web-search/node_modules/chai/package.json +74 -0
- package/plugins/web-search/node_modules/esbuild/README.md +3 -0
- package/plugins/web-search/node_modules/esbuild/package.json +49 -0
- package/plugins/web-search/node_modules/std-env/README.md +118 -0
- package/plugins/web-search/node_modules/std-env/dist/index.cjs +1 -0
- package/plugins/web-search/node_modules/std-env/dist/index.d.cts +92 -0
- package/plugins/web-search/node_modules/std-env/dist/index.d.mts +92 -0
- package/plugins/web-search/node_modules/std-env/dist/index.d.ts +92 -0
- package/plugins/web-search/node_modules/std-env/dist/index.mjs +1 -0
- package/plugins/web-search/node_modules/std-env/package.json +46 -0
- package/plugins/web-search/node_modules/tinyexec/LICENSE +21 -0
- package/plugins/web-search/node_modules/tinyexec/README.md +256 -0
- package/plugins/web-search/node_modules/tinyexec/dist/main.cjs +575 -0
- package/plugins/web-search/node_modules/tinyexec/dist/main.d.cts +70 -0
- package/plugins/web-search/node_modules/tinyexec/dist/main.d.ts +70 -0
- package/plugins/web-search/node_modules/tinyexec/dist/main.js +578 -0
- package/plugins/web-search/node_modules/tinyexec/package.json +66 -0
- package/plugins/web-search/node_modules/tinyrainbow/README.md +28 -0
- package/plugins/web-search/node_modules/tinyrainbow/dist/browser.d.ts +8 -0
- package/plugins/web-search/node_modules/tinyrainbow/dist/browser.js +20 -0
- package/plugins/web-search/node_modules/tinyrainbow/dist/chunk-BVHSVHOK.js +90 -0
- package/plugins/web-search/node_modules/tinyrainbow/dist/index-8b61d5bc.d.ts +59 -0
- package/plugins/web-search/node_modules/tinyrainbow/dist/node.d.ts +8 -0
- package/plugins/web-search/node_modules/tinyrainbow/dist/node.js +22 -0
- package/plugins/web-search/node_modules/tinyrainbow/package.json +37 -0
- package/plugins/web-search/node_modules/typescript/README.md +50 -0
- package/plugins/web-search/node_modules/typescript/package.json +120 -0
- package/plugins/web-search/node_modules/vite/README.md +20 -0
- package/plugins/web-search/node_modules/vite/dist/client/client.mjs +1106 -0
- package/plugins/web-search/node_modules/vite/dist/client/env.mjs +19 -0
- package/plugins/web-search/node_modules/vite/dist/node/chunks/build.js +4 -0
- package/plugins/web-search/node_modules/vite/dist/node/chunks/build2.js +5538 -0
- package/plugins/web-search/node_modules/vite/dist/node/chunks/chunk.js +48 -0
- package/plugins/web-search/node_modules/vite/dist/node/chunks/config.js +36065 -0
- package/plugins/web-search/node_modules/vite/dist/node/chunks/config2.js +4 -0
- package/plugins/web-search/node_modules/vite/dist/node/chunks/dist.js +6758 -0
- package/plugins/web-search/node_modules/vite/dist/node/chunks/lib.js +377 -0
- package/plugins/web-search/node_modules/vite/dist/node/chunks/logger.js +329 -0
- package/plugins/web-search/node_modules/vite/dist/node/chunks/moduleRunnerTransport.d.ts +96 -0
- package/plugins/web-search/node_modules/vite/dist/node/chunks/optimizer.js +4 -0
- package/plugins/web-search/node_modules/vite/dist/node/chunks/postcss-import.js +479 -0
- package/plugins/web-search/node_modules/vite/dist/node/chunks/preview.js +4 -0
- package/plugins/web-search/node_modules/vite/dist/node/chunks/server.js +4 -0
- package/plugins/web-search/node_modules/vite/dist/node/cli.js +698 -0
- package/plugins/web-search/node_modules/vite/dist/node/index.d.ts +3717 -0
- package/plugins/web-search/node_modules/vite/dist/node/index.js +30 -0
- package/plugins/web-search/node_modules/vite/dist/node/module-runner.d.ts +311 -0
- package/plugins/web-search/node_modules/vite/dist/node/module-runner.js +1160 -0
- package/plugins/web-search/node_modules/vite/package.json +199 -0
- package/plugins/web-search/node_modules/vite/types/package.json +4 -0
- package/plugins/web-search/node_modules/vitest/README.md +7 -0
- package/plugins/web-search/node_modules/vitest/dist/browser.d.ts +34 -0
- package/plugins/web-search/node_modules/vitest/dist/browser.js +8 -0
- package/plugins/web-search/node_modules/vitest/dist/chunks/_commonjsHelpers.BFTU3MAI.js +7 -0
- package/plugins/web-search/node_modules/vitest/dist/chunks/base.DfmxU-tU.js +38 -0
- package/plugins/web-search/node_modules/vitest/dist/chunks/benchmark.CYdenmiT.js +37 -0
- package/plugins/web-search/node_modules/vitest/dist/chunks/benchmark.d.BwvBVTda.d.ts +24 -0
- package/plugins/web-search/node_modules/vitest/dist/chunks/cac.0BJqEUeA.js +1469 -0
- package/plugins/web-search/node_modules/vitest/dist/chunks/cli-api.DWGBtMmz.js +10660 -0
- package/plugins/web-search/node_modules/vitest/dist/chunks/config.d.BKdhh7Zx.d.ts +224 -0
- package/plugins/web-search/node_modules/vitest/dist/chunks/console.CtFJOzRO.js +153 -0
- package/plugins/web-search/node_modules/vitest/dist/chunks/constants.DnKduX2e.js +44 -0
- package/plugins/web-search/node_modules/vitest/dist/chunks/coverage.DVF1vEu8.js +25 -0
- package/plugins/web-search/node_modules/vitest/dist/chunks/coverage.DfSpMS-b.js +4350 -0
- package/plugins/web-search/node_modules/vitest/dist/chunks/coverage.d.S9RMNXIe.d.ts +35 -0
- package/plugins/web-search/node_modules/vitest/dist/chunks/creator.GK6I-cL4.js +640 -0
- package/plugins/web-search/node_modules/vitest/dist/chunks/date.Bq6ZW5rf.js +73 -0
- package/plugins/web-search/node_modules/vitest/dist/chunks/defaults.B7q_naMc.js +115 -0
- package/plugins/web-search/node_modules/vitest/dist/chunks/env.D4Lgay0q.js +8 -0
- package/plugins/web-search/node_modules/vitest/dist/chunks/environment.d.cL3nLXbE.d.ts +119 -0
- package/plugins/web-search/node_modules/vitest/dist/chunks/execute.B7h3T_Hc.js +708 -0
- package/plugins/web-search/node_modules/vitest/dist/chunks/git.BVQ8w_Sw.js +72 -0
- package/plugins/web-search/node_modules/vitest/dist/chunks/global.d.MAmajcmJ.d.ts +136 -0
- package/plugins/web-search/node_modules/vitest/dist/chunks/globals.DEHgCU4V.js +26 -0
- package/plugins/web-search/node_modules/vitest/dist/chunks/index.B521nVV-.js +157 -0
- package/plugins/web-search/node_modules/vitest/dist/chunks/index.BCWujgDG.js +231 -0
- package/plugins/web-search/node_modules/vitest/dist/chunks/index.CdQS2e2Q.js +37 -0
- package/plugins/web-search/node_modules/vitest/dist/chunks/index.CmSc2RE5.js +587 -0
- package/plugins/web-search/node_modules/vitest/dist/chunks/index.CwejwG0H.js +105 -0
- package/plugins/web-search/node_modules/vitest/dist/chunks/index.D3XRDfWc.js +213 -0
- package/plugins/web-search/node_modules/vitest/dist/chunks/index.VByaPkjc.js +2183 -0
- package/plugins/web-search/node_modules/vitest/dist/chunks/index.X0nbfr6-.js +6584 -0
- package/plugins/web-search/node_modules/vitest/dist/chunks/inspector.C914Efll.js +57 -0
- package/plugins/web-search/node_modules/vitest/dist/chunks/mocker.d.BE_2ls6u.d.ts +17 -0
- package/plugins/web-search/node_modules/vitest/dist/chunks/node.fjCdwEIl.js +15 -0
- package/plugins/web-search/node_modules/vitest/dist/chunks/reporters.d.BuRON0I0.d.ts +3168 -0
- package/plugins/web-search/node_modules/vitest/dist/chunks/rpc.-pEldfrD.js +83 -0
- package/plugins/web-search/node_modules/vitest/dist/chunks/runBaseTests.9Ij9_de-.js +129 -0
- package/plugins/web-search/node_modules/vitest/dist/chunks/setup-common.Dd054P77.js +60 -0
- package/plugins/web-search/node_modules/vitest/dist/chunks/suite.d.FvehnV49.d.ts +10 -0
- package/plugins/web-search/node_modules/vitest/dist/chunks/typechecker.DRKU1-1g.js +874 -0
- package/plugins/web-search/node_modules/vitest/dist/chunks/utils.CAioKnHs.js +61 -0
- package/plugins/web-search/node_modules/vitest/dist/chunks/utils.XdZDrNZV.js +65 -0
- package/plugins/web-search/node_modules/vitest/dist/chunks/vi.bdSIJ99Y.js +4015 -0
- package/plugins/web-search/node_modules/vitest/dist/chunks/vite.d.BnOPPc46.d.ts +25 -0
- package/plugins/web-search/node_modules/vitest/dist/chunks/vm.BThCzidc.js +756 -0
- package/plugins/web-search/node_modules/vitest/dist/chunks/worker.d.CUgIPz9V.d.ts +176 -0
- package/plugins/web-search/node_modules/vitest/dist/chunks/worker.d.uzWsCv9X.d.ts +8 -0
- package/plugins/web-search/node_modules/vitest/dist/cli.js +27 -0
- package/plugins/web-search/node_modules/vitest/dist/config.cjs +148 -0
- package/plugins/web-search/node_modules/vitest/dist/config.d.ts +100 -0
- package/plugins/web-search/node_modules/vitest/dist/config.js +21 -0
- package/plugins/web-search/node_modules/vitest/dist/coverage.d.ts +108 -0
- package/plugins/web-search/node_modules/vitest/dist/coverage.js +34 -0
- package/plugins/web-search/node_modules/vitest/dist/environments.d.ts +26 -0
- package/plugins/web-search/node_modules/vitest/dist/environments.js +2 -0
- package/plugins/web-search/node_modules/vitest/dist/execute.d.ts +150 -0
- package/plugins/web-search/node_modules/vitest/dist/execute.js +13 -0
- package/plugins/web-search/node_modules/vitest/dist/index.d.ts +651 -0
- package/plugins/web-search/node_modules/vitest/dist/index.js +18 -0
- package/plugins/web-search/node_modules/vitest/dist/mocker.d.ts +1 -0
- package/plugins/web-search/node_modules/vitest/dist/mocker.js +1 -0
- package/plugins/web-search/node_modules/vitest/dist/node.d.ts +158 -0
- package/plugins/web-search/node_modules/vitest/dist/node.js +105 -0
- package/plugins/web-search/node_modules/vitest/dist/path.js +7 -0
- package/plugins/web-search/node_modules/vitest/dist/reporters.d.ts +25 -0
- package/plugins/web-search/node_modules/vitest/dist/reporters.js +23 -0
- package/plugins/web-search/node_modules/vitest/dist/runners.d.ts +46 -0
- package/plugins/web-search/node_modules/vitest/dist/runners.js +235 -0
- package/plugins/web-search/node_modules/vitest/dist/snapshot.d.ts +9 -0
- package/plugins/web-search/node_modules/vitest/dist/snapshot.js +4 -0
- package/plugins/web-search/node_modules/vitest/dist/spy.js +1 -0
- package/plugins/web-search/node_modules/vitest/dist/suite.d.ts +5 -0
- package/plugins/web-search/node_modules/vitest/dist/suite.js +5 -0
- package/plugins/web-search/node_modules/vitest/dist/worker.js +124 -0
- package/plugins/web-search/node_modules/vitest/dist/workers/forks.js +43 -0
- package/plugins/web-search/node_modules/vitest/dist/workers/runVmTests.js +90 -0
- package/plugins/web-search/node_modules/vitest/dist/workers/threads.js +31 -0
- package/plugins/web-search/node_modules/vitest/dist/workers/vmForks.js +47 -0
- package/plugins/web-search/node_modules/vitest/dist/workers/vmThreads.js +37 -0
- package/plugins/web-search/node_modules/vitest/dist/workers.d.ts +40 -0
- package/plugins/web-search/node_modules/vitest/dist/workers.js +30 -0
- package/plugins/web-search/node_modules/vitest/package.json +207 -0
- package/plugins/web-search/package.json +30 -0
- package/plugins/web-search/skills/web-search-howto.md +69 -0
- package/plugins/workboard/agent-seeds/echo-demo/agent.json +7 -0
- package/plugins/workboard/agent-seeds/llm-default/SOUL.md +53 -0
- package/plugins/workboard/agent-seeds/llm-default/agent.json +7 -0
- package/plugins/workboard/dist/client.d.ts +5 -0
- package/plugins/workboard/dist/client.d.ts.map +1 -0
- package/plugins/workboard/dist/client.js +895 -0
- package/plugins/workboard/dist/client.js.map +1 -0
- package/plugins/workboard/dist/db/agents.d.ts +100 -0
- package/plugins/workboard/dist/db/agents.d.ts.map +1 -0
- package/plugins/workboard/dist/db/agents.js +280 -0
- package/plugins/workboard/dist/db/agents.js.map +1 -0
- package/plugins/workboard/dist/db/schema.d.ts +3 -0
- package/plugins/workboard/dist/db/schema.d.ts.map +1 -0
- package/plugins/workboard/dist/db/schema.js +31 -0
- package/plugins/workboard/dist/db/schema.js.map +1 -0
- package/plugins/workboard/dist/db/session-history.d.ts +28 -0
- package/plugins/workboard/dist/db/session-history.d.ts.map +1 -0
- package/plugins/workboard/dist/db/session-history.js +224 -0
- package/plugins/workboard/dist/db/session-history.js.map +1 -0
- package/plugins/workboard/dist/db/tasks.d.ts +260 -0
- package/plugins/workboard/dist/db/tasks.d.ts.map +1 -0
- package/plugins/workboard/dist/db/tasks.js +451 -0
- package/plugins/workboard/dist/db/tasks.js.map +1 -0
- package/plugins/workboard/dist/db/worker-agents.d.ts +16 -0
- package/plugins/workboard/dist/db/worker-agents.d.ts.map +1 -0
- package/plugins/workboard/dist/db/worker-agents.js +62 -0
- package/plugins/workboard/dist/db/worker-agents.js.map +1 -0
- package/plugins/workboard/dist/effective-skills.d.ts +13 -0
- package/plugins/workboard/dist/effective-skills.d.ts.map +1 -0
- package/plugins/workboard/dist/effective-skills.js +126 -0
- package/plugins/workboard/dist/effective-skills.js.map +1 -0
- package/plugins/workboard/dist/fs-worker-agents.d.ts +35 -0
- package/plugins/workboard/dist/fs-worker-agents.d.ts.map +1 -0
- package/plugins/workboard/dist/fs-worker-agents.js +199 -0
- package/plugins/workboard/dist/fs-worker-agents.js.map +1 -0
- package/plugins/workboard/dist/migrate-worker-agents.d.ts +11 -0
- package/plugins/workboard/dist/migrate-worker-agents.d.ts.map +1 -0
- package/plugins/workboard/dist/migrate-worker-agents.js +89 -0
- package/plugins/workboard/dist/migrate-worker-agents.js.map +1 -0
- package/plugins/workboard/dist/routes/handlers.d.ts +106 -0
- package/plugins/workboard/dist/routes/handlers.d.ts.map +1 -0
- package/plugins/workboard/dist/routes/handlers.js +668 -0
- package/plugins/workboard/dist/routes/handlers.js.map +1 -0
- package/plugins/workboard/dist/server.d.ts +6 -0
- package/plugins/workboard/dist/server.d.ts.map +1 -0
- package/plugins/workboard/dist/server.js +368 -0
- package/plugins/workboard/dist/server.js.map +1 -0
- package/plugins/workboard/dist/tools/index.d.ts +70 -0
- package/plugins/workboard/dist/tools/index.d.ts.map +1 -0
- package/plugins/workboard/dist/tools/index.js +963 -0
- package/plugins/workboard/dist/tools/index.js.map +1 -0
- package/plugins/workboard/dist/types.d.ts +27 -0
- package/plugins/workboard/dist/types.d.ts.map +1 -0
- package/plugins/workboard/dist/types.js +16 -0
- package/plugins/workboard/dist/types.js.map +1 -0
- package/plugins/workboard/dist/worker/pool.d.ts +220 -0
- package/plugins/workboard/dist/worker/pool.d.ts.map +1 -0
- package/plugins/workboard/dist/worker/pool.js +866 -0
- package/plugins/workboard/dist/worker/pool.js.map +1 -0
- package/plugins/workboard/dist/worker/tool-policy.d.ts +27 -0
- package/plugins/workboard/dist/worker/tool-policy.d.ts.map +1 -0
- package/plugins/workboard/dist/worker/tool-policy.js +76 -0
- package/plugins/workboard/dist/worker/tool-policy.js.map +1 -0
- package/plugins/workboard/dist/worker-agents-page.d.ts +4 -0
- package/plugins/workboard/dist/worker-agents-page.d.ts.map +1 -0
- package/plugins/workboard/dist/worker-agents-page.js +193 -0
- package/plugins/workboard/dist/worker-agents-page.js.map +1 -0
- package/plugins/workboard/manifest.json +180 -0
- package/plugins/workboard/package.json +37 -0
- package/plugins/workboard/skills/large-input-large-output.md +185 -0
- package/plugins/workboard/skills/workboard-howto.md +166 -0
- package/plugins/workboard/skills/worker-creator.md +267 -0
- package/plugins/workboard/skills/worker-fleet.md +431 -0
|
@@ -0,0 +1,941 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
|
+
// MicroSandbox plugin — client side.
|
|
3
|
+
//
|
|
4
|
+
// Surfaces:
|
|
5
|
+
// - MicroSandboxAdminPage — Sandboxfile editor + builds list +
|
|
6
|
+
// use / reset, rendered in the chat
|
|
7
|
+
// shell's `/admin` surface
|
|
8
|
+
// (adminPages contribution, ADR-0004 §12).
|
|
9
|
+
// - BrowserViewportPanel — noVNC iframe inlined in the chat
|
|
10
|
+
// shell's right column so the user can
|
|
11
|
+
// watch the agent drive the browser
|
|
12
|
+
// without leaving the conversation.
|
|
13
|
+
//
|
|
14
|
+
// (We used to ship two more surfaces: a SandboxStatusPanel right-
|
|
15
|
+
// column widget and a separate BrowserAdminPage. Both went away —
|
|
16
|
+
// the Sandbox admin page covers status, and the chat-shell
|
|
17
|
+
// BrowserViewportPanel is the only place the live VNC view needs
|
|
18
|
+
// to live; admin Browser would have been a third copy of the same
|
|
19
|
+
// iframe.)
|
|
20
|
+
//
|
|
21
|
+
// We bundle every component into one client entry because manifests
|
|
22
|
+
// carry one `client.entry` per plugin. Tree-shaking keeps the
|
|
23
|
+
// admin-only paths cheap when the chat shell is the only thing open.
|
|
24
|
+
import { useCallback, useEffect, useRef, useState } from "react";
|
|
25
|
+
import { AlertTriangle, CheckCircle2, Globe, Hammer, Loader2, RefreshCw, RotateCcw, Save, Settings, Terminal, Trash2, UploadCloud, X, } from "lucide-react";
|
|
26
|
+
import { PluginConfigForm } from "@tianshu/plugin-sdk/client";
|
|
27
|
+
const ROUTE_BASE = "/api/p/microsandbox";
|
|
28
|
+
async function fetchJson(url, init) {
|
|
29
|
+
const r = await fetch(url, { credentials: "include", ...init });
|
|
30
|
+
const text = await r.text();
|
|
31
|
+
let parsed = null;
|
|
32
|
+
if (text) {
|
|
33
|
+
try {
|
|
34
|
+
parsed = JSON.parse(text);
|
|
35
|
+
}
|
|
36
|
+
catch {
|
|
37
|
+
/* not JSON */
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
if (!r.ok) {
|
|
41
|
+
const detail = parsed?.message ??
|
|
42
|
+
parsed?.error ??
|
|
43
|
+
`HTTP ${r.status}`;
|
|
44
|
+
throw new Error(detail);
|
|
45
|
+
}
|
|
46
|
+
return parsed;
|
|
47
|
+
}
|
|
48
|
+
function formatRelative(iso) {
|
|
49
|
+
const t = Date.parse(iso);
|
|
50
|
+
if (Number.isNaN(t))
|
|
51
|
+
return iso;
|
|
52
|
+
const diff = Date.now() - t;
|
|
53
|
+
const m = Math.floor(diff / 60_000);
|
|
54
|
+
if (m < 1)
|
|
55
|
+
return "just now";
|
|
56
|
+
if (m < 60)
|
|
57
|
+
return `${m}m ago`;
|
|
58
|
+
const h = Math.floor(m / 60);
|
|
59
|
+
if (h < 24)
|
|
60
|
+
return `${h}h ago`;
|
|
61
|
+
const d = Math.floor(h / 24);
|
|
62
|
+
return `${d}d ago`;
|
|
63
|
+
}
|
|
64
|
+
function formatUptime(ms) {
|
|
65
|
+
if (ms < 1000)
|
|
66
|
+
return `${ms}ms`;
|
|
67
|
+
const s = Math.floor(ms / 1000);
|
|
68
|
+
if (s < 60)
|
|
69
|
+
return `${s}s`;
|
|
70
|
+
const m = Math.floor(s / 60);
|
|
71
|
+
if (m < 60)
|
|
72
|
+
return `${m}m ${s % 60}s`;
|
|
73
|
+
const h = Math.floor(m / 60);
|
|
74
|
+
return `${h}h ${m % 60}m`;
|
|
75
|
+
}
|
|
76
|
+
/** Render kB values from /proc/meminfo as a compact human
|
|
77
|
+
* string ("1.2 GiB" / "864 MiB"). meminfo's "kB" is actually
|
|
78
|
+
* KiB (1024-based) so we use 1024 throughout. */
|
|
79
|
+
function formatKb(kb) {
|
|
80
|
+
if (!Number.isFinite(kb) || kb < 0)
|
|
81
|
+
return "—";
|
|
82
|
+
if (kb < 1024)
|
|
83
|
+
return `${kb} KiB`;
|
|
84
|
+
const mib = kb / 1024;
|
|
85
|
+
if (mib < 1024)
|
|
86
|
+
return `${Math.round(mib)} MiB`;
|
|
87
|
+
const gib = mib / 1024;
|
|
88
|
+
// 0.1 GiB precision; "1.2 GiB" is more readable than "1234 MiB".
|
|
89
|
+
return `${gib.toFixed(1)} GiB`;
|
|
90
|
+
}
|
|
91
|
+
function extractMetaString(meta, key) {
|
|
92
|
+
if (!meta)
|
|
93
|
+
return null;
|
|
94
|
+
const v = meta[key];
|
|
95
|
+
return typeof v === "string" ? v : null;
|
|
96
|
+
}
|
|
97
|
+
function MicroSandboxAdminPage(_props) {
|
|
98
|
+
// Bumping this counter signals "something changed in the sandbox
|
|
99
|
+
// lifecycle; sections that fetch derived state should re-fetch."
|
|
100
|
+
// BuildsSection bumps it after switching the in-use build
|
|
101
|
+
// (with or without reset). ResetSection listens and re-fetches
|
|
102
|
+
// status whenever it changes.
|
|
103
|
+
const [refreshTick, setRefreshTick] = useState(0);
|
|
104
|
+
const bumpRefresh = useCallback(() => setRefreshTick((n) => n + 1), []);
|
|
105
|
+
return (_jsxs("div", { className: "mx-auto max-w-4xl px-6 py-6 text-gray-200", children: [_jsxs("header", { className: "mb-6 border-b border-gray-800 pb-4", children: [_jsx("h1", { className: "text-lg font-semibold text-gray-100", children: "MicroSandbox" }), _jsx("p", { className: "mt-1 text-[12px] leading-relaxed text-gray-500", children: "Edit your Sandboxfile, build a new image, and switch this tenant to use it. Sanity-check a fresh build via the shell's preview target (\u201Cdoes my apt package show up on PATH?\u201D) before flipping the tenant to it." })] }), _jsx(SandboxfileSection, {}), _jsx("div", { className: "my-6 border-t border-gray-800" }), _jsx(BuildsSection, { onMutate: bumpRefresh }), _jsx("div", { className: "my-6 border-t border-gray-800" }), _jsx(TaskPoolSection, { refreshTick: refreshTick }), _jsx("div", { className: "my-6 border-t border-gray-800" }), _jsx(ShellSection, {}), _jsx("div", { className: "my-6 border-t border-gray-800" }), _jsx(ResetSection, { refreshTick: refreshTick, onMutate: bumpRefresh })] }));
|
|
106
|
+
}
|
|
107
|
+
function SandboxfileSection() {
|
|
108
|
+
const [payload, setPayload] = useState(null);
|
|
109
|
+
const [draft, setDraft] = useState("");
|
|
110
|
+
const [loading, setLoading] = useState(true);
|
|
111
|
+
const [saving, setSaving] = useState(false);
|
|
112
|
+
const [error, setError] = useState(null);
|
|
113
|
+
const [parseError, setParseError] = useState(null);
|
|
114
|
+
const [savedAt, setSavedAt] = useState(null);
|
|
115
|
+
const [templates, setTemplates] = useState([]);
|
|
116
|
+
const load = useCallback(async () => {
|
|
117
|
+
setLoading(true);
|
|
118
|
+
setError(null);
|
|
119
|
+
try {
|
|
120
|
+
const r = await fetchJson(`${ROUTE_BASE}/sandboxfile`);
|
|
121
|
+
setPayload(r);
|
|
122
|
+
setDraft(r.content);
|
|
123
|
+
}
|
|
124
|
+
catch (err) {
|
|
125
|
+
setError(err instanceof Error ? err.message : String(err));
|
|
126
|
+
}
|
|
127
|
+
finally {
|
|
128
|
+
setLoading(false);
|
|
129
|
+
}
|
|
130
|
+
}, []);
|
|
131
|
+
useEffect(() => {
|
|
132
|
+
void load();
|
|
133
|
+
}, [load]);
|
|
134
|
+
// Templates are server-static; fetch once.
|
|
135
|
+
useEffect(() => {
|
|
136
|
+
let cancelled = false;
|
|
137
|
+
(async () => {
|
|
138
|
+
try {
|
|
139
|
+
const r = await fetchJson(`${ROUTE_BASE}/sandboxfile/templates`);
|
|
140
|
+
if (!cancelled)
|
|
141
|
+
setTemplates(r.templates);
|
|
142
|
+
}
|
|
143
|
+
catch {
|
|
144
|
+
// Non-fatal: leave the dropdown empty so users can still
|
|
145
|
+
// author from scratch.
|
|
146
|
+
}
|
|
147
|
+
})();
|
|
148
|
+
return () => {
|
|
149
|
+
cancelled = true;
|
|
150
|
+
};
|
|
151
|
+
}, []);
|
|
152
|
+
const dirty = payload != null && draft !== payload.content;
|
|
153
|
+
function loadTemplate(id) {
|
|
154
|
+
if (!id)
|
|
155
|
+
return;
|
|
156
|
+
const t = templates.find((x) => x.id === id);
|
|
157
|
+
if (!t)
|
|
158
|
+
return;
|
|
159
|
+
if (payload &&
|
|
160
|
+
draft !== payload.content &&
|
|
161
|
+
!window.confirm(`You have unsaved changes. Replace the editor with the "${t.displayName}" template?`)) {
|
|
162
|
+
return;
|
|
163
|
+
}
|
|
164
|
+
setDraft(t.content);
|
|
165
|
+
}
|
|
166
|
+
async function save() {
|
|
167
|
+
setSaving(true);
|
|
168
|
+
setError(null);
|
|
169
|
+
setParseError(null);
|
|
170
|
+
try {
|
|
171
|
+
const r = await fetchJson(`${ROUTE_BASE}/sandboxfile`, {
|
|
172
|
+
method: "PUT",
|
|
173
|
+
headers: { "Content-Type": "application/json" },
|
|
174
|
+
body: JSON.stringify({ content: draft }),
|
|
175
|
+
});
|
|
176
|
+
setPayload({ content: draft, exists: true, path: r.path });
|
|
177
|
+
setParseError(r.parseError);
|
|
178
|
+
setSavedAt(Date.now());
|
|
179
|
+
}
|
|
180
|
+
catch (err) {
|
|
181
|
+
setError(err instanceof Error ? err.message : String(err));
|
|
182
|
+
}
|
|
183
|
+
finally {
|
|
184
|
+
setSaving(false);
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
return (_jsxs("section", { children: [_jsx(SectionHeader, { title: "Sandboxfile", description: payload?.exists === false
|
|
188
|
+
? "No Sandboxfile yet. Edit and save to create one."
|
|
189
|
+
: payload?.path
|
|
190
|
+
? `Saved at ${payload.path}`
|
|
191
|
+
: "", actions: _jsxs(_Fragment, { children: [templates.length > 0 && (_jsxs("select", { value: "", onChange: (e) => {
|
|
192
|
+
loadTemplate(e.target.value);
|
|
193
|
+
e.target.value = "";
|
|
194
|
+
}, className: "rounded-md border border-gray-800 bg-gray-900 px-2 py-1 text-[11px] text-gray-300 hover:border-gray-700 focus:border-blue-700 focus:outline-none", title: "Replace the editor contents with a starting template", children: [_jsx("option", { value: "", children: "Load template\u2026" }), templates.map((t) => (_jsx("option", { value: t.id, title: t.description, children: t.displayName }, t.id)))] })), _jsxs("button", { type: "button", onClick: () => void load(), disabled: loading, className: "btn-ghost flex items-center gap-1.5 px-2 py-1 text-[11px] text-gray-400", title: "Reload from disk", children: [_jsx(RefreshCw, { size: 12, className: loading ? "animate-spin" : "" }), "Reload"] }), _jsxs("button", { type: "button", onClick: () => void save(), disabled: !dirty || saving, className: "flex items-center gap-1.5 rounded-md bg-blue-600 px-3 py-1.5 text-[11px] font-medium text-white hover:bg-blue-500 disabled:cursor-not-allowed disabled:bg-gray-800 disabled:text-gray-500", children: [saving ? (_jsx(Loader2, { size: 12, className: "animate-spin" })) : (_jsx(Save, { size: 12 })), "Save"] })] }) }), error && _jsx(Banner, { kind: "error", text: error }), parseError && (_jsx(Banner, { kind: "warn", text: `Saved, but the file does not parse: ${parseError}` })), !error && !parseError && savedAt && Date.now() - savedAt < 4000 && (_jsx(Banner, { kind: "ok", text: "Saved." })), _jsx("textarea", { value: draft, onChange: (e) => setDraft(e.target.value), spellCheck: false, className: "mt-2 h-64 w-full resize-y rounded-md border border-gray-800 bg-gray-950 px-3 py-2 font-mono text-[12px] leading-relaxed text-gray-200 outline-none focus:border-blue-700", placeholder: "image: python:3.12-slim\ncpus: 4\nmemory_mib: 4096" }), _jsxs("p", { className: "mt-2 text-[11px] leading-relaxed text-gray-500", children: ["Path: ", _jsx("code", { className: "rounded bg-gray-800 px-1", children: payload?.path ?? "…" }), ". v0 grammar: ", _jsx("code", { className: "rounded bg-gray-800 px-1", children: "image:" }), ",", " ", _jsx("code", { className: "rounded bg-gray-800 px-1", children: "cpus:" }), ",", " ", _jsx("code", { className: "rounded bg-gray-800 px-1", children: "memory_mib:" }), ", and the lists", " ", _jsx("code", { className: "rounded bg-gray-800 px-1", children: "apt" }), ",", " ", _jsx("code", { className: "rounded bg-gray-800 px-1", children: "pip" }), ",", " ", _jsx("code", { className: "rounded bg-gray-800 px-1", children: "npm" }), ",", " ", _jsx("code", { className: "rounded bg-gray-800 px-1", children: "exec" }), "."] })] }));
|
|
195
|
+
}
|
|
196
|
+
function BuildsSection({ onMutate }) {
|
|
197
|
+
const [data, setData] = useState(null);
|
|
198
|
+
const [error, setError] = useState(null);
|
|
199
|
+
const [loading, setLoading] = useState(true);
|
|
200
|
+
const [building, setBuilding] = useState(false);
|
|
201
|
+
const [usingId, setUsingId] = useState(null);
|
|
202
|
+
/** When set, the next build will layer on top of this snapshot
|
|
203
|
+
* instead of pulling the Sandboxfile's `image:`. UI surfaces
|
|
204
|
+
* the picker as a dropdown next to the Build button. */
|
|
205
|
+
const [basedOnSnapshot, setBasedOnSnapshot] = useState("");
|
|
206
|
+
/** Live log lines for the in-progress build (or the most recent
|
|
207
|
+
* one if it just finished). Cleared when a new build starts. */
|
|
208
|
+
const [buildLog, setBuildLog] = useState([]);
|
|
209
|
+
/** When set, the current build is in the start → done/error window. */
|
|
210
|
+
const [buildStartedAt, setBuildStartedAt] = useState(null);
|
|
211
|
+
const [elapsedMs, setElapsedMs] = useState(0);
|
|
212
|
+
const logRef = useRef(null);
|
|
213
|
+
// Tick the elapsed counter so the spinner doesn't feel frozen even
|
|
214
|
+
// when the SDK goes quiet for many seconds (e.g. while it pulls a
|
|
215
|
+
// base image).
|
|
216
|
+
useEffect(() => {
|
|
217
|
+
if (buildStartedAt === null)
|
|
218
|
+
return;
|
|
219
|
+
const i = window.setInterval(() => setElapsedMs(Date.now() - buildStartedAt), 250);
|
|
220
|
+
return () => window.clearInterval(i);
|
|
221
|
+
}, [buildStartedAt]);
|
|
222
|
+
// Auto-scroll the log pane on every new line.
|
|
223
|
+
useEffect(() => {
|
|
224
|
+
const el = logRef.current;
|
|
225
|
+
if (el)
|
|
226
|
+
el.scrollTop = el.scrollHeight;
|
|
227
|
+
}, [buildLog]);
|
|
228
|
+
const load = useCallback(async () => {
|
|
229
|
+
setLoading(true);
|
|
230
|
+
setError(null);
|
|
231
|
+
try {
|
|
232
|
+
const r = await fetchJson(`${ROUTE_BASE}/builds`);
|
|
233
|
+
setData(r);
|
|
234
|
+
}
|
|
235
|
+
catch (err) {
|
|
236
|
+
setError(err instanceof Error ? err.message : String(err));
|
|
237
|
+
}
|
|
238
|
+
finally {
|
|
239
|
+
setLoading(false);
|
|
240
|
+
}
|
|
241
|
+
}, []);
|
|
242
|
+
useEffect(() => {
|
|
243
|
+
void load();
|
|
244
|
+
}, [load]);
|
|
245
|
+
async function build() {
|
|
246
|
+
setBuilding(true);
|
|
247
|
+
setError(null);
|
|
248
|
+
setBuildLog([]);
|
|
249
|
+
setBuildStartedAt(Date.now());
|
|
250
|
+
setElapsedMs(0);
|
|
251
|
+
try {
|
|
252
|
+
const params = new URLSearchParams({ stream: "1" });
|
|
253
|
+
if (basedOnSnapshot)
|
|
254
|
+
params.set("from_snapshot", basedOnSnapshot);
|
|
255
|
+
const r = await fetch(`${ROUTE_BASE}/builds?${params.toString()}`, {
|
|
256
|
+
method: "POST",
|
|
257
|
+
credentials: "include",
|
|
258
|
+
headers: { "Content-Type": "application/json" },
|
|
259
|
+
body: "{}",
|
|
260
|
+
});
|
|
261
|
+
if (!r.ok || !r.body) {
|
|
262
|
+
throw new Error(`build request failed: HTTP ${r.status}${r.statusText ? " " + r.statusText : ""}`);
|
|
263
|
+
}
|
|
264
|
+
// Read NDJSON: one JSON object per "\n"-terminated line.
|
|
265
|
+
const reader = r.body.getReader();
|
|
266
|
+
const decoder = new TextDecoder();
|
|
267
|
+
let buf = "";
|
|
268
|
+
let finalError = null;
|
|
269
|
+
// eslint-disable-next-line no-constant-condition
|
|
270
|
+
while (true) {
|
|
271
|
+
const { value, done } = await reader.read();
|
|
272
|
+
if (done)
|
|
273
|
+
break;
|
|
274
|
+
buf += decoder.decode(value, { stream: true });
|
|
275
|
+
let nl;
|
|
276
|
+
// eslint-disable-next-line no-cond-assign
|
|
277
|
+
while ((nl = buf.indexOf("\n")) >= 0) {
|
|
278
|
+
const raw = buf.slice(0, nl).trim();
|
|
279
|
+
buf = buf.slice(nl + 1);
|
|
280
|
+
if (!raw)
|
|
281
|
+
continue;
|
|
282
|
+
let evt;
|
|
283
|
+
try {
|
|
284
|
+
evt = JSON.parse(raw);
|
|
285
|
+
}
|
|
286
|
+
catch {
|
|
287
|
+
// Treat malformed lines as raw log so we don't lose them.
|
|
288
|
+
setBuildLog((prev) => [...prev, raw]);
|
|
289
|
+
continue;
|
|
290
|
+
}
|
|
291
|
+
if (evt.type === "log" && typeof evt.line === "string") {
|
|
292
|
+
const line = evt.line;
|
|
293
|
+
setBuildLog((prev) => [...prev, line]);
|
|
294
|
+
}
|
|
295
|
+
else if (evt.type === "start") {
|
|
296
|
+
setBuildLog((prev) => [
|
|
297
|
+
...prev,
|
|
298
|
+
`[stream] build ${String(evt.buildId ?? "?")} started (image=${String(evt.image ?? "?")})`,
|
|
299
|
+
]);
|
|
300
|
+
}
|
|
301
|
+
else if (evt.type === "done") {
|
|
302
|
+
// The list reload below will surface the new entry; we
|
|
303
|
+
// don't need to do anything else here.
|
|
304
|
+
}
|
|
305
|
+
else if (evt.type === "error") {
|
|
306
|
+
finalError = String(evt.message ?? "build failed");
|
|
307
|
+
const stderr = typeof evt.stderr === "string" && evt.stderr.length > 0
|
|
308
|
+
? `\n${evt.stderr}`
|
|
309
|
+
: "";
|
|
310
|
+
setBuildLog((prev) => [...prev, `[error] ${finalError}${stderr}`]);
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
// Drain any trailing partial line.
|
|
315
|
+
const tail = buf.trim();
|
|
316
|
+
if (tail) {
|
|
317
|
+
try {
|
|
318
|
+
const evt = JSON.parse(tail);
|
|
319
|
+
if (evt.type === "log" && typeof evt.line === "string") {
|
|
320
|
+
setBuildLog((prev) => [...prev, evt.line]);
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
catch {
|
|
324
|
+
/* swallow */
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
if (finalError) {
|
|
328
|
+
setError(finalError);
|
|
329
|
+
}
|
|
330
|
+
await load();
|
|
331
|
+
}
|
|
332
|
+
catch (err) {
|
|
333
|
+
setError(err instanceof Error ? err.message : String(err));
|
|
334
|
+
}
|
|
335
|
+
finally {
|
|
336
|
+
setBuilding(false);
|
|
337
|
+
setBuildStartedAt(null);
|
|
338
|
+
}
|
|
339
|
+
}
|
|
340
|
+
/**
|
|
341
|
+
* Pin a build to a role.
|
|
342
|
+
*
|
|
343
|
+
* @param role "browser" updates the live long-lived sandbox pointer
|
|
344
|
+
* (resets the VM when `reset=true`); "task" updates the
|
|
345
|
+
* per-task pool pointer (no live VM today, so reset is
|
|
346
|
+
* ignored on the wire); "both" matches the legacy
|
|
347
|
+
* behaviour where one snapshot served everything.
|
|
348
|
+
*/
|
|
349
|
+
async function useBuild(buildId, role, reset) {
|
|
350
|
+
setUsingId(buildId);
|
|
351
|
+
setError(null);
|
|
352
|
+
try {
|
|
353
|
+
const params = new URLSearchParams({ build_id: buildId, role });
|
|
354
|
+
if (reset)
|
|
355
|
+
params.set("reset", "1");
|
|
356
|
+
const url = `${ROUTE_BASE}/builds/use?${params.toString()}`;
|
|
357
|
+
const r = await fetchJson(url, { method: "POST" });
|
|
358
|
+
if (reset &&
|
|
359
|
+
typeof r.reset === "object" &&
|
|
360
|
+
r.reset !== null &&
|
|
361
|
+
"failed" in r.reset) {
|
|
362
|
+
setError(`Switched, but reset failed: ${r.reset.failed}`);
|
|
363
|
+
}
|
|
364
|
+
await load();
|
|
365
|
+
// Tell sibling sections (Live sandbox status panel) the
|
|
366
|
+
// sandbox lifecycle changed so they can re-fetch.
|
|
367
|
+
onMutate();
|
|
368
|
+
}
|
|
369
|
+
catch (err) {
|
|
370
|
+
setError(err instanceof Error ? err.message : String(err));
|
|
371
|
+
}
|
|
372
|
+
finally {
|
|
373
|
+
setUsingId(null);
|
|
374
|
+
}
|
|
375
|
+
}
|
|
376
|
+
return (_jsxs("section", { children: [_jsx(SectionHeader, { title: "Builds", description: (() => {
|
|
377
|
+
const b = data?.pointers?.browser;
|
|
378
|
+
const t = data?.pointers?.task;
|
|
379
|
+
if (!b && !t) {
|
|
380
|
+
return "No build selected — the runner uses the configured default image.";
|
|
381
|
+
}
|
|
382
|
+
if (b && t && b.snapshotName === t.snapshotName) {
|
|
383
|
+
return `In use (Browser + Task): ${b.snapshotName}`;
|
|
384
|
+
}
|
|
385
|
+
const parts = [];
|
|
386
|
+
if (b)
|
|
387
|
+
parts.push(`Browser: ${b.snapshotName}`);
|
|
388
|
+
if (t)
|
|
389
|
+
parts.push(`Task: ${t.snapshotName}`);
|
|
390
|
+
return parts.join(" · ");
|
|
391
|
+
})(), actions: _jsxs(_Fragment, { children: [_jsxs("button", { type: "button", onClick: () => void load(), disabled: loading, className: "btn-ghost flex items-center gap-1.5 px-2 py-1 text-[11px] text-gray-400", children: [_jsx(RefreshCw, { size: 12, className: loading ? "animate-spin" : "" }), "Refresh"] }), _jsxs("select", { value: basedOnSnapshot, onChange: (e) => setBasedOnSnapshot(e.target.value), disabled: building, className: "rounded border border-gray-700 bg-gray-900 px-2 py-1 text-[11px] text-gray-200 disabled:cursor-not-allowed disabled:opacity-50", title: "Optional: layer this build on top of an existing snapshot. Leave as 'fresh image' to use the Sandboxfile's image: line.", children: [_jsx("option", { value: "", children: "based on: fresh image" }), (data?.builds ?? []).map((b) => (_jsxs("option", { value: b.snapshotName, children: ["based on: ", b.buildId] }, b.snapshotName)))] }), _jsxs("button", { type: "button", onClick: () => void build(), disabled: building, className: "flex items-center gap-1.5 rounded-md bg-emerald-600 px-3 py-1.5 text-[11px] font-medium text-white hover:bg-emerald-500 disabled:cursor-not-allowed disabled:bg-gray-800 disabled:text-gray-500", title: basedOnSnapshot
|
|
392
|
+
? `Build on top of ${basedOnSnapshot}`
|
|
393
|
+
: "Run apt/pip/npm/exec from your saved Sandboxfile and capture a snapshot", children: [building ? (_jsx(Loader2, { size: 12, className: "animate-spin" })) : (_jsx(Hammer, { size: 12 })), "Build"] })] }) }), error && _jsx(Banner, { kind: "error", text: error }), building && buildLog.length === 0 && (_jsx(Banner, { kind: "info", text: "Building… this typically takes 10-30s for a slim base image plus a few apt/pip layers. " +
|
|
394
|
+
(elapsedMs > 0
|
|
395
|
+
? `(${(elapsedMs / 1000).toFixed(0)}s elapsed)`
|
|
396
|
+
: "") })), (building || buildLog.length > 0) && (_jsxs("div", { className: "mb-3 overflow-hidden rounded-md border border-gray-800 bg-gray-950", children: [_jsx("div", { className: "flex items-center justify-between border-b border-gray-800 px-3 py-1.5", children: _jsxs("div", { className: "flex items-center gap-2 text-[11px] text-gray-300", children: [building ? (_jsx(Loader2, { size: 11, className: "animate-spin text-emerald-400" })) : (_jsx(CheckCircle2, { size: 11, className: "text-emerald-400" })), _jsx("span", { children: building ? "Build in progress" : "Last build log" }), building && elapsedMs > 0 && (_jsxs("span", { className: "text-[10px] text-gray-500", children: [(elapsedMs / 1000).toFixed(0), "s"] })), _jsxs("span", { className: "text-[10px] text-gray-600", children: [buildLog.length, " line", buildLog.length === 1 ? "" : "s"] })] }) }), _jsx("pre", { ref: logRef, className: "max-h-72 overflow-auto whitespace-pre-wrap px-3 py-2 font-mono text-[11px] leading-relaxed text-gray-300", children: buildLog.length > 0
|
|
397
|
+
? buildLog.join("\n")
|
|
398
|
+
: "… waiting for first log line …" })] })), data && data.builds.length === 0 && !building && (_jsxs("p", { className: "rounded-md border border-dashed border-gray-800 px-3 py-6 text-center text-[12px] text-gray-500", children: ["No builds yet. Click ", _jsx("strong", { children: "Build" }), " to create one from your saved Sandboxfile."] })), data && data.builds.length > 0 && (_jsx("ul", { className: "space-y-2", children: data.builds.map((b) => (_jsxs("li", { className: "rounded-md border border-gray-800 bg-gray-900/50 px-3 py-2", children: [_jsxs("div", { className: "flex items-start justify-between gap-3", children: [_jsxs("div", { className: "min-w-0 flex-1", children: [_jsxs("div", { className: "flex flex-wrap items-center gap-2", children: [_jsx("code", { className: "rounded bg-gray-800 px-1.5 py-0.5 text-[11px] text-gray-100", children: b.buildId }), (b.roles?.browser ?? b.published) && (_jsxs("span", { className: "flex items-center gap-1 rounded bg-emerald-900/40 px-1.5 py-0.5 text-[10px] uppercase text-emerald-300", children: [_jsx(CheckCircle2, { size: 10 }), " Browser"] })), b.roles?.task && (_jsxs("span", { className: "flex items-center gap-1 rounded bg-sky-900/40 px-1.5 py-0.5 text-[10px] uppercase text-sky-300", children: [_jsx(CheckCircle2, { size: 10 }), " Task"] })), _jsx("span", { className: "text-[11px] text-gray-400", title: b.basedOnSnapshot ? `layered on snapshot ${b.basedOnSnapshot}` : `image: ${b.baseImage}`, children: b.basedOnSnapshot ? `↳ ${b.basedOnSnapshot.split('-build-').pop() ?? b.basedOnSnapshot}` : b.baseImage }), _jsxs("span", { className: "text-[10px] text-gray-600", children: [(b.durationMs / 1000).toFixed(1), "s \u00B7 ", formatRelative(b.builtAt)] })] }), _jsxs("p", { className: "mt-1 truncate text-[11px] text-gray-500", children: ["snapshot:", " ", _jsx("code", { className: "rounded bg-gray-800 px-1 text-gray-400", children: b.snapshotName })] })] }), (() => {
|
|
399
|
+
// Defensive read: an older server (pre-roles) only
|
|
400
|
+
// sends `b.published` for the browser role and no
|
|
401
|
+
// task field at all. Fall back so the UI keeps
|
|
402
|
+
// rendering during a partial deploy.
|
|
403
|
+
const browserActive = b.roles?.browser ?? b.published;
|
|
404
|
+
const taskActive = b.roles?.task ?? false;
|
|
405
|
+
return (_jsxs("div", { className: "flex flex-shrink-0 flex-col items-stretch gap-1", children: [_jsxs("div", { className: "flex items-stretch gap-px overflow-hidden rounded-md border border-gray-800", children: [_jsxs("button", { type: "button", onClick: () => void useBuild(b.buildId, "browser", false), disabled: usingId === b.buildId || browserActive, className: "flex items-center gap-1 px-2 py-1 text-[11px] text-emerald-200 hover:bg-emerald-900/30 disabled:cursor-not-allowed disabled:opacity-40", title: browserActive
|
|
406
|
+
? "This build is already the active Browser snapshot."
|
|
407
|
+
: "Pin this build as the long-lived Browser sandbox snapshot. The live VM keeps running its current snapshot until you reset.", children: [usingId === b.buildId ? (_jsx(Loader2, { size: 11, className: "animate-spin" })) : (_jsx(UploadCloud, { size: 11 })), browserActive ? "Browser \u2713" : "Use as Browser"] }), !browserActive && (_jsxs("button", { type: "button", onClick: () => void useBuild(b.buildId, "browser", true), disabled: usingId === b.buildId, className: "flex items-center gap-1 border-l border-gray-800 px-2 py-1 text-[11px] text-emerald-300 hover:bg-emerald-900/30 disabled:cursor-not-allowed disabled:opacity-40", title: "Pin as Browser + reset the live VM so the new snapshot takes effect immediately. Adds ~10-20s for the reset.", children: [_jsx(RotateCcw, { size: 11 }), "& Reset"] }))] }), _jsxs("button", { type: "button", onClick: () => void useBuild(b.buildId, "task", false), disabled: usingId === b.buildId || taskActive, className: "flex items-center justify-center gap-1 rounded-md border border-gray-800 px-2 py-1 text-[11px] text-sky-200 hover:bg-sky-900/30 disabled:cursor-not-allowed disabled:opacity-40", title: taskActive
|
|
408
|
+
? "This build is already the active Task snapshot."
|
|
409
|
+
: "Pin this build as the per-task sandbox snapshot. Future per-task sandboxes will boot from it; takes effect on the next task acquire.", children: [usingId === b.buildId ? (_jsx(Loader2, { size: 11, className: "animate-spin" })) : (_jsx(UploadCloud, { size: 11 })), taskActive ? "Task \u2713" : "Use as Task"] })] }));
|
|
410
|
+
})()] }), b.logTail && (_jsxs("details", { className: "mt-1.5 text-[11px]", children: [_jsx("summary", { className: "cursor-pointer text-gray-500 hover:text-gray-400", children: "Log tail" }), _jsx("pre", { className: "mt-1 max-h-40 overflow-auto whitespace-pre-wrap rounded bg-gray-950 px-2 py-1 text-[11px] leading-relaxed text-gray-400", children: b.logTail })] }))] }, b.buildId))) }))] }));
|
|
411
|
+
}
|
|
412
|
+
function ShellSection() {
|
|
413
|
+
const [command, setCommand] = useState("");
|
|
414
|
+
const [workdir, setWorkdir] = useState("/workspace");
|
|
415
|
+
const [target, setTarget] = useState("live");
|
|
416
|
+
const [history, setHistory] = useState([]);
|
|
417
|
+
const [running, setRunning] = useState(false);
|
|
418
|
+
const [historyIdx, setHistoryIdx] = useState(null);
|
|
419
|
+
const [builds, setBuilds] = useState([]);
|
|
420
|
+
const inputRef = useRef(null);
|
|
421
|
+
const idCounter = useRef(0);
|
|
422
|
+
/** AbortController for the in-flight /exec request; lets the user
|
|
423
|
+
* bail out of a hanging command without waiting for the server
|
|
424
|
+
* timeout. */
|
|
425
|
+
const abortRef = useRef(null);
|
|
426
|
+
const recentCommands = history.map((h) => h.command);
|
|
427
|
+
// Pull the build list (newest first) so the user can pick a target.
|
|
428
|
+
// We re-fetch on focus to pick up freshly-built snapshots without
|
|
429
|
+
// a full page reload.
|
|
430
|
+
const loadBuilds = useCallback(async () => {
|
|
431
|
+
try {
|
|
432
|
+
const r = await fetchJson(`${ROUTE_BASE}/builds`);
|
|
433
|
+
setBuilds(r.builds);
|
|
434
|
+
}
|
|
435
|
+
catch {
|
|
436
|
+
/* non-fatal: just leave the dropdown without build entries */
|
|
437
|
+
}
|
|
438
|
+
}, []);
|
|
439
|
+
useEffect(() => {
|
|
440
|
+
void loadBuilds();
|
|
441
|
+
}, [loadBuilds]);
|
|
442
|
+
async function run() {
|
|
443
|
+
const cmd = command.trim();
|
|
444
|
+
if (!cmd || running)
|
|
445
|
+
return;
|
|
446
|
+
const id = ++idCounter.current;
|
|
447
|
+
const wd = workdir.trim() || "/workspace";
|
|
448
|
+
const targetSnapshot = target;
|
|
449
|
+
const entry = {
|
|
450
|
+
id,
|
|
451
|
+
command: cmd,
|
|
452
|
+
workdir: wd,
|
|
453
|
+
target: targetSnapshot,
|
|
454
|
+
startedAt: Date.now(),
|
|
455
|
+
result: null,
|
|
456
|
+
transportError: null,
|
|
457
|
+
};
|
|
458
|
+
setHistory((h) => [...h, entry]);
|
|
459
|
+
setCommand("");
|
|
460
|
+
setHistoryIdx(null);
|
|
461
|
+
setRunning(true);
|
|
462
|
+
const ac = new AbortController();
|
|
463
|
+
abortRef.current = ac;
|
|
464
|
+
try {
|
|
465
|
+
const payload = { command: cmd, workdir: wd };
|
|
466
|
+
if (targetSnapshot !== "live") {
|
|
467
|
+
payload.build_id = targetSnapshot;
|
|
468
|
+
}
|
|
469
|
+
const r = await fetchJson(`${ROUTE_BASE}/exec`, {
|
|
470
|
+
method: "POST",
|
|
471
|
+
headers: { "Content-Type": "application/json" },
|
|
472
|
+
body: JSON.stringify(payload),
|
|
473
|
+
signal: ac.signal,
|
|
474
|
+
});
|
|
475
|
+
setHistory((h) => h.map((e) => (e.id === id ? { ...e, result: r } : e)));
|
|
476
|
+
}
|
|
477
|
+
catch (err) {
|
|
478
|
+
const aborted = err instanceof DOMException && err.name === "AbortError";
|
|
479
|
+
const message = aborted
|
|
480
|
+
? "Cancelled by user. The server-side timeout (60s default) will eventually tear the preview VM down."
|
|
481
|
+
: err instanceof Error
|
|
482
|
+
? err.message
|
|
483
|
+
: String(err);
|
|
484
|
+
setHistory((h) => h.map((e) => e.id === id ? { ...e, transportError: message } : e));
|
|
485
|
+
}
|
|
486
|
+
finally {
|
|
487
|
+
setRunning(false);
|
|
488
|
+
abortRef.current = null;
|
|
489
|
+
// Refocus so the user can type the next command without
|
|
490
|
+
// chasing the cursor.
|
|
491
|
+
requestAnimationFrame(() => inputRef.current?.focus());
|
|
492
|
+
}
|
|
493
|
+
}
|
|
494
|
+
function cancel() {
|
|
495
|
+
if (abortRef.current) {
|
|
496
|
+
abortRef.current.abort();
|
|
497
|
+
abortRef.current = null;
|
|
498
|
+
}
|
|
499
|
+
}
|
|
500
|
+
function clear() {
|
|
501
|
+
setHistory([]);
|
|
502
|
+
idCounter.current = 0;
|
|
503
|
+
}
|
|
504
|
+
function recall(direction) {
|
|
505
|
+
if (recentCommands.length === 0)
|
|
506
|
+
return;
|
|
507
|
+
let next;
|
|
508
|
+
if (direction === -1) {
|
|
509
|
+
// ↑ — walk backwards through history.
|
|
510
|
+
if (historyIdx === null) {
|
|
511
|
+
next = recentCommands.length - 1;
|
|
512
|
+
}
|
|
513
|
+
else if (historyIdx === 0) {
|
|
514
|
+
return;
|
|
515
|
+
}
|
|
516
|
+
else {
|
|
517
|
+
next = historyIdx - 1;
|
|
518
|
+
}
|
|
519
|
+
}
|
|
520
|
+
else {
|
|
521
|
+
// ↓ — walk forward, exit history at the bottom.
|
|
522
|
+
if (historyIdx === null)
|
|
523
|
+
return;
|
|
524
|
+
if (historyIdx >= recentCommands.length - 1) {
|
|
525
|
+
setHistoryIdx(null);
|
|
526
|
+
setCommand("");
|
|
527
|
+
return;
|
|
528
|
+
}
|
|
529
|
+
next = historyIdx + 1;
|
|
530
|
+
}
|
|
531
|
+
setHistoryIdx(next);
|
|
532
|
+
setCommand(recentCommands[next] ?? "");
|
|
533
|
+
}
|
|
534
|
+
function onKeyDown(e) {
|
|
535
|
+
if (e.key === "Enter" && !e.shiftKey) {
|
|
536
|
+
e.preventDefault();
|
|
537
|
+
void run();
|
|
538
|
+
return;
|
|
539
|
+
}
|
|
540
|
+
// Recall when the textarea is single-line; multi-line composition
|
|
541
|
+
// (Shift+Enter) keeps native arrow-key navigation.
|
|
542
|
+
const isSingleLine = !command.includes("\n");
|
|
543
|
+
if (e.key === "ArrowUp" && isSingleLine) {
|
|
544
|
+
e.preventDefault();
|
|
545
|
+
recall(-1);
|
|
546
|
+
}
|
|
547
|
+
else if (e.key === "ArrowDown" && isSingleLine) {
|
|
548
|
+
e.preventDefault();
|
|
549
|
+
recall(1);
|
|
550
|
+
}
|
|
551
|
+
}
|
|
552
|
+
const targetLabel = target === "live"
|
|
553
|
+
? "Live sandbox"
|
|
554
|
+
: `Preview build ${target}`;
|
|
555
|
+
return (_jsxs("section", { children: [_jsx(SectionHeader, { title: "Shell", description: target === "live"
|
|
556
|
+
? "Run a one-shot command inside the running sandbox. Defaults to bash semantics; equivalent to the agent's exec tool."
|
|
557
|
+
: "Boot a throwaway VM from the selected build's snapshot, run the command, then tear it down. Lets you sanity-check a build before switching the tenant to it. The live sandbox is not touched.", actions: _jsxs(_Fragment, { children: [_jsxs("button", { type: "button", onClick: () => void loadBuilds(), className: "btn-ghost flex items-center gap-1.5 px-2 py-1 text-[11px] text-gray-400", title: "Refresh build list", children: [_jsx(RefreshCw, { size: 11 }), "Reload builds"] }), _jsxs("button", { type: "button", onClick: clear, disabled: history.length === 0, className: "btn-ghost flex items-center gap-1.5 px-2 py-1 text-[11px] text-gray-400 disabled:opacity-50", title: "Clear command history (does not affect the sandbox)", children: [_jsx(Trash2, { size: 12 }), "Clear"] })] }) }), history.length === 0 && (_jsxs("p", { className: "mb-2 rounded-md border border-dashed border-gray-800 px-3 py-3 text-center text-[11px] text-gray-500", children: ["Try", " ", _jsx("code", { className: "rounded bg-gray-800 px-1 text-gray-300", children: "ls /workspace" }), " · ", _jsx("code", { className: "rounded bg-gray-800 px-1 text-gray-300", children: "python3 --version" }), " · ", _jsx("code", { className: "rounded bg-gray-800 px-1 text-gray-300", children: "which libreoffice" }), "."] })), _jsx("div", { className: "mb-2 max-h-[420px] space-y-2 overflow-y-auto", children: history.map((e) => (_jsx(ShellEntryView, { entry: e }, e.id))) }), _jsxs("div", { className: "rounded-md border border-gray-800 bg-gray-950 p-2", children: [_jsxs("div", { className: "mb-1.5 flex flex-wrap items-center gap-2 text-[10px] text-gray-500", children: [_jsx("span", { children: "target:" }), _jsxs("select", { value: target, onChange: (e) => setTarget(e.target.value), className: `rounded border px-2 py-0.5 font-mono text-[11px] text-gray-200 outline-none focus:border-blue-700 ${target === "live"
|
|
558
|
+
? "border-emerald-700/40 bg-gray-900"
|
|
559
|
+
: "border-amber-700/40 bg-amber-950/30"}`, title: "Run against the live sandbox or boot a throwaway preview VM from a build", children: [_jsx("option", { value: "live", children: "Live sandbox" }), builds.length > 0 && (_jsx("optgroup", { label: "Preview build\u2026", children: builds.map((b) => (_jsxs("option", { value: b.buildId, children: [b.buildId, " \u00B7 ", b.baseImage, b.published ? " (in use)" : ""] }, b.buildId))) }))] }), _jsx("span", { className: "text-gray-600", children: "\u00B7" }), _jsx("span", { children: "workdir:" }), _jsx("input", { type: "text", value: workdir, onChange: (e) => setWorkdir(e.target.value), spellCheck: false, className: "flex-1 rounded border border-gray-800 bg-gray-900 px-2 py-0.5 font-mono text-[11px] text-gray-200 outline-none focus:border-blue-700" })] }), _jsxs("div", { className: "flex items-end gap-2", children: [_jsx("textarea", { ref: inputRef, value: command, onChange: (e) => {
|
|
560
|
+
setCommand(e.target.value);
|
|
561
|
+
setHistoryIdx(null);
|
|
562
|
+
}, onKeyDown: onKeyDown, disabled: running, spellCheck: false, placeholder: "echo hello", rows: 2, className: "flex-1 resize-y rounded border border-gray-800 bg-gray-900 px-2 py-1 font-mono text-[12px] leading-relaxed text-gray-100 outline-none placeholder:text-gray-600 focus:border-blue-700 disabled:opacity-60" }), running ? (_jsxs("button", { type: "button", onClick: cancel, className: "flex items-center gap-1.5 rounded-md bg-rose-600 px-3 py-1.5 text-[11px] font-medium text-white hover:bg-rose-500", title: "Abort the in-flight request. The preview VM is also torn down server-side after a server-enforced timeout (60s default).", children: [_jsx(X, { size: 12 }), "Cancel"] })) : (_jsxs("button", { type: "button", onClick: () => void run(), disabled: command.trim().length === 0, className: "flex items-center gap-1.5 rounded-md bg-emerald-600 px-3 py-1.5 text-[11px] font-medium text-white hover:bg-emerald-500 disabled:cursor-not-allowed disabled:bg-gray-800 disabled:text-gray-500", children: [_jsx(Terminal, { size: 12 }), "Run"] }))] }), _jsxs("p", { className: "mt-1 text-[10px] text-gray-600", children: ["Target: ", _jsx("strong", { className: "text-gray-400", children: targetLabel }), " · ", "Enter to run \u00B7 Shift+Enter for a newline \u00B7 \u2191/\u2193 to walk history. Per-call timeout 60s (max 5 min). Preview boots add ~5-10s on top of the command time."] })] })] }));
|
|
563
|
+
}
|
|
564
|
+
function ShellEntryView({ entry }) {
|
|
565
|
+
const { result, transportError } = entry;
|
|
566
|
+
const running = result === null && transportError === null;
|
|
567
|
+
const ok = result?.ok === true;
|
|
568
|
+
const failed = (result && !result.ok) || transportError != null;
|
|
569
|
+
return (_jsxs("div", { className: "rounded-md border border-gray-800 bg-gray-900/50 px-3 py-2 font-mono text-[11px] leading-relaxed", children: [_jsxs("div", { className: "mb-1 flex items-center gap-2", children: [running ? (_jsx(Loader2, { size: 11, className: "animate-spin text-gray-400" })) : ok ? (_jsx(CheckCircle2, { size: 11, className: "text-emerald-400" })) : (_jsx(AlertTriangle, { size: 11, className: "text-rose-400" })), _jsx("code", { className: "flex-1 break-all text-gray-200", children: entry.command }), _jsx("span", { className: `rounded px-1 py-0.5 text-[9px] uppercase tracking-wide ${entry.target === "live"
|
|
570
|
+
? "bg-emerald-900/40 text-emerald-300"
|
|
571
|
+
: "bg-amber-900/40 text-amber-300"}`, title: entry.target === "live"
|
|
572
|
+
? "Ran against the tenant's live sandbox"
|
|
573
|
+
: `Ran against build ${entry.target}'s snapshot in a throwaway preview VM`, children: entry.target === "live" ? "live" : `preview ${entry.target}` }), _jsxs("span", { className: "text-[9px] text-gray-600", children: ["cwd:", entry.workdir] }), result && (_jsxs("span", { className: ok
|
|
574
|
+
? "rounded bg-emerald-900/40 px-1.5 py-0.5 text-[9px] text-emerald-300"
|
|
575
|
+
: "rounded bg-rose-900/40 px-1.5 py-0.5 text-[9px] text-rose-300", children: ["exit ", result.exitCode, result.timedOut && " · timed out", " · ", (result.durationMs / 1000).toFixed(2), "s"] }))] }), transportError && (_jsx("pre", { className: "max-h-40 overflow-auto whitespace-pre-wrap rounded bg-rose-950/40 px-2 py-1 text-[11px] text-rose-200", children: transportError })), result && (result.stdout || result.stderr) && (_jsxs("div", { className: "space-y-1", children: [result.stdout && (_jsx("pre", { className: "max-h-72 overflow-auto whitespace-pre-wrap rounded bg-gray-950 px-2 py-1 text-[11px] text-gray-200", children: result.stdout })), result.stderr && (_jsx("pre", { className: "max-h-72 overflow-auto whitespace-pre-wrap rounded bg-amber-950/30 px-2 py-1 text-[11px] text-amber-200", children: result.stderr }))] })), result && !result.stdout && !result.stderr && !failed && (_jsx("p", { className: "text-[10px] italic text-gray-500", children: "(no output)" }))] }));
|
|
576
|
+
}
|
|
577
|
+
function ResetSection({ refreshTick, onMutate, }) {
|
|
578
|
+
const [resetting, setResetting] = useState(false);
|
|
579
|
+
const [status, setStatus] = useState(null);
|
|
580
|
+
const [error, setError] = useState(null);
|
|
581
|
+
const [configOpen, setConfigOpen] = useState(false);
|
|
582
|
+
const loadStatus = useCallback(async () => {
|
|
583
|
+
try {
|
|
584
|
+
const r = await fetchJson(`${ROUTE_BASE}/status`);
|
|
585
|
+
setStatus(r);
|
|
586
|
+
}
|
|
587
|
+
catch (err) {
|
|
588
|
+
setError(err instanceof Error ? err.message : String(err));
|
|
589
|
+
}
|
|
590
|
+
}, []);
|
|
591
|
+
useEffect(() => {
|
|
592
|
+
void loadStatus();
|
|
593
|
+
}, [loadStatus]);
|
|
594
|
+
// Re-fetch status whenever a sibling section signals the sandbox
|
|
595
|
+
// lifecycle changed (e.g. publish + reset, or a build was deleted).
|
|
596
|
+
// Skip on the initial render because loadStatus already ran above.
|
|
597
|
+
const firstTick = useRef(refreshTick);
|
|
598
|
+
useEffect(() => {
|
|
599
|
+
if (refreshTick === firstTick.current)
|
|
600
|
+
return;
|
|
601
|
+
void loadStatus();
|
|
602
|
+
}, [refreshTick, loadStatus]);
|
|
603
|
+
// Live ticker: poll status while the VM is in a transient state
|
|
604
|
+
// (starting / stopping). Stops once we see a steady state so we
|
|
605
|
+
// don't hammer the runner forever.
|
|
606
|
+
useEffect(() => {
|
|
607
|
+
if (!status)
|
|
608
|
+
return;
|
|
609
|
+
const transient = status.state === "starting" || status.state === "stopped";
|
|
610
|
+
if (!transient)
|
|
611
|
+
return;
|
|
612
|
+
const id = window.setInterval(() => void loadStatus(), 2000);
|
|
613
|
+
return () => window.clearInterval(id);
|
|
614
|
+
}, [status, loadStatus]);
|
|
615
|
+
async function reset() {
|
|
616
|
+
setResetting(true);
|
|
617
|
+
setError(null);
|
|
618
|
+
try {
|
|
619
|
+
const r = await fetchJson(`${ROUTE_BASE}/reset`, { method: "POST" });
|
|
620
|
+
setStatus(r.status);
|
|
621
|
+
// Reset returns immediately after the runner promises to
|
|
622
|
+
// restart, but the VM may still be transitioning through
|
|
623
|
+
// “starting”. The transient-state ticker above will follow it
|
|
624
|
+
// until it settles on “ready”.
|
|
625
|
+
onMutate();
|
|
626
|
+
}
|
|
627
|
+
catch (err) {
|
|
628
|
+
setError(err instanceof Error ? err.message : String(err));
|
|
629
|
+
}
|
|
630
|
+
finally {
|
|
631
|
+
setResetting(false);
|
|
632
|
+
}
|
|
633
|
+
}
|
|
634
|
+
return (_jsxs("section", { children: [_jsx(SectionHeader, { title: "Live sandbox", description: "Reset the running VM. After publishing a new build, reset to make it live.", actions: _jsxs(_Fragment, { children: [_jsxs("button", { type: "button", onClick: () => void loadStatus(), className: "btn-ghost flex items-center gap-1.5 px-2 py-1 text-[11px] text-gray-400", children: [_jsx(RefreshCw, { size: 12 }), "Refresh"] }), _jsxs("button", { type: "button", onClick: () => setConfigOpen(true), className: "btn-ghost flex items-center gap-1.5 px-2 py-1 text-[11px] text-gray-300", title: "Edit cpu / memory / timeout for both Browser and Task sandboxes", children: [_jsx(Settings, { size: 12 }), "Configure"] }), _jsxs("button", { type: "button", onClick: () => void reset(), disabled: resetting, className: "flex items-center gap-1.5 rounded-md border border-rose-700/60 bg-rose-950/40 px-3 py-1.5 text-[11px] font-medium text-rose-200 hover:bg-rose-900/40 disabled:cursor-not-allowed disabled:opacity-50", title: "Stop and rebuild the VM from the published snapshot (or default image)", children: [resetting ? (_jsx(Loader2, { size: 12, className: "animate-spin" })) : (_jsx(RotateCcw, { size: 12 })), "Reset sandbox"] })] }) }), error && _jsx(Banner, { kind: "error", text: error }), _jsx("div", { className: "rounded-md border border-gray-800 bg-gray-900/40", children: status && (_jsxs("dl", { className: "grid grid-cols-3 gap-x-4 gap-y-1.5 p-3 text-[11px]", children: [_jsx(Field, { label: "State", children: status.runner === "nullable" ? "not running" : status.state }), _jsx(Field, { label: "Runner", children: status.runner }), _jsx(Field, { label: "Uptime", children: formatUptime(status.uptimeMs) }), extractMetaString(status.meta, "sandboxName") && (_jsx(Field, { label: "Sandbox", children: _jsx("code", { className: "rounded bg-gray-800 px-1", children: extractMetaString(status.meta, "sandboxName") }) })), extractMetaString(status.meta, "activeSnapshot") ? (_jsx(Field, { label: "Booted from", children: _jsxs("code", { className: "rounded bg-emerald-900/40 px-1 text-emerald-200", children: ["snapshot \u00B7 ", extractMetaString(status.meta, "activeSnapshot")] }) })) : extractMetaString(status.meta, "image") ? (_jsx(Field, { label: "Booted from", children: _jsxs("code", { className: "rounded bg-gray-800 px-1", children: ["image \u00B7 ", extractMetaString(status.meta, "image")] }) })) : null, extractMetaString(status.meta, "image") &&
|
|
635
|
+
extractMetaString(status.meta, "activeSnapshot") && (_jsx(Field, { label: "Default image", children: _jsx("code", { className: "rounded bg-gray-800 px-1 text-gray-400", children: extractMetaString(status.meta, "image") }) })), status.liveMemory && (_jsx(Field, { label: "Memory", children: _jsxs("span", { title: `${formatKb(status.liveMemory.usedKb)} used · ${formatKb(status.liveMemory.availableKb)} available · ${formatKb(status.liveMemory.totalKb)} total`, children: [formatKb(status.liveMemory.usedKb), _jsxs("span", { className: "text-gray-500", children: [" / ", formatKb(status.liveMemory.totalKb), " (", " ", Math.round((status.liveMemory.usedKb / status.liveMemory.totalKb) * 100), "%)"] })] }) })), status.lastError && (_jsx(Field, { label: "Last error", children: _jsx("span", { className: "text-rose-300", children: status.lastError }) }))] })) }), _jsx(ConfigureSandboxDialog, { open: configOpen, onClose: () => setConfigOpen(false) })] }));
|
|
636
|
+
}
|
|
637
|
+
function TaskPoolSection({ refreshTick }) {
|
|
638
|
+
const [entries, setEntries] = useState(null);
|
|
639
|
+
const [loading, setLoading] = useState(true);
|
|
640
|
+
const [error, setError] = useState(null);
|
|
641
|
+
const [destroying, setDestroying] = useState(null);
|
|
642
|
+
const load = useCallback(async () => {
|
|
643
|
+
setLoading(true);
|
|
644
|
+
setError(null);
|
|
645
|
+
try {
|
|
646
|
+
const r = await fetchJson(`${ROUTE_BASE}/task-pool`);
|
|
647
|
+
setEntries(r.entries);
|
|
648
|
+
}
|
|
649
|
+
catch (err) {
|
|
650
|
+
setError(err instanceof Error ? err.message : String(err));
|
|
651
|
+
}
|
|
652
|
+
finally {
|
|
653
|
+
setLoading(false);
|
|
654
|
+
}
|
|
655
|
+
}, []);
|
|
656
|
+
useEffect(() => {
|
|
657
|
+
void load();
|
|
658
|
+
}, [load, refreshTick]);
|
|
659
|
+
// Cheap auto-refresh: poll every 5s while the page is open.
|
|
660
|
+
// Sandbox state changes off-channel (a worker pickup spawns a
|
|
661
|
+
// VM, a finally hook stops it) and there's no event we can
|
|
662
|
+
// subscribe to, so the polling loop keeps the panel honest.
|
|
663
|
+
useEffect(() => {
|
|
664
|
+
const t = window.setInterval(() => void load(), 5_000);
|
|
665
|
+
return () => window.clearInterval(t);
|
|
666
|
+
}, [load]);
|
|
667
|
+
async function destroy(name) {
|
|
668
|
+
setDestroying(name);
|
|
669
|
+
setError(null);
|
|
670
|
+
try {
|
|
671
|
+
const url = `${ROUTE_BASE}/task-pool/destroy?sandbox_name=${encodeURIComponent(name)}`;
|
|
672
|
+
await fetchJson(url, { method: "POST" });
|
|
673
|
+
await load();
|
|
674
|
+
}
|
|
675
|
+
catch (err) {
|
|
676
|
+
setError(err instanceof Error ? err.message : String(err));
|
|
677
|
+
}
|
|
678
|
+
finally {
|
|
679
|
+
setDestroying(null);
|
|
680
|
+
}
|
|
681
|
+
}
|
|
682
|
+
const running = entries?.filter((e) => e.poolState === "running").length ?? 0;
|
|
683
|
+
const total = entries?.length ?? 0;
|
|
684
|
+
return (_jsxs("section", { children: [_jsx(SectionHeader, { title: "Per-task sandbox pool", description: total === 0
|
|
685
|
+
? "No per-task sandboxes yet. The pool spawns one when a workboard task is picked up by a worker."
|
|
686
|
+
: `${total} sandbox${total === 1 ? "" : "es"} (${running} running)`, actions: _jsxs("button", { type: "button", onClick: () => void load(), disabled: loading, className: "btn-ghost flex items-center gap-1.5 px-2 py-1 text-[11px] text-gray-400", children: [_jsx(RefreshCw, { size: 12, className: loading ? "animate-spin" : "" }), "Refresh"] }) }), error && _jsx(Banner, { kind: "error", text: error }), entries !== null && entries.length > 0 && (_jsx("div", { className: "overflow-hidden rounded-md border border-gray-800", children: _jsxs("table", { className: "w-full text-[11px]", children: [_jsx("thead", { className: "bg-gray-900/60 text-[10px] uppercase tracking-wide text-gray-500", children: _jsxs("tr", { children: [_jsx("th", { className: "px-3 py-1.5 text-left", children: "State" }), _jsx("th", { className: "px-3 py-1.5 text-left", children: "Sandbox" }), _jsx("th", { className: "px-3 py-1.5 text-left", children: "Task" }), _jsx("th", { className: "px-3 py-1.5 text-left", children: "Created" }), _jsx("th", { className: "px-3 py-1.5 text-right", children: "Actions" })] }) }), _jsx("tbody", { className: "divide-y divide-gray-800", children: entries.map((e) => (_jsxs("tr", { className: "text-gray-300", children: [_jsx("td", { className: "px-3 py-1.5", children: _jsx(PoolStateChip, { state: e.poolState }) }), _jsx("td", { className: "px-3 py-1.5 font-mono text-[10px] text-gray-400", children: _jsx("code", { className: "cursor-pointer hover:text-gray-100", title: "Click to copy", onClick: () => {
|
|
687
|
+
void navigator.clipboard
|
|
688
|
+
?.writeText(e.sandboxName)
|
|
689
|
+
.catch(() => { });
|
|
690
|
+
}, children: e.sandboxName }) }), _jsxs("td", { className: "px-3 py-1.5 font-mono text-[10px] text-gray-500", children: [e.taskId.slice(0, 8), "\u2026"] }), _jsx("td", { className: "px-3 py-1.5 text-[10px] text-gray-500", children: e.createdAt
|
|
691
|
+
? formatRelative(e.createdAt)
|
|
692
|
+
: "—" }), _jsx("td", { className: "px-3 py-1.5 text-right", children: _jsxs("button", { type: "button", onClick: () => void destroy(e.sandboxName), disabled: destroying === e.sandboxName, className: "flex items-center gap-1 rounded border border-gray-800 px-2 py-0.5 text-[10px] text-rose-300 hover:bg-rose-950/40 disabled:cursor-not-allowed disabled:opacity-40", title: e.poolState === "running"
|
|
693
|
+
? "Stop and remove this sandbox (also kills the running task)"
|
|
694
|
+
: "Remove the sandbox image from disk", children: [destroying === e.sandboxName ? (_jsx(Loader2, { size: 10, className: "animate-spin" })) : (_jsx(Trash2, { size: 10 })), e.poolState === "orphan" ? "Forget" : "Destroy"] }) })] }, e.sandboxName))) })] }) }))] }));
|
|
695
|
+
}
|
|
696
|
+
function PoolStateChip({ state }) {
|
|
697
|
+
const className = state === "running"
|
|
698
|
+
? "bg-emerald-900/40 text-emerald-200 border-emerald-700/50"
|
|
699
|
+
: state === "starting"
|
|
700
|
+
? "bg-amber-900/40 text-amber-200 border-amber-700/50"
|
|
701
|
+
: state === "error"
|
|
702
|
+
? "bg-rose-900/40 text-rose-200 border-rose-700/50"
|
|
703
|
+
: state === "orphan"
|
|
704
|
+
? "bg-gray-900/40 text-gray-400 border-gray-700/50"
|
|
705
|
+
: "bg-gray-900/30 text-gray-300 border-gray-800";
|
|
706
|
+
return (_jsx("span", { className: `inline-flex items-center rounded border px-1.5 py-0.5 font-mono text-[10px] uppercase tracking-wide ${className}`, children: state }));
|
|
707
|
+
}
|
|
708
|
+
/**
|
|
709
|
+
* Modal wrapper around the auto-generated PluginConfigForm. The
|
|
710
|
+
* form surface is large (7 numeric fields after the role split),
|
|
711
|
+
* so we keep it out of the always-visible Live sandbox card and
|
|
712
|
+
* surface it on demand.
|
|
713
|
+
*/
|
|
714
|
+
function ConfigureSandboxDialog({ open, onClose, }) {
|
|
715
|
+
if (!open)
|
|
716
|
+
return null;
|
|
717
|
+
return (_jsx("div", { className: "fixed inset-0 z-40 flex items-center justify-center bg-black/60 p-6", onClick: onClose, children: _jsxs("div", { className: "flex max-h-[80vh] w-full max-w-lg flex-col overflow-hidden rounded-lg border border-gray-800 bg-gray-950 shadow-2xl", onClick: (e) => e.stopPropagation(), children: [_jsxs("div", { className: "flex shrink-0 items-center justify-between border-b border-gray-800 px-4 py-3", children: [_jsxs("div", { children: [_jsx("div", { className: "text-sm font-medium text-gray-100", children: "Sandbox runtime parameters" }), _jsx("div", { className: "mt-0.5 text-[11px] text-gray-500", children: "Browser sandbox changes take effect on the next Reset; Task sandbox changes take effect on the next task acquire." })] }), _jsx("button", { type: "button", onClick: onClose, className: "rounded p-1 text-gray-400 hover:bg-gray-800 hover:text-gray-100", "aria-label": "Close configure dialog", children: _jsx(X, { size: 14 }) })] }), _jsx("div", { className: "flex-1 overflow-y-auto px-4 pt-3 [&>div>div>div:last-child]:sticky [&>div>div>div:last-child]:bottom-0 [&>div>div>div:last-child]:bg-gray-950 [&>div>div>div:last-child]:pt-3 [&>div>div>div:last-child]:pb-3", children: _jsx(PluginConfigForm, { pluginId: "microsandbox" }) })] }) }));
|
|
718
|
+
}
|
|
719
|
+
// ─── shared layout helpers ─────────────────────────────────────
|
|
720
|
+
function Field({ label, children }) {
|
|
721
|
+
return (_jsxs(_Fragment, { children: [_jsx("dt", { className: "col-span-1 text-gray-500", children: label }), _jsx("dd", { className: "col-span-2 text-gray-300", children: children })] }));
|
|
722
|
+
}
|
|
723
|
+
function SectionHeader({ title, description, actions, }) {
|
|
724
|
+
return (_jsxs("div", { className: "mb-2 flex items-end justify-between gap-3", children: [_jsxs("div", { children: [_jsx("h2", { className: "text-sm font-semibold text-gray-100", children: title }), description && (_jsx("p", { className: "mt-0.5 text-[11px] text-gray-500", children: description }))] }), actions && _jsx("div", { className: "flex items-center gap-1.5", children: actions })] }));
|
|
725
|
+
}
|
|
726
|
+
function Banner({ kind, text, }) {
|
|
727
|
+
const cls = kind === "ok"
|
|
728
|
+
? "border-emerald-700/40 bg-emerald-950/40 text-emerald-300"
|
|
729
|
+
: kind === "warn"
|
|
730
|
+
? "border-amber-700/40 bg-amber-950/40 text-amber-200"
|
|
731
|
+
: kind === "error"
|
|
732
|
+
? "border-rose-700/50 bg-rose-950/40 text-rose-300"
|
|
733
|
+
: "border-blue-700/40 bg-blue-950/40 text-blue-200";
|
|
734
|
+
const Icon = kind === "ok"
|
|
735
|
+
? CheckCircle2
|
|
736
|
+
: kind === "info"
|
|
737
|
+
? Loader2
|
|
738
|
+
: AlertTriangle;
|
|
739
|
+
return (_jsxs("div", { className: `mb-2 flex items-start gap-2 rounded-md border px-3 py-2 text-[11px] ${cls}`, children: [_jsx(Icon, { size: 12, className: kind === "info" ? "mt-0.5 animate-spin" : "mt-0.5 flex-shrink-0" }), _jsx("span", { className: "break-words", children: text })] }));
|
|
740
|
+
}
|
|
741
|
+
// ─── right-panel: BrowserViewportPanel ───────────────────────
|
|
742
|
+
//
|
|
743
|
+
// Embeds the per-tenant noVNC viewport in the chat shell's right
|
|
744
|
+
// column so the user can watch what the agent's browser tools are
|
|
745
|
+
// doing without leaving the conversation. This is the only
|
|
746
|
+
// surface for the live browser view today — the prior
|
|
747
|
+
// /admin/microsandbox/browser admin page was redundant once the
|
|
748
|
+
// in-chat panel handled both viewing and the dynamic resize loop,
|
|
749
|
+
// so it was retired.
|
|
750
|
+
//
|
|
751
|
+
// Wiring: the BrowserSidecar reports the host port that supervisor's
|
|
752
|
+
// websockify is forwarded to. We poll /browser/status for it (same
|
|
753
|
+
// shape as the admin page uses) and slot it into an iframe pointing
|
|
754
|
+
// at noVNC's `vnc.html?autoconnect=true&resize=scale&reconnect=true`.
|
|
755
|
+
// When the browser stack isn't running yet, the panel shows an empty
|
|
756
|
+
// state with a deep link to the admin Browser page.
|
|
757
|
+
//
|
|
758
|
+
// `resize=scale` (not `remote`): the closed-source predecessor's
|
|
759
|
+
// BrowserPanel ran the same way and copying that decision pays off
|
|
760
|
+
// because it is the more forgiving combination. Logic, briefly:
|
|
761
|
+
//
|
|
762
|
+
// - We drive the *real* Xvfb framebuffer from the host with
|
|
763
|
+
// `xrandr --fb` to match the iframe's pixel size, so chromium
|
|
764
|
+
// gets a 1:1 viewport and page content reflows correctly.
|
|
765
|
+
// - noVNC's client-side `scale` then becomes a no-op in the
|
|
766
|
+
// happy path; when the framebuffer and iframe drift by a few
|
|
767
|
+
// pixels (during a drag, after a layout settle), scaling
|
|
768
|
+
// keeps the canvas stretched edge-to-edge with no black bars
|
|
769
|
+
// or right-side cropping. `resize=remote` would instead ask
|
|
770
|
+
// the noVNC server to RandR-resize, but our Xvfb only has the
|
|
771
|
+
// initial 2400x1800 framebuffer mode — the request would either
|
|
772
|
+
// no-op or fight the host-driven xrandr.
|
|
773
|
+
// - `reconnect=true` so the iframe auto-recovers when a sandbox
|
|
774
|
+
// reset / supervisord restart drops websockify.
|
|
775
|
+
// - We use the full `vnc.html` (not the lite variant) because
|
|
776
|
+
// it ships the toolbar / settings / clipboard helpers users
|
|
777
|
+
// occasionally need; toolbar collapses to a thin strip.
|
|
778
|
+
//
|
|
779
|
+
// Why three resize layers — see browser-routes.ts postBrowserResize.
|
|
780
|
+
// In short: xrandr keeps Xvfb sized to the iframe so chromium
|
|
781
|
+
// fills it; wmctrl re-fits the chrome window inside the new
|
|
782
|
+
// framebuffer; Playwright MCP's browser_resize tells chromium to
|
|
783
|
+
// re-layout the *page viewport* (which is what makes pages reflow
|
|
784
|
+
// to fit the new width — X11 alone won't do that).
|
|
785
|
+
function BrowserViewportPanel(_props) {
|
|
786
|
+
const [data, setData] = useState(null);
|
|
787
|
+
const [error, setError] = useState(null);
|
|
788
|
+
const containerRef = useRef(null);
|
|
789
|
+
const [dragging, setDragging] = useState(false);
|
|
790
|
+
const load = useCallback(async () => {
|
|
791
|
+
try {
|
|
792
|
+
const r = await fetchJson(`${ROUTE_BASE}/browser/status`);
|
|
793
|
+
setData(r);
|
|
794
|
+
setError(null);
|
|
795
|
+
}
|
|
796
|
+
catch (err) {
|
|
797
|
+
setError(err instanceof Error ? err.message : String(err));
|
|
798
|
+
}
|
|
799
|
+
}, []);
|
|
800
|
+
useEffect(() => {
|
|
801
|
+
void load();
|
|
802
|
+
}, [load]);
|
|
803
|
+
// Re-poll while the stack isn't ready so the iframe pops in the
|
|
804
|
+
// moment supervisord finishes booting. Stops polling once ready
|
|
805
|
+
// — the iframe handles its own connection lifecycle from there.
|
|
806
|
+
useEffect(() => {
|
|
807
|
+
if (data?.ready)
|
|
808
|
+
return;
|
|
809
|
+
const id = window.setInterval(() => void load(), 4000);
|
|
810
|
+
return () => window.clearInterval(id);
|
|
811
|
+
}, [data?.ready, load]);
|
|
812
|
+
// Drive the server-side three-layer resize from this panel's
|
|
813
|
+
// actual rendered size. We keep this self-contained instead of
|
|
814
|
+
// wiring through the chat shell because the panel is the only
|
|
815
|
+
// consumer that cares about pixel-perfect viewport sync, and the
|
|
816
|
+
// chat shell already throttles its own layout work elsewhere.
|
|
817
|
+
useDebouncedViewportSync({
|
|
818
|
+
container: containerRef,
|
|
819
|
+
enabled: !!(data?.ready && data.ports.vnc),
|
|
820
|
+
onDraggingChange: setDragging,
|
|
821
|
+
});
|
|
822
|
+
return (_jsxs("div", { className: "flex h-full flex-col", children: [_jsx("div", { className: "flex items-center justify-between border-b border-gray-800 px-4 py-2", children: _jsxs("div", { className: "flex items-center gap-2 text-sm font-medium text-gray-200", children: [_jsx(Globe, { size: 14, className: "text-brand-400" }), "Browser"] }) }), error && (_jsxs("div", { className: "m-3 flex items-start gap-1.5 rounded-md border border-rose-700/50 bg-rose-950/40 px-3 py-2 text-[11px] text-rose-300", children: [_jsx(AlertTriangle, { size: 12, className: "mt-px flex-shrink-0" }), _jsx("span", { className: "break-all", children: error })] })), _jsx("div", { ref: containerRef, className: "relative min-h-0 flex-1 bg-gray-950", children: data?.ready && data.ports.vnc ? (_jsx("iframe", { title: "Browser viewport", src: `http://localhost:${data.ports.vnc}/vnc.html?autoconnect=true&resize=scale&reconnect=true&reconnect_delay=1000`,
|
|
823
|
+
// Disable iframe pointer events while the user drags
|
|
824
|
+
// the chat-shell panel divider — otherwise noVNC swallows
|
|
825
|
+
// the cursor and the resize feels stuck.
|
|
826
|
+
style: { pointerEvents: dragging ? "none" : undefined }, className: "absolute inset-0 h-full w-full bg-gray-950" })) : (_jsx("div", { className: "flex h-full items-center justify-center px-6 text-center text-[12px] text-gray-500", children: data
|
|
827
|
+
? data.hint ?? "Browser stack not running."
|
|
828
|
+
: "Loading…" })) })] }));
|
|
829
|
+
}
|
|
830
|
+
/**
|
|
831
|
+
* Watches a container's box, debounces resize events, and POSTs the
|
|
832
|
+
* latest size to `/browser/resize` once the user stops dragging.
|
|
833
|
+
*
|
|
834
|
+
* Implementation notes copied from the closed-source tianshu
|
|
835
|
+
* BrowserPanel:
|
|
836
|
+
* - We listen to BOTH pointer and mouse events because the chat-shell
|
|
837
|
+
* panel divider uses mousedown/move/up while pinch-zoom uses
|
|
838
|
+
* pointer events.
|
|
839
|
+
* - While a button is down we record the latest size but never send
|
|
840
|
+
* it; on release we wait QUIET_MS for layout to settle, then send
|
|
841
|
+
* once. This avoids hammering the backend (xrandr + wmctrl +
|
|
842
|
+
* Playwright MCP ≈ 200ms each per call) during a continuous drag.
|
|
843
|
+
* - We cap DPR at 2 because retina + a wide panel can balloon to
|
|
844
|
+
* framebuffer sizes Xvfb's `-screen` ceiling will silently
|
|
845
|
+
* truncate.
|
|
846
|
+
*/
|
|
847
|
+
function useDebouncedViewportSync(opts) {
|
|
848
|
+
const { container, enabled, onDraggingChange } = opts;
|
|
849
|
+
useEffect(() => {
|
|
850
|
+
if (!enabled)
|
|
851
|
+
return;
|
|
852
|
+
const el = container.current;
|
|
853
|
+
if (!el)
|
|
854
|
+
return;
|
|
855
|
+
const QUIET_MS = 300;
|
|
856
|
+
const dpr = Math.min(window.devicePixelRatio || 1, 2);
|
|
857
|
+
let timer = null;
|
|
858
|
+
let dragging = false;
|
|
859
|
+
let pending = null;
|
|
860
|
+
let lastSent = { w: 0, h: 0 };
|
|
861
|
+
const post = (w, h) => {
|
|
862
|
+
void fetch(`${ROUTE_BASE}/browser/resize`, {
|
|
863
|
+
method: "POST",
|
|
864
|
+
credentials: "include",
|
|
865
|
+
headers: { "Content-Type": "application/json" },
|
|
866
|
+
body: JSON.stringify({ width: w, height: h }),
|
|
867
|
+
}).catch(() => {
|
|
868
|
+
// Best-effort — a resize that doesn't reach the server
|
|
869
|
+
// just means the viewport stays at its last value, which
|
|
870
|
+
// noVNC's client-side scaling renders fine.
|
|
871
|
+
});
|
|
872
|
+
};
|
|
873
|
+
const flush = () => {
|
|
874
|
+
if (!pending)
|
|
875
|
+
return;
|
|
876
|
+
const { w, h } = pending;
|
|
877
|
+
if (w < 320 || h < 240)
|
|
878
|
+
return; // panel hidden / collapsed
|
|
879
|
+
if (Math.abs(w - lastSent.w) < 8 &&
|
|
880
|
+
Math.abs(h - lastSent.h) < 8) {
|
|
881
|
+
return;
|
|
882
|
+
}
|
|
883
|
+
lastSent = { w, h };
|
|
884
|
+
pending = null;
|
|
885
|
+
post(w, h);
|
|
886
|
+
};
|
|
887
|
+
const scheduleFlush = () => {
|
|
888
|
+
if (timer)
|
|
889
|
+
clearTimeout(timer);
|
|
890
|
+
timer = setTimeout(() => {
|
|
891
|
+
timer = null;
|
|
892
|
+
if (dragging)
|
|
893
|
+
return; // still dragging — wait for release
|
|
894
|
+
flush();
|
|
895
|
+
}, QUIET_MS);
|
|
896
|
+
};
|
|
897
|
+
const onResize = (entries) => {
|
|
898
|
+
const entry = entries[0];
|
|
899
|
+
if (!entry)
|
|
900
|
+
return;
|
|
901
|
+
const w = Math.round(entry.contentRect.width * dpr);
|
|
902
|
+
const h = Math.round(entry.contentRect.height * dpr);
|
|
903
|
+
pending = { w, h };
|
|
904
|
+
scheduleFlush();
|
|
905
|
+
};
|
|
906
|
+
const ro = new ResizeObserver(onResize);
|
|
907
|
+
ro.observe(el);
|
|
908
|
+
const setDragging = (v) => {
|
|
909
|
+
dragging = v;
|
|
910
|
+
onDraggingChange(v);
|
|
911
|
+
if (!v)
|
|
912
|
+
scheduleFlush();
|
|
913
|
+
};
|
|
914
|
+
const onDown = () => setDragging(true);
|
|
915
|
+
const onUp = () => setDragging(false);
|
|
916
|
+
window.addEventListener("mousedown", onDown);
|
|
917
|
+
window.addEventListener("mouseup", onUp);
|
|
918
|
+
window.addEventListener("pointerdown", onDown);
|
|
919
|
+
window.addEventListener("pointerup", onUp);
|
|
920
|
+
window.addEventListener("pointercancel", onUp);
|
|
921
|
+
return () => {
|
|
922
|
+
ro.disconnect();
|
|
923
|
+
if (timer)
|
|
924
|
+
clearTimeout(timer);
|
|
925
|
+
window.removeEventListener("mousedown", onDown);
|
|
926
|
+
window.removeEventListener("mouseup", onUp);
|
|
927
|
+
window.removeEventListener("pointerdown", onDown);
|
|
928
|
+
window.removeEventListener("pointerup", onUp);
|
|
929
|
+
window.removeEventListener("pointercancel", onUp);
|
|
930
|
+
};
|
|
931
|
+
}, [container, enabled, onDraggingChange]);
|
|
932
|
+
}
|
|
933
|
+
const clientExports = {
|
|
934
|
+
components: {
|
|
935
|
+
BrowserViewportPanel: BrowserViewportPanel,
|
|
936
|
+
MicroSandboxAdminPage: MicroSandboxAdminPage,
|
|
937
|
+
},
|
|
938
|
+
};
|
|
939
|
+
export const components = clientExports.components;
|
|
940
|
+
export default clientExports;
|
|
941
|
+
//# sourceMappingURL=client.js.map
|