@copilotkit/web-inspector 1.70.0 → 1.70.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (43) hide show
  1. package/dist/components/learning-view.cjs +1415 -0
  2. package/dist/components/learning-view.cjs.map +1 -0
  3. package/dist/components/learning-view.mjs +1415 -0
  4. package/dist/components/learning-view.mjs.map +1 -0
  5. package/dist/index.cjs +1437 -609
  6. package/dist/index.cjs.map +1 -1
  7. package/dist/index.d.cts +64 -27
  8. package/dist/index.d.cts.map +1 -1
  9. package/dist/index.d.mts +64 -27
  10. package/dist/index.d.mts.map +1 -1
  11. package/dist/index.mjs +1440 -612
  12. package/dist/index.mjs.map +1 -1
  13. package/dist/index.umd.js +3224 -734
  14. package/dist/index.umd.js.map +1 -1
  15. package/dist/lib/home-briefing.cjs +19 -5
  16. package/dist/lib/home-briefing.cjs.map +1 -1
  17. package/dist/lib/home-briefing.mjs +19 -6
  18. package/dist/lib/home-briefing.mjs.map +1 -1
  19. package/dist/lib/inspector-learning.cjs +37 -0
  20. package/dist/lib/inspector-learning.cjs.map +1 -0
  21. package/dist/lib/inspector-learning.mjs +36 -0
  22. package/dist/lib/inspector-learning.mjs.map +1 -0
  23. package/dist/lib/learning-setup.cjs +83 -0
  24. package/dist/lib/learning-setup.cjs.map +1 -0
  25. package/dist/lib/learning-setup.mjs +78 -0
  26. package/dist/lib/learning-setup.mjs.map +1 -0
  27. package/dist/lib/persistence.cjs +56 -3
  28. package/dist/lib/persistence.cjs.map +1 -1
  29. package/dist/lib/persistence.mjs +54 -4
  30. package/dist/lib/persistence.mjs.map +1 -1
  31. package/dist/lib/telemetry.cjs +65 -0
  32. package/dist/lib/telemetry.cjs.map +1 -1
  33. package/dist/lib/telemetry.d.cts.map +1 -1
  34. package/dist/lib/telemetry.d.mts.map +1 -1
  35. package/dist/lib/telemetry.mjs +56 -1
  36. package/dist/lib/telemetry.mjs.map +1 -1
  37. package/dist/package.cjs +1 -1
  38. package/dist/package.mjs +1 -1
  39. package/dist/styles/generated.cjs +1 -1
  40. package/dist/styles/generated.cjs.map +1 -1
  41. package/dist/styles/generated.mjs +1 -1
  42. package/dist/styles/generated.mjs.map +1 -1
  43. package/package.json +5 -3
@@ -0,0 +1,1415 @@
1
+ import { LitElement, css, html, nothing } from "lit";
2
+
3
+ //#region src/components/learning-view.ts
4
+ function deriveLearningViewState(input) {
5
+ if (!input.supported) return input.setupActive ? "setup" : "landing";
6
+ if (!input.snapshot && input.loading) return "loading";
7
+ if (!input.snapshot && input.error) return "error";
8
+ const snapshot = input.snapshot;
9
+ if (!snapshot) return "loading";
10
+ if (snapshot.configuration.state === "selection_required") return "selection_required";
11
+ if (snapshot.configuration.state === "invalid") return "invalid";
12
+ if (snapshot.skillsPage.total > 0 || snapshot.insightsPage.total > 0 || snapshot.pendingCandidateCount > 0) return "results";
13
+ if (snapshot.run.hasActiveRun) return "first_run";
14
+ if (snapshot.run.hasEverSucceeded && snapshot.pendingThreadCount === 0) return "empty";
15
+ if (snapshot.configuration.state === "configured" && snapshot.pendingThreadCount > 0) return "ready";
16
+ if (input.setupActive || snapshot.configuration.state === "configured") return "setup";
17
+ return "landing";
18
+ }
19
+ var CpkLearningView = class extends LitElement {
20
+ constructor(..._args) {
21
+ super(..._args);
22
+ this.supported = false;
23
+ this.loading = false;
24
+ this.refreshing = false;
25
+ this.error = null;
26
+ this.snapshot = null;
27
+ this.setupActive = false;
28
+ this.copyState = "idle";
29
+ this.setupPrompt = "";
30
+ this.promptOpen = false;
31
+ this.promptTrigger = null;
32
+ this.expandedSkillId = null;
33
+ this.selectedInsightId = null;
34
+ this.skillPageKey = "";
35
+ this.handlePromptKeydown = (event) => {
36
+ if (event.key === "Escape") {
37
+ event.preventDefault();
38
+ this.closePrompt();
39
+ return;
40
+ }
41
+ if (event.key !== "Tab") return;
42
+ const dialog = event.currentTarget;
43
+ if (!(dialog instanceof HTMLElement)) return;
44
+ const root = dialog.getRootNode();
45
+ const activeElement = root instanceof ShadowRoot ? root.activeElement : document.activeElement;
46
+ const focusable = [...dialog.querySelectorAll("button:not([disabled]), [href], input:not([disabled]), select:not([disabled]), textarea:not([disabled]), [tabindex]:not([tabindex=\"-1\"])")];
47
+ const first = focusable[0];
48
+ const last = focusable.at(-1);
49
+ if (!first || !last) return;
50
+ if (event.shiftKey && activeElement === first) {
51
+ event.preventDefault();
52
+ last.focus();
53
+ } else if (!event.shiftKey && activeElement === last) {
54
+ event.preventDefault();
55
+ first.focus();
56
+ }
57
+ };
58
+ }
59
+ static {
60
+ this.properties = {
61
+ supported: { type: Boolean },
62
+ loading: { type: Boolean },
63
+ refreshing: { type: Boolean },
64
+ error: { attribute: false },
65
+ snapshot: { attribute: false },
66
+ setupActive: { type: Boolean },
67
+ copyState: { attribute: false },
68
+ setupPrompt: { attribute: false }
69
+ };
70
+ }
71
+ static {
72
+ this.styles = css`
73
+ :host {
74
+ --learning-ink: #202127;
75
+ --learning-muted: #64656f;
76
+ --learning-muted-strong: #858690;
77
+ --learning-line: #dcdce4;
78
+ --learning-line-secondary: #cfcfd7;
79
+ --learning-line-accent: #dcd9ff;
80
+ --learning-soft: #f7f7fa;
81
+ --learning-canvas: #fff;
82
+ --learning-surface: #fff;
83
+ --learning-surface-subtle: #fbfbfd;
84
+ --learning-surface-muted: #f8f8fb;
85
+ --learning-surface-hover: #fafaff;
86
+ --learning-purple: #7567ff;
87
+ --learning-purple-dark: #5549e8;
88
+ --learning-soft-purple: #f0edff;
89
+ --learning-purple-border: #cfc8ff;
90
+ --learning-green: #168b69;
91
+ --learning-soft-green: #f7fbf9;
92
+ --learning-green-border: #b9dfd1;
93
+ --learning-soft-danger: #fff4f4;
94
+ --learning-soft-danger-alt: #fff8f8;
95
+ --learning-danger: #7e2929;
96
+ --learning-danger-muted: #8c4a4a;
97
+ --learning-danger-border: #efc7c7;
98
+ --learning-danger-step-border: #d96a6a;
99
+ --learning-track: #e9edf5;
100
+ --learning-step-number: #edf0f5;
101
+ --learning-step-number-ink: #555661;
102
+ --learning-primary: #202127;
103
+ --learning-primary-ink: #fff;
104
+ --learning-secondary: #fff;
105
+ --learning-secondary-ink: #31323a;
106
+ --learning-disabled: #e5e5ea;
107
+ --learning-disabled-ink: #9a9ba3;
108
+ --learning-on-accent: #fff;
109
+ --learning-outcome: #888993;
110
+ --learning-outcome-dash: #cfd0d8;
111
+ --learning-outcome-arrow: #b0b1b9;
112
+ --learning-code: #34353d;
113
+ --learning-dialog-line: #d9d9e1;
114
+ --learning-skeleton-edge: #eeeef2;
115
+ --learning-skeleton-center: #f8f8fa;
116
+ display: block;
117
+ height: 100%;
118
+ overflow: auto;
119
+ color: var(--learning-ink);
120
+ background: var(--learning-canvas);
121
+ font-family: Inter, ui-sans-serif, system-ui, sans-serif;
122
+ }
123
+ :host([data-color-scheme="dark"]) {
124
+ color-scheme: dark;
125
+ --learning-ink: #f3f4f8;
126
+ --learning-muted: #b0b3be;
127
+ --learning-muted-strong: #b8bbc5;
128
+ --learning-line: #3a3e4b;
129
+ --learning-line-secondary: #4c5161;
130
+ --learning-line-accent: #625f95;
131
+ --learning-soft: #20232d;
132
+ --learning-canvas: #15171e;
133
+ --learning-surface: #1a1d25;
134
+ --learning-surface-subtle: #1d2029;
135
+ --learning-surface-muted: #20232d;
136
+ --learning-surface-hover: #252837;
137
+ --learning-purple: #a296ff;
138
+ --learning-purple-dark: #c4baff;
139
+ --learning-soft-purple: #2a2940;
140
+ --learning-purple-border: #625f95;
141
+ --learning-green: #4dc69d;
142
+ --learning-soft-green: #172923;
143
+ --learning-green-border: #28604d;
144
+ --learning-soft-danger: #321f25;
145
+ --learning-soft-danger-alt: #2d2026;
146
+ --learning-danger: #ffabab;
147
+ --learning-danger-muted: #f2b5ba;
148
+ --learning-danger-border: #7a424e;
149
+ --learning-danger-step-border: #a95464;
150
+ --learning-track: #303440;
151
+ --learning-step-number: #303440;
152
+ --learning-step-number-ink: #d8dae4;
153
+ --learning-primary: #f3f4f8;
154
+ --learning-primary-ink: #16181f;
155
+ --learning-secondary: #20232d;
156
+ --learning-secondary-ink: #edf0f6;
157
+ --learning-disabled: #363a46;
158
+ --learning-disabled-ink: #a4a8b5;
159
+ --learning-on-accent: #171920;
160
+ --learning-outcome: #b0b3be;
161
+ --learning-outcome-dash: #545969;
162
+ --learning-outcome-arrow: #858a99;
163
+ --learning-code: #e2e4ec;
164
+ --learning-dialog-line: #484c5a;
165
+ --learning-skeleton-edge: #2a2d38;
166
+ --learning-skeleton-center: #333744;
167
+ }
168
+ * {
169
+ box-sizing: border-box;
170
+ }
171
+ button,
172
+ a,
173
+ summary {
174
+ font: inherit;
175
+ }
176
+ button:focus-visible,
177
+ a:focus-visible,
178
+ summary:focus-visible {
179
+ outline: 2px solid var(--learning-purple);
180
+ outline-offset: 2px;
181
+ }
182
+ .pane-inner {
183
+ max-width: 880px;
184
+ min-height: 100%;
185
+ margin: 0 auto;
186
+ padding: 32px 36px 70px;
187
+ }
188
+ .pane-heading {
189
+ display: flex;
190
+ align-items: start;
191
+ justify-content: space-between;
192
+ gap: 24px;
193
+ margin-bottom: 24px;
194
+ }
195
+ .pane-heading h1 {
196
+ margin: 0 0 7px;
197
+ font-size: 25px;
198
+ line-height: 1.2;
199
+ letter-spacing: -0.035em;
200
+ }
201
+ .pane-heading p {
202
+ max-width: 630px;
203
+ margin: 0;
204
+ color: var(--learning-muted);
205
+ font-size: 14px;
206
+ line-height: 1.5;
207
+ }
208
+ .refreshing {
209
+ color: var(--learning-muted-strong);
210
+ font-size: 11px;
211
+ }
212
+ .setup-card,
213
+ .analysis-card,
214
+ .content-card {
215
+ border: 1px solid var(--learning-line);
216
+ border-radius: 10px;
217
+ background: var(--learning-surface);
218
+ }
219
+ .setup-card {
220
+ padding: 24px;
221
+ background: var(--learning-surface-subtle);
222
+ }
223
+ .setup-top {
224
+ display: flex;
225
+ align-items: start;
226
+ justify-content: space-between;
227
+ gap: 20px;
228
+ }
229
+ .setup-top h2,
230
+ .analysis-card h2 {
231
+ margin: 0;
232
+ font-size: 19px;
233
+ line-height: 1.25;
234
+ letter-spacing: -0.02em;
235
+ }
236
+ .progress-count {
237
+ font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
238
+ font-size: 13px;
239
+ font-weight: 750;
240
+ white-space: nowrap;
241
+ }
242
+ .progress-track {
243
+ height: 8px;
244
+ margin: 20px 0 18px;
245
+ overflow: hidden;
246
+ background: var(--learning-track);
247
+ border-radius: 999px;
248
+ }
249
+ .progress-fill {
250
+ height: 100%;
251
+ background: var(--learning-purple);
252
+ border-radius: inherit;
253
+ }
254
+ .steps {
255
+ display: grid;
256
+ grid-template-columns: repeat(3, minmax(0, 1fr));
257
+ gap: 10px;
258
+ margin: 0;
259
+ padding: 0;
260
+ list-style: none;
261
+ }
262
+ .step {
263
+ min-height: 142px;
264
+ padding: 15px;
265
+ background: var(--learning-surface);
266
+ border: 1px solid var(--learning-line);
267
+ border-radius: 8px;
268
+ }
269
+ .step.current {
270
+ background: var(--learning-soft-purple);
271
+ border-color: var(--learning-purple);
272
+ }
273
+ .step.error {
274
+ background: var(--learning-soft-danger);
275
+ border-color: var(--learning-danger-step-border);
276
+ }
277
+ .step.complete {
278
+ background: var(--learning-soft-green);
279
+ border-color: var(--learning-green-border);
280
+ }
281
+ .step-header {
282
+ display: flex;
283
+ align-items: center;
284
+ justify-content: space-between;
285
+ margin-bottom: 18px;
286
+ }
287
+ .step-number {
288
+ display: grid;
289
+ place-items: center;
290
+ width: 26px;
291
+ height: 26px;
292
+ color: var(--learning-step-number-ink);
293
+ background: var(--learning-step-number);
294
+ border-radius: 50%;
295
+ font-size: 12px;
296
+ font-weight: 800;
297
+ }
298
+ .step.current .step-number {
299
+ color: var(--learning-on-accent);
300
+ background: var(--learning-purple);
301
+ }
302
+ .step.complete .step-number {
303
+ color: var(--learning-on-accent);
304
+ background: var(--learning-green);
305
+ }
306
+ .step-state {
307
+ color: var(--learning-danger);
308
+ font-size: 9px;
309
+ font-weight: 850;
310
+ letter-spacing: 0.06em;
311
+ text-transform: uppercase;
312
+ }
313
+ .step h3 {
314
+ margin: 0 0 7px;
315
+ font-size: 14px;
316
+ }
317
+ .step p {
318
+ margin: 0;
319
+ color: var(--learning-muted);
320
+ font-size: 12px;
321
+ line-height: 1.45;
322
+ }
323
+ .setup-support {
324
+ margin-top: 14px;
325
+ }
326
+ .collection-panel {
327
+ padding: 15px;
328
+ background: var(--learning-surface);
329
+ border: 1px solid var(--learning-line);
330
+ border-radius: 8px;
331
+ }
332
+ .support-heading {
333
+ margin-bottom: 12px;
334
+ }
335
+ .support-heading h3 {
336
+ margin: 0;
337
+ font-size: 13px;
338
+ }
339
+ .error-alert {
340
+ margin-bottom: 10px;
341
+ padding: 11px 12px;
342
+ color: var(--learning-danger);
343
+ background: var(--learning-soft-danger);
344
+ border: 1px solid var(--learning-danger-border);
345
+ border-radius: 6px;
346
+ }
347
+ .error-alert p {
348
+ margin: 0;
349
+ color: var(--learning-danger-muted);
350
+ font-size: 11px;
351
+ line-height: 1.45;
352
+ }
353
+ .prompt-link {
354
+ display: inline-block;
355
+ margin-top: 7px;
356
+ padding: 0;
357
+ color: var(--learning-danger);
358
+ background: none;
359
+ border: 0;
360
+ font-size: 11px;
361
+ font-weight: 750;
362
+ text-decoration: underline;
363
+ cursor: pointer;
364
+ }
365
+ .collection-summary {
366
+ display: flex;
367
+ align-items: center;
368
+ justify-content: space-between;
369
+ gap: 16px;
370
+ padding: 10px;
371
+ background: var(--learning-soft);
372
+ border-radius: 6px;
373
+ }
374
+ .collection-stat {
375
+ display: flex;
376
+ min-width: 0;
377
+ align-items: center;
378
+ gap: 9px;
379
+ }
380
+ .captured-count {
381
+ color: var(--learning-ink);
382
+ font-size: 28px;
383
+ line-height: 1;
384
+ }
385
+ .collection-stat span {
386
+ font-size: 12px;
387
+ font-weight: 700;
388
+ }
389
+ .technical-details {
390
+ margin-top: 10px;
391
+ color: var(--learning-muted);
392
+ font-size: 10px;
393
+ }
394
+ .technical-details summary {
395
+ cursor: pointer;
396
+ font-weight: 700;
397
+ }
398
+ .technical-details dl {
399
+ display: grid;
400
+ grid-template-columns: auto 1fr;
401
+ gap: 5px 12px;
402
+ margin: 9px 0 0;
403
+ padding: 10px;
404
+ background: var(--learning-soft);
405
+ border-radius: 5px;
406
+ }
407
+ .technical-details dt {
408
+ color: var(--learning-muted-strong);
409
+ }
410
+ .technical-details dd {
411
+ margin: 0;
412
+ font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
413
+ overflow-wrap: anywhere;
414
+ }
415
+ .primary,
416
+ .secondary {
417
+ display: inline-flex;
418
+ align-items: center;
419
+ justify-content: center;
420
+ min-height: 36px;
421
+ padding: 0 14px;
422
+ border-radius: 6px;
423
+ font-size: 12px;
424
+ font-weight: 750;
425
+ text-decoration: none;
426
+ cursor: pointer;
427
+ }
428
+ .primary {
429
+ color: var(--learning-primary-ink);
430
+ background: var(--learning-primary);
431
+ border: 1px solid var(--learning-primary);
432
+ }
433
+ .secondary {
434
+ color: var(--learning-secondary-ink);
435
+ background: var(--learning-secondary);
436
+ border: 1px solid var(--learning-line-secondary);
437
+ }
438
+ .primary:disabled,
439
+ .primary[aria-disabled="true"] {
440
+ color: var(--learning-disabled-ink);
441
+ background: var(--learning-disabled);
442
+ border-color: var(--learning-disabled);
443
+ cursor: not-allowed;
444
+ pointer-events: none;
445
+ }
446
+ .setup-cta:not(:disabled),
447
+ .results-cta {
448
+ min-width: 170px;
449
+ min-height: 40px;
450
+ padding: 0 18px;
451
+ box-shadow: 0 6px 14px rgba(23, 23, 27, 0.2);
452
+ }
453
+ .outcome-preview {
454
+ display: flex;
455
+ align-items: center;
456
+ justify-content: center;
457
+ gap: 8px;
458
+ margin-top: 16px;
459
+ color: var(--learning-outcome);
460
+ font-size: 11px;
461
+ }
462
+ .outcome-preview span {
463
+ padding: 6px 9px;
464
+ background: var(--learning-surface);
465
+ border: 1px dashed var(--learning-outcome-dash);
466
+ border-radius: 5px;
467
+ }
468
+ .outcome-preview b {
469
+ color: var(--learning-outcome-arrow);
470
+ }
471
+ .analysis-card {
472
+ padding: 18px 20px;
473
+ background: var(--learning-surface-muted);
474
+ }
475
+ .analysis-card.ready {
476
+ background: var(--learning-soft-purple);
477
+ border-color: var(--learning-purple-border);
478
+ }
479
+ .analysis-card.error {
480
+ background: var(--learning-soft-danger-alt);
481
+ border-color: var(--learning-danger-border);
482
+ }
483
+ .analysis-row {
484
+ display: flex;
485
+ align-items: center;
486
+ gap: 20px;
487
+ }
488
+ .analysis-copy {
489
+ flex: 1;
490
+ }
491
+ .analysis-card h2 {
492
+ margin-bottom: 7px;
493
+ }
494
+ .analysis-card p {
495
+ margin: 0;
496
+ color: var(--learning-muted);
497
+ font-size: 13px;
498
+ line-height: 1.5;
499
+ }
500
+ .eyebrow {
501
+ margin: 0 0 6px !important;
502
+ color: var(--learning-purple-dark) !important;
503
+ font-size: 10px !important;
504
+ font-weight: 850;
505
+ letter-spacing: 0.09em;
506
+ text-transform: uppercase;
507
+ }
508
+ .retry-strip {
509
+ display: flex;
510
+ align-items: center;
511
+ justify-content: space-between;
512
+ gap: 16px;
513
+ margin-bottom: 12px;
514
+ padding: 11px 12px;
515
+ color: var(--learning-danger);
516
+ background: var(--learning-soft-danger);
517
+ border: 1px solid var(--learning-danger-border);
518
+ border-radius: 6px;
519
+ font-size: 11px;
520
+ }
521
+ .result-section {
522
+ margin-top: 14px;
523
+ }
524
+ .result-section-heading {
525
+ display: flex;
526
+ align-items: baseline;
527
+ gap: 6px;
528
+ margin-bottom: 10px;
529
+ }
530
+ .result-section-heading h2 {
531
+ margin: 0;
532
+ font-size: 14px;
533
+ }
534
+ .result-count {
535
+ color: var(--learning-muted-strong);
536
+ font-size: 10px;
537
+ font-weight: 700;
538
+ }
539
+ .review-link {
540
+ margin-left: auto;
541
+ color: var(--learning-purple-dark);
542
+ font-size: 11px;
543
+ font-weight: 750;
544
+ text-decoration: none;
545
+ }
546
+ .quiet-link {
547
+ display: inline-flex;
548
+ margin-top: 12px;
549
+ color: var(--learning-purple-dark);
550
+ font-size: 11px;
551
+ font-weight: 750;
552
+ text-decoration: none;
553
+ }
554
+ .quiet-link:hover,
555
+ .review-link:hover {
556
+ text-decoration: underline;
557
+ }
558
+ .content-card {
559
+ overflow: hidden;
560
+ }
561
+ .empty-card {
562
+ padding: 24px;
563
+ color: var(--learning-muted);
564
+ background: var(--learning-surface-subtle);
565
+ border: 1px solid var(--learning-line);
566
+ border-radius: 8px;
567
+ }
568
+ .empty-card.compact {
569
+ padding: 15px 16px;
570
+ }
571
+ .empty-card h3 {
572
+ margin: 0 0 6px;
573
+ color: var(--learning-ink);
574
+ font-size: 14px;
575
+ }
576
+ .empty-card p {
577
+ margin: 0;
578
+ font-size: 12px;
579
+ line-height: 1.5;
580
+ }
581
+ .active-skill {
582
+ padding: 16px;
583
+ }
584
+ .active-skill + .active-skill {
585
+ border-top: 1px solid var(--learning-line);
586
+ }
587
+ .active-skill h3 {
588
+ margin: 0 0 6px;
589
+ font-size: 14px;
590
+ }
591
+ .active-skill > p {
592
+ margin: 0;
593
+ color: var(--learning-muted);
594
+ font-size: 12px;
595
+ line-height: 1.45;
596
+ }
597
+ .skill-lineage {
598
+ margin-top: 10px;
599
+ padding: 10px 12px;
600
+ background: var(--learning-surface-muted);
601
+ border: 1px solid var(--learning-line);
602
+ border-radius: 6px;
603
+ }
604
+ .skill-lineage > span {
605
+ display: block;
606
+ margin-bottom: 5px;
607
+ color: var(--learning-muted-strong);
608
+ font-size: 9px;
609
+ font-weight: 800;
610
+ letter-spacing: 0.06em;
611
+ text-transform: uppercase;
612
+ }
613
+ .skill-lineage button {
614
+ display: flex;
615
+ width: 100%;
616
+ align-items: start;
617
+ justify-content: space-between;
618
+ gap: 14px;
619
+ padding: 0;
620
+ color: var(--learning-ink);
621
+ background: none;
622
+ border: 0;
623
+ text-align: left;
624
+ font-size: 11px;
625
+ font-weight: 700;
626
+ line-height: 1.4;
627
+ cursor: pointer;
628
+ }
629
+ .skill-lineage button small {
630
+ flex: 0 0 auto;
631
+ color: var(--learning-purple-dark);
632
+ font-size: 10px;
633
+ font-weight: 750;
634
+ }
635
+ .supporting-unavailable {
636
+ color: var(--learning-muted-strong);
637
+ font-size: 11px;
638
+ font-style: italic;
639
+ }
640
+ .skill-source {
641
+ margin-top: 10px;
642
+ }
643
+ .skill-source summary {
644
+ width: fit-content;
645
+ color: var(--learning-purple-dark);
646
+ cursor: pointer;
647
+ font-size: 11px;
648
+ font-weight: 750;
649
+ }
650
+ .skill-source pre {
651
+ margin: 10px 0 0;
652
+ padding: 12px;
653
+ color: var(--learning-code);
654
+ background: var(--learning-soft);
655
+ border: 1px solid var(--learning-line);
656
+ border-radius: 6px;
657
+ font:
658
+ 11px/1.5 ui-monospace,
659
+ SFMono-Regular,
660
+ Menlo,
661
+ Monaco,
662
+ Consolas,
663
+ monospace;
664
+ white-space: pre-wrap;
665
+ overflow-wrap: anywhere;
666
+ }
667
+ .list-header {
668
+ display: flex;
669
+ align-items: center;
670
+ padding: 10px 14px;
671
+ color: var(--learning-muted-strong);
672
+ background: var(--learning-surface-muted);
673
+ border-bottom: 1px solid var(--learning-line);
674
+ font-size: 10px;
675
+ font-weight: 800;
676
+ letter-spacing: 0.06em;
677
+ text-transform: uppercase;
678
+ }
679
+ .list-header span:last-child {
680
+ margin-left: auto;
681
+ }
682
+ .insight-row {
683
+ display: grid;
684
+ grid-template-columns: minmax(0, 1fr) auto;
685
+ gap: 18px;
686
+ width: 100%;
687
+ padding: 16px;
688
+ color: inherit;
689
+ background: var(--learning-surface);
690
+ border: 0;
691
+ border-bottom: 1px solid var(--learning-line);
692
+ text-align: left;
693
+ cursor: pointer;
694
+ }
695
+ .insight-row:last-child {
696
+ border-bottom: 0;
697
+ }
698
+ .insight-row:hover,
699
+ .insight-row[data-selected="true"] {
700
+ background: var(--learning-surface-hover);
701
+ }
702
+ .insight-row h3 {
703
+ margin: 0 0 6px;
704
+ font-size: 14px;
705
+ line-height: 1.35;
706
+ }
707
+ .insight-row p {
708
+ margin: 0;
709
+ color: var(--learning-muted);
710
+ font-size: 12px;
711
+ line-height: 1.45;
712
+ }
713
+ .evidence-count {
714
+ min-width: 90px;
715
+ color: var(--learning-purple-dark);
716
+ font-size: 11px;
717
+ font-weight: 750;
718
+ text-align: right;
719
+ }
720
+ .detail-panel {
721
+ margin-top: 14px;
722
+ padding: 18px;
723
+ background: var(--learning-surface-hover);
724
+ border: 1px solid var(--learning-line-accent);
725
+ border-radius: 8px;
726
+ }
727
+ .detail-head {
728
+ display: flex;
729
+ align-items: start;
730
+ gap: 14px;
731
+ }
732
+ .detail-head div {
733
+ flex: 1;
734
+ }
735
+ .detail-head h3 {
736
+ margin: 0 0 5px;
737
+ font-size: 14px;
738
+ }
739
+ .detail-head p {
740
+ margin: 0;
741
+ color: var(--learning-muted);
742
+ font-size: 12px;
743
+ line-height: 1.45;
744
+ }
745
+ .close-detail {
746
+ width: 28px;
747
+ height: 28px;
748
+ color: var(--learning-muted);
749
+ background: var(--learning-surface);
750
+ border: 1px solid var(--learning-line);
751
+ border-radius: 5px;
752
+ cursor: pointer;
753
+ }
754
+ .evidence-list {
755
+ display: grid;
756
+ gap: 7px;
757
+ margin-top: 14px;
758
+ }
759
+ .evidence-link,
760
+ .evidence-unavailable {
761
+ display: flex;
762
+ align-items: center;
763
+ gap: 10px;
764
+ min-height: 38px;
765
+ padding: 10px;
766
+ color: var(--learning-code);
767
+ background: var(--learning-surface);
768
+ border: 1px solid var(--learning-line);
769
+ border-radius: 6px;
770
+ font-size: 11px;
771
+ text-align: left;
772
+ }
773
+ .evidence-link {
774
+ width: 100%;
775
+ cursor: pointer;
776
+ }
777
+ .evidence-link span {
778
+ margin-left: auto;
779
+ color: var(--learning-muted-strong);
780
+ }
781
+ .evidence-unavailable {
782
+ color: var(--learning-muted-strong);
783
+ font-style: italic;
784
+ }
785
+ .pagination {
786
+ display: flex;
787
+ align-items: center;
788
+ justify-content: flex-end;
789
+ gap: 8px;
790
+ margin-top: 10px;
791
+ }
792
+ .pagination span {
793
+ margin-right: auto;
794
+ color: var(--learning-muted);
795
+ font-size: 11px;
796
+ }
797
+ .pagination button {
798
+ min-height: 30px;
799
+ padding: 0 10px;
800
+ color: var(--learning-ink);
801
+ background: var(--learning-surface);
802
+ border: 1px solid var(--learning-line);
803
+ border-radius: 5px;
804
+ font-size: 11px;
805
+ font-weight: 700;
806
+ cursor: pointer;
807
+ }
808
+ .pagination button:disabled {
809
+ color: var(--learning-disabled-ink);
810
+ background: var(--learning-surface-muted);
811
+ cursor: default;
812
+ }
813
+ .skeleton {
814
+ display: grid;
815
+ gap: 10px;
816
+ }
817
+ .skeleton span {
818
+ height: 74px;
819
+ background: linear-gradient(
820
+ 90deg,
821
+ var(--learning-skeleton-edge),
822
+ var(--learning-skeleton-center),
823
+ var(--learning-skeleton-edge)
824
+ );
825
+ background-size: 200% 100%;
826
+ border-radius: 8px;
827
+ animation: shimmer 1.3s infinite;
828
+ }
829
+ @keyframes shimmer {
830
+ to {
831
+ background-position: -200% 0;
832
+ }
833
+ }
834
+ .dialog-backdrop {
835
+ position: fixed;
836
+ z-index: 50;
837
+ inset: 0;
838
+ display: grid;
839
+ place-items: center;
840
+ padding: 24px;
841
+ background: rgba(15, 15, 20, 0.42);
842
+ }
843
+ .dialog {
844
+ display: flex;
845
+ width: min(620px, 100%);
846
+ max-height: min(680px, 90vh);
847
+ flex-direction: column;
848
+ background: var(--learning-surface);
849
+ border: 1px solid var(--learning-dialog-line);
850
+ border-radius: 13px;
851
+ box-shadow: 0 22px 70px rgba(0, 0, 0, 0.22);
852
+ }
853
+ .dialog header {
854
+ display: flex;
855
+ align-items: start;
856
+ justify-content: space-between;
857
+ padding: 18px 19px 13px;
858
+ }
859
+ .dialog h2 {
860
+ margin: 0;
861
+ font-size: 16px;
862
+ }
863
+ .dialog header p {
864
+ margin: 4px 0 0;
865
+ color: var(--learning-muted);
866
+ font-size: 11px;
867
+ }
868
+ .dialog-close {
869
+ color: var(--learning-muted);
870
+ background: transparent;
871
+ border: 0;
872
+ font-size: 20px;
873
+ cursor: pointer;
874
+ }
875
+ .dialog pre {
876
+ max-height: 420px;
877
+ overflow: auto;
878
+ margin: 0 19px;
879
+ padding: 12px;
880
+ background: var(--learning-soft);
881
+ border: 1px solid var(--learning-line);
882
+ border-radius: 6px;
883
+ font:
884
+ 11px/1.5 ui-monospace,
885
+ SFMono-Regular,
886
+ Menlo,
887
+ monospace;
888
+ white-space: pre-wrap;
889
+ }
890
+ .dialog footer {
891
+ display: flex;
892
+ justify-content: flex-end;
893
+ gap: 8px;
894
+ padding: 14px 19px 18px;
895
+ }
896
+ .copy-error {
897
+ margin: 10px 19px 0;
898
+ color: var(--learning-danger);
899
+ font-size: 11px;
900
+ }
901
+ @media (max-width: 900px) {
902
+ .steps {
903
+ grid-template-columns: 1fr;
904
+ }
905
+ .step {
906
+ min-height: auto;
907
+ }
908
+ }
909
+ @media (max-width: 640px) {
910
+ .pane-inner {
911
+ padding: 24px 18px 60px;
912
+ }
913
+ .analysis-row,
914
+ .collection-summary {
915
+ align-items: flex-start;
916
+ flex-wrap: wrap;
917
+ }
918
+ .insight-row {
919
+ grid-template-columns: 1fr;
920
+ gap: 8px;
921
+ }
922
+ .evidence-count {
923
+ text-align: left;
924
+ }
925
+ .review-link {
926
+ width: 100%;
927
+ margin: 4px 0 0;
928
+ }
929
+ }
930
+ `;
931
+ }
932
+ emit(name, detail) {
933
+ this.dispatchEvent(new CustomEvent(name, {
934
+ detail,
935
+ bubbles: true,
936
+ composed: true
937
+ }));
938
+ }
939
+ externalLink(url, label, className = "primary", category = "learning") {
940
+ return url ? html`<a
941
+ class=${className}
942
+ href=${url}
943
+ target="_blank"
944
+ rel="noopener noreferrer"
945
+ @click=${() => this.emit("learning-web-link", { category })}
946
+ >${label}</a
947
+ >` : nothing;
948
+ }
949
+ openPrompt(event) {
950
+ const trigger = event?.currentTarget;
951
+ this.promptTrigger = trigger instanceof HTMLElement ? trigger : null;
952
+ this.promptOpen = true;
953
+ this.requestUpdate();
954
+ this.updateComplete.then(() => {
955
+ this.renderRoot.querySelector(".dialog-close")?.focus();
956
+ });
957
+ }
958
+ closePrompt() {
959
+ this.promptOpen = false;
960
+ this.requestUpdate();
961
+ this.updateComplete.then(() => this.promptTrigger?.focus());
962
+ }
963
+ setupPromptButton(label = "Copy the setup prompt") {
964
+ return html`<button
965
+ class="primary"
966
+ type="button"
967
+ @click=${(event) => label === "Open the setup prompt" ? this.openPrompt(event) : this.emit("learning-copy-setup")}
968
+ >
969
+ ${this.copyState === "copied" ? "Prompt copied" : label}
970
+ </button>`;
971
+ }
972
+ renderSetupProgress(mode) {
973
+ const ready = mode === "ready";
974
+ const running = mode === "running";
975
+ const attention = mode === "attention";
976
+ const waitingForLearningSetup = mode === "setup" && this.setupActive && (this.snapshot === null || this.snapshot.configuration.state === "not_configured");
977
+ const completedSteps = ready || running ? 2 : 1;
978
+ const pendingThreads = ready ? this.snapshot?.pendingThreadCount ?? 0 : 0;
979
+ const title = attention ? "Learning setup needs attention" : mode === "setup" ? waitingForLearningSetup ? "Waiting for Learning setup" : "Waiting for the first Thread" : ready ? "Threads ready to analyze" : "Analysis is running in the web app.";
980
+ const container = this.snapshot?.configuration.state === "configured" ? this.snapshot.configuration.container : null;
981
+ return html`<section
982
+ class="setup-card"
983
+ aria-labelledby="learning-setup-title"
984
+ >
985
+ <div class="setup-top">
986
+ <h2 id="learning-setup-title">Set up Learning</h2>
987
+ <span class="progress-count">${completedSteps} of 3 steps</span>
988
+ </div>
989
+ <div class="progress-track" aria-hidden="true">
990
+ <div
991
+ class="progress-fill"
992
+ style="width: ${completedSteps / 3 * 100}%"
993
+ ></div>
994
+ </div>
995
+ <ol class="steps">
996
+ <li class="step complete">
997
+ <div class="step-header"><span class="step-number">✓</span></div>
998
+ <h3>Copy the setup prompt</h3>
999
+ <p>Nice work. You’ve completed the first step.</p>
1000
+ </li>
1001
+ <li
1002
+ class="step ${attention ? "error current" : mode === "setup" ? "current" : "complete"}"
1003
+ >
1004
+ <div class="step-header">
1005
+ <span class="step-number">${ready || running ? "✓" : "2"}</span>
1006
+ ${attention ? html`
1007
+ <span class="step-state">Needs attention</span>
1008
+ ` : nothing}
1009
+ </div>
1010
+ <h3>
1011
+ ${waitingForLearningSetup ? "Set up Learning" : "Create your first Thread"}
1012
+ </h3>
1013
+ <p>
1014
+ ${waitingForLearningSetup ? "Run the copied prompt in your coding agent. This page will continue when Learning is ready." : "Open Checkout Assistant and complete a conversation."}
1015
+ </p>
1016
+ </li>
1017
+ <li class="step ${ready || running ? "current" : ""}">
1018
+ <div class="step-header"><span class="step-number">3</span></div>
1019
+ <h3>Analyze Threads</h3>
1020
+ <p>We'll find patterns and turn them into insights and skills</p>
1021
+ </li>
1022
+ </ol>
1023
+ <div class="setup-support">
1024
+ <section class="collection-panel">
1025
+ <div class="support-heading"><h3>${title}</h3></div>
1026
+ ${attention ? html`<div class="error-alert" role="alert">
1027
+ <p>
1028
+ Inspector did not find the Learning container or app
1029
+ instrumentation. Open the setup prompt, run it in your coding
1030
+ agent, then try again.
1031
+ </p>
1032
+ <button
1033
+ class="prompt-link"
1034
+ type="button"
1035
+ @click=${(event) => this.openPrompt(event)}
1036
+ >
1037
+ Open the setup prompt ↗
1038
+ </button>
1039
+ </div>` : html`<div class="collection-summary">
1040
+ <div class="collection-stat">
1041
+ <strong class="captured-count">${pendingThreads}</strong>
1042
+ <span>New Threads</span>
1043
+ </div>
1044
+ ${ready || running ? this.externalLink(this.snapshot?.links.runs ?? null, "Open in web app", "primary setup-cta", "runs") : html`
1045
+ <button class="primary setup-cta" disabled>Analyze Threads</button>
1046
+ `}
1047
+ </div>`}
1048
+ ${attention ? nothing : html`<details class="technical-details">
1049
+ <summary>Technical details</summary>
1050
+ <dl>
1051
+ <dt>Container</dt>
1052
+ <dd>${container?.id ?? "Waiting for setup"}</dd>
1053
+ <dt>Status</dt>
1054
+ <dd>
1055
+ ${ready ? "Threads available" : running ? "Analysis running" : waitingForLearningSetup ? "Waiting for Learning setup" : "Waiting for first Thread"}
1056
+ </dd>
1057
+ </dl>
1058
+ </details>`}
1059
+ </section>
1060
+ </div>
1061
+ <div class="outcome-preview" aria-label="Learning flow">
1062
+ <span>Threads</span><b>→</b><span>Insights</span><b>→</b
1063
+ ><span>Skills</span>
1064
+ </div>
1065
+ </section>`;
1066
+ }
1067
+ renderPagination(section, page, totalPages) {
1068
+ if (totalPages <= 1) return nothing;
1069
+ return html`<nav class="pagination" aria-label="${section} pages">
1070
+ <span aria-live="polite">Page ${page} of ${totalPages}</span>
1071
+ <button
1072
+ ?disabled=${page <= 1}
1073
+ @click=${() => this.emit("learning-page", {
1074
+ section,
1075
+ page: page - 1
1076
+ })}
1077
+ >
1078
+ Previous
1079
+ </button>
1080
+ <button
1081
+ ?disabled=${page >= totalPages}
1082
+ @click=${() => this.emit("learning-page", {
1083
+ section,
1084
+ page: page + 1
1085
+ })}
1086
+ >
1087
+ Next
1088
+ </button>
1089
+ </nav>`;
1090
+ }
1091
+ renderEvidence(insight) {
1092
+ return html`<section class="detail-panel" aria-label="Insight evidence">
1093
+ <div class="detail-head">
1094
+ <div>
1095
+ <h3>Evidence</h3>
1096
+ <p>${insight.statement}</p>
1097
+ </div>
1098
+ <button
1099
+ class="close-detail"
1100
+ type="button"
1101
+ aria-label="Close evidence"
1102
+ @click=${() => {
1103
+ this.selectedInsightId = null;
1104
+ this.requestUpdate();
1105
+ }}
1106
+ >
1107
+ ×
1108
+ </button>
1109
+ </div>
1110
+ <div class="evidence-list">
1111
+ ${insight.evidence.length === 0 ? html`
1112
+ <div class="evidence-unavailable">Evidence is no longer available</div>
1113
+ ` : insight.evidence.map((evidence) => evidence.status === "unavailable" ? html`
1114
+ <div class="evidence-unavailable">Evidence is no longer available</div>
1115
+ ` : html`<button
1116
+ class="evidence-link"
1117
+ type="button"
1118
+ @click=${() => this.emit("learning-open-evidence", {
1119
+ threadId: evidence.threadId,
1120
+ messageId: evidence.messageIds[0]
1121
+ })}
1122
+ >
1123
+ ⌁
1124
+ ${evidence.threadName ?? `Thread ${evidence.threadId.slice(0, 8)}`}
1125
+ <span>Open Thread →</span>
1126
+ </button>`)}
1127
+ </div>
1128
+ ${insight.evidenceTruncated ? html`
1129
+ <p class="supporting-unavailable">Evidence response shortened</p>
1130
+ ` : nothing}
1131
+ </section>`;
1132
+ }
1133
+ selectInsight(insight) {
1134
+ this.selectedInsightId = insight.id;
1135
+ this.emit("learning-evidence-opened");
1136
+ this.requestUpdate();
1137
+ }
1138
+ supportingInsightLabel(statement) {
1139
+ const firstStop = statement.indexOf(".");
1140
+ return firstStop === -1 ? statement : statement.slice(0, firstStop + 1);
1141
+ }
1142
+ renderSkills(snapshot) {
1143
+ const firstSkillId = snapshot.skillsPage.items[0]?.id ?? null;
1144
+ const containerId = snapshot.configuration.state === "configured" ? snapshot.configuration.container.id : "";
1145
+ const skillPageKey = `${snapshot.projectKey}|${containerId}|${snapshot.skillsPage.page}|${snapshot.skillsPage.items.map((skill) => skill.id).join(",")}`;
1146
+ if (skillPageKey !== this.skillPageKey) {
1147
+ this.skillPageKey = skillPageKey;
1148
+ this.expandedSkillId = snapshot.skillsPage.page === 1 ? firstSkillId : null;
1149
+ }
1150
+ return html`<section class="result-section" aria-labelledby="skills-title">
1151
+ <div class="result-section-heading">
1152
+ <h2 id="skills-title">Skills in registry</h2>
1153
+ <span class="result-count">${snapshot.skillsPage.total}</span>
1154
+ ${snapshot.pendingCandidateCount > 0 ? this.externalLink(snapshot.links.candidates, `${snapshot.pendingCandidateCount} ${snapshot.pendingCandidateCount === 1 ? "Skill" : "Skills"} for review in web app ↗`, "review-link", "candidates") : nothing}
1155
+ </div>
1156
+ ${snapshot.skillsPage.items.length === 0 ? html`
1157
+ <div class="empty-card compact">
1158
+ <h3>No Skills in registry yet</h3>
1159
+ <p>
1160
+ No Insight has produced a Skill that was approved into the registry yet.
1161
+ </p>
1162
+ </div>
1163
+ ` : html`<div class="content-card">
1164
+ ${snapshot.skillsPage.items.map((skill) => {
1165
+ const open = this.expandedSkillId === skill.id;
1166
+ return html`<article class="active-skill">
1167
+ <h3>${skill.name}</h3>
1168
+ <p>${skill.description}</p>
1169
+ <div class="skill-lineage">
1170
+ <span>Supporting Insight</span>
1171
+ ${skill.sourceInsight ? html`<button
1172
+ type="button"
1173
+ @click=${() => this.selectInsight(skill.sourceInsight)}
1174
+ >
1175
+ ${this.supportingInsightLabel(skill.sourceInsight.statement)}<small
1176
+ >${skill.sourceInsight.totalThreadCount}
1177
+ ${skill.sourceInsight.totalThreadCount === 1 ? "Thread" : "Threads"}</small
1178
+ >
1179
+ </button>` : html`
1180
+ <div class="supporting-unavailable">Supporting Insight unavailable</div>
1181
+ `}
1182
+ </div>
1183
+ <details
1184
+ class="skill-source"
1185
+ ?open=${open}
1186
+ @toggle=${(event) => {
1187
+ const nextOpen = event.currentTarget.open;
1188
+ if (nextOpen === open) return;
1189
+ this.expandedSkillId = nextOpen ? skill.id : "";
1190
+ this.emit("learning-skill-toggle", { action: nextOpen ? "expanded" : "collapsed" });
1191
+ this.requestUpdate();
1192
+ }}
1193
+ >
1194
+ <summary>View SKILL.md</summary>
1195
+ <pre>${skill.skillMd}</pre>
1196
+ </details>
1197
+ </article>`;
1198
+ })}
1199
+ </div>`}
1200
+ ${this.renderPagination("skills", snapshot.skillsPage.page, snapshot.skillsPage.totalPages)}
1201
+ </section>`;
1202
+ }
1203
+ renderInsights(snapshot) {
1204
+ const selected = snapshot.insightsPage.items.find((insight) => insight.id === this.selectedInsightId);
1205
+ return html`<section
1206
+ class="result-section"
1207
+ aria-labelledby="insights-title"
1208
+ >
1209
+ <div class="result-section-heading">
1210
+ <h2 id="insights-title">
1211
+ ${snapshot.skillsPage.total > 0 ? "More Insights" : "Insights"}
1212
+ </h2>
1213
+ <span class="result-count">${snapshot.insightsPage.total}</span>
1214
+ </div>
1215
+ ${snapshot.insightsPage.items.length === 0 ? html`
1216
+ <div class="empty-card compact"><h3>No active Insights</h3></div>
1217
+ ` : html`<div class="content-card">
1218
+ <div class="list-header">
1219
+ <span>Pattern</span><span>Evidence</span>
1220
+ </div>
1221
+ ${snapshot.insightsPage.items.map((insight) => html`<button
1222
+ class="insight-row"
1223
+ data-selected=${selected?.id === insight.id}
1224
+ type="button"
1225
+ @click=${() => selected?.id === insight.id ? (this.selectedInsightId = null, this.requestUpdate()) : this.selectInsight(insight)}
1226
+ >
1227
+ <div>
1228
+ <h3>${insight.statement}</h3>
1229
+ <p>${insight.impact}</p>
1230
+ </div>
1231
+ <span class="evidence-count"
1232
+ >${insight.totalThreadCount}
1233
+ ${insight.totalThreadCount === 1 ? "Thread" : "Threads"}</span
1234
+ >
1235
+ </button>`)}
1236
+ </div>`}
1237
+ ${selected ? this.renderEvidence(selected) : nothing}
1238
+ ${this.renderPagination("insights", snapshot.insightsPage.page, snapshot.insightsPage.totalPages)}
1239
+ </section>`;
1240
+ }
1241
+ renderResults(snapshot) {
1242
+ const sourceInsight = snapshot.skillsPage.items.map((skill) => skill.sourceInsight).find((insight) => insight?.id === this.selectedInsightId);
1243
+ return html`
1244
+ ${snapshot.pendingThreadCount > 0 ? html`<section class="analysis-card ready">
1245
+ <div class="analysis-row">
1246
+ <div class="analysis-copy">
1247
+ <h2>Find new Insights and Skills</h2>
1248
+ <p>You have new threads ready to be analyzed.</p>
1249
+ </div>
1250
+ ${this.externalLink(snapshot.links.runs, "Open in web app", "primary results-cta", "runs")}
1251
+ </div>
1252
+ </section>` : nothing}
1253
+ ${this.renderSkills(snapshot)}
1254
+ ${sourceInsight ? this.renderEvidence(sourceInsight) : nothing}
1255
+ ${this.renderInsights(snapshot)}
1256
+ `;
1257
+ }
1258
+ renderRetryStrip() {
1259
+ if (!this.error) return nothing;
1260
+ return html`<div class="retry-strip" role="status">
1261
+ <span>${this.error}</span>
1262
+ <button
1263
+ class="secondary"
1264
+ type="button"
1265
+ @click=${() => this.emit("learning-retry")}
1266
+ >
1267
+ Retry
1268
+ </button>
1269
+ </div>`;
1270
+ }
1271
+ renderEmptyResults(snapshot) {
1272
+ return html`<section class="analysis-card">
1273
+ <div class="analysis-row">
1274
+ <div class="analysis-copy">
1275
+ <p class="eyebrow">Analysis complete</p>
1276
+ <h2>No new Insights or Skills</h2>
1277
+ <p>
1278
+ Create more Threads with Checkout Assistant. You can run Learning
1279
+ again when new Threads are available.
1280
+ </p>
1281
+ </div>
1282
+ </div>
1283
+ </section>
1284
+ <section class="result-section">
1285
+ <div class="result-section-heading">
1286
+ <h2>Skills in registry</h2><span class="result-count">0</span>
1287
+ </div>
1288
+ <div class="empty-card">
1289
+ <h3>No Skills from this analysis</h3>
1290
+ <p>Learning did not generate a Skill for review.</p>
1291
+ </div>
1292
+ </section>
1293
+ <section class="result-section">
1294
+ <div class="result-section-heading">
1295
+ <h2>Insights</h2><span class="result-count">0</span>
1296
+ </div>
1297
+ <div class="empty-card">
1298
+ <h3>No Insights from this analysis</h3>
1299
+ <p>Learning did not find a useful pattern in these Threads.</p>
1300
+ </div>
1301
+ </section>
1302
+ ${this.externalLink(snapshot.links.learning, "Open in web app ↗", "quiet-link", "learning")}`;
1303
+ }
1304
+ renderCompactState(input) {
1305
+ return html`<section class="analysis-card ${input.error ? "error" : ""}">
1306
+ <div class="analysis-row">
1307
+ <div class="analysis-copy">
1308
+ <h2>${input.title}</h2>
1309
+ ${input.copy ? html`<p>${input.copy}</p>` : nothing}
1310
+ </div>
1311
+ ${input.action ?? nothing}
1312
+ </div>
1313
+ </section>`;
1314
+ }
1315
+ render() {
1316
+ const state = deriveLearningViewState({
1317
+ supported: this.supported,
1318
+ loading: this.loading,
1319
+ error: this.error,
1320
+ snapshot: this.snapshot,
1321
+ setupActive: this.setupActive
1322
+ });
1323
+ let content;
1324
+ if (state === "loading") content = html`
1325
+ <div class="skeleton" aria-label="Loading Learning">
1326
+ <span></span><span></span><span></span>
1327
+ </div>
1328
+ `;
1329
+ else if (state === "error") content = this.renderCompactState({
1330
+ title: "Learning data is unavailable",
1331
+ copy: this.error ?? void 0,
1332
+ error: true,
1333
+ action: html`<button
1334
+ class="secondary"
1335
+ type="button"
1336
+ @click=${() => this.emit("learning-retry")}
1337
+ >
1338
+ Retry
1339
+ </button>`
1340
+ });
1341
+ else if (state === "selection_required") content = this.renderCompactState({
1342
+ title: "Inspector cannot choose a Learning container for this agent.",
1343
+ action: this.externalLink(this.snapshot.links.learning, "Open in web app", "primary", "learning")
1344
+ });
1345
+ else if (state === "invalid") content = this.renderSetupProgress("attention");
1346
+ else if (state === "landing") content = nothing;
1347
+ else if (state === "setup") content = this.renderSetupProgress("setup");
1348
+ else if (state === "first_run") content = this.renderSetupProgress("running");
1349
+ else if (state === "ready") content = this.renderSetupProgress("ready");
1350
+ else if (state === "empty") content = this.renderEmptyResults(this.snapshot);
1351
+ else content = this.renderResults(this.snapshot);
1352
+ const retry = state === "error" || !this.snapshot ? nothing : this.renderRetryStrip();
1353
+ return html`<main class="pane-inner" data-learning-state=${state}>
1354
+ <header class="pane-heading">
1355
+ <div>
1356
+ <h1>Learning</h1>
1357
+ <p>Your Agent learns from conversations and improves over time.</p>
1358
+ </div>
1359
+ ${this.refreshing ? html`
1360
+ <span class="refreshing" role="status">Refreshing</span>
1361
+ ` : nothing}
1362
+ </header>
1363
+ ${retry}
1364
+ ${content}
1365
+ </main>
1366
+ ${this.promptOpen ? html`<div class="dialog-backdrop">
1367
+ <section
1368
+ class="dialog"
1369
+ role="dialog"
1370
+ aria-modal="true"
1371
+ aria-labelledby="learning-prompt-title"
1372
+ @keydown=${this.handlePromptKeydown}
1373
+ >
1374
+ <header>
1375
+ <div>
1376
+ <h2 id="learning-prompt-title">Set up Rich Threads</h2>
1377
+ <p>Paste this prompt into your coding agent.</p>
1378
+ </div>
1379
+ <button
1380
+ class="dialog-close"
1381
+ aria-label="Close setup prompt"
1382
+ @click=${() => this.closePrompt()}
1383
+ >
1384
+ ×
1385
+ </button>
1386
+ </header>
1387
+ <pre>${this.setupPrompt}</pre>
1388
+ ${this.copyState === "error" ? html`
1389
+ <p class="copy-error" role="alert">
1390
+ Clipboard access failed. Retry to continue.
1391
+ </p>
1392
+ ` : nothing}
1393
+ <footer>
1394
+ <button
1395
+ class="secondary"
1396
+ @click=${() => this.closePrompt()}
1397
+ >
1398
+ Close
1399
+ </button>
1400
+ <button
1401
+ class="primary"
1402
+ @click=${() => this.emit("learning-copy-setup")}
1403
+ >
1404
+ ${this.copyState === "copied" ? "Prompt copied" : "Copy the setup prompt"}
1405
+ </button>
1406
+ </footer>
1407
+ </section>
1408
+ </div>` : nothing}`;
1409
+ }
1410
+ };
1411
+ if (!customElements.get("cpk-learning-view")) customElements.define("cpk-learning-view", CpkLearningView);
1412
+
1413
+ //#endregion
1414
+ export { deriveLearningViewState };
1415
+ //# sourceMappingURL=learning-view.mjs.map