mirror of
https://github.com/hansjone/dsh-im-ops.git
synced 2026-10-09 03:03:24 +08:00
Keep IM tool approvals in chat and add WhatsApp default model.
Claim in-flight IM turns before ownership flips active so approvals no longer stick only in DSH Web, auto-recover stale session models once, and let WhatsApp bots pick a shared default model for new sessions. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
parent
2723e94541
commit
74c58bdcde
21 changed files with 1388 additions and 395 deletions
105
plugin-src/client/default-model.js
Normal file
105
plugin-src/client/default-model.js
Normal file
|
|
@ -0,0 +1,105 @@
|
|||
import * as React from 'react';
|
||||
|
||||
import {
|
||||
defaultModelKey,
|
||||
normalizeDefaultModel,
|
||||
normalizeModelCatalog,
|
||||
} from '../../src/channels/shared/default-model.mjs';
|
||||
import { h } from './i18n.js';
|
||||
|
||||
export const SET_DEFAULT_MODEL_ENDPOINT = 'bot.model.set';
|
||||
|
||||
export const EMPTY_MODEL_CATALOG = Object.freeze({
|
||||
groups: Object.freeze([]),
|
||||
failures: Object.freeze([]),
|
||||
items: Object.freeze([]),
|
||||
});
|
||||
|
||||
export const ModelCatalogContext = React.createContext(EMPTY_MODEL_CATALOG);
|
||||
|
||||
export function normalizeDefaultModelSelection(value) {
|
||||
return normalizeDefaultModel(value);
|
||||
}
|
||||
|
||||
export function normalizeHostModelCatalog(value) {
|
||||
return normalizeModelCatalog(value);
|
||||
}
|
||||
|
||||
export function DefaultModelEditor({ defaultModel = null, disabled = false, onSave }) {
|
||||
const catalog = React.useContext(ModelCatalogContext) ?? EMPTY_MODEL_CATALOG;
|
||||
const helpId = React.useId();
|
||||
const current = normalizeDefaultModel(defaultModel);
|
||||
const currentKey = defaultModelKey(current);
|
||||
const [saving, setSaving] = React.useState(false);
|
||||
const [error, setError] = React.useState(null);
|
||||
|
||||
const items = [];
|
||||
const seen = new Set();
|
||||
for (const item of Array.isArray(catalog.items) ? catalog.items : []) {
|
||||
if (!item?.key || seen.has(item.key)) continue;
|
||||
seen.add(item.key);
|
||||
items.push(item);
|
||||
}
|
||||
const currentUnavailable = Boolean(currentKey && !seen.has(currentKey));
|
||||
if (currentUnavailable && current) {
|
||||
items.push({
|
||||
key: currentKey,
|
||||
provider: current.provider,
|
||||
model: current.model,
|
||||
label: currentKey,
|
||||
unavailable: true,
|
||||
});
|
||||
}
|
||||
|
||||
const change = async (event) => {
|
||||
const nextKey = event.target.value;
|
||||
if (nextKey === currentKey || saving || disabled) return;
|
||||
setSaving(true);
|
||||
setError(null);
|
||||
try {
|
||||
await onSave?.(nextKey ? normalizeDefaultModel(nextKey) : null);
|
||||
} catch (cause) {
|
||||
setError(cause?.message ?? '默认模型修改失败,请重试。');
|
||||
} finally {
|
||||
setSaving(false);
|
||||
}
|
||||
};
|
||||
|
||||
return h('div', { className: 'dim-preset' },
|
||||
h('div', { className: 'dim-presetHeader' },
|
||||
h('span', { className: 'dim-presetTitle' },
|
||||
h('span', null, '默认模型'),
|
||||
h('span', { className: 'dim-presetHelp' },
|
||||
h('button', {
|
||||
type: 'button',
|
||||
className: 'dim-presetHelpButton',
|
||||
'aria-label': '查看默认模型说明',
|
||||
'aria-describedby': helpId,
|
||||
}, h('span', { 'aria-hidden': 'true' }, '?')),
|
||||
h('span', {
|
||||
id: helpId,
|
||||
className: 'dim-presetTooltip',
|
||||
role: 'tooltip',
|
||||
}, '为该 WhatsApp 机器人的新建会话指定模型,避免每人各自 /model。已有会话需先 /new 再发消息才会生效。'))),
|
||||
saving ? h('span', { className: 'dim-presetStatus' }, '保存中…') : null),
|
||||
React.createElement('select', {
|
||||
className: 'dim-presetSelect',
|
||||
value: currentKey,
|
||||
disabled: disabled || saving,
|
||||
'aria-label': '默认模型',
|
||||
onChange: (event) => { void change(event); },
|
||||
},
|
||||
h('option', { value: '' }, '跟随 Host 默认'),
|
||||
...items.map((item) => h(
|
||||
'option',
|
||||
{ key: item.key, value: item.key },
|
||||
item.unavailable ? [item.key, '(已不可用)'] : item.label,
|
||||
)),
|
||||
),
|
||||
error || currentUnavailable ? h(
|
||||
'p',
|
||||
{ className: 'dim-presetError', role: error ? 'alert' : 'status' },
|
||||
error ?? '当前默认模型已不可用,请选择其他模型或跟随 Host 默认。',
|
||||
) : null,
|
||||
);
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue