dsh-bots 0.2.12 → 0.2.13

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 +144 -2
  2. package/package.json +1 -1
package/lib/client.js CHANGED
@@ -323,6 +323,7 @@
323
323
  .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}
324
324
  .dbs-fileChip:hover{color:var(--dsw-alias-label-primary)}
325
325
  .dbs-fileChipName{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
326
+ .dbs-setLabel{font-size:12px;line-height:16px;color:var(--dsw-alias-label-tertiary);margin:8px 0 4px}
326
327
  .dbs-chatbar{flex:none;display:flex;align-items:center;gap:8px;height:44px;padding:0 12px;border-bottom:1px solid var(--dsw-alias-border-l1,rgba(0,0,0,.08))}
327
328
  .dbs-chatbarName{font-size:14px;line-height:20px;font-weight:600;color:var(--dsw-alias-label-primary);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;min-width:0}
328
329
  .dbs-scrollBody{scrollbar-gutter:stable;flex-direction:column;flex:1;min-height:0;display:flex;overflow:hidden auto}
@@ -458,6 +459,16 @@
458
459
  'chat.stop.noop': '当前没有进行中的生成',
459
460
  'media.openFailed': '打开失败,文件可能已移动或被删除',
460
461
  'chat.members.manage': '管理成员',
462
+ 'chat.settings': '设置',
463
+ 'chat.settings.title': '会话设置',
464
+ 'chat.settings.name': '名称',
465
+ 'chat.settings.desc': '简介',
466
+ 'chat.settings.workspace': '工作区隔离',
467
+ 'chat.settings.root': '工作区根目录',
468
+ 'chat.settings.rootPh': '留空 = 不启用',
469
+ 'chat.settings.paths': '额外可写路径(逗号分隔)',
470
+ 'chat.settings.pathsPh': '/tmp/xxx, /Users/you/shared',
471
+ 'chat.settings.hint': '写入被沙盒限制在工作区(含额外路径)内,读取不受限;同 slug 的 Bot 共享同一目录。',
461
472
  'modal.members.title': '管理群成员',
462
473
  'modal.members.hint': '勾选的 Bot 为群成员;保存后立即生效(可随时再改)。',
463
474
  'action.delete': '删除',
@@ -560,6 +571,16 @@
560
571
  'chat.stop.noop': 'No generation in progress',
561
572
  'media.openFailed': 'Open failed — the file may have moved or been deleted',
562
573
  'chat.members.manage': 'Manage members',
574
+ 'chat.settings': 'Settings',
575
+ 'chat.settings.title': 'Session settings',
576
+ 'chat.settings.name': 'Name',
577
+ 'chat.settings.desc': 'Description',
578
+ 'chat.settings.workspace': 'Workspace jail',
579
+ 'chat.settings.root': 'Workspace root',
580
+ 'chat.settings.rootPh': 'Empty = disabled',
581
+ 'chat.settings.paths': 'Extra writable paths (comma-separated)',
582
+ 'chat.settings.pathsPh': '/tmp/xxx, /Users/you/shared',
583
+ 'chat.settings.hint': 'Writes are sandboxed to the workspace (plus extra paths); reads stay unrestricted. Bots sharing a slug share one directory.',
563
584
  'modal.members.title': 'Manage group members',
564
585
  'modal.members.hint': 'Checked bots are members; changes apply immediately on save (editable again anytime).',
565
586
  'action.delete': 'Delete',
@@ -762,6 +783,7 @@
762
783
  confirmDelete: null,
763
784
  /** Manage-members dialog: group agentId | null (system modal). */
764
785
  manageMembers: null,
786
+ settingsAgentId: null,
765
787
  /** Bumped on a language switch so module-scope `t` output re-renders. */
766
788
  localeRev: 0,
767
789
  };
@@ -1380,6 +1402,13 @@
1380
1402
  return null;
1381
1403
  return e('div', { className: 'dbs-mediaRefs' }, imgs.map((r) => e(MediaImage, { key: r, path: r })), files.map((r) => e(FileChip, { key: r, path: r })));
1382
1404
  }
1405
+ /**
1406
+ * Settings glyph — three sliders, drawn inline (the primitives package
1407
+ * exposes no verified gear export; same policy as SendUpIcon).
1408
+ */
1409
+ function SettingsGlyph() {
1410
+ return e('svg', { viewBox: '0 0 16 16', width: '16', height: '16', 'aria-hidden': true }, e('g', { stroke: 'currentColor', strokeWidth: 1.5, strokeLinecap: 'round' }, e('line', { x1: 2, y1: 4, x2: 14, y2: 4 }), e('line', { x1: 2, y1: 8, x2: 14, y2: 8 }), e('line', { x1: 2, y1: 12, x2: 14, y2: 12 })), e('g', { fill: 'currentColor' }, e('circle', { cx: 10, cy: 4, r: 2 }), e('circle', { cx: 5.5, cy: 8, r: 2 }), e('circle', { cx: 11.5, cy: 12, r: 2 })));
1411
+ }
1383
1412
  function ToolCard(p) {
1384
1413
  const [open, setOpen] = React.useState(false);
1385
1414
  const en = p.entry;
@@ -1695,12 +1724,16 @@
1695
1724
  variant: 'ghost', size: 'sm', title: t('action.close'), 'aria-label': t('action.close'),
1696
1725
  icon: Ico('IconCloseOutline16', { size: 16 }),
1697
1726
  onClick: () => patch({ chatAgentId: null }),
1698
- }), agent !== null ? e(Avatar, { agent, size: 24 }) : null, e('span', { className: 'dbs-chatbarName' }, agent?.name ?? t('chat.loading')), e('span', { className: 'dbs-meta' }, isGroup ? t('chat.group', { n: memberNames.length }) : t('chat.single')), isGroup
1727
+ }), agent !== null ? e(Avatar, { agent, size: 24 }) : null, e('span', { className: 'dbs-chatbarName' }, agent?.name ?? t('chat.loading')), e('span', { className: 'dbs-meta' }, isGroup ? t('chat.group', { n: memberNames.length }) : t('chat.single')), e('span', { style: { flex: 1 } }), isGroup
1699
1728
  ? e(Button, {
1700
1729
  variant: 'ghost', size: 'sm', title: t('chat.members.manage'), 'aria-label': t('chat.members.manage'),
1701
1730
  onClick: () => patch({ manageMembers: p.agentId }),
1702
1731
  }, t('chat.members.manage'))
1703
- : null, e('span', { style: { flex: 1 } })), error !== null
1732
+ : null, e('button', {
1733
+ className: 'dbs-railBtn', type: 'button',
1734
+ title: t('chat.settings'), 'aria-label': t('chat.settings'),
1735
+ onClick: () => patch({ settingsAgentId: p.agentId }),
1736
+ }, e(SettingsGlyph, null))), error !== null
1704
1737
  ? e('div', { className: 'dbs-error', onClick: () => setError(null) }, error)
1705
1738
  : null, e('div', { className: 'dbs-scrollArea' }, e('div', { className: 'dbs-scrollBody', ref: scrollRef, onScroll: onScrollBody }, e('div', { className: 'dbs-scroll' }, e('div', { className: 'dbs-column' }, entries === null
1706
1739
  ? e('div', { className: 'dbs-skeleton' }, e('div', { className: 'dbs-skelRow', style: { width: '42%' } }), e('div', { className: 'dbs-skelRow', style: { width: '76%' } }), e('div', { className: 'dbs-skelRow', style: { width: '58%' } }))
@@ -2161,6 +2194,113 @@
2161
2194
  onClick: () => void submit(),
2162
2195
  }, working ? t('action.saving') : t('action.save')))));
2163
2196
  }
2197
+ /**
2198
+ * Per-session settings: name (+ description) for every chat; singles
2199
+ * additionally get the §14 workspace-jail editor (root + extra writable
2200
+ * paths). updateAgent merges only the name/description/title/avatar
2201
+ * fields engine-side, so saving cannot clobber the rest of a profile;
2202
+ * an empty root removes the jail (workspaceRoot: null).
2203
+ */
2204
+ function AgentSettingsModal() {
2205
+ const s = useStore();
2206
+ const agent = agentById(s.settingsAgentId);
2207
+ const isGroup = agent?.isGroup === true;
2208
+ const [name, setName] = React.useState('');
2209
+ const [desc, setDesc] = React.useState('');
2210
+ const [root, setRoot] = React.useState('');
2211
+ const [paths, setPaths] = React.useState('');
2212
+ const [wsLoaded, setWsLoaded] = React.useState(false);
2213
+ const [working, setWorking] = React.useState(false);
2214
+ const [err, setErr] = React.useState(null);
2215
+ React.useEffect(() => {
2216
+ if (agent === null || agent === undefined)
2217
+ return;
2218
+ setName(String(agent.name ?? ''));
2219
+ setDesc(String(agent.description ?? ''));
2220
+ if (agent.isGroup === true) {
2221
+ setWsLoaded(true);
2222
+ return;
2223
+ }
2224
+ let alive = true;
2225
+ botsCall('workspaceGet', { agentId: agent.id })
2226
+ .then((c) => {
2227
+ if (alive === false)
2228
+ return;
2229
+ setRoot(c.workspaceRoot ?? '');
2230
+ setPaths((c.allowPaths ?? []).join(', '));
2231
+ setWsLoaded(true);
2232
+ })
2233
+ .catch(() => { if (alive)
2234
+ setWsLoaded(true); });
2235
+ return () => { alive = false; };
2236
+ // eslint-disable-next-line react-hooks/exhaustive-deps
2237
+ }, [s.settingsAgentId]);
2238
+ if (agent === null || agent === undefined)
2239
+ return null;
2240
+ const valid = name.trim() !== '';
2241
+ async function save() {
2242
+ if (working || valid === false)
2243
+ return;
2244
+ setWorking(true);
2245
+ setErr(null);
2246
+ try {
2247
+ await botsCall('update', { id: agent.id, profile: { name: name.trim(), description: desc.trim() } });
2248
+ if (agent.isGroup !== true && wsLoaded === true) {
2249
+ const list = paths.split(/[,,]/).map((x) => x.trim()).filter((x) => x !== '');
2250
+ await botsCall('workspaceSet', {
2251
+ agentId: agent.id,
2252
+ workspaceRoot: root.trim() === '' ? null : root.trim(),
2253
+ allowPaths: list,
2254
+ });
2255
+ }
2256
+ patch({ settingsAgentId: null });
2257
+ await refreshAgents();
2258
+ return;
2259
+ }
2260
+ catch (e2) {
2261
+ setErr(String(e2?.message ?? e2));
2262
+ }
2263
+ setWorking(false);
2264
+ }
2265
+ return e('div', {
2266
+ className: 'dbs-modalBackdrop',
2267
+ onClick: () => { if (working === false)
2268
+ patch({ settingsAgentId: null }); },
2269
+ }, e('div', {
2270
+ className: 'dbs-modalCard', role: 'dialog', 'aria-modal': true,
2271
+ 'aria-label': t('chat.settings.title'),
2272
+ onClick: (ev) => { ev.stopPropagation(); },
2273
+ }, e('div', { className: 'dbs-modalTitleRow' }, e('span', { className: 'dbs-modalTitle' }, t('chat.settings.title')), e(Button, {
2274
+ variant: 'ghost', size: 'sm', title: t('action.close'), 'aria-label': t('action.close'),
2275
+ disabled: working,
2276
+ icon: Ico('IconCloseOutline16', { size: 16 }),
2277
+ onClick: () => patch({ settingsAgentId: null }),
2278
+ })), e('div', { className: 'dbs-modalBody' }, e('div', { className: 'dbs-setLabel' }, t('chat.settings.name')), e(Input, {
2279
+ value: name, autoFocus: true, disabled: working,
2280
+ onChange: (ev) => setName(ev.target.value),
2281
+ }), isGroup === false
2282
+ ? e('div', null, e('div', { className: 'dbs-setLabel' }, t('chat.settings.desc')), e(Input, {
2283
+ value: desc, disabled: working,
2284
+ onChange: (ev) => setDesc(ev.target.value),
2285
+ }), e('div', { className: 'dbs-setLabel', style: { marginTop: 12, fontWeight: 600 } }, t('chat.settings.workspace')), e('div', { className: 'dbs-setLabel' }, t('chat.settings.root')), e(Input, {
2286
+ value: root, disabled: working || wsLoaded === false,
2287
+ placeholder: t('chat.settings.rootPh'),
2288
+ onChange: (ev) => setRoot(ev.target.value),
2289
+ }), e('div', { className: 'dbs-setLabel' }, t('chat.settings.paths')), e(Input, {
2290
+ value: paths, disabled: working || wsLoaded === false,
2291
+ placeholder: t('chat.settings.pathsPh'),
2292
+ onChange: (ev) => setPaths(ev.target.value),
2293
+ }), e('div', { className: 'dbs-meta', style: { marginTop: 8 } }, t('chat.settings.hint')))
2294
+ : null, err !== null
2295
+ ? e('div', { className: 'dbs-error', onClick: () => { setErr(null); } }, err)
2296
+ : null), e('div', { className: 'dbs-modalFooter' }, e(Button, {
2297
+ variant: 'ghost', size: 'sm', disabled: working,
2298
+ onClick: () => patch({ settingsAgentId: null }),
2299
+ }, t('action.cancel')), e(Button, {
2300
+ variant: 'primary', size: 'sm', disabled: valid === false || working,
2301
+ onClick: () => void save(),
2302
+ }, working === true ? t('action.saving') : t('action.save')))));
2303
+ }
2164
2304
  /** Delete confirmation modal: same system-dialog chrome as CreateModal. */
2165
2305
  function ConfirmDeleteModal() {
2166
2306
  const s = useStore();
@@ -2239,6 +2379,8 @@
2239
2379
  layers.push(e(CreateModal, { key: 'create' }));
2240
2380
  if (s.manageMembers !== null)
2241
2381
  layers.push(e(ManageMembersModal, { key: 'manage-members' }));
2382
+ if (s.settingsAgentId !== null)
2383
+ layers.push(e(AgentSettingsModal, { key: 'agent-settings' }));
2242
2384
  if (s.confirmDelete !== null)
2243
2385
  layers.push(e(ConfirmDeleteModal, { key: 'confirm-delete' }));
2244
2386
  return layers.length === 0 ? null : e('div', null, layers);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dsh-bots",
3
- "version": "0.2.12",
3
+ "version": "0.2.13",
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",