@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,31 +1,9 @@
|
|
|
1
|
-
|
|
2
|
-
* Inject panel (design §5.1 view 3): the two-phase confirmation UI for
|
|
3
|
-
* message injection. Fully controlled and presentational — the component
|
|
4
|
-
* does NO data fetching; the integration layer supplies `onPrepare` /
|
|
5
|
-
* `onExecute` callbacks that speak to `POST <prefix>/action` and resolve
|
|
6
|
-
* with either the wire success shape or the data layer's normalized
|
|
7
|
-
* ApiError (matched structurally, never imported).
|
|
8
|
-
*
|
|
9
|
-
* Three zones, driven by the pure reducer in ./logic.ts:
|
|
10
|
-
*
|
|
11
|
-
* 1. editor — message textarea + live UTF-8 byte counter, queue/steer mode
|
|
12
|
-
* radios, target row, cursor-cli process-list warning (§4.d/S7) and the
|
|
13
|
-
* audit-fingerprint note (§5.3);
|
|
14
|
-
* 2. confirm — the prepare plan (live target-status snapshot + message
|
|
15
|
-
* digest), the 60s confirmToken countdown, and the deliberately
|
|
16
|
-
* restrained danger button;
|
|
17
|
-
* 3. result — delivered / failed (re-prepare offered) / unknown (terminal:
|
|
18
|
-
* the reducer itself refuses a reset, so no retry affordance can exist —
|
|
19
|
-
* S6 — and the copy points at the session to verify).
|
|
20
|
-
*
|
|
21
|
-
* `capability.inject === false` disables the whole panel with the
|
|
22
|
-
* "enable injection in Settings" note.
|
|
23
|
-
*/
|
|
24
|
-
|
|
1
|
+
import { Button, Pill } from '@deepseek-ai/dsh-client-ui-primitives'
|
|
25
2
|
import { useEffect, useId, useReducer, useState } from 'react'
|
|
26
3
|
import type { ReactNode } from 'react'
|
|
27
4
|
import { t as defaultT } from '../locales/index.ts'
|
|
28
5
|
import type { SidecarLocaleKey } from '../locales/index.ts'
|
|
6
|
+
import { surfaceProps } from '../theme/parts.ts'
|
|
29
7
|
import css from './inject.module.css'
|
|
30
8
|
import {
|
|
31
9
|
byteUsage,
|
|
@@ -103,10 +81,6 @@ function renderCopy(t: InjectTranslate, copy: CopyRef): string {
|
|
|
103
81
|
return t(copy.key, copy.params)
|
|
104
82
|
}
|
|
105
83
|
|
|
106
|
-
// ---------------------------------------------------------------------------
|
|
107
|
-
// Zone building blocks.
|
|
108
|
-
// ---------------------------------------------------------------------------
|
|
109
|
-
|
|
110
84
|
interface WarningsProps {
|
|
111
85
|
t: InjectTranslate
|
|
112
86
|
agent: string | null
|
|
@@ -141,7 +115,7 @@ function PlanBox(props: PlanBoxProps): ReactNode {
|
|
|
141
115
|
<div className={css['planRow']}>
|
|
142
116
|
<span className={css['planKey']}>{t('inject.planTargetLabel')}</span>
|
|
143
117
|
<span className={css['planValue']}>
|
|
144
|
-
<
|
|
118
|
+
<Pill className={css['agentTag']}>{plan.target.agent}</Pill>
|
|
145
119
|
<span className={css['planTitle']} title={plan.target.sessionId}>{targetName}</span>
|
|
146
120
|
</span>
|
|
147
121
|
</div>
|
|
@@ -165,15 +139,6 @@ function PlanBox(props: PlanBoxProps): ReactNode {
|
|
|
165
139
|
)
|
|
166
140
|
}
|
|
167
141
|
|
|
168
|
-
// ---------------------------------------------------------------------------
|
|
169
|
-
// Panel.
|
|
170
|
-
// ---------------------------------------------------------------------------
|
|
171
|
-
|
|
172
|
-
/**
|
|
173
|
-
* Render the two-phase inject panel.
|
|
174
|
-
* @param props - capability, target, and the integration callbacks.
|
|
175
|
-
* @returns the panel.
|
|
176
|
-
*/
|
|
177
142
|
export function InjectPanel(props: InjectPanelProps): ReactNode {
|
|
178
143
|
const t = props.t ?? defaultT
|
|
179
144
|
const now = props.nowMs ?? Date.now
|
|
@@ -274,18 +239,18 @@ export function InjectPanel(props: InjectPanelProps): ReactNode {
|
|
|
274
239
|
}
|
|
275
240
|
}
|
|
276
241
|
|
|
242
|
+
const panelSurface = surfaceProps('inject-panel', css['panel'])
|
|
277
243
|
const closeButton = props.onClose !== undefined
|
|
278
244
|
? (
|
|
279
|
-
<
|
|
245
|
+
<Button type="button" size="sm" variant="outline" onClick={props.onClose}>
|
|
280
246
|
{t('inject.close')}
|
|
281
|
-
</
|
|
247
|
+
</Button>
|
|
282
248
|
)
|
|
283
249
|
: null
|
|
284
250
|
|
|
285
|
-
// ── whole-panel gate: injection capability off ─────────────────────────
|
|
286
251
|
if (!props.capability.inject) {
|
|
287
252
|
return (
|
|
288
|
-
<section
|
|
253
|
+
<section {...panelSurface} aria-label={t('inject.title')} onKeyDown={handleKeyDown}>
|
|
289
254
|
<header className={css['header']}>
|
|
290
255
|
<h3 className={css['title']}>{t('inject.title')}</h3>
|
|
291
256
|
</header>
|
|
@@ -299,7 +264,6 @@ export function InjectPanel(props: InjectPanelProps): ReactNode {
|
|
|
299
264
|
)
|
|
300
265
|
}
|
|
301
266
|
|
|
302
|
-
// ── zone 3: result ──────────────────────────────────────────────────────
|
|
303
267
|
if (state.phase === 'result') {
|
|
304
268
|
const { result } = state
|
|
305
269
|
const actions = resultActions(result.outcome)
|
|
@@ -309,7 +273,7 @@ export function InjectPanel(props: InjectPanelProps): ReactNode {
|
|
|
309
273
|
? css['resultFail']
|
|
310
274
|
: css['resultUnknown']
|
|
311
275
|
return (
|
|
312
|
-
<section
|
|
276
|
+
<section {...panelSurface} aria-label={t('inject.title')} onKeyDown={handleKeyDown}>
|
|
313
277
|
<header className={css['header']}>
|
|
314
278
|
<h3 className={css['title']}>{t('inject.title')}</h3>
|
|
315
279
|
</header>
|
|
@@ -329,36 +293,39 @@ export function InjectPanel(props: InjectPanelProps): ReactNode {
|
|
|
329
293
|
{closeButton}
|
|
330
294
|
{isDeliveredResult(result) && props.onObserve !== undefined
|
|
331
295
|
? (
|
|
332
|
-
<
|
|
296
|
+
<Button
|
|
333
297
|
type="button"
|
|
334
|
-
|
|
298
|
+
size="sm"
|
|
299
|
+
variant="primary"
|
|
335
300
|
onClick={props.onObserve}
|
|
336
301
|
data-testid="agent-sidecar-inject-observe"
|
|
337
302
|
>
|
|
338
303
|
{t('inject.observeListen')}
|
|
339
|
-
</
|
|
304
|
+
</Button>
|
|
340
305
|
)
|
|
341
306
|
: null}
|
|
342
307
|
{actions.canReprepare
|
|
343
308
|
? (
|
|
344
|
-
<
|
|
309
|
+
<Button
|
|
345
310
|
type="button"
|
|
346
|
-
|
|
311
|
+
size="sm"
|
|
312
|
+
variant="primary"
|
|
347
313
|
onClick={() => { dispatch({ type: 'RESET' }) }}
|
|
348
314
|
>
|
|
349
315
|
{t('inject.reprepare')}
|
|
350
|
-
</
|
|
316
|
+
</Button>
|
|
351
317
|
)
|
|
352
318
|
: null}
|
|
353
319
|
{result.outcome === 'delivered' && props.onClose === undefined
|
|
354
320
|
? (
|
|
355
|
-
<
|
|
321
|
+
<Button
|
|
356
322
|
type="button"
|
|
357
|
-
|
|
323
|
+
size="sm"
|
|
324
|
+
variant="primary"
|
|
358
325
|
onClick={() => { dispatch({ type: 'RESET' }) }}
|
|
359
326
|
>
|
|
360
327
|
{t('inject.done')}
|
|
361
|
-
</
|
|
328
|
+
</Button>
|
|
362
329
|
)
|
|
363
330
|
: null}
|
|
364
331
|
</div>
|
|
@@ -367,7 +334,6 @@ export function InjectPanel(props: InjectPanelProps): ReactNode {
|
|
|
367
334
|
)
|
|
368
335
|
}
|
|
369
336
|
|
|
370
|
-
// ── zone 2: confirm / executing ─────────────────────────────────────────
|
|
371
337
|
if (state.phase === 'confirm' || state.phase === 'executing') {
|
|
372
338
|
const executing = state.phase === 'executing'
|
|
373
339
|
const countdown = state.phase === 'confirm'
|
|
@@ -375,7 +341,7 @@ export function InjectPanel(props: InjectPanelProps): ReactNode {
|
|
|
375
341
|
: null
|
|
376
342
|
return (
|
|
377
343
|
<section
|
|
378
|
-
|
|
344
|
+
{...panelSurface}
|
|
379
345
|
aria-label={t('inject.confirmTitle')}
|
|
380
346
|
onKeyDown={handleKeyDown}
|
|
381
347
|
>
|
|
@@ -393,14 +359,15 @@ export function InjectPanel(props: InjectPanelProps): ReactNode {
|
|
|
393
359
|
)
|
|
394
360
|
: null}
|
|
395
361
|
<div className={css['footer']}>
|
|
396
|
-
<
|
|
362
|
+
<Button
|
|
397
363
|
type="button"
|
|
398
|
-
|
|
364
|
+
size="sm"
|
|
365
|
+
variant="outline"
|
|
399
366
|
disabled={executing}
|
|
400
367
|
onClick={() => { dispatch({ type: 'CANCEL' }) }}
|
|
401
368
|
>
|
|
402
369
|
{t('inject.cancel')}
|
|
403
|
-
</
|
|
370
|
+
</Button>
|
|
404
371
|
<button
|
|
405
372
|
type="button"
|
|
406
373
|
className={css['btnDanger']}
|
|
@@ -415,7 +382,6 @@ export function InjectPanel(props: InjectPanelProps): ReactNode {
|
|
|
415
382
|
)
|
|
416
383
|
}
|
|
417
384
|
|
|
418
|
-
// ── zone 1: editor (idle / preparing) ───────────────────────────────────
|
|
419
385
|
const preparing = state.phase === 'preparing'
|
|
420
386
|
const canEdit = props.target !== null && !preparing
|
|
421
387
|
const usage = byteUsage(validation.bytes)
|
|
@@ -423,7 +389,7 @@ export function InjectPanel(props: InjectPanelProps): ReactNode {
|
|
|
423
389
|
const showInvalid = !validation.ok && validation.code !== 'empty'
|
|
424
390
|
|
|
425
391
|
return (
|
|
426
|
-
<section
|
|
392
|
+
<section {...panelSurface} aria-label={t('inject.title')} onKeyDown={handleKeyDown}>
|
|
427
393
|
<header className={css['header']}>
|
|
428
394
|
<h3 className={css['title']}>{t('inject.title')}</h3>
|
|
429
395
|
</header>
|
|
@@ -447,7 +413,7 @@ export function InjectPanel(props: InjectPanelProps): ReactNode {
|
|
|
447
413
|
{props.target !== null
|
|
448
414
|
? (
|
|
449
415
|
<span className={css['planValue']}>
|
|
450
|
-
<
|
|
416
|
+
<Pill className={css['agentTag']}>{props.target.agent}</Pill>
|
|
451
417
|
<span className={css['planTitle']} title={props.target.sessionId}>
|
|
452
418
|
{props.target.title !== undefined && props.target.title !== ''
|
|
453
419
|
? props.target.title
|
|
@@ -520,14 +486,15 @@ export function InjectPanel(props: InjectPanelProps): ReactNode {
|
|
|
520
486
|
|
|
521
487
|
<div className={css['footer']}>
|
|
522
488
|
{closeButton}
|
|
523
|
-
<
|
|
489
|
+
<Button
|
|
524
490
|
type="button"
|
|
525
|
-
|
|
491
|
+
size="sm"
|
|
492
|
+
variant="primary"
|
|
526
493
|
disabled={!gate.canPrepare}
|
|
527
494
|
onClick={() => { void handlePrepare() }}
|
|
528
495
|
>
|
|
529
496
|
{t(preparing ? 'inject.preparing' : 'inject.prepare')}
|
|
530
|
-
</
|
|
497
|
+
</Button>
|
|
531
498
|
</div>
|
|
532
499
|
</div>
|
|
533
500
|
</section>
|