openclaw-linso 1.0.8 → 1.0.10
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/dist/src/monitor.js +67 -5
- package/package.json +1 -1
- package/src/monitor.ts +69 -5
package/dist/src/monitor.js
CHANGED
|
@@ -158,11 +158,13 @@ function handleSlashCommand(raw, deviceId, cfg) {
|
|
|
158
158
|
const name = args[0].toLowerCase();
|
|
159
159
|
if (name === "off" || name === "default" || name === "reset") {
|
|
160
160
|
deviceModelOverrides.delete(deviceId);
|
|
161
|
+
patchSessionModelInStore(deviceId, null, cfg);
|
|
161
162
|
return { kind: "sync", text: "✅ 已恢复默认模型" };
|
|
162
163
|
}
|
|
163
|
-
// 没有 /
|
|
164
|
-
const modelInput = args[0].includes("/") ? args[0] :
|
|
164
|
+
// 没有 / 时,从 cfg 里查找正确的 provider,找不到才用默认
|
|
165
|
+
const modelInput = args[0].includes("/") ? args[0] : resolveModelProvider(args[0], cfg);
|
|
165
166
|
deviceModelOverrides.set(deviceId, modelInput);
|
|
167
|
+
patchSessionModelInStore(deviceId, modelInput, cfg);
|
|
166
168
|
return { kind: "sync", text: `✅ 模型已切换为:${modelInput}` };
|
|
167
169
|
}
|
|
168
170
|
// ── 状态信息 ──────────────────────────────────────────────────────────────
|
|
@@ -391,8 +393,65 @@ async function handleIncomingMessage(deviceId, text, imageUrls, cfg, log) {
|
|
|
391
393
|
}
|
|
392
394
|
// ── 工具函数 ──────────────────────────────────────────────────────────────────
|
|
393
395
|
/**
|
|
394
|
-
*
|
|
396
|
+
* 从 cfg.models.providers 里查找 modelId 属于哪个 provider。
|
|
397
|
+
* 找到返回 "provider/modelId",找不到返回 "DEFAULT_MODEL_PROVIDER/modelId"。
|
|
395
398
|
*/
|
|
399
|
+
function resolveModelProvider(modelId, cfg) {
|
|
400
|
+
const providers = cfg?.models;
|
|
401
|
+
const providerMap = providers?.providers;
|
|
402
|
+
if (providerMap) {
|
|
403
|
+
for (const [providerName, providerCfg] of Object.entries(providerMap)) {
|
|
404
|
+
const models = providerCfg?.models ?? [];
|
|
405
|
+
if (models.some((m) => m.id === modelId)) {
|
|
406
|
+
return `${providerName}/${modelId}`;
|
|
407
|
+
}
|
|
408
|
+
}
|
|
409
|
+
}
|
|
410
|
+
return `${DEFAULT_MODEL_PROVIDER}/${modelId}`;
|
|
411
|
+
}
|
|
412
|
+
/**
|
|
413
|
+
* 直接把 modelOverride / providerOverride 写进 sessions.json,
|
|
414
|
+
* 这样下次 dispatchReplyFromConfig 读 session entry 时就能生效。
|
|
415
|
+
* (session entry 里的 modelOverride 优先级高于 cfg.agents.defaults.model)
|
|
416
|
+
*/
|
|
417
|
+
function patchSessionModelInStore(deviceId, modelOverride, cfg) {
|
|
418
|
+
try {
|
|
419
|
+
const core = getLinsoRuntime();
|
|
420
|
+
const peerId = getDevicePeerId(deviceId);
|
|
421
|
+
const route = core.channel.routing.resolveAgentRoute({
|
|
422
|
+
cfg,
|
|
423
|
+
channel: "linso",
|
|
424
|
+
accountId: "default",
|
|
425
|
+
peer: { kind: "direct", id: peerId },
|
|
426
|
+
});
|
|
427
|
+
const agentId = route.agentId ?? "main";
|
|
428
|
+
const sessionKey = route.sessionKey;
|
|
429
|
+
const store = loadSessionsStore(agentId);
|
|
430
|
+
const entry = store[sessionKey] ?? {};
|
|
431
|
+
if (!modelOverride) {
|
|
432
|
+
// 恢复默认:清除 override
|
|
433
|
+
delete entry.modelOverride;
|
|
434
|
+
delete entry.providerOverride;
|
|
435
|
+
}
|
|
436
|
+
else {
|
|
437
|
+
const slashIdx = modelOverride.indexOf("/");
|
|
438
|
+
if (slashIdx !== -1) {
|
|
439
|
+
entry.providerOverride = modelOverride.slice(0, slashIdx);
|
|
440
|
+
entry.modelOverride = modelOverride.slice(slashIdx + 1);
|
|
441
|
+
}
|
|
442
|
+
else {
|
|
443
|
+
entry.modelOverride = modelOverride;
|
|
444
|
+
delete entry.providerOverride;
|
|
445
|
+
}
|
|
446
|
+
}
|
|
447
|
+
store[sessionKey] = entry;
|
|
448
|
+
saveSessionsStore(agentId, store);
|
|
449
|
+
}
|
|
450
|
+
catch (e) {
|
|
451
|
+
// 非致命,不影响正常消息流
|
|
452
|
+
console.error("[Linso] patchSessionModelInStore failed:", e);
|
|
453
|
+
}
|
|
454
|
+
}
|
|
396
455
|
async function buildStatusCard(deviceId, cfg) {
|
|
397
456
|
const core = getLinsoRuntime();
|
|
398
457
|
const peerId = getDevicePeerId(deviceId);
|
|
@@ -495,13 +554,16 @@ void saveSessionsStore;
|
|
|
495
554
|
* agents.list 为空时,defaults 是唯一生效的模型配置。
|
|
496
555
|
*/
|
|
497
556
|
function patchAgentModel(cfg, _agentId, modelOverride) {
|
|
557
|
+
const defaults = (cfg.agents?.defaults ?? {});
|
|
558
|
+
const existingModels = (defaults.models ?? {});
|
|
498
559
|
return {
|
|
499
560
|
...cfg,
|
|
500
561
|
agents: {
|
|
501
562
|
...(cfg.agents ?? {}),
|
|
502
563
|
defaults: {
|
|
503
|
-
...
|
|
504
|
-
model: modelOverride,
|
|
564
|
+
...defaults,
|
|
565
|
+
model: { primary: modelOverride },
|
|
566
|
+
models: { ...existingModels, [modelOverride]: {} },
|
|
505
567
|
},
|
|
506
568
|
},
|
|
507
569
|
};
|
package/package.json
CHANGED
package/src/monitor.ts
CHANGED
|
@@ -204,11 +204,13 @@ function handleSlashCommand(raw: string, deviceId: string, cfg: OpenClawConfig):
|
|
|
204
204
|
const name = args[0].toLowerCase();
|
|
205
205
|
if (name === "off" || name === "default" || name === "reset") {
|
|
206
206
|
deviceModelOverrides.delete(deviceId);
|
|
207
|
+
patchSessionModelInStore(deviceId, null, cfg);
|
|
207
208
|
return { kind: "sync", text: "✅ 已恢复默认模型" };
|
|
208
209
|
}
|
|
209
|
-
// 没有 /
|
|
210
|
-
const modelInput = args[0].includes("/") ? args[0] :
|
|
210
|
+
// 没有 / 时,从 cfg 里查找正确的 provider,找不到才用默认
|
|
211
|
+
const modelInput = args[0].includes("/") ? args[0] : resolveModelProvider(args[0], cfg);
|
|
211
212
|
deviceModelOverrides.set(deviceId, modelInput);
|
|
213
|
+
patchSessionModelInStore(deviceId, modelInput, cfg);
|
|
212
214
|
return { kind: "sync", text: `✅ 模型已切换为:${modelInput}` };
|
|
213
215
|
}
|
|
214
216
|
|
|
@@ -466,8 +468,67 @@ async function handleIncomingMessage(
|
|
|
466
468
|
// ── 工具函数 ──────────────────────────────────────────────────────────────────
|
|
467
469
|
|
|
468
470
|
/**
|
|
469
|
-
*
|
|
471
|
+
* 从 cfg.models.providers 里查找 modelId 属于哪个 provider。
|
|
472
|
+
* 找到返回 "provider/modelId",找不到返回 "DEFAULT_MODEL_PROVIDER/modelId"。
|
|
470
473
|
*/
|
|
474
|
+
function resolveModelProvider(modelId: string, cfg: OpenClawConfig): string {
|
|
475
|
+
const providers = (cfg as unknown as Record<string, unknown>)?.models as Record<string, unknown>;
|
|
476
|
+
const providerMap = providers?.providers as Record<string, { models?: Array<{ id: string }> }> | undefined;
|
|
477
|
+
if (providerMap) {
|
|
478
|
+
for (const [providerName, providerCfg] of Object.entries(providerMap)) {
|
|
479
|
+
const models = providerCfg?.models ?? [];
|
|
480
|
+
if (models.some((m) => m.id === modelId)) {
|
|
481
|
+
return `${providerName}/${modelId}`;
|
|
482
|
+
}
|
|
483
|
+
}
|
|
484
|
+
}
|
|
485
|
+
return `${DEFAULT_MODEL_PROVIDER}/${modelId}`;
|
|
486
|
+
}
|
|
487
|
+
|
|
488
|
+
/**
|
|
489
|
+
* 直接把 modelOverride / providerOverride 写进 sessions.json,
|
|
490
|
+
* 这样下次 dispatchReplyFromConfig 读 session entry 时就能生效。
|
|
491
|
+
* (session entry 里的 modelOverride 优先级高于 cfg.agents.defaults.model)
|
|
492
|
+
*/
|
|
493
|
+
function patchSessionModelInStore(deviceId: string, modelOverride: string | null, cfg: OpenClawConfig): void {
|
|
494
|
+
try {
|
|
495
|
+
const core = getLinsoRuntime();
|
|
496
|
+
const peerId = getDevicePeerId(deviceId);
|
|
497
|
+
const route = core.channel.routing.resolveAgentRoute({
|
|
498
|
+
cfg,
|
|
499
|
+
channel: "linso",
|
|
500
|
+
accountId: "default",
|
|
501
|
+
peer: { kind: "direct", id: peerId },
|
|
502
|
+
});
|
|
503
|
+
const agentId = route.agentId ?? "main";
|
|
504
|
+
const sessionKey = route.sessionKey;
|
|
505
|
+
const store = loadSessionsStore(agentId);
|
|
506
|
+
const entry: Record<string, unknown> = (store[sessionKey] as Record<string, unknown>) ?? {};
|
|
507
|
+
|
|
508
|
+
if (!modelOverride) {
|
|
509
|
+
// 恢复默认:清除 override
|
|
510
|
+
delete entry.modelOverride;
|
|
511
|
+
delete entry.providerOverride;
|
|
512
|
+
} else {
|
|
513
|
+
const slashIdx = modelOverride.indexOf("/");
|
|
514
|
+
if (slashIdx !== -1) {
|
|
515
|
+
entry.providerOverride = modelOverride.slice(0, slashIdx);
|
|
516
|
+
entry.modelOverride = modelOverride.slice(slashIdx + 1);
|
|
517
|
+
} else {
|
|
518
|
+
entry.modelOverride = modelOverride;
|
|
519
|
+
delete entry.providerOverride;
|
|
520
|
+
}
|
|
521
|
+
}
|
|
522
|
+
|
|
523
|
+
store[sessionKey] = entry;
|
|
524
|
+
saveSessionsStore(agentId, store);
|
|
525
|
+
} catch (e) {
|
|
526
|
+
// 非致命,不影响正常消息流
|
|
527
|
+
console.error("[Linso] patchSessionModelInStore failed:", e);
|
|
528
|
+
}
|
|
529
|
+
}
|
|
530
|
+
|
|
531
|
+
|
|
471
532
|
async function buildStatusCard(deviceId: string, cfg: OpenClawConfig): Promise<string> {
|
|
472
533
|
const core = getLinsoRuntime();
|
|
473
534
|
const peerId = getDevicePeerId(deviceId);
|
|
@@ -582,13 +643,16 @@ void saveSessionsStore;
|
|
|
582
643
|
* agents.list 为空时,defaults 是唯一生效的模型配置。
|
|
583
644
|
*/
|
|
584
645
|
function patchAgentModel(cfg: OpenClawConfig, _agentId: string, modelOverride: string): OpenClawConfig {
|
|
646
|
+
const defaults = (cfg.agents?.defaults ?? {}) as Record<string, unknown>;
|
|
647
|
+
const existingModels = (defaults.models ?? {}) as Record<string, unknown>;
|
|
585
648
|
return {
|
|
586
649
|
...cfg,
|
|
587
650
|
agents: {
|
|
588
651
|
...(cfg.agents ?? {}),
|
|
589
652
|
defaults: {
|
|
590
|
-
...
|
|
591
|
-
model: modelOverride,
|
|
653
|
+
...defaults,
|
|
654
|
+
model: { primary: modelOverride },
|
|
655
|
+
models: { ...existingModels, [modelOverride]: {} },
|
|
592
656
|
},
|
|
593
657
|
},
|
|
594
658
|
} as unknown as OpenClawConfig;
|