@myscheme/voice-navigation-sdk 0.1.5 → 0.1.6

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 (32) hide show
  1. package/dist/actions.js +12 -12
  2. package/dist/microphone-handler.d.ts +2 -0
  3. package/dist/microphone-handler.d.ts.map +1 -1
  4. package/dist/microphone-handler.js +11 -2
  5. package/dist/navigation-controller.d.ts.map +1 -1
  6. package/dist/navigation-controller.js +39 -6
  7. package/dist/server/azure-speech-handler.d.ts +12 -0
  8. package/dist/server/azure-speech-handler.d.ts.map +1 -0
  9. package/dist/server/azure-speech-handler.js +40 -0
  10. package/dist/server/bedrock-embedding-handler.d.ts +15 -0
  11. package/dist/server/bedrock-embedding-handler.d.ts.map +1 -0
  12. package/dist/server/bedrock-embedding-handler.js +123 -0
  13. package/dist/server/bedrock-handler.d.ts +14 -0
  14. package/dist/server/bedrock-handler.d.ts.map +1 -0
  15. package/dist/server/bedrock-handler.js +114 -0
  16. package/dist/server/index.d.ts +4 -0
  17. package/dist/server/index.d.ts.map +1 -1
  18. package/dist/server/index.js +4 -0
  19. package/dist/server/opensearch-env-handler.d.ts +22 -0
  20. package/dist/server/opensearch-env-handler.d.ts.map +1 -0
  21. package/dist/server/opensearch-env-handler.js +221 -0
  22. package/dist/services/azure-speech.d.ts +10 -2
  23. package/dist/services/azure-speech.d.ts.map +1 -1
  24. package/dist/services/azure-speech.js +66 -3
  25. package/dist/services/bedrock.d.ts +13 -4
  26. package/dist/services/bedrock.d.ts.map +1 -1
  27. package/dist/services/bedrock.js +171 -17
  28. package/dist/services/vector-search.d.ts.map +1 -1
  29. package/dist/services/vector-search.js +15 -2
  30. package/dist/types.d.ts +13 -8
  31. package/dist/types.d.ts.map +1 -1
  32. package/package.json +3 -3
package/dist/actions.js CHANGED
@@ -216,14 +216,14 @@ export const performAgentAction = (action, context = {}) => {
216
216
  }
217
217
  case "copy_url": {
218
218
  if (navigator.clipboard && window.isSecureContext) {
219
+ info.copied = true;
220
+ performed = true;
219
221
  navigator.clipboard
220
222
  .writeText(window.location.href)
221
223
  .then(() => console.log("Page URL copied to clipboard"))
222
224
  .catch((error) => {
223
225
  console.warn("Failed to copy URL via clipboard API", error);
224
226
  });
225
- info.copied = true;
226
- performed = true;
227
227
  }
228
228
  else {
229
229
  try {
@@ -620,6 +620,8 @@ export const performAgentAction = (action, context = {}) => {
620
620
  const end = activeElement.selectionEnd || 0;
621
621
  const selectedText = activeElement.value.substring(start, end);
622
622
  if (selectedText && navigator.clipboard) {
623
+ info.cut = true;
624
+ performed = true;
623
625
  navigator.clipboard
624
626
  .writeText(selectedText)
625
627
  .then(() => {
@@ -629,8 +631,6 @@ export const performAgentAction = (action, context = {}) => {
629
631
  activeElement.setSelectionRange(start, start);
630
632
  activeElement.dispatchEvent(new Event("input", { bubbles: true, cancelable: true }));
631
633
  console.log("Cut text to clipboard");
632
- info.cut = true;
633
- performed = true;
634
634
  })
635
635
  .catch((error) => {
636
636
  console.warn("Failed to cut text", error);
@@ -651,12 +651,12 @@ export const performAgentAction = (action, context = {}) => {
651
651
  const end = activeElement.selectionEnd || 0;
652
652
  const selectedText = activeElement.value.substring(start, end);
653
653
  if (selectedText && navigator.clipboard) {
654
+ info.copied = true;
655
+ performed = true;
654
656
  navigator.clipboard
655
657
  .writeText(selectedText)
656
658
  .then(() => {
657
659
  console.log("Copied text to clipboard");
658
- info.copied = true;
659
- performed = true;
660
660
  })
661
661
  .catch((error) => {
662
662
  console.warn("Failed to copy text", error);
@@ -666,12 +666,12 @@ export const performAgentAction = (action, context = {}) => {
666
666
  const selection = window.getSelection();
667
667
  const selectionText = selection?.toString();
668
668
  if (selectionText && navigator.clipboard) {
669
+ info.copied = true;
670
+ performed = true;
669
671
  navigator.clipboard
670
672
  .writeText(selectionText)
671
673
  .then(() => {
672
674
  console.log("Copied selected text to clipboard");
673
- info.copied = true;
674
- performed = true;
675
675
  })
676
676
  .catch((error) => {
677
677
  console.warn("Failed to copy text", error);
@@ -686,12 +686,12 @@ export const performAgentAction = (action, context = {}) => {
686
686
  const selection = window.getSelection();
687
687
  const selectionText = selection?.toString();
688
688
  if (selectionText && navigator.clipboard) {
689
+ info.copied = true;
690
+ performed = true;
689
691
  navigator.clipboard
690
692
  .writeText(selectionText)
691
693
  .then(() => {
692
694
  console.log("Copied selected text to clipboard");
693
- info.copied = true;
694
- performed = true;
695
695
  })
696
696
  .catch((error) => {
697
697
  console.warn("Failed to copy text", error);
@@ -709,6 +709,8 @@ export const performAgentAction = (action, context = {}) => {
709
709
  (activeElement instanceof HTMLInputElement ||
710
710
  activeElement instanceof HTMLTextAreaElement) &&
711
711
  navigator.clipboard) {
712
+ info.pasted = true;
713
+ performed = true;
712
714
  navigator.clipboard
713
715
  .readText()
714
716
  .then((clipboardText) => {
@@ -721,8 +723,6 @@ export const performAgentAction = (action, context = {}) => {
721
723
  activeElement.setSelectionRange(newPos, newPos);
722
724
  activeElement.dispatchEvent(new Event("input", { bubbles: true, cancelable: true }));
723
725
  console.log("Pasted text from clipboard");
724
- info.pasted = true;
725
- performed = true;
726
726
  })
727
727
  .catch((error) => {
728
728
  console.warn("Failed to paste text", error);
@@ -22,6 +22,7 @@ export declare class MicrophoneHandler {
22
22
  private hasPermission;
23
23
  private audioContext;
24
24
  private audioContextUnlocked;
25
+ private activeCallbacks;
25
26
  constructor(config: MicrophoneConfig);
26
27
  hasMicrophonePermission(): boolean;
27
28
  hasUnlockedAudioContext(): boolean;
@@ -36,6 +37,7 @@ export declare class MicrophoneHandler {
36
37
  clearSilenceTimer(): void;
37
38
  getAggregatedText(): string;
38
39
  scheduleSilenceCheck(callbacks?: NavigationCallbacks): void;
40
+ rescheduleSilenceCheck(): void;
39
41
  sendToBedrockAgent(text: string): Promise<AgentActionResponse>;
40
42
  disposeRecognizer(): void;
41
43
  createRecognizer(): Promise<sdk.SpeechRecognizer>;
@@ -1 +1 @@
1
- {"version":3,"file":"microphone-handler.d.ts","sourceRoot":"","sources":["../src/microphone-handler.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,GAAG,MAAM,wCAAwC,CAAC;AAC9D,OAAO,KAAK,EAAE,mBAAmB,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC;AAC3E,OAAO,EAAE,kBAAkB,EAAE,MAAM,4BAA4B,CAAC;AAChE,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAEvD,UAAU,gBAAgB;IACxB,kBAAkB,EAAE,kBAAkB,CAAC;IACvC,cAAc,EAAE,cAAc,CAAC;IAC/B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAED,qBAAa,iBAAiB;IAC5B,OAAO,CAAC,kBAAkB,CAAqB;IAC/C,OAAO,CAAC,cAAc,CAAiB;IACvC,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,cAAc,CAAS;IAC/B,OAAO,CAAC,KAAK,CAAuB;IACpC,OAAO,CAAC,MAAM,CAAuB;IACrC,OAAO,CAAC,UAAU,CAAqC;IACvD,OAAO,CAAC,mBAAmB,CAAgB;IAC3C,OAAO,CAAC,cAAc,CAA8C;IACpE,OAAO,CAAC,WAAW,CAAkB;IACrC,OAAO,CAAC,aAAa,CAAkB;IACvC,OAAO,CAAC,YAAY,CAA6B;IACjD,OAAO,CAAC,oBAAoB,CAAkB;gBAElC,MAAM,EAAE,gBAAgB;IAUpC,uBAAuB,IAAI,OAAO;IAIlC,uBAAuB,IAAI,OAAO;IAO5B,kBAAkB,IAAI,OAAO,CAAC,eAAe,GAAG,SAAS,CAAC;IAoB1D,qBAAqB,IAAI,OAAO,CAAC,OAAO,CAAC;IAgBzC,kBAAkB,CAAC,aAAa,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC;IAwDzD,2BAA2B,IAAI,OAAO,CAAC,OAAO,CAAC;IA2BrD,WAAW,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI;IAYnC,wBAAwB,IAAI,IAAI;IAO1B,eAAe,IAAI,OAAO,CAAC,OAAO,CAAC;IAgBnC,eAAe,IAAI,OAAO,CAAC,OAAO,CAAC;IAkBzC,iBAAiB,IAAI,IAAI;IAUzB,iBAAiB,IAAI,MAAM;IAO3B,oBAAoB,CAAC,SAAS,GAAE,mBAAwB,GAAG,IAAI;IAczD,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,mBAAmB,CAAC;IAiBpE,iBAAiB,IAAI,IAAI;IAgCnB,gBAAgB,IAAI,OAAO,CAAC,GAAG,CAAC,gBAAgB,CAAC;IAmBjD,cAAc,CAAC,SAAS,GAAE,mBAAwB,GAAG,OAAO,CAAC,OAAO,CAAC;IAiHrE,aAAa,IAAI,OAAO,CAAC,MAAM,CAAC;WAoCzB,qBAAqB,IAAI,OAAO,CAAC,OAAO,CAAC;CAYvD"}
1
+ {"version":3,"file":"microphone-handler.d.ts","sourceRoot":"","sources":["../src/microphone-handler.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,GAAG,MAAM,wCAAwC,CAAC;AAC9D,OAAO,KAAK,EAAE,mBAAmB,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC;AAC3E,OAAO,EAAE,kBAAkB,EAAE,MAAM,4BAA4B,CAAC;AAChE,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAEvD,UAAU,gBAAgB;IACxB,kBAAkB,EAAE,kBAAkB,CAAC;IACvC,cAAc,EAAE,cAAc,CAAC;IAC/B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAED,qBAAa,iBAAiB;IAC5B,OAAO,CAAC,kBAAkB,CAAqB;IAC/C,OAAO,CAAC,cAAc,CAAiB;IACvC,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,cAAc,CAAS;IAC/B,OAAO,CAAC,KAAK,CAAuB;IACpC,OAAO,CAAC,MAAM,CAAuB;IACrC,OAAO,CAAC,UAAU,CAAqC;IACvD,OAAO,CAAC,mBAAmB,CAAgB;IAC3C,OAAO,CAAC,cAAc,CAA8C;IACpE,OAAO,CAAC,WAAW,CAAkB;IACrC,OAAO,CAAC,aAAa,CAAkB;IACvC,OAAO,CAAC,YAAY,CAA6B;IACjD,OAAO,CAAC,oBAAoB,CAAkB;IAC9C,OAAO,CAAC,eAAe,CAA2B;gBAEtC,MAAM,EAAE,gBAAgB;IAUpC,uBAAuB,IAAI,OAAO;IAIlC,uBAAuB,IAAI,OAAO;IAO5B,kBAAkB,IAAI,OAAO,CAAC,eAAe,GAAG,SAAS,CAAC;IAoB1D,qBAAqB,IAAI,OAAO,CAAC,OAAO,CAAC;IAgBzC,kBAAkB,CAAC,aAAa,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC;IAwDzD,2BAA2B,IAAI,OAAO,CAAC,OAAO,CAAC;IA2BrD,WAAW,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI;IAYnC,wBAAwB,IAAI,IAAI;IAO1B,eAAe,IAAI,OAAO,CAAC,OAAO,CAAC;IAgBnC,eAAe,IAAI,OAAO,CAAC,OAAO,CAAC;IAkBzC,iBAAiB,IAAI,IAAI;IAUzB,iBAAiB,IAAI,MAAM;IAO3B,oBAAoB,CAAC,SAAS,GAAE,mBAAwB,GAAG,IAAI;IAiB/D,sBAAsB,IAAI,IAAI;IAUxB,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,mBAAmB,CAAC;IAiBpE,iBAAiB,IAAI,IAAI;IAgCnB,gBAAgB,IAAI,OAAO,CAAC,GAAG,CAAC,gBAAgB,CAAC;IAmBjD,cAAc,CAAC,SAAS,GAAE,mBAAwB,GAAG,OAAO,CAAC,OAAO,CAAC;IAoHrE,aAAa,IAAI,OAAO,CAAC,MAAM,CAAC;WAoCzB,qBAAqB,IAAI,OAAO,CAAC,OAAO,CAAC;CAYvD"}
@@ -10,6 +10,7 @@ export class MicrophoneHandler {
10
10
  this.hasPermission = false;
11
11
  this.audioContext = null;
12
12
  this.audioContextUnlocked = false;
13
+ this.activeCallbacks = {};
13
14
  this.azureSpeechService = config.azureSpeechService;
14
15
  this.bedrockService = config.bedrockService;
15
16
  this.language = config.language || "en-IN";
@@ -156,13 +157,20 @@ export class MicrophoneHandler {
156
157
  }
157
158
  scheduleSilenceCheck(callbacks = {}) {
158
159
  this.clearSilenceTimer();
160
+ const callbacksToUse = Object.keys(callbacks).length > 0 ? callbacks : this.activeCallbacks;
159
161
  this.silenceTimerId = setTimeout(() => {
160
162
  console.log("Silence detected - triggering callback");
161
- if (callbacks.onSilence) {
162
- callbacks.onSilence();
163
+ if (callbacksToUse.onSilence) {
164
+ callbacksToUse.onSilence();
163
165
  }
164
166
  }, this.silenceTimeout);
165
167
  }
168
+ rescheduleSilenceCheck() {
169
+ if (!this.isRecording) {
170
+ return;
171
+ }
172
+ this.scheduleSilenceCheck(this.activeCallbacks);
173
+ }
166
174
  async sendToBedrockAgent(text) {
167
175
  if (!text || !text.trim()) {
168
176
  return { action: "unknown" };
@@ -216,6 +224,7 @@ export class MicrophoneHandler {
216
224
  console.warn("Already recording");
217
225
  return false;
218
226
  }
227
+ this.activeCallbacks = callbacks;
219
228
  if (!this.hasPermission) {
220
229
  const granted = await this.requestMicrophonePermission();
221
230
  if (!granted) {
@@ -1 +1 @@
1
- {"version":3,"file":"navigation-controller.d.ts","sourceRoot":"","sources":["../src/navigation-controller.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EACV,gBAAgB,EAKjB,MAAM,YAAY,CAAC;AA2DpB,qBAAa,yBAAyB;IACpC,OAAO,CAAC,MAAM,CAAmB;IACjC,OAAO,CAAC,iBAAiB,CAAoB;IAC7C,OAAO,CAAC,kBAAkB,CAAqB;IAC/C,OAAO,CAAC,cAAc,CAAiB;IACvC,OAAO,CAAC,YAAY,CAAe;IACnC,OAAO,CAAC,EAAE,CAAc;IACxB,OAAO,CAAC,cAAc,CAAc;IACpC,OAAO,CAAC,YAAY,CAAkB;IACtC,OAAO,CAAC,qBAAqB,CAAkB;IAC/C,OAAO,CAAC,eAAe,CAA2B;IAClD,OAAO,CAAC,+BAA+B,CAAkB;IACzD,OAAO,CAAC,wBAAwB,CAA6B;IAC7D,OAAO,CAAC,mBAAmB,CAAoC;IAC/D,OAAO,CAAC,gBAAgB,CAAgB;IACxC,OAAO,CAAC,aAAa,CAAgB;gBAEzB,MAAM,EAAE,gBAAgB;YAkFtB,iBAAiB;IAiD/B,OAAO,CAAC,eAAe;IAoBhB,YAAY,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI;IAepC,oBAAoB,CAAC,OAAO,GAAE;QAAE,MAAM,CAAC,EAAE,MAAM,CAAA;KAAO,GAAG,IAAI;YAOtD,eAAe;IAmE7B,OAAO,CAAC,kBAAkB;YASZ,eAAe;IAwBhB,KAAK,CAChB,OAAO,GAAE;QAAE,MAAM,CAAC,EAAE,MAAM,GAAG,MAAM,CAAA;KAAO,GACzC,OAAO,CAAC,IAAI,CAAC;IAmFH,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAiClC,OAAO,CAAC,aAAa;IAUrB,OAAO,CAAC,aAAa;YAWP,aAAa;YAOb,wBAAwB;IAuCtC,OAAO,CAAC,WAAW;YAoBL,iBAAiB;YAwBjB,iBAAiB;IA0HxB,WAAW,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI;YAI5B,yBAAyB;IAgMvC,OAAO,CAAC,oBAAoB;IAqD5B,OAAO,CAAC,yBAAyB;IAoCjC,OAAO,CAAC,UAAU;IAQlB,OAAO,CAAC,YAAY;IAUpB,OAAO,CAAC,YAAY;IASpB,OAAO,CAAC,4BAA4B;IAiB7B,OAAO,IAAI,IAAI;IAgBtB,OAAO,CAAC,kBAAkB;IA8B1B,OAAO,CAAC,kBAAkB;IAwD1B,OAAO,CAAC,aAAa;IAYrB,OAAO,CAAC,uBAAuB;IAkD/B,OAAO,CAAC,sBAAsB;IAW9B,OAAO,CAAC,wBAAwB;CAmBjC"}
1
+ {"version":3,"file":"navigation-controller.d.ts","sourceRoot":"","sources":["../src/navigation-controller.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EACV,gBAAgB,EAKjB,MAAM,YAAY,CAAC;AA2DpB,qBAAa,yBAAyB;IACpC,OAAO,CAAC,MAAM,CAAmB;IACjC,OAAO,CAAC,iBAAiB,CAAoB;IAC7C,OAAO,CAAC,kBAAkB,CAAqB;IAC/C,OAAO,CAAC,cAAc,CAAiB;IACvC,OAAO,CAAC,YAAY,CAAe;IACnC,OAAO,CAAC,EAAE,CAAc;IACxB,OAAO,CAAC,cAAc,CAAc;IACpC,OAAO,CAAC,YAAY,CAAkB;IACtC,OAAO,CAAC,qBAAqB,CAAkB;IAC/C,OAAO,CAAC,eAAe,CAA2B;IAClD,OAAO,CAAC,+BAA+B,CAAkB;IACzD,OAAO,CAAC,wBAAwB,CAA6B;IAC7D,OAAO,CAAC,mBAAmB,CAAoC;IAC/D,OAAO,CAAC,gBAAgB,CAAgB;IACxC,OAAO,CAAC,aAAa,CAAgB;gBAEzB,MAAM,EAAE,gBAAgB;YAmItB,iBAAiB;IAiD/B,OAAO,CAAC,eAAe;IAoBhB,YAAY,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI;IAepC,oBAAoB,CAAC,OAAO,GAAE;QAAE,MAAM,CAAC,EAAE,MAAM,CAAA;KAAO,GAAG,IAAI;YAOtD,eAAe;IAmE7B,OAAO,CAAC,kBAAkB;YASZ,eAAe;IAwBhB,KAAK,CAChB,OAAO,GAAE;QAAE,MAAM,CAAC,EAAE,MAAM,GAAG,MAAM,CAAA;KAAO,GACzC,OAAO,CAAC,IAAI,CAAC;IAmFH,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAiClC,OAAO,CAAC,aAAa;IAUrB,OAAO,CAAC,aAAa;YAWP,aAAa;YAOb,wBAAwB;IA2CtC,OAAO,CAAC,WAAW;YAoBL,iBAAiB;YAwBjB,iBAAiB;IA8HxB,WAAW,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI;YAI5B,yBAAyB;IAgMvC,OAAO,CAAC,oBAAoB;IAqD5B,OAAO,CAAC,yBAAyB;IAoCjC,OAAO,CAAC,UAAU;IAQlB,OAAO,CAAC,YAAY;IAUpB,OAAO,CAAC,YAAY;IASpB,OAAO,CAAC,4BAA4B;IAiB7B,OAAO,IAAI,IAAI;IAgBtB,OAAO,CAAC,kBAAkB;IA8B1B,OAAO,CAAC,kBAAkB;IAwD1B,OAAO,CAAC,aAAa;IAYrB,OAAO,CAAC,uBAAuB;IAkD/B,OAAO,CAAC,sBAAsB;IAW9B,OAAO,CAAC,wBAAwB;CAmBjC"}
@@ -43,19 +43,47 @@ export class VoiceNavigationController {
43
43
  opensearch: openSearchConfig,
44
44
  };
45
45
  console.log("[Voice Navigation Controller] Constructor called with UI config:", this.config.ui);
46
- if (!this.config.azure?.subscriptionKey || !this.config.azure?.region) {
47
- throw new Error("Azure Speech configuration is required");
46
+ const hasAzureEndpoint = !!this.config.azure?.tokenEndpoint;
47
+ const hasAzureCredentials = !!(this.config.azure?.subscriptionKey && this.config.azure?.region);
48
+ if (!this.config.azure) {
49
+ this.config.azure = { tokenEndpoint: "/api/speech/token" };
50
+ console.log("[VoiceNavigation] Auto-configured Azure endpoint: /api/speech/token");
51
+ }
52
+ else if (!hasAzureEndpoint && !hasAzureCredentials) {
53
+ this.config.azure.tokenEndpoint = "/api/speech/token";
54
+ console.log("[VoiceNavigation] Auto-configured Azure endpoint: /api/speech/token");
55
+ }
56
+ const hasAwsEndpoint = !!this.config.aws?.bedrockEndpoint;
57
+ const hasAwsCredentials = !!(this.config.aws?.accessKeyId &&
58
+ this.config.aws?.secretAccessKey &&
59
+ this.config.aws?.modelId);
60
+ if (!this.config.aws) {
61
+ this.config.aws = {
62
+ bedrockEndpoint: "/api/speech/bedrock",
63
+ embeddingEndpoint: "/api/speech/bedrock-embedding",
64
+ };
65
+ console.log("[VoiceNavigation] Auto-configured AWS endpoints: /api/speech/bedrock, /api/speech/bedrock-embedding");
66
+ }
67
+ else if (!hasAwsEndpoint && !hasAwsCredentials) {
68
+ this.config.aws.bedrockEndpoint = "/api/speech/bedrock";
69
+ this.config.aws.embeddingEndpoint = "/api/speech/bedrock-embedding";
70
+ console.log("[VoiceNavigation] Auto-configured AWS endpoints: /api/speech/bedrock, /api/speech/bedrock-embedding");
48
71
  }
49
- if (!this.config.aws?.accessKeyId ||
50
- !this.config.aws?.secretAccessKey ||
51
- !this.config.aws?.modelId) {
52
- throw new Error("AWS Bedrock configuration is required");
72
+ if (openSearchConfig &&
73
+ !openSearchConfig.searchEndpoint &&
74
+ !openSearchConfig.node) {
75
+ openSearchConfig.searchEndpoint = "/api/opensearch/search";
76
+ openSearchConfig.suggestEndpoint = "/api/opensearch/suggest";
77
+ console.log("[VoiceNavigation] Auto-configured OpenSearch endpoints: /api/opensearch/search, /api/opensearch/suggest");
53
78
  }
54
79
  this.azureSpeechService = new AzureSpeechService({
80
+ tokenEndpoint: this.config.azure.tokenEndpoint,
55
81
  subscriptionKey: this.config.azure.subscriptionKey,
56
82
  region: this.config.azure.region,
57
83
  });
58
84
  this.bedrockService = new BedrockService({
85
+ bedrockEndpoint: this.config.aws.bedrockEndpoint,
86
+ embeddingEndpoint: this.config.aws.embeddingEndpoint,
59
87
  region: this.config.aws.region || "ap-south-1",
60
88
  accessKeyId: this.config.aws.accessKeyId,
61
89
  secretAccessKey: this.config.aws.secretAccessKey,
@@ -350,6 +378,7 @@ export class VoiceNavigationController {
350
378
  }
351
379
  updateTranscript(this.ui, "");
352
380
  this.isProcessing = false;
381
+ this.microphoneHandler.rescheduleSilenceCheck();
353
382
  }
354
383
  }
355
384
  handleError(error) {
@@ -441,6 +470,10 @@ export class VoiceNavigationController {
441
470
  handler: this,
442
471
  onStop: () => this.stop(),
443
472
  transcript: originalText,
473
+ parameters: {
474
+ text: actionData.text || query,
475
+ query: query,
476
+ },
444
477
  });
445
478
  if (typeof this.config.actionHandlers?.[action] === "function") {
446
479
  try {
@@ -0,0 +1,12 @@
1
+ type NextApiRequest = {
2
+ method?: string;
3
+ body?: unknown;
4
+ };
5
+ type NextApiResponse = {
6
+ status: (code: number) => NextApiResponse;
7
+ json: (data: unknown) => void;
8
+ setHeader: (name: string, value: string | string[]) => void;
9
+ };
10
+ export declare function azureSpeechTokenHandler(req: NextApiRequest, res: NextApiResponse): Promise<void>;
11
+ export {};
12
+ //# sourceMappingURL=azure-speech-handler.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"azure-speech-handler.d.ts","sourceRoot":"","sources":["../../src/server/azure-speech-handler.ts"],"names":[],"mappings":"AAiBA,KAAK,cAAc,GAAG;IACpB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,OAAO,CAAC;CAChB,CAAC;AAEF,KAAK,eAAe,GAAG;IACrB,MAAM,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,eAAe,CAAC;IAC1C,IAAI,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAC;IAC9B,SAAS,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,KAAK,IAAI,CAAC;CAC7D,CAAC;AAWF,wBAAsB,uBAAuB,CAC3C,GAAG,EAAE,cAAc,EACnB,GAAG,EAAE,eAAe,GACnB,OAAO,CAAC,IAAI,CAAC,CA0Df"}
@@ -0,0 +1,40 @@
1
+ export async function azureSpeechTokenHandler(req, res) {
2
+ if (req.method !== "POST") {
3
+ res.setHeader("Allow", ["POST"]);
4
+ res.status(405).json({ error: "Method not allowed" });
5
+ return;
6
+ }
7
+ const key = process.env.AZURE_SPEECH_KEY;
8
+ const region = process.env.AZURE_SPEECH_REGION;
9
+ if (!key || !region) {
10
+ console.error("[VoiceNavigation] Missing Azure Speech credentials. Set AZURE_SPEECH_KEY and AZURE_SPEECH_REGION in your .env file");
11
+ res.status(500).json({
12
+ error: "Azure Speech configuration is missing",
13
+ hint: "Set AZURE_SPEECH_KEY and AZURE_SPEECH_REGION environment variables",
14
+ });
15
+ return;
16
+ }
17
+ try {
18
+ const url = `https://${region}.api.cognitive.microsoft.com/sts/v1.0/issueToken`;
19
+ const response = await fetch(url, {
20
+ method: "POST",
21
+ headers: {
22
+ "Ocp-Apim-Subscription-Key": key,
23
+ },
24
+ });
25
+ if (!response.ok) {
26
+ throw new Error(`Azure API responded with status ${response.status}`);
27
+ }
28
+ const token = await response.text();
29
+ res.setHeader("Cache-Control", "no-store, no-cache, max-age=0, must-revalidate");
30
+ const responseData = { token, region };
31
+ res.status(200).json(responseData);
32
+ }
33
+ catch (error) {
34
+ console.error("[VoiceNavigation] Failed to fetch Azure speech token:", error);
35
+ res.status(500).json({
36
+ error: "Failed to get token",
37
+ message: error instanceof Error ? error.message : "Unknown error",
38
+ });
39
+ }
40
+ }
@@ -0,0 +1,15 @@
1
+ type NextApiRequest = {
2
+ method?: string;
3
+ body?: {
4
+ text?: string | string[];
5
+ inputType?: string;
6
+ };
7
+ };
8
+ type NextApiResponse = {
9
+ status: (code: number) => NextApiResponse;
10
+ json: (data: unknown) => void;
11
+ setHeader: (name: string, value: string | string[]) => void;
12
+ };
13
+ export declare function bedrockEmbeddingHandler(req: NextApiRequest, res: NextApiResponse): Promise<void>;
14
+ export {};
15
+ //# sourceMappingURL=bedrock-embedding-handler.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bedrock-embedding-handler.d.ts","sourceRoot":"","sources":["../../src/server/bedrock-embedding-handler.ts"],"names":[],"mappings":"AAsBA,KAAK,cAAc,GAAG;IACpB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE;QACL,IAAI,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;QACzB,SAAS,CAAC,EAAE,MAAM,CAAC;KACpB,CAAC;CACH,CAAC;AAEF,KAAK,eAAe,GAAG;IACrB,MAAM,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,eAAe,CAAC;IAC1C,IAAI,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAC;IAC9B,SAAS,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,KAAK,IAAI,CAAC;CAC7D,CAAC;AA0BF,wBAAsB,uBAAuB,CAC3C,GAAG,EAAE,cAAc,EACnB,GAAG,EAAE,eAAe,GACnB,OAAO,CAAC,IAAI,CAAC,CAwJf"}
@@ -0,0 +1,123 @@
1
+ import crypto from "crypto";
2
+ function sign(key, msg) {
3
+ return crypto.createHmac("sha256", key).update(msg, "utf8").digest();
4
+ }
5
+ function getSignatureKey(key, dateStamp, region, service) {
6
+ const kDate = sign("AWS4" + key, dateStamp);
7
+ const kRegion = sign(kDate, region);
8
+ const kService = sign(kRegion, service);
9
+ const kSigning = sign(kService, "aws4_request");
10
+ return kSigning;
11
+ }
12
+ export async function bedrockEmbeddingHandler(req, res) {
13
+ if (req.method !== "POST") {
14
+ res.setHeader("Allow", ["POST"]);
15
+ res.status(405).json({ error: "Method not allowed" });
16
+ return;
17
+ }
18
+ const region = process.env.AWS_REGION || "ap-south-1";
19
+ const accessKey = process.env.AWS_ACCESS_KEY_ID;
20
+ const secretKey = process.env.AWS_SECRET_ACCESS_KEY;
21
+ const sessionToken = process.env.AWS_SESSION_TOKEN;
22
+ const embeddingModelId = process.env.AWS_EMBEDDING_MODEL_ID || "cohere.embed-multilingual-v3";
23
+ if (!accessKey || !secretKey) {
24
+ console.error("[VoiceNavigation] Missing AWS credentials. Set AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY in your .env file");
25
+ res.status(500).json({
26
+ error: "Missing AWS credentials",
27
+ hint: "Set AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY environment variables",
28
+ });
29
+ return;
30
+ }
31
+ if (!embeddingModelId) {
32
+ res.status(500).json({ error: "Missing AWS_EMBEDDING_MODEL_ID" });
33
+ return;
34
+ }
35
+ const { text, inputType = "search_query" } = req.body || {};
36
+ if (!text) {
37
+ res.status(400).json({ error: "Missing text parameter" });
38
+ return;
39
+ }
40
+ const requestBody = {
41
+ texts: Array.isArray(text) ? text : [text],
42
+ input_type: inputType,
43
+ truncate: "END",
44
+ };
45
+ const body = JSON.stringify(requestBody);
46
+ const service = "bedrock";
47
+ const host = `bedrock-runtime.${region}.amazonaws.com`;
48
+ const encodedModelId = encodeURIComponent(embeddingModelId);
49
+ const path = `/model/${encodedModelId}/invoke`;
50
+ const endpoint = `https://${host}${path}`;
51
+ const canonicalPath = path.replace(/%/g, "%25");
52
+ const amzDate = new Date().toISOString().replace(/[:-]|\.\d{3}/g, "");
53
+ const dateStamp = amzDate.slice(0, 8);
54
+ const headers = {
55
+ "content-type": "application/json",
56
+ host: host,
57
+ "x-amz-date": amzDate,
58
+ };
59
+ if (sessionToken) {
60
+ headers["x-amz-security-token"] = sessionToken;
61
+ }
62
+ const signedHeaders = Object.keys(headers)
63
+ .map((h) => h.toLowerCase())
64
+ .sort()
65
+ .join(";");
66
+ const canonicalHeaders = Object.keys(headers)
67
+ .map((h) => h.toLowerCase())
68
+ .sort()
69
+ .map((k) => `${k}:${headers[k]}\n`)
70
+ .join("");
71
+ const canonicalRequest = "POST\n" +
72
+ canonicalPath +
73
+ "\n" +
74
+ "\n" +
75
+ canonicalHeaders +
76
+ "\n" +
77
+ signedHeaders +
78
+ "\n" +
79
+ crypto.createHash("sha256").update(body, "utf8").digest("hex");
80
+ const credentialScope = `${dateStamp}/${region}/${service}/aws4_request`;
81
+ const stringToSign = "AWS4-HMAC-SHA256\n" +
82
+ amzDate +
83
+ "\n" +
84
+ credentialScope +
85
+ "\n" +
86
+ crypto.createHash("sha256").update(canonicalRequest, "utf8").digest("hex");
87
+ const signingKey = getSignatureKey(secretKey, dateStamp, region, service);
88
+ const signature = crypto
89
+ .createHmac("sha256", signingKey)
90
+ .update(stringToSign, "utf8")
91
+ .digest("hex");
92
+ const authorizationHeader = `AWS4-HMAC-SHA256 Credential=${accessKey}/${credentialScope}, ` +
93
+ `SignedHeaders=${signedHeaders}, Signature=${signature}`;
94
+ const fetchHeaders = {
95
+ ...headers,
96
+ Authorization: authorizationHeader,
97
+ };
98
+ try {
99
+ const response = await fetch(endpoint, {
100
+ method: "POST",
101
+ headers: fetchHeaders,
102
+ body,
103
+ });
104
+ if (!response.ok) {
105
+ const errorText = await response.text();
106
+ console.error("[VoiceNavigation] Bedrock Embedding API error:", response.status, errorText);
107
+ res.status(response.status).json({
108
+ error: "Bedrock Embedding API error",
109
+ details: errorText,
110
+ });
111
+ return;
112
+ }
113
+ const json = await response.json();
114
+ res.status(200).json(json);
115
+ }
116
+ catch (error) {
117
+ console.error("[VoiceNavigation] Bedrock embedding generation error:", error);
118
+ res.status(500).json({
119
+ error: "Failed to generate embeddings",
120
+ message: error instanceof Error ? error.message : "Unknown error",
121
+ });
122
+ }
123
+ }
@@ -0,0 +1,14 @@
1
+ type NextApiRequest = {
2
+ method?: string;
3
+ body?: {
4
+ body?: unknown;
5
+ };
6
+ };
7
+ type NextApiResponse = {
8
+ status: (code: number) => NextApiResponse;
9
+ json: (data: unknown) => void;
10
+ setHeader: (name: string, value: string | string[]) => void;
11
+ };
12
+ export declare function bedrockHandler(req: NextApiRequest, res: NextApiResponse): Promise<void>;
13
+ export {};
14
+ //# sourceMappingURL=bedrock-handler.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bedrock-handler.d.ts","sourceRoot":"","sources":["../../src/server/bedrock-handler.ts"],"names":[],"mappings":"AAsBA,KAAK,cAAc,GAAG;IACpB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE;QACL,IAAI,CAAC,EAAE,OAAO,CAAC;KAChB,CAAC;CACH,CAAC;AAEF,KAAK,eAAe,GAAG;IACrB,MAAM,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,eAAe,CAAC;IAC1C,IAAI,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAC;IAC9B,SAAS,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,KAAK,IAAI,CAAC;CAC7D,CAAC;AA0BF,wBAAsB,cAAc,CAClC,GAAG,EAAE,cAAc,EACnB,GAAG,EAAE,eAAe,GACnB,OAAO,CAAC,IAAI,CAAC,CA0If"}
@@ -0,0 +1,114 @@
1
+ import crypto from "crypto";
2
+ function sign(key, msg) {
3
+ return crypto.createHmac("sha256", key).update(msg, "utf8").digest();
4
+ }
5
+ function getSignatureKey(key, dateStamp, region, service) {
6
+ const kDate = sign("AWS4" + key, dateStamp);
7
+ const kRegion = sign(kDate, region);
8
+ const kService = sign(kRegion, service);
9
+ const kSigning = sign(kService, "aws4_request");
10
+ return kSigning;
11
+ }
12
+ export async function bedrockHandler(req, res) {
13
+ if (req.method !== "POST") {
14
+ res.setHeader("Allow", ["POST"]);
15
+ res.status(405).json({ error: "Method not allowed" });
16
+ return;
17
+ }
18
+ const region = process.env.AWS_REGION || "ap-south-1";
19
+ const accessKey = process.env.AWS_ACCESS_KEY_ID;
20
+ const secretKey = process.env.AWS_SECRET_ACCESS_KEY;
21
+ const sessionToken = process.env.AWS_SESSION_TOKEN;
22
+ const modelId = process.env.AWS_MODEL_ID || "anthropic.claude-3-sonnet-20240229-v1:0";
23
+ if (!accessKey || !secretKey) {
24
+ console.error("[VoiceNavigation] Missing AWS credentials. Set AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY in your .env file");
25
+ res.status(500).json({
26
+ error: "Missing AWS credentials",
27
+ hint: "Set AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY environment variables",
28
+ });
29
+ return;
30
+ }
31
+ const requestBody = req.body?.body;
32
+ if (!requestBody) {
33
+ res.status(400).json({ error: "Missing request body" });
34
+ return;
35
+ }
36
+ const body = JSON.stringify(requestBody);
37
+ const service = "bedrock";
38
+ const host = `bedrock-runtime.${region}.amazonaws.com`;
39
+ const encodedModelId = encodeURIComponent(modelId);
40
+ const path = `/model/${encodedModelId}/invoke`;
41
+ const endpoint = `https://${host}${path}`;
42
+ const canonicalPath = path.replace(/%/g, "%25");
43
+ const amzDate = new Date().toISOString().replace(/[:-]|\.\d{3}/g, "");
44
+ const dateStamp = amzDate.slice(0, 8);
45
+ const headers = {
46
+ "content-type": "application/json",
47
+ host: host,
48
+ "x-amz-date": amzDate,
49
+ };
50
+ if (sessionToken) {
51
+ headers["x-amz-security-token"] = sessionToken;
52
+ }
53
+ const signedHeaders = Object.keys(headers)
54
+ .map((h) => h.toLowerCase())
55
+ .sort()
56
+ .join(";");
57
+ const canonicalHeaders = Object.keys(headers)
58
+ .map((h) => h.toLowerCase())
59
+ .sort()
60
+ .map((k) => `${k}:${headers[k]}\n`)
61
+ .join("");
62
+ const canonicalRequest = "POST\n" +
63
+ canonicalPath +
64
+ "\n" +
65
+ "\n" +
66
+ canonicalHeaders +
67
+ "\n" +
68
+ signedHeaders +
69
+ "\n" +
70
+ crypto.createHash("sha256").update(body, "utf8").digest("hex");
71
+ const credentialScope = `${dateStamp}/${region}/${service}/aws4_request`;
72
+ const stringToSign = "AWS4-HMAC-SHA256\n" +
73
+ amzDate +
74
+ "\n" +
75
+ credentialScope +
76
+ "\n" +
77
+ crypto.createHash("sha256").update(canonicalRequest, "utf8").digest("hex");
78
+ const signingKey = getSignatureKey(secretKey, dateStamp, region, service);
79
+ const signature = crypto
80
+ .createHmac("sha256", signingKey)
81
+ .update(stringToSign, "utf8")
82
+ .digest("hex");
83
+ const authorizationHeader = `AWS4-HMAC-SHA256 Credential=${accessKey}/${credentialScope}, ` +
84
+ `SignedHeaders=${signedHeaders}, Signature=${signature}`;
85
+ const fetchHeaders = {
86
+ ...headers,
87
+ Authorization: authorizationHeader,
88
+ };
89
+ try {
90
+ const response = await fetch(endpoint, {
91
+ method: "POST",
92
+ headers: fetchHeaders,
93
+ body,
94
+ });
95
+ if (!response.ok) {
96
+ const errorText = await response.text();
97
+ console.error("[VoiceNavigation] Bedrock API error:", response.status, errorText);
98
+ res.status(response.status).json({
99
+ error: "Bedrock API error",
100
+ details: errorText,
101
+ });
102
+ return;
103
+ }
104
+ const json = await response.json();
105
+ res.status(200).json(json);
106
+ }
107
+ catch (error) {
108
+ console.error("[VoiceNavigation] Bedrock action extraction error:", error);
109
+ res.status(500).json({
110
+ error: "Failed to extract action",
111
+ message: error instanceof Error ? error.message : "Unknown error",
112
+ });
113
+ }
114
+ }
@@ -1,3 +1,7 @@
1
+ export { azureSpeechTokenHandler } from "./azure-speech-handler.js";
2
+ export { bedrockHandler } from "./bedrock-handler.js";
3
+ export { bedrockEmbeddingHandler } from "./bedrock-embedding-handler.js";
4
+ export { openSearchSearchHandler, openSearchSuggestHandler, } from "./opensearch-env-handler.js";
1
5
  export { createOpenSearchProxyHandler, DEFAULT_OPENSEARCH_PROXY_PATH, } from "./opensearch-handler.js";
2
6
  export type { VectorSearchProxyRequest, VectorSearchProxyResponse, } from "./opensearch-handler.js";
3
7
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/server/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,4BAA4B,EAC5B,6BAA6B,GAC9B,MAAM,yBAAyB,CAAC;AACjC,YAAY,EACV,wBAAwB,EACxB,yBAAyB,GAC1B,MAAM,yBAAyB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/server/index.ts"],"names":[],"mappings":"AAoBA,OAAO,EAAE,uBAAuB,EAAE,MAAM,2BAA2B,CAAC;AACpE,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AACtD,OAAO,EAAE,uBAAuB,EAAE,MAAM,gCAAgC,CAAC;AACzE,OAAO,EACL,uBAAuB,EACvB,wBAAwB,GACzB,MAAM,6BAA6B,CAAC;AAGrC,OAAO,EACL,4BAA4B,EAC5B,6BAA6B,GAC9B,MAAM,yBAAyB,CAAC;AACjC,YAAY,EACV,wBAAwB,EACxB,yBAAyB,GAC1B,MAAM,yBAAyB,CAAC"}
@@ -1 +1,5 @@
1
+ export { azureSpeechTokenHandler } from "./azure-speech-handler.js";
2
+ export { bedrockHandler } from "./bedrock-handler.js";
3
+ export { bedrockEmbeddingHandler } from "./bedrock-embedding-handler.js";
4
+ export { openSearchSearchHandler, openSearchSuggestHandler, } from "./opensearch-env-handler.js";
1
5
  export { createOpenSearchProxyHandler, DEFAULT_OPENSEARCH_PROXY_PATH, } from "./opensearch-handler.js";
@@ -0,0 +1,22 @@
1
+ type NextApiRequest = {
2
+ method?: string;
3
+ headers?: {
4
+ [key: string]: string | string[] | undefined;
5
+ };
6
+ body?: any;
7
+ query?: {
8
+ [key: string]: string | string[];
9
+ };
10
+ socket?: {
11
+ remoteAddress?: string;
12
+ };
13
+ };
14
+ type NextApiResponse = {
15
+ status: (code: number) => NextApiResponse;
16
+ json: (data: any) => void;
17
+ setHeader: (name: string, value: string | string[]) => void;
18
+ };
19
+ export declare function openSearchSearchHandler(req: NextApiRequest, res: NextApiResponse): Promise<void>;
20
+ export declare function openSearchSuggestHandler(req: NextApiRequest, res: NextApiResponse): Promise<void>;
21
+ export {};
22
+ //# sourceMappingURL=opensearch-env-handler.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"opensearch-env-handler.d.ts","sourceRoot":"","sources":["../../src/server/opensearch-env-handler.ts"],"names":[],"mappings":"AAuBA,KAAK,cAAc,GAAG;IACpB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE;QAAE,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,MAAM,EAAE,GAAG,SAAS,CAAA;KAAE,CAAC;IAC3D,IAAI,CAAC,EAAE,GAAG,CAAC;IACX,KAAK,CAAC,EAAE;QAAE,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,MAAM,EAAE,CAAA;KAAE,CAAC;IAC7C,MAAM,CAAC,EAAE;QAAE,aAAa,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;CACrC,CAAC;AAEF,KAAK,eAAe,GAAG;IACrB,MAAM,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,eAAe,CAAC;IAC1C,IAAI,EAAE,CAAC,IAAI,EAAE,GAAG,KAAK,IAAI,CAAC;IAC1B,SAAS,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,KAAK,IAAI,CAAC;CAC7D,CAAC;AAmFF,wBAAsB,uBAAuB,CAC3C,GAAG,EAAE,cAAc,EACnB,GAAG,EAAE,eAAe,GACnB,OAAO,CAAC,IAAI,CAAC,CA6Hf;AAMD,wBAAsB,wBAAwB,CAC5C,GAAG,EAAE,cAAc,EACnB,GAAG,EAAE,eAAe,GACnB,OAAO,CAAC,IAAI,CAAC,CAgFf"}