claw-subagent-service 0.0.62 → 0.0.64
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json
CHANGED
|
@@ -153,11 +153,60 @@ function checkPort(port) {
|
|
|
153
153
|
});
|
|
154
154
|
}
|
|
155
155
|
|
|
156
|
+
/**
|
|
157
|
+
* 确保 openclaw.json 中启用了 chatCompletions 端点
|
|
158
|
+
* 在启动 gateway 前调用,避免 SSE 流式调用返回 404
|
|
159
|
+
*/
|
|
160
|
+
function ensureChatCompletionsConfig(log) {
|
|
161
|
+
const realHome = getRealHomeDir();
|
|
162
|
+
const openclawDir = path.join(realHome, '.openclaw');
|
|
163
|
+
const configPath = path.join(openclawDir, 'openclaw.json');
|
|
164
|
+
|
|
165
|
+
let settings = {};
|
|
166
|
+
let existed = false;
|
|
167
|
+
|
|
168
|
+
try {
|
|
169
|
+
if (fs.existsSync(configPath)) {
|
|
170
|
+
const content = fs.readFileSync(configPath, 'utf-8');
|
|
171
|
+
settings = JSON.parse(content);
|
|
172
|
+
existed = true;
|
|
173
|
+
}
|
|
174
|
+
} catch (err) {
|
|
175
|
+
log?.warn(`[OpenClawClient] 读取 openclaw.json 失败: ${err.message}`);
|
|
176
|
+
settings = {};
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
const current = settings.gateway?.http?.endpoints?.chatCompletions?.enabled;
|
|
180
|
+
if (current === true) {
|
|
181
|
+
log?.info('[OpenClawClient] openclaw.json 中 chatCompletions 已启用');
|
|
182
|
+
return;
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
if (!settings.gateway) settings.gateway = {};
|
|
186
|
+
if (!settings.gateway.http) settings.gateway.http = {};
|
|
187
|
+
if (!settings.gateway.http.endpoints) settings.gateway.http.endpoints = {};
|
|
188
|
+
if (!settings.gateway.http.endpoints.chatCompletions) settings.gateway.http.endpoints.chatCompletions = {};
|
|
189
|
+
settings.gateway.http.endpoints.chatCompletions.enabled = true;
|
|
190
|
+
|
|
191
|
+
try {
|
|
192
|
+
if (!fs.existsSync(openclawDir)) {
|
|
193
|
+
fs.mkdirSync(openclawDir, { recursive: true });
|
|
194
|
+
}
|
|
195
|
+
fs.writeFileSync(configPath, JSON.stringify(settings, null, 2), 'utf-8');
|
|
196
|
+
log?.info(`[OpenClawClient] 已自动在 openclaw.json 中启用 chatCompletions (${existed ? '更新' : '新建'})`);
|
|
197
|
+
} catch (err) {
|
|
198
|
+
log?.error(`[OpenClawClient] 写入 openclaw.json 失败: ${err.message}`);
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
|
|
156
202
|
/**
|
|
157
203
|
* 启动 OpenClaw gateway
|
|
158
204
|
*/
|
|
159
205
|
function startOpenClawGateway(log) {
|
|
160
206
|
return new Promise((resolve) => {
|
|
207
|
+
// 启动前自动修复配置
|
|
208
|
+
ensureChatCompletionsConfig(log);
|
|
209
|
+
|
|
161
210
|
log?.info('[OpenClawClient] 正在启动 OpenClaw gateway...');
|
|
162
211
|
|
|
163
212
|
const child = spawn('openclaw', ['gateway'], {
|
|
@@ -230,8 +279,7 @@ class OpenClawClient {
|
|
|
230
279
|
* 确保 OpenClaw gateway 在运行
|
|
231
280
|
*/
|
|
232
281
|
async ensureGatewayRunning() {
|
|
233
|
-
|
|
234
|
-
|
|
282
|
+
// 每次调用都实际检查端口,避免 gateway 崩溃后缓存状态失效
|
|
235
283
|
const gatewayRunning = await checkPort(18789);
|
|
236
284
|
|
|
237
285
|
if (gatewayRunning) {
|
|
@@ -240,6 +288,8 @@ class OpenClawClient {
|
|
|
240
288
|
return true;
|
|
241
289
|
}
|
|
242
290
|
|
|
291
|
+
this.gatewayStarted = false;
|
|
292
|
+
|
|
243
293
|
// 避免并发启动
|
|
244
294
|
if (this.gatewayStarting) {
|
|
245
295
|
this.log?.info('[OpenClawClient] gateway 正在启动中,等待...');
|
|
@@ -332,7 +382,14 @@ class OpenClawClient {
|
|
|
332
382
|
continue;
|
|
333
383
|
}
|
|
334
384
|
|
|
335
|
-
|
|
385
|
+
if (is404 && isLast) {
|
|
386
|
+
this.log?.error(`[OpenClawClient] 所有 SSE 端点均返回 404。OpenClaw chatCompletions 端点未启用。`);
|
|
387
|
+
this.log?.error(`[OpenClawClient] 请检查 ~/.openclaw/openclaw.json 中是否包含:`);
|
|
388
|
+
this.log?.error(`[OpenClawClient] gateway.http.endpoints.chatCompletions.enabled = true`);
|
|
389
|
+
this.log?.error(`[OpenClawClient] 修改后请重启 OpenClaw gateway: openclaw gateway`);
|
|
390
|
+
} else {
|
|
391
|
+
this.log?.error(`[OpenClawClient] SSE 请求失败: ${err.message}`);
|
|
392
|
+
}
|
|
336
393
|
// 不再内部调用 onError,让错误通过 Promise reject 向上传播,便于调用方回退
|
|
337
394
|
throw err;
|
|
338
395
|
}
|