@design.estate/dees-catalog 6.0.0 → 6.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/dist_bundle/bundle.js +3105 -1500
- package/dist_ts_web/00_commitinfo_data.js +1 -1
- package/dist_ts_web/elements/00group-harness/dees-harness-chat/dees-harness-chat.d.ts +2 -0
- package/dist_ts_web/elements/00group-harness/dees-harness-chat/dees-harness-chat.demo.js +484 -8
- package/dist_ts_web/elements/00group-harness/dees-harness-chat/dees-harness-chat.js +10 -1
- package/dist_ts_web/elements/00group-harness/dees-harness-message/dees-harness-message.d.ts +3 -1
- package/dist_ts_web/elements/00group-harness/dees-harness-message/dees-harness-message.js +24 -4
- package/dist_ts_web/elements/00group-harness/dees-harness-message-list/dees-harness-message-list.d.ts +26 -0
- package/dist_ts_web/elements/00group-harness/dees-harness-message-list/dees-harness-message-list.js +398 -94
- package/dist_ts_web/elements/00group-harness/dees-harness-overflow-text.d.ts +32 -0
- package/dist_ts_web/elements/00group-harness/dees-harness-overflow-text.demo.d.ts +1 -0
- package/dist_ts_web/elements/00group-harness/dees-harness-overflow-text.demo.js +31 -0
- package/dist_ts_web/elements/00group-harness/dees-harness-overflow-text.js +297 -0
- package/dist_ts_web/elements/00group-harness/dees-harness-session-list/dees-harness-session-list.js +1 -9
- package/dist_ts_web/elements/00group-harness/dees-harness-session-sidebar/dees-harness-session-sidebar.d.ts +10 -1
- package/dist_ts_web/elements/00group-harness/dees-harness-session-sidebar/dees-harness-session-sidebar.js +181 -2
- package/dist_ts_web/elements/00group-harness/dees-harness-tool-card/dees-harness-tool-card.d.ts +17 -1
- package/dist_ts_web/elements/00group-harness/dees-harness-tool-card/dees-harness-tool-card.js +480 -36
- package/dist_ts_web/elements/00group-harness/dees-harness-tool-card/renderers.js +28 -24
- package/dist_ts_web/elements/00group-harness/harness.helpers.d.ts +5 -1
- package/dist_ts_web/elements/00group-harness/harness.helpers.js +66 -1
- package/dist_ts_web/elements/00group-harness/index.d.ts +1 -0
- package/dist_ts_web/elements/00group-harness/index.js +2 -1
- package/dist_ts_web/elements/00group-harness/interfaces.d.ts +33 -2
- package/dist_ts_web/elements/00group-harness/toolregistry.d.ts +4 -0
- package/dist_ts_web/elements/00group-harness/toolregistry.js +8 -1
- package/package.json +2 -2
- package/readme.hints.md +16 -1
- package/readme.md +41 -9
- package/readme.playbook.md +8 -4
- package/ts_web/00_commitinfo_data.ts +1 -1
- package/ts_web/elements/00group-harness/dees-harness-chat/dees-harness-chat.demo.ts +490 -7
- package/ts_web/elements/00group-harness/dees-harness-chat/dees-harness-chat.ts +9 -0
- package/ts_web/elements/00group-harness/dees-harness-message/dees-harness-message.ts +24 -3
- package/ts_web/elements/00group-harness/dees-harness-message-list/dees-harness-message-list.ts +397 -84
- package/ts_web/elements/00group-harness/dees-harness-overflow-text.demo.ts +31 -0
- package/ts_web/elements/00group-harness/dees-harness-overflow-text.ts +236 -0
- package/ts_web/elements/00group-harness/dees-harness-session-list/dees-harness-session-list.ts +0 -8
- package/ts_web/elements/00group-harness/dees-harness-session-sidebar/dees-harness-session-sidebar.ts +193 -1
- package/ts_web/elements/00group-harness/dees-harness-tool-card/dees-harness-tool-card.ts +484 -34
- package/ts_web/elements/00group-harness/dees-harness-tool-card/renderers.ts +29 -25
- package/ts_web/elements/00group-harness/harness.helpers.ts +68 -1
- package/ts_web/elements/00group-harness/index.ts +1 -0
- package/ts_web/elements/00group-harness/interfaces.ts +38 -2
- package/ts_web/elements/00group-harness/toolregistry.ts +12 -0
|
@@ -10,7 +10,11 @@ import {
|
|
|
10
10
|
cssManager,
|
|
11
11
|
} from '@design.estate/dees-element';
|
|
12
12
|
import { themeDefaultStyles } from '../../00theme.js';
|
|
13
|
-
import type {
|
|
13
|
+
import type {
|
|
14
|
+
IHarnessToolCall,
|
|
15
|
+
THarnessContentBlock,
|
|
16
|
+
THarnessMessageStreamDelta,
|
|
17
|
+
} from '../interfaces.js';
|
|
14
18
|
import {
|
|
15
19
|
DeesHarnessToolRegistry,
|
|
16
20
|
parseMcpName,
|
|
@@ -19,8 +23,16 @@ import {
|
|
|
19
23
|
} from '../toolregistry.js';
|
|
20
24
|
import { builtinBodyRenderers } from './renderers.js';
|
|
21
25
|
import { harnessCardStyles, harnessPillStyles, harnessMonoStyles } from '../harness.styles.js';
|
|
22
|
-
import {
|
|
26
|
+
import {
|
|
27
|
+
harnessApplyMessageDelta,
|
|
28
|
+
harnessEffectiveToolStatus,
|
|
29
|
+
harnessFormatClockTime,
|
|
30
|
+
harnessFormatDuration,
|
|
31
|
+
harnessTruncate,
|
|
32
|
+
} from '../harness.helpers.js';
|
|
33
|
+
import { DeesHarnessMessageList } from '../dees-harness-message-list/dees-harness-message-list.js';
|
|
23
34
|
import '../dees-harness-content-blocks/dees-harness-content-blocks.js';
|
|
35
|
+
import '../dees-harness-overflow-text.js';
|
|
24
36
|
import '../../00group-dataview/dees-dataview-codebox/dees-dataview-codebox.js';
|
|
25
37
|
import './dees-harness-tool-fullscreen.js';
|
|
26
38
|
import '../../00group-feedback/dees-badge/dees-badge.js';
|
|
@@ -49,12 +61,19 @@ export class DeesHarnessToolCard extends DeesElement {
|
|
|
49
61
|
@property({ attribute: false })
|
|
50
62
|
accessor toolRegistry: DeesHarnessToolRegistry = DeesHarnessToolRegistry.default;
|
|
51
63
|
|
|
64
|
+
/** Nested lists disable this to keep inline subtask streams one level deep. */
|
|
65
|
+
@property({ type: Boolean })
|
|
66
|
+
accessor allowSubtaskStreams: boolean = true;
|
|
67
|
+
|
|
52
68
|
@state()
|
|
53
69
|
accessor expanded: boolean | undefined = undefined;
|
|
54
70
|
|
|
55
71
|
@state()
|
|
56
72
|
accessor outputExpanded: boolean = false;
|
|
57
73
|
|
|
74
|
+
@state()
|
|
75
|
+
accessor bodyMounted: boolean = false;
|
|
76
|
+
|
|
58
77
|
/** Body height cap; taller content scrolls in place and offers fullscreen. */
|
|
59
78
|
@property({ type: Number })
|
|
60
79
|
accessor bodyCapPx: number = 360;
|
|
@@ -75,6 +94,9 @@ export class DeesHarnessToolCard extends DeesElement {
|
|
|
75
94
|
private bodyResizeObserver: ResizeObserver | null = null;
|
|
76
95
|
private observedBodyInner: Element | null = null;
|
|
77
96
|
private fullscreenPortal: HTMLElementTagNameMap['dees-harness-tool-fullscreen'] | null = null;
|
|
97
|
+
private disclosureFrame: number | null = null;
|
|
98
|
+
private subtaskResultElement: HTMLElement | null = null;
|
|
99
|
+
private subtaskResultResizeObserver: ResizeObserver | null = null;
|
|
78
100
|
|
|
79
101
|
public static styles = [
|
|
80
102
|
themeDefaultStyles,
|
|
@@ -88,6 +110,56 @@ export class DeesHarnessToolCard extends DeesElement {
|
|
|
88
110
|
font-family: var(--dees-font-family);
|
|
89
111
|
}
|
|
90
112
|
|
|
113
|
+
.harness-card.subtaskPreviewCard {
|
|
114
|
+
max-height: var(--dees-harness-active-subtask-height, 320px);
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
.harness-card.subtaskPreviewOpen {
|
|
118
|
+
display: flex;
|
|
119
|
+
flex-direction: column;
|
|
120
|
+
height: var(--dees-harness-active-subtask-height, 320px);
|
|
121
|
+
box-sizing: border-box;
|
|
122
|
+
overflow: hidden;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
.harness-card.subtaskPreviewOpen .bodyDisclosure.open,
|
|
126
|
+
.harness-card.subtaskPreviewOpen .bodyDisclosureInner,
|
|
127
|
+
.harness-card.subtaskPreviewOpen .bodyClipFrame {
|
|
128
|
+
flex: 1;
|
|
129
|
+
min-height: 0;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
.harness-card.subtaskPreviewOpen .bodyDisclosure.open {
|
|
133
|
+
display: flex;
|
|
134
|
+
flex-direction: column;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
.harness-card.subtaskPreviewOpen .bodyDisclosureInner {
|
|
138
|
+
display: flex;
|
|
139
|
+
flex-direction: column;
|
|
140
|
+
overflow: hidden;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
.harness-card.subtaskPreviewOpen .bodyClipFrame {
|
|
144
|
+
max-height: none !important;
|
|
145
|
+
overflow: hidden;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
.harness-card.subtaskPreviewOpen .body,
|
|
149
|
+
.harness-card.subtaskPreviewOpen .subtaskPreview {
|
|
150
|
+
min-height: 0;
|
|
151
|
+
height: 100%;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
.harness-card.subtaskPreviewOpen .body {
|
|
155
|
+
grid-template-rows: auto minmax(0, 1fr) auto;
|
|
156
|
+
box-sizing: border-box;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
.harness-card.subtaskPreviewOpen .body.liveSubtaskBody {
|
|
160
|
+
grid-template-rows: minmax(0, 1fr) auto;
|
|
161
|
+
}
|
|
162
|
+
|
|
91
163
|
.header {
|
|
92
164
|
display: flex;
|
|
93
165
|
align-items: center;
|
|
@@ -119,6 +191,37 @@ export class DeesHarnessToolCard extends DeesElement {
|
|
|
119
191
|
color: var(--dees-color-accent-primary);
|
|
120
192
|
}
|
|
121
193
|
|
|
194
|
+
.harness-card.subtaskPreviewOpen.status-running::before,
|
|
195
|
+
.harness-card.subtaskPreviewOpen.status-pending::before {
|
|
196
|
+
animation: harness-card-open-chat-scan 10s linear infinite;
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
@keyframes harness-card-open-chat-scan {
|
|
200
|
+
0% {
|
|
201
|
+
background-position: 100% 0;
|
|
202
|
+
opacity: 0;
|
|
203
|
+
}
|
|
204
|
+
1% {
|
|
205
|
+
opacity: 0.35;
|
|
206
|
+
}
|
|
207
|
+
20% {
|
|
208
|
+
background-position: 0 0;
|
|
209
|
+
opacity: 0.35;
|
|
210
|
+
}
|
|
211
|
+
24%, 100% {
|
|
212
|
+
background-position: 0 0;
|
|
213
|
+
opacity: 0;
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
@media (prefers-reduced-motion: reduce) {
|
|
218
|
+
.harness-card.subtaskPreviewOpen.status-running::before,
|
|
219
|
+
.harness-card.subtaskPreviewOpen.status-pending::before {
|
|
220
|
+
animation: none;
|
|
221
|
+
opacity: 0;
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
|
|
122
225
|
.titleBlock {
|
|
123
226
|
min-width: 0;
|
|
124
227
|
flex: 1;
|
|
@@ -147,12 +250,10 @@ export class DeesHarnessToolCard extends DeesElement {
|
|
|
147
250
|
}
|
|
148
251
|
|
|
149
252
|
.subtitle {
|
|
253
|
+
display: block;
|
|
150
254
|
margin-top: 1px;
|
|
151
255
|
color: var(--dees-color-text-secondary);
|
|
152
256
|
font-size: var(--dees-font-caption1-size, 11px);
|
|
153
|
-
overflow: hidden;
|
|
154
|
-
text-overflow: ellipsis;
|
|
155
|
-
white-space: nowrap;
|
|
156
257
|
}
|
|
157
258
|
|
|
158
259
|
.metaColumn {
|
|
@@ -176,7 +277,7 @@ export class DeesHarnessToolCard extends DeesElement {
|
|
|
176
277
|
inner overflow-x scrollers engage instead. */
|
|
177
278
|
grid-template-columns: minmax(0, 1fr);
|
|
178
279
|
gap: var(--dees-spacing-sm);
|
|
179
|
-
padding:
|
|
280
|
+
padding: var(--dees-spacing-sm) var(--dees-spacing-md) var(--dees-spacing-md);
|
|
180
281
|
}
|
|
181
282
|
|
|
182
283
|
.kvGrid {
|
|
@@ -211,6 +312,30 @@ export class DeesHarnessToolCard extends DeesElement {
|
|
|
211
312
|
/* Three body modes: collapsed (no body), normal (content fits the
|
|
212
313
|
cap), capped (content taller than the cap scrolls inside the frame
|
|
213
314
|
and offers the fullscreen modal). */
|
|
315
|
+
.bodyDisclosure {
|
|
316
|
+
display: grid;
|
|
317
|
+
grid-template-rows: 0fr;
|
|
318
|
+
min-width: 0;
|
|
319
|
+
opacity: 0;
|
|
320
|
+
transform: translateY(-3px);
|
|
321
|
+
transition:
|
|
322
|
+
grid-template-rows var(--dees-transition-default) var(--dees-ease-standard),
|
|
323
|
+
opacity var(--dees-transition-fast) var(--dees-ease-standard),
|
|
324
|
+
transform var(--dees-transition-default) var(--dees-ease-standard);
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
.bodyDisclosure.open {
|
|
328
|
+
grid-template-rows: 1fr;
|
|
329
|
+
opacity: 1;
|
|
330
|
+
transform: translateY(0);
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
.bodyDisclosureInner {
|
|
334
|
+
min-width: 0;
|
|
335
|
+
min-height: 0;
|
|
336
|
+
overflow: hidden;
|
|
337
|
+
}
|
|
338
|
+
|
|
214
339
|
.bodyClipFrame {
|
|
215
340
|
position: relative;
|
|
216
341
|
overflow-y: auto;
|
|
@@ -219,6 +344,129 @@ export class DeesHarnessToolCard extends DeesElement {
|
|
|
219
344
|
scrollbar-color: var(--dees-color-scrollbar-thumb) transparent;
|
|
220
345
|
}
|
|
221
346
|
|
|
347
|
+
.subtaskPreview {
|
|
348
|
+
display: flex;
|
|
349
|
+
flex-direction: column;
|
|
350
|
+
min-width: 0;
|
|
351
|
+
block-size: 260px;
|
|
352
|
+
margin-inline: calc(0px - var(--dees-spacing-md));
|
|
353
|
+
overflow: hidden;
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
.subtaskPreview dees-harness-message-list {
|
|
357
|
+
flex: 1;
|
|
358
|
+
min-height: 0;
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
.subtaskPreviewState {
|
|
362
|
+
flex: 1;
|
|
363
|
+
display: grid;
|
|
364
|
+
place-content: center;
|
|
365
|
+
gap: var(--dees-spacing-xs);
|
|
366
|
+
min-height: 0;
|
|
367
|
+
padding: var(--dees-spacing-md);
|
|
368
|
+
color: var(--dees-color-text-secondary);
|
|
369
|
+
font-size: var(--dees-font-control-size-sm, 12px);
|
|
370
|
+
text-align: center;
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
.subtaskNotice {
|
|
374
|
+
padding: var(--dees-spacing-xs) var(--dees-spacing-sm);
|
|
375
|
+
border-bottom: 1px solid var(--dees-color-border-subtle);
|
|
376
|
+
color: var(--dees-color-text-secondary);
|
|
377
|
+
font-size: var(--dees-font-caption1-size, 11px);
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
.harness-subtask-detail {
|
|
381
|
+
display: grid;
|
|
382
|
+
align-content: start;
|
|
383
|
+
align-self: start;
|
|
384
|
+
gap: 3px;
|
|
385
|
+
min-width: 0;
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
.body:not(.liveSubtaskBody) > .harness-subtask-detail-brief {
|
|
389
|
+
grid-row: 1;
|
|
390
|
+
max-height: 35%;
|
|
391
|
+
}
|
|
392
|
+
|
|
393
|
+
.body:not(.liveSubtaskBody) > .harness-subtask-detail-brief,
|
|
394
|
+
.body:not(.liveSubtaskBody) > .harness-subtask-detail-result {
|
|
395
|
+
grid-template-rows: auto minmax(0, 1fr);
|
|
396
|
+
min-height: 0;
|
|
397
|
+
overflow: hidden;
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
.body:not(.liveSubtaskBody) > .harness-subtask-detail-result {
|
|
401
|
+
grid-row: 2;
|
|
402
|
+
align-self: stretch;
|
|
403
|
+
}
|
|
404
|
+
|
|
405
|
+
.body:not(.liveSubtaskBody) > .harness-subtask-open {
|
|
406
|
+
grid-row: 3;
|
|
407
|
+
align-self: end;
|
|
408
|
+
}
|
|
409
|
+
|
|
410
|
+
.harness-subtask-detail + .harness-subtask-detail {
|
|
411
|
+
padding-top: var(--dees-spacing-sm);
|
|
412
|
+
border-top: 1px solid var(--dees-color-border-subtle);
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
.harness-subtask-detail-label {
|
|
416
|
+
color: var(--dees-color-text-muted);
|
|
417
|
+
font-size: var(--dees-font-caption2-size, 10px);
|
|
418
|
+
font-weight: 700;
|
|
419
|
+
letter-spacing: 0.04em;
|
|
420
|
+
text-transform: uppercase;
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
.harness-subtask-detail-text {
|
|
424
|
+
color: var(--dees-color-text-primary);
|
|
425
|
+
font-size: var(--dees-font-control-size-sm, 12px);
|
|
426
|
+
line-height: 1.5;
|
|
427
|
+
overflow-wrap: anywhere;
|
|
428
|
+
white-space: pre-wrap;
|
|
429
|
+
}
|
|
430
|
+
|
|
431
|
+
.harness-subtask-detail-brief .harness-subtask-detail-text,
|
|
432
|
+
.harness-subtask-detail-result .harness-subtask-detail-text {
|
|
433
|
+
min-height: 0;
|
|
434
|
+
overflow-y: auto;
|
|
435
|
+
scrollbar-width: none;
|
|
436
|
+
}
|
|
437
|
+
|
|
438
|
+
.harness-subtask-detail-brief .harness-subtask-detail-text::-webkit-scrollbar,
|
|
439
|
+
.harness-subtask-detail-result .harness-subtask-detail-text::-webkit-scrollbar {
|
|
440
|
+
display: none;
|
|
441
|
+
}
|
|
442
|
+
|
|
443
|
+
.harness-subtask-detail-text.fadeTop {
|
|
444
|
+
-webkit-mask-image: linear-gradient(to bottom, transparent 0, black 40px, black 100%);
|
|
445
|
+
mask-image: linear-gradient(to bottom, transparent 0, black 40px, black 100%);
|
|
446
|
+
}
|
|
447
|
+
|
|
448
|
+
.harness-subtask-detail-text.fadeBottom {
|
|
449
|
+
-webkit-mask-image: linear-gradient(to bottom, black 0, black calc(100% - 40px), transparent 100%);
|
|
450
|
+
mask-image: linear-gradient(to bottom, black 0, black calc(100% - 40px), transparent 100%);
|
|
451
|
+
}
|
|
452
|
+
|
|
453
|
+
.harness-subtask-detail-text.fadeTop.fadeBottom {
|
|
454
|
+
-webkit-mask-image: linear-gradient(
|
|
455
|
+
to bottom,
|
|
456
|
+
transparent 0,
|
|
457
|
+
black 40px,
|
|
458
|
+
black calc(100% - 40px),
|
|
459
|
+
transparent 100%
|
|
460
|
+
);
|
|
461
|
+
mask-image: linear-gradient(
|
|
462
|
+
to bottom,
|
|
463
|
+
transparent 0,
|
|
464
|
+
black 40px,
|
|
465
|
+
black calc(100% - 40px),
|
|
466
|
+
transparent 100%
|
|
467
|
+
);
|
|
468
|
+
}
|
|
469
|
+
|
|
222
470
|
.maximizeBar {
|
|
223
471
|
display: flex;
|
|
224
472
|
align-items: center;
|
|
@@ -309,6 +557,10 @@ export class DeesHarnessToolCard extends DeesElement {
|
|
|
309
557
|
font-size: var(--dees-font-caption1-size, 11px);
|
|
310
558
|
}
|
|
311
559
|
|
|
560
|
+
.harness-terminal-exit.tone-success {
|
|
561
|
+
color: var(--dees-color-accent-success);
|
|
562
|
+
}
|
|
563
|
+
|
|
312
564
|
.harness-subtask-open {
|
|
313
565
|
justify-self: start;
|
|
314
566
|
display: inline-flex;
|
|
@@ -374,6 +626,10 @@ export class DeesHarnessToolCard extends DeesElement {
|
|
|
374
626
|
}
|
|
375
627
|
|
|
376
628
|
@media (prefers-reduced-motion: reduce) {
|
|
629
|
+
.bodyDisclosure {
|
|
630
|
+
transition: none;
|
|
631
|
+
}
|
|
632
|
+
|
|
377
633
|
.harness-card.returnFlash {
|
|
378
634
|
animation: none;
|
|
379
635
|
}
|
|
@@ -400,20 +656,41 @@ export class DeesHarnessToolCard extends DeesElement {
|
|
|
400
656
|
public get isOpen(): boolean {
|
|
401
657
|
if (this.expanded !== undefined) return this.expanded;
|
|
402
658
|
const descriptor = this.descriptor;
|
|
659
|
+
if (descriptor.kind === 'subtask' && this.call.subtask) {
|
|
660
|
+
return this.allowSubtaskStreams
|
|
661
|
+
&& (this.call.subtask.status.type === 'busy' || this.call.subtask.status.type === 'error');
|
|
662
|
+
}
|
|
403
663
|
if (this.call.status === 'error' || this.call.isError) return true;
|
|
404
664
|
if (typeof descriptor.defaultExpanded === 'function') return descriptor.defaultExpanded(this.enrichedCall);
|
|
405
665
|
return descriptor.defaultExpanded ?? false;
|
|
406
666
|
}
|
|
407
667
|
|
|
668
|
+
private get hasSubtaskPreview(): boolean {
|
|
669
|
+
return this.allowSubtaskStreams
|
|
670
|
+
&& this.descriptor.kind === 'subtask'
|
|
671
|
+
&& this.call.subtask !== undefined;
|
|
672
|
+
}
|
|
673
|
+
|
|
674
|
+
private get hasLiveSubtaskPreview(): boolean {
|
|
675
|
+
return this.hasSubtaskPreview && this.call.subtask?.status.type === 'busy';
|
|
676
|
+
}
|
|
677
|
+
|
|
678
|
+
private get activeSubtaskPreview(): boolean {
|
|
679
|
+
return this.hasSubtaskPreview && this.call.subtask?.status.type === 'busy';
|
|
680
|
+
}
|
|
681
|
+
|
|
408
682
|
public render(): TemplateResult {
|
|
409
683
|
const call = this.enrichedCall;
|
|
410
684
|
const descriptor = this.descriptor;
|
|
685
|
+
const open = this.isOpen;
|
|
686
|
+
const renderBody = this.bodyMounted || open;
|
|
411
687
|
const label = typeof descriptor.label === 'function' ? descriptor.label(call) : descriptor.label;
|
|
412
688
|
const subtitle = descriptor.subtitle?.(call) ?? '';
|
|
413
|
-
const
|
|
689
|
+
const effectiveStatus = harnessEffectiveToolStatus(call);
|
|
690
|
+
const statusTone = effectiveStatus === 'completed' ? 'success' : effectiveStatus;
|
|
414
691
|
const duration = harnessFormatDuration(call.startedAt, call.finishedAt);
|
|
415
692
|
return html`
|
|
416
|
-
<div class="harness-card status-${
|
|
693
|
+
<div class="harness-card status-${effectiveStatus} ${descriptor.destructive ? 'destructive' : ''} ${this.hasSubtaskPreview ? 'subtaskPreviewCard' : ''} ${this.hasSubtaskPreview && open ? 'subtaskPreviewOpen' : ''} ${this.returnFlash ? 'returnFlash' : ''} ${this.outcomeScanTone ? `outcomeScan outcomeScan-${this.outcomeScanTone}` : ''}"
|
|
417
694
|
@animationend=${(event: AnimationEvent) => {
|
|
418
695
|
if (event.animationName === 'harness-card-return-flash') {
|
|
419
696
|
this.endReturnFlash();
|
|
@@ -425,10 +702,8 @@ export class DeesHarnessToolCard extends DeesElement {
|
|
|
425
702
|
<button
|
|
426
703
|
class="header"
|
|
427
704
|
type="button"
|
|
428
|
-
aria-expanded=${
|
|
429
|
-
@click=${
|
|
430
|
-
this.expanded = !this.isOpen;
|
|
431
|
-
}}
|
|
705
|
+
aria-expanded=${open ? 'true' : 'false'}
|
|
706
|
+
@click=${this.toggleDisclosure}
|
|
432
707
|
>
|
|
433
708
|
<span class="toolIcon"><dees-icon .icon=${descriptor.icon} iconSize="15"></dees-icon></span>
|
|
434
709
|
<span class="titleBlock">
|
|
@@ -436,7 +711,9 @@ export class DeesHarnessToolCard extends DeesElement {
|
|
|
436
711
|
<span class="toolLabel">${label}</span>
|
|
437
712
|
${this.renderMcpBadges(call)}
|
|
438
713
|
</span>
|
|
439
|
-
${subtitle
|
|
714
|
+
${subtitle
|
|
715
|
+
? html`<dees-harness-overflow-text class="subtitle" title=${subtitle}>${subtitle}</dees-harness-overflow-text>`
|
|
716
|
+
: ''}
|
|
440
717
|
</span>
|
|
441
718
|
<span class="metaColumn">
|
|
442
719
|
${call.startedAt
|
|
@@ -444,34 +721,69 @@ export class DeesHarnessToolCard extends DeesElement {
|
|
|
444
721
|
: ''}
|
|
445
722
|
${duration ? html`<span class="duration">${duration}</span>` : ''}
|
|
446
723
|
<span class="harness-pill tone-${statusTone}">
|
|
447
|
-
${
|
|
724
|
+
${effectiveStatus}
|
|
448
725
|
</span>
|
|
449
726
|
</span>
|
|
450
727
|
</button>
|
|
451
|
-
${
|
|
728
|
+
${renderBody
|
|
452
729
|
? html`
|
|
453
730
|
<div
|
|
454
|
-
class
|
|
455
|
-
|
|
731
|
+
class=${`bodyDisclosure ${open ? 'open' : ''}`}
|
|
732
|
+
aria-hidden=${String(!open)}
|
|
456
733
|
>
|
|
457
|
-
<div class="
|
|
734
|
+
<div class="bodyDisclosureInner" ?inert=${!open}>
|
|
735
|
+
<div
|
|
736
|
+
class="bodyClipFrame"
|
|
737
|
+
style=${this.uncapped || this.activeSubtaskPreview ? '' : `max-height: ${this.bodyCapPx}px;`}
|
|
738
|
+
>
|
|
739
|
+
<div class=${`body bodyInner ${this.hasLiveSubtaskPreview ? 'liveSubtaskBody' : ''}`}>
|
|
740
|
+
${this.renderBody(call)}
|
|
741
|
+
</div>
|
|
742
|
+
</div>
|
|
743
|
+
${this.bodyOverflowing && !this.uncapped && !this.hasSubtaskPreview
|
|
744
|
+
? html`
|
|
745
|
+
<button class="maximizeBar" type="button" @click=${this.openFullscreen}>
|
|
746
|
+
<dees-icon icon="lucide:Maximize2" iconSize="12"></dees-icon>
|
|
747
|
+
Show everything
|
|
748
|
+
</button>
|
|
749
|
+
`
|
|
750
|
+
: ''}
|
|
751
|
+
</div>
|
|
458
752
|
</div>
|
|
459
|
-
${this.bodyOverflowing && !this.uncapped
|
|
460
|
-
? html`
|
|
461
|
-
<button class="maximizeBar" type="button" @click=${this.openFullscreen}>
|
|
462
|
-
<dees-icon icon="lucide:Maximize2" iconSize="12"></dees-icon>
|
|
463
|
-
Show everything
|
|
464
|
-
</button>
|
|
465
|
-
`
|
|
466
|
-
: ''}
|
|
467
753
|
`
|
|
468
754
|
: ''}
|
|
469
755
|
</div>
|
|
470
756
|
`;
|
|
471
757
|
}
|
|
472
758
|
|
|
759
|
+
private readonly toggleDisclosure = (): void => {
|
|
760
|
+
if (this.isOpen) {
|
|
761
|
+
if (this.disclosureFrame !== null) cancelAnimationFrame(this.disclosureFrame);
|
|
762
|
+
this.disclosureFrame = null;
|
|
763
|
+
this.expanded = false;
|
|
764
|
+
return;
|
|
765
|
+
}
|
|
766
|
+
if (this.bodyMounted) {
|
|
767
|
+
if (this.disclosureFrame !== null) cancelAnimationFrame(this.disclosureFrame);
|
|
768
|
+
this.disclosureFrame = null;
|
|
769
|
+
this.expanded = true;
|
|
770
|
+
return;
|
|
771
|
+
}
|
|
772
|
+
this.bodyMounted = true;
|
|
773
|
+
this.expanded = false;
|
|
774
|
+
void this.updateComplete.then(() => {
|
|
775
|
+
if (!this.isConnected || this.expanded !== false) return;
|
|
776
|
+
this.disclosureFrame = requestAnimationFrame(() => {
|
|
777
|
+
this.disclosureFrame = null;
|
|
778
|
+
if (!this.isConnected || this.expanded !== false) return;
|
|
779
|
+
this.shadowRoot?.querySelector<HTMLElement>('.bodyDisclosure')?.getBoundingClientRect();
|
|
780
|
+
this.expanded = true;
|
|
781
|
+
});
|
|
782
|
+
});
|
|
783
|
+
};
|
|
784
|
+
|
|
473
785
|
private readonly openFullscreen = (): void => {
|
|
474
|
-
if (this.fullscreenPortal) return;
|
|
786
|
+
if (this.fullscreenPortal || this.hasSubtaskPreview) return;
|
|
475
787
|
// Appended to document.body: content-visibility containment in the
|
|
476
788
|
// transcript would trap a position: fixed layer inside this card.
|
|
477
789
|
const portal = document.createElement('dees-harness-tool-fullscreen');
|
|
@@ -538,10 +850,12 @@ export class DeesHarnessToolCard extends DeesElement {
|
|
|
538
850
|
super.willUpdate(changedProperties);
|
|
539
851
|
const previousCall = changedProperties.get('call') as IHarnessToolCall | undefined;
|
|
540
852
|
if (!previousCall || previousCall.id !== this.call.id) return;
|
|
541
|
-
const
|
|
542
|
-
const
|
|
853
|
+
const previousStatus = harnessEffectiveToolStatus(previousCall);
|
|
854
|
+
const currentStatus = harnessEffectiveToolStatus(this.call);
|
|
855
|
+
const wasActive = previousStatus === 'pending' || previousStatus === 'running';
|
|
856
|
+
const outcomeTone = currentStatus === 'error'
|
|
543
857
|
? 'error'
|
|
544
|
-
:
|
|
858
|
+
: currentStatus === 'completed'
|
|
545
859
|
? 'success'
|
|
546
860
|
: null;
|
|
547
861
|
if (wasActive && outcomeTone) {
|
|
@@ -553,10 +867,18 @@ export class DeesHarnessToolCard extends DeesElement {
|
|
|
553
867
|
|
|
554
868
|
public updated(changedProperties: Map<PropertyKey, unknown>): void {
|
|
555
869
|
super.updated(changedProperties);
|
|
870
|
+
if (!this.isConnected) return;
|
|
871
|
+
if (this.isOpen && !this.bodyMounted) this.bodyMounted = true;
|
|
556
872
|
if (changedProperties.has('call') && this.fullscreenPortal) {
|
|
557
873
|
this.fullscreenPortal.call = this.enrichedCall;
|
|
558
874
|
}
|
|
559
|
-
|
|
875
|
+
this.connectSubtaskResultScroll();
|
|
876
|
+
if (!this.isOpen || this.uncapped || this.hasSubtaskPreview) {
|
|
877
|
+
this.bodyResizeObserver?.disconnect();
|
|
878
|
+
this.observedBodyInner = null;
|
|
879
|
+
this.bodyOverflowing = false;
|
|
880
|
+
return;
|
|
881
|
+
}
|
|
560
882
|
const bodyInner = this.shadowRoot?.querySelector('.bodyInner') ?? null;
|
|
561
883
|
if (bodyInner === this.observedBodyInner) return;
|
|
562
884
|
this.bodyResizeObserver?.disconnect();
|
|
@@ -574,7 +896,45 @@ export class DeesHarnessToolCard extends DeesElement {
|
|
|
574
896
|
this.bodyResizeObserver.observe(bodyInner);
|
|
575
897
|
}
|
|
576
898
|
|
|
899
|
+
private readonly syncSubtaskResultScroll = (): void => {
|
|
900
|
+
const result = this.subtaskResultElement;
|
|
901
|
+
if (!result) return;
|
|
902
|
+
result.classList.toggle('fadeTop', result.scrollTop > 1);
|
|
903
|
+
result.classList.toggle(
|
|
904
|
+
'fadeBottom',
|
|
905
|
+
result.scrollHeight - result.scrollTop - result.clientHeight > 1,
|
|
906
|
+
);
|
|
907
|
+
};
|
|
908
|
+
|
|
909
|
+
private connectSubtaskResultScroll(): void {
|
|
910
|
+
const nextResult = this.shadowRoot?.querySelector<HTMLElement>(
|
|
911
|
+
'.harness-subtask-detail-result .harness-subtask-detail-text',
|
|
912
|
+
) ?? null;
|
|
913
|
+
if (nextResult === this.subtaskResultElement) {
|
|
914
|
+
this.syncSubtaskResultScroll();
|
|
915
|
+
return;
|
|
916
|
+
}
|
|
917
|
+
this.subtaskResultElement?.removeEventListener('scroll', this.syncSubtaskResultScroll);
|
|
918
|
+
this.subtaskResultResizeObserver?.disconnect();
|
|
919
|
+
this.subtaskResultElement = nextResult;
|
|
920
|
+
if (!nextResult) return;
|
|
921
|
+
nextResult.addEventListener('scroll', this.syncSubtaskResultScroll, { passive: true });
|
|
922
|
+
this.subtaskResultResizeObserver ??= new ResizeObserver(this.syncSubtaskResultScroll);
|
|
923
|
+
this.subtaskResultResizeObserver.observe(nextResult);
|
|
924
|
+
this.syncSubtaskResultScroll();
|
|
925
|
+
}
|
|
926
|
+
|
|
927
|
+
public async connectedCallback(): Promise<void> {
|
|
928
|
+
const connected = super.connectedCallback();
|
|
929
|
+
if (this.hasUpdated) this.requestUpdate();
|
|
930
|
+
await connected;
|
|
931
|
+
}
|
|
932
|
+
|
|
577
933
|
public async disconnectedCallback(): Promise<void> {
|
|
934
|
+
if (this.disclosureFrame !== null) {
|
|
935
|
+
cancelAnimationFrame(this.disclosureFrame);
|
|
936
|
+
this.disclosureFrame = null;
|
|
937
|
+
}
|
|
578
938
|
if (this.flashFallbackTimeout) {
|
|
579
939
|
clearTimeout(this.flashFallbackTimeout);
|
|
580
940
|
this.flashFallbackTimeout = null;
|
|
@@ -588,6 +948,10 @@ export class DeesHarnessToolCard extends DeesElement {
|
|
|
588
948
|
this.bodyResizeObserver?.disconnect();
|
|
589
949
|
this.bodyResizeObserver = null;
|
|
590
950
|
this.observedBodyInner = null;
|
|
951
|
+
this.subtaskResultElement?.removeEventListener('scroll', this.syncSubtaskResultScroll);
|
|
952
|
+
this.subtaskResultElement = null;
|
|
953
|
+
this.subtaskResultResizeObserver?.disconnect();
|
|
954
|
+
this.subtaskResultResizeObserver = null;
|
|
591
955
|
await super.disconnectedCallback();
|
|
592
956
|
}
|
|
593
957
|
|
|
@@ -608,9 +972,95 @@ export class DeesHarnessToolCard extends DeesElement {
|
|
|
608
972
|
private renderBody(call: IHarnessToolCall): TemplateResult {
|
|
609
973
|
const descriptor = this.descriptor;
|
|
610
974
|
const helpers = this.createHelpers();
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
975
|
+
const base = descriptor.renderBody
|
|
976
|
+
? descriptor.renderBody(call, helpers)
|
|
977
|
+
: (builtinBodyRenderers[descriptor.kind] ?? builtinBodyRenderers.unknown)(
|
|
978
|
+
descriptor.kind === 'subtask' && this.hasLiveSubtaskPreview
|
|
979
|
+
? { ...call, output: undefined, errorText: undefined }
|
|
980
|
+
: call,
|
|
981
|
+
helpers,
|
|
982
|
+
);
|
|
983
|
+
const subtaskAction = descriptor.kind === 'subtask'
|
|
984
|
+
? this.renderSubtaskAction(call)
|
|
985
|
+
: html``;
|
|
986
|
+
if (!this.hasLiveSubtaskPreview || !call.subtask) {
|
|
987
|
+
return descriptor.kind === 'subtask' ? html`${base}${subtaskAction}` : base;
|
|
988
|
+
}
|
|
989
|
+
const subtask = call.subtask;
|
|
990
|
+
return html`
|
|
991
|
+
<section class="subtaskPreview" role="region" aria-label="Live subagent transcript">
|
|
992
|
+
${subtask.previewState === 'ready' && (subtask.notice || subtask.truncated)
|
|
993
|
+
? html`<div class="subtaskNotice">${subtask.notice ?? 'Earlier child messages were omitted.'}</div>`
|
|
994
|
+
: ''}
|
|
995
|
+
${subtask.previewState === 'ready'
|
|
996
|
+
? html`
|
|
997
|
+
<dees-harness-message-list
|
|
998
|
+
.messages=${subtask.messages}
|
|
999
|
+
.permissions=${subtask.permissions ?? []}
|
|
1000
|
+
.questions=${subtask.questions ?? []}
|
|
1001
|
+
.status=${subtask.status}
|
|
1002
|
+
.toolRegistry=${this.toolRegistry}
|
|
1003
|
+
.allowSubtaskStreams=${false}
|
|
1004
|
+
.autoFollow=${this.isOpen}
|
|
1005
|
+
.hideScrollbar=${true}
|
|
1006
|
+
.fadeScrollEdges=${true}
|
|
1007
|
+
.showRoles=${true}
|
|
1008
|
+
.showTimestamps=${false}
|
|
1009
|
+
emptyTitle="Waiting for subagent output"
|
|
1010
|
+
emptyText="The child session is active."
|
|
1011
|
+
>
|
|
1012
|
+
<div slot="leading" class="subtaskThreadBrief">${base}</div>
|
|
1013
|
+
</dees-harness-message-list>
|
|
1014
|
+
`
|
|
1015
|
+
: html`
|
|
1016
|
+
<div class="subtaskPreviewState">
|
|
1017
|
+
${base}
|
|
1018
|
+
<dees-harness-status .status=${subtask.status}></dees-harness-status>
|
|
1019
|
+
<span>${subtask.notice ?? (subtask.previewState === 'loading'
|
|
1020
|
+
? 'Loading live subagent transcript…'
|
|
1021
|
+
: 'Live preview unavailable. Open the subagent chat to follow it.')}</span>
|
|
1022
|
+
</div>
|
|
1023
|
+
`}
|
|
1024
|
+
</section>
|
|
1025
|
+
${subtaskAction}
|
|
1026
|
+
`;
|
|
1027
|
+
}
|
|
1028
|
+
|
|
1029
|
+
private renderSubtaskAction(callArg: IHarnessToolCall): TemplateResult {
|
|
1030
|
+
const childSessionId = callArg.subtask?.sessionId ?? callArg.childSessionId;
|
|
1031
|
+
if (!childSessionId) return html``;
|
|
1032
|
+
return html`
|
|
1033
|
+
<button
|
|
1034
|
+
class="harness-subtask-open"
|
|
1035
|
+
type="button"
|
|
1036
|
+
@click=${() => {
|
|
1037
|
+
this.dispatchEvent(new CustomEvent('harness-subtask-open', {
|
|
1038
|
+
detail: { sessionId: childSessionId, call: callArg },
|
|
1039
|
+
bubbles: true,
|
|
1040
|
+
composed: true,
|
|
1041
|
+
}));
|
|
1042
|
+
}}
|
|
1043
|
+
>
|
|
1044
|
+
${(callArg.subtask
|
|
1045
|
+
? callArg.subtask.status.type !== 'busy'
|
|
1046
|
+
: callArg.status === 'completed' || callArg.status === 'error')
|
|
1047
|
+
? 'Open subagent chat'
|
|
1048
|
+
: 'Follow subagent live'}
|
|
1049
|
+
</button>
|
|
1050
|
+
`;
|
|
1051
|
+
}
|
|
1052
|
+
|
|
1053
|
+
public applySubtaskDelta(delta: THarnessMessageStreamDelta): boolean {
|
|
1054
|
+
if (!this.allowSubtaskStreams || this.call.subtask?.previewState !== 'ready') return false;
|
|
1055
|
+
if (!this.call.subtask.messages.some((message) => message.id === delta.messageId)) return false;
|
|
1056
|
+
const list = this.shadowRoot?.querySelector('.subtaskPreview > dees-harness-message-list');
|
|
1057
|
+
if (list instanceof DeesHarnessMessageList) {
|
|
1058
|
+
list.applyDelta(delta);
|
|
1059
|
+
return true;
|
|
1060
|
+
}
|
|
1061
|
+
if (!harnessApplyMessageDelta(this.call.subtask.messages, delta)) return false;
|
|
1062
|
+
this.requestUpdate();
|
|
1063
|
+
return true;
|
|
614
1064
|
}
|
|
615
1065
|
|
|
616
1066
|
private createHelpers(): IHarnessToolRenderHelpers {
|