dsh-bots 0.2.23 → 0.2.25

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.
Files changed (2) hide show
  1. package/lib/client.js +36 -20
  2. package/package.json +1 -1
package/lib/client.js CHANGED
@@ -336,7 +336,7 @@
336
336
  .dbs-chatview{position:absolute;top:0;bottom:0;pointer-events:auto;display:flex;flex-direction:column;background:var(--dsw-alias-bg-base);font-family:var(--dsw-font-family,inherit);z-index:2;--dsh-chat-content-width:748px;--dsh-composer-card-max-width:calc(var(--dsh-chat-content-width) + 32px);--dsh-composer-side-clearance:16px;--dsh-composer-dock-inset:8px;--dsh-composer-text-max-height:336px;min-width:0}
337
337
  .dbs-mediaRefs{display:flex;flex-wrap:wrap;gap:6px;margin-top:6px;align-items:center}
338
338
  .dbs-mediaImg{max-width:280px;max-height:210px;border-radius:10px;cursor:zoom-in;display:block;border:1px solid var(--dsw-alias-border-l1,rgba(0,0,0,.08))}
339
- .dbs-mediaLoading{width:28px;height:20px;display:inline-flex;align-items:center;color:var(--dsw-alias-label-tertiary)}
339
+ .dbs-mediaLoading{width:28px;height:20px;display:inline-flex;align-items:center;color:var(--dsw-alias-label-tertiary);animation:dbsSpin .8s linear infinite}
340
340
  .dbs-fileChip{display:inline-flex;align-items:center;gap:5px;padding:3px 10px;border-radius:999px;background:var(--dsw-alias-interactive-bg-hover);font-size:12px;line-height:18px;color:var(--dsw-alias-label-secondary);cursor:pointer;max-width:100%;user-select:none}
341
341
  .dbs-fileChip:hover{color:var(--dsw-alias-label-primary)}
342
342
  .dbs-fileChipName{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
@@ -348,8 +348,8 @@
348
348
  .dbs-column{max-width:var(--dsh-chat-content-width);flex-direction:column;gap:16px;width:100%;margin:0 auto;display:flex}
349
349
  .dbs-userRow{flex-direction:column;align-items:flex-end;gap:6px;display:flex}
350
350
  .dbs-userStack{flex-direction:column;align-items:flex-end;gap:8px;min-width:0;max-width:min(525px,82%);display:flex}
351
- .dbs-bubble{background:var(--dsw-specific-bubble);max-width:100%;color:var(--dsw-alias-label-primary);border-radius:22px;padding:10px 16px;font-size:16px;line-height:24px}
352
- .dbs-botRow{color:var(--dsw-alias-label-primary);flex-direction:column;font-size:16px;line-height:28px;display:flex;align-items:flex-start;gap:4px;width:100%}
351
+ .dbs-bubble{background:var(--dsw-specific-bubble);max-width:100%;color:var(--dsw-alias-label-primary);border-radius:22px;padding:10px 16px;font-size:16px;line-height:24px;box-sizing:border-box}
352
+ .dbs-botRow{color:var(--dsw-alias-label-primary);flex-direction:column;font-size:16px;line-height:28px;display:flex;align-items:flex-start;gap:4px;width:100%;box-sizing:border-box}
353
353
  .dbs-author{font-size:14px;line-height:22px;color:var(--dsw-alias-label-secondary);display:flex;align-items:center;gap:8px;font-weight:600;margin-bottom:3px;flex-wrap:wrap}
354
354
  .dbs-authorName{font-weight:600;letter-spacing:.2px}
355
355
  .dbs-md{min-width:0}
@@ -418,15 +418,18 @@
418
418
  .dbs-jump{position:absolute;right:20px;bottom:12px;display:flex;align-items:center;justify-content:center;width:32px;height:32px;border-radius:999px;border:1px solid var(--dsw-alias-border-l2,rgba(0,0,0,.12));background:var(--dsw-specific-input-major,var(--dsw-alias-bg-layer-1,#fff));box-shadow:var(--dsw-shadow-lv2);color:var(--dsw-alias-label-secondary);cursor:pointer;z-index:5;transition:opacity .15s ease,transform .15s ease}
419
419
  .dbs-jump:hover{color:var(--dsw-alias-label-primary);transform:translateY(-1px)}
420
420
  .dbs-jump[data-show="false"]{opacity:0;pointer-events:none;transform:translateY(4px)}
421
- .dbs-typing{display:inline-flex;align-items:center;gap:4px;padding:6px 2px}
422
- .dbs-typing span{width:6px;height:6px;border-radius:999px;background:var(--dsw-alias-label-tertiary);animation:dbsTyping 1.2s ease-in-out infinite}
423
- .dbs-typing span:nth-child(2){animation-delay:.15s}
424
- .dbs-typing span:nth-child(3){animation-delay:.3s}
425
- @keyframes dbsTyping{0%,60%,100%{opacity:.25;transform:translateY(0)}30%{opacity:1;transform:translateY(-3px)}}
421
+ /* Loading states aligned with the native shell: StateDot chase icon where
422
+ available (the real native component), pulse-dot fallback in DeepSeek blue
423
+ at the native 1s cycle; media spinner reuses the native 0.8s linear spin. */
424
+ .dbs-typing{display:inline-flex;align-items:center;gap:6px;padding:6px 2px}
425
+ .dbs-typingText{font-size:12px;line-height:16px;color:var(--dsw-alias-label-tertiary)}
426
+ .dbs-typingDot{width:12px;height:12px;border-radius:999px;background:var(--dsw-static-deepseek-450,var(--dsw-alias-label-tertiary));animation:dbsPulse 1s ease-in-out infinite}
427
+ @keyframes dbsPulse{0%,100%{opacity:.2}50%{opacity:1}}
428
+ @keyframes dbsSpin{to{transform:rotate(360deg)}}
426
429
  .dbs-mdRow{display:flex;align-items:flex-start;gap:0;min-width:0;width:100%}
427
430
  .dbs-caret{flex:none;display:inline-block;width:3px;height:18px;margin-top:5px;border-radius:2px;background:var(--dsw-alias-label-primary);animation:dbsCaret 1s steps(2) infinite}
428
431
  @keyframes dbsCaret{0%,49%{opacity:1}50%,100%{opacity:0}}
429
- .dbs-botRow[data-compact="true"]{padding-left:26px}
432
+ .dbs-botRow[data-compact="true"]{padding-left:30px}
430
433
  .dbs-compactTime{display:flex;justify-content:flex-end;width:100%}
431
434
  .dbs-compactTime .dbs-msgTime{padding:0}
432
435
  .dbs-welcome{display:flex;flex-direction:column;align-items:center;justify-content:center;text-align:center;gap:6px;padding:64px 24px 32px;min-height:50%}
@@ -480,7 +483,7 @@
480
483
  'chat.stop.noop': '当前没有进行中的生成',
481
484
  'media.openFailed': '打开失败,文件可能已移动或被删除',
482
485
  'chat.members.manage': '管理成员',
483
- 'chat.members.cap': '已达群成员上限 6 人(引擎限制)——请先移除一名成员再添加',
486
+ 'chat.members.cap': '已达群成员上限 {cap} 人——可先在下方调大「成员上限」再添加',
484
487
  'chat.settings': '设置',
485
488
  'chat.settings.title': '会话设置',
486
489
  'chat.settings.name': '名称',
@@ -493,6 +496,7 @@
493
496
  'chat.settings.hint': '写入被沙盒限制在工作区(含额外路径)内,读取不受限;同 slug 的 Bot 共享同一目录。',
494
497
  'modal.members.title': '管理群成员',
495
498
  'modal.members.hint': '勾选的 Bot 为群成员;保存后立即生效(可随时再改)。',
499
+ 'modal.members.cap': '成员上限(1–16)',
496
500
  'action.delete': '删除',
497
501
  'delete.title.bot': '删除 Bot',
498
502
  'delete.title.group': '删除群聊',
@@ -595,7 +599,7 @@
595
599
  'chat.stop.noop': 'No generation in progress',
596
600
  'media.openFailed': 'Open failed — the file may have moved or been deleted',
597
601
  'chat.members.manage': 'Manage members',
598
- 'chat.members.cap': 'Group cap is 6 members (engine limit) remove one before adding',
602
+ 'chat.members.cap': 'Group cap is {cap} members raise the cap below first',
599
603
  'chat.settings': 'Settings',
600
604
  'chat.settings.title': 'Session settings',
601
605
  'chat.settings.name': 'Name',
@@ -608,6 +612,7 @@
608
612
  'chat.settings.hint': 'Writes are sandboxed to the workspace (plus extra paths); reads stay unrestricted. Bots sharing a slug share one directory.',
609
613
  'modal.members.title': 'Manage group members',
610
614
  'modal.members.hint': 'Checked bots are members; changes apply immediately on save (editable again anytime).',
615
+ 'modal.members.cap': 'Member cap (1–16)',
611
616
  'action.delete': 'Delete',
612
617
  'delete.title.bot': 'Delete bot',
613
618
  'delete.title.group': 'Delete group chat',
@@ -1816,7 +1821,13 @@
1816
1821
  ? e('div', { className: 'dbs-welcome' }, agent !== null ? e(Avatar, { agent, size: 44 }) : null, e('div', { className: 'dbs-welcomeName' }, agent?.name ?? ''), typeof agent?.description === 'string' && agent.description !== ''
1817
1822
  ? e('div', { className: 'dbs-welcomeDesc' }, agent.description) : null, e('div', { className: 'dbs-welcomeHint' }, isGroup ? t('chat.empty.group') : t('chat.empty.single', { name: agent?.name ?? '' })))
1818
1823
  : thread, composing
1819
- ? e('div', { className: 'dbs-typing', 'aria-label': t('chat.composing'), title: t('chat.composing') }, e('span', null), e('span', null), e('span', null))
1824
+ ? e('div', { className: 'dbs-typing', 'aria-label': t('chat.composing'), title: t('chat.composing') },
1825
+ // Native ongoing state: the StateDot chase matrix
1826
+ // (DeepSeek-blue cells, 1s cycle) — the exact icon the
1827
+ // shell uses while a run is in flight.
1828
+ StateDot !== null
1829
+ ? e(StateDot, { state: 'ongoing', size: 12 })
1830
+ : e('span', { className: 'dbs-typingDot' }), e('span', { className: 'dbs-typingText' }, t('chat.composing')))
1820
1831
  : null))), e('button', {
1821
1832
  type: 'button', className: 'dbs-jump', 'data-show': showJump ? 'true' : 'false',
1822
1833
  'aria-label': t('chat.jump'), title: t('chat.jump'),
@@ -2204,6 +2215,7 @@
2204
2215
  const [picked, setPicked] = React.useState(null);
2205
2216
  const [err, setErr] = React.useState(null);
2206
2217
  const [working, setWorking] = React.useState(false);
2218
+ const [capText, setCapText] = React.useState('8');
2207
2219
  // Seed once per opened group; a group vanishing mid-edit (deleted by
2208
2220
  // the swarm, say) just renders the modal inert until closed.
2209
2221
  React.useEffect(() => {
@@ -2213,23 +2225,24 @@
2213
2225
  for (const id of group.memberIds ?? [])
2214
2226
  init[id] = true;
2215
2227
  setPicked(init);
2228
+ setCapText(String(group.maxMembers ?? 8));
2216
2229
  // eslint-disable-next-line react-hooks/exhaustive-deps
2217
2230
  }, [s.manageMembers]);
2218
2231
  if (group === null || group === undefined)
2219
2232
  return null;
2220
2233
  const singles = s.agents.filter((a) => !a.isGroup && a.isHiddenFromSidebar !== true);
2221
2234
  const pickedIds = picked === null ? [] : Object.keys(picked).filter((k) => picked[k]);
2222
- // Engine hard cap (sdk-bots agents.ts GROUP_MAX_MEMBERS = 6): the glue
2223
- // slice(0, 6)-truncates the roster SILENTLY — an over-cap save writes
2224
- // successfully and just drops whoever ranked past 6. Surface it here
2225
- // instead of letting a save pretend to work.
2226
- const MEMBER_CAP = 6;
2235
+ // Per-group cap (group.json maxMembers, default 8, engine hard max 16):
2236
+ // the glue slice(0, maxMembers)-truncates the roster SILENTLY — an
2237
+ // over-cap save writes successfully and just drops whoever ranked past
2238
+ // the cap. Surface it here instead of letting a save pretend to work.
2239
+ const MEMBER_CAP = Math.min(16, Math.max(1, Math.floor(Number(capText)) || 8));
2227
2240
  const overCap = pickedIds.length > MEMBER_CAP;
2228
2241
  function toggle(id) {
2229
2242
  if (picked === null)
2230
2243
  return;
2231
2244
  if (picked[id] !== true && pickedIds.length >= MEMBER_CAP) {
2232
- setErr(t('chat.members.cap'));
2245
+ setErr(t('chat.members.cap', { cap: MEMBER_CAP }));
2233
2246
  return;
2234
2247
  }
2235
2248
  setErr(null);
@@ -2241,7 +2254,7 @@
2241
2254
  setWorking(true);
2242
2255
  setErr(null);
2243
2256
  try {
2244
- await botsCall('setGroupMembers', { id: group.id, memberIds: pickedIds });
2257
+ await botsCall('setGroupMembers', { id: group.id, memberIds: pickedIds, maxMembers: MEMBER_CAP });
2245
2258
  patch({ manageMembers: null });
2246
2259
  await refreshAgents();
2247
2260
  return;
@@ -2264,7 +2277,10 @@
2264
2277
  disabled: working,
2265
2278
  icon: Ico('IconCloseOutline16', { size: 16 }),
2266
2279
  onClick: () => patch({ manageMembers: null }),
2267
- })), e('div', { className: 'dbs-modalBody' }, e('div', { className: 'dbs-meta', style: { padding: '0 2px 6px' } }, t('modal.members.hint')), picked === null
2280
+ })), e('div', { className: 'dbs-modalBody' }, e('div', { className: 'dbs-meta', style: { padding: '0 2px 6px' } }, t('modal.members.hint')), e('div', { className: 'dbs-setrow', style: { padding: '0 2px 8px', gap: 8 } }, e('span', { className: 'dbs-meta' }, t('modal.members.cap')), e(Input, {
2281
+ value: capText, disabled: working, style: { width: 72 },
2282
+ onChange: (ev) => setCapText(ev.target.value),
2283
+ })), picked === null
2268
2284
  ? e('div', { className: 'dbs-meta', style: { padding: '4px 6px' } }, t('list.loading'))
2269
2285
  : e('div', { className: 'dbs-modalMembers' }, singles.length === 0
2270
2286
  ? e('div', { className: 'dbs-meta', style: { padding: '4px 6px' } }, t('list.empty'))
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dsh-bots",
3
- "version": "0.2.23",
3
+ "version": "0.2.25",
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",