Skip to content

Commit a3f93dd

Browse files
committed
add speech job support
1 parent 8fa452a commit a3f93dd

File tree

16 files changed

+173
-13
lines changed

16 files changed

+173
-13
lines changed

src/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ export * from "./jobs/embedding";
66
export * from "./jobs/models";
77

88
export * from "./providers/anthropic";
9+
export * from "./providers/elevenlabs";
910
export * from "./providers/deepseek";
1011
export * from "./providers/fal";
1112
export * from "./providers/fireworks";

src/jobs/load.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { z } from "zod";
22
import { anthropic, AnthropicJobSchema } from "~/providers/anthropic";
33
import { deepseek, DeepseekJobSchema } from "~/providers/deepseek";
4+
import { elevenlabs, ElevenlabsJobSchema } from "~/providers/elevenlabs";
45
import { fal, FalJobSchema } from "~/providers/fal";
56
import { GoogleJobSchema } from "~/providers/google";
67
import { LumaJobSchema } from "~/providers/luma";
@@ -11,6 +12,7 @@ import { voyage, VoyageJobSchema } from "~/providers/voyage";
1112
export const JobSchema = z.union([
1213
AnthropicJobSchema,
1314
DeepseekJobSchema,
15+
ElevenlabsJobSchema,
1416
FalJobSchema,
1517
GoogleJobSchema,
1618
LumaJobSchema,
@@ -31,6 +33,8 @@ export function load(obj: Job) {
3133
provider = anthropic(obj.options);
3234
} else if (obj.provider === "deepseek") {
3335
provider = deepseek(obj.options);
36+
} else if (obj.provider === "elevenlabs") {
37+
provider = elevenlabs(obj.options);
3438
} else if (obj.provider === "fal") {
3539
provider = fal(obj.options);
3640
} else if (obj.provider === "ollama") {
@@ -59,6 +63,9 @@ export function load(obj: Job) {
5963
if (obj.type === "models" && "models" in provider) {
6064
builder = provider.models();
6165
}
66+
if (obj.type === "speech" && "speech" in provider) {
67+
builder = provider.speech(obj.input.model);
68+
}
6269

6370
if (!builder) {
6471
throw new Error("Failed to load job");

src/jobs/schema.ts

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import { z } from "zod";
22

33
export const JobProviderSchema = z.enum([
44
"anthropic",
5+
"elevenlabs",
56
"deepseek",
67
"fal",
78
"google",
@@ -11,7 +12,13 @@ export const JobProviderSchema = z.enum([
1112
"voyage",
1213
]);
1314

14-
export const JobTypeSchema = z.enum(["chat", "image", "models", "embedding"]);
15+
export const JobTypeSchema = z.enum([
16+
"chat",
17+
"image",
18+
"models",
19+
"embedding",
20+
"speech",
21+
]);
1522

1623
export const JobOptionsSchema = z.object({
1724
apiKey: z.string().optional(),

src/jobs/speech/builder.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
import { JobBuilder } from "~/jobs/builder";
2+
import type { SpeechInput, SpeechOutput } from "./schema";
3+
4+
export class SpeechJobBuilder extends JobBuilder<SpeechInput, SpeechOutput> {
5+
input: SpeechInput;
6+
7+
constructor(model: string) {
8+
super();
9+
this.type = "speech";
10+
this.input = {
11+
model: model,
12+
};
13+
}
14+
}

src/jobs/speech/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
export * from "./schema";
2+
export * from "./builder";

src/jobs/speech/schema.ts

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import { z } from "zod";
2+
3+
export const SpeechInputSchema = z.object({
4+
model: z.string(),
5+
});
6+
7+
export const SpeechOutputSchema = z.object({});
8+
9+
export const SpeechJobSchema = z.object({
10+
type: z.literal("speech"),
11+
input: SpeechInputSchema,
12+
output: SpeechOutputSchema.optional(),
13+
});
14+
15+
export type SpeechInput = z.infer<typeof SpeechInputSchema>;
16+
export type SpeechOutput = z.infer<typeof SpeechOutputSchema>;

src/providers/elevenlabs/index.ts

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
import type { JobOptions } from "~/jobs/schema";
2+
import { z } from "zod";
3+
import { SpeechJobBuilder, SpeechJobSchema } from "~/jobs/speech";
4+
5+
export function elevenlabs(options?: JobOptions) {
6+
options = options || {};
7+
options.apiKey = options.apiKey || process.env.ELEVENLABS_API_KEY;
8+
9+
return {
10+
speech(model: string) {
11+
return new ElevenlabsSpeechJobBuilder(options, model);
12+
},
13+
};
14+
}
15+
16+
class ElevenlabsSpeechJobBuilder extends SpeechJobBuilder {
17+
constructor(options: JobOptions, model: string) {
18+
super(model);
19+
this.provider = "elevenlabs";
20+
this.options = options;
21+
}
22+
}
23+
24+
export const ElevenlabsBaseJobSchema = z.object({
25+
provider: z.literal("fal"),
26+
});
27+
28+
export const ElevenlabsImageJobSchema = SpeechJobSchema.extend(
29+
ElevenlabsBaseJobSchema
30+
);
31+
32+
export const ElevenlabsJobSchema = z.discriminatedUnion("type", [
33+
ElevenlabsImageJobSchema,
34+
]);

src/providers/fal/image.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
import { ImageJobBuilder } from "~/jobs/image";
21
import type { JobOptions } from "~/jobs/schema";
2+
import { ImageJobBuilder } from "~/jobs/image";
33

44
export class FalImageJobBuilder extends ImageJobBuilder {
55
constructor(options: JobOptions, model: string) {

src/providers/luma/index.ts

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,6 @@ export function luma(options?: JobOptions) {
1515
options = options || {};
1616
options.apiKey = options.apiKey || process.env.LUMA_API_KEY;
1717

18-
if (!options.apiKey) {
19-
throw new Error("Luma API key is required");
20-
}
21-
2218
return {
2319
image(model: string) {
2420
return new LumaImageJobBuilder(options, model);

src/providers/openai/index.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,15 +3,12 @@ import { OpenAIChatJobBuilder } from "~/providers/openai/chat";
33
import { OpenAIImageJobBuilder } from "~/providers/openai/image";
44
import { OpenAIEmbeddingJobBuilder } from "~/providers/openai/embedding";
55
import { OpenAIModelsJobBuilder } from "~/providers/openai/models";
6+
import { OpenAISpeechJobBuilder } from "~/providers/openai/speech";
67

78
export function openai(options?: JobOptions) {
89
options = options || {};
910
options.apiKey = options.apiKey || process.env.OPENAI_API_KEY;
1011

11-
if (!options.apiKey) {
12-
throw new Error("OpenAI API key is required");
13-
}
14-
1512
return {
1613
chat(model: string) {
1714
return new OpenAIChatJobBuilder(options, model);
@@ -25,6 +22,9 @@ export function openai(options?: JobOptions) {
2522
models() {
2623
return new OpenAIModelsJobBuilder(options);
2724
},
25+
speech(model: string) {
26+
return new OpenAISpeechJobBuilder(options, model);
27+
},
2828
};
2929
}
3030

0 commit comments

Comments
 (0)