@tanstack/ai-lovable 0.0.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/LICENSE +21 -0
- package/README.md +37 -0
- package/dist/esm/adapters/embedding.d.ts +16 -0
- package/dist/esm/adapters/embedding.js +66 -0
- package/dist/esm/adapters/embedding.js.map +1 -0
- package/dist/esm/adapters/factory.d.ts +16 -0
- package/dist/esm/adapters/factory.js +28 -0
- package/dist/esm/adapters/factory.js.map +1 -0
- package/dist/esm/adapters/image.d.ts +26 -0
- package/dist/esm/adapters/image.js +145 -0
- package/dist/esm/adapters/image.js.map +1 -0
- package/dist/esm/adapters/responses-text.d.ts +24 -0
- package/dist/esm/adapters/responses-text.js +30 -0
- package/dist/esm/adapters/responses-text.js.map +1 -0
- package/dist/esm/adapters/summarize.d.ts +9 -0
- package/dist/esm/adapters/summarize.js +17 -0
- package/dist/esm/adapters/summarize.js.map +1 -0
- package/dist/esm/adapters/text.d.ts +20 -0
- package/dist/esm/adapters/text.js +21 -0
- package/dist/esm/adapters/text.js.map +1 -0
- package/dist/esm/adapters/transcription.d.ts +19 -0
- package/dist/esm/adapters/transcription.js +123 -0
- package/dist/esm/adapters/transcription.js.map +1 -0
- package/dist/esm/adapters/tts.d.ts +16 -0
- package/dist/esm/adapters/tts.js +69 -0
- package/dist/esm/adapters/tts.js.map +1 -0
- package/dist/esm/adapters/video.d.ts +41 -0
- package/dist/esm/adapters/video.js +164 -0
- package/dist/esm/adapters/video.js.map +1 -0
- package/dist/esm/audio/transcription-provider-options.d.ts +6 -0
- package/dist/esm/audio/tts-provider-options.d.ts +8 -0
- package/dist/esm/byok.d.ts +1 -0
- package/dist/esm/byok.js +11 -0
- package/dist/esm/byok.js.map +1 -0
- package/dist/esm/embedding/embedding-provider-options.d.ts +9 -0
- package/dist/esm/image/image-input-to-file.d.ts +8 -0
- package/dist/esm/image/image-input-to-file.js +47 -0
- package/dist/esm/image/image-input-to-file.js.map +1 -0
- package/dist/esm/image/image-provider-options.d.ts +12 -0
- package/dist/esm/index.d.ts +26 -0
- package/dist/esm/index.js +12 -0
- package/dist/esm/message-types.d.ts +44 -0
- package/dist/esm/model-meta.d.ts +71 -0
- package/dist/esm/model-meta.js +63 -0
- package/dist/esm/model-meta.js.map +1 -0
- package/dist/esm/text/responses-provider-options.d.ts +3 -0
- package/dist/esm/text/text-provider-options.d.ts +17 -0
- package/dist/esm/utils/client.d.ts +14 -0
- package/dist/esm/utils/client.js +35 -0
- package/dist/esm/utils/client.js.map +1 -0
- package/dist/esm/video/video-provider-options.d.ts +19 -0
- package/dist/esm/video/video-provider-options.js +47 -0
- package/dist/esm/video/video-provider-options.js.map +1 -0
- package/package.json +79 -0
- package/src/adapters/embedding.ts +102 -0
- package/src/adapters/factory.ts +78 -0
- package/src/adapters/image.ts +304 -0
- package/src/adapters/responses-text.ts +66 -0
- package/src/adapters/summarize.ts +35 -0
- package/src/adapters/text.ts +49 -0
- package/src/adapters/transcription.ts +226 -0
- package/src/adapters/tts.ts +97 -0
- package/src/adapters/video.ts +303 -0
- package/src/audio/transcription-provider-options.ts +7 -0
- package/src/audio/tts-provider-options.ts +21 -0
- package/src/byok.ts +7 -0
- package/src/embedding/embedding-provider-options.ts +9 -0
- package/src/image/image-input-to-file.ts +81 -0
- package/src/image/image-provider-options.ts +17 -0
- package/src/index.ts +125 -0
- package/src/message-types.ts +45 -0
- package/src/model-meta.ts +161 -0
- package/src/text/responses-provider-options.ts +8 -0
- package/src/text/text-provider-options.ts +18 -0
- package/src/utils/client.ts +50 -0
- package/src/video/video-provider-options.ts +128 -0
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module @tanstack/ai-lovable
|
|
3
|
+
*
|
|
4
|
+
* Lovable AI Gateway adapter for TanStack AI.
|
|
5
|
+
*/
|
|
6
|
+
export { LovableTextAdapter, type LovableTextConfig, type LovableTextProviderOptions, } from './adapters/text.js';
|
|
7
|
+
export { createLovableText, lovableText, type LovableTextApi, type LovableResponsesApiConfig, type LovableChatApiConfig, } from './adapters/factory.js';
|
|
8
|
+
export { LovableResponsesTextAdapter, createLovableResponsesText, lovableResponsesText, type LovableResponsesTextConfig, type LovableResponsesTextProviderOptions, } from './adapters/responses-text.js';
|
|
9
|
+
export { createLovableSummarize, lovableSummarize, type LovableSummarizeConfig, type LovableSummarizeModel, } from './adapters/summarize.js';
|
|
10
|
+
export { LovableEmbeddingAdapter, createLovableEmbedding, lovableEmbedding, type LovableEmbeddingConfig, } from './adapters/embedding.js';
|
|
11
|
+
export type { LovableEmbeddingProviderOptions } from './embedding/embedding-provider-options.js';
|
|
12
|
+
export { LovableImageAdapter, createLovableImage, lovableImage, type LovableImageConfig, } from './adapters/image.js';
|
|
13
|
+
export type { LovableImageProviderOptions } from './image/image-provider-options.js';
|
|
14
|
+
/**
|
|
15
|
+
* @experimental Video generation is an experimental feature and may change.
|
|
16
|
+
*/
|
|
17
|
+
export { LovableVideoAdapter, createLovableVideo, lovableVideo, type LovableVideoConfig, } from './adapters/video.js';
|
|
18
|
+
export type { LovableVideoProviderOptions, LovableVideoSize, LovableHdVideoSize, Lovable4kVideoSize, LovableVideoDuration, LovableVideoSeconds, } from './video/video-provider-options.js';
|
|
19
|
+
export { LovableTTSAdapter, createLovableSpeech, lovableSpeech, type LovableTTSConfig, } from './adapters/tts.js';
|
|
20
|
+
export type { LovableTTSProviderOptions, LovableTTSVoice, LovableTTSFormat, } from './audio/tts-provider-options.js';
|
|
21
|
+
export { LovableTranscriptionAdapter, createLovableTranscription, lovableTranscription, type LovableTranscriptionConfig, } from './adapters/transcription.js';
|
|
22
|
+
export type { LovableTranscriptionProviderOptions } from './audio/transcription-provider-options.js';
|
|
23
|
+
export { LOVABLE_CHAT_MODELS, LOVABLE_IMAGE_MODELS, LOVABLE_VIDEO_MODELS, LOVABLE_EMBEDDING_MODELS, LOVABLE_TTS_MODELS, LOVABLE_TRANSCRIPTION_MODELS, } from './model-meta.js';
|
|
24
|
+
export type { LovableChatModel, LovableModelId, LovableChatModelProviderOptionsByName, LovableModelInputModalitiesByName, LovableImageModel, LovableVideoModel, LovableEmbeddingModel, LovableTTSModel, LovableTranscriptionModel, ResolveProviderOptions, ResolveInputModalities, } from './model-meta.js';
|
|
25
|
+
export type { LovableTextMetadata, LovableImageMetadata, LovableAudioMetadata, LovableVideoMetadata, LovableDocumentMetadata, LovableMessageMetadataByModality, } from './message-types.js';
|
|
26
|
+
export { getLovableApiKeyFromEnv, lovableGatewayHeaders, type LovableClientConfig, } from './utils/client.js';
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { getLovableApiKeyFromEnv, lovableGatewayHeaders } from "./utils/client.js";
|
|
2
|
+
import { LovableTextAdapter } from "./adapters/text.js";
|
|
3
|
+
import { LovableResponsesTextAdapter, createLovableResponsesText, lovableResponsesText } from "./adapters/responses-text.js";
|
|
4
|
+
import { createLovableText, lovableText } from "./adapters/factory.js";
|
|
5
|
+
import { createLovableSummarize, lovableSummarize } from "./adapters/summarize.js";
|
|
6
|
+
import { LovableEmbeddingAdapter, createLovableEmbedding, lovableEmbedding } from "./adapters/embedding.js";
|
|
7
|
+
import { LovableImageAdapter, createLovableImage, lovableImage } from "./adapters/image.js";
|
|
8
|
+
import { LovableVideoAdapter, createLovableVideo, lovableVideo } from "./adapters/video.js";
|
|
9
|
+
import { LovableTTSAdapter, createLovableSpeech, lovableSpeech } from "./adapters/tts.js";
|
|
10
|
+
import { LovableTranscriptionAdapter, createLovableTranscription, lovableTranscription } from "./adapters/transcription.js";
|
|
11
|
+
import { LOVABLE_CHAT_MODELS, LOVABLE_EMBEDDING_MODELS, LOVABLE_IMAGE_MODELS, LOVABLE_TRANSCRIPTION_MODELS, LOVABLE_TTS_MODELS, LOVABLE_VIDEO_MODELS } from "./model-meta.js";
|
|
12
|
+
export { LOVABLE_CHAT_MODELS, LOVABLE_EMBEDDING_MODELS, LOVABLE_IMAGE_MODELS, LOVABLE_TRANSCRIPTION_MODELS, LOVABLE_TTS_MODELS, LOVABLE_VIDEO_MODELS, LovableEmbeddingAdapter, LovableImageAdapter, LovableResponsesTextAdapter, LovableTTSAdapter, LovableTextAdapter, LovableTranscriptionAdapter, LovableVideoAdapter, createLovableEmbedding, createLovableImage, createLovableResponsesText, createLovableSpeech, createLovableSummarize, createLovableText, createLovableTranscription, createLovableVideo, getLovableApiKeyFromEnv, lovableEmbedding, lovableGatewayHeaders, lovableImage, lovableResponsesText, lovableSpeech, lovableSummarize, lovableText, lovableTranscription, lovableVideo };
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Metadata for Lovable AI Gateway document content parts.
|
|
3
|
+
*/
|
|
4
|
+
export interface LovableDocumentMetadata {
|
|
5
|
+
}
|
|
6
|
+
/**
|
|
7
|
+
* Metadata for Lovable AI Gateway text content parts.
|
|
8
|
+
*/
|
|
9
|
+
export interface LovableTextMetadata {
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Metadata for Lovable AI Gateway image content parts.
|
|
13
|
+
*/
|
|
14
|
+
export interface LovableImageMetadata {
|
|
15
|
+
/**
|
|
16
|
+
* Specifies the detail level of the image.
|
|
17
|
+
* - 'auto': Let the model decide based on image size and content
|
|
18
|
+
* - 'low': Use low resolution processing (faster, cheaper, less detail)
|
|
19
|
+
* - 'high': Use high resolution processing (slower, more expensive, more detail)
|
|
20
|
+
*
|
|
21
|
+
* @default 'auto'
|
|
22
|
+
*/
|
|
23
|
+
detail?: 'auto' | 'low' | 'high';
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Metadata for Lovable AI Gateway audio content parts.
|
|
27
|
+
*/
|
|
28
|
+
export interface LovableAudioMetadata {
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Metadata for Lovable AI Gateway video content parts.
|
|
32
|
+
*/
|
|
33
|
+
export interface LovableVideoMetadata {
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Map of modality types to their Lovable AI Gateway metadata types.
|
|
37
|
+
*/
|
|
38
|
+
export interface LovableMessageMetadataByModality {
|
|
39
|
+
text: LovableTextMetadata;
|
|
40
|
+
image: LovableImageMetadata;
|
|
41
|
+
audio: LovableAudioMetadata;
|
|
42
|
+
video: LovableVideoMetadata;
|
|
43
|
+
document: LovableDocumentMetadata;
|
|
44
|
+
}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import { LovableEmbeddingProviderOptions } from './embedding/embedding-provider-options.js';
|
|
2
|
+
import { LovableImageProviderOptions, LovableImageSize } from './image/image-provider-options.js';
|
|
3
|
+
import { LovableTextProviderOptions } from './text/text-provider-options.js';
|
|
4
|
+
import { LovableHdVideoSize, LovableVideoDuration, LovableVideoProviderOptions, LovableVideoSize } from './video/video-provider-options.js';
|
|
5
|
+
/**
|
|
6
|
+
* Chat models listed on https://docs.lovable.dev/features/ai.
|
|
7
|
+
* Ids use the `google/` and `openai/` form that the gateway accepts.
|
|
8
|
+
*/
|
|
9
|
+
export declare const LOVABLE_CHAT_MODELS: readonly ["google/gemini-3.7-flash", "google/gemini-3.6-flash", "google/gemini-3.5-flash", "google/gemini-3.1-pro-preview", "google/gemini-3.1-flash-lite", "google/gemini-3-flash-preview", "google/gemini-2.5-pro", "google/gemini-2.5-flash", "google/gemini-2.5-flash-lite", "openai/gpt-5.6-sol", "openai/gpt-5.6-terra", "openai/gpt-5.6-luna", "openai/gpt-5.5-pro", "openai/gpt-5.5", "openai/gpt-5.4-pro", "openai/gpt-5.4", "openai/gpt-5.4-mini", "openai/gpt-5.4-nano", "openai/gpt-5.2", "openai/gpt-5", "openai/gpt-5-mini", "openai/gpt-5-nano"];
|
|
10
|
+
export type LovableChatModel = (typeof LOVABLE_CHAT_MODELS)[number];
|
|
11
|
+
/**
|
|
12
|
+
* A curated chat model id, or any other id the gateway accepts.
|
|
13
|
+
* Uncurated ids fall back to text-only input and the generic provider options.
|
|
14
|
+
*/
|
|
15
|
+
export type LovableModelId = LovableChatModel | (string & {});
|
|
16
|
+
export type LovableChatModelProviderOptionsByName = {
|
|
17
|
+
[K in LovableChatModel]: LovableTextProviderOptions;
|
|
18
|
+
};
|
|
19
|
+
export type LovableModelInputModalitiesByName = {
|
|
20
|
+
[K in LovableChatModel]: readonly ['text', 'image'];
|
|
21
|
+
};
|
|
22
|
+
export type LovableChatModelToolCapabilitiesByName = {
|
|
23
|
+
[K in LovableChatModel]: readonly [];
|
|
24
|
+
};
|
|
25
|
+
export type ResolveProviderOptions<TModel extends string> = TModel extends keyof LovableChatModelProviderOptionsByName ? LovableChatModelProviderOptionsByName[TModel] : LovableTextProviderOptions;
|
|
26
|
+
export type ResolveInputModalities<TModel extends string> = TModel extends keyof LovableModelInputModalitiesByName ? LovableModelInputModalitiesByName[TModel] : readonly ['text'];
|
|
27
|
+
export declare const LOVABLE_IMAGE_MODELS: readonly ["openai/gpt-image-2", "openai/gpt-image-1-mini", "google/gemini-3.1-flash-image", "google/gemini-3.1-flash-lite-image", "google/gemini-3-pro-image", "google/gemini-2.5-flash-image"];
|
|
28
|
+
export type LovableImageModel = (typeof LOVABLE_IMAGE_MODELS)[number];
|
|
29
|
+
export type LovableImageModelProviderOptionsByName = {
|
|
30
|
+
[K in LovableImageModel]: LovableImageProviderOptions;
|
|
31
|
+
};
|
|
32
|
+
export type LovableImageModelSizeByName = {
|
|
33
|
+
[K in LovableImageModel]: LovableImageSize;
|
|
34
|
+
};
|
|
35
|
+
export type LovableImageModelInputModalitiesByName = {
|
|
36
|
+
[K in LovableImageModel]: readonly ['image'];
|
|
37
|
+
};
|
|
38
|
+
/**
|
|
39
|
+
* @experimental Video generation is an experimental feature and may change.
|
|
40
|
+
*/
|
|
41
|
+
export declare const LOVABLE_VIDEO_MODELS: readonly ["google/veo-3.1-lite", "google/veo-3.1-fast", "google/veo-3.1"];
|
|
42
|
+
/**
|
|
43
|
+
* @experimental Video generation is an experimental feature and may change.
|
|
44
|
+
*/
|
|
45
|
+
export type LovableVideoModel = (typeof LOVABLE_VIDEO_MODELS)[number];
|
|
46
|
+
export type LovableVideoModelProviderOptionsByName = {
|
|
47
|
+
[K in LovableVideoModel]: LovableVideoProviderOptions;
|
|
48
|
+
};
|
|
49
|
+
export type LovableVideoModelSizeByName = {
|
|
50
|
+
'google/veo-3.1-lite': LovableHdVideoSize;
|
|
51
|
+
'google/veo-3.1-fast': LovableVideoSize;
|
|
52
|
+
'google/veo-3.1': LovableVideoSize;
|
|
53
|
+
};
|
|
54
|
+
export type LovableVideoModelDurationByName = {
|
|
55
|
+
[K in LovableVideoModel]: LovableVideoDuration;
|
|
56
|
+
};
|
|
57
|
+
export type LovableVideoModelInputModalitiesByName = {
|
|
58
|
+
[K in LovableVideoModel]: readonly ['image'];
|
|
59
|
+
};
|
|
60
|
+
export declare const LOVABLE_EMBEDDING_MODELS: readonly ["google/gemini-embedding-2", "google/gemini-embedding-001", "openai/text-embedding-3-small", "openai/text-embedding-3-large"];
|
|
61
|
+
export type LovableEmbeddingModel = (typeof LOVABLE_EMBEDDING_MODELS)[number];
|
|
62
|
+
export type LovableEmbeddingModelProviderOptionsByName = {
|
|
63
|
+
[K in LovableEmbeddingModel]: LovableEmbeddingProviderOptions;
|
|
64
|
+
};
|
|
65
|
+
export type LovableEmbeddingModelInputModalitiesByName = {
|
|
66
|
+
[K in LovableEmbeddingModel]: readonly ['text'];
|
|
67
|
+
};
|
|
68
|
+
export declare const LOVABLE_TTS_MODELS: readonly ["openai/gpt-4o-mini-tts", "google/gemini-2.5-flash-tts", "google/gemini-2.5-pro-tts", "google/gemini-2.5-flash-lite-preview-tts", "google/gemini-3.1-flash-tts-preview"];
|
|
69
|
+
export type LovableTTSModel = (typeof LOVABLE_TTS_MODELS)[number];
|
|
70
|
+
export declare const LOVABLE_TRANSCRIPTION_MODELS: readonly ["openai/gpt-4o-mini-transcribe", "openai/gpt-4o-transcribe"];
|
|
71
|
+
export type LovableTranscriptionModel = (typeof LOVABLE_TRANSCRIPTION_MODELS)[number];
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
//#region src/model-meta.ts
|
|
2
|
+
/**
|
|
3
|
+
* Chat models listed on https://docs.lovable.dev/features/ai.
|
|
4
|
+
* Ids use the `google/` and `openai/` form that the gateway accepts.
|
|
5
|
+
*/
|
|
6
|
+
var LOVABLE_CHAT_MODELS = [
|
|
7
|
+
"google/gemini-3.7-flash",
|
|
8
|
+
"google/gemini-3.6-flash",
|
|
9
|
+
"google/gemini-3.5-flash",
|
|
10
|
+
"google/gemini-3.1-pro-preview",
|
|
11
|
+
"google/gemini-3.1-flash-lite",
|
|
12
|
+
"google/gemini-3-flash-preview",
|
|
13
|
+
"google/gemini-2.5-pro",
|
|
14
|
+
"google/gemini-2.5-flash",
|
|
15
|
+
"google/gemini-2.5-flash-lite",
|
|
16
|
+
"openai/gpt-5.6-sol",
|
|
17
|
+
"openai/gpt-5.6-terra",
|
|
18
|
+
"openai/gpt-5.6-luna",
|
|
19
|
+
"openai/gpt-5.5-pro",
|
|
20
|
+
"openai/gpt-5.5",
|
|
21
|
+
"openai/gpt-5.4-pro",
|
|
22
|
+
"openai/gpt-5.4",
|
|
23
|
+
"openai/gpt-5.4-mini",
|
|
24
|
+
"openai/gpt-5.4-nano",
|
|
25
|
+
"openai/gpt-5.2",
|
|
26
|
+
"openai/gpt-5",
|
|
27
|
+
"openai/gpt-5-mini",
|
|
28
|
+
"openai/gpt-5-nano"
|
|
29
|
+
];
|
|
30
|
+
var LOVABLE_IMAGE_MODELS = [
|
|
31
|
+
"openai/gpt-image-2",
|
|
32
|
+
"openai/gpt-image-1-mini",
|
|
33
|
+
"google/gemini-3.1-flash-image",
|
|
34
|
+
"google/gemini-3.1-flash-lite-image",
|
|
35
|
+
"google/gemini-3-pro-image",
|
|
36
|
+
"google/gemini-2.5-flash-image"
|
|
37
|
+
];
|
|
38
|
+
/**
|
|
39
|
+
* @experimental Video generation is an experimental feature and may change.
|
|
40
|
+
*/
|
|
41
|
+
var LOVABLE_VIDEO_MODELS = [
|
|
42
|
+
"google/veo-3.1-lite",
|
|
43
|
+
"google/veo-3.1-fast",
|
|
44
|
+
"google/veo-3.1"
|
|
45
|
+
];
|
|
46
|
+
var LOVABLE_EMBEDDING_MODELS = [
|
|
47
|
+
"google/gemini-embedding-2",
|
|
48
|
+
"google/gemini-embedding-001",
|
|
49
|
+
"openai/text-embedding-3-small",
|
|
50
|
+
"openai/text-embedding-3-large"
|
|
51
|
+
];
|
|
52
|
+
var LOVABLE_TTS_MODELS = [
|
|
53
|
+
"openai/gpt-4o-mini-tts",
|
|
54
|
+
"google/gemini-2.5-flash-tts",
|
|
55
|
+
"google/gemini-2.5-pro-tts",
|
|
56
|
+
"google/gemini-2.5-flash-lite-preview-tts",
|
|
57
|
+
"google/gemini-3.1-flash-tts-preview"
|
|
58
|
+
];
|
|
59
|
+
var LOVABLE_TRANSCRIPTION_MODELS = ["openai/gpt-4o-mini-transcribe", "openai/gpt-4o-transcribe"];
|
|
60
|
+
//#endregion
|
|
61
|
+
export { LOVABLE_CHAT_MODELS, LOVABLE_EMBEDDING_MODELS, LOVABLE_IMAGE_MODELS, LOVABLE_TRANSCRIPTION_MODELS, LOVABLE_TTS_MODELS, LOVABLE_VIDEO_MODELS };
|
|
62
|
+
|
|
63
|
+
//# sourceMappingURL=model-meta.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"model-meta.js","names":[],"sources":["../../src/model-meta.ts"],"sourcesContent":["import type { LovableEmbeddingProviderOptions } from './embedding/embedding-provider-options'\nimport type {\n LovableImageProviderOptions,\n LovableImageSize,\n} from './image/image-provider-options'\nimport type { LovableTextProviderOptions } from './text/text-provider-options'\nimport type {\n LovableHdVideoSize,\n LovableVideoDuration,\n LovableVideoProviderOptions,\n LovableVideoSize,\n} from './video/video-provider-options'\n\n/**\n * Chat models listed on https://docs.lovable.dev/features/ai.\n * Ids use the `google/` and `openai/` form that the gateway accepts.\n */\nexport const LOVABLE_CHAT_MODELS = [\n 'google/gemini-3.7-flash',\n 'google/gemini-3.6-flash',\n 'google/gemini-3.5-flash',\n 'google/gemini-3.1-pro-preview',\n 'google/gemini-3.1-flash-lite',\n 'google/gemini-3-flash-preview',\n 'google/gemini-2.5-pro',\n 'google/gemini-2.5-flash',\n 'google/gemini-2.5-flash-lite',\n 'openai/gpt-5.6-sol',\n 'openai/gpt-5.6-terra',\n 'openai/gpt-5.6-luna',\n 'openai/gpt-5.5-pro',\n 'openai/gpt-5.5',\n 'openai/gpt-5.4-pro',\n 'openai/gpt-5.4',\n 'openai/gpt-5.4-mini',\n 'openai/gpt-5.4-nano',\n 'openai/gpt-5.2',\n 'openai/gpt-5',\n 'openai/gpt-5-mini',\n 'openai/gpt-5-nano',\n] as const\n\nexport type LovableChatModel = (typeof LOVABLE_CHAT_MODELS)[number]\n\n/**\n * A curated chat model id, or any other id the gateway accepts.\n * Uncurated ids fall back to text-only input and the generic provider options.\n */\nexport type LovableModelId = LovableChatModel | (string & {})\n\nexport type LovableChatModelProviderOptionsByName = {\n [K in LovableChatModel]: LovableTextProviderOptions\n}\n\nexport type LovableModelInputModalitiesByName = {\n [K in LovableChatModel]: readonly ['text', 'image']\n}\n\nexport type LovableChatModelToolCapabilitiesByName = {\n [K in LovableChatModel]: readonly []\n}\n\nexport type ResolveProviderOptions<TModel extends string> =\n TModel extends keyof LovableChatModelProviderOptionsByName\n ? LovableChatModelProviderOptionsByName[TModel]\n : LovableTextProviderOptions\n\nexport type ResolveInputModalities<TModel extends string> =\n TModel extends keyof LovableModelInputModalitiesByName\n ? LovableModelInputModalitiesByName[TModel]\n : readonly ['text']\n\nexport const LOVABLE_IMAGE_MODELS = [\n 'openai/gpt-image-2',\n 'openai/gpt-image-1-mini',\n 'google/gemini-3.1-flash-image',\n 'google/gemini-3.1-flash-lite-image',\n 'google/gemini-3-pro-image',\n 'google/gemini-2.5-flash-image',\n] as const\n\nexport type LovableImageModel = (typeof LOVABLE_IMAGE_MODELS)[number]\n\nexport type LovableImageModelProviderOptionsByName = {\n [K in LovableImageModel]: LovableImageProviderOptions\n}\n\nexport type LovableImageModelSizeByName = {\n [K in LovableImageModel]: LovableImageSize\n}\n\nexport type LovableImageModelInputModalitiesByName = {\n [K in LovableImageModel]: readonly ['image']\n}\n\n/**\n * @experimental Video generation is an experimental feature and may change.\n */\nexport const LOVABLE_VIDEO_MODELS = [\n 'google/veo-3.1-lite',\n 'google/veo-3.1-fast',\n 'google/veo-3.1',\n] as const\n\n/**\n * @experimental Video generation is an experimental feature and may change.\n */\nexport type LovableVideoModel = (typeof LOVABLE_VIDEO_MODELS)[number]\n\nexport type LovableVideoModelProviderOptionsByName = {\n [K in LovableVideoModel]: LovableVideoProviderOptions\n}\n\nexport type LovableVideoModelSizeByName = {\n 'google/veo-3.1-lite': LovableHdVideoSize\n 'google/veo-3.1-fast': LovableVideoSize\n 'google/veo-3.1': LovableVideoSize\n}\n\nexport type LovableVideoModelDurationByName = {\n [K in LovableVideoModel]: LovableVideoDuration\n}\n\nexport type LovableVideoModelInputModalitiesByName = {\n [K in LovableVideoModel]: readonly ['image']\n}\n\nexport const LOVABLE_EMBEDDING_MODELS = [\n 'google/gemini-embedding-2',\n 'google/gemini-embedding-001',\n 'openai/text-embedding-3-small',\n 'openai/text-embedding-3-large',\n] as const\n\nexport type LovableEmbeddingModel = (typeof LOVABLE_EMBEDDING_MODELS)[number]\n\nexport type LovableEmbeddingModelProviderOptionsByName = {\n [K in LovableEmbeddingModel]: LovableEmbeddingProviderOptions\n}\n\nexport type LovableEmbeddingModelInputModalitiesByName = {\n [K in LovableEmbeddingModel]: readonly ['text']\n}\n\nexport const LOVABLE_TTS_MODELS = [\n 'openai/gpt-4o-mini-tts',\n 'google/gemini-2.5-flash-tts',\n 'google/gemini-2.5-pro-tts',\n 'google/gemini-2.5-flash-lite-preview-tts',\n 'google/gemini-3.1-flash-tts-preview',\n] as const\n\nexport type LovableTTSModel = (typeof LOVABLE_TTS_MODELS)[number]\n\nexport const LOVABLE_TRANSCRIPTION_MODELS = [\n 'openai/gpt-4o-mini-transcribe',\n 'openai/gpt-4o-transcribe',\n] as const\n\nexport type LovableTranscriptionModel =\n (typeof LOVABLE_TRANSCRIPTION_MODELS)[number]\n"],"mappings":";;;;;AAiBA,IAAa,sBAAsB;CACjC;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;AACF;AAgCA,IAAa,uBAAuB;CAClC;CACA;CACA;CACA;CACA;CACA;AACF;;;;AAmBA,IAAa,uBAAuB;CAClC;CACA;CACA;AACF;AAyBA,IAAa,2BAA2B;CACtC;CACA;CACA;CACA;AACF;AAYA,IAAa,qBAAqB;CAChC;CACA;CACA;CACA;CACA;AACF;AAIA,IAAa,+BAA+B,CAC1C,iCACA,0BACF"}
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import { LovableTextProviderOptions } from './text-provider-options.js';
|
|
2
|
+
export type LovableResponsesProviderOptions = Pick<LovableTextProviderOptions, 'temperature' | 'top_p' | 'max_output_tokens' | 'user'>;
|
|
3
|
+
export type ExternalResponsesProviderOptions = LovableResponsesProviderOptions;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
export interface LovableTextProviderOptions {
|
|
2
|
+
temperature?: number | null;
|
|
3
|
+
top_p?: number | null;
|
|
4
|
+
max_tokens?: number | null;
|
|
5
|
+
max_completion_tokens?: number | null;
|
|
6
|
+
max_output_tokens?: number | null;
|
|
7
|
+
frequency_penalty?: number | null;
|
|
8
|
+
presence_penalty?: number | null;
|
|
9
|
+
stop?: string | null | Array<string>;
|
|
10
|
+
seed?: number | null;
|
|
11
|
+
reasoning?: boolean | Record<string, unknown> | null;
|
|
12
|
+
include_reasoning?: boolean | null;
|
|
13
|
+
response_format?: unknown;
|
|
14
|
+
structured_outputs?: boolean | null;
|
|
15
|
+
user?: string | null;
|
|
16
|
+
}
|
|
17
|
+
export type ExternalTextProviderOptions = LovableTextProviderOptions;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { ClientOptions } from 'openai';
|
|
2
|
+
export declare const LOVABLE_DEFAULT_BASE_URL = "https://ai.gateway.lovable.dev/v1";
|
|
3
|
+
export interface LovableClientConfig extends Omit<ClientOptions, 'apiKey'> {
|
|
4
|
+
apiKey: string;
|
|
5
|
+
}
|
|
6
|
+
export declare function getLovableApiKeyFromEnv(): string;
|
|
7
|
+
export declare function lovableGatewayHeaders(apiKey: string): {
|
|
8
|
+
'Lovable-API-Key': string;
|
|
9
|
+
'X-Lovable-AIG-SDK': string;
|
|
10
|
+
};
|
|
11
|
+
export declare function withLovableDefaults(config: LovableClientConfig): ClientOptions;
|
|
12
|
+
export declare function openaiRequestOptions(abortSignal?: AbortSignal): {
|
|
13
|
+
signal: AbortSignal;
|
|
14
|
+
} | undefined;
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { getApiKeyFromEnv } from "@tanstack/ai-utils";
|
|
2
|
+
//#region src/utils/client.ts
|
|
3
|
+
var LOVABLE_DEFAULT_BASE_URL = "https://ai.gateway.lovable.dev/v1";
|
|
4
|
+
function getLovableApiKeyFromEnv() {
|
|
5
|
+
try {
|
|
6
|
+
return getApiKeyFromEnv("LOVABLE_API_KEY");
|
|
7
|
+
} catch (cause) {
|
|
8
|
+
throw new Error("LOVABLE_API_KEY is required. Set it in the environment or pass apiKey to the factory.", { cause });
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
function lovableGatewayHeaders(apiKey) {
|
|
12
|
+
return {
|
|
13
|
+
"Lovable-API-Key": apiKey,
|
|
14
|
+
"X-Lovable-AIG-SDK": "tanstack-ai"
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
function withLovableDefaults(config) {
|
|
18
|
+
const { defaultHeaders, ...rest } = config;
|
|
19
|
+
return {
|
|
20
|
+
...rest,
|
|
21
|
+
baseURL: config.baseURL || "https://ai.gateway.lovable.dev/v1",
|
|
22
|
+
defaultHeaders: {
|
|
23
|
+
...lovableGatewayHeaders(config.apiKey),
|
|
24
|
+
...defaultHeaders
|
|
25
|
+
}
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
function openaiRequestOptions(abortSignal) {
|
|
29
|
+
if (!abortSignal) return void 0;
|
|
30
|
+
return { signal: abortSignal };
|
|
31
|
+
}
|
|
32
|
+
//#endregion
|
|
33
|
+
export { LOVABLE_DEFAULT_BASE_URL, getLovableApiKeyFromEnv, lovableGatewayHeaders, openaiRequestOptions, withLovableDefaults };
|
|
34
|
+
|
|
35
|
+
//# sourceMappingURL=client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.js","names":[],"sources":["../../../src/utils/client.ts"],"sourcesContent":["import { getApiKeyFromEnv } from '@tanstack/ai-utils'\nimport type { ClientOptions } from 'openai'\n\nexport const LOVABLE_DEFAULT_BASE_URL = 'https://ai.gateway.lovable.dev/v1'\n\nexport interface LovableClientConfig extends Omit<ClientOptions, 'apiKey'> {\n apiKey: string\n}\n\nexport function getLovableApiKeyFromEnv(): string {\n try {\n return getApiKeyFromEnv('LOVABLE_API_KEY')\n } catch (cause) {\n throw new Error(\n 'LOVABLE_API_KEY is required. Set it in the environment or pass apiKey to the factory.',\n { cause },\n )\n }\n}\n\nexport function lovableGatewayHeaders(apiKey: string): {\n 'Lovable-API-Key': string\n 'X-Lovable-AIG-SDK': string\n} {\n return {\n 'Lovable-API-Key': apiKey,\n 'X-Lovable-AIG-SDK': 'tanstack-ai',\n }\n}\n\nexport function withLovableDefaults(\n config: LovableClientConfig,\n): ClientOptions {\n const { defaultHeaders, ...rest } = config\n return {\n ...rest,\n baseURL: config.baseURL || LOVABLE_DEFAULT_BASE_URL,\n defaultHeaders: {\n ...lovableGatewayHeaders(config.apiKey),\n ...defaultHeaders,\n },\n }\n}\n\nexport function openaiRequestOptions(\n abortSignal?: AbortSignal,\n): { signal: AbortSignal } | undefined {\n if (!abortSignal) return undefined\n return { signal: abortSignal }\n}\n"],"mappings":";;AAGA,IAAa,2BAA2B;AAMxC,SAAgB,0BAAkC;CAChD,IAAI;EACF,OAAO,iBAAiB,iBAAiB;CAC3C,SAAS,OAAO;EACd,MAAM,IAAI,MACR,yFACA,EAAE,MAAM,CACV;CACF;AACF;AAEA,SAAgB,sBAAsB,QAGpC;CACA,OAAO;EACL,mBAAmB;EACnB,qBAAqB;CACvB;AACF;AAEA,SAAgB,oBACd,QACe;CACf,MAAM,EAAE,gBAAgB,GAAG,SAAS;CACpC,OAAO;EACL,GAAG;EACH,SAAS,OAAO,WAAA;EAChB,gBAAgB;GACd,GAAG,sBAAsB,OAAO,MAAM;GACtC,GAAG;EACL;CACF;AACF;AAEA,SAAgB,qBACd,aACqC;CACrC,IAAI,CAAC,aAAa,OAAO,KAAA;CACzB,OAAO,EAAE,QAAQ,YAAY;AAC/B"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @experimental Video generation is an experimental feature and may change.
|
|
3
|
+
*/
|
|
4
|
+
export type LovableHdVideoSize = '1280x720' | '720x1280' | '1920x1080' | '1080x1920';
|
|
5
|
+
export type Lovable4kVideoSize = '3840x2160' | '2160x3840';
|
|
6
|
+
export type LovableVideoSize = LovableHdVideoSize | Lovable4kVideoSize;
|
|
7
|
+
export type LovableVideoSeconds = '4' | '6' | '8';
|
|
8
|
+
export type LovableVideoDuration = 4 | 6 | 8;
|
|
9
|
+
export interface LovableVideoProviderOptions {
|
|
10
|
+
size?: LovableVideoSize;
|
|
11
|
+
seconds?: LovableVideoSeconds;
|
|
12
|
+
}
|
|
13
|
+
export declare function is4kVideoSize(size: string): size is Lovable4kVideoSize;
|
|
14
|
+
export declare function isHighResVideoSize(size: string): boolean;
|
|
15
|
+
export declare function supports4kVideo(model: string): boolean;
|
|
16
|
+
export declare function validateVideoSize(model: string, size?: string): asserts size is LovableVideoSize | undefined;
|
|
17
|
+
export declare function validateVideoSeconds(model: string, seconds?: number | string): asserts seconds is LovableVideoSeconds | LovableVideoDuration | undefined;
|
|
18
|
+
export declare function validateHighResDuration(model: string, size: string | undefined, seconds: number | string | undefined): void;
|
|
19
|
+
export declare function toApiSeconds(seconds: number | string | undefined): LovableVideoSeconds | undefined;
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
//#region src/video/video-provider-options.ts
|
|
2
|
+
var HD_SIZES = [
|
|
3
|
+
"1280x720",
|
|
4
|
+
"720x1280",
|
|
5
|
+
"1920x1080",
|
|
6
|
+
"1080x1920"
|
|
7
|
+
];
|
|
8
|
+
var FOUR_K_SIZES = ["3840x2160", "2160x3840"];
|
|
9
|
+
var ALL_SIZES = [...HD_SIZES, ...FOUR_K_SIZES];
|
|
10
|
+
var HIGH_RES_SIZES = /* @__PURE__ */ new Set([
|
|
11
|
+
"1920x1080",
|
|
12
|
+
"1080x1920",
|
|
13
|
+
"3840x2160",
|
|
14
|
+
"2160x3840"
|
|
15
|
+
]);
|
|
16
|
+
var FOUR_K_MODELS = /* @__PURE__ */ new Set(["google/veo-3.1-fast", "google/veo-3.1"]);
|
|
17
|
+
function is4kVideoSize(size) {
|
|
18
|
+
return FOUR_K_SIZES.includes(size);
|
|
19
|
+
}
|
|
20
|
+
function isHighResVideoSize(size) {
|
|
21
|
+
return HIGH_RES_SIZES.has(size);
|
|
22
|
+
}
|
|
23
|
+
function supports4kVideo(model) {
|
|
24
|
+
return FOUR_K_MODELS.has(model);
|
|
25
|
+
}
|
|
26
|
+
function validateVideoSize(model, size) {
|
|
27
|
+
if (!size) return;
|
|
28
|
+
if (!ALL_SIZES.includes(size)) throw new Error(`Size "${size}" is not supported by model "${model}". Supported sizes: ${ALL_SIZES.join(", ")}`);
|
|
29
|
+
if (is4kVideoSize(size) && !supports4kVideo(model)) throw new Error(`Size "${size}" is 4K. Only google/veo-3.1-fast and google/veo-3.1 support 4K.`);
|
|
30
|
+
}
|
|
31
|
+
function validateVideoSeconds(model, seconds) {
|
|
32
|
+
if (seconds === void 0) return;
|
|
33
|
+
if (!(typeof seconds === "string" ? seconds === "4" || seconds === "6" || seconds === "8" : seconds === 4 || seconds === 6 || seconds === 8)) throw new Error(`Duration "${seconds}" is not supported by model "${model}". Supported durations: 4, 6, or 8 seconds`);
|
|
34
|
+
}
|
|
35
|
+
function validateHighResDuration(model, size, seconds) {
|
|
36
|
+
if (!size || !isHighResVideoSize(size)) return;
|
|
37
|
+
const asNumber = seconds === void 0 ? void 0 : typeof seconds === "string" ? Number(seconds) : seconds;
|
|
38
|
+
if (asNumber !== void 0 && asNumber !== 8) throw new Error(`Model "${model}" requires 8 second clips at 1080p and 4K. Received duration ${seconds}.`);
|
|
39
|
+
}
|
|
40
|
+
function toApiSeconds(seconds) {
|
|
41
|
+
if (seconds === void 0) return void 0;
|
|
42
|
+
return String(seconds);
|
|
43
|
+
}
|
|
44
|
+
//#endregion
|
|
45
|
+
export { is4kVideoSize, isHighResVideoSize, supports4kVideo, toApiSeconds, validateHighResDuration, validateVideoSeconds, validateVideoSize };
|
|
46
|
+
|
|
47
|
+
//# sourceMappingURL=video-provider-options.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"video-provider-options.js","names":[],"sources":["../../../src/video/video-provider-options.ts"],"sourcesContent":["/**\n * @experimental Video generation is an experimental feature and may change.\n */\n\nexport type LovableHdVideoSize =\n | '1280x720'\n | '720x1280'\n | '1920x1080'\n | '1080x1920'\n\nexport type Lovable4kVideoSize = '3840x2160' | '2160x3840'\n\nexport type LovableVideoSize = LovableHdVideoSize | Lovable4kVideoSize\n\nexport type LovableVideoSeconds = '4' | '6' | '8'\n\nexport type LovableVideoDuration = 4 | 6 | 8\n\nexport interface LovableVideoProviderOptions {\n size?: LovableVideoSize\n seconds?: LovableVideoSeconds\n}\n\nconst HD_SIZES: ReadonlyArray<LovableHdVideoSize> = [\n '1280x720',\n '720x1280',\n '1920x1080',\n '1080x1920',\n]\n\nconst FOUR_K_SIZES: ReadonlyArray<Lovable4kVideoSize> = [\n '3840x2160',\n '2160x3840',\n]\n\nconst ALL_SIZES: ReadonlyArray<LovableVideoSize> = [\n ...HD_SIZES,\n ...FOUR_K_SIZES,\n]\n\nconst HIGH_RES_SIZES: ReadonlySet<string> = new Set([\n '1920x1080',\n '1080x1920',\n '3840x2160',\n '2160x3840',\n])\n\nconst FOUR_K_MODELS: ReadonlySet<string> = new Set([\n 'google/veo-3.1-fast',\n 'google/veo-3.1',\n])\n\nexport function is4kVideoSize(size: string): size is Lovable4kVideoSize {\n return (FOUR_K_SIZES as ReadonlyArray<string>).includes(size)\n}\n\nexport function isHighResVideoSize(size: string): boolean {\n return HIGH_RES_SIZES.has(size)\n}\n\nexport function supports4kVideo(model: string): boolean {\n return FOUR_K_MODELS.has(model)\n}\n\nexport function validateVideoSize(\n model: string,\n size?: string,\n): asserts size is LovableVideoSize | undefined {\n if (!size) return\n\n if (!(ALL_SIZES as ReadonlyArray<string>).includes(size)) {\n throw new Error(\n `Size \"${size}\" is not supported by model \"${model}\". Supported sizes: ${ALL_SIZES.join(', ')}`,\n )\n }\n\n if (is4kVideoSize(size) && !supports4kVideo(model)) {\n throw new Error(\n `Size \"${size}\" is 4K. Only google/veo-3.1-fast and google/veo-3.1 support 4K.`,\n )\n }\n}\n\nexport function validateVideoSeconds(\n model: string,\n seconds?: number | string,\n): asserts seconds is LovableVideoSeconds | LovableVideoDuration | undefined {\n if (seconds === undefined) return\n\n const isValid =\n typeof seconds === 'string'\n ? seconds === '4' || seconds === '6' || seconds === '8'\n : seconds === 4 || seconds === 6 || seconds === 8\n\n if (!isValid) {\n throw new Error(\n `Duration \"${seconds}\" is not supported by model \"${model}\". Supported durations: 4, 6, or 8 seconds`,\n )\n }\n}\n\nexport function validateHighResDuration(\n model: string,\n size: string | undefined,\n seconds: number | string | undefined,\n): void {\n if (!size || !isHighResVideoSize(size)) return\n\n const asNumber =\n seconds === undefined\n ? undefined\n : typeof seconds === 'string'\n ? Number(seconds)\n : seconds\n\n if (asNumber !== undefined && asNumber !== 8) {\n throw new Error(\n `Model \"${model}\" requires 8 second clips at 1080p and 4K. Received duration ${seconds}.`,\n )\n }\n}\n\nexport function toApiSeconds(\n seconds: number | string | undefined,\n): LovableVideoSeconds | undefined {\n if (seconds === undefined) return undefined\n return String(seconds) as LovableVideoSeconds\n}\n"],"mappings":";AAuBA,IAAM,WAA8C;CAClD;CACA;CACA;CACA;AACF;AAEA,IAAM,eAAkD,CACtD,aACA,WACF;AAEA,IAAM,YAA6C,CACjD,GAAG,UACH,GAAG,YACL;AAEA,IAAM,iCAAsC,IAAI,IAAI;CAClD;CACA;CACA;CACA;AACF,CAAC;AAED,IAAM,gCAAqC,IAAI,IAAI,CACjD,uBACA,gBACF,CAAC;AAED,SAAgB,cAAc,MAA0C;CACtE,OAAQ,aAAuC,SAAS,IAAI;AAC9D;AAEA,SAAgB,mBAAmB,MAAuB;CACxD,OAAO,eAAe,IAAI,IAAI;AAChC;AAEA,SAAgB,gBAAgB,OAAwB;CACtD,OAAO,cAAc,IAAI,KAAK;AAChC;AAEA,SAAgB,kBACd,OACA,MAC8C;CAC9C,IAAI,CAAC,MAAM;CAEX,IAAI,CAAE,UAAoC,SAAS,IAAI,GACrD,MAAM,IAAI,MACR,SAAS,KAAK,+BAA+B,MAAM,sBAAsB,UAAU,KAAK,IAAI,GAC9F;CAGF,IAAI,cAAc,IAAI,KAAK,CAAC,gBAAgB,KAAK,GAC/C,MAAM,IAAI,MACR,SAAS,KAAK,iEAChB;AAEJ;AAEA,SAAgB,qBACd,OACA,SAC2E;CAC3E,IAAI,YAAY,KAAA,GAAW;CAO3B,IAAI,EAJF,OAAO,YAAY,WACf,YAAY,OAAO,YAAY,OAAO,YAAY,MAClD,YAAY,KAAK,YAAY,KAAK,YAAY,IAGlD,MAAM,IAAI,MACR,aAAa,QAAQ,+BAA+B,MAAM,2CAC5D;AAEJ;AAEA,SAAgB,wBACd,OACA,MACA,SACM;CACN,IAAI,CAAC,QAAQ,CAAC,mBAAmB,IAAI,GAAG;CAExC,MAAM,WACJ,YAAY,KAAA,IACR,KAAA,IACA,OAAO,YAAY,WACjB,OAAO,OAAO,IACd;CAER,IAAI,aAAa,KAAA,KAAa,aAAa,GACzC,MAAM,IAAI,MACR,UAAU,MAAM,+DAA+D,QAAQ,EACzF;AAEJ;AAEA,SAAgB,aACd,SACiC;CACjC,IAAI,YAAY,KAAA,GAAW,OAAO,KAAA;CAClC,OAAO,OAAO,OAAO;AACvB"}
|
package/package.json
ADDED
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@tanstack/ai-lovable",
|
|
3
|
+
"version": "0.0.0",
|
|
4
|
+
"description": "Lovable AI Gateway adapter for TanStack AI chat, embeddings, image, video, speech, and transcription.",
|
|
5
|
+
"author": "Tanner Linsley",
|
|
6
|
+
"license": "MIT",
|
|
7
|
+
"homepage": "https://tanstack.com/ai",
|
|
8
|
+
"repository": {
|
|
9
|
+
"type": "git",
|
|
10
|
+
"url": "git+https://github.com/TanStack/ai.git",
|
|
11
|
+
"directory": "packages/ai-lovable"
|
|
12
|
+
},
|
|
13
|
+
"bugs": {
|
|
14
|
+
"url": "https://github.com/TanStack/ai/issues"
|
|
15
|
+
},
|
|
16
|
+
"funding": {
|
|
17
|
+
"type": "github",
|
|
18
|
+
"url": "https://github.com/sponsors/tannerlinsley"
|
|
19
|
+
},
|
|
20
|
+
"type": "module",
|
|
21
|
+
"module": "./dist/esm/index.js",
|
|
22
|
+
"types": "./dist/esm/index.d.ts",
|
|
23
|
+
"exports": {
|
|
24
|
+
".": {
|
|
25
|
+
"types": "./dist/esm/index.d.ts",
|
|
26
|
+
"import": "./dist/esm/index.js"
|
|
27
|
+
},
|
|
28
|
+
"./byok": {
|
|
29
|
+
"types": "./dist/esm/byok.d.ts",
|
|
30
|
+
"import": "./dist/esm/byok.js"
|
|
31
|
+
}
|
|
32
|
+
},
|
|
33
|
+
"files": [
|
|
34
|
+
"dist",
|
|
35
|
+
"src"
|
|
36
|
+
],
|
|
37
|
+
"keywords": [
|
|
38
|
+
"ai",
|
|
39
|
+
"ai-sdk",
|
|
40
|
+
"typescript",
|
|
41
|
+
"tanstack",
|
|
42
|
+
"lovable",
|
|
43
|
+
"ai-gateway",
|
|
44
|
+
"adapter",
|
|
45
|
+
"llm",
|
|
46
|
+
"chat",
|
|
47
|
+
"embeddings",
|
|
48
|
+
"image-generation",
|
|
49
|
+
"video-generation",
|
|
50
|
+
"tts",
|
|
51
|
+
"transcription",
|
|
52
|
+
"streaming"
|
|
53
|
+
],
|
|
54
|
+
"devDependencies": {
|
|
55
|
+
"@vitest/coverage-v8": "4.1.10",
|
|
56
|
+
"vite": "^8.2.1",
|
|
57
|
+
"zod": "^4.2.0",
|
|
58
|
+
"@tanstack/ai": "0.49.0"
|
|
59
|
+
},
|
|
60
|
+
"peerDependencies": {
|
|
61
|
+
"zod": "^4.0.0",
|
|
62
|
+
"@tanstack/ai": "^0.49.0"
|
|
63
|
+
},
|
|
64
|
+
"dependencies": {
|
|
65
|
+
"openai": "^6.41.0",
|
|
66
|
+
"@tanstack/ai-utils": "^0.4.0",
|
|
67
|
+
"@tanstack/openai-base": "^0.10.4"
|
|
68
|
+
},
|
|
69
|
+
"scripts": {
|
|
70
|
+
"build": "vite build",
|
|
71
|
+
"clean": "premove ./build ./dist",
|
|
72
|
+
"lint:fix": "oxlint src --type-aware --fix",
|
|
73
|
+
"test:build": "publint --strict",
|
|
74
|
+
"test:oxlint": "oxlint src --type-aware",
|
|
75
|
+
"test:lib": "vitest run",
|
|
76
|
+
"test:lib:dev": "pnpm test:lib --watch",
|
|
77
|
+
"test:types": "tsc"
|
|
78
|
+
}
|
|
79
|
+
}
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
import OpenAI from 'openai'
|
|
2
|
+
import { BaseEmbeddingAdapter } from '@tanstack/ai/adapters'
|
|
3
|
+
import { toRunErrorPayload } from '@tanstack/ai/adapter-internals'
|
|
4
|
+
import { generateId } from '@tanstack/ai-utils'
|
|
5
|
+
import { requireTextOnlyEmbeddingInput } from '@tanstack/ai'
|
|
6
|
+
import { getLovableApiKeyFromEnv, withLovableDefaults } from '../utils/client'
|
|
7
|
+
import type {
|
|
8
|
+
EmbeddingOptions,
|
|
9
|
+
EmbeddingResult,
|
|
10
|
+
TokenUsage,
|
|
11
|
+
} from '@tanstack/ai'
|
|
12
|
+
import type OpenAI_SDK from 'openai'
|
|
13
|
+
import type {
|
|
14
|
+
LovableEmbeddingModel,
|
|
15
|
+
LovableEmbeddingModelInputModalitiesByName,
|
|
16
|
+
LovableEmbeddingModelProviderOptionsByName,
|
|
17
|
+
} from '../model-meta'
|
|
18
|
+
import type { LovableEmbeddingProviderOptions } from '../embedding/embedding-provider-options'
|
|
19
|
+
import type { LovableClientConfig } from '../utils/client'
|
|
20
|
+
|
|
21
|
+
export interface LovableEmbeddingConfig extends LovableClientConfig {}
|
|
22
|
+
|
|
23
|
+
export class LovableEmbeddingAdapter<
|
|
24
|
+
TModel extends LovableEmbeddingModel,
|
|
25
|
+
> extends BaseEmbeddingAdapter<
|
|
26
|
+
TModel,
|
|
27
|
+
LovableEmbeddingProviderOptions,
|
|
28
|
+
LovableEmbeddingModelProviderOptionsByName,
|
|
29
|
+
LovableEmbeddingModelInputModalitiesByName
|
|
30
|
+
> {
|
|
31
|
+
readonly name = 'lovable' as const
|
|
32
|
+
|
|
33
|
+
protected client: OpenAI
|
|
34
|
+
|
|
35
|
+
constructor(config: LovableEmbeddingConfig, model: TModel) {
|
|
36
|
+
super(model, {})
|
|
37
|
+
this.client = new OpenAI(withLovableDefaults(config))
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
async createEmbeddings(
|
|
41
|
+
options: EmbeddingOptions<LovableEmbeddingProviderOptions>,
|
|
42
|
+
): Promise<EmbeddingResult> {
|
|
43
|
+
const { model, logger, modelOptions } = options
|
|
44
|
+
const texts = requireTextOnlyEmbeddingInput(options.input, this.name, model)
|
|
45
|
+
|
|
46
|
+
try {
|
|
47
|
+
const request: OpenAI_SDK.EmbeddingCreateParams = {
|
|
48
|
+
...modelOptions,
|
|
49
|
+
model,
|
|
50
|
+
input: texts,
|
|
51
|
+
encoding_format: 'float',
|
|
52
|
+
}
|
|
53
|
+
if (options.dimensions !== undefined) {
|
|
54
|
+
request.dimensions = options.dimensions
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
logger.request(
|
|
58
|
+
`activity=embed provider=${this.name} model=${model} inputs=${texts.length}`,
|
|
59
|
+
{ provider: this.name, model },
|
|
60
|
+
)
|
|
61
|
+
|
|
62
|
+
const response = await this.client.embeddings.create(request)
|
|
63
|
+
|
|
64
|
+
const usage: TokenUsage = {
|
|
65
|
+
promptTokens: response.usage.prompt_tokens,
|
|
66
|
+
completionTokens: 0,
|
|
67
|
+
totalTokens: response.usage.total_tokens,
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
return {
|
|
71
|
+
id: generateId(this.name),
|
|
72
|
+
model,
|
|
73
|
+
embeddings: response.data.map((item) => ({
|
|
74
|
+
vector: item.embedding,
|
|
75
|
+
index: item.index,
|
|
76
|
+
})),
|
|
77
|
+
usage,
|
|
78
|
+
}
|
|
79
|
+
} catch (error: unknown) {
|
|
80
|
+
logger.errors(`${this.name}.createEmbeddings fatal`, {
|
|
81
|
+
error: toRunErrorPayload(error, `${this.name}.createEmbeddings failed`),
|
|
82
|
+
source: `${this.name}.createEmbeddings`,
|
|
83
|
+
})
|
|
84
|
+
throw error
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
export function createLovableEmbedding<TModel extends LovableEmbeddingModel>(
|
|
90
|
+
model: TModel,
|
|
91
|
+
apiKey: string,
|
|
92
|
+
config?: Omit<LovableEmbeddingConfig, 'apiKey'>,
|
|
93
|
+
): LovableEmbeddingAdapter<TModel> {
|
|
94
|
+
return new LovableEmbeddingAdapter({ apiKey, ...config }, model)
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
export function lovableEmbedding<TModel extends LovableEmbeddingModel>(
|
|
98
|
+
model: TModel,
|
|
99
|
+
config?: Omit<LovableEmbeddingConfig, 'apiKey'>,
|
|
100
|
+
): LovableEmbeddingAdapter<TModel> {
|
|
101
|
+
return createLovableEmbedding(model, getLovableApiKeyFromEnv(), config)
|
|
102
|
+
}
|