@myscheme/voice-navigation-sdk 0.1.6 → 0.1.8

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,332 @@
1
+ import * as sdk from "microsoft-cognitiveservices-speech-sdk";
2
+ export class VoiceFeedbackService {
3
+ constructor(config) {
4
+ this.synthesizer = null;
5
+ this.isSpeaking = false;
6
+ this.enabled = config.enabled ?? true;
7
+ this.language = config.language || "en-IN";
8
+ this.azureSpeechService = config.azureSpeechService;
9
+ this.bedrockService = config.bedrockService;
10
+ console.log("[VoiceFeedback] Service initialized - enabled:", this.enabled, "language:", this.language);
11
+ }
12
+ setEnabled(enabled) {
13
+ this.enabled = enabled;
14
+ console.log("[VoiceFeedback] Voice feedback", enabled ? "enabled" : "disabled");
15
+ if (!enabled && this.isSpeaking) {
16
+ this.stopSpeaking();
17
+ }
18
+ }
19
+ isEnabled() {
20
+ return this.enabled;
21
+ }
22
+ setLanguage(language) {
23
+ this.language = language;
24
+ console.log("[VoiceFeedback] Language changed to:", language);
25
+ }
26
+ async initializeSynthesizer() {
27
+ if (this.synthesizer) {
28
+ console.log("[VoiceFeedback] Synthesizer already initialized");
29
+ return;
30
+ }
31
+ console.log("[VoiceFeedback] Initializing synthesizer...");
32
+ try {
33
+ const tokenResponse = await this.azureSpeechService.fetchToken();
34
+ const speechConfig = sdk.SpeechConfig.fromAuthorizationToken(tokenResponse.token, tokenResponse.region);
35
+ const voiceName = this.getVoiceForLanguage(this.language);
36
+ speechConfig.speechSynthesisVoiceName = voiceName;
37
+ const audioConfig = sdk.AudioConfig.fromDefaultSpeakerOutput();
38
+ this.synthesizer = new sdk.SpeechSynthesizer(speechConfig, audioConfig);
39
+ console.log("[VoiceFeedback] Synthesizer initialized with voice:", voiceName);
40
+ }
41
+ catch (error) {
42
+ console.error("[VoiceFeedback] Failed to initialize synthesizer:", error);
43
+ throw error;
44
+ }
45
+ }
46
+ getVoiceForLanguage(language) {
47
+ const voiceMap = {
48
+ "en-IN": "en-IN-NeerjaNeural",
49
+ "en-US": "en-US-AriaNeural",
50
+ "en-GB": "en-GB-SoniaNeural",
51
+ "hi-IN": "hi-IN-SwaraNeural",
52
+ "ta-IN": "ta-IN-PallaviNeural",
53
+ "te-IN": "te-IN-ShrutiNeural",
54
+ "bn-IN": "bn-IN-TanishaaNeural",
55
+ "mr-IN": "mr-IN-AarohiNeural",
56
+ "gu-IN": "gu-IN-DhwaniNeural",
57
+ "kn-IN": "kn-IN-SapnaNeural",
58
+ "ml-IN": "ml-IN-SobhanaNeural",
59
+ "pa-IN": "pa-IN-SwaraNeural",
60
+ };
61
+ return voiceMap[language] || voiceMap["en-IN"];
62
+ }
63
+ async generateFeedbackMessage(context) {
64
+ const { action, actionResult, transcript, elementInfo } = context;
65
+ const prompt = this.buildPromptForAction(action, actionResult, transcript, elementInfo);
66
+ console.log("[VoiceFeedback] Requesting AI message generation...");
67
+ try {
68
+ const response = await this.bedrockService.generateFeedbackMessage(prompt, this.language);
69
+ console.log("[VoiceFeedback] AI generated message:", response);
70
+ return response;
71
+ }
72
+ catch (error) {
73
+ console.error("[VoiceFeedback] Failed to generate AI message:", error);
74
+ const fallback = this.getFallbackMessage(action, actionResult, elementInfo);
75
+ console.log("[VoiceFeedback] Using fallback message:", fallback);
76
+ return fallback;
77
+ }
78
+ }
79
+ buildPromptForAction(action, actionResult, transcript, elementInfo) {
80
+ let prompt = `Generate a brief, natural spoken feedback message (max 10 words) for this voice navigation action:\n\n`;
81
+ prompt += `Action: ${action}\n`;
82
+ if (transcript) {
83
+ prompt += `User said: "${transcript}"\n`;
84
+ }
85
+ if (elementInfo) {
86
+ if (elementInfo.label) {
87
+ prompt += `Element description: ${elementInfo.label}\n`;
88
+ }
89
+ else if (elementInfo.text) {
90
+ prompt += `Element text: ${elementInfo.text}\n`;
91
+ }
92
+ if (elementInfo.type)
93
+ prompt += `Input type: ${elementInfo.type}\n`;
94
+ if (!elementInfo.label && !elementInfo.text && elementInfo.tag) {
95
+ prompt += `Element type: ${elementInfo.tag}\n`;
96
+ }
97
+ }
98
+ if (actionResult) {
99
+ if (actionResult.info?.pageName) {
100
+ prompt += `Navigating to: ${actionResult.info.pageName}\n`;
101
+ }
102
+ if (actionResult.info?.direction) {
103
+ prompt += `Direction: ${actionResult.info.direction}\n`;
104
+ }
105
+ }
106
+ prompt += `\nGenerate a concise, conversational confirmation message. Be specific about what happened.`;
107
+ return prompt;
108
+ }
109
+ getFallbackMessage(action, actionResult, elementInfo) {
110
+ if (action.startsWith("navigate_") && actionResult?.info?.pageName) {
111
+ return `Navigating to ${actionResult.info.pageName}`;
112
+ }
113
+ if ((action === "focus_next" ||
114
+ action === "tab_next" ||
115
+ action === "focus_previous" ||
116
+ action === "tab_back") &&
117
+ actionResult?.info?.elementTag) {
118
+ if (elementInfo?.label) {
119
+ return elementInfo.label;
120
+ }
121
+ return `${actionResult.info.elementTag}`;
122
+ }
123
+ const actionLabel = action.replace(/_/g, " ");
124
+ return actionLabel;
125
+ }
126
+ async speak(message) {
127
+ if (!this.enabled || !message) {
128
+ console.log("[VoiceFeedback] Skipping speak - enabled:", this.enabled, "message:", !!message);
129
+ return;
130
+ }
131
+ console.log("[VoiceFeedback] Attempting to speak:", message);
132
+ try {
133
+ await this.initializeSynthesizer();
134
+ if (!this.synthesizer) {
135
+ console.warn("[VoiceFeedback] Synthesizer not available after initialization");
136
+ return;
137
+ }
138
+ if (this.isSpeaking) {
139
+ console.log("[VoiceFeedback] Canceling current speech to avoid stacking...");
140
+ this.stopSpeaking();
141
+ await new Promise((resolve) => setTimeout(resolve, 100));
142
+ }
143
+ this.isSpeaking = true;
144
+ console.log("[VoiceFeedback] Starting speech synthesis...");
145
+ return new Promise((resolve, reject) => {
146
+ if (!this.synthesizer) {
147
+ reject(new Error("Synthesizer not initialized"));
148
+ return;
149
+ }
150
+ this.synthesizer.speakTextAsync(message, (result) => {
151
+ this.isSpeaking = false;
152
+ if (result.reason === sdk.ResultReason.SynthesizingAudioCompleted) {
153
+ console.log("[VoiceFeedback] Speech completed successfully");
154
+ resolve();
155
+ }
156
+ else {
157
+ console.warn("[VoiceFeedback] Speech synthesis failed:", result.reason);
158
+ reject(new Error(`Speech synthesis failed: ${result.reason}`));
159
+ }
160
+ }, (error) => {
161
+ this.isSpeaking = false;
162
+ console.error("[VoiceFeedback] Speech synthesis error:", error);
163
+ reject(error);
164
+ });
165
+ });
166
+ }
167
+ catch (error) {
168
+ this.isSpeaking = false;
169
+ console.error("[VoiceFeedback] Failed to speak feedback:", error);
170
+ throw error;
171
+ }
172
+ }
173
+ stopSpeaking() {
174
+ if (this.synthesizer && this.isSpeaking) {
175
+ try {
176
+ this.synthesizer.close();
177
+ this.synthesizer = null;
178
+ this.isSpeaking = false;
179
+ console.log("[VoiceFeedback] Stopped speaking");
180
+ }
181
+ catch (error) {
182
+ console.error("[VoiceFeedback] Error stopping speech:", error);
183
+ }
184
+ }
185
+ }
186
+ async provideFeedback(context) {
187
+ if (!this.enabled) {
188
+ console.log("[VoiceFeedback] Feedback disabled, skipping");
189
+ return;
190
+ }
191
+ console.log("[VoiceFeedback] Providing feedback for action:", context.action);
192
+ const simpleActions = [
193
+ "scroll_up",
194
+ "scroll_down",
195
+ "scroll_left",
196
+ "scroll_right",
197
+ "scroll_top",
198
+ "scroll_bottom",
199
+ "page_up",
200
+ "page_down",
201
+ "zoom_in",
202
+ "zoom_out",
203
+ "click",
204
+ "enter",
205
+ "submit",
206
+ ];
207
+ if (simpleActions.includes(context.action)) {
208
+ console.log("[VoiceFeedback] Using immediate fallback for simple action");
209
+ try {
210
+ const fallbackMessage = this.getFallbackMessage(context.action, context.actionResult, context.elementInfo);
211
+ await this.speak(fallbackMessage);
212
+ return;
213
+ }
214
+ catch (error) {
215
+ console.error("[VoiceFeedback] Fallback failed:", error);
216
+ return;
217
+ }
218
+ }
219
+ try {
220
+ const messagePromise = this.generateFeedbackMessage(context);
221
+ const timeoutPromise = new Promise((_, reject) => setTimeout(() => reject(new Error("Feedback generation timeout")), 3000));
222
+ const message = await Promise.race([messagePromise, timeoutPromise]);
223
+ console.log("[VoiceFeedback] Generated message:", message);
224
+ if (!message) {
225
+ console.warn("[VoiceFeedback] No message generated");
226
+ return;
227
+ }
228
+ await this.speak(message);
229
+ console.log("[VoiceFeedback] Feedback completed successfully");
230
+ }
231
+ catch (error) {
232
+ console.error("[VoiceFeedback] Error providing feedback:", error);
233
+ try {
234
+ const fallbackMessage = this.getFallbackMessage(context.action, context.actionResult, context.elementInfo);
235
+ console.log("[VoiceFeedback] Using fallback message:", fallbackMessage);
236
+ await this.speak(fallbackMessage);
237
+ }
238
+ catch (fallbackError) {
239
+ console.error("[VoiceFeedback] Fallback also failed:", fallbackError);
240
+ }
241
+ }
242
+ }
243
+ async provideImmediateFeedback(message) {
244
+ if (!this.enabled) {
245
+ return;
246
+ }
247
+ try {
248
+ await this.speak(message);
249
+ }
250
+ catch (error) {
251
+ console.error("[VoiceFeedback] Error providing immediate feedback:", error);
252
+ }
253
+ }
254
+ async announceFocusChange(element, direction) {
255
+ if (!this.enabled) {
256
+ return;
257
+ }
258
+ const elementInfo = this.extractElementInfo(element);
259
+ await this.provideFeedback({
260
+ action: direction === "next" ? "focus_next" : "focus_previous",
261
+ actionResult: {
262
+ performed: true,
263
+ info: {
264
+ focused: true,
265
+ direction,
266
+ elementTag: element.tagName,
267
+ },
268
+ },
269
+ elementInfo,
270
+ });
271
+ }
272
+ extractElementInfo(element) {
273
+ const info = {
274
+ tag: element.tagName.toLowerCase(),
275
+ };
276
+ const ariaLabel = element.getAttribute("aria-label");
277
+ const ariaLabelledBy = element.getAttribute("aria-labelledby");
278
+ const title = element.getAttribute("title");
279
+ const alt = element.getAttribute("alt");
280
+ const placeholder = element.getAttribute("placeholder");
281
+ let labelledByText = "";
282
+ if (ariaLabelledBy) {
283
+ const referencedElement = document.getElementById(ariaLabelledBy);
284
+ if (referencedElement) {
285
+ labelledByText = referencedElement.textContent?.trim() || "";
286
+ }
287
+ }
288
+ let childImageLabel = "";
289
+ if (!ariaLabel && !labelledByText && !title && !alt) {
290
+ const childImage = element.querySelector("img");
291
+ if (childImage) {
292
+ const imgAlt = childImage.getAttribute("alt");
293
+ const imgTitle = childImage.getAttribute("title");
294
+ childImageLabel = imgAlt || imgTitle || "";
295
+ }
296
+ if (!childImageLabel) {
297
+ const svgTitle = element.querySelector("svg title");
298
+ if (svgTitle) {
299
+ childImageLabel = svgTitle.textContent?.trim() || "";
300
+ }
301
+ }
302
+ }
303
+ let textContent = "";
304
+ if (!childImageLabel &&
305
+ (element instanceof HTMLButtonElement ||
306
+ element instanceof HTMLAnchorElement)) {
307
+ textContent = element.textContent?.trim().slice(0, 50) || "";
308
+ }
309
+ const associatedLabel = element.closest("label")?.textContent?.trim();
310
+ info.label =
311
+ ariaLabel ||
312
+ labelledByText ||
313
+ title ||
314
+ alt ||
315
+ childImageLabel ||
316
+ textContent ||
317
+ placeholder ||
318
+ associatedLabel;
319
+ info.text = textContent || alt || placeholder || undefined;
320
+ if (element instanceof HTMLInputElement) {
321
+ info.type = element.type;
322
+ }
323
+ return info;
324
+ }
325
+ dispose() {
326
+ this.stopSpeaking();
327
+ if (this.synthesizer) {
328
+ this.synthesizer.close();
329
+ this.synthesizer = null;
330
+ }
331
+ }
332
+ }
package/dist/types.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- export type CoreNavigationAction = "zoom_in" | "zoom_out" | "scroll_up" | "scroll_down" | "scroll_left" | "scroll_right" | "page_up" | "page_down" | "scroll_top" | "scroll_bottom" | "go_back" | "go_forward" | "reload_page" | "print_page" | "copy_url" | "open_menu" | "close_menu" | "focus_search" | "toggle_fullscreen" | "exit_fullscreen" | "play_media" | "pause_media" | "mute_media" | "unmute_media" | "search_content" | "stop" | "quit" | "tab_next" | "tab_back" | "click" | "enter" | "submit" | "move_left" | "move_right" | "move_up" | "move_down" | "move_beginning" | "move_end" | "select_all" | "select_line" | "type_text" | "cut" | "copy" | "paste" | "clear" | "unknown";
1
+ export type CoreNavigationAction = "zoom_in" | "zoom_out" | "scroll_up" | "scroll_down" | "scroll_left" | "scroll_right" | "page_up" | "page_down" | "scroll_top" | "scroll_bottom" | "go_back" | "go_forward" | "reload_page" | "print_page" | "copy_url" | "open_menu" | "close_menu" | "focus_search" | "toggle_fullscreen" | "exit_fullscreen" | "play_media" | "pause_media" | "mute_media" | "unmute_media" | "search_content" | "stop" | "quit" | "tab_next" | "tab_back" | "focus_next" | "focus_previous" | "click" | "enter" | "submit" | "activate" | "move_left" | "move_right" | "move_up" | "move_down" | "move_beginning" | "move_end" | "select_all" | "select_line" | "type_text" | "cut" | "copy" | "paste" | "clear" | "unknown";
2
2
  export type NavigationAction = CoreNavigationAction | `navigate_${string}`;
3
3
  export type ButtonPlacement = "bottom-right" | "bottom-left" | "top-right" | "top-left" | "center-right" | "center-left";
4
4
  export interface UIConfig {
@@ -22,6 +22,9 @@ export interface NavigationConfig {
22
22
  region?: string;
23
23
  };
24
24
  language?: string;
25
+ voiceFeedback?: {
26
+ enabled?: boolean;
27
+ };
25
28
  autoStart?: boolean;
26
29
  actionHandlers?: Partial<Record<NavigationAction, (context?: ActionContext) => void>>;
27
30
  opensearch?: OpenSearchConfig;
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
package/dist/ui.d.ts.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"ui.d.ts","sourceRoot":"","sources":["../src/ui.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,UAAU,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAuC/E,eAAO,MAAM,2BAA2B,GACtC,YAAW,eAAgC,KAC1C,IAqHF,CAAC;AAKF,eAAO,MAAM,qBAAqB,GAChC,YAAW,eAAgC,KAC1C,UAgEF,CAAC;AA+EF,eAAO,MAAM,oBAAoB,GAC/B,gBAAgB,MAAM,KACrB,OAAO,CAAC,UAAU,CAuEpB,CAAC;AAKF,eAAO,MAAM,YAAY,GAAI,IAAI,UAAU,EAAE,MAAM,MAAM,KAAG,IAE3D,CAAC;AAKF,eAAO,MAAM,QAAQ,GAAI,IAAI,UAAU,EAAE,OAAO,eAAe,KAAG,IAgDjE,CAAC;AAKF,eAAO,MAAM,gBAAgB,GAAI,IAAI,UAAU,EAAE,MAAM,MAAM,KAAG,IAE/D,CAAC;AAKF,eAAO,MAAM,qBAAqB,GAChC,IAAI,UAAU,EACd,YAAY,MAAM,EAClB,WAAW,OAAO,EAClB,OAAM,GAAQ,KACb,IAkBF,CAAC;AAKF,eAAO,MAAM,SAAS,GAAI,IAAI,UAAU,EAAE,OAAO,KAAK,KAAG,IAGxD,CAAC;AAKF,eAAO,MAAM,SAAS,GAAI,MAAM,MAAM,EAAE,SAAQ,GAAQ,KAAG,IAU1D,CAAC"}
1
+ {"version":3,"file":"ui.d.ts","sourceRoot":"","sources":["../src/ui.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,UAAU,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAuC/E,eAAO,MAAM,2BAA2B,GACtC,YAAW,eAAgC,KAC1C,IAkIF,CAAC;AAKF,eAAO,MAAM,qBAAqB,GAChC,YAAW,eAAgC,KAC1C,UAgEF,CAAC;AA+EF,eAAO,MAAM,oBAAoB,GAC/B,gBAAgB,MAAM,KACrB,OAAO,CAAC,UAAU,CAuEpB,CAAC;AAKF,eAAO,MAAM,YAAY,GAAI,IAAI,UAAU,EAAE,MAAM,MAAM,KAAG,IAE3D,CAAC;AAKF,eAAO,MAAM,QAAQ,GAAI,IAAI,UAAU,EAAE,OAAO,eAAe,KAAG,IA0DjE,CAAC;AAKF,eAAO,MAAM,gBAAgB,GAAI,IAAI,UAAU,EAAE,MAAM,MAAM,KAAG,IAE/D,CAAC;AAKF,eAAO,MAAM,qBAAqB,GAChC,IAAI,UAAU,EACd,YAAY,MAAM,EAClB,WAAW,OAAO,EAClB,OAAM,GAAQ,KACb,IAkBF,CAAC;AAKF,eAAO,MAAM,SAAS,GAAI,IAAI,UAAU,EAAE,OAAO,KAAK,KAAG,IAGxD,CAAC;AAKF,eAAO,MAAM,SAAS,GAAI,MAAM,MAAM,EAAE,SAAQ,GAAQ,KAAG,IAU1D,CAAC"}
package/dist/ui.js CHANGED
@@ -85,6 +85,10 @@ export const injectFloatingControlStyles = (placement = "bottom-right") => {
85
85
  color: #bae6fd;
86
86
  }
87
87
 
88
+ .navigate-control__status:empty {
89
+ display: none;
90
+ }
91
+
88
92
  .navigate-control__transcript {
89
93
  font-size: 0.95rem;
90
94
  line-height: 1.4;
@@ -123,6 +127,15 @@ export const injectFloatingControlStyles = (placement = "bottom-right") => {
123
127
  background: #7c3aed;
124
128
  }
125
129
 
130
+ .navigate-control--hidden {
131
+ display: none !important;
132
+ visibility: hidden !important;
133
+ }
134
+
135
+ .navigate-control--hidden .navigate-control__panel {
136
+ display: none !important;
137
+ }
138
+
126
139
  @media (max-width: 640px) {
127
140
  .navigate-control {
128
141
  ${mobilePlacementStyles}
@@ -238,13 +251,12 @@ export const attachToCustomButton = async (buttonSelector) => {
238
251
  if (!root) {
239
252
  root = document.createElement("div");
240
253
  root.id = "navigate-control-panel";
241
- root.className = "navigate-control";
242
- root.style.display = "none";
254
+ root.className = "navigate-control navigate-control--hidden";
243
255
  }
244
256
  root.dataset.state = root.dataset.state || "idle";
245
257
  root.innerHTML = `
246
258
  <div class="navigate-control__panel">
247
- <div class="navigate-control__status">Tap your button to start voice control</div>
259
+ <div class="navigate-control__status"></div>
248
260
  <div class="navigate-control__transcript" role="status" aria-live="polite"></div>
249
261
  <div class="navigate-control__action" aria-live="polite"></div>
250
262
  </div>
@@ -264,6 +276,7 @@ export const attachToCustomButton = async (buttonSelector) => {
264
276
  });
265
277
  }
266
278
  customButton.setAttribute("aria-pressed", "false");
279
+ customButton.dataset.voiceState = "idle";
267
280
  if (!customButton.getAttribute("aria-label")) {
268
281
  customButton.setAttribute("aria-label", "Start voice control");
269
282
  }
@@ -282,6 +295,7 @@ export const updateStatus = (ui, text) => {
282
295
  };
283
296
  export const setState = (ui, state) => {
284
297
  ui.root.dataset.state = state;
298
+ ui.button.dataset.voiceState = state;
285
299
  const updateLabel = (text) => {
286
300
  if (ui.label) {
287
301
  ui.label.textContent = text;
@@ -292,9 +306,14 @@ export const setState = (ui, state) => {
292
306
  updateLabel("Start");
293
307
  ui.button.setAttribute("aria-pressed", "false");
294
308
  ui.button.setAttribute("aria-label", "Start voice control");
295
- updateStatus(ui, ui.isCustomButton
296
- ? "Tap your button to start voice control"
297
- : "Tap to start voice control");
309
+ if (ui.isCustomButton) {
310
+ updateStatus(ui, "");
311
+ updateTranscript(ui, "");
312
+ ui.action.textContent = "";
313
+ }
314
+ else {
315
+ updateStatus(ui, "Tap to start voice control");
316
+ }
298
317
  break;
299
318
  case "loading":
300
319
  updateLabel("Loading...");
@@ -314,11 +333,17 @@ export const setState = (ui, state) => {
314
333
  break;
315
334
  case "error":
316
335
  updateLabel("Error");
336
+ ui.button.setAttribute("aria-pressed", "false");
317
337
  ui.button.setAttribute("aria-label", "Error occurred");
318
338
  break;
319
339
  }
320
340
  if (ui.isCustomButton) {
321
- ui.root.style.display = state === "idle" ? "none" : "flex";
341
+ if (state === "idle" || state === "error") {
342
+ ui.root.classList.add("navigate-control--hidden");
343
+ }
344
+ else {
345
+ ui.root.classList.remove("navigate-control--hidden");
346
+ }
322
347
  }
323
348
  };
324
349
  export const updateTranscript = (ui, text) => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@myscheme/voice-navigation-sdk",
3
- "version": "0.1.6",
3
+ "version": "0.1.8",
4
4
  "description": "Voice navigation SDK using Azure Speech and AWS Bedrock",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",