@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.
Files changed (53) hide show
  1. package/README.md +78 -11
  2. package/lib/client.js +8659 -7589
  3. package/lib/client.js.map +1 -1
  4. package/package.json +3 -1
  5. package/src/client/analysis/AnalysisPanel.tsx +19 -27
  6. package/src/client/analysis/analysis.module.css +36 -97
  7. package/src/client/board/Board.tsx +115 -61
  8. package/src/client/board/board.module.css +72 -151
  9. package/src/client/board/project-view-logic.ts +21 -34
  10. package/src/client/board/project-view.module.css +41 -96
  11. package/src/client/board/project-view.tsx +29 -13
  12. package/src/client/board/strings.ts +68 -107
  13. package/src/client/commands.ts +30 -15
  14. package/src/client/detail/SessionDetail.tsx +92 -58
  15. package/src/client/detail/detail.module.css +62 -218
  16. package/src/client/detail/strings.ts +64 -88
  17. package/src/client/detail-view.module.css +30 -55
  18. package/src/client/detail-view.tsx +80 -108
  19. package/src/client/dsh-tools/LineageTree.tsx +22 -13
  20. package/src/client/dsh-tools/SearchPanel.tsx +18 -11
  21. package/src/client/dsh-tools/dsh-tools.module.css +50 -139
  22. package/src/client/dsh-tools/strings.ts +42 -77
  23. package/src/client/index.ts +285 -124
  24. package/src/client/inject/InjectPanel.tsx +31 -64
  25. package/src/client/inject/inject.module.css +97 -198
  26. package/src/client/lifecycle/handoff.ts +83 -0
  27. package/src/client/locales/en.ts +74 -2
  28. package/src/client/locales/host.ts +131 -0
  29. package/src/client/locales/index.ts +196 -8
  30. package/src/client/locales/react.ts +10 -0
  31. package/src/client/locales/view.ts +38 -0
  32. package/src/client/locales/zh.ts +194 -134
  33. package/src/client/mount.tsx +72 -38
  34. package/src/client/navigation/CenterOverlay.tsx +40 -0
  35. package/src/client/navigation/center-overlay.module.css +51 -0
  36. package/src/client/navigation/center.ts +45 -0
  37. package/src/client/navigation/modal-isolation.ts +152 -0
  38. package/src/client/navigation/modal-surface-anchor.ts +72 -0
  39. package/src/client/navigation/sidebar-entry.module.css +73 -0
  40. package/src/client/navigation/sidebar-entry.ts +309 -0
  41. package/src/client/primitives/StaticPill.tsx +21 -0
  42. package/src/client/settings-card.module.css +35 -119
  43. package/src/client/settings-card.tsx +31 -153
  44. package/src/client/settings-fields.tsx +131 -0
  45. package/src/client/sidebar/SidebarTab.tsx +156 -0
  46. package/src/client/sidebar/model.ts +65 -0
  47. package/src/client/sidebar/sidebar-tab.module.css +118 -0
  48. package/src/client/sidebar-tab.tsx +46 -320
  49. package/src/client/theme/agsc.module.css +31 -0
  50. package/src/client/theme/parts.ts +56 -0
  51. package/src/client/ui-integration.ts +86 -0
  52. package/src/client/widget.tsx +9 -8
  53. package/src/client/inject/overlay.module.css +0 -22
@@ -1,9 +1,4 @@
1
- /*
2
- * Session-detail styles (design §5.1 view 2 / §5.3): every color rides a
3
- * --dsw-alias-* design token with a neutral fallback — no theme colors are
4
- * hardcoded as the only value. The gap marker uses the warn palette,
5
- * deliberately restrained (a thin honesty note, not an alarm).
6
- */
1
+ /* Session-detail layout over the shared Agent Sidecar / DSH token contract. */
7
2
 
8
3
  .root {
9
4
  display: flex;
@@ -13,8 +8,8 @@
13
8
  min-height: 420px;
14
9
  padding: 16px 20px;
15
10
  box-sizing: border-box;
16
- color: var(--dsw-alias-label-primary, #1f2328);
17
- background: var(--dsw-alias-bg-base, transparent);
11
+ color: var(--agsc-fg);
12
+ background: var(--agsc-bg);
18
13
  }
19
14
 
20
15
  /* -------------------------------------------------------------- header */
@@ -32,48 +27,21 @@
32
27
  flex-wrap: wrap;
33
28
  }
34
29
 
35
- .closeButton {
36
- font-size: 12px;
37
- font-family: inherit;
38
- color: var(--dsw-alias-label-secondary, #57606a);
39
- background: transparent;
40
- border: 1px solid var(--dsw-alias-border-l1, rgba(0, 0, 0, 0.08));
41
- border-radius: 6px;
42
- padding: 2px 10px;
43
- cursor: pointer;
44
- }
45
-
46
- .closeButton:hover {
47
- color: var(--dsw-alias-label-primary, #1f2328);
48
- border-color: var(--dsw-alias-border-l2, rgba(0, 0, 0, 0.12));
49
- background: var(--dsw-alias-interactive-bg-hover, rgba(0, 0, 0, 0.04));
50
- }
51
-
52
30
  .agent {
53
31
  display: inline-flex;
54
32
  align-items: center;
55
33
  gap: 5px;
56
34
  font-size: 13px;
57
35
  font-weight: 650;
58
- color: var(--dsw-alias-label-primary, #1f2328);
36
+ color: var(--dsw-alias-label-primary);
59
37
  }
60
38
 
61
39
  .agentGlyph {
62
40
  flex: none;
63
- color: var(--dsw-alias-brand-primary, #4d6bfe);
41
+ color: var(--dsw-alias-brand-primary);
64
42
  }
65
43
 
66
44
  .badge {
67
- display: inline-flex;
68
- align-items: center;
69
- gap: 5px;
70
- font-size: 12px;
71
- line-height: 20px;
72
- padding: 0 8px;
73
- border-radius: 999px;
74
- border: 1px solid var(--dsw-alias-border-l1, rgba(0, 0, 0, 0.08));
75
- background: var(--dsw-alias-bg-layer-1, rgba(0, 0, 0, 0.03));
76
- color: var(--dsw-alias-label-secondary, #57606a);
77
45
  white-space: nowrap;
78
46
  }
79
47
 
@@ -82,82 +50,37 @@
82
50
  height: 8px;
83
51
  border-radius: 50%;
84
52
  flex: none;
85
- background: var(--dsw-alias-label-tertiary, #6e7781);
53
+ background: var(--agsc-fg-dimmed);
86
54
  }
87
55
 
88
56
  .dot[data-tone='success'] {
89
- background: var(--dsw-alias-state-success-primary, #1a7f37);
57
+ background: var(--agsc-ok);
90
58
  }
91
59
 
92
60
  .dot[data-tone='warn'] {
93
- background: var(--dsw-alias-state-warn-primary, #9a6700);
61
+ background: var(--agsc-warn);
94
62
  }
95
63
 
96
64
  .dot[data-tone='danger'] {
97
- background: var(--dsw-alias-state-error-primary, #cf222e);
65
+ background: var(--agsc-err);
98
66
  }
99
67
 
100
68
  .dot[data-tone='neutral'] {
101
- background: var(--dsw-alias-label-tertiary, #6e7781);
69
+ background: var(--agsc-fg-secondary);
102
70
  }
103
71
 
104
72
  .dot[data-tone='muted'] {
105
- background: var(--dsw-alias-label-dimmed, #8c959f);
73
+ background: var(--agsc-fg-dimmed);
106
74
  }
107
75
 
108
76
  .spacer {
109
77
  flex: 1;
110
78
  }
111
79
 
112
- .listenButton {
113
- font-size: 12px;
114
- font-family: inherit;
115
- color: var(--dsw-alias-label-secondary, #57606a);
116
- background: transparent;
117
- border: 1px solid var(--dsw-alias-border-l1, rgba(0, 0, 0, 0.08));
118
- border-radius: 999px;
119
- padding: 2px 12px;
120
- cursor: pointer;
121
- }
122
-
123
- .listenButton:hover {
124
- color: var(--dsw-alias-label-primary, #1f2328);
125
- border-color: var(--dsw-alias-border-l2, rgba(0, 0, 0, 0.12));
126
- }
127
-
128
- .listenButton[data-active] {
129
- color: var(--dsw-alias-brand-primary, #4d6bfe);
130
- border-color: var(--dsw-alias-brand-primary, #4d6bfe);
131
- /* brand tint from the real token (brand-secondary/tertiary do not exist
132
- * in the dsh token table — UX-15). */
133
- background: color-mix(in srgb, var(--dsw-alias-brand-primary, #4d6bfe) 8%, transparent);
134
- }
135
-
136
- .refreshButton {
137
- font-size: 12px;
138
- font-family: inherit;
139
- color: var(--dsw-alias-label-secondary, #57606a);
140
- background: transparent;
141
- border: 1px solid var(--dsw-alias-border-l1, rgba(0, 0, 0, 0.08));
142
- border-radius: 999px;
143
- padding: 2px 12px;
144
- cursor: pointer;
145
- }
146
-
147
- .refreshButton:hover:enabled {
148
- color: var(--dsw-alias-label-primary, #1f2328);
149
- border-color: var(--dsw-alias-border-l2, rgba(0, 0, 0, 0.12));
150
- }
151
-
152
- .refreshButton:disabled {
153
- cursor: default;
154
- opacity: 0.6;
155
- }
156
-
157
80
  .title {
158
81
  font-size: 15px;
159
82
  font-weight: 600;
160
- color: var(--dsw-alias-label-primary, #1f2328);
83
+ color: var(--dsw-alias-label-primary);
161
84
  overflow: hidden;
162
85
  text-overflow: ellipsis;
163
86
  white-space: nowrap;
@@ -172,7 +95,7 @@
172
95
 
173
96
  .project {
174
97
  font-size: 12px;
175
- color: var(--dsw-alias-label-secondary, #57606a);
98
+ color: var(--dsw-alias-label-secondary);
176
99
  overflow: hidden;
177
100
  text-overflow: ellipsis;
178
101
  white-space: nowrap;
@@ -181,32 +104,28 @@
181
104
  /* Click-to-copy session id (UX-17): plain-text look, button semantics. */
182
105
  .sessionId {
183
106
  font-size: 11px;
184
- font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
185
- color: var(--dsw-alias-label-tertiary, #6e7781);
186
- background: transparent;
187
- border: none;
188
- padding: 0;
107
+ font-family: var(--ds-font-family-code);
108
+ color: var(--dsw-alias-label-tertiary);
189
109
  overflow: hidden;
190
110
  text-overflow: ellipsis;
191
111
  white-space: nowrap;
192
112
  flex: none;
193
113
  max-width: 40%;
194
- cursor: pointer;
195
114
  }
196
115
 
197
116
  .sessionId:hover {
198
- color: var(--dsw-alias-label-primary, #1f2328);
117
+ color: var(--dsw-alias-label-primary);
199
118
  text-decoration: underline;
200
119
  }
201
120
 
202
121
  .copiedBubble {
203
122
  flex: none;
204
- font-size: 10px;
205
- line-height: 16px;
206
- padding: 0 6px;
207
- border-radius: 999px;
208
- color: var(--dsw-alias-state-success-primary, #1a7f37);
209
- border: 1px solid var(--dsw-alias-state-success-secondary, rgba(26, 127, 55, 0.24));
123
+ color: var(--agsc-ok);
124
+ }
125
+
126
+ .copiedBubble > span,
127
+ .sourceBadge > span {
128
+ color: inherit;
210
129
  }
211
130
 
212
131
  .metaRow {
@@ -218,7 +137,7 @@
218
137
 
219
138
  .disclaimer {
220
139
  font-size: 11px;
221
- color: var(--dsw-alias-label-caption, var(--dsw-alias-label-tertiary, #6e7781));
140
+ color: var(--dsw-alias-label-caption);
222
141
  }
223
142
 
224
143
  .sourceList {
@@ -228,23 +147,15 @@
228
147
  }
229
148
 
230
149
  .sourceBadge {
231
- font-size: 11px;
232
- line-height: 16px;
233
- padding: 0 6px;
234
- border-radius: 999px;
235
- border: 1px solid var(--dsw-alias-border-l1, rgba(0, 0, 0, 0.08));
236
- color: var(--dsw-alias-label-secondary, #57606a);
237
- background: var(--dsw-alias-bg-layer-1, rgba(0, 0, 0, 0.03));
238
150
  white-space: nowrap;
239
151
  }
240
152
 
241
153
  .sourceBadge[data-tone='success'] {
242
- color: var(--dsw-alias-state-success-primary, #1a7f37);
243
- border-color: var(--dsw-alias-state-success-secondary, rgba(26, 127, 55, 0.24));
154
+ color: var(--agsc-ok);
244
155
  }
245
156
 
246
157
  .sourceBadge[data-tone='muted'] {
247
- color: var(--dsw-alias-label-dimmed, #8c959f);
158
+ color: var(--agsc-fg-dimmed);
248
159
  }
249
160
 
250
161
  /* -------------------------------------------------------------- banner */
@@ -253,10 +164,10 @@
253
164
  font-size: 12px;
254
165
  line-height: 18px;
255
166
  padding: 6px 10px;
256
- border-radius: 8px;
257
- color: var(--dsw-alias-state-warn-label, var(--dsw-alias-state-warn-primary, #9a6700));
258
- background: var(--dsw-alias-state-warn-tertiary, rgba(154, 103, 0, 0.08));
259
- border: 1px solid var(--dsw-alias-state-warn-secondary, rgba(154, 103, 0, 0.24));
167
+ border-radius: var(--agsc-radius-control);
168
+ color: var(--agsc-warn);
169
+ background: var(--dsw-alias-state-warn-tertiary);
170
+ border: 1px solid var(--dsw-alias-state-warn-secondary);
260
171
  }
261
172
 
262
173
  /* --------------------------------------------- loading / empty / error */
@@ -276,18 +187,18 @@
276
187
  .bodyStateTitle {
277
188
  font-size: 14px;
278
189
  font-weight: 600;
279
- color: var(--dsw-alias-label-primary, #1f2328);
190
+ color: var(--dsw-alias-label-primary);
280
191
  }
281
192
 
282
193
  .bodyState[data-kind='error'] .bodyStateTitle {
283
- color: var(--dsw-alias-state-error-primary, #cf222e);
194
+ color: var(--agsc-err);
284
195
  }
285
196
 
286
197
  .bodyStateHint {
287
198
  font-size: 12px;
288
199
  max-width: 420px;
289
200
  line-height: 20px;
290
- color: var(--dsw-alias-label-secondary, #57606a);
201
+ color: var(--dsw-alias-label-secondary);
291
202
  }
292
203
 
293
204
  /* --------------------------------------- kind filter chips (UX-03) */
@@ -299,32 +210,9 @@
299
210
  flex-wrap: wrap;
300
211
  }
301
212
 
302
- .filterChip {
303
- font-size: 11px;
304
- font-family: inherit;
305
- line-height: 18px;
306
- padding: 0 10px;
307
- border-radius: 999px;
308
- color: var(--dsw-alias-label-secondary, #57606a);
309
- background: transparent;
310
- border: 1px solid var(--dsw-alias-border-l1, rgba(0, 0, 0, 0.08));
311
- cursor: pointer;
312
- }
313
-
314
- .filterChip:hover {
315
- color: var(--dsw-alias-label-primary, #1f2328);
316
- border-color: var(--dsw-alias-border-l2, rgba(0, 0, 0, 0.12));
317
- }
318
-
319
- .filterChip[data-active] {
320
- color: var(--dsw-alias-brand-primary, #4d6bfe);
321
- border-color: var(--dsw-alias-brand-primary, #4d6bfe);
322
- background: color-mix(in srgb, var(--dsw-alias-brand-primary, #4d6bfe) 8%, transparent);
323
- }
324
-
325
213
  .filterHiddenNote {
326
214
  font-size: 11px;
327
- color: var(--dsw-alias-label-tertiary, #6e7781);
215
+ color: var(--dsw-alias-label-tertiary);
328
216
  }
329
217
 
330
218
  /* --------------------------------------------------------------- pager */
@@ -334,31 +222,9 @@
334
222
  justify-content: center;
335
223
  }
336
224
 
337
- .loadMoreButton {
338
- font-size: 12px;
339
- font-family: inherit;
340
- color: var(--dsw-alias-label-secondary, #57606a);
341
- background: transparent;
342
- border: 1px solid var(--dsw-alias-border-l1, rgba(0, 0, 0, 0.08));
343
- border-radius: 6px;
344
- padding: 3px 14px;
345
- cursor: pointer;
346
- }
347
-
348
- .loadMoreButton:hover:enabled {
349
- color: var(--dsw-alias-label-primary, #1f2328);
350
- border-color: var(--dsw-alias-border-l2, rgba(0, 0, 0, 0.12));
351
- background: var(--dsw-alias-interactive-bg-hover, rgba(0, 0, 0, 0.04));
352
- }
353
-
354
- .loadMoreButton:disabled {
355
- cursor: default;
356
- opacity: 0.6;
357
- }
358
-
359
225
  .pagerNote {
360
226
  font-size: 11px;
361
- color: var(--dsw-alias-label-tertiary, #6e7781);
227
+ color: var(--dsw-alias-label-tertiary);
362
228
  }
363
229
 
364
230
  .hiddenNotice {
@@ -367,17 +233,7 @@
367
233
  justify-content: center;
368
234
  gap: 8px;
369
235
  font-size: 11px;
370
- color: var(--dsw-alias-label-tertiary, #6e7781);
371
- }
372
-
373
- .showAllButton {
374
- font-size: 11px;
375
- font-family: inherit;
376
- color: var(--dsw-alias-brand-primary, #4d6bfe);
377
- background: transparent;
378
- border: none;
379
- padding: 0;
380
- cursor: pointer;
236
+ color: var(--dsw-alias-label-tertiary);
381
237
  }
382
238
 
383
239
  /* ------------------------------------------------------------ timeline */
@@ -398,15 +254,15 @@
398
254
  flex-direction: column;
399
255
  gap: 4px;
400
256
  padding: 6px 10px;
401
- border-radius: 8px;
402
- border: 1px solid var(--dsw-alias-border-l1, rgba(0, 0, 0, 0.06));
403
- background: var(--dsw-alias-bg-layer-1, rgba(0, 0, 0, 0.02));
257
+ border-radius: var(--agsc-radius-control);
258
+ border: 1px solid var(--agsc-border);
259
+ background: var(--agsc-bg-raised);
404
260
  }
405
261
 
406
262
  .event[data-new] {
407
- border-color: var(--dsw-alias-brand-primary, #4d6bfe);
263
+ border-color: var(--agsc-accent);
408
264
  /* brand tint from the real token (UX-15). */
409
- background: color-mix(in srgb, var(--dsw-alias-brand-primary, #4d6bfe) 6%, transparent);
265
+ background: color-mix(in srgb, var(--agsc-accent) 6%, transparent);
410
266
  }
411
267
 
412
268
  /* Aggregated streaming-chunk run (UX-03): quiet one-line stand-in. */
@@ -417,14 +273,14 @@
417
273
  font-size: 11px;
418
274
  line-height: 16px;
419
275
  padding: 4px 10px;
420
- border-radius: 6px;
421
- color: var(--dsw-alias-label-tertiary, #6e7781);
422
- background: var(--dsw-alias-bg-layer-1, rgba(0, 0, 0, 0.02));
423
- border: 1px dashed var(--dsw-alias-border-l2, rgba(0, 0, 0, 0.12));
276
+ border-radius: var(--agsc-radius-control);
277
+ color: var(--dsw-alias-label-tertiary);
278
+ background: var(--agsc-bg-raised);
279
+ border: 1px dashed var(--agsc-border-strong);
424
280
  }
425
281
 
426
282
  .chunkRun[data-new] {
427
- border-color: var(--dsw-alias-brand-primary, #4d6bfe);
283
+ border-color: var(--agsc-accent);
428
284
  }
429
285
 
430
286
  .chunkRunLabel {
@@ -441,22 +297,22 @@
441
297
  .eventGlyph {
442
298
  flex: none;
443
299
  font-size: 12px;
444
- color: var(--dsw-alias-label-tertiary, #6e7781);
300
+ color: var(--dsw-alias-label-tertiary);
445
301
  }
446
302
 
447
303
  .event[data-kind='user'] .eventGlyph,
448
304
  .event[data-kind='assistant'] .eventGlyph {
449
- color: var(--dsw-alias-brand-primary, #4d6bfe);
305
+ color: var(--dsw-alias-brand-primary);
450
306
  }
451
307
 
452
308
  .event[data-kind='error'] .eventGlyph {
453
- color: var(--dsw-alias-state-error-primary, #cf222e);
309
+ color: var(--dsw-alias-state-error-primary);
454
310
  }
455
311
 
456
312
  .eventLabel {
457
313
  font-size: 12px;
458
314
  font-weight: 600;
459
- color: var(--dsw-alias-label-primary, #1f2328);
315
+ color: var(--dsw-alias-label-primary);
460
316
  white-space: nowrap;
461
317
  overflow: hidden;
462
318
  text-overflow: ellipsis;
@@ -464,18 +320,13 @@
464
320
 
465
321
  .eventSeq {
466
322
  font-size: 10px;
467
- font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
468
- color: var(--dsw-alias-label-tertiary, #6e7781);
323
+ font-family: var(--ds-font-family-code);
324
+ color: var(--dsw-alias-label-tertiary);
469
325
  flex: none;
470
326
  }
471
327
 
472
328
  .eventNew {
473
- font-size: 10px;
474
- line-height: 14px;
475
- padding: 0 5px;
476
- border-radius: 999px;
477
- color: var(--dsw-alias-brand-primary, #4d6bfe);
478
- border: 1px solid var(--dsw-alias-brand-primary, #4d6bfe);
329
+ color: var(--agsc-accent);
479
330
  flex: none;
480
331
  }
481
332
 
@@ -485,37 +336,30 @@
485
336
 
486
337
  .eventTime {
487
338
  font-size: 11px;
488
- color: var(--dsw-alias-label-caption, var(--dsw-alias-label-tertiary, #6e7781));
339
+ color: var(--dsw-alias-label-caption);
489
340
  flex: none;
490
341
  }
491
342
 
492
343
  .eventSummary {
493
344
  font-size: 12px;
494
345
  line-height: 18px;
495
- color: var(--dsw-alias-label-secondary, #57606a);
346
+ color: var(--dsw-alias-label-secondary);
496
347
  overflow-wrap: anywhere;
497
348
  }
498
349
 
499
350
  .expandButton {
500
351
  align-self: flex-start;
501
- font-size: 11px;
502
- font-family: inherit;
503
- color: var(--dsw-alias-brand-primary, #4d6bfe);
504
- background: transparent;
505
- border: none;
506
- padding: 0;
507
- cursor: pointer;
508
352
  }
509
353
 
510
354
  .eventBody {
511
355
  margin: 0;
512
356
  padding: 8px 10px;
513
- border-radius: 6px;
357
+ border-radius: var(--agsc-radius-control);
514
358
  font-size: 11px;
515
359
  line-height: 16px;
516
- font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
517
- color: var(--dsw-alias-label-primary, #1f2328);
518
- background: var(--dsw-alias-bg-layer-2, rgba(0, 0, 0, 0.04));
360
+ font-family: var(--ds-font-family-code);
361
+ color: var(--dsw-alias-label-primary);
362
+ background: var(--dsw-alias-bg-layer-2);
519
363
  white-space: pre-wrap;
520
364
  overflow-wrap: anywhere;
521
365
  max-height: 320px;
@@ -528,9 +372,9 @@
528
372
  font-size: 11px;
529
373
  line-height: 16px;
530
374
  padding: 4px 10px;
531
- border-radius: 6px;
375
+ border-radius: var(--agsc-radius-control);
532
376
  text-align: center;
533
- color: var(--dsw-alias-state-warn-label, var(--dsw-alias-state-warn-primary, #9a6700));
534
- background: var(--dsw-alias-state-warn-tertiary, rgba(154, 103, 0, 0.06));
535
- border: 1px dashed var(--dsw-alias-state-warn-secondary, rgba(154, 103, 0, 0.32));
377
+ color: var(--agsc-warn);
378
+ background: var(--dsw-alias-state-warn-tertiary);
379
+ border: 1px dashed var(--dsw-alias-state-warn-secondary);
536
380
  }
@@ -1,111 +1,87 @@
1
- /**
2
- * Centralized user-facing strings for the session-detail view (design §5.1
3
- * view 2, §5.3 honesty wording). Deliberately a module-local table — NOT
4
- * part of the main locale registry (locales/zh.ts / locales/en.ts): the
5
- * locale tables are owned by parallel tasks and the S7 integration wave
6
- * folds this table in centrally. Same posture as board/strings.ts.
7
- *
8
- * Chinese is the primary UI language. Templates use `{name}` placeholders
9
- * resolved by `formatTemplate` in `logic.ts`.
10
- *
11
- * Pure data module: no imports, no logic.
12
- *
13
- * @module
14
- */
1
+ import { createLocaleView } from '../locales/view.ts'
15
2
 
16
- export const DETAIL_STRINGS = {
17
- /** Header block (session meta + controls). */
3
+ /** Dynamic session-detail vocabulary; templates are interpolated by `formatTemplate`. */
4
+ export const DETAIL_STRINGS = createLocaleView({
18
5
  header: {
19
- close: '返回看板',
20
- listenOn: '监听中',
21
- listenOff: '监听',
22
- listenHint: '开启后新事件将实时追加并高亮',
23
- refresh: '刷新',
24
- refreshing: '刷新中…',
25
- refreshHint: '手动拉取最新时间线窗口',
26
- copyIdTitle: '点击复制会话 ID',
27
- copied: '已复制',
28
- untitled: '(无标题)',
29
- unknownProject: '未知项目',
30
- /** Design §5.3 / SKILL.md wording: statuses are inferred observations. */
31
- observedDisclaimer: '状态为从持久化数据推断的观察值,可能滞后',
6
+ close: 'detail.header.close',
7
+ listenOn: 'detail.header.listenOn',
8
+ listenOff: 'detail.header.listenOff',
9
+ listenHint: 'detail.header.listenHint',
10
+ refresh: 'detail.header.refresh',
11
+ refreshing: 'detail.header.refreshing',
12
+ refreshHint: 'detail.header.refreshHint',
13
+ copyIdTitle: 'detail.header.copyIdTitle',
14
+ copied: 'detail.header.copied',
15
+ untitled: 'detail.header.untitled',
16
+ unknownProject: 'detail.header.unknownProject',
17
+ observedDisclaimer: 'detail.header.observedDisclaimer',
32
18
  },
33
- /** Session status badge labels (observed values, see disclaimer). */
34
19
  status: {
35
- working: '工作中',
36
- waiting: '等待中',
37
- idle: '空闲',
38
- dead: '已结束',
39
- unknown: '未知',
20
+ working: 'detail.status.working',
21
+ waiting: 'detail.status.waiting',
22
+ idle: 'detail.status.idle',
23
+ dead: 'detail.status.dead',
24
+ unknown: 'detail.status.unknown',
40
25
  },
41
- /** Timeline source badges (provenance of the merged page, honest labels). */
42
26
  sources: {
43
- title: '数据来源',
44
- dshLive: 'dsh 实时',
45
- dshCold: 'dsh 冷读',
46
- sidecarReplay: 'sidecar 重放',
47
- sidecarBuffer: 'sidecar 缓冲',
48
- none: '来源未知',
27
+ title: 'detail.sources.title',
28
+ dshLive: 'detail.sources.dshLive',
29
+ dshCold: 'detail.sources.dshCold',
30
+ sidecarReplay: 'detail.sources.sidecarReplay',
31
+ sidecarBuffer: 'detail.sources.sidecarBuffer',
32
+ none: 'detail.sources.none',
49
33
  },
50
- /** Normalized event-kind labels; unknown kinds keep their raw text. */
51
34
  kind: {
52
- user: '用户消息',
53
- assistant: '助手回复',
54
- thinking: '思考',
55
- toolCall: '工具调用',
56
- toolResult: '工具结果',
57
- turn: '回合',
58
- step: '步骤',
59
- error: '错误',
60
- other: '事件',
35
+ user: 'detail.kind.user',
36
+ assistant: 'detail.kind.assistant',
37
+ thinking: 'detail.kind.thinking',
38
+ toolCall: 'detail.kind.toolCall',
39
+ toolResult: 'detail.kind.toolResult',
40
+ turn: 'detail.kind.turn',
41
+ step: 'detail.kind.step',
42
+ error: 'detail.kind.error',
43
+ other: 'detail.kind.other',
61
44
  },
62
- /** Seq-discontinuity marker row (design §4.b.3 honest presentation). */
63
45
  gap: {
64
- label: '缺口:可能有 {n} 条事件未捕获(256 队列上限或未持久化)',
46
+ label: 'detail.gap.label',
65
47
  },
66
- /** Kind filter chips (UX-03): protocol noise hidden by default, honestly counted. */
67
48
  filter: {
68
- conversation: '只看对话',
69
- all: '全部事件',
70
- hiddenNotice: '已隐藏 {n} 条协议事件',
49
+ conversation: 'detail.filter.conversation',
50
+ all: 'detail.filter.all',
51
+ hiddenNotice: 'detail.filter.hiddenNotice',
71
52
  },
72
- /** Timeline list chrome. */
73
53
  timeline: {
74
- loadMore: '加载更多历史',
75
- loadingMore: '加载中…',
76
- noMore: '已到时间线起点',
77
- expand: '展开',
78
- collapse: '收起',
79
- newBadge: '',
80
- seq: 'seq {n}',
81
- hiddenNotice: '为保持流畅,较早的 {n} 条已折叠',
82
- showAll: '全部显示',
83
- /** Aggregated row for an adjacent run of empty streaming chunks (UX-03). */
84
- chunkRun: '{n} 个流式分块',
54
+ loadMore: 'detail.timeline.loadMore',
55
+ loadingMore: 'detail.timeline.loadingMore',
56
+ noMore: 'detail.timeline.noMore',
57
+ expand: 'detail.timeline.expand',
58
+ collapse: 'detail.timeline.collapse',
59
+ newBadge: 'detail.timeline.newBadge',
60
+ seq: 'detail.timeline.seq',
61
+ hiddenNotice: 'detail.timeline.hiddenNotice',
62
+ showAll: 'detail.timeline.showAll',
63
+ chunkRun: 'detail.timeline.chunkRun',
85
64
  },
86
- /** Loading / empty / error body states. */
87
65
  states: {
88
- loadingTitle: '正在加载时间线…',
89
- emptyTitle: '暂无事件',
90
- emptyHint: '该会话还没有可展示的规范化事件。',
91
- errorTitle: '时间线加载失败',
92
- /** Fallback template when the reason code has no friendly mapping. */
93
- errorFallback: '错误码:{reason}',
66
+ loadingTitle: 'detail.states.loadingTitle',
67
+ emptyTitle: 'detail.states.emptyTitle',
68
+ emptyHint: 'detail.states.emptyHint',
69
+ errorTitle: 'detail.states.errorTitle',
70
+ errorFallback: 'detail.states.errorFallback',
94
71
  errors: {
95
- session_not_found: '会话不存在或已不可见',
96
- invalid_cursor: '分页游标无效,请重新打开详情',
97
- fusion_not_wired: '当前 host 未启用时间线能力',
98
- network_error: '网络错误,无法联系 dsh host',
99
- request_timeout: '请求超时',
72
+ session_not_found: 'detail.states.errors.session_not_found',
73
+ invalid_cursor: 'detail.states.errors.invalid_cursor',
74
+ fusion_not_wired: 'detail.states.errors.fusion_not_wired',
75
+ network_error: 'detail.states.errors.network_error',
76
+ request_timeout: 'detail.states.errors.request_timeout',
100
77
  },
101
78
  },
102
- /** Relative time templates (coarse buckets, matches the board wording). */
103
79
  time: {
104
- justNow: '刚刚',
105
- minutesAgo: '{n} 分钟前',
106
- hoursAgo: '{n} 小时前',
107
- daysAgo: '{n} 天前',
80
+ justNow: 'detail.time.justNow',
81
+ minutesAgo: 'detail.time.minutesAgo',
82
+ hoursAgo: 'detail.time.hoursAgo',
83
+ daysAgo: 'detail.time.daysAgo',
108
84
  },
109
- } as const
85
+ } as const)
110
86
 
111
87
  export type DetailStrings = typeof DETAIL_STRINGS