@ibealec/create-zed-bridge 1.0.0 → 1.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,2572 @@
1
+ "use strict";
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __export = (target, all) => {
9
+ for (var name in all)
10
+ __defProp(target, name, { get: all[name], enumerable: true });
11
+ };
12
+ var __copyProps = (to, from, except, desc) => {
13
+ if (from && typeof from === "object" || typeof from === "function") {
14
+ for (let key of __getOwnPropNames(from))
15
+ if (!__hasOwnProp.call(to, key) && key !== except)
16
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
+ }
18
+ return to;
19
+ };
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
+ // If the importer is in node compatibility mode or this is not an ESM
22
+ // file that has been converted to a CommonJS file using a Babel-
23
+ // compatible transform (i.e. "__esModule" has not been set), then set
24
+ // "default" to the CommonJS "module.exports" for node compatibility.
25
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
+ mod
27
+ ));
28
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
+
30
+ // src/index.ts
31
+ var index_exports = {};
32
+ __export(index_exports, {
33
+ ClaudeBridgeProvider: () => ClaudeBridgeProvider,
34
+ ClaudeTerminal: () => ClaudeTerminal,
35
+ TaskStatusToast: () => TaskStatusToast,
36
+ captureContext: () => captureContext,
37
+ captureElementScreenshot: () => captureElementScreenshot,
38
+ capturePageContext: () => capturePageContext,
39
+ useClaudeBridge: () => useClaudeBridge
40
+ });
41
+ module.exports = __toCommonJS(index_exports);
42
+
43
+ // src/ClaudeBridgeProvider.tsx
44
+ var import_react6 = require("react");
45
+
46
+ // src/websocket-client.ts
47
+ var BridgeWebSocketClient = class {
48
+ constructor(config) {
49
+ this.ws = null;
50
+ this.messageHandlers = /* @__PURE__ */ new Set();
51
+ this.connectionHandlers = /* @__PURE__ */ new Set();
52
+ this.reconnectAttempts = 0;
53
+ this.maxReconnectAttempts = 5;
54
+ this.reconnectDelay = 1e3;
55
+ this.reconnectTimeout = null;
56
+ this.pingInterval = null;
57
+ this.config = config;
58
+ }
59
+ connect() {
60
+ if (this.ws?.readyState === WebSocket.OPEN) {
61
+ return;
62
+ }
63
+ try {
64
+ const wsUrl = this.config.serverUrl.replace(/^http/, "ws").replace(/\/$/, "");
65
+ this.ws = new WebSocket(`${wsUrl}/ws/bridge?token=${encodeURIComponent(this.config.token)}`);
66
+ this.ws.onopen = () => {
67
+ console.log("[ClaudeBridge] WebSocket connected");
68
+ this.reconnectAttempts = 0;
69
+ this.notifyConnectionHandlers(true);
70
+ this.startPingInterval();
71
+ };
72
+ this.ws.onmessage = (event) => {
73
+ try {
74
+ const message = JSON.parse(event.data);
75
+ this.notifyMessageHandlers(message);
76
+ } catch (error) {
77
+ console.error("[ClaudeBridge] Failed to parse message:", error);
78
+ }
79
+ };
80
+ this.ws.onclose = () => {
81
+ console.log("[ClaudeBridge] WebSocket disconnected");
82
+ this.notifyConnectionHandlers(false);
83
+ this.stopPingInterval();
84
+ this.scheduleReconnect();
85
+ };
86
+ this.ws.onerror = (error) => {
87
+ console.error("[ClaudeBridge] WebSocket error:", error);
88
+ this.config.onError?.(new Error("WebSocket connection error"));
89
+ };
90
+ } catch (error) {
91
+ console.error("[ClaudeBridge] Failed to connect:", error);
92
+ this.scheduleReconnect();
93
+ }
94
+ }
95
+ disconnect() {
96
+ this.stopPingInterval();
97
+ if (this.reconnectTimeout) {
98
+ clearTimeout(this.reconnectTimeout);
99
+ this.reconnectTimeout = null;
100
+ }
101
+ if (this.ws) {
102
+ this.ws.close();
103
+ this.ws = null;
104
+ }
105
+ }
106
+ scheduleReconnect() {
107
+ if (this.reconnectAttempts >= this.maxReconnectAttempts) {
108
+ console.log("[ClaudeBridge] Max reconnect attempts reached");
109
+ return;
110
+ }
111
+ const delay = this.reconnectDelay * Math.pow(2, this.reconnectAttempts);
112
+ this.reconnectAttempts++;
113
+ console.log(`[ClaudeBridge] Reconnecting in ${delay}ms (attempt ${this.reconnectAttempts})`);
114
+ this.reconnectTimeout = setTimeout(() => this.connect(), delay);
115
+ }
116
+ startPingInterval() {
117
+ this.pingInterval = setInterval(() => {
118
+ if (this.ws?.readyState === WebSocket.OPEN) {
119
+ this.send({ type: "ping" });
120
+ }
121
+ }, 3e4);
122
+ }
123
+ stopPingInterval() {
124
+ if (this.pingInterval) {
125
+ clearInterval(this.pingInterval);
126
+ this.pingInterval = null;
127
+ }
128
+ }
129
+ send(message) {
130
+ if (this.ws?.readyState !== WebSocket.OPEN) {
131
+ console.warn("[ClaudeBridge] Cannot send message: not connected");
132
+ return false;
133
+ }
134
+ try {
135
+ this.ws.send(JSON.stringify(message));
136
+ return true;
137
+ } catch (error) {
138
+ console.error("[ClaudeBridge] Failed to send message:", error);
139
+ return false;
140
+ }
141
+ }
142
+ createTask(prompt, context) {
143
+ console.log("[ClaudeBridge] createTask context:", {
144
+ sourceFile: context.sourceFile,
145
+ sourceLine: context.sourceLine,
146
+ componentName: context.componentName
147
+ });
148
+ const request = {
149
+ prompt,
150
+ context,
151
+ projectPath: this.config.projectRoot
152
+ };
153
+ return this.send({
154
+ type: "create_task",
155
+ ...request
156
+ });
157
+ }
158
+ continueTask(taskId, prompt, context) {
159
+ return this.send({
160
+ type: "continue_task",
161
+ taskId,
162
+ prompt,
163
+ context
164
+ });
165
+ }
166
+ onMessage(handler) {
167
+ this.messageHandlers.add(handler);
168
+ return () => this.messageHandlers.delete(handler);
169
+ }
170
+ onConnection(handler) {
171
+ this.connectionHandlers.add(handler);
172
+ return () => this.connectionHandlers.delete(handler);
173
+ }
174
+ notifyMessageHandlers(message) {
175
+ for (const handler of this.messageHandlers) {
176
+ try {
177
+ handler(message);
178
+ } catch (error) {
179
+ console.error("[ClaudeBridge] Message handler error:", error);
180
+ }
181
+ }
182
+ }
183
+ notifyConnectionHandlers(connected) {
184
+ for (const handler of this.connectionHandlers) {
185
+ try {
186
+ handler(connected);
187
+ } catch (error) {
188
+ console.error("[ClaudeBridge] Connection handler error:", error);
189
+ }
190
+ }
191
+ }
192
+ get isConnected() {
193
+ return this.ws?.readyState === WebSocket.OPEN;
194
+ }
195
+ };
196
+
197
+ // src/context-capture.ts
198
+ function captureContext(element) {
199
+ return {
200
+ selectedText: getSelectedText(),
201
+ selectedElement: {
202
+ tagName: element.tagName.toLowerCase(),
203
+ className: element.className,
204
+ id: element.id || void 0,
205
+ innerText: truncateText(element.innerText, 200)
206
+ },
207
+ sourceFile: getSourceFile(element),
208
+ sourceLine: getSourceLine(element),
209
+ sourceColumn: getSourceColumn(element),
210
+ componentName: getComponentName(element),
211
+ domPath: getDomPath(element),
212
+ parentComponents: getParentComponents(element),
213
+ currentUrl: window.location.href,
214
+ pageTitle: document.title
215
+ };
216
+ }
217
+ function getSelectedText() {
218
+ const selection = window.getSelection();
219
+ if (selection && selection.toString().trim()) {
220
+ return selection.toString().trim();
221
+ }
222
+ return void 0;
223
+ }
224
+ function truncateText(text, maxLength) {
225
+ const cleaned = text.replace(/\s+/g, " ").trim();
226
+ if (cleaned.length <= maxLength) {
227
+ return cleaned;
228
+ }
229
+ return cleaned.slice(0, maxLength) + "...";
230
+ }
231
+ function getSourceFile(element) {
232
+ let current = element;
233
+ while (current) {
234
+ const locatorId = current.getAttribute("data-locatorjs-id");
235
+ if (locatorId) {
236
+ const [filePath] = locatorId.split(":");
237
+ return filePath;
238
+ }
239
+ const sourceFile = current.getAttribute("data-source-file");
240
+ if (sourceFile) {
241
+ return sourceFile;
242
+ }
243
+ current = current.parentElement;
244
+ }
245
+ return void 0;
246
+ }
247
+ function getSourceLine(element) {
248
+ let current = element;
249
+ while (current) {
250
+ const locatorId = current.getAttribute("data-locatorjs-id");
251
+ if (locatorId) {
252
+ const parts = locatorId.split(":");
253
+ if (parts.length >= 2) {
254
+ const line = parseInt(parts[1], 10);
255
+ if (!isNaN(line)) return line;
256
+ }
257
+ }
258
+ const sourceLine = current.getAttribute("data-source-line");
259
+ if (sourceLine) {
260
+ const line = parseInt(sourceLine, 10);
261
+ if (!isNaN(line)) return line;
262
+ }
263
+ current = current.parentElement;
264
+ }
265
+ return void 0;
266
+ }
267
+ function getSourceColumn(element) {
268
+ let current = element;
269
+ while (current) {
270
+ const locatorId = current.getAttribute("data-locatorjs-id");
271
+ if (locatorId) {
272
+ const parts = locatorId.split(":");
273
+ if (parts.length >= 3) {
274
+ const col = parseInt(parts[2], 10);
275
+ if (!isNaN(col)) return col;
276
+ }
277
+ }
278
+ current = current.parentElement;
279
+ }
280
+ return void 0;
281
+ }
282
+ function getComponentName(element) {
283
+ const fiber = getReactFiber(element);
284
+ if (fiber) {
285
+ const name = getFiberComponentName(fiber);
286
+ if (name) return name;
287
+ }
288
+ let current = element;
289
+ while (current) {
290
+ const componentName = current.getAttribute("data-component");
291
+ if (componentName) return componentName;
292
+ current = current.parentElement;
293
+ }
294
+ return void 0;
295
+ }
296
+ function getReactFiber(element) {
297
+ const keys = Object.keys(element);
298
+ for (const key of keys) {
299
+ if (key.startsWith("__reactFiber$") || key.startsWith("__reactInternalInstance$")) {
300
+ return element[key];
301
+ }
302
+ }
303
+ return null;
304
+ }
305
+ function getFiberComponentName(fiber) {
306
+ if (!fiber) return void 0;
307
+ if (fiber.type) {
308
+ if (typeof fiber.type === "function") {
309
+ return fiber.type.displayName || fiber.type.name || void 0;
310
+ }
311
+ if (typeof fiber.type === "string") {
312
+ return void 0;
313
+ }
314
+ if (fiber.type.displayName) {
315
+ return fiber.type.displayName;
316
+ }
317
+ if (fiber.type.render?.displayName || fiber.type.render?.name) {
318
+ return fiber.type.render.displayName || fiber.type.render.name;
319
+ }
320
+ }
321
+ if (fiber.return) {
322
+ return getFiberComponentName(fiber.return);
323
+ }
324
+ return void 0;
325
+ }
326
+ function getDomPath(element) {
327
+ const path = [];
328
+ let current = element;
329
+ while (current && current !== document.body) {
330
+ let selector = current.tagName.toLowerCase();
331
+ if (current.id) {
332
+ selector += `#${current.id}`;
333
+ } else if (current.className) {
334
+ const classes = current.className.split(/\s+/).filter((c) => c && !c.startsWith("__")).slice(0, 2).join(".");
335
+ if (classes) {
336
+ selector += `.${classes}`;
337
+ }
338
+ }
339
+ path.unshift(selector);
340
+ current = current.parentElement;
341
+ }
342
+ path.unshift("body");
343
+ return path.join(" > ");
344
+ }
345
+ function getParentComponents(element) {
346
+ const components = [];
347
+ const seen = /* @__PURE__ */ new Set();
348
+ let fiber = getReactFiber(element);
349
+ while (fiber) {
350
+ const name = getFiberComponentName(fiber);
351
+ if (name && !seen.has(name) && !isBuiltInComponent(name)) {
352
+ seen.add(name);
353
+ components.push(name);
354
+ }
355
+ fiber = fiber.return;
356
+ }
357
+ return components.reverse().slice(0, 10);
358
+ }
359
+ function isBuiltInComponent(name) {
360
+ const builtIns = [
361
+ "Fragment",
362
+ "Suspense",
363
+ "StrictMode",
364
+ "Profiler",
365
+ "Provider",
366
+ "Consumer",
367
+ "Context"
368
+ ];
369
+ return builtIns.some((b) => name.includes(b));
370
+ }
371
+ function capturePageContext() {
372
+ const mainContent = document.querySelector("main") || document.querySelector('[role="main"]');
373
+ const pageStructure = getPageStructure();
374
+ return {
375
+ selectedText: getSelectedText(),
376
+ selectedElement: {
377
+ tagName: "body",
378
+ className: document.body.className || "",
379
+ id: document.body.id || void 0,
380
+ innerText: truncateText(getVisibleTextContent(), 500)
381
+ },
382
+ componentName: mainContent ? getComponentName(mainContent) : void 0,
383
+ domPath: "body",
384
+ parentComponents: getRootComponents(),
385
+ currentUrl: window.location.href,
386
+ pageTitle: document.title
387
+ // Include page structure info in the innerText
388
+ };
389
+ }
390
+ function getPageStructure() {
391
+ const parts = [];
392
+ const landmarks = [
393
+ { selector: 'header, [role="banner"]', name: "header" },
394
+ { selector: 'nav, [role="navigation"]', name: "navigation" },
395
+ { selector: 'main, [role="main"]', name: "main content" },
396
+ { selector: 'aside, [role="complementary"]', name: "sidebar" },
397
+ { selector: 'footer, [role="contentinfo"]', name: "footer" }
398
+ ];
399
+ for (const { selector, name } of landmarks) {
400
+ if (document.querySelector(selector)) {
401
+ parts.push(name);
402
+ }
403
+ }
404
+ const buttons = document.querySelectorAll('button, [role="button"]').length;
405
+ const links = document.querySelectorAll("a[href]").length;
406
+ const forms = document.querySelectorAll("form").length;
407
+ const inputs = document.querySelectorAll("input, textarea, select").length;
408
+ if (buttons > 0) parts.push(`${buttons} buttons`);
409
+ if (links > 0) parts.push(`${links} links`);
410
+ if (forms > 0) parts.push(`${forms} forms`);
411
+ if (inputs > 0) parts.push(`${inputs} inputs`);
412
+ return parts.join(", ");
413
+ }
414
+ function getVisibleTextContent() {
415
+ const clone = document.body.cloneNode(true);
416
+ const toRemove = clone.querySelectorAll('script, style, noscript, [hidden], [aria-hidden="true"]');
417
+ toRemove.forEach((el) => el.remove());
418
+ const text = clone.innerText || clone.textContent || "";
419
+ return text.replace(/\s+/g, " ").trim();
420
+ }
421
+ function getRootComponents() {
422
+ const components = [];
423
+ const seen = /* @__PURE__ */ new Set();
424
+ const root = document.getElementById("root") || document.getElementById("app") || document.querySelector("[data-reactroot]");
425
+ if (root) {
426
+ const fiber = getReactFiber(root);
427
+ if (fiber) {
428
+ let current = fiber;
429
+ let depth = 0;
430
+ while (current && depth < 5) {
431
+ const name = getFiberComponentName(current);
432
+ if (name && !seen.has(name) && !isBuiltInComponent(name)) {
433
+ seen.add(name);
434
+ components.push(name);
435
+ }
436
+ current = current.child;
437
+ depth++;
438
+ }
439
+ }
440
+ }
441
+ return components;
442
+ }
443
+
444
+ // src/screenshot-capture.ts
445
+ var import_html2canvas = __toESM(require("html2canvas"), 1);
446
+ async function captureElementScreenshot(element, options = {}) {
447
+ const { padding = 20, maxWidth = 800, maxHeight = 600 } = options;
448
+ try {
449
+ const rect = element.getBoundingClientRect();
450
+ const x = Math.max(0, rect.left - padding + window.scrollX);
451
+ const y = Math.max(0, rect.top - padding + window.scrollY);
452
+ const width = Math.min(rect.width + padding * 2, maxWidth);
453
+ const height = Math.min(rect.height + padding * 2, maxHeight);
454
+ const canvas = await (0, import_html2canvas.default)(document.body, {
455
+ x,
456
+ y,
457
+ width,
458
+ height,
459
+ scrollX: -window.scrollX,
460
+ scrollY: -window.scrollY,
461
+ windowWidth: document.documentElement.scrollWidth,
462
+ windowHeight: document.documentElement.scrollHeight,
463
+ useCORS: true,
464
+ allowTaint: true,
465
+ backgroundColor: null,
466
+ logging: false
467
+ });
468
+ return canvas.toDataURL("image/png");
469
+ } catch (error) {
470
+ console.error("[ClaudeBridge] Screenshot capture failed:", error);
471
+ return void 0;
472
+ }
473
+ }
474
+ function createHighlightOverlay() {
475
+ const overlay = document.createElement("div");
476
+ overlay.id = "claude-bridge-highlight";
477
+ overlay.style.cssText = `
478
+ position: fixed;
479
+ pointer-events: none;
480
+ border: 2px solid #6366f1;
481
+ background: rgba(99, 102, 241, 0.1);
482
+ border-radius: 4px;
483
+ z-index: 999998;
484
+ transition: all 0.1s ease-out;
485
+ display: none;
486
+ `;
487
+ document.body.appendChild(overlay);
488
+ const label = document.createElement("div");
489
+ label.style.cssText = `
490
+ position: absolute;
491
+ top: -24px;
492
+ left: 0;
493
+ background: #6366f1;
494
+ color: white;
495
+ font-size: 11px;
496
+ font-family: ui-monospace, monospace;
497
+ padding: 2px 6px;
498
+ border-radius: 3px;
499
+ white-space: nowrap;
500
+ `;
501
+ overlay.appendChild(label);
502
+ return {
503
+ show: (element) => {
504
+ const rect = element.getBoundingClientRect();
505
+ overlay.style.display = "block";
506
+ overlay.style.top = `${rect.top}px`;
507
+ overlay.style.left = `${rect.left}px`;
508
+ overlay.style.width = `${rect.width}px`;
509
+ overlay.style.height = `${rect.height}px`;
510
+ let labelText = element.tagName.toLowerCase();
511
+ if (element.id) {
512
+ labelText += `#${element.id}`;
513
+ } else if (element.className) {
514
+ const firstClass = element.className.split(/\s+/)[0];
515
+ if (firstClass && !firstClass.startsWith("__")) {
516
+ labelText += `.${firstClass}`;
517
+ }
518
+ }
519
+ label.textContent = labelText;
520
+ },
521
+ hide: () => {
522
+ overlay.style.display = "none";
523
+ },
524
+ destroy: () => {
525
+ overlay.remove();
526
+ }
527
+ };
528
+ }
529
+
530
+ // src/SelectionOverlay.tsx
531
+ var import_react = require("react");
532
+ var import_jsx_runtime = require("react/jsx-runtime");
533
+ function SelectionOverlay({
534
+ active,
535
+ onElementSelect,
536
+ selectedElement
537
+ }) {
538
+ const highlightRef = (0, import_react.useRef)(null);
539
+ const hoveredElementRef = (0, import_react.useRef)(null);
540
+ (0, import_react.useEffect)(() => {
541
+ highlightRef.current = createHighlightOverlay();
542
+ return () => {
543
+ highlightRef.current?.destroy();
544
+ highlightRef.current = null;
545
+ };
546
+ }, []);
547
+ (0, import_react.useEffect)(() => {
548
+ if (selectedElement) {
549
+ highlightRef.current?.show(selectedElement);
550
+ } else if (!active) {
551
+ highlightRef.current?.hide();
552
+ }
553
+ }, [selectedElement, active]);
554
+ const handleMouseMove = (0, import_react.useCallback)(
555
+ (e) => {
556
+ if (!active || selectedElement) return;
557
+ const target = e.target;
558
+ if (target.id === "claude-bridge-highlight" || target.id === "claude-bridge-overlay" || target.closest("#claude-bridge-prompt-dialog")) {
559
+ return;
560
+ }
561
+ if (target === hoveredElementRef.current) return;
562
+ hoveredElementRef.current = target;
563
+ highlightRef.current?.show(target);
564
+ },
565
+ [active, selectedElement]
566
+ );
567
+ const handleClick = (0, import_react.useCallback)(
568
+ (e) => {
569
+ if (!active) return;
570
+ const target = e.target;
571
+ if (target.id === "claude-bridge-highlight" || target.id === "claude-bridge-overlay" || target.closest("#claude-bridge-prompt-dialog")) {
572
+ return;
573
+ }
574
+ e.preventDefault();
575
+ e.stopPropagation();
576
+ onElementSelect(target);
577
+ },
578
+ [active, onElementSelect]
579
+ );
580
+ (0, import_react.useEffect)(() => {
581
+ if (!active) {
582
+ highlightRef.current?.hide();
583
+ return;
584
+ }
585
+ document.addEventListener("mousemove", handleMouseMove, true);
586
+ document.addEventListener("click", handleClick, true);
587
+ return () => {
588
+ document.removeEventListener("mousemove", handleMouseMove, true);
589
+ document.removeEventListener("click", handleClick, true);
590
+ };
591
+ }, [active, handleMouseMove, handleClick]);
592
+ if (!active) return null;
593
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
594
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
595
+ "div",
596
+ {
597
+ id: "claude-bridge-overlay",
598
+ style: {
599
+ position: "fixed",
600
+ top: 0,
601
+ left: 0,
602
+ right: 0,
603
+ bottom: 0,
604
+ zIndex: 999997,
605
+ pointerEvents: "none",
606
+ background: "rgba(0, 0, 0, 0.02)"
607
+ }
608
+ }
609
+ ),
610
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
611
+ "div",
612
+ {
613
+ style: {
614
+ position: "fixed",
615
+ top: 16,
616
+ left: "50%",
617
+ transform: "translateX(-50%)",
618
+ zIndex: 999999,
619
+ background: "#6366f1",
620
+ color: "white",
621
+ padding: "8px 16px",
622
+ borderRadius: 8,
623
+ fontSize: 14,
624
+ fontFamily: "system-ui, -apple-system, sans-serif",
625
+ boxShadow: "0 4px 12px rgba(0, 0, 0, 0.15)",
626
+ display: "flex",
627
+ alignItems: "center",
628
+ gap: 8
629
+ },
630
+ children: [
631
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
632
+ "span",
633
+ {
634
+ style: {
635
+ width: 8,
636
+ height: 8,
637
+ borderRadius: "50%",
638
+ background: "#22c55e",
639
+ animation: "claude-bridge-pulse 1.5s infinite"
640
+ }
641
+ }
642
+ ),
643
+ "Click an element to select it",
644
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
645
+ "span",
646
+ {
647
+ style: {
648
+ opacity: 0.7,
649
+ fontSize: 12,
650
+ marginLeft: 4
651
+ },
652
+ children: "(ESC to cancel)"
653
+ }
654
+ )
655
+ ]
656
+ }
657
+ ),
658
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("style", { children: `
659
+ @keyframes claude-bridge-pulse {
660
+ 0%, 100% { opacity: 1; }
661
+ 50% { opacity: 0.5; }
662
+ }
663
+ ` })
664
+ ] });
665
+ }
666
+
667
+ // src/PromptDialog.tsx
668
+ var import_react2 = require("react");
669
+ var import_jsx_runtime2 = require("react/jsx-runtime");
670
+ function PromptDialog({
671
+ open,
672
+ element,
673
+ onSubmit,
674
+ onClose,
675
+ onSwitchToQuestionMode,
676
+ isSubmitting = false
677
+ }) {
678
+ const [prompt, setPrompt] = (0, import_react2.useState)("");
679
+ const inputRef = (0, import_react2.useRef)(null);
680
+ (0, import_react2.useEffect)(() => {
681
+ if (open && inputRef.current) {
682
+ inputRef.current.focus();
683
+ }
684
+ }, [open]);
685
+ (0, import_react2.useEffect)(() => {
686
+ if (!open) {
687
+ setPrompt("");
688
+ }
689
+ }, [open]);
690
+ const handleSubmit = () => {
691
+ if (!prompt.trim() || isSubmitting) return;
692
+ onSubmit(prompt.trim());
693
+ };
694
+ const handleKeyDown = (e) => {
695
+ if ((e.metaKey || e.ctrlKey) && e.key === "Enter") {
696
+ e.preventDefault();
697
+ handleSubmit();
698
+ }
699
+ if (e.key === "Escape") {
700
+ e.preventDefault();
701
+ onClose();
702
+ }
703
+ };
704
+ if (!open || !element) return null;
705
+ const context = captureContext(element);
706
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
707
+ "div",
708
+ {
709
+ id: "claude-bridge-prompt-dialog",
710
+ style: {
711
+ position: "fixed",
712
+ bottom: 24,
713
+ left: "50%",
714
+ transform: "translateX(-50%)",
715
+ zIndex: 1e6,
716
+ width: "100%",
717
+ maxWidth: 600,
718
+ background: "#1e1e2e",
719
+ borderRadius: 12,
720
+ boxShadow: "0 8px 32px rgba(0, 0, 0, 0.3)",
721
+ fontFamily: "system-ui, -apple-system, sans-serif",
722
+ overflow: "hidden"
723
+ },
724
+ children: [
725
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
726
+ "div",
727
+ {
728
+ style: {
729
+ padding: "12px 16px",
730
+ borderBottom: "1px solid rgba(255, 255, 255, 0.1)",
731
+ display: "flex",
732
+ alignItems: "center",
733
+ gap: 8
734
+ },
735
+ children: [
736
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
737
+ "div",
738
+ {
739
+ style: {
740
+ width: 8,
741
+ height: 8,
742
+ borderRadius: "50%",
743
+ background: "#6366f1"
744
+ }
745
+ }
746
+ ),
747
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
748
+ "span",
749
+ {
750
+ style: {
751
+ color: "rgba(255, 255, 255, 0.9)",
752
+ fontSize: 13,
753
+ fontWeight: 500
754
+ },
755
+ children: context.componentName || context.selectedElement.tagName
756
+ }
757
+ ),
758
+ context.sourceFile && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
759
+ "span",
760
+ {
761
+ style: {
762
+ color: "rgba(255, 255, 255, 0.5)",
763
+ fontSize: 12,
764
+ fontFamily: "ui-monospace, monospace"
765
+ },
766
+ children: [
767
+ context.sourceFile,
768
+ context.sourceLine ? `:${context.sourceLine}` : ""
769
+ ]
770
+ }
771
+ ),
772
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { style: { flex: 1 } }),
773
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
774
+ "button",
775
+ {
776
+ onClick: onClose,
777
+ style: {
778
+ background: "transparent",
779
+ border: "none",
780
+ color: "rgba(255, 255, 255, 0.5)",
781
+ cursor: "pointer",
782
+ padding: 4,
783
+ borderRadius: 4,
784
+ fontSize: 18,
785
+ lineHeight: 1
786
+ },
787
+ children: "\xD7"
788
+ }
789
+ )
790
+ ]
791
+ }
792
+ ),
793
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: { padding: 16 }, children: [
794
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
795
+ "textarea",
796
+ {
797
+ ref: inputRef,
798
+ value: prompt,
799
+ onChange: (e) => setPrompt(e.target.value),
800
+ onKeyDown: handleKeyDown,
801
+ placeholder: "What would you like Claude to change?",
802
+ disabled: isSubmitting,
803
+ style: {
804
+ width: "100%",
805
+ minHeight: 80,
806
+ maxHeight: 200,
807
+ padding: 12,
808
+ background: "rgba(255, 255, 255, 0.05)",
809
+ border: "1px solid rgba(255, 255, 255, 0.1)",
810
+ borderRadius: 8,
811
+ color: "white",
812
+ fontSize: 14,
813
+ fontFamily: "inherit",
814
+ resize: "vertical",
815
+ outline: "none"
816
+ }
817
+ }
818
+ ),
819
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
820
+ "div",
821
+ {
822
+ style: {
823
+ display: "flex",
824
+ flexWrap: "wrap",
825
+ gap: 8,
826
+ marginTop: 12
827
+ },
828
+ children: ["Make this bigger", "Change the color", "Add padding", "Hide this element"].map(
829
+ (suggestion) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
830
+ "button",
831
+ {
832
+ onClick: () => setPrompt(suggestion),
833
+ disabled: isSubmitting,
834
+ style: {
835
+ background: "rgba(255, 255, 255, 0.05)",
836
+ border: "1px solid rgba(255, 255, 255, 0.1)",
837
+ borderRadius: 4,
838
+ padding: "4px 8px",
839
+ color: "rgba(255, 255, 255, 0.7)",
840
+ fontSize: 12,
841
+ cursor: "pointer"
842
+ },
843
+ children: suggestion
844
+ },
845
+ suggestion
846
+ )
847
+ )
848
+ }
849
+ )
850
+ ] }),
851
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
852
+ "div",
853
+ {
854
+ style: {
855
+ padding: "12px 16px",
856
+ borderTop: "1px solid rgba(255, 255, 255, 0.1)",
857
+ display: "flex",
858
+ justifyContent: "space-between",
859
+ alignItems: "center"
860
+ },
861
+ children: [
862
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: { display: "flex", alignItems: "center", gap: 12 }, children: [
863
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
864
+ "span",
865
+ {
866
+ style: {
867
+ color: "rgba(255, 255, 255, 0.4)",
868
+ fontSize: 12
869
+ },
870
+ children: [
871
+ navigator.platform.includes("Mac") ? "\u2318" : "Ctrl",
872
+ "+Enter to submit"
873
+ ]
874
+ }
875
+ ),
876
+ onSwitchToQuestionMode && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
877
+ "button",
878
+ {
879
+ onClick: onSwitchToQuestionMode,
880
+ disabled: isSubmitting,
881
+ style: {
882
+ background: "transparent",
883
+ border: "none",
884
+ color: "#22c55e",
885
+ fontSize: 12,
886
+ cursor: "pointer",
887
+ padding: 0,
888
+ textDecoration: "underline"
889
+ },
890
+ children: "Just ask a question instead"
891
+ }
892
+ )
893
+ ] }),
894
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
895
+ "button",
896
+ {
897
+ onClick: handleSubmit,
898
+ disabled: !prompt.trim() || isSubmitting,
899
+ style: {
900
+ background: prompt.trim() && !isSubmitting ? "#6366f1" : "rgba(99, 102, 241, 0.3)",
901
+ border: "none",
902
+ borderRadius: 6,
903
+ padding: "8px 16px",
904
+ color: "white",
905
+ fontSize: 14,
906
+ fontWeight: 500,
907
+ cursor: prompt.trim() && !isSubmitting ? "pointer" : "not-allowed",
908
+ display: "flex",
909
+ alignItems: "center",
910
+ gap: 6
911
+ },
912
+ children: isSubmitting ? /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_jsx_runtime2.Fragment, { children: [
913
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
914
+ "span",
915
+ {
916
+ style: {
917
+ width: 14,
918
+ height: 14,
919
+ border: "2px solid rgba(255, 255, 255, 0.3)",
920
+ borderTopColor: "white",
921
+ borderRadius: "50%",
922
+ animation: "claude-bridge-spin 0.8s linear infinite"
923
+ }
924
+ }
925
+ ),
926
+ "Sending..."
927
+ ] }) : "Send to Claude"
928
+ }
929
+ )
930
+ ]
931
+ }
932
+ ),
933
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("style", { children: `
934
+ @keyframes claude-bridge-spin {
935
+ to { transform: rotate(360deg); }
936
+ }
937
+ ` })
938
+ ]
939
+ }
940
+ );
941
+ }
942
+
943
+ // src/QuestionDialog.tsx
944
+ var import_react3 = require("react");
945
+ var import_jsx_runtime3 = require("react/jsx-runtime");
946
+ function QuestionDialog({
947
+ open,
948
+ selectedElement,
949
+ onSubmit,
950
+ onClose,
951
+ onSwitchToTaskMode,
952
+ isSubmitting = false
953
+ }) {
954
+ const [prompt, setPrompt] = (0, import_react3.useState)("");
955
+ const [includeElement, setIncludeElement] = (0, import_react3.useState)(true);
956
+ const inputRef = (0, import_react3.useRef)(null);
957
+ (0, import_react3.useEffect)(() => {
958
+ if (open && inputRef.current) {
959
+ inputRef.current.focus();
960
+ }
961
+ }, [open]);
962
+ (0, import_react3.useEffect)(() => {
963
+ if (!open) {
964
+ setPrompt("");
965
+ }
966
+ }, [open]);
967
+ (0, import_react3.useEffect)(() => {
968
+ setIncludeElement(!!selectedElement);
969
+ }, [selectedElement]);
970
+ const handleSubmit = () => {
971
+ if (!prompt.trim() || isSubmitting) return;
972
+ onSubmit(prompt.trim(), includeElement && !!selectedElement);
973
+ };
974
+ const handleKeyDown = (e) => {
975
+ if ((e.metaKey || e.ctrlKey) && e.key === "Enter") {
976
+ e.preventDefault();
977
+ handleSubmit();
978
+ }
979
+ if (e.key === "Escape") {
980
+ e.preventDefault();
981
+ onClose();
982
+ }
983
+ };
984
+ if (!open) return null;
985
+ const pageContext = capturePageContext();
986
+ const elementContext = selectedElement ? captureContext(selectedElement) : null;
987
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
988
+ "div",
989
+ {
990
+ id: "claude-bridge-question-dialog",
991
+ style: {
992
+ position: "fixed",
993
+ bottom: 24,
994
+ left: "50%",
995
+ transform: "translateX(-50%)",
996
+ zIndex: 1e6,
997
+ width: "100%",
998
+ maxWidth: 600,
999
+ background: "#1e1e2e",
1000
+ borderRadius: 12,
1001
+ boxShadow: "0 8px 32px rgba(0, 0, 0, 0.3)",
1002
+ fontFamily: "system-ui, -apple-system, sans-serif",
1003
+ overflow: "hidden"
1004
+ },
1005
+ children: [
1006
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
1007
+ "div",
1008
+ {
1009
+ style: {
1010
+ padding: "12px 16px",
1011
+ borderBottom: "1px solid rgba(255, 255, 255, 0.1)",
1012
+ display: "flex",
1013
+ alignItems: "center",
1014
+ gap: 8
1015
+ },
1016
+ children: [
1017
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
1018
+ "div",
1019
+ {
1020
+ style: {
1021
+ width: 8,
1022
+ height: 8,
1023
+ borderRadius: "50%",
1024
+ background: "#22c55e"
1025
+ // Green to differentiate from task dialog
1026
+ }
1027
+ }
1028
+ ),
1029
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
1030
+ "span",
1031
+ {
1032
+ style: {
1033
+ color: "rgba(255, 255, 255, 0.9)",
1034
+ fontSize: 13,
1035
+ fontWeight: 500
1036
+ },
1037
+ children: "Ask a Question"
1038
+ }
1039
+ ),
1040
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
1041
+ "span",
1042
+ {
1043
+ style: {
1044
+ color: "rgba(255, 255, 255, 0.5)",
1045
+ fontSize: 12
1046
+ },
1047
+ children: pageContext.pageTitle
1048
+ }
1049
+ ),
1050
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { style: { flex: 1 } }),
1051
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
1052
+ "button",
1053
+ {
1054
+ onClick: onClose,
1055
+ style: {
1056
+ background: "transparent",
1057
+ border: "none",
1058
+ color: "rgba(255, 255, 255, 0.5)",
1059
+ cursor: "pointer",
1060
+ padding: 4,
1061
+ borderRadius: 4,
1062
+ fontSize: 18,
1063
+ lineHeight: 1
1064
+ },
1065
+ children: "\xD7"
1066
+ }
1067
+ )
1068
+ ]
1069
+ }
1070
+ ),
1071
+ selectedElement && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
1072
+ "div",
1073
+ {
1074
+ style: {
1075
+ padding: "8px 16px",
1076
+ background: "rgba(34, 197, 94, 0.1)",
1077
+ borderBottom: "1px solid rgba(255, 255, 255, 0.1)",
1078
+ display: "flex",
1079
+ alignItems: "center",
1080
+ gap: 8
1081
+ },
1082
+ children: /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
1083
+ "label",
1084
+ {
1085
+ style: {
1086
+ display: "flex",
1087
+ alignItems: "center",
1088
+ gap: 8,
1089
+ cursor: "pointer",
1090
+ flex: 1
1091
+ },
1092
+ children: [
1093
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
1094
+ "input",
1095
+ {
1096
+ type: "checkbox",
1097
+ checked: includeElement,
1098
+ onChange: (e) => setIncludeElement(e.target.checked),
1099
+ style: { cursor: "pointer" }
1100
+ }
1101
+ ),
1102
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
1103
+ "span",
1104
+ {
1105
+ style: {
1106
+ color: "rgba(255, 255, 255, 0.7)",
1107
+ fontSize: 12
1108
+ },
1109
+ children: "Include selected element:"
1110
+ }
1111
+ ),
1112
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
1113
+ "span",
1114
+ {
1115
+ style: {
1116
+ color: "rgba(255, 255, 255, 0.9)",
1117
+ fontSize: 12,
1118
+ fontFamily: "ui-monospace, monospace"
1119
+ },
1120
+ children: [
1121
+ elementContext?.componentName || elementContext?.selectedElement.tagName,
1122
+ elementContext?.sourceFile && /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("span", { style: { color: "rgba(255, 255, 255, 0.5)", marginLeft: 4 }, children: [
1123
+ "(",
1124
+ elementContext.sourceFile,
1125
+ elementContext.sourceLine ? `:${elementContext.sourceLine}` : "",
1126
+ ")"
1127
+ ] })
1128
+ ]
1129
+ }
1130
+ )
1131
+ ]
1132
+ }
1133
+ )
1134
+ }
1135
+ ),
1136
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { style: { padding: 16 }, children: [
1137
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
1138
+ "textarea",
1139
+ {
1140
+ ref: inputRef,
1141
+ value: prompt,
1142
+ onChange: (e) => setPrompt(e.target.value),
1143
+ onKeyDown: handleKeyDown,
1144
+ placeholder: "Ask a question about this page or codebase...",
1145
+ disabled: isSubmitting,
1146
+ style: {
1147
+ width: "100%",
1148
+ minHeight: 80,
1149
+ maxHeight: 200,
1150
+ padding: 12,
1151
+ background: "rgba(255, 255, 255, 0.05)",
1152
+ border: "1px solid rgba(255, 255, 255, 0.1)",
1153
+ borderRadius: 8,
1154
+ color: "white",
1155
+ fontSize: 14,
1156
+ fontFamily: "inherit",
1157
+ resize: "vertical",
1158
+ outline: "none"
1159
+ }
1160
+ }
1161
+ ),
1162
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
1163
+ "div",
1164
+ {
1165
+ style: {
1166
+ display: "flex",
1167
+ flexWrap: "wrap",
1168
+ gap: 8,
1169
+ marginTop: 12
1170
+ },
1171
+ children: [
1172
+ "What does this page do?",
1173
+ "Where are the backend routes?",
1174
+ "How does this component work?",
1175
+ "What API calls does this make?"
1176
+ ].map((suggestion) => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
1177
+ "button",
1178
+ {
1179
+ onClick: () => setPrompt(suggestion),
1180
+ disabled: isSubmitting,
1181
+ style: {
1182
+ background: "rgba(255, 255, 255, 0.05)",
1183
+ border: "1px solid rgba(255, 255, 255, 0.1)",
1184
+ borderRadius: 4,
1185
+ padding: "4px 8px",
1186
+ color: "rgba(255, 255, 255, 0.7)",
1187
+ fontSize: 12,
1188
+ cursor: "pointer"
1189
+ },
1190
+ children: suggestion
1191
+ },
1192
+ suggestion
1193
+ ))
1194
+ }
1195
+ )
1196
+ ] }),
1197
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
1198
+ "div",
1199
+ {
1200
+ style: {
1201
+ padding: "12px 16px",
1202
+ borderTop: "1px solid rgba(255, 255, 255, 0.1)",
1203
+ display: "flex",
1204
+ justifyContent: "space-between",
1205
+ alignItems: "center"
1206
+ },
1207
+ children: [
1208
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { style: { display: "flex", alignItems: "center", gap: 12 }, children: [
1209
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
1210
+ "span",
1211
+ {
1212
+ style: {
1213
+ color: "rgba(255, 255, 255, 0.4)",
1214
+ fontSize: 12
1215
+ },
1216
+ children: [
1217
+ navigator.platform.includes("Mac") ? "\u2318" : "Ctrl",
1218
+ "+Enter to submit"
1219
+ ]
1220
+ }
1221
+ ),
1222
+ onSwitchToTaskMode && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
1223
+ "button",
1224
+ {
1225
+ onClick: onSwitchToTaskMode,
1226
+ disabled: isSubmitting,
1227
+ style: {
1228
+ background: "transparent",
1229
+ border: "none",
1230
+ color: "#6366f1",
1231
+ fontSize: 12,
1232
+ cursor: "pointer",
1233
+ padding: 0,
1234
+ textDecoration: "underline"
1235
+ },
1236
+ children: "Make changes instead"
1237
+ }
1238
+ )
1239
+ ] }),
1240
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
1241
+ "button",
1242
+ {
1243
+ onClick: handleSubmit,
1244
+ disabled: !prompt.trim() || isSubmitting,
1245
+ style: {
1246
+ background: prompt.trim() && !isSubmitting ? "#22c55e" : "rgba(34, 197, 94, 0.3)",
1247
+ border: "none",
1248
+ borderRadius: 6,
1249
+ padding: "8px 16px",
1250
+ color: "white",
1251
+ fontSize: 14,
1252
+ fontWeight: 500,
1253
+ cursor: prompt.trim() && !isSubmitting ? "pointer" : "not-allowed",
1254
+ display: "flex",
1255
+ alignItems: "center",
1256
+ gap: 6
1257
+ },
1258
+ children: isSubmitting ? /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_jsx_runtime3.Fragment, { children: [
1259
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
1260
+ "span",
1261
+ {
1262
+ style: {
1263
+ width: 14,
1264
+ height: 14,
1265
+ border: "2px solid rgba(255, 255, 255, 0.3)",
1266
+ borderTopColor: "white",
1267
+ borderRadius: "50%",
1268
+ animation: "claude-bridge-spin 0.8s linear infinite"
1269
+ }
1270
+ }
1271
+ ),
1272
+ "Asking..."
1273
+ ] }) : "Ask Claude"
1274
+ }
1275
+ )
1276
+ ]
1277
+ }
1278
+ ),
1279
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("style", { children: `
1280
+ @keyframes claude-bridge-spin {
1281
+ to { transform: rotate(360deg); }
1282
+ }
1283
+ ` })
1284
+ ]
1285
+ }
1286
+ );
1287
+ }
1288
+
1289
+ // src/TaskStatusToast.tsx
1290
+ var import_react5 = require("react");
1291
+
1292
+ // src/ClaudeTerminal.tsx
1293
+ var import_react4 = require("react");
1294
+ var import_xterm = require("@xterm/xterm");
1295
+ var import_addon_fit = require("@xterm/addon-fit");
1296
+ var import_addon_webgl = require("@xterm/addon-webgl");
1297
+ var import_xterm2 = require("@xterm/xterm/css/xterm.css");
1298
+ var import_jsx_runtime4 = require("react/jsx-runtime");
1299
+ var XTERM_CRITICAL_CSS = `
1300
+ .xterm {
1301
+ cursor: text;
1302
+ position: relative;
1303
+ user-select: none;
1304
+ -ms-user-select: none;
1305
+ -webkit-user-select: none;
1306
+ }
1307
+ .xterm.focus,
1308
+ .xterm:focus {
1309
+ outline: none;
1310
+ }
1311
+ .xterm .xterm-helpers {
1312
+ position: absolute;
1313
+ top: 0;
1314
+ z-index: 5;
1315
+ }
1316
+ .xterm .xterm-helper-textarea {
1317
+ padding: 0;
1318
+ border: 0;
1319
+ margin: 0;
1320
+ position: absolute;
1321
+ opacity: 0;
1322
+ left: -9999em;
1323
+ top: 0;
1324
+ width: 0;
1325
+ height: 0;
1326
+ z-index: -5;
1327
+ white-space: nowrap;
1328
+ overflow: hidden;
1329
+ resize: none;
1330
+ }
1331
+ .xterm .xterm-helper-textarea:focus {
1332
+ outline: none;
1333
+ }
1334
+ .xterm .composition-view {
1335
+ background: #000;
1336
+ color: #FFF;
1337
+ display: none;
1338
+ position: absolute;
1339
+ white-space: nowrap;
1340
+ z-index: 1;
1341
+ }
1342
+ .xterm .composition-view.active {
1343
+ display: block;
1344
+ }
1345
+ .xterm .xterm-viewport {
1346
+ background-color: #000;
1347
+ overflow-y: scroll;
1348
+ cursor: default;
1349
+ position: absolute;
1350
+ right: 0;
1351
+ left: 0;
1352
+ top: 0;
1353
+ bottom: 0;
1354
+ }
1355
+ .xterm .xterm-screen {
1356
+ position: relative;
1357
+ }
1358
+ .xterm .xterm-screen canvas {
1359
+ position: absolute;
1360
+ left: 0;
1361
+ top: 0;
1362
+ }
1363
+ .xterm-char-measure-element {
1364
+ display: inline-block;
1365
+ visibility: hidden;
1366
+ position: absolute;
1367
+ top: 0;
1368
+ left: -9999em;
1369
+ line-height: normal;
1370
+ }
1371
+ .xterm.enable-mouse-events {
1372
+ cursor: default;
1373
+ }
1374
+ .xterm .xterm-cursor-pointer {
1375
+ cursor: pointer;
1376
+ }
1377
+ .xterm.xterm-cursor-style-block .xterm-cursor:not(.xterm-cursor-blink),
1378
+ .xterm.xterm-cursor-style-bar .xterm-cursor:not(.xterm-cursor-blink),
1379
+ .xterm.xterm-cursor-style-underline .xterm-cursor:not(.xterm-cursor-blink) {
1380
+ visibility: visible;
1381
+ }
1382
+ `;
1383
+ function ClaudeTerminal({
1384
+ serverUrl,
1385
+ token,
1386
+ sessionId,
1387
+ onSessionSelect,
1388
+ onConnectionChange,
1389
+ onSessionsUpdate,
1390
+ terminalOptions = {},
1391
+ style,
1392
+ className
1393
+ }) {
1394
+ const containerRef = (0, import_react4.useRef)(null);
1395
+ const terminalRef = (0, import_react4.useRef)(null);
1396
+ const fitAddonRef = (0, import_react4.useRef)(null);
1397
+ const wsRef = (0, import_react4.useRef)(null);
1398
+ const handleMessageRef = (0, import_react4.useRef)(null);
1399
+ const [connected, setConnected] = (0, import_react4.useState)(false);
1400
+ const [sessions, setSessions] = (0, import_react4.useState)([]);
1401
+ const [attachedSessionId, setAttachedSessionId] = (0, import_react4.useState)(null);
1402
+ const [error, setError] = (0, import_react4.useState)(null);
1403
+ (0, import_react4.useEffect)(() => {
1404
+ if (!containerRef.current) return;
1405
+ const terminal = new import_xterm.Terminal({
1406
+ cursorBlink: true,
1407
+ cursorStyle: "block",
1408
+ fontSize: terminalOptions.fontSize ?? 14,
1409
+ fontFamily: terminalOptions.fontFamily ?? 'Menlo, Monaco, "Courier New", monospace',
1410
+ theme: {
1411
+ background: terminalOptions.theme?.background ?? "#1a1a1a",
1412
+ foreground: terminalOptions.theme?.foreground ?? "#f0f0f0",
1413
+ cursor: terminalOptions.theme?.cursor ?? "#f0f0f0",
1414
+ cursorAccent: "#1a1a1a",
1415
+ black: "#1a1a1a",
1416
+ red: "#ff5555",
1417
+ green: "#50fa7b",
1418
+ yellow: "#f1fa8c",
1419
+ blue: "#6272a4",
1420
+ magenta: "#ff79c6",
1421
+ cyan: "#8be9fd",
1422
+ white: "#f8f8f2",
1423
+ brightBlack: "#6272a4",
1424
+ brightRed: "#ff6e6e",
1425
+ brightGreen: "#69ff94",
1426
+ brightYellow: "#ffffa5",
1427
+ brightBlue: "#d6acff",
1428
+ brightMagenta: "#ff92df",
1429
+ brightCyan: "#a4ffff",
1430
+ brightWhite: "#ffffff"
1431
+ },
1432
+ allowProposedApi: true,
1433
+ scrollback: 1e4,
1434
+ disableStdin: false,
1435
+ allowTransparency: true
1436
+ });
1437
+ const fitAddon = new import_addon_fit.FitAddon();
1438
+ terminal.loadAddon(fitAddon);
1439
+ terminal.open(containerRef.current);
1440
+ try {
1441
+ const webglAddon = new import_addon_webgl.WebglAddon();
1442
+ webglAddon.onContextLoss(() => {
1443
+ webglAddon.dispose();
1444
+ });
1445
+ terminal.loadAddon(webglAddon);
1446
+ } catch (e) {
1447
+ console.warn("[ClaudeTerminal] WebGL addon could not be loaded:", e);
1448
+ }
1449
+ terminalRef.current = terminal;
1450
+ fitAddonRef.current = fitAddon;
1451
+ requestAnimationFrame(() => {
1452
+ fitAddon.fit();
1453
+ });
1454
+ const resizeObserver = new ResizeObserver(() => {
1455
+ requestAnimationFrame(() => {
1456
+ fitAddon.fit();
1457
+ if (wsRef.current?.readyState === WebSocket.OPEN && attachedSessionId) {
1458
+ wsRef.current.send(JSON.stringify({
1459
+ type: "terminal_resize",
1460
+ sessionId: attachedSessionId,
1461
+ cols: terminal.cols,
1462
+ rows: terminal.rows
1463
+ }));
1464
+ }
1465
+ });
1466
+ });
1467
+ resizeObserver.observe(containerRef.current);
1468
+ return () => {
1469
+ resizeObserver.disconnect();
1470
+ terminal.dispose();
1471
+ terminalRef.current = null;
1472
+ fitAddonRef.current = null;
1473
+ };
1474
+ }, [terminalOptions.fontSize, terminalOptions.fontFamily, terminalOptions.theme]);
1475
+ (0, import_react4.useEffect)(() => {
1476
+ const terminal = terminalRef.current;
1477
+ if (!terminal) return;
1478
+ const disposable = terminal.onData((data) => {
1479
+ if (wsRef.current?.readyState === WebSocket.OPEN && attachedSessionId) {
1480
+ wsRef.current.send(JSON.stringify({
1481
+ type: "terminal_input",
1482
+ sessionId: attachedSessionId,
1483
+ data
1484
+ }));
1485
+ }
1486
+ });
1487
+ return () => disposable.dispose();
1488
+ }, [attachedSessionId]);
1489
+ const attachedSessionIdRef = (0, import_react4.useRef)(null);
1490
+ attachedSessionIdRef.current = attachedSessionId;
1491
+ (0, import_react4.useEffect)(() => {
1492
+ handleMessageRef.current = (event) => {
1493
+ try {
1494
+ const message = JSON.parse(event.data);
1495
+ switch (message.type) {
1496
+ case "connected":
1497
+ wsRef.current?.send(JSON.stringify({ type: "get_sessions" }));
1498
+ break;
1499
+ case "sessions_list":
1500
+ if (message.sessions) {
1501
+ setSessions(message.sessions);
1502
+ onSessionsUpdate?.(message.sessions);
1503
+ }
1504
+ break;
1505
+ case "terminal_attached":
1506
+ if (message.sessionId) {
1507
+ setAttachedSessionId(message.sessionId);
1508
+ setError(null);
1509
+ if (message.scrollback && terminalRef.current) {
1510
+ terminalRef.current.write(message.scrollback);
1511
+ }
1512
+ if (fitAddonRef.current && terminalRef.current) {
1513
+ fitAddonRef.current.fit();
1514
+ wsRef.current?.send(JSON.stringify({
1515
+ type: "terminal_resize",
1516
+ sessionId: message.sessionId,
1517
+ cols: terminalRef.current.cols,
1518
+ rows: terminalRef.current.rows
1519
+ }));
1520
+ }
1521
+ }
1522
+ break;
1523
+ case "terminal_output":
1524
+ if (message.data && terminalRef.current && message.sessionId === attachedSessionIdRef.current) {
1525
+ terminalRef.current.write(message.data);
1526
+ }
1527
+ break;
1528
+ case "terminal_detached":
1529
+ if (message.sessionId === attachedSessionIdRef.current) {
1530
+ setAttachedSessionId(null);
1531
+ }
1532
+ break;
1533
+ case "error":
1534
+ setError(message.error || "Unknown error");
1535
+ console.error("[ClaudeTerminal] Error:", message.error);
1536
+ break;
1537
+ case "pong":
1538
+ break;
1539
+ }
1540
+ } catch (e) {
1541
+ console.error("[ClaudeTerminal] Failed to parse message:", e);
1542
+ }
1543
+ };
1544
+ }, [onSessionsUpdate]);
1545
+ (0, import_react4.useEffect)(() => {
1546
+ const wsUrl = serverUrl.replace(/^http/, "ws").replace(/\/$/, "");
1547
+ const ws = new WebSocket(`${wsUrl}/ws/bridge?token=${encodeURIComponent(token)}`);
1548
+ ws.onopen = () => {
1549
+ setConnected(true);
1550
+ setError(null);
1551
+ onConnectionChange?.(true);
1552
+ };
1553
+ ws.onmessage = (event) => {
1554
+ handleMessageRef.current?.(event);
1555
+ };
1556
+ ws.onclose = () => {
1557
+ setConnected(false);
1558
+ setAttachedSessionId(null);
1559
+ onConnectionChange?.(false);
1560
+ };
1561
+ ws.onerror = () => {
1562
+ setError("WebSocket connection error");
1563
+ };
1564
+ wsRef.current = ws;
1565
+ const pingInterval = setInterval(() => {
1566
+ if (ws.readyState === WebSocket.OPEN) {
1567
+ ws.send(JSON.stringify({ type: "ping" }));
1568
+ }
1569
+ }, 3e4);
1570
+ return () => {
1571
+ clearInterval(pingInterval);
1572
+ ws.close();
1573
+ wsRef.current = null;
1574
+ };
1575
+ }, [serverUrl, token, onConnectionChange]);
1576
+ (0, import_react4.useEffect)(() => {
1577
+ if (sessionId && connected && !attachedSessionId) {
1578
+ wsRef.current?.send(JSON.stringify({
1579
+ type: "attach_terminal",
1580
+ sessionId
1581
+ }));
1582
+ }
1583
+ }, [sessionId, connected, attachedSessionId]);
1584
+ (0, import_react4.useEffect)(() => {
1585
+ if (attachedSessionId && terminalRef.current && fitAddonRef.current) {
1586
+ const timer = setTimeout(() => {
1587
+ fitAddonRef.current?.fit();
1588
+ terminalRef.current?.focus();
1589
+ }, 50);
1590
+ return () => clearTimeout(timer);
1591
+ }
1592
+ }, [attachedSessionId]);
1593
+ const handleContainerClick = (0, import_react4.useCallback)(() => {
1594
+ terminalRef.current?.focus();
1595
+ }, []);
1596
+ const handleSelectSession = (0, import_react4.useCallback)((session) => {
1597
+ terminalRef.current?.clear();
1598
+ if (attachedSessionId) {
1599
+ wsRef.current?.send(JSON.stringify({
1600
+ type: "detach_terminal",
1601
+ sessionId: attachedSessionId
1602
+ }));
1603
+ }
1604
+ wsRef.current?.send(JSON.stringify({
1605
+ type: "attach_terminal",
1606
+ sessionId: session.id
1607
+ }));
1608
+ onSessionSelect?.(session);
1609
+ }, [attachedSessionId, onSessionSelect]);
1610
+ if (!sessionId && !attachedSessionId) {
1611
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
1612
+ "div",
1613
+ {
1614
+ className,
1615
+ style: {
1616
+ background: "#1a1a1a",
1617
+ color: "#f0f0f0",
1618
+ padding: "20px",
1619
+ fontFamily: 'Menlo, Monaco, "Courier New", monospace',
1620
+ ...style
1621
+ },
1622
+ children: !connected ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { children: "Connecting to server..." }) : error ? /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { style: { color: "#ff5555" }, children: [
1623
+ "Error: ",
1624
+ error
1625
+ ] }) : sessions.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { children: "No Claude sessions available" }) : /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { children: [
1626
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { style: { marginBottom: "10px", fontSize: "14px" }, children: "Select a Claude session:" }),
1627
+ sessions.map((session) => /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
1628
+ "div",
1629
+ {
1630
+ onClick: () => handleSelectSession(session),
1631
+ style: {
1632
+ padding: "10px",
1633
+ margin: "5px 0",
1634
+ background: "#2a2a2a",
1635
+ borderRadius: "4px",
1636
+ cursor: "pointer",
1637
+ border: "1px solid #3a3a3a"
1638
+ },
1639
+ onMouseOver: (e) => {
1640
+ e.currentTarget.style.background = "#3a3a3a";
1641
+ },
1642
+ onMouseOut: (e) => {
1643
+ e.currentTarget.style.background = "#2a2a2a";
1644
+ },
1645
+ children: [
1646
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { style: { fontWeight: "bold" }, children: session.displayName || session.name }),
1647
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { style: { fontSize: "12px", color: "#888", marginTop: "4px" }, children: session.workingDir })
1648
+ ]
1649
+ },
1650
+ session.id
1651
+ ))
1652
+ ] })
1653
+ }
1654
+ );
1655
+ }
1656
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_jsx_runtime4.Fragment, { children: [
1657
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("style", { children: XTERM_CRITICAL_CSS }),
1658
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
1659
+ "div",
1660
+ {
1661
+ ref: containerRef,
1662
+ className,
1663
+ onClick: handleContainerClick,
1664
+ style: {
1665
+ width: "100%",
1666
+ height: "100%",
1667
+ ...style
1668
+ }
1669
+ }
1670
+ )
1671
+ ] });
1672
+ }
1673
+
1674
+ // src/TaskStatusToast.tsx
1675
+ var import_jsx_runtime5 = require("react/jsx-runtime");
1676
+ var MIN_WIDTH = 400;
1677
+ var MIN_HEIGHT = 300;
1678
+ var DEFAULT_WIDTH = 700;
1679
+ var DEFAULT_HEIGHT = 500;
1680
+ function TaskStatusToast({
1681
+ task,
1682
+ serverUrl,
1683
+ token,
1684
+ onDismiss,
1685
+ killOnClose = true
1686
+ }) {
1687
+ const [visible, setVisible] = (0, import_react5.useState)(false);
1688
+ const [expanded, setExpanded] = (0, import_react5.useState)(false);
1689
+ const [size, setSize] = (0, import_react5.useState)({ width: DEFAULT_WIDTH, height: DEFAULT_HEIGHT });
1690
+ const [isResizing, setIsResizing] = (0, import_react5.useState)(false);
1691
+ const resizeRef = (0, import_react5.useRef)(null);
1692
+ (0, import_react5.useEffect)(() => {
1693
+ if (task) {
1694
+ setVisible(true);
1695
+ if (task.sessionId && (task.status === "running" || task.status === "starting")) {
1696
+ setExpanded(true);
1697
+ }
1698
+ }
1699
+ }, [task, task?.sessionId, task?.status]);
1700
+ (0, import_react5.useEffect)(() => {
1701
+ if (task && !expanded && (task.status === "completed" || task.status === "failed")) {
1702
+ const timer = setTimeout(() => {
1703
+ setVisible(false);
1704
+ setTimeout(onDismiss, 300);
1705
+ }, 1e4);
1706
+ return () => clearTimeout(timer);
1707
+ }
1708
+ }, [task?.status, expanded, onDismiss]);
1709
+ const handleResizeStart = (0, import_react5.useCallback)((e, direction) => {
1710
+ e.preventDefault();
1711
+ e.stopPropagation();
1712
+ setIsResizing(true);
1713
+ resizeRef.current = {
1714
+ startX: e.clientX,
1715
+ startY: e.clientY,
1716
+ startWidth: size.width,
1717
+ startHeight: size.height
1718
+ };
1719
+ const handleMouseMove = (moveEvent) => {
1720
+ if (!resizeRef.current) return;
1721
+ let newWidth = resizeRef.current.startWidth;
1722
+ let newHeight = resizeRef.current.startHeight;
1723
+ if (direction.includes("w")) {
1724
+ newWidth = resizeRef.current.startWidth - (moveEvent.clientX - resizeRef.current.startX);
1725
+ }
1726
+ if (direction.includes("n")) {
1727
+ newHeight = resizeRef.current.startHeight - (moveEvent.clientY - resizeRef.current.startY);
1728
+ }
1729
+ setSize({
1730
+ width: Math.max(MIN_WIDTH, newWidth),
1731
+ height: Math.max(MIN_HEIGHT, newHeight)
1732
+ });
1733
+ };
1734
+ const handleMouseUp = () => {
1735
+ setIsResizing(false);
1736
+ resizeRef.current = null;
1737
+ document.removeEventListener("mousemove", handleMouseMove);
1738
+ document.removeEventListener("mouseup", handleMouseUp);
1739
+ };
1740
+ document.addEventListener("mousemove", handleMouseMove);
1741
+ document.addEventListener("mouseup", handleMouseUp);
1742
+ }, [size]);
1743
+ const killSession = (0, import_react5.useCallback)((sessionId) => {
1744
+ return new Promise((resolve) => {
1745
+ const wsUrl = serverUrl.replace(/^http/, "ws").replace(/\/$/, "");
1746
+ const ws = new WebSocket(`${wsUrl}/ws/bridge?token=${encodeURIComponent(token)}`);
1747
+ ws.onopen = () => {
1748
+ ws.send(JSON.stringify({
1749
+ type: "kill_session",
1750
+ sessionId
1751
+ }));
1752
+ setTimeout(() => {
1753
+ ws.close();
1754
+ resolve();
1755
+ }, 100);
1756
+ };
1757
+ ws.onerror = () => {
1758
+ ws.close();
1759
+ resolve();
1760
+ };
1761
+ setTimeout(() => {
1762
+ if (ws.readyState !== WebSocket.CLOSED) {
1763
+ ws.close();
1764
+ }
1765
+ resolve();
1766
+ }, 2e3);
1767
+ });
1768
+ }, [serverUrl, token]);
1769
+ const handleDismiss = (0, import_react5.useCallback)(async () => {
1770
+ if (killOnClose && task?.sessionId) {
1771
+ await killSession(task.sessionId);
1772
+ }
1773
+ setVisible(false);
1774
+ setExpanded(false);
1775
+ setTimeout(onDismiss, 300);
1776
+ }, [killOnClose, task?.sessionId, killSession, onDismiss]);
1777
+ const handleToggleExpand = (0, import_react5.useCallback)(() => {
1778
+ setExpanded(!expanded);
1779
+ }, [expanded]);
1780
+ if (!task || !visible) return null;
1781
+ const statusColors = {
1782
+ queued: { bg: "#6366f1", text: "Queued" },
1783
+ starting: { bg: "#f59e0b", text: "Starting..." },
1784
+ running: { bg: "#22c55e", text: "Running" },
1785
+ completed: { bg: "#22c55e", text: "Completed" },
1786
+ failed: { bg: "#ef4444", text: "Failed" }
1787
+ };
1788
+ const status = statusColors[task.status] || statusColors.queued;
1789
+ const zedUrl = task.sessionId ? `${serverUrl}?token=${encodeURIComponent(token)}&session=${task.sessionId}` : `${serverUrl}?token=${encodeURIComponent(token)}`;
1790
+ const handleOpenZed = () => {
1791
+ window.open(zedUrl, "_blank");
1792
+ };
1793
+ if (!expanded) {
1794
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
1795
+ "div",
1796
+ {
1797
+ style: {
1798
+ position: "fixed",
1799
+ bottom: 24,
1800
+ right: 24,
1801
+ zIndex: 1000001,
1802
+ background: "#1e1e2e",
1803
+ borderRadius: 12,
1804
+ boxShadow: "0 8px 32px rgba(0, 0, 0, 0.3)",
1805
+ fontFamily: "system-ui, -apple-system, sans-serif",
1806
+ minWidth: 320,
1807
+ maxWidth: 400,
1808
+ opacity: visible ? 1 : 0,
1809
+ transform: visible ? "translateY(0)" : "translateY(20px)",
1810
+ transition: "opacity 0.3s, transform 0.3s"
1811
+ },
1812
+ children: [
1813
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
1814
+ "div",
1815
+ {
1816
+ style: {
1817
+ padding: "12px 16px",
1818
+ borderBottom: "1px solid rgba(255, 255, 255, 0.1)",
1819
+ display: "flex",
1820
+ alignItems: "center",
1821
+ gap: 10
1822
+ },
1823
+ children: [
1824
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1825
+ "div",
1826
+ {
1827
+ style: {
1828
+ width: 10,
1829
+ height: 10,
1830
+ borderRadius: "50%",
1831
+ background: status.bg,
1832
+ animation: task.status === "running" || task.status === "starting" ? "claude-bridge-pulse 1.5s infinite" : "none"
1833
+ }
1834
+ }
1835
+ ),
1836
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
1837
+ "span",
1838
+ {
1839
+ style: {
1840
+ color: "rgba(255, 255, 255, 0.9)",
1841
+ fontSize: 14,
1842
+ fontWeight: 500,
1843
+ flex: 1
1844
+ },
1845
+ children: [
1846
+ "Claude Task: ",
1847
+ status.text
1848
+ ]
1849
+ }
1850
+ ),
1851
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1852
+ "button",
1853
+ {
1854
+ onClick: handleDismiss,
1855
+ style: {
1856
+ background: "transparent",
1857
+ border: "none",
1858
+ color: "rgba(255, 255, 255, 0.5)",
1859
+ cursor: "pointer",
1860
+ padding: 4,
1861
+ fontSize: 18,
1862
+ lineHeight: 1
1863
+ },
1864
+ children: "\xD7"
1865
+ }
1866
+ )
1867
+ ]
1868
+ }
1869
+ ),
1870
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { style: { padding: "12px 16px" }, children: [
1871
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1872
+ "p",
1873
+ {
1874
+ style: {
1875
+ color: "rgba(255, 255, 255, 0.7)",
1876
+ fontSize: 13,
1877
+ margin: 0,
1878
+ lineHeight: 1.5,
1879
+ overflow: "hidden",
1880
+ textOverflow: "ellipsis",
1881
+ display: "-webkit-box",
1882
+ WebkitLineClamp: 2,
1883
+ WebkitBoxOrient: "vertical"
1884
+ },
1885
+ children: task.prompt
1886
+ }
1887
+ ),
1888
+ task.error && /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
1889
+ "p",
1890
+ {
1891
+ style: {
1892
+ color: "#ef4444",
1893
+ fontSize: 12,
1894
+ margin: "8px 0 0"
1895
+ },
1896
+ children: [
1897
+ "Error: ",
1898
+ task.error
1899
+ ]
1900
+ }
1901
+ )
1902
+ ] }),
1903
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
1904
+ "div",
1905
+ {
1906
+ style: {
1907
+ padding: "12px 16px",
1908
+ borderTop: "1px solid rgba(255, 255, 255, 0.1)",
1909
+ display: "flex",
1910
+ justifyContent: "flex-end",
1911
+ gap: 8
1912
+ },
1913
+ children: [
1914
+ task.sessionId && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1915
+ "button",
1916
+ {
1917
+ onClick: handleToggleExpand,
1918
+ style: {
1919
+ background: "#374151",
1920
+ border: "none",
1921
+ borderRadius: 6,
1922
+ padding: "8px 16px",
1923
+ color: "white",
1924
+ fontSize: 13,
1925
+ fontWeight: 500,
1926
+ cursor: "pointer",
1927
+ display: "flex",
1928
+ alignItems: "center",
1929
+ gap: 6
1930
+ },
1931
+ children: "Show Terminal"
1932
+ }
1933
+ ),
1934
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
1935
+ "button",
1936
+ {
1937
+ onClick: handleOpenZed,
1938
+ style: {
1939
+ background: "#6366f1",
1940
+ border: "none",
1941
+ borderRadius: 6,
1942
+ padding: "8px 16px",
1943
+ color: "white",
1944
+ fontSize: 13,
1945
+ fontWeight: 500,
1946
+ cursor: "pointer",
1947
+ display: "flex",
1948
+ alignItems: "center",
1949
+ gap: 6
1950
+ },
1951
+ children: [
1952
+ "Open in Zed Controller",
1953
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { style: { fontSize: 11 }, children: "\u2197" })
1954
+ ]
1955
+ }
1956
+ )
1957
+ ]
1958
+ }
1959
+ ),
1960
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("style", { children: `
1961
+ @keyframes claude-bridge-pulse {
1962
+ 0%, 100% { opacity: 1; }
1963
+ 50% { opacity: 0.5; }
1964
+ }
1965
+ ` })
1966
+ ]
1967
+ }
1968
+ );
1969
+ }
1970
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
1971
+ "div",
1972
+ {
1973
+ style: {
1974
+ position: "fixed",
1975
+ bottom: 24,
1976
+ right: 24,
1977
+ zIndex: 1000001,
1978
+ width: size.width,
1979
+ height: size.height,
1980
+ background: "#1e1e2e",
1981
+ borderRadius: 12,
1982
+ boxShadow: "0 8px 32px rgba(0, 0, 0, 0.4)",
1983
+ fontFamily: "system-ui, -apple-system, sans-serif",
1984
+ display: "flex",
1985
+ flexDirection: "column",
1986
+ opacity: visible ? 1 : 0,
1987
+ transition: isResizing ? "none" : "opacity 0.3s",
1988
+ overflow: "hidden"
1989
+ },
1990
+ children: [
1991
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1992
+ "div",
1993
+ {
1994
+ onMouseDown: (e) => handleResizeStart(e, "n"),
1995
+ style: {
1996
+ position: "absolute",
1997
+ top: 0,
1998
+ left: 20,
1999
+ right: 20,
2000
+ height: 6,
2001
+ cursor: "ns-resize",
2002
+ zIndex: 10
2003
+ }
2004
+ }
2005
+ ),
2006
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
2007
+ "div",
2008
+ {
2009
+ onMouseDown: (e) => handleResizeStart(e, "w"),
2010
+ style: {
2011
+ position: "absolute",
2012
+ left: 0,
2013
+ top: 20,
2014
+ bottom: 20,
2015
+ width: 6,
2016
+ cursor: "ew-resize",
2017
+ zIndex: 10
2018
+ }
2019
+ }
2020
+ ),
2021
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
2022
+ "div",
2023
+ {
2024
+ onMouseDown: (e) => handleResizeStart(e, "nw"),
2025
+ style: {
2026
+ position: "absolute",
2027
+ top: 0,
2028
+ left: 0,
2029
+ width: 20,
2030
+ height: 20,
2031
+ cursor: "nwse-resize",
2032
+ zIndex: 11
2033
+ }
2034
+ }
2035
+ ),
2036
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
2037
+ "div",
2038
+ {
2039
+ style: {
2040
+ padding: "10px 16px",
2041
+ borderBottom: "1px solid rgba(255, 255, 255, 0.1)",
2042
+ display: "flex",
2043
+ alignItems: "center",
2044
+ gap: 10,
2045
+ flexShrink: 0
2046
+ },
2047
+ children: [
2048
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
2049
+ "div",
2050
+ {
2051
+ style: {
2052
+ width: 10,
2053
+ height: 10,
2054
+ borderRadius: "50%",
2055
+ background: status.bg,
2056
+ animation: task.status === "running" || task.status === "starting" ? "claude-bridge-pulse 1.5s infinite" : "none"
2057
+ }
2058
+ }
2059
+ ),
2060
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
2061
+ "span",
2062
+ {
2063
+ style: {
2064
+ color: "rgba(255, 255, 255, 0.9)",
2065
+ fontSize: 14,
2066
+ fontWeight: 500,
2067
+ flex: 1,
2068
+ overflow: "hidden",
2069
+ textOverflow: "ellipsis",
2070
+ whiteSpace: "nowrap"
2071
+ },
2072
+ title: task.prompt,
2073
+ children: [
2074
+ status.text,
2075
+ ": ",
2076
+ task.prompt.slice(0, 50),
2077
+ task.prompt.length > 50 ? "..." : ""
2078
+ ]
2079
+ }
2080
+ ),
2081
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
2082
+ "button",
2083
+ {
2084
+ onClick: handleToggleExpand,
2085
+ title: "Minimize",
2086
+ style: {
2087
+ background: "transparent",
2088
+ border: "none",
2089
+ color: "rgba(255, 255, 255, 0.5)",
2090
+ cursor: "pointer",
2091
+ padding: 4,
2092
+ fontSize: 14,
2093
+ lineHeight: 1
2094
+ },
2095
+ children: "\u2212"
2096
+ }
2097
+ ),
2098
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
2099
+ "button",
2100
+ {
2101
+ onClick: handleOpenZed,
2102
+ title: "Open in Zed Controller",
2103
+ style: {
2104
+ background: "transparent",
2105
+ border: "none",
2106
+ color: "rgba(255, 255, 255, 0.5)",
2107
+ cursor: "pointer",
2108
+ padding: 4,
2109
+ fontSize: 14,
2110
+ lineHeight: 1
2111
+ },
2112
+ children: "\u2197"
2113
+ }
2114
+ ),
2115
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
2116
+ "button",
2117
+ {
2118
+ onClick: handleDismiss,
2119
+ title: "Close",
2120
+ style: {
2121
+ background: "transparent",
2122
+ border: "none",
2123
+ color: "rgba(255, 255, 255, 0.5)",
2124
+ cursor: "pointer",
2125
+ padding: 4,
2126
+ fontSize: 18,
2127
+ lineHeight: 1
2128
+ },
2129
+ children: "\xD7"
2130
+ }
2131
+ )
2132
+ ]
2133
+ }
2134
+ ),
2135
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { style: { flex: 1, minHeight: 0 }, children: task.sessionId ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
2136
+ ClaudeTerminal,
2137
+ {
2138
+ serverUrl,
2139
+ token,
2140
+ sessionId: task.sessionId,
2141
+ style: { width: "100%", height: "100%" }
2142
+ }
2143
+ ) : /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
2144
+ "div",
2145
+ {
2146
+ style: {
2147
+ display: "flex",
2148
+ alignItems: "center",
2149
+ justifyContent: "center",
2150
+ height: "100%",
2151
+ color: "rgba(255, 255, 255, 0.5)"
2152
+ },
2153
+ children: "Waiting for session..."
2154
+ }
2155
+ ) }),
2156
+ task.error && /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
2157
+ "div",
2158
+ {
2159
+ style: {
2160
+ padding: "8px 16px",
2161
+ background: "rgba(239, 68, 68, 0.2)",
2162
+ borderTop: "1px solid rgba(239, 68, 68, 0.3)",
2163
+ color: "#ef4444",
2164
+ fontSize: 12,
2165
+ flexShrink: 0
2166
+ },
2167
+ children: [
2168
+ "Error: ",
2169
+ task.error
2170
+ ]
2171
+ }
2172
+ ),
2173
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("style", { children: `
2174
+ @keyframes claude-bridge-pulse {
2175
+ 0%, 100% { opacity: 1; }
2176
+ 50% { opacity: 0.5; }
2177
+ }
2178
+ ` })
2179
+ ]
2180
+ }
2181
+ );
2182
+ }
2183
+
2184
+ // src/ClaudeBridgeProvider.tsx
2185
+ var import_jsx_runtime6 = require("react/jsx-runtime");
2186
+ var initialState = {
2187
+ connected: false,
2188
+ selectionMode: false,
2189
+ questionMode: false,
2190
+ selectedElement: null,
2191
+ activeTask: null,
2192
+ tasks: []
2193
+ };
2194
+ function reducer(state, action) {
2195
+ switch (action.type) {
2196
+ case "SET_CONNECTED":
2197
+ return { ...state, connected: action.connected };
2198
+ case "SET_SELECTION_MODE":
2199
+ return {
2200
+ ...state,
2201
+ selectionMode: action.enabled,
2202
+ questionMode: action.enabled ? false : state.questionMode,
2203
+ // Turn off question mode when entering selection mode
2204
+ selectedElement: action.enabled ? state.selectedElement : null
2205
+ };
2206
+ case "SET_QUESTION_MODE":
2207
+ return {
2208
+ ...state,
2209
+ questionMode: action.enabled,
2210
+ selectionMode: action.enabled ? false : state.selectionMode
2211
+ // Turn off selection mode when entering question mode
2212
+ };
2213
+ case "SET_SELECTED_ELEMENT":
2214
+ return { ...state, selectedElement: action.element };
2215
+ case "SET_ACTIVE_TASK":
2216
+ return { ...state, activeTask: action.task };
2217
+ case "ADD_TASK":
2218
+ return { ...state, tasks: [...state.tasks, action.task] };
2219
+ case "UPDATE_TASK":
2220
+ return {
2221
+ ...state,
2222
+ tasks: state.tasks.map(
2223
+ (t) => t.id === action.taskId ? { ...t, ...action.updates } : t
2224
+ ),
2225
+ activeTask: state.activeTask?.id === action.taskId ? { ...state.activeTask, ...action.updates } : state.activeTask
2226
+ };
2227
+ case "CLEAR_TASKS":
2228
+ return { ...state, tasks: [], activeTask: null };
2229
+ default:
2230
+ return state;
2231
+ }
2232
+ }
2233
+ var ClaudeBridgeContext = (0, import_react6.createContext)(null);
2234
+ function ClaudeBridgeProvider({
2235
+ children,
2236
+ serverUrl,
2237
+ token,
2238
+ enabled = true,
2239
+ projectRoot,
2240
+ shortcut = "Meta+Shift+K",
2241
+ questionShortcut = "Meta+Shift+?",
2242
+ onTaskCreated,
2243
+ onTaskProgress,
2244
+ onTaskCompleted,
2245
+ onTaskFailed,
2246
+ onError
2247
+ }) {
2248
+ const [state, dispatch] = (0, import_react6.useReducer)(reducer, initialState);
2249
+ const wsClientRef = (0, import_react6.useRef)(null);
2250
+ const pendingTaskResolveRef = (0, import_react6.useRef)(null);
2251
+ const config = {
2252
+ serverUrl,
2253
+ token,
2254
+ enabled,
2255
+ projectRoot,
2256
+ shortcut,
2257
+ questionShortcut,
2258
+ onTaskCreated,
2259
+ onTaskProgress,
2260
+ onTaskCompleted,
2261
+ onTaskFailed,
2262
+ onError
2263
+ };
2264
+ (0, import_react6.useEffect)(() => {
2265
+ if (!enabled) return;
2266
+ const client = new BridgeWebSocketClient(config);
2267
+ wsClientRef.current = client;
2268
+ const unsubConnection = client.onConnection((connected) => {
2269
+ dispatch({ type: "SET_CONNECTED", connected });
2270
+ });
2271
+ const unsubMessage = client.onMessage((message) => {
2272
+ handleMessage(message);
2273
+ });
2274
+ client.connect();
2275
+ return () => {
2276
+ unsubConnection();
2277
+ unsubMessage();
2278
+ client.disconnect();
2279
+ wsClientRef.current = null;
2280
+ };
2281
+ }, [enabled, serverUrl, token]);
2282
+ const handleMessage = (0, import_react6.useCallback)((message) => {
2283
+ switch (message.type) {
2284
+ case "task_created":
2285
+ if (message.task) {
2286
+ dispatch({ type: "ADD_TASK", task: message.task });
2287
+ dispatch({ type: "SET_ACTIVE_TASK", task: message.task });
2288
+ onTaskCreated?.(message.task.id);
2289
+ pendingTaskResolveRef.current?.(message.task.id);
2290
+ pendingTaskResolveRef.current = null;
2291
+ }
2292
+ break;
2293
+ case "task_progress":
2294
+ if (message.taskId && message.output) {
2295
+ dispatch({
2296
+ type: "UPDATE_TASK",
2297
+ taskId: message.taskId,
2298
+ updates: { status: "running" }
2299
+ });
2300
+ onTaskProgress?.(message.taskId, message.output);
2301
+ }
2302
+ break;
2303
+ case "task_completed":
2304
+ if (message.taskId) {
2305
+ dispatch({
2306
+ type: "UPDATE_TASK",
2307
+ taskId: message.taskId,
2308
+ updates: {
2309
+ status: "completed",
2310
+ completedAt: (/* @__PURE__ */ new Date()).toISOString()
2311
+ }
2312
+ });
2313
+ onTaskCompleted?.(message.taskId);
2314
+ }
2315
+ break;
2316
+ case "task_failed":
2317
+ if (message.taskId) {
2318
+ dispatch({
2319
+ type: "UPDATE_TASK",
2320
+ taskId: message.taskId,
2321
+ updates: {
2322
+ status: "failed",
2323
+ error: message.error,
2324
+ completedAt: (/* @__PURE__ */ new Date()).toISOString()
2325
+ }
2326
+ });
2327
+ onTaskFailed?.(message.taskId, message.error || "Unknown error");
2328
+ pendingTaskResolveRef.current?.(null);
2329
+ pendingTaskResolveRef.current = null;
2330
+ }
2331
+ break;
2332
+ case "pong":
2333
+ break;
2334
+ default:
2335
+ console.log("[ClaudeBridge] Unknown message type:", message.type);
2336
+ }
2337
+ }, [onTaskCreated, onTaskProgress, onTaskCompleted, onTaskFailed]);
2338
+ const matchesShortcut = (0, import_react6.useCallback)((e, shortcutStr) => {
2339
+ const keys = shortcutStr.split("+");
2340
+ const requiresMeta = keys.includes("Meta");
2341
+ const requiresCtrl = keys.includes("Ctrl");
2342
+ const requiresShift = keys.includes("Shift");
2343
+ const requiresAlt = keys.includes("Alt");
2344
+ const key = keys.find((k) => !["Meta", "Ctrl", "Shift", "Alt"].includes(k));
2345
+ return (requiresMeta ? e.metaKey : true) && (requiresCtrl ? e.ctrlKey : true) && (requiresShift ? e.shiftKey : true) && (requiresAlt ? e.altKey : true) && e.key.toUpperCase() === key?.toUpperCase();
2346
+ }, []);
2347
+ (0, import_react6.useEffect)(() => {
2348
+ if (!enabled) return;
2349
+ const handleKeyDown = (e) => {
2350
+ if (matchesShortcut(e, shortcut)) {
2351
+ e.preventDefault();
2352
+ if (!state.selectionMode) {
2353
+ dispatch({ type: "SET_ACTIVE_TASK", task: null });
2354
+ }
2355
+ dispatch({ type: "SET_SELECTION_MODE", enabled: !state.selectionMode });
2356
+ return;
2357
+ }
2358
+ if (matchesShortcut(e, questionShortcut)) {
2359
+ e.preventDefault();
2360
+ if (!state.questionMode) {
2361
+ dispatch({ type: "SET_ACTIVE_TASK", task: null });
2362
+ }
2363
+ dispatch({ type: "SET_QUESTION_MODE", enabled: !state.questionMode });
2364
+ return;
2365
+ }
2366
+ if (e.key === "Escape") {
2367
+ if (state.selectionMode) {
2368
+ dispatch({ type: "SET_SELECTION_MODE", enabled: false });
2369
+ }
2370
+ if (state.questionMode) {
2371
+ dispatch({ type: "SET_QUESTION_MODE", enabled: false });
2372
+ }
2373
+ }
2374
+ };
2375
+ window.addEventListener("keydown", handleKeyDown);
2376
+ return () => window.removeEventListener("keydown", handleKeyDown);
2377
+ }, [enabled, shortcut, questionShortcut, state.selectionMode, state.questionMode, matchesShortcut]);
2378
+ const enableSelectionMode = (0, import_react6.useCallback)(() => {
2379
+ dispatch({ type: "SET_ACTIVE_TASK", task: null });
2380
+ dispatch({ type: "SET_SELECTION_MODE", enabled: true });
2381
+ }, []);
2382
+ const disableSelectionMode = (0, import_react6.useCallback)(() => {
2383
+ dispatch({ type: "SET_SELECTION_MODE", enabled: false });
2384
+ }, []);
2385
+ const enableQuestionMode = (0, import_react6.useCallback)(() => {
2386
+ dispatch({ type: "SET_ACTIVE_TASK", task: null });
2387
+ dispatch({ type: "SET_QUESTION_MODE", enabled: true });
2388
+ }, []);
2389
+ const disableQuestionMode = (0, import_react6.useCallback)(() => {
2390
+ dispatch({ type: "SET_QUESTION_MODE", enabled: false });
2391
+ }, []);
2392
+ const submitTask = (0, import_react6.useCallback)(async (prompt) => {
2393
+ if (!state.selectedElement || !wsClientRef.current?.isConnected) {
2394
+ return null;
2395
+ }
2396
+ const context = captureContext(state.selectedElement);
2397
+ console.log("[ClaudeBridge] submitTask captured context:", {
2398
+ sourceFile: context.sourceFile,
2399
+ sourceLine: context.sourceLine,
2400
+ componentName: context.componentName,
2401
+ element: state.selectedElement.tagName
2402
+ });
2403
+ const screenshot = await captureElementScreenshot(state.selectedElement);
2404
+ const fullContext = {
2405
+ ...context,
2406
+ screenshot
2407
+ };
2408
+ const taskIdPromise = new Promise((resolve) => {
2409
+ pendingTaskResolveRef.current = resolve;
2410
+ setTimeout(() => {
2411
+ if (pendingTaskResolveRef.current === resolve) {
2412
+ pendingTaskResolveRef.current = null;
2413
+ resolve(null);
2414
+ }
2415
+ }, 1e4);
2416
+ });
2417
+ const sent = wsClientRef.current.createTask(prompt, fullContext);
2418
+ if (!sent) {
2419
+ pendingTaskResolveRef.current = null;
2420
+ return null;
2421
+ }
2422
+ dispatch({ type: "SET_SELECTION_MODE", enabled: false });
2423
+ return taskIdPromise;
2424
+ }, [state.selectedElement]);
2425
+ const continueTask = (0, import_react6.useCallback)(async (taskId, prompt) => {
2426
+ if (!wsClientRef.current?.isConnected) {
2427
+ throw new Error("Not connected");
2428
+ }
2429
+ let context = void 0;
2430
+ if (state.selectedElement) {
2431
+ const baseContext = captureContext(state.selectedElement);
2432
+ const screenshot = await captureElementScreenshot(state.selectedElement);
2433
+ context = { ...baseContext, screenshot };
2434
+ }
2435
+ const sent = wsClientRef.current.continueTask(taskId, prompt, context);
2436
+ if (!sent) {
2437
+ throw new Error("Failed to send continue task message");
2438
+ }
2439
+ }, [state.selectedElement]);
2440
+ const submitQuestion = (0, import_react6.useCallback)(async (prompt, includeSelectedElement = false) => {
2441
+ if (!wsClientRef.current?.isConnected) {
2442
+ return null;
2443
+ }
2444
+ let context;
2445
+ if (includeSelectedElement && state.selectedElement) {
2446
+ const baseContext = captureContext(state.selectedElement);
2447
+ const screenshot = await captureElementScreenshot(state.selectedElement);
2448
+ context = { ...baseContext, screenshot };
2449
+ } else {
2450
+ context = capturePageContext();
2451
+ }
2452
+ const questionPrompt = `[QUESTION - No code changes expected, just provide information]
2453
+
2454
+ ${prompt}`;
2455
+ const taskIdPromise = new Promise((resolve) => {
2456
+ pendingTaskResolveRef.current = resolve;
2457
+ setTimeout(() => {
2458
+ if (pendingTaskResolveRef.current === resolve) {
2459
+ pendingTaskResolveRef.current = null;
2460
+ resolve(null);
2461
+ }
2462
+ }, 1e4);
2463
+ });
2464
+ const sent = wsClientRef.current.createTask(questionPrompt, context);
2465
+ if (!sent) {
2466
+ pendingTaskResolveRef.current = null;
2467
+ return null;
2468
+ }
2469
+ dispatch({ type: "SET_QUESTION_MODE", enabled: false });
2470
+ return taskIdPromise;
2471
+ }, [state.selectedElement]);
2472
+ const handleElementSelect = (0, import_react6.useCallback)((element) => {
2473
+ dispatch({ type: "SET_SELECTED_ELEMENT", element });
2474
+ }, []);
2475
+ const handlePromptSubmit = (0, import_react6.useCallback)(async (prompt) => {
2476
+ await submitTask(prompt);
2477
+ }, [submitTask]);
2478
+ const handlePromptClose = (0, import_react6.useCallback)(() => {
2479
+ dispatch({ type: "SET_SELECTED_ELEMENT", element: null });
2480
+ }, []);
2481
+ const handleQuestionSubmit = (0, import_react6.useCallback)(async (prompt, includeElement) => {
2482
+ await submitQuestion(prompt, includeElement);
2483
+ }, [submitQuestion]);
2484
+ const handleQuestionClose = (0, import_react6.useCallback)(() => {
2485
+ dispatch({ type: "SET_QUESTION_MODE", enabled: false });
2486
+ }, []);
2487
+ const handleSwitchToQuestionMode = (0, import_react6.useCallback)(() => {
2488
+ dispatch({ type: "SET_QUESTION_MODE", enabled: true });
2489
+ }, []);
2490
+ const handleSwitchToTaskMode = (0, import_react6.useCallback)(() => {
2491
+ dispatch({ type: "SET_QUESTION_MODE", enabled: false });
2492
+ if (!state.selectedElement) {
2493
+ dispatch({ type: "SET_SELECTION_MODE", enabled: true });
2494
+ }
2495
+ }, [state.selectedElement]);
2496
+ const handleToastDismiss = (0, import_react6.useCallback)(() => {
2497
+ dispatch({ type: "SET_ACTIVE_TASK", task: null });
2498
+ }, []);
2499
+ const contextValue = {
2500
+ state,
2501
+ config,
2502
+ enableSelectionMode,
2503
+ disableSelectionMode,
2504
+ enableQuestionMode,
2505
+ disableQuestionMode,
2506
+ submitTask,
2507
+ submitQuestion,
2508
+ continueTask
2509
+ };
2510
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(ClaudeBridgeContext.Provider, { value: contextValue, children: [
2511
+ children,
2512
+ enabled && /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_jsx_runtime6.Fragment, { children: [
2513
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
2514
+ SelectionOverlay,
2515
+ {
2516
+ active: state.selectionMode,
2517
+ onElementSelect: handleElementSelect,
2518
+ selectedElement: state.selectedElement
2519
+ }
2520
+ ),
2521
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
2522
+ PromptDialog,
2523
+ {
2524
+ open: state.selectedElement !== null && !state.questionMode,
2525
+ element: state.selectedElement,
2526
+ onSubmit: handlePromptSubmit,
2527
+ onClose: handlePromptClose,
2528
+ onSwitchToQuestionMode: handleSwitchToQuestionMode,
2529
+ isSubmitting: state.activeTask?.status === "starting" || state.activeTask?.status === "running"
2530
+ }
2531
+ ),
2532
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
2533
+ QuestionDialog,
2534
+ {
2535
+ open: state.questionMode,
2536
+ selectedElement: state.selectedElement,
2537
+ onSubmit: handleQuestionSubmit,
2538
+ onClose: handleQuestionClose,
2539
+ onSwitchToTaskMode: handleSwitchToTaskMode,
2540
+ isSubmitting: state.activeTask?.status === "starting" || state.activeTask?.status === "running"
2541
+ }
2542
+ ),
2543
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
2544
+ TaskStatusToast,
2545
+ {
2546
+ task: state.activeTask,
2547
+ serverUrl,
2548
+ token,
2549
+ onDismiss: handleToastDismiss
2550
+ }
2551
+ )
2552
+ ] })
2553
+ ] });
2554
+ }
2555
+ function useClaudeBridge() {
2556
+ const context = (0, import_react6.useContext)(ClaudeBridgeContext);
2557
+ if (!context) {
2558
+ throw new Error("useClaudeBridge must be used within a ClaudeBridgeProvider");
2559
+ }
2560
+ return context;
2561
+ }
2562
+ // Annotate the CommonJS export names for ESM import in node:
2563
+ 0 && (module.exports = {
2564
+ ClaudeBridgeProvider,
2565
+ ClaudeTerminal,
2566
+ TaskStatusToast,
2567
+ captureContext,
2568
+ captureElementScreenshot,
2569
+ capturePageContext,
2570
+ useClaudeBridge
2571
+ });
2572
+ //# sourceMappingURL=index.cjs.map