@umituz/react-native-ai-gemini-provider 3.0.40 → 3.0.42
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/package.json +1 -4
- package/src/application/builders/config-builder.ts +102 -0
- package/src/application/builders/index.ts +8 -0
- package/src/application/dtos/generation-request.dto.ts +89 -0
- package/src/application/dtos/index.ts +8 -0
- package/src/application/index.ts +16 -0
- package/src/application/providers/gemini-provider.ts +135 -0
- package/src/application/providers/index.ts +6 -0
- package/src/application/use-cases/generate-json.use-case.ts +73 -0
- package/src/application/use-cases/generate-text.use-case.ts +81 -0
- package/src/application/use-cases/index.ts +20 -0
- package/src/application/use-cases/stream-content.use-case.ts +46 -0
- package/src/domain/entities/error.types.ts +0 -5
- package/src/domain/entities/gemini.types.ts +3 -1
- package/src/domain/index.ts +16 -0
- package/src/domain/repositories/index.ts +19 -0
- package/src/domain/repositories/streaming.repository.ts +41 -0
- package/src/domain/repositories/structured-text.repository.ts +41 -0
- package/src/domain/repositories/text-generation.repository.ts +38 -0
- package/src/domain/services/validation.service.ts +157 -0
- package/src/domain/value-objects/api-key.vo.ts +55 -0
- package/src/domain/value-objects/index.ts +8 -0
- package/src/domain/value-objects/model-name.vo.ts +66 -0
- package/src/domain/value-objects/timeout.vo.ts +69 -0
- package/src/index.ts +110 -25
- package/src/infrastructure/external/gemini-client.singleton.ts +49 -0
- package/src/infrastructure/external/gemini-sdk.adapter.ts +143 -0
- package/src/infrastructure/external/index.ts +7 -0
- package/src/infrastructure/index.ts +16 -0
- package/src/infrastructure/mappers/content.mapper.ts +80 -0
- package/src/infrastructure/mappers/error.mapper.ts +152 -0
- package/src/infrastructure/mappers/index.ts +7 -0
- package/src/infrastructure/mappers/response.mapper.ts +165 -0
- package/src/infrastructure/repositories/base-gemini.repository.ts +94 -0
- package/src/infrastructure/repositories/gemini-streaming.repository.impl.ts +119 -0
- package/src/infrastructure/repositories/gemini-structured-text.repository.impl.ts +108 -0
- package/src/infrastructure/repositories/gemini-text.repository.impl.ts +76 -0
- package/src/infrastructure/repositories/index.ts +10 -0
- package/src/infrastructure/utils/index.ts +6 -0
- package/src/presentation/hooks/index.ts +8 -0
- package/src/presentation/hooks/use-gemini.hook.ts +181 -0
- package/src/presentation/hooks/use-operation-manager.hook.ts +67 -0
- package/src/presentation/index.ts +10 -0
- package/src/presentation/providers/gemini-provider.tsx +93 -0
- package/src/presentation/providers/index.ts +10 -0
- package/dist/domain/entities/error.types.d.ts +0 -96
- package/dist/domain/entities/gemini.types.d.ts +0 -128
- package/dist/domain/entities/index.d.ts +0 -6
- package/dist/domain/entities/models.d.ts +0 -23
- package/dist/index.d.ts +0 -15
- package/dist/infrastructure/services/BaseService.d.ts +0 -29
- package/dist/infrastructure/services/ChatSession.d.ts +0 -63
- package/dist/infrastructure/services/GeminiClient.d.ts +0 -16
- package/dist/infrastructure/services/GeminiProvider.d.ts +0 -10
- package/dist/infrastructure/services/Streaming.d.ts +0 -7
- package/dist/infrastructure/services/StructuredText.d.ts +0 -6
- package/dist/infrastructure/services/TextGeneration.d.ts +0 -8
- package/dist/infrastructure/services/index.d.ts +0 -6
- package/dist/infrastructure/telemetry/TelemetryHooks.d.ts +0 -41
- package/dist/infrastructure/telemetry/index.d.ts +0 -4
- package/dist/infrastructure/utils/async/execute-state.util.d.ts +0 -49
- package/dist/infrastructure/utils/async/index.d.ts +0 -4
- package/dist/infrastructure/utils/content-mapper.util.d.ts +0 -45
- package/dist/infrastructure/utils/error-mapper.util.d.ts +0 -2
- package/dist/infrastructure/utils/gemini-data-transformer.util.d.ts +0 -2
- package/dist/infrastructure/utils/json-parser.util.d.ts +0 -9
- package/dist/infrastructure/utils/stream-processor.util.d.ts +0 -14
- package/dist/presentation/hooks/index.d.ts +0 -1
- package/dist/presentation/hooks/useGemini.d.ts +0 -17
- package/dist/presentation/hooks/useOperationManager.d.ts +0 -23
- package/dist/providers/ConfigBuilder.d.ts +0 -46
- package/dist/providers/ProviderFactory.d.ts +0 -25
- package/dist/providers/index.d.ts +0 -7
- package/src/infrastructure/services/BaseService.ts +0 -53
- package/src/infrastructure/services/ChatSession.ts +0 -199
- package/src/infrastructure/services/GeminiClient.ts +0 -112
- package/src/infrastructure/services/Streaming.ts +0 -56
- package/src/infrastructure/services/StructuredText.ts +0 -57
- package/src/infrastructure/services/TextGeneration.ts +0 -57
- package/src/infrastructure/telemetry/TelemetryHooks.ts +0 -110
- package/src/infrastructure/utils/async/execute-state.util.ts +0 -93
- package/src/infrastructure/utils/content-mapper.util.ts +0 -175
- package/src/infrastructure/utils/error-mapper.util.ts +0 -145
- package/src/infrastructure/utils/gemini-data-transformer.util.ts +0 -40
- package/src/infrastructure/utils/text-calculations.util.ts +0 -70
- package/src/presentation/hooks/useGemini.ts +0 -125
- package/src/presentation/hooks/useOperationManager.ts +0 -88
- package/src/providers/ConfigBuilder.ts +0 -112
- package/src/providers/ProviderFactory.ts +0 -65
|
@@ -1,125 +0,0 @@
|
|
|
1
|
-
import { useState, useCallback, useMemo } from "react";
|
|
2
|
-
import type { GeminiGenerationConfig } from "../../domain/entities";
|
|
3
|
-
import { DEFAULT_MODELS } from "../../domain/entities";
|
|
4
|
-
import { textGeneration } from "../../infrastructure/services/TextGeneration";
|
|
5
|
-
import { structuredText } from "../../infrastructure/services/StructuredText";
|
|
6
|
-
import { executeWithState, type AsyncStateSetters } from "../../infrastructure/utils/async/execute-state.util";
|
|
7
|
-
import { useOperationManager } from "./useOperationManager";
|
|
8
|
-
|
|
9
|
-
export interface UseGeminiOptions {
|
|
10
|
-
model?: string;
|
|
11
|
-
generationConfig?: GeminiGenerationConfig;
|
|
12
|
-
onSuccess?: (result: string) => void;
|
|
13
|
-
onError?: (error: string) => void;
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
export interface UseGeminiReturn {
|
|
17
|
-
generate: (prompt: string) => Promise<void>;
|
|
18
|
-
generateJSON: <T>(prompt: string, schema: Record<string, unknown>) => Promise<T | null>;
|
|
19
|
-
result: string | null;
|
|
20
|
-
jsonResult: unknown;
|
|
21
|
-
isGenerating: boolean;
|
|
22
|
-
error: string | null;
|
|
23
|
-
reset: () => void;
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
export function useGemini(options: UseGeminiOptions = {}): UseGeminiReturn {
|
|
27
|
-
const [result, setResult] = useState<string | null>(null);
|
|
28
|
-
const [jsonResult, setJsonResult] = useState<unknown>(null);
|
|
29
|
-
const [isGenerating, setIsGenerating] = useState(false);
|
|
30
|
-
const [error, setError] = useState<string | null>(null);
|
|
31
|
-
|
|
32
|
-
const { executeOperation, abort } = useOperationManager();
|
|
33
|
-
|
|
34
|
-
const setters: AsyncStateSetters<string, unknown> = useMemo(
|
|
35
|
-
() => ({
|
|
36
|
-
setIsLoading: setIsGenerating,
|
|
37
|
-
setError,
|
|
38
|
-
setResult,
|
|
39
|
-
setSecondaryResult: setJsonResult,
|
|
40
|
-
}),
|
|
41
|
-
[]
|
|
42
|
-
);
|
|
43
|
-
|
|
44
|
-
const callbacks = useMemo(
|
|
45
|
-
() => ({ onSuccess: options.onSuccess, onError: options.onError }),
|
|
46
|
-
[options.onSuccess, options.onError]
|
|
47
|
-
);
|
|
48
|
-
|
|
49
|
-
const model = options.model ?? DEFAULT_MODELS.TEXT;
|
|
50
|
-
|
|
51
|
-
const generate = useCallback(
|
|
52
|
-
async (prompt: string) => {
|
|
53
|
-
await executeOperation(async (signal, _operationId) => {
|
|
54
|
-
await executeWithState(
|
|
55
|
-
setters,
|
|
56
|
-
callbacks,
|
|
57
|
-
async () => {
|
|
58
|
-
return textGeneration.generateText(
|
|
59
|
-
model,
|
|
60
|
-
prompt,
|
|
61
|
-
options.generationConfig,
|
|
62
|
-
signal
|
|
63
|
-
);
|
|
64
|
-
},
|
|
65
|
-
(text: string) => {
|
|
66
|
-
setResult(text);
|
|
67
|
-
}
|
|
68
|
-
);
|
|
69
|
-
});
|
|
70
|
-
},
|
|
71
|
-
[model, options.generationConfig, setters, callbacks, executeOperation]
|
|
72
|
-
);
|
|
73
|
-
|
|
74
|
-
const generateJSON = useCallback(
|
|
75
|
-
async <T>(prompt: string, schema: Record<string, unknown>): Promise<T | null> => {
|
|
76
|
-
return executeOperation(async (signal, _operationId) => {
|
|
77
|
-
const jsonSetters: AsyncStateSetters<unknown, unknown> = {
|
|
78
|
-
setIsLoading: setIsGenerating,
|
|
79
|
-
setError,
|
|
80
|
-
setResult: setJsonResult,
|
|
81
|
-
setSecondaryResult: (value) =>
|
|
82
|
-
setResult(typeof value === "string" ? value : JSON.stringify(value)),
|
|
83
|
-
};
|
|
84
|
-
|
|
85
|
-
const jsonCallbacks = {
|
|
86
|
-
onSuccess: options.onSuccess
|
|
87
|
-
? (result: unknown) => options.onSuccess?.(JSON.stringify(result))
|
|
88
|
-
: undefined,
|
|
89
|
-
onError: options.onError,
|
|
90
|
-
};
|
|
91
|
-
|
|
92
|
-
const operationResult = await executeWithState<unknown>(
|
|
93
|
-
jsonSetters,
|
|
94
|
-
jsonCallbacks,
|
|
95
|
-
async () => {
|
|
96
|
-
return structuredText.generateStructuredText<T>(
|
|
97
|
-
model,
|
|
98
|
-
prompt,
|
|
99
|
-
schema,
|
|
100
|
-
options.generationConfig,
|
|
101
|
-
signal
|
|
102
|
-
);
|
|
103
|
-
},
|
|
104
|
-
(parsed: unknown) => {
|
|
105
|
-
setJsonResult(parsed);
|
|
106
|
-
setResult(JSON.stringify(parsed, null, 2));
|
|
107
|
-
}
|
|
108
|
-
);
|
|
109
|
-
|
|
110
|
-
return operationResult as T | null;
|
|
111
|
-
});
|
|
112
|
-
},
|
|
113
|
-
[model, options.generationConfig, callbacks, executeOperation]
|
|
114
|
-
);
|
|
115
|
-
|
|
116
|
-
const reset = useCallback(() => {
|
|
117
|
-
abort();
|
|
118
|
-
setResult(null);
|
|
119
|
-
setJsonResult(null);
|
|
120
|
-
setIsGenerating(false);
|
|
121
|
-
setError(null);
|
|
122
|
-
}, [abort]);
|
|
123
|
-
|
|
124
|
-
return { generate, generateJSON, result, jsonResult, isGenerating, error, reset };
|
|
125
|
-
}
|
|
@@ -1,88 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Operation Manager Hook
|
|
3
|
-
* Reusable abort controller and operation ID management
|
|
4
|
-
* Eliminates code duplication in hooks
|
|
5
|
-
*/
|
|
6
|
-
|
|
7
|
-
import { useRef, useCallback, useEffect } from "react";
|
|
8
|
-
|
|
9
|
-
export interface OperationManager {
|
|
10
|
-
/**
|
|
11
|
-
* Execute an operation with abort support and operation ID tracking
|
|
12
|
-
*/
|
|
13
|
-
executeOperation: <T>(
|
|
14
|
-
operation: (signal: AbortSignal, operationId: number) => Promise<T>
|
|
15
|
-
) => Promise<T>;
|
|
16
|
-
|
|
17
|
-
/**
|
|
18
|
-
* Abort current operation
|
|
19
|
-
*/
|
|
20
|
-
abort: () => void;
|
|
21
|
-
|
|
22
|
-
/**
|
|
23
|
-
* Check if current operation is active
|
|
24
|
-
*/
|
|
25
|
-
isOperationActive: (operationId: number) => boolean;
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
/**
|
|
29
|
-
* Hook for managing operations with abort control
|
|
30
|
-
*/
|
|
31
|
-
export function useOperationManager(): OperationManager {
|
|
32
|
-
const abortControllerRef = useRef<AbortController | null>(null);
|
|
33
|
-
const operationIdRef = useRef(0);
|
|
34
|
-
|
|
35
|
-
const abort = useCallback(() => {
|
|
36
|
-
if (abortControllerRef.current) {
|
|
37
|
-
abortControllerRef.current.abort();
|
|
38
|
-
abortControllerRef.current = null;
|
|
39
|
-
}
|
|
40
|
-
operationIdRef.current++;
|
|
41
|
-
}, []);
|
|
42
|
-
|
|
43
|
-
const isOperationActive = useCallback((operationId: number): boolean => {
|
|
44
|
-
return operationId === operationIdRef.current;
|
|
45
|
-
}, []);
|
|
46
|
-
|
|
47
|
-
const executeOperation = useCallback(
|
|
48
|
-
async <T>(
|
|
49
|
-
operation: (signal: AbortSignal, operationId: number) => Promise<T>
|
|
50
|
-
): Promise<T> => {
|
|
51
|
-
// Abort any existing operation
|
|
52
|
-
if (abortControllerRef.current) {
|
|
53
|
-
abortControllerRef.current.abort();
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
// Create new controller and increment operation ID
|
|
57
|
-
const controller = new AbortController();
|
|
58
|
-
abortControllerRef.current = controller;
|
|
59
|
-
const currentOpId = ++operationIdRef.current;
|
|
60
|
-
|
|
61
|
-
try {
|
|
62
|
-
return await operation(controller.signal, currentOpId);
|
|
63
|
-
} finally {
|
|
64
|
-
// Clean up only if this is still the current operation
|
|
65
|
-
if (currentOpId === operationIdRef.current) {
|
|
66
|
-
abortControllerRef.current = null;
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
},
|
|
70
|
-
[]
|
|
71
|
-
);
|
|
72
|
-
|
|
73
|
-
// Cleanup on unmount
|
|
74
|
-
useEffect(() => {
|
|
75
|
-
return () => {
|
|
76
|
-
if (abortControllerRef.current) {
|
|
77
|
-
abortControllerRef.current.abort();
|
|
78
|
-
}
|
|
79
|
-
operationIdRef.current++;
|
|
80
|
-
};
|
|
81
|
-
}, []);
|
|
82
|
-
|
|
83
|
-
return {
|
|
84
|
-
executeOperation,
|
|
85
|
-
abort,
|
|
86
|
-
isOperationActive,
|
|
87
|
-
};
|
|
88
|
-
}
|
|
@@ -1,112 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Config Builder Pattern
|
|
3
|
-
* Fluent API for building provider configuration
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
import { DEFAULT_MODELS } from "../domain/entities";
|
|
7
|
-
import type { GeminiConfig } from "../domain/entities";
|
|
8
|
-
|
|
9
|
-
export interface ProviderConfig {
|
|
10
|
-
apiKey: string;
|
|
11
|
-
textModel: string;
|
|
12
|
-
timeout: number;
|
|
13
|
-
strategy?: "cost" | "quality";
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
/**
|
|
17
|
-
* Builder for constructing provider configuration
|
|
18
|
-
* Provides a fluent API with validation and defaults
|
|
19
|
-
*/
|
|
20
|
-
export class ConfigBuilder {
|
|
21
|
-
private config: Omit<Partial<ProviderConfig>, 'textModel' | 'timeout'> & {
|
|
22
|
-
textModel: string;
|
|
23
|
-
timeout: number;
|
|
24
|
-
} = {
|
|
25
|
-
textModel: DEFAULT_MODELS.TEXT,
|
|
26
|
-
timeout: 30000,
|
|
27
|
-
};
|
|
28
|
-
|
|
29
|
-
/**
|
|
30
|
-
* Set API key (required)
|
|
31
|
-
*/
|
|
32
|
-
withApiKey(apiKey: string): this {
|
|
33
|
-
if (!apiKey || typeof apiKey !== "string" || apiKey.trim().length === 0) {
|
|
34
|
-
throw new Error("API key must be a non-empty string");
|
|
35
|
-
}
|
|
36
|
-
this.config.apiKey = apiKey.trim();
|
|
37
|
-
return this;
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
/**
|
|
41
|
-
* Set text model
|
|
42
|
-
*/
|
|
43
|
-
withTextModel(model: string): this {
|
|
44
|
-
if (!model || !model.startsWith("gemini-")) {
|
|
45
|
-
throw new Error("Invalid model name");
|
|
46
|
-
}
|
|
47
|
-
this.config.textModel = model;
|
|
48
|
-
return this;
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
/**
|
|
52
|
-
* Set request timeout (ms)
|
|
53
|
-
*/
|
|
54
|
-
withTimeout(timeout: number): this {
|
|
55
|
-
if (timeout <= 0 || timeout > 300000) {
|
|
56
|
-
throw new Error("Timeout must be between 1ms and 300000ms (5 minutes)");
|
|
57
|
-
}
|
|
58
|
-
this.config.timeout = timeout;
|
|
59
|
-
return this;
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
/**
|
|
63
|
-
* Set strategy (applies preset timeout)
|
|
64
|
-
*/
|
|
65
|
-
withStrategy(strategy: "cost" | "quality"): this {
|
|
66
|
-
this.config.strategy = strategy;
|
|
67
|
-
|
|
68
|
-
// Apply strategy-based defaults
|
|
69
|
-
if (strategy === "quality") {
|
|
70
|
-
this.config.timeout = 60000;
|
|
71
|
-
} else {
|
|
72
|
-
this.config.timeout = 30000;
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
return this;
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
/**
|
|
79
|
-
* Build final configuration
|
|
80
|
-
*/
|
|
81
|
-
build(): ProviderConfig {
|
|
82
|
-
if (!this.config.apiKey) {
|
|
83
|
-
throw new Error("API key is required. Call withApiKey() before build()");
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
return {
|
|
87
|
-
apiKey: this.config.apiKey,
|
|
88
|
-
textModel: this.config.textModel,
|
|
89
|
-
timeout: this.config.timeout,
|
|
90
|
-
strategy: this.config.strategy,
|
|
91
|
-
};
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
/**
|
|
95
|
-
* Convert to GeminiConfig format
|
|
96
|
-
*/
|
|
97
|
-
toGeminiConfig(): GeminiConfig {
|
|
98
|
-
const config = this.build();
|
|
99
|
-
return {
|
|
100
|
-
apiKey: config.apiKey,
|
|
101
|
-
textModel: config.textModel,
|
|
102
|
-
defaultTimeoutMs: config.timeout,
|
|
103
|
-
};
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
/**
|
|
107
|
-
* Create a new builder instance
|
|
108
|
-
*/
|
|
109
|
-
static create(): ConfigBuilder {
|
|
110
|
-
return new ConfigBuilder();
|
|
111
|
-
}
|
|
112
|
-
}
|
|
@@ -1,65 +0,0 @@
|
|
|
1
|
-
import { geminiClient } from "../infrastructure/services/GeminiClient";
|
|
2
|
-
import { ConfigBuilder, type ProviderConfig } from "./ConfigBuilder";
|
|
3
|
-
|
|
4
|
-
// Re-export for public API
|
|
5
|
-
export { ConfigBuilder } from "./ConfigBuilder";
|
|
6
|
-
export type { ProviderConfig } from "./ConfigBuilder";
|
|
7
|
-
|
|
8
|
-
export interface ProviderFactoryOptions {
|
|
9
|
-
apiKey: string;
|
|
10
|
-
timeout?: number;
|
|
11
|
-
textModel?: string;
|
|
12
|
-
strategy?: "cost" | "quality";
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
class ProviderFactory {
|
|
16
|
-
private currentConfig: ProviderConfig | null = null;
|
|
17
|
-
|
|
18
|
-
/**
|
|
19
|
-
* Initialize provider with configuration
|
|
20
|
-
*/
|
|
21
|
-
initialize(options: ProviderFactoryOptions): void {
|
|
22
|
-
// Build configuration using builder pattern (inline, no state needed)
|
|
23
|
-
const builder = ConfigBuilder.create().withApiKey(options.apiKey);
|
|
24
|
-
|
|
25
|
-
if (options.strategy) {
|
|
26
|
-
builder.withStrategy(options.strategy);
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
if (options.textModel) {
|
|
30
|
-
builder.withTextModel(options.textModel);
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
if (options.timeout) {
|
|
34
|
-
builder.withTimeout(options.timeout);
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
this.currentConfig = builder.build();
|
|
38
|
-
|
|
39
|
-
// Initialize Gemini client
|
|
40
|
-
const geminiConfig = builder.toGeminiConfig();
|
|
41
|
-
geminiClient.initialize(geminiConfig);
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
/**
|
|
45
|
-
* Check if provider is initialized
|
|
46
|
-
*/
|
|
47
|
-
isInitialized(): boolean {
|
|
48
|
-
return this.currentConfig !== null;
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
/**
|
|
52
|
-
* Update configuration
|
|
53
|
-
* API key changes require re-initialization
|
|
54
|
-
*/
|
|
55
|
-
updateConfig(updates: Partial<ProviderFactoryOptions>): void {
|
|
56
|
-
if (!this.currentConfig) {
|
|
57
|
-
throw new Error("Provider not initialized. Call initialize() first.");
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
// Re-initialize with merged config to ensure GeminiClient is updated
|
|
61
|
-
this.initialize({ ...this.currentConfig, ...updates });
|
|
62
|
-
}
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
export const providerFactory = new ProviderFactory();
|