dsh-live-voice-debugger 0.5.0 → 0.5.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/ARCHITECTURE.md CHANGED
@@ -4,6 +4,6 @@ This public, optional client plugin builds separately from Live Voice. It contri
4
4
 
5
5
  The panel samples current state at a selectable 1, 2, 5, 10 or 20 Hz (default 10). State and event panes scroll independently. Event recording can be paused independently from live state sampling and the entire event history can be cleared. Resuming recording starts from the current baseline without replaying changes that occurred while paused. Changing the sampling rate preserves the history. While connected, coordinator notifications produce a bounded 200-entry state-difference history filterable by module. This is an initial inspector, not a complete semantic event logger: changes hidden inside an adapter can only be sampled, and native recognition internals remain unavailable. No audio is retained. Free-form text is hidden by default and can be inspected explicitly in memory, never persisted. Closing the panel releases subscriptions and timers.
6
6
 
7
- Build from the repository root with `pnpm build`, or build this package with `pnpm --filter dsh-live-voice-debugger build`. The generated client/server entries land in lib, not in the main client bundle. For local installation, add the packages/live-voice-debugger directory as a separate DSH plugin using the supported plugin manager; both the main plugin's diagnostic bridge and this plugin must be loaded. Then open Settings → Live Voice → Developer and open the separate inspector window (allow site popups if blocked). Publication is explicit through the npm workflow. Configure npm Trusted Publishing for this package with workflow publish.yml and environment npm. Select the debugger-only target when the aligned main version already exists. Publishing both packages is sequential, not atomic.
7
+ For normal use, install the prebuilt npm package with `npx dsh plugin add --profile web dsh-live-voice-debugger`. Generated `lib/` directories are ignored and never committed. For local development, build before linking: build from the repository root with `pnpm build`, or build this package with `pnpm --filter dsh-live-voice-debugger build`. The generated client/server entries land in lib, not in the main client bundle. For local installation, add the packages/live-voice-debugger directory as a separate DSH plugin using the supported plugin manager; both the main plugin's diagnostic bridge and this plugin must be loaded. Then open Settings → Live Voice → Developer and open the separate inspector window (allow site popups if blocked). Publication is explicit through the npm workflow. Configure npm Trusted Publishing for this package with workflow publish.yml and environment npm. Select the debugger-only target when the aligned main version already exists. Publishing both packages is sequential, not atomic.
8
8
 
9
9
  Tests deliver simulated activity, processing and final results through the real coordinator callback boundary; PCM chunks are supplied through the HTTP adapter's fake Web Audio input. They assert the same diagnostic projection that the panel reads. The panel itself never injects test events into live capture or playback.
package/lib/client.js CHANGED
@@ -34,11 +34,224 @@ __export(apply_exports, {
34
34
  inject: () => inject
35
35
  });
36
36
  module.exports = __toCommonJS(apply_exports);
37
+ var import_react22 = __toESM(require("react"), 1);
38
+
39
+ // ../live-voice/src/shared/design-system/buttons/IconButton.tsx
40
+ var import_react2 = __toESM(require("react"), 1);
41
+
42
+ // ../live-voice/src/shared/design-system/icons/Icon.tsx
43
+ var import_react = __toESM(require("react"), 1);
44
+
45
+ // ../live-voice/src/shared/design-system/icons/icons.ts
46
+ var iconPaths = {
47
+ conversation: "M4 3h16v13H8l-4 4V3M8 7h8M8 11h5",
48
+ keyboard: "M3 6h18v12H3V6M7 10h.01M11 10h.01M15 10h.01M18 10h.01M7 14h10",
49
+ headphones: "M3 14v-3a9 9 0 0 1 18 0v3M3 12h4v8H3v-8M17 12h4v8h-4v-8",
50
+ commands: "M3 6l2 2 3-4M11 6h10M3 14l2 2 3-4M11 14h10M11 20h10",
51
+ bug: "M8 8h8v9a4 4 0 0 1-8 0V8M9 8V6a3 3 0 0 1 6 0v2M3 9l5 2M16 11l5-2M3 16h5M16 16h5M5 22l3-3M16 19l3 3",
52
+ meeting: "M8 3a3 3 0 1 0 0 6 3 3 0 0 0 0-6M16 4a3 3 0 1 0 0 6 3 3 0 0 0 0-6M2 20v-3a6 6 0 0 1 12 0v3M16 13a5 5 0 0 1 6 5v2",
53
+ meetingOff: "M8 3a3 3 0 1 0 0 6 3 3 0 0 0 0-6M16 4a3 3 0 1 0 0 6 3 3 0 0 0 0-6M2 20v-3a6 6 0 0 1 12 0v3M17 16l5 5M22 16l-5 5",
54
+ mic: "M9 5a3 3 0 0 1 6 0v7a3 3 0 0 1-6 0V5M6 10v2a6 6 0 0 0 12 0v-2M12 18v4M8 22h8",
55
+ micOff: "M9 9v3a3 3 0 0 0 5.12 2.12M15 9V5a3 3 0 0 0-5.64-1.42M6 10v2a6 6 0 0 0 9.5 4.88M18 10v2a6 6 0 0 1-.5 2.4M12 18v4M8 22h8M3 3l18 18",
56
+ speaker: "M3 9h4l6-5v16l-6-5H3V9M17 8a6 6 0 0 1 0 8M20 5a10 10 0 0 1 0 14",
57
+ speakerOff: "M3 9h4l6-5v16l-6-5H3V9M17 9l5 6M22 9l-5 6",
58
+ pause: "M8 5v14M16 5v14",
59
+ play: "M7 4l13 8-13 8z",
60
+ stop: "M6 6h12v12H6z",
61
+ skipNext: "M5 5l10 7-10 7V5M19 5v14",
62
+ skipPrevious: "M19 5l-10 7 10 7V5M5 5v14",
63
+ send: "M3 11.5L21 3l-8.5 18-2-7.5L3 11.5zm7.5 2L21 3",
64
+ queue: "M5 6h14M5 12h10M5 18h6M18 15v6M15 18h6",
65
+ settings: "M4 7h16M4 17h16M8 4v6M16 14v6",
66
+ filter: "M3 5h18l-7 8v6l-4 2v-8L3 5z",
67
+ link: "M10 13a5 5 0 0 0 7.07 0l3-3a5 5 0 0 0-7.07-7.07l-1.7 1.7M14 11a5 5 0 0 0-7.07 0l-3 3a5 5 0 0 0 7.07 7.07l1.7-1.7",
68
+ chevron: "M6 9l6 6 6-6",
69
+ clock: "M12 3a9 9 0 1 0 0 18 9 9 0 0 0 0-18M12 7v5l3 2",
70
+ close: "M6 6l12 12M18 6 6 18"
71
+ };
72
+
73
+ // ../live-voice/src/shared/design-system/icons/Icon.tsx
74
+ function Icon({ name, className }) {
75
+ return /* @__PURE__ */ import_react.default.createElement(
76
+ "svg",
77
+ {
78
+ className,
79
+ viewBox: "0 0 24 24",
80
+ fill: "none",
81
+ stroke: "currentColor",
82
+ strokeWidth: 1.8,
83
+ strokeLinecap: "round",
84
+ strokeLinejoin: "round",
85
+ "aria-hidden": true
86
+ },
87
+ /* @__PURE__ */ import_react.default.createElement("path", { d: iconPaths[name] })
88
+ );
89
+ }
90
+
91
+ // ../live-voice/src/shared/design-system/buttons/PillButton.tsx
37
92
  var import_react3 = __toESM(require("react"), 1);
93
+
94
+ // ../live-voice/src/shared/design-system/buttons/ToggleButton.tsx
95
+ var import_react4 = __toESM(require("react"), 1);
96
+
97
+ // ../live-voice/src/shared/design-system/feedback/ErrorMessage.tsx
98
+ var import_react5 = __toESM(require("react"), 1);
99
+
100
+ // ../live-voice/src/shared/design-system/feedback/StatusBadge.tsx
101
+ var import_react6 = __toESM(require("react"), 1);
102
+
103
+ // ../live-voice/src/shared/design-system/feedback/StatusMessage.tsx
104
+ var import_react7 = __toESM(require("react"), 1);
105
+
106
+ // ../live-voice/src/shared/design-system/feedback/Hint.tsx
107
+ var import_react8 = __toESM(require("react"), 1);
108
+ function Hint({
109
+ label,
110
+ children,
111
+ id: suppliedId
112
+ }) {
113
+ const generatedId = import_react8.default.useId();
114
+ const id = suppliedId || generatedId;
115
+ const [open, setOpen] = import_react8.default.useState(false);
116
+ const trigger = import_react8.default.useRef(null);
117
+ const bubble = import_react8.default.useRef(null);
118
+ const hovered = import_react8.default.useRef(false);
119
+ const focused = import_react8.default.useRef(false);
120
+ const timer = import_react8.default.useRef(void 0);
121
+ const cancel = () => clearTimeout(timer.current);
122
+ const closeLater = () => {
123
+ cancel();
124
+ timer.current = setTimeout(() => {
125
+ if (!hovered.current && !focused.current) setOpen(false);
126
+ }, 120);
127
+ };
128
+ import_react8.default.useEffect(() => () => clearTimeout(timer.current), []);
129
+ import_react8.default.useLayoutEffect(() => {
130
+ const node = bubble.current;
131
+ if (!open || !node || !trigger.current) return;
132
+ node.showPopover?.();
133
+ const position = () => {
134
+ const anchor = trigger.current.getBoundingClientRect();
135
+ const rect = node.getBoundingClientRect();
136
+ node.style.left = Math.max(12, Math.min(anchor.left, window.innerWidth - rect.width - 12)) + "px";
137
+ const below = anchor.bottom + 8;
138
+ node.style.top = Math.max(
139
+ 12,
140
+ below + rect.height <= window.innerHeight - 12 ? below : anchor.top - rect.height - 8
141
+ ) + "px";
142
+ };
143
+ position();
144
+ const dismiss = (e) => {
145
+ if (e.key === "Escape") {
146
+ e.stopPropagation();
147
+ setOpen(false);
148
+ }
149
+ };
150
+ const outside = (e) => {
151
+ if (!node.contains(e.target) && !trigger.current?.contains(e.target))
152
+ setOpen(false);
153
+ };
154
+ document.addEventListener("keydown", dismiss, true);
155
+ document.addEventListener("pointerdown", outside, true);
156
+ window.addEventListener("resize", position);
157
+ window.addEventListener("scroll", position, true);
158
+ return () => {
159
+ node.hidePopover?.();
160
+ document.removeEventListener("keydown", dismiss, true);
161
+ document.removeEventListener("pointerdown", outside, true);
162
+ window.removeEventListener("resize", position);
163
+ window.removeEventListener("scroll", position, true);
164
+ };
165
+ }, [open]);
166
+ return /* @__PURE__ */ import_react8.default.createElement(
167
+ "span",
168
+ {
169
+ className: "dlv-hint",
170
+ onMouseEnter: () => {
171
+ hovered.current = true;
172
+ cancel();
173
+ setOpen(true);
174
+ },
175
+ onMouseLeave: () => {
176
+ hovered.current = false;
177
+ closeLater();
178
+ }
179
+ },
180
+ /* @__PURE__ */ import_react8.default.createElement(
181
+ "button",
182
+ {
183
+ ref: trigger,
184
+ type: "button",
185
+ className: "dlv-hint-trigger",
186
+ "aria-label": label,
187
+ "aria-describedby": open ? id : void 0,
188
+ "aria-expanded": open,
189
+ onFocus: () => {
190
+ focused.current = true;
191
+ cancel();
192
+ setOpen(true);
193
+ },
194
+ onBlur: () => {
195
+ focused.current = false;
196
+ closeLater();
197
+ },
198
+ onClick: () => setOpen(true)
199
+ },
200
+ "?"
201
+ ),
202
+ /* @__PURE__ */ import_react8.default.createElement(
203
+ "span",
204
+ {
205
+ ref: bubble,
206
+ id,
207
+ role: "tooltip",
208
+ popover: "manual",
209
+ hidden: !open,
210
+ className: "dlv-hint-bubble"
211
+ },
212
+ children
213
+ )
214
+ );
215
+ }
216
+
217
+ // ../live-voice/src/shared/design-system/forms/CheckboxField.tsx
218
+ var import_react9 = __toESM(require("react"), 1);
219
+
220
+ // ../live-voice/src/shared/design-system/forms/NumberField.tsx
221
+ var import_react11 = __toESM(require("react"), 1);
222
+
223
+ // ../live-voice/src/shared/design-system/forms/DraftField.tsx
224
+ var import_react10 = __toESM(require("react"), 1);
225
+
226
+ // ../live-voice/src/shared/design-system/forms/SelectField.tsx
227
+ var import_react12 = __toESM(require("react"), 1);
228
+
229
+ // ../live-voice/src/shared/design-system/forms/TextAreaField.tsx
230
+ var import_react13 = __toESM(require("react"), 1);
231
+
232
+ // ../live-voice/src/shared/design-system/forms/TextField.tsx
233
+ var import_react14 = __toESM(require("react"), 1);
234
+
235
+ // ../live-voice/src/shared/design-system/layout/SettingsCard.tsx
236
+ var import_react15 = __toESM(require("react"), 1);
237
+
238
+ // ../live-voice/src/shared/design-system/layout/SettingsSection.tsx
239
+ var import_react17 = __toESM(require("react"), 1);
240
+
241
+ // ../live-voice/src/shared/design-system/layout/SettingsSectionBody.tsx
242
+ var import_react16 = __toESM(require("react"), 1);
243
+
244
+ // ../live-voice/src/shared/design-system/layout/SettingsSubcard.tsx
245
+ var import_react18 = __toESM(require("react"), 1);
246
+
247
+ // ../live-voice/src/shared/design-system/layout/SettingsTabs.tsx
248
+ var import_react19 = __toESM(require("react"), 1);
249
+
250
+ // src/apply.tsx
38
251
  var import_client = require("react-dom/client");
39
252
 
40
253
  // src/DebuggerPanel.tsx
41
- var import_react2 = __toESM(require("react"), 1);
254
+ var import_react21 = __toESM(require("react"), 1);
42
255
 
43
256
  // ../live-voice/src/modules/core/diagnostics.ts
44
257
  var DIAGNOSTIC_KEY = /* @__PURE__ */ Symbol.for("dsh-live-voice.diagnostics.v1");
@@ -159,7 +372,7 @@ function createInspector(source, now = Date.now, limit = 200) {
159
372
  }
160
373
 
161
374
  // src/StateTree.tsx
162
- var import_react = __toESM(require("react"), 1);
375
+ var import_react20 = __toESM(require("react"), 1);
163
376
  function StateTree({
164
377
  name,
165
378
  value,
@@ -167,9 +380,9 @@ function StateTree({
167
380
  depth = 0
168
381
  }) {
169
382
  if (value === null || typeof value !== "object")
170
- return /* @__PURE__ */ import_react.default.createElement("div", { className: "dlvd-leaf" }, /* @__PURE__ */ import_react.default.createElement("code", null, name), /* @__PURE__ */ import_react.default.createElement("span", { "data-kind": typeof value }, String(value)));
383
+ return /* @__PURE__ */ import_react20.default.createElement("div", { className: "dlvd-leaf" }, /* @__PURE__ */ import_react20.default.createElement("code", null, name), /* @__PURE__ */ import_react20.default.createElement("span", { "data-kind": typeof value }, String(value)));
171
384
  const entries = Object.entries(value);
172
- return /* @__PURE__ */ import_react.default.createElement("details", { className: "dlvd-branch", open: depth < 3 }, /* @__PURE__ */ import_react.default.createElement("summary", null, /* @__PURE__ */ import_react.default.createElement("code", null, name), /* @__PURE__ */ import_react.default.createElement("small", null, Array.isArray(value) ? "[" + entries.length + "]" : "{" + entries.length + "}")), entries.slice(0, 100).map(([key, child]) => /* @__PURE__ */ import_react.default.createElement(StateTree, { key, name: key, value: child, omitted, depth: depth + 1 })), entries.length > 100 && /* @__PURE__ */ import_react.default.createElement("p", null, omitted));
385
+ return /* @__PURE__ */ import_react20.default.createElement("details", { className: "dlvd-branch", open: depth < 3 }, /* @__PURE__ */ import_react20.default.createElement("summary", null, /* @__PURE__ */ import_react20.default.createElement("code", null, name), /* @__PURE__ */ import_react20.default.createElement("small", null, Array.isArray(value) ? "[" + entries.length + "]" : "{" + entries.length + "}")), entries.slice(0, 100).map(([key, child]) => /* @__PURE__ */ import_react20.default.createElement(StateTree, { key, name: key, value: child, omitted, depth: depth + 1 })), entries.length > 100 && /* @__PURE__ */ import_react20.default.createElement("p", null, omitted));
173
386
  }
174
387
 
175
388
  // src/DebuggerPanel.tsx
@@ -178,17 +391,17 @@ function DebuggerPanel({
178
391
  onClose,
179
392
  target = window
180
393
  }) {
181
- const [frozen, setFrozen] = import_react2.default.useState(false);
182
- const [refreshHz, setRefreshHz] = import_react2.default.useState(10);
183
- const updateRef = import_react2.default.useRef(null);
184
- const [content, setContent] = import_react2.default.useState(false);
185
- const [module2, setModule] = import_react2.default.useState("");
186
- const [view, setView] = import_react2.default.useState(null);
187
- const [failed, setFailed] = import_react2.default.useState(false);
188
- const [eventsPaused, setEventsPaused] = import_react2.default.useState(false);
189
- const pausedRef = import_react2.default.useRef(false);
190
- const inspectorRef = import_react2.default.useRef(null);
191
- import_react2.default.useEffect(() => {
394
+ const [frozen, setFrozen] = import_react21.default.useState(false);
395
+ const [refreshHz, setRefreshHz] = import_react21.default.useState(10);
396
+ const updateRef = import_react21.default.useRef(null);
397
+ const [content, setContent] = import_react21.default.useState(false);
398
+ const [module2, setModule] = import_react21.default.useState("");
399
+ const [view, setView] = import_react21.default.useState(null);
400
+ const [failed, setFailed] = import_react21.default.useState(false);
401
+ const [eventsPaused, setEventsPaused] = import_react21.default.useState(false);
402
+ const pausedRef = import_react21.default.useRef(false);
403
+ const inspectorRef = import_react21.default.useRef(null);
404
+ import_react21.default.useEffect(() => {
192
405
  if (frozen) return;
193
406
  let inspector = null;
194
407
  let source = null;
@@ -221,13 +434,13 @@ function DebuggerPanel({
221
434
  inspectorRef.current = null;
222
435
  };
223
436
  }, [frozen, content, target]);
224
- import_react2.default.useEffect(() => {
437
+ import_react21.default.useEffect(() => {
225
438
  if (frozen) return;
226
439
  const timer = setInterval(() => updateRef.current?.(), 1e3 / refreshHz);
227
440
  return () => clearInterval(timer);
228
441
  }, [frozen, refreshHz]);
229
442
  const modules = [...new Set(view?.transitions.map((entry) => entry.module) ?? [])].sort();
230
- return /* @__PURE__ */ import_react2.default.createElement("aside", { className: "dlvd-panel", "aria-label": copy.title }, /* @__PURE__ */ import_react2.default.createElement("header", null, /* @__PURE__ */ import_react2.default.createElement("strong", null, copy.title), /* @__PURE__ */ import_react2.default.createElement("span", null, refreshHz, " Hz"), /* @__PURE__ */ import_react2.default.createElement("button", { type: "button", onClick: onClose, "aria-label": copy.close }, "\xD7")), /* @__PURE__ */ import_react2.default.createElement("p", null, copy.help), /* @__PURE__ */ import_react2.default.createElement("div", { className: "dlvd-toolbar" }, /* @__PURE__ */ import_react2.default.createElement("label", null, copy.refreshRate, /* @__PURE__ */ import_react2.default.createElement("select", { value: refreshHz, onChange: (event) => setRefreshHz(Number(event.target.value)) }, [1, 2, 5, 10, 20].map((hz) => /* @__PURE__ */ import_react2.default.createElement("option", { key: hz, value: hz }, hz, " Hz")))), /* @__PURE__ */ import_react2.default.createElement("button", { type: "button", onClick: () => setFrozen(!frozen) }, frozen ? copy.resume : copy.freeze), /* @__PURE__ */ import_react2.default.createElement("label", null, /* @__PURE__ */ import_react2.default.createElement(
443
+ return /* @__PURE__ */ import_react21.default.createElement("aside", { className: "dlvd-panel", "aria-label": copy.title }, /* @__PURE__ */ import_react21.default.createElement("header", null, /* @__PURE__ */ import_react21.default.createElement("strong", null, copy.title), /* @__PURE__ */ import_react21.default.createElement("span", null, refreshHz, " Hz"), /* @__PURE__ */ import_react21.default.createElement("button", { type: "button", onClick: onClose, "aria-label": copy.close }, "\xD7")), /* @__PURE__ */ import_react21.default.createElement("p", null, copy.help), /* @__PURE__ */ import_react21.default.createElement("div", { className: "dlvd-toolbar" }, /* @__PURE__ */ import_react21.default.createElement("label", null, copy.refreshRate, /* @__PURE__ */ import_react21.default.createElement("select", { value: refreshHz, onChange: (event) => setRefreshHz(Number(event.target.value)) }, [1, 2, 5, 10, 20].map((hz) => /* @__PURE__ */ import_react21.default.createElement("option", { key: hz, value: hz }, hz, " Hz")))), /* @__PURE__ */ import_react21.default.createElement("button", { type: "button", onClick: () => setFrozen(!frozen) }, frozen ? copy.resume : copy.freeze), /* @__PURE__ */ import_react21.default.createElement("label", null, /* @__PURE__ */ import_react21.default.createElement(
231
444
  "input",
232
445
  {
233
446
  type: "checkbox",
@@ -238,7 +451,7 @@ function DebuggerPanel({
238
451
  setContent(event.target.checked);
239
452
  }
240
453
  }
241
- ), copy.content)), failed ? /* @__PURE__ */ import_react2.default.createElement("p", { role: "alert" }, copy.error) : !view ? /* @__PURE__ */ import_react2.default.createElement("p", { role: "status" }, copy.waiting) : /* @__PURE__ */ import_react2.default.createElement("div", { className: "dlvd-columns" }, /* @__PURE__ */ import_react2.default.createElement("section", { className: "dlvd-state-pane", "aria-label": copy.states }, /* @__PURE__ */ import_react2.default.createElement("h3", null, copy.states), /* @__PURE__ */ import_react2.default.createElement("div", { className: "dlvd-scroll", tabIndex: 0 }, /* @__PURE__ */ import_react2.default.createElement(StateTree, { name: "context", value: view.state, omitted: copy.omitted }))), /* @__PURE__ */ import_react2.default.createElement("section", { className: "dlvd-event-pane", "aria-label": copy.transitions }, /* @__PURE__ */ import_react2.default.createElement("h3", null, copy.transitions), /* @__PURE__ */ import_react2.default.createElement("div", { className: "dlvd-toolbar" }, /* @__PURE__ */ import_react2.default.createElement(
454
+ ), copy.content)), failed ? /* @__PURE__ */ import_react21.default.createElement("p", { role: "alert" }, copy.error) : !view ? /* @__PURE__ */ import_react21.default.createElement("p", { role: "status" }, copy.waiting) : /* @__PURE__ */ import_react21.default.createElement("div", { className: "dlvd-columns" }, /* @__PURE__ */ import_react21.default.createElement("section", { className: "dlvd-state-pane", "aria-label": copy.states }, /* @__PURE__ */ import_react21.default.createElement("h3", null, copy.states), /* @__PURE__ */ import_react21.default.createElement("div", { className: "dlvd-scroll", tabIndex: 0 }, /* @__PURE__ */ import_react21.default.createElement(StateTree, { name: "context", value: view.state, omitted: copy.omitted }))), /* @__PURE__ */ import_react21.default.createElement("section", { className: "dlvd-event-pane", "aria-label": copy.transitions }, /* @__PURE__ */ import_react21.default.createElement("h3", null, copy.transitions), /* @__PURE__ */ import_react21.default.createElement("div", { className: "dlvd-toolbar" }, /* @__PURE__ */ import_react21.default.createElement(
242
455
  "button",
243
456
  {
244
457
  type: "button",
@@ -251,7 +464,7 @@ function DebuggerPanel({
251
464
  }
252
465
  },
253
466
  eventsPaused ? copy.eventsResume : copy.eventsPause
254
- ), /* @__PURE__ */ import_react2.default.createElement(
467
+ ), /* @__PURE__ */ import_react21.default.createElement(
255
468
  "button",
256
469
  {
257
470
  type: "button",
@@ -261,7 +474,7 @@ function DebuggerPanel({
261
474
  }
262
475
  },
263
476
  copy.eventsClear
264
- )), /* @__PURE__ */ import_react2.default.createElement("label", null, copy.filter, /* @__PURE__ */ import_react2.default.createElement("select", { value: module2, onChange: (event) => setModule(event.target.value) }, /* @__PURE__ */ import_react2.default.createElement("option", { value: "" }, copy.all), modules.map((name) => /* @__PURE__ */ import_react2.default.createElement("option", { key: name }, name)))), /* @__PURE__ */ import_react2.default.createElement("div", { className: "dlvd-history dlvd-scroll", tabIndex: 0 }, view.transitions.filter((entry) => !module2 || entry.module === module2).slice().reverse().map((entry) => /* @__PURE__ */ import_react2.default.createElement("details", { key: entry.sequence, "data-level": entry.level }, /* @__PURE__ */ import_react2.default.createElement("summary", null, /* @__PURE__ */ import_react2.default.createElement("small", null, new Date(entry.timeMs).toLocaleTimeString()), " ", /* @__PURE__ */ import_react2.default.createElement("code", null, entry.sessionId, " / ", entry.module)), /* @__PURE__ */ import_react2.default.createElement(StateTree, { name: "before", value: entry.before, omitted: copy.omitted }), /* @__PURE__ */ import_react2.default.createElement(StateTree, { name: "after", value: entry.after, omitted: copy.omitted }))), !view.transitions.length && /* @__PURE__ */ import_react2.default.createElement("p", null, copy.empty)))));
477
+ )), /* @__PURE__ */ import_react21.default.createElement("label", null, copy.filter, /* @__PURE__ */ import_react21.default.createElement("select", { value: module2, onChange: (event) => setModule(event.target.value) }, /* @__PURE__ */ import_react21.default.createElement("option", { value: "" }, copy.all), modules.map((name) => /* @__PURE__ */ import_react21.default.createElement("option", { key: name }, name)))), /* @__PURE__ */ import_react21.default.createElement("div", { className: "dlvd-history dlvd-scroll", tabIndex: 0 }, view.transitions.filter((entry) => !module2 || entry.module === module2).slice().reverse().map((entry) => /* @__PURE__ */ import_react21.default.createElement("details", { key: entry.sequence, "data-level": entry.level }, /* @__PURE__ */ import_react21.default.createElement("summary", null, /* @__PURE__ */ import_react21.default.createElement("small", null, new Date(entry.timeMs).toLocaleTimeString()), " ", /* @__PURE__ */ import_react21.default.createElement("code", null, entry.sessionId, " / ", entry.module)), /* @__PURE__ */ import_react21.default.createElement(StateTree, { name: "before", value: entry.before, omitted: copy.omitted }), /* @__PURE__ */ import_react21.default.createElement(StateTree, { name: "after", value: entry.after, omitted: copy.omitted }))), !view.transitions.length && /* @__PURE__ */ import_react21.default.createElement("p", null, copy.empty)))));
265
478
  }
266
479
 
267
480
  // src/locales.ts
@@ -273,6 +486,7 @@ var dictionaries = {
273
486
  close: "Close debugger",
274
487
  content: "Inspect text content (sensitive)",
275
488
  developer: "Developer",
489
+ diagnostics: "Diagnostics",
276
490
  empty: "No transitions recorded yet.",
277
491
  error: "Diagnostic source failed.",
278
492
  eventsClear: "Clear events",
@@ -296,6 +510,7 @@ var dictionaries = {
296
510
  close: "Fechar debugger",
297
511
  content: "Inspecionar conte\xFAdo de texto (sens\xEDvel)",
298
512
  developer: "Desenvolvedor",
513
+ diagnostics: "Diagn\xF3stico",
299
514
  empty: "Nenhuma transi\xE7\xE3o registrada ainda.",
300
515
  error: "A fonte de diagn\xF3stico falhou.",
301
516
  eventsClear: "Limpar eventos",
@@ -319,6 +534,7 @@ var dictionaries = {
319
534
  close: "Cerrar depurador",
320
535
  content: "Inspeccionar contenido de texto (sensible)",
321
536
  developer: "Desarrollador",
537
+ diagnostics: "Diagn\xF3stico",
322
538
  empty: "Todav\xEDa no hay transiciones registradas.",
323
539
  error: "La fuente de diagn\xF3stico fall\xF3.",
324
540
  eventsClear: "Borrar eventos",
@@ -342,6 +558,7 @@ var dictionaries = {
342
558
  close: "Fermer le d\xE9bogueur",
343
559
  content: "Inspecter le texte (sensible)",
344
560
  developer: "D\xE9veloppeur",
561
+ diagnostics: "Diagnostic",
345
562
  empty: "Aucune transition enregistr\xE9e.",
346
563
  error: "La source de diagnostic a \xE9chou\xE9.",
347
564
  eventsClear: "Effacer les \xE9v\xE9nements",
@@ -365,6 +582,7 @@ var dictionaries = {
365
582
  close: "\u0921\u0940\u092C\u0917\u0930 \u092C\u0902\u0926 \u0915\u0930\u0947\u0902",
366
583
  content: "\u091F\u0947\u0915\u094D\u0938\u094D\u091F \u0938\u093E\u092E\u0917\u094D\u0930\u0940 \u0926\u0947\u0916\u0947\u0902 (\u0938\u0902\u0935\u0947\u0926\u0928\u0936\u0940\u0932)",
367
584
  developer: "\u0921\u0947\u0935\u0932\u092A\u0930",
585
+ diagnostics: "\u0928\u093F\u0926\u093E\u0928",
368
586
  empty: "\u0905\u092D\u0940 \u0915\u094B\u0908 \u091F\u094D\u0930\u093E\u0902\u091C\u093C\u093F\u0936\u0928 \u0926\u0930\u094D\u091C \u0928\u0939\u0940\u0902 \u0939\u0948\u0964",
369
587
  error: "\u0921\u093E\u092F\u0917\u094D\u0928\u094B\u0938\u094D\u091F\u093F\u0915 \u0938\u094D\u0930\u094B\u0924 \u0935\u093F\u092B\u0932 \u0939\u0941\u0906\u0964",
370
588
  eventsClear: "\u0907\u0935\u0947\u0902\u091F \u0938\u093E\u092B\u093C \u0915\u0930\u0947\u0902",
@@ -388,6 +606,7 @@ var dictionaries = {
388
606
  close: "\u5173\u95ED\u8C03\u8BD5\u5668",
389
607
  content: "\u67E5\u770B\u6587\u672C\u5185\u5BB9\uFF08\u654F\u611F\uFF09",
390
608
  developer: "\u5F00\u53D1\u8005",
609
+ diagnostics: "\u8BCA\u65AD",
391
610
  empty: "\u5C1A\u672A\u8BB0\u5F55\u72B6\u6001\u8F6C\u6362\u3002",
392
611
  error: "\u8BCA\u65AD\u6570\u636E\u6E90\u5931\u8D25\u3002",
393
612
  eventsClear: "\u6E05\u9664\u4E8B\u4EF6",
@@ -409,13 +628,26 @@ var dictionaries = {
409
628
 
410
629
  // src/styles.ts
411
630
  var styles = `
412
- .dlvd-columns{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1fr);gap:16px;flex:1;min-height:0;overflow:hidden}.dlvd-state-pane,.dlvd-event-pane{display:flex;flex-direction:column;min-width:0;min-height:0;overflow:hidden}.dlvd-event-pane{border-left:1px solid #344154;padding-left:16px}.dlvd-columns h3{margin:0 0 10px}.dlvd-scroll{flex:1;min-height:0;overflow:auto;overscroll-behavior:contain;scrollbar-gutter:stable;padding-right:8px}.dlvd-scroll:focus-visible{outline:2px solid #8db9ff;outline-offset:-2px}.dlvd-history summary{overflow-wrap:anywhere}.dlvd-panel>header,.dlvd-panel>p,.dlvd-panel>.dlvd-toolbar{flex-shrink:0}
631
+ .dlvd-columns{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1fr);gap:16px;flex:1;min-height:0;overflow:hidden}.dlvd-state-pane,.dlvd-event-pane{display:flex;flex-direction:column;min-width:0;min-height:0;overflow:hidden}.dlvd-event-pane{border-left:1px solid var(--dsw-alias-border-l1, #ffffff0f);padding-left:16px}.dlvd-columns h3{margin:0 0 10px}.dlvd-scroll{flex:1;min-height:0;overflow:auto;overscroll-behavior:contain;scrollbar-gutter:stable;padding-right:8px}.dlvd-scroll:focus-visible{outline:2px solid var(--dsw-alias-state-business-primary, #7aaaff);outline-offset:-2px}.dlvd-history summary{overflow-wrap:anywhere}.dlvd-panel>header,.dlvd-panel>p,.dlvd-panel>.dlvd-toolbar{flex-shrink:0}
413
632
 
414
- .dlvd-window{margin:0;background:#101722;color:#e6edf5;color-scheme:dark}.dlvd-window .dlvd-panel{position:static;width:100%;height:100dvh;max-height:none;min-width:0;resize:none;border:0;border-radius:0;box-shadow:none}
415
- .dlvd-panel{position:fixed;right:16px;top:16px;width:min(520px,calc(100vw - 32px));height:80vh;max-height:80vh;overflow:hidden;display:flex;flex-direction:column;z-index:1000;padding:16px;border:1px solid #526177;border-radius:14px;background:#101722;color:#e6edf5;box-shadow:0 12px 40px #0008;font:13px/1.6 system-ui;resize:both;min-width:280px;box-sizing:border-box;color-scheme:dark}
416
- .dlvd-panel header{display:flex;align-items:center;gap:12px;position:sticky;top:-16px;background:#101722;padding:8px 0;z-index:1}.dlvd-panel header strong{flex:1}.dlvd-panel button,.dlvd-panel select{background:#243247;color:#e6edf5;border:1px solid #526177;border-radius:6px;padding:5px 9px;cursor:pointer}.dlvd-panel button:focus-visible,.dlvd-panel summary:focus-visible{outline:2px solid #8db9ff}.dlvd-toolbar{display:flex;gap:12px;align-items:center;flex-wrap:wrap;margin-bottom:12px}.dlvd-panel p{color:#aebed1}.dlvd-branch{margin-left:10px;border-left:1px solid #344154;padding-left:9px}.dlvd-branch summary{cursor:pointer;padding:3px 0}.dlvd-panel small{color:#aebed1;margin-left:8px}.dlvd-leaf{display:flex;gap:12px;justify-content:space-between;padding:2px 0;overflow-wrap:anywhere}.dlvd-leaf code{color:#b4c9e4}.dlvd-leaf span{white-space:pre-wrap;text-align:right;max-width:65%}.dlvd-leaf [data-kind=boolean]{color:#c8a5ff}.dlvd-leaf [data-kind=number]{color:#7cdbb6}.dlvd-history{margin-top:12px}.dlvd-history>details{border-top:1px solid #344154;padding:6px 0}.dlvd-history [data-level=error]{border-left:3px solid #ff8a8a;padding-left:8px}
633
+ .dlvd-window{margin:0;background:var(--dsw-alias-bg-base, #151517);color:var(--dsw-alias-label-primary, #f9fafb);color-scheme:var(--dlvd-color-scheme, dark)}.dlvd-window .dlvd-panel{position:static;width:100%;height:100dvh;max-height:none;min-width:0;resize:none;border:0;border-radius:0;box-shadow:none}
634
+ .dlvd-panel{position:fixed;right:16px;top:16px;width:min(520px,calc(100vw - 32px));height:80vh;max-height:80vh;overflow:hidden;display:flex;flex-direction:column;z-index:1000;padding:16px;border:1px solid var(--dsw-alias-border-l2, #ffffff1f);border-radius:14px;background:var(--dsw-alias-bg-base, #151517);color:var(--dsw-alias-label-primary, #f9fafb);box-shadow:0 12px 40px #0008;font:13px/1.6 system-ui;resize:both;min-width:280px;box-sizing:border-box;color-scheme:var(--dlvd-color-scheme, dark)}
635
+ .dlvd-panel header{display:flex;align-items:center;gap:12px;position:sticky;top:-16px;background:var(--dsw-alias-bg-base, #151517);padding:8px 0;z-index:1}.dlvd-panel header strong{flex:1}.dlvd-panel button,.dlvd-panel select{background:var(--dsw-alias-bg-layer-1, #232324);color:var(--dsw-alias-label-primary, #f9fafb);border:1px solid var(--dsw-alias-border-l2, #ffffff1f);border-radius:6px;padding:5px 9px;cursor:pointer}.dlvd-panel button:focus-visible,.dlvd-panel summary:focus-visible{outline:2px solid var(--dsw-alias-state-business-primary, #7aaaff)}.dlvd-toolbar{display:flex;gap:12px;align-items:center;flex-wrap:wrap;margin-bottom:12px}.dlvd-panel p{color:var(--dsw-alias-label-tertiary, #adb2b8)}.dlvd-branch{margin-left:10px;border-left:1px solid var(--dsw-alias-border-l1, #ffffff0f);padding-left:9px}.dlvd-branch summary{cursor:pointer;padding:3px 0}.dlvd-panel small{color:var(--dsw-alias-label-tertiary, #adb2b8);margin-left:8px}.dlvd-leaf{display:flex;gap:12px;justify-content:space-between;padding:2px 0;overflow-wrap:anywhere}.dlvd-leaf code{color:var(--dsw-alias-label-secondary, #cfd3d6)}.dlvd-leaf span{white-space:pre-wrap;text-align:right;max-width:65%}.dlvd-leaf [data-kind=boolean]{color:var(--dsw-alias-label-primary, #f9fafb)}.dlvd-leaf [data-kind=number]{color:var(--dsw-alias-label-primary, #f9fafb)}.dlvd-history{margin-top:12px}.dlvd-history>details{border-top:1px solid var(--dsw-alias-border-l1, #ffffff0f);padding:6px 0}.dlvd-history [data-level=error]{border-left:3px solid var(--dsw-alias-state-error-primary, #f25a5a);padding-left:8px}
636
+ .dlvd-panel button,.dlvd-panel select{font:inherit}.dlvd-panel button:hover{background:var(--dsw-alias-interactive-bg-hover, #ffffff14)}.dlvd-panel select:focus-visible,.dlvd-panel input:focus-visible{outline:2px solid var(--dsw-alias-state-business-primary, #7aaaff);outline-offset:2px}.dlvd-panel input{accent-color:var(--dsw-alias-state-business-primary, #7aaaff)}.dlvd-scroll{scrollbar-color:var(--dsw-alias-scrollbar-bg-l1, #3c3c3d) transparent}.dlvd-panel [data-kind=boolean],.dlvd-panel [data-kind=number]{font-variant-numeric:tabular-nums}
417
637
  `;
418
638
 
639
+ // src/theme.ts
640
+ function syncDebuggerTheme(source, destination) {
641
+ const theme = source.getComputedStyle(source.document.body);
642
+ const target = destination.documentElement.style;
643
+ for (const name of Array.from(theme)) {
644
+ if (name.startsWith("--dsw-alias-")) target.setProperty(name, theme.getPropertyValue(name));
645
+ }
646
+ const scheme = theme.colorScheme;
647
+ target.setProperty("--dlvd-color-scheme", scheme && scheme !== "normal" ? scheme : "dark");
648
+ destination.body.style.fontFamily = theme.fontFamily || "system-ui";
649
+ }
650
+
419
651
  // ../live-voice/src/modules/core/developerExtension.ts
420
652
  var DEVELOPER_KEY = /* @__PURE__ */ Symbol.for("dsh-live-voice.developer.v1");
421
653
  var DEVELOPER_CHANGED = "dsh-live-voice:developer-changed";
@@ -468,12 +700,12 @@ function apply(ctx) {
468
700
  notify();
469
701
  };
470
702
  function Host() {
471
- import_react3.default.useSyncExternalStore(localeSubscribe, localeSnapshot);
703
+ import_react22.default.useSyncExternalStore(localeSubscribe, localeSnapshot);
472
704
  const labels = copy();
473
- import_react3.default.useEffect(() => {
705
+ import_react22.default.useEffect(() => {
474
706
  if (popup && !popup.closed) popup.document.title = labels.title;
475
707
  }, [labels.title]);
476
- return /* @__PURE__ */ import_react3.default.createElement(DebuggerPanel, { copy: labels, target: window, onClose: () => queueMicrotask(close) });
708
+ return /* @__PURE__ */ import_react22.default.createElement(DebuggerPanel, { copy: labels, target: window, onClose: () => queueMicrotask(close) });
477
709
  }
478
710
  const open = () => {
479
711
  if (popup && !popup.closed) {
@@ -499,6 +731,7 @@ function apply(ctx) {
499
731
  doc.title = copy().title;
500
732
  doc.body.replaceChildren();
501
733
  doc.body.className = "dlvd-window";
734
+ syncDebuggerTheme(window, doc);
502
735
  const style = doc.createElement("style");
503
736
  style.textContent = styles;
504
737
  doc.head.appendChild(style);
@@ -506,10 +739,11 @@ function apply(ctx) {
506
739
  container.dataset.plugin = namespace;
507
740
  doc.body.appendChild(container);
508
741
  root = (0, import_client.createRoot)(container);
509
- root.render(/* @__PURE__ */ import_react3.default.createElement(Host, null));
742
+ root.render(/* @__PURE__ */ import_react22.default.createElement(Host, null));
510
743
  enabled = true;
511
744
  closedTimer = setInterval(() => {
512
745
  if (popup?.closed) close();
746
+ else if (popup) syncDebuggerTheme(window, popup.document);
513
747
  }, 250);
514
748
  notify();
515
749
  } catch {
@@ -520,18 +754,10 @@ function apply(ctx) {
520
754
  }
521
755
  };
522
756
  function Settings() {
523
- const active = import_react3.default.useSyncExternalStore(subscribe, () => enabled);
524
- const failed = import_react3.default.useSyncExternalStore(subscribe, () => blocked);
525
- import_react3.default.useSyncExternalStore(localeSubscribe, localeSnapshot);
757
+ const failed = import_react22.default.useSyncExternalStore(subscribe, () => blocked);
758
+ import_react22.default.useSyncExternalStore(localeSubscribe, localeSnapshot);
526
759
  const labels = copy();
527
- return /* @__PURE__ */ import_react3.default.createElement("section", null, /* @__PURE__ */ import_react3.default.createElement("h2", null, labels.title), /* @__PURE__ */ import_react3.default.createElement("p", null, labels.help), /* @__PURE__ */ import_react3.default.createElement("label", null, /* @__PURE__ */ import_react3.default.createElement(
528
- "input",
529
- {
530
- type: "checkbox",
531
- checked: active,
532
- onChange: (event) => event.target.checked ? open() : close()
533
- }
534
- ), labels.activate), failed && /* @__PURE__ */ import_react3.default.createElement("p", { role: "alert" }, labels.popupBlocked));
760
+ return /* @__PURE__ */ import_react22.default.createElement("div", { className: "dlv-diagnostics-launcher" }, /* @__PURE__ */ import_react22.default.createElement("button", { type: "button", className: "dlv-diagnostics-button", onClick: open }, /* @__PURE__ */ import_react22.default.createElement(Icon, { name: "bug" }), labels.diagnostics), /* @__PURE__ */ import_react22.default.createElement(Hint, { label: labels.diagnostics }, labels.activate), failed && /* @__PURE__ */ import_react22.default.createElement("p", { role: "alert" }, labels.popupBlocked));
535
761
  }
536
762
  ctx.effect(
537
763
  () => publishDeveloperExtension(window, {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dsh-live-voice-debugger",
3
- "version": "0.5.0",
3
+ "version": "0.5.1",
4
4
  "type": "module",
5
5
  "description": "Optional read-only state inspector for DSH Live Voice.",
6
6
  "license": "Apache-2.0",
@@ -39,7 +39,7 @@
39
39
  },
40
40
  "repository": {
41
41
  "type": "git",
42
- "url": "git+https://github.com/victorwads/dsh-live-voice.git",
42
+ "url": "git+https://github.com/wads-dev/dsh-live-voice.git",
43
43
  "directory": "packages/live-voice-debugger"
44
44
  }
45
45
  }