@kwirthmagnify/kwirth-plugin-provider-debug 0.1.0 → 0.1.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.
Files changed (2) hide show
  1. package/front.js +159 -11
  2. package/package.json +1 -1
package/front.js CHANGED
@@ -99,6 +99,8 @@
99
99
  this.events = [];
100
100
  this.providers = [];
101
101
  this.signals = [];
102
+ this.configAccepted = false;
103
+ this.subscribed = false;
102
104
  this.paused = false;
103
105
  this.started = false;
104
106
  }
@@ -232,6 +234,27 @@
232
234
  if (token === "true" || token === "false" || token === "null") return theme.palette.secondary.main;
233
235
  return theme.palette.warning.main;
234
236
  };
237
+ const paint = (text, color, keyBase) => {
238
+ const needle = (props.highlight ?? "").trim();
239
+ if (needle === "") return [/* @__PURE__ */ import_react2.default.createElement("span", { key: keyBase, style: color ? { color } : void 0 }, text)];
240
+ const nodes = [];
241
+ const lower = text.toLowerCase();
242
+ const target = needle.toLowerCase();
243
+ let from = 0;
244
+ let at = lower.indexOf(target);
245
+ while (at >= 0) {
246
+ if (at > from) nodes.push(/* @__PURE__ */ import_react2.default.createElement("span", { key: `${keyBase}-${from}`, style: color ? { color } : void 0 }, text.slice(from, at)));
247
+ nodes.push(
248
+ // el marcador permite que el buscador centre la COINCIDENCIA y no la tarjeta: con un
249
+ // JSON de miles de líneas, centrar la tarjeta deja el resultado fuera de pantalla
250
+ /* @__PURE__ */ import_react2.default.createElement("span", { key: `${keyBase}-h${at}`, "data-pd-hit": "1", style: { backgroundColor: theme.palette.text.primary, color: theme.palette.background.paper } }, text.slice(at, at + needle.length))
251
+ );
252
+ from = at + needle.length;
253
+ at = lower.indexOf(target, from);
254
+ }
255
+ if (from < text.length) nodes.push(/* @__PURE__ */ import_react2.default.createElement("span", { key: `${keyBase}-${from}`, style: color ? { color } : void 0 }, text.slice(from)));
256
+ return nodes;
257
+ };
235
258
  const render = () => {
236
259
  let text;
237
260
  try {
@@ -244,11 +267,11 @@
244
267
  let match;
245
268
  TOKEN.lastIndex = 0;
246
269
  while ((match = TOKEN.exec(text)) !== null) {
247
- if (match.index > last) nodes.push(/* @__PURE__ */ import_react2.default.createElement("span", { key: `p${last}` }, text.slice(last, match.index)));
248
- nodes.push(/* @__PURE__ */ import_react2.default.createElement("span", { key: `t${match.index}`, style: { color: colorOf(match[0]) } }, match[0]));
270
+ if (match.index > last) nodes.push(...paint(text.slice(last, match.index), void 0, `p${last}`));
271
+ nodes.push(...paint(match[0], colorOf(match[0]), `t${match.index}`));
249
272
  last = match.index + match[0].length;
250
273
  }
251
- if (last < text.length) nodes.push(/* @__PURE__ */ import_react2.default.createElement("span", { key: `p${last}` }, text.slice(last)));
274
+ if (last < text.length) nodes.push(...paint(text.slice(last), void 0, `p${last}`));
252
275
  return nodes;
253
276
  };
254
277
  return /* @__PURE__ */ import_react2.default.createElement(import_material2.Box, { component: "pre", sx: { m: 0, fontFamily: "monospace", fontSize: "0.75rem", whiteSpace: "pre-wrap", wordBreak: "break-all", overflowX: "auto" } }, render());
@@ -263,14 +286,56 @@
263
286
  const [boxTop, setBoxTop] = (0, import_react3.useState)(0);
264
287
  const [, forceRender] = (0, import_react3.useState)(0);
265
288
  const [copied, setCopied] = (0, import_react3.useState)(null);
289
+ const [search, setSearch] = (0, import_react3.useState)("");
290
+ const [matchPos, setMatchPos] = (0, import_react3.useState)(-1);
291
+ const [expanded, setExpanded] = (0, import_react3.useState)(/* @__PURE__ */ new Set());
292
+ const cardRefs = (0, import_react3.useRef)(/* @__PURE__ */ new Map());
293
+ const searchText = (0, import_react3.useRef)(/* @__PURE__ */ new WeakMap());
266
294
  (0, import_react3.useEffect)(() => {
267
295
  if (boxRef.current) setBoxTop(boxRef.current.getBoundingClientRect().top);
268
296
  });
269
297
  const clear = () => {
270
298
  data.events = [];
271
299
  data.signals = [];
300
+ setExpanded(/* @__PURE__ */ new Set());
301
+ cardRefs.current.clear();
302
+ setMatchPos(-1);
272
303
  forceRender((n) => n + 1);
273
304
  };
305
+ const textOf = (event) => {
306
+ const cached = searchText.current.get(event);
307
+ if (cached !== void 0) return cached;
308
+ let text;
309
+ try {
310
+ text = (event.providerId + " " + JSON.stringify(event.event)).toLowerCase();
311
+ } catch {
312
+ text = event.providerId.toLowerCase();
313
+ }
314
+ searchText.current.set(event, text);
315
+ return text;
316
+ };
317
+ const matches = () => {
318
+ const needle = search.trim().toLowerCase();
319
+ if (needle === "") return [];
320
+ return data.events.filter((event) => textOf(event).includes(needle));
321
+ };
322
+ const isMatch = (event) => {
323
+ const needle = search.trim().toLowerCase();
324
+ return needle !== "" && textOf(event).includes(needle);
325
+ };
326
+ const goToMatch = (pos) => {
327
+ const found2 = matches();
328
+ if (found2.length === 0) return;
329
+ const next = (pos % found2.length + found2.length) % found2.length;
330
+ const target = found2[next];
331
+ setMatchPos(next);
332
+ setExpanded((prev) => new Set(prev).add(target));
333
+ setTimeout(() => {
334
+ const card = cardRefs.current.get(target);
335
+ const hit = card?.querySelector("[data-pd-hit]");
336
+ (hit ?? card)?.scrollIntoView({ block: "center" });
337
+ }, 0);
338
+ };
274
339
  const writeClipboard = async (text) => {
275
340
  try {
276
341
  await navigator.clipboard.writeText(text);
@@ -295,7 +360,7 @@
295
360
  writeClipboard(JSON.stringify(event.event, null, 2)).then((ok) => {
296
361
  if (!ok) return;
297
362
  setCopied(event);
298
- setTimeout(() => setCopied((current) => current === event ? null : current), 1500);
363
+ setTimeout(() => setCopied((current2) => current2 === event ? null : current2), 1500);
299
364
  });
300
365
  };
301
366
  const summaryOf = (event) => {
@@ -311,14 +376,86 @@
311
376
  if (data.providers.length === 0) return /* @__PURE__ */ import_react3.default.createElement(import_material3.Typography, { variant: "body2", color: "text.secondary" }, "No providers running.");
312
377
  return /* @__PURE__ */ import_react3.default.createElement(import_material3.Stack, { direction: "row", spacing: 1, flexWrap: "wrap", useFlexGap: true }, data.providers.map((p) => /* @__PURE__ */ import_react3.default.createElement(import_material3.Chip, { key: p.id, label: p.id, size: "small", variant: p.id === instanceConfig.providerId ? "filled" : "outlined" })));
313
378
  };
314
- const formatEvent = (event, index) => /* @__PURE__ */ import_react3.default.createElement(import_material3.Accordion, { key: index, disableGutters: true, slotProps: { transition: { unmountOnExit: true } } }, /* @__PURE__ */ import_react3.default.createElement(import_material3.AccordionSummary, { expandIcon: /* @__PURE__ */ import_react3.default.createElement(import_icons_material2.ExpandMore, null) }, /* @__PURE__ */ import_react3.default.createElement(import_material3.Stack, { direction: "row", spacing: 1.5, alignItems: "center", sx: { minWidth: 0, width: "100%" } }, /* @__PURE__ */ import_react3.default.createElement(import_material3.Typography, { variant: "caption", color: "text.secondary", sx: { fontFamily: "monospace" } }, new Date(event.ts).toISOString()), /* @__PURE__ */ import_react3.default.createElement(import_material3.Chip, { label: event.providerId, size: "small", variant: "outlined", sx: { fontSize: "0.65rem", height: 18 } }), /* @__PURE__ */ import_react3.default.createElement(import_material3.Typography, { variant: "caption", color: "text.secondary", noWrap: true }, summaryOf(event.event)), /* @__PURE__ */ import_react3.default.createElement(import_material3.Tooltip, { title: copied === event ? "Copied" : "Copy event JSON" }, /* @__PURE__ */ import_react3.default.createElement(import_material3.IconButton, { size: "small", "aria-label": "Copy event JSON", sx: { ml: "auto" }, onClick: (e) => {
315
- e.stopPropagation();
316
- copy(event);
317
- } }, copied === event ? /* @__PURE__ */ import_react3.default.createElement(import_icons_material2.Check, { fontSize: "small", color: "success" }) : /* @__PURE__ */ import_react3.default.createElement(import_icons_material2.ContentCopy, { fontSize: "small" }))))), /* @__PURE__ */ import_react3.default.createElement(import_material3.AccordionDetails, null, /* @__PURE__ */ import_react3.default.createElement(JsonBlock, { value: event.event })));
379
+ const toggle = (event) => setExpanded((prev) => {
380
+ const next = new Set(prev);
381
+ if (next.has(event)) next.delete(event);
382
+ else next.add(event);
383
+ return next;
384
+ });
385
+ const formatEvent = (event, index, current2) => {
386
+ const open = expanded.has(event);
387
+ return /* @__PURE__ */ import_react3.default.createElement(
388
+ import_material3.Paper,
389
+ {
390
+ key: index,
391
+ variant: "outlined",
392
+ ref: (el) => {
393
+ if (el) cardRefs.current.set(event, el);
394
+ else cardRefs.current.delete(event);
395
+ },
396
+ sx: { mb: 0.5, ...current2 === event ? { outline: 2, outlineColor: "warning.main", outlineOffset: -2 } : {} }
397
+ },
398
+ /* @__PURE__ */ import_react3.default.createElement(import_material3.Stack, { direction: "row", spacing: 1.5, alignItems: "center", sx: { minWidth: 0, px: 1, py: 0.5, cursor: "pointer" }, onClick: () => toggle(event) }, /* @__PURE__ */ import_react3.default.createElement(import_material3.IconButton, { size: "small", "aria-label": open ? "Collapse event" : "Expand event", onClick: (e) => {
399
+ e.stopPropagation();
400
+ toggle(event);
401
+ } }, open ? /* @__PURE__ */ import_react3.default.createElement(import_icons_material2.ExpandLess, { fontSize: "small" }) : /* @__PURE__ */ import_react3.default.createElement(import_icons_material2.ExpandMore, { fontSize: "small" })), /* @__PURE__ */ import_react3.default.createElement(import_material3.Typography, { variant: "caption", color: isMatch(event) ? "warning.main" : "text.secondary", sx: { fontFamily: "monospace" } }, new Date(event.ts).toISOString()), /* @__PURE__ */ import_react3.default.createElement(import_material3.Chip, { label: event.providerId, size: "small", variant: "outlined", sx: { fontSize: "0.65rem", height: 18 } }), /* @__PURE__ */ import_react3.default.createElement(import_material3.Typography, { variant: "caption", color: "text.secondary", noWrap: true }, summaryOf(event.event)), /* @__PURE__ */ import_react3.default.createElement(import_material3.Tooltip, { title: copied === event ? "Copied" : "Copy event JSON" }, /* @__PURE__ */ import_react3.default.createElement(import_material3.IconButton, { size: "small", "aria-label": "Copy event JSON", sx: { ml: "auto" }, onClick: (e) => {
402
+ e.stopPropagation();
403
+ copy(event);
404
+ } }, copied === event ? /* @__PURE__ */ import_react3.default.createElement(import_icons_material2.Check, { fontSize: "small", color: "success" }) : /* @__PURE__ */ import_react3.default.createElement(import_icons_material2.ContentCopy, { fontSize: "small" })))),
405
+ open && /* @__PURE__ */ import_react3.default.createElement(import_material3.Box, { sx: { px: 2, pb: 1 } }, /* @__PURE__ */ import_react3.default.createElement(JsonBlock, { value: event.event, highlight: search }))
406
+ );
407
+ };
318
408
  if (!data.started) {
319
409
  return /* @__PURE__ */ import_react3.default.createElement(import_material3.Box, { sx: { p: 2 } }, /* @__PURE__ */ import_react3.default.createElement(import_material3.Typography, { color: "text.secondary" }, "Provider Debug not started. Start the channel (tab settings \u2699 \u2192 Start) to subscribe to a provider and watch its raw events."));
320
410
  }
321
- return /* @__PURE__ */ import_react3.default.createElement(import_material3.Card, { sx: { flex: 1, width: "98%", alignSelf: "center", m: 1 } }, /* @__PURE__ */ import_react3.default.createElement(import_material3.CardHeader, { title: /* @__PURE__ */ import_react3.default.createElement(import_material3.Stack, { direction: "row", alignItems: "center", sx: { width: "100%" } }, /* @__PURE__ */ import_react3.default.createElement(import_material3.Typography, { mr: 4 }, /* @__PURE__ */ import_react3.default.createElement("b", null, "Provider:"), " ", instanceConfig.providerId || "(none)"), /* @__PURE__ */ import_react3.default.createElement(import_material3.Typography, { mr: 4 }, /* @__PURE__ */ import_react3.default.createElement("b", null, "Events:"), " ", data.events.length, " / ", config.maxEvents), /* @__PURE__ */ import_react3.default.createElement(import_material3.Typography, { mr: 4 }, /* @__PURE__ */ import_react3.default.createElement(import_icons_material2.Info, { fontSize: "small", sx: { mb: 0.25 } }), /* @__PURE__ */ import_react3.default.createElement("b", null, "\xA0Status:"), " ", data.paused ? "paused" : data.started ? "started" : "stopped"), /* @__PURE__ */ import_react3.default.createElement(import_material3.Tooltip, { title: "Clear captured events" }, /* @__PURE__ */ import_react3.default.createElement("span", { style: { marginLeft: "auto" } }, /* @__PURE__ */ import_react3.default.createElement(import_material3.IconButton, { size: "small", "aria-label": "Clear captured events", onClick: clear, disabled: data.events.length === 0 && data.signals.length === 0 }, /* @__PURE__ */ import_react3.default.createElement(import_icons_material2.DeleteSweep, { fontSize: "small" }))))) }), /* @__PURE__ */ import_react3.default.createElement(import_material3.CardContent, null, /* @__PURE__ */ import_react3.default.createElement(import_material3.Stack, { direction: "column", spacing: 1, sx: { mb: 1 } }, /* @__PURE__ */ import_react3.default.createElement(import_material3.Typography, { variant: "caption", color: "text.secondary" }, "Running providers"), formatProviders(), data.signals.map((s, index) => /* @__PURE__ */ import_react3.default.createElement(import_material3.Typography, { key: index, variant: "caption", color: "text.secondary" }, "*** ", s, " ***"))), /* @__PURE__ */ import_react3.default.createElement(import_material3.Box, { ref: boxRef, sx: { display: "flex", flexDirection: "column", overflowY: "auto", overflowX: "hidden", width: "100%", flexGrow: 1, height: `calc(100vh - ${boxTop}px - 35px)` } }, /* @__PURE__ */ import_react3.default.createElement(import_material3.Box, { sx: { flex: 1, overflowY: "auto", ml: 1, mr: 1 } }, data.events.map((e, index) => formatEvent(e, index))))));
411
+ const found = matches();
412
+ const current = matchPos >= 0 && matchPos < found.length ? found[matchPos] : void 0;
413
+ return /* @__PURE__ */ import_react3.default.createElement(import_material3.Card, { sx: { flex: 1, width: "98%", alignSelf: "center", m: 1 } }, /* @__PURE__ */ import_react3.default.createElement(import_material3.CardHeader, { title: /* @__PURE__ */ import_react3.default.createElement(import_material3.Stack, { direction: "row", alignItems: "center", sx: { width: "100%" } }, /* @__PURE__ */ import_react3.default.createElement(import_material3.Typography, { mr: 4 }, /* @__PURE__ */ import_react3.default.createElement("b", null, "Provider:"), " ", instanceConfig.providerId || "(none)"), /* @__PURE__ */ import_react3.default.createElement(import_material3.Typography, { mr: 4 }, /* @__PURE__ */ import_react3.default.createElement("b", null, "Events:"), " ", data.events.length, " / ", config.maxEvents), /* @__PURE__ */ import_react3.default.createElement(import_material3.Typography, { mr: 4 }, /* @__PURE__ */ import_react3.default.createElement(import_icons_material2.Info, { fontSize: "small", sx: { mb: 0.25 } }), /* @__PURE__ */ import_react3.default.createElement("b", null, "\xA0Status:"), " ", data.paused ? "paused" : data.started ? "started" : "stopped"), /* @__PURE__ */ import_react3.default.createElement(import_material3.Stack, { direction: "row", alignItems: "center", spacing: 0.5, sx: { ml: "auto" } }, /* @__PURE__ */ import_react3.default.createElement(import_material3.Typography, { variant: "caption", color: found.length === 0 && search.trim() !== "" ? "warning.main" : "text.secondary", sx: { minWidth: 44, textAlign: "right" } }, `${matchPos + 1}/${found.length}`), /* @__PURE__ */ import_react3.default.createElement(
414
+ import_material3.TextField,
415
+ {
416
+ value: search,
417
+ onChange: (e) => {
418
+ setSearch(e.target.value);
419
+ setMatchPos(-1);
420
+ },
421
+ onKeyDown: (e) => {
422
+ if (e.key !== "Enter") return;
423
+ e.preventDefault();
424
+ goToMatch(e.shiftKey ? matchPos - 1 : matchPos + 1);
425
+ },
426
+ placeholder: "Search events",
427
+ variant: "standard",
428
+ sx: { width: 200 },
429
+ slotProps: {
430
+ htmlInput: { "aria-label": "Search events" },
431
+ input: {
432
+ startAdornment: /* @__PURE__ */ import_react3.default.createElement(import_material3.InputAdornment, { position: "start" }, /* @__PURE__ */ import_react3.default.createElement(import_icons_material2.Search, { fontSize: "small" })),
433
+ // siempre presente y deshabilitado: si se renderiza en
434
+ // condicional desaparece bajo el propio click que lo pulsa
435
+ endAdornment: /* @__PURE__ */ import_react3.default.createElement(import_material3.InputAdornment, { position: "end" }, /* @__PURE__ */ import_react3.default.createElement(import_material3.IconButton, { size: "small", "aria-label": "Clear search", disabled: search === "", onClick: () => {
436
+ setSearch("");
437
+ setMatchPos(-1);
438
+ } }, /* @__PURE__ */ import_react3.default.createElement(import_icons_material2.Clear, { fontSize: "small" })))
439
+ }
440
+ }
441
+ }
442
+ ), /* @__PURE__ */ import_react3.default.createElement(import_material3.Tooltip, { title: "Previous match (Shift+Enter)" }, /* @__PURE__ */ import_react3.default.createElement("span", null, /* @__PURE__ */ import_react3.default.createElement(import_material3.IconButton, { size: "small", "aria-label": "Previous match", disabled: found.length === 0, onClick: () => goToMatch(matchPos - 1) }, /* @__PURE__ */ import_react3.default.createElement(import_icons_material2.ArrowUpward, { fontSize: "small" })))), /* @__PURE__ */ import_react3.default.createElement(import_material3.Tooltip, { title: "Next match (Enter)" }, /* @__PURE__ */ import_react3.default.createElement("span", null, /* @__PURE__ */ import_react3.default.createElement(import_material3.IconButton, { size: "small", "aria-label": "Next match", disabled: found.length === 0, onClick: () => goToMatch(matchPos + 1) }, /* @__PURE__ */ import_react3.default.createElement(import_icons_material2.ArrowDownward, { fontSize: "small" })))), /* @__PURE__ */ import_react3.default.createElement(import_material3.Tooltip, { title: "Clear captured events" }, /* @__PURE__ */ import_react3.default.createElement("span", null, /* @__PURE__ */ import_react3.default.createElement(import_material3.IconButton, { size: "small", "aria-label": "Clear captured events", onClick: clear, disabled: data.events.length === 0 && data.signals.length === 0 }, /* @__PURE__ */ import_react3.default.createElement(import_icons_material2.DeleteSweep, { fontSize: "small" })))))) }), /* @__PURE__ */ import_react3.default.createElement(import_material3.CardContent, null, /* @__PURE__ */ import_react3.default.createElement(import_material3.Stack, { direction: "column", spacing: 1, sx: { mb: 1 } }, /* @__PURE__ */ import_react3.default.createElement(import_material3.Stack, { direction: "row", spacing: 1, alignItems: "center", flexWrap: "wrap", useFlexGap: true }, /* @__PURE__ */ import_react3.default.createElement(import_material3.Typography, { variant: "caption", color: "text.secondary" }, "Running providers"), formatProviders(), /* @__PURE__ */ import_react3.default.createElement(import_material3.Stack, { direction: "row", spacing: 1, sx: { ml: "auto" } }, /* @__PURE__ */ import_react3.default.createElement(
443
+ import_material3.Chip,
444
+ {
445
+ label: "config",
446
+ size: "small",
447
+ color: data.configAccepted ? "success" : "default",
448
+ variant: data.configAccepted ? "filled" : "outlined"
449
+ }
450
+ ), /* @__PURE__ */ import_react3.default.createElement(
451
+ import_material3.Chip,
452
+ {
453
+ label: "subscribed",
454
+ size: "small",
455
+ color: data.subscribed ? "success" : "default",
456
+ variant: data.subscribed ? "filled" : "outlined"
457
+ }
458
+ ))), data.signals.map((s, index) => /* @__PURE__ */ import_react3.default.createElement(import_material3.Typography, { key: index, variant: "caption", color: "text.secondary" }, "*** ", s, " ***"))), /* @__PURE__ */ import_react3.default.createElement(import_material3.Box, { ref: boxRef, sx: { display: "flex", flexDirection: "column", overflowY: "auto", overflowX: "hidden", width: "100%", flexGrow: 1, height: `calc(100vh - ${boxTop}px - 35px)` } }, /* @__PURE__ */ import_react3.default.createElement(import_material3.Box, { sx: { flex: 1, overflowY: "auto", ml: 1, mr: 1 } }, data.events.map((e, index) => formatEvent(e, index, current))))));
322
459
  };
323
460
 
324
461
  // src/front/ProviderDebugChannel.ts
@@ -374,8 +511,15 @@
374
511
  return { action: import_kwirth_common_front.EChannelRefreshAction.REFRESH };
375
512
  case import_kwirth_common.EInstanceMessageType.SIGNAL: {
376
513
  const signalMessage = JSON.parse(wsEvent.data);
377
- if (signalMessage.flow === import_kwirth_common.EInstanceMessageFlow.RESPONSE && signalMessage.action === import_kwirth_common.EInstanceMessageAction.START) {
378
- channelObject.instanceId = signalMessage.instance;
514
+ const startResponse = signalMessage.flow === import_kwirth_common.EInstanceMessageFlow.RESPONSE && signalMessage.action === import_kwirth_common.EInstanceMessageAction.START;
515
+ if (startResponse) channelObject.instanceId = signalMessage.instance;
516
+ if (startResponse && signalMessage.level === void 0) {
517
+ data.configAccepted = true;
518
+ return { action: import_kwirth_common_front.EChannelRefreshAction.REFRESH };
519
+ }
520
+ if (startResponse && signalMessage.level === import_kwirth_common.ESignalMessageLevel.INFO) {
521
+ data.subscribed = true;
522
+ return { action: import_kwirth_common_front.EChannelRefreshAction.REFRESH };
379
523
  }
380
524
  if (signalMessage.text) data.signals.push(signalMessage.text);
381
525
  return { action: import_kwirth_common_front.EChannelRefreshAction.REFRESH };
@@ -394,6 +538,8 @@
394
538
  const data = channelObject.data;
395
539
  data.events = [];
396
540
  data.signals = [];
541
+ data.configAccepted = false;
542
+ data.subscribed = false;
397
543
  data.paused = false;
398
544
  data.started = true;
399
545
  return true;
@@ -410,6 +556,8 @@
410
556
  }
411
557
  stopChannel(channelObject) {
412
558
  const data = channelObject.data;
559
+ data.configAccepted = false;
560
+ data.subscribed = false;
413
561
  data.paused = false;
414
562
  data.started = false;
415
563
  return true;
package/package.json CHANGED
@@ -4,7 +4,7 @@
4
4
  "id": "provider-debug",
5
5
  "name": "@kwirthmagnify/kwirth-plugin-provider-debug",
6
6
  "displayName": "Provider Debug",
7
- "version": "0.1.0",
7
+ "version": "0.1.2",
8
8
  "description": "Provider debugging channel for Kwirth - subscribes to a running provider and streams its raw events",
9
9
  "icon": "DataObjectOutlined",
10
10
  "requiresRestart": false,