@design.estate/dees-catalog 6.1.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 +3097 -1497
- 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 +476 -36
- package/dist_ts_web/elements/00group-harness/dees-harness-tool-card/renderers.js +23 -20
- 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 +31 -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 +480 -34
- package/ts_web/elements/00group-harness/dees-harness-tool-card/renderers.ts +24 -21
- 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 +36 -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;
|
|
@@ -378,6 +626,10 @@ export class DeesHarnessToolCard extends DeesElement {
|
|
|
378
626
|
}
|
|
379
627
|
|
|
380
628
|
@media (prefers-reduced-motion: reduce) {
|
|
629
|
+
.bodyDisclosure {
|
|
630
|
+
transition: none;
|
|
631
|
+
}
|
|
632
|
+
|
|
381
633
|
.harness-card.returnFlash {
|
|
382
634
|
animation: none;
|
|
383
635
|
}
|
|
@@ -404,20 +656,41 @@ export class DeesHarnessToolCard extends DeesElement {
|
|
|
404
656
|
public get isOpen(): boolean {
|
|
405
657
|
if (this.expanded !== undefined) return this.expanded;
|
|
406
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
|
+
}
|
|
407
663
|
if (this.call.status === 'error' || this.call.isError) return true;
|
|
408
664
|
if (typeof descriptor.defaultExpanded === 'function') return descriptor.defaultExpanded(this.enrichedCall);
|
|
409
665
|
return descriptor.defaultExpanded ?? false;
|
|
410
666
|
}
|
|
411
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
|
+
|
|
412
682
|
public render(): TemplateResult {
|
|
413
683
|
const call = this.enrichedCall;
|
|
414
684
|
const descriptor = this.descriptor;
|
|
685
|
+
const open = this.isOpen;
|
|
686
|
+
const renderBody = this.bodyMounted || open;
|
|
415
687
|
const label = typeof descriptor.label === 'function' ? descriptor.label(call) : descriptor.label;
|
|
416
688
|
const subtitle = descriptor.subtitle?.(call) ?? '';
|
|
417
|
-
const
|
|
689
|
+
const effectiveStatus = harnessEffectiveToolStatus(call);
|
|
690
|
+
const statusTone = effectiveStatus === 'completed' ? 'success' : effectiveStatus;
|
|
418
691
|
const duration = harnessFormatDuration(call.startedAt, call.finishedAt);
|
|
419
692
|
return html`
|
|
420
|
-
<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}` : ''}"
|
|
421
694
|
@animationend=${(event: AnimationEvent) => {
|
|
422
695
|
if (event.animationName === 'harness-card-return-flash') {
|
|
423
696
|
this.endReturnFlash();
|
|
@@ -429,10 +702,8 @@ export class DeesHarnessToolCard extends DeesElement {
|
|
|
429
702
|
<button
|
|
430
703
|
class="header"
|
|
431
704
|
type="button"
|
|
432
|
-
aria-expanded=${
|
|
433
|
-
@click=${
|
|
434
|
-
this.expanded = !this.isOpen;
|
|
435
|
-
}}
|
|
705
|
+
aria-expanded=${open ? 'true' : 'false'}
|
|
706
|
+
@click=${this.toggleDisclosure}
|
|
436
707
|
>
|
|
437
708
|
<span class="toolIcon"><dees-icon .icon=${descriptor.icon} iconSize="15"></dees-icon></span>
|
|
438
709
|
<span class="titleBlock">
|
|
@@ -440,7 +711,9 @@ export class DeesHarnessToolCard extends DeesElement {
|
|
|
440
711
|
<span class="toolLabel">${label}</span>
|
|
441
712
|
${this.renderMcpBadges(call)}
|
|
442
713
|
</span>
|
|
443
|
-
${subtitle
|
|
714
|
+
${subtitle
|
|
715
|
+
? html`<dees-harness-overflow-text class="subtitle" title=${subtitle}>${subtitle}</dees-harness-overflow-text>`
|
|
716
|
+
: ''}
|
|
444
717
|
</span>
|
|
445
718
|
<span class="metaColumn">
|
|
446
719
|
${call.startedAt
|
|
@@ -448,34 +721,69 @@ export class DeesHarnessToolCard extends DeesElement {
|
|
|
448
721
|
: ''}
|
|
449
722
|
${duration ? html`<span class="duration">${duration}</span>` : ''}
|
|
450
723
|
<span class="harness-pill tone-${statusTone}">
|
|
451
|
-
${
|
|
724
|
+
${effectiveStatus}
|
|
452
725
|
</span>
|
|
453
726
|
</span>
|
|
454
727
|
</button>
|
|
455
|
-
${
|
|
728
|
+
${renderBody
|
|
456
729
|
? html`
|
|
457
730
|
<div
|
|
458
|
-
class
|
|
459
|
-
|
|
731
|
+
class=${`bodyDisclosure ${open ? 'open' : ''}`}
|
|
732
|
+
aria-hidden=${String(!open)}
|
|
460
733
|
>
|
|
461
|
-
<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>
|
|
462
752
|
</div>
|
|
463
|
-
${this.bodyOverflowing && !this.uncapped
|
|
464
|
-
? html`
|
|
465
|
-
<button class="maximizeBar" type="button" @click=${this.openFullscreen}>
|
|
466
|
-
<dees-icon icon="lucide:Maximize2" iconSize="12"></dees-icon>
|
|
467
|
-
Show everything
|
|
468
|
-
</button>
|
|
469
|
-
`
|
|
470
|
-
: ''}
|
|
471
753
|
`
|
|
472
754
|
: ''}
|
|
473
755
|
</div>
|
|
474
756
|
`;
|
|
475
757
|
}
|
|
476
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
|
+
|
|
477
785
|
private readonly openFullscreen = (): void => {
|
|
478
|
-
if (this.fullscreenPortal) return;
|
|
786
|
+
if (this.fullscreenPortal || this.hasSubtaskPreview) return;
|
|
479
787
|
// Appended to document.body: content-visibility containment in the
|
|
480
788
|
// transcript would trap a position: fixed layer inside this card.
|
|
481
789
|
const portal = document.createElement('dees-harness-tool-fullscreen');
|
|
@@ -542,10 +850,12 @@ export class DeesHarnessToolCard extends DeesElement {
|
|
|
542
850
|
super.willUpdate(changedProperties);
|
|
543
851
|
const previousCall = changedProperties.get('call') as IHarnessToolCall | undefined;
|
|
544
852
|
if (!previousCall || previousCall.id !== this.call.id) return;
|
|
545
|
-
const
|
|
546
|
-
const
|
|
853
|
+
const previousStatus = harnessEffectiveToolStatus(previousCall);
|
|
854
|
+
const currentStatus = harnessEffectiveToolStatus(this.call);
|
|
855
|
+
const wasActive = previousStatus === 'pending' || previousStatus === 'running';
|
|
856
|
+
const outcomeTone = currentStatus === 'error'
|
|
547
857
|
? 'error'
|
|
548
|
-
:
|
|
858
|
+
: currentStatus === 'completed'
|
|
549
859
|
? 'success'
|
|
550
860
|
: null;
|
|
551
861
|
if (wasActive && outcomeTone) {
|
|
@@ -557,10 +867,18 @@ export class DeesHarnessToolCard extends DeesElement {
|
|
|
557
867
|
|
|
558
868
|
public updated(changedProperties: Map<PropertyKey, unknown>): void {
|
|
559
869
|
super.updated(changedProperties);
|
|
870
|
+
if (!this.isConnected) return;
|
|
871
|
+
if (this.isOpen && !this.bodyMounted) this.bodyMounted = true;
|
|
560
872
|
if (changedProperties.has('call') && this.fullscreenPortal) {
|
|
561
873
|
this.fullscreenPortal.call = this.enrichedCall;
|
|
562
874
|
}
|
|
563
|
-
|
|
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
|
+
}
|
|
564
882
|
const bodyInner = this.shadowRoot?.querySelector('.bodyInner') ?? null;
|
|
565
883
|
if (bodyInner === this.observedBodyInner) return;
|
|
566
884
|
this.bodyResizeObserver?.disconnect();
|
|
@@ -578,7 +896,45 @@ export class DeesHarnessToolCard extends DeesElement {
|
|
|
578
896
|
this.bodyResizeObserver.observe(bodyInner);
|
|
579
897
|
}
|
|
580
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
|
+
|
|
581
933
|
public async disconnectedCallback(): Promise<void> {
|
|
934
|
+
if (this.disclosureFrame !== null) {
|
|
935
|
+
cancelAnimationFrame(this.disclosureFrame);
|
|
936
|
+
this.disclosureFrame = null;
|
|
937
|
+
}
|
|
582
938
|
if (this.flashFallbackTimeout) {
|
|
583
939
|
clearTimeout(this.flashFallbackTimeout);
|
|
584
940
|
this.flashFallbackTimeout = null;
|
|
@@ -592,6 +948,10 @@ export class DeesHarnessToolCard extends DeesElement {
|
|
|
592
948
|
this.bodyResizeObserver?.disconnect();
|
|
593
949
|
this.bodyResizeObserver = null;
|
|
594
950
|
this.observedBodyInner = null;
|
|
951
|
+
this.subtaskResultElement?.removeEventListener('scroll', this.syncSubtaskResultScroll);
|
|
952
|
+
this.subtaskResultElement = null;
|
|
953
|
+
this.subtaskResultResizeObserver?.disconnect();
|
|
954
|
+
this.subtaskResultResizeObserver = null;
|
|
595
955
|
await super.disconnectedCallback();
|
|
596
956
|
}
|
|
597
957
|
|
|
@@ -612,9 +972,95 @@ export class DeesHarnessToolCard extends DeesElement {
|
|
|
612
972
|
private renderBody(call: IHarnessToolCall): TemplateResult {
|
|
613
973
|
const descriptor = this.descriptor;
|
|
614
974
|
const helpers = this.createHelpers();
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
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;
|
|
618
1064
|
}
|
|
619
1065
|
|
|
620
1066
|
private createHelpers(): IHarnessToolRenderHelpers {
|