diff --git a/src/app/(dashboard)/dashboard/cli-tools/components/OpenCodeToolCard.js b/src/app/(dashboard)/dashboard/cli-tools/components/OpenCodeToolCard.js index ca6ba00b..720a1db4 100644 --- a/src/app/(dashboard)/dashboard/cli-tools/components/OpenCodeToolCard.js +++ b/src/app/(dashboard)/dashboard/cli-tools/components/OpenCodeToolCard.js @@ -19,6 +19,8 @@ export default function OpenCodeToolCard({ tool, isExpanded, onToggle, baseUrl, const [modelAliases, setModelAliases] = useState({}); const [showManualConfigModal, setShowManualConfigModal] = useState(false); const [customBaseUrl, setCustomBaseUrl] = useState(""); + const [selectedModels, setSelectedModels] = useState([]); + const [activeModel, setActiveModel] = useState(""); useEffect(() => { if (apiKeys?.length > 0 && !selectedApiKey) { @@ -38,10 +40,13 @@ export default function OpenCodeToolCard({ tool, isExpanded, onToggle, baseUrl, if (isExpanded) fetchModelAliases(); }, [isExpanded]); - // Sync model and subagent model from existing config + // Sync models from existing config useEffect(() => { - if (status?.config?.model?.startsWith("9router/")) { - setSelectedModel(status.config.model.replace("9router/", "")); + if (status?.opencode?.models) { + setSelectedModels(status.opencode.models); + } + if (status?.opencode?.activeModel) { + setActiveModel(status.opencode.activeModel); } // Parse subagent settings from agent.explorer if exists @@ -104,8 +109,9 @@ export default function OpenCodeToolCard({ tool, isExpanded, onToggle, baseUrl, body: JSON.stringify({ baseUrl: getEffectiveBaseUrl(), apiKey: keyToUse, - model: selectedModel, - subagentModel: subagentModel || selectedModel + models: selectedModels, + activeModel: activeModel === "" ? "" : (activeModel || selectedModels[0]), + subagentModel: subagentModel }), }); const data = await res.json(); @@ -132,6 +138,8 @@ export default function OpenCodeToolCard({ tool, isExpanded, onToggle, baseUrl, setMessage({ type: "success", text: "Settings reset successfully!" }); setSelectedModel(""); setSubagentModel(""); + setSelectedModels([]); + setActiveModel(""); checkStatus(); } else { setMessage({ type: "error", text: data.error || "Failed to reset settings" }); @@ -148,7 +156,14 @@ export default function OpenCodeToolCard({ tool, isExpanded, onToggle, baseUrl, ? selectedApiKey : (!cloudEnabled ? "sk_9router" : ""); - const effectiveSubagentModel = subagentModel || selectedModel; + const modelsToShow = selectedModels.length > 0 ? selectedModels : ["provider/model-id"]; + const activeModelToShow = activeModel || selectedModels[0] || modelsToShow[0]; + const effectiveSubagentModel = subagentModel || activeModelToShow; + + const modelsObj = {}; + modelsToShow.forEach(m => { + modelsObj[m] = { name: m }; + }); return [{ filename: "~/.config/opencode/opencode.json", @@ -157,13 +172,10 @@ export default function OpenCodeToolCard({ tool, isExpanded, onToggle, baseUrl, "9router": { npm: "@ai-sdk/openai-compatible", options: { baseURL: getEffectiveBaseUrl(), apiKey: keyToUse }, - models: { - [selectedModel || "provider/model-id"]: { name: selectedModel || "provider/model-id" }, - [effectiveSubagentModel]: { name: effectiveSubagentModel } - }, + models: modelsObj, }, }, - model: `9router/${selectedModel || "provider/model-id"}`, + model: `9router/${activeModelToShow}`, agent: { explorer: { description: "Fast explorer subagent for codebase exploration", @@ -279,13 +291,84 @@ export default function OpenCodeToolCard({ tool, isExpanded, onToggle, baseUrl, )} - {/* Model */} -
- Model - arrow_forward - setSelectedModel(e.target.value)} placeholder="provider/model-id" className="flex-1 px-2 py-1.5 bg-surface rounded border border-border text-xs focus:outline-none focus:ring-1 focus:ring-primary/50" /> - - {selectedModel && } + {/* Models */} +
+ Models + arrow_forward +
+
+ {selectedModels.length === 0 ? ( + No models selected + ) : ( + selectedModels.map((model) => ( + { + if (model === activeModel) { + try { + const res = await fetch("/api/cli-tools/opencode-settings", { + method: "PATCH", + headers: { "Content-Type": "application/json" }, + body: JSON.stringify({ clearActiveModel: true }), + }); + if (res.ok) { + setActiveModel(""); + checkStatus(); + } + } catch (error) { + console.log("Error clearing active model:", error); + } + } else { + setActiveModel(model); + } + }} + className={`inline-flex items-center gap-1 px-2 py-0.5 rounded text-xs cursor-pointer transition-colors ${ + model === activeModel + ? "bg-primary/10 text-primary border border-primary" + : "bg-black/5 dark:bg-white/5 text-text-muted border border-transparent hover:border-border" + }`} + title={model === activeModel ? "Click to clear active model" : "Click to set as active"} + > + {model === activeModel && star} + {model} + + + )) + )} +
+
+ + + {selectedModels.length > 0 && activeModel ? ( + <>Active: {activeModel} + ) : selectedModels.length > 0 ? ( + Click a model to set/clear active + ) : ( + "Select models to add" + )} + +
+
{/* Subagent Model */} @@ -326,7 +409,7 @@ export default function OpenCodeToolCard({ tool, isExpanded, onToggle, baseUrl, )}
-