@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,9 +1,4 @@
|
|
|
1
|
-
/*
|
|
2
|
-
* Project correlation view styles (T5.5): same visual language as
|
|
3
|
-
* board.module.css — every color rides a --dsw-alias-* design token with
|
|
4
|
-
* a neutral fallback, flex top bar, grouped sections. Sessions render as
|
|
5
|
-
* compact rows inside per-agent lanes instead of the board's card grid.
|
|
6
|
-
*/
|
|
1
|
+
/* Project correlation layout consumes the shared Agent Sidecar theme. */
|
|
7
2
|
|
|
8
3
|
.root {
|
|
9
4
|
display: flex;
|
|
@@ -14,8 +9,8 @@
|
|
|
14
9
|
padding: 16px 20px;
|
|
15
10
|
box-sizing: border-box;
|
|
16
11
|
overflow-y: auto;
|
|
17
|
-
color: var(--
|
|
18
|
-
background: var(--
|
|
12
|
+
color: var(--agsc-fg);
|
|
13
|
+
background: var(--agsc-bg);
|
|
19
14
|
}
|
|
20
15
|
|
|
21
16
|
/* ------------------------------------------------------------- top bar */
|
|
@@ -30,21 +25,12 @@
|
|
|
30
25
|
.title {
|
|
31
26
|
font-size: 15px;
|
|
32
27
|
font-weight: 650;
|
|
33
|
-
color: var(--
|
|
28
|
+
color: var(--agsc-fg);
|
|
34
29
|
}
|
|
35
30
|
|
|
36
31
|
.summary {
|
|
37
32
|
font-size: 12px;
|
|
38
|
-
color: var(--
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
.loadingChip {
|
|
42
|
-
font-size: 11px;
|
|
43
|
-
line-height: 18px;
|
|
44
|
-
padding: 0 8px;
|
|
45
|
-
border-radius: 999px;
|
|
46
|
-
color: var(--dsw-alias-label-secondary, #57606a);
|
|
47
|
-
background: var(--dsw-alias-bg-layer-2, rgba(0, 0, 0, 0.04));
|
|
33
|
+
color: var(--agsc-fg-secondary);
|
|
48
34
|
}
|
|
49
35
|
|
|
50
36
|
/* -------------------------------------------------------------- banner */
|
|
@@ -53,14 +39,14 @@
|
|
|
53
39
|
font-size: 12px;
|
|
54
40
|
line-height: 18px;
|
|
55
41
|
padding: 6px 10px;
|
|
56
|
-
border-radius:
|
|
57
|
-
border: 1px solid var(--
|
|
42
|
+
border-radius: var(--agsc-radius-control);
|
|
43
|
+
border: 1px solid var(--agsc-border);
|
|
58
44
|
}
|
|
59
45
|
|
|
60
46
|
.banner[data-tone='danger'] {
|
|
61
|
-
color: var(--
|
|
62
|
-
background: var(--dsw-alias-state-error-secondary
|
|
63
|
-
border-color: var(--dsw-alias-state-error-secondary
|
|
47
|
+
color: var(--agsc-err);
|
|
48
|
+
background: var(--dsw-alias-state-error-secondary);
|
|
49
|
+
border-color: var(--dsw-alias-state-error-secondary);
|
|
64
50
|
}
|
|
65
51
|
|
|
66
52
|
/* -------------------------------------------------------- empty states */
|
|
@@ -80,14 +66,14 @@
|
|
|
80
66
|
.emptyTitle {
|
|
81
67
|
font-size: 14px;
|
|
82
68
|
font-weight: 600;
|
|
83
|
-
color: var(--
|
|
69
|
+
color: var(--agsc-fg);
|
|
84
70
|
}
|
|
85
71
|
|
|
86
72
|
.emptyHint {
|
|
87
73
|
font-size: 12px;
|
|
88
74
|
max-width: 420px;
|
|
89
75
|
line-height: 20px;
|
|
90
|
-
color: var(--
|
|
76
|
+
color: var(--agsc-fg-secondary);
|
|
91
77
|
}
|
|
92
78
|
|
|
93
79
|
/* -------------------------------------------------------- group blocks */
|
|
@@ -97,9 +83,9 @@
|
|
|
97
83
|
flex-direction: column;
|
|
98
84
|
gap: 8px;
|
|
99
85
|
padding: 10px 12px;
|
|
100
|
-
border-radius:
|
|
101
|
-
border: 1px solid var(--
|
|
102
|
-
background: var(--
|
|
86
|
+
border-radius: var(--agsc-radius-card);
|
|
87
|
+
border: 1px solid var(--agsc-border-strong);
|
|
88
|
+
background: var(--agsc-bg-raised);
|
|
103
89
|
}
|
|
104
90
|
|
|
105
91
|
.groupHead {
|
|
@@ -113,7 +99,7 @@
|
|
|
113
99
|
.groupName {
|
|
114
100
|
font-size: 13px;
|
|
115
101
|
font-weight: 600;
|
|
116
|
-
color: var(--
|
|
102
|
+
color: var(--agsc-fg);
|
|
117
103
|
overflow: hidden;
|
|
118
104
|
text-overflow: ellipsis;
|
|
119
105
|
white-space: nowrap;
|
|
@@ -134,9 +120,9 @@
|
|
|
134
120
|
line-height: 18px;
|
|
135
121
|
padding: 0 7px;
|
|
136
122
|
border-radius: 999px;
|
|
137
|
-
border: 1px solid var(--
|
|
138
|
-
background: var(--dsw-alias-bg-layer-2
|
|
139
|
-
color: var(--
|
|
123
|
+
border: 1px solid var(--agsc-border);
|
|
124
|
+
background: var(--dsw-alias-bg-layer-2);
|
|
125
|
+
color: var(--agsc-fg-secondary);
|
|
140
126
|
white-space: nowrap;
|
|
141
127
|
}
|
|
142
128
|
|
|
@@ -145,8 +131,8 @@
|
|
|
145
131
|
line-height: 18px;
|
|
146
132
|
padding: 0 7px;
|
|
147
133
|
border-radius: 999px;
|
|
148
|
-
color: var(--dsw-alias-
|
|
149
|
-
background: var(--
|
|
134
|
+
color: var(--dsw-alias-label-primary-foreground);
|
|
135
|
+
background: var(--agsc-accent);
|
|
150
136
|
white-space: nowrap;
|
|
151
137
|
}
|
|
152
138
|
|
|
@@ -157,7 +143,7 @@
|
|
|
157
143
|
.groupMeta {
|
|
158
144
|
font-size: 11px;
|
|
159
145
|
flex: none;
|
|
160
|
-
color: var(--
|
|
146
|
+
color: var(--agsc-fg-dimmed);
|
|
161
147
|
white-space: nowrap;
|
|
162
148
|
}
|
|
163
149
|
|
|
@@ -181,12 +167,12 @@
|
|
|
181
167
|
gap: 5px;
|
|
182
168
|
font-size: 12px;
|
|
183
169
|
font-weight: 600;
|
|
184
|
-
color: var(--
|
|
170
|
+
color: var(--agsc-fg);
|
|
185
171
|
}
|
|
186
172
|
|
|
187
173
|
.glyph {
|
|
188
174
|
flex: none;
|
|
189
|
-
color: var(--
|
|
175
|
+
color: var(--agsc-accent);
|
|
190
176
|
}
|
|
191
177
|
|
|
192
178
|
.laneSessions {
|
|
@@ -198,19 +184,6 @@
|
|
|
198
184
|
/* UX-20: lane truncation fold (same look as the board's group fold). */
|
|
199
185
|
.showMore {
|
|
200
186
|
align-self: flex-start;
|
|
201
|
-
font-size: 12px;
|
|
202
|
-
font-family: inherit;
|
|
203
|
-
color: var(--dsw-alias-label-secondary, #57606a);
|
|
204
|
-
background: transparent;
|
|
205
|
-
border: 1px dashed var(--dsw-alias-border-l2, rgba(0, 0, 0, 0.12));
|
|
206
|
-
border-radius: 6px;
|
|
207
|
-
padding: 2px 10px;
|
|
208
|
-
cursor: pointer;
|
|
209
|
-
}
|
|
210
|
-
|
|
211
|
-
.showMore:hover {
|
|
212
|
-
color: var(--dsw-alias-label-primary, #1f2328);
|
|
213
|
-
background: var(--dsw-alias-interactive-bg-hover, rgba(0, 0, 0, 0.04));
|
|
214
187
|
}
|
|
215
188
|
|
|
216
189
|
/* -------------------------------------------------------- session rows */
|
|
@@ -224,36 +197,25 @@
|
|
|
224
197
|
font-family: inherit;
|
|
225
198
|
font-size: 12px;
|
|
226
199
|
padding: 5px 8px;
|
|
227
|
-
border-radius:
|
|
228
|
-
border: 1px solid var(--
|
|
229
|
-
background: var(--dsw-alias-bg-base
|
|
230
|
-
color: var(--
|
|
200
|
+
border-radius: var(--agsc-radius-control);
|
|
201
|
+
border: 1px solid var(--agsc-border);
|
|
202
|
+
background: var(--dsw-alias-bg-base);
|
|
203
|
+
color: var(--agsc-fg);
|
|
231
204
|
cursor: pointer;
|
|
232
205
|
}
|
|
233
206
|
|
|
234
207
|
.session:hover {
|
|
235
|
-
border-color: var(--
|
|
236
|
-
background: var(--dsw-alias-interactive-bg-hover
|
|
208
|
+
border-color: var(--agsc-border-strong);
|
|
209
|
+
background: var(--dsw-alias-interactive-bg-hover);
|
|
237
210
|
}
|
|
238
211
|
|
|
239
212
|
.session:focus-visible {
|
|
240
|
-
outline: 2px solid var(--
|
|
213
|
+
outline: 2px solid var(--agsc-accent);
|
|
241
214
|
outline-offset: 1px;
|
|
242
215
|
}
|
|
243
216
|
|
|
244
|
-
.
|
|
245
|
-
display: inline-flex;
|
|
246
|
-
align-items: center;
|
|
247
|
-
gap: 5px;
|
|
217
|
+
.statusPill {
|
|
248
218
|
flex: none;
|
|
249
|
-
font-size: 11px;
|
|
250
|
-
line-height: 18px;
|
|
251
|
-
padding: 0 7px;
|
|
252
|
-
border-radius: 999px;
|
|
253
|
-
border: 1px solid var(--dsw-alias-border-l1, rgba(0, 0, 0, 0.08));
|
|
254
|
-
background: var(--dsw-alias-bg-layer-1, rgba(0, 0, 0, 0.03));
|
|
255
|
-
color: var(--dsw-alias-label-secondary, #57606a);
|
|
256
|
-
white-space: nowrap;
|
|
257
219
|
}
|
|
258
220
|
|
|
259
221
|
.dot {
|
|
@@ -261,36 +223,24 @@
|
|
|
261
223
|
height: 7px;
|
|
262
224
|
border-radius: 50%;
|
|
263
225
|
flex: none;
|
|
264
|
-
background: var(--dsw-alias-label-tertiary
|
|
265
|
-
}
|
|
266
|
-
|
|
267
|
-
.dot[data-tone='success'] {
|
|
268
|
-
background: var(--dsw-alias-state-success-primary, #1a7f37);
|
|
269
|
-
}
|
|
270
|
-
|
|
271
|
-
.dot[data-tone='warn'] {
|
|
272
|
-
background: var(--dsw-alias-state-warn-primary, #9a6700);
|
|
273
|
-
}
|
|
274
|
-
|
|
275
|
-
.dot[data-tone='danger'] {
|
|
276
|
-
background: var(--dsw-alias-state-error-primary, #cf222e);
|
|
226
|
+
background: var(--dsw-alias-label-tertiary);
|
|
277
227
|
}
|
|
278
228
|
|
|
279
229
|
.dot[data-tone='neutral'] {
|
|
280
|
-
background: var(--dsw-alias-label-tertiary
|
|
230
|
+
background: var(--dsw-alias-label-tertiary);
|
|
281
231
|
}
|
|
282
232
|
|
|
283
233
|
.dot[data-tone='muted'] {
|
|
284
|
-
background: var(--
|
|
234
|
+
background: var(--agsc-fg-dimmed);
|
|
285
235
|
}
|
|
286
236
|
|
|
287
237
|
.attention {
|
|
288
238
|
font-size: 11px;
|
|
289
|
-
color: var(--
|
|
239
|
+
color: var(--agsc-warn);
|
|
290
240
|
}
|
|
291
241
|
|
|
292
242
|
.attention[data-kind='gap'] {
|
|
293
|
-
color: var(--
|
|
243
|
+
color: var(--agsc-err);
|
|
294
244
|
}
|
|
295
245
|
|
|
296
246
|
.sessionTitle {
|
|
@@ -302,24 +252,19 @@
|
|
|
302
252
|
|
|
303
253
|
.liveChip {
|
|
304
254
|
flex: none;
|
|
305
|
-
|
|
306
|
-
line-height: 16px;
|
|
307
|
-
padding: 0 6px;
|
|
308
|
-
border-radius: 999px;
|
|
309
|
-
color: var(--dsw-alias-state-success-primary, #1a7f37);
|
|
310
|
-
border: 1px solid var(--dsw-alias-state-success-primary, rgba(26, 127, 55, 0.4));
|
|
255
|
+
color: var(--agsc-ok);
|
|
311
256
|
}
|
|
312
257
|
|
|
313
258
|
.sessionId {
|
|
314
259
|
flex: none;
|
|
315
260
|
font-size: 11px;
|
|
316
|
-
font-family:
|
|
317
|
-
color: var(--
|
|
261
|
+
font-family: var(--agsc-font-mono);
|
|
262
|
+
color: var(--agsc-fg-dimmed);
|
|
318
263
|
}
|
|
319
264
|
|
|
320
265
|
.sessionTime {
|
|
321
266
|
flex: none;
|
|
322
267
|
margin-left: auto;
|
|
323
268
|
font-size: 11px;
|
|
324
|
-
color: var(--
|
|
269
|
+
color: var(--agsc-fg-dimmed);
|
|
325
270
|
}
|
|
@@ -14,6 +14,7 @@
|
|
|
14
14
|
* blanking data the user already has.
|
|
15
15
|
*/
|
|
16
16
|
|
|
17
|
+
import { Button, Pill, StateDot, type StateDotState } from '@deepseek-ai/dsh-client-ui-primitives'
|
|
17
18
|
import { useState } from 'react'
|
|
18
19
|
import type { ReactElement } from 'react'
|
|
19
20
|
import {
|
|
@@ -26,6 +27,7 @@ import {
|
|
|
26
27
|
type ProjectGroupVM,
|
|
27
28
|
} from './project-view-logic.ts'
|
|
28
29
|
import { formatTemplate, sliceCardsForDisplay } from './logic.ts'
|
|
30
|
+
import { surfaceProps } from '../theme/parts.ts'
|
|
29
31
|
import styles from './project-view.module.css'
|
|
30
32
|
|
|
31
33
|
export interface ProjectViewProps {
|
|
@@ -39,11 +41,18 @@ export interface ProjectViewProps {
|
|
|
39
41
|
nowMs?: number
|
|
40
42
|
}
|
|
41
43
|
|
|
44
|
+
function sessionDotState(status: DerivedProjectSessionVM['badge']['status']): StateDotState | null {
|
|
45
|
+
if (status === 'working') return 'ongoing'
|
|
46
|
+
if (status === 'waiting') return 'warning'
|
|
47
|
+
return null
|
|
48
|
+
}
|
|
49
|
+
|
|
42
50
|
function SessionRow(props: {
|
|
43
51
|
session: DerivedProjectSessionVM
|
|
44
52
|
onSelect: (sessionId: string) => void
|
|
45
53
|
}): ReactElement {
|
|
46
54
|
const { session, onSelect } = props
|
|
55
|
+
const dotState = sessionDotState(session.badge.status)
|
|
47
56
|
return (
|
|
48
57
|
<button
|
|
49
58
|
type="button"
|
|
@@ -51,19 +60,21 @@ function SessionRow(props: {
|
|
|
51
60
|
onClick={() => onSelect(session.sessionId)}
|
|
52
61
|
data-testid="agent-sidecar-project-session"
|
|
53
62
|
>
|
|
54
|
-
<
|
|
55
|
-
|
|
63
|
+
<Pill className={styles['statusPill']}>
|
|
64
|
+
{dotState === null
|
|
65
|
+
? <span className={styles['dot']} data-tone={session.badge.tone} />
|
|
66
|
+
: <StateDot state={dotState} size={8} />}
|
|
56
67
|
{session.badge.label}
|
|
57
68
|
{session.badge.attention !== null && (
|
|
58
69
|
<span className={styles['attention']} data-kind={session.badge.attention}>
|
|
59
70
|
{session.badge.attentionLabel}
|
|
60
71
|
</span>
|
|
61
72
|
)}
|
|
62
|
-
</
|
|
73
|
+
</Pill>
|
|
63
74
|
<span className={styles['sessionTitle']} title={session.title}>
|
|
64
75
|
{session.displayTitle}
|
|
65
76
|
</span>
|
|
66
|
-
{session.live && <
|
|
77
|
+
{session.live && <Pill className={styles['liveChip']}>{PROJECT_VIEW_STRINGS.liveChip}</Pill>}
|
|
67
78
|
<span className={styles['sessionId']} title={session.sessionId}>
|
|
68
79
|
{session.shortId}
|
|
69
80
|
</span>
|
|
@@ -100,22 +111,24 @@ function AgentLane(props: {
|
|
|
100
111
|
))}
|
|
101
112
|
</div>
|
|
102
113
|
{hiddenCount > 0 && (
|
|
103
|
-
<
|
|
104
|
-
|
|
114
|
+
<Button
|
|
115
|
+
size="sm"
|
|
116
|
+
variant="outline"
|
|
105
117
|
className={styles['showMore']}
|
|
106
118
|
onClick={() => { setExpanded(true) }}
|
|
107
119
|
>
|
|
108
120
|
{formatTemplate(PROJECT_VIEW_STRINGS.showAllSessions, { n: lane.sessions.length })}
|
|
109
|
-
</
|
|
121
|
+
</Button>
|
|
110
122
|
)}
|
|
111
123
|
{expanded && lane.sessions.length > LANE_SESSION_LIMIT && (
|
|
112
|
-
<
|
|
113
|
-
|
|
124
|
+
<Button
|
|
125
|
+
size="sm"
|
|
126
|
+
variant="outline"
|
|
114
127
|
className={styles['showMore']}
|
|
115
128
|
onClick={() => { setExpanded(false) }}
|
|
116
129
|
>
|
|
117
130
|
{formatTemplate(PROJECT_VIEW_STRINGS.showLessSessions, { n: LANE_SESSION_LIMIT })}
|
|
118
|
-
</
|
|
131
|
+
</Button>
|
|
119
132
|
)}
|
|
120
133
|
</div>
|
|
121
134
|
)
|
|
@@ -168,13 +181,16 @@ export function ProjectView(props: ProjectViewProps): ReactElement {
|
|
|
168
181
|
const hasContent = vm.groups.length > 0
|
|
169
182
|
|
|
170
183
|
return (
|
|
171
|
-
<div
|
|
184
|
+
<div
|
|
185
|
+
{...surfaceProps('project-view', styles['root'])}
|
|
186
|
+
data-testid="agent-sidecar-project-view"
|
|
187
|
+
>
|
|
172
188
|
<header className={styles['topbar']}>
|
|
173
189
|
<span className={styles['title']}>{PROJECT_VIEW_STRINGS.title}</span>
|
|
174
190
|
<span className={styles['summary']}>{vm.summaryLabel}</span>
|
|
175
191
|
{props.loading && (
|
|
176
|
-
<span
|
|
177
|
-
{PROJECT_VIEW_STRINGS.loading}
|
|
192
|
+
<span role="status">
|
|
193
|
+
<Pill>{PROJECT_VIEW_STRINGS.loading}</Pill>
|
|
178
194
|
</span>
|
|
179
195
|
)}
|
|
180
196
|
</header>
|
|
@@ -1,136 +1,97 @@
|
|
|
1
|
-
|
|
2
|
-
* Centralized user-facing strings for the board view and the footer widget
|
|
3
|
-
* (design §5.1 view 1 / view 4, §5.3 honesty wording).
|
|
4
|
-
*
|
|
5
|
-
* Chinese is the primary UI language for now; every string the components
|
|
6
|
-
* render lives in this single table so the i18n skeleton (T2.3,
|
|
7
|
-
* `ctx.locale.register`) can take it over without hunting through JSX.
|
|
8
|
-
* Templates use `{name}` placeholders resolved by `formatTemplate` in
|
|
9
|
-
* `logic.ts` — plain message strings, locale-registry friendly.
|
|
10
|
-
*
|
|
11
|
-
* Pure data module: no imports, no logic.
|
|
12
|
-
*
|
|
13
|
-
* @module
|
|
14
|
-
*/
|
|
1
|
+
import { createLocaleView } from '../locales/view.ts'
|
|
15
2
|
|
|
16
|
-
|
|
17
|
-
|
|
3
|
+
/** Dynamic board vocabulary; template leaves are interpolated by `formatTemplate`. */
|
|
4
|
+
export const BOARD_STRINGS = createLocaleView({
|
|
18
5
|
status: {
|
|
19
|
-
working: '
|
|
20
|
-
waiting: '
|
|
21
|
-
idle: '
|
|
22
|
-
dead: '
|
|
23
|
-
unknown: '
|
|
6
|
+
working: 'board.status.working',
|
|
7
|
+
waiting: 'board.status.waiting',
|
|
8
|
+
idle: 'board.status.idle',
|
|
9
|
+
dead: 'board.status.dead',
|
|
10
|
+
unknown: 'board.status.unknown',
|
|
24
11
|
},
|
|
25
|
-
/**
|
|
26
|
-
* Badge attention markers. Only the per-session gap marker renders at
|
|
27
|
-
* card level; the global stream-health notice lives in the top banner
|
|
28
|
-
* alone (UX-18: repeating it on every card was pure noise).
|
|
29
|
-
*/
|
|
30
12
|
attention: {
|
|
31
|
-
gap: '
|
|
13
|
+
gap: 'board.attention.gap',
|
|
32
14
|
},
|
|
33
|
-
/** Daemon supervisor state labels for the top-bar badge. */
|
|
34
15
|
daemon: {
|
|
35
|
-
probe: '
|
|
36
|
-
adopted: '
|
|
37
|
-
defer: '
|
|
38
|
-
reprobe: '
|
|
39
|
-
hosting: '
|
|
40
|
-
hosted: '
|
|
41
|
-
backoff: '
|
|
42
|
-
failed: '
|
|
16
|
+
probe: 'board.daemon.probe',
|
|
17
|
+
adopted: 'board.daemon.adopted',
|
|
18
|
+
defer: 'board.daemon.defer',
|
|
19
|
+
reprobe: 'board.daemon.reprobe',
|
|
20
|
+
hosting: 'board.daemon.hosting',
|
|
21
|
+
hosted: 'board.daemon.hosted',
|
|
22
|
+
backoff: 'board.daemon.backoff',
|
|
23
|
+
failed: 'board.daemon.failed',
|
|
43
24
|
},
|
|
44
|
-
/** Stream health indicator labels. */
|
|
45
25
|
stream: {
|
|
46
|
-
ok: '
|
|
47
|
-
degraded: '
|
|
48
|
-
unknown: '
|
|
26
|
+
ok: 'board.stream.ok',
|
|
27
|
+
degraded: 'board.stream.degraded',
|
|
28
|
+
unknown: 'board.stream.unknown',
|
|
49
29
|
},
|
|
50
|
-
/** Top banner texts (design §5.3: degraded warning / FAILED red banner). */
|
|
51
30
|
banner: {
|
|
52
|
-
daemonFailed: '
|
|
53
|
-
streamDegraded: '
|
|
31
|
+
daemonFailed: 'board.banner.daemonFailed',
|
|
32
|
+
streamDegraded: 'board.banner.streamDegraded',
|
|
54
33
|
},
|
|
55
|
-
/** Empty-state guidance blocks. */
|
|
56
34
|
empty: {
|
|
57
|
-
daemonFailedTitle: '
|
|
58
|
-
daemonFailedHint:
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
noSessionsTitle: '暂无被观测的会话',
|
|
66
|
-
noSessionsHint:
|
|
67
|
-
'本机 agent(claude / codex / cursor / dsh …)开始工作后会自动出现在这里。',
|
|
35
|
+
daemonFailedTitle: 'board.empty.daemonFailedTitle',
|
|
36
|
+
daemonFailedHint: 'board.empty.daemonFailedHint',
|
|
37
|
+
daemonDeferTitle: 'board.empty.daemonDeferTitle',
|
|
38
|
+
daemonDeferHint: 'board.empty.daemonDeferHint',
|
|
39
|
+
filteredTitle: 'board.empty.filteredTitle',
|
|
40
|
+
filteredHint: 'board.empty.filteredHint',
|
|
41
|
+
noSessionsTitle: 'board.empty.noSessionsTitle',
|
|
42
|
+
noSessionsHint: 'board.empty.noSessionsHint',
|
|
68
43
|
},
|
|
69
|
-
/** Top bar controls. */
|
|
70
44
|
topbar: {
|
|
71
|
-
title: '
|
|
72
|
-
refresh: '
|
|
73
|
-
refreshing: '
|
|
74
|
-
refreshTitle: '
|
|
75
|
-
refreshFailed: '
|
|
76
|
-
dismiss: '
|
|
77
|
-
showDead: '
|
|
78
|
-
timeWindow: '
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
clearStatusFilterTitle: '取消状态过滤,显示全部会话',
|
|
45
|
+
title: 'board.topbar.title',
|
|
46
|
+
refresh: 'board.topbar.refresh',
|
|
47
|
+
refreshing: 'board.topbar.refreshing',
|
|
48
|
+
refreshTitle: 'board.topbar.refreshTitle',
|
|
49
|
+
refreshFailed: 'board.topbar.refreshFailed',
|
|
50
|
+
dismiss: 'board.topbar.dismiss',
|
|
51
|
+
showDead: 'board.topbar.showDead',
|
|
52
|
+
timeWindow: 'board.topbar.timeWindow',
|
|
53
|
+
countWorking: 'board.topbar.countWorking',
|
|
54
|
+
countWaiting: 'board.topbar.countWaiting',
|
|
55
|
+
countTotal: 'board.topbar.countTotal',
|
|
56
|
+
filterByStatusTitle: 'board.topbar.filterByStatusTitle',
|
|
57
|
+
clearStatusFilterTitle: 'board.topbar.clearStatusFilterTitle',
|
|
85
58
|
},
|
|
86
|
-
/** Group collapse / truncation controls (UX-02). */
|
|
87
59
|
group: {
|
|
88
|
-
collapseTitle: '
|
|
89
|
-
expandTitle: '
|
|
90
|
-
showAll: '
|
|
91
|
-
showLess: '
|
|
60
|
+
collapseTitle: 'board.group.collapseTitle',
|
|
61
|
+
expandTitle: 'board.group.expandTitle',
|
|
62
|
+
showAll: 'board.group.showAll',
|
|
63
|
+
showLess: 'board.group.showLess',
|
|
92
64
|
},
|
|
93
|
-
/** Session card texts. */
|
|
94
65
|
card: {
|
|
95
|
-
noEvent: '
|
|
96
|
-
untitled: '
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
copied: '已复制',
|
|
66
|
+
noEvent: 'board.card.noEvent',
|
|
67
|
+
untitled: 'board.card.untitled',
|
|
68
|
+
observedDisclaimer: 'board.card.observedDisclaimer',
|
|
69
|
+
observedValue: 'board.card.observedValue',
|
|
70
|
+
lastReconcile: 'board.card.lastReconcile',
|
|
71
|
+
neverReconciled: 'board.card.neverReconciled',
|
|
72
|
+
copyId: 'board.card.copyId',
|
|
73
|
+
copied: 'board.card.copied',
|
|
104
74
|
},
|
|
105
|
-
/**
|
|
106
|
-
* Relative time templates. Ages ≥ 24h render as an absolute short date
|
|
107
|
-
* (`MM-DD HH:mm`, see formatRelativeTime) instead of a `{n} 天前` bucket
|
|
108
|
-
* (UX-13: whole columns of "3 天前" carried zero information).
|
|
109
|
-
*/
|
|
110
75
|
time: {
|
|
111
|
-
justNow: '
|
|
112
|
-
minutesAgo: '
|
|
113
|
-
hoursAgo: '
|
|
76
|
+
justNow: 'board.time.justNow',
|
|
77
|
+
minutesAgo: 'board.time.minutesAgo',
|
|
78
|
+
hoursAgo: 'board.time.hoursAgo',
|
|
114
79
|
},
|
|
115
|
-
/** Time-window option templates. */
|
|
116
80
|
timeWindow: {
|
|
117
|
-
hours: '
|
|
118
|
-
days: '
|
|
81
|
+
hours: 'board.timeWindow.hours',
|
|
82
|
+
days: 'board.timeWindow.days',
|
|
119
83
|
},
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
/** Sessions with an empty `project` fall into this group (task spec). */
|
|
123
|
-
unknownProject: '未知项目',
|
|
124
|
-
/** Footer widget. */
|
|
84
|
+
groupCount: 'board.groupCount',
|
|
85
|
+
unknownProject: 'board.unknownProject',
|
|
125
86
|
widget: {
|
|
126
|
-
label: '
|
|
87
|
+
label: 'board.widget.label',
|
|
127
88
|
connection: {
|
|
128
|
-
ok: '
|
|
129
|
-
degraded: '
|
|
130
|
-
off: '
|
|
89
|
+
ok: 'board.widget.connection.ok',
|
|
90
|
+
degraded: 'board.widget.connection.degraded',
|
|
91
|
+
off: 'board.widget.connection.off',
|
|
131
92
|
},
|
|
132
|
-
working: '
|
|
93
|
+
working: 'board.widget.working',
|
|
133
94
|
},
|
|
134
|
-
} as const
|
|
95
|
+
} as const)
|
|
135
96
|
|
|
136
97
|
export type BoardStrings = typeof BOARD_STRINGS
|