From 84815818f7fa20daf50ebce51378d9ccbcc06d05 Mon Sep 17 00:00:00 2001 From: Stefan Rinke Date: Sun, 15 Feb 2026 23:15:33 +0100 Subject: [PATCH] added admin interface --- Dockerfile | 3 + README.md | 30 + cmd/picoclaw/main.go | 3 + config/config.schema.json | 444 +++++++++ pkg/channels/webui.go | 63 +- ui/index.html | 2 +- ui/package-lock.json | 1985 +++++++++++++++++++------------------ ui/package.json | 25 +- ui/src/main.js | 169 ---- ui/src/main.ts | 679 +++++++++++++ ui/src/style.css | 119 +++ ui/src/vite-env.d.ts | 1 + ui/tsconfig.json | 19 + 13 files changed, 2373 insertions(+), 1169 deletions(-) create mode 100644 config/config.schema.json delete mode 100644 ui/src/main.js create mode 100644 ui/src/main.ts create mode 100644 ui/src/vite-env.d.ts create mode 100644 ui/tsconfig.json diff --git a/Dockerfile b/Dockerfile index 2c693cf4b..2776aa7ec 100644 --- a/Dockerfile +++ b/Dockerfile @@ -29,6 +29,9 @@ COPY --from=builder /src/build/picoclaw /usr/local/bin/picoclaw # Copy built Web UI assets COPY --from=builder /src/ui/dist /usr/local/share/picoclaw/ui/dist +# Copy config schema for /admin/schema +COPY --from=builder /src/config/config.schema.json /usr/local/share/picoclaw/config/config.schema.json + # Create picoclaw home directory RUN /usr/local/bin/picoclaw onboard diff --git a/README.md b/README.md index 3ea63d024..390d1a091 100644 --- a/README.md +++ b/README.md @@ -702,6 +702,8 @@ picoclaw agent -m "Hello"
Full config example +Schema: `config/config.schema.json` + ```json { "agents": { @@ -796,6 +798,32 @@ If you set `gateway.token`, open: The listen address is controlled by `gateway.bind` (`local`, `tailnet`, `all`). +### Admin Web UI (Config Editor) + +The gateway also serves an admin web UI at: + +`http://:18790/admin` + +It provides two editing modes: + +- **Form editor**: a generic UI generated from `config/config.schema.json` (served by the gateway). +- **Raw JSON editor**: edit the full config as JSON. + +**Authentication** + +The admin UI uses the same bearer token as the Admin API. +Set `gateway.admin_token` (or `PICOCLAW_GATEWAY_ADMIN_TOKEN`) and enter it in the UI. +Requests are sent with: + +`Authorization: Bearer ` + +If `gateway.admin_token` is empty, `/admin/*` will always return `401 Unauthorized`. + +**Writable config required** + +Saving changes writes to the normal config path (e.g. `~/.picoclaw/config.json`, or `/root/.picoclaw/config.json` in Docker). +If the config file is mounted read-only, saving will fail with **"config is not writable"**. + ### Admin API (Config Update + Graceful Restart) The gateway also exposes an **API-only** management interface for remote administration. @@ -803,6 +831,8 @@ The gateway also exposes an **API-only** management interface for remote adminis It supports: - **Replace config**: `PUT /admin/config` +- **Read config**: `GET /admin/config` +- **Read config schema**: `GET /admin/schema` - **Graceful drain + exit(0)** (so Docker/systemd can restart it): `POST /admin/drain-exit` **Authentication** diff --git a/cmd/picoclaw/main.go b/cmd/picoclaw/main.go index 8ae91ede0..82c406627 100644 --- a/cmd/picoclaw/main.go +++ b/cmd/picoclaw/main.go @@ -735,6 +735,9 @@ func gatewayCmd() { wc.SetConfigUpdate(func(raw []byte) error { return saveConfigRawAtomic(configPath, raw) }) + wc.SetConfigRead(func() ([]byte, error) { + return os.ReadFile(configPath) + }) wc.SetDrainExit(func(timeout time.Duration) error { shutdown(timeout) os.Exit(0) diff --git a/config/config.schema.json b/config/config.schema.json new file mode 100644 index 000000000..b57907ff6 --- /dev/null +++ b/config/config.schema.json @@ -0,0 +1,444 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://github.com/sipeed/picoclaw/blob/main/config/config.schema.json", + "title": "PicoClaw Config", + "type": "object", + "additionalProperties": false, + "required": [ + "agents", + "channels", + "providers", + "gateway", + "tools", + "heartbeat", + "devices" + ], + "properties": { + "agents": { "$ref": "#/$defs/AgentsConfig" }, + "channels": { "$ref": "#/$defs/ChannelsConfig" }, + "providers": { "$ref": "#/$defs/ProvidersConfig" }, + "gateway": { "$ref": "#/$defs/GatewayConfig" }, + "tools": { "$ref": "#/$defs/ToolsConfig" }, + "heartbeat": { "$ref": "#/$defs/HeartbeatConfig" }, + "devices": { "$ref": "#/$defs/DevicesConfig" } + }, + "$defs": { + "FlexibleStringSlice": { + "type": "array", + "items": { + "anyOf": [{ "type": "string" }, { "type": "number" }] + }, + "description": "List of allowed sender identifiers for a channel. Each entry may be a string or a numeric ID (some chat platforms use numeric IDs).", + "examples": [["alice", "bob", 123456789]], + "default": [] + }, + "AgentsConfig": { + "type": "object", + "additionalProperties": false, + "required": ["defaults"], + "properties": { + "defaults": { "$ref": "#/$defs/AgentDefaults" } + } + }, + "AgentDefaults": { + "type": "object", + "additionalProperties": false, + "required": [ + "workspace", + "restrict_to_workspace", + "provider", + "model", + "max_tokens", + "temperature", + "max_tool_iterations" + ], + "properties": { + "workspace": { "type": "string", "default": "~/.picoclaw/workspace" }, + "restrict_to_workspace": { "type": "boolean", "default": true }, + "provider": { + "type": "string", + "default": "", + "description": "Provider key to use by default for agent requests. Must match a key under the top-level 'providers' section. Empty means provider-specific default behavior.", + "enum": [ + "", + "openrouter", + "zhipu", + "anthropic", + "openai", + "gemini", + "groq", + "vllm", + "ollama", + "together", + "deepinfra", + "mistral", + "qwen", + "moonshot", + "shengsuanyun", + "deepseek", + "github_copilot" + ], + "examples": ["openrouter"] + }, + "model": { "type": "string", "default": "glm-4.7" }, + "max_tokens": { "type": "integer", "minimum": 1, "default": 8192 }, + "temperature": { "type": "number", "minimum": 0, "default": 0.7 }, + "max_tool_iterations": { + "type": "integer", + "minimum": 1, + "default": 20 + } + } + }, + "ChannelsConfig": { + "type": "object", + "additionalProperties": false, + "required": [ + "whatsapp", + "telegram", + "feishu", + "discord", + "maixcam", + "qq", + "dingtalk", + "slack", + "line", + "onebot", + "webui" + ], + "properties": { + "whatsapp": { "$ref": "#/$defs/WhatsAppConfig" }, + "telegram": { "$ref": "#/$defs/TelegramConfig" }, + "feishu": { "$ref": "#/$defs/FeishuConfig" }, + "discord": { "$ref": "#/$defs/DiscordConfig" }, + "maixcam": { "$ref": "#/$defs/MaixCamConfig" }, + "qq": { "$ref": "#/$defs/QQConfig" }, + "dingtalk": { "$ref": "#/$defs/DingTalkConfig" }, + "slack": { "$ref": "#/$defs/SlackConfig" }, + "line": { "$ref": "#/$defs/LINEConfig" }, + "onebot": { "$ref": "#/$defs/OneBotConfig" }, + "webui": { "$ref": "#/$defs/WebUIConfig" } + } + }, + "WhatsAppConfig": { + "type": "object", + "additionalProperties": false, + "required": ["enabled", "bridge_url", "allow_from"], + "properties": { + "enabled": { "type": "boolean", "default": false }, + "bridge_url": { "type": "string", "default": "ws://localhost:3001" }, + "allow_from": { "$ref": "#/$defs/FlexibleStringSlice" } + } + }, + "TelegramConfig": { + "type": "object", + "additionalProperties": false, + "required": ["enabled", "token", "proxy", "allow_from"], + "properties": { + "enabled": { "type": "boolean", "default": false }, + "token": { "type": "string", "default": "" }, + "proxy": { "type": "string", "default": "" }, + "allow_from": { "$ref": "#/$defs/FlexibleStringSlice" } + } + }, + "FeishuConfig": { + "type": "object", + "additionalProperties": false, + "required": [ + "enabled", + "app_id", + "app_secret", + "encrypt_key", + "verification_token", + "allow_from" + ], + "properties": { + "enabled": { "type": "boolean", "default": false }, + "app_id": { "type": "string", "default": "" }, + "app_secret": { "type": "string", "default": "" }, + "encrypt_key": { "type": "string", "default": "" }, + "verification_token": { "type": "string", "default": "" }, + "allow_from": { "$ref": "#/$defs/FlexibleStringSlice" } + } + }, + "DiscordConfig": { + "type": "object", + "additionalProperties": false, + "required": ["enabled", "token", "allow_from"], + "properties": { + "enabled": { "type": "boolean", "default": false }, + "token": { "type": "string", "default": "" }, + "allow_from": { "$ref": "#/$defs/FlexibleStringSlice" } + } + }, + "MaixCamConfig": { + "type": "object", + "additionalProperties": false, + "required": ["enabled", "host", "port", "allow_from"], + "properties": { + "enabled": { "type": "boolean", "default": false }, + "host": { "type": "string", "default": "0.0.0.0" }, + "port": { + "type": "integer", + "minimum": 1, + "maximum": 65535, + "default": 18790 + }, + "allow_from": { "$ref": "#/$defs/FlexibleStringSlice" } + } + }, + "QQConfig": { + "type": "object", + "additionalProperties": false, + "required": ["enabled", "app_id", "app_secret", "allow_from"], + "properties": { + "enabled": { "type": "boolean", "default": false }, + "app_id": { "type": "string", "default": "" }, + "app_secret": { "type": "string", "default": "" }, + "allow_from": { "$ref": "#/$defs/FlexibleStringSlice" } + } + }, + "DingTalkConfig": { + "type": "object", + "additionalProperties": false, + "required": ["enabled", "client_id", "client_secret", "allow_from"], + "properties": { + "enabled": { "type": "boolean", "default": false }, + "client_id": { "type": "string", "default": "" }, + "client_secret": { "type": "string", "default": "" }, + "allow_from": { "$ref": "#/$defs/FlexibleStringSlice" } + } + }, + "SlackConfig": { + "type": "object", + "additionalProperties": false, + "required": ["enabled", "bot_token", "app_token", "allow_from"], + "properties": { + "enabled": { "type": "boolean", "default": false }, + "bot_token": { "type": "string", "default": "" }, + "app_token": { "type": "string", "default": "" }, + "allow_from": { "$ref": "#/$defs/FlexibleStringSlice" } + } + }, + "LINEConfig": { + "type": "object", + "additionalProperties": false, + "required": [ + "enabled", + "channel_secret", + "channel_access_token", + "webhook_host", + "webhook_port", + "webhook_path", + "allow_from" + ], + "properties": { + "enabled": { "type": "boolean", "default": false }, + "channel_secret": { "type": "string", "default": "" }, + "channel_access_token": { "type": "string", "default": "" }, + "webhook_host": { "type": "string", "default": "0.0.0.0" }, + "webhook_port": { + "type": "integer", + "minimum": 1, + "maximum": 65535, + "default": 18791 + }, + "webhook_path": { "type": "string", "default": "/webhook/line" }, + "allow_from": { "$ref": "#/$defs/FlexibleStringSlice" } + } + }, + "OneBotConfig": { + "type": "object", + "additionalProperties": false, + "required": [ + "enabled", + "ws_url", + "access_token", + "reconnect_interval", + "group_trigger_prefix", + "allow_from" + ], + "properties": { + "enabled": { "type": "boolean", "default": false }, + "ws_url": { "type": "string", "default": "ws://127.0.0.1:3001" }, + "access_token": { "type": "string", "default": "" }, + "reconnect_interval": { "type": "integer", "minimum": 0, "default": 5 }, + "group_trigger_prefix": { + "type": "array", + "items": { "type": "string" }, + "default": [] + }, + "allow_from": { "$ref": "#/$defs/FlexibleStringSlice" } + } + }, + "WebUIConfig": { + "type": "object", + "additionalProperties": false, + "required": ["enabled"], + "properties": { + "enabled": { "type": "boolean", "default": true } + } + }, + "ProvidersConfig": { + "type": "object", + "additionalProperties": false, + "required": [ + "anthropic", + "openai", + "openrouter", + "groq", + "zhipu", + "vllm", + "gemini", + "nvidia", + "moonshot", + "shengsuanyun", + "deepseek", + "github_copilot" + ], + "properties": { + "anthropic": { "$ref": "#/$defs/ProviderConfig" }, + "openai": { "$ref": "#/$defs/ProviderConfig" }, + "openrouter": { "$ref": "#/$defs/ProviderConfig" }, + "groq": { "$ref": "#/$defs/ProviderConfig" }, + "zhipu": { "$ref": "#/$defs/ProviderConfig" }, + "vllm": { "$ref": "#/$defs/ProviderConfig" }, + "gemini": { "$ref": "#/$defs/ProviderConfig" }, + "nvidia": { "$ref": "#/$defs/ProviderConfig" }, + "moonshot": { "$ref": "#/$defs/ProviderConfig" }, + "shengsuanyun": { "$ref": "#/$defs/ProviderConfig" }, + "deepseek": { "$ref": "#/$defs/ProviderConfig" }, + "github_copilot": { "$ref": "#/$defs/ProviderConfig" } + } + }, + "ProviderConfig": { + "type": "object", + "additionalProperties": false, + "required": ["api_key", "api_base"], + "properties": { + "api_key": { + "type": "string", + "default": "", + "description": "Provider API key / token.", + "examples": ["sk-...", "Bearer ..."] + }, + "api_base": { + "type": "string", + "default": "", + "description": "Optional API base URL override (useful for self-hosted / proxy / compatible endpoints).", + "examples": ["https://api.openai.com/v1", "http://localhost:8000/v1"] + }, + "proxy": { + "type": "string", + "default": "", + "description": "Optional HTTP(S) proxy URL for provider requests.", + "examples": ["http://127.0.0.1:7890"] + }, + "auth_method": { + "type": "string", + "default": "", + "description": "Optional provider-specific auth method override (if supported by the provider integration)." + }, + "connect_mode": { + "type": "string", + "default": "", + "description": "Optional provider-specific connection mode (if supported by the provider integration)." + } + } + }, + "GatewayConfig": { + "type": "object", + "additionalProperties": false, + "required": ["host", "bind", "port", "token", "admin_token"], + "properties": { + "host": { + "type": "string", + "default": "0.0.0.0", + "description": "Gateway host used for display/logging. The actual listen address is controlled by gateway.bind.", + "examples": ["0.0.0.0", "127.0.0.1"] + }, + "bind": { + "type": "string", + "enum": ["local", "tailnet", "all"], + "default": "all", + "description": "Controls the IP address the gateway binds to. local=127.0.0.1, all=0.0.0.0, tailnet=your Tailscale IP.", + "examples": ["local", "tailnet", "all"] + }, + "port": { + "type": "integer", + "minimum": 1, + "maximum": 65535, + "default": 18790, + "description": "TCP port for the gateway HTTP server.", + "examples": [18790] + }, + "token": { + "type": "string", + "default": "", + "description": "Optional shared-secret token required for Web UI websocket connections. If set, the browser must connect with ?token=.", + "examples": ["change-me"] + }, + "admin_token": { + "type": "string", + "default": "", + "description": "Bearer token required for /admin/* management endpoints and the /admin web UI. If empty, /admin/* returns 401.", + "examples": ["admin-change-me"] + } + } + }, + "ToolsConfig": { + "type": "object", + "additionalProperties": false, + "required": ["web"], + "properties": { + "web": { "$ref": "#/$defs/WebToolsConfig" } + } + }, + "WebToolsConfig": { + "type": "object", + "additionalProperties": false, + "required": ["brave", "duckduckgo"], + "properties": { + "brave": { "$ref": "#/$defs/BraveConfig" }, + "duckduckgo": { "$ref": "#/$defs/DuckDuckGoConfig" } + } + }, + "BraveConfig": { + "type": "object", + "additionalProperties": false, + "required": ["enabled", "api_key", "max_results"], + "properties": { + "enabled": { "type": "boolean", "default": false }, + "api_key": { "type": "string", "default": "" }, + "max_results": { "type": "integer", "minimum": 1, "default": 5 } + } + }, + "DuckDuckGoConfig": { + "type": "object", + "additionalProperties": false, + "required": ["enabled", "max_results"], + "properties": { + "enabled": { "type": "boolean", "default": true }, + "max_results": { "type": "integer", "minimum": 1, "default": 5 } + } + }, + "HeartbeatConfig": { + "type": "object", + "additionalProperties": false, + "required": ["enabled", "interval"], + "properties": { + "enabled": { "type": "boolean", "default": true }, + "interval": { "type": "integer", "minimum": 1, "default": 30 } + } + }, + "DevicesConfig": { + "type": "object", + "additionalProperties": false, + "required": ["enabled", "monitor_usb"], + "properties": { + "enabled": { "type": "boolean", "default": false }, + "monitor_usb": { "type": "boolean", "default": true } + } + } + } +} diff --git a/pkg/channels/webui.go b/pkg/channels/webui.go index 2df57826e..8e2e28258 100644 --- a/pkg/channels/webui.go +++ b/pkg/channels/webui.go @@ -30,6 +30,7 @@ type WebUIChannel struct { acceptingWS atomic.Bool drainExitFn func(timeout time.Duration) error configUpdateFn func(raw []byte) error + configReadFn func() ([]byte, error) } type webUIClient struct { @@ -70,6 +71,10 @@ func (c *WebUIChannel) SetConfigUpdate(fn func(raw []byte) error) { c.configUpdateFn = fn } +func (c *WebUIChannel) SetConfigRead(fn func() ([]byte, error)) { + c.configReadFn = fn +} + func (c *WebUIChannel) Start(ctx context.Context) error { addr, err := c.cfg.ResolvedAddr() if err != nil { @@ -79,6 +84,7 @@ func (c *WebUIChannel) Start(ctx context.Context) error { mux := http.NewServeMux() mux.HandleFunc("/ws", c.handleWS) mux.HandleFunc("/admin/config", c.handleAdminConfig) + mux.HandleFunc("/admin/schema", c.handleAdminSchema) mux.HandleFunc("/admin/drain-exit", c.handleAdminDrainExit) mux.HandleFunc("/healthz", func(w http.ResponseWriter, r *http.Request) { w.WriteHeader(http.StatusOK) @@ -291,8 +297,8 @@ func (c *WebUIChannel) isAdminAuthorized(r *http.Request) bool { } func (c *WebUIChannel) handleAdminConfig(w http.ResponseWriter, r *http.Request) { - if r.Method != http.MethodPut { - w.Header().Set("Allow", http.MethodPut) + if r.Method != http.MethodGet && r.Method != http.MethodPut { + w.Header().Set("Allow", strings.Join([]string{http.MethodGet, http.MethodPut}, ", ")) http.Error(w, "Method not allowed", http.StatusMethodNotAllowed) return } @@ -300,6 +306,23 @@ func (c *WebUIChannel) handleAdminConfig(w http.ResponseWriter, r *http.Request) http.Error(w, "Unauthorized", http.StatusUnauthorized) return } + + if r.Method == http.MethodGet { + if c.configReadFn == nil { + http.Error(w, "Config read not available", http.StatusNotImplemented) + return + } + raw, err := c.configReadFn() + if err != nil { + http.Error(w, err.Error(), http.StatusInternalServerError) + return + } + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(http.StatusOK) + w.Write(raw) + return + } + if c.configUpdateFn == nil { http.Error(w, "Config update not available", http.StatusNotImplemented) return @@ -327,6 +350,28 @@ func (c *WebUIChannel) handleAdminConfig(w http.ResponseWriter, r *http.Request) w.Write([]byte("ok")) } +func (c *WebUIChannel) handleAdminSchema(w http.ResponseWriter, r *http.Request) { + if r.Method != http.MethodGet { + w.Header().Set("Allow", http.MethodGet) + http.Error(w, "Method not allowed", http.StatusMethodNotAllowed) + return + } + if !c.isAdminAuthorized(r) { + http.Error(w, "Unauthorized", http.StatusUnauthorized) + return + } + + path := c.findConfigSchemaPath() + raw, err := os.ReadFile(path) + if err != nil { + http.Error(w, "Schema not available", http.StatusNotFound) + return + } + w.Header().Set("Content-Type", "application/schema+json") + w.WriteHeader(http.StatusOK) + w.Write(raw) +} + type drainExitRequest struct { TimeoutSeconds int `json:"timeout_seconds"` } @@ -411,3 +456,17 @@ func (c *WebUIChannel) findUIRoot() string { } return "ui" } + +func (c *WebUIChannel) findConfigSchemaPath() string { + candidates := []string{ + filepath.Join(string(os.PathSeparator), "usr", "local", "share", "picoclaw", "config", "config.schema.json"), + filepath.Join(string(os.PathSeparator), "usr", "share", "picoclaw", "config", "config.schema.json"), + filepath.Join("config", "config.schema.json"), + } + for _, p := range candidates { + if st, err := os.Stat(p); err == nil && !st.IsDir() { + return p + } + } + return filepath.Join("config", "config.schema.json") +} diff --git a/ui/index.html b/ui/index.html index d90de7fbb..dd8259d2e 100644 --- a/ui/index.html +++ b/ui/index.html @@ -7,6 +7,6 @@
- + diff --git a/ui/package-lock.json b/ui/package-lock.json index 9a5555486..20330ef66 100644 --- a/ui/package-lock.json +++ b/ui/package-lock.json @@ -1,987 +1,1002 @@ { - "name": "picoclaw-ui", - "version": "0.0.0", - "lockfileVersion": 3, - "requires": true, - "packages": { - "": { - "name": "picoclaw-ui", - "version": "0.0.0", - "devDependencies": { - "vite": "^5.4.0" - } - }, - "node_modules/@esbuild/aix-ppc64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.21.5.tgz", - "integrity": "sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==", - "cpu": [ - "ppc64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "aix" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/android-arm": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.21.5.tgz", - "integrity": "sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/android-arm64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.21.5.tgz", - "integrity": "sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/android-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.21.5.tgz", - "integrity": "sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/darwin-arm64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.21.5.tgz", - "integrity": "sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/darwin-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.21.5.tgz", - "integrity": "sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/freebsd-arm64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.21.5.tgz", - "integrity": "sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/freebsd-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.21.5.tgz", - "integrity": "sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-arm": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.21.5.tgz", - "integrity": "sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-arm64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.21.5.tgz", - "integrity": "sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-ia32": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.21.5.tgz", - "integrity": "sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==", - "cpu": [ - "ia32" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-loong64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.21.5.tgz", - "integrity": "sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==", - "cpu": [ - "loong64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-mips64el": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.21.5.tgz", - "integrity": "sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==", - "cpu": [ - "mips64el" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-ppc64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.21.5.tgz", - "integrity": "sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w==", - "cpu": [ - "ppc64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-riscv64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.21.5.tgz", - "integrity": "sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==", - "cpu": [ - "riscv64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-s390x": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.21.5.tgz", - "integrity": "sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==", - "cpu": [ - "s390x" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.21.5.tgz", - "integrity": "sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/netbsd-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.21.5.tgz", - "integrity": "sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "netbsd" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/openbsd-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.21.5.tgz", - "integrity": "sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "openbsd" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/sunos-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.21.5.tgz", - "integrity": "sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "sunos" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/win32-arm64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.21.5.tgz", - "integrity": "sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/win32-ia32": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.21.5.tgz", - "integrity": "sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==", - "cpu": [ - "ia32" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/win32-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.21.5.tgz", - "integrity": "sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@rollup/rollup-android-arm-eabi": { - "version": "4.57.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.57.1.tgz", - "integrity": "sha512-A6ehUVSiSaaliTxai040ZpZ2zTevHYbvu/lDoeAteHI8QnaosIzm4qwtezfRg1jOYaUmnzLX1AOD6Z+UJjtifg==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ] - }, - "node_modules/@rollup/rollup-android-arm64": { - "version": "4.57.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.57.1.tgz", - "integrity": "sha512-dQaAddCY9YgkFHZcFNS/606Exo8vcLHwArFZ7vxXq4rigo2bb494/xKMMwRRQW6ug7Js6yXmBZhSBRuBvCCQ3w==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ] - }, - "node_modules/@rollup/rollup-darwin-arm64": { - "version": "4.57.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.57.1.tgz", - "integrity": "sha512-crNPrwJOrRxagUYeMn/DZwqN88SDmwaJ8Cvi/TN1HnWBU7GwknckyosC2gd0IqYRsHDEnXf328o9/HC6OkPgOg==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ] - }, - "node_modules/@rollup/rollup-darwin-x64": { - "version": "4.57.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.57.1.tgz", - "integrity": "sha512-Ji8g8ChVbKrhFtig5QBV7iMaJrGtpHelkB3lsaKzadFBe58gmjfGXAOfI5FV0lYMH8wiqsxKQ1C9B0YTRXVy4w==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ] - }, - "node_modules/@rollup/rollup-freebsd-arm64": { - "version": "4.57.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.57.1.tgz", - "integrity": "sha512-R+/WwhsjmwodAcz65guCGFRkMb4gKWTcIeLy60JJQbXrJ97BOXHxnkPFrP+YwFlaS0m+uWJTstrUA9o+UchFug==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ] - }, - "node_modules/@rollup/rollup-freebsd-x64": { - "version": "4.57.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.57.1.tgz", - "integrity": "sha512-IEQTCHeiTOnAUC3IDQdzRAGj3jOAYNr9kBguI7MQAAZK3caezRrg0GxAb6Hchg4lxdZEI5Oq3iov/w/hnFWY9Q==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ] - }, - "node_modules/@rollup/rollup-linux-arm-gnueabihf": { - "version": "4.57.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.57.1.tgz", - "integrity": "sha512-F8sWbhZ7tyuEfsmOxwc2giKDQzN3+kuBLPwwZGyVkLlKGdV1nvnNwYD0fKQ8+XS6hp9nY7B+ZeK01EBUE7aHaw==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-arm-musleabihf": { - "version": "4.57.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.57.1.tgz", - "integrity": "sha512-rGfNUfn0GIeXtBP1wL5MnzSj98+PZe/AXaGBCRmT0ts80lU5CATYGxXukeTX39XBKsxzFpEeK+Mrp9faXOlmrw==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-arm64-gnu": { - "version": "4.57.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.57.1.tgz", - "integrity": "sha512-MMtej3YHWeg/0klK2Qodf3yrNzz6CGjo2UntLvk2RSPlhzgLvYEB3frRvbEF2wRKh1Z2fDIg9KRPe1fawv7C+g==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-arm64-musl": { - "version": "4.57.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.57.1.tgz", - "integrity": "sha512-1a/qhaaOXhqXGpMFMET9VqwZakkljWHLmZOX48R0I/YLbhdxr1m4gtG1Hq7++VhVUmf+L3sTAf9op4JlhQ5u1Q==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-loong64-gnu": { - "version": "4.57.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.57.1.tgz", - "integrity": "sha512-QWO6RQTZ/cqYtJMtxhkRkidoNGXc7ERPbZN7dVW5SdURuLeVU7lwKMpo18XdcmpWYd0qsP1bwKPf7DNSUinhvA==", - "cpu": [ - "loong64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-loong64-musl": { - "version": "4.57.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-musl/-/rollup-linux-loong64-musl-4.57.1.tgz", - "integrity": "sha512-xpObYIf+8gprgWaPP32xiN5RVTi/s5FCR+XMXSKmhfoJjrpRAjCuuqQXyxUa/eJTdAE6eJ+KDKaoEqjZQxh3Gw==", - "cpu": [ - "loong64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-ppc64-gnu": { - "version": "4.57.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.57.1.tgz", - "integrity": "sha512-4BrCgrpZo4hvzMDKRqEaW1zeecScDCR+2nZ86ATLhAoJ5FQ+lbHVD3ttKe74/c7tNT9c6F2viwB3ufwp01Oh2w==", - "cpu": [ - "ppc64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-ppc64-musl": { - "version": "4.57.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-musl/-/rollup-linux-ppc64-musl-4.57.1.tgz", - "integrity": "sha512-NOlUuzesGauESAyEYFSe3QTUguL+lvrN1HtwEEsU2rOwdUDeTMJdO5dUYl/2hKf9jWydJrO9OL/XSSf65R5+Xw==", - "cpu": [ - "ppc64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-riscv64-gnu": { - "version": "4.57.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.57.1.tgz", - "integrity": "sha512-ptA88htVp0AwUUqhVghwDIKlvJMD/fmL/wrQj99PRHFRAG6Z5nbWoWG4o81Nt9FT+IuqUQi+L31ZKAFeJ5Is+A==", - "cpu": [ - "riscv64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-riscv64-musl": { - "version": "4.57.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.57.1.tgz", - "integrity": "sha512-S51t7aMMTNdmAMPpBg7OOsTdn4tySRQvklmL3RpDRyknk87+Sp3xaumlatU+ppQ+5raY7sSTcC2beGgvhENfuw==", - "cpu": [ - "riscv64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-s390x-gnu": { - "version": "4.57.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.57.1.tgz", - "integrity": "sha512-Bl00OFnVFkL82FHbEqy3k5CUCKH6OEJL54KCyx2oqsmZnFTR8IoNqBF+mjQVcRCT5sB6yOvK8A37LNm/kPJiZg==", - "cpu": [ - "s390x" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-x64-gnu": { - "version": "4.57.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.57.1.tgz", - "integrity": "sha512-ABca4ceT4N+Tv/GtotnWAeXZUZuM/9AQyCyKYyKnpk4yoA7QIAuBt6Hkgpw8kActYlew2mvckXkvx0FfoInnLg==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-x64-musl": { - "version": "4.57.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.57.1.tgz", - "integrity": "sha512-HFps0JeGtuOR2convgRRkHCekD7j+gdAuXM+/i6kGzQtFhlCtQkpwtNzkNj6QhCDp7DRJ7+qC/1Vg2jt5iSOFw==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-openbsd-x64": { - "version": "4.57.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-openbsd-x64/-/rollup-openbsd-x64-4.57.1.tgz", - "integrity": "sha512-H+hXEv9gdVQuDTgnqD+SQffoWoc0Of59AStSzTEj/feWTBAnSfSD3+Dql1ZruJQxmykT/JVY0dE8Ka7z0DH1hw==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "openbsd" - ] - }, - "node_modules/@rollup/rollup-openharmony-arm64": { - "version": "4.57.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.57.1.tgz", - "integrity": "sha512-4wYoDpNg6o/oPximyc/NG+mYUejZrCU2q+2w6YZqrAs2UcNUChIZXjtafAiiZSUc7On8v5NyNj34Kzj/Ltk6dQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "openharmony" - ] - }, - "node_modules/@rollup/rollup-win32-arm64-msvc": { - "version": "4.57.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.57.1.tgz", - "integrity": "sha512-O54mtsV/6LW3P8qdTcamQmuC990HDfR71lo44oZMZlXU4tzLrbvTii87Ni9opq60ds0YzuAlEr/GNwuNluZyMQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ] - }, - "node_modules/@rollup/rollup-win32-ia32-msvc": { - "version": "4.57.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.57.1.tgz", - "integrity": "sha512-P3dLS+IerxCT/7D2q2FYcRdWRl22dNbrbBEtxdWhXrfIMPP9lQhb5h4Du04mdl5Woq05jVCDPCMF7Ub0NAjIew==", - "cpu": [ - "ia32" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ] - }, - "node_modules/@rollup/rollup-win32-x64-gnu": { - "version": "4.57.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.57.1.tgz", - "integrity": "sha512-VMBH2eOOaKGtIJYleXsi2B8CPVADrh+TyNxJ4mWPnKfLB/DBUmzW+5m1xUrcwWoMfSLagIRpjUFeW5CO5hyciQ==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ] - }, - "node_modules/@rollup/rollup-win32-x64-msvc": { - "version": "4.57.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.57.1.tgz", - "integrity": "sha512-mxRFDdHIWRxg3UfIIAwCm6NzvxG0jDX/wBN6KsQFTvKFqqg9vTrWUE68qEjHt19A5wwx5X5aUi2zuZT7YR0jrA==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ] - }, - "node_modules/@types/estree": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz", - "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==", - "dev": true, - "license": "MIT" - }, - "node_modules/esbuild": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.21.5.tgz", - "integrity": "sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==", - "dev": true, - "hasInstallScript": true, - "license": "MIT", - "bin": { - "esbuild": "bin/esbuild" - }, - "engines": { - "node": ">=12" - }, - "optionalDependencies": { - "@esbuild/aix-ppc64": "0.21.5", - "@esbuild/android-arm": "0.21.5", - "@esbuild/android-arm64": "0.21.5", - "@esbuild/android-x64": "0.21.5", - "@esbuild/darwin-arm64": "0.21.5", - "@esbuild/darwin-x64": "0.21.5", - "@esbuild/freebsd-arm64": "0.21.5", - "@esbuild/freebsd-x64": "0.21.5", - "@esbuild/linux-arm": "0.21.5", - "@esbuild/linux-arm64": "0.21.5", - "@esbuild/linux-ia32": "0.21.5", - "@esbuild/linux-loong64": "0.21.5", - "@esbuild/linux-mips64el": "0.21.5", - "@esbuild/linux-ppc64": "0.21.5", - "@esbuild/linux-riscv64": "0.21.5", - "@esbuild/linux-s390x": "0.21.5", - "@esbuild/linux-x64": "0.21.5", - "@esbuild/netbsd-x64": "0.21.5", - "@esbuild/openbsd-x64": "0.21.5", - "@esbuild/sunos-x64": "0.21.5", - "@esbuild/win32-arm64": "0.21.5", - "@esbuild/win32-ia32": "0.21.5", - "@esbuild/win32-x64": "0.21.5" - } - }, - "node_modules/fsevents": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", - "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", - "dev": true, - "hasInstallScript": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": "^8.16.0 || ^10.6.0 || >=11.0.0" - } - }, - "node_modules/nanoid": { - "version": "3.3.11", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz", - "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "MIT", - "bin": { - "nanoid": "bin/nanoid.cjs" - }, - "engines": { - "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" - } - }, - "node_modules/picocolors": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", - "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", - "dev": true, - "license": "ISC" - }, - "node_modules/postcss": { - "version": "8.5.6", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.6.tgz", - "integrity": "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/postcss" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "MIT", - "dependencies": { - "nanoid": "^3.3.11", - "picocolors": "^1.1.1", - "source-map-js": "^1.2.1" - }, - "engines": { - "node": "^10 || ^12 || >=14" - } - }, - "node_modules/rollup": { - "version": "4.57.1", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.57.1.tgz", - "integrity": "sha512-oQL6lgK3e2QZeQ7gcgIkS2YZPg5slw37hYufJ3edKlfQSGGm8ICoxswK15ntSzF/a8+h7ekRy7k7oWc3BQ7y8A==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/estree": "1.0.8" - }, - "bin": { - "rollup": "dist/bin/rollup" - }, - "engines": { - "node": ">=18.0.0", - "npm": ">=8.0.0" - }, - "optionalDependencies": { - "@rollup/rollup-android-arm-eabi": "4.57.1", - "@rollup/rollup-android-arm64": "4.57.1", - "@rollup/rollup-darwin-arm64": "4.57.1", - "@rollup/rollup-darwin-x64": "4.57.1", - "@rollup/rollup-freebsd-arm64": "4.57.1", - "@rollup/rollup-freebsd-x64": "4.57.1", - "@rollup/rollup-linux-arm-gnueabihf": "4.57.1", - "@rollup/rollup-linux-arm-musleabihf": "4.57.1", - "@rollup/rollup-linux-arm64-gnu": "4.57.1", - "@rollup/rollup-linux-arm64-musl": "4.57.1", - "@rollup/rollup-linux-loong64-gnu": "4.57.1", - "@rollup/rollup-linux-loong64-musl": "4.57.1", - "@rollup/rollup-linux-ppc64-gnu": "4.57.1", - "@rollup/rollup-linux-ppc64-musl": "4.57.1", - "@rollup/rollup-linux-riscv64-gnu": "4.57.1", - "@rollup/rollup-linux-riscv64-musl": "4.57.1", - "@rollup/rollup-linux-s390x-gnu": "4.57.1", - "@rollup/rollup-linux-x64-gnu": "4.57.1", - "@rollup/rollup-linux-x64-musl": "4.57.1", - "@rollup/rollup-openbsd-x64": "4.57.1", - "@rollup/rollup-openharmony-arm64": "4.57.1", - "@rollup/rollup-win32-arm64-msvc": "4.57.1", - "@rollup/rollup-win32-ia32-msvc": "4.57.1", - "@rollup/rollup-win32-x64-gnu": "4.57.1", - "@rollup/rollup-win32-x64-msvc": "4.57.1", - "fsevents": "~2.3.2" - } - }, - "node_modules/source-map-js": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", - "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", - "dev": true, - "license": "BSD-3-Clause", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/vite": { - "version": "5.4.21", - "resolved": "https://registry.npmjs.org/vite/-/vite-5.4.21.tgz", - "integrity": "sha512-o5a9xKjbtuhY6Bi5S3+HvbRERmouabWbyUcpXXUA1u+GNUKoROi9byOJ8M0nHbHYHkYICiMlqxkg1KkYmm25Sw==", - "dev": true, - "license": "MIT", - "dependencies": { - "esbuild": "^0.21.3", - "postcss": "^8.4.43", - "rollup": "^4.20.0" - }, - "bin": { - "vite": "bin/vite.js" - }, - "engines": { - "node": "^18.0.0 || >=20.0.0" - }, - "funding": { - "url": "https://github.com/vitejs/vite?sponsor=1" - }, - "optionalDependencies": { - "fsevents": "~2.3.3" - }, - "peerDependencies": { - "@types/node": "^18.0.0 || >=20.0.0", - "less": "*", - "lightningcss": "^1.21.0", - "sass": "*", - "sass-embedded": "*", - "stylus": "*", - "sugarss": "*", - "terser": "^5.4.0" - }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - }, - "less": { - "optional": true - }, - "lightningcss": { - "optional": true - }, - "sass": { - "optional": true - }, - "sass-embedded": { - "optional": true - }, - "stylus": { - "optional": true - }, - "sugarss": { - "optional": true - }, - "terser": { - "optional": true - } - } - } - } + "name": "picoclaw-ui", + "version": "0.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "picoclaw-ui", + "version": "0.0.0", + "devDependencies": { + "typescript": "^5.4.5", + "vite": "^5.4.0" + } + }, + "node_modules/@esbuild/aix-ppc64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.21.5.tgz", + "integrity": "sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-arm": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.21.5.tgz", + "integrity": "sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.21.5.tgz", + "integrity": "sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.21.5.tgz", + "integrity": "sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/darwin-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.21.5.tgz", + "integrity": "sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/darwin-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.21.5.tgz", + "integrity": "sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.21.5.tgz", + "integrity": "sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/freebsd-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.21.5.tgz", + "integrity": "sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-arm": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.21.5.tgz", + "integrity": "sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.21.5.tgz", + "integrity": "sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-ia32": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.21.5.tgz", + "integrity": "sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.21.5.tgz", + "integrity": "sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-mips64el": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.21.5.tgz", + "integrity": "sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==", + "cpu": [ + "mips64el" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-ppc64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.21.5.tgz", + "integrity": "sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-riscv64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.21.5.tgz", + "integrity": "sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-s390x": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.21.5.tgz", + "integrity": "sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.21.5.tgz", + "integrity": "sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/netbsd-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.21.5.tgz", + "integrity": "sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/openbsd-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.21.5.tgz", + "integrity": "sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/sunos-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.21.5.tgz", + "integrity": "sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.21.5.tgz", + "integrity": "sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-ia32": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.21.5.tgz", + "integrity": "sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.21.5.tgz", + "integrity": "sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@rollup/rollup-android-arm-eabi": { + "version": "4.57.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.57.1.tgz", + "integrity": "sha512-A6ehUVSiSaaliTxai040ZpZ2zTevHYbvu/lDoeAteHI8QnaosIzm4qwtezfRg1jOYaUmnzLX1AOD6Z+UJjtifg==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-android-arm64": { + "version": "4.57.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.57.1.tgz", + "integrity": "sha512-dQaAddCY9YgkFHZcFNS/606Exo8vcLHwArFZ7vxXq4rigo2bb494/xKMMwRRQW6ug7Js6yXmBZhSBRuBvCCQ3w==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-darwin-arm64": { + "version": "4.57.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.57.1.tgz", + "integrity": "sha512-crNPrwJOrRxagUYeMn/DZwqN88SDmwaJ8Cvi/TN1HnWBU7GwknckyosC2gd0IqYRsHDEnXf328o9/HC6OkPgOg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-darwin-x64": { + "version": "4.57.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.57.1.tgz", + "integrity": "sha512-Ji8g8ChVbKrhFtig5QBV7iMaJrGtpHelkB3lsaKzadFBe58gmjfGXAOfI5FV0lYMH8wiqsxKQ1C9B0YTRXVy4w==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-freebsd-arm64": { + "version": "4.57.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.57.1.tgz", + "integrity": "sha512-R+/WwhsjmwodAcz65guCGFRkMb4gKWTcIeLy60JJQbXrJ97BOXHxnkPFrP+YwFlaS0m+uWJTstrUA9o+UchFug==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-freebsd-x64": { + "version": "4.57.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.57.1.tgz", + "integrity": "sha512-IEQTCHeiTOnAUC3IDQdzRAGj3jOAYNr9kBguI7MQAAZK3caezRrg0GxAb6Hchg4lxdZEI5Oq3iov/w/hnFWY9Q==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-linux-arm-gnueabihf": { + "version": "4.57.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.57.1.tgz", + "integrity": "sha512-F8sWbhZ7tyuEfsmOxwc2giKDQzN3+kuBLPwwZGyVkLlKGdV1nvnNwYD0fKQ8+XS6hp9nY7B+ZeK01EBUE7aHaw==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm-musleabihf": { + "version": "4.57.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.57.1.tgz", + "integrity": "sha512-rGfNUfn0GIeXtBP1wL5MnzSj98+PZe/AXaGBCRmT0ts80lU5CATYGxXukeTX39XBKsxzFpEeK+Mrp9faXOlmrw==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-gnu": { + "version": "4.57.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.57.1.tgz", + "integrity": "sha512-MMtej3YHWeg/0klK2Qodf3yrNzz6CGjo2UntLvk2RSPlhzgLvYEB3frRvbEF2wRKh1Z2fDIg9KRPe1fawv7C+g==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-musl": { + "version": "4.57.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.57.1.tgz", + "integrity": "sha512-1a/qhaaOXhqXGpMFMET9VqwZakkljWHLmZOX48R0I/YLbhdxr1m4gtG1Hq7++VhVUmf+L3sTAf9op4JlhQ5u1Q==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-loong64-gnu": { + "version": "4.57.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.57.1.tgz", + "integrity": "sha512-QWO6RQTZ/cqYtJMtxhkRkidoNGXc7ERPbZN7dVW5SdURuLeVU7lwKMpo18XdcmpWYd0qsP1bwKPf7DNSUinhvA==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-loong64-musl": { + "version": "4.57.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-musl/-/rollup-linux-loong64-musl-4.57.1.tgz", + "integrity": "sha512-xpObYIf+8gprgWaPP32xiN5RVTi/s5FCR+XMXSKmhfoJjrpRAjCuuqQXyxUa/eJTdAE6eJ+KDKaoEqjZQxh3Gw==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-ppc64-gnu": { + "version": "4.57.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.57.1.tgz", + "integrity": "sha512-4BrCgrpZo4hvzMDKRqEaW1zeecScDCR+2nZ86ATLhAoJ5FQ+lbHVD3ttKe74/c7tNT9c6F2viwB3ufwp01Oh2w==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-ppc64-musl": { + "version": "4.57.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-musl/-/rollup-linux-ppc64-musl-4.57.1.tgz", + "integrity": "sha512-NOlUuzesGauESAyEYFSe3QTUguL+lvrN1HtwEEsU2rOwdUDeTMJdO5dUYl/2hKf9jWydJrO9OL/XSSf65R5+Xw==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-gnu": { + "version": "4.57.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.57.1.tgz", + "integrity": "sha512-ptA88htVp0AwUUqhVghwDIKlvJMD/fmL/wrQj99PRHFRAG6Z5nbWoWG4o81Nt9FT+IuqUQi+L31ZKAFeJ5Is+A==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-musl": { + "version": "4.57.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.57.1.tgz", + "integrity": "sha512-S51t7aMMTNdmAMPpBg7OOsTdn4tySRQvklmL3RpDRyknk87+Sp3xaumlatU+ppQ+5raY7sSTcC2beGgvhENfuw==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-s390x-gnu": { + "version": "4.57.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.57.1.tgz", + "integrity": "sha512-Bl00OFnVFkL82FHbEqy3k5CUCKH6OEJL54KCyx2oqsmZnFTR8IoNqBF+mjQVcRCT5sB6yOvK8A37LNm/kPJiZg==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-gnu": { + "version": "4.57.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.57.1.tgz", + "integrity": "sha512-ABca4ceT4N+Tv/GtotnWAeXZUZuM/9AQyCyKYyKnpk4yoA7QIAuBt6Hkgpw8kActYlew2mvckXkvx0FfoInnLg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-musl": { + "version": "4.57.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.57.1.tgz", + "integrity": "sha512-HFps0JeGtuOR2convgRRkHCekD7j+gdAuXM+/i6kGzQtFhlCtQkpwtNzkNj6QhCDp7DRJ7+qC/1Vg2jt5iSOFw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-openbsd-x64": { + "version": "4.57.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-openbsd-x64/-/rollup-openbsd-x64-4.57.1.tgz", + "integrity": "sha512-H+hXEv9gdVQuDTgnqD+SQffoWoc0Of59AStSzTEj/feWTBAnSfSD3+Dql1ZruJQxmykT/JVY0dE8Ka7z0DH1hw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ] + }, + "node_modules/@rollup/rollup-openharmony-arm64": { + "version": "4.57.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.57.1.tgz", + "integrity": "sha512-4wYoDpNg6o/oPximyc/NG+mYUejZrCU2q+2w6YZqrAs2UcNUChIZXjtafAiiZSUc7On8v5NyNj34Kzj/Ltk6dQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ] + }, + "node_modules/@rollup/rollup-win32-arm64-msvc": { + "version": "4.57.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.57.1.tgz", + "integrity": "sha512-O54mtsV/6LW3P8qdTcamQmuC990HDfR71lo44oZMZlXU4tzLrbvTii87Ni9opq60ds0YzuAlEr/GNwuNluZyMQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-ia32-msvc": { + "version": "4.57.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.57.1.tgz", + "integrity": "sha512-P3dLS+IerxCT/7D2q2FYcRdWRl22dNbrbBEtxdWhXrfIMPP9lQhb5h4Du04mdl5Woq05jVCDPCMF7Ub0NAjIew==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-x64-gnu": { + "version": "4.57.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.57.1.tgz", + "integrity": "sha512-VMBH2eOOaKGtIJYleXsi2B8CPVADrh+TyNxJ4mWPnKfLB/DBUmzW+5m1xUrcwWoMfSLagIRpjUFeW5CO5hyciQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-x64-msvc": { + "version": "4.57.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.57.1.tgz", + "integrity": "sha512-mxRFDdHIWRxg3UfIIAwCm6NzvxG0jDX/wBN6KsQFTvKFqqg9vTrWUE68qEjHt19A5wwx5X5aUi2zuZT7YR0jrA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@types/estree": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz", + "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==", + "dev": true, + "license": "MIT" + }, + "node_modules/esbuild": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.21.5.tgz", + "integrity": "sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=12" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.21.5", + "@esbuild/android-arm": "0.21.5", + "@esbuild/android-arm64": "0.21.5", + "@esbuild/android-x64": "0.21.5", + "@esbuild/darwin-arm64": "0.21.5", + "@esbuild/darwin-x64": "0.21.5", + "@esbuild/freebsd-arm64": "0.21.5", + "@esbuild/freebsd-x64": "0.21.5", + "@esbuild/linux-arm": "0.21.5", + "@esbuild/linux-arm64": "0.21.5", + "@esbuild/linux-ia32": "0.21.5", + "@esbuild/linux-loong64": "0.21.5", + "@esbuild/linux-mips64el": "0.21.5", + "@esbuild/linux-ppc64": "0.21.5", + "@esbuild/linux-riscv64": "0.21.5", + "@esbuild/linux-s390x": "0.21.5", + "@esbuild/linux-x64": "0.21.5", + "@esbuild/netbsd-x64": "0.21.5", + "@esbuild/openbsd-x64": "0.21.5", + "@esbuild/sunos-x64": "0.21.5", + "@esbuild/win32-arm64": "0.21.5", + "@esbuild/win32-ia32": "0.21.5", + "@esbuild/win32-x64": "0.21.5" + } + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/nanoid": { + "version": "3.3.11", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz", + "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "node_modules/picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "dev": true, + "license": "ISC" + }, + "node_modules/postcss": { + "version": "8.5.6", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.6.tgz", + "integrity": "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "nanoid": "^3.3.11", + "picocolors": "^1.1.1", + "source-map-js": "^1.2.1" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/rollup": { + "version": "4.57.1", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.57.1.tgz", + "integrity": "sha512-oQL6lgK3e2QZeQ7gcgIkS2YZPg5slw37hYufJ3edKlfQSGGm8ICoxswK15ntSzF/a8+h7ekRy7k7oWc3BQ7y8A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/estree": "1.0.8" + }, + "bin": { + "rollup": "dist/bin/rollup" + }, + "engines": { + "node": ">=18.0.0", + "npm": ">=8.0.0" + }, + "optionalDependencies": { + "@rollup/rollup-android-arm-eabi": "4.57.1", + "@rollup/rollup-android-arm64": "4.57.1", + "@rollup/rollup-darwin-arm64": "4.57.1", + "@rollup/rollup-darwin-x64": "4.57.1", + "@rollup/rollup-freebsd-arm64": "4.57.1", + "@rollup/rollup-freebsd-x64": "4.57.1", + "@rollup/rollup-linux-arm-gnueabihf": "4.57.1", + "@rollup/rollup-linux-arm-musleabihf": "4.57.1", + "@rollup/rollup-linux-arm64-gnu": "4.57.1", + "@rollup/rollup-linux-arm64-musl": "4.57.1", + "@rollup/rollup-linux-loong64-gnu": "4.57.1", + "@rollup/rollup-linux-loong64-musl": "4.57.1", + "@rollup/rollup-linux-ppc64-gnu": "4.57.1", + "@rollup/rollup-linux-ppc64-musl": "4.57.1", + "@rollup/rollup-linux-riscv64-gnu": "4.57.1", + "@rollup/rollup-linux-riscv64-musl": "4.57.1", + "@rollup/rollup-linux-s390x-gnu": "4.57.1", + "@rollup/rollup-linux-x64-gnu": "4.57.1", + "@rollup/rollup-linux-x64-musl": "4.57.1", + "@rollup/rollup-openbsd-x64": "4.57.1", + "@rollup/rollup-openharmony-arm64": "4.57.1", + "@rollup/rollup-win32-arm64-msvc": "4.57.1", + "@rollup/rollup-win32-ia32-msvc": "4.57.1", + "@rollup/rollup-win32-x64-gnu": "4.57.1", + "@rollup/rollup-win32-x64-msvc": "4.57.1", + "fsevents": "~2.3.2" + } + }, + "node_modules/source-map-js": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", + "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/typescript": { + "version": "5.9.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz", + "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/vite": { + "version": "5.4.21", + "resolved": "https://registry.npmjs.org/vite/-/vite-5.4.21.tgz", + "integrity": "sha512-o5a9xKjbtuhY6Bi5S3+HvbRERmouabWbyUcpXXUA1u+GNUKoROi9byOJ8M0nHbHYHkYICiMlqxkg1KkYmm25Sw==", + "dev": true, + "license": "MIT", + "dependencies": { + "esbuild": "^0.21.3", + "postcss": "^8.4.43", + "rollup": "^4.20.0" + }, + "bin": { + "vite": "bin/vite.js" + }, + "engines": { + "node": "^18.0.0 || >=20.0.0" + }, + "funding": { + "url": "https://github.com/vitejs/vite?sponsor=1" + }, + "optionalDependencies": { + "fsevents": "~2.3.3" + }, + "peerDependencies": { + "@types/node": "^18.0.0 || >=20.0.0", + "less": "*", + "lightningcss": "^1.21.0", + "sass": "*", + "sass-embedded": "*", + "stylus": "*", + "sugarss": "*", + "terser": "^5.4.0" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "less": { + "optional": true + }, + "lightningcss": { + "optional": true + }, + "sass": { + "optional": true + }, + "sass-embedded": { + "optional": true + }, + "stylus": { + "optional": true + }, + "sugarss": { + "optional": true + }, + "terser": { + "optional": true + } + } + } + } } diff --git a/ui/package.json b/ui/package.json index e606400a6..32cac9e49 100644 --- a/ui/package.json +++ b/ui/package.json @@ -1,14 +1,15 @@ { - "name": "picoclaw-ui", - "private": true, - "version": "0.0.0", - "type": "module", - "scripts": { - "dev": "vite", - "build": "vite build", - "preview": "vite preview" - }, - "devDependencies": { - "vite": "^5.4.0" - } + "name": "picoclaw-ui", + "private": true, + "version": "0.0.0", + "type": "module", + "scripts": { + "dev": "vite", + "build": "vite build", + "preview": "vite preview" + }, + "devDependencies": { + "typescript": "^5.4.5", + "vite": "^5.4.0" + } } diff --git a/ui/src/main.js b/ui/src/main.js deleted file mode 100644 index 562684137..000000000 --- a/ui/src/main.js +++ /dev/null @@ -1,169 +0,0 @@ -import './style.css' - -const app = document.querySelector('#app') - -const THEME_STORAGE_KEY = 'picoclaw.theme' - -function getStoredTheme() { - const v = localStorage.getItem(THEME_STORAGE_KEY) - if (v === 'light' || v === 'dark' || v === 'system') return v - return 'system' -} - -function applyTheme(mode) { - const root = document.documentElement - if (mode === 'system') { - root.removeAttribute('data-theme') - } else { - root.setAttribute('data-theme', mode) - } -} - -let themeMode = getStoredTheme() -applyTheme(themeMode) - -app.innerHTML = ` -
-
-
PicoClaw
-
- -
disconnected
-
-
- -
- -
- - -
-
-` - -const chat = document.querySelector('#chat') -const statusEl = document.querySelector('#status') -const themeSelect = document.querySelector('#theme') -const form = document.querySelector('#form') -const input = document.querySelector('#input') - -const chatId = 'browser' -const TOKEN_STORAGE_KEY = 'picoclaw.gateway_token' -const urlParams = new URLSearchParams(location.search) -const tokenFromUrl = urlParams.get('token') || '' -const tokenFromStorage = localStorage.getItem(TOKEN_STORAGE_KEY) || '' -let gatewayToken = tokenFromUrl || tokenFromStorage -let tokenCameFromUrl = !!tokenFromUrl - -function removeTokenFromUrl() { - const p = new URLSearchParams(location.search) - if (!p.has('token')) return - p.delete('token') - const qs = p.toString() - const newUrl = `${location.pathname}${qs ? `?${qs}` : ''}${location.hash || ''}` - history.replaceState(null, '', newUrl) -} - -themeSelect.value = themeMode -themeSelect.addEventListener('change', () => { - themeMode = themeSelect.value - localStorage.setItem(THEME_STORAGE_KEY, themeMode) - applyTheme(themeMode) -}) - -const media = window.matchMedia('(prefers-color-scheme: dark)') -media.addEventListener('change', () => { - if (themeMode === 'system') applyTheme('system') -}) - -function addMessage(role, text) { - const item = document.createElement('div') - item.className = `msg ${role}` - - const bubble = document.createElement('div') - bubble.className = 'bubble' - bubble.textContent = text - - item.appendChild(bubble) - chat.appendChild(item) - chat.scrollTop = chat.scrollHeight -} - -function wsUrl() { - const proto = location.protocol === 'https:' ? 'wss:' : 'ws:' - const tokenPart = gatewayToken ? `&token=${encodeURIComponent(gatewayToken)}` : '' - return `${proto}//${location.host}/ws?chat_id=${encodeURIComponent(chatId)}${tokenPart}` -} - -let ws -let reconnectTimer - -function setStatus(s) { - statusEl.textContent = s - statusEl.dataset.state = s -} - -function connect() { - if (ws && (ws.readyState === WebSocket.OPEN || ws.readyState === WebSocket.CONNECTING)) return - - setStatus('connecting') - ws = new WebSocket(wsUrl()) - - ws.addEventListener('open', () => { - setStatus('connected') - - if (tokenCameFromUrl && gatewayToken) { - localStorage.setItem(TOKEN_STORAGE_KEY, gatewayToken) - removeTokenFromUrl() - tokenCameFromUrl = false - } - }) - - ws.addEventListener('close', () => { - setStatus('disconnected') - if (!reconnectTimer) { - reconnectTimer = setTimeout(() => { - reconnectTimer = null - connect() - }, 1000) - } - }) - - ws.addEventListener('message', (ev) => { - try { - const msg = JSON.parse(ev.data) - if (msg && msg.type === 'message' && typeof msg.content === 'string') { - addMessage('assistant', msg.content) - } - } catch { - } - }) -} - -form.addEventListener('submit', (e) => { - e.preventDefault() - const text = input.value.trim() - if (!text) return - input.value = '' - - addMessage('user', text) - - if (!ws || ws.readyState !== WebSocket.OPEN) { - connect() - } - - const payload = { chat_id: chatId, content: text } - try { - ws.send(JSON.stringify(payload)) - } catch { - } -}) - -connect() diff --git a/ui/src/main.ts b/ui/src/main.ts new file mode 100644 index 000000000..ddf76097a --- /dev/null +++ b/ui/src/main.ts @@ -0,0 +1,679 @@ +import "./style.css"; + +const app = document.querySelector("#app"); +if (!app) { + throw new Error("Missing #app element"); +} + +const appEl = app; + +const THEME_STORAGE_KEY = "picoclaw.theme"; + +type ThemeMode = "system" | "light" | "dark"; + +function getStoredTheme(): ThemeMode { + const v = localStorage.getItem(THEME_STORAGE_KEY); + if (v === "light" || v === "dark" || v === "system") return v; + return "system"; +} + +function applyTheme(mode: ThemeMode): void { + const root = document.documentElement; + if (mode === "system") { + root.removeAttribute("data-theme"); + } else { + root.setAttribute("data-theme", mode); + } +} + +let themeMode: ThemeMode = getStoredTheme(); +applyTheme(themeMode); + +const ADMIN_TOKEN_STORAGE_KEY = "picoclaw.admin_token"; + +type JSONSchema = { + $ref?: string; + title?: string; + description?: string; + type?: unknown; + properties?: Record; + required?: string[]; + items?: JSONSchema; + enum?: unknown[]; + default?: unknown; + examples?: unknown[]; + anyOf?: JSONSchema[]; + allOf?: JSONSchema[]; + oneOf?: JSONSchema[]; + $defs?: Record; +}; + +function isRecord(v: unknown): v is Record { + return typeof v === "object" && v !== null && !Array.isArray(v); +} + +function resolveRef(root: JSONSchema, ref: string): JSONSchema | null { + if (!ref.startsWith("#/$defs/")) return null; + const name = ref.slice("#/$defs/".length); + const defs = root.$defs; + if (!defs) return null; + return defs[name] ?? null; +} + +function mergeSchemas(a: JSONSchema, b: JSONSchema): JSONSchema { + return { + ...a, + ...b, + properties: { + ...(a.properties ?? {}), + ...(b.properties ?? {}), + }, + required: Array.from( + new Set([...(a.required ?? []), ...(b.required ?? [])]), + ), + }; +} + +function normalizeSchema(root: JSONSchema, schema: JSONSchema): JSONSchema { + let s = schema; + if (s.$ref) { + const r = resolveRef(root, s.$ref); + if (r) s = mergeSchemas(r, { ...s, $ref: undefined }); + } + if (s.allOf && s.allOf.length > 0) { + let out: JSONSchema = { ...s, allOf: undefined }; + for (const part of s.allOf) + out = mergeSchemas(out, normalizeSchema(root, part)); + s = out; + } + return s; +} + +function getSchemaType(schema: JSONSchema): string | null { + const t = schema.type; + if (typeof t === "string") return t; + return null; +} + +function deepGet(obj: unknown, path: string[]): unknown { + let cur: unknown = obj; + for (const p of path) { + if (!isRecord(cur)) return undefined; + cur = cur[p]; + } + return cur; +} + +function deepSet(obj: unknown, path: string[], value: unknown): void { + if (!isRecord(obj)) return; + let cur: Record = obj; + for (let i = 0; i < path.length - 1; i++) { + const p = path[i]; + const next = cur[p]; + if (!isRecord(next)) { + cur[p] = {}; + } + cur = cur[p] as Record; + } + cur[path[path.length - 1]] = value; +} + +function renderAdminUI(): void { + appEl.innerHTML = ` +
+
+
PicoClaw Admin
+
+ +
idle
+
+
+ +
+
+
Connection
+
+ +
+ + +
+
+
+ +
+
Mode
+
+ + +
+
+ + + +
+
Config Form
+
+
+
+
+ `; + + const statusEl = document.querySelector("#status"); + const themeSelect = document.querySelector("#theme"); + const adminTokenInput = + document.querySelector("#adminToken"); + const loadBtn = document.querySelector("#load"); + const saveBtn = document.querySelector("#save"); + const rawTextarea = document.querySelector("#raw"); + const modeInputs = + document.querySelectorAll("input[name=mode]"); + const jsonPanel = document.querySelector("#jsonPanel"); + const formPanel = document.querySelector("#formPanel"); + const formRoot = document.querySelector("#formRoot"); + + if ( + !statusEl || + !themeSelect || + !adminTokenInput || + !loadBtn || + !saveBtn || + !rawTextarea || + !jsonPanel || + !formPanel || + !formRoot + ) { + throw new Error("Missing admin UI elements"); + } + + const statusDiv = statusEl; + const themeSelectEl = themeSelect; + const adminTokenInputEl = adminTokenInput; + const loadBtnEl = loadBtn; + const saveBtnEl = saveBtn; + const rawTextareaEl = rawTextarea; + const jsonPanelEl = jsonPanel; + const formPanelEl = formPanel; + const formRootEl = formRoot; + const setStatus = (s: string): void => { + statusDiv.textContent = s; + statusDiv.dataset.state = s; + }; + + themeSelectEl.value = themeMode; + themeSelectEl.addEventListener("change", () => { + const v = themeSelectEl.value; + if (v === "light" || v === "dark" || v === "system") { + themeMode = v; + } else { + themeMode = "system"; + } + localStorage.setItem(THEME_STORAGE_KEY, themeMode); + applyTheme(themeMode); + }); + + adminTokenInputEl.value = localStorage.getItem(ADMIN_TOKEN_STORAGE_KEY) || ""; + adminTokenInputEl.addEventListener("input", () => { + localStorage.setItem(ADMIN_TOKEN_STORAGE_KEY, adminTokenInputEl.value); + }); + + let schemaRoot: JSONSchema | null = null; + let configObj: unknown = null; + + function authHeaders(): HeadersInit { + const token = adminTokenInputEl.value.trim(); + return token ? { Authorization: `Bearer ${token}` } : {}; + } + + async function loadAll(): Promise { + setStatus("loading"); + try { + const [schemaResp, cfgResp] = await Promise.all([ + fetch("/admin/schema", { headers: authHeaders() }), + fetch("/admin/config", { headers: authHeaders() }), + ]); + if (!schemaResp.ok) + throw new Error( + `schema: ${schemaResp.status} ${schemaResp.statusText}`, + ); + if (!cfgResp.ok) + throw new Error(`config: ${cfgResp.status} ${cfgResp.statusText}`); + schemaRoot = (await schemaResp.json()) as JSONSchema; + configObj = (await cfgResp.json()) as unknown; + rawTextareaEl.value = JSON.stringify(configObj, null, 2); + renderForm(); + setStatus("loaded"); + } catch (e) { + setStatus(e instanceof Error ? e.message : "load failed"); + } + } + + async function saveAll(): Promise { + setStatus("saving"); + try { + const raw = rawTextareaEl.value.trim(); + const body = + raw.length > 0 ? raw : JSON.stringify(configObj ?? {}, null, 2); + const resp = await fetch("/admin/config", { + method: "PUT", + headers: { + ...authHeaders(), + "Content-Type": "application/json", + }, + body, + }); + if (!resp.ok) { + const text = await resp.text().catch(() => ""); + throw new Error(text || `${resp.status} ${resp.statusText}`); + } + setStatus("saved"); + } catch (e) { + setStatus(e instanceof Error ? e.message : "save failed"); + } + } + + function renderForm(): void { + if (!schemaRoot || !configObj) { + formRootEl.innerHTML = ""; + return; + } + const root = normalizeSchema(schemaRoot, schemaRoot); + formRootEl.innerHTML = ""; + const node = renderSchemaNode(schemaRoot, root, [], configObj); + formRootEl.appendChild(node); + } + + function schemaLabel(schema: JSONSchema, key: string | null): string { + if (typeof schema.title === "string" && schema.title.trim() !== "") + return schema.title; + if (key) return key; + return "value"; + } + + function schemaHelp(schema: JSONSchema): string { + const parts: string[] = []; + if ( + typeof schema.description === "string" && + schema.description.trim() !== "" + ) { + parts.push(schema.description.trim()); + } + if (schema.default !== undefined) { + parts.push(`default: ${JSON.stringify(schema.default)}`); + } + if (Array.isArray(schema.examples) && schema.examples.length > 0) { + parts.push(`example: ${JSON.stringify(schema.examples[0])}`); + } + return parts.join(" ยท "); + } + + function renderSchemaNode( + schemaRoot0: JSONSchema, + schema0: JSONSchema, + path: string[], + obj: unknown, + key: string | null = null, + ): HTMLElement { + const schema = normalizeSchema(schemaRoot0, schema0); + const t = getSchemaType(schema); + const label = schemaLabel(schema, key); + const help = schemaHelp(schema); + + const wrap = document.createElement("div"); + wrap.className = "node"; + + const header = document.createElement("div"); + header.className = "node-header"; + header.textContent = label; + wrap.appendChild(header); + + if (help) { + const helpEl = document.createElement("div"); + helpEl.className = "node-help"; + helpEl.textContent = help; + wrap.appendChild(helpEl); + } + + if (schema.enum && Array.isArray(schema.enum)) { + const select = document.createElement("select"); + select.className = "input"; + for (const v of schema.enum) { + const opt = document.createElement("option"); + opt.value = String(v); + opt.textContent = String(v); + select.appendChild(opt); + } + const cur = deepGet(obj, path); + if (cur !== undefined) select.value = String(cur); + select.addEventListener("change", () => { + deepSet(obj, path, select.value); + rawTextareaEl.value = JSON.stringify(configObj ?? {}, null, 2); + }); + wrap.appendChild(select); + return wrap; + } + + if (t === "object" && schema.properties) { + const req = new Set(schema.required ?? []); + const props = schema.properties; + const keys = Object.keys(props); + keys.sort(); + for (const k of keys) { + const childSchema = props[k]; + const row = document.createElement("div"); + row.className = "row"; + + const child = renderSchemaNode( + schemaRoot0, + childSchema, + [...path, k], + obj, + k, + ); + if (req.has(k)) { + child.classList.add("required"); + } + row.appendChild(child); + wrap.appendChild(row); + } + return wrap; + } + + if (t === "boolean") { + const input = document.createElement("input"); + input.type = "checkbox"; + input.className = "checkbox"; + const cur = deepGet(obj, path); + input.checked = Boolean(cur ?? schema.default ?? false); + input.addEventListener("change", () => { + deepSet(obj, path, input.checked); + rawTextareaEl.value = JSON.stringify(configObj ?? {}, null, 2); + }); + wrap.appendChild(input); + return wrap; + } + + if (t === "number" || t === "integer") { + const input = document.createElement("input"); + input.type = "number"; + input.className = "input"; + if (t === "integer") input.step = "1"; + const cur = deepGet(obj, path); + if (typeof cur === "number") input.value = String(cur); + else if (typeof schema.default === "number") + input.value = String(schema.default); + input.addEventListener("input", () => { + const v = input.value.trim(); + if (v === "") { + deepSet(obj, path, null); + } else { + const n = Number(v); + deepSet(obj, path, Number.isFinite(n) ? n : null); + } + rawTextareaEl.value = JSON.stringify(configObj ?? {}, null, 2); + }); + wrap.appendChild(input); + return wrap; + } + + if (t === "array" && schema.items) { + const textarea = document.createElement("textarea"); + textarea.className = "textarea"; + const cur = deepGet(obj, path); + textarea.value = JSON.stringify(cur ?? schema.default ?? [], null, 2); + textarea.addEventListener("input", () => { + try { + const v = JSON.parse(textarea.value); + deepSet(obj, path, v); + rawTextareaEl.value = JSON.stringify(configObj ?? {}, null, 2); + } catch { + // ignore + } + }); + wrap.appendChild(textarea); + return wrap; + } + + // string or unknown: simple text input + const input = document.createElement("input"); + input.type = "text"; + input.className = "input"; + const cur = deepGet(obj, path); + if (typeof cur === "string") input.value = cur; + else if (typeof schema.default === "string") input.value = schema.default; + input.addEventListener("input", () => { + deepSet(obj, path, input.value); + rawTextareaEl.value = JSON.stringify(configObj ?? {}, null, 2); + }); + wrap.appendChild(input); + return wrap; + } + + function switchMode(mode: "form" | "json"): void { + if (mode === "json") { + jsonPanelEl.style.display = "block"; + formPanelEl.style.display = "none"; + } else { + jsonPanelEl.style.display = "none"; + formPanelEl.style.display = "block"; + // Try to parse the JSON editor back into config when switching to form. + try { + configObj = JSON.parse(rawTextareaEl.value); + renderForm(); + } catch { + // ignore + } + } + } + + modeInputs.forEach((i) => { + i.addEventListener("change", () => { + const v = i.value === "json" ? "json" : "form"; + switchMode(v); + }); + }); + + loadBtnEl.addEventListener("click", (e) => { + e.preventDefault(); + void loadAll(); + }); + saveBtnEl.addEventListener("click", (e) => { + e.preventDefault(); + void saveAll(); + }); + + void loadAll(); +} + +function renderChatUI(): void { + appEl.innerHTML = ` +
+
+
PicoClaw
+
+ +
disconnected
+
+
+ +
+ +
+ + +
+
+`; + + const chat = document.querySelector("#chat"); + const statusEl = document.querySelector("#status"); + const themeSelect = document.querySelector("#theme"); + const form = document.querySelector("#form"); + const input = document.querySelector("#input"); + + if (!chat || !statusEl || !themeSelect || !form || !input) { + throw new Error("Missing UI elements"); + } + + const chatEl = chat as HTMLDivElement; + const statusDiv = statusEl as HTMLDivElement; + + const chatId = "browser"; + const TOKEN_STORAGE_KEY = "picoclaw.gateway_token"; + + const urlParams = new URLSearchParams(location.search); + const tokenFromUrl = urlParams.get("token") || ""; + const tokenFromStorage = localStorage.getItem(TOKEN_STORAGE_KEY) || ""; + const gatewayToken = tokenFromUrl || tokenFromStorage; + let tokenCameFromUrl = Boolean(tokenFromUrl); + + function removeTokenFromUrl(): void { + const p = new URLSearchParams(location.search); + if (!p.has("token")) return; + p.delete("token"); + const qs = p.toString(); + const newUrl = `${location.pathname}${qs ? `?${qs}` : ""}${location.hash || ""}`; + history.replaceState(null, "", newUrl); + } + + themeSelect.value = themeMode; + + themeSelect.addEventListener("change", () => { + const v = themeSelect.value; + if (v === "light" || v === "dark" || v === "system") { + themeMode = v; + } else { + themeMode = "system"; + } + localStorage.setItem(THEME_STORAGE_KEY, themeMode); + applyTheme(themeMode); + }); + + const media = window.matchMedia("(prefers-color-scheme: dark)"); + media.addEventListener("change", () => { + if (themeMode === "system") applyTheme("system"); + }); + + function addMessage(role: "user" | "assistant", text: string): void { + const item = document.createElement("div"); + item.className = `msg ${role}`; + + const bubble = document.createElement("div"); + bubble.className = "bubble"; + bubble.textContent = text; + + item.appendChild(bubble); + chatEl.appendChild(item); + chatEl.scrollTop = chatEl.scrollHeight; + } + + function wsUrl(): string { + const proto = location.protocol === "https:" ? "wss:" : "ws:"; + const tokenPart = gatewayToken + ? `&token=${encodeURIComponent(gatewayToken)}` + : ""; + return `${proto}//${location.host}/ws?chat_id=${encodeURIComponent(chatId)}${tokenPart}`; + } + + type WSMessage = { type?: unknown; content?: unknown }; + + let ws: WebSocket | null = null; + let reconnectTimer: number | null = null; + + function setStatus(s: string): void { + statusDiv.textContent = s; + statusDiv.dataset.state = s; + } + + function connect(): void { + if ( + ws && + (ws.readyState === WebSocket.OPEN || + ws.readyState === WebSocket.CONNECTING) + ) + return; + + setStatus("connecting"); + ws = new WebSocket(wsUrl()); + + ws.addEventListener("open", () => { + setStatus("connected"); + + if (tokenCameFromUrl && gatewayToken) { + localStorage.setItem(TOKEN_STORAGE_KEY, gatewayToken); + removeTokenFromUrl(); + tokenCameFromUrl = false; + } + }); + + ws.addEventListener("close", () => { + setStatus("disconnected"); + if (reconnectTimer == null) { + reconnectTimer = window.setTimeout(() => { + reconnectTimer = null; + connect(); + }, 1000); + } + }); + + ws.addEventListener("message", (ev: MessageEvent) => { + try { + const msg = JSON.parse(ev.data) as WSMessage; + if (msg && msg.type === "message" && typeof msg.content === "string") { + addMessage("assistant", msg.content); + } + } catch { + // ignore + } + }); + } + + form.addEventListener("submit", (e) => { + e.preventDefault(); + const text = input.value.trim(); + if (!text) return; + input.value = ""; + + addMessage("user", text); + + if (!ws || ws.readyState !== WebSocket.OPEN) { + connect(); + } + + const payload = { chat_id: chatId, content: text }; + try { + ws?.send(JSON.stringify(payload)); + } catch { + // ignore + } + }); + + connect(); +} + +if (location.pathname.startsWith("/admin")) { + renderAdminUI(); +} else { + renderChatUI(); +} diff --git a/ui/src/style.css b/ui/src/style.css index 24845387c..a9d3fbde8 100644 --- a/ui/src/style.css +++ b/ui/src/style.css @@ -205,3 +205,122 @@ html, body { .btn:hover { background: rgba(37, 99, 235, 0.22); } + +.admin { + overflow: auto; + padding: 16px; + border: 1px solid var(--border); + border-radius: 14px; + background: var(--panel); + backdrop-filter: blur(10px); + box-shadow: var(--shadow); + display: grid; + gap: 14px; +} + +.panel { + border: 1px solid var(--border); + border-radius: 14px; + background: var(--panel-solid); + padding: 14px; +} + +.panel-title { + font-weight: 700; + margin-bottom: 10px; +} + +.grid { + display: grid; + grid-template-columns: 1fr; + gap: 12px; +} + +.row { + display: flex; + gap: 10px; + flex-wrap: wrap; + align-items: stretch; + width: 100%; +} + +.row > .node { + flex: 1 1 100%; + min-width: 0; +} + +.field { + display: grid; + gap: 6px; +} + +.field-label { + font-size: 12px; + color: var(--muted); +} + +.field-help { + font-size: 12px; + color: var(--muted); +} + +.textarea { + width: 100%; + min-height: 38px; + height: 38px; + padding: 10px 12px; + border-radius: 12px; + border: 1px solid var(--border); + background: var(--input-bg); + color: var(--text); + outline: none; + resize: vertical; + font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace; + font-size: 12px; +} + +#raw.textarea { + min-height: 280px; + height: 280px; +} + +.textarea:focus { + border-color: rgba(37, 99, 235, 0.65); + box-shadow: 0 0 0 3px rgba(37, 99, 235, 0.18); +} + +.radio { + display: inline-flex; + gap: 8px; + align-items: center; + color: var(--text); +} + +.form { + display: grid; + gap: 12px; +} + +.node { + width: 100%; + padding: 10px 12px; + border: 1px solid var(--border); + border-radius: 12px; + background: rgba(37, 99, 235, 0.04); +} + +.node.required > .node-header::after { + content: " *"; + color: #ed4245; +} + +.node-header { + font-weight: 650; + margin-bottom: 6px; +} + +.node-help { + font-size: 12px; + color: var(--muted); + margin-bottom: 8px; +} diff --git a/ui/src/vite-env.d.ts b/ui/src/vite-env.d.ts new file mode 100644 index 000000000..11f02fe2a --- /dev/null +++ b/ui/src/vite-env.d.ts @@ -0,0 +1 @@ +/// diff --git a/ui/tsconfig.json b/ui/tsconfig.json new file mode 100644 index 000000000..8387eaf59 --- /dev/null +++ b/ui/tsconfig.json @@ -0,0 +1,19 @@ +{ + "compilerOptions": { + "target": "ES2020", + "useDefineForClassFields": true, + "module": "ESNext", + "lib": ["ES2020", "DOM", "DOM.Iterable"], + "skipLibCheck": true, + + "moduleResolution": "Bundler", + "resolveJsonModule": true, + "isolatedModules": true, + "noEmit": true, + "jsx": "preserve", + + "strict": true, + "types": [] + }, + "include": ["src"] +}