@myscheme/voice-navigation-sdk 0.1.6 → 0.1.7

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.
@@ -2,6 +2,7 @@ import { MicrophoneHandler } from "./microphone-handler.js";
2
2
  import { AzureSpeechService } from "./services/azure-speech.js";
3
3
  import { BedrockService } from "./services/bedrock.js";
4
4
  import { PageRegistry } from "./services/page-registry.js";
5
+ import { VoiceFeedbackService } from "./services/voice-feedback.js";
5
6
  import { loadNavigationPages } from "./services/xml-parser.js";
6
7
  import { VectorSearchService, } from "./services/vector-search.js";
7
8
  import { performAgentAction, formatActionLabel, extractAgentAction, setPageRegistry, } from "./actions.js";
@@ -99,6 +100,15 @@ export class VoiceNavigationController {
99
100
  bedrockService: this.bedrockService,
100
101
  language: this.config.language || "en-IN",
101
102
  });
103
+ const voiceFeedbackEnabled = this.config.voiceFeedback?.enabled !== false;
104
+ console.log("[VoiceNavigation] Initializing voice feedback service - enabled:", voiceFeedbackEnabled);
105
+ this.voiceFeedbackService = new VoiceFeedbackService({
106
+ enabled: voiceFeedbackEnabled,
107
+ language: this.config.language || "en-IN",
108
+ azureSpeechService: this.azureSpeechService,
109
+ bedrockService: this.bedrockService,
110
+ });
111
+ console.log("[VoiceNavigation] Voice feedback service initialized successfully");
102
112
  if (openSearchConfig) {
103
113
  try {
104
114
  this.vectorSearchService = new VectorSearchService(openSearchConfig);
@@ -439,6 +449,30 @@ export class VoiceNavigationController {
439
449
  query,
440
450
  originalText,
441
451
  });
452
+ if (actionResult.performed && actionResult.info?.pendingNavigation) {
453
+ console.log("[VoiceNavigation] Search result with navigation - waiting for feedback:", action);
454
+ try {
455
+ await this.provideActionFeedback(action, actionResult, originalText);
456
+ console.log("[VoiceNavigation] Search feedback complete, now navigating to:", actionResult.info.navigationUrl);
457
+ if (actionResult.info.navigationUrl) {
458
+ window.location.href = actionResult.info.navigationUrl;
459
+ actionResult.info.navigated = true;
460
+ actionResult.info.pendingNavigation = false;
461
+ }
462
+ }
463
+ catch (err) {
464
+ console.error("[VoiceNavigation] Voice feedback error (search):", err);
465
+ if (actionResult.info.navigationUrl) {
466
+ window.location.href = actionResult.info.navigationUrl;
467
+ }
468
+ }
469
+ }
470
+ else if (actionResult.performed) {
471
+ console.log("[VoiceNavigation] Search result without navigation - non-blocking feedback");
472
+ void this.provideActionFeedback(action, actionResult, originalText).catch((err) => {
473
+ console.error("[VoiceNavigation] Voice feedback error (search):", err);
474
+ });
475
+ }
442
476
  if (typeof this.config.actionHandlers?.[action] === "function") {
443
477
  try {
444
478
  this.config.actionHandlers[action]({
@@ -475,6 +509,75 @@ export class VoiceNavigationController {
475
509
  query: query,
476
510
  },
477
511
  });
512
+ console.log("[VoiceNavigation] Action performed:", action, "result:", actionResult.performed);
513
+ const isCriticalAction = action.startsWith("navigate_") ||
514
+ action === "focus_next" ||
515
+ action === "tab_next" ||
516
+ action === "focus_previous" ||
517
+ action === "tab_back" ||
518
+ action === "go_back" ||
519
+ action === "go_forward" ||
520
+ action === "reload_page";
521
+ if (actionResult.performed && isCriticalAction) {
522
+ console.log("[VoiceNavigation] Critical action - waiting for voice feedback to complete:", action);
523
+ try {
524
+ await this.provideActionFeedback(action, actionResult, originalText);
525
+ console.log("[VoiceNavigation] Voice feedback completed for critical action:", action);
526
+ if (actionResult.info?.pendingNavigation) {
527
+ if (actionResult.info.navigationUrl) {
528
+ console.log("[VoiceNavigation] Feedback complete, now navigating to:", actionResult.info.navigationUrl);
529
+ window.location.href = actionResult.info.navigationUrl;
530
+ actionResult.info.navigated = true;
531
+ actionResult.info.pendingNavigation = false;
532
+ }
533
+ else if (actionResult.info.navigationType === "back") {
534
+ console.log("[VoiceNavigation] Feedback complete, navigating back");
535
+ window.history.back();
536
+ actionResult.info.navigated = true;
537
+ actionResult.info.pendingNavigation = false;
538
+ }
539
+ else if (actionResult.info.navigationType === "forward") {
540
+ console.log("[VoiceNavigation] Feedback complete, navigating forward");
541
+ window.history.forward();
542
+ actionResult.info.navigated = true;
543
+ actionResult.info.pendingNavigation = false;
544
+ }
545
+ else if (actionResult.info.navigationType === "reload") {
546
+ console.log("[VoiceNavigation] Feedback complete, reloading page");
547
+ window.location.reload();
548
+ actionResult.info.reloaded = true;
549
+ actionResult.info.pendingNavigation = false;
550
+ }
551
+ }
552
+ }
553
+ catch (err) {
554
+ console.error("[VoiceNavigation] Voice feedback error (critical action):", err);
555
+ if (actionResult.info?.pendingNavigation) {
556
+ if (actionResult.info.navigationUrl) {
557
+ console.log("[VoiceNavigation] Feedback failed, but proceeding with navigation:", actionResult.info.navigationUrl);
558
+ window.location.href = actionResult.info.navigationUrl;
559
+ }
560
+ else if (actionResult.info.navigationType === "back") {
561
+ window.history.back();
562
+ }
563
+ else if (actionResult.info.navigationType === "forward") {
564
+ window.history.forward();
565
+ }
566
+ else if (actionResult.info.navigationType === "reload") {
567
+ window.location.reload();
568
+ }
569
+ }
570
+ }
571
+ }
572
+ else if (actionResult.performed) {
573
+ console.log("[VoiceNavigation] Non-critical action - providing feedback non-blocking:", action);
574
+ void this.provideActionFeedback(action, actionResult, originalText).catch((err) => {
575
+ console.error("[VoiceNavigation] Voice feedback error:", err);
576
+ });
577
+ }
578
+ else {
579
+ console.log("[VoiceNavigation] Action not performed, skipping voice feedback");
580
+ }
478
581
  if (typeof this.config.actionHandlers?.[action] === "function") {
479
582
  try {
480
583
  this.config.actionHandlers[action]({
@@ -503,6 +606,62 @@ export class VoiceNavigationController {
503
606
  }
504
607
  setLanguage(language) {
505
608
  this.microphoneHandler.setLanguage(language);
609
+ this.voiceFeedbackService.setLanguage(language);
610
+ }
611
+ setVoiceFeedback(enabled) {
612
+ this.voiceFeedbackService.setEnabled(enabled);
613
+ }
614
+ isVoiceFeedbackEnabled() {
615
+ return this.voiceFeedbackService.isEnabled();
616
+ }
617
+ async provideActionFeedback(action, actionResult, transcript) {
618
+ console.log("[VoiceNavigation] provideActionFeedback called for action:", action);
619
+ if (!this.voiceFeedbackService) {
620
+ console.error("[VoiceNavigation] Voice feedback service not initialized!");
621
+ return;
622
+ }
623
+ console.log("[VoiceNavigation] Voice feedback service exists, checking if enabled...");
624
+ console.log("[VoiceNavigation] Voice feedback enabled:", this.voiceFeedbackService.isEnabled());
625
+ try {
626
+ if (action.startsWith("navigate_") && actionResult.info?.pageName) {
627
+ console.log("[VoiceNavigation] Handling navigation feedback");
628
+ await this.voiceFeedbackService.provideFeedback({
629
+ action,
630
+ actionResult,
631
+ transcript,
632
+ });
633
+ return;
634
+ }
635
+ if ((action === "focus_next" ||
636
+ action === "tab_next" ||
637
+ action === "focus_previous" ||
638
+ action === "tab_back") &&
639
+ actionResult.performed) {
640
+ console.log("[VoiceNavigation] Handling focus feedback");
641
+ const focusedElement = document.activeElement;
642
+ if (focusedElement && focusedElement !== document.body) {
643
+ await this.voiceFeedbackService.announceFocusChange(focusedElement, actionResult.info.direction === "next" ||
644
+ actionResult.info.direction === "forward"
645
+ ? "next"
646
+ : "previous");
647
+ return;
648
+ }
649
+ }
650
+ if (actionResult.performed) {
651
+ console.log("[VoiceNavigation] Handling general action feedback");
652
+ await this.voiceFeedbackService.provideFeedback({
653
+ action,
654
+ actionResult,
655
+ transcript,
656
+ });
657
+ }
658
+ else {
659
+ console.log("[VoiceNavigation] Action not performed in feedback check");
660
+ }
661
+ }
662
+ catch (error) {
663
+ console.error("[VoiceNavigation] Failed to provide voice feedback:", error);
664
+ }
506
665
  }
507
666
  async executeVectorSearchAction(options) {
508
667
  const vectorService = this.vectorSearchService;
@@ -628,7 +787,9 @@ export class VoiceNavigationController {
628
787
  });
629
788
  this.prepareForNavigation({ target: resolvedUrl });
630
789
  baseInfo.message = "Opening the best matching result.";
631
- window.location.href = resolvedUrl;
790
+ baseInfo.pendingNavigation = true;
791
+ baseInfo.navigationUrl = resolvedUrl;
792
+ baseInfo.navigated = false;
632
793
  return {
633
794
  performed: true,
634
795
  info: baseInfo,
@@ -8,5 +8,6 @@ type NextApiResponse = {
8
8
  setHeader: (name: string, value: string | string[]) => void;
9
9
  };
10
10
  export declare function azureSpeechTokenHandler(req: NextApiRequest, res: NextApiResponse): Promise<void>;
11
+ export declare function POST(_request: Request): Promise<Response>;
11
12
  export {};
12
13
  //# sourceMappingURL=azure-speech-handler.d.ts.map
@@ -1 +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"}
1
+ {"version":3,"file":"azure-speech-handler.d.ts","sourceRoot":"","sources":["../../src/server/azure-speech-handler.ts"],"names":[],"mappings":"AAwBA,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;AA6EF,wBAAsB,uBAAuB,CAC3C,GAAG,EAAE,cAAc,EACnB,GAAG,EAAE,eAAe,GACnB,OAAO,CAAC,IAAI,CAAC,CAqBf;AAMD,wBAAsB,IAAI,CAAC,QAAQ,EAAE,OAAO,GAAG,OAAO,CAAC,QAAQ,CAAC,CAmB/D"}
@@ -1,18 +1,16 @@
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
- }
1
+ async function getAzureSpeechToken() {
7
2
  const key = process.env.AZURE_SPEECH_KEY;
8
3
  const region = process.env.AZURE_SPEECH_REGION;
9
4
  if (!key || !region) {
10
5
  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;
6
+ return {
7
+ success: false,
8
+ statusCode: 500,
9
+ error: {
10
+ error: "Azure Speech configuration is missing",
11
+ hint: "Set AZURE_SPEECH_KEY and AZURE_SPEECH_REGION environment variables",
12
+ },
13
+ };
16
14
  }
17
15
  try {
18
16
  const url = `https://${region}.api.cognitive.microsoft.com/sts/v1.0/issueToken`;
@@ -26,15 +24,56 @@ export async function azureSpeechTokenHandler(req, res) {
26
24
  throw new Error(`Azure API responded with status ${response.status}`);
27
25
  }
28
26
  const token = await response.text();
29
- res.setHeader("Cache-Control", "no-store, no-cache, max-age=0, must-revalidate");
30
27
  const responseData = { token, region };
31
- res.status(200).json(responseData);
28
+ return {
29
+ success: true,
30
+ statusCode: 200,
31
+ data: responseData,
32
+ };
32
33
  }
33
34
  catch (error) {
34
35
  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",
36
+ return {
37
+ success: false,
38
+ statusCode: 500,
39
+ error: {
40
+ error: "Failed to get token",
41
+ message: error instanceof Error ? error.message : "Unknown error",
42
+ },
43
+ };
44
+ }
45
+ }
46
+ export async function azureSpeechTokenHandler(req, res) {
47
+ if (req.method !== "POST") {
48
+ res.setHeader("Allow", ["POST"]);
49
+ res.status(405).json({ error: "Method not allowed" });
50
+ return;
51
+ }
52
+ const result = await getAzureSpeechToken();
53
+ res.setHeader("Cache-Control", "no-store, no-cache, max-age=0, must-revalidate");
54
+ if (result.success && result.data) {
55
+ res.status(result.statusCode).json(result.data);
56
+ }
57
+ else {
58
+ res.status(result.statusCode).json(result.error);
59
+ }
60
+ }
61
+ export async function POST(_request) {
62
+ const result = await getAzureSpeechToken();
63
+ const headers = {
64
+ "Content-Type": "application/json",
65
+ "Cache-Control": "no-store, no-cache, max-age=0, must-revalidate",
66
+ };
67
+ if (result.success && result.data) {
68
+ return new Response(JSON.stringify(result.data), {
69
+ status: result.statusCode,
70
+ headers,
71
+ });
72
+ }
73
+ else {
74
+ return new Response(JSON.stringify(result.error), {
75
+ status: result.statusCode,
76
+ headers,
38
77
  });
39
78
  }
40
79
  }
@@ -11,5 +11,6 @@ type NextApiResponse = {
11
11
  setHeader: (name: string, value: string | string[]) => void;
12
12
  };
13
13
  export declare function bedrockEmbeddingHandler(req: NextApiRequest, res: NextApiResponse): Promise<void>;
14
+ export declare function BedrockEmbeddingPOST(request: Request): Promise<Response>;
14
15
  export {};
15
16
  //# sourceMappingURL=bedrock-embedding-handler.d.ts.map
@@ -1 +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"}
1
+ {"version":3,"file":"bedrock-embedding-handler.d.ts","sourceRoot":"","sources":["../../src/server/bedrock-embedding-handler.ts"],"names":[],"mappings":"AA4BA,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;AA0MF,wBAAsB,uBAAuB,CAC3C,GAAG,EAAE,cAAc,EACnB,GAAG,EAAE,eAAe,GACnB,OAAO,CAAC,IAAI,CAAC,CAiBf;AAMD,wBAAsB,oBAAoB,CACxC,OAAO,EAAE,OAAO,GACf,OAAO,CAAC,QAAQ,CAAC,CAkCnB"}
@@ -9,12 +9,7 @@ function getSignatureKey(key, dateStamp, region, service) {
9
9
  const kSigning = sign(kService, "aws4_request");
10
10
  return kSigning;
11
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
- }
12
+ async function generateBedrockEmbedding(text, inputType = "search_query") {
18
13
  const region = process.env.AWS_REGION || "ap-south-1";
19
14
  const accessKey = process.env.AWS_ACCESS_KEY_ID;
20
15
  const secretKey = process.env.AWS_SECRET_ACCESS_KEY;
@@ -22,20 +17,28 @@ export async function bedrockEmbeddingHandler(req, res) {
22
17
  const embeddingModelId = process.env.AWS_EMBEDDING_MODEL_ID || "cohere.embed-multilingual-v3";
23
18
  if (!accessKey || !secretKey) {
24
19
  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;
20
+ return {
21
+ success: false,
22
+ statusCode: 500,
23
+ error: {
24
+ error: "Missing AWS credentials",
25
+ hint: "Set AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY environment variables",
26
+ },
27
+ };
30
28
  }
31
29
  if (!embeddingModelId) {
32
- res.status(500).json({ error: "Missing AWS_EMBEDDING_MODEL_ID" });
33
- return;
30
+ return {
31
+ success: false,
32
+ statusCode: 500,
33
+ error: { error: "Missing AWS_EMBEDDING_MODEL_ID" },
34
+ };
34
35
  }
35
- const { text, inputType = "search_query" } = req.body || {};
36
36
  if (!text) {
37
- res.status(400).json({ error: "Missing text parameter" });
38
- return;
37
+ return {
38
+ success: false,
39
+ statusCode: 400,
40
+ error: { error: "Missing text parameter" },
41
+ };
39
42
  }
40
43
  const requestBody = {
41
44
  texts: Array.isArray(text) ? text : [text],
@@ -104,20 +107,77 @@ export async function bedrockEmbeddingHandler(req, res) {
104
107
  if (!response.ok) {
105
108
  const errorText = await response.text();
106
109
  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;
110
+ return {
111
+ success: false,
112
+ statusCode: response.status,
113
+ error: {
114
+ error: "Bedrock Embedding API error",
115
+ details: errorText,
116
+ },
117
+ };
112
118
  }
113
119
  const json = await response.json();
114
- res.status(200).json(json);
120
+ return {
121
+ success: true,
122
+ statusCode: 200,
123
+ data: json,
124
+ };
115
125
  }
116
126
  catch (error) {
117
127
  console.error("[VoiceNavigation] Bedrock embedding generation error:", error);
118
- res.status(500).json({
119
- error: "Failed to generate embeddings",
128
+ return {
129
+ success: false,
130
+ statusCode: 500,
131
+ error: {
132
+ error: "Failed to generate embeddings",
133
+ message: error instanceof Error ? error.message : "Unknown error",
134
+ },
135
+ };
136
+ }
137
+ }
138
+ export async function bedrockEmbeddingHandler(req, res) {
139
+ if (req.method !== "POST") {
140
+ res.setHeader("Allow", ["POST"]);
141
+ res.status(405).json({ error: "Method not allowed" });
142
+ return;
143
+ }
144
+ const { text, inputType = "search_query" } = req.body || {};
145
+ const result = await generateBedrockEmbedding(text, inputType);
146
+ if (result.success && result.data) {
147
+ res.status(result.statusCode).json(result.data);
148
+ }
149
+ else {
150
+ res.status(result.statusCode).json(result.error);
151
+ }
152
+ }
153
+ export async function BedrockEmbeddingPOST(request) {
154
+ try {
155
+ const body = await request.json();
156
+ const { text, inputType = "search_query" } = body || {};
157
+ const result = await generateBedrockEmbedding(text, inputType);
158
+ const headers = {
159
+ "Content-Type": "application/json",
160
+ };
161
+ if (result.success && result.data) {
162
+ return new Response(JSON.stringify(result.data), {
163
+ status: result.statusCode,
164
+ headers,
165
+ });
166
+ }
167
+ else {
168
+ return new Response(JSON.stringify(result.error), {
169
+ status: result.statusCode,
170
+ headers,
171
+ });
172
+ }
173
+ }
174
+ catch (error) {
175
+ return new Response(JSON.stringify({
176
+ error: "Invalid request",
120
177
  message: error instanceof Error ? error.message : "Unknown error",
178
+ }), {
179
+ status: 400,
180
+ headers: { "Content-Type": "application/json" },
121
181
  });
122
182
  }
123
183
  }
@@ -10,5 +10,6 @@ type NextApiResponse = {
10
10
  setHeader: (name: string, value: string | string[]) => void;
11
11
  };
12
12
  export declare function bedrockHandler(req: NextApiRequest, res: NextApiResponse): Promise<void>;
13
+ export declare function BedrockPOST(request: Request): Promise<Response>;
13
14
  export {};
14
15
  //# sourceMappingURL=bedrock-handler.d.ts.map
@@ -1 +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"}
1
+ {"version":3,"file":"bedrock-handler.d.ts","sourceRoot":"","sources":["../../src/server/bedrock-handler.ts"],"names":[],"mappings":"AA4BA,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;AAqLF,wBAAsB,cAAc,CAClC,GAAG,EAAE,cAAc,EACnB,GAAG,EAAE,eAAe,GACnB,OAAO,CAAC,IAAI,CAAC,CAkBf;AAMD,wBAAsB,WAAW,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,QAAQ,CAAC,CAkCrE"}
@@ -9,12 +9,7 @@ function getSignatureKey(key, dateStamp, region, service) {
9
9
  const kSigning = sign(kService, "aws4_request");
10
10
  return kSigning;
11
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
- }
12
+ async function invokeBedrock(requestBody) {
18
13
  const region = process.env.AWS_REGION || "ap-south-1";
19
14
  const accessKey = process.env.AWS_ACCESS_KEY_ID;
20
15
  const secretKey = process.env.AWS_SECRET_ACCESS_KEY;
@@ -22,16 +17,21 @@ export async function bedrockHandler(req, res) {
22
17
  const modelId = process.env.AWS_MODEL_ID || "anthropic.claude-3-sonnet-20240229-v1:0";
23
18
  if (!accessKey || !secretKey) {
24
19
  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;
20
+ return {
21
+ success: false,
22
+ statusCode: 500,
23
+ error: {
24
+ error: "Missing AWS credentials",
25
+ hint: "Set AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY environment variables",
26
+ },
27
+ };
30
28
  }
31
- const requestBody = req.body?.body;
32
29
  if (!requestBody) {
33
- res.status(400).json({ error: "Missing request body" });
34
- return;
30
+ return {
31
+ success: false,
32
+ statusCode: 400,
33
+ error: { error: "Missing request body" },
34
+ };
35
35
  }
36
36
  const body = JSON.stringify(requestBody);
37
37
  const service = "bedrock";
@@ -95,20 +95,77 @@ export async function bedrockHandler(req, res) {
95
95
  if (!response.ok) {
96
96
  const errorText = await response.text();
97
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;
98
+ return {
99
+ success: false,
100
+ statusCode: response.status,
101
+ error: {
102
+ error: "Bedrock API error",
103
+ details: errorText,
104
+ },
105
+ };
103
106
  }
104
107
  const json = await response.json();
105
- res.status(200).json(json);
108
+ return {
109
+ success: true,
110
+ statusCode: 200,
111
+ data: json,
112
+ };
106
113
  }
107
114
  catch (error) {
108
115
  console.error("[VoiceNavigation] Bedrock action extraction error:", error);
109
- res.status(500).json({
110
- error: "Failed to extract action",
116
+ return {
117
+ success: false,
118
+ statusCode: 500,
119
+ error: {
120
+ error: "Failed to extract action",
121
+ message: error instanceof Error ? error.message : "Unknown error",
122
+ },
123
+ };
124
+ }
125
+ }
126
+ export async function bedrockHandler(req, res) {
127
+ if (req.method !== "POST") {
128
+ res.setHeader("Allow", ["POST"]);
129
+ res.status(405).json({ error: "Method not allowed" });
130
+ return;
131
+ }
132
+ const requestBody = req.body?.body;
133
+ const result = await invokeBedrock(requestBody);
134
+ if (result.success && result.data) {
135
+ res.status(result.statusCode).json(result.data);
136
+ }
137
+ else {
138
+ res.status(result.statusCode).json(result.error);
139
+ }
140
+ }
141
+ export async function BedrockPOST(request) {
142
+ try {
143
+ const body = await request.json();
144
+ const requestBody = body?.body;
145
+ const result = await invokeBedrock(requestBody);
146
+ const headers = {
147
+ "Content-Type": "application/json",
148
+ };
149
+ if (result.success && result.data) {
150
+ return new Response(JSON.stringify(result.data), {
151
+ status: result.statusCode,
152
+ headers,
153
+ });
154
+ }
155
+ else {
156
+ return new Response(JSON.stringify(result.error), {
157
+ status: result.statusCode,
158
+ headers,
159
+ });
160
+ }
161
+ }
162
+ catch (error) {
163
+ return new Response(JSON.stringify({
164
+ error: "Invalid request",
111
165
  message: error instanceof Error ? error.message : "Unknown error",
166
+ }), {
167
+ status: 400,
168
+ headers: { "Content-Type": "application/json" },
112
169
  });
113
170
  }
114
171
  }
@@ -2,6 +2,9 @@ export { azureSpeechTokenHandler } from "./azure-speech-handler.js";
2
2
  export { bedrockHandler } from "./bedrock-handler.js";
3
3
  export { bedrockEmbeddingHandler } from "./bedrock-embedding-handler.js";
4
4
  export { openSearchSearchHandler, openSearchSuggestHandler, } from "./opensearch-env-handler.js";
5
+ export { POST } from "./azure-speech-handler.js";
6
+ export { BedrockPOST } from "./bedrock-handler.js";
7
+ export { BedrockEmbeddingPOST } from "./bedrock-embedding-handler.js";
5
8
  export { createOpenSearchProxyHandler, DEFAULT_OPENSEARCH_PROXY_PATH, } from "./opensearch-handler.js";
6
9
  export type { VectorSearchProxyRequest, VectorSearchProxyResponse, } from "./opensearch-handler.js";
7
10
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
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
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/server/index.ts"],"names":[],"mappings":"AAkCA,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,EAAE,IAAI,EAAE,MAAM,2BAA2B,CAAC;AACjD,OAAO,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AACnD,OAAO,EAAE,oBAAoB,EAAE,MAAM,gCAAgC,CAAC;AAGtE,OAAO,EACL,4BAA4B,EAC5B,6BAA6B,GAC9B,MAAM,yBAAyB,CAAC;AACjC,YAAY,EACV,wBAAwB,EACxB,yBAAyB,GAC1B,MAAM,yBAAyB,CAAC"}
@@ -2,4 +2,7 @@ export { azureSpeechTokenHandler } from "./azure-speech-handler.js";
2
2
  export { bedrockHandler } from "./bedrock-handler.js";
3
3
  export { bedrockEmbeddingHandler } from "./bedrock-embedding-handler.js";
4
4
  export { openSearchSearchHandler, openSearchSuggestHandler, } from "./opensearch-env-handler.js";
5
+ export { POST } from "./azure-speech-handler.js";
6
+ export { BedrockPOST } from "./bedrock-handler.js";
7
+ export { BedrockEmbeddingPOST } from "./bedrock-embedding-handler.js";
5
8
  export { createOpenSearchProxyHandler, DEFAULT_OPENSEARCH_PROXY_PATH, } from "./opensearch-handler.js";
@@ -27,5 +27,8 @@ export declare class BedrockService {
27
27
  embedText(text: string): Promise<number[]>;
28
28
  private embedTextViaProxy;
29
29
  private embedTextDirect;
30
+ generateFeedbackMessage(prompt: string, language: string): Promise<string>;
31
+ private generateFeedbackViaProxy;
32
+ private generateFeedbackDirect;
30
33
  }
31
34
  //# sourceMappingURL=bedrock.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"bedrock.d.ts","sourceRoot":"","sources":["../../src/services/bedrock.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,mBAAmB,EAAmB,MAAM,aAAa,CAAC;AACxE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAEvD,MAAM,WAAW,aAAa;IAE5B,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAG3B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,gBAAgB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAClC;AAmCD,qBAAa,cAAc;IACzB,OAAO,CAAC,MAAM,CAAqC;IACnD,OAAO,CAAC,aAAa,CAAuB;IAC5C,OAAO,CAAC,gBAAgB,CAAgB;IACxC,OAAO,CAAC,YAAY,CAA6B;IACjD,OAAO,CAAC,eAAe,CAAuB;IAC9C,OAAO,CAAC,oBAAoB,CAAuB;IACnD,OAAO,CAAC,QAAQ,CAAkB;gBAEtB,MAAM,EAAE,aAAa;IA6CjC,eAAe,CAAC,QAAQ,EAAE,YAAY,GAAG,IAAI;IAO7C,OAAO,CAAC,iBAAiB;IA+BnB,aAAa,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,mBAAmB,CAAC;YAWtD,qBAAqB;YA2ErB,mBAAmB;IAyEjC,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,aAAa,GAAG,cAAc;IAO9C,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;YAWlC,iBAAiB;YAkFjB,eAAe;CAoF9B"}
1
+ {"version":3,"file":"bedrock.d.ts","sourceRoot":"","sources":["../../src/services/bedrock.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,mBAAmB,EAAmB,MAAM,aAAa,CAAC;AACxE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAEvD,MAAM,WAAW,aAAa;IAE5B,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAG3B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,gBAAgB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAClC;AAyCD,qBAAa,cAAc;IACzB,OAAO,CAAC,MAAM,CAAqC;IACnD,OAAO,CAAC,aAAa,CAAuB;IAC5C,OAAO,CAAC,gBAAgB,CAAgB;IACxC,OAAO,CAAC,YAAY,CAA6B;IACjD,OAAO,CAAC,eAAe,CAAuB;IAC9C,OAAO,CAAC,oBAAoB,CAAuB;IACnD,OAAO,CAAC,QAAQ,CAAkB;gBAEtB,MAAM,EAAE,aAAa;IA6CjC,eAAe,CAAC,QAAQ,EAAE,YAAY,GAAG,IAAI;IAO7C,OAAO,CAAC,iBAAiB;IA+BnB,aAAa,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,mBAAmB,CAAC;YAWtD,qBAAqB;YA2ErB,mBAAmB;IAyEjC,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,aAAa,GAAG,cAAc;IAO9C,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;YAWlC,iBAAiB;YAkFjB,eAAe;IAwFvB,uBAAuB,CAC3B,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,MAAM,CAAC;YA0BJ,wBAAwB;YAwExB,sBAAsB;CA+DrC"}