From ff85eec5ed504725013e61aefb3d6f6b68cc3967 Mon Sep 17 00:00:00 2001 From: Nelson Neto Date: Thu, 5 Feb 2026 10:07:40 -0300 Subject: [PATCH 1/3] feat: add Synthetic LLM provider support Add support for Synthetic as a first-class provider with models: - synthetic/hf:moonshotai/Kimi-K2.5 (coordinator/worker) - synthetic/hf:deepseek-ai/DeepSeek-V3.2 (coordinator) - synthetic/hf:MiniMaxAI/MiniMax-M2.1 (worker/lite) - synthetic/hf:Qwen/Qwen3-Coder-480B-A35B-Instruct (worker/lite) Includes test coverage and proper changeset. Refs: #148, #150 --- .changeset/add-synthetic-provider.md | 39 +++++++++++++ bun.lock | 24 +++----- packages/opencode-swarm-plugin/bin/swarm.ts | 55 +++++++++++++++++++ .../src/model-selection.test.ts | 39 +++++++++++++ 4 files changed, 142 insertions(+), 15 deletions(-) create mode 100644 .changeset/add-synthetic-provider.md diff --git a/.changeset/add-synthetic-provider.md b/.changeset/add-synthetic-provider.md new file mode 100644 index 0000000..1fb6641 --- /dev/null +++ b/.changeset/add-synthetic-provider.md @@ -0,0 +1,39 @@ +--- +"opencode-swarm-plugin": minor +--- + +## 🐝 Add Synthetic LLM Provider Support + +Adds support for **Synthetic** as a first-class LLM provider in swarm-tools. + +**New Models Available:** + +**Coordinator Models (Complex Tasks):** +- `synthetic/hf:moonshotai/Kimi-K2.5` - Strong reasoning model +- `synthetic/hf:deepseek-ai/DeepSeek-V3.2` - Advanced reasoning + +**Worker Models (Parallel Tasks):** +- `synthetic/hf:moonshotai/Kimi-K2.5` - Strong reasoning +- `synthetic/hf:MiniMaxAI/MiniMax-M2.1` - Fast and cost-effective +- `synthetic/hf:Qwen/Qwen3-Coder-480B-A35B-Instruct` - Powerful coding model + +**Lite Models (Docs, Tests, Simple Edits):** +- `synthetic/hf:MiniMaxAI/MiniMax-M2.1` - Fast and cost-effective +- `synthetic/hf:Qwen/Qwen3-Coder-480B-A35B-Instruct` - Powerful coding model + +**Why it matters:** +- Synthetic provides OpenAI-compatible API at `https://api.synthetic.new/openai/v1` +- Enables users already configured with Synthetic in OpenCode to use swarm-tools +- Cost-effective alternative for multi-agent workflows +- Qwen3-Coder specialized for coding tasks + +**Usage:** +```bash +swarm setup # Select Synthetic models during setup +``` + +**Requirements:** +- Synthetic API access configured in OpenCode +- No additional configuration needed in swarm-tools + +Refs: #148, #150 diff --git a/bun.lock b/bun.lock index 3805505..1a4086b 100644 --- a/bun.lock +++ b/bun.lock @@ -210,9 +210,11 @@ }, "peerDependencies": { "clawdbot": "*", + "openclaw": "*", }, "optionalPeers": [ "clawdbot", + "openclaw", ], }, }, @@ -530,7 +532,7 @@ "@inquirer/type": ["@inquirer/type@3.0.10", "", { "peerDependencies": { "@types/node": ">=18" }, "optionalPeers": ["@types/node"] }, "sha512-BvziSRxfz5Ov8ch0z/n3oijRSEcEsHnhggm4xFZe93DHcUCTlutlq9Ox4SVENAfcRD22UQq7T/atg9Wr3k09eA=="], - "@ioredis/commands": ["@ioredis/commands@1.4.0", "", {}, "sha512-aFT2yemJJo+TZCmieA7qnYGQooOS7QfNmYrzGtsYd3g9j5iDP8AimYYAesf79ohjbLG12XxC4nG5DyEnC88AsQ=="], + "@ioredis/commands": ["@ioredis/commands@1.5.0", "", {}, "sha512-eUgLqrMf8nJkZxT24JvVRrQya1vZkQh8BBeYNwGDqa5I0VUi8ACx7uFvAaLxintokpTenkK6DASvo/bvNbBGow=="], "@isaacs/balanced-match": ["@isaacs/balanced-match@4.0.1", "", {}, "sha512-yzMTt9lEb8Gv7zRioUilSglI0c0smZ9k5D65677DLWLtWJaXIS3CqcGyUFByYKlnUj6TkjLVs54fBl6+TiGQDQ=="], @@ -870,7 +872,7 @@ "@types/babel__traverse": ["@types/babel__traverse@7.28.0", "", { "dependencies": { "@babel/types": "^7.28.2" } }, "sha512-8PvcXf70gTDZBgt9ptxJ8elBeBjcLOAcOtoO/mPJjtji1+CdGbHgm77om1GrsPxsiE+uXIpNSK64UYaIwQXd4Q=="], - "@types/bun": ["@types/bun@1.3.6", "", { "dependencies": { "bun-types": "1.3.6" } }, "sha512-uWCv6FO/8LcpREhenN1d1b6fcspAB+cefwD7uti8C8VffIv0Um08TKMn98FynpTiU38+y2dUO55T11NgDt8VAA=="], + "@types/bun": ["@types/bun@1.3.8", "", { "dependencies": { "bun-types": "1.3.8" } }, "sha512-3LvWJ2q5GerAXYxO2mffLTqOzEu5qnhEAlh48Vnu8WQfnmSwbgagjGZV6BoHKJztENYEDn6QmVd949W4uESRJA=="], "@types/chai": ["@types/chai@5.2.3", "", { "dependencies": { "@types/deep-eql": "*", "assertion-error": "^2.0.1" } }, "sha512-Mw558oeA9fFbv65/y4mHtXDs9bPnFMZAL/jxdPFUpOHHIXX91mcgEHbS5Lahr+pwZFR8A7GQleRWeI6cGFC2UA=="], @@ -1580,7 +1582,7 @@ "internmap": ["internmap@2.0.3", "", {}, "sha512-5Hh7Y1wQbvY5ooGgPbDaL5iYLAPzMTUrjMulskHLH6wnv/A+1q5rgEaiuqEjB+oxGXIVZs1FF+R/KPN3ZSQYYg=="], - "ioredis": ["ioredis@5.8.2", "", { "dependencies": { "@ioredis/commands": "1.4.0", "cluster-key-slot": "^1.1.0", "debug": "^4.3.4", "denque": "^2.1.0", "lodash.defaults": "^4.2.0", "lodash.isarguments": "^3.1.0", "redis-errors": "^1.2.0", "redis-parser": "^3.0.0", "standard-as-callback": "^2.1.0" } }, "sha512-C6uC+kleiIMmjViJINWk80sOQw5lEzse1ZmvD+S/s8p8CWapftSaC+kocGTx6xrbrJ4WmYQGC08ffHLr6ToR6Q=="], + "ioredis": ["ioredis@5.9.2", "", { "dependencies": { "@ioredis/commands": "1.5.0", "cluster-key-slot": "^1.1.0", "debug": "^4.3.4", "denque": "^2.1.0", "lodash.defaults": "^4.2.0", "lodash.isarguments": "^3.1.0", "redis-errors": "^1.2.0", "redis-parser": "^3.0.0", "standard-as-callback": "^2.1.0" } }, "sha512-tAAg/72/VxOUW7RQSX1pIxJVucYKcjFjfvj60L57jrZpYCHC3XN0WCQ3sNYL4Gmvv+7GPvTAjc+KSdeNuE8oWQ=="], "ipaddr.js": ["ipaddr.js@2.3.0", "", {}, "sha512-Zv/pA+ciVFbCSBBjGfaKUya/CcGmUHzTydLMaTwrUUEM2DIEO3iZvueGxmacvmN50fGpGVKeTXpb2LcYQxeVdg=="], @@ -2528,7 +2530,7 @@ "@tailwindcss/vite/vite": ["vite@5.4.21", "", { "dependencies": { "esbuild": "^0.21.3", "postcss": "^8.4.43", "rollup": "^4.20.0" }, "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" }, "optionalPeers": ["@types/node", "less", "lightningcss", "sass", "sass-embedded", "stylus", "sugarss", "terser"], "bin": { "vite": "bin/vite.js" } }, "sha512-o5a9xKjbtuhY6Bi5S3+HvbRERmouabWbyUcpXXUA1u+GNUKoROi9byOJ8M0nHbHYHkYICiMlqxkg1KkYmm25Sw=="], - "@types/bun/bun-types": ["bun-types@1.3.6", "", { "dependencies": { "@types/node": "*" } }, "sha512-OlFwHcnNV99r//9v5IIOgQ9Uk37gZqrNMCcqEaExdkVq3Avwqok1bJFmvGMCkCE0FqzdY8VMOZpfpR3lwI+CsQ=="], + "@types/bun/bun-types": ["bun-types@1.3.8", "", { "dependencies": { "@types/node": "*" } }, "sha512-fL99nxdOWvV4LqjmC+8Q9kW3M4QTtTR1eePs94v5ctGqU8OeceWrSUaRw3JYb7tU3FkMIAjkueehrHPPPGKi5Q=="], "@typescript-eslint/eslint-plugin/ignore": ["ignore@7.0.5", "", {}, "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg=="], @@ -2542,8 +2544,6 @@ "ai-sdk-ollama/ai": ["ai@6.0.67", "", { "dependencies": { "@ai-sdk/gateway": "3.0.32", "@ai-sdk/provider": "3.0.7", "@ai-sdk/provider-utils": "4.0.13", "@opentelemetry/api": "1.9.0" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-xBnTcByHCj3OcG6V8G1s6zvSEqK0Bdiu+IEXYcpGrve1iGFFRgcrKeZtr/WAW/7gupnSvBbDF24BEv1OOfqi1g=="], - "bullmq/ioredis": ["ioredis@5.9.2", "", { "dependencies": { "@ioredis/commands": "1.5.0", "cluster-key-slot": "^1.1.0", "debug": "^4.3.4", "denque": "^2.1.0", "lodash.defaults": "^4.2.0", "lodash.isarguments": "^3.1.0", "redis-errors": "^1.2.0", "redis-parser": "^3.0.0", "standard-as-callback": "^2.1.0" } }, "sha512-tAAg/72/VxOUW7RQSX1pIxJVucYKcjFjfvj60L57jrZpYCHC3XN0WCQ3sNYL4Gmvv+7GPvTAjc+KSdeNuE8oWQ=="], - "chalk/ansi-styles": ["ansi-styles@4.3.0", "", { "dependencies": { "color-convert": "^2.0.1" } }, "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg=="], "cliui/wrap-ansi": ["wrap-ansi@7.0.0", "", { "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", "strip-ansi": "^6.0.0" } }, "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q=="], @@ -2596,9 +2596,7 @@ "next/postcss": ["postcss@8.4.31", "", { "dependencies": { "nanoid": "^3.3.6", "picocolors": "^1.0.0", "source-map-js": "^1.0.2" } }, "sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ=="], - "opencode-swarm-plugin/@types/bun": ["@types/bun@1.3.8", "", { "dependencies": { "bun-types": "1.3.8" } }, "sha512-3LvWJ2q5GerAXYxO2mffLTqOzEu5qnhEAlh48Vnu8WQfnmSwbgagjGZV6BoHKJztENYEDn6QmVd949W4uESRJA=="], - - "opencode-swarm-plugin/bun-types": ["bun-types@1.3.6", "", { "dependencies": { "@types/node": "*" } }, "sha512-OlFwHcnNV99r//9v5IIOgQ9Uk37gZqrNMCcqEaExdkVq3Avwqok1bJFmvGMCkCE0FqzdY8VMOZpfpR3lwI+CsQ=="], + "opencode-swarm-plugin/bun-types": ["bun-types@1.3.8", "", { "dependencies": { "@types/node": "*" } }, "sha512-fL99nxdOWvV4LqjmC+8Q9kW3M4QTtTR1eePs94v5ctGqU8OeceWrSUaRw3JYb7tU3FkMIAjkueehrHPPPGKi5Q=="], "opencode-swarm-plugin/evalite": ["evalite@0.19.0", "", { "dependencies": { "@ai-sdk/provider": "^2.0.0", "@fastify/static": "^8.2.0", "@fastify/websocket": "11.2.0", "@stricli/auto-complete": "^1.2.0", "@stricli/core": "^1.2.0", "@vitest/runner": "^4.0.0", "@vitest/utils": "^4.0.1", "better-sqlite3": "^11.6.0", "fastify": "^5.6.1", "file-type": "^19.6.0", "jiti": "^2.6.1", "table": "^6.9.0", "tinyrainbow": "^3.0.3" }, "bin": { "evalite": "dist/bin.js" } }, "sha512-tR9HJFJaqzzcjeqKklCRIWuGTK4g5VtOtKSC4cu5DfG3eDLfruRkz+tuSmYJjBVGp5vQe1M85/Hq0ALpeWx5sw=="], @@ -2634,13 +2632,13 @@ "swarm-mail/ai": ["ai@6.0.67", "", { "dependencies": { "@ai-sdk/gateway": "3.0.32", "@ai-sdk/provider": "3.0.7", "@ai-sdk/provider-utils": "4.0.13", "@opentelemetry/api": "1.9.0" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-xBnTcByHCj3OcG6V8G1s6zvSEqK0Bdiu+IEXYcpGrve1iGFFRgcrKeZtr/WAW/7gupnSvBbDF24BEv1OOfqi1g=="], - "swarm-mail/bun-types": ["bun-types@1.3.6", "", { "dependencies": { "@types/node": "*" } }, "sha512-OlFwHcnNV99r//9v5IIOgQ9Uk37gZqrNMCcqEaExdkVq3Avwqok1bJFmvGMCkCE0FqzdY8VMOZpfpR3lwI+CsQ=="], + "swarm-mail/bun-types": ["bun-types@1.3.8", "", { "dependencies": { "@types/node": "*" } }, "sha512-fL99nxdOWvV4LqjmC+8Q9kW3M4QTtTR1eePs94v5ctGqU8OeceWrSUaRw3JYb7tU3FkMIAjkueehrHPPPGKi5Q=="], "swarm-mail/vitest": ["vitest@2.1.9", "", { "dependencies": { "@vitest/expect": "2.1.9", "@vitest/mocker": "2.1.9", "@vitest/pretty-format": "^2.1.9", "@vitest/runner": "2.1.9", "@vitest/snapshot": "2.1.9", "@vitest/spy": "2.1.9", "@vitest/utils": "2.1.9", "chai": "^5.1.2", "debug": "^4.3.7", "expect-type": "^1.1.0", "magic-string": "^0.30.12", "pathe": "^1.1.2", "std-env": "^3.8.0", "tinybench": "^2.9.0", "tinyexec": "^0.3.1", "tinypool": "^1.0.1", "tinyrainbow": "^1.2.0", "vite": "^5.0.0", "vite-node": "2.1.9", "why-is-node-running": "^2.3.0" }, "peerDependencies": { "@edge-runtime/vm": "*", "@types/node": "^18.0.0 || >=20.0.0", "@vitest/browser": "2.1.9", "@vitest/ui": "2.1.9", "happy-dom": "*", "jsdom": "*" }, "optionalPeers": ["@edge-runtime/vm", "@types/node", "@vitest/browser", "@vitest/ui", "happy-dom", "jsdom"], "bin": { "vitest": "vitest.mjs" } }, "sha512-MSmPM9REYqDGBI8439mA4mWhV5sKmDlBKWIYbA3lRb2PTHACE0mgKwA8yQ2xq9vxDTuk4iPrECBAEW2aoFXY0Q=="], "swarm-mail/zod": ["zod@3.25.76", "", {}, "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ=="], - "swarm-queue/bun-types": ["bun-types@1.3.6", "", { "dependencies": { "@types/node": "*" } }, "sha512-OlFwHcnNV99r//9v5IIOgQ9Uk37gZqrNMCcqEaExdkVq3Avwqok1bJFmvGMCkCE0FqzdY8VMOZpfpR3lwI+CsQ=="], + "swarm-queue/bun-types": ["bun-types@1.3.8", "", { "dependencies": { "@types/node": "*" } }, "sha512-fL99nxdOWvV4LqjmC+8Q9kW3M4QTtTR1eePs94v5ctGqU8OeceWrSUaRw3JYb7tU3FkMIAjkueehrHPPPGKi5Q=="], "swarm-queue/zod": ["zod@3.25.76", "", {}, "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ=="], @@ -2718,8 +2716,6 @@ "ai-sdk-ollama/ai/@ai-sdk/gateway": ["@ai-sdk/gateway@3.0.32", "", { "dependencies": { "@ai-sdk/provider": "3.0.7", "@ai-sdk/provider-utils": "4.0.13", "@vercel/oidc": "3.1.0" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-7clZRr07P9rpur39t1RrbIe7x8jmwnwUWI8tZs+BvAfX3NFgdSVGGIaT7bTz2pb08jmLXzTSDbrOTqAQ7uBkBQ=="], - "bullmq/ioredis/@ioredis/commands": ["@ioredis/commands@1.5.0", "", {}, "sha512-eUgLqrMf8nJkZxT24JvVRrQya1vZkQh8BBeYNwGDqa5I0VUi8ACx7uFvAaLxintokpTenkK6DASvo/bvNbBGow=="], - "cliui/wrap-ansi/ansi-styles": ["ansi-styles@4.3.0", "", { "dependencies": { "color-convert": "^2.0.1" } }, "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg=="], "cytoscape-fcose/cose-base/layout-base": ["layout-base@2.0.1", "", {}, "sha512-dp3s92+uNI1hWIpPGH3jK2kxE2lMjdXdr+DH8ynZHpd6PUlH6x6cbuXnoMmiNumznqaNO31xu9e79F0uuZ0JFg=="], @@ -2788,8 +2784,6 @@ "next/postcss/nanoid": ["nanoid@3.3.11", "", { "bin": { "nanoid": "bin/nanoid.cjs" } }, "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w=="], - "opencode-swarm-plugin/@types/bun/bun-types": ["bun-types@1.3.8", "", { "dependencies": { "@types/node": "*" } }, "sha512-fL99nxdOWvV4LqjmC+8Q9kW3M4QTtTR1eePs94v5ctGqU8OeceWrSUaRw3JYb7tU3FkMIAjkueehrHPPPGKi5Q=="], - "opencode-swarm-plugin/evalite/@ai-sdk/provider": ["@ai-sdk/provider@2.0.0", "", { "dependencies": { "json-schema": "^0.4.0" } }, "sha512-6o7Y2SeO9vFKB8lArHXehNuusnpddKPk7xqL7T2/b+OvXMRIXUO1rR4wcv1hAFUAT9avGZshty3Wlua/XA7TvA=="], "opencode-swarm-plugin/vitest/@vitest/expect": ["@vitest/expect@3.2.4", "", { "dependencies": { "@types/chai": "^5.2.2", "@vitest/spy": "3.2.4", "@vitest/utils": "3.2.4", "chai": "^5.2.0", "tinyrainbow": "^2.0.0" } }, "sha512-Io0yyORnB6sikFlt8QW5K7slY4OjqNX9jmJQ02QDda8lyM6B5oNgVWoSoKPac8/kgnCUzuHQKrSLtu/uOqqrig=="], diff --git a/packages/opencode-swarm-plugin/bin/swarm.ts b/packages/opencode-swarm-plugin/bin/swarm.ts index 60e86c4..10dc942 100755 --- a/packages/opencode-swarm-plugin/bin/swarm.ts +++ b/packages/opencode-swarm-plugin/bin/swarm.ts @@ -339,6 +339,16 @@ const COORDINATOR_MODELS: ModelOption[] = [ label: "Gemini 1.5 Pro", hint: "More capable, larger context", }, + { + value: "synthetic/hf:moonshotai/Kimi-K2.5", + label: "Synthetic Kimi K2.5", + hint: "Strong reasoning model via Synthetic", + }, + { + value: "synthetic/hf:deepseek-ai/DeepSeek-V3.2", + label: "Synthetic DeepSeek V3.2", + hint: "Advanced reasoning via Synthetic", + }, ]; const WORKER_MODELS: ModelOption[] = [ @@ -362,6 +372,16 @@ const WORKER_MODELS: ModelOption[] = [ label: "Gemini 2.0 Flash", hint: "Fast and capable", }, + { + value: "synthetic/hf:moonshotai/Kimi-K2.5", + label: "Synthetic Kimi K2.5", + hint: "Strong reasoning via Synthetic", + }, + { + value: "synthetic/hf:MiniMaxAI/MiniMax-M2.1", + label: "Synthetic MiniMax M2.1", + hint: "Fast and cost-effective via Synthetic", + }, ]; // ============================================================================ @@ -2419,6 +2439,16 @@ async function setup(forceReinstall = false, nonInteractive = false) { label: "Gemini 1.5 Pro", hint: "More capable", }, + { + value: "synthetic/hf:moonshotai/Kimi-K2.5", + label: "Synthetic Kimi K2.5", + hint: "Strong reasoning model via Synthetic", + }, + { + value: "synthetic/hf:deepseek-ai/DeepSeek-V3.2", + label: "Synthetic DeepSeek V3.2", + hint: "Advanced reasoning via Synthetic", + }, ], initialValue: DEFAULT_COORDINATOR, }); @@ -2467,6 +2497,21 @@ async function setup(forceReinstall = false, nonInteractive = false) { label: "Gemini 1.5 Pro", hint: "More capable", }, + { + value: "synthetic/hf:moonshotai/Kimi-K2.5", + label: "Synthetic Kimi K2.5", + hint: "Strong reasoning via Synthetic", + }, + { + value: "synthetic/hf:MiniMaxAI/MiniMax-M2.1", + label: "Synthetic MiniMax M2.1", + hint: "Fast and cost-effective via Synthetic", + }, + { + value: "synthetic/hf:Qwen/Qwen3-Coder-480B-A35B-Instruct", + label: "Synthetic Qwen3 Coder 480B", + hint: "Powerful coding model via Synthetic", + }, ], initialValue: DEFAULT_WORKER, }); @@ -2501,6 +2546,16 @@ async function setup(forceReinstall = false, nonInteractive = false) { label: "Gemini 2.0 Flash", hint: "Fast and capable", }, + { + value: "synthetic/hf:MiniMaxAI/MiniMax-M2.1", + label: "Synthetic MiniMax M2.1", + hint: "Fast and cost-effective via Synthetic", + }, + { + value: "synthetic/hf:Qwen/Qwen3-Coder-480B-A35B-Instruct", + label: "Synthetic Qwen3 Coder 480B", + hint: "Powerful coding model via Synthetic", + }, ], initialValue: DEFAULT_LITE, }); diff --git a/packages/opencode-swarm-plugin/src/model-selection.test.ts b/packages/opencode-swarm-plugin/src/model-selection.test.ts index f2b291c..b8752bd 100644 --- a/packages/opencode-swarm-plugin/src/model-selection.test.ts +++ b/packages/opencode-swarm-plugin/src/model-selection.test.ts @@ -185,4 +185,43 @@ describe("selectWorkerModel", () => { const result = selectWorkerModel(subtask, mockConfig); expect(result).toBe("anthropic/claude-haiku-4-5"); }); + + test("uses Synthetic model when explicitly provided", () => { + const subtask: DecomposedSubtask & { model?: string } = { + title: "Complex reasoning task", + description: "Use advanced reasoning", + files: ["src/ai.ts"], + estimated_effort: "large", + model: "synthetic/hf:moonshotai/Kimi-K2.5", + }; + + const result = selectWorkerModel(subtask, mockConfig); + expect(result).toBe("synthetic/hf:moonshotai/Kimi-K2.5"); + }); + + test("synthetic DeepSeek model is selectable", () => { + const subtask: DecomposedSubtask & { model?: string } = { + title: "Deep reasoning task", + description: "Deep analysis required", + files: ["src/deep.ts"], + estimated_effort: "large", + model: "synthetic/hf:deepseek-ai/DeepSeek-V3.2", + }; + + const result = selectWorkerModel(subtask, mockConfig); + expect(result).toBe("synthetic/hf:deepseek-ai/DeepSeek-V3.2"); + }); + + test("synthetic MiniMax model is selectable for worker tasks", () => { + const subtask: DecomposedSubtask & { model?: string } = { + title: "Fast processing task", + description: "Process data quickly", + files: ["src/process.ts"], + estimated_effort: "small", + model: "synthetic/hf:MiniMaxAI/MiniMax-M2.1", + }; + + const result = selectWorkerModel(subtask, mockConfig); + expect(result).toBe("synthetic/hf:MiniMaxAI/MiniMax-M2.1"); + }); }); From 09b0001cb0bc2c797668279f7662dcfb09d77752 Mon Sep 17 00:00:00 2001 From: Nelson Neto Date: Thu, 5 Feb 2026 10:20:32 -0300 Subject: [PATCH 2/3] fix: add missing Qwen3-Coder to WORKER_MODELS constant Adds synthetic/hf:Qwen/Qwen3-Coder-480B-A35B-Instruct to WORKER_MODELS array to maintain consistency with interactive selection prompts. Refs: CodeRabbit feedback on PR #162 --- packages/opencode-swarm-plugin/bin/swarm.ts | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/packages/opencode-swarm-plugin/bin/swarm.ts b/packages/opencode-swarm-plugin/bin/swarm.ts index 10dc942..381e49b 100755 --- a/packages/opencode-swarm-plugin/bin/swarm.ts +++ b/packages/opencode-swarm-plugin/bin/swarm.ts @@ -382,6 +382,11 @@ const WORKER_MODELS: ModelOption[] = [ label: "Synthetic MiniMax M2.1", hint: "Fast and cost-effective via Synthetic", }, + { + value: "synthetic/hf:Qwen/Qwen3-Coder-480B-A35B-Instruct", + label: "Synthetic Qwen3 Coder 480B", + hint: "Powerful coding model via Synthetic", + }, ]; // ============================================================================ From 631936dab10e09fab7eeec423c05dbb5cc405ac8 Mon Sep 17 00:00:00 2001 From: Nelson Neto Date: Thu, 5 Feb 2026 10:28:30 -0300 Subject: [PATCH 3/3] docs: add JSDoc comments to model constants Add descriptive JSDoc comments to COORDINATOR_MODELS and WORKER_MODELS constants for better documentation and CodeRabbit coverage. Refs: CodeRabbit feedback on PR #162 --- packages/opencode-swarm-plugin/bin/swarm.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/packages/opencode-swarm-plugin/bin/swarm.ts b/packages/opencode-swarm-plugin/bin/swarm.ts index 381e49b..79e5425 100755 --- a/packages/opencode-swarm-plugin/bin/swarm.ts +++ b/packages/opencode-swarm-plugin/bin/swarm.ts @@ -313,6 +313,7 @@ interface ModelOption { hint: string; } +/** Available coordinator models for orchestration and planning tasks */ const COORDINATOR_MODELS: ModelOption[] = [ { value: "anthropic/claude-sonnet-4-5", @@ -351,6 +352,7 @@ const COORDINATOR_MODELS: ModelOption[] = [ }, ]; +/** Available worker models for parallel task execution */ const WORKER_MODELS: ModelOption[] = [ { value: "anthropic/claude-haiku-4-5",