From eea480c41835414b27afa59f4146e0b7d348881d Mon Sep 17 00:00:00 2001 From: ashutoshhota Date: Wed, 22 Jul 2026 17:47:03 +0530 Subject: [PATCH 1/3] fix(qwen): forward role-specific model config on launch and restore --- backend/internal/adapters/agent/qwen/qwen.go | 26 ++++++++ .../internal/adapters/agent/qwen/qwen_test.go | 66 ++++++++++++++++++- 2 files changed, 89 insertions(+), 3 deletions(-) diff --git a/backend/internal/adapters/agent/qwen/qwen.go b/backend/internal/adapters/agent/qwen/qwen.go index 5e17767dcc..76c12450e3 100644 --- a/backend/internal/adapters/agent/qwen/qwen.go +++ b/backend/internal/adapters/agent/qwen/qwen.go @@ -52,6 +52,23 @@ func New() *Plugin { var _ adapters.Adapter = (*Plugin)(nil) var _ ports.Agent = (*Plugin)(nil) +// GetConfigSpec reports the per-project agent config keys Qwen Code +// understands. +func (p *Plugin) GetConfigSpec(ctx context.Context) (ports.ConfigSpec, error) { + if err := ctx.Err(); err != nil { + return ports.ConfigSpec{}, err + } + return ports.ConfigSpec{ + Fields: []ports.ConfigField{ + { + Key: "model", + Type: ports.ConfigFieldString, + Description: "Model override passed to `qwen --model`.", + }, + }, + }, nil +} + // Manifest returns the adapter's static self-description. func (p *Plugin) Manifest() adapters.Manifest { return adapters.Manifest{ @@ -79,6 +96,7 @@ func (p *Plugin) GetLaunchCommand(ctx context.Context, cfg ports.LaunchConfig) ( cmd = []string{binary} appendApprovalFlags(&cmd, cfg.Permissions) + appendModelFlag(&cmd, cfg.Config) systemPrompt, err := launchSystemPromptText(cfg) if err != nil { @@ -132,6 +150,7 @@ func (p *Plugin) GetRestoreCommand(ctx context.Context, cfg ports.RestoreConfig) cmd = make([]string, 0, 3) cmd = append(cmd, binary) appendApprovalFlags(&cmd, cfg.Permissions) + appendModelFlag(&cmd, cfg.Config) systemPrompt, err := restoreSystemPromptText(cfg) if err != nil { return nil, false, err @@ -229,6 +248,13 @@ func appendApprovalFlags(cmd *[]string, permissions ports.PermissionMode) { } } +// appendModelFlag appends --model if a non-empty model is configured. +func appendModelFlag(cmd *[]string, cfg ports.AgentConfig) { + if model := strings.TrimSpace(cfg.Model); model != "" { + *cmd = append(*cmd, "--model", model) + } +} + type qwenSubmitCommand struct { Type string `json:"type"` Text string `json:"text"` diff --git a/backend/internal/adapters/agent/qwen/qwen_test.go b/backend/internal/adapters/agent/qwen/qwen_test.go index 732e147b1c..0b5205ddfc 100644 --- a/backend/internal/adapters/agent/qwen/qwen_test.go +++ b/backend/internal/adapters/agent/qwen/qwen_test.go @@ -224,6 +224,59 @@ func TestGetLaunchCommandWorkerRequiresDataDirForRemoteInput(t *testing.T) { } } +func TestGetLaunchCommandAppendsConfiguredModel(t *testing.T) { + plugin := &Plugin{resolvedBinary: "qwen"} + + cmd, err := plugin.GetLaunchCommand(context.Background(), ports.LaunchConfig{ + Config: domain.AgentConfig{Model: "qwen-plus"}, + Permissions: ports.PermissionModeBypassPermissions, + Prompt: "fix it", + }) + if err != nil { + t.Fatal(err) + } + if !containsSubsequence(cmd, []string{"--model", "qwen-plus"}) { + t.Fatalf("command %#v missing --model qwen-plus", cmd) + } +} + +func TestGetLaunchCommandOmitsBlankConfiguredModel(t *testing.T) { + plugin := &Plugin{resolvedBinary: "qwen"} + + cmd, err := plugin.GetLaunchCommand(context.Background(), ports.LaunchConfig{ + Config: domain.AgentConfig{Model: " "}, + Permissions: ports.PermissionModeBypassPermissions, + Prompt: "fix it", + }) + if err != nil { + t.Fatal(err) + } + if contains(cmd, "--model") { + t.Fatalf("command %#v contains unexpected --model flag", cmd) + } +} + +func TestGetRestoreCommandAppendsConfiguredModel(t *testing.T) { + plugin := &Plugin{resolvedBinary: "qwen"} + + cmd, ok, err := plugin.GetRestoreCommand(context.Background(), ports.RestoreConfig{ + Config: domain.AgentConfig{Model: "qwen-max"}, + Permissions: ports.PermissionModeAuto, + Session: ports.SessionRef{ + Metadata: map[string]string{ports.MetadataKeyAgentSessionID: "sess-123"}, + }, + }) + if err != nil { + t.Fatal(err) + } + if !ok { + t.Fatal("ok = false, want true") + } + if !containsSubsequence(cmd, []string{"--model", "qwen-max"}) { + t.Fatalf("command %#v missing --model qwen-max", cmd) + } +} + func TestGetPromptDeliveryStrategy(t *testing.T) { plugin := &Plugin{} @@ -244,15 +297,22 @@ func TestGetPromptDeliveryStrategy(t *testing.T) { } } -func TestGetConfigSpecHasNoCustomFieldsYet(t *testing.T) { +func TestGetConfigSpecReportsModelField(t *testing.T) { plugin := &Plugin{} spec, err := plugin.GetConfigSpec(context.Background()) if err != nil { t.Fatal(err) } - if len(spec.Fields) != 0 { - t.Fatalf("unexpected config fields: %#v", spec.Fields) + if len(spec.Fields) != 1 { + t.Fatalf("want 1 config field, got %d: %#v", len(spec.Fields), spec.Fields) + } + f := spec.Fields[0] + if f.Key != "model" { + t.Fatalf("field key = %q, want %q", f.Key, "model") + } + if f.Type != ports.ConfigFieldString { + t.Fatalf("field type = %q, want %q", f.Type, ports.ConfigFieldString) } } From af9d5a666dd0c86b45c497a582199915fb00b61e Mon Sep 17 00:00:00 2001 From: ashutoshhota Date: Thu, 23 Jul 2026 19:41:49 +0530 Subject: [PATCH 2/3] fix(qwen): assert full ConfigField in GetConfigSpec test --- .../internal/adapters/agent/qwen/qwen_test.go | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/backend/internal/adapters/agent/qwen/qwen_test.go b/backend/internal/adapters/agent/qwen/qwen_test.go index 0b5205ddfc..45182f9ca9 100644 --- a/backend/internal/adapters/agent/qwen/qwen_test.go +++ b/backend/internal/adapters/agent/qwen/qwen_test.go @@ -304,15 +304,15 @@ func TestGetConfigSpecReportsModelField(t *testing.T) { if err != nil { t.Fatal(err) } - if len(spec.Fields) != 1 { - t.Fatalf("want 1 config field, got %d: %#v", len(spec.Fields), spec.Fields) - } - f := spec.Fields[0] - if f.Key != "model" { - t.Fatalf("field key = %q, want %q", f.Key, "model") + want := []ports.ConfigField{ + { + Key: "model", + Type: ports.ConfigFieldString, + Description: "Model override passed to `qwen --model`.", + }, } - if f.Type != ports.ConfigFieldString { - t.Fatalf("field type = %q, want %q", f.Type, ports.ConfigFieldString) + if !reflect.DeepEqual(spec.Fields, want) { + t.Fatalf("config fields\nwant: %#v\n got: %#v", want, spec.Fields) } } From 3cfd240b845dd461968839ca85e1ecba0b88ad07 Mon Sep 17 00:00:00 2001 From: Dhruv Sharma Date: Fri, 24 Jul 2026 16:59:30 +0530 Subject: [PATCH 3/3] test(qwen): cover trimmed model in worker launch --- .../internal/adapters/agent/qwen/qwen_test.go | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/backend/internal/adapters/agent/qwen/qwen_test.go b/backend/internal/adapters/agent/qwen/qwen_test.go index 45182f9ca9..04b718b64a 100644 --- a/backend/internal/adapters/agent/qwen/qwen_test.go +++ b/backend/internal/adapters/agent/qwen/qwen_test.go @@ -224,19 +224,28 @@ func TestGetLaunchCommandWorkerRequiresDataDirForRemoteInput(t *testing.T) { } } -func TestGetLaunchCommandAppendsConfiguredModel(t *testing.T) { +func TestGetLaunchCommandWorkerAppendsTrimmedConfiguredModel(t *testing.T) { plugin := &Plugin{resolvedBinary: "qwen"} cmd, err := plugin.GetLaunchCommand(context.Background(), ports.LaunchConfig{ - Config: domain.AgentConfig{Model: "qwen-plus"}, + Kind: domain.KindWorker, + DataDir: t.TempDir(), + SessionID: "sess-123", + Config: domain.AgentConfig{Model: " qwen-plus "}, Permissions: ports.PermissionModeBypassPermissions, Prompt: "fix it", }) if err != nil { t.Fatal(err) } - if !containsSubsequence(cmd, []string{"--model", "qwen-plus"}) { - t.Fatalf("command %#v missing --model qwen-plus", cmd) + if runtime.GOOS == "windows" { + if !containsSubsequence(cmd, []string{"--model", "qwen-plus"}) { + t.Fatalf("command %#v missing trimmed --model qwen-plus", cmd) + } + return + } + if len(cmd) != 3 || !strings.Contains(cmd[2], "'--model' 'qwen-plus'") { + t.Fatalf("worker command %#v missing trimmed --model qwen-plus", cmd) } }