openclaw-linso 1.0.9 → 1.0.11
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/index.js +1 -1
- package/dist/src/monitor.js +62 -3
- package/package.json +1 -1
- package/src/monitor.ts +64 -3
package/dist/index.js
CHANGED
|
@@ -7,7 +7,7 @@ import { setLinsoRuntime } from "./src/runtime.js";
|
|
|
7
7
|
export { monitorLinsoProvider } from "./src/monitor.js";
|
|
8
8
|
export { linsoPlugin } from "./src/channel.js";
|
|
9
9
|
const plugin = {
|
|
10
|
-
id: "linso",
|
|
10
|
+
id: "openclaw-linso",
|
|
11
11
|
name: "Linso iOS Channel",
|
|
12
12
|
description: "Linso iOS App WebSocket 直连渠道,与飞书接入方式完全一致",
|
|
13
13
|
register(api) {
|
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);
|
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);
|