@concavejs/devtools 0.0.1-alpha.10

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,7 @@
1
+ /**
2
+ * Client entry point for DevTools
3
+ * This is injected into the browser by the Vite plugin
4
+ */
5
+ export declare function initDevTools(options?: {
6
+ position?: "bottom-right" | "bottom-left" | "top-right" | "top-left";
7
+ }): void;
package/dist/client.js ADDED
@@ -0,0 +1,6 @@
1
+ import "react/jsx-runtime";
2
+ import "react-dom/client";
3
+ import { i as m } from "./client-CRYWrjNv.js";
4
+ export {
5
+ m as initDevTools
6
+ };
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Page Agent — Thin IIFE injected into the page context.
3
+ *
4
+ * Intercepts WebSocket traffic using the same WebSocketInterceptor,
5
+ * but instead of a full EventStore it posts events to the content script
6
+ * via window.postMessage. Buffers the last 500 events for late-opening panels.
7
+ */
8
+ export {};
@@ -0,0 +1,14 @@
1
+ /**
2
+ * DevTools Panel Entry — React app rendered inside the Chrome DevTools "Concave" tab.
3
+ *
4
+ * Uses chrome.devtools.inspectedWindow.reload({ injectedScript }) to install a
5
+ * WebSocket interceptor BEFORE any page scripts run. This guarantees full
6
+ * interception without any permissions beyond the devtools_page manifest key.
7
+ *
8
+ * Flow:
9
+ * 1. Panel opens → try eval() injection (catches new WS connections)
10
+ * 2. If page already has a connection → show "Reload" button
11
+ * 3. Reload uses inspectedWindow.reload({ injectedScript }) — runs before page JS
12
+ * 4. On navigation → re-inject via eval()
13
+ */
14
+ import "../devtools.css";
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Concave DevTools
3
+ *
4
+ * Client-side development tools for Convex/Concave applications
5
+ */
6
+ export type { DevToolsEvent, QueryEvent, MutationEvent, ActionEvent, SubscriptionEvent, LogEvent, AuthEvent, ActiveSubscription, PerformanceMetrics, EventType, EventStatus, SubscriptionStatus, } from "./types";
7
+ export { EventStore, getGlobalEventStore } from "./store/event-store";
8
+ export type { EventListener, StoreSnapshot, ExportedSession } from "./store/event-store";
9
+ export { WebSocketInterceptor } from "./interceptor/websocket-interceptor";
10
+ export { DevToolbar } from "./overlay/DevToolbar";
11
+ export { SubscriptionsPanel } from "./overlay/SubscriptionsPanel";
12
+ export { PerformancePanel } from "./overlay/PerformancePanel";
13
+ export { LogsPanel } from "./overlay/LogsPanel";
14
+ export { SettingsPanel } from "./overlay/SettingsPanel";
15
+ export { DataInspector } from "./overlay/DataInspector";
16
+ export { initDevTools } from "./client";
17
+ export { default as concaveDevTools } from "./vite-plugin/index";
18
+ export type { DevToolsOptions } from "./vite-plugin/index";
package/dist/index.js ADDED
@@ -0,0 +1,486 @@
1
+ import { b as M, D as k, E as A, L as D, P as $, a as C, S as R, g as W, i as O } from "./client-CRYWrjNv.js";
2
+ import { concaveDevTools as N } from "./vite-plugin.js";
3
+ function P(c) {
4
+ const t = c.split(".");
5
+ if (t.length < 2) return null;
6
+ try {
7
+ const n = t[1].replace(/-/g, "+").replace(/_/g, "/"), e = n + "=".repeat((4 - n.length % 4) % 4), o = JSON.parse(atob(e)), s = ["iss", "sub", "aud", "exp", "iat", "nbf"], i = {};
8
+ for (const a of s) {
9
+ const d = o[a];
10
+ d !== void 0 && (i[a] = d);
11
+ }
12
+ return typeof i.exp == "number" && (i.expIso = new Date(i.exp * 1e3).toISOString()), typeof i.iat == "number" && (i.iatIso = new Date(i.iat * 1e3).toISOString()), Object.keys(i).length > 0 ? i : null;
13
+ } catch {
14
+ return null;
15
+ }
16
+ }
17
+ const v = /* @__PURE__ */ Symbol.for("__concaveDevToolsInternalWsListener"), m = /* @__PURE__ */ Symbol.for("__concaveDevToolsWsDelayMs");
18
+ function q() {
19
+ const c = window.__concaveDevToolsLatencyConfig;
20
+ if (!c) return 0;
21
+ const t = (s) => {
22
+ const i = Number(s);
23
+ return !Number.isFinite(i) || i <= 0 ? 0 : Math.min(i, 5e3);
24
+ }, n = t(c.latencyMs);
25
+ let e = t(c.jitterMs);
26
+ if (n <= 0 && e <= 0) return 0;
27
+ n > 0 && e > n && (e = n);
28
+ const o = e > 0 ? (Math.random() * 2 - 1) * e : 0;
29
+ return Math.max(0, n + o);
30
+ }
31
+ function T(c) {
32
+ const t = c[m];
33
+ if (typeof t == "number" && Number.isFinite(t) && t >= 0)
34
+ return t;
35
+ const n = q();
36
+ try {
37
+ Object.defineProperty(c, m, {
38
+ value: n,
39
+ configurable: !0
40
+ });
41
+ } catch {
42
+ c[m] = n;
43
+ }
44
+ return n;
45
+ }
46
+ function E(c, t, n) {
47
+ if (c[v]) {
48
+ c.call(t, n);
49
+ return;
50
+ }
51
+ let e = 0;
52
+ try {
53
+ e = T(n);
54
+ } catch {
55
+ e = 0;
56
+ }
57
+ if (e <= 0) {
58
+ c.call(t, n);
59
+ return;
60
+ }
61
+ setTimeout(() => {
62
+ c.call(t, n);
63
+ }, e);
64
+ }
65
+ class L {
66
+ eventStore;
67
+ originalWebSocket;
68
+ pendingQueries = /* @__PURE__ */ new Map();
69
+ pendingMutations = /* @__PURE__ */ new Map();
70
+ pendingActions = /* @__PURE__ */ new Map();
71
+ pendingAuthTokenType = null;
72
+ /** Tracks the most recent mutation event ID for causality linking */
73
+ lastMutationEventId = null;
74
+ lastMutationTimestamp = 0;
75
+ constructor(t) {
76
+ this.eventStore = t, this.originalWebSocket = window.WebSocket;
77
+ }
78
+ /**
79
+ * Install the WebSocket interceptor
80
+ */
81
+ install() {
82
+ const t = this;
83
+ window.__concaveDevToolsLatencyConfig || (window.__concaveDevToolsLatencyConfig = { latencyMs: 0, jitterMs: 0 });
84
+ const n = this.originalWebSocket;
85
+ class e extends n {
86
+ constructor(s, i) {
87
+ super(s, i);
88
+ const a = this.addEventListener.bind(this), d = this.removeEventListener.bind(this), g = /* @__PURE__ */ new WeakMap();
89
+ this.addEventListener = (u, r, h) => {
90
+ if (u === "message" && typeof r == "function") {
91
+ let l = g.get(r);
92
+ l || (l = (y) => {
93
+ try {
94
+ const f = T(y);
95
+ t.handleServerMessage(y.data, f);
96
+ } catch (f) {
97
+ console.warn("[DevTools] Error parsing server message:", f);
98
+ }
99
+ E(r, this, y);
100
+ }, l[v] = !0, g.set(r, l)), a("message", l, h);
101
+ } else
102
+ a(u, r, h);
103
+ }, this.removeEventListener = (u, r, h) => {
104
+ if (u === "message" && typeof r == "function") {
105
+ const l = g.get(r);
106
+ d("message", l ?? r, h);
107
+ } else
108
+ d(u, r, h);
109
+ };
110
+ let b = null, p = null;
111
+ Object.defineProperty(this, "onmessage", {
112
+ get: () => b,
113
+ set: (u) => {
114
+ if (p && (d("message", p), p = null), b = u, u) {
115
+ const r = (h) => {
116
+ try {
117
+ const l = T(h);
118
+ t.handleServerMessage(h.data, l);
119
+ } catch (l) {
120
+ console.warn("[DevTools] Error parsing server message:", l);
121
+ }
122
+ E(u, this, h);
123
+ };
124
+ r[v] = !0, p = r, a("message", r);
125
+ }
126
+ },
127
+ configurable: !0,
128
+ enumerable: !0
129
+ });
130
+ const I = this.send.bind(this);
131
+ this.send = (u) => {
132
+ try {
133
+ typeof u == "string" && t.handleClientMessage(u);
134
+ } catch (r) {
135
+ console.warn("[DevTools] Error parsing client message:", r);
136
+ }
137
+ I(u);
138
+ };
139
+ }
140
+ }
141
+ window.WebSocket = e, console.log("[DevTools] WebSocket interceptor installed");
142
+ }
143
+ /**
144
+ * Uninstall the interceptor
145
+ */
146
+ uninstall() {
147
+ window.WebSocket = this.originalWebSocket;
148
+ }
149
+ /**
150
+ * Handle client → server messages
151
+ */
152
+ handleClientMessage(t) {
153
+ try {
154
+ const n = JSON.parse(t);
155
+ switch (console.log("[DevTools] Client message:", n.type, n), n.type) {
156
+ case "ModifyQuerySet":
157
+ this.handleModifyQuerySet(n.modifications);
158
+ break;
159
+ case "Mutation":
160
+ this.handleMutationRequest(n);
161
+ break;
162
+ case "Action":
163
+ this.handleActionRequest(n);
164
+ break;
165
+ case "Connect":
166
+ this.handleConnectMessage(n);
167
+ break;
168
+ case "Authenticate":
169
+ this.handleAuthenticateMessage(n);
170
+ break;
171
+ }
172
+ } catch (n) {
173
+ console.warn("[DevTools] Failed to parse client message:", n);
174
+ }
175
+ }
176
+ /**
177
+ * Handle server → client messages
178
+ */
179
+ handleServerMessage(t, n = 0) {
180
+ try {
181
+ const e = JSON.parse(t);
182
+ switch (console.log("[DevTools] Server message:", e.type, e), e.type) {
183
+ case "Transition":
184
+ this.handleTransition(e, n);
185
+ break;
186
+ case "MutationResponse":
187
+ this.handleMutationResponse(e, n);
188
+ break;
189
+ case "ActionResponse":
190
+ this.handleActionResponse(e, n);
191
+ break;
192
+ case "AuthError":
193
+ this.handleAuthErrorResponse(e);
194
+ break;
195
+ }
196
+ } catch (e) {
197
+ console.warn("[DevTools] Failed to parse server message:", e);
198
+ }
199
+ }
200
+ /**
201
+ * Handle query set modifications (subscriptions)
202
+ */
203
+ handleModifyQuerySet(t) {
204
+ const n = Date.now();
205
+ for (const e of t)
206
+ if (e.type === "Add") {
207
+ this.pendingQueries.set(e.queryId, {
208
+ queryId: e.queryId,
209
+ udfPath: e.udfPath,
210
+ args: e.args,
211
+ componentPath: e.componentPath,
212
+ startTime: n
213
+ });
214
+ const o = {
215
+ id: `sub-${e.queryId}-${n}`,
216
+ timestamp: n,
217
+ type: "subscription",
218
+ queryId: e.queryId,
219
+ udfPath: e.udfPath,
220
+ args: e.args,
221
+ componentPath: e.componentPath,
222
+ status: "added"
223
+ };
224
+ this.eventStore.addEvent(o);
225
+ const s = {
226
+ id: `query-pending-${e.queryId}-${n}`,
227
+ timestamp: n,
228
+ type: "query",
229
+ queryId: e.queryId,
230
+ udfPath: e.udfPath,
231
+ args: e.args,
232
+ componentPath: e.componentPath,
233
+ status: "pending"
234
+ };
235
+ this.eventStore.addEvent(s);
236
+ } else if (e.type === "Remove") {
237
+ const o = this.pendingQueries.get(e.queryId);
238
+ if (this.pendingQueries.delete(e.queryId), o) {
239
+ const s = {
240
+ id: `sub-${e.queryId}-${n}`,
241
+ timestamp: n,
242
+ type: "subscription",
243
+ queryId: e.queryId,
244
+ udfPath: o.udfPath,
245
+ args: o.args,
246
+ componentPath: o.componentPath,
247
+ status: "removed"
248
+ };
249
+ this.eventStore.addEvent(s);
250
+ }
251
+ }
252
+ }
253
+ /**
254
+ * Handle mutation requests
255
+ */
256
+ handleMutationRequest(t) {
257
+ const n = Date.now();
258
+ this.pendingMutations.set(t.requestId, {
259
+ requestId: t.requestId,
260
+ udfPath: t.udfPath,
261
+ args: t.args,
262
+ componentPath: t.componentPath,
263
+ startTime: n
264
+ });
265
+ const e = {
266
+ id: `mutation-pending-${t.requestId}-${n}`,
267
+ timestamp: n,
268
+ type: "mutation",
269
+ requestId: t.requestId,
270
+ udfPath: t.udfPath,
271
+ args: t.args,
272
+ componentPath: t.componentPath,
273
+ status: "pending"
274
+ };
275
+ this.eventStore.addEvent(e);
276
+ }
277
+ /**
278
+ * Handle action requests
279
+ */
280
+ handleActionRequest(t) {
281
+ const n = Date.now();
282
+ this.pendingActions.set(t.requestId, {
283
+ requestId: t.requestId,
284
+ udfPath: t.udfPath,
285
+ args: t.args,
286
+ componentPath: t.componentPath,
287
+ startTime: n
288
+ });
289
+ const e = {
290
+ id: `action-pending-${t.requestId}-${n}`,
291
+ timestamp: n,
292
+ type: "action",
293
+ requestId: t.requestId,
294
+ udfPath: t.udfPath,
295
+ args: t.args,
296
+ componentPath: t.componentPath,
297
+ status: "pending"
298
+ };
299
+ this.eventStore.addEvent(e);
300
+ }
301
+ handleConnectMessage(t) {
302
+ const n = {};
303
+ typeof t.connectionCount == "number" && (n.connectionCount = t.connectionCount), typeof t.lastCloseReason == "string" && (n.lastCloseReason = t.lastCloseReason), typeof t.clientTs == "number" && (n.clientTs = t.clientTs), typeof t.sessionId == "string" && (n.sessionId = t.sessionId), this.emitAuthEvent({
304
+ direction: "client",
305
+ messageType: "Connect",
306
+ status: "success",
307
+ details: n
308
+ });
309
+ }
310
+ handleAuthenticateMessage(t) {
311
+ const n = {};
312
+ if (typeof t.baseVersion == "number" && (n.baseVersion = t.baseVersion), typeof t.tokenType == "string" && (n.tokenType = t.tokenType), typeof t.value == "string" && t.value.length > 0) {
313
+ const e = t.value;
314
+ n.tokenLength = e.length, n.tokenPreview = e.length > 24 ? `${e.slice(0, 12)}…${e.slice(-10)}` : e;
315
+ const o = P(e);
316
+ o && (n.jwtClaims = o);
317
+ }
318
+ this.pendingAuthTokenType = t.tokenType ?? "Unknown", this.emitAuthEvent({
319
+ direction: "client",
320
+ messageType: "Authenticate",
321
+ status: "success",
322
+ tokenType: t.tokenType,
323
+ details: n
324
+ });
325
+ }
326
+ /**
327
+ * Handle state transitions (query updates)
328
+ */
329
+ handleTransition(t, n = 0) {
330
+ const e = Date.now();
331
+ this.pendingAuthTokenType && (this.emitAuthEvent({
332
+ direction: "server",
333
+ messageType: "Authenticated",
334
+ status: "success",
335
+ tokenType: this.pendingAuthTokenType,
336
+ details: { modificationCount: t.modifications.length }
337
+ }), this.pendingAuthTokenType = null);
338
+ for (const o of t.modifications)
339
+ if (o.type === "QueryUpdated") {
340
+ const s = this.pendingQueries.get(o.queryId);
341
+ if (!s) continue;
342
+ const i = e - s.startTime, a = this.resolveOperationTimings(i, n), d = this.lastMutationEventId && e - this.lastMutationTimestamp < 2e3 ? this.lastMutationEventId : void 0, g = {
343
+ id: `query-${o.queryId}-${e}`,
344
+ timestamp: e,
345
+ type: "query",
346
+ queryId: o.queryId,
347
+ udfPath: s.udfPath,
348
+ args: s.args,
349
+ componentPath: s.componentPath,
350
+ status: "success",
351
+ result: o.value,
352
+ logLines: o.logLines,
353
+ trace: o.trace,
354
+ ...a,
355
+ triggeredBy: d
356
+ };
357
+ this.eventStore.addEvent(g), Array.isArray(o.logLines) && o.logLines.length > 0 && this.emitLogEvents(o.logLines, g.id);
358
+ } else if (o.type === "QueryFailed") {
359
+ const s = this.pendingQueries.get(o.queryId);
360
+ if (!s) continue;
361
+ const i = e - s.startTime, a = this.resolveOperationTimings(i, n), d = {
362
+ id: `query-${o.queryId}-${e}`,
363
+ timestamp: e,
364
+ type: "query",
365
+ queryId: o.queryId,
366
+ udfPath: s.udfPath,
367
+ args: s.args,
368
+ componentPath: s.componentPath,
369
+ status: "error",
370
+ error: o.errorMessage,
371
+ logLines: o.logLines,
372
+ ...a
373
+ };
374
+ this.eventStore.addEvent(d), Array.isArray(o.logLines) && o.logLines.length > 0 && this.emitLogEvents(o.logLines, d.id);
375
+ }
376
+ }
377
+ /**
378
+ * Handle mutation responses
379
+ */
380
+ handleMutationResponse(t, n = 0) {
381
+ const e = this.pendingMutations.get(t.requestId);
382
+ if (!e) return;
383
+ const o = Date.now(), s = o - e.startTime, i = this.resolveOperationTimings(s, n), a = {
384
+ id: `mutation-${t.requestId}-${o}`,
385
+ timestamp: o,
386
+ type: "mutation",
387
+ requestId: t.requestId,
388
+ udfPath: e.udfPath,
389
+ args: e.args,
390
+ componentPath: e.componentPath,
391
+ status: t.success ? "success" : "error",
392
+ result: t.success ? t.result : void 0,
393
+ error: t.success ? void 0 : t.result,
394
+ logLines: t.logLines,
395
+ trace: t.trace,
396
+ ...i
397
+ };
398
+ this.eventStore.addEvent(a), this.lastMutationEventId = a.id, this.lastMutationTimestamp = o, t.logLines && t.logLines.length > 0 && this.emitLogEvents(t.logLines, a.id), this.pendingMutations.delete(t.requestId);
399
+ }
400
+ /**
401
+ * Handle action responses
402
+ */
403
+ handleActionResponse(t, n = 0) {
404
+ const e = this.pendingActions.get(t.requestId);
405
+ if (!e) return;
406
+ const o = Date.now(), s = o - e.startTime, i = this.resolveOperationTimings(s, n), a = {
407
+ id: `action-${t.requestId}-${o}`,
408
+ timestamp: o,
409
+ type: "action",
410
+ requestId: t.requestId,
411
+ udfPath: e.udfPath,
412
+ args: e.args,
413
+ componentPath: e.componentPath,
414
+ status: t.success ? "success" : "error",
415
+ result: t.success ? t.result : void 0,
416
+ error: t.success ? void 0 : t.result,
417
+ logLines: t.logLines,
418
+ trace: t.trace,
419
+ ...i
420
+ };
421
+ this.eventStore.addEvent(a), t.logLines && t.logLines.length > 0 && this.emitLogEvents(t.logLines, a.id), this.pendingActions.delete(t.requestId);
422
+ }
423
+ handleAuthErrorResponse(t) {
424
+ const n = {};
425
+ typeof t.baseVersion == "number" && (n.baseVersion = t.baseVersion), typeof t.authUpdateAttempted == "boolean" && (n.authUpdateAttempted = t.authUpdateAttempted), this.emitAuthEvent({
426
+ direction: "server",
427
+ messageType: "AuthError",
428
+ status: "error",
429
+ tokenType: this.pendingAuthTokenType ?? void 0,
430
+ error: t.error ?? "Authentication failed",
431
+ details: n
432
+ }), this.pendingAuthTokenType = null;
433
+ }
434
+ resolveOperationTimings(t, n) {
435
+ const e = Number.isFinite(t) && t >= 0 ? t : 0, o = Number.isFinite(n) && n > 0 ? n : 0;
436
+ return {
437
+ duration: e,
438
+ simulatedDelayMs: o,
439
+ endToEndDurationMs: e + o
440
+ };
441
+ }
442
+ emitAuthEvent(t) {
443
+ const n = Date.now(), e = {
444
+ id: `auth-${t.direction}-${t.messageType}-${n}-${Math.random().toString(36).slice(2, 8)}`,
445
+ timestamp: n,
446
+ type: "auth",
447
+ direction: t.direction,
448
+ messageType: t.messageType,
449
+ status: t.status,
450
+ tokenType: t.tokenType,
451
+ error: t.error,
452
+ details: t.details
453
+ };
454
+ this.eventStore.addEvent(e);
455
+ }
456
+ /**
457
+ * Extract and emit log events from logLines
458
+ */
459
+ emitLogEvents(t, n) {
460
+ const e = Date.now();
461
+ for (const o of t) {
462
+ const s = o.match(/^\[(log|info|warn|error)\]\s+(.+)$/i), i = s ? s[1].toLowerCase() : "log", a = s ? s[2] : o, d = {
463
+ id: `log-${e}-${Math.random()}`,
464
+ timestamp: e,
465
+ type: "log",
466
+ level: i,
467
+ message: a,
468
+ relatedEventId: n
469
+ };
470
+ this.eventStore.addEvent(d);
471
+ }
472
+ }
473
+ }
474
+ export {
475
+ M as DataInspector,
476
+ k as DevToolbar,
477
+ A as EventStore,
478
+ D as LogsPanel,
479
+ $ as PerformancePanel,
480
+ C as SettingsPanel,
481
+ R as SubscriptionsPanel,
482
+ L as WebSocketInterceptor,
483
+ N as concaveDevTools,
484
+ W as getGlobalEventStore,
485
+ O as initDevTools
486
+ };
@@ -0,0 +1,5 @@
1
+ /**
2
+ * WebSocket Interceptor exports
3
+ */
4
+ export { WebSocketInterceptor } from "./websocket-interceptor";
5
+ export { getGlobalEventStore } from "../store/event-store";
@@ -0,0 +1,68 @@
1
+ /**
2
+ * WebSocket Interceptor for Convex Sync Protocol
3
+ *
4
+ * Intercepts WebSocket messages to capture queries, mutations, actions, subscriptions,
5
+ * and authentication protocol events.
6
+ */
7
+ import type { EventStore } from "../store/event-store";
8
+ export declare class WebSocketInterceptor {
9
+ private eventStore;
10
+ private originalWebSocket;
11
+ private pendingQueries;
12
+ private pendingMutations;
13
+ private pendingActions;
14
+ private pendingAuthTokenType;
15
+ /** Tracks the most recent mutation event ID for causality linking */
16
+ private lastMutationEventId;
17
+ private lastMutationTimestamp;
18
+ constructor(eventStore: EventStore);
19
+ /**
20
+ * Install the WebSocket interceptor
21
+ */
22
+ install(): void;
23
+ /**
24
+ * Uninstall the interceptor
25
+ */
26
+ uninstall(): void;
27
+ /**
28
+ * Handle client → server messages
29
+ */
30
+ private handleClientMessage;
31
+ /**
32
+ * Handle server → client messages
33
+ */
34
+ private handleServerMessage;
35
+ /**
36
+ * Handle query set modifications (subscriptions)
37
+ */
38
+ private handleModifyQuerySet;
39
+ /**
40
+ * Handle mutation requests
41
+ */
42
+ private handleMutationRequest;
43
+ /**
44
+ * Handle action requests
45
+ */
46
+ private handleActionRequest;
47
+ private handleConnectMessage;
48
+ private handleAuthenticateMessage;
49
+ /**
50
+ * Handle state transitions (query updates)
51
+ */
52
+ private handleTransition;
53
+ /**
54
+ * Handle mutation responses
55
+ */
56
+ private handleMutationResponse;
57
+ /**
58
+ * Handle action responses
59
+ */
60
+ private handleActionResponse;
61
+ private handleAuthErrorResponse;
62
+ private resolveOperationTimings;
63
+ private emitAuthEvent;
64
+ /**
65
+ * Extract and emit log events from logLines
66
+ */
67
+ private emitLogEvents;
68
+ }
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Activity Panel - Unified view of queries, mutations, and actions
3
+ * with focused list-first debugging UX
4
+ */
5
+ import type { EventStore } from "../store/event-store";
6
+ interface ActivityPanelProps {
7
+ eventStore: EventStore;
8
+ panelConnectionState?: {
9
+ waitingForConnection: boolean;
10
+ needsReload: boolean;
11
+ onReload: () => void;
12
+ agentAttached?: boolean;
13
+ socketSeen?: boolean;
14
+ captureLive?: boolean;
15
+ };
16
+ }
17
+ export declare function ActivityPanel({ eventStore, panelConnectionState }: ActivityPanelProps): import("react/jsx-runtime").JSX.Element;
18
+ export {};
@@ -0,0 +1,23 @@
1
+ /**
2
+ * ContextMenu - Native-style right-click context menu for DevTools panels
3
+ */
4
+ export interface MenuItem {
5
+ label: string;
6
+ action: () => void;
7
+ shortcut?: string;
8
+ disabled?: boolean;
9
+ separator?: boolean;
10
+ }
11
+ export interface ContextMenuProps {
12
+ x: number;
13
+ y: number;
14
+ items: MenuItem[];
15
+ onClose: () => void;
16
+ }
17
+ export declare function ContextMenu({ x, y, items, onClose }: ContextMenuProps): import("react/jsx-runtime").JSX.Element;
18
+ /** State type for panels using context menus */
19
+ export interface ContextMenuState {
20
+ x: number;
21
+ y: number;
22
+ items: MenuItem[];
23
+ }
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Data Inspector - Advanced JSON viewer with syntax highlighting, search, and diff
3
+ */
4
+ import type { JSONValue } from "../types";
5
+ interface DataInspectorProps {
6
+ data: JSONValue;
7
+ label?: string;
8
+ onCopy?: () => void;
9
+ maxHeight?: number;
10
+ }
11
+ export declare function DataInspector({ data, label, onCopy, maxHeight, }: DataInspectorProps): import("react/jsx-runtime").JSX.Element;
12
+ export {};
@@ -0,0 +1,19 @@
1
+ /**
2
+ * Main DevTools Overlay Component
3
+ */
4
+ import type { EventStore } from "../store/event-store";
5
+ interface DevToolbarProps {
6
+ eventStore: EventStore;
7
+ position?: "bottom-right" | "bottom-left" | "top-right" | "top-left";
8
+ mode?: "overlay" | "panel";
9
+ panelConnectionState?: {
10
+ waitingForConnection: boolean;
11
+ needsReload: boolean;
12
+ onReload: () => void;
13
+ agentAttached?: boolean;
14
+ socketSeen?: boolean;
15
+ captureLive?: boolean;
16
+ };
17
+ }
18
+ export declare function DevToolbar({ eventStore, position, mode, panelConnectionState, }: DevToolbarProps): import("react/jsx-runtime").JSX.Element;
19
+ export {};