fix: 修复 QQ Bot 配置后 Gateway 无法启动的问题
1. 清除旧版 "agent" 废弃键 — 保存 channel 配置时自动删除旧的 agent 键, 防止 OpenClaw 报 "agent.* was moved" 错误(前端 + 服务端双重防御) 2. Dashboard URL 动态端口探测 — 将硬编码 18789 改为扫描 18789-18799, 解决端口被占用时打不开 Dashboard 的问题 3. 安装脚本配置格式升级 — install.sh / install.ps1 / install-silent.ps1 生成的 openclaw.json 从旧的 "agent" 格式迁移到 "agents.defaults.model.primary" 4. 文档示例同步更新 — CLAUDE.md / cloud.html / guide.html 中的配置示例 影响文件: 14 个(portable/, install/, website/, u-claw-app/, usb-release/) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -87,7 +87,7 @@ Both portable and desktop versions auto-find a free port in range 18789–18799
|
||||
- **China mirrors**: All downloads use `npmmirror.com` — Node.js binaries from `npmmirror.com/mirrors/node`, npm packages from `registry.npmmirror.com`
|
||||
- **Environment variables**: `OPENCLAW_HOME`, `OPENCLAW_STATE_DIR`, `OPENCLAW_CONFIG_PATH` control where OpenClaw reads config
|
||||
- **macOS quarantine**: Mac scripts run `xattr -rd com.apple.quarantine` to remove Gatekeeper blocks
|
||||
- **Config format**: `{"gateway":{"mode":"local","auth":{"token":"uclaw"}},"agent":{"model":"...","apiKey":"..."}}`
|
||||
- **Config format**: `{"gateway":{"mode":"local","auth":{"token":"uclaw"}},"models":{"mode":"merge","providers":{"xxx":{...}}},"agents":{"defaults":{"model":{"primary":"provider/model"}}}}`
|
||||
- **Config hot-reload**: OpenClaw watches `openclaw.json` and applies changes without restart
|
||||
|
||||
## What NOT to Commit
|
||||
|
||||
@@ -520,31 +520,46 @@ if ($hasConfig) {
|
||||
|
||||
# Write config
|
||||
if ($cfg.provider -eq "custom" -and $cfg.baseUrl) {
|
||||
$providerName = "custom"
|
||||
$configJson = @"
|
||||
{
|
||||
"gateway": {
|
||||
"mode": "local",
|
||||
"auth": { "token": "uclaw" }
|
||||
},
|
||||
"agent": {
|
||||
"model": "$($cfg.model)",
|
||||
"apiKey": "$apiKey",
|
||||
"baseUrl": "$($cfg.baseUrl)"
|
||||
}
|
||||
"models": {
|
||||
"mode": "merge",
|
||||
"providers": {
|
||||
"$providerName": {
|
||||
"baseUrl": "$($cfg.baseUrl)",
|
||||
"apiKey": "$apiKey",
|
||||
"api": "openai-completions",
|
||||
"models": [{ "id": "$($cfg.model)" }]
|
||||
}
|
||||
}
|
||||
},
|
||||
"agents": { "defaults": { "model": { "primary": "$providerName/$($cfg.model)" } } }
|
||||
}
|
||||
"@
|
||||
} else {
|
||||
$providerName = $cfg.provider
|
||||
$configJson = @"
|
||||
{
|
||||
"gateway": {
|
||||
"mode": "local",
|
||||
"auth": { "token": "uclaw" }
|
||||
},
|
||||
"agent": {
|
||||
"model": "$($cfg.model)",
|
||||
"apiKey": "$apiKey",
|
||||
"provider": "$($cfg.provider)"
|
||||
}
|
||||
"models": {
|
||||
"mode": "merge",
|
||||
"providers": {
|
||||
"$providerName": {
|
||||
"apiKey": "$apiKey",
|
||||
"api": "$(if ($providerName -eq 'anthropic') {'anthropic'} else {'openai-completions'})",
|
||||
"models": [{ "id": "$($cfg.model)" }]
|
||||
}
|
||||
}
|
||||
},
|
||||
"agents": { "defaults": { "model": { "primary": "$providerName/$($cfg.model)" } } }
|
||||
}
|
||||
"@
|
||||
}
|
||||
|
||||
@@ -887,11 +887,18 @@ else
|
||||
"mode": "local",
|
||||
"auth": { "token": "uclaw" }
|
||||
},
|
||||
"agent": {
|
||||
"model": "$MODEL_NAME",
|
||||
"apiKey": "$API_KEY",
|
||||
"baseUrl": "$BASE_URL"
|
||||
}
|
||||
"models": {
|
||||
"mode": "merge",
|
||||
"providers": {
|
||||
"custom": {
|
||||
"baseUrl": "$BASE_URL",
|
||||
"apiKey": "$API_KEY",
|
||||
"api": "openai-completions",
|
||||
"models": [{ "id": "$MODEL_NAME" }]
|
||||
}
|
||||
}
|
||||
},
|
||||
"agents": { "defaults": { "model": { "primary": "custom/$MODEL_NAME" } } }
|
||||
}
|
||||
CFGEOF
|
||||
elif [ "$PROVIDER" = "anthropic" ]; then
|
||||
@@ -901,11 +908,17 @@ CFGEOF
|
||||
"mode": "local",
|
||||
"auth": { "token": "uclaw" }
|
||||
},
|
||||
"agent": {
|
||||
"model": "$MODEL_NAME",
|
||||
"apiKey": "$API_KEY",
|
||||
"provider": "anthropic"
|
||||
}
|
||||
"models": {
|
||||
"mode": "merge",
|
||||
"providers": {
|
||||
"anthropic": {
|
||||
"apiKey": "$API_KEY",
|
||||
"api": "anthropic",
|
||||
"models": [{ "id": "$MODEL_NAME" }]
|
||||
}
|
||||
}
|
||||
},
|
||||
"agents": { "defaults": { "model": { "primary": "anthropic/$MODEL_NAME" } } }
|
||||
}
|
||||
CFGEOF
|
||||
elif [ "$PROVIDER" = "openai" ]; then
|
||||
@@ -915,11 +928,17 @@ CFGEOF
|
||||
"mode": "local",
|
||||
"auth": { "token": "uclaw" }
|
||||
},
|
||||
"agent": {
|
||||
"model": "$MODEL_NAME",
|
||||
"apiKey": "$API_KEY",
|
||||
"provider": "openai"
|
||||
}
|
||||
"models": {
|
||||
"mode": "merge",
|
||||
"providers": {
|
||||
"openai": {
|
||||
"apiKey": "$API_KEY",
|
||||
"api": "openai-completions",
|
||||
"models": [{ "id": "$MODEL_NAME" }]
|
||||
}
|
||||
}
|
||||
},
|
||||
"agents": { "defaults": { "model": { "primary": "openai/$MODEL_NAME" } } }
|
||||
}
|
||||
CFGEOF
|
||||
fi
|
||||
|
||||
@@ -603,6 +603,8 @@ async function launchOpenClaw() {
|
||||
try {
|
||||
const res = await fetch('/api/config');
|
||||
const existing = res.ok ? await res.json() : {};
|
||||
// 清除旧版废弃键,防止 OpenClaw 报 "agent.* was moved" 错误
|
||||
delete existing.agent;
|
||||
existing.channels = Object.assign(existing.channels || {}, channels);
|
||||
await fetch('/api/config', {
|
||||
method: 'POST',
|
||||
|
||||
@@ -172,21 +172,38 @@ function switchOS(os) {
|
||||
document.querySelectorAll('.os-tab')[os === 'mac' ? 0 : 1].classList.add('active');
|
||||
}
|
||||
|
||||
// Check if gateway is running
|
||||
function checkStatus() {
|
||||
fetch('http://127.0.0.1:18789/', { mode: 'no-cors', cache: 'no-cache' })
|
||||
.then(() => {
|
||||
document.getElementById('statusDot').className = 'status-dot on';
|
||||
document.getElementById('statusText').textContent = 'OpenClaw 运行中';
|
||||
const link = document.getElementById('statusLink');
|
||||
link.style.display = 'inline';
|
||||
link.href = 'http://127.0.0.1:18789/#token=uclaw';
|
||||
})
|
||||
.catch(() => {
|
||||
document.getElementById('statusDot').className = 'status-dot off';
|
||||
document.getElementById('statusText').textContent = 'OpenClaw 未运行 — 请先双击启动脚本';
|
||||
document.getElementById('statusLink').style.display = 'none';
|
||||
});
|
||||
// Check if gateway is running (scan 18789-18799)
|
||||
var _gwPort = null;
|
||||
async function checkStatus() {
|
||||
var found = null;
|
||||
if (_gwPort) {
|
||||
// Fast path: check last known port first
|
||||
try {
|
||||
await fetch('http://127.0.0.1:' + _gwPort + '/', { mode: 'no-cors', cache: 'no-cache' });
|
||||
found = _gwPort;
|
||||
} catch(e) { _gwPort = null; }
|
||||
}
|
||||
if (!found) {
|
||||
for (var p = 18789; p <= 18799; p++) {
|
||||
try {
|
||||
await fetch('http://127.0.0.1:' + p + '/', { mode: 'no-cors', cache: 'no-cache' });
|
||||
found = p;
|
||||
_gwPort = p;
|
||||
break;
|
||||
} catch(e) {}
|
||||
}
|
||||
}
|
||||
if (found) {
|
||||
document.getElementById('statusDot').className = 'status-dot on';
|
||||
document.getElementById('statusText').textContent = 'OpenClaw 运行中 (端口 ' + found + ')';
|
||||
var link = document.getElementById('statusLink');
|
||||
link.style.display = 'inline';
|
||||
link.href = 'http://127.0.0.1:' + found + '/#token=uclaw';
|
||||
} else {
|
||||
document.getElementById('statusDot').className = 'status-dot off';
|
||||
document.getElementById('statusText').textContent = 'OpenClaw 未运行 — 请先双击启动脚本';
|
||||
document.getElementById('statusLink').style.display = 'none';
|
||||
}
|
||||
}
|
||||
checkStatus();
|
||||
setInterval(checkStatus, 5000);
|
||||
|
||||
@@ -642,6 +642,8 @@ async function saveChannelsAndOpen() {
|
||||
try {
|
||||
var res = await fetch('/api/config');
|
||||
var existing = res.ok ? await res.json() : {};
|
||||
// 清除旧版废弃键,防止 OpenClaw 报 "agent.* was moved" 错误
|
||||
delete existing.agent;
|
||||
existing.channels = Object.assign(existing.channels || {}, channels);
|
||||
await fetch('/api/config', {
|
||||
method: 'POST',
|
||||
@@ -652,7 +654,7 @@ async function saveChannelsAndOpen() {
|
||||
} catch(e) {}
|
||||
}
|
||||
|
||||
window.open('http://127.0.0.1:18789/#token=uclaw', '_blank');
|
||||
window.open(gatewayUrl(), '_blank');
|
||||
}
|
||||
|
||||
// --- View config ---
|
||||
@@ -677,15 +679,35 @@ function showToast(msg, isError) {
|
||||
setTimeout(function() { t.className = 'toast'; }, 3000);
|
||||
}
|
||||
|
||||
// --- Find active gateway port (18789-18799) ---
|
||||
var _gatewayPort = null;
|
||||
async function findGatewayPort() {
|
||||
for (var p = 18789; p <= 18799; p++) {
|
||||
try {
|
||||
await fetch('http://127.0.0.1:' + p + '/', { mode: 'no-cors' });
|
||||
_gatewayPort = p;
|
||||
return p;
|
||||
} catch(e) {}
|
||||
}
|
||||
_gatewayPort = null;
|
||||
return null;
|
||||
}
|
||||
|
||||
function gatewayUrl() {
|
||||
var p = _gatewayPort || 18789;
|
||||
return 'http://127.0.0.1:' + p + '/#token=uclaw';
|
||||
}
|
||||
|
||||
// --- Check gateway status ---
|
||||
async function checkGateway() {
|
||||
var dot = document.getElementById('statusDot');
|
||||
var text = document.getElementById('statusText');
|
||||
try {
|
||||
await fetch('http://127.0.0.1:18789/', { mode: 'no-cors' });
|
||||
var port = await findGatewayPort();
|
||||
if (port) {
|
||||
dot.className = 'dot on';
|
||||
text.innerHTML = 'Gateway 运行中 · <a href="http://127.0.0.1:18789/#token=uclaw" target="_blank">打开 Dashboard →</a>';
|
||||
} catch(e) {
|
||||
text.innerHTML = 'Gateway 运行中 (端口 ' + port + ') · <a href="' + gatewayUrl() + '" target="_blank">打开 Dashboard →</a>';
|
||||
document.getElementById('gatewayUrl').textContent = 'http://127.0.0.1:' + port;
|
||||
} else {
|
||||
dot.className = 'dot off';
|
||||
text.innerHTML = 'Gateway 未启动 · 请先运行 Windows-Start.bat 或 Mac-Start.command';
|
||||
}
|
||||
|
||||
@@ -398,6 +398,8 @@ const server = http.createServer((req, res) => {
|
||||
req.on('end', () => {
|
||||
try {
|
||||
const config = JSON.parse(body);
|
||||
// 清除旧版废弃键,防止 OpenClaw 报 "agent.* was moved" 错误
|
||||
delete config.agent;
|
||||
const dir = path.dirname(CONFIG_PATH);
|
||||
if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true });
|
||||
fs.writeFileSync(CONFIG_PATH, JSON.stringify(config, null, 2));
|
||||
|
||||
@@ -603,6 +603,8 @@ async function launchOpenClaw() {
|
||||
try {
|
||||
const res = await fetch('/api/config');
|
||||
const existing = res.ok ? await res.json() : {};
|
||||
// 清除旧版废弃键,防止 OpenClaw 报 "agent.* was moved" 错误
|
||||
delete existing.agent;
|
||||
existing.channels = Object.assign(existing.channels || {}, channels);
|
||||
await fetch('/api/config', {
|
||||
method: 'POST',
|
||||
|
||||
@@ -603,6 +603,8 @@ async function launchOpenClaw() {
|
||||
try {
|
||||
const res = await fetch('/api/config');
|
||||
const existing = res.ok ? await res.json() : {};
|
||||
// 清除旧版废弃键,防止 OpenClaw 报 "agent.* was moved" 错误
|
||||
delete existing.agent;
|
||||
existing.channels = Object.assign(existing.channels || {}, channels);
|
||||
await fetch('/api/config', {
|
||||
method: 'POST',
|
||||
|
||||
@@ -483,11 +483,13 @@
|
||||
</div>
|
||||
<pre><span class="c-comment">// 虾盘 U 盘已预装此配置,注册后填入 apiKey 即用</span>
|
||||
{
|
||||
<span class="c-key">"agent"</span>: {
|
||||
<span class="c-key">"model"</span>: <span class="c-str">"deepseek-chat"</span>,
|
||||
<span class="c-key">"apiKey"</span>: <span class="c-str">"sk-xp-your-key-here"</span>,
|
||||
<span class="c-key">"baseUrl"</span>: <span class="c-url">"https://api.u-claw.org/v1"</span>
|
||||
}
|
||||
<span class="c-key">"models"</span>: { <span class="c-key">"mode"</span>: <span class="c-str">"merge"</span>, <span class="c-key">"providers"</span>: {
|
||||
<span class="c-key">"uclaw"</span>: {
|
||||
<span class="c-key">"baseUrl"</span>: <span class="c-url">"https://api.u-claw.org/v1"</span>,
|
||||
<span class="c-key">"apiKey"</span>: <span class="c-str">"sk-xp-your-key-here"</span>
|
||||
}
|
||||
}},
|
||||
<span class="c-key">"agents"</span>: { <span class="c-key">"defaults"</span>: { <span class="c-key">"model"</span>: { <span class="c-key">"primary"</span>: <span class="c-str">"uclaw/deepseek-chat"</span> }}}
|
||||
}</pre>
|
||||
</div>
|
||||
</div>
|
||||
@@ -594,11 +596,13 @@
|
||||
</div>
|
||||
<pre><span class="c-comment">// 出厂预装,插上 U 盘即生效</span>
|
||||
{
|
||||
<span class="c-key">"agent"</span>: {
|
||||
<span class="c-key">"model"</span>: <span class="c-str">"deepseek-chat"</span>,
|
||||
<span class="c-key">"apiKey"</span>: <span class="c-str">"注册后填入你的 Key"</span>,
|
||||
<span class="c-key">"baseUrl"</span>: <span class="c-url">"https://api.u-claw.org/v1"</span>
|
||||
}
|
||||
<span class="c-key">"models"</span>: { <span class="c-key">"mode"</span>: <span class="c-str">"merge"</span>, <span class="c-key">"providers"</span>: {
|
||||
<span class="c-key">"uclaw"</span>: {
|
||||
<span class="c-key">"baseUrl"</span>: <span class="c-url">"https://api.u-claw.org/v1"</span>,
|
||||
<span class="c-key">"apiKey"</span>: <span class="c-str">"注册后填入你的 Key"</span>
|
||||
}
|
||||
}},
|
||||
<span class="c-key">"agents"</span>: { <span class="c-key">"defaults"</span>: { <span class="c-key">"model"</span>: { <span class="c-key">"primary"</span>: <span class="c-str">"uclaw/deepseek-chat"</span> }}}
|
||||
}</pre>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -592,11 +592,15 @@ cp -R portable/ /Volumes/你的U盘/U-Claw/</code></pre>
|
||||
<h2>配置文件格式</h2>
|
||||
<pre><code>{
|
||||
"gateway": {"mode": "local", "auth": {"token": "uclaw"}},
|
||||
"agent": {
|
||||
"model": "deepseek-chat",
|
||||
"apiKey": "sk-xxx",
|
||||
"baseUrl": "https://api.deepseek.com/v1"
|
||||
},
|
||||
"models": {"mode": "merge", "providers": {
|
||||
"deepseek": {
|
||||
"baseUrl": "https://api.deepseek.com/v1",
|
||||
"apiKey": "sk-xxx",
|
||||
"api": "openai-completions",
|
||||
"models": [{"id": "deepseek-chat"}]
|
||||
}
|
||||
}},
|
||||
"agents": {"defaults": {"model": {"primary": "deepseek/deepseek-chat"}}},
|
||||
"channels": {"qqbot": {"token": "appid:secret"}}
|
||||
}</code></pre>
|
||||
</div>
|
||||
|
||||
@@ -198,31 +198,46 @@ if ($SkipConfig) {
|
||||
}
|
||||
|
||||
if ($resolvedProvider -eq "custom" -and $resolvedBaseUrl) {
|
||||
$pName = "custom"
|
||||
$configJson = @"
|
||||
{
|
||||
"gateway": {
|
||||
"mode": "local",
|
||||
"auth": { "token": "uclaw" }
|
||||
},
|
||||
"agent": {
|
||||
"model": "$resolvedModel",
|
||||
"apiKey": "$ApiKey",
|
||||
"baseUrl": "$resolvedBaseUrl"
|
||||
}
|
||||
"models": {
|
||||
"mode": "merge",
|
||||
"providers": {
|
||||
"$pName": {
|
||||
"baseUrl": "$resolvedBaseUrl",
|
||||
"apiKey": "$ApiKey",
|
||||
"api": "openai-completions",
|
||||
"models": [{ "id": "$resolvedModel" }]
|
||||
}
|
||||
}
|
||||
},
|
||||
"agents": { "defaults": { "model": { "primary": "$pName/$resolvedModel" } } }
|
||||
}
|
||||
"@
|
||||
} else {
|
||||
$pName = $resolvedProvider
|
||||
$configJson = @"
|
||||
{
|
||||
"gateway": {
|
||||
"mode": "local",
|
||||
"auth": { "token": "uclaw" }
|
||||
},
|
||||
"agent": {
|
||||
"model": "$resolvedModel",
|
||||
"apiKey": "$ApiKey",
|
||||
"provider": "$resolvedProvider"
|
||||
}
|
||||
"models": {
|
||||
"mode": "merge",
|
||||
"providers": {
|
||||
"$pName": {
|
||||
"apiKey": "$ApiKey",
|
||||
"api": "$(if ($pName -eq 'anthropic') {'anthropic'} else {'openai-completions'})",
|
||||
"models": [{ "id": "$resolvedModel" }]
|
||||
}
|
||||
}
|
||||
},
|
||||
"agents": { "defaults": { "model": { "primary": "$pName/$resolvedModel" } } }
|
||||
}
|
||||
"@
|
||||
}
|
||||
|
||||
@@ -520,31 +520,46 @@ if ($hasConfig) {
|
||||
|
||||
# Write config
|
||||
if ($cfg.provider -eq "custom" -and $cfg.baseUrl) {
|
||||
$providerName = "custom"
|
||||
$configJson = @"
|
||||
{
|
||||
"gateway": {
|
||||
"mode": "local",
|
||||
"auth": { "token": "uclaw" }
|
||||
},
|
||||
"agent": {
|
||||
"model": "$($cfg.model)",
|
||||
"apiKey": "$apiKey",
|
||||
"baseUrl": "$($cfg.baseUrl)"
|
||||
}
|
||||
"models": {
|
||||
"mode": "merge",
|
||||
"providers": {
|
||||
"$providerName": {
|
||||
"baseUrl": "$($cfg.baseUrl)",
|
||||
"apiKey": "$apiKey",
|
||||
"api": "openai-completions",
|
||||
"models": [{ "id": "$($cfg.model)" }]
|
||||
}
|
||||
}
|
||||
},
|
||||
"agents": { "defaults": { "model": { "primary": "$providerName/$($cfg.model)" } } }
|
||||
}
|
||||
"@
|
||||
} else {
|
||||
$providerName = $cfg.provider
|
||||
$configJson = @"
|
||||
{
|
||||
"gateway": {
|
||||
"mode": "local",
|
||||
"auth": { "token": "uclaw" }
|
||||
},
|
||||
"agent": {
|
||||
"model": "$($cfg.model)",
|
||||
"apiKey": "$apiKey",
|
||||
"provider": "$($cfg.provider)"
|
||||
}
|
||||
"models": {
|
||||
"mode": "merge",
|
||||
"providers": {
|
||||
"$providerName": {
|
||||
"apiKey": "$apiKey",
|
||||
"api": "$(if ($providerName -eq 'anthropic') {'anthropic'} else {'openai-completions'})",
|
||||
"models": [{ "id": "$($cfg.model)" }]
|
||||
}
|
||||
}
|
||||
},
|
||||
"agents": { "defaults": { "model": { "primary": "$providerName/$($cfg.model)" } } }
|
||||
}
|
||||
"@
|
||||
}
|
||||
|
||||
@@ -887,11 +887,18 @@ else
|
||||
"mode": "local",
|
||||
"auth": { "token": "uclaw" }
|
||||
},
|
||||
"agent": {
|
||||
"model": "$MODEL_NAME",
|
||||
"apiKey": "$API_KEY",
|
||||
"baseUrl": "$BASE_URL"
|
||||
}
|
||||
"models": {
|
||||
"mode": "merge",
|
||||
"providers": {
|
||||
"custom": {
|
||||
"baseUrl": "$BASE_URL",
|
||||
"apiKey": "$API_KEY",
|
||||
"api": "openai-completions",
|
||||
"models": [{ "id": "$MODEL_NAME" }]
|
||||
}
|
||||
}
|
||||
},
|
||||
"agents": { "defaults": { "model": { "primary": "custom/$MODEL_NAME" } } }
|
||||
}
|
||||
CFGEOF
|
||||
elif [ "$PROVIDER" = "anthropic" ]; then
|
||||
@@ -901,11 +908,17 @@ CFGEOF
|
||||
"mode": "local",
|
||||
"auth": { "token": "uclaw" }
|
||||
},
|
||||
"agent": {
|
||||
"model": "$MODEL_NAME",
|
||||
"apiKey": "$API_KEY",
|
||||
"provider": "anthropic"
|
||||
}
|
||||
"models": {
|
||||
"mode": "merge",
|
||||
"providers": {
|
||||
"anthropic": {
|
||||
"apiKey": "$API_KEY",
|
||||
"api": "anthropic",
|
||||
"models": [{ "id": "$MODEL_NAME" }]
|
||||
}
|
||||
}
|
||||
},
|
||||
"agents": { "defaults": { "model": { "primary": "anthropic/$MODEL_NAME" } } }
|
||||
}
|
||||
CFGEOF
|
||||
elif [ "$PROVIDER" = "openai" ]; then
|
||||
@@ -915,11 +928,17 @@ CFGEOF
|
||||
"mode": "local",
|
||||
"auth": { "token": "uclaw" }
|
||||
},
|
||||
"agent": {
|
||||
"model": "$MODEL_NAME",
|
||||
"apiKey": "$API_KEY",
|
||||
"provider": "openai"
|
||||
}
|
||||
"models": {
|
||||
"mode": "merge",
|
||||
"providers": {
|
||||
"openai": {
|
||||
"apiKey": "$API_KEY",
|
||||
"api": "openai-completions",
|
||||
"models": [{ "id": "$MODEL_NAME" }]
|
||||
}
|
||||
}
|
||||
},
|
||||
"agents": { "defaults": { "model": { "primary": "openai/$MODEL_NAME" } } }
|
||||
}
|
||||
CFGEOF
|
||||
fi
|
||||
|
||||
Reference in New Issue
Block a user