@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
- * Board styles (design §5.4): every color rides a --dsw-alias-* design
3
- * token with a neutral fallback — no theme colors are hardcoded as the
4
- * only value. Layout follows the dsh-project-kanban blueprint (flex top
5
- * bar, grouped sections, auto-fill card grid).
6
- */
1
+ /* Board layout consumes the public Agent Sidecar theme contract. */
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(--dsw-alias-label-primary, #1f2328);
18
- background: var(--dsw-alias-bg-base, transparent);
12
+ color: var(--agsc-fg);
13
+ background: var(--agsc-bg);
19
14
  }
20
15
 
21
16
  /* ------------------------------------------------------------- top bar */
@@ -30,84 +25,35 @@
30
25
  .title {
31
26
  font-size: 15px;
32
27
  font-weight: 650;
33
- color: var(--dsw-alias-label-primary, #1f2328);
28
+ color: var(--agsc-fg);
34
29
  margin-right: 2px;
35
30
  }
36
31
 
37
- .badge {
38
- display: inline-flex;
39
- align-items: center;
40
- gap: 5px;
41
- font-size: 12px;
42
- line-height: 20px;
43
- padding: 0 8px;
44
- border-radius: 999px;
45
- border: 1px solid var(--dsw-alias-border-l1, rgba(0, 0, 0, 0.08));
46
- background: var(--dsw-alias-bg-layer-1, rgba(0, 0, 0, 0.03));
47
- color: var(--dsw-alias-label-secondary, #57606a);
48
- white-space: nowrap;
49
- }
50
-
51
32
  .dot {
52
33
  width: 8px;
53
34
  height: 8px;
54
35
  border-radius: 50%;
55
36
  flex: none;
56
- background: var(--dsw-alias-label-tertiary, #6e7781);
57
- }
58
-
59
- .dot[data-tone='success'] {
60
- background: var(--dsw-alias-state-success-primary, #1a7f37);
61
- }
62
-
63
- .dot[data-tone='warn'] {
64
- background: var(--dsw-alias-state-warn-primary, #9a6700);
65
- }
66
-
67
- .dot[data-tone='danger'] {
68
- background: var(--dsw-alias-state-error-primary, #cf222e);
37
+ background: var(--dsw-alias-label-tertiary);
69
38
  }
70
39
 
71
40
  .dot[data-tone='neutral'] {
72
- background: var(--dsw-alias-label-tertiary, #6e7781);
41
+ background: var(--dsw-alias-label-tertiary);
73
42
  }
74
43
 
75
44
  .dot[data-tone='muted'] {
76
- background: var(--dsw-alias-label-dimmed, #8c959f);
45
+ background: var(--agsc-fg-dimmed);
77
46
  }
78
47
 
79
48
  /* UX-01: clickable working/waiting count badges + the total counter. */
80
49
 
81
50
  .countBadge {
82
- display: inline-flex;
83
- align-items: center;
84
- gap: 5px;
85
- font-size: 12px;
86
- font-family: inherit;
87
- line-height: 20px;
88
- padding: 0 8px;
89
- border-radius: 999px;
90
- border: 1px solid var(--dsw-alias-border-l1, rgba(0, 0, 0, 0.08));
91
- background: var(--dsw-alias-bg-layer-1, rgba(0, 0, 0, 0.03));
92
- color: var(--dsw-alias-label-secondary, #57606a);
93
51
  white-space: nowrap;
94
- cursor: pointer;
95
- }
96
-
97
- .countBadge:hover {
98
- color: var(--dsw-alias-label-primary, #1f2328);
99
- border-color: var(--dsw-alias-border-l2, rgba(0, 0, 0, 0.12));
100
- background: var(--dsw-alias-interactive-bg-hover, rgba(0, 0, 0, 0.04));
101
- }
102
-
103
- .countBadge[aria-pressed='true'] {
104
- color: var(--dsw-alias-brand-primary, #4d6bfe);
105
- border-color: var(--dsw-alias-brand-primary, #4d6bfe);
106
52
  }
107
53
 
108
54
  .countTotal {
109
55
  font-size: 12px;
110
- color: var(--dsw-alias-label-secondary, #57606a);
56
+ color: var(--agsc-fg-secondary);
111
57
  white-space: nowrap;
112
58
  }
113
59
 
@@ -120,79 +66,52 @@
120
66
  align-items: center;
121
67
  gap: 5px;
122
68
  font-size: 12px;
123
- color: var(--dsw-alias-label-secondary, #57606a);
69
+ color: var(--agsc-fg-secondary);
124
70
  white-space: nowrap;
125
71
  }
126
72
 
127
73
  .select {
74
+ height: 28px;
128
75
  font-size: 12px;
129
76
  font-family: inherit;
130
- color: var(--dsw-alias-label-primary, #1f2328);
131
- background: var(--dsw-alias-bg-layer-1, transparent);
132
- border: 1px solid var(--dsw-alias-border-l2, rgba(0, 0, 0, 0.12));
133
- border-radius: 6px;
134
- padding: 2px 6px;
77
+ color: var(--agsc-fg);
78
+ background: var(--agsc-bg-raised);
79
+ border: 1px solid var(--agsc-border-strong);
80
+ border-radius: 14px;
81
+ padding: 0 10px;
135
82
  }
136
83
 
137
84
  .checkbox {
138
- accent-color: var(--dsw-alias-brand-primary, #4d6bfe);
85
+ accent-color: var(--agsc-accent);
139
86
  margin: 0;
140
87
  }
141
88
 
142
- .refresh {
143
- font-size: 12px;
144
- font-family: inherit;
145
- color: var(--dsw-alias-label-secondary, #57606a);
146
- background: transparent;
147
- border: 1px solid var(--dsw-alias-border-l1, rgba(0, 0, 0, 0.08));
148
- border-radius: 6px;
149
- padding: 2px 10px;
150
- cursor: pointer;
151
- }
152
-
153
- .refresh:hover {
154
- color: var(--dsw-alias-label-primary, #1f2328);
155
- border-color: var(--dsw-alias-border-l2, rgba(0, 0, 0, 0.12));
156
- background: var(--dsw-alias-interactive-bg-hover, rgba(0, 0, 0, 0.04));
157
- }
158
-
159
- .refresh:disabled {
160
- cursor: default;
161
- opacity: 0.6;
162
- }
163
-
164
89
  /* -------------------------------------------------------------- banner */
165
90
 
166
91
  .banner {
167
92
  font-size: 12px;
168
93
  line-height: 18px;
169
94
  padding: 6px 10px;
170
- border-radius: 8px;
171
- border: 1px solid var(--dsw-alias-border-l1, rgba(0, 0, 0, 0.08));
95
+ border-radius: var(--agsc-radius-control);
96
+ border: 1px solid var(--agsc-border);
172
97
  }
173
98
 
174
99
  .banner[data-tone='warn'] {
175
- color: var(--dsw-alias-state-warn-label, var(--dsw-alias-state-warn-primary, #9a6700));
176
- background: var(--dsw-alias-state-warn-tertiary, rgba(154, 103, 0, 0.08));
177
- border-color: var(--dsw-alias-state-warn-secondary, rgba(154, 103, 0, 0.24));
100
+ color: var(--agsc-warn);
101
+ background: var(--dsw-alias-state-warn-tertiary);
102
+ border-color: var(--dsw-alias-state-warn-secondary);
178
103
  }
179
104
 
180
105
  .banner[data-tone='danger'] {
181
- color: var(--dsw-alias-state-error-primary, #cf222e);
182
- background: var(--dsw-alias-state-error-secondary, rgba(207, 34, 46, 0.08));
183
- border-color: var(--dsw-alias-state-error-secondary, rgba(207, 34, 46, 0.24));
106
+ color: var(--agsc-err);
107
+ background: var(--dsw-alias-state-error-secondary);
108
+ border-color: var(--dsw-alias-state-error-secondary);
184
109
  }
185
110
 
186
111
  .bannerDismiss {
187
112
  margin-left: 10px;
188
- padding: 0;
189
- border: none;
190
- background: transparent;
191
- font-size: 12px;
192
- font-family: inherit;
193
113
  color: inherit;
194
114
  text-decoration: underline;
195
- cursor: pointer;
196
115
  }
197
116
 
198
117
  /* -------------------------------------------------------- empty states */
@@ -212,14 +131,14 @@
212
131
  .emptyTitle {
213
132
  font-size: 14px;
214
133
  font-weight: 600;
215
- color: var(--dsw-alias-label-primary, #1f2328);
134
+ color: var(--agsc-fg);
216
135
  }
217
136
 
218
137
  .emptyHint {
219
138
  font-size: 12px;
220
139
  max-width: 420px;
221
140
  line-height: 20px;
222
- color: var(--dsw-alias-label-secondary, #57606a);
141
+ color: var(--agsc-fg-secondary);
223
142
  }
224
143
 
225
144
  /* -------------------------------------------------------- group blocks */
@@ -248,36 +167,23 @@
248
167
  .chevron {
249
168
  flex: none;
250
169
  font-size: 10px;
251
- color: var(--dsw-alias-label-tertiary, #6e7781);
170
+ color: var(--agsc-fg-dimmed);
252
171
  }
253
172
 
254
173
  .groupAttention {
255
174
  flex: none;
256
175
  font-size: 11px;
257
- color: var(--dsw-alias-state-warn-primary, #9a6700);
176
+ color: var(--agsc-warn);
258
177
  }
259
178
 
260
179
  .showMore {
261
180
  align-self: flex-start;
262
- font-size: 12px;
263
- font-family: inherit;
264
- color: var(--dsw-alias-label-secondary, #57606a);
265
- background: transparent;
266
- border: 1px dashed var(--dsw-alias-border-l2, rgba(0, 0, 0, 0.12));
267
- border-radius: 6px;
268
- padding: 2px 10px;
269
- cursor: pointer;
270
- }
271
-
272
- .showMore:hover {
273
- color: var(--dsw-alias-label-primary, #1f2328);
274
- background: var(--dsw-alias-interactive-bg-hover, rgba(0, 0, 0, 0.04));
275
181
  }
276
182
 
277
183
  .groupName {
278
184
  font-size: 13px;
279
185
  font-weight: 600;
280
- color: var(--dsw-alias-label-primary, #1f2328);
186
+ color: var(--agsc-fg);
281
187
  overflow: hidden;
282
188
  text-overflow: ellipsis;
283
189
  white-space: nowrap;
@@ -286,8 +192,8 @@
286
192
  .groupCount {
287
193
  font-size: 11px;
288
194
  flex: none;
289
- color: var(--dsw-alias-label-secondary, #57606a);
290
- background: var(--dsw-alias-bg-layer-2, rgba(0, 0, 0, 0.04));
195
+ color: var(--agsc-fg-secondary);
196
+ background: var(--dsw-alias-bg-layer-2);
291
197
  border-radius: 999px;
292
198
  padding: 0 8px;
293
199
  line-height: 18px;
@@ -305,24 +211,37 @@
305
211
  display: flex;
306
212
  flex-direction: column;
307
213
  gap: 6px;
308
- text-align: left;
309
- font-family: inherit;
310
214
  min-width: 0;
311
215
  padding: 10px 12px;
312
- border-radius: 8px;
313
- border: 1px solid var(--dsw-alias-border-l1, rgba(0, 0, 0, 0.08));
314
- background: var(--dsw-alias-bg-layer-1, rgba(0, 0, 0, 0.02));
315
- cursor: pointer;
216
+ border-radius: var(--agsc-radius-card);
217
+ border: 1px solid var(--agsc-border-strong);
218
+ background: var(--agsc-bg-raised);
316
219
  }
317
220
 
318
221
  .card:hover {
319
- border-color: var(--dsw-alias-border-l2, rgba(0, 0, 0, 0.12));
320
- background: var(--dsw-alias-interactive-bg-hover, rgba(0, 0, 0, 0.04));
222
+ border-color: var(--dsw-alias-label-dimmed);
223
+ background: var(--dsw-alias-interactive-bg-hover);
321
224
  }
322
225
 
323
- .card:focus-visible {
324
- outline: 2px solid var(--dsw-alias-brand-primary, #4d6bfe);
325
- outline-offset: 1px;
226
+ .cardOpen {
227
+ display: flex;
228
+ flex-direction: column;
229
+ gap: 6px;
230
+ width: 100%;
231
+ min-width: 0;
232
+ padding: 0;
233
+ border: 0;
234
+ border-radius: var(--agsc-radius-control);
235
+ color: inherit;
236
+ background: none;
237
+ font: inherit;
238
+ text-align: left;
239
+ cursor: pointer;
240
+ }
241
+
242
+ .cardOpen:focus-visible {
243
+ outline: 2px solid var(--agsc-accent);
244
+ outline-offset: 2px;
326
245
  }
327
246
 
328
247
  .cardHead {
@@ -343,54 +262,56 @@
343
262
  overflow: hidden;
344
263
  text-overflow: ellipsis;
345
264
  white-space: nowrap;
346
- color: var(--dsw-alias-label-primary, #1f2328);
265
+ color: var(--agsc-fg);
347
266
  }
348
267
 
349
268
  .glyph {
350
269
  flex: none;
351
- color: var(--dsw-alias-brand-primary, #4d6bfe);
270
+ color: var(--agsc-accent);
271
+ }
272
+
273
+ .statusPill {
274
+ max-width: 100%;
352
275
  }
353
276
 
354
277
  .attention {
355
278
  font-size: 11px;
356
- color: var(--dsw-alias-state-warn-primary, #9a6700);
279
+ color: var(--agsc-warn);
357
280
  }
358
281
 
359
282
  .attention[data-kind='gap'] {
360
- color: var(--dsw-alias-state-error-primary, #cf222e);
283
+ color: var(--agsc-err);
361
284
  }
362
285
 
363
286
  .cardTitle {
364
287
  font-size: 13px;
365
- color: var(--dsw-alias-label-primary, #1f2328);
288
+ color: var(--agsc-fg);
366
289
  overflow: hidden;
367
290
  text-overflow: ellipsis;
368
291
  white-space: nowrap;
369
292
  }
370
293
 
371
294
  .cardId {
295
+ align-self: flex-start;
296
+ max-width: 100%;
297
+ justify-content: flex-start;
372
298
  font-size: 11px;
373
- font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
374
- color: var(--dsw-alias-label-tertiary, #6e7781);
299
+ font-family: var(--agsc-font-mono);
300
+ color: var(--agsc-fg-secondary);
375
301
  overflow: hidden;
376
302
  text-overflow: ellipsis;
377
303
  white-space: nowrap;
378
- cursor: copy;
379
- }
380
-
381
- .cardId:hover {
382
- color: var(--dsw-alias-label-secondary, #57606a);
383
304
  }
384
305
 
385
306
  .copied {
386
307
  margin-left: 6px;
387
308
  font-family: inherit;
388
- color: var(--dsw-alias-state-success-primary, #1a7f37);
309
+ color: var(--agsc-ok);
389
310
  }
390
311
 
391
312
  .cardEvent {
392
313
  font-size: 12px;
393
- color: var(--dsw-alias-label-secondary, #57606a);
314
+ color: var(--agsc-fg-secondary);
394
315
  overflow: hidden;
395
316
  text-overflow: ellipsis;
396
317
  white-space: nowrap;
@@ -398,5 +319,5 @@
398
319
 
399
320
  .cardTime {
400
321
  font-size: 11px;
401
- color: var(--dsw-alias-label-caption, var(--dsw-alias-label-tertiary, #6e7781));
322
+ color: var(--agsc-fg-secondary);
402
323
  }
@@ -13,13 +13,10 @@
13
13
  * and the group-level `lastActivityAt`. Only the fields this view renders
14
14
  * are mirrored; extra wire fields are structurally ignored.
15
15
  *
16
- * Reuse contract (T2.2, read-only): tone/glyph/relative-time/label tools
17
- * are imported from `./logic.ts` without touching its exports, so both
18
- * board views speak the same visual language. Strings NEW to this view
19
- * live in the module-local {@link PROJECT_VIEW_STRINGS} table (S7 unifies
20
- * locales later); strings emitted by reused board tools (status labels,
21
- * relative time, the unknown-project label) intentionally stay with the
22
- * board table so the two views can never drift apart.
16
+ * Reuse contract (T2.2): tone/glyph/relative-time/label tools are imported
17
+ * from `./logic.ts`, so both board views speak the same visual language.
18
+ * Project-only copy is exposed through the dynamic
19
+ * {@link PROJECT_VIEW_STRINGS} locale facade.
23
20
  *
24
21
  * @module
25
22
  */
@@ -35,39 +32,29 @@ import {
35
32
  statusRank,
36
33
  type StatusBadgeVM,
37
34
  } from './logic.ts'
35
+ import { createLocaleView } from '../locales/view.ts'
38
36
 
39
37
  // ---------------------------------------------------------------------------
40
- // Module-local strings (project-view-only vocabulary; Chinese primary).
38
+ // Project-view-only locale facade.
41
39
  // ---------------------------------------------------------------------------
42
40
 
43
- export const PROJECT_VIEW_STRINGS = {
44
- /** View heading. */
45
- title: '项目关联',
46
- /** Header count summary. */
47
- summary: '{projects} 个项目 · {sessions} 个会话',
48
- /** Cross-agent badge, shown when a project hosts 2+ agent kinds. */
49
- crossAgent: '{n} 种 agent',
50
- /** Group header session count. */
51
- sessionCount: '{n} 个会话',
52
- /** Group header recency line. */
53
- lastActive: '最近活跃 {time}',
54
- /** Marker on sessions live in this dsh process (UnifiedSession.live). */
55
- liveChip: '实时',
56
- /** Untitled-session fallback. */
57
- untitled: '(无标题)',
58
- /** Lane truncation fold (UX-20; mirrors the board's group fold). */
59
- showAllSessions: '展开全部 {n} 个会话',
60
- showLessSessions: '只看前 {n} 个',
61
- /** Empty state (no groups at all). */
41
+ export const PROJECT_VIEW_STRINGS = createLocaleView({
42
+ title: 'project.title',
43
+ summary: 'project.summary',
44
+ crossAgent: 'project.crossAgent',
45
+ sessionCount: 'project.sessionCount',
46
+ lastActive: 'project.lastActive',
47
+ liveChip: 'project.liveChip',
48
+ untitled: 'project.untitled',
49
+ showAllSessions: 'project.showAllSessions',
50
+ showLessSessions: 'project.showLessSessions',
62
51
  empty: {
63
- title: '暂无项目关联',
64
- hint: '时间窗内没有跨 agent 的项目活动;agent 在某个项目目录下开始工作后会出现在这里。',
52
+ title: 'project.empty.title',
53
+ hint: 'project.empty.hint',
65
54
  },
66
- /** Loading placeholder (first fetch, nothing to show yet). */
67
- loading: '正在加载项目关联…',
68
- /** Error banner prefix; the raw error detail is appended by the view. */
69
- errorTitle: '项目关联加载失败',
70
- } as const
55
+ loading: 'project.loading',
56
+ errorTitle: 'project.errorTitle',
57
+ } as const)
71
58
 
72
59
  export type ProjectViewStrings = typeof PROJECT_VIEW_STRINGS
73
60