dsh-client-auto-continue 0.10.2 → 0.11.0

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
@@ -82,7 +82,23 @@ var ECHO_WINDOW_MS = 10 * 60 * 1e3;
82
82
  // src/client/locales.ts
83
83
  var zh = {
84
84
  "card.title": "自动继续",
85
- "card.description": "请求因网络等原因(非人为)中断后, 自动发送「继续」续跑。",
85
+ "card.eyebrow": "中断接力器",
86
+ "card.description": "接住意外中断的请求,等现场稳定下来,再把对话交还给 Agent。",
87
+ "flow.interrupted": "检测中断",
88
+ "flow.grace": "安全等待",
89
+ "flow.continue": "发送继续",
90
+ "repo.star": "去 GitHub 点 Star",
91
+ "repo.aria": "打开 dsh-auto-continue 的 GitHub 开源地址并点 Star",
92
+ "section.handoff.title": "接力方式",
93
+ "section.handoff.description": "决定中断后说什么,以及什么时候暂时停手。",
94
+ "section.safety.title": "安全节奏",
95
+ "section.safety.description": "先确认上一步,再控制等待与连续续跑的边界。",
96
+ "section.recovery.title": "恢复雷达",
97
+ "section.recovery.description": "扫描掉线会话,识别可恢复错误并逐步退避。",
98
+ "section.loop.title": "循环断路器",
99
+ "section.loop.description": "发现空转时及时换路,而不是让 Agent 原地消耗。",
100
+ "section.live.title": "现场状态",
101
+ "section.live.description": "看看今天接住了多少次,以及哪些会话还在暂停。",
86
102
  "field.paused": "暂停自动继续",
87
103
  "field.pausedHint": "全局暂停: 实时与扫描都不会再自动发送, 已排队的待发送也会取消。",
88
104
  "field.continueText": "继续文本",
@@ -117,6 +133,7 @@ var zh = {
117
133
  "field.classifyHint": "仅自动恢复临时性错误(网络/超时/5xx 等); 认证/余额/模型不存在等永久性错误跳过并通知。",
118
134
  "field.retryableErrorPatterns": "自定义可恢复错误",
119
135
  "field.retryableErrorPatternsHint": "每行一个大小写不敏感的普通文本片段; 命中错误码、HTTP 状态或消息时覆盖内置分类。请只填 provider 稳定且足够具体的文案, 过宽会重复请求。",
136
+ "field.retryableErrorPatternsPlaceholder": "例如:Upstream rejected the request as invalid",
120
137
  "field.backoffFactor": "退避系数",
121
138
  "field.backoffFactorHint": "连续失败时冷却间隔的倍率(如 2 表示 20s→40s→80s 递增)。",
122
139
  "field.backoffMaxMs": "最大退避间隔 (ms)",
@@ -170,7 +187,23 @@ var zh = {
170
187
  };
171
188
  var en = {
172
189
  "card.title": "Auto continue",
173
- "card.description": 'When a request is interrupted by a non-human cause, automatically send "Continue" to resume.',
190
+ "card.eyebrow": "Continuity relay",
191
+ "card.description": "Catches an interrupted request, waits for things to settle, then hands the thread back to the agent.",
192
+ "flow.interrupted": "Interrupted",
193
+ "flow.grace": "Safe pause",
194
+ "flow.continue": "Continue",
195
+ "repo.star": "Star on GitHub",
196
+ "repo.aria": "Open the dsh-auto-continue repository on GitHub and star it",
197
+ "section.handoff.title": "The handoff",
198
+ "section.handoff.description": "Choose what gets sent after an interruption and when the relay should stand down.",
199
+ "section.safety.title": "Safety rhythm",
200
+ "section.safety.description": "Confirm the previous step, then set the boundaries for waiting and repeated resumes.",
201
+ "section.recovery.title": "Recovery radar",
202
+ "section.recovery.description": "Find dropped sessions, recognize recoverable errors, and back off gracefully.",
203
+ "section.loop.title": "Loop breaker",
204
+ "section.loop.description": "Spot a spinning agent and route it forward before it burns time in place.",
205
+ "section.live.title": "Live signal",
206
+ "section.live.description": "See what the relay caught today and which sessions are still paused.",
174
207
  "field.paused": "Pause auto-continue",
175
208
  "field.pausedHint": "Globally pause: no live or scan auto-send fires, and queued pending sends are cancelled.",
176
209
  "field.continueText": "Continue text",
@@ -205,6 +238,7 @@ var en = {
205
238
  "field.classifyHint": "Auto-resume transient failures only (network/timeout/5xx…); auth, balance and model errors are skipped and notified.",
206
239
  "field.retryableErrorPatterns": "Custom retryable errors",
207
240
  "field.retryableErrorPatternsHint": "One case-insensitive literal per line. A match in the error code, HTTP status, or message overrides built-in classification. Use only stable, provider-specific text; broad matches can repeat requests.",
241
+ "field.retryableErrorPatternsPlaceholder": "For example: Upstream rejected the request as invalid",
208
242
  "field.backoffFactor": "Backoff factor",
209
243
  "field.backoffFactorHint": "Cooldown multiplier per consecutive failure (2 = 20s→40s→80s…).",
210
244
  "field.backoffMaxMs": "Max backoff (ms)",
@@ -588,39 +622,194 @@ var CardForm = class {
588
622
  // src/client/styles.ts
589
623
  var css = `
590
624
  .dshAcCard {
625
+ --dsh-ac-violet: #8b7cff;
626
+ --dsh-ac-cyan: #45cce5;
627
+ --dsh-ac-mint: #46d69d;
628
+ --dsh-ac-amber: #f1b95c;
629
+ isolation: isolate;
630
+ position: relative;
631
+ overflow: hidden;
591
632
  border: 1px solid var(--dsw-alias-border-l2);
592
633
  background: var(--dsw-alias-bg-layer-3);
593
- border-radius: 12px;
634
+ border-radius: 16px;
594
635
  list-style: none;
595
- transition: border-color .16s, background .16s;
636
+ box-shadow: 0 10px 34px rgb(0 0 0 / 8%);
637
+ transition: border-color .2s ease, background .2s ease, box-shadow .2s ease, transform .2s ease;
638
+ }
639
+ .dshAcCard::before {
640
+ content: "";
641
+ z-index: 2;
642
+ position: absolute;
643
+ inset: 0 0 auto;
644
+ height: 2px;
645
+ pointer-events: none;
646
+ opacity: .72;
647
+ background: linear-gradient(90deg, transparent 1%, var(--dsh-ac-violet) 22%, var(--dsh-ac-cyan) 52%, var(--dsh-ac-mint) 80%, transparent 99%);
648
+ }
649
+ .dshAcCard::after {
650
+ content: "";
651
+ z-index: -1;
652
+ position: absolute;
653
+ width: 190px;
654
+ height: 190px;
655
+ top: -104px;
656
+ left: -76px;
657
+ pointer-events: none;
658
+ border-radius: 999px;
659
+ background: radial-gradient(circle, rgb(139 124 255 / 14%) 0, transparent 68%);
660
+ }
661
+ .dshAcCard:hover {
662
+ border-color: color-mix(in srgb, var(--dsh-ac-violet) 48%, var(--dsw-alias-border-l2));
663
+ box-shadow: 0 14px 42px rgb(0 0 0 / 12%);
664
+ transform: translateY(-1px);
596
665
  }
597
- .dshAcCard:hover { border-color: var(--dsw-alias-label-dimmed); }
598
666
  .dshAcCardOpen {
599
667
  background: var(--dsw-alias-bg-layer-2);
600
- border-color: var(--dsw-alias-label-dimmed);
668
+ border-color: color-mix(in srgb, var(--dsh-ac-violet) 42%, var(--dsw-alias-border-l2));
669
+ box-shadow: 0 18px 54px rgb(0 0 0 / 14%);
670
+ transform: none;
671
+ }
672
+ .dshAcHeaderFrame {
673
+ align-items: stretch;
674
+ flex-direction: column;
675
+ display: flex;
601
676
  }
602
677
  .dshAcHeader {
603
678
  appearance: none;
604
- width: 100%;
679
+ min-width: 0;
680
+ flex: 1;
605
681
  font: inherit;
606
682
  color: inherit;
607
683
  text-align: left;
608
684
  cursor: pointer;
609
685
  background: none;
610
686
  border: 0;
611
- border-radius: 12px;
687
+ border-radius: 16px;
612
688
  align-items: center;
613
- gap: 12px;
614
- padding: 14px 16px;
689
+ gap: 14px;
690
+ padding: 18px 18px 12px;
615
691
  display: flex;
616
692
  }
617
- .dshAcHeader:focus-visible { outline: 2px solid var(--dsw-alias-brand-primary); outline-offset: -2px; }
618
- .dshAcHeadText { flex-direction: column; flex: 1; gap: 4px; min-width: 0; display: flex; }
619
- .dshAcName { color: var(--dsw-alias-label-primary); font-size: 15px; font-weight: 600; line-height: 1.4; }
620
- .dshAcDescription { color: var(--dsw-alias-label-tertiary); font-size: 13px; line-height: 1.5; }
621
- .dshAcChevron { color: var(--dsw-alias-label-tertiary); flex: none; transition: transform .16s; }
693
+ .dshAcHeader:focus-visible { outline: 2px solid var(--dsh-ac-violet); outline-offset: -3px; }
694
+ .dshAcRelayMark {
695
+ width: 54px;
696
+ height: 54px;
697
+ flex: none;
698
+ place-items: center;
699
+ display: grid;
700
+ color: var(--dsh-ac-cyan);
701
+ border: 1px solid color-mix(in srgb, var(--dsh-ac-violet) 42%, var(--dsw-alias-border-l2));
702
+ border-radius: 17px;
703
+ background: color-mix(in srgb, var(--dsw-alias-bg-layer-2) 84%, var(--dsh-ac-violet) 16%);
704
+ box-shadow: inset 0 0 0 1px rgb(255 255 255 / 4%), 0 8px 24px rgb(62 51 153 / 16%);
705
+ }
706
+ .dshAcRelayMark svg { width: 44px; height: 44px; overflow: visible; }
707
+ .dshAcRelayArc { fill: none; stroke: currentColor; stroke-width: 1.7; stroke-linecap: round; }
708
+ .dshAcRelayArcEcho { opacity: .42; }
709
+ .dshAcRelayNode { stroke: var(--dsw-alias-bg-layer-3); stroke-width: 1.5; }
710
+ .dshAcRelayNodeStart { fill: var(--dsh-ac-amber); }
711
+ .dshAcRelayNodeEnd { fill: var(--dsh-ac-mint); }
712
+ .dshAcRelayPulse { fill: var(--dsh-ac-violet); opacity: .85; }
713
+ .dshAcCard:hover .dshAcRelayPulse, .dshAcCardOpen .dshAcRelayPulse {
714
+ animation: dshAcRelayTravel 1.8s cubic-bezier(.4, 0, .2, 1) infinite;
715
+ }
716
+ .dshAcHeadText { flex-direction: column; flex: 1; gap: 3px; min-width: 0; display: flex; }
717
+ .dshAcEyebrow {
718
+ color: color-mix(in srgb, var(--dsh-ac-violet) 76%, var(--dsw-alias-label-secondary));
719
+ font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
720
+ font-size: 10px;
721
+ font-weight: 700;
722
+ line-height: 1.4;
723
+ letter-spacing: .12em;
724
+ text-transform: uppercase;
725
+ }
726
+ .dshAcName {
727
+ color: var(--dsw-alias-label-primary);
728
+ font-family: ui-rounded, "SF Pro Rounded", "Segoe UI", sans-serif;
729
+ font-size: 18px;
730
+ font-weight: 680;
731
+ letter-spacing: -.015em;
732
+ line-height: 1.35;
733
+ }
734
+ .dshAcDescription { max-width: 660px; color: var(--dsw-alias-label-tertiary); font-size: 13px; line-height: 1.5; }
735
+ .dshAcJourney { flex-wrap: wrap; align-items: center; gap: 7px; margin-top: 4px; display: flex; }
736
+ .dshAcJourneyStep {
737
+ align-items: center;
738
+ gap: 5px;
739
+ color: var(--dsw-alias-label-secondary);
740
+ font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
741
+ font-size: 10px;
742
+ font-weight: 600;
743
+ line-height: 1.4;
744
+ letter-spacing: .02em;
745
+ display: inline-flex;
746
+ }
747
+ .dshAcJourneyDot { width: 5px; height: 5px; flex: none; border-radius: 999px; background: currentColor; box-shadow: 0 0 0 3px rgb(255 255 255 / 3%); }
748
+ .dshAcJourneyInterrupted .dshAcJourneyDot { color: var(--dsh-ac-amber); }
749
+ .dshAcJourneyGrace .dshAcJourneyDot { color: var(--dsh-ac-cyan); }
750
+ .dshAcJourneyContinue .dshAcJourneyDot { color: var(--dsh-ac-mint); }
751
+ .dshAcJourneyLine {
752
+ width: 25px;
753
+ height: 1px;
754
+ flex: none;
755
+ opacity: .7;
756
+ background: linear-gradient(90deg, var(--dsh-ac-violet), var(--dsh-ac-cyan), var(--dsh-ac-mint));
757
+ background-size: 220% 100%;
758
+ }
759
+ .dshAcCard:hover .dshAcJourneyLine, .dshAcCardOpen .dshAcJourneyLine { animation: dshAcSignalSweep 1.8s linear infinite; }
760
+ .dshAcChevron {
761
+ width: 30px;
762
+ height: 30px;
763
+ color: var(--dsw-alias-label-tertiary);
764
+ border: 1px solid var(--dsw-alias-border-l2);
765
+ border-radius: 999px;
766
+ flex: none;
767
+ place-items: center;
768
+ display: grid;
769
+ transition: color .18s ease, border-color .18s ease, transform .18s ease;
770
+ }
771
+ .dshAcChevron svg { width: 16px; height: 16px; fill: none; stroke: currentColor; stroke-width: 1.5; stroke-linecap: round; stroke-linejoin: round; }
772
+ .dshAcHeader:hover .dshAcChevron { color: var(--dsh-ac-violet); border-color: color-mix(in srgb, var(--dsh-ac-violet) 48%, var(--dsw-alias-border-l2)); }
622
773
  .dshAcChevronOpen { transform: rotate(180deg); }
623
- .dshAcBody { border-top: 1px solid var(--dsw-alias-border-l2); margin: 0 16px; padding-bottom: 8px; }
774
+ .dshAcGithub {
775
+ min-width: 0;
776
+ max-width: none;
777
+ align-self: stretch;
778
+ align-items: center;
779
+ gap: 10px;
780
+ margin: 0 18px 16px;
781
+ padding: 9px 11px;
782
+ color: var(--dsw-alias-label-primary);
783
+ text-decoration: none;
784
+ border: 1px solid var(--dsw-alias-border-l2);
785
+ border-radius: 13px;
786
+ background: color-mix(in srgb, var(--dsw-alias-bg-layer-2) 90%, var(--dsh-ac-violet) 10%);
787
+ display: flex;
788
+ transition: border-color .18s ease, background .18s ease, transform .18s ease;
789
+ }
790
+ .dshAcGithub:hover {
791
+ border-color: color-mix(in srgb, var(--dsh-ac-violet) 58%, var(--dsw-alias-border-l2));
792
+ background: color-mix(in srgb, var(--dsw-alias-bg-layer-2) 82%, var(--dsh-ac-violet) 18%);
793
+ transform: translateY(-1px);
794
+ }
795
+ .dshAcGithub:focus-visible { outline: 2px solid var(--dsh-ac-violet); outline-offset: 2px; }
796
+ .dshAcGithubIcon { width: 23px; height: 23px; flex: none; color: var(--dsw-alias-label-primary); }
797
+ .dshAcGithubIcon svg { width: 100%; height: 100%; fill: currentColor; }
798
+ .dshAcGithubText { min-width: 0; flex: 1; flex-direction: column; gap: 1px; display: flex; }
799
+ .dshAcGithubAction { font-size: 12px; font-weight: 680; line-height: 1.4; }
800
+ .dshAcGithubAction::before { content: "★"; color: var(--dsh-ac-amber); margin-right: 5px; }
801
+ .dshAcGithubSlug {
802
+ overflow: hidden;
803
+ color: var(--dsw-alias-label-tertiary);
804
+ font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
805
+ font-size: 9.5px;
806
+ line-height: 1.4;
807
+ text-overflow: ellipsis;
808
+ white-space: nowrap;
809
+ }
810
+ .dshAcExternal { width: 15px; height: 15px; flex: none; color: var(--dsw-alias-label-tertiary); }
811
+ .dshAcExternal svg { width: 100%; height: 100%; fill: none; stroke: currentColor; stroke-width: 1.25; stroke-linecap: round; stroke-linejoin: round; }
812
+ .dshAcBody { border-top: 1px solid var(--dsw-alias-border-l2); margin: 0 18px 12px; padding: 4px 0 0; }
624
813
  .dshAcReadOnly { color: var(--dsw-alias-label-tertiary); margin: 12px 0 0; font-size: 12px; line-height: 1.5; }
625
814
  .dshAcPending {
626
815
  white-space: nowrap;
@@ -657,8 +846,53 @@ var css = `
657
846
  .dshAcSave { background: var(--dsw-alias-label-primary); color: var(--dsw-alias-bg-layer-3); }
658
847
  .dshAcDiscard:disabled, .dshAcSave:disabled { opacity: .4; cursor: default; }
659
848
  .dshAcDiscard:focus-visible, .dshAcSave:focus-visible { outline: 2px solid var(--dsw-alias-brand-primary); outline-offset: 1px; }
660
- .dshAcField { flex-direction: column; gap: 6px; padding: 12px 0; display: flex; }
661
- .dshAcField + .dshAcField { border-top: 1px solid var(--dsw-alias-border-l2); }
849
+ .dshAcFormCanvas { flex-direction: column; gap: 14px; padding: 12px 0 8px; display: flex; }
850
+ .dshAcFormSection {
851
+ --dsh-ac-section: var(--dsh-ac-violet);
852
+ overflow: hidden;
853
+ border: 1px solid var(--dsw-alias-border-l2);
854
+ border-radius: 14px;
855
+ background: var(--dsw-alias-bg-layer-3);
856
+ background: color-mix(in srgb, var(--dsw-alias-bg-layer-3) 95%, var(--dsh-ac-section) 5%);
857
+ }
858
+ .dshAcFormSection-handoff { --dsh-ac-section: var(--dsh-ac-mint); }
859
+ .dshAcFormSection-safety { --dsh-ac-section: var(--dsh-ac-amber); }
860
+ .dshAcFormSection-recovery { --dsh-ac-section: var(--dsh-ac-cyan); }
861
+ .dshAcFormSection-loop { --dsh-ac-section: var(--dsh-ac-violet); }
862
+ .dshAcFormSection-live { --dsh-ac-section: color-mix(in srgb, var(--dsh-ac-violet) 60%, var(--dsh-ac-cyan)); }
863
+ .dshAcSectionHead {
864
+ align-items: center;
865
+ gap: 11px;
866
+ padding: 13px 14px 11px;
867
+ border-bottom: 1px solid var(--dsw-alias-border-l2);
868
+ display: flex;
869
+ }
870
+ .dshAcSectionSignal {
871
+ width: 4px;
872
+ height: 34px;
873
+ flex: none;
874
+ border-radius: 999px;
875
+ background: var(--dsh-ac-section);
876
+ box-shadow: 0 0 18px color-mix(in srgb, var(--dsh-ac-section) 55%, transparent);
877
+ }
878
+ .dshAcSectionCopy { min-width: 0; flex-direction: column; gap: 2px; display: flex; }
879
+ .dshAcSectionTitle {
880
+ color: var(--dsw-alias-label-primary);
881
+ font-family: ui-rounded, "SF Pro Rounded", "Segoe UI", sans-serif;
882
+ font-size: 14px;
883
+ font-weight: 680;
884
+ line-height: 1.4;
885
+ }
886
+ .dshAcSectionDescription { color: var(--dsw-alias-label-tertiary); font-size: 11.5px; line-height: 1.45; }
887
+ .dshAcSectionGrid {
888
+ grid-template-columns: repeat(2, minmax(0, 1fr));
889
+ column-gap: 22px;
890
+ padding: 0 14px 4px;
891
+ display: grid;
892
+ }
893
+ .dshAcField { min-width: 0; flex-direction: column; gap: 6px; padding: 12px 0; border-top: 1px solid var(--dsw-alias-border-l2); display: flex; }
894
+ .dshAcSectionGrid > .dshAcField:first-child { border-top: 0; }
895
+ .dshAcFieldWide { grid-column: 1 / -1; }
662
896
  .dshAcHead { align-items: center; gap: 8px; display: flex; }
663
897
  .dshAcLabel { min-width: 0; color: var(--dsw-alias-label-primary); flex: 1; font-size: 13px; font-weight: 500; line-height: 1.5; }
664
898
  .dshAcBadges { align-items: center; gap: 8px; display: inline-flex; }
@@ -685,6 +919,8 @@ var css = `
685
919
  .dshAcReset:hover:not(:disabled) { color: var(--dsw-alias-label-primary); }
686
920
  .dshAcReset:disabled { cursor: default; }
687
921
  .dshAcInput {
922
+ box-sizing: border-box;
923
+ width: 100%;
688
924
  border: 1px solid var(--dsw-alias-border-l2);
689
925
  background: var(--dsw-alias-bg-layer-3);
690
926
  height: 34px;
@@ -700,6 +936,8 @@ var css = `
700
936
  .dshAcInputInvalid { border-color: var(--dsw-alias-label-error); }
701
937
  .dshAcTextArea { box-sizing: border-box; height: auto; min-height: 84px; padding: 8px 12px; resize: vertical; }
702
938
  .dshAcSelect {
939
+ box-sizing: border-box;
940
+ width: 100%;
703
941
  border: 1px solid var(--dsw-alias-border-l2);
704
942
  background: var(--dsw-alias-bg-layer-3);
705
943
  height: 34px;
@@ -714,7 +952,8 @@ var css = `
714
952
  .dshAcSelect:disabled { color: var(--dsw-alias-label-tertiary); cursor: default; }
715
953
  .dshAcInvalid { color: var(--dsw-alias-label-error); margin: 0; font-size: 12px; line-height: 1.5; }
716
954
  .dshAcHint { color: var(--dsw-alias-label-tertiary); margin: 0; font-size: 12px; line-height: 1.5; }
717
- .dshAcPanel { border-top: 1px solid var(--dsw-alias-border-l2); flex-direction: column; gap: 8px; padding: 12px 0; display: flex; }
955
+ .dshAcPanel { min-width: 0; flex-direction: column; gap: 8px; padding: 12px 0 14px; display: flex; }
956
+ .dshAcPanel + .dshAcPanel { border-left: 1px solid var(--dsw-alias-border-l2); padding-left: 20px; }
718
957
  .dshAcPanelHead { align-items: center; gap: 8px; display: flex; }
719
958
  .dshAcPanelTitle { color: var(--dsw-alias-label-primary); flex: 1; font-size: 13px; font-weight: 600; line-height: 1.5; }
720
959
  .dshAcStats { gap: 4px 16px; margin: 0; grid-template-columns: repeat(2, minmax(0, 1fr)); display: grid; }
@@ -740,6 +979,43 @@ var css = `
740
979
  font-size: 12px;
741
980
  line-height: 1.5;
742
981
  }
982
+ @keyframes dshAcRelayTravel {
983
+ 0% { opacity: 0; transform: translate(-19px, 18px) scale(.7); }
984
+ 18% { opacity: 1; }
985
+ 82% { opacity: 1; }
986
+ 100% { opacity: 0; transform: translate(12px, 6px) scale(1.15); }
987
+ }
988
+ @keyframes dshAcSignalSweep {
989
+ from { background-position: 100% 0; }
990
+ to { background-position: -120% 0; }
991
+ }
992
+ @media (max-width: 820px) {
993
+ .dshAcSectionGrid { grid-template-columns: minmax(0, 1fr); }
994
+ .dshAcFieldWide { grid-column: auto; }
995
+ .dshAcPanel + .dshAcPanel {
996
+ border-top: 1px solid var(--dsw-alias-border-l2);
997
+ border-left: 0;
998
+ padding-left: 0;
999
+ }
1000
+ }
1001
+ @media (max-width: 560px) {
1002
+ .dshAcHeader { align-items: flex-start; gap: 11px; padding: 15px 13px 10px; }
1003
+ .dshAcRelayMark { width: 46px; height: 46px; border-radius: 14px; }
1004
+ .dshAcRelayMark svg { width: 38px; height: 38px; }
1005
+ .dshAcName { font-size: 16px; }
1006
+ .dshAcDescription { font-size: 12px; }
1007
+ .dshAcJourney { gap: 5px; }
1008
+ .dshAcJourneyLine { width: 13px; }
1009
+ .dshAcChevron { width: 27px; height: 27px; }
1010
+ .dshAcPending { display: none; }
1011
+ .dshAcGithub { margin: 0 13px 13px; }
1012
+ .dshAcBody { margin-right: 13px; margin-left: 13px; }
1013
+ }
1014
+ @media (prefers-reduced-motion: reduce) {
1015
+ .dshAcCard, .dshAcGithub, .dshAcChevron { transition: none; }
1016
+ .dshAcCard:hover, .dshAcGithub:hover { transform: none; }
1017
+ .dshAcRelayPulse, .dshAcJourneyLine { animation: none !important; }
1018
+ }
743
1019
  `;
744
1020
  function injectStyles() {
745
1021
  if (typeof document === "undefined") return;
@@ -826,6 +1102,47 @@ var AutoContinueSettingsCardController = class {
826
1102
  return { hooks: { autoContinueSettingsCard: this.store }, ...this.form.actions() };
827
1103
  }
828
1104
  };
1105
+ var REPOSITORY_URL = "https://github.com/HsiangNianian/dsh-auto-continue";
1106
+ var REPOSITORY_SLUG = "HsiangNianian/dsh-auto-continue";
1107
+ function RelayMark() {
1108
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("svg", { viewBox: "0 0 48 48", "aria-hidden": "true", focusable: "false", children: [
1109
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { className: "dshAcRelayArc", d: "M9 30c4-12 10-18 19-18 5 0 9 2 12 6" }),
1110
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { className: "dshAcRelayArc dshAcRelayArcEcho", d: "M8 35c6 3 12 3 17 0 5-3 8-8 15-9" }),
1111
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("circle", { className: "dshAcRelayNode dshAcRelayNodeStart", cx: "9", cy: "30", r: "3" }),
1112
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("circle", { className: "dshAcRelayNode dshAcRelayNodeEnd", cx: "40", cy: "18", r: "3" }),
1113
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("circle", { className: "dshAcRelayPulse", cx: "28", cy: "12", r: "2.5" })
1114
+ ] });
1115
+ }
1116
+ function ChevronMark() {
1117
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("svg", { viewBox: "0 0 16 16", "aria-hidden": "true", focusable: "false", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "m3.5 6 4.5 4 4.5-4" }) });
1118
+ }
1119
+ function GitHubMark() {
1120
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("svg", { viewBox: "0 0 24 24", "aria-hidden": "true", focusable: "false", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M12 2.4a9.8 9.8 0 0 0-3.1 19.1c.5.1.7-.2.7-.5v-1.9c-2.8.6-3.4-1.2-3.4-1.2-.5-1.1-1.1-1.4-1.1-1.4-.9-.6.1-.6.1-.6 1 0 1.5 1 1.5 1 .9 1.5 2.3 1.1 2.9.8.1-.6.4-1.1.6-1.3-2.2-.3-4.6-1.1-4.6-4.9 0-1.1.4-2 1-2.7-.1-.3-.4-1.3.1-2.7 0 0 .8-.3 2.8 1a9.5 9.5 0 0 1 5 0c1.9-1.3 2.8-1 2.8-1 .5 1.4.2 2.4.1 2.7.6.7 1 1.6 1 2.7 0 3.8-2.3 4.6-4.6 4.9.4.3.7.9.7 1.8V21c0 .3.2.6.7.5A9.8 9.8 0 0 0 12 2.4Z" }) });
1121
+ }
1122
+ function ExternalMark() {
1123
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("svg", { viewBox: "0 0 16 16", "aria-hidden": "true", focusable: "false", children: [
1124
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M6 3h7v7M13 3 7 9" }),
1125
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M11 9v3a1 1 0 0 1-1 1H4a1 1 0 0 1-1-1V6a1 1 0 0 1 1-1h3" })
1126
+ ] });
1127
+ }
1128
+ function RelayJourney(props) {
1129
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: "dshAcJourney", children: [
1130
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: "dshAcJourneyStep dshAcJourneyInterrupted", children: [
1131
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "dshAcJourneyDot", "aria-hidden": "true" }),
1132
+ props.t("flow.interrupted")
1133
+ ] }),
1134
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "dshAcJourneyLine", "aria-hidden": "true" }),
1135
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: "dshAcJourneyStep dshAcJourneyGrace", children: [
1136
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "dshAcJourneyDot", "aria-hidden": "true" }),
1137
+ props.t("flow.grace")
1138
+ ] }),
1139
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "dshAcJourneyLine", "aria-hidden": "true" }),
1140
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: "dshAcJourneyStep dshAcJourneyContinue", children: [
1141
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "dshAcJourneyDot", "aria-hidden": "true" }),
1142
+ props.t("flow.continue")
1143
+ ] })
1144
+ ] });
1145
+ }
829
1146
  function SettingsCard(props) {
830
1147
  const [open, setOpen] = (0, import_react.useState)(false);
831
1148
  const { state: state2 } = props;
@@ -833,25 +1150,48 @@ function SettingsCard(props) {
833
1150
  const title = props.t(props.titleKey);
834
1151
  const blocked = !state2.dirty || state2.invalid || state2.saving;
835
1152
  return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("li", { className: open ? "dshAcCard dshAcCardOpen" : "dshAcCard", children: [
836
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
837
- "button",
838
- {
839
- type: "button",
840
- className: "dshAcHeader",
841
- "aria-expanded": open,
842
- "aria-label": `${props.t(open ? "chrome.collapse" : "chrome.expand")}: ${title}`,
843
- title: props.t(props.descriptionKey),
844
- onClick: () => setOpen(!open),
845
- children: [
846
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: "dshAcHeadText", children: [
847
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "dshAcName", children: title }),
848
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "dshAcDescription", children: props.t(props.descriptionKey) })
849
- ] }),
850
- state2.dirty ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "dshAcPending", title: props.t("chrome.unsaved"), children: props.t("chrome.unsaved") }) : null,
851
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: open ? "dshAcChevron dshAcChevronOpen" : "dshAcChevron", children: "▾" })
852
- ]
853
- }
854
- ),
1153
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "dshAcHeaderFrame", children: [
1154
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
1155
+ "button",
1156
+ {
1157
+ type: "button",
1158
+ className: "dshAcHeader",
1159
+ "aria-expanded": open,
1160
+ "aria-label": `${props.t(open ? "chrome.collapse" : "chrome.expand")}: ${title}`,
1161
+ title: props.t(props.descriptionKey),
1162
+ onClick: () => setOpen(!open),
1163
+ children: [
1164
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "dshAcRelayMark", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(RelayMark, {}) }),
1165
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: "dshAcHeadText", children: [
1166
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "dshAcEyebrow", children: props.t("card.eyebrow") }),
1167
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "dshAcName", children: title }),
1168
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "dshAcDescription", children: props.t(props.descriptionKey) }),
1169
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(RelayJourney, { t: props.t })
1170
+ ] }),
1171
+ state2.dirty ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "dshAcPending", title: props.t("chrome.unsaved"), children: props.t("chrome.unsaved") }) : null,
1172
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: open ? "dshAcChevron dshAcChevronOpen" : "dshAcChevron", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ChevronMark, {}) })
1173
+ ]
1174
+ }
1175
+ ),
1176
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
1177
+ "a",
1178
+ {
1179
+ className: "dshAcGithub",
1180
+ href: REPOSITORY_URL,
1181
+ target: "_blank",
1182
+ rel: "noreferrer",
1183
+ "aria-label": props.t("repo.aria"),
1184
+ children: [
1185
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "dshAcGithubIcon", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(GitHubMark, {}) }),
1186
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: "dshAcGithubText", children: [
1187
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "dshAcGithubAction", children: props.t("repo.star") }),
1188
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "dshAcGithubSlug", children: REPOSITORY_SLUG })
1189
+ ] }),
1190
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "dshAcExternal", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ExternalMark, {}) })
1191
+ ]
1192
+ }
1193
+ )
1194
+ ] }),
855
1195
  open ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "dshAcBody", children: [
856
1196
  !state2.writable ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "dshAcReadOnly", role: "status", children: props.t("chrome.readOnly") }) : null,
857
1197
  props.children,
@@ -874,7 +1214,7 @@ function SettingsCard(props) {
874
1214
  }
875
1215
  function ValueField(props) {
876
1216
  const className = props.invalid ? "dshAcInput dshAcInputInvalid" : "dshAcInput";
877
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "dshAcField", children: [
1217
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: props.wide === true ? "dshAcField dshAcFieldWide" : "dshAcField", children: [
878
1218
  /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "dshAcHead", children: [
879
1219
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("label", { className: "dshAcLabel", htmlFor: props.id, children: props.label }),
880
1220
  props.overridden ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: "dshAcBadges", children: [
@@ -912,7 +1252,7 @@ function ValueField(props) {
912
1252
  ] });
913
1253
  }
914
1254
  function BooleanField(props) {
915
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "dshAcField", children: [
1255
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: props.wide === true ? "dshAcField dshAcFieldWide" : "dshAcField", children: [
916
1256
  /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "dshAcHead", children: [
917
1257
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("label", { className: "dshAcLabel", htmlFor: props.id, children: props.label }),
918
1258
  props.overridden ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: "dshAcBadges", children: [
@@ -938,6 +1278,18 @@ function BooleanField(props) {
938
1278
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "dshAcHint", children: props.hint })
939
1279
  ] });
940
1280
  }
1281
+ function SettingsSection(props) {
1282
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("section", { className: `dshAcFormSection dshAcFormSection-${props.tone}`, children: [
1283
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("header", { className: "dshAcSectionHead", children: [
1284
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "dshAcSectionSignal", "aria-hidden": "true" }),
1285
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: "dshAcSectionCopy", children: [
1286
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "dshAcSectionTitle", children: props.t(props.titleKey) }),
1287
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "dshAcSectionDescription", children: props.t(props.descriptionKey) })
1288
+ ] })
1289
+ ] }),
1290
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "dshAcSectionGrid", children: props.children })
1291
+ ] });
1292
+ }
941
1293
  function LivePanels(props) {
942
1294
  const { t } = props;
943
1295
  const [, refresh] = (0, import_react.useState)(0);
@@ -1057,7 +1409,7 @@ function AutoContinueSettingsCard(props) {
1057
1409
  const state2 = props.useAutoContinueSettingsCard((snapshot) => snapshot);
1058
1410
  const disabled = !state2.writable;
1059
1411
  const shared = { t, disabled };
1060
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
1412
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1061
1413
  SettingsCard,
1062
1414
  {
1063
1415
  t,
@@ -1066,328 +1418,388 @@ function AutoContinueSettingsCard(props) {
1066
1418
  state: state2,
1067
1419
  onSave: props.save,
1068
1420
  onDiscard: props.discard,
1069
- children: [
1070
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1071
- BooleanField,
1072
- {
1073
- id: "auto-continue-paused",
1074
- label: t("field.paused"),
1075
- hint: t("field.pausedHint"),
1076
- ...shared,
1077
- ...state2.paused,
1078
- onEdit: (text) => props.edit("paused", text),
1079
- onReset: () => props.resetField("paused")
1080
- }
1081
- ),
1082
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1083
- ValueField,
1084
- {
1085
- id: "auto-continue-continue-text",
1086
- label: t("field.continueText"),
1087
- hint: t("field.continueTextHint"),
1088
- ...shared,
1089
- ...state2.continueText,
1090
- onEdit: (text) => props.edit("continueText", text),
1091
- placeholder: t("default.continueText"),
1092
- onReset: () => props.resetField("continueText")
1093
- }
1094
- ),
1095
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1096
- ValueField,
1097
- {
1098
- id: "auto-continue-continue-text-max-tokens",
1099
- label: t("field.continueTextMaxTokens"),
1100
- hint: t("field.continueTextMaxTokensHint"),
1101
- ...shared,
1102
- ...state2.continueTextMaxTokens,
1103
- onEdit: (text) => props.edit("continueTextMaxTokens", text),
1104
- placeholder: t("default.continueTextMaxTokens"),
1105
- onReset: () => props.resetField("continueTextMaxTokens")
1106
- }
1107
- ),
1108
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1109
- BooleanField,
1110
- {
1111
- id: "auto-continue-guard-tools",
1112
- label: t("field.guardTools"),
1113
- hint: t("field.guardToolsHint"),
1114
- ...shared,
1115
- ...state2.guardTools,
1116
- onEdit: (text) => props.edit("guardTools", text),
1117
- onReset: () => props.resetField("guardTools")
1118
- }
1119
- ),
1120
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1121
- ValueField,
1421
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "dshAcFormCanvas", children: [
1422
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
1423
+ SettingsSection,
1122
1424
  {
1123
- id: "auto-continue-guard-pending-text",
1124
- label: t("field.guardPendingText"),
1125
- hint: t("field.guardPendingTextHint"),
1126
- ...shared,
1127
- ...state2.guardPendingText,
1128
- onEdit: (text) => props.edit("guardPendingText", text),
1129
- placeholder: t("default.guardPendingText"),
1130
- onReset: () => props.resetField("guardPendingText")
1131
- }
1132
- ),
1133
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1134
- ValueField,
1135
- {
1136
- id: "auto-continue-guard-done-text",
1137
- label: t("field.guardDoneText"),
1138
- hint: t("field.guardDoneTextHint"),
1139
- ...shared,
1140
- ...state2.guardDoneText,
1141
- onEdit: (text) => props.edit("guardDoneText", text),
1142
- placeholder: t("default.guardDoneText"),
1143
- onReset: () => props.resetField("guardDoneText")
1144
- }
1145
- ),
1146
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1147
- ValueField,
1148
- {
1149
- id: "auto-continue-grace-ms",
1150
- label: t("field.graceMs"),
1151
- hint: t("field.graceMsHint"),
1152
- numeric: true,
1153
- ...shared,
1154
- ...state2.graceMs,
1155
- onEdit: (text) => props.edit("graceMs", text),
1156
- onReset: () => props.resetField("graceMs")
1157
- }
1158
- ),
1159
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1160
- ValueField,
1161
- {
1162
- id: "auto-continue-cooldown-ms",
1163
- label: t("field.cooldownMs"),
1164
- hint: t("field.cooldownMsHint"),
1165
- numeric: true,
1166
- ...shared,
1167
- ...state2.cooldownMs,
1168
- onEdit: (text) => props.edit("cooldownMs", text),
1169
- onReset: () => props.resetField("cooldownMs")
1170
- }
1171
- ),
1172
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1173
- ValueField,
1174
- {
1175
- id: "auto-continue-max-consecutive",
1176
- label: t("field.maxConsecutive"),
1177
- hint: t("field.maxConsecutiveHint"),
1178
- numeric: true,
1179
- ...shared,
1180
- ...state2.maxConsecutive,
1181
- onEdit: (text) => props.edit("maxConsecutive", text),
1182
- onReset: () => props.resetField("maxConsecutive")
1183
- }
1184
- ),
1185
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1186
- BooleanField,
1187
- {
1188
- id: "auto-continue-scan-on-boot",
1189
- label: t("field.scanOnBoot"),
1190
- hint: t("field.scanOnBootHint"),
1191
- ...shared,
1192
- ...state2.scanOnBoot,
1193
- onEdit: (text) => props.edit("scanOnBoot", text),
1194
- onReset: () => props.resetField("scanOnBoot")
1195
- }
1196
- ),
1197
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1198
- ValueField,
1199
- {
1200
- id: "auto-continue-scan-limit",
1201
- label: t("field.scanLimit"),
1202
- hint: t("field.scanLimitHint"),
1203
- numeric: true,
1204
- ...shared,
1205
- ...state2.scanLimit,
1206
- onEdit: (text) => props.edit("scanLimit", text),
1207
- onReset: () => props.resetField("scanLimit")
1208
- }
1209
- ),
1210
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1211
- ValueField,
1212
- {
1213
- id: "auto-continue-fresh-ms",
1214
- label: t("field.freshMs"),
1215
- hint: t("field.freshMsHint"),
1216
- numeric: true,
1217
- ...shared,
1218
- ...state2.freshMs,
1219
- onEdit: (text) => props.edit("freshMs", text),
1220
- onReset: () => props.resetField("freshMs")
1221
- }
1222
- ),
1223
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1224
- BooleanField,
1225
- {
1226
- id: "auto-continue-verbose",
1227
- label: t("field.verbose"),
1228
- hint: t("field.verboseHint"),
1229
- ...shared,
1230
- ...state2.verbose,
1231
- onEdit: (text) => props.edit("verbose", text),
1232
- onReset: () => props.resetField("verbose")
1233
- }
1234
- ),
1235
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1236
- BooleanField,
1237
- {
1238
- id: "auto-continue-classify",
1239
- label: t("field.classify"),
1240
- hint: t("field.classifyHint"),
1241
- ...shared,
1242
- ...state2.classify,
1243
- onEdit: (text) => props.edit("classify", text),
1244
- onReset: () => props.resetField("classify")
1245
- }
1246
- ),
1247
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1248
- ValueField,
1249
- {
1250
- id: "auto-continue-retryable-error-patterns",
1251
- label: t("field.retryableErrorPatterns"),
1252
- hint: t("field.retryableErrorPatternsHint"),
1253
- multiline: true,
1254
- ...shared,
1255
- ...state2.retryableErrorPatterns,
1256
- onEdit: (text) => props.edit("retryableErrorPatterns", text),
1257
- placeholder: "Upstream rejected the request as invalid",
1258
- onReset: () => props.resetField("retryableErrorPatterns")
1259
- }
1260
- ),
1261
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1262
- ValueField,
1263
- {
1264
- id: "auto-continue-backoff-factor",
1265
- label: t("field.backoffFactor"),
1266
- hint: t("field.backoffFactorHint"),
1267
- numeric: true,
1268
- ...shared,
1269
- ...state2.backoffFactor,
1270
- onEdit: (text) => props.edit("backoffFactor", text),
1271
- onReset: () => props.resetField("backoffFactor")
1272
- }
1273
- ),
1274
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1275
- ValueField,
1276
- {
1277
- id: "auto-continue-backoff-max",
1278
- label: t("field.backoffMaxMs"),
1279
- hint: t("field.backoffMaxMsHint"),
1280
- numeric: true,
1281
- ...shared,
1282
- ...state2.backoffMaxMs,
1283
- onEdit: (text) => props.edit("backoffMaxMs", text),
1284
- onReset: () => props.resetField("backoffMaxMs")
1285
- }
1286
- ),
1287
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1288
- BooleanField,
1289
- {
1290
- id: "auto-continue-notify",
1291
- label: t("field.notify"),
1292
- hint: t("field.notifyHint"),
1293
- ...shared,
1294
- ...state2.notify,
1295
- onEdit: (text) => props.edit("notify", text),
1296
- onReset: () => props.resetField("notify")
1297
- }
1298
- ),
1299
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1300
- BooleanField,
1301
- {
1302
- id: "auto-continue-loop-guard",
1303
- label: t("field.loopGuard"),
1304
- hint: t("field.loopGuardHint"),
1305
- ...shared,
1306
- ...state2.loopGuard,
1307
- onEdit: (text) => props.edit("loopGuard", text),
1308
- onReset: () => props.resetField("loopGuard")
1309
- }
1310
- ),
1311
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1312
- ValueField,
1313
- {
1314
- id: "auto-continue-loop-short-chars",
1315
- label: t("field.loopShortChars"),
1316
- hint: t("field.loopShortCharsHint"),
1317
- numeric: true,
1318
- ...shared,
1319
- ...state2.loopShortChars,
1320
- onEdit: (text) => props.edit("loopShortChars", text),
1321
- onReset: () => props.resetField("loopShortChars")
1322
- }
1323
- ),
1324
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1325
- ValueField,
1326
- {
1327
- id: "auto-continue-loop-window-ms",
1328
- label: t("field.loopWindowMs"),
1329
- hint: t("field.loopWindowMsHint"),
1330
- numeric: true,
1331
- ...shared,
1332
- ...state2.loopWindowMs,
1333
- onEdit: (text) => props.edit("loopWindowMs", text),
1334
- onReset: () => props.resetField("loopWindowMs")
1425
+ t,
1426
+ titleKey: "section.handoff.title",
1427
+ descriptionKey: "section.handoff.description",
1428
+ tone: "handoff",
1429
+ children: [
1430
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1431
+ BooleanField,
1432
+ {
1433
+ wide: true,
1434
+ id: "auto-continue-paused",
1435
+ label: t("field.paused"),
1436
+ hint: t("field.pausedHint"),
1437
+ ...shared,
1438
+ ...state2.paused,
1439
+ onEdit: (text) => props.edit("paused", text),
1440
+ onReset: () => props.resetField("paused")
1441
+ }
1442
+ ),
1443
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1444
+ ValueField,
1445
+ {
1446
+ id: "auto-continue-continue-text",
1447
+ label: t("field.continueText"),
1448
+ hint: t("field.continueTextHint"),
1449
+ ...shared,
1450
+ ...state2.continueText,
1451
+ onEdit: (text) => props.edit("continueText", text),
1452
+ placeholder: t("default.continueText"),
1453
+ onReset: () => props.resetField("continueText")
1454
+ }
1455
+ ),
1456
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1457
+ ValueField,
1458
+ {
1459
+ id: "auto-continue-continue-text-max-tokens",
1460
+ label: t("field.continueTextMaxTokens"),
1461
+ hint: t("field.continueTextMaxTokensHint"),
1462
+ ...shared,
1463
+ ...state2.continueTextMaxTokens,
1464
+ onEdit: (text) => props.edit("continueTextMaxTokens", text),
1465
+ placeholder: t("default.continueTextMaxTokens"),
1466
+ onReset: () => props.resetField("continueTextMaxTokens")
1467
+ }
1468
+ )
1469
+ ]
1335
1470
  }
1336
1471
  ),
1337
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1338
- ValueField,
1472
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
1473
+ SettingsSection,
1339
1474
  {
1340
- id: "auto-continue-loop-short-count",
1341
- label: t("field.loopShortCount"),
1342
- hint: t("field.loopShortCountHint"),
1343
- numeric: true,
1344
- ...shared,
1345
- ...state2.loopShortCount,
1346
- onEdit: (text) => props.edit("loopShortCount", text),
1347
- onReset: () => props.resetField("loopShortCount")
1475
+ t,
1476
+ titleKey: "section.safety.title",
1477
+ descriptionKey: "section.safety.description",
1478
+ tone: "safety",
1479
+ children: [
1480
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1481
+ BooleanField,
1482
+ {
1483
+ wide: true,
1484
+ id: "auto-continue-guard-tools",
1485
+ label: t("field.guardTools"),
1486
+ hint: t("field.guardToolsHint"),
1487
+ ...shared,
1488
+ ...state2.guardTools,
1489
+ onEdit: (text) => props.edit("guardTools", text),
1490
+ onReset: () => props.resetField("guardTools")
1491
+ }
1492
+ ),
1493
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1494
+ ValueField,
1495
+ {
1496
+ wide: true,
1497
+ id: "auto-continue-guard-pending-text",
1498
+ label: t("field.guardPendingText"),
1499
+ hint: t("field.guardPendingTextHint"),
1500
+ ...shared,
1501
+ ...state2.guardPendingText,
1502
+ onEdit: (text) => props.edit("guardPendingText", text),
1503
+ placeholder: t("default.guardPendingText"),
1504
+ onReset: () => props.resetField("guardPendingText")
1505
+ }
1506
+ ),
1507
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1508
+ ValueField,
1509
+ {
1510
+ wide: true,
1511
+ id: "auto-continue-guard-done-text",
1512
+ label: t("field.guardDoneText"),
1513
+ hint: t("field.guardDoneTextHint"),
1514
+ ...shared,
1515
+ ...state2.guardDoneText,
1516
+ onEdit: (text) => props.edit("guardDoneText", text),
1517
+ placeholder: t("default.guardDoneText"),
1518
+ onReset: () => props.resetField("guardDoneText")
1519
+ }
1520
+ ),
1521
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1522
+ ValueField,
1523
+ {
1524
+ id: "auto-continue-grace-ms",
1525
+ label: t("field.graceMs"),
1526
+ hint: t("field.graceMsHint"),
1527
+ numeric: true,
1528
+ ...shared,
1529
+ ...state2.graceMs,
1530
+ onEdit: (text) => props.edit("graceMs", text),
1531
+ onReset: () => props.resetField("graceMs")
1532
+ }
1533
+ ),
1534
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1535
+ ValueField,
1536
+ {
1537
+ id: "auto-continue-cooldown-ms",
1538
+ label: t("field.cooldownMs"),
1539
+ hint: t("field.cooldownMsHint"),
1540
+ numeric: true,
1541
+ ...shared,
1542
+ ...state2.cooldownMs,
1543
+ onEdit: (text) => props.edit("cooldownMs", text),
1544
+ onReset: () => props.resetField("cooldownMs")
1545
+ }
1546
+ ),
1547
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1548
+ ValueField,
1549
+ {
1550
+ id: "auto-continue-max-consecutive",
1551
+ label: t("field.maxConsecutive"),
1552
+ hint: t("field.maxConsecutiveHint"),
1553
+ numeric: true,
1554
+ ...shared,
1555
+ ...state2.maxConsecutive,
1556
+ onEdit: (text) => props.edit("maxConsecutive", text),
1557
+ onReset: () => props.resetField("maxConsecutive")
1558
+ }
1559
+ )
1560
+ ]
1348
1561
  }
1349
1562
  ),
1350
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1351
- ValueField,
1563
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
1564
+ SettingsSection,
1352
1565
  {
1353
- id: "auto-continue-loop-tool-repeat",
1354
- label: t("field.loopToolRepeat"),
1355
- hint: t("field.loopToolRepeatHint"),
1356
- numeric: true,
1357
- ...shared,
1358
- ...state2.loopToolRepeat,
1359
- onEdit: (text) => props.edit("loopToolRepeat", text),
1360
- onReset: () => props.resetField("loopToolRepeat")
1566
+ t,
1567
+ titleKey: "section.recovery.title",
1568
+ descriptionKey: "section.recovery.description",
1569
+ tone: "recovery",
1570
+ children: [
1571
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1572
+ BooleanField,
1573
+ {
1574
+ id: "auto-continue-scan-on-boot",
1575
+ label: t("field.scanOnBoot"),
1576
+ hint: t("field.scanOnBootHint"),
1577
+ ...shared,
1578
+ ...state2.scanOnBoot,
1579
+ onEdit: (text) => props.edit("scanOnBoot", text),
1580
+ onReset: () => props.resetField("scanOnBoot")
1581
+ }
1582
+ ),
1583
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1584
+ BooleanField,
1585
+ {
1586
+ id: "auto-continue-classify",
1587
+ label: t("field.classify"),
1588
+ hint: t("field.classifyHint"),
1589
+ ...shared,
1590
+ ...state2.classify,
1591
+ onEdit: (text) => props.edit("classify", text),
1592
+ onReset: () => props.resetField("classify")
1593
+ }
1594
+ ),
1595
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1596
+ ValueField,
1597
+ {
1598
+ id: "auto-continue-scan-limit",
1599
+ label: t("field.scanLimit"),
1600
+ hint: t("field.scanLimitHint"),
1601
+ numeric: true,
1602
+ ...shared,
1603
+ ...state2.scanLimit,
1604
+ onEdit: (text) => props.edit("scanLimit", text),
1605
+ onReset: () => props.resetField("scanLimit")
1606
+ }
1607
+ ),
1608
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1609
+ ValueField,
1610
+ {
1611
+ id: "auto-continue-fresh-ms",
1612
+ label: t("field.freshMs"),
1613
+ hint: t("field.freshMsHint"),
1614
+ numeric: true,
1615
+ ...shared,
1616
+ ...state2.freshMs,
1617
+ onEdit: (text) => props.edit("freshMs", text),
1618
+ onReset: () => props.resetField("freshMs")
1619
+ }
1620
+ ),
1621
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1622
+ ValueField,
1623
+ {
1624
+ wide: true,
1625
+ id: "auto-continue-retryable-error-patterns",
1626
+ label: t("field.retryableErrorPatterns"),
1627
+ hint: t("field.retryableErrorPatternsHint"),
1628
+ multiline: true,
1629
+ ...shared,
1630
+ ...state2.retryableErrorPatterns,
1631
+ onEdit: (text) => props.edit("retryableErrorPatterns", text),
1632
+ placeholder: t("field.retryableErrorPatternsPlaceholder"),
1633
+ onReset: () => props.resetField("retryableErrorPatterns")
1634
+ }
1635
+ ),
1636
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1637
+ ValueField,
1638
+ {
1639
+ id: "auto-continue-backoff-factor",
1640
+ label: t("field.backoffFactor"),
1641
+ hint: t("field.backoffFactorHint"),
1642
+ numeric: true,
1643
+ ...shared,
1644
+ ...state2.backoffFactor,
1645
+ onEdit: (text) => props.edit("backoffFactor", text),
1646
+ onReset: () => props.resetField("backoffFactor")
1647
+ }
1648
+ ),
1649
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1650
+ ValueField,
1651
+ {
1652
+ id: "auto-continue-backoff-max",
1653
+ label: t("field.backoffMaxMs"),
1654
+ hint: t("field.backoffMaxMsHint"),
1655
+ numeric: true,
1656
+ ...shared,
1657
+ ...state2.backoffMaxMs,
1658
+ onEdit: (text) => props.edit("backoffMaxMs", text),
1659
+ onReset: () => props.resetField("backoffMaxMs")
1660
+ }
1661
+ ),
1662
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1663
+ BooleanField,
1664
+ {
1665
+ id: "auto-continue-notify",
1666
+ label: t("field.notify"),
1667
+ hint: t("field.notifyHint"),
1668
+ ...shared,
1669
+ ...state2.notify,
1670
+ onEdit: (text) => props.edit("notify", text),
1671
+ onReset: () => props.resetField("notify")
1672
+ }
1673
+ ),
1674
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1675
+ BooleanField,
1676
+ {
1677
+ id: "auto-continue-verbose",
1678
+ label: t("field.verbose"),
1679
+ hint: t("field.verboseHint"),
1680
+ ...shared,
1681
+ ...state2.verbose,
1682
+ onEdit: (text) => props.edit("verbose", text),
1683
+ onReset: () => props.resetField("verbose")
1684
+ }
1685
+ )
1686
+ ]
1361
1687
  }
1362
1688
  ),
1363
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1364
- ValueField,
1689
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
1690
+ SettingsSection,
1365
1691
  {
1366
- id: "auto-continue-loop-repeat-text",
1367
- label: t("field.loopRepeatText"),
1368
- hint: t("field.loopRepeatTextHint"),
1369
- numeric: true,
1370
- ...shared,
1371
- ...state2.loopRepeatText,
1372
- onEdit: (text) => props.edit("loopRepeatText", text),
1373
- onReset: () => props.resetField("loopRepeatText")
1692
+ t,
1693
+ titleKey: "section.loop.title",
1694
+ descriptionKey: "section.loop.description",
1695
+ tone: "loop",
1696
+ children: [
1697
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1698
+ BooleanField,
1699
+ {
1700
+ wide: true,
1701
+ id: "auto-continue-loop-guard",
1702
+ label: t("field.loopGuard"),
1703
+ hint: t("field.loopGuardHint"),
1704
+ ...shared,
1705
+ ...state2.loopGuard,
1706
+ onEdit: (text) => props.edit("loopGuard", text),
1707
+ onReset: () => props.resetField("loopGuard")
1708
+ }
1709
+ ),
1710
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1711
+ ValueField,
1712
+ {
1713
+ id: "auto-continue-loop-short-chars",
1714
+ label: t("field.loopShortChars"),
1715
+ hint: t("field.loopShortCharsHint"),
1716
+ numeric: true,
1717
+ ...shared,
1718
+ ...state2.loopShortChars,
1719
+ onEdit: (text) => props.edit("loopShortChars", text),
1720
+ onReset: () => props.resetField("loopShortChars")
1721
+ }
1722
+ ),
1723
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1724
+ ValueField,
1725
+ {
1726
+ id: "auto-continue-loop-window-ms",
1727
+ label: t("field.loopWindowMs"),
1728
+ hint: t("field.loopWindowMsHint"),
1729
+ numeric: true,
1730
+ ...shared,
1731
+ ...state2.loopWindowMs,
1732
+ onEdit: (text) => props.edit("loopWindowMs", text),
1733
+ onReset: () => props.resetField("loopWindowMs")
1734
+ }
1735
+ ),
1736
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1737
+ ValueField,
1738
+ {
1739
+ id: "auto-continue-loop-short-count",
1740
+ label: t("field.loopShortCount"),
1741
+ hint: t("field.loopShortCountHint"),
1742
+ numeric: true,
1743
+ ...shared,
1744
+ ...state2.loopShortCount,
1745
+ onEdit: (text) => props.edit("loopShortCount", text),
1746
+ onReset: () => props.resetField("loopShortCount")
1747
+ }
1748
+ ),
1749
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1750
+ ValueField,
1751
+ {
1752
+ id: "auto-continue-loop-repeat-text",
1753
+ label: t("field.loopRepeatText"),
1754
+ hint: t("field.loopRepeatTextHint"),
1755
+ numeric: true,
1756
+ ...shared,
1757
+ ...state2.loopRepeatText,
1758
+ onEdit: (text) => props.edit("loopRepeatText", text),
1759
+ onReset: () => props.resetField("loopRepeatText")
1760
+ }
1761
+ ),
1762
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1763
+ ValueField,
1764
+ {
1765
+ id: "auto-continue-loop-tool-repeat",
1766
+ label: t("field.loopToolRepeat"),
1767
+ hint: t("field.loopToolRepeatHint"),
1768
+ numeric: true,
1769
+ ...shared,
1770
+ ...state2.loopToolRepeat,
1771
+ onEdit: (text) => props.edit("loopToolRepeat", text),
1772
+ onReset: () => props.resetField("loopToolRepeat")
1773
+ }
1774
+ ),
1775
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1776
+ ValueField,
1777
+ {
1778
+ wide: true,
1779
+ id: "auto-continue-loop-text",
1780
+ label: t("field.loopText"),
1781
+ hint: t("field.loopTextHint"),
1782
+ ...shared,
1783
+ ...state2.loopText,
1784
+ onEdit: (text) => props.edit("loopText", text),
1785
+ placeholder: t("default.loopText"),
1786
+ onReset: () => props.resetField("loopText")
1787
+ }
1788
+ )
1789
+ ]
1374
1790
  }
1375
1791
  ),
1376
1792
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1377
- ValueField,
1793
+ SettingsSection,
1378
1794
  {
1379
- id: "auto-continue-loop-text",
1380
- label: t("field.loopText"),
1381
- hint: t("field.loopTextHint"),
1382
- ...shared,
1383
- ...state2.loopText,
1384
- onEdit: (text) => props.edit("loopText", text),
1385
- placeholder: t("default.loopText"),
1386
- onReset: () => props.resetField("loopText")
1795
+ t,
1796
+ titleKey: "section.live.title",
1797
+ descriptionKey: "section.live.description",
1798
+ tone: "live",
1799
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(LivePanels, { t })
1387
1800
  }
1388
- ),
1389
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(LivePanels, { t })
1390
- ]
1801
+ )
1802
+ ] })
1391
1803
  }
1392
1804
  );
1393
1805
  }