dsh-bots 0.2.16 → 0.2.18
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/lib/client.js +58 -10
- package/package.json +1 -1
package/lib/client.js
CHANGED
|
@@ -284,6 +284,12 @@
|
|
|
284
284
|
.dbs-navBody{display:flex;flex-direction:column;min-height:0;flex:1}
|
|
285
285
|
.dbs-botsBody{overflow-y:auto;scrollbar-gutter:stable;padding-right:var(--dsh-sidebar-inline-padding,8px)}
|
|
286
286
|
.dbs-navBodyErr{padding:6px 12px;font-size:12px;line-height:20px;color:var(--dsw-alias-label-tertiary)}
|
|
287
|
+
.dbs-secHead{position:relative}
|
|
288
|
+
.dbs-secHead .dbs-rowActions{display:none}
|
|
289
|
+
.dbs-secHead:hover .dbs-rowActions,.dbs-secHead:focus-within .dbs-rowActions{display:inline-flex}
|
|
290
|
+
.dbs-secMenu{position:absolute;top:100%;right:0;z-index:40;min-width:148px;background:var(--dsw-alias-bg-layer-1);border:1px solid var(--dsw-alias-border-l2);border-radius:12px;padding:4px;box-shadow:0 12px 40px rgba(0,0,0,.22);animation:dbs-modal-in .14s ease-out}
|
|
291
|
+
.dbs-secMenuItem{display:flex;align-items:center;gap:8px;width:100%;padding:6px 10px;border-radius:8px;font-size:13px;line-height:18px;color:var(--dsw-alias-label-primary);cursor:pointer;background:none;border:none;text-align:left}
|
|
292
|
+
.dbs-secMenuItem:hover{background:var(--dsw-alias-interactive-bg-hover)}
|
|
287
293
|
.dbs-prow,.dbs-srow{cursor:pointer;user-select:none;color:var(--dsw-alias-label-primary);border-radius:8px;align-items:center;gap:6px;padding:0 8px;display:flex;box-sizing:border-box}
|
|
288
294
|
/* Native mirror (dsh-client-ui-sidebar/workspace): header-class rows outdent
|
|
289
295
|
their label 4px (pl:4 → x=16 from the window edge) while list rows keep
|
|
@@ -464,6 +470,7 @@
|
|
|
464
470
|
'chat.stop.noop': '当前没有进行中的生成',
|
|
465
471
|
'media.openFailed': '打开失败,文件可能已移动或被删除',
|
|
466
472
|
'chat.members.manage': '管理成员',
|
|
473
|
+
'chat.members.cap': '已达群成员上限 6 人(引擎限制)——请先移除一名成员再添加',
|
|
467
474
|
'chat.settings': '设置',
|
|
468
475
|
'chat.settings.title': '会话设置',
|
|
469
476
|
'chat.settings.name': '名称',
|
|
@@ -488,6 +495,8 @@
|
|
|
488
495
|
'list.loading': '加载中…',
|
|
489
496
|
'list.empty': '还没有 Bot,点 + 新建。',
|
|
490
497
|
'section.groups': '群聊',
|
|
498
|
+
'list.more': '更多操作',
|
|
499
|
+
'list.refresh': '刷新列表',
|
|
491
500
|
'section.singles': '单聊',
|
|
492
501
|
'chat.group': '群聊 · {n} 名成员',
|
|
493
502
|
'chat.single': '单聊',
|
|
@@ -576,6 +585,7 @@
|
|
|
576
585
|
'chat.stop.noop': 'No generation in progress',
|
|
577
586
|
'media.openFailed': 'Open failed — the file may have moved or been deleted',
|
|
578
587
|
'chat.members.manage': 'Manage members',
|
|
588
|
+
'chat.members.cap': 'Group cap is 6 members (engine limit) — remove one before adding',
|
|
579
589
|
'chat.settings': 'Settings',
|
|
580
590
|
'chat.settings.title': 'Session settings',
|
|
581
591
|
'chat.settings.name': 'Name',
|
|
@@ -600,6 +610,8 @@
|
|
|
600
610
|
'list.loading': 'Loading…',
|
|
601
611
|
'list.empty': 'No bots yet — use + to create one.',
|
|
602
612
|
'section.groups': 'Groups',
|
|
613
|
+
'list.more': 'More actions',
|
|
614
|
+
'list.refresh': 'Refresh list',
|
|
603
615
|
'section.singles': 'Direct',
|
|
604
616
|
'chat.group': 'Group · {n} members',
|
|
605
617
|
'chat.single': 'Direct',
|
|
@@ -789,6 +801,7 @@
|
|
|
789
801
|
/** Manage-members dialog: group agentId | null (system modal). */
|
|
790
802
|
manageMembers: null,
|
|
791
803
|
settingsAgentId: null,
|
|
804
|
+
sectionMenu: null,
|
|
792
805
|
/** Bumped on a language switch so module-scope `t` output re-renders. */
|
|
793
806
|
localeRev: 0,
|
|
794
807
|
};
|
|
@@ -1127,19 +1140,32 @@
|
|
|
1127
1140
|
* are: creating the first bot or group never requires a trip to the
|
|
1128
1141
|
* footer. `addAction` opens the same system-style modal as before.
|
|
1129
1142
|
*/
|
|
1130
|
-
function sectionRows(label, list, addAction) {
|
|
1143
|
+
function sectionRows(label, list, addAction, menuKind, menuItems) {
|
|
1144
|
+
const menuOpen = s.sectionMenu === menuKind;
|
|
1131
1145
|
return e('div', { key: label }, e('div', {
|
|
1132
|
-
className: 'dbs-navBodyErr',
|
|
1146
|
+
className: 'dbs-navBodyErr dbs-secHead',
|
|
1133
1147
|
// Native sectionHeader outdent: label at x=16 (12 sidebar
|
|
1134
1148
|
// padding + 4), aligned with the group headers. The previous
|
|
1135
1149
|
// 12px here pushed section labels 8px right of the native
|
|
1136
1150
|
// baseline, making both sections read horizontally off.
|
|
1137
1151
|
style: { padding: '4px 8px 2px 4px', display: 'flex', alignItems: 'center' },
|
|
1138
|
-
}, e('span', { style: { flex: 1 } }, label),
|
|
1152
|
+
}, e('span', { style: { flex: 1 } }, label),
|
|
1153
|
+
// Native workspace pattern: header actions appear on hover
|
|
1154
|
+
// (.dbs-rowActions is hover-gated in .dbs-secHead CSS).
|
|
1155
|
+
e('div', { className: 'dbs-rowActions', style: { alignItems: 'center', gap: 2 } }, e(Button, {
|
|
1139
1156
|
variant: 'ghost', size: 'sm', title: addAction.title, 'aria-label': addAction.title,
|
|
1140
1157
|
icon: Ico('IconPlusOutline16', { size: 14 }),
|
|
1141
1158
|
onClick: addAction.onClick,
|
|
1142
|
-
})
|
|
1159
|
+
}), e(Button, {
|
|
1160
|
+
variant: 'ghost', size: 'sm', title: t('list.more'), 'aria-label': t('list.more'),
|
|
1161
|
+
icon: Ico('IconEllipsisOutline16', { size: 14 }),
|
|
1162
|
+
onClick: () => patch({ sectionMenu: menuOpen ? null : menuKind }),
|
|
1163
|
+
})), menuOpen
|
|
1164
|
+
? e(React.Fragment, null, e('div', { style: { position: 'fixed', inset: 0, zIndex: 39 }, onClick: () => patch({ sectionMenu: null }) }), e('div', { className: 'dbs-secMenu', onClick: (ev) => { ev.stopPropagation(); } }, menuItems.map((item) => e('button', {
|
|
1165
|
+
key: item.label, className: 'dbs-secMenuItem', type: 'button',
|
|
1166
|
+
onClick: () => { patch({ sectionMenu: null }); item.onClick(); },
|
|
1167
|
+
}, item.label))))
|
|
1168
|
+
: null), list.map(row));
|
|
1143
1169
|
}
|
|
1144
1170
|
// No footer: the gateway status moved to the Bots group-header dot's
|
|
1145
1171
|
// hover tooltip (0.2.8) — see SidebarNav's StateDot `title`.
|
|
@@ -1153,12 +1179,18 @@
|
|
|
1153
1179
|
? sectionRows(t('section.groups'), groups, {
|
|
1154
1180
|
title: t('group.new'),
|
|
1155
1181
|
onClick: () => patch({ create: 'group', createName: '', createMembers: {}, createWorking: false, error: null }),
|
|
1156
|
-
}
|
|
1182
|
+
}, 'groups', [
|
|
1183
|
+
{ label: t('group.new'), onClick: () => patch({ create: 'group', createName: '', createMembers: {}, createWorking: false, error: null }) },
|
|
1184
|
+
{ label: t('list.refresh'), onClick: () => { void refreshAgents(); } },
|
|
1185
|
+
])
|
|
1157
1186
|
: null, s.agentsLoaded
|
|
1158
1187
|
? sectionRows(t('section.singles'), singles, {
|
|
1159
1188
|
title: t('bot.new'),
|
|
1160
1189
|
onClick: () => patch({ create: 'bot', createName: '', createDesc: '', createWorking: false, error: null }),
|
|
1161
|
-
}
|
|
1190
|
+
}, 'singles', [
|
|
1191
|
+
{ label: t('bot.new'), onClick: () => patch({ create: 'bot', createName: '', createDesc: '', createWorking: false, error: null }) },
|
|
1192
|
+
{ label: t('list.refresh'), onClick: () => { void refreshAgents(); } },
|
|
1193
|
+
])
|
|
1162
1194
|
: null);
|
|
1163
1195
|
}
|
|
1164
1196
|
// =========================================================
|
|
@@ -2149,8 +2181,24 @@
|
|
|
2149
2181
|
return null;
|
|
2150
2182
|
const singles = s.agents.filter((a) => !a.isGroup && a.isHiddenFromSidebar !== true);
|
|
2151
2183
|
const pickedIds = picked === null ? [] : Object.keys(picked).filter((k) => picked[k]);
|
|
2184
|
+
// Engine hard cap (sdk-bots agents.ts GROUP_MAX_MEMBERS = 6): the glue
|
|
2185
|
+
// slice(0, 6)-truncates the roster SILENTLY — an over-cap save writes
|
|
2186
|
+
// successfully and just drops whoever ranked past 6. Surface it here
|
|
2187
|
+
// instead of letting a save pretend to work.
|
|
2188
|
+
const MEMBER_CAP = 6;
|
|
2189
|
+
const overCap = pickedIds.length > MEMBER_CAP;
|
|
2190
|
+
function toggle(id) {
|
|
2191
|
+
if (picked === null)
|
|
2192
|
+
return;
|
|
2193
|
+
if (picked[id] !== true && pickedIds.length >= MEMBER_CAP) {
|
|
2194
|
+
setErr(t('chat.members.cap'));
|
|
2195
|
+
return;
|
|
2196
|
+
}
|
|
2197
|
+
setErr(null);
|
|
2198
|
+
setPicked({ ...picked, [id]: !picked[id] });
|
|
2199
|
+
}
|
|
2152
2200
|
async function submit() {
|
|
2153
|
-
if (working || picked === null)
|
|
2201
|
+
if (working || picked === null || overCap)
|
|
2154
2202
|
return;
|
|
2155
2203
|
setWorking(true);
|
|
2156
2204
|
setErr(null);
|
|
@@ -2186,16 +2234,16 @@
|
|
|
2186
2234
|
key: m.id,
|
|
2187
2235
|
className: 'dbs-member' + (picked[m.id] ? ' checked' : ''),
|
|
2188
2236
|
style: { cursor: 'pointer', padding: '4px 6px', borderRadius: 8 },
|
|
2189
|
-
onClick: () =>
|
|
2237
|
+
onClick: () => toggle(m.id),
|
|
2190
2238
|
}, e('input', { type: 'checkbox', checked: Boolean(picked[m.id]), readOnly: true }), e(Avatar, { agent: m, size: 18 }), e('span', { className: 'dbs-title' }, m.name))), singles.length > 0
|
|
2191
|
-
? e('div', { className: 'dbs-meta', style: { padding: '6px 6px 0' } }, t('chat.group', { n: pickedIds.length }))
|
|
2239
|
+
? e('div', { className: 'dbs-meta', style: { padding: '6px 6px 0' } }, t('chat.group', { n: pickedIds.length }) + ' / ' + String(MEMBER_CAP))
|
|
2192
2240
|
: null), err !== null
|
|
2193
2241
|
? e('div', { className: 'dbs-error', onClick: () => { setErr(null); } }, err)
|
|
2194
2242
|
: null), e('div', { className: 'dbs-modalFooter' }, e(Button, {
|
|
2195
2243
|
variant: 'ghost', size: 'sm', disabled: working,
|
|
2196
2244
|
onClick: () => patch({ manageMembers: null }),
|
|
2197
2245
|
}, t('action.cancel')), e(Button, {
|
|
2198
|
-
variant: 'primary', size: 'sm', disabled: picked === null || working,
|
|
2246
|
+
variant: 'primary', size: 'sm', disabled: picked === null || working || overCap,
|
|
2199
2247
|
onClick: () => void submit(),
|
|
2200
2248
|
}, working ? t('action.saving') : t('action.save')))));
|
|
2201
2249
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dsh-bots",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.18",
|
|
4
4
|
"description": "Multi-bot workbench for DeepSeek Harness: bridges the sdk-bots orchestration gateway (group chats, single bots) into the dsh web shell with official-styled UI.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "lib/index.js",
|