@copilotkit/web-inspector 1.61.0 → 1.61.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.
- package/dist/index.cjs +512 -78
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +23 -2
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.mts +23 -2
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +513 -79
- package/dist/index.mjs.map +1 -1
- package/dist/index.umd.js +614 -109
- package/dist/index.umd.js.map +1 -1
- package/dist/lib/context-helpers.cjs.map +1 -1
- package/dist/lib/context-helpers.mjs.map +1 -1
- package/dist/lib/persistence.cjs.map +1 -1
- package/dist/lib/persistence.mjs.map +1 -1
- package/dist/lib/telemetry.cjs +78 -12
- package/dist/lib/telemetry.cjs.map +1 -1
- package/dist/lib/telemetry.mjs +72 -13
- package/dist/lib/telemetry.mjs.map +1 -1
- package/dist/lib/types.d.cts +8 -0
- package/dist/lib/types.d.cts.map +1 -0
- package/dist/lib/types.d.mts +8 -0
- package/dist/lib/types.d.mts.map +1 -0
- package/dist/package.cjs +12 -0
- package/dist/package.cjs.map +1 -0
- package/dist/package.mjs +6 -0
- package/dist/package.mjs.map +1 -0
- package/package.json +2 -2
- package/src/__tests__/web-inspector.spec.ts +399 -1
- package/src/index.ts +649 -109
- package/src/lib/__tests__/telemetry.test.ts +150 -10
- package/src/lib/context-helpers.ts +1 -1
- package/src/lib/persistence.ts +1 -1
- package/src/lib/telemetry.ts +162 -18
package/src/index.ts
CHANGED
|
@@ -28,7 +28,7 @@ import type {
|
|
|
28
28
|
DockMode,
|
|
29
29
|
Position,
|
|
30
30
|
Size,
|
|
31
|
-
} from "./lib/types";
|
|
31
|
+
} from "./lib/types.js";
|
|
32
32
|
import {
|
|
33
33
|
applyAnchorPosition as applyAnchorPositionHelper,
|
|
34
34
|
centerContext as centerContextHelper,
|
|
@@ -37,7 +37,7 @@ import {
|
|
|
37
37
|
updateAnchorFromPosition as updateAnchorFromPositionHelper,
|
|
38
38
|
updateSizeFromElement,
|
|
39
39
|
clampSize as clampSizeToViewport,
|
|
40
|
-
} from "./lib/context-helpers";
|
|
40
|
+
} from "./lib/context-helpers.js";
|
|
41
41
|
import {
|
|
42
42
|
loadInspectorState,
|
|
43
43
|
saveInspectorState,
|
|
@@ -45,17 +45,27 @@ import {
|
|
|
45
45
|
isValidPosition,
|
|
46
46
|
isValidSize,
|
|
47
47
|
isValidDockMode,
|
|
48
|
-
} from "./lib/persistence";
|
|
49
|
-
import type { PersistedState } from "./lib/persistence";
|
|
48
|
+
} from "./lib/persistence.js";
|
|
49
|
+
import type { PersistedState } from "./lib/persistence.js";
|
|
50
50
|
import {
|
|
51
51
|
TELEMETRY_DOCS_URL,
|
|
52
52
|
ensureTelemetryDistinctId,
|
|
53
|
+
getRuntimeUrlType,
|
|
53
54
|
getTelemetryDistinctIdForUrl,
|
|
54
55
|
maybeShowDisclosure,
|
|
55
56
|
trackBannerClicked,
|
|
56
57
|
trackBannerViewed,
|
|
58
|
+
trackTalkToEngineerClicked,
|
|
59
|
+
trackThreadsEmptyEnabledViewed,
|
|
60
|
+
trackThreadsEnabledViewed,
|
|
61
|
+
trackThreadsIntelligenceSignupClicked,
|
|
62
|
+
trackThreadsLockedViewed,
|
|
57
63
|
trackThreadsTabClicked,
|
|
58
|
-
|
|
64
|
+
trackThreadsTalkToEngineerClicked,
|
|
65
|
+
} from "./lib/telemetry.js";
|
|
66
|
+
import type { InspectorThreadTelemetryProps } from "./lib/telemetry.js";
|
|
67
|
+
|
|
68
|
+
export type { Anchor } from "./lib/types.js";
|
|
59
69
|
|
|
60
70
|
export const WEB_INSPECTOR_TAG = "cpk-web-inspector" as const;
|
|
61
71
|
|
|
@@ -88,6 +98,10 @@ const DEFAULT_WINDOW_SIZE: Size = { width: 840, height: 700 };
|
|
|
88
98
|
const DOCKED_LEFT_WIDTH = 500; // Sensible width for left dock with collapsed sidebar
|
|
89
99
|
const MAX_AGENT_EVENTS = 200;
|
|
90
100
|
const MAX_TOTAL_EVENTS = 500;
|
|
101
|
+
const INTELLIGENCE_SIGNUP_URL = "https://go.copilotkit.ai/intelligence-signup";
|
|
102
|
+
const TALK_TO_ENGINEER_URL = "https://www.copilotkit.ai/talk-to-an-engineer";
|
|
103
|
+
|
|
104
|
+
type ThreadServiceStatus = "available" | "unavailable" | "unknown" | "error";
|
|
91
105
|
|
|
92
106
|
type InspectorAgentEventType =
|
|
93
107
|
| "RUN_STARTED"
|
|
@@ -334,9 +348,10 @@ function eventColors(type: string): { bg: string; fg: string } {
|
|
|
334
348
|
return { bg: "rgba(133,236,206,0.15)", fg: "#189370" };
|
|
335
349
|
if (type.startsWith("STATE"))
|
|
336
350
|
return { bg: "rgba(190,194,255,0.102)", fg: "#5558B2" };
|
|
351
|
+
if (type === "RUN_ERROR" || type === "ERROR")
|
|
352
|
+
return { bg: "rgba(250,95,103,0.13)", fg: "#c0333a" };
|
|
337
353
|
if (type.startsWith("RUN_") || type.startsWith("STEP_"))
|
|
338
354
|
return { bg: "rgba(255,172,77,0.2)", fg: "#996300" };
|
|
339
|
-
if (type === "ERROR") return { bg: "rgba(250,95,103,0.13)", fg: "#c0333a" };
|
|
340
355
|
return { bg: "#F7F7F9", fg: "#838389" };
|
|
341
356
|
}
|
|
342
357
|
|
|
@@ -674,6 +689,7 @@ export class ɵCpkThreadDetails extends LitElement {
|
|
|
674
689
|
thread: { attribute: false },
|
|
675
690
|
runtimeUrl: { attribute: false },
|
|
676
691
|
headers: { attribute: false },
|
|
692
|
+
threadInspectionAvailable: { attribute: false },
|
|
677
693
|
agentStateInput: { attribute: false },
|
|
678
694
|
agentEventsInput: { attribute: false },
|
|
679
695
|
liveMessageVersion: { attribute: false },
|
|
@@ -701,6 +717,7 @@ export class ɵCpkThreadDetails extends LitElement {
|
|
|
701
717
|
thread: ɵThread | null = null;
|
|
702
718
|
runtimeUrl = "";
|
|
703
719
|
headers: Record<string, string> = {};
|
|
720
|
+
threadInspectionAvailable = false;
|
|
704
721
|
agentStateInput: Record<string, unknown> | null = null;
|
|
705
722
|
agentEventsInput: ApiAgentEvent[] = [];
|
|
706
723
|
/**
|
|
@@ -1456,7 +1473,7 @@ export class ɵCpkThreadDetails extends LitElement {
|
|
|
1456
1473
|
threadId: string,
|
|
1457
1474
|
silent: boolean = false,
|
|
1458
1475
|
): Promise<void> {
|
|
1459
|
-
if (!this.runtimeUrl) {
|
|
1476
|
+
if (!this.runtimeUrl || !this.threadInspectionAvailable) {
|
|
1460
1477
|
if (!silent) this._conversation = [];
|
|
1461
1478
|
return;
|
|
1462
1479
|
}
|
|
@@ -1468,7 +1485,7 @@ export class ɵCpkThreadDetails extends LitElement {
|
|
|
1468
1485
|
}
|
|
1469
1486
|
try {
|
|
1470
1487
|
const res = await fetch(
|
|
1471
|
-
|
|
1488
|
+
this.getThreadInspectionUrl(threadId, "messages"),
|
|
1472
1489
|
{ headers: { ...this.headers }, signal: controller.signal },
|
|
1473
1490
|
);
|
|
1474
1491
|
if (controller.signal.aborted || this.threadId !== threadId) return;
|
|
@@ -1494,7 +1511,7 @@ export class ɵCpkThreadDetails extends LitElement {
|
|
|
1494
1511
|
|
|
1495
1512
|
private async fetchEvents(threadId: string): Promise<void> {
|
|
1496
1513
|
this._eventsNotAvailable = false;
|
|
1497
|
-
if (!this.runtimeUrl) {
|
|
1514
|
+
if (!this.runtimeUrl || !this.threadInspectionAvailable) {
|
|
1498
1515
|
this._fetchedEvents = null;
|
|
1499
1516
|
return;
|
|
1500
1517
|
}
|
|
@@ -1503,10 +1520,10 @@ export class ɵCpkThreadDetails extends LitElement {
|
|
|
1503
1520
|
this._loadingEvents = true;
|
|
1504
1521
|
this._eventsError = null;
|
|
1505
1522
|
try {
|
|
1506
|
-
const res = await fetch(
|
|
1507
|
-
|
|
1508
|
-
|
|
1509
|
-
);
|
|
1523
|
+
const res = await fetch(this.getThreadInspectionUrl(threadId, "events"), {
|
|
1524
|
+
headers: { ...this.headers },
|
|
1525
|
+
signal: controller.signal,
|
|
1526
|
+
});
|
|
1510
1527
|
// Drop results if a newer fetch superseded this one (thread switched
|
|
1511
1528
|
// mid-flight). Without this, switching A→B can leave thread B's view
|
|
1512
1529
|
// showing thread A's events when A's request resolves last.
|
|
@@ -1541,7 +1558,7 @@ export class ɵCpkThreadDetails extends LitElement {
|
|
|
1541
1558
|
|
|
1542
1559
|
private async fetchState(threadId: string): Promise<void> {
|
|
1543
1560
|
this._stateNotAvailable = false;
|
|
1544
|
-
if (!this.runtimeUrl) {
|
|
1561
|
+
if (!this.runtimeUrl || !this.threadInspectionAvailable) {
|
|
1545
1562
|
this._fetchedState = null;
|
|
1546
1563
|
return;
|
|
1547
1564
|
}
|
|
@@ -1550,10 +1567,10 @@ export class ɵCpkThreadDetails extends LitElement {
|
|
|
1550
1567
|
this._loadingState = true;
|
|
1551
1568
|
this._stateError = null;
|
|
1552
1569
|
try {
|
|
1553
|
-
const res = await fetch(
|
|
1554
|
-
|
|
1555
|
-
|
|
1556
|
-
);
|
|
1570
|
+
const res = await fetch(this.getThreadInspectionUrl(threadId, "state"), {
|
|
1571
|
+
headers: { ...this.headers },
|
|
1572
|
+
signal: controller.signal,
|
|
1573
|
+
});
|
|
1557
1574
|
if (controller.signal.aborted || this.threadId !== threadId) return;
|
|
1558
1575
|
if (res.status === 501) {
|
|
1559
1576
|
this._stateNotAvailable = true;
|
|
@@ -1579,6 +1596,13 @@ export class ɵCpkThreadDetails extends LitElement {
|
|
|
1579
1596
|
}
|
|
1580
1597
|
}
|
|
1581
1598
|
|
|
1599
|
+
private getThreadInspectionUrl(
|
|
1600
|
+
threadId: string,
|
|
1601
|
+
resource: "messages" | "events" | "state",
|
|
1602
|
+
): string {
|
|
1603
|
+
return `${this.runtimeUrl.replace(/\/+$/, "")}/threads/${encodeURIComponent(threadId)}/${resource}`;
|
|
1604
|
+
}
|
|
1605
|
+
|
|
1582
1606
|
private mapMessages(messages: ApiThreadMessage[]): ConversationItem[] {
|
|
1583
1607
|
const items: ConversationItem[] = [];
|
|
1584
1608
|
const toolCallMap = new Map<string, ConversationToolCall>();
|
|
@@ -2444,6 +2468,7 @@ export class WebInspectorElement extends LitElement {
|
|
|
2444
2468
|
// `${bannerId}:${cta}`) so copy-button retries and accidental multi-clicks
|
|
2445
2469
|
// don't inflate funnel counts beyond one signal per intent type per banner.
|
|
2446
2470
|
private clickedBannerIds: Set<string> = new Set();
|
|
2471
|
+
private viewedThreadsTelemetryStates: Set<string> = new Set();
|
|
2447
2472
|
|
|
2448
2473
|
get core(): CopilotKitCore | null {
|
|
2449
2474
|
return this._core;
|
|
@@ -2525,7 +2550,54 @@ export class WebInspectorElement extends LitElement {
|
|
|
2525
2550
|
];
|
|
2526
2551
|
}
|
|
2527
2552
|
|
|
2553
|
+
private getThreadServiceStatus(): ThreadServiceStatus {
|
|
2554
|
+
if (!this._core) return "unknown";
|
|
2555
|
+
if (!this._core.threadEndpoints) return "unknown";
|
|
2556
|
+
return this._core.threadEndpoints?.list === false
|
|
2557
|
+
? "unavailable"
|
|
2558
|
+
: "available";
|
|
2559
|
+
}
|
|
2560
|
+
|
|
2561
|
+
private areThreadEndpointsAvailable(): boolean {
|
|
2562
|
+
return this.getThreadServiceStatus() !== "unavailable";
|
|
2563
|
+
}
|
|
2564
|
+
|
|
2565
|
+
private getThreadsTelemetryProps(
|
|
2566
|
+
extra: Partial<InspectorThreadTelemetryProps> = {},
|
|
2567
|
+
options: { includeUrlAttribution?: boolean } = {},
|
|
2568
|
+
): InspectorThreadTelemetryProps {
|
|
2569
|
+
const distinctId =
|
|
2570
|
+
options.includeUrlAttribution && !this.core?.telemetryDisabled
|
|
2571
|
+
? getTelemetryDistinctIdForUrl()
|
|
2572
|
+
: null;
|
|
2573
|
+
const threadServiceStatus = this.getThreadServiceStatus();
|
|
2574
|
+
return {
|
|
2575
|
+
posthog_distinct_id: distinctId ?? undefined,
|
|
2576
|
+
intelligence_status:
|
|
2577
|
+
threadServiceStatus === "available"
|
|
2578
|
+
? "intelligence_enabled"
|
|
2579
|
+
: threadServiceStatus === "unavailable"
|
|
2580
|
+
? "intelligence_not_enabled"
|
|
2581
|
+
: "unknown",
|
|
2582
|
+
thread_service_status: threadServiceStatus,
|
|
2583
|
+
license_status: this.core?.licenseStatus ?? undefined,
|
|
2584
|
+
runtime_mode: this.core?.runtimeMode ?? undefined,
|
|
2585
|
+
runtime_url_type: getRuntimeUrlType(this.core?.runtimeUrl),
|
|
2586
|
+
telemetry_disabled: this.core?.telemetryDisabled ?? false,
|
|
2587
|
+
...extra,
|
|
2588
|
+
};
|
|
2589
|
+
}
|
|
2590
|
+
|
|
2591
|
+
private getIntelligenceSignupUrl(): string {
|
|
2592
|
+
return this.appendRefParam(INTELLIGENCE_SIGNUP_URL, "cpk-inspector");
|
|
2593
|
+
}
|
|
2594
|
+
|
|
2595
|
+
private getTalkToEngineerUrl(): string {
|
|
2596
|
+
return this.appendRefParam(TALK_TO_ENGINEER_URL, "cpk-inspector-threads");
|
|
2597
|
+
}
|
|
2598
|
+
|
|
2528
2599
|
private subscribeToThreadStore(agentId: string, store: ɵThreadStore): void {
|
|
2600
|
+
if (!this.areThreadEndpointsAvailable()) return;
|
|
2529
2601
|
if (this._threadStoreSubscriptions.has(agentId)) return;
|
|
2530
2602
|
const threadsSub = store.select(ɵselectThreads).subscribe((threads) => {
|
|
2531
2603
|
this._threadsByAgent.set(agentId, threads as ɵThread[]);
|
|
@@ -2585,12 +2657,14 @@ export class WebInspectorElement extends LitElement {
|
|
|
2585
2657
|
if (this.core?.getThreadStore(agentId)) return;
|
|
2586
2658
|
const core = this.core;
|
|
2587
2659
|
if (!core?.runtimeUrl) return;
|
|
2660
|
+
if (!this.areThreadEndpointsAvailable()) return;
|
|
2588
2661
|
|
|
2589
2662
|
const store = ɵcreateThreadStore({ fetch: globalThis.fetch });
|
|
2590
2663
|
store.start();
|
|
2591
2664
|
store.setContext({
|
|
2592
2665
|
runtimeUrl: core.runtimeUrl,
|
|
2593
|
-
headers: {},
|
|
2666
|
+
headers: { ...core.headers },
|
|
2667
|
+
wsUrl: core.intelligence?.wsUrl,
|
|
2594
2668
|
agentId,
|
|
2595
2669
|
});
|
|
2596
2670
|
this._ownedThreadStores.set(agentId, store);
|
|
@@ -2609,6 +2683,25 @@ export class WebInspectorElement extends LitElement {
|
|
|
2609
2683
|
store.refresh();
|
|
2610
2684
|
}
|
|
2611
2685
|
|
|
2686
|
+
// Keep inspector-owned thread stores in sync when the host updates headers
|
|
2687
|
+
// at runtime (e.g. a refreshed auth/CSRF token via core.setHeaders). Mirrors
|
|
2688
|
+
// useThreads(), which re-dispatches the context whenever core.headers change,
|
|
2689
|
+
// so the owned stores' /threads requests stay authorized.
|
|
2690
|
+
private updateOwnedThreadStoreHeaders(
|
|
2691
|
+
headers: Readonly<Record<string, string>>,
|
|
2692
|
+
): void {
|
|
2693
|
+
const core = this.core;
|
|
2694
|
+
if (!core?.runtimeUrl) return;
|
|
2695
|
+
for (const [agentId, store] of this._ownedThreadStores) {
|
|
2696
|
+
store.setContext({
|
|
2697
|
+
runtimeUrl: core.runtimeUrl,
|
|
2698
|
+
headers: { ...headers },
|
|
2699
|
+
wsUrl: core.intelligence?.wsUrl,
|
|
2700
|
+
agentId,
|
|
2701
|
+
});
|
|
2702
|
+
}
|
|
2703
|
+
}
|
|
2704
|
+
|
|
2612
2705
|
private removeOwnedThreadStore(agentId: string): void {
|
|
2613
2706
|
const store = this._ownedThreadStores.get(agentId);
|
|
2614
2707
|
if (!store) return;
|
|
@@ -2639,8 +2732,12 @@ export class WebInspectorElement extends LitElement {
|
|
|
2639
2732
|
maybeShowDisclosure();
|
|
2640
2733
|
}
|
|
2641
2734
|
this.flushPendingBannerViewed();
|
|
2642
|
-
|
|
2643
|
-
this.
|
|
2735
|
+
if (this.areThreadEndpointsAvailable()) {
|
|
2736
|
+
for (const agentId of this._ownedThreadStores.keys()) {
|
|
2737
|
+
this.refreshOwnedThreadStore(agentId);
|
|
2738
|
+
}
|
|
2739
|
+
} else {
|
|
2740
|
+
this.teardownOwnedThreadStores();
|
|
2644
2741
|
}
|
|
2645
2742
|
} else {
|
|
2646
2743
|
// Clear stale thread data immediately when the server goes away
|
|
@@ -2653,6 +2750,9 @@ export class WebInspectorElement extends LitElement {
|
|
|
2653
2750
|
this.coreProperties = properties;
|
|
2654
2751
|
this.requestUpdate();
|
|
2655
2752
|
},
|
|
2753
|
+
onHeadersChanged: ({ headers }) => {
|
|
2754
|
+
this.updateOwnedThreadStoreHeaders(headers);
|
|
2755
|
+
},
|
|
2656
2756
|
onError: ({ code, error }) => {
|
|
2657
2757
|
this.lastCoreError = { code, message: error.message };
|
|
2658
2758
|
this.requestUpdate();
|
|
@@ -2684,6 +2784,14 @@ export class WebInspectorElement extends LitElement {
|
|
|
2684
2784
|
this.coreUnsubscribe = core.subscribe(this.coreSubscriber).unsubscribe;
|
|
2685
2785
|
this.processAgentsChanged(core.agents);
|
|
2686
2786
|
|
|
2787
|
+
if (core.runtimeConnectionStatus === "connected") {
|
|
2788
|
+
if (!core.telemetryDisabled) {
|
|
2789
|
+
ensureTelemetryDistinctId();
|
|
2790
|
+
maybeShowDisclosure();
|
|
2791
|
+
}
|
|
2792
|
+
this.flushPendingBannerViewed();
|
|
2793
|
+
}
|
|
2794
|
+
|
|
2687
2795
|
// Subscribe to any already-registered thread stores. `getThreadStores` was
|
|
2688
2796
|
// added in the same release as this inspector; guard so consumers still on
|
|
2689
2797
|
// an older @copilotkit/core don't throw when assigning `inspector.core`.
|
|
@@ -2830,8 +2938,11 @@ export class WebInspectorElement extends LitElement {
|
|
|
2830
2938
|
onRunStartedEvent: ({ event }) => {
|
|
2831
2939
|
this.recordAgentEvent(agentId, "RUN_STARTED", event);
|
|
2832
2940
|
},
|
|
2833
|
-
onRunFinishedEvent: (
|
|
2834
|
-
this.recordAgentEvent(agentId, "RUN_FINISHED", {
|
|
2941
|
+
onRunFinishedEvent: (params) => {
|
|
2942
|
+
this.recordAgentEvent(agentId, "RUN_FINISHED", {
|
|
2943
|
+
event: params.event,
|
|
2944
|
+
result: "result" in params ? params.result : undefined,
|
|
2945
|
+
});
|
|
2835
2946
|
this.refreshOwnedThreadStore(agentId);
|
|
2836
2947
|
},
|
|
2837
2948
|
onRunErrorEvent: ({ event }) => {
|
|
@@ -3375,6 +3486,10 @@ ${argsString}</pre
|
|
|
3375
3486
|
const base =
|
|
3376
3487
|
"font-mono text-[10px] font-medium inline-flex items-center rounded-sm px-1.5 py-0.5 border";
|
|
3377
3488
|
|
|
3489
|
+
if (type === "RUN_ERROR") {
|
|
3490
|
+
return `${base} bg-rose-50 text-rose-700 border-rose-200`;
|
|
3491
|
+
}
|
|
3492
|
+
|
|
3378
3493
|
if (type.startsWith("RUN_")) {
|
|
3379
3494
|
return `${base} bg-blue-50 text-blue-700 border-blue-200`;
|
|
3380
3495
|
}
|
|
@@ -3399,10 +3514,6 @@ ${argsString}</pre
|
|
|
3399
3514
|
return `${base} bg-sky-50 text-sky-700 border-sky-200`;
|
|
3400
3515
|
}
|
|
3401
3516
|
|
|
3402
|
-
if (type === "RUN_ERROR") {
|
|
3403
|
-
return `${base} bg-rose-50 text-rose-700 border-rose-200`;
|
|
3404
|
-
}
|
|
3405
|
-
|
|
3406
3517
|
return `${base} bg-gray-100 text-gray-600 border-gray-200`;
|
|
3407
3518
|
}
|
|
3408
3519
|
|
|
@@ -5762,6 +5873,45 @@ ${argsString}</pre
|
|
|
5762
5873
|
});
|
|
5763
5874
|
}
|
|
5764
5875
|
|
|
5876
|
+
private handleTalkToEngineerClick = (): void => {
|
|
5877
|
+
if (this.core?.telemetryDisabled) return;
|
|
5878
|
+
trackTalkToEngineerClicked(
|
|
5879
|
+
this.getThreadsTelemetryProps(
|
|
5880
|
+
{
|
|
5881
|
+
cta: "talk_to_engineer",
|
|
5882
|
+
cta_surface: "threads_header",
|
|
5883
|
+
},
|
|
5884
|
+
{ includeUrlAttribution: true },
|
|
5885
|
+
),
|
|
5886
|
+
);
|
|
5887
|
+
};
|
|
5888
|
+
|
|
5889
|
+
private handleThreadsIntelligenceSignupClick = (): void => {
|
|
5890
|
+
if (this.core?.telemetryDisabled) return;
|
|
5891
|
+
trackThreadsIntelligenceSignupClicked(
|
|
5892
|
+
this.getThreadsTelemetryProps(
|
|
5893
|
+
{
|
|
5894
|
+
cta: "signup",
|
|
5895
|
+
cta_surface: "threads_locked",
|
|
5896
|
+
},
|
|
5897
|
+
{ includeUrlAttribution: true },
|
|
5898
|
+
),
|
|
5899
|
+
);
|
|
5900
|
+
};
|
|
5901
|
+
|
|
5902
|
+
private handleThreadsTalkToEngineerClick = (): void => {
|
|
5903
|
+
if (this.core?.telemetryDisabled) return;
|
|
5904
|
+
trackThreadsTalkToEngineerClicked(
|
|
5905
|
+
this.getThreadsTelemetryProps(
|
|
5906
|
+
{
|
|
5907
|
+
cta: "talk_to_engineer",
|
|
5908
|
+
cta_surface: "threads_locked",
|
|
5909
|
+
},
|
|
5910
|
+
{ includeUrlAttribution: true },
|
|
5911
|
+
),
|
|
5912
|
+
);
|
|
5913
|
+
};
|
|
5914
|
+
|
|
5765
5915
|
private handleThreadDividerPointerDown = (event: PointerEvent) => {
|
|
5766
5916
|
this.threadDividerResizing = true;
|
|
5767
5917
|
this.threadDividerPointerId = event.pointerId;
|
|
@@ -5794,7 +5944,326 @@ ${argsString}</pre
|
|
|
5794
5944
|
this.threadDividerResizing = false;
|
|
5795
5945
|
};
|
|
5796
5946
|
|
|
5947
|
+
private trackThreadsViewStateOnce(
|
|
5948
|
+
state: "locked" | "empty_enabled" | "enabled",
|
|
5949
|
+
threadCount: number,
|
|
5950
|
+
): void {
|
|
5951
|
+
if (this.core?.telemetryDisabled) return;
|
|
5952
|
+
const key = `${state}:${this.getThreadServiceStatus()}`;
|
|
5953
|
+
if (this.viewedThreadsTelemetryStates.has(key)) return;
|
|
5954
|
+
this.viewedThreadsTelemetryStates.add(key);
|
|
5955
|
+
const props = this.getThreadsTelemetryProps({ thread_count: threadCount });
|
|
5956
|
+
if (state === "locked") {
|
|
5957
|
+
trackThreadsLockedViewed(props);
|
|
5958
|
+
} else if (state === "empty_enabled") {
|
|
5959
|
+
trackThreadsEmptyEnabledViewed(props);
|
|
5960
|
+
} else {
|
|
5961
|
+
trackThreadsEnabledViewed(props);
|
|
5962
|
+
}
|
|
5963
|
+
}
|
|
5964
|
+
|
|
5965
|
+
private renderThreadsLockedBackgroundMockup() {
|
|
5966
|
+
const threadRows = [
|
|
5967
|
+
{ width: 74, accent: true },
|
|
5968
|
+
{ width: 92 },
|
|
5969
|
+
{ width: 68 },
|
|
5970
|
+
{ width: 84 },
|
|
5971
|
+
{ width: 58 },
|
|
5972
|
+
{ width: 76 },
|
|
5973
|
+
];
|
|
5974
|
+
|
|
5975
|
+
return html`
|
|
5976
|
+
<div
|
|
5977
|
+
aria-hidden="true"
|
|
5978
|
+
style="
|
|
5979
|
+
position: absolute;
|
|
5980
|
+
inset: 0;
|
|
5981
|
+
display: grid;
|
|
5982
|
+
grid-template-columns: minmax(180px, 28%) 1fr;
|
|
5983
|
+
overflow: hidden;
|
|
5984
|
+
opacity: 0.58;
|
|
5985
|
+
pointer-events: none;
|
|
5986
|
+
"
|
|
5987
|
+
>
|
|
5988
|
+
<div
|
|
5989
|
+
style="
|
|
5990
|
+
display: flex;
|
|
5991
|
+
flex-direction: column;
|
|
5992
|
+
gap: 12px;
|
|
5993
|
+
padding: 28px 24px;
|
|
5994
|
+
border-right: 1px solid #dbdbe5;
|
|
5995
|
+
background: #fafafa;
|
|
5996
|
+
"
|
|
5997
|
+
>
|
|
5998
|
+
${threadRows.map(
|
|
5999
|
+
(row) => html`
|
|
6000
|
+
<div
|
|
6001
|
+
style="
|
|
6002
|
+
padding: 12px;
|
|
6003
|
+
border-radius: 8px;
|
|
6004
|
+
background: ${row.accent ? "#eee6fe" : "#ffffff"};
|
|
6005
|
+
box-shadow: inset 0 0 0 1px #eeeef4;
|
|
6006
|
+
"
|
|
6007
|
+
>
|
|
6008
|
+
<div
|
|
6009
|
+
style="
|
|
6010
|
+
height: 8px;
|
|
6011
|
+
width: ${row.width}%;
|
|
6012
|
+
border-radius: 99px;
|
|
6013
|
+
background: ${row.accent ? "#a984f5" : "#d7d7df"};
|
|
6014
|
+
"
|
|
6015
|
+
></div>
|
|
6016
|
+
<div
|
|
6017
|
+
style="
|
|
6018
|
+
height: 6px;
|
|
6019
|
+
width: 88%;
|
|
6020
|
+
margin-top: 10px;
|
|
6021
|
+
border-radius: 99px;
|
|
6022
|
+
background: #e3e3eb;
|
|
6023
|
+
"
|
|
6024
|
+
></div>
|
|
6025
|
+
<div
|
|
6026
|
+
style="
|
|
6027
|
+
height: 6px;
|
|
6028
|
+
width: 62%;
|
|
6029
|
+
margin-top: 7px;
|
|
6030
|
+
border-radius: 99px;
|
|
6031
|
+
background: #e8e8ef;
|
|
6032
|
+
"
|
|
6033
|
+
></div>
|
|
6034
|
+
</div>
|
|
6035
|
+
`,
|
|
6036
|
+
)}
|
|
6037
|
+
</div>
|
|
6038
|
+
<div
|
|
6039
|
+
style="
|
|
6040
|
+
min-width: 0;
|
|
6041
|
+
padding: 42px 48px;
|
|
6042
|
+
background: #ffffff;
|
|
6043
|
+
"
|
|
6044
|
+
>
|
|
6045
|
+
<div
|
|
6046
|
+
style="
|
|
6047
|
+
height: 10px;
|
|
6048
|
+
width: 180px;
|
|
6049
|
+
border-radius: 99px;
|
|
6050
|
+
background: #d7d7df;
|
|
6051
|
+
"
|
|
6052
|
+
></div>
|
|
6053
|
+
<div
|
|
6054
|
+
style="
|
|
6055
|
+
height: 8px;
|
|
6056
|
+
width: min(520px, 58%);
|
|
6057
|
+
margin-top: 28px;
|
|
6058
|
+
border-radius: 99px;
|
|
6059
|
+
background: #e3e3eb;
|
|
6060
|
+
"
|
|
6061
|
+
></div>
|
|
6062
|
+
<div
|
|
6063
|
+
style="
|
|
6064
|
+
height: 8px;
|
|
6065
|
+
width: min(430px, 48%);
|
|
6066
|
+
margin-top: 12px;
|
|
6067
|
+
border-radius: 99px;
|
|
6068
|
+
background: #e8e8ef;
|
|
6069
|
+
"
|
|
6070
|
+
></div>
|
|
6071
|
+
<div
|
|
6072
|
+
style="
|
|
6073
|
+
display: grid;
|
|
6074
|
+
grid-template-columns: repeat(2, minmax(0, 1fr));
|
|
6075
|
+
gap: 16px;
|
|
6076
|
+
max-width: 620px;
|
|
6077
|
+
margin-top: 30px;
|
|
6078
|
+
"
|
|
6079
|
+
>
|
|
6080
|
+
<div
|
|
6081
|
+
style="
|
|
6082
|
+
height: 116px;
|
|
6083
|
+
border-radius: 8px;
|
|
6084
|
+
background: #f5f5f8;
|
|
6085
|
+
box-shadow: inset 0 0 0 1px #eeeef4;
|
|
6086
|
+
"
|
|
6087
|
+
></div>
|
|
6088
|
+
<div
|
|
6089
|
+
style="
|
|
6090
|
+
height: 116px;
|
|
6091
|
+
border-radius: 8px;
|
|
6092
|
+
background: #f5f5f8;
|
|
6093
|
+
box-shadow: inset 0 0 0 1px #eeeef4;
|
|
6094
|
+
"
|
|
6095
|
+
></div>
|
|
6096
|
+
</div>
|
|
6097
|
+
<div
|
|
6098
|
+
style="
|
|
6099
|
+
height: 10px;
|
|
6100
|
+
width: min(680px, 74%);
|
|
6101
|
+
margin-top: 34px;
|
|
6102
|
+
border-radius: 99px;
|
|
6103
|
+
background: #e3e3eb;
|
|
6104
|
+
"
|
|
6105
|
+
></div>
|
|
6106
|
+
<div
|
|
6107
|
+
style="
|
|
6108
|
+
height: 10px;
|
|
6109
|
+
width: min(560px, 60%);
|
|
6110
|
+
margin-top: 14px;
|
|
6111
|
+
border-radius: 99px;
|
|
6112
|
+
background: #e8e8ef;
|
|
6113
|
+
"
|
|
6114
|
+
></div>
|
|
6115
|
+
</div>
|
|
6116
|
+
</div>
|
|
6117
|
+
`;
|
|
6118
|
+
}
|
|
6119
|
+
|
|
6120
|
+
private renderThreadsLockedView() {
|
|
6121
|
+
this.trackThreadsViewStateOnce("locked", 0);
|
|
6122
|
+
return html`
|
|
6123
|
+
<div
|
|
6124
|
+
style="
|
|
6125
|
+
position: relative;
|
|
6126
|
+
height: 100%;
|
|
6127
|
+
display: flex;
|
|
6128
|
+
align-items: center;
|
|
6129
|
+
justify-content: center;
|
|
6130
|
+
padding: 32px;
|
|
6131
|
+
overflow: hidden;
|
|
6132
|
+
background: #ffffff;
|
|
6133
|
+
"
|
|
6134
|
+
>
|
|
6135
|
+
${this.renderThreadsLockedBackgroundMockup()}
|
|
6136
|
+
<div
|
|
6137
|
+
aria-hidden="true"
|
|
6138
|
+
style="
|
|
6139
|
+
position: absolute;
|
|
6140
|
+
inset: 0;
|
|
6141
|
+
pointer-events: none;
|
|
6142
|
+
background:
|
|
6143
|
+
radial-gradient(circle at center, rgba(255,255,255,0.9) 0, rgba(255,255,255,0.78) 24%, rgba(255,255,255,0.34) 48%, rgba(255,255,255,0.56) 100%);
|
|
6144
|
+
"
|
|
6145
|
+
></div>
|
|
6146
|
+
<div
|
|
6147
|
+
style="
|
|
6148
|
+
position: relative;
|
|
6149
|
+
z-index: 1;
|
|
6150
|
+
max-width: 440px;
|
|
6151
|
+
text-align: center;
|
|
6152
|
+
color: #57575b;
|
|
6153
|
+
"
|
|
6154
|
+
>
|
|
6155
|
+
<div
|
|
6156
|
+
aria-hidden="true"
|
|
6157
|
+
style="
|
|
6158
|
+
margin: 0 auto 18px;
|
|
6159
|
+
display: flex;
|
|
6160
|
+
justify-content: center;
|
|
6161
|
+
"
|
|
6162
|
+
>
|
|
6163
|
+
<div
|
|
6164
|
+
style="
|
|
6165
|
+
display: flex;
|
|
6166
|
+
height: 44px;
|
|
6167
|
+
width: 44px;
|
|
6168
|
+
align-items: center;
|
|
6169
|
+
justify-content: center;
|
|
6170
|
+
border: 1px solid #dfd6fb;
|
|
6171
|
+
border-radius: 8px;
|
|
6172
|
+
background: #eee6fe;
|
|
6173
|
+
color: #57575b;
|
|
6174
|
+
box-shadow: 0 8px 18px rgba(87, 87, 91, 0.14);
|
|
6175
|
+
"
|
|
6176
|
+
>
|
|
6177
|
+
${this.renderIcon("Lock")}
|
|
6178
|
+
</div>
|
|
6179
|
+
</div>
|
|
6180
|
+
<h2
|
|
6181
|
+
style="
|
|
6182
|
+
margin: 0 0 8px;
|
|
6183
|
+
font-size: 16px;
|
|
6184
|
+
line-height: 1.35;
|
|
6185
|
+
font-weight: 600;
|
|
6186
|
+
color: #010507;
|
|
6187
|
+
"
|
|
6188
|
+
>
|
|
6189
|
+
Enable Intelligence to inspect Threads.
|
|
6190
|
+
</h2>
|
|
6191
|
+
<p
|
|
6192
|
+
style="
|
|
6193
|
+
margin: 0 auto 18px;
|
|
6194
|
+
max-width: 380px;
|
|
6195
|
+
font-size: 13px;
|
|
6196
|
+
line-height: 1.55;
|
|
6197
|
+
color: #57575b;
|
|
6198
|
+
"
|
|
6199
|
+
>
|
|
6200
|
+
Persist conversations and inspect saved thread history from the
|
|
6201
|
+
Inspector.
|
|
6202
|
+
</p>
|
|
6203
|
+
<div
|
|
6204
|
+
style="
|
|
6205
|
+
display: flex;
|
|
6206
|
+
flex-wrap: wrap;
|
|
6207
|
+
justify-content: center;
|
|
6208
|
+
gap: 8px;
|
|
6209
|
+
"
|
|
6210
|
+
>
|
|
6211
|
+
<a
|
|
6212
|
+
href=${this.getTalkToEngineerUrl()}
|
|
6213
|
+
target="_blank"
|
|
6214
|
+
rel="noopener"
|
|
6215
|
+
style="
|
|
6216
|
+
display: inline-flex;
|
|
6217
|
+
min-height: 34px;
|
|
6218
|
+
align-items: center;
|
|
6219
|
+
justify-content: center;
|
|
6220
|
+
gap: 6px;
|
|
6221
|
+
border-radius: 6px;
|
|
6222
|
+
background: #010507;
|
|
6223
|
+
padding: 8px 12px;
|
|
6224
|
+
font-size: 12px;
|
|
6225
|
+
font-weight: 600;
|
|
6226
|
+
color: #ffffff;
|
|
6227
|
+
text-decoration: none;
|
|
6228
|
+
"
|
|
6229
|
+
@click=${this.handleThreadsTalkToEngineerClick}
|
|
6230
|
+
>
|
|
6231
|
+
Talk to an Engineer
|
|
6232
|
+
</a>
|
|
6233
|
+
<a
|
|
6234
|
+
href=${this.getIntelligenceSignupUrl()}
|
|
6235
|
+
target="_blank"
|
|
6236
|
+
rel="noopener"
|
|
6237
|
+
style="
|
|
6238
|
+
display: inline-flex;
|
|
6239
|
+
min-height: 34px;
|
|
6240
|
+
align-items: center;
|
|
6241
|
+
justify-content: center;
|
|
6242
|
+
gap: 6px;
|
|
6243
|
+
border-radius: 6px;
|
|
6244
|
+
border: 1px solid #dbdbe5;
|
|
6245
|
+
background: #ffffff;
|
|
6246
|
+
padding: 8px 12px;
|
|
6247
|
+
font-size: 12px;
|
|
6248
|
+
font-weight: 600;
|
|
6249
|
+
color: #57575b;
|
|
6250
|
+
text-decoration: none;
|
|
6251
|
+
"
|
|
6252
|
+
@click=${this.handleThreadsIntelligenceSignupClick}
|
|
6253
|
+
>
|
|
6254
|
+
Sign up for Intelligence
|
|
6255
|
+
</a>
|
|
6256
|
+
</div>
|
|
6257
|
+
</div>
|
|
6258
|
+
</div>
|
|
6259
|
+
`;
|
|
6260
|
+
}
|
|
6261
|
+
|
|
5797
6262
|
private renderThreadsView() {
|
|
6263
|
+
if (!this.areThreadEndpointsAvailable()) {
|
|
6264
|
+
return this.renderThreadsLockedView();
|
|
6265
|
+
}
|
|
6266
|
+
|
|
5798
6267
|
const displayThreads =
|
|
5799
6268
|
this.selectedContext === "all-agents"
|
|
5800
6269
|
? this._threads
|
|
@@ -5818,88 +6287,110 @@ ${argsString}</pre
|
|
|
5818
6287
|
? (displayThreads.find((t) => t.id === this.selectedThreadId) ?? null)
|
|
5819
6288
|
: null;
|
|
5820
6289
|
|
|
6290
|
+
if (!threadsErrorMessage) {
|
|
6291
|
+
this.trackThreadsViewStateOnce(
|
|
6292
|
+
displayThreads.length === 0 ? "empty_enabled" : "enabled",
|
|
6293
|
+
displayThreads.length,
|
|
6294
|
+
);
|
|
6295
|
+
}
|
|
6296
|
+
|
|
5821
6297
|
return html`
|
|
5822
|
-
<div style="display:flex;height:100%;overflow:hidden;">
|
|
5823
|
-
<!-- Left sidebar: thread list -->
|
|
6298
|
+
<div style="display:flex;height:100%;overflow:hidden;flex-direction:column;">
|
|
5824
6299
|
<div
|
|
5825
|
-
style="
|
|
6300
|
+
style="display:flex;align-items:center;justify-content:flex-end;border-bottom:1px solid #DBDBE5;background:#ffffff;padding:8px 12px;flex-shrink:0;"
|
|
5826
6301
|
>
|
|
5827
|
-
<
|
|
5828
|
-
|
|
5829
|
-
|
|
5830
|
-
|
|
5831
|
-
|
|
5832
|
-
@
|
|
5833
|
-
|
|
5834
|
-
|
|
5835
|
-
|
|
5836
|
-
></cpk-thread-list>
|
|
6302
|
+
<a
|
|
6303
|
+
href=${this.getTalkToEngineerUrl()}
|
|
6304
|
+
target="_blank"
|
|
6305
|
+
rel="noopener"
|
|
6306
|
+
style="display:inline-flex;align-items:center;gap:6px;border-radius:6px;border:1px solid #dbdbe5;background:#ffffff;padding:7px 10px;font-size:12px;font-weight:600;color:#57575b;text-decoration:none;"
|
|
6307
|
+
@click=${this.handleTalkToEngineerClick}
|
|
6308
|
+
>
|
|
6309
|
+
Talk to an Engineer
|
|
6310
|
+
</a>
|
|
5837
6311
|
</div>
|
|
6312
|
+
<div style="display:flex;min-height:0;flex:1;overflow:hidden;">
|
|
6313
|
+
<!-- Left sidebar: thread list -->
|
|
6314
|
+
<div
|
|
6315
|
+
style="width:${this.threadListWidth}px;flex-shrink:0;overflow:hidden;display:flex;flex-direction:column;border-right:1px solid #DBDBE5;"
|
|
6316
|
+
>
|
|
6317
|
+
<cpk-thread-list
|
|
6318
|
+
style="height:100%;"
|
|
6319
|
+
.threads=${displayThreads}
|
|
6320
|
+
.selectedThreadId=${this.selectedThreadId}
|
|
6321
|
+
.errorMessage=${threadsErrorMessage}
|
|
6322
|
+
@threadSelected=${(e: CustomEvent<string>) => {
|
|
6323
|
+
this.selectedThreadId = e.detail;
|
|
6324
|
+
this.requestUpdate();
|
|
6325
|
+
}}
|
|
6326
|
+
></cpk-thread-list>
|
|
6327
|
+
</div>
|
|
5838
6328
|
|
|
5839
|
-
|
|
5840
|
-
|
|
5841
|
-
|
|
5842
|
-
|
|
5843
|
-
|
|
5844
|
-
|
|
5845
|
-
|
|
5846
|
-
|
|
5847
|
-
|
|
5848
|
-
|
|
5849
|
-
|
|
5850
|
-
|
|
5851
|
-
|
|
5852
|
-
|
|
5853
|
-
|
|
5854
|
-
|
|
5855
|
-
|
|
5856
|
-
|
|
5857
|
-
|
|
5858
|
-
|
|
5859
|
-
|
|
5860
|
-
|
|
5861
|
-
|
|
5862
|
-
|
|
5863
|
-
|
|
5864
|
-
|
|
5865
|
-
|
|
5866
|
-
|
|
5867
|
-
|
|
5868
|
-
|
|
5869
|
-
|
|
5870
|
-
|
|
5871
|
-
|
|
5872
|
-
|
|
5873
|
-
|
|
5874
|
-
|
|
5875
|
-
|
|
5876
|
-
|
|
5877
|
-
|
|
5878
|
-
|
|
5879
|
-
|
|
5880
|
-
|
|
5881
|
-
|
|
5882
|
-
justify-content: center;
|
|
5883
|
-
gap: 8px;
|
|
5884
|
-
color: #838389;
|
|
5885
|
-
"
|
|
5886
|
-
>
|
|
5887
|
-
<svg
|
|
5888
|
-
width="32"
|
|
5889
|
-
height="32"
|
|
5890
|
-
viewBox="0 0 24 24"
|
|
5891
|
-
fill="none"
|
|
5892
|
-
stroke="#c0c0c8"
|
|
5893
|
-
stroke-width="1.5"
|
|
5894
|
-
stroke-linecap="round"
|
|
5895
|
-
stroke-linejoin="round"
|
|
6329
|
+
<!-- Resize divider -->
|
|
6330
|
+
<div
|
|
6331
|
+
style="width:4px;flex-shrink:0;cursor:col-resize;background:transparent;position:relative;z-index:1;"
|
|
6332
|
+
@pointerdown=${this.handleThreadDividerPointerDown}
|
|
6333
|
+
@pointermove=${this.handleThreadDividerPointerMove}
|
|
6334
|
+
@pointerup=${this.handleThreadDividerPointerUp}
|
|
6335
|
+
@pointercancel=${this.handleThreadDividerPointerUp}
|
|
6336
|
+
></div>
|
|
6337
|
+
|
|
6338
|
+
<!-- Center + right: thread details or empty state -->
|
|
6339
|
+
<div style="flex:1;min-width:0;overflow:hidden;display:flex;">
|
|
6340
|
+
${
|
|
6341
|
+
selectedThread
|
|
6342
|
+
? html`<cpk-thread-details
|
|
6343
|
+
style="flex:1;min-width:0;"
|
|
6344
|
+
.threadId=${selectedThread.id}
|
|
6345
|
+
.thread=${selectedThread}
|
|
6346
|
+
.runtimeUrl=${this._core?.runtimeUrl ?? ""}
|
|
6347
|
+
.headers=${this._core?.headers ?? {}}
|
|
6348
|
+
.threadInspectionAvailable=${
|
|
6349
|
+
this._core?.threadEndpoints?.inspect !== false
|
|
6350
|
+
}
|
|
6351
|
+
.liveMessageVersion=${
|
|
6352
|
+
this.liveMessageVersion.get(selectedThread.id) ?? 0
|
|
6353
|
+
}
|
|
6354
|
+
.agentStateInput=${this.getLatestStateForAgent(
|
|
6355
|
+
selectedThread.agentId,
|
|
6356
|
+
)}
|
|
6357
|
+
.agentEventsInput=${
|
|
6358
|
+
this.agentEvents.get(selectedThread.agentId) ?? []
|
|
6359
|
+
}
|
|
6360
|
+
></cpk-thread-details>`
|
|
6361
|
+
: html`
|
|
6362
|
+
<div
|
|
6363
|
+
style="
|
|
6364
|
+
flex: 1;
|
|
6365
|
+
display: flex;
|
|
6366
|
+
flex-direction: column;
|
|
6367
|
+
align-items: center;
|
|
6368
|
+
justify-content: center;
|
|
6369
|
+
gap: 8px;
|
|
6370
|
+
color: #838389;
|
|
6371
|
+
"
|
|
5896
6372
|
>
|
|
5897
|
-
<
|
|
5898
|
-
|
|
5899
|
-
|
|
5900
|
-
|
|
5901
|
-
|
|
5902
|
-
|
|
6373
|
+
<svg
|
|
6374
|
+
width="32"
|
|
6375
|
+
height="32"
|
|
6376
|
+
viewBox="0 0 24 24"
|
|
6377
|
+
fill="none"
|
|
6378
|
+
stroke="#c0c0c8"
|
|
6379
|
+
stroke-width="1.5"
|
|
6380
|
+
stroke-linecap="round"
|
|
6381
|
+
stroke-linejoin="round"
|
|
6382
|
+
>
|
|
6383
|
+
<path d="M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z" />
|
|
6384
|
+
</svg>
|
|
6385
|
+
<span style="font-size: 13px">${
|
|
6386
|
+
displayThreads.length === 0
|
|
6387
|
+
? "No threads yet"
|
|
6388
|
+
: "Select a thread to inspect"
|
|
6389
|
+
}</span>
|
|
6390
|
+
</div>
|
|
6391
|
+
`
|
|
6392
|
+
}
|
|
6393
|
+
</div>
|
|
5903
6394
|
</div>
|
|
5904
6395
|
</div>
|
|
5905
6396
|
`;
|
|
@@ -6571,8 +7062,8 @@ ${prettyEvent}</pre
|
|
|
6571
7062
|
}
|
|
6572
7063
|
|
|
6573
7064
|
if (key === "threads") {
|
|
6574
|
-
if (
|
|
6575
|
-
trackThreadsTabClicked();
|
|
7065
|
+
if (previousMenu !== "threads" && !this.core?.telemetryDisabled) {
|
|
7066
|
+
trackThreadsTabClicked(this.getThreadsTelemetryProps());
|
|
6576
7067
|
}
|
|
6577
7068
|
this.autoSelectLatestThread();
|
|
6578
7069
|
}
|
|
@@ -7252,6 +7743,22 @@ ${prettyEvent}</pre
|
|
|
7252
7743
|
}
|
|
7253
7744
|
</button>
|
|
7254
7745
|
</div>
|
|
7746
|
+
<pre
|
|
7747
|
+
style="
|
|
7748
|
+
margin: 0;
|
|
7749
|
+
max-height: 180px;
|
|
7750
|
+
overflow: auto;
|
|
7751
|
+
white-space: pre-wrap;
|
|
7752
|
+
word-break: break-word;
|
|
7753
|
+
border-radius: 6px;
|
|
7754
|
+
border: 1px solid #eeeef4;
|
|
7755
|
+
background: #f7f7f9;
|
|
7756
|
+
padding: 10px;
|
|
7757
|
+
font-size: 11px;
|
|
7758
|
+
line-height: 1.5;
|
|
7759
|
+
color: #2d2d30;
|
|
7760
|
+
"
|
|
7761
|
+
>${this.formatContextValue(context.value)}</pre>
|
|
7255
7762
|
`
|
|
7256
7763
|
: html`
|
|
7257
7764
|
<div class="flex items-center justify-center py-4 text-xs text-gray-500">
|
|
@@ -7600,10 +8107,15 @@ ${prettyEvent}</pre
|
|
|
7600
8107
|
): Promise<string | null> {
|
|
7601
8108
|
const renderer = new marked.Renderer();
|
|
7602
8109
|
renderer.link = (href, title, text) => {
|
|
7603
|
-
const safeHref = this.escapeHtmlAttr(
|
|
8110
|
+
const safeHref = this.escapeHtmlAttr(
|
|
8111
|
+
this.isSafeAnnouncementHref(href ?? "")
|
|
8112
|
+
? this.appendRefParam(href ?? "")
|
|
8113
|
+
: "#",
|
|
8114
|
+
);
|
|
7604
8115
|
const titleAttr = title ? ` title="${this.escapeHtmlAttr(title)}"` : "";
|
|
7605
8116
|
return `<a href="${safeHref}" target="_blank" rel="noopener"${titleAttr}>${text}</a>`;
|
|
7606
8117
|
};
|
|
8118
|
+
renderer.html = (html) => escapeHtml(html);
|
|
7607
8119
|
renderer.code = (code, lang) => {
|
|
7608
8120
|
const safeLang = (lang ?? "").replace(/[^a-z0-9-]/gi, "");
|
|
7609
8121
|
const langClass = safeLang ? ` class="language-${safeLang}"` : "";
|
|
@@ -7614,6 +8126,24 @@ ${prettyEvent}</pre
|
|
|
7614
8126
|
return marked.parse(markdown, { renderer, async: false });
|
|
7615
8127
|
}
|
|
7616
8128
|
|
|
8129
|
+
private isSafeAnnouncementHref(href: string): boolean {
|
|
8130
|
+
try {
|
|
8131
|
+
const url = new URL(
|
|
8132
|
+
href,
|
|
8133
|
+
typeof window !== "undefined"
|
|
8134
|
+
? window.location.href
|
|
8135
|
+
: "https://copilotkit.ai",
|
|
8136
|
+
);
|
|
8137
|
+
return (
|
|
8138
|
+
url.protocol === "http:" ||
|
|
8139
|
+
url.protocol === "https:" ||
|
|
8140
|
+
url.protocol === "mailto:"
|
|
8141
|
+
);
|
|
8142
|
+
} catch {
|
|
8143
|
+
return false;
|
|
8144
|
+
}
|
|
8145
|
+
}
|
|
8146
|
+
|
|
7617
8147
|
private copyResetTimeouts = new WeakMap<HTMLButtonElement, number>();
|
|
7618
8148
|
|
|
7619
8149
|
private encodeBase64(value: string): string {
|
|
@@ -7678,8 +8208,9 @@ ${prettyEvent}</pre
|
|
|
7678
8208
|
}
|
|
7679
8209
|
};
|
|
7680
8210
|
|
|
7681
|
-
private appendRefParam(href: string): string {
|
|
8211
|
+
private appendRefParam(href: string, ref = "cpk-inspector"): string {
|
|
7682
8212
|
try {
|
|
8213
|
+
const isRootRelative = href.startsWith("/") && !href.startsWith("//");
|
|
7683
8214
|
const url = new URL(
|
|
7684
8215
|
href,
|
|
7685
8216
|
typeof window !== "undefined"
|
|
@@ -7687,7 +8218,7 @@ ${prettyEvent}</pre
|
|
|
7687
8218
|
: "https://copilotkit.ai",
|
|
7688
8219
|
);
|
|
7689
8220
|
if (!url.searchParams.has("ref")) {
|
|
7690
|
-
url.searchParams.append("ref",
|
|
8221
|
+
url.searchParams.append("ref", ref);
|
|
7691
8222
|
}
|
|
7692
8223
|
// Propagate the inspector's anonymous distinct-ID so the website /
|
|
7693
8224
|
// Ops API can call posthog.alias(...) on signup-flow landing and
|
|
@@ -7696,19 +8227,28 @@ ${prettyEvent}</pre
|
|
|
7696
8227
|
// suppresses cross-domain ID leaks too.
|
|
7697
8228
|
if (
|
|
7698
8229
|
!url.searchParams.has("posthog_distinct_id") &&
|
|
7699
|
-
!this.core?.telemetryDisabled
|
|
8230
|
+
!this.core?.telemetryDisabled &&
|
|
8231
|
+
this.isCopilotKitDestination(url)
|
|
7700
8232
|
) {
|
|
7701
8233
|
const distinctId = getTelemetryDistinctIdForUrl();
|
|
7702
8234
|
if (distinctId) {
|
|
7703
8235
|
url.searchParams.append("posthog_distinct_id", distinctId);
|
|
7704
8236
|
}
|
|
7705
8237
|
}
|
|
8238
|
+
if (isRootRelative) {
|
|
8239
|
+
return `${url.pathname}${url.search}${url.hash}`;
|
|
8240
|
+
}
|
|
7706
8241
|
return url.toString();
|
|
7707
8242
|
} catch {
|
|
7708
8243
|
return href;
|
|
7709
8244
|
}
|
|
7710
8245
|
}
|
|
7711
8246
|
|
|
8247
|
+
private isCopilotKitDestination(url: URL): boolean {
|
|
8248
|
+
const hostname = url.hostname.toLowerCase();
|
|
8249
|
+
return hostname === "copilotkit.ai" || hostname.endsWith(".copilotkit.ai");
|
|
8250
|
+
}
|
|
8251
|
+
|
|
7712
8252
|
private escapeHtmlAttr(value: string): string {
|
|
7713
8253
|
return escapeHtml(value).replace(/"/g, """).replace(/'/g, "'");
|
|
7714
8254
|
}
|