Skip to content

Commit a6b9005

Browse files
committed
feat: add --meta support to wsh tab create
Allows callers to pre-populate tab metadata at creation time via --meta key=value (repeatable), addressing the meta payload capability requested in #3285. The new field is optional and additive; existing call sites continue to work unchanged.
1 parent fba9315 commit a6b9005

6 files changed

Lines changed: 52 additions & 4 deletions

File tree

cmd/wsh/cmd/wshcmd-tab.go

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ package cmd
66
import (
77
"fmt"
88
"os"
9+
"strings"
910

1011
"github.com/spf13/cobra"
1112
"github.com/wavetermdev/waveterm/pkg/wshrpc"
@@ -48,6 +49,7 @@ var (
4849
tabCreateFlagWorkspaceId string
4950
tabCreateFlagName string
5051
tabCreateFlagNoActivate bool
52+
tabCreateFlagMeta []string
5153
tabRenameFlagTabId string
5254
)
5355

@@ -60,6 +62,7 @@ func init() {
6062
tabCreateCmd.Flags().StringVarP(&tabCreateFlagWorkspaceId, "workspace", "w", "", "workspace id (defaults to the caller's workspace)")
6163
tabCreateCmd.Flags().StringVarP(&tabCreateFlagName, "name", "n", "", "tab name (defaults to next auto-generated name)")
6264
tabCreateCmd.Flags().BoolVar(&tabCreateFlagNoActivate, "no-activate", false, "do not switch focus to the newly created tab")
65+
tabCreateCmd.Flags().StringArrayVar(&tabCreateFlagMeta, "meta", nil, "metadata key=value pairs (repeatable)")
6366

6467
tabRenameCmd.Flags().StringVarP(&tabRenameFlagTabId, "tab", "t", "", "tab id to rename (defaults to WAVETERM_TABID)")
6568
}
@@ -69,10 +72,22 @@ func tabCreateRun(cmd *cobra.Command, args []string) (rtnErr error) {
6972
sendActivity("tab:create", rtnErr == nil)
7073
}()
7174

75+
var metaMap map[string]string
76+
if len(tabCreateFlagMeta) > 0 {
77+
metaMap = make(map[string]string, len(tabCreateFlagMeta))
78+
for _, kv := range tabCreateFlagMeta {
79+
idx := strings.IndexByte(kv, '=')
80+
if idx <= 0 {
81+
return fmt.Errorf("--meta value %q must be in key=value format with a non-empty key", kv)
82+
}
83+
metaMap[kv[:idx]] = kv[idx+1:]
84+
}
85+
}
7286
data := wshrpc.CommandCreateTabData{
7387
WorkspaceId: tabCreateFlagWorkspaceId,
7488
TabName: tabCreateFlagName,
7589
ActivateTab: !tabCreateFlagNoActivate,
90+
Meta: metaMap,
7691
}
7792
tabId, err := wshclient.CreateTabCommand(RpcClient, data, &wshrpc.RpcOpts{Timeout: 5000})
7893
if err != nil {

docs/docs/wsh-reference.mdx

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1132,7 +1132,7 @@ Manage tabs from the command line. Provides `create`, `rename`, and `focus` subc
11321132
Create a new tab in a workspace.
11331133
11341134
```sh
1135-
wsh tab create [-w <workspaceid>] [-n <name>] [--no-activate]
1135+
wsh tab create [-w <workspaceid>] [-n <name>] [--no-activate] [--meta key=value ...]
11361136
```
11371137
11381138
When `--workspace` is omitted, the tab is created in the workspace of the calling block. The new tab id is printed to stdout, making it easy to capture from scripts.
@@ -1142,6 +1142,7 @@ Flags:
11421142
- `-w, --workspace <id>` - target workspace id (defaults to the caller's workspace)
11431143
- `-n, --name <name>` - tab name (defaults to the next auto-generated name, e.g. `T3`)
11441144
- `--no-activate` - create the tab without switching focus to it
1145+
- `--meta key=value` - set a metadata key on the new tab; may be repeated for multiple keys
11451146
11461147
Examples:
11471148
@@ -1154,6 +1155,9 @@ tabid=$(wsh tab create --name "build-output")
11541155
11551156
# Create a background tab in a specific workspace
11561157
wsh tab create -w 9b1d... -n "logs" --no-activate
1158+
1159+
# Create a tab with custom metadata
1160+
wsh tab create --name "agent" --meta env=prod --meta owner=ci
11571161
```
11581162
11591163
---

frontend/types/gotypes.d.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -320,6 +320,7 @@ declare global {
320320
workspaceid?: string;
321321
tabname?: string;
322322
activatetab?: boolean;
323+
meta?: {[key: string]: string};
323324
};
324325

325326
// wshrpc.CommandDebugTermData

pkg/wshrpc/wshrpc_tab_test.go

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ func TestCommandCreateTabDataJSONTags(t *testing.T) {
6767
"WorkspaceId": "workspaceid,omitempty",
6868
"TabName": "tabname,omitempty",
6969
"ActivateTab": "activatetab,omitempty",
70+
"Meta": "meta,omitempty",
7071
}
7172
for fieldName, want := range expected {
7273
field, ok := rtype.FieldByName(fieldName)
@@ -79,3 +80,19 @@ func TestCommandCreateTabDataJSONTags(t *testing.T) {
7980
}
8081
}
8182
}
83+
84+
func TestCommandCreateTabDataMetaField(t *testing.T) {
85+
rtype := reflect.TypeOf(CommandCreateTabData{})
86+
field, ok := rtype.FieldByName("Meta")
87+
if !ok {
88+
t.Fatalf("Meta field not found on CommandCreateTabData")
89+
}
90+
expected := reflect.TypeOf(map[string]string{})
91+
if field.Type != expected {
92+
t.Fatalf("Meta field type = %v, want %v", field.Type, expected)
93+
}
94+
got := field.Tag.Get("json")
95+
if got != "meta,omitempty" {
96+
t.Fatalf("Meta json tag = %q, want %q", got, "meta,omitempty")
97+
}
98+
}

pkg/wshrpc/wshrpctypes.go

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -301,9 +301,10 @@ type CommandCreateSubBlockData struct {
301301
}
302302

303303
type CommandCreateTabData struct {
304-
WorkspaceId string `json:"workspaceid,omitempty"`
305-
TabName string `json:"tabname,omitempty"`
306-
ActivateTab bool `json:"activatetab,omitempty"`
304+
WorkspaceId string `json:"workspaceid,omitempty"`
305+
TabName string `json:"tabname,omitempty"`
306+
ActivateTab bool `json:"activatetab,omitempty"`
307+
Meta map[string]string `json:"meta,omitempty"`
307308
}
308309

309310
type CommandControllerResyncData struct {

pkg/wshrpc/wshserver/wshserver.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -215,6 +215,16 @@ func (ws *WshServer) CreateTabCommand(ctx context.Context, data wshrpc.CommandCr
215215
if err != nil {
216216
return "", fmt.Errorf("error creating tab: %w", err)
217217
}
218+
if len(data.Meta) > 0 {
219+
tabORef := waveobj.ORef{OType: waveobj.OType_Tab, OID: tabId}
220+
metaAny := make(waveobj.MetaMapType, len(data.Meta))
221+
for k, v := range data.Meta {
222+
metaAny[k] = v
223+
}
224+
if metaErr := wstore.UpdateObjectMeta(ctx, tabORef, metaAny, false); metaErr != nil {
225+
return "", fmt.Errorf("error setting tab meta: %w", metaErr)
226+
}
227+
}
218228
updates := waveobj.ContextGetUpdatesRtn(ctx)
219229
go func() {
220230
defer func() {

0 commit comments

Comments
 (0)