@voquill/voice-ai 0.1.0
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/dist/aldea.utils.d.ts +16 -0
- package/dist/aldea.utils.d.ts.map +1 -0
- package/dist/aldea.utils.js +42 -0
- package/dist/assemblyai.utils.d.ts +6 -0
- package/dist/assemblyai.utils.d.ts.map +1 -0
- package/dist/assemblyai.utils.js +24 -0
- package/dist/azure-openai.utils.d.ts +29 -0
- package/dist/azure-openai.utils.d.ts.map +1 -0
- package/dist/azure-openai.utils.js +67 -0
- package/dist/azure.utils.d.ts +30 -0
- package/dist/azure.utils.d.ts.map +1 -0
- package/dist/azure.utils.js +253 -0
- package/dist/claude.utils.d.ts +26 -0
- package/dist/claude.utils.d.ts.map +1 -0
- package/dist/claude.utils.js +229 -0
- package/dist/deepgram.utils.d.ts +5 -0
- package/dist/deepgram.utils.d.ts.map +1 -0
- package/dist/deepgram.utils.js +25 -0
- package/dist/deepseek.utils.d.ts +26 -0
- package/dist/deepseek.utils.d.ts.map +1 -0
- package/dist/deepseek.utils.js +102 -0
- package/dist/elevenlabs.utils.d.ts +6 -0
- package/dist/elevenlabs.utils.d.ts.map +1 -0
- package/dist/elevenlabs.utils.js +29 -0
- package/dist/gemini.utils.d.ts +41 -0
- package/dist/gemini.utils.d.ts.map +1 -0
- package/dist/gemini.utils.js +271 -0
- package/dist/groq.utils.d.ts +42 -0
- package/dist/groq.utils.d.ts.map +1 -0
- package/dist/groq.utils.js +141 -0
- package/dist/index.d.ts +14 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +13 -0
- package/dist/openai.utils.d.ts +55 -0
- package/dist/openai.utils.d.ts.map +1 -0
- package/dist/openai.utils.js +275 -0
- package/dist/openrouter.utils.d.ts +69 -0
- package/dist/openrouter.utils.d.ts.map +1 -0
- package/dist/openrouter.utils.js +148 -0
- package/dist/speaches.utils.d.ts +18 -0
- package/dist/speaches.utils.d.ts.map +1 -0
- package/dist/speaches.utils.js +38 -0
- package/package.json +35 -0
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
export type AldeaTranscriptionArgs = {
|
|
2
|
+
apiKey: string;
|
|
3
|
+
blob: ArrayBuffer | Buffer;
|
|
4
|
+
ext?: string;
|
|
5
|
+
language?: string;
|
|
6
|
+
};
|
|
7
|
+
export type AldeaTranscribeAudioOutput = {
|
|
8
|
+
text: string;
|
|
9
|
+
wordsUsed: number;
|
|
10
|
+
};
|
|
11
|
+
export declare const aldeaTranscribeAudio: ({ apiKey, blob, }: AldeaTranscriptionArgs) => Promise<AldeaTranscribeAudioOutput>;
|
|
12
|
+
export type AldeaTestIntegrationArgs = {
|
|
13
|
+
apiKey: string;
|
|
14
|
+
};
|
|
15
|
+
export declare const aldeaTestIntegration: ({ apiKey, }: AldeaTestIntegrationArgs) => Promise<boolean>;
|
|
16
|
+
//# sourceMappingURL=aldea.utils.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"aldea.utils.d.ts","sourceRoot":"","sources":["../src/aldea.utils.ts"],"names":[],"mappings":"AAIA,MAAM,MAAM,sBAAsB,GAAG;IACnC,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,WAAW,GAAG,MAAM,CAAC;IAC3B,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB,CAAC;AAEF,MAAM,MAAM,0BAA0B,GAAG;IACvC,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;CACnB,CAAC;AAmBF,eAAO,MAAM,oBAAoB,GAAU,mBAGxC,sBAAsB,KAAG,OAAO,CAAC,0BAA0B,CAmC7D,CAAC;AAEF,MAAM,MAAM,wBAAwB,GAAG;IACrC,MAAM,EAAE,MAAM,CAAC;CAChB,CAAC;AAEF,eAAO,MAAM,oBAAoB,GAAU,aAExC,wBAAwB,KAAG,OAAO,CAAC,OAAO,CAgB5C,CAAC"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { retry, countWords } from "@voquill/utilities";
|
|
2
|
+
const ALDEA_API_URL = "https://api.aldea.ai/v1/listen";
|
|
3
|
+
export const aldeaTranscribeAudio = async ({ apiKey, blob, }) => {
|
|
4
|
+
return retry({
|
|
5
|
+
retries: 3,
|
|
6
|
+
fn: async () => {
|
|
7
|
+
const bodyData = blob instanceof ArrayBuffer ? blob : blob.buffer;
|
|
8
|
+
const response = await fetch(ALDEA_API_URL, {
|
|
9
|
+
method: "POST",
|
|
10
|
+
headers: {
|
|
11
|
+
Authorization: `Bearer ${apiKey.trim()}`,
|
|
12
|
+
},
|
|
13
|
+
body: bodyData,
|
|
14
|
+
});
|
|
15
|
+
if (!response.ok) {
|
|
16
|
+
const errorText = await response.text().catch(() => "Unknown error");
|
|
17
|
+
throw new Error(`Aldea API request failed with status ${response.status}: ${errorText}`);
|
|
18
|
+
}
|
|
19
|
+
const data = await response.json();
|
|
20
|
+
const transcript = data?.results?.channels?.[0]?.alternatives?.[0]?.transcript;
|
|
21
|
+
if (!transcript) {
|
|
22
|
+
throw new Error("Transcription failed: No transcript in Aldea API response");
|
|
23
|
+
}
|
|
24
|
+
return { text: transcript, wordsUsed: countWords(transcript) };
|
|
25
|
+
},
|
|
26
|
+
});
|
|
27
|
+
};
|
|
28
|
+
export const aldeaTestIntegration = async ({ apiKey, }) => {
|
|
29
|
+
try {
|
|
30
|
+
const response = await fetch(ALDEA_API_URL, {
|
|
31
|
+
method: "POST",
|
|
32
|
+
headers: {
|
|
33
|
+
Authorization: `Bearer ${apiKey.trim()}`,
|
|
34
|
+
},
|
|
35
|
+
body: new ArrayBuffer(0),
|
|
36
|
+
});
|
|
37
|
+
return response.ok || response.status === 400;
|
|
38
|
+
}
|
|
39
|
+
catch (error) {
|
|
40
|
+
throw new Error(`Aldea integration test failed: ${error instanceof Error ? error.message : "Unknown error"}`);
|
|
41
|
+
}
|
|
42
|
+
};
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export type AssemblyAITestIntegrationArgs = {
|
|
2
|
+
apiKey: string;
|
|
3
|
+
};
|
|
4
|
+
export declare const assemblyaiTestIntegration: ({ apiKey, }: AssemblyAITestIntegrationArgs) => Promise<boolean>;
|
|
5
|
+
export declare const convertFloat32ToPCM16: (float32Array: Float32Array | number[]) => ArrayBuffer;
|
|
6
|
+
//# sourceMappingURL=assemblyai.utils.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"assemblyai.utils.d.ts","sourceRoot":"","sources":["../src/assemblyai.utils.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,6BAA6B,GAAG;IAC1C,MAAM,EAAE,MAAM,CAAC;CAChB,CAAC;AAEF,eAAO,MAAM,yBAAyB,GAAU,aAE7C,6BAA6B,KAAG,OAAO,CAAC,OAAO,CAUjD,CAAC;AAEF,eAAO,MAAM,qBAAqB,GAChC,cAAc,YAAY,GAAG,MAAM,EAAE,KACpC,WAaF,CAAC"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
export const assemblyaiTestIntegration = async ({ apiKey, }) => {
|
|
2
|
+
try {
|
|
3
|
+
const response = await fetch("https://api.assemblyai.com/v2/transcript", {
|
|
4
|
+
method: "GET",
|
|
5
|
+
headers: { Authorization: apiKey },
|
|
6
|
+
});
|
|
7
|
+
return response.ok || response.status === 404;
|
|
8
|
+
}
|
|
9
|
+
catch {
|
|
10
|
+
return false;
|
|
11
|
+
}
|
|
12
|
+
};
|
|
13
|
+
export const convertFloat32ToPCM16 = (float32Array) => {
|
|
14
|
+
const samples = Array.isArray(float32Array)
|
|
15
|
+
? float32Array
|
|
16
|
+
: Array.from(float32Array);
|
|
17
|
+
const buffer = new ArrayBuffer(samples.length * 2);
|
|
18
|
+
const view = new DataView(buffer);
|
|
19
|
+
for (let i = 0; i < samples.length; i++) {
|
|
20
|
+
const s = Math.max(-1, Math.min(1, samples[i]));
|
|
21
|
+
view.setInt16(i * 2, s < 0 ? s * 0x8000 : s * 0x7fff, true);
|
|
22
|
+
}
|
|
23
|
+
return buffer;
|
|
24
|
+
};
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import type { JsonResponse, LlmChatInput, LlmStreamEvent } from "@voquill/types";
|
|
2
|
+
export declare const AZURE_OPENAI_MODELS: readonly ["gpt-5-mini", "gpt-5-nano", "gpt-4o", "gpt-4o-mini", "gpt-4", "gpt-35-turbo"];
|
|
3
|
+
export type AzureOpenAIModel = (typeof AZURE_OPENAI_MODELS)[number];
|
|
4
|
+
export type AzureOpenAIGenerateTextArgs = {
|
|
5
|
+
apiKey: string;
|
|
6
|
+
endpoint: string;
|
|
7
|
+
deploymentName: string;
|
|
8
|
+
system?: string;
|
|
9
|
+
prompt: string;
|
|
10
|
+
jsonResponse?: JsonResponse;
|
|
11
|
+
};
|
|
12
|
+
export type AzureOpenAIGenerateResponseOutput = {
|
|
13
|
+
text: string;
|
|
14
|
+
tokensUsed: number;
|
|
15
|
+
};
|
|
16
|
+
export declare const azureOpenAIGenerateText: ({ apiKey, endpoint, deploymentName, system, prompt, jsonResponse, }: AzureOpenAIGenerateTextArgs) => Promise<AzureOpenAIGenerateResponseOutput>;
|
|
17
|
+
export type AzureOpenAITestIntegrationArgs = {
|
|
18
|
+
apiKey: string;
|
|
19
|
+
endpoint: string;
|
|
20
|
+
};
|
|
21
|
+
export declare const azureOpenAITestIntegration: ({ apiKey, endpoint, }: AzureOpenAITestIntegrationArgs) => Promise<boolean>;
|
|
22
|
+
export type AzureOpenAIStreamChatArgs = {
|
|
23
|
+
apiKey: string;
|
|
24
|
+
endpoint: string;
|
|
25
|
+
deploymentName: string;
|
|
26
|
+
input: LlmChatInput;
|
|
27
|
+
};
|
|
28
|
+
export declare function azureOpenaiStreamChat({ apiKey, endpoint, deploymentName, input, }: AzureOpenAIStreamChatArgs): AsyncGenerator<LlmStreamEvent>;
|
|
29
|
+
//# sourceMappingURL=azure-openai.utils.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"azure-openai.utils.d.ts","sourceRoot":"","sources":["../src/azure-openai.utils.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,YAAY,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAGjF,eAAO,MAAM,mBAAmB,yFAOtB,CAAC;AACX,MAAM,MAAM,gBAAgB,GAAG,CAAC,OAAO,mBAAmB,CAAC,CAAC,MAAM,CAAC,CAAC;AAEpE,MAAM,MAAM,2BAA2B,GAAG;IACxC,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,cAAc,EAAE,MAAM,CAAC;IACvB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,YAAY,CAAC,EAAE,YAAY,CAAC;CAC7B,CAAC;AAEF,MAAM,MAAM,iCAAiC,GAAG;IAC9C,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,MAAM,CAAC;CACpB,CAAC;AAWF,eAAO,MAAM,uBAAuB,GAAU,qEAO3C,2BAA2B,KAAG,OAAO,CAAC,iCAAiC,CAqCzE,CAAC;AAEF,MAAM,MAAM,8BAA8B,GAAG;IAC3C,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;CAClB,CAAC;AAEF,eAAO,MAAM,0BAA0B,GAAU,uBAG9C,8BAA8B,KAAG,OAAO,CAAC,OAAO,CAQlD,CAAC;AAMF,MAAM,MAAM,yBAAyB,GAAG;IACtC,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,cAAc,EAAE,MAAM,CAAC;IACvB,KAAK,EAAE,YAAY,CAAC;CACrB,CAAC;AAEF,wBAAuB,qBAAqB,CAAC,EAC3C,MAAM,EACN,QAAQ,EACR,cAAc,EACd,KAAK,GACN,EAAE,yBAAyB,GAAG,cAAc,CAAC,cAAc,CAAC,CAG5D"}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { AzureOpenAI } from "openai";
|
|
2
|
+
import { retry, countWords } from "@voquill/utilities";
|
|
3
|
+
import { openaiCompatibleStreamChat } from "./openai.utils";
|
|
4
|
+
export const AZURE_OPENAI_MODELS = [
|
|
5
|
+
"gpt-5-mini",
|
|
6
|
+
"gpt-5-nano",
|
|
7
|
+
"gpt-4o",
|
|
8
|
+
"gpt-4o-mini",
|
|
9
|
+
"gpt-4",
|
|
10
|
+
"gpt-35-turbo",
|
|
11
|
+
];
|
|
12
|
+
const createClient = (apiKey, endpoint) => {
|
|
13
|
+
return new AzureOpenAI({
|
|
14
|
+
apiKey: apiKey.trim(),
|
|
15
|
+
endpoint: endpoint.trim(),
|
|
16
|
+
apiVersion: "2024-10-21",
|
|
17
|
+
dangerouslyAllowBrowser: true,
|
|
18
|
+
});
|
|
19
|
+
};
|
|
20
|
+
export const azureOpenAIGenerateText = async ({ apiKey, endpoint, deploymentName, system, prompt, jsonResponse, }) => {
|
|
21
|
+
return retry({
|
|
22
|
+
retries: 3,
|
|
23
|
+
fn: async () => {
|
|
24
|
+
const client = createClient(apiKey, endpoint);
|
|
25
|
+
const messages = [];
|
|
26
|
+
if (system) {
|
|
27
|
+
messages.push({ role: "system", content: system });
|
|
28
|
+
}
|
|
29
|
+
messages.push({ role: "user", content: prompt });
|
|
30
|
+
const response = await client.chat.completions.create({
|
|
31
|
+
messages,
|
|
32
|
+
model: deploymentName,
|
|
33
|
+
temperature: 1,
|
|
34
|
+
max_completion_tokens: 1024,
|
|
35
|
+
response_format: jsonResponse
|
|
36
|
+
? {
|
|
37
|
+
type: "json_schema",
|
|
38
|
+
json_schema: {
|
|
39
|
+
name: jsonResponse.name,
|
|
40
|
+
description: jsonResponse.description,
|
|
41
|
+
schema: jsonResponse.schema,
|
|
42
|
+
strict: true,
|
|
43
|
+
},
|
|
44
|
+
}
|
|
45
|
+
: undefined,
|
|
46
|
+
});
|
|
47
|
+
const content = response.choices?.[0]?.message?.content || "";
|
|
48
|
+
return {
|
|
49
|
+
text: content,
|
|
50
|
+
tokensUsed: response.usage?.total_tokens ?? countWords(content),
|
|
51
|
+
};
|
|
52
|
+
},
|
|
53
|
+
});
|
|
54
|
+
};
|
|
55
|
+
export const azureOpenAITestIntegration = async ({ apiKey, endpoint, }) => {
|
|
56
|
+
const client = createClient(apiKey, endpoint);
|
|
57
|
+
await client.chat.completions.create({
|
|
58
|
+
messages: [{ role: "user", content: "test" }],
|
|
59
|
+
model: "gpt-4o-mini",
|
|
60
|
+
max_completion_tokens: 5,
|
|
61
|
+
});
|
|
62
|
+
return true;
|
|
63
|
+
};
|
|
64
|
+
export async function* azureOpenaiStreamChat({ apiKey, endpoint, deploymentName, input, }) {
|
|
65
|
+
const client = createClient(apiKey, endpoint);
|
|
66
|
+
yield* openaiCompatibleStreamChat(client, deploymentName, input);
|
|
67
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
export type AzureTranscriptionArgs = {
|
|
2
|
+
subscriptionKey: string;
|
|
3
|
+
region: string;
|
|
4
|
+
blob: ArrayBuffer | Buffer;
|
|
5
|
+
language?: string;
|
|
6
|
+
prompt?: string;
|
|
7
|
+
};
|
|
8
|
+
export type AzureTranscribeAudioOutput = {
|
|
9
|
+
text: string;
|
|
10
|
+
};
|
|
11
|
+
export declare const azureTranscribeAudio: ({ subscriptionKey, region, blob, language, prompt, }: AzureTranscriptionArgs) => Promise<AzureTranscribeAudioOutput>;
|
|
12
|
+
export type AzureTestIntegrationArgs = {
|
|
13
|
+
subscriptionKey: string;
|
|
14
|
+
region: string;
|
|
15
|
+
};
|
|
16
|
+
export declare const azureTestIntegration: ({ subscriptionKey, region, }: AzureTestIntegrationArgs) => Promise<boolean>;
|
|
17
|
+
export type AzureStreamingSession = {
|
|
18
|
+
writeAudioChunk: (chunk: Float32Array) => void;
|
|
19
|
+
finalize: () => Promise<string>;
|
|
20
|
+
cleanup: () => void;
|
|
21
|
+
};
|
|
22
|
+
export type CreateAzureStreamingSessionArgs = {
|
|
23
|
+
subscriptionKey: string;
|
|
24
|
+
region: string;
|
|
25
|
+
sampleRate: number;
|
|
26
|
+
language?: string;
|
|
27
|
+
prompt?: string;
|
|
28
|
+
};
|
|
29
|
+
export declare const createAzureStreamingSession: ({ subscriptionKey, region, sampleRate, language, prompt, }: CreateAzureStreamingSessionArgs) => Promise<AzureStreamingSession>;
|
|
30
|
+
//# sourceMappingURL=azure.utils.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"azure.utils.d.ts","sourceRoot":"","sources":["../src/azure.utils.ts"],"names":[],"mappings":"AAEA,MAAM,MAAM,sBAAsB,GAAG;IACnC,eAAe,EAAE,MAAM,CAAC;IACxB,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,WAAW,GAAG,MAAM,CAAC;IAC3B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB,CAAC;AAEF,MAAM,MAAM,0BAA0B,GAAG;IACvC,IAAI,EAAE,MAAM,CAAC;CACd,CAAC;AAiGF,eAAO,MAAM,oBAAoB,GAAU,sDAMxC,sBAAsB,KAAG,OAAO,CAAC,0BAA0B,CAwD7D,CAAC;AAEF,MAAM,MAAM,wBAAwB,GAAG;IACrC,eAAe,EAAE,MAAM,CAAC;IACxB,MAAM,EAAE,MAAM,CAAC;CAChB,CAAC;AAEF,eAAO,MAAM,oBAAoB,GAAU,8BAGxC,wBAAwB,KAAG,OAAO,CAAC,OAAO,CAa5C,CAAC;AAEF,MAAM,MAAM,qBAAqB,GAAG;IAClC,eAAe,EAAE,CAAC,KAAK,EAAE,YAAY,KAAK,IAAI,CAAC;IAC/C,QAAQ,EAAE,MAAM,OAAO,CAAC,MAAM,CAAC,CAAC;IAChC,OAAO,EAAE,MAAM,IAAI,CAAC;CACrB,CAAC;AAEF,MAAM,MAAM,+BAA+B,GAAG;IAC5C,eAAe,EAAE,MAAM,CAAC;IACxB,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB,CAAC;AAEF,eAAO,MAAM,2BAA2B,GAAU,4DAM/C,+BAA+B,KAAG,OAAO,CAAC,qBAAqB,CAyIjE,CAAC"}
|
|
@@ -0,0 +1,253 @@
|
|
|
1
|
+
import * as sdk from "microsoft-cognitiveservices-speech-sdk";
|
|
2
|
+
const AZURE_LOCALE_REGEX = /^[a-z]{2,3}-[A-Z]{2}$/;
|
|
3
|
+
const mapToAzureLocale = (language) => {
|
|
4
|
+
if (!language || language.trim() === "") {
|
|
5
|
+
return "en-US";
|
|
6
|
+
}
|
|
7
|
+
const trimmedLanguage = language.trim();
|
|
8
|
+
if (trimmedLanguage.includes("-")) {
|
|
9
|
+
if (AZURE_LOCALE_REGEX.test(trimmedLanguage)) {
|
|
10
|
+
return trimmedLanguage;
|
|
11
|
+
}
|
|
12
|
+
const baseLang = trimmedLanguage.split("-")[0];
|
|
13
|
+
if (baseLang) {
|
|
14
|
+
return mapToAzureLocale(baseLang);
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
const languageMap = {
|
|
18
|
+
en: "en-US",
|
|
19
|
+
es: "es-ES",
|
|
20
|
+
fr: "fr-FR",
|
|
21
|
+
de: "de-DE",
|
|
22
|
+
it: "it-IT",
|
|
23
|
+
pt: "pt-PT",
|
|
24
|
+
ru: "ru-RU",
|
|
25
|
+
ja: "ja-JP",
|
|
26
|
+
ko: "ko-KR",
|
|
27
|
+
zh: "zh-CN",
|
|
28
|
+
ar: "ar-SA",
|
|
29
|
+
nl: "nl-NL",
|
|
30
|
+
sv: "sv-SE",
|
|
31
|
+
tr: "tr-TR",
|
|
32
|
+
pl: "pl-PL",
|
|
33
|
+
ca: "ca-ES",
|
|
34
|
+
id: "id-ID",
|
|
35
|
+
hi: "hi-IN",
|
|
36
|
+
fi: "fi-FI",
|
|
37
|
+
vi: "vi-VN",
|
|
38
|
+
he: "he-IL",
|
|
39
|
+
uk: "uk-UA",
|
|
40
|
+
el: "el-GR",
|
|
41
|
+
ms: "ms-MY",
|
|
42
|
+
cs: "cs-CZ",
|
|
43
|
+
ro: "ro-RO",
|
|
44
|
+
da: "da-DK",
|
|
45
|
+
hu: "hu-HU",
|
|
46
|
+
ta: "ta-IN",
|
|
47
|
+
no: "nb-NO",
|
|
48
|
+
th: "th-TH",
|
|
49
|
+
ur: "ur-PK",
|
|
50
|
+
hr: "hr-HR",
|
|
51
|
+
bg: "bg-BG",
|
|
52
|
+
lt: "lt-LT",
|
|
53
|
+
sk: "sk-SK",
|
|
54
|
+
sl: "sl-SI",
|
|
55
|
+
et: "et-EE",
|
|
56
|
+
lv: "lv-LV",
|
|
57
|
+
fa: "fa-IR",
|
|
58
|
+
sr: "sr-RS",
|
|
59
|
+
bn: "bn-IN",
|
|
60
|
+
af: "af-ZA",
|
|
61
|
+
hy: "hy-AM",
|
|
62
|
+
az: "az-AZ",
|
|
63
|
+
eu: "eu-ES",
|
|
64
|
+
bs: "bs-BA",
|
|
65
|
+
gl: "gl-ES",
|
|
66
|
+
gu: "gu-IN",
|
|
67
|
+
is: "is-IS",
|
|
68
|
+
kk: "kk-KZ",
|
|
69
|
+
kn: "kn-IN",
|
|
70
|
+
km: "km-KH",
|
|
71
|
+
lo: "lo-LA",
|
|
72
|
+
mk: "mk-MK",
|
|
73
|
+
ml: "ml-IN",
|
|
74
|
+
mr: "mr-IN",
|
|
75
|
+
mn: "mn-MN",
|
|
76
|
+
ne: "ne-NP",
|
|
77
|
+
ps: "ps-AF",
|
|
78
|
+
si: "si-LK",
|
|
79
|
+
sw: "sw-KE",
|
|
80
|
+
te: "te-IN",
|
|
81
|
+
uz: "uz-UZ",
|
|
82
|
+
cy: "cy-GB",
|
|
83
|
+
am: "am-ET",
|
|
84
|
+
ka: "ka-GE",
|
|
85
|
+
my: "my-MM",
|
|
86
|
+
so: "so-SO",
|
|
87
|
+
sq: "sq-AL",
|
|
88
|
+
};
|
|
89
|
+
return languageMap[trimmedLanguage] || "en-US";
|
|
90
|
+
};
|
|
91
|
+
export const azureTranscribeAudio = async ({ subscriptionKey, region, blob, language = "en-US", prompt, }) => {
|
|
92
|
+
return new Promise((resolve, reject) => {
|
|
93
|
+
const azureLocale = mapToAzureLocale(language);
|
|
94
|
+
const trimmedRegion = region.trim();
|
|
95
|
+
const trimmedKey = subscriptionKey.trim();
|
|
96
|
+
const speechConfig = sdk.SpeechConfig.fromSubscription(trimmedKey, trimmedRegion);
|
|
97
|
+
speechConfig.speechRecognitionLanguage = azureLocale;
|
|
98
|
+
const audioBuffer = blob instanceof ArrayBuffer ? blob : blob.buffer;
|
|
99
|
+
const dataView = new DataView(audioBuffer);
|
|
100
|
+
const sampleRate = dataView.getUint32(24, true);
|
|
101
|
+
const bitsPerSample = dataView.getUint16(34, true);
|
|
102
|
+
const channels = dataView.getUint16(22, true);
|
|
103
|
+
const audioFormat = sdk.AudioStreamFormat.getWaveFormatPCM(sampleRate, bitsPerSample, channels);
|
|
104
|
+
const pushStream = sdk.AudioInputStream.createPushStream(audioFormat);
|
|
105
|
+
const uint8Array = new Uint8Array(audioBuffer);
|
|
106
|
+
const wavHeaderSize = 44;
|
|
107
|
+
const audioData = uint8Array.slice(wavHeaderSize);
|
|
108
|
+
pushStream.write(audioData.buffer);
|
|
109
|
+
pushStream.close();
|
|
110
|
+
const audioConfig = sdk.AudioConfig.fromStreamInput(pushStream);
|
|
111
|
+
const recognizer = new sdk.SpeechRecognizer(speechConfig, audioConfig);
|
|
112
|
+
if (prompt) {
|
|
113
|
+
const phraseListGrammar = sdk.PhraseListGrammar.fromRecognizer(recognizer);
|
|
114
|
+
const phrases = prompt.split(/[\s,]+/).filter(p => p.length > 0);
|
|
115
|
+
phrases.forEach(phrase => phraseListGrammar.addPhrase(phrase));
|
|
116
|
+
}
|
|
117
|
+
recognizer.recognizeOnceAsync((result) => {
|
|
118
|
+
recognizer.close();
|
|
119
|
+
if (result.reason === sdk.ResultReason.RecognizedSpeech) {
|
|
120
|
+
resolve({ text: result.text });
|
|
121
|
+
}
|
|
122
|
+
else if (result.reason === sdk.ResultReason.NoMatch) {
|
|
123
|
+
resolve({ text: "" });
|
|
124
|
+
}
|
|
125
|
+
else {
|
|
126
|
+
reject(new Error(`Azure recognition failed: ${result.errorDetails}`));
|
|
127
|
+
}
|
|
128
|
+
}, (error) => {
|
|
129
|
+
recognizer.close();
|
|
130
|
+
reject(new Error(`Azure API request failed: ${error}`));
|
|
131
|
+
});
|
|
132
|
+
});
|
|
133
|
+
};
|
|
134
|
+
export const azureTestIntegration = async ({ subscriptionKey, region, }) => {
|
|
135
|
+
try {
|
|
136
|
+
const silentBuffer = new ArrayBuffer(0);
|
|
137
|
+
await azureTranscribeAudio({
|
|
138
|
+
subscriptionKey,
|
|
139
|
+
region,
|
|
140
|
+
blob: silentBuffer,
|
|
141
|
+
});
|
|
142
|
+
return true;
|
|
143
|
+
}
|
|
144
|
+
catch (error) {
|
|
145
|
+
const errorMessage = error instanceof Error ? error.message : "";
|
|
146
|
+
return !errorMessage.includes("authentication") && !errorMessage.includes("subscription");
|
|
147
|
+
}
|
|
148
|
+
};
|
|
149
|
+
export const createAzureStreamingSession = async ({ subscriptionKey, region, sampleRate, language, prompt, }) => {
|
|
150
|
+
return new Promise((resolve, reject) => {
|
|
151
|
+
const azureLocale = mapToAzureLocale(language);
|
|
152
|
+
const trimmedRegion = region.trim();
|
|
153
|
+
const trimmedKey = subscriptionKey.trim();
|
|
154
|
+
const speechConfig = sdk.SpeechConfig.fromSubscription(trimmedKey, trimmedRegion);
|
|
155
|
+
speechConfig.speechRecognitionLanguage = azureLocale;
|
|
156
|
+
const audioFormat = sdk.AudioStreamFormat.getWaveFormatPCM(sampleRate, 16, 1);
|
|
157
|
+
const pushStream = sdk.AudioInputStream.createPushStream(audioFormat);
|
|
158
|
+
const audioConfig = sdk.AudioConfig.fromStreamInput(pushStream);
|
|
159
|
+
const recognizer = new sdk.SpeechRecognizer(speechConfig, audioConfig);
|
|
160
|
+
if (prompt) {
|
|
161
|
+
const phraseListGrammar = sdk.PhraseListGrammar.fromRecognizer(recognizer);
|
|
162
|
+
const phrases = prompt.split(/[\s,]+/).filter(p => p.length > 0);
|
|
163
|
+
phrases.forEach(phrase => phraseListGrammar.addPhrase(phrase));
|
|
164
|
+
}
|
|
165
|
+
let fullTranscript = "";
|
|
166
|
+
let isFinalized = false;
|
|
167
|
+
recognizer.recognized = (_s, e) => {
|
|
168
|
+
if (e.result.reason === sdk.ResultReason.RecognizedSpeech) {
|
|
169
|
+
fullTranscript += (fullTranscript ? " " : "") + e.result.text;
|
|
170
|
+
console.log("[Azure Streaming] Recognized segment, length:", e.result.text.length);
|
|
171
|
+
}
|
|
172
|
+
else if (e.result.reason === sdk.ResultReason.NoMatch) {
|
|
173
|
+
console.log("[Azure Streaming] No speech recognized in segment");
|
|
174
|
+
}
|
|
175
|
+
};
|
|
176
|
+
recognizer.recognizing = (_s, e) => {
|
|
177
|
+
if (e.result.reason === sdk.ResultReason.RecognizingSpeech) {
|
|
178
|
+
console.log("[Azure Streaming] Recognizing, length:", e.result.text.length);
|
|
179
|
+
}
|
|
180
|
+
};
|
|
181
|
+
recognizer.canceled = (_s, e) => {
|
|
182
|
+
console.error("[Azure Streaming] Recognition canceled:", e.errorDetails);
|
|
183
|
+
if (e.reason === sdk.CancellationReason.Error) {
|
|
184
|
+
console.error("[Azure Streaming] Error code:", e.errorCode);
|
|
185
|
+
}
|
|
186
|
+
};
|
|
187
|
+
recognizer.sessionStarted = () => {
|
|
188
|
+
console.log("[Azure Streaming] Session started");
|
|
189
|
+
};
|
|
190
|
+
recognizer.sessionStopped = () => {
|
|
191
|
+
console.log("[Azure Streaming] Session stopped");
|
|
192
|
+
};
|
|
193
|
+
recognizer.startContinuousRecognitionAsync(() => {
|
|
194
|
+
console.log("[Azure Streaming] Continuous recognition started");
|
|
195
|
+
const writeAudioChunk = (chunk) => {
|
|
196
|
+
if (isFinalized) {
|
|
197
|
+
console.warn("[Azure Streaming] Attempted to write chunk after finalization");
|
|
198
|
+
return;
|
|
199
|
+
}
|
|
200
|
+
const pcm16Buffer = new ArrayBuffer(chunk.length * 2);
|
|
201
|
+
const pcm16View = new Int16Array(pcm16Buffer);
|
|
202
|
+
for (let i = 0; i < chunk.length; i++) {
|
|
203
|
+
const s = Math.max(-1, Math.min(1, chunk[i] ?? 0));
|
|
204
|
+
pcm16View[i] = s < 0 ? s * 0x8000 : s * 0x7FFF;
|
|
205
|
+
}
|
|
206
|
+
pushStream.write(pcm16Buffer);
|
|
207
|
+
};
|
|
208
|
+
const finalize = () => {
|
|
209
|
+
return new Promise((resolveFinalize) => {
|
|
210
|
+
if (isFinalized) {
|
|
211
|
+
console.log("[Azure Streaming] Already finalized, returning transcript");
|
|
212
|
+
resolveFinalize(fullTranscript);
|
|
213
|
+
return;
|
|
214
|
+
}
|
|
215
|
+
isFinalized = true;
|
|
216
|
+
console.log("[Azure Streaming] Finalizing session...");
|
|
217
|
+
pushStream.close();
|
|
218
|
+
const timeout = setTimeout(() => {
|
|
219
|
+
console.log("[Azure Streaming] Timeout reached, finalizing with transcript length:", fullTranscript.length);
|
|
220
|
+
recognizer.close();
|
|
221
|
+
resolveFinalize(fullTranscript);
|
|
222
|
+
}, 2000);
|
|
223
|
+
recognizer.stopContinuousRecognitionAsync(() => {
|
|
224
|
+
clearTimeout(timeout);
|
|
225
|
+
console.log("[Azure Streaming] Recognition stopped, final transcript length:", fullTranscript.length);
|
|
226
|
+
recognizer.close();
|
|
227
|
+
resolveFinalize(fullTranscript);
|
|
228
|
+
}, (error) => {
|
|
229
|
+
clearTimeout(timeout);
|
|
230
|
+
console.error("[Azure Streaming] Error stopping recognition:", error);
|
|
231
|
+
recognizer.close();
|
|
232
|
+
resolveFinalize(fullTranscript);
|
|
233
|
+
});
|
|
234
|
+
});
|
|
235
|
+
};
|
|
236
|
+
const cleanup = () => {
|
|
237
|
+
if (!isFinalized) {
|
|
238
|
+
pushStream.close();
|
|
239
|
+
recognizer.close();
|
|
240
|
+
}
|
|
241
|
+
};
|
|
242
|
+
resolve({
|
|
243
|
+
writeAudioChunk,
|
|
244
|
+
finalize,
|
|
245
|
+
cleanup,
|
|
246
|
+
});
|
|
247
|
+
}, (error) => {
|
|
248
|
+
console.error("[Azure Streaming] Failed to start recognition:", error);
|
|
249
|
+
recognizer.close();
|
|
250
|
+
reject(new Error(`Failed to start Azure recognition: ${error}`));
|
|
251
|
+
});
|
|
252
|
+
});
|
|
253
|
+
};
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import type { JsonResponse, LlmChatInput, LlmStreamEvent } from "@voquill/types";
|
|
2
|
+
export declare const CLAUDE_MODELS: readonly ["claude-opus-4-5-20251101", "claude-opus-4-5", "claude-3-7-sonnet-latest", "claude-3-7-sonnet-20250219", "claude-3-5-haiku-latest", "claude-3-5-haiku-20241022", "claude-haiku-4-5", "claude-haiku-4-5-20251001", "claude-sonnet-4-20250514", "claude-sonnet-4-0", "claude-4-sonnet-20250514", "claude-sonnet-4-5", "claude-sonnet-4-5-20250929", "claude-opus-4-0", "claude-opus-4-20250514", "claude-4-opus-20250514", "claude-opus-4-1-20250805", "claude-3-opus-latest", "claude-3-opus-20240229", "claude-3-haiku-20240307"];
|
|
3
|
+
export type ClaudeModel = (typeof CLAUDE_MODELS)[number];
|
|
4
|
+
export type ClaudeGenerateTextArgs = {
|
|
5
|
+
apiKey: string;
|
|
6
|
+
model?: ClaudeModel;
|
|
7
|
+
system?: string;
|
|
8
|
+
prompt: string;
|
|
9
|
+
jsonResponse?: JsonResponse;
|
|
10
|
+
};
|
|
11
|
+
export type ClaudeGenerateResponseOutput = {
|
|
12
|
+
text: string;
|
|
13
|
+
tokensUsed: number;
|
|
14
|
+
};
|
|
15
|
+
export declare const claudeGenerateTextResponse: ({ apiKey, model, system, prompt, jsonResponse, }: ClaudeGenerateTextArgs) => Promise<ClaudeGenerateResponseOutput>;
|
|
16
|
+
export type ClaudeTestIntegrationArgs = {
|
|
17
|
+
apiKey: string;
|
|
18
|
+
};
|
|
19
|
+
export declare const claudeTestIntegration: ({ apiKey, }: ClaudeTestIntegrationArgs) => Promise<boolean>;
|
|
20
|
+
export type ClaudeStreamChatArgs = {
|
|
21
|
+
apiKey: string;
|
|
22
|
+
model: string;
|
|
23
|
+
input: LlmChatInput;
|
|
24
|
+
};
|
|
25
|
+
export declare function claudeStreamChat({ apiKey, model, input, }: ClaudeStreamChatArgs): AsyncGenerator<LlmStreamEvent>;
|
|
26
|
+
//# sourceMappingURL=claude.utils.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"claude.utils.d.ts","sourceRoot":"","sources":["../src/claude.utils.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EACV,YAAY,EACZ,YAAY,EAGZ,cAAc,EACf,MAAM,gBAAgB,CAAC;AAExB,eAAO,MAAM,aAAa,6gBAqBhB,CAAC;AACX,MAAM,MAAM,WAAW,GAAG,CAAC,OAAO,aAAa,CAAC,CAAC,MAAM,CAAC,CAAC;AASzD,MAAM,MAAM,sBAAsB,GAAG;IACnC,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,WAAW,CAAC;IACpB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,YAAY,CAAC,EAAE,YAAY,CAAC;CAC7B,CAAC;AAEF,MAAM,MAAM,4BAA4B,GAAG;IACzC,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,MAAM,CAAC;CACpB,CAAC;AAEF,eAAO,MAAM,0BAA0B,GAAU,kDAM9C,sBAAsB,KAAG,OAAO,CAAC,4BAA4B,CAoC/D,CAAC;AAEF,MAAM,MAAM,yBAAyB,GAAG;IACtC,MAAM,EAAE,MAAM,CAAC;CAChB,CAAC;AAEF,eAAO,MAAM,qBAAqB,GAAU,aAEzC,yBAAyB,KAAG,OAAO,CAAC,OAAO,CAoB7C,CAAC;AAiFF,MAAM,MAAM,oBAAoB,GAAG;IACjC,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,YAAY,CAAC;CACrB,CAAC;AAEF,wBAAuB,gBAAgB,CAAC,EACtC,MAAM,EACN,KAAK,EACL,KAAK,GACN,EAAE,oBAAoB,GAAG,cAAc,CAAC,cAAc,CAAC,CA0GvD"}
|