diff --git a/.github/workflows/build-helper.yml b/.github/workflows/build-helper.yml
index a38ea73d5..96ce7d55b 100644
--- a/.github/workflows/build-helper.yml
+++ b/.github/workflows/build-helper.yml
@@ -10,7 +10,7 @@ on:
- "v[0-9]+.[0-9]+.[0-9]+*"
workflow_dispatch:
env:
- GO_VERSION: "1.22"
+ GO_VERSION: "1.23"
NODE_VERSION: 22
jobs:
build-app:
diff --git a/.github/workflows/testdriver.yml b/.github/workflows/testdriver.yml
index 47d428df6..2a9cbb37c 100644
--- a/.github/workflows/testdriver.yml
+++ b/.github/workflows/testdriver.yml
@@ -23,7 +23,7 @@ on:
workflow_dispatch: null
env:
- GO_VERSION: "1.22"
+ GO_VERSION: "1.23"
NODE_VERSION: 22
permissions:
diff --git a/cmd/server/main-server.go b/cmd/server/main-server.go
index f433c6015..0d32a8def 100644
--- a/cmd/server/main-server.go
+++ b/cmd/server/main-server.go
@@ -143,6 +143,7 @@ func beforeSendActivityUpdate(ctx context.Context) {
activity.NumWindows, _ = wstore.DBGetCount[*waveobj.Window](ctx)
activity.NumSSHConn = conncontroller.GetNumSSHHasConnected()
activity.NumWSLConn = wsl.GetNumWSLHasConnected()
+ activity.NumWSNamed, activity.NumWS, _ = wstore.DBGetWSCounts(ctx)
err := telemetry.UpdateActivity(ctx, activity)
if err != nil {
log.Printf("error updating before activity: %v\n", err)
diff --git a/cmd/wsh/cmd/csscolormap.go b/cmd/wsh/cmd/csscolormap.go
new file mode 100644
index 000000000..f2b52485e
--- /dev/null
+++ b/cmd/wsh/cmd/csscolormap.go
@@ -0,0 +1,147 @@
+// Copyright 2024, Command Line Inc.
+// SPDX-License-Identifier: Apache-2.0
+
+package cmd
+
+var CssColorNames = map[string]bool{
+ "aliceblue": true,
+ "antiquewhite": true,
+ "aqua": true,
+ "aquamarine": true,
+ "azure": true,
+ "beige": true,
+ "bisque": true,
+ "black": true,
+ "blanchedalmond": true,
+ "blue": true,
+ "blueviolet": true,
+ "brown": true,
+ "burlywood": true,
+ "cadetblue": true,
+ "chartreuse": true,
+ "chocolate": true,
+ "coral": true,
+ "cornflowerblue": true,
+ "cornsilk": true,
+ "crimson": true,
+ "cyan": true,
+ "darkblue": true,
+ "darkcyan": true,
+ "darkgoldenrod": true,
+ "darkgray": true,
+ "darkgreen": true,
+ "darkkhaki": true,
+ "darkmagenta": true,
+ "darkolivegreen": true,
+ "darkorange": true,
+ "darkorchid": true,
+ "darkred": true,
+ "darksalmon": true,
+ "darkseagreen": true,
+ "darkslateblue": true,
+ "darkslategray": true,
+ "darkturquoise": true,
+ "darkviolet": true,
+ "deeppink": true,
+ "deepskyblue": true,
+ "dimgray": true,
+ "dodgerblue": true,
+ "firebrick": true,
+ "floralwhite": true,
+ "forestgreen": true,
+ "fuchsia": true,
+ "gainsboro": true,
+ "ghostwhite": true,
+ "gold": true,
+ "goldenrod": true,
+ "gray": true,
+ "green": true,
+ "greenyellow": true,
+ "honeydew": true,
+ "hotpink": true,
+ "indianred": true,
+ "indigo": true,
+ "ivory": true,
+ "khaki": true,
+ "lavender": true,
+ "lavenderblush": true,
+ "lawngreen": true,
+ "lemonchiffon": true,
+ "lightblue": true,
+ "lightcoral": true,
+ "lightcyan": true,
+ "lightgoldenrodyellow": true,
+ "lightgray": true,
+ "lightgreen": true,
+ "lightpink": true,
+ "lightsalmon": true,
+ "lightseagreen": true,
+ "lightskyblue": true,
+ "lightslategray": true,
+ "lightsteelblue": true,
+ "lightyellow": true,
+ "lime": true,
+ "limegreen": true,
+ "linen": true,
+ "magenta": true,
+ "maroon": true,
+ "mediumaquamarine": true,
+ "mediumblue": true,
+ "mediumorchid": true,
+ "mediumpurple": true,
+ "mediumseagreen": true,
+ "mediumslateblue": true,
+ "mediumspringgreen": true,
+ "mediumturquoise": true,
+ "mediumvioletred": true,
+ "midnightblue": true,
+ "mintcream": true,
+ "mistyrose": true,
+ "moccasin": true,
+ "navajowhite": true,
+ "navy": true,
+ "oldlace": true,
+ "olive": true,
+ "olivedrab": true,
+ "orange": true,
+ "orangered": true,
+ "orchid": true,
+ "palegoldenrod": true,
+ "palegreen": true,
+ "paleturquoise": true,
+ "palevioletred": true,
+ "papayawhip": true,
+ "peachpuff": true,
+ "peru": true,
+ "pink": true,
+ "plum": true,
+ "powderblue": true,
+ "purple": true,
+ "red": true,
+ "rosybrown": true,
+ "royalblue": true,
+ "saddlebrown": true,
+ "salmon": true,
+ "sandybrown": true,
+ "seagreen": true,
+ "seashell": true,
+ "sienna": true,
+ "silver": true,
+ "skyblue": true,
+ "slateblue": true,
+ "slategray": true,
+ "snow": true,
+ "springgreen": true,
+ "steelblue": true,
+ "tan": true,
+ "teal": true,
+ "thistle": true,
+ "tomato": true,
+ "turquoise": true,
+ "violet": true,
+ "wheat": true,
+ "white": true,
+ "whitesmoke": true,
+ "yellow": true,
+ "yellowgreen": true,
+}
diff --git a/cmd/wsh/cmd/wshcmd-setbg.go b/cmd/wsh/cmd/wshcmd-setbg.go
new file mode 100644
index 000000000..b40e2fcf8
--- /dev/null
+++ b/cmd/wsh/cmd/wshcmd-setbg.go
@@ -0,0 +1,186 @@
+// Copyright 2024, Command Line Inc.
+// SPDX-License-Identifier: Apache-2.0
+
+package cmd
+
+import (
+ "encoding/hex"
+ "encoding/json"
+ "fmt"
+ "os"
+ "path/filepath"
+ "strings"
+
+ "github.com/spf13/cobra"
+ "github.com/wavetermdev/waveterm/pkg/util/utilfn"
+ "github.com/wavetermdev/waveterm/pkg/wavebase"
+ "github.com/wavetermdev/waveterm/pkg/wshrpc"
+ "github.com/wavetermdev/waveterm/pkg/wshrpc/wshclient"
+)
+
+var setBgCmd = &cobra.Command{
+ Use: "setbg [--opacity value] [--tile|--center] [--scale value] (image-path|\"#color\"|color-name)",
+ Short: "set background image or color for a tab",
+ Long: `Set a background image or color for a tab. Colors can be specified as:
+ - A quoted hex value like "#ff0000" (quotes required to prevent # being interpreted as a shell comment)
+ - A CSS color name like "blue" or "forestgreen"
+Or provide a path to a supported image file (jpg, png, gif, webp, or svg).
+
+You can also:
+ - Use --clear to remove the background
+ - Use --opacity without other arguments to change just the opacity
+ - Use --center for centered images without scaling (good for logos)
+ - Use --scale with --center to control image size
+ - Use --print to see the metadata without applying it`,
+ RunE: setBgRun,
+ PreRunE: preRunSetupRpcClient,
+}
+
+var (
+ setBgOpacity float64
+ setBgTile bool
+ setBgCenter bool
+ setBgSize string
+ setBgClear bool
+ setBgPrint bool
+)
+
+func init() {
+ rootCmd.AddCommand(setBgCmd)
+ setBgCmd.Flags().Float64Var(&setBgOpacity, "opacity", 0.5, "background opacity (0.0-1.0)")
+ setBgCmd.Flags().BoolVar(&setBgTile, "tile", false, "tile the background image")
+ setBgCmd.Flags().BoolVar(&setBgCenter, "center", false, "center the image without scaling")
+ setBgCmd.Flags().StringVar(&setBgSize, "size", "auto", "size for centered images (px, %, or auto)")
+ setBgCmd.Flags().BoolVar(&setBgClear, "clear", false, "clear the background")
+ setBgCmd.Flags().BoolVar(&setBgPrint, "print", false, "print the metadata without applying it")
+
+ // Make tile and center mutually exclusive
+ setBgCmd.MarkFlagsMutuallyExclusive("tile", "center")
+}
+
+func validateHexColor(color string) error {
+ if !strings.HasPrefix(color, "#") {
+ return fmt.Errorf("color must start with #")
+ }
+ colorHex := color[1:]
+ if len(colorHex) != 6 && len(colorHex) != 8 {
+ return fmt.Errorf("color must be in #RRGGBB or #RRGGBBAA format")
+ }
+ _, err := hex.DecodeString(colorHex)
+ if err != nil {
+ return fmt.Errorf("invalid hex color: %v", err)
+ }
+ return nil
+}
+
+func setBgRun(cmd *cobra.Command, args []string) (rtnErr error) {
+ defer func() {
+ sendActivity("setbg", rtnErr == nil)
+ }()
+
+ // Create base metadata
+ meta := map[string]interface{}{}
+
+ // Handle opacity-only change or clear
+ if len(args) == 0 {
+ if !cmd.Flags().Changed("opacity") && !setBgClear {
+ OutputHelpMessage(cmd)
+ return fmt.Errorf("setbg requires an image path or color value")
+ }
+ if setBgOpacity < 0 || setBgOpacity > 1 {
+ return fmt.Errorf("opacity must be between 0.0 and 1.0")
+ }
+ if cmd.Flags().Changed("opacity") {
+ meta["bg:opacity"] = setBgOpacity
+ }
+ } else if len(args) > 1 {
+ OutputHelpMessage(cmd)
+ return fmt.Errorf("too many arguments")
+ } else {
+ // Handle background setting
+ meta["bg:*"] = true
+ if setBgOpacity < 0 || setBgOpacity > 1 {
+ return fmt.Errorf("opacity must be between 0.0 and 1.0")
+ }
+ meta["bg:opacity"] = setBgOpacity
+
+ input := args[0]
+ var bgStyle string
+
+ // Check for hex color
+ if strings.HasPrefix(input, "#") {
+ if err := validateHexColor(input); err != nil {
+ return err
+ }
+ bgStyle = input
+ } else if CssColorNames[strings.ToLower(input)] {
+ // Handle CSS color name
+ bgStyle = strings.ToLower(input)
+ } else {
+ // Handle image input
+ absPath, err := filepath.Abs(wavebase.ExpandHomeDirSafe(input))
+ if err != nil {
+ return fmt.Errorf("resolving image path: %v", err)
+ }
+
+ fileInfo, err := os.Stat(absPath)
+ if err != nil {
+ return fmt.Errorf("cannot access image file: %v", err)
+ }
+ if fileInfo.IsDir() {
+ return fmt.Errorf("path is a directory, not an image file")
+ }
+
+ mimeType := utilfn.DetectMimeType(absPath, fileInfo, true)
+ switch mimeType {
+ case "image/jpeg", "image/png", "image/gif", "image/webp", "image/svg+xml":
+ // Valid image type
+ default:
+ return fmt.Errorf("file does not appear to be a valid image (detected type: %s)", mimeType)
+ }
+
+ // Create URL-safe path
+ escapedPath := strings.ReplaceAll(absPath, "'", "\\'")
+ bgStyle = fmt.Sprintf("url('%s')", escapedPath)
+
+ switch {
+ case setBgTile:
+ bgStyle += " repeat"
+ case setBgCenter:
+ bgStyle += fmt.Sprintf(" no-repeat center/%s", setBgSize)
+ default:
+ bgStyle += " center/cover no-repeat"
+ }
+ }
+
+ meta["bg"] = bgStyle
+ }
+
+ if setBgPrint {
+ jsonBytes, err := json.MarshalIndent(meta, "", " ")
+ if err != nil {
+ return fmt.Errorf("error formatting metadata: %v", err)
+ }
+ WriteStdout(string(jsonBytes) + "\n")
+ return nil
+ }
+
+ // Resolve tab reference
+ oRef, err := resolveSimpleId("tab")
+ if err != nil {
+ return err
+ }
+
+ // Send RPC request
+ setMetaWshCmd := wshrpc.CommandSetMetaData{
+ ORef: *oRef,
+ Meta: meta,
+ }
+ err = wshclient.SetMetaCommand(RpcClient, setMetaWshCmd, &wshrpc.RpcOpts{Timeout: 2000})
+ if err != nil {
+ return fmt.Errorf("setting background: %v", err)
+ }
+
+ WriteStdout("background set\n")
+ return nil
+}
diff --git a/docs/docs/customization.mdx b/docs/docs/customization.mdx
index ad5f93603..ff3d30803 100644
--- a/docs/docs/customization.mdx
+++ b/docs/docs/customization.mdx
@@ -65,6 +65,41 @@ You can also suppress the help widgets in the bottom right by setting the config
+## Tab Backgrounds
+
+Wave supports powerful custom backgrounds for your tabs using images, patterns, gradients, and colors. The quickest way to set an image background is using the `wsh setbg` command:
+
+```bash
+# Set an image background with 50% opacity (default)
+wsh setbg ~/pictures/background.jpg
+
+# Set a color background (use quotes to prevent # being interpreted as a shell comment)
+wsh setbg "#ff0000" # hex color
+wsh setbg forestgreen # CSS color name
+
+# Adjust opacity
+wsh setbg --opacity 0.3 ~/pictures/light-pattern.png
+wsh setbg --opacity 0.7 # change only opacity of current background
+
+# Image positioning options
+wsh setbg --tile ~/pictures/texture.png # create tiled pattern
+wsh setbg --center ~/pictures/logo.png # center without scaling
+wsh setbg --center --size 200px ~/pictures/logo.png # center with specific size (px, %, auto)
+
+# Remove background
+wsh setbg --clear
+```
+
+You can use any JPEG, PNG, GIF, WebP, or SVG image as your background. The `--center` option is particularly useful for logos or icons where you want to maintain the original size.
+
+To preview the metadata for any background without applying it, use the `--print` flag:
+
+```bash
+wsh setbg --print "#ff0000"
+```
+
+For more advanced customization options including gradients, colors, and saving your own background presets, check out our [Background Configuration](/presets#background-configurations) documentation.
+
## Presets
For more advanced customization, to set up multiple AI models, and your own tab backgrounds, check out our [Presets Documentation](./presets).
diff --git a/docs/docs/presets.mdx b/docs/docs/presets.mdx
index 6b2dd5611..31b15115e 100644
--- a/docs/docs/presets.mdx
+++ b/docs/docs/presets.mdx
@@ -18,7 +18,7 @@ wsh editconfig presets.json
:::
-### File format
+## File format
Presets follow the following format:
@@ -61,7 +61,7 @@ A complete example of a preset for an AI model is the following:
}
```
-### Preset type
+## Preset Types
The type of the preset determines where it can be discovered in the app. Currently, the two types that will be discovered in the app are `bg` and `ai`.
@@ -90,7 +90,7 @@ Configs in a preset are applied in order to override the default config values,
:::
-#### AI configurations
+## AI Configurations
| Key Name | Type | Function |
| ------------- | ------ | -------------------------------------------------------------------------------------------------- |
@@ -106,15 +106,104 @@ Configs in a preset are applied in order to override the default config values,
| ai:maxtokens | int | max tokens to pass to API |
| ai:timeoutms | int | timeout (in milliseconds) for AI calls |
-#### Background configurations
+
-| Key Name | Type | Function |
-| -------------------- | ------ | ----------------------------------------------------------------------------------------------- |
-| bg:\* | bool | reset all existing bg keys |
-| bg:opacity | float | the opacity of the background |
-| bg:blendmode | string | the [blend mode](https://developer.mozilla.org/en-US/docs/Web/CSS/blend-mode) of the background |
-| bg:bordercolor | string | the color of the border |
-| bg:activebordercolor | string | the color of the border when a block is active |
+## Background Configurations
+
+Wave's background system harnesses the full power of CSS backgrounds, letting you create rich visual effects through the "background" attribute. You can apply solid colors, gradients (both linear and radial), images, and even blend multiple elements together. The system offers preset configurations while maintaining the flexibility of pure CSS, making it both powerful and easy to use.
+
+| Key Name | Type | Function |
+| -------------------- | ------ | ------------------------------------------------------------------------------------------------------- |
+| bg:\* | bool | reset all existing bg keys (recommended to prevent any existing background settings from carrying over) |
+| bg | string | CSS `background` attribute for the tab (supports colors, gradients images, etc.) |
+| bg:opacity | float | the opacity of the background (defaults to 0.5) |
+| bg:blendmode | string | the [blend mode](https://developer.mozilla.org/en-US/docs/Web/CSS/blend-mode) of the background |
+| bg:bordercolor | string | the color of the border when a block is not active (rarely used) |
+| bg:activebordercolor | string | the color of the border when a block is active |
+
+### Simple solid color with opacity:
+
+```json
+{
+ "bg@blue": {
+ "display:name": "Blue",
+ "bg:*": true,
+ "bg": "blue",
+ "bg:opacity": 0.3,
+ "bg:activebordercolor": "rgba(0, 0, 255, 1.0)"
+ }
+}
+```
+
+### Complex gradient combining multiple effects:
+
+```json
+{
+ "bg@duskhorizon": {
+ "display:name": "Dusk Horizon",
+ "bg:*": true,
+ "bg": "linear-gradient(0deg, rgba(128,0,0,1) 0%, rgba(204,85,0,0.7) 20%, rgba(255,140,0,0.6) 45%, rgba(160,90,160,0.5) 65%, rgba(60,60,120,1) 100%), radial-gradient(circle at 30% 30%, rgba(255,255,255,0.1), transparent 60%), radial-gradient(circle at 70% 70%, rgba(255,255,255,0.05), transparent 70%)",
+ "bg:opacity": 0.9,
+ "bg:blendmode": "overlay"
+ }
+}
+```
+
+### Repeating pattern background:
+
+```json
+{
+ "bg@pattern": {
+ "display:name": "Diamond Pattern",
+ "bg:*": true,
+ "bg": "url('/path/to/pattern.png') repeat",
+ "bg:opacity": 0.15
+ }
+}
+```
+
+### Full-cover background image:
+
+```json
+{
+ "bg@cover": {
+ "display:name": "Ocean Scene",
+ "bg:*": true,
+ "bg": "url('/path/to/ocean.jpg') center/cover no-repeat",
+ "bg:opacity": 0.2
+ }
+}
+```
+
+Replace image URLs with your own assets. All examples use reduced opacity to work well with dark themes.
+
+:::info
+Background images can be specified using URLs or local file paths. While URLs are supported, it's recommended to download and serve images locally for better reliability. For local files, you must use absolute paths or paths starting with `~` (e.g. `~/Downloads/background.png`). The system will automatically rewrite local paths to ensure proper access. We support all common web image formats: PNG, JPEG/JPG, WebP, GIF, and SVG.
+:::
+
+:::tip
+You can use `wsh setbg --print` to help generate the JSON for your background presets. For example:
+
+```bash
+# Preview the metadata for a gradient background
+ wsh setbg --print "#ff0000"
+{
+ "bg:*": true,
+ "bg": "#ff0000",
+ "bg:opacity": 0.5
+}
+
+# Preview a centered logo configuration
+wsh setbg --print --center --opacity 0.3 ~/logo.png
+{
+ "bg:*": true,
+ "bg": "url('/absolute/path/to/logo.png') no-repeat center/auto",
+ "bg:opacity": 0.3
+}
+```
+
+Copy the output and use it as a starting point for your preset configuration, just add the required `display:name` field!
+:::
#### Unset a default value
diff --git a/docs/docs/telemetry.mdx b/docs/docs/telemetry.mdx
index d9c0b8a87..6715ca01c 100644
--- a/docs/docs/telemetry.mdx
+++ b/docs/docs/telemetry.mdx
@@ -51,12 +51,15 @@ When telemetry is active, we collect the following data. It is stored in the `te
| NumTabs | The number of existing tabs open on a given day. |
| NewTab | The number of new tabs created on a given day |
| NumWindows | The number of existing windows open on a given day. |
+| NumWS | The number of existing workspaces on a given day. |
+| NumWSNamed | The number of named workspaces on a give day. |
| NewTab | The number of new tabs opened on a given day. |
| NumStartup | The number of times waveterm has been started on a given day. |
| NumShutdown | The number of times waveterm has been shut down on a given day. |
| SetTabTheme | The number of times the tab theme is changed from the context menu |
| NumMagnify | The number of times any block is magnified |
| NumPanics | The number of backend (golang) panics caught in the current day |
+| NumAIReqs | The number of AI requests made in the current day |
| NumSSHConn | The number of distinct SSH connections that have been made to distinct hosts |
| NumWSLConns | The number of distinct WSL connections that have been made to distinct distros |
| Renderers | The number of new block views of each type are open on a given day. |
diff --git a/docs/docs/wsh.mdx b/docs/docs/wsh.mdx
index a2f27abff..6766e78f7 100644
--- a/docs/docs/wsh.mdx
+++ b/docs/docs/wsh.mdx
@@ -145,6 +145,74 @@ wsh editconfig widgets.json
---
+## setbg
+
+The `setbg` command allows you to set a background image or color for the current tab with various customization options.
+
+```bash
+wsh setbg [--opacity value] [--tile|--center] [--size value] (image-path|"#color"|color-name)
+```
+
+You can set a background using:
+
+- An image file (displayed as cover, tiled, or centered)
+- A hex color (must be quoted like "#ff0000")
+- A CSS color name (like "blue" or "forestgreen")
+
+Flags:
+
+- `--opacity value` - set the background opacity (0.0-1.0, default 0.5)
+- `--tile` - tile the background image instead of using cover mode
+- `--center` - center the image without scaling (good for logos)
+- `--size` - size for centered images (px, %, or auto)
+- `--clear` - remove the background
+- `--print` - show the metadata without applying it
+
+Supported image formats: JPEG, PNG, GIF, WebP, and SVG.
+
+Examples:
+
+```bash
+# Set an image background with default settings
+wsh setbg ~/pictures/background.jpg
+
+# Set a background with custom opacity
+wsh setbg --opacity 0.3 ~/pictures/light-pattern.png
+
+# Set a tiled background
+wsh setbg --tile --opacity 0.2 ~/pictures/texture.png
+
+# Center an image (good for logos)
+wsh setbg --center ~/pictures/logo.png
+wsh setbg --center --size 200px ~/pictures/logo.png
+
+# Set color backgrounds
+wsh setbg "#ff0000" # hex color (requires quotes)
+wsh setbg forestgreen # CSS color name
+
+# Change just the opacity of current background
+wsh setbg --opacity 0.7
+
+# Remove background
+wsh setbg --clear
+
+# Preview the metadata
+wsh setbg --print "#ff0000"
+```
+
+The command validates that:
+
+- Color values are valid hex codes or CSS color names
+- Image paths point to accessible, supported image files
+- The opacity value is between 0.0 and 1.0
+- The center and tile options are not used together
+
+:::tip
+Use `--print` to preview the metadata for any background configuration without applying it. You can then copy this JSON representation to use as a [Background Preset](/presets#background-configurations)
+:::
+
+---
+
## run
The `run` command creates a new terminal command block and executes a specified command within it. The command can be provided either as arguments after `--` or using the `-c` flag. Unless the `-x` or `-X` flags are passed, commands can be re-executed by pressing `Enter` once the command has finished running.
diff --git a/emain/emain.ts b/emain/emain.ts
index 92ca38acb..9fedeb32d 100644
--- a/emain/emain.ts
+++ b/emain/emain.ts
@@ -410,7 +410,6 @@ electron.ipcMain.on("set-window-init-status", (event, status: "ready" | "wave-re
return;
}
if (status === "ready") {
- console.log("initResolve");
tabView.initResolve();
if (tabView.savedInitOpts) {
console.log("savedInitOpts");
@@ -419,7 +418,6 @@ electron.ipcMain.on("set-window-init-status", (event, status: "ready" | "wave-re
console.log("no-savedInitOpts");
}
} else if (status === "wave-ready") {
- console.log("waveReadyResolve");
tabView.waveReadyResolve();
}
});
diff --git a/frontend/app/block/blockframe.tsx b/frontend/app/block/blockframe.tsx
index 949108f0c..843ae7fe9 100644
--- a/frontend/app/block/blockframe.tsx
+++ b/frontend/app/block/blockframe.tsx
@@ -15,6 +15,8 @@ import { TypeAheadModal } from "@/app/modals/typeaheadmodal";
import { ContextMenuModel } from "@/app/store/contextmenu";
import {
atoms,
+ createBlock,
+ getApi,
getBlockComponentModel,
getConnStatusAtom,
getHostName,
@@ -182,6 +184,9 @@ const BlockFrame_Header = ({
const prevMagifiedState = React.useRef(magnified);
const manageConnection = util.useAtomValueSafe(viewModel?.manageConnection);
const dragHandleRef = preview ? null : nodeModel.dragHandleRef;
+ const connName = blockData?.meta?.connection;
+ const allSettings = jotai.useAtomValue(atoms.fullConfigAtom);
+ const wshEnabled = allSettings?.connections?.[connName]?.["conn:wshenabled"] ?? true;
React.useEffect(() => {
if (!magnified || preview || prevMagifiedState.current) {
@@ -239,6 +244,11 @@ const BlockFrame_Header = ({
);
}
+ const wshInstallButton: IconButtonDecl = {
+ elemtype: "iconbutton",
+ icon: "link-slash",
+ title: "wsh is not installed for this connection",
+ };
return (