@shendeguize/dsh-agent-sidecar 0.1.1 → 0.2.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/README.md +78 -11
- package/lib/client.js +8659 -7589
- package/lib/client.js.map +1 -1
- package/package.json +3 -1
- package/src/client/analysis/AnalysisPanel.tsx +19 -27
- package/src/client/analysis/analysis.module.css +36 -97
- package/src/client/board/Board.tsx +115 -61
- package/src/client/board/board.module.css +72 -151
- package/src/client/board/project-view-logic.ts +21 -34
- package/src/client/board/project-view.module.css +41 -96
- package/src/client/board/project-view.tsx +29 -13
- package/src/client/board/strings.ts +68 -107
- package/src/client/commands.ts +30 -15
- package/src/client/detail/SessionDetail.tsx +92 -58
- package/src/client/detail/detail.module.css +62 -218
- package/src/client/detail/strings.ts +64 -88
- package/src/client/detail-view.module.css +30 -55
- package/src/client/detail-view.tsx +80 -108
- package/src/client/dsh-tools/LineageTree.tsx +22 -13
- package/src/client/dsh-tools/SearchPanel.tsx +18 -11
- package/src/client/dsh-tools/dsh-tools.module.css +50 -139
- package/src/client/dsh-tools/strings.ts +42 -77
- package/src/client/index.ts +285 -124
- package/src/client/inject/InjectPanel.tsx +31 -64
- package/src/client/inject/inject.module.css +97 -198
- package/src/client/lifecycle/handoff.ts +83 -0
- package/src/client/locales/en.ts +74 -2
- package/src/client/locales/host.ts +131 -0
- package/src/client/locales/index.ts +196 -8
- package/src/client/locales/react.ts +10 -0
- package/src/client/locales/view.ts +38 -0
- package/src/client/locales/zh.ts +194 -134
- package/src/client/mount.tsx +72 -38
- package/src/client/navigation/CenterOverlay.tsx +40 -0
- package/src/client/navigation/center-overlay.module.css +51 -0
- package/src/client/navigation/center.ts +45 -0
- package/src/client/navigation/modal-isolation.ts +152 -0
- package/src/client/navigation/modal-surface-anchor.ts +72 -0
- package/src/client/navigation/sidebar-entry.module.css +73 -0
- package/src/client/navigation/sidebar-entry.ts +309 -0
- package/src/client/primitives/StaticPill.tsx +21 -0
- package/src/client/settings-card.module.css +35 -119
- package/src/client/settings-card.tsx +31 -153
- package/src/client/settings-fields.tsx +131 -0
- package/src/client/sidebar/SidebarTab.tsx +156 -0
- package/src/client/sidebar/model.ts +65 -0
- package/src/client/sidebar/sidebar-tab.module.css +118 -0
- package/src/client/sidebar-tab.tsx +46 -320
- package/src/client/theme/agsc.module.css +31 -0
- package/src/client/theme/parts.ts +56 -0
- package/src/client/ui-integration.ts +86 -0
- package/src/client/widget.tsx +9 -8
- package/src/client/inject/overlay.module.css +0 -22
|
@@ -1,41 +1,30 @@
|
|
|
1
|
-
/* Inject panel (design §5.1 view 3). Every color rides a dsh --dsw-alias-*
|
|
2
|
-
* design token WITH a neutral fallback (UX-16: same token+fallback
|
|
3
|
-
* discipline as every other CSS module), and error tones ride the
|
|
4
|
-
* state-error-* family the board uses. The confirm-injection button is
|
|
5
|
-
* the one danger affordance: eye-catching (error-toned border/text,
|
|
6
|
-
* filled on hover) but restrained (no permanent solid red block). */
|
|
7
|
-
|
|
8
1
|
.panel {
|
|
9
|
-
border: 1px solid var(--dsw-alias-border-l2, rgba(0, 0, 0, 0.12));
|
|
10
|
-
border-radius: 12px;
|
|
11
|
-
background: var(--dsw-alias-bg-layer-2, rgba(0, 0, 0, 0.04));
|
|
12
|
-
max-width: 560px;
|
|
13
2
|
display: flex;
|
|
14
3
|
flex-direction: column;
|
|
4
|
+
max-width: 560px;
|
|
5
|
+
border: 1px solid var(--agsc-border-strong);
|
|
6
|
+
border-radius: var(--agsc-radius-card);
|
|
7
|
+
background: var(--agsc-bg);
|
|
15
8
|
}
|
|
16
9
|
|
|
17
|
-
/* ── header ────────────────────────────────────────────────────────────── */
|
|
18
|
-
|
|
19
10
|
.header {
|
|
20
11
|
display: flex;
|
|
21
12
|
align-items: center;
|
|
22
13
|
gap: 12px;
|
|
23
14
|
padding: 14px 16px 10px;
|
|
24
|
-
border-bottom: 1px solid var(--
|
|
15
|
+
border-bottom: 1px solid var(--agsc-border-strong);
|
|
25
16
|
}
|
|
26
17
|
|
|
27
18
|
.title {
|
|
28
19
|
flex: 1;
|
|
29
20
|
min-width: 0;
|
|
30
21
|
margin: 0;
|
|
22
|
+
color: var(--agsc-fg);
|
|
31
23
|
font-size: 15px;
|
|
32
24
|
font-weight: 600;
|
|
33
25
|
line-height: 1.4;
|
|
34
|
-
color: var(--dsw-alias-label-primary, #1f2328);
|
|
35
26
|
}
|
|
36
27
|
|
|
37
|
-
/* ── body ──────────────────────────────────────────────────────────────── */
|
|
38
|
-
|
|
39
28
|
.body {
|
|
40
29
|
display: flex;
|
|
41
30
|
flex-direction: column;
|
|
@@ -43,117 +32,120 @@
|
|
|
43
32
|
padding: 12px 16px 14px;
|
|
44
33
|
}
|
|
45
34
|
|
|
46
|
-
.capabilityOff
|
|
47
|
-
margin: 0;
|
|
48
|
-
border-radius: 8px;
|
|
49
|
-
padding: 10px 12px;
|
|
50
|
-
font-size: 13px;
|
|
51
|
-
line-height: 1.6;
|
|
52
|
-
background: var(--dsw-alias-bg-module-platform, rgba(0, 0, 0, 0.03));
|
|
53
|
-
color: var(--dsw-alias-label-secondary, #57606a);
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
/* ── notices (editor banners after a failed/expired attempt) ───────────── */
|
|
57
|
-
|
|
35
|
+
.capabilityOff,
|
|
58
36
|
.noticeWarn,
|
|
59
|
-
.noticeError
|
|
37
|
+
.noticeError,
|
|
38
|
+
.warnBar,
|
|
39
|
+
.auditNote,
|
|
40
|
+
.resultOk,
|
|
41
|
+
.resultFail,
|
|
42
|
+
.resultUnknown {
|
|
60
43
|
margin: 0;
|
|
61
|
-
border-radius: 8px;
|
|
62
44
|
padding: 8px 10px;
|
|
45
|
+
border-radius: var(--agsc-radius-control);
|
|
46
|
+
background: var(--agsc-bg-raised);
|
|
47
|
+
color: var(--agsc-fg-secondary);
|
|
63
48
|
font-size: 12px;
|
|
64
49
|
line-height: 1.6;
|
|
65
|
-
background: var(--dsw-alias-bg-module-platform, rgba(0, 0, 0, 0.03));
|
|
66
|
-
color: var(--dsw-alias-label-secondary, #57606a);
|
|
67
50
|
}
|
|
68
51
|
|
|
69
|
-
.
|
|
70
|
-
|
|
71
|
-
|
|
52
|
+
.noticeWarn,
|
|
53
|
+
.warnBar {
|
|
54
|
+
border: 1px solid var(--agsc-warn);
|
|
55
|
+
color: var(--agsc-warn);
|
|
72
56
|
}
|
|
73
57
|
|
|
74
|
-
.
|
|
75
|
-
|
|
58
|
+
.noticeError,
|
|
59
|
+
.resultFail {
|
|
60
|
+
border: 1px solid var(--agsc-err);
|
|
61
|
+
color: var(--agsc-err);
|
|
76
62
|
}
|
|
77
63
|
|
|
78
|
-
|
|
64
|
+
.noticeDetail,
|
|
65
|
+
.noTarget,
|
|
66
|
+
.modeHint,
|
|
67
|
+
.planKey,
|
|
68
|
+
.observedNote,
|
|
69
|
+
.resultDetail {
|
|
70
|
+
color: var(--agsc-fg-dimmed);
|
|
71
|
+
}
|
|
79
72
|
|
|
80
|
-
.targetRow
|
|
73
|
+
.targetRow,
|
|
74
|
+
.planRow {
|
|
81
75
|
display: flex;
|
|
82
76
|
align-items: baseline;
|
|
83
77
|
gap: 10px;
|
|
84
78
|
min-width: 0;
|
|
85
79
|
}
|
|
86
80
|
|
|
87
|
-
.noTarget
|
|
81
|
+
.noTarget,
|
|
82
|
+
.planKey,
|
|
83
|
+
.modeHint,
|
|
84
|
+
.resultDetail {
|
|
88
85
|
font-size: 12px;
|
|
89
86
|
line-height: 1.5;
|
|
90
|
-
color: var(--dsw-alias-label-tertiary, #6e7781);
|
|
91
87
|
}
|
|
92
88
|
|
|
93
89
|
.agentTag {
|
|
94
90
|
flex: none;
|
|
95
|
-
border-radius: 999px;
|
|
96
|
-
padding: 1px 8px;
|
|
97
|
-
font-size: 11px;
|
|
98
|
-
line-height: 17px;
|
|
99
|
-
font-weight: 500;
|
|
100
|
-
background: var(--dsw-alias-bg-module-platform, rgba(0, 0, 0, 0.03));
|
|
101
|
-
color: var(--dsw-alias-label-secondary, #57606a);
|
|
102
91
|
}
|
|
103
92
|
|
|
104
93
|
.planTitle {
|
|
105
94
|
min-width: 0;
|
|
106
95
|
overflow: hidden;
|
|
107
|
-
|
|
108
|
-
white-space: nowrap;
|
|
96
|
+
color: var(--agsc-fg);
|
|
109
97
|
font-size: 13px;
|
|
110
98
|
line-height: 1.5;
|
|
111
|
-
|
|
99
|
+
text-overflow: ellipsis;
|
|
100
|
+
white-space: nowrap;
|
|
112
101
|
}
|
|
113
102
|
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
.
|
|
103
|
+
.field,
|
|
104
|
+
.modeText,
|
|
105
|
+
.planPreview {
|
|
117
106
|
display: flex;
|
|
118
107
|
flex-direction: column;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
.field {
|
|
119
111
|
gap: 6px;
|
|
120
112
|
}
|
|
121
113
|
|
|
122
|
-
.label
|
|
114
|
+
.label,
|
|
115
|
+
.modeLabel {
|
|
116
|
+
color: var(--agsc-fg);
|
|
123
117
|
font-size: 13px;
|
|
124
118
|
line-height: 1.5;
|
|
125
|
-
color: var(--dsw-alias-label-primary, #1f2328);
|
|
126
119
|
}
|
|
127
120
|
|
|
128
121
|
.textarea {
|
|
129
122
|
appearance: none;
|
|
130
|
-
resize: vertical;
|
|
131
123
|
min-height: 96px;
|
|
132
|
-
|
|
133
|
-
border-radius: 8px;
|
|
134
|
-
background: var(--dsw-alias-bg-layer-3, #ffffff);
|
|
124
|
+
resize: vertical;
|
|
135
125
|
padding: 8px 10px;
|
|
126
|
+
border: 1px solid var(--agsc-border-strong);
|
|
127
|
+
border-radius: var(--agsc-radius-control);
|
|
128
|
+
background: var(--agsc-bg-raised);
|
|
129
|
+
color: var(--agsc-fg);
|
|
136
130
|
font: inherit;
|
|
137
131
|
font-size: 13px;
|
|
138
132
|
line-height: 1.6;
|
|
139
|
-
color: var(--dsw-alias-label-primary, #1f2328);
|
|
140
133
|
}
|
|
141
134
|
|
|
142
135
|
.textarea:focus-visible {
|
|
136
|
+
border-color: var(--agsc-accent);
|
|
143
137
|
outline: none;
|
|
144
|
-
border-color: var(--dsw-alias-brand-primary, #4d6bfe);
|
|
145
138
|
}
|
|
146
139
|
|
|
147
140
|
.textarea::placeholder {
|
|
148
|
-
color: var(--
|
|
141
|
+
color: var(--agsc-fg-dimmed);
|
|
149
142
|
}
|
|
150
143
|
|
|
151
144
|
.textarea:disabled {
|
|
152
|
-
opacity: 0.5;
|
|
153
145
|
cursor: default;
|
|
146
|
+
opacity: 0.5;
|
|
154
147
|
}
|
|
155
148
|
|
|
156
|
-
/* Byte counter: thin progress track + numeric readout. */
|
|
157
149
|
.byteRow {
|
|
158
150
|
display: flex;
|
|
159
151
|
align-items: center;
|
|
@@ -163,52 +155,49 @@
|
|
|
163
155
|
.byteBar {
|
|
164
156
|
flex: 1;
|
|
165
157
|
height: 3px;
|
|
166
|
-
border-radius: 2px;
|
|
167
|
-
background: var(--dsw-alias-bg-module-platform, rgba(0, 0, 0, 0.03));
|
|
168
158
|
overflow: hidden;
|
|
159
|
+
border-radius: 2px;
|
|
160
|
+
background: var(--agsc-border);
|
|
169
161
|
}
|
|
170
162
|
|
|
171
163
|
.byteFill {
|
|
172
164
|
height: 100%;
|
|
173
165
|
border-radius: 2px;
|
|
174
|
-
background: var(--
|
|
166
|
+
background: var(--agsc-accent);
|
|
175
167
|
transition: width .12s;
|
|
176
168
|
}
|
|
177
169
|
|
|
178
|
-
/* Modifier applied ALONGSIDE .byteFill (no `composes`; see settings card). */
|
|
179
170
|
.byteFillOver {
|
|
180
|
-
background: var(--
|
|
171
|
+
background: var(--agsc-err);
|
|
181
172
|
}
|
|
182
173
|
|
|
183
174
|
.byteText,
|
|
184
175
|
.byteTextOver {
|
|
185
176
|
flex: none;
|
|
177
|
+
color: var(--agsc-fg-dimmed);
|
|
186
178
|
font-size: 11px;
|
|
187
|
-
line-height: 1.5;
|
|
188
179
|
font-variant-numeric: tabular-nums;
|
|
189
|
-
|
|
180
|
+
line-height: 1.5;
|
|
190
181
|
}
|
|
191
182
|
|
|
192
|
-
.byteTextOver
|
|
193
|
-
|
|
183
|
+
.byteTextOver,
|
|
184
|
+
.invalid {
|
|
185
|
+
color: var(--agsc-err);
|
|
194
186
|
}
|
|
195
187
|
|
|
196
188
|
.invalid {
|
|
197
189
|
margin: 0;
|
|
198
190
|
font-size: 12px;
|
|
199
191
|
line-height: 1.5;
|
|
200
|
-
color: var(--dsw-alias-state-error-primary, #cf222e);
|
|
201
192
|
}
|
|
202
193
|
|
|
203
|
-
/* ── mode radios ───────────────────────────────────────────────────────── */
|
|
204
|
-
|
|
205
194
|
.modes {
|
|
206
|
-
margin: 0;
|
|
207
|
-
border: 0;
|
|
208
|
-
padding: 0;
|
|
209
195
|
display: flex;
|
|
210
196
|
flex-direction: column;
|
|
211
197
|
gap: 8px;
|
|
198
|
+
margin: 0;
|
|
199
|
+
padding: 0;
|
|
200
|
+
border: 0;
|
|
212
201
|
}
|
|
213
202
|
|
|
214
203
|
.modeOption {
|
|
@@ -219,10 +208,10 @@
|
|
|
219
208
|
}
|
|
220
209
|
|
|
221
210
|
.modeOption input {
|
|
222
|
-
accent-color: var(--dsw-alias-brand-primary, #4d6bfe);
|
|
223
211
|
width: 14px;
|
|
224
212
|
height: 14px;
|
|
225
213
|
margin: 3px 0 0;
|
|
214
|
+
accent-color: var(--agsc-accent);
|
|
226
215
|
cursor: pointer;
|
|
227
216
|
}
|
|
228
217
|
|
|
@@ -231,71 +220,26 @@
|
|
|
231
220
|
}
|
|
232
221
|
|
|
233
222
|
.modeText {
|
|
234
|
-
display: flex;
|
|
235
|
-
flex-direction: column;
|
|
236
223
|
gap: 2px;
|
|
237
224
|
min-width: 0;
|
|
238
225
|
}
|
|
239
226
|
|
|
240
|
-
.modeLabel {
|
|
241
|
-
font-size: 13px;
|
|
242
|
-
line-height: 1.5;
|
|
243
|
-
color: var(--dsw-alias-label-primary, #1f2328);
|
|
244
|
-
}
|
|
245
|
-
|
|
246
|
-
.modeHint {
|
|
247
|
-
font-size: 12px;
|
|
248
|
-
line-height: 1.5;
|
|
249
|
-
color: var(--dsw-alias-label-tertiary, #6e7781);
|
|
250
|
-
}
|
|
251
|
-
|
|
252
|
-
/* ── warnings & audit note ─────────────────────────────────────────────── */
|
|
253
|
-
|
|
254
|
-
.warnBar {
|
|
255
|
-
margin: 0;
|
|
256
|
-
border: 1px solid var(--dsw-alias-state-error-primary, #cf222e);
|
|
257
|
-
border-radius: 8px;
|
|
258
|
-
padding: 8px 10px;
|
|
259
|
-
font-size: 12px;
|
|
260
|
-
line-height: 1.6;
|
|
261
|
-
background: var(--dsw-alias-bg-module-platform, rgba(0, 0, 0, 0.03));
|
|
262
|
-
color: var(--dsw-alias-state-error-primary, #cf222e);
|
|
263
|
-
}
|
|
264
|
-
|
|
265
227
|
.auditNote {
|
|
266
|
-
margin: 0;
|
|
267
|
-
border-radius: 8px;
|
|
268
228
|
padding: 8px 10px;
|
|
269
|
-
font-size: 12px;
|
|
270
|
-
line-height: 1.6;
|
|
271
|
-
background: var(--dsw-alias-bg-module-platform, rgba(0, 0, 0, 0.03));
|
|
272
|
-
color: var(--dsw-alias-label-secondary, #57606a);
|
|
273
229
|
}
|
|
274
230
|
|
|
275
|
-
/* ── confirm plan ──────────────────────────────────────────────────────── */
|
|
276
|
-
|
|
277
231
|
.planBox {
|
|
278
|
-
border: 1px solid var(--dsw-alias-border-l2, rgba(0, 0, 0, 0.12));
|
|
279
|
-
border-radius: 8px;
|
|
280
|
-
background: var(--dsw-alias-bg-layer-3, #ffffff);
|
|
281
|
-
padding: 10px 12px;
|
|
282
232
|
display: flex;
|
|
283
233
|
flex-direction: column;
|
|
284
234
|
gap: 6px;
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
align-items: baseline;
|
|
290
|
-
gap: 10px;
|
|
291
|
-
min-width: 0;
|
|
235
|
+
padding: 10px 12px;
|
|
236
|
+
border: 1px solid var(--agsc-border-strong);
|
|
237
|
+
border-radius: var(--agsc-radius-control);
|
|
238
|
+
background: var(--agsc-bg-raised);
|
|
292
239
|
}
|
|
293
240
|
|
|
294
241
|
.planKey {
|
|
295
242
|
flex: none;
|
|
296
|
-
font-size: 12px;
|
|
297
|
-
line-height: 1.5;
|
|
298
|
-
color: var(--dsw-alias-label-tertiary, #6e7781);
|
|
299
243
|
}
|
|
300
244
|
|
|
301
245
|
.planValue {
|
|
@@ -303,85 +247,67 @@
|
|
|
303
247
|
align-items: baseline;
|
|
304
248
|
gap: 8px;
|
|
305
249
|
min-width: 0;
|
|
250
|
+
color: var(--agsc-fg);
|
|
306
251
|
font-size: 13px;
|
|
307
252
|
line-height: 1.5;
|
|
308
|
-
color: var(--dsw-alias-label-primary, #1f2328);
|
|
309
253
|
}
|
|
310
254
|
|
|
311
255
|
.observedNote {
|
|
312
256
|
margin: 0;
|
|
313
257
|
font-size: 11px;
|
|
314
258
|
line-height: 1.5;
|
|
315
|
-
color: var(--dsw-alias-label-tertiary, #6e7781);
|
|
316
259
|
}
|
|
317
260
|
|
|
318
261
|
.planPreview {
|
|
319
|
-
display: flex;
|
|
320
|
-
flex-direction: column;
|
|
321
262
|
gap: 4px;
|
|
322
263
|
min-width: 0;
|
|
323
264
|
}
|
|
324
265
|
|
|
325
266
|
.preview {
|
|
326
|
-
margin: 0;
|
|
327
|
-
border: 1px solid var(--dsw-alias-border-l2, rgba(0, 0, 0, 0.12));
|
|
328
|
-
border-radius: 6px;
|
|
329
|
-
background: var(--dsw-alias-bg-layer-2, rgba(0, 0, 0, 0.04));
|
|
330
|
-
padding: 8px 10px;
|
|
331
267
|
max-height: 120px;
|
|
332
268
|
overflow: auto;
|
|
269
|
+
margin: 0;
|
|
270
|
+
padding: 8px 10px;
|
|
271
|
+
border: 1px solid var(--agsc-border-strong);
|
|
272
|
+
border-radius: 6px;
|
|
273
|
+
background: var(--agsc-bg);
|
|
274
|
+
color: var(--agsc-fg-secondary);
|
|
333
275
|
font-size: 12px;
|
|
334
276
|
line-height: 1.6;
|
|
335
277
|
white-space: pre-wrap;
|
|
336
278
|
word-break: break-word;
|
|
337
|
-
color: var(--dsw-alias-label-secondary, #57606a);
|
|
338
279
|
}
|
|
339
280
|
|
|
340
281
|
.countdown {
|
|
341
282
|
margin: 0;
|
|
283
|
+
color: var(--agsc-fg-secondary);
|
|
342
284
|
font-size: 12px;
|
|
343
|
-
line-height: 1.5;
|
|
344
285
|
font-variant-numeric: tabular-nums;
|
|
345
|
-
|
|
286
|
+
line-height: 1.5;
|
|
346
287
|
}
|
|
347
288
|
|
|
348
|
-
/* ── results ───────────────────────────────────────────────────────────── */
|
|
349
|
-
|
|
350
289
|
.resultOk,
|
|
351
290
|
.resultFail,
|
|
352
291
|
.resultUnknown {
|
|
353
|
-
margin: 0;
|
|
354
|
-
border-radius: 8px;
|
|
355
292
|
padding: 10px 12px;
|
|
293
|
+
color: var(--agsc-fg);
|
|
356
294
|
font-size: 13px;
|
|
357
|
-
line-height: 1.6;
|
|
358
|
-
background: var(--dsw-alias-bg-module-platform, rgba(0, 0, 0, 0.03));
|
|
359
|
-
color: var(--dsw-alias-label-primary, #1f2328);
|
|
360
295
|
}
|
|
361
296
|
|
|
362
297
|
.resultOk {
|
|
363
|
-
border: 1px solid var(--
|
|
364
|
-
}
|
|
365
|
-
|
|
366
|
-
.resultFail {
|
|
367
|
-
border: 1px solid var(--dsw-alias-state-error-primary, #cf222e);
|
|
368
|
-
color: var(--dsw-alias-state-error-primary, #cf222e);
|
|
298
|
+
border: 1px solid var(--agsc-ok);
|
|
369
299
|
}
|
|
370
300
|
|
|
371
301
|
.resultUnknown {
|
|
372
|
-
border: 1px solid var(--
|
|
373
|
-
color: var(--
|
|
302
|
+
border: 1px solid var(--agsc-fg-dimmed);
|
|
303
|
+
color: var(--agsc-fg-secondary);
|
|
374
304
|
}
|
|
375
305
|
|
|
376
306
|
.resultDetail {
|
|
377
307
|
margin: 0;
|
|
378
|
-
font-size: 12px;
|
|
379
308
|
line-height: 1.6;
|
|
380
|
-
color: var(--dsw-alias-label-tertiary, #6e7781);
|
|
381
309
|
}
|
|
382
310
|
|
|
383
|
-
/* ── footer buttons ────────────────────────────────────────────────────── */
|
|
384
|
-
|
|
385
311
|
.footer {
|
|
386
312
|
display: flex;
|
|
387
313
|
align-items: center;
|
|
@@ -390,58 +316,31 @@
|
|
|
390
316
|
padding-top: 4px;
|
|
391
317
|
}
|
|
392
318
|
|
|
393
|
-
.btn,
|
|
394
|
-
.btnPrimary,
|
|
395
319
|
.btnDanger {
|
|
396
320
|
appearance: none;
|
|
397
|
-
border: 1px solid transparent;
|
|
398
|
-
border-radius: 8px;
|
|
399
321
|
padding: 5px 14px;
|
|
322
|
+
border: 1px solid var(--agsc-err);
|
|
323
|
+
border-radius: var(--agsc-radius-control);
|
|
324
|
+
background: transparent;
|
|
325
|
+
color: var(--agsc-err);
|
|
400
326
|
font: inherit;
|
|
401
327
|
font-size: 13px;
|
|
328
|
+
font-weight: 600;
|
|
402
329
|
line-height: 1.5;
|
|
403
330
|
cursor: pointer;
|
|
404
331
|
}
|
|
405
332
|
|
|
406
|
-
.btn {
|
|
407
|
-
border-color: var(--dsw-alias-border-l2, rgba(0, 0, 0, 0.12));
|
|
408
|
-
background: none;
|
|
409
|
-
color: var(--dsw-alias-label-secondary, #57606a);
|
|
410
|
-
}
|
|
411
|
-
|
|
412
|
-
.btn:hover:not(:disabled) {
|
|
413
|
-
color: var(--dsw-alias-label-primary, #1f2328);
|
|
414
|
-
border-color: var(--dsw-alias-label-dimmed, #8c959f);
|
|
415
|
-
}
|
|
416
|
-
|
|
417
|
-
.btnPrimary {
|
|
418
|
-
background: var(--dsw-alias-label-primary, #1f2328);
|
|
419
|
-
color: var(--dsw-alias-bg-layer-3, #ffffff);
|
|
420
|
-
}
|
|
421
|
-
|
|
422
|
-
/* The danger action: outlined error tone at rest, fills on hover. */
|
|
423
|
-
.btnDanger {
|
|
424
|
-
border-color: var(--dsw-alias-state-error-primary, #cf222e);
|
|
425
|
-
background: none;
|
|
426
|
-
color: var(--dsw-alias-state-error-primary, #cf222e);
|
|
427
|
-
font-weight: 600;
|
|
428
|
-
}
|
|
429
|
-
|
|
430
333
|
.btnDanger:hover:not(:disabled) {
|
|
431
|
-
background: var(--
|
|
432
|
-
color: var(--
|
|
334
|
+
background: var(--agsc-err);
|
|
335
|
+
color: var(--agsc-bg-raised);
|
|
433
336
|
}
|
|
434
337
|
|
|
435
|
-
.btn:disabled,
|
|
436
|
-
.btnPrimary:disabled,
|
|
437
338
|
.btnDanger:disabled {
|
|
438
|
-
opacity: 0.4;
|
|
439
339
|
cursor: default;
|
|
340
|
+
opacity: 0.4;
|
|
440
341
|
}
|
|
441
342
|
|
|
442
|
-
.btn:focus-visible,
|
|
443
|
-
.btnPrimary:focus-visible,
|
|
444
343
|
.btnDanger:focus-visible {
|
|
445
|
-
outline: 2px solid var(--
|
|
344
|
+
outline: 2px solid var(--agsc-accent);
|
|
446
345
|
outline-offset: 1px;
|
|
447
346
|
}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
export type ResourceDisposer = () => void
|
|
2
|
+
|
|
3
|
+
/** Narrow clock port for deterministic handoff tests. */
|
|
4
|
+
export interface HandoffScheduler {
|
|
5
|
+
setTimeout(callback: () => void, delayMs: number): unknown
|
|
6
|
+
clearTimeout(handle: unknown): void
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export interface HandoffOptions {
|
|
10
|
+
isCollision(error: unknown): boolean
|
|
11
|
+
onError(error: unknown): void
|
|
12
|
+
onTimeout(): void
|
|
13
|
+
scheduler?: HandoffScheduler
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
const DEFAULT_DELAYS_MS = [8, 16, 32, 64, 128, 256, 496] as const
|
|
17
|
+
|
|
18
|
+
const defaultScheduler: HandoffScheduler = {
|
|
19
|
+
setTimeout: (callback, delayMs) => globalThis.setTimeout(callback, delayMs),
|
|
20
|
+
clearTimeout: (handle) => globalThis.clearTimeout(handle as ReturnType<typeof setTimeout>),
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Acquire a registry resource now, or briefly wait for an overlapping old
|
|
25
|
+
* fiber to release it. The returned lease owns both waiting and acquisition.
|
|
26
|
+
*/
|
|
27
|
+
export function acquireWithHandoff(
|
|
28
|
+
register: () => ResourceDisposer | undefined,
|
|
29
|
+
options: HandoffOptions,
|
|
30
|
+
): ResourceDisposer {
|
|
31
|
+
const scheduler = options.scheduler ?? defaultScheduler
|
|
32
|
+
let stopped = false
|
|
33
|
+
let attempts = 0
|
|
34
|
+
let delayIndex = 0
|
|
35
|
+
let timer: unknown
|
|
36
|
+
let acquired: ResourceDisposer | undefined
|
|
37
|
+
|
|
38
|
+
const finishError = (error: unknown): void => {
|
|
39
|
+
stopped = true
|
|
40
|
+
options.onError(error)
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
const attempt = (): void => {
|
|
44
|
+
if (stopped) return
|
|
45
|
+
timer = undefined
|
|
46
|
+
attempts += 1
|
|
47
|
+
try {
|
|
48
|
+
acquired = register()
|
|
49
|
+
} catch (error) {
|
|
50
|
+
if (!options.isCollision(error)) {
|
|
51
|
+
finishError(error)
|
|
52
|
+
return
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
if (acquired !== undefined) return
|
|
56
|
+
if (attempts >= 8 || delayIndex >= DEFAULT_DELAYS_MS.length) {
|
|
57
|
+
stopped = true
|
|
58
|
+
options.onTimeout()
|
|
59
|
+
return
|
|
60
|
+
}
|
|
61
|
+
const delay = DEFAULT_DELAYS_MS[delayIndex++]
|
|
62
|
+
try {
|
|
63
|
+
timer = scheduler.setTimeout(attempt, delay!)
|
|
64
|
+
} catch (error) {
|
|
65
|
+
finishError(error)
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
attempt()
|
|
70
|
+
return () => {
|
|
71
|
+
if (stopped) return
|
|
72
|
+
stopped = true
|
|
73
|
+
if (timer !== undefined) scheduler.clearTimeout(timer)
|
|
74
|
+
const dispose = acquired
|
|
75
|
+
acquired = undefined
|
|
76
|
+
dispose?.()
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/** Only known duplicate-registry diagnostics are eligible for handoff. */
|
|
81
|
+
export function isRegistrationCollision(error: unknown): boolean {
|
|
82
|
+
return error instanceof Error && /\b(?:duplicate|already registered)\b/i.test(error.message)
|
|
83
|
+
}
|