@copilotkit/web-inspector 1.56.5-canary.1777972218 → 1.57.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -1809,7 +1809,7 @@ ${(0, lit_directives_unsafe_html_js.unsafeHTML)(highlightedJson(event.payload))}
1809
1809
  };
1810
1810
  if (!customElements.get("cpk-thread-list")) customElements.define("cpk-thread-list", CpkThreadList);
1811
1811
  if (!customElements.get("cpk-thread-details")) customElements.define("cpk-thread-details", ɵCpkThreadDetails);
1812
- var WebInspectorElement = class WebInspectorElement extends lit.LitElement {
1812
+ var WebInspectorElement = class extends lit.LitElement {
1813
1813
  constructor(..._args3) {
1814
1814
  super(..._args3);
1815
1815
  this._core = null;
@@ -1821,6 +1821,7 @@ var WebInspectorElement = class WebInspectorElement extends lit.LitElement {
1821
1821
  this.agentSubscriptions = /* @__PURE__ */ new Map();
1822
1822
  this.agentEvents = /* @__PURE__ */ new Map();
1823
1823
  this.agentMessages = /* @__PURE__ */ new Map();
1824
+ this.agentRunThreadId = /* @__PURE__ */ new Map();
1824
1825
  this.liveMessageVersion = /* @__PURE__ */ new Map();
1825
1826
  this.agentStates = /* @__PURE__ */ new Map();
1826
1827
  this.flattenedEvents = [];
@@ -1867,12 +1868,6 @@ var WebInspectorElement = class WebInspectorElement extends lit.LitElement {
1867
1868
  150
1868
1869
  ];
1869
1870
  this._evtColResize = null;
1870
- this._threadsUnlocked = false;
1871
- this._threadsUnlocking = false;
1872
- this._threadsGateError = null;
1873
- this._threadsGateCodeInvalid = false;
1874
- this._threadsGateInvalidTimer = null;
1875
- this._threadsUnlockingTimer = null;
1876
1871
  this.announcementHtml = null;
1877
1872
  this.announcementTimestamp = null;
1878
1873
  this.announcementPreviewText = null;
@@ -2130,6 +2125,31 @@ var WebInspectorElement = class WebInspectorElement extends lit.LitElement {
2130
2125
  this.handleDismissAnnouncement = () => {
2131
2126
  this.markAnnouncementSeen();
2132
2127
  };
2128
+ this.copyResetTimeouts = /* @__PURE__ */ new WeakMap();
2129
+ this.handleAnnouncementContentClick = (event) => {
2130
+ const button = (event.target instanceof HTMLElement ? event.target : null)?.closest(".announcement-code__copy");
2131
+ if (!(button instanceof HTMLButtonElement)) return;
2132
+ event.preventDefault();
2133
+ event.stopPropagation();
2134
+ const encoded = button.getAttribute("data-copy") ?? "";
2135
+ const code = this.decodeBase64(encoded);
2136
+ if (!code) return;
2137
+ const showCopied = () => {
2138
+ const existing = this.copyResetTimeouts.get(button);
2139
+ if (existing !== void 0) window.clearTimeout(existing);
2140
+ button.setAttribute("data-copied", "true");
2141
+ button.setAttribute("aria-label", "Code copied");
2142
+ button.textContent = "Copied";
2143
+ const id = window.setTimeout(() => {
2144
+ button.removeAttribute("data-copied");
2145
+ button.setAttribute("aria-label", "Copy code");
2146
+ button.textContent = "Copy";
2147
+ this.copyResetTimeouts.delete(button);
2148
+ }, 1500);
2149
+ this.copyResetTimeouts.set(button, id);
2150
+ };
2151
+ if (typeof navigator !== "undefined" && navigator.clipboard?.writeText) navigator.clipboard.writeText(code).then(showCopied, () => {});
2152
+ };
2133
2153
  }
2134
2154
  static {
2135
2155
  this.properties = {
@@ -2297,6 +2317,12 @@ var WebInspectorElement = class WebInspectorElement extends lit.LitElement {
2297
2317
  this._threadsErrorByAgent.delete(agentId);
2298
2318
  this._threads = Array.from(this._threadsByAgent.values()).flat();
2299
2319
  this.requestUpdate();
2320
+ },
2321
+ onAgentRunStarted: ({ agent }) => {
2322
+ this.subscribeToAgent(agent);
2323
+ const runThreadId = agent.threadId;
2324
+ if (agent.agentId && runThreadId) this.agentRunThreadId.set(agent.agentId, runThreadId);
2325
+ this.requestUpdate();
2300
2326
  }
2301
2327
  };
2302
2328
  this.coreUnsubscribe = core.subscribe(this.coreSubscriber).unsubscribe;
@@ -2535,7 +2561,7 @@ var WebInspectorElement = class WebInspectorElement extends lit.LitElement {
2535
2561
  const messages = this.normalizeAgentMessages(agent.messages);
2536
2562
  if (messages) this.agentMessages.set(agent.agentId, messages);
2537
2563
  else this.agentMessages.delete(agent.agentId);
2538
- const runThreadId = agent.threadId;
2564
+ const runThreadId = this.agentRunThreadId.get(agent.agentId);
2539
2565
  if (runThreadId) this.liveMessageVersion.set(runThreadId, (this.liveMessageVersion.get(runThreadId) ?? 0) + 1);
2540
2566
  this.requestUpdate();
2541
2567
  } catch (error) {
@@ -3001,43 +3027,61 @@ ${argsString}</pre
3001
3027
  }
3002
3028
 
3003
3029
  .announcement-content {
3004
- color: #010507;
3005
- font-size: 12px;
3030
+ color: #1f2230;
3031
+ font-size: 13px;
3006
3032
  font-family: "Plus Jakarta Sans", system-ui, sans-serif;
3007
- line-height: 1.5;
3033
+ line-height: 1.55;
3008
3034
  }
3009
3035
 
3010
3036
  .announcement-content h1,
3011
3037
  .announcement-content h2,
3012
3038
  .announcement-content h3 {
3039
+ color: #010507;
3013
3040
  font-weight: 700;
3014
- margin: 0.4rem 0 0.2rem;
3041
+ line-height: 1.3;
3042
+ margin: 0.9rem 0 0.4rem;
3043
+ }
3044
+ .announcement-content > h1:first-child,
3045
+ .announcement-content > h2:first-child,
3046
+ .announcement-content > h3:first-child {
3047
+ margin-top: 0;
3015
3048
  }
3016
3049
 
3017
3050
  .announcement-content h1 {
3018
- font-size: 0.75rem;
3051
+ font-size: 1.15rem;
3052
+ letter-spacing: -0.01em;
3019
3053
  }
3020
3054
  .announcement-content h2 {
3021
- font-size: 0.8rem;
3055
+ font-size: 1rem;
3022
3056
  }
3023
3057
  .announcement-content h3 {
3024
- font-size: 0.75rem;
3058
+ font-size: 0.9rem;
3059
+ text-transform: none;
3025
3060
  }
3026
3061
 
3027
3062
  .announcement-content p {
3028
- margin: 0.2rem 0;
3063
+ margin: 0.45rem 0;
3064
+ }
3065
+
3066
+ .announcement-content strong {
3067
+ color: #010507;
3068
+ font-weight: 700;
3029
3069
  }
3030
3070
 
3031
3071
  .announcement-content ul {
3032
3072
  list-style: disc;
3033
3073
  padding-left: 1.25rem;
3034
- margin: 0.2rem 0;
3074
+ margin: 0.45rem 0;
3035
3075
  }
3036
3076
 
3037
3077
  .announcement-content ol {
3038
3078
  list-style: decimal;
3039
3079
  padding-left: 1.25rem;
3040
- margin: 0.2rem 0;
3080
+ margin: 0.45rem 0;
3081
+ }
3082
+
3083
+ .announcement-content li + li {
3084
+ margin-top: 0.15rem;
3041
3085
  }
3042
3086
 
3043
3087
  .announcement-content a {
@@ -3045,6 +3089,96 @@ ${argsString}</pre
3045
3089
  text-decoration: underline;
3046
3090
  }
3047
3091
 
3092
+ .announcement-content :not(pre) > code {
3093
+ background: #f3f3f7;
3094
+ border: 1px solid #e4e4ec;
3095
+ border-radius: 4px;
3096
+ padding: 1px 5px;
3097
+ font-size: 0.85em;
3098
+ color: #4a3a8a;
3099
+ }
3100
+
3101
+ .announcement-code {
3102
+ position: relative;
3103
+ margin: 0.6rem 0;
3104
+ }
3105
+
3106
+ .announcement-code pre {
3107
+ background: #0f1117;
3108
+ color: #e6e8f2;
3109
+ border-radius: 8px;
3110
+ padding: 10px 12px;
3111
+ overflow-x: auto;
3112
+ font-size: 12px;
3113
+ line-height: 1.5;
3114
+ white-space: pre;
3115
+ }
3116
+
3117
+ .announcement-code pre code::after {
3118
+ content: "";
3119
+ display: inline-block;
3120
+ width: 80px;
3121
+ }
3122
+
3123
+ .announcement-code__copy-shield {
3124
+ position: absolute;
3125
+ top: 4px;
3126
+ right: 4px;
3127
+ padding: 4px 4px 4px 24px;
3128
+ border-top-right-radius: 8px;
3129
+ background: linear-gradient(
3130
+ to right,
3131
+ rgba(15, 17, 23, 0) 0%,
3132
+ rgba(15, 17, 23, 0.95) 40%,
3133
+ #0f1117 100%
3134
+ );
3135
+ pointer-events: none;
3136
+ }
3137
+
3138
+ .announcement-code pre code {
3139
+ background: transparent;
3140
+ border: none;
3141
+ padding: 0;
3142
+ color: inherit;
3143
+ font-size: inherit;
3144
+ }
3145
+
3146
+ .announcement-code pre::-webkit-scrollbar {
3147
+ height: 6px;
3148
+ }
3149
+ .announcement-code pre::-webkit-scrollbar-track {
3150
+ background: transparent;
3151
+ }
3152
+ .announcement-code pre::-webkit-scrollbar-thumb {
3153
+ background: rgba(255, 255, 255, 0.2);
3154
+ border-radius: 3px;
3155
+ }
3156
+
3157
+ .announcement-code__copy {
3158
+ position: relative;
3159
+ pointer-events: auto;
3160
+ padding: 3px 8px;
3161
+ font-family: "Plus Jakarta Sans", system-ui, sans-serif;
3162
+ font-size: 11px;
3163
+ font-weight: 600;
3164
+ color: #e6e8f2;
3165
+ background: #1f222d;
3166
+ border: 1px solid rgba(255, 255, 255, 0.15);
3167
+ border-radius: 5px;
3168
+ cursor: pointer;
3169
+ transition:
3170
+ background 0.12s ease,
3171
+ color 0.12s ease;
3172
+ }
3173
+ .announcement-code__copy:hover {
3174
+ background: #2a2e3c;
3175
+ }
3176
+ .announcement-code__copy[data-copied="true"] {
3177
+ background: #eee6fe;
3178
+ color: #6430ab;
3179
+ border-color: transparent;
3180
+ }
3181
+
3048
3182
  .announcement-body {
3049
3183
  position: relative;
3050
3184
  overflow: hidden;
@@ -3524,7 +3658,6 @@ ${argsString}</pre
3524
3658
  </div>
3525
3659
  </div>
3526
3660
  </div>
3527
- ${this.renderAnnouncementBanner()}
3528
3661
  <div
3529
3662
  class="flex flex-wrap items-center gap-2 border-t border-gray-100 px-3 py-2 text-xs"
3530
3663
  >
@@ -3548,6 +3681,7 @@ ${argsString}</pre
3548
3681
  </div>
3549
3682
  <div class="flex flex-1 flex-col overflow-hidden">
3550
3683
  <div id="cpk-main-scroll" class="flex-1 overflow-auto">
3684
+ ${this.renderAnnouncementBanner()}
3551
3685
  ${this.renderCoreWarningBanner()} ${this.renderMainContent()}
3552
3686
  <slot></slot>
3553
3687
  </div>
@@ -3595,7 +3729,6 @@ ${argsString}</pre
3595
3729
  }
3596
3730
  hydrateStateFromStorageEarly() {
3597
3731
  if (typeof document === "undefined" || typeof window === "undefined") return;
3598
- if (document.cookie.includes("cpk_threads_access=1")) this._threadsUnlocked = true;
3599
3732
  const persisted = require_persistence.loadInspectorState(INSPECTOR_STORAGE_KEY);
3600
3733
  if (!persisted) return;
3601
3734
  if (typeof persisted.isOpen === "boolean") this.isOpen = persisted.isOpen;
@@ -4071,364 +4204,7 @@ ${argsString}</pre
4071
4204
  if (this.selectedMenu === "threads") return this.renderThreadsView();
4072
4205
  return lit.nothing;
4073
4206
  }
4074
- renderThreadsGate() {
4075
- return lit.html`
4076
- <div style="
4077
- position:relative;
4078
- display:flex;
4079
- flex-direction:column;
4080
- align-items:center;
4081
- justify-content:center;
4082
- padding:40px 24px;
4083
- min-height:100%;
4084
- text-align:center;
4085
- background:linear-gradient(135deg,#f5f4ff 0%,#ede9fe 100%);
4086
- overflow:hidden;
4087
- ">
4088
- <!-- Blurred ellipses from Figma/storybook -->
4089
- <div style="position:absolute;width:570px;height:570px;border-radius:50%;top:-80px;left:-120px;opacity:0.25;background:#757CF2;filter:blur(120px);pointer-events:none;"></div>
4090
- <div style="position:absolute;width:570px;height:570px;border-radius:50%;bottom:-100px;right:-80px;opacity:0.2;background:#FFAC4D;filter:blur(120px);pointer-events:none;"></div>
4091
- <div style="position:absolute;width:400px;height:400px;border-radius:50%;bottom:20px;left:-60px;opacity:0.15;background:#FFAC4D;filter:blur(100px);pointer-events:none;"></div>
4092
-
4093
- ${this._threadsUnlocking ? this._renderUnlockingCard() : this._renderEarlyAccessCard()}
4094
- </div>
4095
- `;
4096
- }
4097
- static {
4098
- this.THREADS_REQUEST_URL = "https://r3x69.share-na2.hsforms.com/2uiZg8EkiT7a_KykeXV1ajQ";
4099
- }
4100
- _renderEarlyAccessCard() {
4101
- const invalid = this._threadsGateCodeInvalid;
4102
- return lit.html`
4103
- <div
4104
- style="
4105
- position:relative;
4106
- z-index:1;
4107
- background:#ffffff;
4108
- border:1px solid #E5E5EA;
4109
- border-radius:20px;
4110
- box-shadow:0 16px 48px rgba(1,5,7,0.12),0 2px 6px rgba(1,5,7,0.05);
4111
- padding:28px;
4112
- width:400px;
4113
- max-width:100%;
4114
- display:flex;
4115
- flex-direction:column;
4116
- gap:18px;
4117
- text-align:left;
4118
- font-family:'Plus Jakarta Sans', system-ui, sans-serif;
4119
- "
4120
- >
4121
- <!-- Kicker pill -->
4122
- <div>
4123
- <span
4124
- style="
4125
- display:inline-flex;
4126
- align-items:center;
4127
- gap:4px;
4128
- padding:4px 10px;
4129
- border-radius:999px;
4130
- background:#F3F3FC;
4131
- color:#757CF2;
4132
- font-family:'Spline Sans Mono', ui-monospace, monospace;
4133
- font-size:10px;
4134
- font-weight:500;
4135
- letter-spacing:0.08em;
4136
- text-transform:uppercase;
4137
- "
4138
- >Early Access</span
4139
- >
4140
- </div>
4141
-
4142
- <!-- Title + description -->
4143
- <div style="display:flex;flex-direction:column;gap:8px;">
4144
- <h2
4145
- style="
4146
- font-family:'Plus Jakarta Sans', system-ui, sans-serif;
4147
- font-size:24px;
4148
- font-weight:700;
4149
- color:#010507;
4150
- line-height:1.2;
4151
- letter-spacing:-0.015em;
4152
- margin:0;
4153
- "
4154
- >
4155
- <span
4156
- style="
4157
- background:linear-gradient(90deg, #757CF2 0%, #5AE4BB 100%);
4158
- -webkit-background-clip:text;
4159
- background-clip:text;
4160
- color:transparent;
4161
- -webkit-text-fill-color:transparent;
4162
- "
4163
- >Threads</span
4164
- >
4165
- are in private beta
4166
- </h2>
4167
- <p
4168
- style="
4169
- font-size:14px;
4170
- font-weight:500;
4171
- color:#5C5C66;
4172
- line-height:1.55;
4173
- margin:0;
4174
- "
4175
- >
4176
- Spin up separate conversations with your agent, one per task, bug,
4177
- or feature, and jump back into any of them without losing context.
4178
- </p>
4179
- </div>
4180
-
4181
- <!-- Bullets -->
4182
- <div
4183
- style="display:flex;flex-direction:column;gap:8px;padding:4px 0;"
4184
- >
4185
- ${[
4186
- "One agent, many conversations",
4187
- "Persistent history across sessions",
4188
- "Jump between threads in a click"
4189
- ].map((label) => lit.html`
4190
- <div style="display:flex;align-items:center;gap:10px;">
4191
- <svg
4192
- width="14"
4193
- height="14"
4194
- viewBox="0 0 24 24"
4195
- fill="none"
4196
- stroke="#010507"
4197
- stroke-width="2.5"
4198
- stroke-linecap="round"
4199
- stroke-linejoin="round"
4200
- style="flex-shrink:0;"
4201
- >
4202
- <polyline points="20 6 9 17 4 12"></polyline>
4203
- </svg>
4204
- <span style="font-size:13px;font-weight:500;color:#010507;"
4205
- >${label}</span
4206
- >
4207
- </div>
4208
- `)}
4209
- </div>
4210
-
4211
- <!-- Primary CTA: dark MonoPillButton with adjacent arrow circle -->
4212
- <div>
4213
- <a
4214
- href=${WebInspectorElement.THREADS_REQUEST_URL}
4215
- target="_blank"
4216
- rel="noopener noreferrer"
4217
- style="
4218
- display:inline-flex;
4219
- align-items:center;
4220
- gap:8px;
4221
- text-decoration:none;
4222
- cursor:pointer;
4223
- "
4224
- >
4225
- <span
4226
- style="
4227
- display:inline-flex;
4228
- align-items:center;
4229
- justify-content:center;
4230
- background:#010507;
4231
- color:#ffffff;
4232
- font-family:'Spline Sans Mono', ui-monospace, monospace;
4233
- font-size:13px;
4234
- font-weight:500;
4235
- letter-spacing:0.06em;
4236
- text-transform:uppercase;
4237
- padding:14px 22px;
4238
- border-radius:999px;
4239
- box-shadow:0 4px 12px rgba(1,5,7,0.18);
4240
- "
4241
- >Request Early Access</span
4242
- >
4243
- <span
4244
- style="
4245
- display:inline-flex;
4246
- align-items:center;
4247
- justify-content:center;
4248
- width:36px;
4249
- height:36px;
4250
- border-radius:999px;
4251
- background:#010507;
4252
- color:#ffffff;
4253
- box-shadow:0 4px 12px rgba(1,5,7,0.18);
4254
- "
4255
- >
4256
- <svg
4257
- width="14"
4258
- height="14"
4259
- viewBox="0 0 24 24"
4260
- fill="none"
4261
- stroke="currentColor"
4262
- stroke-width="2"
4263
- stroke-linecap="round"
4264
- stroke-linejoin="round"
4265
- >
4266
- <line x1="5" y1="12" x2="19" y2="12"></line>
4267
- <polyline points="12 5 19 12 12 19"></polyline>
4268
- </svg>
4269
- </span>
4270
- </a>
4271
- </div>
4272
-
4273
- <!-- Divider + invite-code section -->
4274
- <div
4275
- style="
4276
- display:flex;
4277
- flex-direction:column;
4278
- gap:8px;
4279
- padding-top:14px;
4280
- border-top:1px dashed #E5E5EA;
4281
- "
4282
- >
4283
- <span style="font-size:12px;font-weight:500;color:#8A8A94;"
4284
- >Have an invite code?</span
4285
- >
4286
- <div style="display:flex;gap:8px;">
4287
- <div
4288
- style="
4289
- flex:1;
4290
- background:#ffffff;
4291
- border:1px solid ${invalid ? "#FA5F67" : "#E5E5EA"};
4292
- border-radius:10px;
4293
- padding:2px 4px 2px 12px;
4294
- transition:border-color 150ms ease;
4295
- "
4296
- >
4297
- <input
4298
- id="cpk-gate-input"
4299
- type="text"
4300
- placeholder="Enter access code"
4301
- style="
4302
- width:100%;
4303
- padding:10px 0;
4304
- font-family:'Plus Jakarta Sans', system-ui, sans-serif;
4305
- font-size:13px;
4306
- font-weight:500;
4307
- color:#010507;
4308
- background:transparent;
4309
- border:none;
4310
- outline:none;
4311
- "
4312
- @keydown=${(e) => {
4313
- if (e.key === "Enter") this._submitThreadsCode(e.currentTarget.value);
4314
- }}
4315
- />
4316
- </div>
4317
- <button
4318
- style="
4319
- background:#010507;
4320
- color:#ffffff;
4321
- border:none;
4322
- border-radius:10px;
4323
- padding:0 16px;
4324
- font-family:'Spline Sans Mono', ui-monospace, monospace;
4325
- font-size:11px;
4326
- font-weight:500;
4327
- letter-spacing:0.06em;
4328
- text-transform:uppercase;
4329
- cursor:pointer;
4330
- white-space:nowrap;
4331
- "
4332
- @click=${() => {
4333
- const input = this.shadowRoot?.getElementById("cpk-gate-input");
4334
- if (input) this._submitThreadsCode(input.value);
4335
- }}
4336
- >
4337
- Unlock
4338
- </button>
4339
- </div>
4340
- ${invalid ? lit.html`
4341
- <div style="font-size: 11px; font-weight: 500; color: #fa5f67">
4342
- That code isn't valid. Double-check your invite email.
4343
- </div>
4344
- ` : lit.nothing}
4345
- </div>
4346
- </div>
4347
- `;
4348
- }
4349
- _renderUnlockingCard() {
4350
- return lit.html`
4351
- <div
4352
- style="
4353
- position: relative;
4354
- z-index: 1;
4355
- background: #ffffff;
4356
- border: 1px solid #e5e5ea;
4357
- border-radius: 20px;
4358
- box-shadow:
4359
- 0 16px 48px rgba(1, 5, 7, 0.12),
4360
- 0 2px 6px rgba(1, 5, 7, 0.05);
4361
- padding: 32px;
4362
- width: 340px;
4363
- max-width: 100%;
4364
- display: flex;
4365
- flex-direction: column;
4366
- align-items: center;
4367
- gap: 16px;
4368
- text-align: center;
4369
- font-family: &quot;Plus Jakarta Sans&quot;, system-ui, sans-serif;
4370
- "
4371
- >
4372
- <div
4373
- style="
4374
- width: 56px;
4375
- height: 56px;
4376
- border-radius: 999px;
4377
- background: linear-gradient(135deg, #bec2ff 0%, #85ecce 100%);
4378
- display: flex;
4379
- align-items: center;
4380
- justify-content: center;
4381
- "
4382
- >
4383
- <svg
4384
- width="24"
4385
- height="24"
4386
- viewBox="0 0 24 24"
4387
- fill="none"
4388
- stroke="#010507"
4389
- stroke-width="2.5"
4390
- stroke-linecap="round"
4391
- stroke-linejoin="round"
4392
- >
4393
- <polyline points="20 6 9 17 4 12"></polyline>
4394
- </svg>
4395
- </div>
4396
- <div style="font-size: 18px; font-weight: 700; color: #010507">
4397
- Welcome to Threads
4398
- </div>
4399
- <div style="font-size: 13px; color: #5c5c66; line-height: 1.5">
4400
- Loading your conversations…
4401
- </div>
4402
- </div>
4403
- `;
4404
- }
4405
- _submitThreadsCode(value) {
4406
- if (value.trim().toLowerCase() === "earlyaccess") {
4407
- document.cookie = "cpk_threads_access=1; path=/; max-age=31536000; SameSite=Lax";
4408
- this._threadsGateError = null;
4409
- this._threadsGateCodeInvalid = false;
4410
- this._threadsUnlocking = true;
4411
- if (this._threadsUnlockingTimer !== null) clearTimeout(this._threadsUnlockingTimer);
4412
- this._threadsUnlockingTimer = setTimeout(() => {
4413
- this._threadsUnlocking = false;
4414
- this._threadsUnlocked = true;
4415
- this._threadsUnlockingTimer = null;
4416
- this.requestUpdate();
4417
- }, 2e3);
4418
- } else {
4419
- this._threadsGateCodeInvalid = true;
4420
- this._threadsGateError = null;
4421
- if (this._threadsGateInvalidTimer !== null) clearTimeout(this._threadsGateInvalidTimer);
4422
- this._threadsGateInvalidTimer = setTimeout(() => {
4423
- this._threadsGateCodeInvalid = false;
4424
- this._threadsGateInvalidTimer = null;
4425
- this.requestUpdate();
4426
- }, 1600);
4427
- }
4428
- this.requestUpdate();
4429
- }
4430
4207
  renderThreadsView() {
4431
- if (!this._threadsUnlocked) return this.renderThreadsGate();
4432
4208
  const displayThreads = this.selectedContext === "all-agents" ? this._threads : this._threadsByAgent.get(this.selectedContext) ?? [];
4433
4209
  let threadsErrorMessage = null;
4434
4210
  if (this.selectedContext === "all-agents") threadsErrorMessage = this._threadsErrorByAgent.values().next().value?.message ?? null;
@@ -5515,7 +5291,7 @@ ${prettyEvent}</pre
5515
5291
  <span>Loading latest announcement…</span>
5516
5292
  </div>`;
5517
5293
  if (!this.announcementHtml) return lit.nothing;
5518
- return lit.html`<div class="mx-4 mb-3 rounded-xl border border-slate-200 bg-white px-4 py-3">
5294
+ return lit.html`<div class="mx-4 mt-3 mb-3 rounded-xl border border-slate-200 bg-white px-4 py-3">
5519
5295
  <div
5520
5296
  class="mb-2 flex items-center gap-2 text-xs font-semibold text-slate-900"
5521
5297
  >
@@ -5535,7 +5311,10 @@ ${prettyEvent}</pre
5535
5311
  </button>
5536
5312
  </div>
5537
5313
  <div class="announcement-body ${this.announcementExpanded ? "announcement-body--expanded" : "announcement-body--collapsed"}">
5538
- <div class="announcement-content">
5314
+ <div
5315
+ class="announcement-content"
5316
+ @click=${this.handleAnnouncementContentClick}
5317
+ >
5539
5318
  ${(0, lit_directives_unsafe_html_js.unsafeHTML)(this.announcementHtml)}
5540
5319
  </div>
5541
5320
  ${!this.announcementExpanded ? lit.html`
@@ -5602,7 +5381,28 @@ ${prettyEvent}</pre
5602
5381
  renderer.link = (href, title, text) => {
5603
5382
  return `<a href="${this.escapeHtmlAttr(this.appendRefParam(href ?? ""))}" target="_blank" rel="noopener"${title ? ` title="${this.escapeHtmlAttr(title)}"` : ""}>${text}</a>`;
5604
5383
  };
5605
- return marked.marked.parse(markdown, { renderer });
5384
+ renderer.code = (code, lang) => {
5385
+ const safeLang = (lang ?? "").replace(/[^a-z0-9-]/gi, "");
5386
+ return `<div class="announcement-code"><pre><code${safeLang ? ` class="language-${safeLang}"` : ""}>${escapeHtml(code)}</code></pre><div class="announcement-code__copy-shield"><button type="button" class="announcement-code__copy" data-copy="${this.encodeBase64(code)}" aria-label="Copy code">Copy</button></div></div>`;
5387
+ };
5388
+ return marked.marked.parse(markdown, {
5389
+ renderer,
5390
+ async: false
5391
+ });
5392
+ }
5393
+ encodeBase64(value) {
5394
+ if (typeof window === "undefined" || typeof window.btoa !== "function") return "";
5395
+ const bytes = new TextEncoder().encode(value);
5396
+ let binary = "";
5397
+ for (const b of bytes) binary += String.fromCharCode(b);
5398
+ return window.btoa(binary);
5399
+ }
5400
+ decodeBase64(value) {
5401
+ if (typeof window === "undefined" || typeof window.atob !== "function") return "";
5402
+ const decoded = window.atob(value);
5403
+ const bytes = new Uint8Array(decoded.length);
5404
+ for (let i = 0; i < decoded.length; i++) bytes[i] = decoded.charCodeAt(i);
5405
+ return new TextDecoder().decode(bytes);
5606
5406
  }
5607
5407
  appendRefParam(href) {
5608
5408
  try {
@@ -5614,7 +5414,7 @@ ${prettyEvent}</pre
5614
5414
  }
5615
5415
  }
5616
5416
  escapeHtmlAttr(value) {
5617
- return value.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;").replace(/'/g, "&#39;");
5417
+ return escapeHtml(value).replace(/"/g, "&quot;").replace(/'/g, "&#39;");
5618
5418
  }
5619
5419
  loadStoredAnnouncementTimestamp() {
5620
5420
  if (typeof window === "undefined" || !window.localStorage) return null;