dsh-project-room 0.2.6 → 0.2.8

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/client.js +140 -75
  2. package/package.json +1 -1
package/client.js CHANGED
@@ -303,42 +303,42 @@ window.__ModuleLoader__.load({
303
303
  flex: 1; min-width: 0; height: 22px; box-sizing: border-box; padding: 0 6px;
304
304
  border-radius: 6px; border: 1px solid var(--dsw-alias-border-l1);
305
305
  background: var(--dsw-alias-bg-layer-1); color: var(--dsw-alias-label-primary);
306
- font-size: 0.6875rem; outline: none;
306
+ font-size: calc(11px + var(--dsh-content-font-delta, 0px)); outline: none;
307
307
  }
308
308
  .pr-head { display: flex; align-items: center; gap: 6px; padding: 2px 6px 4px; flex: 0 0 auto; }
309
- .pr-head-title { font-size: 0.71875rem; letter-spacing: 0.04em; font-weight: 600; color: var(--dsw-alias-label-secondary); }
310
- .pr-head-count { font-size: 0.625rem; color: var(--dsw-alias-label-secondary); opacity: .75; margin-left: auto; }
309
+ .pr-head-title { font-size: calc(11.5px + var(--dsh-content-font-delta, 0px)); letter-spacing: 0.04em; font-weight: 600; color: var(--dsw-alias-label-secondary); }
310
+ .pr-head-count { font-size: calc(10px + var(--dsh-content-font-delta, 0px)); color: var(--dsw-alias-label-secondary); opacity: .75; margin-left: auto; }
311
311
  /* 「未分组」那一行:折叠按钮 + 清理按钮 */
312
312
  .pr-loose-row { display: flex; gap: 4px; align-items: center; padding: 0 6px 6px; flex: 0 0 auto; }
313
313
  .pr-loose-toggle {
314
314
  padding: 1px 6px;
315
315
  border: 1px solid var(--dsw-alias-border-l1); border-radius: 6px;
316
316
  background: transparent; color: var(--dsw-alias-label-secondary);
317
- font-size: 0.625rem; line-height: 1.6; cursor: pointer; flex: 0 0 auto;
317
+ font-size: calc(10px + var(--dsh-content-font-delta, 0px)); line-height: 1.6; cursor: pointer; flex: 0 0 auto;
318
318
  }
319
319
  .pr-loose-toggle:hover { background: var(--dsw-alias-bg-layer-2); color: var(--dsw-alias-label-primary); }
320
320
  .pr-chip-badge {
321
321
  flex: 0 0 auto; min-width: 14px; height: 14px; padding: 0 3px; border-radius: 7px;
322
322
  display: inline-flex; align-items: center; justify-content: center;
323
323
  background: var(--dsw-alias-bg-layer-2); color: var(--dsw-alias-label-secondary);
324
- font-size: 0.5625rem; line-height: 1; font-variant-numeric: tabular-nums;
324
+ font-size: calc(9px + var(--dsh-content-font-delta, 0px)); line-height: 1; font-variant-numeric: tabular-nums;
325
325
  }
326
- .pr-chip-elapsed { flex: 0 0 auto; font-size: 0.5625rem; line-height: 1; font-variant-numeric: tabular-nums; color: var(--dsw-alias-state-success-primary); }
326
+ .pr-chip-elapsed { flex: 0 0 auto; font-size: calc(9px + var(--dsh-content-font-delta, 0px)); line-height: 1; font-variant-numeric: tabular-nums; color: var(--dsw-alias-state-success-primary); }
327
327
  /* 分身子行:树状(├ / └ 竖线缩进) */
328
328
  .pr-chip-clones { display: flex; flex-direction: column; gap: 1px; margin-top: 1px; padding-left: 0; }
329
329
  .pr-clone-row {
330
330
  display: flex; align-items: center; gap: 3px;
331
- font-size: 0.59375rem; line-height: 1.5; color: var(--dsw-alias-label-secondary);
331
+ font-size: calc(9.5px + var(--dsh-content-font-delta, 0px)); line-height: 1.5; color: var(--dsw-alias-label-secondary);
332
332
  cursor: pointer; border-radius: 3px; padding: 0;
333
333
  }
334
334
  .pr-clone-row:hover { background: var(--dsw-alias-interactive-bg-hover, rgba(255,255,255,0.06)); color: var(--dsw-alias-label-primary); }
335
- .pr-tree-rail { flex: 0 0 auto; width: 7px; color: var(--dsw-alias-border-l2, #4a4a4a); font-size: 0.5625rem; line-height: 1.5; }
335
+ .pr-tree-rail { flex: 0 0 auto; width: 7px; color: var(--dsw-alias-border-l2, #4a4a4a); font-size: calc(9px + var(--dsh-content-font-delta, 0px)); line-height: 1.5; }
336
336
  .pr-clone-dot { flex: 0 0 auto; width: 5px; height: 5px; border-radius: 50%; background: transparent; box-shadow: inset 0 0 0 1px var(--dsw-alias-label-secondary); }
337
337
  .pr-clone-dot.on { background: var(--dsw-alias-state-success-primary, #4ade80); box-shadow: none; }
338
338
  /* 同理:分身子行名不再 ellipsis,长任务名完整显示(行高会自动撑开)。 */
339
339
  .pr-clone-name { min-width: 0; white-space: normal; overflow-wrap: anywhere; word-break: break-word; }
340
340
  .pr-clone-elapsed {
341
- flex: 0 0 auto; margin-left: 3px; font-size: 0.5625rem; line-height: 1;
341
+ flex: 0 0 auto; margin-left: 3px; font-size: calc(9px + var(--dsh-content-font-delta, 0px)); line-height: 1;
342
342
  font-variant-numeric: tabular-nums;
343
343
  color: var(--dsw-alias-state-success-primary);
344
344
  }
@@ -347,31 +347,31 @@ window.__ModuleLoader__.load({
347
347
  position: fixed; z-index: 1000; min-width: 168px; padding: 4px;
348
348
  border-radius: 8px; border: 1px solid var(--dsw-alias-border-l2);
349
349
  background: var(--dsw-alias-bg-layer-2); box-shadow: 0 12px 32px rgba(0,0,0,.45);
350
- font-size: 0.75rem;
350
+ font-size: calc(12px + var(--dsh-content-font-delta, 0px));
351
351
  }
352
352
  .pr-menu-item {
353
353
  display: block; width: 100%; text-align: left; padding: 5px 8px; border: none; border-radius: 5px;
354
- background: transparent; color: var(--dsw-alias-label-primary); font: inherit; font-size: 0.75rem; cursor: pointer;
354
+ background: transparent; color: var(--dsw-alias-label-primary); font: inherit; font-size: calc(12px + var(--dsh-content-font-delta, 0px)); cursor: pointer;
355
355
  }
356
356
  .pr-menu-item:hover { background: var(--dsw-alias-bg-layer-1); }
357
- .pr-menu-msg { padding: 4px 8px; font-size: 0.65625rem; color: var(--dsw-alias-label-secondary); }
357
+ .pr-menu-msg { padding: 4px 8px; font-size: calc(10.5px + var(--dsh-content-font-delta, 0px)); color: var(--dsw-alias-label-secondary); }
358
358
  .pr-modal { position: fixed; inset: 0; z-index: 1001; display: flex; align-items: center; justify-content: center; background: rgba(0,0,0,.45); }
359
- .pr-modal-box { width: min(420px, 88vw); padding: 14px; border-radius: 10px; background: var(--dsw-alias-bg-base); border: 1px solid var(--dsw-alias-border-l2); }
360
- .pr-modal-title { font-size: 0.8125rem; font-weight: 600; margin-bottom: 8px; }
361
- .pr-modal-input { width: 100%; box-sizing: border-box; height: 30px; padding: 0 8px; border-radius: 6px; border: 1px solid var(--dsw-alias-border-l1); background: var(--dsw-alias-bg-layer-1); color: var(--dsw-alias-label-primary); font-size: 0.78125rem; outline: none; }
359
+ .pr-modal-box { width: min(420px, 88vw); padding: 14px; border-radius: 10px; background-color: #141a1b; background-image: linear-gradient(var(--dsw-alias-bg-base), var(--dsw-alias-bg-base)); border: 1px solid var(--dsw-alias-border-l2); box-shadow: 0 18px 48px rgba(0,0,0,.5); }
360
+ .pr-modal-title { font-size: calc(13px + var(--dsh-content-font-delta, 0px)); font-weight: 600; margin-bottom: 8px; }
361
+ .pr-modal-input { width: 100%; box-sizing: border-box; height: 30px; padding: 0 8px; border-radius: 6px; border: 1px solid var(--dsw-alias-border-l1); background: var(--dsw-alias-bg-layer-1); color: var(--dsw-alias-label-primary); font-size: calc(12.5px + var(--dsh-content-font-delta, 0px)); outline: none; }
362
362
  .pr-modal-actions { display: flex; justify-content: flex-end; gap: 8px; margin-top: 12px; }
363
363
  /* 头部「+ 新项目」按钮 */
364
364
  .pr-new-btn {
365
365
  flex: 0 0 auto; height: 18px; padding: 0 6px; border-radius: 5px;
366
366
  border: 1px solid var(--dsw-alias-border-l1); background: transparent;
367
- color: var(--dsw-alias-label-secondary); font-size: 0.625rem; line-height: 1; cursor: pointer;
367
+ color: var(--dsw-alias-label-secondary); font-size: calc(10px + var(--dsh-content-font-delta, 0px)); line-height: 1; cursor: pointer;
368
368
  }
369
369
  .pr-new-btn:hover { background: var(--dsw-alias-bg-layer-2); color: var(--dsw-alias-label-primary); }
370
370
  /* 房间关闭按钮:显式带文字,避免全屏遮罩下只剩一个小图标找不着 */
371
371
  .pr-close-btn {
372
372
  flex: 0 0 auto; height: 22px; padding: 0 10px; border-radius: 6px;
373
373
  border: 1px solid var(--dsw-alias-border-l2); background: var(--dsw-alias-bg-layer-2);
374
- color: var(--dsw-alias-label-primary); font-size: 0.71875rem; line-height: 1; cursor: pointer;
374
+ color: var(--dsw-alias-label-primary); font-size: calc(11.5px + var(--dsh-content-font-delta, 0px)); line-height: 1; cursor: pointer;
375
375
  }
376
376
  .pr-close-btn:hover { border-color: var(--dsw-alias-brand-primary); }
377
377
  /* 一页三段布局 */
@@ -396,11 +396,11 @@ window.__ModuleLoader__.load({
396
396
  .pr-section { margin-bottom: 16px; }
397
397
  .pr-section:last-child { margin-bottom: 4px; }
398
398
  .pr-section-title {
399
- font-size: 0.6875rem; font-weight: 700; letter-spacing: .06em;
399
+ font-size: calc(11px + var(--dsh-content-font-delta, 0px)); font-weight: 700; letter-spacing: .06em;
400
400
  color: var(--dsw-alias-label-secondary); text-transform: uppercase;
401
401
  margin-bottom: 6px;
402
402
  }
403
- .pr-loose-msg { font-size: 0.625rem; color: var(--dsw-alias-label-secondary); padding: 0 6px 6px; line-height: 1.5; flex: 0 0 auto; }
403
+ .pr-loose-msg { font-size: calc(10px + var(--dsh-content-font-delta, 0px)); color: var(--dsw-alias-label-secondary); padding: 0 6px 6px; line-height: 1.5; flex: 0 0 auto; }
404
404
 
405
405
  /* 运行中快捷栏(对齐 AI-Agent-Hub):两段竖排 —— 上「运行中」、下「完成未读」 */
406
406
  .pr-runbar { display: flex; flex-direction: column; gap: 4px; padding: 2px 4px 6px; flex: 0 0 auto; min-width: 0; }
@@ -413,7 +413,7 @@ window.__ModuleLoader__.load({
413
413
  }
414
414
  .pr-runbar-sec-title {
415
415
  display: flex; align-items: center; gap: 4px; min-width: 0;
416
- padding: 0 2px; font-size: 0.5625rem; line-height: 1.4;
416
+ padding: 0 2px; font-size: calc(9px + var(--dsh-content-font-delta, 0px)); line-height: 1.4;
417
417
  color: var(--dsw-alias-label-secondary); letter-spacing: .03em;
418
418
  }
419
419
  .pr-runbar-sec[data-kind="done"] .pr-runbar-sec-title { color: #d97757; }
@@ -425,7 +425,7 @@ window.__ModuleLoader__.load({
425
425
  width: 10px; height: 10px; border-radius: 50%; flex: 0 0 auto;
426
426
  display: inline-flex; align-items: center; justify-content: center;
427
427
  background: #d97757; color: #fff;
428
- font-size: 0.5rem; font-weight: 700; line-height: 1;
428
+ font-size: calc(8px + var(--dsh-content-font-delta, 0px)); font-weight: 700; line-height: 1;
429
429
  }
430
430
  .pr-runbar-sec-label { flex: 0 0 auto; white-space: nowrap; }
431
431
  .pr-runbar-sec-count {
@@ -436,12 +436,12 @@ window.__ModuleLoader__.load({
436
436
  子行样式与侧栏芯片的 pr-clone-row / pr-tree-rail 完全一致。 */
437
437
  .pr-run-wrap { display: inline-flex; flex-direction: column; gap: 1px; align-items: flex-start; }
438
438
  .pr-run-clones { display: flex; flex-direction: column; gap: 1px; padding-left: 6px; margin: 0 0 1px; }
439
- .pr-run-clones .pr-clone-row { font-size: 0.5625rem; line-height: 1.4; }
439
+ .pr-run-clones .pr-clone-row { font-size: calc(9px + var(--dsh-content-font-delta, 0px)); line-height: 1.4; }
440
440
  .pr-readall {
441
441
  /* 2026-11-11:一键已读搬进「完成未读」区的小标题里,靠右对齐 */
442
442
  flex: 0 0 auto; margin: 0 0 0 auto; padding: 1px 6px; border-radius: 8px;
443
443
  border: 1px solid var(--dsw-alias-border-l1); background: transparent;
444
- color: #d97757; font-size: 0.59375rem; line-height: 1.4;
444
+ color: #d97757; font-size: calc(9.5px + var(--dsh-content-font-delta, 0px)); line-height: 1.4;
445
445
  white-space: nowrap; cursor: pointer;
446
446
  }
447
447
  .pr-readall:hover { background: var(--dsw-alias-bg-layer-2); }
@@ -451,7 +451,7 @@ window.__ModuleLoader__.load({
451
451
  min-height: 20px; padding: 2px 7px 2px 3px; border-radius: 11px;
452
452
  border: 1px solid transparent; background: transparent;
453
453
  color: var(--dsw-alias-label-secondary);
454
- font: inherit; font-size: 0.71875rem; line-height: 1.2; white-space: nowrap; cursor: pointer;
454
+ font: inherit; font-size: calc(11.5px + var(--dsh-content-font-delta, 0px)); line-height: 1.2; white-space: nowrap; cursor: pointer;
455
455
  }
456
456
  .pr-run-pill:hover { background: var(--dsw-alias-bg-layer-1); }
457
457
  .pr-run-pill[data-active="1"] {
@@ -462,28 +462,28 @@ window.__ModuleLoader__.load({
462
462
  .pr-run-avatar { width: 16px; height: 16px; border-radius: 50%; display: inline-flex; align-items: center; justify-content: center; flex: 0 0 auto; line-height: 1; }
463
463
  .pr-run-project { display: inline-flex; align-items: center; gap: 3px; flex: 0 0 auto; min-width: 0; }
464
464
  .pr-run-project-dot { width: 6px; height: 6px; border-radius: 2px; flex: 0 0 auto; }
465
- .pr-run-project-name { font-size: 0.5625rem; line-height: 1; font-variant-numeric: tabular-nums; white-space: nowrap; }
465
+ .pr-run-project-name { font-size: calc(9px + var(--dsh-content-font-delta, 0px)); line-height: 1; font-variant-numeric: tabular-nums; white-space: nowrap; }
466
466
  /* 2026-11-09 用户令「标题要显示全」:快捷栏 pill 名字原来 nowrap+ellipsis 会被吃掉,改为可换行。 */
467
467
  .pr-run-name { min-width: 0; flex: 0 1 auto; white-space: normal; overflow-wrap: anywhere; word-break: break-word; }
468
468
  .pr-run-badge {
469
469
  flex: 0 0 auto; min-width: 14px; height: 14px; padding: 0 3px; border-radius: 7px;
470
470
  display: inline-flex; align-items: center; justify-content: center;
471
471
  background: var(--dsw-alias-bg-layer-2); color: var(--dsw-alias-label-secondary);
472
- font-size: 0.5625rem; line-height: 1; font-variant-numeric: tabular-nums;
472
+ font-size: calc(9px + var(--dsh-content-font-delta, 0px)); line-height: 1; font-variant-numeric: tabular-nums;
473
473
  }
474
- .pr-run-done { display: inline-flex; align-items: center; gap: 3px; flex: 0 0 auto; font-size: 0.5625rem; line-height: 1; color: var(--dsw-alias-brand-primary); }
474
+ .pr-run-done { display: inline-flex; align-items: center; gap: 3px; flex: 0 0 auto; font-size: calc(9px + var(--dsh-content-font-delta, 0px)); line-height: 1; color: var(--dsw-alias-brand-primary); }
475
475
  .pr-run-check {
476
476
  width: 10px; height: 10px; border-radius: 50%; display: inline-flex; align-items: center; justify-content: center;
477
- background: #d97757; color: #fff; font-size: 0.5rem; font-weight: 700; line-height: 1;
477
+ background: #d97757; color: #fff; font-size: calc(8px + var(--dsh-content-font-delta, 0px)); font-weight: 700; line-height: 1;
478
478
  }
479
- .pr-run-elapsed { flex: 0 0 auto; font-size: 0.5625rem; line-height: 1; font-variant-numeric: tabular-nums; color: var(--dsw-alias-state-success-primary); }
479
+ .pr-run-elapsed { flex: 0 0 auto; font-size: calc(9px + var(--dsh-content-font-delta, 0px)); line-height: 1; font-variant-numeric: tabular-nums; color: var(--dsw-alias-state-success-primary); }
480
480
 
481
481
  /* 项目行:22px 紧凑行高 + 顶部细线,读起来像「项目」而不是一行会话 */
482
482
  .pr-proj {
483
483
  display: flex; align-items: center; gap: 6px;
484
484
  height: 22px; min-height: 22px; padding: 0 6px;
485
485
  margin-top: 6px; border-radius: 6px;
486
- font-size: 0.75rem; font-weight: 600;
486
+ font-size: calc(12px + var(--dsh-content-font-delta, 0px)); font-weight: 600;
487
487
  box-shadow: inset 0 1px 0 var(--dsw-alias-border-l1);
488
488
  cursor: pointer; overflow: hidden;
489
489
  }
@@ -492,11 +492,11 @@ window.__ModuleLoader__.load({
492
492
  .pr-dot { width: 6px; height: 6px; border-radius: 2px; flex: 0 0 auto; }
493
493
  .pr-proj-name { flex: 0 1 auto; max-width: 100%; min-width: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
494
494
  .pr-spacer { flex: 1 1 auto; min-width: 4px; }
495
- .pr-meta { font-size: 0.625rem; font-weight: 500; color: var(--dsw-alias-label-secondary); flex: 0 0 auto; font-variant-numeric: tabular-nums; }
495
+ .pr-meta { font-size: calc(10px + var(--dsh-content-font-delta, 0px)); font-weight: 500; color: var(--dsw-alias-label-secondary); flex: 0 0 auto; font-variant-numeric: tabular-nums; }
496
496
  .pr-icon-btn {
497
497
  width: 18px; height: 18px; flex: 0 0 auto; border: none; padding: 0; border-radius: 5px;
498
498
  background: transparent; color: var(--dsw-alias-label-secondary);
499
- cursor: pointer; font-size: 0.625rem; line-height: 1;
499
+ cursor: pointer; font-size: calc(10px + var(--dsh-content-font-delta, 0px)); line-height: 1;
500
500
  }
501
501
  .pr-icon-btn:hover { background: var(--dsw-alias-bg-layer-2); color: var(--dsw-alias-label-primary); }
502
502
  /* 图钉:默认隐藏,悬停显形;已置顶常显 */
@@ -519,7 +519,7 @@ window.__ModuleLoader__.load({
519
519
  padding: 0; border-radius: 11px;
520
520
  border: 1px solid transparent; background: transparent;
521
521
  color: var(--dsw-alias-label-secondary);
522
- font: inherit; font-size: 0.71875rem; line-height: 1.2;
522
+ font: inherit; font-size: calc(11.5px + var(--dsh-content-font-delta, 0px)); line-height: 1.2;
523
523
  cursor: pointer; box-sizing: border-box; overflow-wrap: anywhere;
524
524
  }
525
525
  /* 本体那一行(头像 + 名字 + badge + 圆点 + 时长):单独成盒,选中背景只作用在它上面 */
@@ -579,25 +579,25 @@ window.__ModuleLoader__.load({
579
579
  100% { transform: scale(1); opacity: 1; box-shadow: 0 0 0 0 transparent; }
580
580
  }
581
581
  .pr-running-dot { width: 6px; height: 6px; border-radius: 50%; flex: 0 0 auto; background: var(--dsw-alias-state-success-primary); animation: pr-pulse 1.4s ease-in-out infinite; }
582
- .pr-empty { padding: 10px 8px; font-size: 0.6875rem; color: var(--dsw-alias-label-secondary); text-align: center; }
582
+ .pr-empty { padding: 10px 8px; font-size: calc(11px + var(--dsh-content-font-delta, 0px)); color: var(--dsw-alias-label-secondary); text-align: center; }
583
583
 
584
584
  /* 房间浮层 */
585
585
  .pr-overlay { position: fixed; z-index: 900; display: flex; flex-direction: column; background: var(--dsw-alias-bg-base); border-left: 1px solid var(--dsw-alias-border-l1); }
586
586
  .pr-panel { width: 100%; height: 100%; display: flex; flex-direction: column; background: var(--dsw-alias-bg-base); }
587
587
  .pr-panel-head { display: flex; align-items: center; gap: 8px; padding: 10px 14px; border-bottom: 1px solid var(--dsw-alias-border-l1); }
588
- .pr-panel-title { font-size: 0.8125rem; font-weight: 700; }/* 2026-11-10 用户令「群聊页字体太大」:14px→13px,与分区标题/正文一起收一档 */
588
+ .pr-panel-title { font-size: calc(13px + var(--dsh-content-font-delta, 0px)); font-weight: 700; }/* 2026-11-10 用户令「群聊页字体太大」:14px→13px,与分区标题/正文一起收一档 */
589
589
  .pr-tabs { display: flex; gap: 2px; margin-left: 10px; }
590
- .pr-tab { padding: 3px 10px; border-radius: 6px; border: none; background: transparent; color: var(--dsw-alias-label-secondary); font-size: 0.75rem; cursor: pointer; }
590
+ .pr-tab { padding: 3px 10px; border-radius: 6px; border: none; background: transparent; color: var(--dsw-alias-label-secondary); font-size: calc(12px + var(--dsh-content-font-delta, 0px)); cursor: pointer; }
591
591
  .pr-tab.on { background: var(--dsw-alias-bg-layer-2); color: var(--dsw-alias-label-primary); font-weight: 600; }
592
592
  .pr-panel-body { flex: 1; min-height: 0; overflow: hidden; padding: 12px 14px; display: flex; flex-direction: column; }
593
593
  .pr-panel-foot { border-top: 1px solid var(--dsw-alias-border-l1); padding: 8px 14px; display: flex; gap: 8px; align-items: flex-end; }
594
- .pr-textarea { flex: 1; min-height: 34px; max-height: 120px; resize: vertical; padding: 6px 8px; border-radius: 6px; border: 1px solid var(--dsw-alias-border-l1); background: var(--dsw-alias-bg-layer-1); color: var(--dsw-alias-label-primary); font-size: 0.75rem; font-family: inherit; outline: none; }
595
- .pr-btn { padding: 6px 12px; border-radius: 6px; border: 1px solid var(--dsw-alias-border-l2); background: var(--dsw-alias-bg-layer-2); color: var(--dsw-alias-label-primary); font-size: 0.75rem; cursor: pointer; white-space: nowrap; }
594
+ .pr-textarea { flex: 1; min-height: 34px; max-height: 120px; resize: vertical; padding: 6px 8px; border-radius: 6px; border: 1px solid var(--dsw-alias-border-l1); background: var(--dsw-alias-bg-layer-1); color: var(--dsw-alias-label-primary); font-size: calc(12px + var(--dsh-content-font-delta, 0px)); font-family: inherit; outline: none; }
595
+ .pr-btn { padding: 6px 12px; border-radius: 6px; border: 1px solid var(--dsw-alias-border-l2); background: var(--dsw-alias-bg-layer-2); color: var(--dsw-alias-label-primary); font-size: calc(12px + var(--dsh-content-font-delta, 0px)); cursor: pointer; white-space: nowrap; }
596
596
  .pr-btn:hover { border-color: var(--dsw-alias-brand-primary); }
597
597
  .pr-btn.primary { background: var(--dsw-alias-brand-primary); border-color: var(--dsw-alias-brand-primary); color: #08111a; font-weight: 600; }
598
598
  .pr-btn:disabled { opacity: .5; cursor: default; }
599
- .pr-board { width: 100%; min-height: 200px; resize: vertical; padding: 10px; border-radius: 8px; border: 1px solid var(--dsw-alias-border-l1); background: var(--dsw-alias-bg-layer-1); color: var(--dsw-alias-label-primary); font-size: 0.78125rem; line-height: 1.6; font-family: ui-monospace, SFMono-Regular, Consolas, monospace; outline: none; }
600
- .pr-todo { display: flex; align-items: center; gap: 8px; padding: 5px 0; border-bottom: 1px dashed var(--dsw-alias-border-l1); font-size: 0.78125rem; }
599
+ .pr-board { width: 100%; min-height: 200px; resize: vertical; padding: 10px; border-radius: 8px; border: 1px solid var(--dsw-alias-border-l1); background: var(--dsw-alias-bg-layer-1); color: var(--dsw-alias-label-primary); font-size: calc(12.5px + var(--dsh-content-font-delta, 0px)); line-height: 1.6; font-family: ui-monospace, SFMono-Regular, Consolas, monospace; outline: none; }
600
+ .pr-todo { display: flex; align-items: center; gap: 8px; padding: 5px 0; border-bottom: 1px dashed var(--dsw-alias-border-l1); font-size: calc(12.5px + var(--dsh-content-font-delta, 0px)); }
601
601
  .pr-todo input[type=checkbox] { flex: 0 0 auto; }
602
602
  .pr-todo-text { flex: 1; min-width: 0; }
603
603
  .pr-todo.done .pr-todo-text { text-decoration: line-through; opacity: .55; }
@@ -619,7 +619,7 @@ window.__ModuleLoader__.load({
619
619
  display: flex; align-items: flex-start; gap: 5px; padding: 5px 8px;
620
620
  border-bottom: 1px solid var(--dsw-alias-border-l1);
621
621
  background: var(--dsw-alias-bg-layer-2);
622
- font-size: 0.71875rem; font-weight: 600;/* 2026-11-09 用户令:lane 标题完整显示 */
622
+ font-size: calc(11.5px + var(--dsh-content-font-delta, 0px)); font-weight: 600;/* 2026-11-09 用户令:lane 标题完整显示 */
623
623
  }
624
624
  /* ⚠️ 2026-11-10 补回上面这条规则的收尾花括号:58ca983 改 lane 标题换行时把块尾的 } 弄丢了,
625
625
  浏览器(Chrome 120+ 支持 CSS 嵌套)会把 .pr-lane-name 之后的**全部规则**当成
@@ -629,7 +629,7 @@ window.__ModuleLoader__.load({
629
629
  .pr-lane-archive {
630
630
  margin-left: auto; flex: 0 0 auto; height: 18px; padding: 0 6px; border-radius: 5px;
631
631
  border: 1px solid transparent; background: transparent;
632
- color: var(--dsw-alias-label-secondary); font-size: 0.625rem; line-height: 1; cursor: pointer;
632
+ color: var(--dsw-alias-label-secondary); font-size: calc(10px + var(--dsh-content-font-delta, 0px)); line-height: 1; cursor: pointer;
633
633
  }
634
634
  .pr-lane-archive:hover {
635
635
  border-color: var(--dsw-alias-border-l2); background: var(--dsw-alias-bg-layer-1);
@@ -637,13 +637,13 @@ window.__ModuleLoader__.load({
637
637
  }
638
638
  .pr-lane-dot { width: 7px; height: 7px; border-radius: 50%; flex: 0 0 auto; }
639
639
  .pr-lane-sub {
640
- padding: 0 8px 4px; font-size: 0.59375rem; color: var(--dsw-alias-label-secondary);
640
+ padding: 0 8px 4px; font-size: calc(9.5px + var(--dsh-content-font-delta, 0px)); color: var(--dsw-alias-label-secondary);
641
641
  border-bottom: 1px solid var(--dsw-alias-border-l1);
642
642
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
643
643
  }
644
644
  .pr-lane-body { flex: 1; min-height: 90px; max-height: 210px; overflow-y: auto; padding: 6px; display: flex; flex-direction: column; gap: 5px; }
645
645
  .pr-lane-msg {
646
- font-size: 0.6875rem; line-height: 1.4; color: var(--dsw-alias-label-primary);
646
+ font-size: calc(11px + var(--dsh-content-font-delta, 0px)); line-height: 1.4; color: var(--dsw-alias-label-primary);
647
647
  background: var(--dsw-alias-bg-base); border-radius: 6px; padding: 4px 6px;
648
648
  display: -webkit-box; -webkit-line-clamp: 4; -webkit-box-orient: vertical; overflow: hidden;
649
649
  white-space: pre-wrap; word-break: break-word;
@@ -656,25 +656,25 @@ window.__ModuleLoader__.load({
656
656
  /* 看板:渲染视图(纵向滚动)+ 编辑切换 */
657
657
  .pr-board-section { display: flex; flex-direction: column; min-height: 0; }
658
658
  .pr-section-head { display: flex; align-items: center; gap: 8px; margin-bottom: 6px; }
659
- .pr-board-toggle { height: 22px; padding: 0 9px; font-size: 0.6875rem; }
659
+ .pr-board-toggle { height: 22px; padding: 0 9px; font-size: calc(11px + var(--dsh-content-font-delta, 0px)); }
660
660
  .pr-board-count {
661
- margin-left: auto; font-size: 0.625rem; color: var(--dsw-alias-label-secondary);
661
+ margin-left: auto; font-size: calc(10px + var(--dsh-content-font-delta, 0px)); color: var(--dsw-alias-label-secondary);
662
662
  font-variant-numeric: tabular-nums; white-space: nowrap;
663
663
  }
664
664
  .pr-md-view {
665
665
  flex: 1; min-height: 120px; max-height: 42vh; overflow-y: auto;
666
666
  padding: 8px 10px; border: 1px solid var(--dsw-alias-border-l1); border-radius: 8px;
667
- background: var(--dsw-alias-bg-layer-1); font-size: 0.75rem; line-height: 1.55;
667
+ background: var(--dsw-alias-bg-layer-1); font-size: calc(12px + var(--dsh-content-font-delta, 0px)); line-height: 1.55;
668
668
  word-break: break-word;
669
669
  }
670
- .pr-md-h { margin: 6px 0 4px; font-size: 0.78125rem; font-weight: 700; color: var(--dsw-alias-label-primary); }
670
+ .pr-md-h { margin: 6px 0 4px; font-size: calc(12.5px + var(--dsh-content-font-delta, 0px)); font-weight: 700; color: var(--dsw-alias-label-primary); }
671
671
  .pr-md-h:first-child { margin-top: 0; }
672
672
  .pr-md-p { margin: 2px 0; color: var(--dsw-alias-label-primary); white-space: pre-wrap; }
673
673
  .pr-md-ul { margin: 3px 0; padding-left: 16px; }
674
674
  .pr-md-ul li { margin: 1px 0; }
675
675
  .pr-md-code {
676
676
  padding: 0 4px; border-radius: 4px; background: var(--dsw-alias-bg-layer-2);
677
- font-size: 0.6875rem; font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
677
+ font-size: calc(11px + var(--dsh-content-font-delta, 0px)); font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
678
678
  }
679
679
  .pr-board-edit { min-height: 200px; max-height: 42vh; }
680
680
  .pr-board-actions { display: flex; gap: 8px; margin-top: 6px; align-items: center; }
@@ -700,10 +700,10 @@ window.__ModuleLoader__.load({
700
700
  overflow-wrap: anywhere;
701
701
  text-overflow: clip;
702
702
  }
703
- .pr-hint { font-size: 0.6875rem; color: var(--dsw-alias-label-secondary); padding: 6px 0; }
704
- .pr-err { font-size: 0.71875rem; color: #f87171; padding: 4px 0; }
703
+ .pr-hint { font-size: calc(11px + var(--dsh-content-font-delta, 0px)); color: var(--dsw-alias-label-secondary); padding: 6px 0; }
704
+ .pr-err { font-size: calc(11.5px + var(--dsh-content-font-delta, 0px)); color: #f87171; padding: 4px 0; }
705
705
  .pr-send-row { display: flex; gap: 6px; align-items: center; width: 100%; }
706
- .pr-select { max-width: 200px; height: 30px; padding: 0 6px; border-radius: 6px; border: 1px solid var(--dsw-alias-border-l1); background: var(--dsw-alias-bg-layer-1); color: var(--dsw-alias-label-primary); font-size: 0.75rem; }
706
+ .pr-select { max-width: 200px; height: 30px; padding: 0 6px; border-radius: 6px; border: 1px solid var(--dsw-alias-border-l1); background: var(--dsw-alias-bg-layer-1); color: var(--dsw-alias-label-primary); font-size: calc(12px + var(--dsh-content-font-delta, 0px)); }
707
707
  `;
708
708
 
709
709
  function ensureStyle() {
@@ -924,7 +924,11 @@ function summarizeMessage(raw) {
924
924
  const groups = React.useMemo(() => {
925
925
  const map = new Map();
926
926
  for (const [id, session] of Object.entries(byId)) {
927
- if (!session || session.blank) continue;
927
+ if (!session) continue;
928
+ // 2026-11-12:blank 会话原本一律不显示。但「+ 新项目」刚建出来的会话在首轮对话前
929
+ // 就是 blank,标题已是「项目 · 成员」——一并过滤会让新项目在侧栏彻底看不见
930
+ // (用户报「新项目建不了,没反应」)。所以 blank 只过滤**还没被命名**的空壳。
931
+ if (session.blank && !projectOfTitle(session.displayTitle || session.title)) continue;
928
932
  if (archived.has(String(id))) continue;
929
933
  // 2026-11-10(用户令):白名单改「事后隐藏」——只跳过**归档失败过**的会话,
930
934
  // 不再用磁盘白名单全量过滤(那样会让新建会话因轮询延迟而整段生命期不可见)。
@@ -1384,27 +1388,67 @@ function summarizeMessage(raw) {
1384
1388
  /** 设置:项目管理者名称(默认 Yat2,存 localStorage) */
1385
1389
  const renderSettings = () => {
1386
1390
  if (!settings) return null;
1387
- const save = () => {
1391
+ /**
1392
+ * 改名(2026-11-12 用户令「设置里面重命名之后所有管理者应该都重命名呀」):
1393
+ * 以前只写 localStorage,已有会话标题仍带旧名 → 排序/房间投递按新名匹配不到,
1394
+ * 管理者看着像「消失了」。现在改名后把所有 `<项目> · <旧名>` 的会话一并改成新名。
1395
+ */
1396
+ const save = async () => {
1388
1397
  const name = String(settings.manager || '').trim();
1389
1398
  if (!name) { setSettings({ ...settings, msg: '名称不能为空' }); return; }
1399
+ const oldName = managerName();
1390
1400
  try { window.localStorage.setItem('projectRoom.managerName', name); } catch { /* 存不了就本次生效 */ }
1391
- setSettings(null);
1401
+ if (name === oldName) { setSettings(null); return; }
1402
+
1403
+ // 找出所有「某项目 · 旧管理者名」的会话,逐个改标题
1404
+ const targets = [];
1405
+ for (const [id, session] of Object.entries(byId)) {
1406
+ if (!session) continue;
1407
+ const title = String(session.displayTitle || session.title || '');
1408
+ const parsed = projectOfTitle(title);
1409
+ if (!parsed) continue;
1410
+ if (parsed.member !== oldName) continue;
1411
+ targets.push({ id, project: parsed.project });
1412
+ }
1413
+ if (!targets.length) { setSettings(null); return; }
1414
+
1415
+ setSettings({ ...settings, busy: true, msg: `正在把 ${targets.length} 个管理者会话改名为「${name}」…` });
1416
+ let ok = 0;
1417
+ const failed = [];
1418
+ for (const t of targets) {
1419
+ try {
1420
+ const res = await fetch(`${API}/rename`, {
1421
+ method: 'POST', headers: { 'content-type': 'application/json' },
1422
+ body: JSON.stringify({ sessionId: t.id, title: `${t.project}${SEP}${name}` }),
1423
+ });
1424
+ const data = await res.json();
1425
+ // 坑:/project-room/rename 失败也返回 HTTP 200 + {ok:false},只看 res.ok 会漏判
1426
+ if (data && data.ok) ok += 1; else failed.push(`${t.project}(${(data && data.error) || '未知'})`);
1427
+ } catch (error) {
1428
+ failed.push(`${t.project}(${String((error && error.message) || error)})`);
1429
+ }
1430
+ }
1431
+ if (!failed.length) { setSettings(null); return; }
1432
+ setSettings({
1433
+ ...settings, busy: false,
1434
+ msg: `已改名 ${ok} 个;失败 ${failed.length} 个:${failed.slice(0, 3).join('、')}${failed.length > 3 ? '…' : ''}`,
1435
+ });
1392
1436
  };
1393
1437
  return h('div', { className: 'pr-modal', onClick: () => setSettings(null) },
1394
1438
  h('div', { className: 'pr-modal-box', onClick: (event) => event.stopPropagation() },
1395
1439
  h('div', { className: 'pr-modal-title' }, '设置'),
1396
- h('div', { className: 'pr-hint' }, '项目管理者名称(排序时永远排第一、新建项目的默认成员名)'),
1440
+ h('div', { className: 'pr-hint' }, '管理者名(每个项目排第一、新建项目的默认成员名;改名会把所有管理者会话一并改名)'),
1397
1441
  h('input', {
1398
1442
  className: 'pr-modal-input',
1399
1443
  value: settings.manager || '',
1400
1444
  autoFocus: true,
1401
1445
  placeholder: DEFAULT_MANAGER,
1446
+ disabled: Boolean(settings.busy),
1402
1447
  onChange: (event) => setSettings({ ...settings, manager: event.target.value, msg: '' }),
1403
1448
  onKeyDown: (event) => { if (event.key === 'Enter') save(); if (event.key === 'Escape') setSettings(null); },
1404
1449
  }),
1405
1450
  h('div', { className: 'pr-hint', style: { marginTop: '6px' } },
1406
- '注意:这只影响本插件的排序与默认名。若要让「管理者协议注入」也认这个名字,'
1407
- + '还需要改 hub-desktop-ui 里的 MANAGER_NAMES(那是另一个插件的硬编码)。'),
1451
+ '提示:改名只影响侧栏的排序、新建项目默认名与会话标题,DSH 里既有的会话标题会同步改。'),
1408
1452
  settings.msg ? h('div', { className: 'pr-err' }, settings.msg) : null,
1409
1453
  // 2026-11-10(用户令「事后隐藏」):归档失败过的会话被记进 localStorage 隐藏集,
1410
1454
  // 这里提供恢复入口,免得误隐藏之后找不回来。
@@ -1452,7 +1496,8 @@ function summarizeMessage(raw) {
1452
1496
  const submit = async () => {
1453
1497
  const project = String(newProject.name || '').trim();
1454
1498
  const member = String(newProject.member || managerName()).trim() || managerName();
1455
- if (!project) return;
1499
+ // 2026-11-12:空项目名原来直接 return,点「创建」毫无反馈(用户报「没反应」)。
1500
+ if (!project) { setNewProject({ ...newProject, msg: '请先填项目名' }); return; }
1456
1501
  setNewProject({ ...newProject, busy: true, msg: '创建中…' });
1457
1502
  try {
1458
1503
  const svc = clientCtx && typeof clientCtx.get === 'function' ? clientCtx.get('uiWorkspace') : null;
@@ -1464,17 +1509,37 @@ function summarizeMessage(raw) {
1464
1509
  const raw = await svc.connectWorkspace(workspaceId, { agentPreset: 'cordis' });
1465
1510
  sessionId = typeof raw === 'string' ? raw : ((raw && (raw.sessionId || raw.id)) || '');
1466
1511
  }
1467
- if (!sessionId && typeof svc.startSession === 'function') {
1468
- svc.startSession(workspaceId, { agentPreset: 'cordis' });
1512
+ // 2026-11-12:拿不到 id 时改走 `sessions.create`。不能只调 startSession——
1513
+ // 它返回 void,之后 sessionId 仍为空就不改名,弹窗静默关闭、列表毫无变化。
1514
+ if (!sessionId) {
1515
+ const sessionsSvc = clientCtx && typeof clientCtx.get === 'function' ? clientCtx.get('sessions') : null;
1516
+ if (sessionsSvc && typeof sessionsSvc.create === 'function') {
1517
+ sessionId = await sessionsSvc.create(
1518
+ workspaceId !== undefined ? { workspaceId, agentPreset: 'cordis' } : { agentPreset: 'cordis' },
1519
+ );
1520
+ }
1521
+ }
1522
+ if (!sessionId) {
1523
+ setNewProject({ ...newProject, busy: false, msg: '创建失败:没拿到新会话 id(先切一个工作区再试)' });
1524
+ return;
1469
1525
  }
1470
- if (sessionId) {
1471
- await fetch(`${API}/rename`, {
1472
- method: 'POST', headers: { 'content-type': 'application/json' },
1473
- body: JSON.stringify({ sessionId, title: `${project} · ${member}` }),
1474
- });
1526
+ const renameRes = await fetch(`${API}/rename`, {
1527
+ method: 'POST', headers: { 'content-type': 'application/json' },
1528
+ body: JSON.stringify({ sessionId, title: `${project} · ${member}` }),
1529
+ });
1530
+ // 宿主这条路由失败时也是 HTTP 200 + {ok:false},只看 res.ok 会漏判。
1531
+ let renameData = null;
1532
+ try { renameData = await renameRes.json(); } catch { renameData = null; }
1533
+ if (!renameRes.ok || !renameData || renameData.ok === false) {
1534
+ const why = (renameData && renameData.error) ? `:${renameData.error}` : '';
1535
+ setNewProject({ ...newProject, busy: false, msg: `会话已建,但改名失败(HTTP ${renameRes.status}${why})` });
1536
+ return;
1475
1537
  }
1476
1538
  // 初始化房间看板(不存在则建模板)
1477
1539
  try { await fetch(`${API}/board?project=${encodeURIComponent(project)}`, { method: 'POST' }); } catch { /* 看板可选 */ }
1540
+ // 2026-11-12:建完立刻打开该会话。此前只建不打开,而侧栏又不显示 blank 会话,
1541
+ // 用户点「创建」后界面上什么都没发生——这就是「新项目建不了,没反应」。
1542
+ openSessionById(sessionId);
1478
1543
  setNewProject(null);
1479
1544
  } catch (error) {
1480
1545
  setNewProject({ ...newProject, busy: false, msg: `失败:${String((error && error.message) || error)}` });
@@ -1492,15 +1557,15 @@ function summarizeMessage(raw) {
1492
1557
  onKeyDown: (event) => { if (event.key === 'Enter') submit(); if (event.key === 'Escape') setNewProject(null); },
1493
1558
  }),
1494
1559
  h('div', { style: { height: '8px' } }),
1495
- h('input', {
1496
- className: 'pr-modal-input',
1497
- placeholder: `成员的 agent 名(默认 ${managerName()})`,
1498
- value: newProject.member || '',
1499
- onChange: (event) => setNewProject({ ...newProject, member: event.target.value, msg: '' }),
1500
- onKeyDown: (event) => { if (event.key === 'Enter') submit(); if (event.key === 'Escape') setNewProject(null); },
1501
- }),
1502
- h('div', { style: { marginTop: '6px', fontSize: '10.5px', color: 'var(--dsw-alias-label-secondary)' } },
1503
- `创建后会话标题为「${String(newProject.name || '项目名').trim()} · ${String(newProject.member || 'Yat2').trim() || 'Yat2'}」`),
1560
+ // 2026-11-12 用户令:新建项目不再让用户填管理者名称,只留项目名;
1561
+ // 管理者名统一取 ⚙ 设置里的值(submit 里 member 为空即回落 managerName())。
1562
+ h('div', {
1563
+ style: {
1564
+ fontSize: 'calc(10.5px + var(--dsh-content-font-delta, 0px))',
1565
+ color: 'var(--dsw-alias-label-secondary)',
1566
+ },
1567
+ },
1568
+ `创建后会话标题为「${String(newProject.name || '项目名').trim()} · ${String(newProject.member || managerName()).trim() || managerName()}」,管理者名可在 ⚙ 设置里改`),
1504
1569
  newProject.msg ? h('div', { className: 'pr-hint' }, newProject.msg) : null,
1505
1570
  h('div', { className: 'pr-modal-actions' },
1506
1571
  h('button', { className: 'pr-btn', onClick: () => setNewProject(null), disabled: newProject.busy }, '取消'),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dsh-project-room",
3
- "version": "0.2.6",
3
+ "version": "0.2.8",
4
4
  "type": "module",
5
5
  "description": "Project rooms for DeepSeek Harness: group sessions into projects, see per-project runtime, and open a room with a shared board, task list, todo queue and message delivery to member sessions.",
6
6
  "main": "index.js",