@copilotkit/web-inspector 1.69.0 → 1.69.1
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 +2418 -152
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +372 -6
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.mts +372 -6
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +2419 -156
- package/dist/index.mjs.map +1 -1
- package/dist/index.umd.js +3134 -236
- package/dist/index.umd.js.map +1 -1
- package/dist/lib/event-snippets.cjs +559 -0
- package/dist/lib/event-snippets.cjs.map +1 -0
- package/dist/lib/event-snippets.d.cts +61 -0
- package/dist/lib/event-snippets.d.cts.map +1 -0
- package/dist/lib/event-snippets.d.mts +61 -0
- package/dist/lib/event-snippets.d.mts.map +1 -0
- package/dist/lib/event-snippets.mjs +537 -0
- package/dist/lib/event-snippets.mjs.map +1 -0
- package/dist/lib/home-briefing.cjs +23 -3
- package/dist/lib/home-briefing.cjs.map +1 -1
- package/dist/lib/home-briefing.mjs +23 -4
- package/dist/lib/home-briefing.mjs.map +1 -1
- package/dist/lib/inspector-nav.cjs +1 -0
- package/dist/lib/inspector-nav.cjs.map +1 -1
- package/dist/lib/inspector-nav.d.cts +11 -0
- package/dist/lib/inspector-nav.d.cts.map +1 -0
- package/dist/lib/inspector-nav.d.mts +11 -0
- package/dist/lib/inspector-nav.d.mts.map +1 -0
- package/dist/lib/inspector-nav.mjs +1 -0
- package/dist/lib/inspector-nav.mjs.map +1 -1
- package/dist/lib/telemetry.cjs +46 -1
- package/dist/lib/telemetry.cjs.map +1 -1
- package/dist/lib/telemetry.d.cts.map +1 -1
- package/dist/lib/telemetry.d.mts.map +1 -1
- package/dist/lib/telemetry.mjs +44 -2
- package/dist/lib/telemetry.mjs.map +1 -1
- package/dist/package.cjs +1 -1
- package/dist/package.mjs +1 -1
- package/dist/styles/generated.cjs +1 -1
- package/dist/styles/generated.cjs.map +1 -1
- package/dist/styles/generated.mjs +1 -1
- package/dist/styles/generated.mjs.map +1 -1
- package/package.json +3 -3
package/dist/index.cjs
CHANGED
|
@@ -9,6 +9,7 @@ const require_inspector_metadata = require('./lib/inspector-metadata.cjs');
|
|
|
9
9
|
const require_home_briefing = require('./lib/home-briefing.cjs');
|
|
10
10
|
const require_inspector_nav = require('./lib/inspector-nav.cjs');
|
|
11
11
|
const require_thread_selection = require('./lib/thread-selection.cjs');
|
|
12
|
+
const require_event_snippets = require('./lib/event-snippets.cjs');
|
|
12
13
|
const require_telemetry = require('./lib/telemetry.cjs');
|
|
13
14
|
let lit = require("lit");
|
|
14
15
|
let marked = require("marked");
|
|
@@ -34,11 +35,215 @@ const WHATS_NEW_VIEW_LABEL = "What's new";
|
|
|
34
35
|
/** Menu key of the What's new leaf — the news signal's destination. */
|
|
35
36
|
const WHATS_NEW_MENU_KEY = "whats-new";
|
|
36
37
|
const NEWS_SIGNAL_ID = "whats-new";
|
|
37
|
-
const
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
38
|
+
const LAUNCHER_SIGNAL_COLORS = {
|
|
39
|
+
news: "#A78BFA",
|
|
40
|
+
error: "#F87171"
|
|
41
|
+
};
|
|
42
|
+
/**
|
|
43
|
+
* The failure gesture, four phases in series:
|
|
44
|
+
*
|
|
45
|
+
* ```
|
|
46
|
+
* beat 400ms → open 250ms → hold 2500ms → close 250ms (3400ms total)
|
|
47
|
+
* ```
|
|
48
|
+
*
|
|
49
|
+
* Sequential rather than simultaneous, deliberately: the beat says *here*, the
|
|
50
|
+
* pill says *this*. The beat is short so the words arrive quickly.
|
|
51
|
+
*
|
|
52
|
+
* **All four durations live here and nowhere else.** The stylesheet reads the
|
|
53
|
+
* two animated phases as custom properties injected from these numbers rather
|
|
54
|
+
* than restating them, because they are taste and will be tuned by eye after
|
|
55
|
+
* the first live look — tuning the feel must be a number, not a refactor.
|
|
56
|
+
*/
|
|
57
|
+
const ERROR_GESTURE_MS = {
|
|
58
|
+
beat: 400,
|
|
59
|
+
open: 250,
|
|
60
|
+
hold: 2500,
|
|
61
|
+
close: 250
|
|
62
|
+
};
|
|
63
|
+
/**
|
|
64
|
+
* The words the pill carries, which are the words the panel already carries.
|
|
65
|
+
*
|
|
66
|
+
* `Runtime error` is the System Health runtime tile's own label, and
|
|
67
|
+
* `Failed to load threads` is the Threads view's own heading. The outside and
|
|
68
|
+
* the inside must agree, so these are shared rather than paraphrased.
|
|
69
|
+
*/
|
|
70
|
+
const RUNTIME_ERROR_LABEL = "Runtime error";
|
|
71
|
+
const THREADS_LOAD_ERROR_LABEL = "Failed to load threads";
|
|
72
|
+
const AGENT_RUN_FAILED_LABEL = "Agent run failed";
|
|
73
|
+
const TOOL_ERROR_LABEL = "Tool error";
|
|
74
|
+
const MEMORY_LOAD_ERROR_LABEL = "Failed to load learning data";
|
|
75
|
+
/**
|
|
76
|
+
* Copy on the landing view. Titles match the pill.
|
|
77
|
+
*
|
|
78
|
+
* The two fields differ in what they can promise. `advice` is about the
|
|
79
|
+
* reader's next move and is always true. `highlight` is a claim about *this
|
|
80
|
+
* view* — that the failed item is visible below — and the error carries no
|
|
81
|
+
* guarantee of that: a code mapped to `run` can arrive with no run in the
|
|
82
|
+
* buffer at all, and a tool error can arrive without the call id the
|
|
83
|
+
* highlight needs. So it is rendered only once the item is actually there.
|
|
84
|
+
* A card pointing at something the reader cannot find is worse than a card
|
|
85
|
+
* that stays quiet, because it sends them looking.
|
|
86
|
+
*/
|
|
87
|
+
const EVENT_ERROR_GUIDANCE = {
|
|
88
|
+
run: {
|
|
89
|
+
title: AGENT_RUN_FAILED_LABEL,
|
|
90
|
+
highlight: "The failed run event is highlighted below."
|
|
91
|
+
},
|
|
92
|
+
tool: {
|
|
93
|
+
title: TOOL_ERROR_LABEL,
|
|
94
|
+
highlight: "The failed tool call is highlighted below."
|
|
95
|
+
},
|
|
96
|
+
memory: {
|
|
97
|
+
title: MEMORY_LOAD_ERROR_LABEL,
|
|
98
|
+
advice: "Confirm CopilotKit Intelligence is connected, then retry Learning."
|
|
99
|
+
}
|
|
100
|
+
};
|
|
101
|
+
/**
|
|
102
|
+
* The pill's second line, shared by every subject that carries a pill.
|
|
103
|
+
*
|
|
104
|
+
* **This is the one string in the feature that exists nowhere else in the
|
|
105
|
+
* product.** Every other word the launcher shows is word-identical to the
|
|
106
|
+
* panel, which is the standing rule; this line is a deliberate, owner-approved
|
|
107
|
+
* exception to it, because the pill became clickable and an invitation that
|
|
108
|
+
* says nothing is not an invitation.
|
|
109
|
+
*
|
|
110
|
+
* It is shown, never spoken: the polite live region carries the failure class
|
|
111
|
+
* alone. A screen-reader user cannot act on an instruction delivered through
|
|
112
|
+
* an announcement, and it would double the spoken length.
|
|
113
|
+
*/
|
|
114
|
+
const PILL_SUBLINE_LABEL = "Open Inspector for details";
|
|
115
|
+
const HUD_OPEN_INSPECTOR_LABEL = "Open Inspector";
|
|
116
|
+
const HUD_THREADS_OFF_LABEL = "Turn on Threads";
|
|
117
|
+
const HUD_THREADS_ON_LABEL = "Threads on";
|
|
118
|
+
const HUD_INTELLIGENCE_OFF_LABEL = "Turn on Intelligence";
|
|
119
|
+
const HUD_INTELLIGENCE_ON_LABEL = "Intelligence connected";
|
|
120
|
+
const HUD_THREADS_OFF_DETAIL = "Inspect conversations from this app.";
|
|
121
|
+
const HUD_THREADS_ON_DETAIL = "Threads is on. Opens the Threads view.";
|
|
122
|
+
const HUD_INTELLIGENCE_OFF_DETAIL = "Connect Intelligence to use Threads and Learning.";
|
|
123
|
+
const HUD_INTELLIGENCE_ON_DETAIL = "Intelligence is connected. Opens Home.";
|
|
124
|
+
const HUD_LEARNING_OFF_LABEL = "Turn on Learning";
|
|
125
|
+
const HUD_LEARNING_ON_LABEL = "Learning on";
|
|
126
|
+
const HUD_LEARNING_OFF_DETAIL = "Connect Intelligence to use Learning.";
|
|
127
|
+
const HUD_LEARNING_ON_DETAIL = "Learning is on. Opens the Learning view.";
|
|
128
|
+
const HUD_OPEN_INSPECTOR_DETAIL = "Same as clicking the circle. Opens the full Inspector.";
|
|
129
|
+
const LAUNCHER_SIGNALS = {
|
|
130
|
+
"whats-new": {
|
|
131
|
+
tone: "news",
|
|
132
|
+
markerTarget: WHATS_NEW_MENU_KEY,
|
|
133
|
+
landingTarget: "home",
|
|
134
|
+
cadence: 2100,
|
|
135
|
+
priority: 0,
|
|
136
|
+
accessibleLabel: "new content"
|
|
137
|
+
},
|
|
138
|
+
connection: {
|
|
139
|
+
tone: "error",
|
|
140
|
+
markerTarget: "home",
|
|
141
|
+
landingTarget: "home",
|
|
142
|
+
cadence: ERROR_GESTURE_MS.beat,
|
|
143
|
+
priority: 5,
|
|
144
|
+
accessibleLabel: "runtime error",
|
|
145
|
+
pillLabel: RUNTIME_ERROR_LABEL
|
|
146
|
+
},
|
|
147
|
+
threads: {
|
|
148
|
+
tone: "error",
|
|
149
|
+
markerTarget: "threads",
|
|
150
|
+
landingTarget: "threads",
|
|
151
|
+
cadence: ERROR_GESTURE_MS.beat,
|
|
152
|
+
priority: 4,
|
|
153
|
+
accessibleLabel: "thread loading error",
|
|
154
|
+
pillLabel: THREADS_LOAD_ERROR_LABEL
|
|
155
|
+
},
|
|
156
|
+
run: {
|
|
157
|
+
tone: "error",
|
|
158
|
+
markerTarget: "ag-ui-events",
|
|
159
|
+
landingTarget: "ag-ui-events",
|
|
160
|
+
cadence: ERROR_GESTURE_MS.beat,
|
|
161
|
+
priority: 3,
|
|
162
|
+
accessibleLabel: "agent run failed",
|
|
163
|
+
pillLabel: AGENT_RUN_FAILED_LABEL
|
|
164
|
+
},
|
|
165
|
+
tool: {
|
|
166
|
+
tone: "error",
|
|
167
|
+
markerTarget: "agents",
|
|
168
|
+
landingTarget: "agents",
|
|
169
|
+
cadence: ERROR_GESTURE_MS.beat,
|
|
170
|
+
priority: 2,
|
|
171
|
+
accessibleLabel: "tool error",
|
|
172
|
+
pillLabel: TOOL_ERROR_LABEL
|
|
173
|
+
},
|
|
174
|
+
memory: {
|
|
175
|
+
tone: "error",
|
|
176
|
+
markerTarget: "memories",
|
|
177
|
+
landingTarget: "memories",
|
|
178
|
+
cadence: ERROR_GESTURE_MS.beat,
|
|
179
|
+
priority: 1,
|
|
180
|
+
accessibleLabel: "learning error",
|
|
181
|
+
pillLabel: MEMORY_LOAD_ERROR_LABEL
|
|
182
|
+
}
|
|
183
|
+
};
|
|
184
|
+
/** Highest priority first, so the winner of the single dot is the head. */
|
|
185
|
+
const LAUNCHER_SIGNAL_PRIORITY_ORDER = Object.keys(LAUNCHER_SIGNALS).sort((a, b) => LAUNCHER_SIGNALS[b].priority - LAUNCHER_SIGNALS[a].priority);
|
|
186
|
+
/** Wiring *state* — red until the problem heals. */
|
|
187
|
+
const WIRING_ERROR_KEYS = ["connection", "threads"];
|
|
188
|
+
/** Unread *events* — red until the landing view is read. */
|
|
189
|
+
const EVENT_ERROR_KEYS = [
|
|
190
|
+
"run",
|
|
191
|
+
"tool",
|
|
192
|
+
"memory"
|
|
193
|
+
];
|
|
194
|
+
function isWiringErrorKey(key) {
|
|
195
|
+
return WIRING_ERROR_KEYS.includes(key);
|
|
196
|
+
}
|
|
197
|
+
/**
|
|
198
|
+
* Takes a plain string rather than a `LauncherSignalKey`, because one caller
|
|
199
|
+
* reads the subject back out of a `data-` attribute, where the DOM can only
|
|
200
|
+
* offer `string | undefined`. Narrowing untrusted input is what a guard is
|
|
201
|
+
* for; `LauncherSignalKey` still satisfies the parameter, so the callers that
|
|
202
|
+
* already hold one are unaffected.
|
|
203
|
+
*/
|
|
204
|
+
function isEventErrorKey(key) {
|
|
205
|
+
return EVENT_ERROR_KEYS.includes(key);
|
|
206
|
+
}
|
|
207
|
+
/** Narrows a signal key to an error source, excluding the announcement. */
|
|
208
|
+
function isErrorSignalKey(key) {
|
|
209
|
+
return isWiringErrorKey(key) || isEventErrorKey(key);
|
|
210
|
+
}
|
|
211
|
+
/**
|
|
212
|
+
* The control range is the point, not an oversight: an attribute selector has
|
|
213
|
+
* to escape those characters too, and CSS.escape — which the fallback below
|
|
214
|
+
* stands in for — escapes them as well. Hoisted so the suppression can sit on
|
|
215
|
+
* the pattern rather than three lines above it.
|
|
216
|
+
*/
|
|
217
|
+
const SELECTOR_ESCAPE_PATTERN = /[\0-\x1f\x7f!"#$%&'()*+,./:;<=>?@[\\\]^`{|}~]/g;
|
|
218
|
+
/** Attribute selector value. jsdom does not implement CSS.escape. */
|
|
219
|
+
function escapeSelectorValue(value) {
|
|
220
|
+
if (typeof CSS !== "undefined" && typeof CSS.escape === "function") return CSS.escape(value);
|
|
221
|
+
return value.replace(SELECTOR_ESCAPE_PATTERN, "\\$&");
|
|
222
|
+
}
|
|
223
|
+
function eventErrorKeyForCode(code) {
|
|
224
|
+
switch (code) {
|
|
225
|
+
case _copilotkit_core.CopilotKitCoreErrorCode.TOOL_NOT_FOUND:
|
|
226
|
+
case _copilotkit_core.CopilotKitCoreErrorCode.TOOL_HANDLER_FAILED:
|
|
227
|
+
case _copilotkit_core.CopilotKitCoreErrorCode.TOOL_ARGUMENT_PARSE_FAILED:
|
|
228
|
+
case _copilotkit_core.CopilotKitCoreErrorCode.AGENT_NOT_FOUND: return "tool";
|
|
229
|
+
case _copilotkit_core.CopilotKitCoreErrorCode.AGENT_CONNECT_FAILED:
|
|
230
|
+
case _copilotkit_core.CopilotKitCoreErrorCode.AGENT_RUN_FAILED:
|
|
231
|
+
case _copilotkit_core.CopilotKitCoreErrorCode.AGENT_RUN_FAILED_EVENT:
|
|
232
|
+
case _copilotkit_core.CopilotKitCoreErrorCode.AGENT_RUN_ERROR_EVENT: return "run";
|
|
233
|
+
default: return null;
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
/**
|
|
237
|
+
* Coalesce inspector-owned GET /threads sends. The first refresh goes out
|
|
238
|
+
* at once. Further calls in this window share one trailing request, so a
|
|
239
|
+
* flaky network does not fire a burst of list fetches and error cards.
|
|
240
|
+
*/
|
|
241
|
+
const THREAD_LIST_DEBOUNCE_MS = 300;
|
|
242
|
+
/** The launcher's accessible name with nothing wrong. */
|
|
243
|
+
const LAUNCHER_BASE_LABEL = "Web Inspector";
|
|
41
244
|
const EDGE_MARGIN = 16;
|
|
245
|
+
/** HUD card plus the hover bridge. Used to pick left vs right. */
|
|
246
|
+
const LAUNCHER_HUD_WIDTH = 248;
|
|
42
247
|
const DRAG_THRESHOLD = 6;
|
|
43
248
|
const MIN_WINDOW_WIDTH = 880;
|
|
44
249
|
const MIN_WINDOW_WIDTH_DOCKED_LEFT = 640;
|
|
@@ -514,6 +719,7 @@ var CpkThreadList = class extends PortableLitElement {
|
|
|
514
719
|
super(..._args);
|
|
515
720
|
this.threads = [];
|
|
516
721
|
this.selectedThreadId = null;
|
|
722
|
+
this.inAppThreadId = null;
|
|
517
723
|
this.errorMessage = null;
|
|
518
724
|
this.suppressEmptyState = false;
|
|
519
725
|
this._query = "";
|
|
@@ -525,6 +731,7 @@ var CpkThreadList = class extends PortableLitElement {
|
|
|
525
731
|
this.properties = {
|
|
526
732
|
threads: { attribute: false },
|
|
527
733
|
selectedThreadId: { attribute: false },
|
|
734
|
+
inAppThreadId: { attribute: false },
|
|
528
735
|
errorMessage: { attribute: false },
|
|
529
736
|
suppressEmptyState: { attribute: false },
|
|
530
737
|
_query: { state: true }
|
|
@@ -675,6 +882,11 @@ var CpkThreadList = class extends PortableLitElement {
|
|
|
675
882
|
color: #087653;
|
|
676
883
|
}
|
|
677
884
|
|
|
885
|
+
.cpk-tl__pill--in-app {
|
|
886
|
+
background: #bec2ff;
|
|
887
|
+
color: #010507;
|
|
888
|
+
}
|
|
889
|
+
|
|
678
890
|
/* ── Empty state ── */
|
|
679
891
|
.cpk-tl__empty {
|
|
680
892
|
padding: 32px 16px;
|
|
@@ -798,6 +1010,9 @@ var CpkThreadList = class extends PortableLitElement {
|
|
|
798
1010
|
${thread.isExample ? lit.html`
|
|
799
1011
|
<span class="cpk-tl__pill cpk-tl__pill--example">Example</span>
|
|
800
1012
|
` : lit.nothing}
|
|
1013
|
+
${this.inAppThreadId === thread.id ? lit.html`
|
|
1014
|
+
<span class="cpk-tl__pill cpk-tl__pill--in-app">In app</span>
|
|
1015
|
+
` : lit.nothing}
|
|
801
1016
|
</span>
|
|
802
1017
|
</button>
|
|
803
1018
|
`)}
|
|
@@ -864,6 +1079,8 @@ var CpkThreadInspector = class CpkThreadInspector extends PortableLitElement {
|
|
|
864
1079
|
this.agentStateInput = null;
|
|
865
1080
|
this.agentEventsInput = [];
|
|
866
1081
|
this.liveMessageVersion = 0;
|
|
1082
|
+
this.viewInAppMode = "hidden";
|
|
1083
|
+
this.viewInAppError = null;
|
|
867
1084
|
this.focusMessageId = null;
|
|
868
1085
|
this.focusRequestId = 0;
|
|
869
1086
|
this._tab = "timeline";
|
|
@@ -937,6 +1154,8 @@ var CpkThreadInspector = class CpkThreadInspector extends PortableLitElement {
|
|
|
937
1154
|
agentStateInput: { attribute: false },
|
|
938
1155
|
agentEventsInput: { attribute: false },
|
|
939
1156
|
liveMessageVersion: { attribute: false },
|
|
1157
|
+
viewInAppMode: { attribute: false },
|
|
1158
|
+
viewInAppError: { attribute: false },
|
|
940
1159
|
focusMessageId: { attribute: false },
|
|
941
1160
|
focusRequestId: { attribute: false },
|
|
942
1161
|
_tab: { state: true },
|
|
@@ -1259,6 +1478,37 @@ var CpkThreadInspector = class CpkThreadInspector extends PortableLitElement {
|
|
|
1259
1478
|
overflow-wrap: anywhere;
|
|
1260
1479
|
}
|
|
1261
1480
|
|
|
1481
|
+
.cpk-td__view-in-app {
|
|
1482
|
+
appearance: none;
|
|
1483
|
+
flex-shrink: 0;
|
|
1484
|
+
margin: 0;
|
|
1485
|
+
border: 1px solid #5558b2;
|
|
1486
|
+
border-radius: 6px;
|
|
1487
|
+
background: #5558b2;
|
|
1488
|
+
color: #ffffff;
|
|
1489
|
+
font-family: "Plus Jakarta Sans", sans-serif;
|
|
1490
|
+
font-size: 11px;
|
|
1491
|
+
font-weight: 600;
|
|
1492
|
+
padding: 5px 10px;
|
|
1493
|
+
cursor: pointer;
|
|
1494
|
+
}
|
|
1495
|
+
|
|
1496
|
+
.cpk-td__view-in-app:focus-visible {
|
|
1497
|
+
outline: 2px solid #010507;
|
|
1498
|
+
outline-offset: 2px;
|
|
1499
|
+
}
|
|
1500
|
+
|
|
1501
|
+
.cpk-td__view-in-app--stop {
|
|
1502
|
+
background: #ffffff;
|
|
1503
|
+
color: #5558b2;
|
|
1504
|
+
}
|
|
1505
|
+
|
|
1506
|
+
.cpk-td__view-in-app-error {
|
|
1507
|
+
flex-basis: 100%;
|
|
1508
|
+
color: #c0333a;
|
|
1509
|
+
font-size: 11px;
|
|
1510
|
+
}
|
|
1511
|
+
|
|
1262
1512
|
/*
|
|
1263
1513
|
* Each tab's content is wrapped in this panel so the keep-mounted
|
|
1264
1514
|
* inactive panels can be hidden via display:none without disturbing
|
|
@@ -2851,8 +3101,32 @@ var CpkThreadInspector = class CpkThreadInspector extends PortableLitElement {
|
|
|
2851
3101
|
</span>
|
|
2852
3102
|
`)}
|
|
2853
3103
|
</div>
|
|
3104
|
+
${this.renderViewInAppAction()}
|
|
2854
3105
|
${bulkControls}
|
|
2855
3106
|
</div>
|
|
3107
|
+
`;
|
|
3108
|
+
}
|
|
3109
|
+
renderViewInAppAction() {
|
|
3110
|
+
if (this.viewInAppMode === "hidden") return lit.nothing;
|
|
3111
|
+
const isStop = this.viewInAppMode === "stop";
|
|
3112
|
+
return lit.html`
|
|
3113
|
+
<button
|
|
3114
|
+
type="button"
|
|
3115
|
+
class="cpk-td__view-in-app ${isStop ? "cpk-td__view-in-app--stop" : ""}"
|
|
3116
|
+
data-testid="cpk-inspector-view-in-app"
|
|
3117
|
+
aria-label=${isStop ? "Stop viewing this thread in the app" : "View this thread in your app"}
|
|
3118
|
+
@click=${() => {
|
|
3119
|
+
this.dispatchEvent(new CustomEvent(isStop ? "stopViewing" : "viewInApp", {
|
|
3120
|
+
bubbles: true,
|
|
3121
|
+
composed: true
|
|
3122
|
+
}));
|
|
3123
|
+
}}
|
|
3124
|
+
>
|
|
3125
|
+
${isStop ? "Stop viewing" : "View in your app"}
|
|
3126
|
+
</button>
|
|
3127
|
+
${this.viewInAppError ? lit.html`<span class="cpk-td__view-in-app-error" role="alert"
|
|
3128
|
+
>${this.viewInAppError}</span
|
|
3129
|
+
>` : lit.nothing}
|
|
2856
3130
|
`;
|
|
2857
3131
|
}
|
|
2858
3132
|
renderActiveBulkControls() {
|
|
@@ -4132,7 +4406,33 @@ var WebInspectorElement = class WebInspectorElement extends lit.LitElement {
|
|
|
4132
4406
|
inspect: "ag-ui-events"
|
|
4133
4407
|
};
|
|
4134
4408
|
this.lastScrolledAgentNavigationLayout = null;
|
|
4409
|
+
this.eventSnippets = [];
|
|
4410
|
+
this.selectedSnippetId = null;
|
|
4411
|
+
this.snippetRecipe = "tool-call";
|
|
4412
|
+
this.snippetName = "";
|
|
4413
|
+
this.snippetJson = "[]";
|
|
4414
|
+
this.snippetToolName = "";
|
|
4415
|
+
this.snippetToolArgs = "{}";
|
|
4416
|
+
this.snippetReasoningText = "";
|
|
4417
|
+
this.snippetTextContent = "";
|
|
4418
|
+
this.snippetActivityType = "a2ui-surface";
|
|
4419
|
+
this.snippetActivityContent = "{}";
|
|
4420
|
+
this.snippetError = null;
|
|
4421
|
+
this.snippetBanner = null;
|
|
4422
|
+
this.snippetConfirmOpen = false;
|
|
4423
|
+
this.lastInject = null;
|
|
4424
|
+
this.snippetListWidth = 200;
|
|
4425
|
+
this.snippetDividerResizing = false;
|
|
4426
|
+
this.snippetDividerPointerId = -1;
|
|
4427
|
+
this.snippetDividerStartX = 0;
|
|
4428
|
+
this.snippetDividerStartWidth = 0;
|
|
4135
4429
|
this.selectedThreadId = null;
|
|
4430
|
+
this.inAppThreadId = null;
|
|
4431
|
+
this.inAppAgentId = null;
|
|
4432
|
+
this.inAppSource = null;
|
|
4433
|
+
this.activeViewInAppRequestId = null;
|
|
4434
|
+
this.viewInAppError = null;
|
|
4435
|
+
this.inspectorBridgeUnsubscribers = [];
|
|
4136
4436
|
this.selectedRealThreadIsExplicit = false;
|
|
4137
4437
|
this.selectedLocalExampleThreadId = null;
|
|
4138
4438
|
this.requestedThreadId = null;
|
|
@@ -4196,9 +4496,39 @@ var WebInspectorElement = class WebInspectorElement extends lit.LitElement {
|
|
|
4196
4496
|
this.announcementLoaded = false;
|
|
4197
4497
|
this.announcementPromise = null;
|
|
4198
4498
|
this.newsSignalArmed = false;
|
|
4199
|
-
this.
|
|
4200
|
-
this.
|
|
4499
|
+
this.pulsingSignal = null;
|
|
4500
|
+
this.pendingPulseSignal = null;
|
|
4201
4501
|
this.pulseTimeoutId = null;
|
|
4502
|
+
this.errorSignalArmed = {
|
|
4503
|
+
connection: false,
|
|
4504
|
+
threads: false
|
|
4505
|
+
};
|
|
4506
|
+
this.eventErrorArmed = {
|
|
4507
|
+
run: false,
|
|
4508
|
+
tool: false,
|
|
4509
|
+
memory: false
|
|
4510
|
+
};
|
|
4511
|
+
this.eventErrorDetails = {
|
|
4512
|
+
run: null,
|
|
4513
|
+
tool: null,
|
|
4514
|
+
memory: null
|
|
4515
|
+
};
|
|
4516
|
+
this.pendingScrollToEventId = null;
|
|
4517
|
+
this.pendingScrollToToolCallId = null;
|
|
4518
|
+
this.threadRefreshLastSentAt = /* @__PURE__ */ new Map();
|
|
4519
|
+
this.threadRefreshTrailingTimers = /* @__PURE__ */ new Map();
|
|
4520
|
+
this.errorBeatSpent = false;
|
|
4521
|
+
this.errorSignalViewedSources = /* @__PURE__ */ new Set();
|
|
4522
|
+
this.gestureSignal = null;
|
|
4523
|
+
this.pillPhase = null;
|
|
4524
|
+
this.pillDirection = null;
|
|
4525
|
+
this.pillTimeoutId = null;
|
|
4526
|
+
this.launcherHudOpen = false;
|
|
4527
|
+
this.launcherHudSide = "left";
|
|
4528
|
+
this.launcherHudHelp = null;
|
|
4529
|
+
this.launcherHudCloseTimer = null;
|
|
4530
|
+
this.hudLandingMenu = null;
|
|
4531
|
+
this.pillOutcome = null;
|
|
4202
4532
|
this.viewedNewsSignalIds = /* @__PURE__ */ new Set();
|
|
4203
4533
|
this.pendingNewsSignalViewed = null;
|
|
4204
4534
|
this.viewedBannerSurfaces = /* @__PURE__ */ new Set();
|
|
@@ -4272,9 +4602,59 @@ var WebInspectorElement = class WebInspectorElement extends lit.LitElement {
|
|
|
4272
4602
|
this.customTabIcons = { threads: `<svg class="h-3.5 w-3.5" width="15" height="15" viewBox="0 0 15 15" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M9.04167 15C8.29167 15 7.65972 14.7431 7.14583 14.2292C6.63194 13.7153 6.375 13.0972 6.375 12.375C6.375 11.3194 6.80208 10.3646 7.65625 9.51042C8.51042 8.65625 9.57639 8.125 10.8542 7.91667C10.8125 7.41667 10.6875 7.03819 10.4792 6.78125C10.2708 6.52431 9.98611 6.39583 9.625 6.39583C9.20833 6.39583 8.75694 6.56944 8.27083 6.91667C7.78472 7.26389 7.20833 7.83333 6.54167 8.625C5.45833 9.91667 4.66319 10.7569 4.15625 11.1458C3.64931 11.5347 3.10417 11.7292 2.52083 11.7292C1.8125 11.7292 1.21528 11.4653 0.729167 10.9375C0.243056 10.4097 0 9.77083 0 9.02083C0 8.27083 0.163194 7.50347 0.489583 6.71875C0.815972 5.93403 1.36806 4.99306 2.14583 3.89583C2.40972 3.53472 2.60417 3.22917 2.72917 2.97917C2.85417 2.72917 2.91667 2.52778 2.91667 2.375C2.91667 2.27778 2.89931 2.20486 2.86458 2.15625C2.82986 2.10764 2.77778 2.08333 2.70833 2.08333C2.56944 2.08333 2.39583 2.17014 2.1875 2.34375C1.97917 2.51736 1.73611 2.78472 1.45833 3.14583L0 1.66667C0.444444 1.125 0.895833 0.711806 1.35417 0.427083C1.8125 0.142361 2.26389 0 2.70833 0C3.34722 0 3.88889 0.222222 4.33333 0.666667C4.77778 1.11111 5 1.66667 5 2.33333C5 2.73611 4.89583 3.18056 4.6875 3.66667C4.47917 4.15278 4.13194 4.73611 3.64583 5.41667C3.11806 6.16667 2.72569 6.82639 2.46875 7.39583C2.21181 7.96528 2.08333 8.46528 2.08333 8.89583C2.08333 9.13194 2.12153 9.31597 2.19792 9.44792C2.27431 9.57986 2.38194 9.64583 2.52083 9.64583C2.65972 9.64583 2.78125 9.60764 2.88542 9.53125C2.98958 9.45486 3.18056 9.27083 3.45833 8.97917C3.63889 8.78472 3.85417 8.54514 4.10417 8.26042C4.35417 7.97569 4.65972 7.625 5.02083 7.20833C5.89583 6.16667 6.6875 5.42361 7.39583 4.97917C8.10417 4.53472 8.84722 4.3125 9.625 4.3125C10.5556 4.3125 11.3194 4.625 11.9167 5.25C12.5139 5.875 12.8542 6.72917 12.9375 7.8125H15V9.89583H12.9375C12.8264 11.4514 12.4201 12.691 11.7188 13.6146C11.0174 14.5382 10.125 15 9.04167 15ZM9.08333 12.9167C9.52778 12.9167 9.90278 12.6632 10.2083 12.1562C10.5139 11.6493 10.7222 10.9444 10.8333 10.0417C10.1944 10.1944 9.63889 10.4965 9.16667 10.9479C8.69444 11.3993 8.45833 11.8472 8.45833 12.2917C8.45833 12.4861 8.51389 12.6389 8.625 12.75C8.73611 12.8611 8.88889 12.9167 9.08333 12.9167Z" fill="currentColor"/></svg>` };
|
|
4273
4603
|
this.handleDocumentVisibilityChange = () => {
|
|
4274
4604
|
this.accountCtaMotionPaused = document.visibilityState !== "visible";
|
|
4275
|
-
if (document.visibilityState === "visible" &&
|
|
4605
|
+
if (document.visibilityState === "visible" && !this.isOpen) this.flushPendingSignalPulse();
|
|
4606
|
+
this.requestUpdate();
|
|
4607
|
+
};
|
|
4608
|
+
this.handlePillClick = (event) => {
|
|
4609
|
+
event.preventDefault();
|
|
4610
|
+
event.stopPropagation();
|
|
4611
|
+
this.openInspector("floating_button");
|
|
4612
|
+
};
|
|
4613
|
+
this.handleLauncherHudEnter = () => {
|
|
4614
|
+
this.openLauncherHud();
|
|
4615
|
+
};
|
|
4616
|
+
this.handleLauncherHudLeave = () => {
|
|
4617
|
+
if (this.launcherHudCloseTimer !== null) clearTimeout(this.launcherHudCloseTimer);
|
|
4618
|
+
this.launcherHudCloseTimer = setTimeout(() => {
|
|
4619
|
+
this.launcherHudCloseTimer = null;
|
|
4620
|
+
this.closeLauncherHud();
|
|
4621
|
+
}, 160);
|
|
4622
|
+
};
|
|
4623
|
+
this.handleLauncherHudFocusIn = () => {
|
|
4624
|
+
this.openLauncherHud();
|
|
4625
|
+
};
|
|
4626
|
+
this.handleLauncherHudFocusOut = (event) => {
|
|
4627
|
+
const next = event.relatedTarget;
|
|
4628
|
+
const wrapper = event.currentTarget;
|
|
4629
|
+
if (next instanceof Node && wrapper instanceof Node && wrapper.contains(next)) return;
|
|
4630
|
+
this.closeLauncherHud();
|
|
4631
|
+
};
|
|
4632
|
+
this.handleLauncherHudKeydown = (event) => {
|
|
4633
|
+
if (event.key !== "Escape") return;
|
|
4634
|
+
if (!this.launcherHudOpen) return;
|
|
4635
|
+
event.preventDefault();
|
|
4636
|
+
event.stopPropagation();
|
|
4637
|
+
this.closeLauncherHud();
|
|
4638
|
+
this.activeRoot.querySelector(".console-button")?.focus();
|
|
4639
|
+
};
|
|
4640
|
+
this.handleHudActionClick = (event, row) => {
|
|
4641
|
+
event.preventDefault();
|
|
4642
|
+
event.stopPropagation();
|
|
4643
|
+
this.hudLandingMenu = row === "inspector" ? null : row === "threads" ? "threads" : row === "learning" ? "memories" : "home";
|
|
4644
|
+
this.closeLauncherHud();
|
|
4645
|
+
this.openInspector("floating_button");
|
|
4646
|
+
};
|
|
4647
|
+
this.handleHudHelpClick = (event, row) => {
|
|
4648
|
+
event.preventDefault();
|
|
4649
|
+
event.stopPropagation();
|
|
4650
|
+
this.launcherHudHelp = this.launcherHudHelp === row ? null : row;
|
|
4276
4651
|
this.requestUpdate();
|
|
4277
4652
|
};
|
|
4653
|
+
this.handleHudRowClick = (event, row) => {
|
|
4654
|
+
const target = event.target;
|
|
4655
|
+
if (target instanceof Element && target.closest(".cpk-launcher-hud__help, [data-cpk-hud-action]")) return;
|
|
4656
|
+
this.handleHudActionClick(event, row);
|
|
4657
|
+
};
|
|
4278
4658
|
this.handleSidebarToggle = () => {
|
|
4279
4659
|
this.sidebarRailTooltip = null;
|
|
4280
4660
|
this.sidebarCollapsed = !this.sidebarCollapsed;
|
|
@@ -4306,6 +4686,17 @@ var WebInspectorElement = class WebInspectorElement extends lit.LitElement {
|
|
|
4306
4686
|
this.persistState();
|
|
4307
4687
|
this.requestUpdate();
|
|
4308
4688
|
};
|
|
4689
|
+
this.handleEventErrorBannerKeydown = (event) => {
|
|
4690
|
+
if (event.key !== "Enter" && event.key !== " ") return;
|
|
4691
|
+
event.preventDefault();
|
|
4692
|
+
this.refocusEventErrorLanding(event);
|
|
4693
|
+
};
|
|
4694
|
+
this.refocusEventErrorLanding = (event) => {
|
|
4695
|
+
const key = event.currentTarget?.dataset.cpkEventError;
|
|
4696
|
+
if (!key || !isEventErrorKey(key)) return;
|
|
4697
|
+
this.applyEventErrorLanding(key);
|
|
4698
|
+
this.requestUpdate();
|
|
4699
|
+
};
|
|
4309
4700
|
this.handleSystemColorSchemeChange = (event) => {
|
|
4310
4701
|
if (this.hasExplicitColorScheme) return;
|
|
4311
4702
|
this.colorScheme = event.matches ? "dark" : "light";
|
|
@@ -4635,6 +5026,19 @@ var WebInspectorElement = class WebInspectorElement extends lit.LitElement {
|
|
|
4635
5026
|
this.handlePlaygroundStop = () => {
|
|
4636
5027
|
this.playgroundAgent?.abortRun();
|
|
4637
5028
|
};
|
|
5029
|
+
this.handleSnippetImportChange = async (event) => {
|
|
5030
|
+
const input = event.target;
|
|
5031
|
+
const file = input.files?.[0];
|
|
5032
|
+
input.value = "";
|
|
5033
|
+
if (!file) return;
|
|
5034
|
+
try {
|
|
5035
|
+
this.eventSnippets = require_event_snippets.importEventSnippets(await file.text());
|
|
5036
|
+
this.snippetError = null;
|
|
5037
|
+
} catch (error) {
|
|
5038
|
+
this.snippetError = error instanceof Error ? error.message : "Import failed.";
|
|
5039
|
+
}
|
|
5040
|
+
this.requestUpdate();
|
|
5041
|
+
};
|
|
4638
5042
|
this.handleInspectorMetadataActionClick = (action, placement) => {
|
|
4639
5043
|
if (!this.isOpen || this.runtimeStatus !== _copilotkit_core.CopilotKitCoreRuntimeConnectionStatus.Connected || this.core?.telemetryDisabled) return;
|
|
4640
5044
|
if (action.kind === "enable_intelligence") {
|
|
@@ -4662,6 +5066,26 @@ var WebInspectorElement = class WebInspectorElement extends lit.LitElement {
|
|
|
4662
5066
|
if (this.core?.telemetryDisabled) return;
|
|
4663
5067
|
require_telemetry.trackThreadsTalkToEngineerClicked(this.getThreadsCtaTelemetryProps("talk_to_engineer", "threads_locked"));
|
|
4664
5068
|
};
|
|
5069
|
+
this.handleSnippetListDividerPointerDown = (event) => {
|
|
5070
|
+
this.snippetDividerResizing = true;
|
|
5071
|
+
this.snippetDividerPointerId = event.pointerId;
|
|
5072
|
+
this.snippetDividerStartX = event.clientX;
|
|
5073
|
+
this.snippetDividerStartWidth = this.snippetListWidth;
|
|
5074
|
+
event.currentTarget.setPointerCapture(event.pointerId);
|
|
5075
|
+
event.preventDefault();
|
|
5076
|
+
};
|
|
5077
|
+
this.handleSnippetListDividerPointerMove = (event) => {
|
|
5078
|
+
if (!this.snippetDividerResizing || this.snippetDividerPointerId !== event.pointerId) return;
|
|
5079
|
+
const delta = event.clientX - this.snippetDividerStartX;
|
|
5080
|
+
this.snippetListWidth = Math.max(160, Math.min(360, this.snippetDividerStartWidth + delta));
|
|
5081
|
+
this.requestUpdate();
|
|
5082
|
+
};
|
|
5083
|
+
this.handleSnippetListDividerPointerUp = (event) => {
|
|
5084
|
+
if (this.snippetDividerPointerId !== event.pointerId) return;
|
|
5085
|
+
const target = event.currentTarget;
|
|
5086
|
+
if (target.hasPointerCapture(this.snippetDividerPointerId)) target.releasePointerCapture(this.snippetDividerPointerId);
|
|
5087
|
+
this.snippetDividerResizing = false;
|
|
5088
|
+
};
|
|
4665
5089
|
this.handleThreadDividerPointerDown = (event) => {
|
|
4666
5090
|
this.threadDividerResizing = true;
|
|
4667
5091
|
this.threadDividerPointerId = event.pointerId;
|
|
@@ -4682,6 +5106,40 @@ var WebInspectorElement = class WebInspectorElement extends lit.LitElement {
|
|
|
4682
5106
|
if (target.hasPointerCapture(this.threadDividerPointerId)) target.releasePointerCapture(this.threadDividerPointerId);
|
|
4683
5107
|
this.threadDividerResizing = false;
|
|
4684
5108
|
};
|
|
5109
|
+
this.handleViewInApp = () => {
|
|
5110
|
+
const thread = this.getSelectedRealThread();
|
|
5111
|
+
if (!thread) return;
|
|
5112
|
+
if (this.activeViewInAppRequestId && this.inAppAgentId) (0, _copilotkit_core.emitInspectorStopViewing)({
|
|
5113
|
+
requestId: this.activeViewInAppRequestId,
|
|
5114
|
+
agentId: this.inAppAgentId
|
|
5115
|
+
});
|
|
5116
|
+
this.viewInAppError = null;
|
|
5117
|
+
const requestId = (0, _copilotkit_core.createInspectorThreadRequestId)();
|
|
5118
|
+
this.activeViewInAppRequestId = requestId;
|
|
5119
|
+
if (!(0, _copilotkit_core.emitInspectorViewThread)({
|
|
5120
|
+
requestId,
|
|
5121
|
+
threadId: thread.id,
|
|
5122
|
+
agentId: thread.agentId
|
|
5123
|
+
})) {
|
|
5124
|
+
this.activeViewInAppRequestId = null;
|
|
5125
|
+
this.inAppThreadId = null;
|
|
5126
|
+
this.inAppAgentId = null;
|
|
5127
|
+
this.inAppSource = null;
|
|
5128
|
+
this.viewInAppError = "No official chat for this agent is on the page.";
|
|
5129
|
+
}
|
|
5130
|
+
this.requestUpdate();
|
|
5131
|
+
};
|
|
5132
|
+
this.handleStopViewing = () => {
|
|
5133
|
+
const requestId = this.activeViewInAppRequestId;
|
|
5134
|
+
const agentId = this.inAppAgentId;
|
|
5135
|
+
if (!requestId || !agentId) return;
|
|
5136
|
+
this.viewInAppError = null;
|
|
5137
|
+
(0, _copilotkit_core.emitInspectorStopViewing)({
|
|
5138
|
+
requestId,
|
|
5139
|
+
agentId
|
|
5140
|
+
});
|
|
5141
|
+
this.requestUpdate();
|
|
5142
|
+
};
|
|
4685
5143
|
this.handleThreadsExampleOverviewVideoControl = () => {
|
|
4686
5144
|
const video = this.threadsExampleOverviewVideoElement;
|
|
4687
5145
|
if (!video) return;
|
|
@@ -4884,6 +5342,11 @@ var WebInspectorElement = class WebInspectorElement extends lit.LitElement {
|
|
|
4884
5342
|
label: "AG-UI Events",
|
|
4885
5343
|
icon: "Zap"
|
|
4886
5344
|
},
|
|
5345
|
+
{
|
|
5346
|
+
key: "event-snippets",
|
|
5347
|
+
label: "Event Snippets",
|
|
5348
|
+
icon: "Code"
|
|
5349
|
+
},
|
|
4887
5350
|
{
|
|
4888
5351
|
key: "agents",
|
|
4889
5352
|
label: "Agent",
|
|
@@ -5102,7 +5565,7 @@ var WebInspectorElement = class WebInspectorElement extends lit.LitElement {
|
|
|
5102
5565
|
const statusSub = store.select(createThreadStoreStatusSelector()).subscribe(({ error, isLoading }) => {
|
|
5103
5566
|
if (capabilityGeneration !== this.threadCapabilityGeneration || !this.areThreadEndpointsAvailable()) return;
|
|
5104
5567
|
if (error) this._threadsErrorByAgent.set(agentId, error);
|
|
5105
|
-
else this._threadsErrorByAgent.delete(agentId);
|
|
5568
|
+
else if (!isLoading) this._threadsErrorByAgent.delete(agentId);
|
|
5106
5569
|
this._threadsLoadingByAgent.set(agentId, isLoading);
|
|
5107
5570
|
this.requestUpdate();
|
|
5108
5571
|
});
|
|
@@ -5116,7 +5579,7 @@ var WebInspectorElement = class WebInspectorElement extends lit.LitElement {
|
|
|
5116
5579
|
this._threadsLoadingByAgent.set(agentId, (0, _copilotkit_core.ɵselectThreadsIsLoading)(initialState));
|
|
5117
5580
|
const initialError = (0, _copilotkit_core.ɵselectThreadsError)(initialState);
|
|
5118
5581
|
if (initialError) this._threadsErrorByAgent.set(agentId, initialError);
|
|
5119
|
-
else this._threadsErrorByAgent.delete(agentId);
|
|
5582
|
+
else if (!(0, _copilotkit_core.ɵselectThreadsIsLoading)(initialState)) this._threadsErrorByAgent.delete(agentId);
|
|
5120
5583
|
this.rebuildFlattenedThreads();
|
|
5121
5584
|
this.autoSelectLatestThread();
|
|
5122
5585
|
}
|
|
@@ -5197,8 +5660,28 @@ var WebInspectorElement = class WebInspectorElement extends lit.LitElement {
|
|
|
5197
5660
|
if (!this.areThreadEndpointsAvailable()) return;
|
|
5198
5661
|
const store = this._ownedThreadStores.get(agentId);
|
|
5199
5662
|
if (!store) return;
|
|
5663
|
+
const now = Date.now();
|
|
5664
|
+
const waitMs = THREAD_LIST_DEBOUNCE_MS - (now - (this.threadRefreshLastSentAt.get(agentId) ?? 0));
|
|
5665
|
+
if (waitMs <= 0) {
|
|
5666
|
+
this.sendOwnedThreadRefresh(agentId, store, now);
|
|
5667
|
+
return;
|
|
5668
|
+
}
|
|
5669
|
+
if (this.threadRefreshTrailingTimers.has(agentId)) return;
|
|
5670
|
+
this.threadRefreshTrailingTimers.set(agentId, setTimeout(() => {
|
|
5671
|
+
this.threadRefreshTrailingTimers.delete(agentId);
|
|
5672
|
+
const current = this._ownedThreadStores.get(agentId);
|
|
5673
|
+
if (!current) return;
|
|
5674
|
+
this.sendOwnedThreadRefresh(agentId, current, Date.now());
|
|
5675
|
+
}, waitMs));
|
|
5676
|
+
}
|
|
5677
|
+
sendOwnedThreadRefresh(agentId, store, sentAt) {
|
|
5678
|
+
this.threadRefreshLastSentAt.set(agentId, sentAt);
|
|
5200
5679
|
store.refresh();
|
|
5201
5680
|
}
|
|
5681
|
+
cancelThreadRefreshDebounce() {
|
|
5682
|
+
for (const timer of this.threadRefreshTrailingTimers.values()) clearTimeout(timer);
|
|
5683
|
+
this.threadRefreshTrailingTimers.clear();
|
|
5684
|
+
}
|
|
5202
5685
|
updateOwnedThreadStoreHeaders(headers) {
|
|
5203
5686
|
if (!this.areThreadEndpointsAvailable()) return;
|
|
5204
5687
|
const core = this.core;
|
|
@@ -5254,6 +5737,7 @@ var WebInspectorElement = class WebInspectorElement extends lit.LitElement {
|
|
|
5254
5737
|
this.runtimeStatus = core.runtimeConnectionStatus;
|
|
5255
5738
|
this.coreProperties = core.properties;
|
|
5256
5739
|
this.lastCoreError = null;
|
|
5740
|
+
this.clearAllEventErrors();
|
|
5257
5741
|
const supportsInspectorMetadata = this.coreSupportsInspectorMetadata(core);
|
|
5258
5742
|
this.updateInspectorMetadataProjection(this.readCoreInspectorMetadata(core));
|
|
5259
5743
|
this.coreSubscriber = {
|
|
@@ -5289,11 +5773,12 @@ var WebInspectorElement = class WebInspectorElement extends lit.LitElement {
|
|
|
5289
5773
|
this.updateInspectorMetadataProjection(inspectorMetadata);
|
|
5290
5774
|
this.requestUpdate();
|
|
5291
5775
|
} } : {},
|
|
5292
|
-
onError: ({ code, error }) => {
|
|
5776
|
+
onError: ({ code, error, context }) => {
|
|
5293
5777
|
this.lastCoreError = {
|
|
5294
5778
|
code,
|
|
5295
5779
|
message: error.message
|
|
5296
5780
|
};
|
|
5781
|
+
this.armEventErrorFromCode(code, error.message, context);
|
|
5297
5782
|
this.requestUpdate();
|
|
5298
5783
|
},
|
|
5299
5784
|
onAgentsChanged: ({ agents }) => {
|
|
@@ -5386,6 +5871,7 @@ var WebInspectorElement = class WebInspectorElement extends lit.LitElement {
|
|
|
5386
5871
|
}),
|
|
5387
5872
|
memoryStore.select(_copilotkit_core.ɵselectMemoriesError).subscribe((v) => {
|
|
5388
5873
|
this._memoriesError = v;
|
|
5874
|
+
if (v) this.armEventError("memory", v.message);
|
|
5389
5875
|
this.requestUpdate();
|
|
5390
5876
|
}),
|
|
5391
5877
|
memoryStore.select(_copilotkit_core.ɵselectMemoriesAvailable).subscribe((v) => {
|
|
@@ -5472,10 +5958,12 @@ var WebInspectorElement = class WebInspectorElement extends lit.LitElement {
|
|
|
5472
5958
|
this._recallQuery = "";
|
|
5473
5959
|
this.coreSubscriber = null;
|
|
5474
5960
|
this.runtimeStatus = null;
|
|
5961
|
+
this.cancelThreadRefreshDebounce();
|
|
5475
5962
|
this.inspectorMetadataValue = void 0;
|
|
5476
5963
|
this.inspectorMetadataProjection = require_inspector_metadata.projectInspectorMetadata(void 0, void 0);
|
|
5477
5964
|
this.metadataTelemetryFingerprints.clear();
|
|
5478
5965
|
this.lastCoreError = null;
|
|
5966
|
+
this.clearAllEventErrors();
|
|
5479
5967
|
this.coreProperties = {};
|
|
5480
5968
|
this.cachedTools = [];
|
|
5481
5969
|
this.toolSignature = "";
|
|
@@ -5789,6 +6277,19 @@ var WebInspectorElement = class WebInspectorElement extends lit.LitElement {
|
|
|
5789
6277
|
this.persistState();
|
|
5790
6278
|
this.requestUpdate();
|
|
5791
6279
|
}
|
|
6280
|
+
focusEventSnippets(options) {
|
|
6281
|
+
this.pendingPersistedMenu = null;
|
|
6282
|
+
this.selectedMenu = "event-snippets";
|
|
6283
|
+
this.settingsOpen = false;
|
|
6284
|
+
this.lastSelectedMenuByGroup.inspect = "event-snippets";
|
|
6285
|
+
this.contextMenuOpen = false;
|
|
6286
|
+
this.layoutMenuOpen = false;
|
|
6287
|
+
this.reloadEventSnippets();
|
|
6288
|
+
if (options.snippetId) this.selectEventSnippet(options.snippetId);
|
|
6289
|
+
if (options.agentId && this.contextOptions.some((option) => option.key === options.agentId)) this.selectedContext = options.agentId;
|
|
6290
|
+
this.persistState();
|
|
6291
|
+
this.requestUpdate();
|
|
6292
|
+
}
|
|
5792
6293
|
filterEvents(events) {
|
|
5793
6294
|
const query = this.eventFilterText.trim().toLowerCase();
|
|
5794
6295
|
return events.filter((event) => {
|
|
@@ -5834,22 +6335,28 @@ var WebInspectorElement = class WebInspectorElement extends lit.LitElement {
|
|
|
5834
6335
|
}
|
|
5835
6336
|
renderToolCallDetails(toolCalls) {
|
|
5836
6337
|
if (!Array.isArray(toolCalls) || toolCalls.length === 0) return lit.nothing;
|
|
6338
|
+
const toolError = this.eventErrorDetails.tool;
|
|
5837
6339
|
return lit.html`
|
|
5838
6340
|
<div class="mt-2 space-y-2">
|
|
5839
6341
|
${toolCalls.map((call, index) => {
|
|
5840
6342
|
const functionName = call.function?.name ?? call.toolName ?? "Unknown function";
|
|
5841
6343
|
const callId = typeof call?.id === "string" ? call.id : `tool-call-${index + 1}`;
|
|
5842
6344
|
const argsString = this.formatToolCallArguments(call.function?.arguments);
|
|
6345
|
+
const isFailedCall = toolError?.toolCallId !== void 0 && toolError.toolCallId === callId;
|
|
5843
6346
|
return lit.html`
|
|
5844
6347
|
<div
|
|
5845
|
-
class
|
|
6348
|
+
class=${isFailedCall ? "rounded-md border border-rose-300 bg-rose-50 p-3 text-xs text-gray-900" : "rounded-md border border-gray-200 bg-gray-50 p-3 text-xs text-gray-700"}
|
|
6349
|
+
data-cpk-failed-tool-call=${isFailedCall ? callId : void 0}
|
|
5846
6350
|
>
|
|
5847
6351
|
<div
|
|
5848
6352
|
class="flex flex-wrap items-center justify-between gap-1 font-medium text-gray-900"
|
|
5849
6353
|
>
|
|
5850
|
-
<span>${functionName}</span>
|
|
5851
|
-
<span class="text-[10px] text-gray-
|
|
6354
|
+
<span>${functionName}${isFailedCall ? " failed" : ""}</span>
|
|
6355
|
+
<span class="text-[10px] text-gray-600">ID: ${callId}</span>
|
|
5852
6356
|
</div>
|
|
6357
|
+
${isFailedCall && toolError?.message ? lit.html`<p class="mt-2 break-words leading-relaxed text-gray-800">
|
|
6358
|
+
${toolError.message}
|
|
6359
|
+
</p>` : lit.nothing}
|
|
5853
6360
|
${argsString ? lit.html`<pre
|
|
5854
6361
|
class="mt-2 overflow-auto rounded bg-white p-2 text-[11px] leading-relaxed text-gray-800"
|
|
5855
6362
|
>
|
|
@@ -6001,18 +6508,28 @@ ${argsString}</pre
|
|
|
6001
6508
|
.console-button-wrapper {
|
|
6002
6509
|
position: relative;
|
|
6003
6510
|
display: inline-flex;
|
|
6004
|
-
|
|
6005
|
-
|
|
6006
|
-
|
|
6511
|
+
/* The launcher's surface and edge, shared by the button and the pill so
|
|
6512
|
+
the two cannot drift apart. A dark grey rather than near-black: the
|
|
6513
|
+
launcher sits on a customer's page, and 1,5,7 against white is a
|
|
6514
|
+
harder edge than this surface needs. */
|
|
6515
|
+
--cpk-launcher-face: rgba(28, 31, 36, 0.95);
|
|
6516
|
+
--cpk-launcher-face-solid: rgb(28, 31, 36);
|
|
6517
|
+
--cpk-launcher-edge: rgba(190, 194, 255, 0.25);
|
|
6007
6518
|
/* The launcher's own size, exposed so the signal dot can be placed
|
|
6008
6519
|
against the OUTER rim with a length rather than a percentage.
|
|
6009
6520
|
Percentages resolve against the padding box, which the 1px border
|
|
6010
|
-
insets, and the dot would land inside the rim.
|
|
6521
|
+
insets, and the dot would land inside the rim.
|
|
6522
|
+
|
|
6523
|
+
Declared on the wrapper rather than on the button so the pill, which
|
|
6524
|
+
is the button's sibling, can clear the mark by the same length. */
|
|
6011
6525
|
--cpk-launcher-size: clamp(
|
|
6012
6526
|
${LAUNCHER_MIN_SIZE}px,
|
|
6013
6527
|
7vw,
|
|
6014
6528
|
${LAUNCHER_MAX_SIZE}px
|
|
6015
6529
|
);
|
|
6530
|
+
}
|
|
6531
|
+
|
|
6532
|
+
.console-button {
|
|
6016
6533
|
width: var(--cpk-launcher-size);
|
|
6017
6534
|
height: var(--cpk-launcher-size);
|
|
6018
6535
|
/* Keep the 1px border inside the declared outer size. */
|
|
@@ -6414,14 +6931,14 @@ ${argsString}</pre
|
|
|
6414
6931
|
|
|
6415
6932
|
/* ── Floating button ─────────────────────────────────────────── */
|
|
6416
6933
|
.console-button {
|
|
6417
|
-
background-color:
|
|
6418
|
-
border-color:
|
|
6934
|
+
background-color: var(--cpk-launcher-face) !important;
|
|
6935
|
+
border-color: var(--cpk-launcher-edge) !important;
|
|
6419
6936
|
box-shadow:
|
|
6420
6937
|
0 0 0 1px rgba(190, 194, 255, 0.15),
|
|
6421
6938
|
0 4px 14px rgba(1, 5, 7, 0.28) !important;
|
|
6422
6939
|
}
|
|
6423
6940
|
.console-button:hover {
|
|
6424
|
-
background-color:
|
|
6941
|
+
background-color: var(--cpk-launcher-face-solid) !important;
|
|
6425
6942
|
border-color: rgba(190, 194, 255, 0.45) !important;
|
|
6426
6943
|
}
|
|
6427
6944
|
.console-button:focus-visible {
|
|
@@ -6439,7 +6956,6 @@ ${argsString}</pre
|
|
|
6439
6956
|
* that forces a repaint every frame is not acceptable.
|
|
6440
6957
|
*/
|
|
6441
6958
|
.console-button[data-cpk-signal] {
|
|
6442
|
-
--cpk-launcher-face: rgba(1, 5, 7, 0.95);
|
|
6443
6959
|
isolation: isolate;
|
|
6444
6960
|
}
|
|
6445
6961
|
|
|
@@ -6549,11 +7065,197 @@ ${argsString}</pre
|
|
|
6549
7065
|
box-shadow: 0 0 0 1.5px var(--cpk-launcher-face);
|
|
6550
7066
|
}
|
|
6551
7067
|
|
|
7068
|
+
/* ── Launcher pill: the launcher opens sideways and says what ─── */
|
|
7069
|
+
/*
|
|
7070
|
+
* The pill is laid out at its FULL width from the first frame and
|
|
7071
|
+
* revealed by animating a rectangular clip. Nothing is scaled and
|
|
7072
|
+
* nothing is resized.
|
|
7073
|
+
*
|
|
7074
|
+
* That is not a stylistic choice. This component is permanently mounted
|
|
7075
|
+
* on top of a customer's application, so no property that forces a
|
|
7076
|
+
* layout on every frame is acceptable — and animating "width" does
|
|
7077
|
+
* exactly that, sixty times a second, on someone else's page. A clip
|
|
7078
|
+
* leaves the element's geometry constant and changes only the visible
|
|
7079
|
+
* region, which the compositor handles. Animating a horizontal scale
|
|
7080
|
+
* was the other candidate and squashes the mark itself, not merely the
|
|
7081
|
+
* rounded end, so the logo would need counter-scaling and the dot and
|
|
7082
|
+
* halo would become ellipses.
|
|
7083
|
+
*
|
|
7084
|
+
* The launcher's own face and border are repeated here so the two form
|
|
7085
|
+
* one capsule: the button paints last and therefore on top, with no
|
|
7086
|
+
* z-index needed. The mark's own ring and shadow are deliberately left
|
|
7087
|
+
* alone for the whole gesture — the circle's outline staying visible
|
|
7088
|
+
* inside the open pill was looked at against the alternative and kept.
|
|
7089
|
+
*
|
|
7090
|
+
* A column, not a row: the pill carries a heading and a subline stacked,
|
|
7091
|
+
* centred against a height that does not change. "justify-content"
|
|
7092
|
+
* centres the pair vertically and "align-items" keeps both lines flush
|
|
7093
|
+
* left, so the pill never grows taller than the launcher it opens from.
|
|
7094
|
+
*/
|
|
7095
|
+
.cpk-launcher-pill {
|
|
7096
|
+
position: absolute;
|
|
7097
|
+
top: 50%;
|
|
7098
|
+
margin-top: calc(var(--cpk-launcher-size) / -2);
|
|
7099
|
+
height: var(--cpk-launcher-size);
|
|
7100
|
+
display: inline-flex;
|
|
7101
|
+
flex-direction: column;
|
|
7102
|
+
justify-content: center;
|
|
7103
|
+
align-items: flex-start;
|
|
7104
|
+
gap: 1px;
|
|
7105
|
+
box-sizing: border-box;
|
|
7106
|
+
border-radius: 999px;
|
|
7107
|
+
border: 1px solid var(--cpk-launcher-edge);
|
|
7108
|
+
background: var(--cpk-launcher-face);
|
|
7109
|
+
color: #ffffff;
|
|
7110
|
+
white-space: nowrap;
|
|
7111
|
+
pointer-events: none;
|
|
7112
|
+
opacity: 0;
|
|
7113
|
+
}
|
|
7114
|
+
|
|
7115
|
+
/* The failure class, word-identical to the panel's own wording. */
|
|
7116
|
+
.cpk-launcher-pill__heading {
|
|
7117
|
+
font-size: 12px;
|
|
7118
|
+
font-weight: 600;
|
|
7119
|
+
line-height: 1.2;
|
|
7120
|
+
}
|
|
7121
|
+
|
|
7122
|
+
/*
|
|
7123
|
+
* The one line of copy in this feature that exists nowhere else in the
|
|
7124
|
+
* product. The heading above is word-identical to the panel, which is
|
|
7125
|
+
* the standing rule; this line is a deliberate, owner-approved exception
|
|
7126
|
+
* to it, because the pill is now clickable and has to say so.
|
|
7127
|
+
*
|
|
7128
|
+
* It is NOT spoken. A screen-reader user cannot act on an instruction
|
|
7129
|
+
* delivered through an announcement, and it would double the spoken
|
|
7130
|
+
* length — so the live region carries the failure class alone.
|
|
7131
|
+
*/
|
|
7132
|
+
.cpk-launcher-pill__subline {
|
|
7133
|
+
font-size: 10.5px;
|
|
7134
|
+
font-weight: 500;
|
|
7135
|
+
line-height: 1.2;
|
|
7136
|
+
opacity: 0.72;
|
|
7137
|
+
}
|
|
7138
|
+
|
|
7139
|
+
/*
|
|
7140
|
+
* Two directions, one animation with the inset on the other side. The
|
|
7141
|
+
* padding on the launcher's side clears the mark, so the words never sit
|
|
7142
|
+
* under it. The text-side padding is derived from the capsule's radius
|
|
7143
|
+
* (half the launcher size), NOT a bare literal: padding is measured from
|
|
7144
|
+
* the bounding box, but the first half-height of that side is the rounded
|
|
7145
|
+
* cap. Half the size lands the text exactly where the cap ends and the
|
|
7146
|
+
* straight edge begins. A literal 14px put it 16px inside the curve at the
|
|
7147
|
+
* production launcher size, which is itself a clamp on the viewport.
|
|
7148
|
+
*/
|
|
7149
|
+
.cpk-launcher-pill[data-cpk-pill-direction="left"] {
|
|
7150
|
+
right: 0;
|
|
7151
|
+
padding: 0 calc(var(--cpk-launcher-size) + 12px) 0
|
|
7152
|
+
calc(var(--cpk-launcher-size) / 2);
|
|
7153
|
+
clip-path: inset(0 0 0 calc(100% - var(--cpk-launcher-size)));
|
|
7154
|
+
}
|
|
7155
|
+
.cpk-launcher-pill[data-cpk-pill-direction="right"] {
|
|
7156
|
+
left: 0;
|
|
7157
|
+
padding: 0 calc(var(--cpk-launcher-size) / 2) 0
|
|
7158
|
+
calc(var(--cpk-launcher-size) + 12px);
|
|
7159
|
+
clip-path: inset(0 calc(100% - var(--cpk-launcher-size)) 0 0);
|
|
7160
|
+
}
|
|
7161
|
+
|
|
7162
|
+
/*
|
|
7163
|
+
* "round" on both stops, so the revealing edge is the capsule's own
|
|
7164
|
+
* rounded end travelling sideways rather than a straight vertical line
|
|
7165
|
+
* wiping across it. An unrounded inset reads as a wipe; this reads as an
|
|
7166
|
+
* opening. It adds no animated property: the clip is still the clip.
|
|
7167
|
+
*/
|
|
7168
|
+
@keyframes cpk-launcher-pill-left {
|
|
7169
|
+
0% {
|
|
7170
|
+
opacity: 0;
|
|
7171
|
+
clip-path: inset(
|
|
7172
|
+
0 0 0 calc(100% - var(--cpk-launcher-size)) round 999px
|
|
7173
|
+
);
|
|
7174
|
+
}
|
|
7175
|
+
100% {
|
|
7176
|
+
opacity: 1;
|
|
7177
|
+
clip-path: inset(0 0 0 0 round 999px);
|
|
7178
|
+
}
|
|
7179
|
+
}
|
|
7180
|
+
|
|
7181
|
+
@keyframes cpk-launcher-pill-right {
|
|
7182
|
+
0% {
|
|
7183
|
+
opacity: 0;
|
|
7184
|
+
clip-path: inset(
|
|
7185
|
+
0 calc(100% - var(--cpk-launcher-size)) 0 0 round 999px
|
|
7186
|
+
);
|
|
7187
|
+
}
|
|
7188
|
+
100% {
|
|
7189
|
+
opacity: 1;
|
|
7190
|
+
clip-path: inset(0 0 0 0 round 999px);
|
|
7191
|
+
}
|
|
7192
|
+
}
|
|
7193
|
+
|
|
7194
|
+
/*
|
|
7195
|
+
* The pill takes the pointer exactly while it is on screen, so the
|
|
7196
|
+
* instruction it now carries is honest: a click on it opens the
|
|
7197
|
+
* Inspector, the same action as pressing the mark. During the beat the
|
|
7198
|
+
* clip covers only the mark itself, and a click target nobody can see
|
|
7199
|
+
* over someone else's page is not something to ship — so the base rule
|
|
7200
|
+
* keeps "pointer-events: none" and only the three visible phases take it
|
|
7201
|
+
* back.
|
|
7202
|
+
* The button paints last and therefore wins the pointer where the two
|
|
7203
|
+
* overlap, so dragging the launcher is unaffected throughout.
|
|
7204
|
+
*/
|
|
7205
|
+
.cpk-launcher-pill[data-cpk-pill-phase="opening"],
|
|
7206
|
+
.cpk-launcher-pill[data-cpk-pill-phase="holding"],
|
|
7207
|
+
.cpk-launcher-pill[data-cpk-pill-phase="closing"] {
|
|
7208
|
+
pointer-events: auto;
|
|
7209
|
+
cursor: pointer;
|
|
7210
|
+
}
|
|
7211
|
+
|
|
7212
|
+
/* Closing is the same animation played backwards, so the two phases can
|
|
7213
|
+
never drift apart. */
|
|
7214
|
+
.cpk-launcher-pill[data-cpk-pill-phase="opening"],
|
|
7215
|
+
.cpk-launcher-pill[data-cpk-pill-phase="closing"] {
|
|
7216
|
+
animation-timing-function: cubic-bezier(0.16, 1, 0.3, 1);
|
|
7217
|
+
animation-iteration-count: 1;
|
|
7218
|
+
animation-fill-mode: forwards;
|
|
7219
|
+
}
|
|
7220
|
+
.cpk-launcher-pill[data-cpk-pill-phase="opening"] {
|
|
7221
|
+
animation-duration: var(--cpk-launcher-pill-open);
|
|
7222
|
+
}
|
|
7223
|
+
.cpk-launcher-pill[data-cpk-pill-phase="closing"] {
|
|
7224
|
+
animation-duration: var(--cpk-launcher-pill-close);
|
|
7225
|
+
animation-direction: reverse;
|
|
7226
|
+
}
|
|
7227
|
+
.cpk-launcher-pill[data-cpk-pill-phase="opening"][data-cpk-pill-direction="left"],
|
|
7228
|
+
.cpk-launcher-pill[data-cpk-pill-phase="closing"][data-cpk-pill-direction="left"] {
|
|
7229
|
+
animation-name: cpk-launcher-pill-left;
|
|
7230
|
+
}
|
|
7231
|
+
.cpk-launcher-pill[data-cpk-pill-phase="opening"][data-cpk-pill-direction="right"],
|
|
7232
|
+
.cpk-launcher-pill[data-cpk-pill-phase="closing"][data-cpk-pill-direction="right"] {
|
|
7233
|
+
animation-name: cpk-launcher-pill-right;
|
|
7234
|
+
}
|
|
7235
|
+
|
|
7236
|
+
/* The hold is the end state of the reveal, held. */
|
|
7237
|
+
.cpk-launcher-pill[data-cpk-pill-phase="holding"] {
|
|
7238
|
+
opacity: 1;
|
|
7239
|
+
clip-path: inset(0 0 0 0);
|
|
7240
|
+
}
|
|
7241
|
+
|
|
6552
7242
|
/*
|
|
6553
7243
|
* Reduced motion: the halo is held statically rather than animated, so
|
|
6554
7244
|
* the information arrives without the movement.
|
|
6555
7245
|
*/
|
|
6556
7246
|
@media (prefers-reduced-motion: reduce) {
|
|
7247
|
+
/*
|
|
7248
|
+
* The pill is shown by opacity alone, with no clip animation and the
|
|
7249
|
+
* same hold. The instruction is to reduce motion, not to withhold
|
|
7250
|
+
* information, and this reader needs the label as much as anyone.
|
|
7251
|
+
*/
|
|
7252
|
+
.cpk-launcher-pill[data-cpk-pill-phase="opening"],
|
|
7253
|
+
.cpk-launcher-pill[data-cpk-pill-phase="holding"],
|
|
7254
|
+
.cpk-launcher-pill[data-cpk-pill-phase="closing"] {
|
|
7255
|
+
animation: none !important;
|
|
7256
|
+
opacity: 1;
|
|
7257
|
+
clip-path: inset(0 0 0 0);
|
|
7258
|
+
}
|
|
6557
7259
|
.cpk-launcher-signal-wash {
|
|
6558
7260
|
opacity: 0.85;
|
|
6559
7261
|
}
|
|
@@ -6573,58 +7275,275 @@ ${argsString}</pre
|
|
|
6573
7275
|
}
|
|
6574
7276
|
}
|
|
6575
7277
|
|
|
6576
|
-
/*
|
|
6577
|
-
|
|
6578
|
-
|
|
6579
|
-
|
|
6580
|
-
|
|
6581
|
-
|
|
6582
|
-
.inspector-nav-signal-dot {
|
|
6583
|
-
display: inline-block;
|
|
6584
|
-
flex: none;
|
|
6585
|
-
width: 6px;
|
|
6586
|
-
height: 6px;
|
|
6587
|
-
border-radius: 50%;
|
|
6588
|
-
background: ${(0, lit.unsafeCSS)(NEWS_SIGNAL_COLOR)};
|
|
7278
|
+
/* ── Launcher HUD: hover menu, quieter than the error island ── */
|
|
7279
|
+
.console-button-wrapper[data-cpk-hud="open"] .cpk-launcher-hud {
|
|
7280
|
+
pointer-events: auto;
|
|
7281
|
+
opacity: 1;
|
|
7282
|
+
transform: none;
|
|
7283
|
+
visibility: visible;
|
|
6589
7284
|
}
|
|
6590
7285
|
|
|
6591
|
-
|
|
6592
|
-
|
|
6593
|
-
|
|
6594
|
-
|
|
6595
|
-
|
|
7286
|
+
.cpk-launcher-hud {
|
|
7287
|
+
position: absolute;
|
|
7288
|
+
top: 0;
|
|
7289
|
+
z-index: 4;
|
|
7290
|
+
padding-right: 14px;
|
|
7291
|
+
pointer-events: none;
|
|
7292
|
+
opacity: 0;
|
|
7293
|
+
visibility: hidden;
|
|
7294
|
+
transform: translateX(8px);
|
|
7295
|
+
transition:
|
|
7296
|
+
opacity 160ms ease,
|
|
7297
|
+
transform 200ms cubic-bezier(0.16, 1, 0.3, 1);
|
|
6596
7298
|
}
|
|
6597
7299
|
|
|
6598
|
-
|
|
6599
|
-
|
|
6600
|
-
|
|
6601
|
-
|
|
7300
|
+
.cpk-launcher-hud[data-cpk-hud-side="left"] {
|
|
7301
|
+
right: 100%;
|
|
7302
|
+
padding-right: 14px;
|
|
7303
|
+
padding-left: 0;
|
|
6602
7304
|
}
|
|
6603
7305
|
|
|
6604
|
-
.
|
|
6605
|
-
|
|
6606
|
-
|
|
6607
|
-
|
|
6608
|
-
|
|
6609
|
-
|
|
6610
|
-
) !important;
|
|
6611
|
-
color: #010507 !important;
|
|
7306
|
+
.cpk-launcher-hud[data-cpk-hud-side="right"] {
|
|
7307
|
+
left: 100%;
|
|
7308
|
+
right: auto;
|
|
7309
|
+
padding-right: 0;
|
|
7310
|
+
padding-left: 14px;
|
|
7311
|
+
transform: translateX(-8px);
|
|
6612
7312
|
}
|
|
6613
7313
|
|
|
6614
|
-
|
|
6615
|
-
|
|
6616
|
-
|
|
6617
|
-
* Active: brand surface/surfaceContainerActive (lilac tint) +
|
|
6618
|
-
* border/borderActionEnabled underline.
|
|
6619
|
-
* Dark fill is for primary action buttons only, not nav tabs.
|
|
6620
|
-
*/
|
|
6621
|
-
.cpk-tab-active {
|
|
6622
|
-
background-color: rgba(190, 194, 255, 0.18);
|
|
6623
|
-
color: #010507;
|
|
6624
|
-
font-weight: 600;
|
|
7314
|
+
.console-button-wrapper[data-cpk-hud="open"]
|
|
7315
|
+
.cpk-launcher-hud[data-cpk-hud-side="right"] {
|
|
7316
|
+
transform: none;
|
|
6625
7317
|
}
|
|
6626
|
-
|
|
6627
|
-
|
|
7318
|
+
|
|
7319
|
+
.cpk-launcher-hud__card {
|
|
7320
|
+
--hud-fill: rgb(28 31 36 / 0.88);
|
|
7321
|
+
--hud-line: rgb(190 194 255 / 0.5);
|
|
7322
|
+
position: relative;
|
|
7323
|
+
width: 228px;
|
|
7324
|
+
padding: 4px;
|
|
7325
|
+
border: 1px dotted var(--hud-line);
|
|
7326
|
+
border-radius: 10px;
|
|
7327
|
+
background: var(--hud-fill);
|
|
7328
|
+
color: #fff;
|
|
7329
|
+
backdrop-filter: blur(12px) saturate(1.2);
|
|
7330
|
+
box-shadow: 0 8px 20px rgb(1 5 7 / 0.18);
|
|
7331
|
+
}
|
|
7332
|
+
|
|
7333
|
+
.cpk-launcher-hud__arrow {
|
|
7334
|
+
position: absolute;
|
|
7335
|
+
top: calc(var(--cpk-launcher-size) / 2);
|
|
7336
|
+
width: 10px;
|
|
7337
|
+
height: 10px;
|
|
7338
|
+
background: var(--hud-fill);
|
|
7339
|
+
transform: translateY(-50%) rotate(45deg);
|
|
7340
|
+
}
|
|
7341
|
+
|
|
7342
|
+
.cpk-launcher-hud[data-cpk-hud-side="left"] .cpk-launcher-hud__arrow {
|
|
7343
|
+
right: -5px;
|
|
7344
|
+
border-top: 1px solid var(--hud-line);
|
|
7345
|
+
border-right: 1px solid var(--hud-line);
|
|
7346
|
+
}
|
|
7347
|
+
|
|
7348
|
+
.cpk-launcher-hud[data-cpk-hud-side="right"] .cpk-launcher-hud__arrow {
|
|
7349
|
+
left: -5px;
|
|
7350
|
+
border-bottom: 1px solid var(--hud-line);
|
|
7351
|
+
border-left: 1px solid var(--hud-line);
|
|
7352
|
+
}
|
|
7353
|
+
|
|
7354
|
+
.cpk-launcher-hud__list {
|
|
7355
|
+
margin: 0;
|
|
7356
|
+
padding: 0;
|
|
7357
|
+
list-style: none;
|
|
7358
|
+
}
|
|
7359
|
+
|
|
7360
|
+
.cpk-launcher-hud__list + .cpk-launcher-hud__list {
|
|
7361
|
+
margin-top: 4px;
|
|
7362
|
+
padding-top: 4px;
|
|
7363
|
+
border-top: 1px dotted var(--hud-line);
|
|
7364
|
+
}
|
|
7365
|
+
|
|
7366
|
+
.cpk-launcher-hud__row {
|
|
7367
|
+
position: relative;
|
|
7368
|
+
display: grid;
|
|
7369
|
+
grid-template-columns: 1fr 28px;
|
|
7370
|
+
align-items: start;
|
|
7371
|
+
border-radius: 7px;
|
|
7372
|
+
cursor: pointer;
|
|
7373
|
+
}
|
|
7374
|
+
|
|
7375
|
+
.cpk-launcher-hud__row + .cpk-launcher-hud__row {
|
|
7376
|
+
margin-top: 1px;
|
|
7377
|
+
}
|
|
7378
|
+
|
|
7379
|
+
.cpk-launcher-hud__row:hover,
|
|
7380
|
+
.cpk-launcher-hud__row:focus-within,
|
|
7381
|
+
.cpk-launcher-hud__row[data-cpk-hud-help="open"] {
|
|
7382
|
+
background: rgb(255 255 255 / 0.06);
|
|
7383
|
+
}
|
|
7384
|
+
|
|
7385
|
+
.cpk-launcher-hud__action {
|
|
7386
|
+
display: flex;
|
|
7387
|
+
gap: 8px;
|
|
7388
|
+
min-height: 32px;
|
|
7389
|
+
align-items: center;
|
|
7390
|
+
padding: 6px 8px;
|
|
7391
|
+
border: 0;
|
|
7392
|
+
border-radius: 7px;
|
|
7393
|
+
background: transparent;
|
|
7394
|
+
color: #fff;
|
|
7395
|
+
font-family: inherit;
|
|
7396
|
+
font-size: 12px;
|
|
7397
|
+
font-weight: 600;
|
|
7398
|
+
text-align: start;
|
|
7399
|
+
cursor: pointer;
|
|
7400
|
+
}
|
|
7401
|
+
|
|
7402
|
+
/* Stretch the row action over the whole tab, including the detail
|
|
7403
|
+
copy. The help mark sits above this layer. */
|
|
7404
|
+
.cpk-launcher-hud__action::after {
|
|
7405
|
+
content: "";
|
|
7406
|
+
position: absolute;
|
|
7407
|
+
inset: 0;
|
|
7408
|
+
}
|
|
7409
|
+
|
|
7410
|
+
.cpk-launcher-hud__check {
|
|
7411
|
+
flex: none;
|
|
7412
|
+
width: 14px;
|
|
7413
|
+
height: 14px;
|
|
7414
|
+
color: #34d399;
|
|
7415
|
+
}
|
|
7416
|
+
|
|
7417
|
+
.cpk-launcher-hud__help {
|
|
7418
|
+
position: relative;
|
|
7419
|
+
z-index: 1;
|
|
7420
|
+
display: inline-flex;
|
|
7421
|
+
width: 28px;
|
|
7422
|
+
height: 32px;
|
|
7423
|
+
align-items: center;
|
|
7424
|
+
justify-content: center;
|
|
7425
|
+
padding: 0;
|
|
7426
|
+
border: 0;
|
|
7427
|
+
background: transparent;
|
|
7428
|
+
color: rgb(255 255 255 / 0.78);
|
|
7429
|
+
font-size: 12px;
|
|
7430
|
+
font-weight: 600;
|
|
7431
|
+
cursor: pointer;
|
|
7432
|
+
}
|
|
7433
|
+
|
|
7434
|
+
.cpk-launcher-hud__help span {
|
|
7435
|
+
display: inline-flex;
|
|
7436
|
+
width: 16px;
|
|
7437
|
+
height: 16px;
|
|
7438
|
+
align-items: center;
|
|
7439
|
+
justify-content: center;
|
|
7440
|
+
border: 1px dotted rgb(190 194 255 / 0.55);
|
|
7441
|
+
border-radius: 50%;
|
|
7442
|
+
line-height: 1;
|
|
7443
|
+
}
|
|
7444
|
+
|
|
7445
|
+
.cpk-launcher-hud__help:focus-visible,
|
|
7446
|
+
.cpk-launcher-hud__action:focus-visible {
|
|
7447
|
+
outline: 2px solid #bec2ff;
|
|
7448
|
+
outline-offset: 1px;
|
|
7449
|
+
}
|
|
7450
|
+
|
|
7451
|
+
.cpk-launcher-hud__detail {
|
|
7452
|
+
grid-column: 1 / -1;
|
|
7453
|
+
max-height: 0;
|
|
7454
|
+
margin: 0;
|
|
7455
|
+
padding: 0 8px;
|
|
7456
|
+
overflow: hidden;
|
|
7457
|
+
color: rgb(255 255 255 / 0.78);
|
|
7458
|
+
font-size: 11px;
|
|
7459
|
+
font-weight: 400;
|
|
7460
|
+
line-height: 1.4;
|
|
7461
|
+
opacity: 0;
|
|
7462
|
+
pointer-events: none;
|
|
7463
|
+
transform: translateY(-6px);
|
|
7464
|
+
transition:
|
|
7465
|
+
max-height 200ms cubic-bezier(0.16, 1, 0.3, 1),
|
|
7466
|
+
opacity 150ms ease-out,
|
|
7467
|
+
transform 200ms cubic-bezier(0.16, 1, 0.3, 1),
|
|
7468
|
+
padding-bottom 200ms cubic-bezier(0.16, 1, 0.3, 1);
|
|
7469
|
+
}
|
|
7470
|
+
|
|
7471
|
+
.cpk-launcher-hud__row:hover .cpk-launcher-hud__detail,
|
|
7472
|
+
.cpk-launcher-hud__row:focus-within .cpk-launcher-hud__detail,
|
|
7473
|
+
.cpk-launcher-hud__row[data-cpk-hud-help="open"] .cpk-launcher-hud__detail {
|
|
7474
|
+
max-height: 72px;
|
|
7475
|
+
padding: 0 8px 7px;
|
|
7476
|
+
opacity: 1;
|
|
7477
|
+
transform: none;
|
|
7478
|
+
}
|
|
7479
|
+
|
|
7480
|
+
@media (prefers-reduced-motion: reduce) {
|
|
7481
|
+
.cpk-launcher-hud,
|
|
7482
|
+
.cpk-launcher-hud__detail {
|
|
7483
|
+
transition: none;
|
|
7484
|
+
}
|
|
7485
|
+
}
|
|
7486
|
+
|
|
7487
|
+
/*
|
|
7488
|
+
* Marker on the navigation entry, which is what keeps a signal alive
|
|
7489
|
+
* once the panel is open and the launcher is hidden. Static by design:
|
|
7490
|
+
* the beat belongs to the launcher, and movement here would compete with
|
|
7491
|
+
* the live event stream a developer is actually watching.
|
|
7492
|
+
*
|
|
7493
|
+
* Tone-selected rather than tone-agnostic, because the marker has to
|
|
7494
|
+
* agree with the dot that sent the reader here. Same shape, same
|
|
7495
|
+
* placement, one declaration different — as on the launcher, where the
|
|
7496
|
+
* treatment is shared and only the injected colour changes.
|
|
7497
|
+
*/
|
|
7498
|
+
.inspector-nav-signal-dot {
|
|
7499
|
+
display: inline-block;
|
|
7500
|
+
flex: none;
|
|
7501
|
+
width: 6px;
|
|
7502
|
+
height: 6px;
|
|
7503
|
+
border-radius: 50%;
|
|
7504
|
+
background: ${(0, lit.unsafeCSS)(LAUNCHER_SIGNAL_COLORS.news)};
|
|
7505
|
+
}
|
|
7506
|
+
.inspector-nav-signal-dot[data-cpk-signal-tone="error"] {
|
|
7507
|
+
background: ${(0, lit.unsafeCSS)(LAUNCHER_SIGNAL_COLORS.error)};
|
|
7508
|
+
}
|
|
7509
|
+
|
|
7510
|
+
/* ── Inspector window ────────────────────────────────────────── */
|
|
7511
|
+
.inspector-window {
|
|
7512
|
+
border: 1px solid #d8d8e8 !important;
|
|
7513
|
+
border-radius: 5px !important;
|
|
7514
|
+
box-shadow: none !important;
|
|
7515
|
+
}
|
|
7516
|
+
|
|
7517
|
+
/* ── Header drag area ────────────────────────────────────────── */
|
|
7518
|
+
.drag-handle {
|
|
7519
|
+
border-bottom-color: #d8d8e8 !important;
|
|
7520
|
+
background-color: #f7f6fd !important;
|
|
7521
|
+
}
|
|
7522
|
+
|
|
7523
|
+
.inspector-account-strip {
|
|
7524
|
+
background: linear-gradient(
|
|
7525
|
+
90deg,
|
|
7526
|
+
#ffffff 0%,
|
|
7527
|
+
#f3f1ff 58%,
|
|
7528
|
+
#eefbf7 100%
|
|
7529
|
+
) !important;
|
|
7530
|
+
color: #010507 !important;
|
|
7531
|
+
}
|
|
7532
|
+
|
|
7533
|
+
/* ── Tab buttons ─────────────────────────────────────────────── */
|
|
7534
|
+
/*
|
|
7535
|
+
* Named classes owned by this component — no Tailwind conflict.
|
|
7536
|
+
* Active: brand surface/surfaceContainerActive (lilac tint) +
|
|
7537
|
+
* border/borderActionEnabled underline.
|
|
7538
|
+
* Dark fill is for primary action buttons only, not nav tabs.
|
|
7539
|
+
*/
|
|
7540
|
+
.cpk-tab-active {
|
|
7541
|
+
background-color: rgba(190, 194, 255, 0.18);
|
|
7542
|
+
color: #010507;
|
|
7543
|
+
font-weight: 600;
|
|
7544
|
+
}
|
|
7545
|
+
.cpk-tab-icon {
|
|
7546
|
+
display: inline-flex;
|
|
6628
7547
|
flex-shrink: 0;
|
|
6629
7548
|
align-items: center;
|
|
6630
7549
|
}
|
|
@@ -6917,6 +7836,7 @@ ${argsString}</pre
|
|
|
6917
7836
|
require_persistence.clearLegacyAnnouncementReadState();
|
|
6918
7837
|
this.tryAutoAttachCore();
|
|
6919
7838
|
this.ensureAnnouncementLoading();
|
|
7839
|
+
this.subscribeToInspectorThreadBridge();
|
|
6920
7840
|
}
|
|
6921
7841
|
this.requestUpdate();
|
|
6922
7842
|
}
|
|
@@ -6939,13 +7859,16 @@ ${argsString}</pre
|
|
|
6939
7859
|
clearTimeout(this.transitionTimeoutId);
|
|
6940
7860
|
this.transitionTimeoutId = null;
|
|
6941
7861
|
}
|
|
7862
|
+
this.unsubscribeFromInspectorThreadBridge();
|
|
6942
7863
|
this.threadsSetupPromptCopyGeneration += 1;
|
|
6943
7864
|
if (this.threadsSetupPromptCopyResetTimeoutId !== null) {
|
|
6944
7865
|
window.clearTimeout(this.threadsSetupPromptCopyResetTimeoutId);
|
|
6945
7866
|
this.threadsSetupPromptCopyResetTimeoutId = null;
|
|
6946
7867
|
}
|
|
6947
7868
|
this.threadsSetupPromptCopyState = "idle";
|
|
6948
|
-
this.
|
|
7869
|
+
this.stopSignalPulse();
|
|
7870
|
+
this.cancelGestureTail();
|
|
7871
|
+
this.cancelThreadRefreshDebounce();
|
|
6949
7872
|
this.clearInspectorUsageRefresh();
|
|
6950
7873
|
this.cleanupThreadsExampleOverviewVideo();
|
|
6951
7874
|
this.removeDockStyles(true);
|
|
@@ -6988,6 +7911,7 @@ ${argsString}</pre
|
|
|
6988
7911
|
` : this.renderButton();
|
|
6989
7912
|
}
|
|
6990
7913
|
willUpdate() {
|
|
7914
|
+
this.evaluateErrorSignals();
|
|
6991
7915
|
this.reconcileSelectedMenuVisibility();
|
|
6992
7916
|
if (this.isOpen && this.dockMode === "docked-left") this.setAttribute("data-docked", "true");
|
|
6993
7917
|
else this.removeAttribute("data-docked");
|
|
@@ -6997,7 +7921,11 @@ ${argsString}</pre
|
|
|
6997
7921
|
this.syncThreadsExampleOverviewVideo();
|
|
6998
7922
|
this.maybeTrackInspectorMetadataViews();
|
|
6999
7923
|
this.maybeTrackNewsSignalViewed();
|
|
7924
|
+
this.resolvePillDirection();
|
|
7925
|
+
this.maybeTrackErrorSignalViewed();
|
|
7000
7926
|
this.maybeCompleteWhatsNewView();
|
|
7927
|
+
this.maybeCompleteEventErrorView();
|
|
7928
|
+
this.flushErrorLandingScroll();
|
|
7001
7929
|
this.maybeTrackHomeViewed();
|
|
7002
7930
|
if (!this.isOpen) {
|
|
7003
7931
|
this.lastScrolledAgentNavigationLayout = null;
|
|
@@ -7055,20 +7983,33 @@ ${argsString}</pre
|
|
|
7055
7983
|
"select-none",
|
|
7056
7984
|
this.isDragging ? "cursor-grabbing" : "cursor-pointer"
|
|
7057
7985
|
].join(" ");
|
|
7058
|
-
const
|
|
7059
|
-
|
|
7060
|
-
|
|
7986
|
+
const activeSignal = this.getActiveLauncherSignal();
|
|
7987
|
+
const signal = activeSignal ? LAUNCHER_SIGNALS[activeSignal] : null;
|
|
7988
|
+
const signalStyles = signal ? {
|
|
7989
|
+
"--cpk-launcher-signal": LAUNCHER_SIGNAL_COLORS[signal.tone],
|
|
7990
|
+
"--cpk-launcher-cadence": `${signal.cadence}ms`
|
|
7061
7991
|
} : {};
|
|
7062
7992
|
return lit.html`
|
|
7063
|
-
<div
|
|
7993
|
+
<div
|
|
7994
|
+
class="console-button-wrapper"
|
|
7995
|
+
data-cpk-hud=${this.launcherHudOpen ? "open" : "closed"}
|
|
7996
|
+
@pointerenter=${this.handleLauncherHudEnter}
|
|
7997
|
+
@pointerleave=${this.handleLauncherHudLeave}
|
|
7998
|
+
@focusin=${this.handleLauncherHudFocusIn}
|
|
7999
|
+
@focusout=${this.handleLauncherHudFocusOut}
|
|
8000
|
+
@keydown=${this.handleLauncherHudKeydown}
|
|
8001
|
+
>
|
|
8002
|
+
${this.renderLauncherPill()}
|
|
7064
8003
|
<button
|
|
7065
8004
|
class=${buttonClasses}
|
|
7066
8005
|
type="button"
|
|
7067
|
-
aria-
|
|
7068
|
-
|
|
8006
|
+
aria-expanded=${this.launcherHudOpen ? "true" : "false"}
|
|
8007
|
+
aria-controls=${this.launcherHudOpen ? "cpk-launcher-hud" : lit.nothing}
|
|
8008
|
+
aria-label=${signal && signal.tone === "error" ? `${LAUNCHER_BASE_LABEL}, ${signal.accessibleLabel}` : LAUNCHER_BASE_LABEL}
|
|
8009
|
+
title=${activeSignal === NEWS_SIGNAL_ID ? `${WHATS_NEW_VIEW_LABEL} — unread` : lit.nothing}
|
|
7069
8010
|
data-drag-context="button"
|
|
7070
|
-
data-cpk-signal=${
|
|
7071
|
-
data-cpk-signal-pulsing=${
|
|
8011
|
+
data-cpk-signal=${signal ? signal.tone : lit.nothing}
|
|
8012
|
+
data-cpk-signal-pulsing=${activeSignal !== null && this.pulsingSignal === activeSignal ? "true" : lit.nothing}
|
|
7072
8013
|
style=${(0, lit_directives_style_map_js.styleMap)(signalStyles)}
|
|
7073
8014
|
data-dragging=${this.isDragging && this.pointerContext === "button" ? "true" : "false"}
|
|
7074
8015
|
@pointerdown=${this.handlePointerDown}
|
|
@@ -7083,16 +8024,210 @@ ${argsString}</pre
|
|
|
7083
8024
|
class="cpk-launcher-mark h-6 w-auto"
|
|
7084
8025
|
loading="lazy"
|
|
7085
8026
|
/>
|
|
7086
|
-
${
|
|
8027
|
+
${activeSignal !== null ? lit.html`<span
|
|
7087
8028
|
class="cpk-launcher-signal-wash"
|
|
7088
8029
|
aria-hidden="true"
|
|
7089
8030
|
></span>
|
|
7090
8031
|
<span
|
|
7091
8032
|
class="cpk-launcher-signal-dot"
|
|
7092
|
-
data-cpk-signal-dot=${
|
|
8033
|
+
data-cpk-signal-dot=${activeSignal}
|
|
7093
8034
|
aria-hidden="true"
|
|
7094
8035
|
></span>` : lit.nothing}
|
|
7095
8036
|
</button>
|
|
8037
|
+
${lit.html`<span
|
|
8038
|
+
class="sr-only"
|
|
8039
|
+
data-cpk-launcher-announcement
|
|
8040
|
+
role="status"
|
|
8041
|
+
aria-live="polite"
|
|
8042
|
+
>${this.getGestureLabel() ?? ""}</span
|
|
8043
|
+
>`}
|
|
8044
|
+
${this.renderLauncherHud()}
|
|
8045
|
+
</div>
|
|
8046
|
+
`;
|
|
8047
|
+
}
|
|
8048
|
+
/**
|
|
8049
|
+
* The words the running gesture carries, or null when the launcher is quiet.
|
|
8050
|
+
*
|
|
8051
|
+
* Read from the signal's own description rather than from a condition on the
|
|
8052
|
+
* tone, so a third signal can carry a pill by declaring a label.
|
|
8053
|
+
*/
|
|
8054
|
+
getGestureLabel() {
|
|
8055
|
+
if (this.gestureSignal === null) return null;
|
|
8056
|
+
return LAUNCHER_SIGNALS[this.gestureSignal].pillLabel ?? null;
|
|
8057
|
+
}
|
|
8058
|
+
/**
|
|
8059
|
+
* The pill, laid out at its full width and clipped, for the whole gesture.
|
|
8060
|
+
*
|
|
8061
|
+
* It renders from the first frame of the beat — clipped to nothing, so it
|
|
8062
|
+
* shows nothing — because the room it needs cannot be measured until it has
|
|
8063
|
+
* been laid out, and the direction is decided at gesture start.
|
|
8064
|
+
*/
|
|
8065
|
+
renderLauncherPill() {
|
|
8066
|
+
const key = this.gestureSignal;
|
|
8067
|
+
if (key === null || this.pillPhase === null) return lit.nothing;
|
|
8068
|
+
const signal = LAUNCHER_SIGNALS[key];
|
|
8069
|
+
const label = signal.pillLabel;
|
|
8070
|
+
if (label === void 0) return lit.nothing;
|
|
8071
|
+
return lit.html`
|
|
8072
|
+
<span
|
|
8073
|
+
class="cpk-launcher-pill"
|
|
8074
|
+
data-cpk-launcher-pill=${key}
|
|
8075
|
+
data-cpk-pill-phase=${this.pillPhase}
|
|
8076
|
+
data-cpk-pill-direction=${this.pillDirection ?? "left"}
|
|
8077
|
+
style=${(0, lit_directives_style_map_js.styleMap)({
|
|
8078
|
+
"--cpk-launcher-signal": LAUNCHER_SIGNAL_COLORS[signal.tone],
|
|
8079
|
+
"--cpk-launcher-pill-open": `${ERROR_GESTURE_MS.open}ms`,
|
|
8080
|
+
"--cpk-launcher-pill-close": `${ERROR_GESTURE_MS.close}ms`
|
|
8081
|
+
})}
|
|
8082
|
+
aria-hidden="true"
|
|
8083
|
+
@click=${this.handlePillClick}
|
|
8084
|
+
>
|
|
8085
|
+
<span class="cpk-launcher-pill__heading" data-cpk-pill-heading
|
|
8086
|
+
>${label}</span
|
|
8087
|
+
>
|
|
8088
|
+
<span class="cpk-launcher-pill__subline" data-cpk-pill-subline
|
|
8089
|
+
>${PILL_SUBLINE_LABEL}</span
|
|
8090
|
+
>
|
|
8091
|
+
</span>
|
|
8092
|
+
`;
|
|
8093
|
+
}
|
|
8094
|
+
isLauncherHudBlocked() {
|
|
8095
|
+
return this.gestureSignal !== null;
|
|
8096
|
+
}
|
|
8097
|
+
resolveLauncherHudSide() {
|
|
8098
|
+
if (typeof window === "undefined") {
|
|
8099
|
+
this.launcherHudSide = "left";
|
|
8100
|
+
return;
|
|
8101
|
+
}
|
|
8102
|
+
const button = this.activeRoot.querySelector(".console-button");
|
|
8103
|
+
if (!button) {
|
|
8104
|
+
this.launcherHudSide = "left";
|
|
8105
|
+
return;
|
|
8106
|
+
}
|
|
8107
|
+
if (button.getBoundingClientRect().left - LAUNCHER_HUD_WIDTH >= EDGE_MARGIN) {
|
|
8108
|
+
this.launcherHudSide = "left";
|
|
8109
|
+
return;
|
|
8110
|
+
}
|
|
8111
|
+
this.launcherHudSide = "right";
|
|
8112
|
+
}
|
|
8113
|
+
openLauncherHud() {
|
|
8114
|
+
if (this.isLauncherHudBlocked() || this.isOpen) return;
|
|
8115
|
+
this.resolveLauncherHudSide();
|
|
8116
|
+
if (this.launcherHudCloseTimer !== null) {
|
|
8117
|
+
clearTimeout(this.launcherHudCloseTimer);
|
|
8118
|
+
this.launcherHudCloseTimer = null;
|
|
8119
|
+
}
|
|
8120
|
+
if (this.launcherHudOpen) return;
|
|
8121
|
+
this.launcherHudOpen = true;
|
|
8122
|
+
this.requestUpdate();
|
|
8123
|
+
}
|
|
8124
|
+
closeLauncherHud() {
|
|
8125
|
+
if (this.launcherHudCloseTimer !== null) {
|
|
8126
|
+
clearTimeout(this.launcherHudCloseTimer);
|
|
8127
|
+
this.launcherHudCloseTimer = null;
|
|
8128
|
+
}
|
|
8129
|
+
if (!this.launcherHudOpen && this.launcherHudHelp === null) return;
|
|
8130
|
+
this.launcherHudOpen = false;
|
|
8131
|
+
this.launcherHudHelp = null;
|
|
8132
|
+
this.requestUpdate();
|
|
8133
|
+
}
|
|
8134
|
+
renderHudCheck() {
|
|
8135
|
+
return lit.html`
|
|
8136
|
+
<svg
|
|
8137
|
+
class="cpk-launcher-hud__check"
|
|
8138
|
+
viewBox="0 0 16 16"
|
|
8139
|
+
aria-hidden="true"
|
|
8140
|
+
focusable="false"
|
|
8141
|
+
data-cpk-hud-check
|
|
8142
|
+
>
|
|
8143
|
+
<path
|
|
8144
|
+
fill="none"
|
|
8145
|
+
stroke="currentColor"
|
|
8146
|
+
stroke-width="2"
|
|
8147
|
+
stroke-linecap="round"
|
|
8148
|
+
stroke-linejoin="round"
|
|
8149
|
+
d="M3 8.5 6.5 12 13 4.5"
|
|
8150
|
+
/>
|
|
8151
|
+
</svg>
|
|
8152
|
+
`;
|
|
8153
|
+
}
|
|
8154
|
+
renderHudRow(args) {
|
|
8155
|
+
const helpOpen = this.launcherHudHelp === args.id;
|
|
8156
|
+
const detailId = `cpk-hud-detail-${args.id}`;
|
|
8157
|
+
return lit.html`
|
|
8158
|
+
<li
|
|
8159
|
+
class="cpk-launcher-hud__row"
|
|
8160
|
+
data-cpk-hud-row=${args.id}
|
|
8161
|
+
data-cpk-hud-help=${helpOpen ? "open" : lit.nothing}
|
|
8162
|
+
@click=${(event) => this.handleHudRowClick(event, args.id)}
|
|
8163
|
+
>
|
|
8164
|
+
<button
|
|
8165
|
+
type="button"
|
|
8166
|
+
class="cpk-launcher-hud__action"
|
|
8167
|
+
data-cpk-hud-action
|
|
8168
|
+
aria-describedby=${detailId}
|
|
8169
|
+
@click=${(event) => this.handleHudActionClick(event, args.id)}
|
|
8170
|
+
@pointerdown=${(event) => event.stopPropagation()}
|
|
8171
|
+
>
|
|
8172
|
+
${args.connected ? this.renderHudCheck() : lit.nothing}${args.label}
|
|
8173
|
+
</button>
|
|
8174
|
+
<button
|
|
8175
|
+
type="button"
|
|
8176
|
+
class="cpk-launcher-hud__help"
|
|
8177
|
+
aria-expanded=${helpOpen ? "true" : "false"}
|
|
8178
|
+
aria-controls=${detailId}
|
|
8179
|
+
aria-label=${`About ${args.label}`}
|
|
8180
|
+
@click=${(event) => this.handleHudHelpClick(event, args.id)}
|
|
8181
|
+
@pointerdown=${(event) => event.stopPropagation()}
|
|
8182
|
+
>
|
|
8183
|
+
<span aria-hidden="true">?</span>
|
|
8184
|
+
</button>
|
|
8185
|
+
<p class="cpk-launcher-hud__detail" id=${detailId}>${args.detail}</p>
|
|
8186
|
+
</li>
|
|
8187
|
+
`;
|
|
8188
|
+
}
|
|
8189
|
+
renderLauncherHud() {
|
|
8190
|
+
if (!this.launcherHudOpen) return lit.nothing;
|
|
8191
|
+
const threadsOn = this.areThreadEndpointsAvailable();
|
|
8192
|
+
const intelligenceOn = Boolean(this._core?.intelligence);
|
|
8193
|
+
const learningOn = intelligenceOn && this._memoriesAvailable;
|
|
8194
|
+
return lit.html`
|
|
8195
|
+
<div
|
|
8196
|
+
class="cpk-launcher-hud"
|
|
8197
|
+
id="cpk-launcher-hud"
|
|
8198
|
+
data-cpk-launcher-hud
|
|
8199
|
+
data-cpk-hud-side=${this.launcherHudSide}
|
|
8200
|
+
>
|
|
8201
|
+
<div class="cpk-launcher-hud__card">
|
|
8202
|
+
<span class="cpk-launcher-hud__arrow" aria-hidden="true"></span>
|
|
8203
|
+
<ul class="cpk-launcher-hud__list" role="list">
|
|
8204
|
+
${this.renderHudRow({
|
|
8205
|
+
id: "inspector",
|
|
8206
|
+
label: HUD_OPEN_INSPECTOR_LABEL,
|
|
8207
|
+
detail: HUD_OPEN_INSPECTOR_DETAIL
|
|
8208
|
+
})}
|
|
8209
|
+
</ul>
|
|
8210
|
+
<ul class="cpk-launcher-hud__list" role="list">
|
|
8211
|
+
${this.renderHudRow({
|
|
8212
|
+
id: "threads",
|
|
8213
|
+
label: threadsOn ? HUD_THREADS_ON_LABEL : HUD_THREADS_OFF_LABEL,
|
|
8214
|
+
detail: threadsOn ? HUD_THREADS_ON_DETAIL : HUD_THREADS_OFF_DETAIL,
|
|
8215
|
+
connected: threadsOn
|
|
8216
|
+
})}
|
|
8217
|
+
${this.renderHudRow({
|
|
8218
|
+
id: "intelligence",
|
|
8219
|
+
label: intelligenceOn ? HUD_INTELLIGENCE_ON_LABEL : HUD_INTELLIGENCE_OFF_LABEL,
|
|
8220
|
+
detail: intelligenceOn ? HUD_INTELLIGENCE_ON_DETAIL : HUD_INTELLIGENCE_OFF_DETAIL,
|
|
8221
|
+
connected: intelligenceOn
|
|
8222
|
+
})}
|
|
8223
|
+
${this.renderHudRow({
|
|
8224
|
+
id: "learning",
|
|
8225
|
+
label: learningOn ? HUD_LEARNING_ON_LABEL : HUD_LEARNING_OFF_LABEL,
|
|
8226
|
+
detail: learningOn ? HUD_LEARNING_ON_DETAIL : HUD_LEARNING_OFF_DETAIL,
|
|
8227
|
+
connected: learningOn
|
|
8228
|
+
})}
|
|
8229
|
+
</ul>
|
|
8230
|
+
</div>
|
|
7096
8231
|
</div>
|
|
7097
8232
|
`;
|
|
7098
8233
|
}
|
|
@@ -7114,7 +8249,6 @@ ${argsString}</pre
|
|
|
7114
8249
|
`;
|
|
7115
8250
|
}
|
|
7116
8251
|
renderInspectorSidebar(iconRail, automaticallyCollapsed, agentSelector) {
|
|
7117
|
-
const unread = this.newsSignalArmed && this.announcementLoaded;
|
|
7118
8252
|
const homeModel = this.getHomeModel();
|
|
7119
8253
|
return lit.html`
|
|
7120
8254
|
<aside
|
|
@@ -7156,7 +8290,7 @@ ${argsString}</pre
|
|
|
7156
8290
|
</button>` : lit.nothing}
|
|
7157
8291
|
${items.map((item) => {
|
|
7158
8292
|
const isSelected = this.selectedMenu === item.key;
|
|
7159
|
-
const
|
|
8293
|
+
const marker = this.getNavigationSignalFor(item.key);
|
|
7160
8294
|
return lit.html`
|
|
7161
8295
|
<button
|
|
7162
8296
|
type="button"
|
|
@@ -7164,7 +8298,7 @@ ${argsString}</pre
|
|
|
7164
8298
|
data-inspector-group=${group}
|
|
7165
8299
|
data-inspector-menu-key=${item.key}
|
|
7166
8300
|
aria-current=${isSelected ? "page" : lit.nothing}
|
|
7167
|
-
aria-label=${
|
|
8301
|
+
aria-label=${marker ? `${item.label}, ${marker.accessibleLabel}` : item.label}
|
|
7168
8302
|
data-inspector-tooltip=${item.label}
|
|
7169
8303
|
title=${iconRail ? lit.nothing : item.label}
|
|
7170
8304
|
style=${INTERACTIVE_FOCUS_BASE_STYLE}
|
|
@@ -7178,8 +8312,12 @@ ${argsString}</pre
|
|
|
7178
8312
|
${item.key === "threads" ? (0, lit_directives_unsafe_html_js.unsafeHTML)(this.customTabIcons.threads) : this.renderIcon(item.icon)}
|
|
7179
8313
|
</span>
|
|
7180
8314
|
<span class="inspector-nav-label">${item.label}</span>
|
|
7181
|
-
${
|
|
7182
|
-
<span
|
|
8315
|
+
${marker ? lit.html`
|
|
8316
|
+
<span
|
|
8317
|
+
class="inspector-nav-signal-dot"
|
|
8318
|
+
data-cpk-signal-tone=${marker.tone}
|
|
8319
|
+
aria-hidden="true"
|
|
8320
|
+
></span>
|
|
7183
8321
|
` : lit.nothing}
|
|
7184
8322
|
</button>
|
|
7185
8323
|
`;
|
|
@@ -7653,6 +8791,31 @@ ${argsString}</pre
|
|
|
7653
8791
|
`)}
|
|
7654
8792
|
</dl>
|
|
7655
8793
|
</section>
|
|
8794
|
+
`;
|
|
8795
|
+
}
|
|
8796
|
+
renderEventErrorBanner(key) {
|
|
8797
|
+
const error = this.eventErrorDetails[key];
|
|
8798
|
+
if (!error) return lit.nothing;
|
|
8799
|
+
const guide = EVENT_ERROR_GUIDANCE[key];
|
|
8800
|
+
return lit.html`
|
|
8801
|
+
<div
|
|
8802
|
+
class="mx-3 mt-3 flex cursor-pointer items-start gap-2 rounded-lg border border-rose-200 bg-rose-50 px-3 py-2 text-left text-[11px] text-rose-950"
|
|
8803
|
+
role="alert"
|
|
8804
|
+
tabindex="0"
|
|
8805
|
+
data-cpk-event-error=${key}
|
|
8806
|
+
@click=${this.refocusEventErrorLanding}
|
|
8807
|
+
@keydown=${this.handleEventErrorBannerKeydown}
|
|
8808
|
+
>
|
|
8809
|
+
<span class="mt-0.5 shrink-0">${this.renderIcon("TriangleAlert")}</span>
|
|
8810
|
+
<div class="min-w-0 flex-1 space-y-1">
|
|
8811
|
+
<p class="font-semibold">${guide.title}</p>
|
|
8812
|
+
${error.agentId ? lit.html`<p>Agent: ${error.agentId}</p>` : lit.nothing}
|
|
8813
|
+
${error.toolName ? lit.html`<p>Tool: ${error.toolName}</p>` : lit.nothing}
|
|
8814
|
+
<p class="break-words leading-relaxed">${error.message}</p>
|
|
8815
|
+
${guide.advice ? lit.html`<p class="leading-relaxed">${guide.advice}</p>` : lit.nothing}
|
|
8816
|
+
${guide.highlight && this.hasEventErrorHighlight(key) ? lit.html`<p class="leading-relaxed">${guide.highlight}</p>` : lit.nothing}
|
|
8817
|
+
</div>
|
|
8818
|
+
</div>
|
|
7656
8819
|
`;
|
|
7657
8820
|
}
|
|
7658
8821
|
handleHomeLastEventSelect(eventId, agentId) {
|
|
@@ -8371,21 +9534,34 @@ ${argsString}</pre
|
|
|
8371
9534
|
this.draggedDuringInteraction = false;
|
|
8372
9535
|
}
|
|
8373
9536
|
openInspector(source, options = {}) {
|
|
8374
|
-
if (options.
|
|
9537
|
+
if (options.snippetId || options.menu === "event-snippets") this.focusEventSnippets(options);
|
|
9538
|
+
else if (options.threadId) this.focusThread(options);
|
|
8375
9539
|
if (this.isPoppedOut) return;
|
|
8376
9540
|
if (this.isOpen) return;
|
|
8377
9541
|
const hadUnseenAnnouncement = this.newsSignalArmed;
|
|
9542
|
+
const activeSignalAtOpen = this.getActiveLauncherSignal();
|
|
8378
9543
|
const firstOpen = !this.hasOpenedInspector;
|
|
8379
9544
|
this.hasOpenedInspector = true;
|
|
8380
9545
|
this.homeViewedThisOpen = false;
|
|
8381
|
-
|
|
8382
|
-
|
|
8383
|
-
|
|
9546
|
+
this.closeLauncherHud();
|
|
9547
|
+
const hudMenu = this.hudLandingMenu;
|
|
9548
|
+
this.hudLandingMenu = null;
|
|
9549
|
+
if (hudMenu) {
|
|
9550
|
+
this.selectedMenu = hudMenu;
|
|
9551
|
+
this.lastSelectedMenuByGroup[require_inspector_nav.getGroupForMenu(hudMenu)] = hudMenu;
|
|
9552
|
+
} else if (activeSignalAtOpen !== null && source === "floating_button") {
|
|
9553
|
+
const landing = LAUNCHER_SIGNALS[activeSignalAtOpen].landingTarget;
|
|
9554
|
+
this.selectedMenu = landing;
|
|
9555
|
+
this.lastSelectedMenuByGroup[require_inspector_nav.getGroupForMenu(landing)] = landing;
|
|
9556
|
+
if (landing === "agents" || landing === "ag-ui-events") {
|
|
9557
|
+
if (isEventErrorKey(activeSignalAtOpen)) this.applyEventErrorLanding(activeSignalAtOpen);
|
|
9558
|
+
}
|
|
8384
9559
|
}
|
|
8385
9560
|
this.ensureAnnouncementLoading();
|
|
8386
9561
|
this.isOpen = true;
|
|
9562
|
+
this.cancelGestureTail();
|
|
8387
9563
|
this.persistState();
|
|
8388
|
-
this.trackOpened(source, hadUnseenAnnouncement, firstOpen);
|
|
9564
|
+
this.trackOpened(source, hadUnseenAnnouncement, firstOpen, activeSignalAtOpen);
|
|
8389
9565
|
if (this.dockMode !== "floating") this.applyDockStyles();
|
|
8390
9566
|
this.ensureWindowPlacement();
|
|
8391
9567
|
this.requestUpdate();
|
|
@@ -8400,7 +9576,6 @@ ${argsString}</pre
|
|
|
8400
9576
|
if (this.isPoppedOut) return;
|
|
8401
9577
|
if (!this.isOpen) return;
|
|
8402
9578
|
this.isOpen = false;
|
|
8403
|
-
if (this.newsSignalPulsePending) this.startNewsSignalPulse();
|
|
8404
9579
|
if (this.dockMode !== "floating") this.removeDockStyles();
|
|
8405
9580
|
this.persistState();
|
|
8406
9581
|
this.updateHostTransform("button");
|
|
@@ -8408,6 +9583,7 @@ ${argsString}</pre
|
|
|
8408
9583
|
this.updateComplete.then(() => {
|
|
8409
9584
|
this.measureContext("button");
|
|
8410
9585
|
this.applyAnchorPosition("button");
|
|
9586
|
+
this.flushPendingSignalPulse();
|
|
8411
9587
|
});
|
|
8412
9588
|
}
|
|
8413
9589
|
renderIcon(name) {
|
|
@@ -8588,6 +9764,7 @@ ${argsString}</pre
|
|
|
8588
9764
|
contentText,
|
|
8589
9765
|
contentRaw: raw.content !== void 0 ? this.sanitizeForLogging(raw.content) : void 0,
|
|
8590
9766
|
toolCalls,
|
|
9767
|
+
toolCallId: typeof raw.toolCallId === "string" ? raw.toolCallId : void 0,
|
|
8591
9768
|
activityType: typeof raw.activityType === "string" ? raw.activityType : void 0
|
|
8592
9769
|
};
|
|
8593
9770
|
}
|
|
@@ -8770,16 +9947,16 @@ ${argsString}</pre
|
|
|
8770
9947
|
@submit=${this.handlePlaygroundSubmit}
|
|
8771
9948
|
>
|
|
8772
9949
|
${this.playgroundError ? lit.html`<div
|
|
8773
|
-
class="mx-auto mb-2 flex max-w-3xl items-start gap-2 rounded-lg border border-rose-200 bg-rose-50 px-2.5 py-2 text-[10px] text-rose-
|
|
9950
|
+
class="mx-auto mb-2 flex max-w-3xl items-start gap-2 rounded-lg border border-rose-200 bg-rose-50 px-2.5 py-2 text-[10px] text-rose-950"
|
|
8774
9951
|
role="alert"
|
|
8775
9952
|
data-playground-error
|
|
8776
9953
|
>
|
|
8777
|
-
<span class="mt-0.5 shrink-0
|
|
9954
|
+
<span class="mt-0.5 shrink-0"
|
|
8778
9955
|
>${this.renderIcon("TriangleAlert")}</span
|
|
8779
9956
|
>
|
|
8780
9957
|
<div class="min-w-0 flex-1">
|
|
8781
9958
|
<p class="font-semibold">Agent run failed</p>
|
|
8782
|
-
<p class="mt-0.5 break-words leading-relaxed
|
|
9959
|
+
<p class="mt-0.5 break-words leading-relaxed">
|
|
8783
9960
|
${this.playgroundError}
|
|
8784
9961
|
</p>
|
|
8785
9962
|
</div>
|
|
@@ -8814,23 +9991,574 @@ ${argsString}</pre
|
|
|
8814
9991
|
?disabled=${sendDisabled}
|
|
8815
9992
|
@click=${this.playgroundIsRunning ? this.handlePlaygroundStop : lit.nothing}
|
|
8816
9993
|
>
|
|
8817
|
-
${this.renderIcon(this.playgroundIsRunning ? "Square" : "ArrowUp")}
|
|
8818
|
-
</button>
|
|
9994
|
+
${this.renderIcon(this.playgroundIsRunning ? "Square" : "ArrowUp")}
|
|
9995
|
+
</button>
|
|
9996
|
+
</div>
|
|
9997
|
+
<p
|
|
9998
|
+
class="mx-auto max-w-3xl px-3 py-2 text-center text-[10px] leading-4 text-gray-500"
|
|
9999
|
+
>
|
|
10000
|
+
AI can make mistakes. Please verify important information.
|
|
10001
|
+
</p>
|
|
10002
|
+
</form>
|
|
10003
|
+
`;
|
|
10004
|
+
}
|
|
10005
|
+
reloadEventSnippets() {
|
|
10006
|
+
this.eventSnippets = require_event_snippets.loadEventSnippets();
|
|
10007
|
+
}
|
|
10008
|
+
renderSnippetImportControl() {
|
|
10009
|
+
return lit.html`
|
|
10010
|
+
<label
|
|
10011
|
+
class="inline-flex shrink-0 cursor-pointer items-center rounded-md border border-gray-300 bg-white px-3 py-1.5 text-[11px] text-gray-700"
|
|
10012
|
+
data-testid="cpk-snippet-import"
|
|
10013
|
+
>
|
|
10014
|
+
Import
|
|
10015
|
+
<input
|
|
10016
|
+
type="file"
|
|
10017
|
+
accept="application/json"
|
|
10018
|
+
class="hidden"
|
|
10019
|
+
@change=${this.handleSnippetImportChange}
|
|
10020
|
+
/>
|
|
10021
|
+
</label>
|
|
10022
|
+
`;
|
|
10023
|
+
}
|
|
10024
|
+
selectEventSnippet(id) {
|
|
10025
|
+
const snippet = this.eventSnippets.find((item) => item.id === id);
|
|
10026
|
+
this.selectedSnippetId = id;
|
|
10027
|
+
if (!snippet) {
|
|
10028
|
+
this.requestUpdate();
|
|
10029
|
+
return;
|
|
10030
|
+
}
|
|
10031
|
+
const editor = require_event_snippets.editorStateFromSnippet(snippet);
|
|
10032
|
+
this.snippetRecipe = editor.recipe;
|
|
10033
|
+
this.snippetName = editor.name;
|
|
10034
|
+
this.snippetJson = editor.json;
|
|
10035
|
+
this.snippetToolName = editor.draft.toolName;
|
|
10036
|
+
this.snippetToolArgs = editor.draft.toolArgs;
|
|
10037
|
+
this.snippetReasoningText = editor.draft.reasoningText;
|
|
10038
|
+
this.snippetTextContent = editor.draft.textContent;
|
|
10039
|
+
this.snippetActivityType = editor.draft.activityType;
|
|
10040
|
+
this.snippetActivityContent = editor.draft.activityContent;
|
|
10041
|
+
this.snippetError = null;
|
|
10042
|
+
this.requestUpdate();
|
|
10043
|
+
}
|
|
10044
|
+
compileSnippetDraft() {
|
|
10045
|
+
switch (this.snippetRecipe) {
|
|
10046
|
+
case "tool-call": return require_event_snippets.compileToolCallRecipe({
|
|
10047
|
+
toolName: this.snippetToolName,
|
|
10048
|
+
argsJson: this.snippetToolArgs,
|
|
10049
|
+
threadId: this.getSnippetThreadId(),
|
|
10050
|
+
runId: this.getSnippetRunId()
|
|
10051
|
+
});
|
|
10052
|
+
case "reasoning": return require_event_snippets.compileReasoningRecipe({
|
|
10053
|
+
text: this.snippetReasoningText,
|
|
10054
|
+
threadId: this.getSnippetThreadId(),
|
|
10055
|
+
runId: this.getSnippetRunId()
|
|
10056
|
+
});
|
|
10057
|
+
case "text": return require_event_snippets.compileTextRecipe({
|
|
10058
|
+
text: this.snippetTextContent,
|
|
10059
|
+
threadId: this.getSnippetThreadId(),
|
|
10060
|
+
runId: this.getSnippetRunId()
|
|
10061
|
+
});
|
|
10062
|
+
case "activity": return require_event_snippets.compileActivityRecipe({
|
|
10063
|
+
activityType: this.snippetActivityType,
|
|
10064
|
+
contentJson: this.snippetActivityContent,
|
|
10065
|
+
threadId: this.getSnippetThreadId(),
|
|
10066
|
+
runId: this.getSnippetRunId()
|
|
10067
|
+
});
|
|
10068
|
+
case "raw": return require_event_snippets.parseSnippetEvents(this.snippetJson);
|
|
10069
|
+
}
|
|
10070
|
+
}
|
|
10071
|
+
getSnippetThreadId() {
|
|
10072
|
+
return this.selectedThreadId ?? "inspector-snippet";
|
|
10073
|
+
}
|
|
10074
|
+
getSnippetRunId() {
|
|
10075
|
+
return `inspector-snippet-${Date.now()}`;
|
|
10076
|
+
}
|
|
10077
|
+
getSnippetTargetAgent() {
|
|
10078
|
+
const core = this._core;
|
|
10079
|
+
if (!core) return null;
|
|
10080
|
+
const selected = this.selectedContext !== "all-agents" ? this.selectedContext : null;
|
|
10081
|
+
if (selected) return core.getAgent(selected) ?? null;
|
|
10082
|
+
const first = this.contextOptions.find((option) => option.key !== "all-agents");
|
|
10083
|
+
return first ? core.getAgent(first.key) ?? null : null;
|
|
10084
|
+
}
|
|
10085
|
+
applyRecipeToEditor() {
|
|
10086
|
+
try {
|
|
10087
|
+
const events = this.compileSnippetDraft();
|
|
10088
|
+
this.snippetJson = JSON.stringify(events, null, 2);
|
|
10089
|
+
this.snippetError = null;
|
|
10090
|
+
} catch (error) {
|
|
10091
|
+
this.snippetError = error instanceof Error ? error.message : "Could not compile recipe.";
|
|
10092
|
+
}
|
|
10093
|
+
this.requestUpdate();
|
|
10094
|
+
}
|
|
10095
|
+
handleSnippetRecipeChange(event) {
|
|
10096
|
+
const value = event.target.value;
|
|
10097
|
+
if (value === "tool-call" || value === "reasoning" || value === "text" || value === "activity" || value === "raw") {
|
|
10098
|
+
this.snippetRecipe = value;
|
|
10099
|
+
if (value !== "raw") this.applyRecipeToEditor();
|
|
10100
|
+
else this.requestUpdate();
|
|
10101
|
+
}
|
|
10102
|
+
}
|
|
10103
|
+
saveCurrentSnippet(source) {
|
|
10104
|
+
try {
|
|
10105
|
+
const events = require_event_snippets.parseSnippetEvents(this.snippetJson);
|
|
10106
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
10107
|
+
const snippet = {
|
|
10108
|
+
id: this.selectedSnippetId ?? require_event_snippets.createSnippetId(),
|
|
10109
|
+
name: this.snippetName.trim() || require_event_snippets.recipeLabel(this.snippetRecipe),
|
|
10110
|
+
recipe: this.snippetRecipe,
|
|
10111
|
+
events,
|
|
10112
|
+
createdAt: this.eventSnippets.find((item) => item.id === this.selectedSnippetId)?.createdAt ?? now,
|
|
10113
|
+
updatedAt: now
|
|
10114
|
+
};
|
|
10115
|
+
this.eventSnippets = require_event_snippets.upsertEventSnippet(snippet);
|
|
10116
|
+
this.selectedSnippetId = snippet.id;
|
|
10117
|
+
this.snippetBanner = "Snippet saved.";
|
|
10118
|
+
this.snippetError = null;
|
|
10119
|
+
if (!this.core?.telemetryDisabled) require_telemetry.trackEventSnippetsSaved({
|
|
10120
|
+
recipe: this.snippetRecipe,
|
|
10121
|
+
source,
|
|
10122
|
+
success: true
|
|
10123
|
+
});
|
|
10124
|
+
} catch (error) {
|
|
10125
|
+
this.snippetError = error instanceof Error ? error.message : "Could not save snippet.";
|
|
10126
|
+
if (!this.core?.telemetryDisabled) require_telemetry.trackEventSnippetsSaved({
|
|
10127
|
+
recipe: this.snippetRecipe,
|
|
10128
|
+
source,
|
|
10129
|
+
success: false
|
|
10130
|
+
});
|
|
10131
|
+
}
|
|
10132
|
+
this.requestUpdate();
|
|
10133
|
+
}
|
|
10134
|
+
async runCurrentSnippet() {
|
|
10135
|
+
this.snippetError = null;
|
|
10136
|
+
this.snippetBanner = null;
|
|
10137
|
+
let events;
|
|
10138
|
+
try {
|
|
10139
|
+
events = require_event_snippets.expandSnippetEventsForRun(require_event_snippets.parseSnippetEvents(this.snippetJson));
|
|
10140
|
+
} catch (error) {
|
|
10141
|
+
this.snippetError = error instanceof Error ? error.message : "Snippet JSON is invalid.";
|
|
10142
|
+
this.requestUpdate();
|
|
10143
|
+
return;
|
|
10144
|
+
}
|
|
10145
|
+
if (require_event_snippets.snippetContainsToolCall(events) && !this.snippetConfirmOpen) {
|
|
10146
|
+
this.snippetConfirmOpen = true;
|
|
10147
|
+
this.requestUpdate();
|
|
10148
|
+
return;
|
|
10149
|
+
}
|
|
10150
|
+
this.snippetConfirmOpen = false;
|
|
10151
|
+
const core = this._core;
|
|
10152
|
+
const agent = this.getSnippetTargetAgent();
|
|
10153
|
+
if (!core || !agent) {
|
|
10154
|
+
this.snippetError = "No agent is available to inject into.";
|
|
10155
|
+
this.requestUpdate();
|
|
10156
|
+
return;
|
|
10157
|
+
}
|
|
10158
|
+
if (agent.isRunning) {
|
|
10159
|
+
this.snippetError = "The agent is running. Wait for the current run to end.";
|
|
10160
|
+
this.requestUpdate();
|
|
10161
|
+
return;
|
|
10162
|
+
}
|
|
10163
|
+
try {
|
|
10164
|
+
const result = await (0, _copilotkit_core.ɵinjectInspectorEvents)({
|
|
10165
|
+
core,
|
|
10166
|
+
agent,
|
|
10167
|
+
events
|
|
10168
|
+
});
|
|
10169
|
+
this.lastInject = {
|
|
10170
|
+
snippetId: this.selectedSnippetId ?? "unsaved",
|
|
10171
|
+
agentId: agent.agentId ?? "default",
|
|
10172
|
+
runId: this.getSnippetRunId(),
|
|
10173
|
+
messageIds: result.messageIds
|
|
10174
|
+
};
|
|
10175
|
+
this.snippetBanner = "Inspector injected these events into the live thread.";
|
|
10176
|
+
if (!this.core?.telemetryDisabled) require_telemetry.trackEventSnippetsRun({
|
|
10177
|
+
recipe: this.snippetRecipe,
|
|
10178
|
+
source: "pane",
|
|
10179
|
+
success: true
|
|
10180
|
+
});
|
|
10181
|
+
} catch (error) {
|
|
10182
|
+
this.snippetError = error instanceof Error ? error.message : "Could not run snippet.";
|
|
10183
|
+
if (!this.core?.telemetryDisabled) require_telemetry.trackEventSnippetsRun({
|
|
10184
|
+
recipe: this.snippetRecipe,
|
|
10185
|
+
source: "pane",
|
|
10186
|
+
success: false
|
|
10187
|
+
});
|
|
10188
|
+
}
|
|
10189
|
+
this.requestUpdate();
|
|
10190
|
+
}
|
|
10191
|
+
resetLastSnippetRun() {
|
|
10192
|
+
const last = this.lastInject;
|
|
10193
|
+
const core = this._core;
|
|
10194
|
+
if (!last || !core) return;
|
|
10195
|
+
const agent = core.getAgent(last.agentId);
|
|
10196
|
+
if (!agent) {
|
|
10197
|
+
this.snippetError = "The injected agent is no longer available.";
|
|
10198
|
+
this.requestUpdate();
|
|
10199
|
+
return;
|
|
10200
|
+
}
|
|
10201
|
+
(0, _copilotkit_core.ɵresetInspectorInject)({
|
|
10202
|
+
agent,
|
|
10203
|
+
messageIds: last.messageIds
|
|
10204
|
+
});
|
|
10205
|
+
this.lastInject = null;
|
|
10206
|
+
this.snippetBanner = "Last inject was removed from the thread. App state from a tool handler was not undone.";
|
|
10207
|
+
this.requestUpdate();
|
|
10208
|
+
}
|
|
10209
|
+
renderEventSnippetsView() {
|
|
10210
|
+
if (this.eventSnippets.length === 0 && this.selectedSnippetId === null) this.reloadEventSnippets();
|
|
10211
|
+
const agent = this.getSnippetTargetAgent();
|
|
10212
|
+
const runBlocked = agent?.isRunning === true;
|
|
10213
|
+
const canRunJson = require_event_snippets.snippetJsonIsRunnable(this.snippetJson);
|
|
10214
|
+
const canRun = canRunJson && !!agent && !runBlocked;
|
|
10215
|
+
const canSave = canRunJson;
|
|
10216
|
+
const canDelete = this.selectedSnippetId !== null;
|
|
10217
|
+
const canExport = this.eventSnippets.length > 0;
|
|
10218
|
+
const canReset = this.lastInject !== null;
|
|
10219
|
+
const snippetGroups = require_event_snippets.groupEventSnippets(this.eventSnippets);
|
|
10220
|
+
const tools = this._core?.tools ?? [];
|
|
10221
|
+
return lit.html`
|
|
10222
|
+
<div class="flex h-full min-h-0 flex-col bg-white">
|
|
10223
|
+
<div
|
|
10224
|
+
class="flex items-center justify-between gap-4 border-b border-gray-200 px-4 py-3"
|
|
10225
|
+
>
|
|
10226
|
+
<div class="min-w-0">
|
|
10227
|
+
<h2 class="text-sm font-semibold text-gray-900">Event Snippets</h2>
|
|
10228
|
+
<p class="mt-1 text-[11px] text-gray-500">
|
|
10229
|
+
Compile AG-UI events, run them on the live agent, and save them
|
|
10230
|
+
for later. Tool-call runs use the real frontend-tool handler.
|
|
10231
|
+
</p>
|
|
10232
|
+
</div>
|
|
10233
|
+
${this.renderSnippetImportControl()}
|
|
10234
|
+
</div>
|
|
10235
|
+
${this.snippetBanner ? lit.html`<div
|
|
10236
|
+
class="border-b border-emerald-200 bg-emerald-50 px-4 py-2 text-[11px] text-emerald-800"
|
|
10237
|
+
role="status"
|
|
10238
|
+
>
|
|
10239
|
+
${this.snippetBanner}
|
|
10240
|
+
</div>` : lit.nothing}
|
|
10241
|
+
${this.snippetError ? lit.html`<div
|
|
10242
|
+
class="border-b border-rose-200 bg-rose-50 px-4 py-2 text-[11px] text-rose-800"
|
|
10243
|
+
role="alert"
|
|
10244
|
+
>
|
|
10245
|
+
${this.snippetError}
|
|
10246
|
+
</div>` : lit.nothing}
|
|
10247
|
+
${this.snippetConfirmOpen ? lit.html`<div
|
|
10248
|
+
class="border-b border-amber-200 bg-amber-50 px-4 py-2 text-[11px] text-amber-900"
|
|
10249
|
+
role="alertdialog"
|
|
10250
|
+
aria-label="Confirm tool-call run"
|
|
10251
|
+
>
|
|
10252
|
+
<p>
|
|
10253
|
+
This snippet contains a tool call. Run will execute the real
|
|
10254
|
+
handler on the live thread.
|
|
10255
|
+
</p>
|
|
10256
|
+
<div class="mt-2 flex gap-2">
|
|
10257
|
+
<button
|
|
10258
|
+
type="button"
|
|
10259
|
+
class="rounded-md bg-gray-900 px-2 py-1 text-[11px] text-white"
|
|
10260
|
+
data-testid="cpk-snippet-run-handler"
|
|
10261
|
+
@click=${() => {
|
|
10262
|
+
this.snippetConfirmOpen = true;
|
|
10263
|
+
this.runCurrentSnippet();
|
|
10264
|
+
}}
|
|
10265
|
+
>
|
|
10266
|
+
Run handler
|
|
10267
|
+
</button>
|
|
10268
|
+
<button
|
|
10269
|
+
type="button"
|
|
10270
|
+
class="rounded-md border border-gray-300 bg-white px-2 py-1 text-[11px]"
|
|
10271
|
+
@click=${() => {
|
|
10272
|
+
this.snippetConfirmOpen = false;
|
|
10273
|
+
this.requestUpdate();
|
|
10274
|
+
}}
|
|
10275
|
+
>
|
|
10276
|
+
Cancel
|
|
10277
|
+
</button>
|
|
10278
|
+
</div>
|
|
10279
|
+
</div>` : lit.nothing}
|
|
10280
|
+
<div class="flex min-h-0 flex-1">
|
|
10281
|
+
<div
|
|
10282
|
+
class="inspector-snippet-sidebar shrink-0"
|
|
10283
|
+
style="width:${this.snippetListWidth}px"
|
|
10284
|
+
data-testid="cpk-snippet-list"
|
|
10285
|
+
>
|
|
10286
|
+
${snippetGroups.length === 0 ? lit.html`
|
|
10287
|
+
<p class="px-2 py-2 text-[11px] text-gray-500">No saved snippets yet.</p>
|
|
10288
|
+
` : lit.html`
|
|
10289
|
+
<nav class="inspector-sidebar-nav" aria-label="Saved snippets">
|
|
10290
|
+
${snippetGroups.map((group) => lit.html`
|
|
10291
|
+
<div class="inspector-sidebar-section">
|
|
10292
|
+
<div
|
|
10293
|
+
class="inspector-sidebar-label"
|
|
10294
|
+
data-testid="cpk-snippet-category"
|
|
10295
|
+
data-recipe=${group.recipe}
|
|
10296
|
+
>
|
|
10297
|
+
${group.label}
|
|
10298
|
+
</div>
|
|
10299
|
+
${group.snippets.map((snippet) => {
|
|
10300
|
+
const isSelected = snippet.id === this.selectedSnippetId;
|
|
10301
|
+
return lit.html`
|
|
10302
|
+
<button
|
|
10303
|
+
type="button"
|
|
10304
|
+
class="inspector-nav-control inspector-sidebar-control ${isSelected ? "inspector-nav-control-active" : ""}"
|
|
10305
|
+
data-testid="cpk-snippet-item"
|
|
10306
|
+
data-recipe=${snippet.recipe}
|
|
10307
|
+
aria-current=${isSelected ? "page" : lit.nothing}
|
|
10308
|
+
aria-label="${require_event_snippets.recipeLabel(snippet.recipe)}: ${snippet.name}"
|
|
10309
|
+
style=${INTERACTIVE_FOCUS_BASE_STYLE}
|
|
10310
|
+
@click=${() => this.selectEventSnippet(snippet.id)}
|
|
10311
|
+
>
|
|
10312
|
+
<span
|
|
10313
|
+
class="inspector-nav-icon"
|
|
10314
|
+
aria-hidden="true"
|
|
10315
|
+
>
|
|
10316
|
+
<span
|
|
10317
|
+
class="flex h-6 w-6 items-center justify-center rounded-md ${require_event_snippets.recipeIconWrapClass(snippet.recipe)}"
|
|
10318
|
+
>
|
|
10319
|
+
${this.renderIcon(require_event_snippets.recipeIconName(snippet.recipe))}
|
|
10320
|
+
</span>
|
|
10321
|
+
</span>
|
|
10322
|
+
<span class="inspector-nav-label"
|
|
10323
|
+
>${snippet.name}</span
|
|
10324
|
+
>
|
|
10325
|
+
</button>
|
|
10326
|
+
`;
|
|
10327
|
+
})}
|
|
10328
|
+
</div>
|
|
10329
|
+
`)}
|
|
10330
|
+
</nav>
|
|
10331
|
+
`}
|
|
10332
|
+
</div>
|
|
10333
|
+
<div
|
|
10334
|
+
class="w-1.5 shrink-0 cursor-col-resize bg-gray-200 hover:bg-gray-400"
|
|
10335
|
+
role="separator"
|
|
10336
|
+
aria-orientation="vertical"
|
|
10337
|
+
aria-label="Resize snippet list"
|
|
10338
|
+
title="Drag to resize"
|
|
10339
|
+
data-testid="cpk-snippet-list-resize"
|
|
10340
|
+
style="touch-action:none"
|
|
10341
|
+
@pointerdown=${this.handleSnippetListDividerPointerDown}
|
|
10342
|
+
@pointermove=${this.handleSnippetListDividerPointerMove}
|
|
10343
|
+
@pointerup=${this.handleSnippetListDividerPointerUp}
|
|
10344
|
+
@pointercancel=${this.handleSnippetListDividerPointerUp}
|
|
10345
|
+
></div>
|
|
10346
|
+
<div class="flex min-h-0 min-w-0 flex-1 flex-col gap-2 overflow-auto p-4">
|
|
10347
|
+
<label class="text-[11px] text-gray-600">
|
|
10348
|
+
Name
|
|
10349
|
+
<input
|
|
10350
|
+
class="mt-1 w-full rounded-md border border-gray-200 px-2 py-1 text-[11px]"
|
|
10351
|
+
data-testid="cpk-snippet-name"
|
|
10352
|
+
.value=${this.snippetName}
|
|
10353
|
+
@input=${(event) => {
|
|
10354
|
+
this.snippetName = event.target.value;
|
|
10355
|
+
}}
|
|
10356
|
+
/>
|
|
10357
|
+
</label>
|
|
10358
|
+
<label class="text-[11px] text-gray-600">
|
|
10359
|
+
Recipe
|
|
10360
|
+
<select
|
|
10361
|
+
class="mt-1 w-full rounded-md border border-gray-200 px-2 py-1 text-[11px]"
|
|
10362
|
+
data-testid="cpk-snippet-recipe"
|
|
10363
|
+
.value=${this.snippetRecipe}
|
|
10364
|
+
@change=${this.handleSnippetRecipeChange}
|
|
10365
|
+
>
|
|
10366
|
+
${[
|
|
10367
|
+
"tool-call",
|
|
10368
|
+
"reasoning",
|
|
10369
|
+
"text",
|
|
10370
|
+
"activity",
|
|
10371
|
+
"raw"
|
|
10372
|
+
].map((recipe) => lit.html`<option
|
|
10373
|
+
value=${recipe}
|
|
10374
|
+
?selected=${recipe === this.snippetRecipe}
|
|
10375
|
+
>
|
|
10376
|
+
${require_event_snippets.recipeLabel(recipe)}
|
|
10377
|
+
</option>`)}
|
|
10378
|
+
</select>
|
|
10379
|
+
</label>
|
|
10380
|
+
${this.snippetRecipe === "tool-call" ? lit.html`
|
|
10381
|
+
<label class="text-[11px] text-gray-600">
|
|
10382
|
+
Tool
|
|
10383
|
+
<input
|
|
10384
|
+
list="cpk-snippet-tools"
|
|
10385
|
+
class="mt-1 w-full rounded-md border border-gray-200 px-2 py-1 text-[11px]"
|
|
10386
|
+
data-testid="cpk-snippet-tool-name"
|
|
10387
|
+
.value=${this.snippetToolName}
|
|
10388
|
+
@input=${(event) => {
|
|
10389
|
+
this.snippetToolName = event.target.value;
|
|
10390
|
+
this.applyRecipeToEditor();
|
|
10391
|
+
}}
|
|
10392
|
+
/>
|
|
10393
|
+
<datalist id="cpk-snippet-tools">
|
|
10394
|
+
${tools.map((tool) => lit.html`<option value=${tool.name}></option>`)}
|
|
10395
|
+
</datalist>
|
|
10396
|
+
</label>
|
|
10397
|
+
<label class="text-[11px] text-gray-600">
|
|
10398
|
+
Args JSON
|
|
10399
|
+
<textarea
|
|
10400
|
+
class="mt-1 h-20 w-full rounded-md border border-gray-200 px-2 py-1 font-mono text-[11px]"
|
|
10401
|
+
data-testid="cpk-snippet-tool-args"
|
|
10402
|
+
.value=${this.snippetToolArgs}
|
|
10403
|
+
@input=${(event) => {
|
|
10404
|
+
this.snippetToolArgs = event.target.value;
|
|
10405
|
+
this.applyRecipeToEditor();
|
|
10406
|
+
}}
|
|
10407
|
+
></textarea>
|
|
10408
|
+
</label>
|
|
10409
|
+
` : lit.nothing}
|
|
10410
|
+
${this.snippetRecipe === "reasoning" ? lit.html`<label class="text-[11px] text-gray-600">
|
|
10411
|
+
Reasoning
|
|
10412
|
+
<textarea
|
|
10413
|
+
class="mt-1 h-20 w-full rounded-md border border-gray-200 px-2 py-1 text-[11px]"
|
|
10414
|
+
data-testid="cpk-snippet-reasoning"
|
|
10415
|
+
.value=${this.snippetReasoningText}
|
|
10416
|
+
@input=${(event) => {
|
|
10417
|
+
this.snippetReasoningText = event.target.value;
|
|
10418
|
+
this.applyRecipeToEditor();
|
|
10419
|
+
}}
|
|
10420
|
+
></textarea>
|
|
10421
|
+
</label>` : lit.nothing}
|
|
10422
|
+
${this.snippetRecipe === "text" ? lit.html`<label class="text-[11px] text-gray-600">
|
|
10423
|
+
Assistant text
|
|
10424
|
+
<textarea
|
|
10425
|
+
class="mt-1 h-20 w-full rounded-md border border-gray-200 px-2 py-1 text-[11px]"
|
|
10426
|
+
data-testid="cpk-snippet-text"
|
|
10427
|
+
.value=${this.snippetTextContent}
|
|
10428
|
+
@input=${(event) => {
|
|
10429
|
+
this.snippetTextContent = event.target.value;
|
|
10430
|
+
this.applyRecipeToEditor();
|
|
10431
|
+
}}
|
|
10432
|
+
></textarea>
|
|
10433
|
+
</label>` : lit.nothing}
|
|
10434
|
+
${this.snippetRecipe === "activity" ? lit.html`
|
|
10435
|
+
<label class="text-[11px] text-gray-600">
|
|
10436
|
+
Activity type
|
|
10437
|
+
<input
|
|
10438
|
+
list="cpk-snippet-activity"
|
|
10439
|
+
class="mt-1 w-full rounded-md border border-gray-200 px-2 py-1 text-[11px]"
|
|
10440
|
+
data-testid="cpk-snippet-activity-type"
|
|
10441
|
+
.value=${this.snippetActivityType}
|
|
10442
|
+
@input=${(event) => {
|
|
10443
|
+
this.snippetActivityType = event.target.value;
|
|
10444
|
+
this.applyRecipeToEditor();
|
|
10445
|
+
}}
|
|
10446
|
+
/>
|
|
10447
|
+
<datalist id="cpk-snippet-activity">
|
|
10448
|
+
${require_event_snippets.ACTIVITY_STARTERS.map((type) => lit.html`<option value=${type}></option>`)}
|
|
10449
|
+
</datalist>
|
|
10450
|
+
</label>
|
|
10451
|
+
<label class="text-[11px] text-gray-600">
|
|
10452
|
+
Content JSON
|
|
10453
|
+
<textarea
|
|
10454
|
+
class="mt-1 h-24 w-full rounded-md border border-gray-200 px-2 py-1 font-mono text-[11px]"
|
|
10455
|
+
data-testid="cpk-snippet-activity-content"
|
|
10456
|
+
.value=${this.snippetActivityContent}
|
|
10457
|
+
@input=${(event) => {
|
|
10458
|
+
this.snippetActivityContent = event.target.value;
|
|
10459
|
+
this.applyRecipeToEditor();
|
|
10460
|
+
}}
|
|
10461
|
+
></textarea>
|
|
10462
|
+
</label>
|
|
10463
|
+
` : lit.nothing}
|
|
10464
|
+
<label class="text-[11px] text-gray-600">
|
|
10465
|
+
Events JSON
|
|
10466
|
+
<textarea
|
|
10467
|
+
class="mt-1 h-40 w-full rounded-md border border-gray-200 px-2 py-1 font-mono text-[11px]"
|
|
10468
|
+
data-testid="cpk-snippet-json"
|
|
10469
|
+
.value=${this.snippetJson}
|
|
10470
|
+
@input=${(event) => {
|
|
10471
|
+
this.snippetJson = event.target.value;
|
|
10472
|
+
this.requestUpdate();
|
|
10473
|
+
}}
|
|
10474
|
+
></textarea>
|
|
10475
|
+
</label>
|
|
10476
|
+
<div class="flex flex-wrap gap-2">
|
|
10477
|
+
<button
|
|
10478
|
+
type="button"
|
|
10479
|
+
class="rounded-md bg-gray-900 px-3 py-1.5 text-[11px] text-white disabled:opacity-50"
|
|
10480
|
+
data-testid="cpk-snippet-run"
|
|
10481
|
+
?disabled=${!canRun}
|
|
10482
|
+
title=${runBlocked ? "The agent is running. Wait for the current run to end." : !agent ? "No agent is available to inject into." : !canRunJson ? "Events JSON must be a non-empty event array." : "Run snippet"}
|
|
10483
|
+
@click=${() => void this.runCurrentSnippet()}
|
|
10484
|
+
>
|
|
10485
|
+
${runBlocked ? "Agent running" : "Run"}
|
|
10486
|
+
</button>
|
|
10487
|
+
<button
|
|
10488
|
+
type="button"
|
|
10489
|
+
class="rounded-md border border-gray-300 bg-white px-3 py-1.5 text-[11px] disabled:opacity-50"
|
|
10490
|
+
data-testid="cpk-snippet-save"
|
|
10491
|
+
?disabled=${!canSave}
|
|
10492
|
+
title=${canSave ? "Save snippet" : "Events JSON must be a non-empty event array."}
|
|
10493
|
+
@click=${() => this.saveCurrentSnippet("pane")}
|
|
10494
|
+
>
|
|
10495
|
+
Save
|
|
10496
|
+
</button>
|
|
10497
|
+
<button
|
|
10498
|
+
type="button"
|
|
10499
|
+
class="rounded-md border border-gray-300 bg-white px-3 py-1.5 text-[11px] disabled:opacity-50"
|
|
10500
|
+
data-testid="cpk-snippet-reset"
|
|
10501
|
+
?disabled=${!canReset}
|
|
10502
|
+
title=${canReset ? "Remove the last inject from the thread" : "No Inspector inject to reset."}
|
|
10503
|
+
@click=${() => this.resetLastSnippetRun()}
|
|
10504
|
+
>
|
|
10505
|
+
Reset last run
|
|
10506
|
+
</button>
|
|
10507
|
+
<button
|
|
10508
|
+
type="button"
|
|
10509
|
+
class="rounded-md border border-gray-300 bg-white px-3 py-1.5 text-[11px] disabled:opacity-50"
|
|
10510
|
+
data-testid="cpk-snippet-delete"
|
|
10511
|
+
?disabled=${!canDelete}
|
|
10512
|
+
title=${canDelete ? "Delete this snippet" : "Select a snippet to delete."}
|
|
10513
|
+
@click=${() => {
|
|
10514
|
+
if (!this.selectedSnippetId) return;
|
|
10515
|
+
if (!window.confirm("Delete this snippet?")) return;
|
|
10516
|
+
this.eventSnippets = require_event_snippets.deleteEventSnippet(this.selectedSnippetId);
|
|
10517
|
+
this.selectedSnippetId = null;
|
|
10518
|
+
this.requestUpdate();
|
|
10519
|
+
}}
|
|
10520
|
+
>
|
|
10521
|
+
Delete
|
|
10522
|
+
</button>
|
|
10523
|
+
<button
|
|
10524
|
+
type="button"
|
|
10525
|
+
class="rounded-md border border-gray-300 bg-white px-3 py-1.5 text-[11px] disabled:opacity-50"
|
|
10526
|
+
data-testid="cpk-snippet-export"
|
|
10527
|
+
?disabled=${!canExport}
|
|
10528
|
+
title=${canExport ? "Export snippets" : "Save a snippet before you export."}
|
|
10529
|
+
@click=${() => {
|
|
10530
|
+
if (!canExport) return;
|
|
10531
|
+
const blob = new Blob([require_event_snippets.exportEventSnippetsJson(this.eventSnippets)], { type: "application/json" });
|
|
10532
|
+
const url = URL.createObjectURL(blob);
|
|
10533
|
+
const link = document.createElement("a");
|
|
10534
|
+
link.href = url;
|
|
10535
|
+
link.download = "event-snippets.json";
|
|
10536
|
+
link.click();
|
|
10537
|
+
URL.revokeObjectURL(url);
|
|
10538
|
+
}}
|
|
10539
|
+
>
|
|
10540
|
+
Export
|
|
10541
|
+
</button>
|
|
10542
|
+
</div>
|
|
10543
|
+
</div>
|
|
8819
10544
|
</div>
|
|
8820
|
-
|
|
8821
|
-
class="mx-auto max-w-3xl px-3 py-2 text-center text-[10px] leading-4 text-gray-500"
|
|
8822
|
-
>
|
|
8823
|
-
AI can make mistakes. Please verify important information.
|
|
8824
|
-
</p>
|
|
8825
|
-
</form>
|
|
10545
|
+
</div>
|
|
8826
10546
|
`;
|
|
8827
10547
|
}
|
|
8828
10548
|
renderMainContent() {
|
|
8829
10549
|
if (this.settingsOpen) return this.renderSettingsPanel();
|
|
8830
10550
|
if (this.selectedMenu === "home") return this.renderHomeView();
|
|
8831
10551
|
if (this.selectedMenu === WHATS_NEW_MENU_KEY) return this.renderWhatsNewView();
|
|
8832
|
-
if (this.selectedMenu === "ag-ui-events") return
|
|
10552
|
+
if (this.selectedMenu === "ag-ui-events") return lit.html`
|
|
10553
|
+
<div class="flex h-full min-h-0 flex-col">
|
|
10554
|
+
${this.renderEventErrorBanner("run")}
|
|
10555
|
+
<div class="min-h-0 flex-1 overflow-hidden">
|
|
10556
|
+
${this.renderEventsTable()}
|
|
10557
|
+
</div>
|
|
10558
|
+
</div>
|
|
10559
|
+
`;
|
|
8833
10560
|
if (this.selectedMenu === "playground") return this.renderPlaygroundView();
|
|
10561
|
+
if (this.selectedMenu === "event-snippets") return this.renderEventSnippetsView();
|
|
8834
10562
|
if (this.selectedMenu === "agents") return this.renderAgentsView();
|
|
8835
10563
|
if (this.selectedMenu === "frontend-tools") return this.renderToolsView();
|
|
8836
10564
|
if (this.selectedMenu === "capabilities") return this.renderCapabilitiesView();
|
|
@@ -9214,8 +10942,9 @@ ${argsString}</pre
|
|
|
9214
10942
|
</div>
|
|
9215
10943
|
`;
|
|
9216
10944
|
}
|
|
9217
|
-
trackOpened(source, hadUnseenAnnouncement, firstOpen = false) {
|
|
10945
|
+
trackOpened(source, hadUnseenAnnouncement, firstOpen = false, activeSignal = null) {
|
|
9218
10946
|
if (this.core?.telemetryDisabled) return;
|
|
10947
|
+
const errorSignal = activeSignal !== null && isErrorSignalKey(activeSignal) ? activeSignal : null;
|
|
9219
10948
|
require_telemetry.trackInspectorOpened({
|
|
9220
10949
|
open_source: source,
|
|
9221
10950
|
...this.runtimeStatus === "connected" ? {
|
|
@@ -9224,6 +10953,8 @@ ${argsString}</pre
|
|
|
9224
10953
|
} : {},
|
|
9225
10954
|
runtime_url_type: require_telemetry.getRuntimeUrlType(this.core?.runtimeUrl),
|
|
9226
10955
|
has_unseen_announcement: hadUnseenAnnouncement,
|
|
10956
|
+
has_error_signal: errorSignal !== null,
|
|
10957
|
+
...errorSignal === null ? {} : { error_signal_source: errorSignal },
|
|
9227
10958
|
first_open: firstOpen
|
|
9228
10959
|
});
|
|
9229
10960
|
}
|
|
@@ -9387,6 +11118,51 @@ ${argsString}</pre
|
|
|
9387
11118
|
example_kind: exampleKind
|
|
9388
11119
|
});
|
|
9389
11120
|
}
|
|
11121
|
+
subscribeToInspectorThreadBridge() {
|
|
11122
|
+
this.unsubscribeFromInspectorThreadBridge();
|
|
11123
|
+
if (!(0, _copilotkit_core.isInspectorThreadBridgeEnabled)()) return;
|
|
11124
|
+
this.inspectorBridgeUnsubscribers.push((0, _copilotkit_core.onInspectorActiveThread)((payload) => {
|
|
11125
|
+
if (payload.requestId !== this.activeViewInAppRequestId) return;
|
|
11126
|
+
this.inAppThreadId = payload.threadId;
|
|
11127
|
+
this.inAppAgentId = payload.agentId;
|
|
11128
|
+
this.inAppSource = payload.source;
|
|
11129
|
+
if (payload.source === "app") {
|
|
11130
|
+
this.activeViewInAppRequestId = null;
|
|
11131
|
+
this.viewInAppError = null;
|
|
11132
|
+
}
|
|
11133
|
+
this.requestUpdate();
|
|
11134
|
+
}), (0, _copilotkit_core.onInspectorViewThreadResult)((payload) => {
|
|
11135
|
+
if (payload.requestId !== this.activeViewInAppRequestId) return;
|
|
11136
|
+
if (payload.ok) {
|
|
11137
|
+
this.viewInAppError = null;
|
|
11138
|
+
this.inAppThreadId = payload.threadId;
|
|
11139
|
+
this.inAppAgentId = payload.agentId;
|
|
11140
|
+
this.inAppSource = "override";
|
|
11141
|
+
} else {
|
|
11142
|
+
this.activeViewInAppRequestId = null;
|
|
11143
|
+
this.inAppThreadId = null;
|
|
11144
|
+
this.inAppAgentId = null;
|
|
11145
|
+
this.inAppSource = null;
|
|
11146
|
+
this.viewInAppError = "The app could not load that thread. The previous chat is back.";
|
|
11147
|
+
}
|
|
11148
|
+
this.requestUpdate();
|
|
11149
|
+
}));
|
|
11150
|
+
}
|
|
11151
|
+
unsubscribeFromInspectorThreadBridge() {
|
|
11152
|
+
for (const unsubscribe of this.inspectorBridgeUnsubscribers) unsubscribe();
|
|
11153
|
+
this.inspectorBridgeUnsubscribers = [];
|
|
11154
|
+
}
|
|
11155
|
+
getViewInAppMode(thread, isExample) {
|
|
11156
|
+
if (!(0, _copilotkit_core.isInspectorThreadBridgeEnabled)()) return "hidden";
|
|
11157
|
+
if (!thread || isExample) return "hidden";
|
|
11158
|
+
if (this.activeViewInAppRequestId && this.inAppSource === "override" && this.inAppThreadId === thread.id) return "stop";
|
|
11159
|
+
return "view";
|
|
11160
|
+
}
|
|
11161
|
+
getSelectedRealThread() {
|
|
11162
|
+
if (!this.selectedThreadId) return null;
|
|
11163
|
+
if (this.selectedThreadId === this.selectedLocalExampleThreadId) return null;
|
|
11164
|
+
return this.getActiveThreadsState().displayThreads.find((thread) => thread.id === this.selectedThreadId) ?? null;
|
|
11165
|
+
}
|
|
9390
11166
|
getCurrentExampleTourProps() {
|
|
9391
11167
|
const exampleKind = this.selectedThreadId ? getExampleKind(this.selectedThreadId) : void 0;
|
|
9392
11168
|
const tourPair = getExampleTourTelemetryPair(this.exampleTourStep);
|
|
@@ -10006,7 +11782,7 @@ ${argsString}</pre
|
|
|
10006
11782
|
<line x1="12" y1="16" x2="12.01" y2="16" />
|
|
10007
11783
|
</svg>
|
|
10008
11784
|
<span style="font-size: 13px; color: #c0333a;">
|
|
10009
|
-
|
|
11785
|
+
${MEMORY_LOAD_ERROR_LABEL}
|
|
10010
11786
|
</span>
|
|
10011
11787
|
<span
|
|
10012
11788
|
style="
|
|
@@ -10019,6 +11795,17 @@ ${argsString}</pre
|
|
|
10019
11795
|
>
|
|
10020
11796
|
${this._memoriesError.message}
|
|
10021
11797
|
</span>
|
|
11798
|
+
<span
|
|
11799
|
+
style="
|
|
11800
|
+
max-width: 320px;
|
|
11801
|
+
text-align: center;
|
|
11802
|
+
font-size: 11px;
|
|
11803
|
+
line-height: 1.5;
|
|
11804
|
+
color: #c0333a;
|
|
11805
|
+
"
|
|
11806
|
+
>
|
|
11807
|
+
${EVENT_ERROR_GUIDANCE.memory.advice}
|
|
11808
|
+
</span>
|
|
10022
11809
|
</div>
|
|
10023
11810
|
`;
|
|
10024
11811
|
if (this._memoriesLoading && this._memories.length === 0) return lit.html`
|
|
@@ -10202,6 +11989,7 @@ ${argsString}</pre
|
|
|
10202
11989
|
data-color-scheme=${this.colorScheme}
|
|
10203
11990
|
.threads=${visibleThreads}
|
|
10204
11991
|
.selectedThreadId=${this.selectedThreadId}
|
|
11992
|
+
.inAppThreadId=${this.inAppThreadId}
|
|
10205
11993
|
.errorMessage=${threadsErrorMessage}
|
|
10206
11994
|
.suppressEmptyState=${loadingWithoutRows}
|
|
10207
11995
|
@threadSelected=${(e) => {
|
|
@@ -10271,6 +12059,10 @@ ${argsString}</pre
|
|
|
10271
12059
|
.headers=${this._core?.headers ?? {}}
|
|
10272
12060
|
.threadInspectionAvailable=${selectedThreadIsLocalExample || this.areThreadEndpointsAvailable() && this._core?.threadEndpoints?.inspect !== false}
|
|
10273
12061
|
.liveMessageVersion=${this.liveMessageVersion.get(selectedThread.id) ?? 0}
|
|
12062
|
+
.viewInAppMode=${this.getViewInAppMode(selectedThread, selectedThreadIsLocalExample)}
|
|
12063
|
+
.viewInAppError=${this.viewInAppError}
|
|
12064
|
+
@viewInApp=${this.handleViewInApp}
|
|
12065
|
+
@stopViewing=${this.handleStopViewing}
|
|
10274
12066
|
.focusMessageId=${this.focusedThreadMessageId}
|
|
10275
12067
|
.focusRequestId=${this.threadFocusRequestId}
|
|
10276
12068
|
.agentStateInput=${this.getLatestStateForAgent(selectedThread.agentId)}
|
|
@@ -10439,7 +12231,10 @@ ${argsString}</pre
|
|
|
10439
12231
|
</div>
|
|
10440
12232
|
</div>
|
|
10441
12233
|
`;
|
|
10442
|
-
else
|
|
12234
|
+
else {
|
|
12235
|
+
const runError = this.eventErrorDetails.run;
|
|
12236
|
+
const failedRunEventId = runError ? this.findLatestRunErrorEvent(runError.agentId)?.id : void 0;
|
|
12237
|
+
body = lit.html`
|
|
10443
12238
|
<div class="relative h-full w-full overflow-y-auto overflow-x-hidden">
|
|
10444
12239
|
<table class="w-full table-fixed border-collapse text-xs box-border">
|
|
10445
12240
|
<colgroup>
|
|
@@ -10451,10 +12246,10 @@ ${argsString}</pre
|
|
|
10451
12246
|
<thead class="sticky top-0 z-10">
|
|
10452
12247
|
<tr class="bg-white">
|
|
10453
12248
|
${[
|
|
10454
|
-
|
|
10455
|
-
|
|
10456
|
-
|
|
10457
|
-
|
|
12249
|
+
"Agent",
|
|
12250
|
+
"Time",
|
|
12251
|
+
"Event Type"
|
|
12252
|
+
].map((label, col) => lit.html` <th
|
|
10458
12253
|
class="border-b border-gray-200 bg-white px-3 py-2 text-left font-medium text-gray-900"
|
|
10459
12254
|
style="position:relative;overflow:hidden;"
|
|
10460
12255
|
>
|
|
@@ -10476,16 +12271,18 @@ ${argsString}</pre
|
|
|
10476
12271
|
</thead>
|
|
10477
12272
|
<tbody>
|
|
10478
12273
|
${filteredEvents.map((event, index) => {
|
|
10479
|
-
|
|
10480
|
-
|
|
10481
|
-
|
|
10482
|
-
|
|
10483
|
-
|
|
10484
|
-
|
|
10485
|
-
|
|
12274
|
+
const isFailedRunEvent = failedRunEventId !== void 0 && event.id === failedRunEventId;
|
|
12275
|
+
const rowBg = isFailedRunEvent ? "bg-rose-50" : index % 2 === 0 ? "bg-white" : "bg-gray-50/50";
|
|
12276
|
+
const badgeClasses = this.getEventBadgeClasses(event.type);
|
|
12277
|
+
const extractedEvent = this.extractEventFromPayload(event.payload);
|
|
12278
|
+
const inlineEvent = this.stringifyPayload(extractedEvent, false) || "—";
|
|
12279
|
+
const prettyEvent = this.stringifyPayload(extractedEvent, true) || inlineEvent;
|
|
12280
|
+
const isExpanded = this.expandedRows.has(event.id);
|
|
12281
|
+
return lit.html`
|
|
10486
12282
|
<tr
|
|
10487
12283
|
class="${rowBg} cursor-pointer transition hover:bg-blue-50/50"
|
|
10488
12284
|
data-inspector-event-id=${event.id}
|
|
12285
|
+
data-cpk-failed-run-event=${isFailedRunEvent ? event.id : void 0}
|
|
10489
12286
|
@click=${(clickEvent) => this.toggleRowExpansion(event.id, clickEvent)}
|
|
10490
12287
|
>
|
|
10491
12288
|
<td
|
|
@@ -10518,9 +12315,9 @@ ${prettyEvent}</pre
|
|
|
10518
12315
|
<button
|
|
10519
12316
|
class="absolute right-0 top-0 cursor-pointer rounded px-2 py-1 text-[10px] opacity-0 transition group-hover:opacity-100 ${this.copiedEvents.has(event.id) ? "bg-green-100 text-green-700" : "bg-gray-100 text-gray-600 hover:bg-gray-200 hover:text-gray-900"}"
|
|
10520
12317
|
@click=${(e) => {
|
|
10521
|
-
|
|
10522
|
-
|
|
10523
|
-
|
|
12318
|
+
e.stopPropagation();
|
|
12319
|
+
this.copyToClipboard(prettyEvent, event.id, e);
|
|
12320
|
+
}}
|
|
10524
12321
|
>
|
|
10525
12322
|
${this.copiedEvents.has(event.id) ? lit.html`
|
|
10526
12323
|
<span>✓ Copied</span>
|
|
@@ -10533,11 +12330,12 @@ ${prettyEvent}</pre
|
|
|
10533
12330
|
</td>
|
|
10534
12331
|
</tr>
|
|
10535
12332
|
`;
|
|
10536
|
-
|
|
12333
|
+
})}
|
|
10537
12334
|
</tbody>
|
|
10538
12335
|
</table>
|
|
10539
12336
|
</div>
|
|
10540
12337
|
`;
|
|
12338
|
+
}
|
|
10541
12339
|
return lit.html`
|
|
10542
12340
|
<div
|
|
10543
12341
|
class="${embedded ? "flex h-[28rem] min-h-[20rem] flex-col" : "flex h-full flex-col"}"
|
|
@@ -10602,6 +12400,7 @@ ${prettyEvent}</pre
|
|
|
10602
12400
|
}
|
|
10603
12401
|
renderAgentsView() {
|
|
10604
12402
|
if (this.selectedContext === "all-agents") return lit.html`
|
|
12403
|
+
${this.renderEventErrorBanner("tool")}
|
|
10605
12404
|
<div
|
|
10606
12405
|
class="flex h-full items-center justify-center px-4 py-8 text-center"
|
|
10607
12406
|
>
|
|
@@ -10625,6 +12424,7 @@ ${prettyEvent}</pre
|
|
|
10625
12424
|
const messages = this.getLatestMessagesForAgent(agentId);
|
|
10626
12425
|
return lit.html`
|
|
10627
12426
|
<div class="cpk-agent-view flex flex-col gap-4 p-4 overflow-auto">
|
|
12427
|
+
${this.renderEventErrorBanner("tool")}
|
|
10628
12428
|
<!-- Agent Overview Card -->
|
|
10629
12429
|
<div
|
|
10630
12430
|
class="cpk-agent-overview rounded-lg border border-gray-200 bg-white p-4"
|
|
@@ -10757,8 +12557,13 @@ ${prettyEvent}</pre
|
|
|
10757
12557
|
const toolCalls = msg.toolCalls ?? [];
|
|
10758
12558
|
const hasContent = rawContent.trim().length > 0;
|
|
10759
12559
|
const contentFallback = toolCalls.length > 0 ? "Invoked tool call" : "—";
|
|
12560
|
+
const toolError = this.eventErrorDetails.tool;
|
|
12561
|
+
const isFailedResult = role === "tool" && toolError?.toolCallId !== void 0 && toolError.toolCallId === msg.toolCallId;
|
|
10760
12562
|
return lit.html`
|
|
10761
|
-
<div
|
|
12563
|
+
<div
|
|
12564
|
+
class=${isFailedResult ? "flex items-start bg-rose-50" : "flex items-start"}
|
|
12565
|
+
data-cpk-failed-tool-result=${isFailedResult ? msg.toolCallId : lit.nothing}
|
|
12566
|
+
>
|
|
10762
12567
|
<div class="w-40 shrink-0 px-4 py-2">
|
|
10763
12568
|
<span
|
|
10764
12569
|
class="inline-flex rounded px-2 py-0.5 text-[10px] font-medium ${roleColors[role] || roleColors.unknown}"
|
|
@@ -10864,6 +12669,81 @@ ${prettyEvent}</pre
|
|
|
10864
12669
|
</div>
|
|
10865
12670
|
`;
|
|
10866
12671
|
}
|
|
12672
|
+
/**
|
|
12673
|
+
* The Agent view is empty on "All Agents". Pick the agent that just failed
|
|
12674
|
+
* a tool, or the one with the most recent activity.
|
|
12675
|
+
*/
|
|
12676
|
+
applyEventErrorLanding(key) {
|
|
12677
|
+
const error = this.eventErrorDetails[key];
|
|
12678
|
+
if (!error) {
|
|
12679
|
+
if (this.selectedMenu === "agents") this.focusAgentForView();
|
|
12680
|
+
return;
|
|
12681
|
+
}
|
|
12682
|
+
if (error.agentId && this.contextOptions.some((option) => option.key === error.agentId)) this.selectedContext = error.agentId;
|
|
12683
|
+
else if (this.selectedMenu === "agents") this.focusAgentForView(error);
|
|
12684
|
+
if (key === "tool" && error.toolCallId) {
|
|
12685
|
+
this.pendingScrollToToolCallId = error.toolCallId;
|
|
12686
|
+
return;
|
|
12687
|
+
}
|
|
12688
|
+
if (key === "run") {
|
|
12689
|
+
this.eventFilterText = "";
|
|
12690
|
+
this.eventTypeFilter = "all";
|
|
12691
|
+
const event = this.findLatestRunErrorEvent(error.agentId);
|
|
12692
|
+
if (!event) return;
|
|
12693
|
+
this.expandedRows.clear();
|
|
12694
|
+
this.expandedRows.add(event.id);
|
|
12695
|
+
this.pendingScrollToEventId = event.id;
|
|
12696
|
+
}
|
|
12697
|
+
}
|
|
12698
|
+
/**
|
|
12699
|
+
* Whether the landing view really carries the item the card points at.
|
|
12700
|
+
* Mirrors the two branches of `applyEventErrorLanding` that can bail out.
|
|
12701
|
+
*/
|
|
12702
|
+
hasEventErrorHighlight(key) {
|
|
12703
|
+
const error = this.eventErrorDetails[key];
|
|
12704
|
+
if (!error) return false;
|
|
12705
|
+
if (key === "tool") return error.toolCallId !== void 0;
|
|
12706
|
+
if (key === "run") return this.findLatestRunErrorEvent(error.agentId) !== void 0;
|
|
12707
|
+
return false;
|
|
12708
|
+
}
|
|
12709
|
+
findLatestRunErrorEvent(agentId) {
|
|
12710
|
+
return (agentId && agentId !== "all-agents" ? this.agentEvents.get(agentId) ?? [] : this.flattenedEvents).find((event) => event.type === "RUN_ERROR");
|
|
12711
|
+
}
|
|
12712
|
+
flushErrorLandingScroll() {
|
|
12713
|
+
const eventId = this.pendingScrollToEventId;
|
|
12714
|
+
if (eventId) {
|
|
12715
|
+
this.pendingScrollToEventId = null;
|
|
12716
|
+
Array.from(this.activeRoot.querySelectorAll("[data-inspector-event-id]")).find((candidate) => candidate.dataset.inspectorEventId === eventId)?.scrollIntoView?.({ block: "center" });
|
|
12717
|
+
}
|
|
12718
|
+
const toolCallId = this.pendingScrollToToolCallId;
|
|
12719
|
+
if (toolCallId) {
|
|
12720
|
+
this.pendingScrollToToolCallId = null;
|
|
12721
|
+
const escaped = escapeSelectorValue(toolCallId);
|
|
12722
|
+
(this.activeRoot.querySelector(`[data-cpk-failed-tool-call="${escaped}"]`) ?? this.activeRoot.querySelector(`[data-cpk-failed-tool-result="${escaped}"]`))?.scrollIntoView?.({ block: "center" });
|
|
12723
|
+
}
|
|
12724
|
+
}
|
|
12725
|
+
/**
|
|
12726
|
+
* The Agent view is empty on "All Agents". Pick the agent that just failed
|
|
12727
|
+
* a tool, or the one with the most recent activity.
|
|
12728
|
+
*/
|
|
12729
|
+
focusAgentForView(error) {
|
|
12730
|
+
const agentOptions = this.contextOptions.filter((opt) => opt.key !== "all-agents");
|
|
12731
|
+
if (agentOptions.length === 0) return;
|
|
12732
|
+
const errorAgentId = error?.agentId;
|
|
12733
|
+
if (errorAgentId && agentOptions.some((option) => option.key === errorAgentId)) {
|
|
12734
|
+
this.selectedContext = errorAgentId;
|
|
12735
|
+
return;
|
|
12736
|
+
}
|
|
12737
|
+
if (this.selectedContext !== "all-agents") return;
|
|
12738
|
+
const mostRecent = agentOptions.reduce((best, opt) => {
|
|
12739
|
+
const ts = this.getAgentStats(opt.key).lastActivity ?? -1;
|
|
12740
|
+
return best === null || ts > best.ts ? {
|
|
12741
|
+
key: opt.key,
|
|
12742
|
+
ts
|
|
12743
|
+
} : best;
|
|
12744
|
+
}, null);
|
|
12745
|
+
this.selectedContext = mostRecent ? mostRecent.key : agentOptions[0].key;
|
|
12746
|
+
}
|
|
10867
12747
|
handleMenuSelect(key) {
|
|
10868
12748
|
if (!this.menuItems.some((item) => item.key === key)) return;
|
|
10869
12749
|
const previousMenu = this.selectedMenu;
|
|
@@ -10872,19 +12752,6 @@ ${prettyEvent}</pre
|
|
|
10872
12752
|
this.selectedMenu = key;
|
|
10873
12753
|
this.settingsOpen = false;
|
|
10874
12754
|
this.lastSelectedMenuByGroup[require_inspector_nav.getGroupForMenu(key)] = key;
|
|
10875
|
-
if (key === "agents" && this.selectedContext === "all-agents") {
|
|
10876
|
-
const agentOptions = this.contextOptions.filter((opt) => opt.key !== "all-agents");
|
|
10877
|
-
if (agentOptions.length > 0) {
|
|
10878
|
-
const mostRecent = agentOptions.reduce((best, opt) => {
|
|
10879
|
-
const ts = this.getAgentStats(opt.key).lastActivity ?? -1;
|
|
10880
|
-
return best === null || ts > best.ts ? {
|
|
10881
|
-
key: opt.key,
|
|
10882
|
-
ts
|
|
10883
|
-
} : best;
|
|
10884
|
-
}, null);
|
|
10885
|
-
this.selectedContext = mostRecent ? mostRecent.key : agentOptions[0].key;
|
|
10886
|
-
}
|
|
10887
|
-
}
|
|
10888
12755
|
if (previousMenu === "agents" && key !== "agents") {
|
|
10889
12756
|
if (this.contextOptions.filter((opt) => opt.key !== "all-agents").length > 1) this.selectedContext = "all-agents";
|
|
10890
12757
|
}
|
|
@@ -10898,10 +12765,13 @@ ${prettyEvent}</pre
|
|
|
10898
12765
|
if (previousMenu !== "memories" && !this.core?.telemetryDisabled) require_telemetry.trackMemoriesTabClicked(this.getMemoriesTelemetryProps());
|
|
10899
12766
|
}
|
|
10900
12767
|
if (key === "home" && previousMenu !== "home") this.homeViewedThisOpen = false;
|
|
10901
|
-
if (key === "
|
|
10902
|
-
|
|
10903
|
-
if (
|
|
10904
|
-
|
|
12768
|
+
if (key === "event-snippets") this.reloadEventSnippets();
|
|
12769
|
+
if (key === "ag-ui-events" || key === "agents") {
|
|
12770
|
+
if (!(this.pendingScrollToEventId !== null || this.pendingScrollToToolCallId !== null)) requestAnimationFrame(() => {
|
|
12771
|
+
const scroller = this.activeRoot.querySelector("#cpk-main-scroll");
|
|
12772
|
+
if (scroller) scroller.scrollTop = 0;
|
|
12773
|
+
});
|
|
12774
|
+
}
|
|
10905
12775
|
this.contextMenuOpen = false;
|
|
10906
12776
|
this.layoutMenuOpen = false;
|
|
10907
12777
|
this.persistState();
|
|
@@ -11537,50 +13407,443 @@ ${prettyEvent}</pre
|
|
|
11537
13407
|
else this.expandedRows.add(eventId);
|
|
11538
13408
|
this.requestUpdate();
|
|
11539
13409
|
}
|
|
13410
|
+
/** Whether a given subject currently has something to say. */
|
|
13411
|
+
isSignalArmed(key) {
|
|
13412
|
+
if (isWiringErrorKey(key)) return this.errorSignalArmed[key];
|
|
13413
|
+
if (isEventErrorKey(key)) return this.eventErrorArmed[key];
|
|
13414
|
+
return this.newsSignalArmed;
|
|
13415
|
+
}
|
|
13416
|
+
/**
|
|
13417
|
+
* The signal that owns the single launcher dot, or null when the launcher is
|
|
13418
|
+
* quiet. Precedence rather than replacement: a suppressed signal stays armed
|
|
13419
|
+
* and takes the dot as soon as the higher-priority one clears, and its own
|
|
13420
|
+
* navigation marker is visible the whole time.
|
|
13421
|
+
*/
|
|
13422
|
+
getActiveLauncherSignal() {
|
|
13423
|
+
for (const key of LAUNCHER_SIGNAL_PRIORITY_ORDER) if (this.isSignalArmed(key)) return key;
|
|
13424
|
+
return null;
|
|
13425
|
+
}
|
|
13426
|
+
/**
|
|
13427
|
+
* The marker a navigation entry carries, or null for an unmarked entry.
|
|
13428
|
+
*
|
|
13429
|
+
* Markers are independent of the launcher's single dot, so a suppressed
|
|
13430
|
+
* signal is never actually hidden once the panel is open. They also render
|
|
13431
|
+
* on the entry that is *currently selected*: for the news signal that never
|
|
13432
|
+
* mattered, because its marker clears as soon as the view renders, but a
|
|
13433
|
+
* state mirror stays true while it is being read and suppressing it on the
|
|
13434
|
+
* active entry would make it reappear on navigating away.
|
|
13435
|
+
*/
|
|
13436
|
+
getNavigationSignalFor(key) {
|
|
13437
|
+
for (const signalKey of LAUNCHER_SIGNAL_PRIORITY_ORDER) {
|
|
13438
|
+
const signal = LAUNCHER_SIGNALS[signalKey];
|
|
13439
|
+
if (signal.markerTarget !== key) continue;
|
|
13440
|
+
if (!this.isSignalArmed(signalKey)) continue;
|
|
13441
|
+
if (signalKey === NEWS_SIGNAL_ID && !this.announcementLoaded) continue;
|
|
13442
|
+
return signal;
|
|
13443
|
+
}
|
|
13444
|
+
return null;
|
|
13445
|
+
}
|
|
13446
|
+
/** Whether a wiring error source is currently red. */
|
|
13447
|
+
hasArmedErrorSignal() {
|
|
13448
|
+
return WIRING_ERROR_KEYS.some((source) => this.errorSignalArmed[source]);
|
|
13449
|
+
}
|
|
13450
|
+
armEventErrorFromCode(code, message, context) {
|
|
13451
|
+
const key = eventErrorKeyForCode(code);
|
|
13452
|
+
if (key === null) return;
|
|
13453
|
+
const agentId = typeof context?.agentId === "string" && context.agentId.length > 0 ? context.agentId : void 0;
|
|
13454
|
+
const toolName = typeof context?.toolName === "string" && context.toolName.length > 0 ? context.toolName : void 0;
|
|
13455
|
+
const toolCallId = typeof context?.toolCallId === "string" && context.toolCallId.length > 0 ? context.toolCallId : void 0;
|
|
13456
|
+
this.armEventError(key, message, {
|
|
13457
|
+
agentId,
|
|
13458
|
+
toolName,
|
|
13459
|
+
toolCallId
|
|
13460
|
+
});
|
|
13461
|
+
}
|
|
13462
|
+
armEventError(key, message, extras = {}) {
|
|
13463
|
+
this.eventErrorDetails[key] = {
|
|
13464
|
+
message,
|
|
13465
|
+
...extras
|
|
13466
|
+
};
|
|
13467
|
+
const wasArmed = this.eventErrorArmed[key];
|
|
13468
|
+
this.eventErrorArmed[key] = true;
|
|
13469
|
+
if (!wasArmed) this.startSignalPulse(key);
|
|
13470
|
+
if (this.isOpen && !this.settingsOpen && this.selectedMenu === LAUNCHER_SIGNALS[key].landingTarget) this.applyEventErrorLanding(key);
|
|
13471
|
+
this.requestUpdate();
|
|
13472
|
+
}
|
|
13473
|
+
clearEventError(key) {
|
|
13474
|
+
if (!this.eventErrorArmed[key]) return;
|
|
13475
|
+
this.eventErrorArmed[key] = false;
|
|
13476
|
+
this.errorSignalViewedSources.delete(key);
|
|
13477
|
+
this.retireSignal(key);
|
|
13478
|
+
this.requestUpdate();
|
|
13479
|
+
}
|
|
13480
|
+
clearAllEventErrors() {
|
|
13481
|
+
for (const key of EVENT_ERROR_KEYS) {
|
|
13482
|
+
this.eventErrorDetails[key] = null;
|
|
13483
|
+
if (!this.eventErrorArmed[key]) continue;
|
|
13484
|
+
this.eventErrorArmed[key] = false;
|
|
13485
|
+
this.retireSignal(key);
|
|
13486
|
+
}
|
|
13487
|
+
}
|
|
13488
|
+
/**
|
|
13489
|
+
* An event error is unread until its landing view is actually on screen.
|
|
13490
|
+
* Opening the Inspector for a different leaf must not burn it.
|
|
13491
|
+
*/
|
|
13492
|
+
maybeCompleteEventErrorView() {
|
|
13493
|
+
if (!this.isOpen || this.settingsOpen) return;
|
|
13494
|
+
for (const key of EVENT_ERROR_KEYS) {
|
|
13495
|
+
if (!this.eventErrorArmed[key]) continue;
|
|
13496
|
+
if (this.selectedMenu !== LAUNCHER_SIGNALS[key].landingTarget) continue;
|
|
13497
|
+
this.clearEventError(key);
|
|
13498
|
+
}
|
|
13499
|
+
}
|
|
13500
|
+
isReducedMotionPreferred() {
|
|
13501
|
+
return typeof window !== "undefined" && window.matchMedia?.("(prefers-reduced-motion: reduce)").matches === true;
|
|
13502
|
+
}
|
|
11540
13503
|
armNewsSignal(options) {
|
|
11541
13504
|
const wasArmed = this.newsSignalArmed;
|
|
11542
13505
|
this.newsSignalArmed = true;
|
|
11543
|
-
if (options.pulse
|
|
11544
|
-
this.newsSignalPulsePending = true;
|
|
11545
|
-
if (!wasArmed) this.requestUpdate();
|
|
11546
|
-
} else if (options.pulse) this.startNewsSignalPulse();
|
|
13506
|
+
if (options.pulse) this.startSignalPulse(NEWS_SIGNAL_ID);
|
|
11547
13507
|
else if (!wasArmed) this.requestUpdate();
|
|
11548
13508
|
}
|
|
11549
13509
|
clearNewsSignal() {
|
|
11550
13510
|
if (!this.newsSignalArmed) return;
|
|
11551
13511
|
this.newsSignalArmed = false;
|
|
11552
|
-
this.newsSignalPulsePending = false;
|
|
11553
13512
|
if (this.announcementTimestamp) require_persistence.saveAnnouncementReadTimestamp(this.announcementTimestamp);
|
|
11554
|
-
|
|
13513
|
+
this.retireSignal(NEWS_SIGNAL_ID);
|
|
11555
13514
|
this.requestUpdate();
|
|
11556
13515
|
}
|
|
11557
|
-
|
|
11558
|
-
|
|
11559
|
-
|
|
11560
|
-
|
|
13516
|
+
/**
|
|
13517
|
+
* Requests one beat for a signal, running it now or deferring it.
|
|
13518
|
+
*
|
|
13519
|
+
* There is a single pending slot and four reasons a beat cannot land. All
|
|
13520
|
+
* four are the same situation — "cannot land now, run later" — and treating
|
|
13521
|
+
* them alike is the point: three separate behaviours for one situation would
|
|
13522
|
+
* not survive a third signal.
|
|
13523
|
+
*
|
|
13524
|
+
* Reason 3 is not cosmetic. Starting a beat while one runs does not restart
|
|
13525
|
+
* the animation, because the attribute it binds to does not change value and
|
|
13526
|
+
* the pseudo-element selectors match on attribute *presence*; the running
|
|
13527
|
+
* beat would merely change colour mid-flight. A failure that arms during an
|
|
13528
|
+
* announcement beat must wait for that beat to end, or it would run only as
|
|
13529
|
+
* its final fraction.
|
|
13530
|
+
*
|
|
13531
|
+
* A failure's beat is followed by a pill, and the whole 3.4-second gesture
|
|
13532
|
+
* holds this one slot for its full duration. That is not a second scheduling
|
|
13533
|
+
* concept: reason 3 already says "another beat is running", and a gesture is
|
|
13534
|
+
* simply a longer beat.
|
|
13535
|
+
*/
|
|
13536
|
+
startSignalPulse(key) {
|
|
13537
|
+
if (this.isOpen || typeof document !== "undefined" && document.visibilityState !== "visible" || this.gestureSlotSignal !== null && this.gestureSlotSignal !== key || this.getActiveLauncherSignal() !== key) {
|
|
13538
|
+
const pending = this.pendingPulseSignal;
|
|
13539
|
+
if (pending === null || LAUNCHER_SIGNALS[key].priority >= LAUNCHER_SIGNALS[pending].priority) this.pendingPulseSignal = key;
|
|
11561
13540
|
this.requestUpdate();
|
|
11562
13541
|
return;
|
|
11563
13542
|
}
|
|
11564
|
-
this.
|
|
11565
|
-
this.
|
|
11566
|
-
|
|
13543
|
+
this.stopSignalPulse();
|
|
13544
|
+
this.pendingPulseSignal = null;
|
|
13545
|
+
this.pulsingSignal = key;
|
|
13546
|
+
if (isWiringErrorKey(key)) this.errorBeatSpent = true;
|
|
13547
|
+
else if (this.announcementTimestamp && key === NEWS_SIGNAL_ID) require_persistence.saveAnnouncementPulsedTimestamp(this.announcementTimestamp);
|
|
13548
|
+
this.beginGestureTail(key);
|
|
11567
13549
|
this.requestUpdate();
|
|
11568
13550
|
if (typeof window === "undefined") return;
|
|
11569
13551
|
this.pulseTimeoutId = setTimeout(() => {
|
|
11570
13552
|
this.pulseTimeoutId = null;
|
|
11571
|
-
this.
|
|
13553
|
+
this.pulsingSignal = null;
|
|
11572
13554
|
this.requestUpdate();
|
|
11573
|
-
|
|
13555
|
+
if (this.gestureSignal === key && this.pillPhase === "closed") {
|
|
13556
|
+
this.openPill();
|
|
13557
|
+
return;
|
|
13558
|
+
}
|
|
13559
|
+
if (this.gestureSignal === key) {
|
|
13560
|
+
this.endGesture();
|
|
13561
|
+
return;
|
|
13562
|
+
}
|
|
13563
|
+
this.flushPendingSignalPulse();
|
|
13564
|
+
}, LAUNCHER_SIGNALS[key].cadence);
|
|
11574
13565
|
}
|
|
11575
|
-
|
|
13566
|
+
stopSignalPulse() {
|
|
11576
13567
|
if (this.pulseTimeoutId !== null) {
|
|
11577
13568
|
clearTimeout(this.pulseTimeoutId);
|
|
11578
13569
|
this.pulseTimeoutId = null;
|
|
11579
13570
|
}
|
|
11580
|
-
this.
|
|
13571
|
+
this.pulsingSignal = null;
|
|
13572
|
+
}
|
|
13573
|
+
/**
|
|
13574
|
+
* Runs a deferred beat if it can land now, and drops it if its reason to
|
|
13575
|
+
* exist has gone: a nudge about a problem that no longer exists is worse
|
|
13576
|
+
* than no nudge at all.
|
|
13577
|
+
*/
|
|
13578
|
+
flushPendingSignalPulse() {
|
|
13579
|
+
const key = this.pendingPulseSignal;
|
|
13580
|
+
if (key === null) return;
|
|
13581
|
+
if (!this.isSignalArmed(key)) {
|
|
13582
|
+
this.pendingPulseSignal = null;
|
|
13583
|
+
this.requestUpdate();
|
|
13584
|
+
return;
|
|
13585
|
+
}
|
|
13586
|
+
this.startSignalPulse(key);
|
|
13587
|
+
}
|
|
13588
|
+
/**
|
|
13589
|
+
* Drops a signal's gesture, pending or running, when the signal goes quiet.
|
|
13590
|
+
*
|
|
13591
|
+
* The pill closes early: it states a condition, and the condition has
|
|
13592
|
+
* stopped being true. The beat is left to finish, because a beat asserts
|
|
13593
|
+
* nothing — it says *here*, and "here" is still true.
|
|
13594
|
+
*/
|
|
13595
|
+
retireSignal(key) {
|
|
13596
|
+
if (this.pendingPulseSignal === key) this.pendingPulseSignal = null;
|
|
13597
|
+
if (this.gestureSignal === key) this.closePillEarly();
|
|
13598
|
+
this.flushPendingSignalPulse();
|
|
13599
|
+
}
|
|
13600
|
+
/**
|
|
13601
|
+
* The signal holding the single gesture slot: a beat in flight, or the pill
|
|
13602
|
+
* and spoken sentence that follow it. One slot, not two — see reason 3 in
|
|
13603
|
+
* `startSignalPulse`.
|
|
13604
|
+
*/
|
|
13605
|
+
get gestureSlotSignal() {
|
|
13606
|
+
return this.pulsingSignal ?? this.gestureSignal;
|
|
13607
|
+
}
|
|
13608
|
+
/**
|
|
13609
|
+
* Opens the gesture's tail alongside the beat, for a signal that carries a
|
|
13610
|
+
* pill. The pill is rendered immediately — clipped to nothing, so it shows
|
|
13611
|
+
* nothing — because its full width has to be on the page before the room
|
|
13612
|
+
* either side of the launcher can be measured.
|
|
13613
|
+
*
|
|
13614
|
+
* A signal with no pill label gets no tail at all, so the announcement's
|
|
13615
|
+
* gesture is exactly the beat it has always been.
|
|
13616
|
+
*/
|
|
13617
|
+
beginGestureTail(key) {
|
|
13618
|
+
this.cancelPillTimeout();
|
|
13619
|
+
if (LAUNCHER_SIGNALS[key].pillLabel === void 0) {
|
|
13620
|
+
this.gestureSignal = null;
|
|
13621
|
+
this.pillPhase = null;
|
|
13622
|
+
this.pillDirection = null;
|
|
13623
|
+
return;
|
|
13624
|
+
}
|
|
13625
|
+
this.gestureSignal = key;
|
|
13626
|
+
this.pillPhase = "closed";
|
|
13627
|
+
this.pillDirection = null;
|
|
13628
|
+
this.closeLauncherHud();
|
|
13629
|
+
}
|
|
13630
|
+
/**
|
|
13631
|
+
* Chooses the side, or suppresses the pill, from the room actually available
|
|
13632
|
+
* at gesture start. Measured once, from the DOM, because the launcher is
|
|
13633
|
+
* draggable and its position persists: a reader who parked it near the left
|
|
13634
|
+
* edge would otherwise get a permanently truncated pill.
|
|
13635
|
+
*
|
|
13636
|
+
* Where neither side has room there is no pill at all rather than a cut-off
|
|
13637
|
+
* one — the dot and the beat still fire, so the signal is intact and only
|
|
13638
|
+
* the label is lost. Constraining where the reader may drag the control to
|
|
13639
|
+
* protect this animation was considered and rejected: the page is theirs.
|
|
13640
|
+
*/
|
|
13641
|
+
resolvePillDirection() {
|
|
13642
|
+
if (this.pillDirection !== null || this.pillPhase === null) return;
|
|
13643
|
+
const wrapper = this.activeRoot.querySelector(".console-button-wrapper");
|
|
13644
|
+
const button = wrapper?.querySelector(".console-button");
|
|
13645
|
+
const pill = wrapper?.querySelector(".cpk-launcher-pill");
|
|
13646
|
+
if (!button || !pill || typeof window === "undefined") return;
|
|
13647
|
+
const mark = button.getBoundingClientRect();
|
|
13648
|
+
const overhang = Math.max(0, pill.getBoundingClientRect().width - mark.width);
|
|
13649
|
+
const viewportWidth = window.innerWidth;
|
|
13650
|
+
if (overhang === 0) {
|
|
13651
|
+
this.setPillOutcome("left");
|
|
13652
|
+
return;
|
|
13653
|
+
}
|
|
13654
|
+
if (mark.left - overhang >= EDGE_MARGIN) {
|
|
13655
|
+
this.setPillOutcome("left");
|
|
13656
|
+
return;
|
|
13657
|
+
}
|
|
13658
|
+
if (mark.right + overhang <= viewportWidth - EDGE_MARGIN) {
|
|
13659
|
+
this.setPillOutcome("right");
|
|
13660
|
+
return;
|
|
13661
|
+
}
|
|
13662
|
+
this.setPillOutcome(null);
|
|
13663
|
+
}
|
|
13664
|
+
/** Records the measurement's verdict, and drops the pill when it is null. */
|
|
13665
|
+
setPillOutcome(direction) {
|
|
13666
|
+
if (direction === null) {
|
|
13667
|
+
this.pillPhase = null;
|
|
13668
|
+
this.pillDirection = null;
|
|
13669
|
+
this.pillOutcome = "suppressed";
|
|
13670
|
+
this.requestUpdate();
|
|
13671
|
+
return;
|
|
13672
|
+
}
|
|
13673
|
+
this.pillDirection = direction;
|
|
13674
|
+
this.pillOutcome = "shown";
|
|
13675
|
+
this.requestUpdate();
|
|
13676
|
+
}
|
|
13677
|
+
/** Runs the pill's three phases in series once the beat has finished. */
|
|
13678
|
+
openPill() {
|
|
13679
|
+
this.resolvePillDirection();
|
|
13680
|
+
if (this.pillPhase === null) {
|
|
13681
|
+
this.endGesture();
|
|
13682
|
+
return;
|
|
13683
|
+
}
|
|
13684
|
+
this.advancePill("opening", ERROR_GESTURE_MS.open, () => {
|
|
13685
|
+
this.advancePill("holding", ERROR_GESTURE_MS.hold, () => {
|
|
13686
|
+
this.advancePill("closing", ERROR_GESTURE_MS.close, () => {
|
|
13687
|
+
this.endGesture();
|
|
13688
|
+
});
|
|
13689
|
+
});
|
|
13690
|
+
});
|
|
13691
|
+
}
|
|
13692
|
+
advancePill(phase, duration, next) {
|
|
13693
|
+
this.cancelPillTimeout();
|
|
13694
|
+
this.pillPhase = phase;
|
|
13695
|
+
this.requestUpdate();
|
|
13696
|
+
if (typeof window === "undefined") return;
|
|
13697
|
+
this.pillTimeoutId = setTimeout(() => {
|
|
13698
|
+
this.pillTimeoutId = null;
|
|
13699
|
+
next();
|
|
13700
|
+
}, duration);
|
|
13701
|
+
}
|
|
13702
|
+
/**
|
|
13703
|
+
* Closes the pill before its hold is out, because the failure it names has
|
|
13704
|
+
* been fixed. A pill that has not opened yet is simply dropped; the beat is
|
|
13705
|
+
* never cut short.
|
|
13706
|
+
*/
|
|
13707
|
+
closePillEarly() {
|
|
13708
|
+
if (this.pillPhase === null) {
|
|
13709
|
+
this.endGesture();
|
|
13710
|
+
return;
|
|
13711
|
+
}
|
|
13712
|
+
if (this.pillPhase === "closing") return;
|
|
13713
|
+
if (this.pillPhase === "closed") {
|
|
13714
|
+
this.pillPhase = null;
|
|
13715
|
+
this.requestUpdate();
|
|
13716
|
+
return;
|
|
13717
|
+
}
|
|
13718
|
+
this.advancePill("closing", ERROR_GESTURE_MS.close, () => {
|
|
13719
|
+
this.endGesture();
|
|
13720
|
+
});
|
|
13721
|
+
}
|
|
13722
|
+
/** Releases the slot and leaves the plain mark with its dot behind. */
|
|
13723
|
+
endGesture() {
|
|
13724
|
+
this.cancelGestureTail();
|
|
13725
|
+
this.requestUpdate();
|
|
13726
|
+
this.flushPendingSignalPulse();
|
|
13727
|
+
}
|
|
13728
|
+
/**
|
|
13729
|
+
* Drops the gesture's tail outright, with no closing animation, for the
|
|
13730
|
+
* cases where the launcher itself has gone: the panel opened over it, or the
|
|
13731
|
+
* element was removed from the page.
|
|
13732
|
+
*/
|
|
13733
|
+
cancelGestureTail() {
|
|
13734
|
+
this.cancelPillTimeout();
|
|
13735
|
+
this.gestureSignal = null;
|
|
13736
|
+
this.pillPhase = null;
|
|
13737
|
+
this.pillDirection = null;
|
|
13738
|
+
}
|
|
13739
|
+
cancelPillTimeout() {
|
|
13740
|
+
if (this.pillTimeoutId !== null) {
|
|
13741
|
+
clearTimeout(this.pillTimeoutId);
|
|
13742
|
+
this.pillTimeoutId = null;
|
|
13743
|
+
}
|
|
13744
|
+
}
|
|
13745
|
+
/**
|
|
13746
|
+
* Whether each error source is currently broken.
|
|
13747
|
+
*
|
|
13748
|
+
* Only two *wiring* conditions qualify. App errors (runs, tools, memory)
|
|
13749
|
+
* are unread events on a different latch — they name themselves on the pill
|
|
13750
|
+
* and clear when their landing view is read. Notably absent from *this*
|
|
13751
|
+
* latch:
|
|
13752
|
+
*
|
|
13753
|
+
* - **A failed agent run.** A run is an event. It arms `run`, not this
|
|
13754
|
+
* state. The resting wiring dot must not stay red for the rest of a debug
|
|
13755
|
+
* hour.
|
|
13756
|
+
* - **The core error channel as a wiring source.** Handshake failure already
|
|
13757
|
+
* sets the connection state. Other codes arm `run` or `tool`.
|
|
13758
|
+
* - **Memory failures before Learning is live.** The memory store is lazy
|
|
13759
|
+
* because creating it opens a realtime connection. Once it exists, a load
|
|
13760
|
+
* failure arms `memory`.
|
|
13761
|
+
* - **Product states.** An unconfigured Intelligence and an unentitled
|
|
13762
|
+
* Memory plan are not defects. The signal fires only where wiring is
|
|
13763
|
+
* present and the call still fails — which for threads is guaranteed by
|
|
13764
|
+
* `_threadsErrorByAgent` only ever being written while the thread
|
|
13765
|
+
* endpoints are available.
|
|
13766
|
+
*
|
|
13767
|
+
* Known limitation: the runtime handshake runs once, on connect. A server
|
|
13768
|
+
* that dies *after* the page loaded leaves the connection state at connected
|
|
13769
|
+
* and raises nothing; the next page load re-runs the handshake and the
|
|
13770
|
+
* signal appears then. The signal reports the wiring state as last
|
|
13771
|
+
* established. Closing that gap means a re-probe in the core, which is a
|
|
13772
|
+
* runtime concern.
|
|
13773
|
+
*/
|
|
13774
|
+
isErrorSourceBroken(source) {
|
|
13775
|
+
if (source === "connection") {
|
|
13776
|
+
const state = this.getCoreStatusSummary().state;
|
|
13777
|
+
if (require_home_briefing.runtimeConnectionNeedsAttention(state)) return true;
|
|
13778
|
+
return this.errorSignalArmed.connection && state === "connecting";
|
|
13779
|
+
}
|
|
13780
|
+
return this._threadsErrorByAgent.size > 0;
|
|
13781
|
+
}
|
|
13782
|
+
/**
|
|
13783
|
+
* Mirrors both error latches onto the live state. Called from `willUpdate`,
|
|
13784
|
+
* because every mutation of the underlying state already requests an update,
|
|
13785
|
+
* so the resting dot follows the state within the same render.
|
|
13786
|
+
*/
|
|
13787
|
+
evaluateErrorSignals() {
|
|
13788
|
+
const wasArmed = this.hasArmedErrorSignal();
|
|
13789
|
+
for (const source of WIRING_ERROR_KEYS) {
|
|
13790
|
+
if (this.isErrorSourceBroken(source)) {
|
|
13791
|
+
if (this.errorSignalArmed[source]) continue;
|
|
13792
|
+
this.errorSignalArmed[source] = true;
|
|
13793
|
+
continue;
|
|
13794
|
+
}
|
|
13795
|
+
if (!this.errorSignalArmed[source]) continue;
|
|
13796
|
+
this.errorSignalArmed[source] = false;
|
|
13797
|
+
this.errorSignalViewedSources.delete(source);
|
|
13798
|
+
this.retireSignal(source);
|
|
13799
|
+
}
|
|
13800
|
+
this.onErrorSignalsChanged(wasArmed);
|
|
13801
|
+
}
|
|
13802
|
+
/**
|
|
13803
|
+
* Applies the rising-edge rule after a latch changed.
|
|
13804
|
+
*
|
|
13805
|
+
* The beat fires on the transition from "no failure" to "at least one
|
|
13806
|
+
* failure", evaluated globally across the sources and never again while
|
|
13807
|
+
* anything is red — one root cause, one nudge.
|
|
13808
|
+
*/
|
|
13809
|
+
onErrorSignalsChanged(wasArmed) {
|
|
13810
|
+
if (!this.hasArmedErrorSignal()) {
|
|
13811
|
+
this.errorBeatSpent = false;
|
|
13812
|
+
this.pillOutcome = null;
|
|
13813
|
+
return;
|
|
13814
|
+
}
|
|
13815
|
+
if (wasArmed || this.errorBeatSpent) return;
|
|
13816
|
+
const active = this.getActiveLauncherSignal();
|
|
13817
|
+
if (active !== null && isErrorSignalKey(active)) this.startSignalPulse(active);
|
|
13818
|
+
}
|
|
13819
|
+
/**
|
|
13820
|
+
* Records `oss.inspector.error_signal_viewed` once per source per outage,
|
|
13821
|
+
* when the dot is actually on screen.
|
|
13822
|
+
*
|
|
13823
|
+
* Unlike the announcement's launcher event this fires immediately rather
|
|
13824
|
+
* than waiting for the runtime handshake to report `telemetryDisabled`.
|
|
13825
|
+
* The held-queue would never drain for the connection source — a connection
|
|
13826
|
+
* failure means the handshake did not complete — so queuing would guarantee
|
|
13827
|
+
* zero data for the case this event exists to measure. `trackOpened` already
|
|
13828
|
+
* sends on the same terms. Both opt-out layers still gate it: the local
|
|
13829
|
+
* opt-out inside `track`, and the runtime's flag once it is known.
|
|
13830
|
+
*/
|
|
13831
|
+
maybeTrackErrorSignalViewed() {
|
|
13832
|
+
if (this.isOpen || typeof document === "undefined" || document.visibilityState !== "visible") return;
|
|
13833
|
+
const active = this.getActiveLauncherSignal();
|
|
13834
|
+
if (active === null || !isErrorSignalKey(active)) return;
|
|
13835
|
+
if (this.errorSignalViewedSources.has(active)) return;
|
|
13836
|
+
if (this.pillOutcome === null && LAUNCHER_SIGNALS[active].pillLabel !== void 0) return;
|
|
13837
|
+
if (this.core?.telemetryDisabled) return;
|
|
13838
|
+
this.errorSignalViewedSources.add(active);
|
|
13839
|
+
require_telemetry.trackErrorSignalViewed({
|
|
13840
|
+
source: active,
|
|
13841
|
+
presentation: this.isReducedMotionPreferred() ? "reduced_motion" : "animated",
|
|
13842
|
+
label: this.pillOutcome ?? "suppressed"
|
|
13843
|
+
});
|
|
11581
13844
|
}
|
|
11582
13845
|
maybeTrackNewsSignalViewed() {
|
|
11583
|
-
if (!this.newsSignalArmed ||
|
|
13846
|
+
if (!this.newsSignalArmed || this.pulsingSignal !== NEWS_SIGNAL_ID || this.isOpen || typeof document === "undefined" || document.visibilityState !== "visible") return;
|
|
11584
13847
|
const id = this.announcementTimestamp;
|
|
11585
13848
|
if (!id || this.viewedNewsSignalIds.has(id)) return;
|
|
11586
13849
|
this.viewedNewsSignalIds.add(id);
|
|
@@ -11767,7 +14030,10 @@ exports.CpkThreadInspector = CpkThreadInspector;
|
|
|
11767
14030
|
exports.THREAD_INSPECTOR_TAG = THREAD_INSPECTOR_TAG;
|
|
11768
14031
|
exports.WEB_INSPECTOR_TAG = WEB_INSPECTOR_TAG;
|
|
11769
14032
|
exports.WebInspectorElement = WebInspectorElement;
|
|
14033
|
+
exports.compileChatSnippet = require_event_snippets.compileChatSnippet;
|
|
14034
|
+
exports.compileFromActivityMessage = require_event_snippets.compileFromActivityMessage;
|
|
11770
14035
|
exports.defineWebInspector = defineWebInspector;
|
|
14036
|
+
exports.upsertEventSnippet = require_event_snippets.upsertEventSnippet;
|
|
11771
14037
|
exports.ɵCpkThreadDetails = ɵCpkThreadDetails;
|
|
11772
14038
|
exports.ɵbuildCapabilityRows = buildCapabilityRows;
|
|
11773
14039
|
exports.ɵmaxRecallScore = maxRecallScore;
|