@design.estate/dees-catalog 5.0.0 → 6.0.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 +518 -131
- 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 +7 -2
- package/dist_ts_web/elements/00group-harness/dees-harness-chat/dees-harness-chat.demo.js +1 -2
- package/dist_ts_web/elements/00group-harness/dees-harness-chat/dees-harness-chat.js +110 -26
- package/dist_ts_web/elements/00group-harness/dees-harness-session-sidebar/dees-harness-session-sidebar.d.ts +5 -0
- package/dist_ts_web/elements/00group-harness/dees-harness-session-sidebar/dees-harness-session-sidebar.js +287 -66
- package/dist_ts_web/elements/00group-harness/dees-harness-tool-card/dees-harness-tool-card.d.ts +5 -0
- package/dist_ts_web/elements/00group-harness/dees-harness-tool-card/dees-harness-tool-card.js +87 -3
- package/dist_ts_web/elements/00group-harness/harness.styles.js +23 -4
- package/package.json +1 -1
- package/readme.md +5 -3
- package/ts_web/00_commitinfo_data.ts +1 -1
- package/ts_web/elements/00group-harness/dees-harness-chat/dees-harness-chat.demo.ts +0 -1
- package/ts_web/elements/00group-harness/dees-harness-chat/dees-harness-chat.ts +101 -25
- package/ts_web/elements/00group-harness/dees-harness-session-sidebar/dees-harness-session-sidebar.ts +318 -73
- package/ts_web/elements/00group-harness/dees-harness-tool-card/dees-harness-tool-card.ts +79 -1
- package/ts_web/elements/00group-harness/harness.styles.ts +22 -3
package/ts_web/elements/00group-harness/dees-harness-session-sidebar/dees-harness-session-sidebar.ts
CHANGED
|
@@ -26,6 +26,7 @@ import '../../00group-utility/dees-icon/dees-icon.js';
|
|
|
26
26
|
const { repeat } = directives;
|
|
27
27
|
|
|
28
28
|
const formatTokenCount = (valueArg: number): string => valueArg.toLocaleString('en-US');
|
|
29
|
+
type TSessionSidebarSection = 'tasks' | 'metrics' | 'scratchpad' | 'intelligence';
|
|
29
30
|
|
|
30
31
|
declare global {
|
|
31
32
|
interface HTMLElementTagNameMap {
|
|
@@ -90,13 +91,20 @@ export class DeesHarnessSessionSidebar extends DeesElement {
|
|
|
90
91
|
@state()
|
|
91
92
|
private accessor intelligenceQuestion: string = '';
|
|
92
93
|
|
|
94
|
+
@state()
|
|
95
|
+
private accessor expandedSection: TSessionSidebarSection | undefined = undefined;
|
|
96
|
+
|
|
97
|
+
private sectionStateInitialized = false;
|
|
98
|
+
|
|
93
99
|
public static styles = [
|
|
94
100
|
themeDefaultStyles,
|
|
95
101
|
cssManager.defaultStyles,
|
|
96
102
|
css`
|
|
97
103
|
:host {
|
|
98
|
-
display:
|
|
104
|
+
display: flex;
|
|
105
|
+
flex-direction: column;
|
|
99
106
|
min-width: 0;
|
|
107
|
+
min-height: 0;
|
|
100
108
|
height: 100%;
|
|
101
109
|
font-family: var(--dees-font-family);
|
|
102
110
|
color: var(--dees-color-text-primary);
|
|
@@ -105,32 +113,206 @@ export class DeesHarnessSessionSidebar extends DeesElement {
|
|
|
105
113
|
.sidebar {
|
|
106
114
|
display: flex;
|
|
107
115
|
flex-direction: column;
|
|
108
|
-
min-height:
|
|
116
|
+
min-height: 0;
|
|
117
|
+
height: 100%;
|
|
118
|
+
overflow: hidden;
|
|
109
119
|
}
|
|
110
120
|
|
|
111
121
|
.section {
|
|
112
|
-
|
|
122
|
+
display: flex;
|
|
123
|
+
flex: 0 0 auto;
|
|
124
|
+
flex-direction: column;
|
|
125
|
+
min-height: 0;
|
|
126
|
+
overflow: hidden;
|
|
113
127
|
border-bottom: 1px solid var(--dees-color-border-subtle);
|
|
114
128
|
}
|
|
115
129
|
|
|
130
|
+
.section.expanded {
|
|
131
|
+
flex: 1 1 0;
|
|
132
|
+
}
|
|
133
|
+
|
|
116
134
|
.section:last-child {
|
|
117
135
|
border-bottom: 0;
|
|
118
136
|
}
|
|
119
137
|
|
|
120
138
|
.sectionHeading {
|
|
121
139
|
display: flex;
|
|
140
|
+
flex: 0 0 auto;
|
|
122
141
|
align-items: center;
|
|
123
142
|
gap: var(--dees-spacing-xs);
|
|
124
|
-
|
|
143
|
+
width: 100%;
|
|
144
|
+
min-height: 30px;
|
|
145
|
+
margin: 0;
|
|
146
|
+
padding: 6px var(--dees-spacing-md) 6px var(--dees-spacing-xs);
|
|
147
|
+
border: 0;
|
|
148
|
+
background: var(--dees-color-bg-secondary);
|
|
125
149
|
color: var(--dees-color-text-primary);
|
|
150
|
+
font-family: inherit;
|
|
126
151
|
font-size: var(--dees-font-control-size-sm, 12px);
|
|
127
152
|
font-weight: 650;
|
|
153
|
+
text-align: left;
|
|
154
|
+
cursor: pointer;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
.sectionHeading:hover {
|
|
158
|
+
background: var(--dees-color-badge-default-bg);
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
.sectionHeading:focus-visible {
|
|
162
|
+
position: relative;
|
|
163
|
+
z-index: 1;
|
|
164
|
+
outline: 2px solid var(--dees-color-accent-primary);
|
|
165
|
+
outline-offset: -2px;
|
|
128
166
|
}
|
|
129
167
|
|
|
130
168
|
.sectionHeading dees-icon {
|
|
169
|
+
flex: 0 0 auto;
|
|
131
170
|
color: var(--dees-color-text-secondary);
|
|
132
171
|
}
|
|
133
172
|
|
|
173
|
+
.sectionHeadingText {
|
|
174
|
+
min-width: 0;
|
|
175
|
+
overflow: hidden;
|
|
176
|
+
text-overflow: ellipsis;
|
|
177
|
+
white-space: nowrap;
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
.sectionSummary {
|
|
181
|
+
flex: 0 0 auto;
|
|
182
|
+
margin-left: auto;
|
|
183
|
+
color: var(--dees-color-text-muted);
|
|
184
|
+
font-size: var(--dees-font-caption2-size, 10px);
|
|
185
|
+
font-variant-numeric: tabular-nums;
|
|
186
|
+
font-weight: 500;
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
.sectionContent {
|
|
190
|
+
flex: 1;
|
|
191
|
+
min-height: 0;
|
|
192
|
+
overflow-x: hidden;
|
|
193
|
+
overflow-y: auto;
|
|
194
|
+
padding: var(--dees-spacing-sm) var(--dees-spacing-md);
|
|
195
|
+
scrollbar-width: thin;
|
|
196
|
+
scrollbar-color: var(--dees-color-scrollbar-thumb) transparent;
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
.sectionContent[hidden] {
|
|
200
|
+
display: none;
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
.sectionContent dees-harness-todos {
|
|
204
|
+
min-width: 0;
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
.scratchpadSection .sectionContent:not([hidden]) {
|
|
208
|
+
display: flex;
|
|
209
|
+
flex-direction: column;
|
|
210
|
+
overflow: hidden;
|
|
211
|
+
padding: 0;
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
.scratchpadSection textarea {
|
|
215
|
+
flex: 1;
|
|
216
|
+
min-height: 0;
|
|
217
|
+
resize: none;
|
|
218
|
+
overflow-y: auto;
|
|
219
|
+
padding: var(--dees-spacing-sm) var(--dees-spacing-md);
|
|
220
|
+
border: 0;
|
|
221
|
+
border-radius: 0;
|
|
222
|
+
background: color-mix(in srgb, var(--dees-color-bg-secondary) 92%, black);
|
|
223
|
+
color: var(--dees-color-text-secondary);
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
.scratchpadSection textarea:focus-visible {
|
|
227
|
+
border-color: transparent;
|
|
228
|
+
background: color-mix(in srgb, var(--dees-color-bg-secondary) 92%, black);
|
|
229
|
+
box-shadow: none;
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
.scratchpadSection .conflict,
|
|
233
|
+
.scratchpadSection .error {
|
|
234
|
+
margin-right: var(--dees-spacing-md);
|
|
235
|
+
margin-left: var(--dees-spacing-md);
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
.scratchpadFooter {
|
|
239
|
+
display: flex;
|
|
240
|
+
flex: 0 0 auto;
|
|
241
|
+
align-items: center;
|
|
242
|
+
justify-content: space-between;
|
|
243
|
+
gap: var(--dees-spacing-sm);
|
|
244
|
+
padding: var(--dees-spacing-xs) var(--dees-spacing-md) var(--dees-spacing-sm);
|
|
245
|
+
border-top: 0;
|
|
246
|
+
background: linear-gradient(
|
|
247
|
+
to bottom,
|
|
248
|
+
color-mix(in srgb, var(--dees-color-bg-secondary) 92%, black),
|
|
249
|
+
var(--dees-color-bg-secondary)
|
|
250
|
+
);
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
.scratchpadFooter .editorMeta {
|
|
254
|
+
margin-top: 0;
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
.intelligenceSection .sectionContent:not([hidden]) {
|
|
258
|
+
display: flex;
|
|
259
|
+
flex-direction: column;
|
|
260
|
+
overflow: hidden;
|
|
261
|
+
padding: 0;
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
.intelligenceHistory {
|
|
265
|
+
flex: 1;
|
|
266
|
+
min-height: 0;
|
|
267
|
+
overflow-x: hidden;
|
|
268
|
+
overflow-y: auto;
|
|
269
|
+
padding: var(--dees-spacing-sm) var(--dees-spacing-md);
|
|
270
|
+
scrollbar-width: thin;
|
|
271
|
+
scrollbar-color: var(--dees-color-scrollbar-thumb) transparent;
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
.intelligenceComposer {
|
|
275
|
+
flex: 0 0 auto;
|
|
276
|
+
padding: var(--dees-spacing-sm) var(--dees-spacing-md) var(--dees-spacing-md);
|
|
277
|
+
background: linear-gradient(
|
|
278
|
+
to bottom,
|
|
279
|
+
var(--dees-color-bg-primary),
|
|
280
|
+
var(--dees-color-bg-secondary)
|
|
281
|
+
);
|
|
282
|
+
box-shadow: var(--dees-shadow-up-sm);
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
.intelligenceComposer textarea {
|
|
286
|
+
min-height: 64px;
|
|
287
|
+
max-height: 160px;
|
|
288
|
+
resize: none;
|
|
289
|
+
padding: var(--dees-spacing-sm) 0;
|
|
290
|
+
border: 0;
|
|
291
|
+
border-radius: 0;
|
|
292
|
+
background: transparent;
|
|
293
|
+
color: var(--dees-color-text-primary);
|
|
294
|
+
font-family: inherit;
|
|
295
|
+
font-size: var(--dees-font-control-size, 13px);
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
.intelligenceComposer textarea:focus-visible {
|
|
299
|
+
border-color: transparent;
|
|
300
|
+
box-shadow: none;
|
|
301
|
+
outline: 2px solid color-mix(in srgb, var(--dees-color-accent-primary) 55%, transparent);
|
|
302
|
+
outline-offset: 2px;
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
.intelligenceControls {
|
|
306
|
+
display: flex;
|
|
307
|
+
align-items: center;
|
|
308
|
+
gap: var(--dees-spacing-sm);
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
.intelligenceControls .hint {
|
|
312
|
+
flex: 1;
|
|
313
|
+
min-width: 0;
|
|
314
|
+
}
|
|
315
|
+
|
|
134
316
|
.metricList {
|
|
135
317
|
display: grid;
|
|
136
318
|
gap: 6px;
|
|
@@ -281,6 +463,16 @@ export class DeesHarnessSessionSidebar extends DeesElement {
|
|
|
281
463
|
];
|
|
282
464
|
|
|
283
465
|
protected willUpdate(changedPropertiesArg: Map<PropertyKey, unknown>): void {
|
|
466
|
+
const availableSections = this.availableSections;
|
|
467
|
+
if (!this.sectionStateInitialized && availableSections.length > 0) {
|
|
468
|
+
this.expandedSection = this.defaultExpandedSection;
|
|
469
|
+
this.sectionStateInitialized = true;
|
|
470
|
+
} else if (
|
|
471
|
+
this.expandedSection !== undefined
|
|
472
|
+
&& !availableSections.includes(this.expandedSection)
|
|
473
|
+
) {
|
|
474
|
+
this.expandedSection = this.defaultExpandedSection;
|
|
475
|
+
}
|
|
284
476
|
if (!changedPropertiesArg.has('scratchpad')) return;
|
|
285
477
|
const next = this.scratchpad;
|
|
286
478
|
if (!next) {
|
|
@@ -324,14 +516,70 @@ export class DeesHarnessSessionSidebar extends DeesElement {
|
|
|
324
516
|
return Object.values(this.metrics).some((value) => value !== undefined);
|
|
325
517
|
}
|
|
326
518
|
|
|
327
|
-
private
|
|
519
|
+
private get availableSections(): TSessionSidebarSection[] {
|
|
520
|
+
return [
|
|
521
|
+
...(this.showTasks ? ['tasks' as const] : []),
|
|
522
|
+
...(this.hasMetrics ? ['metrics' as const] : []),
|
|
523
|
+
...(this.scratchpad ? ['scratchpad' as const] : []),
|
|
524
|
+
...(this.intelligenceEnabled ? ['intelligence' as const] : []),
|
|
525
|
+
];
|
|
526
|
+
}
|
|
527
|
+
|
|
528
|
+
private get defaultExpandedSection(): TSessionSidebarSection | undefined {
|
|
529
|
+
if (this.showTasks && this.todos.length > 0) return 'tasks';
|
|
530
|
+
if (this.hasMetrics) return 'metrics';
|
|
531
|
+
if (this.scratchpad) return 'scratchpad';
|
|
532
|
+
if (this.intelligenceEnabled) return 'intelligence';
|
|
533
|
+
return this.showTasks ? 'tasks' : undefined;
|
|
534
|
+
}
|
|
535
|
+
|
|
536
|
+
private renderSection(
|
|
537
|
+
idArg: TSessionSidebarSection,
|
|
538
|
+
labelArg: string,
|
|
539
|
+
iconArg: string,
|
|
540
|
+
contentArg: TemplateResult,
|
|
541
|
+
summaryArg = '',
|
|
542
|
+
): TemplateResult {
|
|
543
|
+
const expanded = this.expandedSection === idArg;
|
|
544
|
+
const contentId = `harness-session-section-${idArg}`;
|
|
328
545
|
return html`
|
|
329
|
-
<section class
|
|
330
|
-
<
|
|
546
|
+
<section class=${`section ${idArg}Section ${expanded ? 'expanded' : ''}`}>
|
|
547
|
+
<button
|
|
548
|
+
class="sectionHeading"
|
|
549
|
+
type="button"
|
|
550
|
+
aria-expanded=${String(expanded)}
|
|
551
|
+
aria-controls=${contentId}
|
|
552
|
+
@click=${() => {
|
|
553
|
+
this.sectionStateInitialized = true;
|
|
554
|
+
this.expandedSection = expanded ? undefined : idArg;
|
|
555
|
+
}}
|
|
556
|
+
>
|
|
557
|
+
<dees-icon
|
|
558
|
+
icon=${expanded ? 'lucide:ChevronDown' : 'lucide:ChevronRight'}
|
|
559
|
+
iconSize="13"
|
|
560
|
+
></dees-icon>
|
|
561
|
+
<dees-icon icon=${iconArg} iconSize="13"></dees-icon>
|
|
562
|
+
<span class="sectionHeadingText">${labelArg}</span>
|
|
563
|
+
${summaryArg ? html`<span class="sectionSummary">${summaryArg}</span>` : ''}
|
|
564
|
+
</button>
|
|
565
|
+
<div id=${contentId} class="sectionContent" ?hidden=${!expanded}>
|
|
566
|
+
${contentArg}
|
|
567
|
+
</div>
|
|
331
568
|
</section>
|
|
332
569
|
`;
|
|
333
570
|
}
|
|
334
571
|
|
|
572
|
+
private renderTasks(): TemplateResult {
|
|
573
|
+
const completed = this.todos.filter((todo) => todo.status === 'completed').length;
|
|
574
|
+
return this.renderSection(
|
|
575
|
+
'tasks',
|
|
576
|
+
'Tasks',
|
|
577
|
+
'lucide:ListChecks',
|
|
578
|
+
html`<dees-harness-todos .todos=${this.todos} .showProgress=${false}></dees-harness-todos>`,
|
|
579
|
+
this.todos.length > 0 ? `${completed}/${this.todos.length}` : '',
|
|
580
|
+
);
|
|
581
|
+
}
|
|
582
|
+
|
|
335
583
|
private renderMetrics(): TemplateResult {
|
|
336
584
|
const metrics = this.metrics;
|
|
337
585
|
const percentage = this.contextPercentage;
|
|
@@ -342,12 +590,11 @@ export class DeesHarnessSessionSidebar extends DeesElement {
|
|
|
342
590
|
['Context window', metrics.maxContextTokens],
|
|
343
591
|
['Current context', metrics.currentContextTokens],
|
|
344
592
|
];
|
|
345
|
-
return
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
</div>
|
|
593
|
+
return this.renderSection(
|
|
594
|
+
'metrics',
|
|
595
|
+
'Tokens',
|
|
596
|
+
'lucide:Gauge',
|
|
597
|
+
html`
|
|
351
598
|
<div class="metricList">
|
|
352
599
|
${rows.map(([label, value]) => value === undefined ? '' : html`
|
|
353
600
|
<div class="metricRow">
|
|
@@ -372,19 +619,17 @@ export class DeesHarnessSessionSidebar extends DeesElement {
|
|
|
372
619
|
</div>
|
|
373
620
|
`}
|
|
374
621
|
</div>
|
|
375
|
-
|
|
376
|
-
|
|
622
|
+
`,
|
|
623
|
+
);
|
|
377
624
|
}
|
|
378
625
|
|
|
379
626
|
private renderScratchpad(): TemplateResult {
|
|
380
627
|
const scratchpad = this.scratchpad!;
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
<span>Session Scratchpad</span>
|
|
387
|
-
</div>
|
|
628
|
+
return this.renderSection(
|
|
629
|
+
'scratchpad',
|
|
630
|
+
'Session Scratchpad',
|
|
631
|
+
'lucide:NotebookPen',
|
|
632
|
+
html`
|
|
388
633
|
<textarea
|
|
389
634
|
aria-label="Session scratchpad"
|
|
390
635
|
maxlength="32768"
|
|
@@ -401,11 +646,6 @@ export class DeesHarnessSessionSidebar extends DeesElement {
|
|
|
401
646
|
}
|
|
402
647
|
}}
|
|
403
648
|
></textarea>
|
|
404
|
-
<div class="editorMeta">
|
|
405
|
-
Revision ${scratchpad.revision}${scratchpad.updatedAt
|
|
406
|
-
? ` · updated by ${updatedBy} ${new Date(scratchpad.updatedAt).toLocaleString()}`
|
|
407
|
-
: ''}
|
|
408
|
-
</div>
|
|
409
649
|
${this.scratchpadStale ? html`
|
|
410
650
|
<div class="conflict" role="status">
|
|
411
651
|
A newer revision arrived. Keep this draft on the latest revision or discard it.
|
|
@@ -426,7 +666,8 @@ export class DeesHarnessSessionSidebar extends DeesElement {
|
|
|
426
666
|
</div>
|
|
427
667
|
` : ''}
|
|
428
668
|
${this.scratchpadError ? html`<div class="error" role="alert">${this.scratchpadError}</div>` : ''}
|
|
429
|
-
<div class="
|
|
669
|
+
<div class="scratchpadFooter">
|
|
670
|
+
<span class="editorMeta">rev. ${scratchpad.revision}</span>
|
|
430
671
|
<dees-button
|
|
431
672
|
size="sm"
|
|
432
673
|
type="accent"
|
|
@@ -436,57 +677,61 @@ export class DeesHarnessSessionSidebar extends DeesElement {
|
|
|
436
677
|
@clicked=${this.saveScratchpad}
|
|
437
678
|
></dees-button>
|
|
438
679
|
</div>
|
|
439
|
-
|
|
440
|
-
|
|
680
|
+
`,
|
|
681
|
+
);
|
|
441
682
|
}
|
|
442
683
|
|
|
443
684
|
private renderIntelligence(): TemplateResult {
|
|
444
|
-
return
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
685
|
+
return this.renderSection(
|
|
686
|
+
'intelligence',
|
|
687
|
+
'Session Intelligence',
|
|
688
|
+
'lucide:Sparkles',
|
|
689
|
+
html`
|
|
690
|
+
<div class="intelligenceHistory" role="log" aria-live="polite">
|
|
691
|
+
${this.intelligenceExchanges.length ? html`
|
|
692
|
+
<div class="exchangeList">
|
|
693
|
+
${repeat(
|
|
694
|
+
this.intelligenceExchanges,
|
|
695
|
+
(exchange) => exchange.id,
|
|
696
|
+
(exchange) => this.renderExchange(exchange),
|
|
697
|
+
)}
|
|
698
|
+
</div>
|
|
699
|
+
` : html`<div class="empty">Ask about this session without interrupting its main work.</div>`}
|
|
449
700
|
</div>
|
|
450
|
-
|
|
451
|
-
<
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
701
|
+
<div class="intelligenceComposer">
|
|
702
|
+
<textarea
|
|
703
|
+
class="intelligenceInput"
|
|
704
|
+
aria-label="Ask Session Intelligence"
|
|
705
|
+
placeholder="Ask a parallel question…"
|
|
706
|
+
maxlength="8192"
|
|
707
|
+
rows="2"
|
|
708
|
+
.value=${this.intelligenceQuestion}
|
|
709
|
+
?disabled=${this.disabled || this.intelligenceBusy}
|
|
710
|
+
@input=${(event: InputEvent) => {
|
|
711
|
+
this.intelligenceQuestion = (event.currentTarget as HTMLTextAreaElement).value;
|
|
712
|
+
}}
|
|
713
|
+
@keydown=${(event: KeyboardEvent) => {
|
|
714
|
+
if (event.key === 'Enter' && (event.metaKey || event.ctrlKey)) {
|
|
715
|
+
event.preventDefault();
|
|
716
|
+
this.askIntelligence();
|
|
717
|
+
}
|
|
718
|
+
}}
|
|
719
|
+
></textarea>
|
|
720
|
+
<div class="intelligenceControls">
|
|
721
|
+
<span class="hint">Parallel session · Ctrl/⌘ + Enter</span>
|
|
722
|
+
<dees-button
|
|
723
|
+
size="sm"
|
|
724
|
+
type="accent"
|
|
725
|
+
text="Ask"
|
|
726
|
+
.status=${this.intelligenceBusy ? 'pending' : 'normal'}
|
|
727
|
+
?disabled=${this.disabled || this.intelligenceBusy || !this.intelligenceQuestion.trim()}
|
|
728
|
+
@clicked=${this.askIntelligence}
|
|
729
|
+
></dees-button>
|
|
457
730
|
</div>
|
|
458
|
-
|
|
459
|
-
<textarea
|
|
460
|
-
class="intelligenceInput"
|
|
461
|
-
aria-label="Ask Session Intelligence"
|
|
462
|
-
placeholder="Ask a parallel question…"
|
|
463
|
-
maxlength="8192"
|
|
464
|
-
.value=${this.intelligenceQuestion}
|
|
465
|
-
?disabled=${this.disabled || this.intelligenceBusy}
|
|
466
|
-
@input=${(event: InputEvent) => {
|
|
467
|
-
this.intelligenceQuestion = (event.currentTarget as HTMLTextAreaElement).value;
|
|
468
|
-
}}
|
|
469
|
-
@keydown=${(event: KeyboardEvent) => {
|
|
470
|
-
if (event.key === 'Enter' && (event.metaKey || event.ctrlKey)) {
|
|
471
|
-
event.preventDefault();
|
|
472
|
-
this.askIntelligence();
|
|
473
|
-
}
|
|
474
|
-
}}
|
|
475
|
-
></textarea>
|
|
476
|
-
<div class="hint">Runs separately from the main session. Ctrl/⌘ + Enter to ask.</div>
|
|
477
|
-
${this.intelligenceError ? html`<div class="error" role="alert">${this.intelligenceError}</div>` : ''}
|
|
478
|
-
<div class="actions">
|
|
479
|
-
<dees-button
|
|
480
|
-
size="sm"
|
|
481
|
-
type="accent"
|
|
482
|
-
text="Ask"
|
|
483
|
-
.status=${this.intelligenceBusy ? 'pending' : 'normal'}
|
|
484
|
-
?disabled=${this.disabled || this.intelligenceBusy || !this.intelligenceQuestion.trim()}
|
|
485
|
-
@clicked=${this.askIntelligence}
|
|
486
|
-
></dees-button>
|
|
731
|
+
${this.intelligenceError ? html`<div class="error" role="alert">${this.intelligenceError}</div>` : ''}
|
|
487
732
|
</div>
|
|
488
|
-
|
|
489
|
-
|
|
733
|
+
`,
|
|
734
|
+
);
|
|
490
735
|
}
|
|
491
736
|
|
|
492
737
|
private renderExchange(exchangeArg: IHarnessIntelligenceExchange): TemplateResult {
|
|
@@ -69,6 +69,9 @@ export class DeesHarnessToolCard extends DeesElement {
|
|
|
69
69
|
@state()
|
|
70
70
|
accessor returnFlash: boolean = false;
|
|
71
71
|
|
|
72
|
+
@state()
|
|
73
|
+
accessor outcomeScanTone: 'success' | 'error' | null = null;
|
|
74
|
+
|
|
72
75
|
private bodyResizeObserver: ResizeObserver | null = null;
|
|
73
76
|
private observedBodyInner: Element | null = null;
|
|
74
77
|
private fullscreenPortal: HTMLElementTagNameMap['dees-harness-tool-fullscreen'] | null = null;
|
|
@@ -332,6 +335,30 @@ export class DeesHarnessToolCard extends DeesElement {
|
|
|
332
335
|
transform-origin: center;
|
|
333
336
|
}
|
|
334
337
|
|
|
338
|
+
.harness-card.outcomeScan {
|
|
339
|
+
--harness-outcome-scan-color: var(--dees-color-accent-success);
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
.harness-card.outcomeScan-error {
|
|
343
|
+
--harness-outcome-scan-color: var(--dees-color-accent-error);
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
.harness-card.outcomeScan::after {
|
|
347
|
+
content: '';
|
|
348
|
+
position: absolute;
|
|
349
|
+
inset: 0;
|
|
350
|
+
pointer-events: none;
|
|
351
|
+
background: linear-gradient(
|
|
352
|
+
105deg,
|
|
353
|
+
transparent 40%,
|
|
354
|
+
color-mix(in srgb, var(--harness-outcome-scan-color) 3%, transparent) 45%,
|
|
355
|
+
color-mix(in srgb, var(--harness-outcome-scan-color) 14%, transparent) 50%,
|
|
356
|
+
color-mix(in srgb, var(--harness-outcome-scan-color) 3%, transparent) 55%,
|
|
357
|
+
transparent 60%
|
|
358
|
+
) 100% 0 / 250% 100% no-repeat;
|
|
359
|
+
animation: harness-tool-outcome-scan 0.48s linear 0.08s both;
|
|
360
|
+
}
|
|
361
|
+
|
|
335
362
|
@keyframes harness-card-return-flash {
|
|
336
363
|
0%, 100% {
|
|
337
364
|
transform: scale(1);
|
|
@@ -341,10 +368,20 @@ export class DeesHarnessToolCard extends DeesElement {
|
|
|
341
368
|
}
|
|
342
369
|
}
|
|
343
370
|
|
|
371
|
+
@keyframes harness-tool-outcome-scan {
|
|
372
|
+
from { background-position: 100% 0; }
|
|
373
|
+
to { background-position: 0 0; }
|
|
374
|
+
}
|
|
375
|
+
|
|
344
376
|
@media (prefers-reduced-motion: reduce) {
|
|
345
377
|
.harness-card.returnFlash {
|
|
346
378
|
animation: none;
|
|
347
379
|
}
|
|
380
|
+
|
|
381
|
+
.harness-card.outcomeScan::after {
|
|
382
|
+
animation: none;
|
|
383
|
+
opacity: 0;
|
|
384
|
+
}
|
|
348
385
|
}
|
|
349
386
|
`,
|
|
350
387
|
];
|
|
@@ -376,10 +413,12 @@ export class DeesHarnessToolCard extends DeesElement {
|
|
|
376
413
|
const statusTone = call.isError ? 'error' : call.status === 'completed' ? 'success' : call.status;
|
|
377
414
|
const duration = harnessFormatDuration(call.startedAt, call.finishedAt);
|
|
378
415
|
return html`
|
|
379
|
-
<div class="harness-card status-${call.isError ? 'error' : call.status} ${descriptor.destructive ? 'destructive' : ''} ${this.returnFlash ? 'returnFlash' : ''}"
|
|
416
|
+
<div class="harness-card status-${call.isError ? 'error' : call.status} ${descriptor.destructive ? 'destructive' : ''} ${this.returnFlash ? 'returnFlash' : ''} ${this.outcomeScanTone ? `outcomeScan outcomeScan-${this.outcomeScanTone}` : ''}"
|
|
380
417
|
@animationend=${(event: AnimationEvent) => {
|
|
381
418
|
if (event.animationName === 'harness-card-return-flash') {
|
|
382
419
|
this.endReturnFlash();
|
|
420
|
+
} else if (event.animationName === 'harness-tool-outcome-scan') {
|
|
421
|
+
this.endOutcomeScan();
|
|
383
422
|
}
|
|
384
423
|
}}
|
|
385
424
|
>
|
|
@@ -444,6 +483,7 @@ export class DeesHarnessToolCard extends DeesElement {
|
|
|
444
483
|
};
|
|
445
484
|
|
|
446
485
|
private flashFallbackTimeout: ReturnType<typeof setTimeout> | null = null;
|
|
486
|
+
private outcomeScanFallbackTimeout: ReturnType<typeof setTimeout> | null = null;
|
|
447
487
|
|
|
448
488
|
private readonly closeFullscreen = (): void => {
|
|
449
489
|
const portal = this.fullscreenPortal;
|
|
@@ -480,8 +520,42 @@ export class DeesHarnessToolCard extends DeesElement {
|
|
|
480
520
|
}));
|
|
481
521
|
}
|
|
482
522
|
|
|
523
|
+
private startOutcomeScan(toneArg: 'success' | 'error'): void {
|
|
524
|
+
if (this.outcomeScanFallbackTimeout) clearTimeout(this.outcomeScanFallbackTimeout);
|
|
525
|
+
this.outcomeScanTone = toneArg;
|
|
526
|
+
this.outcomeScanFallbackTimeout = setTimeout(() => this.endOutcomeScan(), 750);
|
|
527
|
+
}
|
|
528
|
+
|
|
529
|
+
private endOutcomeScan(): void {
|
|
530
|
+
if (this.outcomeScanFallbackTimeout) {
|
|
531
|
+
clearTimeout(this.outcomeScanFallbackTimeout);
|
|
532
|
+
this.outcomeScanFallbackTimeout = null;
|
|
533
|
+
}
|
|
534
|
+
this.outcomeScanTone = null;
|
|
535
|
+
}
|
|
536
|
+
|
|
537
|
+
public willUpdate(changedProperties: Map<PropertyKey, unknown>): void {
|
|
538
|
+
super.willUpdate(changedProperties);
|
|
539
|
+
const previousCall = changedProperties.get('call') as IHarnessToolCall | undefined;
|
|
540
|
+
if (!previousCall || previousCall.id !== this.call.id) return;
|
|
541
|
+
const wasActive = previousCall.status === 'pending' || previousCall.status === 'running';
|
|
542
|
+
const outcomeTone = this.call.status === 'error' || this.call.isError
|
|
543
|
+
? 'error'
|
|
544
|
+
: this.call.status === 'completed'
|
|
545
|
+
? 'success'
|
|
546
|
+
: null;
|
|
547
|
+
if (wasActive && outcomeTone) {
|
|
548
|
+
this.startOutcomeScan(outcomeTone);
|
|
549
|
+
} else if (!outcomeTone && this.outcomeScanTone) {
|
|
550
|
+
this.endOutcomeScan();
|
|
551
|
+
}
|
|
552
|
+
}
|
|
553
|
+
|
|
483
554
|
public updated(changedProperties: Map<PropertyKey, unknown>): void {
|
|
484
555
|
super.updated(changedProperties);
|
|
556
|
+
if (changedProperties.has('call') && this.fullscreenPortal) {
|
|
557
|
+
this.fullscreenPortal.call = this.enrichedCall;
|
|
558
|
+
}
|
|
485
559
|
if (this.uncapped) return;
|
|
486
560
|
const bodyInner = this.shadowRoot?.querySelector('.bodyInner') ?? null;
|
|
487
561
|
if (bodyInner === this.observedBodyInner) return;
|
|
@@ -505,6 +579,10 @@ export class DeesHarnessToolCard extends DeesElement {
|
|
|
505
579
|
clearTimeout(this.flashFallbackTimeout);
|
|
506
580
|
this.flashFallbackTimeout = null;
|
|
507
581
|
}
|
|
582
|
+
if (this.outcomeScanFallbackTimeout) {
|
|
583
|
+
clearTimeout(this.outcomeScanFallbackTimeout);
|
|
584
|
+
this.outcomeScanFallbackTimeout = null;
|
|
585
|
+
}
|
|
508
586
|
this.fullscreenPortal?.remove();
|
|
509
587
|
this.fullscreenPortal = null;
|
|
510
588
|
this.bodyResizeObserver?.disconnect();
|
|
@@ -7,6 +7,7 @@ import { css, type CSSResult } from '@design.estate/dees-element';
|
|
|
7
7
|
*/
|
|
8
8
|
export const harnessCardStyles: CSSResult = css`
|
|
9
9
|
.harness-card {
|
|
10
|
+
position: relative;
|
|
10
11
|
border: 1px solid var(--dees-color-border-subtle);
|
|
11
12
|
border-left: 2px solid var(--dees-color-border-default);
|
|
12
13
|
border-radius: var(--dees-radius-lg);
|
|
@@ -17,6 +18,14 @@ export const harnessCardStyles: CSSResult = css`
|
|
|
17
18
|
.harness-card.status-running,
|
|
18
19
|
.harness-card.status-pending {
|
|
19
20
|
border-left-color: var(--dees-color-accent-primary);
|
|
21
|
+
}
|
|
22
|
+
.harness-card.status-running::before,
|
|
23
|
+
.harness-card.status-pending::before,
|
|
24
|
+
.harness-card.outcomeScan::before {
|
|
25
|
+
content: '';
|
|
26
|
+
position: absolute;
|
|
27
|
+
inset: 0;
|
|
28
|
+
pointer-events: none;
|
|
20
29
|
background:
|
|
21
30
|
linear-gradient(
|
|
22
31
|
105deg,
|
|
@@ -25,9 +34,13 @@ export const harnessCardStyles: CSSResult = css`
|
|
|
25
34
|
color-mix(in srgb, var(--dees-color-accent-primary) 20%, transparent) 50%,
|
|
26
35
|
color-mix(in srgb, var(--dees-color-accent-primary) 6%, transparent) 55%,
|
|
27
36
|
transparent 60%
|
|
28
|
-
) 100% 0 / 250% 100% no-repeat
|
|
29
|
-
var(--dees-color-bg-secondary);
|
|
37
|
+
) 100% 0 / 250% 100% no-repeat;
|
|
30
38
|
animation: harness-card-running-scan 2s linear infinite;
|
|
39
|
+
opacity: 1;
|
|
40
|
+
transition: opacity 0.18s var(--dees-ease-out);
|
|
41
|
+
}
|
|
42
|
+
.harness-card.outcomeScan::before {
|
|
43
|
+
opacity: 0;
|
|
31
44
|
}
|
|
32
45
|
.harness-card.status-completed {
|
|
33
46
|
border-left-color: var(--dees-color-accent-success);
|
|
@@ -47,13 +60,19 @@ export const harnessCardStyles: CSSResult = css`
|
|
|
47
60
|
@media (prefers-reduced-motion: reduce) {
|
|
48
61
|
.harness-card.status-running,
|
|
49
62
|
.harness-card.status-pending {
|
|
50
|
-
animation: none;
|
|
51
63
|
background: color-mix(
|
|
52
64
|
in srgb,
|
|
53
65
|
var(--dees-color-accent-primary) 8%,
|
|
54
66
|
var(--dees-color-bg-secondary)
|
|
55
67
|
);
|
|
56
68
|
}
|
|
69
|
+
.harness-card.status-running::before,
|
|
70
|
+
.harness-card.status-pending::before,
|
|
71
|
+
.harness-card.outcomeScan::before {
|
|
72
|
+
animation: none;
|
|
73
|
+
opacity: 0;
|
|
74
|
+
transition: none;
|
|
75
|
+
}
|
|
57
76
|
}
|
|
58
77
|
`;
|
|
59
78
|
|