dsh-ntr 0.2.0 → 0.2.1

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 CHANGED
@@ -2612,18 +2612,34 @@ window.__ModuleLoader__.load({
2612
2612
  --ntr-success: color-mix(in srgb, var(--dsw-alias-state-success-primary, #16a34a) 72%, var(--dsw-alias-label-primary, #111827));
2613
2613
  --ntr-accent: var(--dsw-alias-button-primary-fill, #2563eb);
2614
2614
  width: 100%; max-width: 960px; box-sizing: border-box; margin: 0 auto;
2615
- padding: 20px; overflow: auto; font-size: var(--ntr-font); line-height: 1.55;
2615
+ padding: 28px 32px; min-width: 0; container-type: inline-size; font-size: var(--ntr-font); line-height: 1.55;
2616
2616
  }
2617
- .dwa-root button, .dwa-root input, .dwa-root select { font-family: inherit; }
2617
+ .dwa-root [hidden] { display: none !important; }
2618
+ .dwa-root button, .dwa-root input, .dwa-root select, .dwa-root textarea { font-family: inherit; }
2619
+ .dwa-root input, .dwa-root textarea { min-width: 0; }
2620
+ .dwa-tabs { display: flex; gap: 24px; flex-wrap: wrap; border-bottom: var(--ntr-line); margin-bottom: 24px; }
2621
+ .dwa-tabs > button { font: inherit; color: var(--ntr-muted); background: transparent; border: 0; border-bottom: 2px solid transparent; padding: 0 0 12px; min-height: 40px; white-space: nowrap; cursor: pointer; }
2622
+ .dwa-tabs > button:hover { color: var(--dsw-alias-label-primary, #111827); }
2623
+ .dwa-tabs > button[aria-pressed="true"] { color: var(--dsw-alias-label-primary, #111827); border-bottom-color: currentColor; font-weight: 550; }
2624
+ .dwa-detail-tabs { margin: 4px 0 20px; gap: 20px; }
2625
+ .dwa-detail-tabs > button { font-size: var(--ntr-font-sm); }
2626
+ .dwa-row-actions { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
2627
+ .dwa-notice { display: flex; align-items: center; gap: 12px; margin-bottom: 16px; }
2628
+ .dwa-notice > span { flex: 1; min-width: 0; overflow-wrap: anywhere; }
2629
+ .dwa-empty { text-align: center; padding: 40px 16px; color: var(--ntr-muted); }
2630
+ .dwa-empty h3 { font-size: 16px; font-weight: 550; color: var(--dsw-alias-label-primary, #111827); margin: 0 0 8px; }
2631
+ .dwa-empty .dwa-btn { margin-top: 20px; }
2632
+ .dwa-health { display: flex; justify-content: space-between; align-items: center; gap: 12px; margin-top: 24px; color: var(--ntr-muted); font-size: var(--ntr-font-sm); flex-wrap: wrap; }
2633
+ .dwa-health-status { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
2634
+ .dwa-health-status > span:last-child:not(:nth-child(2)) { padding-left: 12px; border-left: var(--ntr-line); }
2635
+ .dwa-back { margin-bottom: 16px; }
2618
2636
  .dwa-root button:focus-visible, .dwa-root input:focus-visible, .dwa-root select:focus-visible {
2619
2637
  outline: 2px solid var(--ntr-accent); outline-offset: 2px;
2620
2638
  }
2621
- .dwa-page-header { display: flex; align-items: flex-start; justify-content: space-between; gap: 16px; margin-bottom: 20px; }
2639
+ .dwa-page-header { display: flex; align-items: center; justify-content: space-between; gap: 16px; margin-bottom: 28px; }
2622
2640
  .dwa-page-heading { min-width: 0; }
2623
- .dwa-page-title { margin: 0; font-size: 20px; line-height: 1.35; font-weight: 650; letter-spacing: -0.02em; }
2641
+ .dwa-page-title { margin: 0; font-size: 20px; line-height: 1.35; font-weight: 550; letter-spacing: -0.02em; }
2624
2642
  .dwa-page-description { margin: 5px 0 0; color: var(--ntr-muted); font-size: var(--ntr-font-sm); }
2625
- .dwa-page-status { display: flex; align-items: center; gap: 8px; margin-top: 10px; color: var(--ntr-muted); font-size: var(--ntr-font-xs); }
2626
- .dwa-page-actions { display: flex; align-items: center; gap: 8px; flex-shrink: 0; }
2627
2643
  .dwa-btn {
2628
2644
  min-height: 32px; box-sizing: border-box; font: inherit; border-radius: var(--ntr-radius-sm);
2629
2645
  border: 1px solid var(--dsw-alias-border-l2, #d1d5db); background: var(--dsw-alias-bg-layer-1, #fff);
@@ -2636,14 +2652,16 @@ window.__ModuleLoader__.load({
2636
2652
  .dwa-btn-primary { background: var(--ntr-accent); color: var(--dsw-alias-label-primary-foreground, #fff); border-color: transparent; font-weight: 550; }
2637
2653
  .dwa-btn-primary:hover { background: var(--ntr-accent); border-color: transparent; opacity: 0.88; }
2638
2654
  .dwa-btn-secondary { background: var(--dsw-alias-bg-layer-2, #f3f4f6); }
2655
+ .dwa-btn-quiet { background: transparent; border-color: transparent; color: var(--ntr-muted); }
2656
+ .dwa-btn-quiet:hover { border-color: transparent; color: var(--dsw-alias-label-primary, #111827); }
2639
2657
  .dwa-btn-danger { color: var(--ntr-danger); border-color: var(--dsw-alias-state-error-secondary, #fca5a5); }
2640
2658
  .dwa-btn-danger:hover { background: var(--dsw-alias-interactive-bg-hover-danger, #fee2e2); }
2641
2659
  .dwa-section { margin-bottom: 24px; }
2642
2660
  .dwa-section-heading { display: flex; align-items: flex-start; justify-content: space-between; gap: 12px; margin-bottom: 10px; }
2643
- .dwa-section-title { font-size: 14px; font-weight: 650; margin: 0; display: flex; align-items: center; gap: 8px; }
2661
+ .dwa-section-title { font-size: 13px; font-weight: 550; margin: 0; display: flex; align-items: center; gap: 8px; }
2644
2662
  .dwa-section-copy { margin: 3px 0 0; font-size: var(--ntr-font-xs); color: var(--ntr-muted); }
2645
2663
  .dwa-card { border: var(--ntr-line); border-radius: var(--ntr-radius); padding: 16px; background: var(--dsw-alias-bg-layer-1, #fff); font-size: var(--ntr-font); line-height: 1.55; }
2646
- .dwa-card-warn { border-left: 3px solid var(--dsw-alias-state-warn-primary, #d97706); background: var(--dsw-alias-state-warn-tertiary, #fffbeb); }
2664
+ .dwa-card-warn { border-color: color-mix(in srgb, var(--ntr-warn) 30%, var(--dsw-alias-border-l2, #e5e7eb)); background: var(--dsw-alias-state-warn-tertiary, #fffbeb); }
2647
2665
  .dwa-mode-banner { display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: 5px 16px; align-items: start; margin-bottom: 24px; padding: 14px 16px; }
2648
2666
  .dwa-mode-title { display: flex; align-items: center; gap: 8px; font-weight: 650; }
2649
2667
  .dwa-mode-copy { grid-column: 1 / -1; color: var(--ntr-muted); font-size: var(--ntr-font-xs); }
@@ -2653,25 +2671,21 @@ window.__ModuleLoader__.load({
2653
2671
  .dwa-badge-warn { background: var(--dsw-alias-state-warn-tertiary, #fef3c7); color: var(--ntr-warn); }
2654
2672
  .dwa-badge-info { background: var(--dsw-alias-state-business-tertiary, #dbeafe); color: var(--dsw-alias-state-business-primary, #2563eb); }
2655
2673
  .dwa-dot { width: 7px; height: 7px; border-radius: 50%; display: inline-block; flex-shrink: 0; }
2656
- .dwa-agent-list { display: flex; flex-direction: column; gap: 8px; }
2657
- .dwa-agent-card { border: var(--ntr-line); border-radius: var(--ntr-radius); background: var(--dsw-alias-bg-layer-1, #fff); overflow: visible; transition: border-color 0.15s ease; }
2658
- .dwa-agent-card.is-open { border-color: var(--dsw-alias-border-l1, #c7ccd1); }
2659
- .dwa-agent-row { display: grid; grid-template-columns: 28px minmax(0, 1fr) auto; align-items: center; gap: 10px; padding: 12px 14px; }
2674
+ .dwa-agent-list { display: flex; flex-direction: column; border-top: var(--ntr-line); }
2675
+ .dwa-agent-card { border-bottom: var(--ntr-line); min-width: 0; }
2676
+ .dwa-agent-row { display: grid; grid-template-columns: 38px minmax(0, 1fr) auto; align-items: center; gap: 14px; padding: 16px 0; }
2677
+ .dwa-agent-avatar { display: grid; place-items: center; width: 38px; height: 38px; border: var(--ntr-line); border-radius: 9px; background: var(--dsw-alias-bg-layer-2, #f3f4f6); color: var(--ntr-muted); font: 12px var(--ds-font-family-code, monospace); }
2660
2678
  .dwa-caret { font-size: 14px; line-height: 1; display: inline-flex; align-items: center; justify-content: center; width: 1em; }
2661
2679
  .dwa-caret-btn { font: inherit; border: none; background: var(--dsw-alias-bg-layer-2, #f3f4f6); width: 28px; height: 28px; padding: 0; border-radius: var(--ntr-radius-sm); display: inline-flex; align-items: center; justify-content: center; color: var(--ntr-muted); cursor: pointer; }
2662
2680
  .dwa-caret-btn:hover { background: var(--dsw-alias-interactive-bg-active, #e5e7eb); color: inherit; }
2663
2681
  .dwa-agent-summary { min-width: 0; }
2664
2682
  .dwa-agent-titleline { display: flex; align-items: center; gap: 8px; min-width: 0; flex-wrap: wrap; }
2665
- .dwa-agent-name { font-size: 13px; font-weight: 650; overflow-wrap: anywhere; }
2683
+ .dwa-agent-name { font-size: 13px; font-weight: 550; overflow-wrap: anywhere; }
2666
2684
  .dwa-agent-meta { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; margin-top: 4px; color: var(--ntr-muted); font-size: var(--ntr-font-xs); }
2667
2685
  .dwa-agent-meta-separator { opacity: 0.45; }
2668
- .dwa-agent-body { border-top: var(--ntr-line); padding: 0 16px 16px; }
2669
- .dwa-subsection { padding-top: 16px; }
2670
- .dwa-subsection + .dwa-subsection { margin-top: 16px; border-top: var(--ntr-line); }
2671
- .dwa-subsection-head { display: flex; align-items: flex-start; justify-content: space-between; gap: 12px; margin-bottom: 12px; }
2672
- .dwa-subsection-title { margin: 0; font-size: 13px; font-weight: 650; }
2673
- .dwa-subsection-copy { margin: 3px 0 0; color: var(--ntr-muted); font-size: var(--ntr-font-xs); }
2674
- .dwa-form-row { display: flex; gap: var(--ntr-gap-3); margin-bottom: 14px; align-items: flex-start; }
2686
+ .dwa-agent-body { padding: 0 0 24px 52px; }
2687
+ .dwa-subsection { min-width: 0; }
2688
+ .dwa-form-row { display: flex; gap: var(--ntr-gap-3); margin-bottom: 14px; align-items: stretch; }
2675
2689
  .dwa-form-col { flex: 1; display: flex; flex-direction: column; gap: 6px; min-width: 0; }
2676
2690
  .dwa-form-label { font-size: var(--ntr-font-sm); font-weight: 600; color: var(--dsw-alias-label-primary, #374151); }
2677
2691
  .dwa-hint { font-size: var(--ntr-font-xs); line-height: 1.55; color: var(--ntr-muted); }
@@ -2680,11 +2694,13 @@ window.__ModuleLoader__.load({
2680
2694
  .dwa-select { min-height: 32px; font: inherit; font-size: var(--ntr-font-sm); padding: 5px 8px; border: 1px solid var(--dsw-alias-border-l2, #d1d5db); border-radius: var(--ntr-radius-sm); background: var(--dsw-alias-bg-layer-1, #fff); color: inherit; }
2681
2695
  .dwa-input:hover, .dwa-select:hover { border-color: var(--dsw-alias-border-l1, #9ca3af); }
2682
2696
  .dwa-input:focus, .dwa-select:focus { border-color: var(--ntr-accent); }
2683
- .dwa-input-mono, .dwa-mono { font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace; }
2697
+ .dwa-input-mono, .dwa-mono { font-family: var(--ds-font-family-code, ui-monospace), SFMono-Regular, Menlo, Monaco, Consolas, monospace; }
2684
2698
  .dwa-stderr { max-height: 120px; overflow: auto; font-family: monospace; font-size: var(--ntr-font-xs); white-space: pre-wrap; color: var(--ntr-warn); margin: 12px 0 0; }
2685
2699
  .dwa-default-hint { background: var(--dsw-alias-bg-layer-2, #f9fafb); border: var(--ntr-line); border-radius: var(--ntr-radius-sm); padding: 10px 12px; font-size: var(--ntr-font-sm); display: flex; align-items: center; justify-content: space-between; margin: 12px 0 14px; gap: 12px; }
2686
2700
  .dwa-form-actions { display: flex; align-items: center; gap: 8px; margin-top: 16px; padding-top: 14px; border-top: var(--ntr-line); flex-wrap: wrap; }
2687
2701
  .dwa-form-actions .dwa-btn-primary { min-width: 88px; }
2702
+ .dwa-form-actions > .dwa-hint:first-child { margin-right: auto; }
2703
+ .dwa-form-actions > .dwa-hint:last-child:not(:first-child) { width: 100%; }
2688
2704
  .dwa-menu-wrap { position: relative; }
2689
2705
  .dwa-menu-wrap > .dwa-btn { width: 32px; padding: 0; }
2690
2706
  .dwa-menu { position: absolute; right: 0; top: calc(100% + 4px); z-index: 20; min-width: 190px; border: var(--ntr-line); border-radius: var(--ntr-radius-sm); background: var(--dsw-alias-bg-layer-1, #fff); box-shadow: 0 8px 24px rgba(0, 0, 0, 0.12); padding: 4px; display: flex; flex-direction: column; }
@@ -2692,10 +2708,10 @@ window.__ModuleLoader__.load({
2692
2708
  .dwa-menu-item:hover { background: var(--dsw-alias-interactive-bg-active, #f3f4f6); }
2693
2709
  .dwa-menu-item-danger { color: var(--ntr-danger); }
2694
2710
  .dwa-menu-confirm { display: flex; align-items: center; gap: 4px; padding: 4px; }
2695
- .dwa-add-panel { border: var(--ntr-line); border-radius: var(--ntr-radius); background: var(--dsw-alias-bg-layer-1, #fff); }
2696
- .dwa-add-toggle { width: 100%; border: 0; background: transparent; color: inherit; padding: 13px 16px; display: flex; align-items: center; justify-content: space-between; gap: 12px; text-align: left; cursor: pointer; border-radius: var(--ntr-radius); }
2697
- .dwa-add-toggle:hover { background: var(--dsw-alias-interactive-bg-active, #f9fafb); }
2698
- .dwa-add-content { border-top: var(--ntr-line); padding: 14px 16px 16px; }
2711
+ .dwa-add-panel .dwa-agent-row { display: none; }
2712
+ .dwa-add-panel .dwa-agent-body { padding: 0 0 24px; }
2713
+ .dwa-add-panel .dwa-agent-card { border: 0; }
2714
+ .dwa-add-content { padding-top: 10px; }
2699
2715
  .dwa-chip { min-height: 30px; font: inherit; font-size: var(--ntr-font-sm); border: var(--ntr-line); border-radius: 999px; padding: 4px 12px; background: var(--dsw-alias-bg-layer-1, #fff); cursor: pointer; color: inherit; }
2700
2716
  .dwa-chip:hover { background: var(--dsw-alias-interactive-bg-active, #f3f4f6); }
2701
2717
  .dwa-chip-active { border-color: var(--ntr-accent); background: color-mix(in srgb, var(--dsw-alias-state-business-primary, #2563eb) 8%, transparent); color: var(--dsw-alias-state-business-primary, #2563eb); font-weight: 550; }
@@ -2727,13 +2743,13 @@ window.__ModuleLoader__.load({
2727
2743
  .dwa-model-status { margin-left: auto; white-space: nowrap; }
2728
2744
  .dwa-model-search { width: 200px; min-height: 30px; }
2729
2745
  .dwa-model-empty { padding: 6px; }
2730
- .dwa-model-row { display: flex; align-items: center; gap: 6px; width: 100%; border: none; background: none; padding: 5px 6px; border-radius: 5px; cursor: pointer; color: inherit; font: inherit; font-size: var(--ntr-font-sm); text-align: left; }
2746
+ .dwa-model-row { display: flex; align-items: center; gap: 8px; width: 100%; min-height: 38px; border: none; background: none; padding: 7px 8px; border-radius: 5px; cursor: pointer; color: inherit; font: inherit; font-size: var(--ntr-font-sm); text-align: left; }
2731
2747
  .dwa-model-row:hover { background: var(--dsw-alias-interactive-bg-active, #f3f4f6); }
2732
2748
  .dwa-model-row.is-on { background: color-mix(in srgb, var(--dsw-alias-state-business-primary, #2563eb) 8%, transparent); color: var(--dsw-alias-state-business-primary, #2563eb); }
2733
2749
  .dwa-model-row-mark { width: 12px; flex: none; text-align: center; opacity: 0.75; }
2734
2750
  .dwa-model-row-name { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
2735
2751
  /* Name and credit keep their room; the id is the only cell that collapses. */
2736
- .dwa-model-row-desc { flex: 0 0 auto; max-width: 45%; opacity: 0.75; font-size: 10px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
2752
+ .dwa-model-row-desc { flex: 0 0 auto; max-width: 45%; opacity: 0.75; font-size: var(--ntr-font-sm); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
2737
2753
  /* The trailing 14px is reserved for the fade mask: while the id fits, the
2738
2754
  gradient only covers empty padding; once it overflows, its tail dissolves
2739
2755
  instead of ending in a hard ellipsis. armModelIdMarquee reads the same
@@ -2747,12 +2763,12 @@ window.__ModuleLoader__.load({
2747
2763
  }
2748
2764
  .dwa-model-row-remove { flex: none; opacity: 0.5; padding: 0 2px; }
2749
2765
  .dwa-model-row:hover .dwa-model-row-remove { opacity: 1; }
2750
- .dwa-seg { display: inline-flex; border-radius: var(--ntr-radius-sm); border: 1px solid var(--dsw-alias-border-l2, #d1d5db); overflow: hidden; vertical-align: middle; }
2751
- .dwa-seg > button { min-height: 30px; font: inherit; font-size: var(--ntr-font-sm); color: inherit; border: none; background: var(--dsw-alias-bg-layer-1, #fff); padding: 4px 14px; cursor: pointer; }
2752
- .dwa-seg > button + button { border-left: 1px solid var(--dsw-alias-border-l2, #d1d5db); }
2766
+ .dwa-seg { display: inline-flex; gap: 4px; padding: 4px; box-sizing: border-box; border-radius: var(--ntr-radius-sm); border: var(--ntr-line); background: var(--dsw-alias-bg-layer-2, #f3f4f6); vertical-align: middle; }
2767
+ .dwa-seg > button { min-height: 32px; font: inherit; font-size: var(--ntr-font-sm); color: var(--ntr-muted); border: 1px solid transparent; border-radius: 4px; background: transparent; padding: 4px 12px; cursor: pointer; white-space: nowrap; }
2753
2768
  .dwa-seg > button:hover { background: var(--dsw-alias-interactive-bg-active, #f3f4f6); }
2754
- .dwa-seg > button.is-on { background: var(--ntr-accent); color: var(--dsw-alias-label-primary-foreground, #fff); font-weight: 550; }
2755
- .dwa-preference-row { display: flex; align-items: center; justify-content: space-between; gap: 16px; padding: 10px 0; }
2769
+ .dwa-seg > button.is-on { background: var(--dsw-alias-bg-layer-1, #fff); border: var(--ntr-line); color: var(--dsw-alias-label-primary, #111827); font-weight: 550; }
2770
+ .dwa-preferences { border-top: var(--ntr-line); }
2771
+ .dwa-preference-row { display: flex; align-items: center; justify-content: space-between; gap: 16px; padding: 20px 0; }
2756
2772
  .dwa-preference-row + .dwa-preference-row { border-top: var(--ntr-line); }
2757
2773
  /* A control that needs the whole card: the label sits above it, not beside
2758
2774
  it. A right-aligned segmented control squeezed its labels into two lines
@@ -2777,13 +2793,20 @@ window.__ModuleLoader__.load({
2777
2793
  .dwa-deadline-warn { margin-top: 10px; padding: 9px 12px; border-left: 3px solid var(--dsw-alias-state-warn-primary, #d97706); background: var(--dsw-alias-state-warn-secondary, #fffbeb); border-radius: var(--ntr-radius-sm); font-size: var(--ntr-font-xs); line-height: 1.55; }
2778
2794
  .dwa-deadline-reset { display: flex; justify-content: flex-end; margin-top: 8px; }
2779
2795
  @media (max-width: 640px) {
2780
- .dwa-root { padding: 14px; }
2781
- .dwa-page-header { flex-direction: column; }
2782
- .dwa-page-actions { width: 100%; }
2783
- .dwa-page-actions .dwa-btn { width: 100%; }
2796
+ .dwa-root { padding: 20px 16px; }
2797
+ }
2798
+ @container (max-width: 640px) {
2799
+ .dwa-page-header { align-items: flex-start; flex-wrap: wrap; }
2800
+ .dwa-agent-body { padding-left: 0; }
2801
+ .dwa-agent-row { grid-template-columns: 32px minmax(0, 1fr) auto; gap: 10px; }
2802
+ .dwa-agent-avatar { width: 32px; height: 32px; }
2803
+ .dwa-section-heading { flex-wrap: wrap; }
2804
+ .dwa-tabs { gap: 20px; }
2805
+ .dwa-notice { flex-wrap: wrap; }
2806
+ .dwa-seg-wide > button { padding-inline: 5px; }
2784
2807
  .dwa-model-toolbar-actions { width: 100%; }
2785
2808
  .dwa-model-search { flex: 1 1 auto; width: auto; }
2786
- .dwa-subsection-head, .dwa-preference-row { align-items: flex-start; flex-direction: column; }
2809
+ .dwa-preference-row { align-items: flex-start; flex-direction: column; }
2787
2810
  .dwa-default-hint { align-items: flex-start; flex-direction: column; }
2788
2811
  /* The slider's scale: up to eight rungs with full unit words ("15 分钟")
2789
2812
  need a smaller face before they can collide on a narrow panel. The rung
@@ -3271,11 +3294,7 @@ window.__ModuleLoader__.load({
3271
3294
  children: acp.label("权限请求的等待时长与超时处理方式。", "How long to wait for a permission request, and what happens when nobody answers.")
3272
3295
  })] })
3273
3296
  }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
3274
- className: "dwa-card",
3275
- style: {
3276
- paddingTop: 4,
3277
- paddingBottom: 4
3278
- },
3297
+ className: "dwa-preferences",
3279
3298
  children: [
3280
3299
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)(DeadlineModeBlock, {
3281
3300
  acp,
@@ -3301,17 +3320,21 @@ window.__ModuleLoader__.load({
3301
3320
  })]
3302
3321
  });
3303
3322
  }
3304
- /** Settings configuration section for ACP agents. */
3305
3323
  function AcpSettingsSection(props) {
3306
3324
  const acp = props.acp;
3307
3325
  ensureStyle();
3308
3326
  const ui = useUi$1(acp);
3309
3327
  const ledger = permissionLedgerCard(ui);
3310
- const [addOpen, setAddOpen] = (0, react.useState)(true);
3328
+ const [page, setPage] = (0, react.useState)("agents");
3329
+ const [addOpen, setAddOpen] = (0, react.useState)(false);
3311
3330
  const [addTarget, setAddTarget] = (0, react.useState)(void 0);
3312
- const [createNonce, setCreateNonce] = (0, react.useState)(0);
3313
3331
  const { configured, available } = partitionAgents(ui.detectedAgents, ui.agents);
3314
3332
  const selected = addTarget ?? available[0] ?? NEW_AGENT_SEED;
3333
+ const openAdd = () => {
3334
+ setAddOpen(true);
3335
+ setPage("add");
3336
+ };
3337
+ const presetProblem = ui.preset !== void 0 && (!ui.preset.installed || ui.preset.problem !== void 0);
3315
3338
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
3316
3339
  className: "dwa-root",
3317
3340
  children: [
@@ -3319,39 +3342,18 @@ window.__ModuleLoader__.load({
3319
3342
  className: "dwa-page-header",
3320
3343
  children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
3321
3344
  className: "dwa-page-heading",
3322
- children: [
3323
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("h2", {
3324
- className: "dwa-page-title",
3325
- children: acp.label("NTR 智能体", "NTR Agents")
3326
- }),
3327
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
3328
- className: "dwa-page-description",
3329
- children: acp.label("管理智能体连接、可用模型与对话显示偏好。", "Manage agent connections, available models, and conversation display preferences.")
3330
- }),
3331
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
3332
- className: "dwa-page-status",
3333
- children: [
3334
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
3335
- className: "dwa-dot",
3336
- style: { background: ui.stream === "live" ? "var(--dsw-alias-state-success-primary, #22c55e)" : ui.stream === "down" ? "var(--dsw-alias-state-error-primary, #ef4444)" : "var(--dsw-alias-state-idle-primary, #9ca3af)" },
3337
- title: ui.stream
3338
- }),
3339
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: streamText(ui.stream, acp) }),
3340
- ui.detectSummary !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", { children: ["· ", ui.detectSummary] })
3341
- ]
3342
- })
3343
- ]
3344
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
3345
- className: "dwa-page-actions",
3346
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
3347
- className: "dwa-btn",
3348
- onClick: () => {
3349
- acp.resync();
3350
- acp.detectAgents();
3351
- },
3352
- disabled: ui.detecting,
3353
- children: ui.detecting ? acp.label("检测中...", "Detecting...") : acp.label("重新检测与刷新", "Re-detect & Refresh")
3354
- })
3345
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("h2", {
3346
+ className: "dwa-page-title",
3347
+ children: acp.label("NTR 设置", "NTR settings")
3348
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
3349
+ className: "dwa-page-description",
3350
+ children: acp.label("连接智能体,设置你的对话偏好。", "Connect agents and set your conversation preferences.")
3351
+ })]
3352
+ }), page === "agents" && configured.length > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
3353
+ type: "button",
3354
+ className: "dwa-btn dwa-btn-primary",
3355
+ onClick: openAdd,
3356
+ children: acp.label("添加智能体", "Add agent")
3355
3357
  })]
3356
3358
  }),
3357
3359
  ledger.visible && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
@@ -3393,18 +3395,20 @@ window.__ModuleLoader__.load({
3393
3395
  })]
3394
3396
  }),
3395
3397
  permission.options.map((option) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
3396
- className: "dwa-btn dwa-btn-primary",
3398
+ type: "button",
3399
+ className: "dwa-btn",
3397
3400
  onClick: () => {
3398
3401
  acp.respondPermission(permission.requestId, option.optionId).catch(() => void 0);
3399
3402
  },
3400
3403
  children: option.name
3401
3404
  }, option.optionId)),
3402
3405
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
3403
- className: "dwa-btn",
3406
+ type: "button",
3407
+ className: "dwa-btn dwa-btn-quiet",
3404
3408
  onClick: () => {
3405
3409
  acp.respondPermission(permission.requestId).catch(() => void 0);
3406
3410
  },
3407
- children: acp.label("拒绝", "Dismiss")
3411
+ children: acp.label("取消", "Cancel")
3408
3412
  })
3409
3413
  ]
3410
3414
  }, permission.requestId))
@@ -3422,12 +3426,81 @@ window.__ModuleLoader__.load({
3422
3426
  style: { flex: 1 },
3423
3427
  children: ui.notice
3424
3428
  }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
3425
- className: "dwa-btn",
3429
+ type: "button",
3430
+ className: "dwa-btn dwa-btn-quiet",
3431
+ "aria-label": acp.label("关闭通知", "Dismiss notice"),
3426
3432
  onClick: () => acp.clearNotice(),
3427
3433
  children: "✕"
3428
3434
  })]
3429
3435
  }),
3430
- ui.preset !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
3436
+ presetProblem && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
3437
+ className: "dwa-card dwa-card-warn dwa-notice",
3438
+ role: "status",
3439
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: acp.label("NTR 模式需要检查,当前可能无法开始对话。", "NTR mode needs attention; new conversations may be unavailable.") }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
3440
+ type: "button",
3441
+ className: "dwa-btn",
3442
+ onClick: () => setPage("diagnostics"),
3443
+ children: acp.label("查看诊断", "View diagnostics")
3444
+ })]
3445
+ }),
3446
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("nav", {
3447
+ className: "dwa-tabs",
3448
+ "aria-label": acp.label("NTR 设置分类", "NTR settings categories"),
3449
+ children: [
3450
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
3451
+ type: "button",
3452
+ "aria-pressed": page === "agents",
3453
+ onClick: () => setPage("agents"),
3454
+ children: acp.label("智能体", "Agents")
3455
+ }),
3456
+ ui.approvalDeadlines !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
3457
+ type: "button",
3458
+ "aria-pressed": page === "approvals",
3459
+ onClick: () => setPage("approvals"),
3460
+ children: acp.label("审批时限", "Approval deadlines")
3461
+ }),
3462
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
3463
+ type: "button",
3464
+ "aria-pressed": page === "appearance",
3465
+ onClick: () => setPage("appearance"),
3466
+ children: acp.label("对话外观", "Appearance")
3467
+ })
3468
+ ]
3469
+ }),
3470
+ page === "diagnostics" && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
3471
+ className: "dwa-section",
3472
+ children: [
3473
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("h3", {
3474
+ className: "dwa-section-title",
3475
+ children: acp.label("连接诊断", "Connection diagnostics")
3476
+ }),
3477
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
3478
+ className: "dwa-preference-row",
3479
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: acp.label("宿主事件流", "Host event stream") }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
3480
+ className: "dwa-hint",
3481
+ children: streamText(ui.stream, acp)
3482
+ })]
3483
+ }),
3484
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
3485
+ className: "dwa-row-actions",
3486
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
3487
+ type: "button",
3488
+ className: "dwa-btn",
3489
+ onClick: () => {
3490
+ acp.resync();
3491
+ acp.detectAgents();
3492
+ },
3493
+ disabled: ui.detecting,
3494
+ children: ui.detecting ? acp.label("检测中...", "Detecting...") : acp.label("重新检测与刷新", "Re-detect & Refresh")
3495
+ }), ui.detectSummary !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
3496
+ className: "dwa-hint",
3497
+ role: "status",
3498
+ children: ui.detectSummary
3499
+ })]
3500
+ })
3501
+ ]
3502
+ }),
3503
+ page === "diagnostics" && ui.preset !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
3431
3504
  className: "dwa-card dwa-mode-banner",
3432
3505
  children: [
3433
3506
  /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
@@ -3460,28 +3533,42 @@ window.__ModuleLoader__.load({
3460
3533
  }),
3461
3534
  /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
3462
3535
  className: "dwa-section",
3536
+ hidden: page !== "agents",
3537
+ "aria-label": acp.label("已接入的智能体", "Connected agents"),
3463
3538
  children: [
3464
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
3539
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
3465
3540
  className: "dwa-section-heading",
3466
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("h3", {
3541
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", { children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("h3", {
3467
3542
  className: "dwa-section-title",
3468
- children: [acp.label("已接入的智能体", "Connected agents"), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
3543
+ children: [acp.label("已接入的智能体", "Connected agents"), ui.agentsLoaded && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
3469
3544
  className: "dwa-badge",
3470
3545
  children: configured.length
3471
3546
  })]
3472
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
3473
- className: "dwa-section-copy",
3474
- children: acp.label("展开智能体可管理模型、启动命令与工作区。", "Expand an agent to manage its models, launch command, and workspace.")
3475
- })] })
3547
+ }) }), configured.length > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
3548
+ className: "dwa-hint",
3549
+ children: acp.label("默认项用于新的 NTR 会话", "The default serves new NTR conversations")
3550
+ })]
3476
3551
  }),
3477
- configured.length === 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
3478
- className: "dwa-card",
3479
- style: {
3480
- textAlign: "center",
3481
- color: "var(--ntr-muted)",
3482
- padding: 20
3483
- },
3484
- children: acp.label("尚未启用任何 Agent。从下方「添加智能体」点一个检测到的预设(会展开预填命令的创建卡),再点「保存并启用」;也可以直接新建自定义 Agent。", "No agents configured yet. Pick a detected preset from \"Add agent\" below (it opens a creation card prefilled with its command), then click \"Save & Enable\" — or create a custom one from scratch.")
3552
+ !ui.agentsLoaded && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
3553
+ className: "dwa-empty",
3554
+ role: "status",
3555
+ children: acp.label("正在读取智能体…", "Loading agents…")
3556
+ }),
3557
+ ui.agentsLoaded && configured.length === 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
3558
+ className: "dwa-empty",
3559
+ children: [
3560
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("h3", { children: acp.label("接入第一个智能体", "Connect your first agent") }),
3561
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
3562
+ className: "dwa-section-copy",
3563
+ children: acp.label("选择已有预设,或填写自己的 ACP 启动命令。", "Choose a preset or enter your own ACP launch command.")
3564
+ }),
3565
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
3566
+ type: "button",
3567
+ className: "dwa-btn dwa-btn-primary",
3568
+ onClick: openAdd,
3569
+ children: acp.label("添加智能体", "Add agent")
3570
+ })
3571
+ ]
3485
3572
  }),
3486
3573
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
3487
3574
  className: "dwa-agent-list",
@@ -3492,36 +3579,33 @@ window.__ModuleLoader__.load({
3492
3579
  activeAgent,
3493
3580
  acp,
3494
3581
  isDefault: ui.defaultAgent === info.id,
3495
- synthesized
3582
+ synthesized,
3583
+ active: page === "agents"
3496
3584
  }, info.id);
3497
3585
  })
3498
3586
  })
3499
3587
  ]
3500
3588
  }),
3501
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("section", {
3589
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
3502
3590
  className: "dwa-section",
3503
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
3591
+ hidden: page !== "add",
3592
+ "aria-label": acp.label("添加智能体", "Add agent"),
3593
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
3594
+ type: "button",
3595
+ className: "dwa-btn dwa-btn-quiet dwa-back",
3596
+ onClick: () => setPage("agents"),
3597
+ children: acp.label("返回智能体列表", "Back to agents")
3598
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
3504
3599
  className: "dwa-add-panel",
3505
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
3506
- type: "button",
3507
- className: "dwa-add-toggle",
3508
- "aria-expanded": addOpen,
3509
- onClick: () => setAddOpen((open) => !open),
3510
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
3600
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
3601
+ className: "dwa-section-heading",
3602
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("h3", {
3511
3603
  className: "dwa-section-title",
3512
3604
  children: acp.label("添加智能体", "Add agent")
3513
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
3605
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
3514
3606
  className: "dwa-section-copy",
3515
- style: { display: "block" },
3516
3607
  children: acp.label("从预设快速启用,或创建自定义连接。", "Enable a preset or create a custom connection.")
3517
- })] }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
3518
- className: "dwa-caret-btn",
3519
- "aria-hidden": true,
3520
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
3521
- className: "dwa-caret",
3522
- children: addOpen ? "▾" : "▸"
3523
- })
3524
- })]
3608
+ })] })
3525
3609
  }), addOpen && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
3526
3610
  className: "dwa-add-content",
3527
3611
  children: [
@@ -3551,21 +3635,28 @@ window.__ModuleLoader__.load({
3551
3635
  isDefault: false,
3552
3636
  synthesized: false,
3553
3637
  newCustom: selected.id === "",
3638
+ active: page === "add",
3554
3639
  onCreated: () => {
3555
3640
  setAddTarget(void 0);
3556
- setCreateNonce((nonce) => nonce + 1);
3641
+ setAddOpen(false);
3642
+ setPage("agents");
3557
3643
  }
3558
- }, selected.id === "" ? `custom-${createNonce}` : selected.id)
3644
+ }, selected.id)
3559
3645
  ]
3560
3646
  })]
3561
- })
3647
+ })]
3562
3648
  }),
3563
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ApprovalDeadlinesCard, {
3564
- acp,
3565
- ui
3649
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
3650
+ hidden: page !== "approvals",
3651
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ApprovalDeadlinesCard, {
3652
+ acp,
3653
+ ui
3654
+ })
3566
3655
  }),
3567
3656
  /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
3568
3657
  className: "dwa-section",
3658
+ hidden: page !== "appearance",
3659
+ "aria-label": acp.label("对话外观", "Appearance"),
3569
3660
  children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
3570
3661
  className: "dwa-section-heading",
3571
3662
  children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("h3", {
@@ -3576,11 +3667,7 @@ window.__ModuleLoader__.load({
3576
3667
  children: acp.label("设置对话中 NTR 挂牌的进程存活提示。", "Choose how the NTR tag indicates a running agent process.")
3577
3668
  })] })
3578
3669
  }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
3579
- className: "dwa-card",
3580
- style: {
3581
- paddingTop: 4,
3582
- paddingBottom: 4
3583
- },
3670
+ className: "dwa-preferences",
3584
3671
  children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
3585
3672
  className: "dwa-preference-row",
3586
3673
  children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
@@ -3627,15 +3714,35 @@ window.__ModuleLoader__.load({
3627
3714
  })]
3628
3715
  })]
3629
3716
  })]
3717
+ }),
3718
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("footer", {
3719
+ className: "dwa-health",
3720
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
3721
+ className: "dwa-health-status",
3722
+ children: [
3723
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
3724
+ className: "dwa-dot",
3725
+ style: { background: ui.stream === "live" ? "var(--ntr-success)" : ui.stream === "down" ? "var(--ntr-danger)" : "var(--ntr-muted)" }
3726
+ }),
3727
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: streamText(ui.stream, acp) }),
3728
+ ui.preset !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: ui.preset.installed && !presetProblem ? acp.label("NTR 模式已就绪", "NTR mode ready") : acp.label("NTR 模式需检查", "NTR mode needs attention") })
3729
+ ]
3730
+ }), page !== "diagnostics" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
3731
+ type: "button",
3732
+ className: "dwa-btn dwa-btn-quiet",
3733
+ onClick: () => setPage("diagnostics"),
3734
+ children: acp.label("查看诊断", "View diagnostics")
3735
+ })]
3630
3736
  })
3631
3737
  ]
3632
3738
  });
3633
3739
  }
3634
3740
  /** One row per agent: compact when collapsed, the full form when expanded. */
3635
- function AgentRow({ detected, activeAgent, acp, isDefault, synthesized, newCustom = false, onCreated }) {
3741
+ function AgentRow({ detected, activeAgent, acp, isDefault, synthesized, active, newCustom = false, onCreated }) {
3636
3742
  const ui = useUi$1(acp);
3637
3743
  const configured = activeAgent !== void 0 || detected.currentConfig !== void 0;
3638
3744
  const [expanded, setExpanded] = (0, react.useState)(!configured);
3745
+ const [detailPage, setDetailPage] = (0, react.useState)(configured ? "models" : "connection");
3639
3746
  const [form, setForm] = (0, react.useState)(() => initialForm(detected, activeAgent));
3640
3747
  const [saving, setSaving] = (0, react.useState)(false);
3641
3748
  const [savedSuccess, setSavedSuccess] = (0, react.useState)(false);
@@ -3671,7 +3778,9 @@ window.__ModuleLoader__.load({
3671
3778
  const formIncomplete = splitCommandLine(form.commandLine).command === "" || !idValid || idTaken || cwdInvalid || rootsInvalid || idleInvalid || mcpInvalid;
3672
3779
  const payload = buildPayload(form, detected, newCustom);
3673
3780
  const current = persistedDef(detected, activeAgent);
3674
- const showSaveWarning = current !== void 0 && !payloadEquals(payload, current) && activeAgent !== void 0 && activeAgent.state !== "stopped";
3781
+ const clearingIdleOverride = payload.idleTimeoutMs === void 0 && detected.currentConfig?.idleTimeoutMs !== void 0;
3782
+ const dirty = current !== void 0 && (!payloadEquals(payload, current) || clearingIdleOverride);
3783
+ const showSaveWarning = dirty && activeAgent !== void 0 && activeAgent.state !== "stopped";
3675
3784
  const handleUseDefault = () => patch({ commandLine: formatCommandLine(detected.defaultCommand, detected.defaultArgs) });
3676
3785
  const handleSave = async () => {
3677
3786
  setSaving(true);
@@ -3711,7 +3820,7 @@ window.__ModuleLoader__.load({
3711
3820
  const displayName = newCustom ? acp.label("新建自定义 Agent", "New Custom Agent") : activeAgent?.title ?? detected.currentConfig?.title ?? detected.name;
3712
3821
  const stderr = activeAgent?.state === "error" ? activeAgent.stderrTail ?? [] : [];
3713
3822
  const errorSummary = stderr.length > 0 ? stderr[stderr.length - 1] : void 0;
3714
- const currentModel = ui.modelCatalogs[detected.id]?.catalog.model?.currentValue;
3823
+ const selectedModelCount = form.exposed?.length ?? 0;
3715
3824
  const isPreset = PRESET_IDS.has(detected.id);
3716
3825
  const open = expanded || activeAgent?.state === "error" && configured;
3717
3826
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
@@ -3719,17 +3828,10 @@ window.__ModuleLoader__.load({
3719
3828
  children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
3720
3829
  className: "dwa-agent-row",
3721
3830
  children: [
3722
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
3723
- type: "button",
3724
- className: "dwa-caret-btn",
3725
- "aria-expanded": open,
3726
- onClick: () => setExpanded((value) => !value),
3727
- title: open ? acp.label("收起", "Collapse") : acp.label("展开配置与模型", "Expand configuration and models"),
3728
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
3729
- className: "dwa-caret",
3730
- "aria-hidden": true,
3731
- children: open ? "▾" : "▸"
3732
- })
3831
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
3832
+ className: "dwa-agent-avatar",
3833
+ "aria-hidden": true,
3834
+ children: displayName.slice(0, 2).toUpperCase()
3733
3835
  }),
3734
3836
  /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
3735
3837
  className: "dwa-agent-summary",
@@ -3743,7 +3845,7 @@ window.__ModuleLoader__.load({
3743
3845
  children: displayName
3744
3846
  }),
3745
3847
  isDefault && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
3746
- className: "dwa-badge dwa-badge-success",
3848
+ className: "dwa-badge dwa-badge-info",
3747
3849
  children: acp.label("默认", "Default")
3748
3850
  }),
3749
3851
  !isPreset && !newCustom && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
@@ -3770,7 +3872,7 @@ window.__ModuleLoader__.load({
3770
3872
  configured && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [state !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
3771
3873
  className: "dwa-agent-meta-separator",
3772
3874
  children: "·"
3773
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: currentModel === void 0 ? acp.label("未探测模型", "Model not probed") : `${acp.label("模型", "Model")}: ${currentModel}` })] }),
3875
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: acp.label(`${String(selectedModelCount)} 个已选模型`, `${String(selectedModelCount)} selected models`) })] }),
3774
3876
  !synthesized && !newCustom && !detected.detected && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
3775
3877
  style: { color: "var(--ntr-warn)" },
3776
3878
  title: detected.description,
@@ -3789,24 +3891,31 @@ window.__ModuleLoader__.load({
3789
3891
  ]
3790
3892
  }),
3791
3893
  /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
3792
- style: {
3793
- display: "flex",
3794
- alignItems: "center",
3795
- gap: 6
3796
- },
3797
- children: [activeAgent?.state === "error" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
3798
- className: "dwa-btn",
3799
- disabled: testing,
3800
- onClick: () => void handleTest(),
3801
- children: testing ? acp.label("测试中...", "Testing...") : acp.label("测试", "Test")
3802
- }), configured && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(RowMenu, {
3803
- acp,
3804
- canStop: activeAgent !== void 0 && activeAgent.state !== "stopped",
3805
- onStop: () => void acp.stopAgent(detected.id),
3806
- onRemove: async () => {
3807
- await acp.deleteAgent(detected.id).catch(() => {});
3808
- }
3809
- })]
3894
+ className: "dwa-row-actions",
3895
+ children: [
3896
+ configured && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
3897
+ type: "button",
3898
+ className: "dwa-btn dwa-btn-quiet",
3899
+ "aria-expanded": open,
3900
+ "aria-label": acp.label(`${open ? "收起" : "管理"} ${displayName}`, `${open ? "Collapse" : "Manage"} ${displayName}`),
3901
+ onClick: () => setExpanded((value) => !value),
3902
+ children: open ? acp.label("收起", "Collapse") : acp.label("管理", "Manage")
3903
+ }),
3904
+ activeAgent?.state === "error" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
3905
+ className: "dwa-btn",
3906
+ disabled: testing,
3907
+ onClick: () => void handleTest(),
3908
+ children: testing ? acp.label("测试中...", "Testing...") : acp.label("测试", "Test")
3909
+ }),
3910
+ configured && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(RowMenu, {
3911
+ acp,
3912
+ canStop: activeAgent !== void 0 && activeAgent.state !== "stopped",
3913
+ onStop: () => void acp.stopAgent(detected.id),
3914
+ onRemove: async () => {
3915
+ await acp.deleteAgent(detected.id).catch(() => {});
3916
+ }
3917
+ })
3918
+ ]
3810
3919
  })
3811
3920
  ]
3812
3921
  }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
@@ -3817,42 +3926,52 @@ window.__ModuleLoader__.load({
3817
3926
  className: "dwa-stderr",
3818
3927
  children: stderr.join("\n")
3819
3928
  }),
3820
- configured && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
3929
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("nav", {
3930
+ className: "dwa-tabs dwa-detail-tabs",
3931
+ "aria-label": acp.label(`${displayName} 配置`, `${displayName} settings`),
3932
+ children: [
3933
+ configured && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
3934
+ type: "button",
3935
+ "aria-pressed": detailPage === "models",
3936
+ onClick: () => setDetailPage("models"),
3937
+ children: acp.label("模型", "Models")
3938
+ }),
3939
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
3940
+ type: "button",
3941
+ "aria-pressed": detailPage === "connection",
3942
+ onClick: () => setDetailPage("connection"),
3943
+ children: acp.label("连接", "Connection")
3944
+ }),
3945
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
3946
+ type: "button",
3947
+ "aria-pressed": detailPage === "advanced",
3948
+ onClick: () => setDetailPage("advanced"),
3949
+ children: acp.label("高级", "Advanced")
3950
+ })
3951
+ ]
3952
+ }),
3953
+ configured && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("section", {
3821
3954
  className: "dwa-subsection",
3822
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
3823
- className: "dwa-subsection-head",
3824
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("h4", {
3825
- className: "dwa-subsection-title",
3826
- children: acp.label("模型与默认值", "Models & defaults")
3827
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
3828
- className: "dwa-subsection-copy",
3829
- children: acp.label("检测模型目录,并控制对话中可选择的模型。", "Detect the model catalog and choose what appears in conversations.")
3830
- })] })
3831
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ModelCatalogBlock, {
3955
+ hidden: detailPage !== "models",
3956
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ModelCatalogBlock, {
3832
3957
  agentId: detected.id,
3833
3958
  detected,
3834
3959
  acp,
3835
- active: open,
3960
+ active: active && open && detailPage === "models",
3836
3961
  exposed: form.exposed,
3837
3962
  onExposedChange: (exposed) => patch({ exposed }),
3838
3963
  autoDiscover: form.autoDiscoverModels,
3839
3964
  onAutoDiscoverChange: (autoDiscoverModels) => patch({ autoDiscoverModels }),
3840
3965
  isDefault
3841
- })]
3966
+ })
3842
3967
  }),
3843
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
3968
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("section", {
3844
3969
  className: "dwa-subsection",
3845
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
3846
- className: "dwa-subsection-head",
3847
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("h4", {
3848
- className: "dwa-subsection-title",
3849
- children: acp.label("连接配置", "Connection")
3850
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
3851
- className: "dwa-subsection-copy",
3852
- children: acp.label("设置显示名与启动命令,高级选项按需展开。", "Set the display name and launch command; expand advanced options only when needed.")
3853
- })] })
3854
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(AgentDetails, {
3970
+ hidden: detailPage === "models",
3971
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(AgentDetails, {
3855
3972
  acp,
3973
+ advancedOpen: detailPage === "advanced",
3974
+ dirty,
3856
3975
  detected,
3857
3976
  form,
3858
3977
  patch,
@@ -3873,7 +3992,7 @@ window.__ModuleLoader__.load({
3873
3992
  onUseDefault: handleUseDefault,
3874
3993
  onSave: () => void handleSave(),
3875
3994
  onTest: () => void handleTest()
3876
- })]
3995
+ })
3877
3996
  })
3878
3997
  ]
3879
3998
  })]
@@ -3976,111 +4095,90 @@ window.__ModuleLoader__.load({
3976
4095
  return payload;
3977
4096
  }
3978
4097
  /** The expanded body: connection form, workspace allow-list, env, actions. */
3979
- function AgentDetails({ acp, detected, form, patch, isConfigured, newCustom, formIncomplete, idValid, idTaken, cwdInvalid, rootsInvalid, idleInvalid, mcpInvalid, saving, savedSuccess, testing, testResult, showSaveWarning, onUseDefault, onSave, onTest }) {
3980
- useUi$1(acp);
3981
- const [advancedOpen, setAdvancedOpen] = (0, react.useState)(false);
4098
+ function AgentDetails({ acp, advancedOpen, dirty, detected, form, patch, isConfigured, newCustom, formIncomplete, idValid, idTaken, cwdInvalid, rootsInvalid, idleInvalid, mcpInvalid, saving, savedSuccess, testing, testResult, showSaveWarning, onUseDefault, onSave, onTest }) {
3982
4099
  const parsedCommand = splitCommandLine(form.commandLine);
3983
4100
  const commandPreview = parsedCommand.command === "" ? acp.label("填整条命令,例如:codebuddy --acp", "Type the whole command, e.g. codebuddy --acp") : `${acp.label("程序", "Program")}: ${parsedCommand.command}` + (parsedCommand.args.length === 0 ? "" : ` ${acp.label("参数", "Arguments")}: ${parsedCommand.args.join(" ")}`);
3984
4101
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", { children: [
3985
- newCustom && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
3986
- className: "dwa-form-row",
3987
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
3988
- className: "dwa-form-col",
3989
- children: [
3990
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("label", {
3991
- className: "dwa-form-label",
3992
- children: acp.label("Agent ID(唯一标识,创建后不可改)", "Agent ID (unique, immutable after creation)")
3993
- }),
3994
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
3995
- className: "dwa-input dwa-input-mono",
3996
- value: form.agentId,
3997
- onChange: (e) => patch({ agentId: e.target.value }),
3998
- placeholder: "e.g. my-agent"
3999
- }),
4000
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
4001
- className: idValid && !idTaken ? "dwa-hint" : "dwa-error",
4002
- children: idTaken ? acp.label("该 ID 已被现有 Agent 占用。", "This id is already taken by a configured agent.") : idValid ? acp.label("小写字母或数字开头,可用 a-z 0-9 . _ -,最长 64 字符。", "Starts with a lowercase letter or digit; a-z 0-9 . _ - allowed; max 64 chars.") : acp.label("ID 格式不合法:小写字母或数字开头,可用 a-z 0-9 . _ -。", "Invalid id: start with a lowercase letter or digit; only a-z 0-9 . _ - allowed.")
4003
- })
4004
- ]
4005
- })
4006
- }),
4007
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
4008
- className: "dwa-form-row",
4009
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
4010
- className: "dwa-form-col",
4011
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("label", {
4012
- className: "dwa-form-label",
4013
- children: acp.label("显示名", "Display Name")
4014
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
4015
- className: "dwa-input",
4016
- value: form.title,
4017
- onChange: (e) => patch({ title: e.target.value }),
4018
- placeholder: detected.name === "" ? acp.label("我的 Agent", "My Agent") : detected.name
4019
- })]
4020
- })
4021
- }),
4022
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
4023
- className: "dwa-form-row",
4024
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
4025
- className: "dwa-form-col",
4026
- children: [
4027
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("label", {
4028
- className: "dwa-form-label",
4029
- children: acp.label("启动命令(程序 + 参数)", "Launch Command (program + arguments)")
4030
- }),
4031
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
4032
- className: "dwa-input dwa-input-mono",
4033
- value: form.commandLine,
4034
- onChange: (e) => patch({ commandLine: e.target.value }),
4035
- placeholder: detected.defaultCommand === "" ? "e.g. codebuddy --acp" : formatCommandLine(detected.defaultCommand, detected.defaultArgs)
4036
- }),
4037
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
4038
- className: "dwa-hint",
4039
- children: commandPreview
4040
- }),
4041
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
4042
- className: "dwa-hint",
4043
- children: acp.label("参数直接跟在程序后面即可;路径里含空格时用引号包住整条路径,例如 \"C:\\Program Files\\nodejs\\node.exe\" --acp。", "Arguments go right after the program; quote a whole path that contains spaces, e.g. \"C:\\Program Files\\nodejs\\node.exe\" --acp.")
4044
- })
4045
- ]
4046
- })
4047
- }),
4048
4102
  /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
4049
- style: {
4050
- display: "flex",
4051
- alignItems: "center",
4052
- gap: 8,
4053
- marginTop: 12,
4054
- flexWrap: "wrap"
4055
- },
4103
+ hidden: advancedOpen,
4056
4104
  children: [
4057
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
4058
- type: "button",
4059
- className: "dwa-btn dwa-btn-secondary",
4060
- "aria-expanded": advancedOpen,
4061
- onClick: () => setAdvancedOpen((value) => !value),
4062
- children: [
4063
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
4064
- className: "dwa-caret",
4065
- "aria-hidden": true,
4066
- children: advancedOpen ? "▾" : "▸"
4067
- }),
4068
- " ",
4069
- acp.label("高级参数", "Advanced Parameters")
4070
- ]
4105
+ newCustom && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
4106
+ className: "dwa-form-row",
4107
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
4108
+ className: "dwa-form-col",
4109
+ children: [
4110
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("label", {
4111
+ className: "dwa-form-label",
4112
+ children: acp.label("Agent ID(唯一标识,创建后不可改)", "Agent ID (unique, immutable after creation)")
4113
+ }),
4114
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
4115
+ className: "dwa-input dwa-input-mono",
4116
+ "aria-label": acp.label("Agent ID", "Agent ID"),
4117
+ value: form.agentId,
4118
+ onChange: (e) => patch({ agentId: e.target.value }),
4119
+ placeholder: "e.g. my-agent"
4120
+ }),
4121
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
4122
+ className: idValid && !idTaken ? "dwa-hint" : "dwa-error",
4123
+ children: idTaken ? acp.label("该 ID 已被现有 Agent 占用。", "This id is already taken by a configured agent.") : idValid ? acp.label("小写字母或数字开头,可用 a-z 0-9 . _ -,最长 64 字符。", "Starts with a lowercase letter or digit; a-z 0-9 . _ - allowed; max 64 chars.") : acp.label("ID 格式不合法:小写字母或数字开头,可用 a-z 0-9 . _ -。", "Invalid id: start with a lowercase letter or digit; only a-z 0-9 . _ - allowed.")
4124
+ })
4125
+ ]
4126
+ })
4071
4127
  }),
4072
- !advancedOpen && (cwdInvalid || rootsInvalid) && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
4073
- className: "dwa-error",
4074
- children: acp.label("里面有非法的工作空间路径", "Contains an invalid workspace path")
4128
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
4129
+ className: "dwa-form-row",
4130
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
4131
+ className: "dwa-form-col",
4132
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("label", {
4133
+ className: "dwa-form-label",
4134
+ children: acp.label("显示名", "Display Name")
4135
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
4136
+ className: "dwa-input",
4137
+ "aria-label": acp.label("显示名", "Display Name"),
4138
+ value: form.title,
4139
+ onChange: (e) => patch({ title: e.target.value }),
4140
+ placeholder: detected.name === "" ? acp.label("我的 Agent", "My Agent") : detected.name
4141
+ })]
4142
+ })
4075
4143
  }),
4076
- !advancedOpen && mcpInvalid && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
4077
- className: "dwa-error",
4078
- children: acp.label("里面的 MCP 服务器配置不是合法 JSON", "Contains an invalid MCP server list")
4144
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
4145
+ className: "dwa-form-row",
4146
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
4147
+ className: "dwa-form-col",
4148
+ children: [
4149
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("label", {
4150
+ className: "dwa-form-label",
4151
+ children: acp.label("启动命令(程序 + 参数)", "Launch Command (program + arguments)")
4152
+ }),
4153
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
4154
+ className: "dwa-input dwa-input-mono",
4155
+ "aria-label": acp.label("启动命令(程序 + 参数)", "Launch Command (program + arguments)"),
4156
+ value: form.commandLine,
4157
+ onChange: (e) => patch({ commandLine: e.target.value }),
4158
+ placeholder: detected.defaultCommand === "" ? "e.g. codebuddy --acp" : formatCommandLine(detected.defaultCommand, detected.defaultArgs)
4159
+ }),
4160
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
4161
+ className: "dwa-hint",
4162
+ children: commandPreview
4163
+ }),
4164
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
4165
+ className: "dwa-hint",
4166
+ children: acp.label("含空格的程序路径请加引号。", "Quote the program path if it contains spaces.")
4167
+ })
4168
+ ]
4169
+ })
4170
+ }),
4171
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(WorkspaceBlock, {
4172
+ acp,
4173
+ form,
4174
+ patch,
4175
+ cwdInvalid,
4176
+ rootsInvalid
4079
4177
  })
4080
4178
  ]
4081
4179
  }),
4082
4180
  /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
4083
- style: advancedOpen ? void 0 : { display: "none" },
4181
+ hidden: !advancedOpen,
4084
4182
  children: [
4085
4183
  !newCustom && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
4086
4184
  className: "dwa-default-hint",
@@ -4125,13 +4223,6 @@ window.__ModuleLoader__.load({
4125
4223
  })]
4126
4224
  })
4127
4225
  }),
4128
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)(WorkspaceBlock, {
4129
- acp,
4130
- form,
4131
- patch,
4132
- cwdInvalid,
4133
- rootsInvalid
4134
- }),
4135
4226
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
4136
4227
  className: "dwa-form-row",
4137
4228
  children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
@@ -4143,19 +4234,14 @@ window.__ModuleLoader__.load({
4143
4234
  }),
4144
4235
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
4145
4236
  className: "dwa-input dwa-input-mono",
4237
+ "aria-label": acp.label("空闲释放(毫秒)", "Idle Release (ms)"),
4146
4238
  value: form.idleStr,
4147
4239
  onChange: (e) => patch({ idleStr: e.target.value }),
4148
4240
  placeholder: acp.label(`留空 = 宿主默认(承载会话 ${String(DEFAULT_IDLE_RELEASE_MS / 6e4)} 分钟 / 探测进程 ${String(DEFAULT_PROBE_RELEASE_MS / 6e4)} 分钟)`, `Blank = host default (${String(DEFAULT_IDLE_RELEASE_MS / 6e4)} min for a chat process / ${String(DEFAULT_PROBE_RELEASE_MS / 6e4)} min for a probe)`)
4149
4241
  }),
4150
4242
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
4151
4243
  className: idleInvalid ? "dwa-error" : "dwa-hint",
4152
- children: idleInvalid ? acp.label("必须是 0(永不释放)或 [1000, 86400000] 之间的整数毫秒。", "Must be 0 (never release) or an integer in [1000, 86400000] ms.") : /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [
4153
- acp.label("空闲超过此时长就挂起进程(会话保留,下一条消息自动恢复)。", "The process is parked once it has been idle this long (the session is kept and resumes on the next message)."),
4154
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("br", {}),
4155
- acp.label("0 = 永不释放;回合在跑、取消未结算或审批待答时不释放。", "0 = never; a process with a running turn, an unsettled cancel, or a pending approval is never released."),
4156
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("br", {}),
4157
- acp.label("只对承载过会话的进程生效;探测进程固定 5 分钟释放,填 0 也拦不住。", "This window applies only to a process that has hosted a session; the model-probe process is always released after 5 minutes, and 0 does not stop it.")
4158
- ] })
4244
+ children: idleInvalid ? acp.label("必须是 0(永不释放)或 [1000, 86400000] 之间的整数毫秒。", "Must be 0 (never release) or an integer in [1000, 86400000] ms.") : /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_jsx_runtime.Fragment, { children: acp.label("承载过会话的进程空闲后挂起;0 不释放,探测进程固定 5 分钟。", "Park idle chat processes; 0 keeps them alive. Probe processes always release after 5 minutes.") })
4159
4245
  })
4160
4246
  ]
4161
4247
  })
@@ -4245,6 +4331,7 @@ window.__ModuleLoader__.load({
4245
4331
  minHeight: 96,
4246
4332
  resize: "vertical"
4247
4333
  },
4334
+ "aria-label": acp.label("MCP 服务器(JSON)", "MCP Servers (JSON)"),
4248
4335
  value: form.mcpText,
4249
4336
  onChange: (e) => patch({ mcpText: e.target.value }),
4250
4337
  spellCheck: false,
@@ -4256,15 +4343,29 @@ window.__ModuleLoader__.load({
4256
4343
  }),
4257
4344
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
4258
4345
  className: "dwa-hint",
4259
- children: acp.label("这些 MCP 服务器会在建会话时交给 agent,由 agent 自己拉起并使用(stdio 需填 command,可选 args / env;http 与 sse 需填 url,可选 headers)。agent 自己配置的 MCP 服务器不受影响,这里只是额外追加。", "These MCP servers are handed to the agent when a session is created; the agent launches and uses them itself (stdio needs command, with optional args / env; http and sse need url, with optional headers). The MCP servers the agent configures for itself are unaffected — this only adds more.")
4346
+ children: acp.label("额外追加给智能体的 MCP 服务器,不影响其已有配置。", "Additional MCP servers for the agent; its own configuration is unchanged.")
4260
4347
  })
4261
4348
  ]
4262
4349
  })
4263
4350
  ]
4264
4351
  }),
4352
+ !advancedOpen && (mcpInvalid || idleInvalid) && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
4353
+ className: "dwa-error",
4354
+ role: "alert",
4355
+ children: acp.label("请检查「高级」中的无效配置。", "Check the invalid settings in Advanced.")
4356
+ }),
4357
+ advancedOpen && (!idValid || idTaken || cwdInvalid || rootsInvalid || parsedCommand.command === "") && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
4358
+ className: "dwa-error",
4359
+ role: "alert",
4360
+ children: acp.label("请检查「连接」中的未完成或无效配置。", "Check the incomplete or invalid settings in Connection.")
4361
+ }),
4265
4362
  /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
4266
4363
  className: "dwa-form-actions",
4267
4364
  children: [
4365
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
4366
+ className: "dwa-hint",
4367
+ children: isConfigured ? dirty ? acp.label("有未保存的更改", "Unsaved changes") : acp.label("配置已保存", "Settings saved") : ""
4368
+ }),
4268
4369
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
4269
4370
  className: "dwa-btn",
4270
4371
  onClick: onTest,
@@ -4275,8 +4376,8 @@ window.__ModuleLoader__.load({
4275
4376
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
4276
4377
  className: "dwa-btn dwa-btn-primary",
4277
4378
  onClick: onSave,
4278
- disabled: saving || testing || formIncomplete,
4279
- children: saving ? acp.label("保存中...", "Saving...") : savedSuccess ? acp.label("✓ 已保存", "✓ Saved") : isConfigured ? acp.label("保存", "Save") : acp.label("保存并启用", "Save & Enable")
4379
+ disabled: saving || testing || formIncomplete || isConfigured && !dirty,
4380
+ children: saving ? acp.label("保存中...", "Saving...") : savedSuccess ? acp.label("✓ 已保存", "✓ Saved") : isConfigured ? acp.label("保存更改", "Save changes") : acp.label("保存并启用", "Save & Enable")
4280
4381
  }),
4281
4382
  showSaveWarning && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
4282
4383
  className: "dwa-hint",
@@ -4352,7 +4453,7 @@ window.__ModuleLoader__.load({
4352
4453
  }),
4353
4454
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
4354
4455
  className: "dwa-hint",
4355
- children: acp.label("对话里的 NTR 会话以该 DSH 会话选中的工作区为工作目录(agent 进程也从那里启动);此项只在 /acp 直连会话与宿主未上报工作区时生效。", "An NTR session inside a conversation runs — and starts its agent process — in that DSH session’s own workspace; this value applies to /acp-direct sessions and when the host reports no workspace.")
4456
+ children: acp.label("聊天使用会话工作区;此处用于直连会话或宿主未提供工作区时。", "Chats use their session workspace; this applies to direct sessions or when the host provides no workspace.")
4356
4457
  }),
4357
4458
  !form.rootsOpen && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
4358
4459
  className: "dwa-hint",
@@ -4721,7 +4822,7 @@ window.__ModuleLoader__.load({
4721
4822
  fontWeight: 400
4722
4823
  },
4723
4824
  title: acp.label("NTR 模式下的对话只列出这里勾选的模型;未勾选的仍可用——正在生效的那个也会以「· 当前」列出来,其余不列出。", "The NTR surfaces only list what is checked here; unchecked models still work, and the one currently in force is still listed with a \"· current\" row — the rest are not offered."),
4724
- children: acp.label("(NTR 座位 / 芯片的下拉列表)", "(the NTR seat and chip pickers)")
4825
+ children: acp.label("仅影响菜单可见性", "Menu visibility only")
4725
4826
  })]
4726
4827
  }),
4727
4828
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
@@ -4743,6 +4844,7 @@ window.__ModuleLoader__.load({
4743
4844
  children: probing ? acp.label("模型检测中...", "Probing models...") : acp.label("检测可用模型", "Detect available models")
4744
4845
  }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
4745
4846
  className: "dwa-input dwa-model-search",
4847
+ "aria-label": acp.label("搜索模型", "Search models"),
4746
4848
  value: search,
4747
4849
  onChange: (e) => setSearch(e.target.value),
4748
4850
  placeholder: acp.label("搜索模型…", "Search models…")
@@ -4860,7 +4962,7 @@ window.__ModuleLoader__.load({
4860
4962
  className: "dwa-model-list",
4861
4963
  children: [selectedChoices.length === 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
4862
4964
  className: "dwa-hint dwa-model-empty",
4863
- children: acp.label("还没有选择模型(点左侧的模型加入)", "Nothing selected yet — pick models on the left")
4965
+ children: acp.label("尚未选择模型,从「全部模型」中加入。", "No models selected. Add from All models.")
4864
4966
  }), selectedChoices.map((choice) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
4865
4967
  type: "button",
4866
4968
  className: "dwa-model-row is-on",