This commit is contained in:
decolua
2026-04-06 17:32:44 +07:00
parent 7db4b9834e
commit 307be3b63d
18 changed files with 406 additions and 179 deletions
@@ -22,6 +22,8 @@ export default function OpenClawToolCard({
const [message, setMessage] = useState(null);
const [selectedApiKey, setSelectedApiKey] = useState("");
const [selectedModel, setSelectedModel] = useState("");
const [agentModels, setAgentModels] = useState({}); // { [agentId]: modelId }
const [agentModalFor, setAgentModalFor] = useState(null); // agentId opening modal
const [modalOpen, setModalOpen] = useState(false);
const [modelAliases, setModelAliases] = useState({});
const [showManualConfigModal, setShowManualConfigModal] = useState(false);
@@ -74,14 +76,18 @@ export default function OpenClawToolCard({
const provider = openclawStatus.settings?.models?.providers?.["9router"];
if (provider) {
const primaryModel = openclawStatus.settings?.agents?.defaults?.model?.primary;
if (primaryModel) {
const modelId = primaryModel.replace("9router/", "");
setSelectedModel(modelId);
}
if (primaryModel) setSelectedModel(primaryModel.replace("9router/", ""));
if (provider.apiKey && apiKeys?.some(k => k.key === provider.apiKey)) {
setSelectedApiKey(provider.apiKey);
}
}
// Init per-agent models from enriched agents list
const agentList = openclawStatus.agents || [];
const initAgentModels = {};
agentList.forEach((agent) => {
if (agent.currentModel) initAgentModels[agent.id] = agent.currentModel;
});
setAgentModels(initAgentModels);
}
}, [openclawStatus, apiKeys]);
@@ -131,7 +137,8 @@ export default function OpenClawToolCard({
body: JSON.stringify({
baseUrl: getEffectiveBaseUrl(),
apiKey: keyToUse,
model: selectedModel
model: selectedModel,
agentModels,
}),
});
const data = await res.json();
@@ -170,7 +177,12 @@ export default function OpenClawToolCard({
};
const handleModelSelect = (model) => {
setSelectedModel(model.value);
if (agentModalFor) {
setAgentModels(prev => ({ ...prev, [agentModalFor]: model.value }));
setAgentModalFor(null);
} else {
setSelectedModel(model.value);
}
setModalOpen(false);
};
@@ -298,14 +310,31 @@ export default function OpenClawToolCard({
)}
</div>
{/* Model */}
{/* Default Model */}
<div className="flex items-center gap-2">
<span className="w-32 shrink-0 text-sm font-semibold text-text-main text-right">Model</span>
<span className="w-32 shrink-0 text-sm font-semibold text-text-main text-right">Default Model</span>
<span className="material-symbols-outlined text-text-muted text-[14px]">arrow_forward</span>
<input type="text" value={selectedModel} onChange={(e) => 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" />
<button onClick={() => setModalOpen(true)} disabled={!hasActiveProviders} className={`px-2 py-1.5 rounded border text-xs transition-colors shrink-0 whitespace-nowrap ${hasActiveProviders ? "bg-surface border-border text-text-main hover:border-primary cursor-pointer" : "opacity-50 cursor-not-allowed border-border"}`}>Select Model</button>
<button onClick={() => { setAgentModalFor(null); setModalOpen(true); }} disabled={!hasActiveProviders} className={`px-2 py-1.5 rounded border text-xs transition-colors shrink-0 whitespace-nowrap ${hasActiveProviders ? "bg-surface border-border text-text-main hover:border-primary cursor-pointer" : "opacity-50 cursor-not-allowed border-border"}`}>Select</button>
{selectedModel && <button onClick={() => setSelectedModel("")} className="p-1 text-text-muted hover:text-red-500 rounded transition-colors" title="Clear"><span className="material-symbols-outlined text-[14px]">close</span></button>}
</div>
{/* Per-agent model overrides */}
{(openclawStatus.agents || []).filter(a => a.agentDir).map((agent) => (
<div key={agent.id} className="flex items-center gap-2 pl-4">
<span className="w-32 shrink-0 text-xs text-primary text-right truncate" title={agent.name || agent.id}>Agent {agent.name || agent.id}</span>
<span className="material-symbols-outlined text-text-muted text-[14px]">arrow_forward</span>
<input
type="text"
value={agentModels[agent.id] || ""}
onChange={(e) => setAgentModels(prev => ({ ...prev, [agent.id]: e.target.value }))}
placeholder={`default (${selectedModel || "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"
/>
<button onClick={() => { setAgentModalFor(agent.id); setModalOpen(true); }} disabled={!hasActiveProviders} className={`px-2 py-1.5 rounded border text-xs transition-colors shrink-0 whitespace-nowrap ${hasActiveProviders ? "bg-surface border-border text-text-main hover:border-primary cursor-pointer" : "opacity-50 cursor-not-allowed border-border"}`}>Select</button>
{agentModels[agent.id] && <button onClick={() => setAgentModels(prev => ({ ...prev, [agent.id]: "" }))} className="p-1 text-text-muted hover:text-red-500 rounded transition-colors" title="Clear"><span className="material-symbols-outlined text-[14px]">close</span></button>}
</div>
))}
</div>
{message && (