@strands-agents/sdk 0.2.0 → 0.2.1
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/src/agent/__tests__/agent.hook.test.js +130 -28
- package/dist/src/agent/__tests__/agent.hook.test.js.map +1 -1
- package/dist/src/agent/agent.d.ts.map +1 -1
- package/dist/src/agent/agent.js +64 -47
- package/dist/src/agent/agent.js.map +1 -1
- package/dist/src/conversation-manager/__tests__/null-conversation-manager.test.js +2 -2
- package/dist/src/conversation-manager/__tests__/null-conversation-manager.test.js.map +1 -1
- package/dist/src/conversation-manager/sliding-window-conversation-manager.js +1 -1
- package/dist/src/conversation-manager/sliding-window-conversation-manager.js.map +1 -1
- package/dist/src/hooks/__tests__/events.test.js +37 -8
- package/dist/src/hooks/__tests__/events.test.js.map +1 -1
- package/dist/src/hooks/events.d.ts +7 -3
- package/dist/src/hooks/events.d.ts.map +1 -1
- package/dist/src/hooks/events.js +7 -3
- package/dist/src/hooks/events.js.map +1 -1
- package/dist/src/models/__tests__/gemini.test.d.ts +2 -0
- package/dist/src/models/__tests__/gemini.test.d.ts.map +1 -0
- package/dist/src/models/__tests__/gemini.test.js +280 -0
- package/dist/src/models/__tests__/gemini.test.js.map +1 -0
- package/dist/src/models/gemini/adapters.d.ts +37 -0
- package/dist/src/models/gemini/adapters.d.ts.map +1 -0
- package/dist/src/models/gemini/adapters.js +119 -0
- package/dist/src/models/gemini/adapters.js.map +1 -0
- package/dist/src/models/gemini/errors.d.ts +37 -0
- package/dist/src/models/gemini/errors.d.ts.map +1 -0
- package/dist/src/models/gemini/errors.js +58 -0
- package/dist/src/models/gemini/errors.js.map +1 -0
- package/dist/src/models/gemini/model.d.ts +136 -0
- package/dist/src/models/gemini/model.d.ts.map +1 -0
- package/dist/src/models/gemini/model.js +230 -0
- package/dist/src/models/gemini/model.js.map +1 -0
- package/dist/src/models/gemini/types.d.ts +62 -0
- package/dist/src/models/gemini/types.d.ts.map +1 -0
- package/dist/src/models/gemini/types.js +5 -0
- package/dist/src/models/gemini/types.js.map +1 -0
- package/dist/src/models/openai.d.ts.map +1 -1
- package/dist/src/models/openai.js +3 -40
- package/dist/src/models/openai.js.map +1 -1
- package/dist/src/tsconfig.tsbuildinfo +1 -1
- package/dist/src/types/media.d.ts +7 -0
- package/dist/src/types/media.d.ts.map +1 -1
- package/dist/src/types/media.js +43 -0
- package/dist/src/types/media.js.map +1 -1
- package/dist/src/vended-tools/bash/__tests__/bash.test.js +3 -2
- package/dist/src/vended-tools/bash/__tests__/bash.test.js.map +1 -1
- package/package.json +12 -2
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Error handling utilities for the Gemini model provider.
|
|
3
|
+
*
|
|
4
|
+
* @internal This module is not part of the public API.
|
|
5
|
+
*/
|
|
6
|
+
/**
|
|
7
|
+
* Recognized error types from Gemini API responses.
|
|
8
|
+
*
|
|
9
|
+
* This union type will expand as more error types are supported
|
|
10
|
+
* (e.g., 'throttling', 'invalidRequest').
|
|
11
|
+
*/
|
|
12
|
+
export type GeminiErrorType = 'contextOverflow';
|
|
13
|
+
/**
|
|
14
|
+
* Configuration for handling a specific error status.
|
|
15
|
+
* If messagePatterns is provided, the error message must match one of the patterns.
|
|
16
|
+
* If messagePatterns is not provided, the status alone triggers the error type.
|
|
17
|
+
*/
|
|
18
|
+
export interface ErrorStatusConfig {
|
|
19
|
+
type: GeminiErrorType;
|
|
20
|
+
messagePatterns?: Set<string>;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Mapping of Gemini API error statuses to error handling configuration.
|
|
24
|
+
* Maps status codes to either direct error types or message-pattern-based detection.
|
|
25
|
+
*/
|
|
26
|
+
export declare const ERROR_STATUS_MAP: Record<string, ErrorStatusConfig>;
|
|
27
|
+
/**
|
|
28
|
+
* Classifies a Gemini API error based on status and message patterns.
|
|
29
|
+
* Returns the error type if recognized, undefined otherwise.
|
|
30
|
+
*
|
|
31
|
+
* @param error - The error to classify
|
|
32
|
+
* @returns The error type if recognized, undefined otherwise
|
|
33
|
+
*
|
|
34
|
+
* @internal
|
|
35
|
+
*/
|
|
36
|
+
export declare function classifyGeminiError(error: Error): GeminiErrorType | undefined;
|
|
37
|
+
//# sourceMappingURL=errors.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../../../src/models/gemini/errors.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAIH;;;;;GAKG;AACH,MAAM,MAAM,eAAe,GAAG,iBAAiB,CAAA;AAE/C;;;;GAIG;AACH,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,eAAe,CAAA;IACrB,eAAe,CAAC,EAAE,GAAG,CAAC,MAAM,CAAC,CAAA;CAC9B;AAED;;;GAGG;AACH,eAAO,MAAM,gBAAgB,EAAE,MAAM,CAAC,MAAM,EAAE,iBAAiB,CAK9D,CAAA;AAED;;;;;;;;GAQG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,KAAK,GAAG,eAAe,GAAG,SAAS,CAoC7E"}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Error handling utilities for the Gemini model provider.
|
|
3
|
+
*
|
|
4
|
+
* @internal This module is not part of the public API.
|
|
5
|
+
*/
|
|
6
|
+
import { logger } from '../../logging/logger.js';
|
|
7
|
+
/**
|
|
8
|
+
* Mapping of Gemini API error statuses to error handling configuration.
|
|
9
|
+
* Maps status codes to either direct error types or message-pattern-based detection.
|
|
10
|
+
*/
|
|
11
|
+
export const ERROR_STATUS_MAP = {
|
|
12
|
+
INVALID_ARGUMENT: {
|
|
13
|
+
type: 'contextOverflow',
|
|
14
|
+
messagePatterns: new Set(['exceeds the maximum number of tokens']),
|
|
15
|
+
},
|
|
16
|
+
};
|
|
17
|
+
/**
|
|
18
|
+
* Classifies a Gemini API error based on status and message patterns.
|
|
19
|
+
* Returns the error type if recognized, undefined otherwise.
|
|
20
|
+
*
|
|
21
|
+
* @param error - The error to classify
|
|
22
|
+
* @returns The error type if recognized, undefined otherwise
|
|
23
|
+
*
|
|
24
|
+
* @internal
|
|
25
|
+
*/
|
|
26
|
+
export function classifyGeminiError(error) {
|
|
27
|
+
if (!error.message) {
|
|
28
|
+
return undefined;
|
|
29
|
+
}
|
|
30
|
+
let status;
|
|
31
|
+
let message;
|
|
32
|
+
try {
|
|
33
|
+
const parsed = JSON.parse(error.message);
|
|
34
|
+
status = parsed?.error?.status || '';
|
|
35
|
+
message = parsed?.error?.message || '';
|
|
36
|
+
}
|
|
37
|
+
catch {
|
|
38
|
+
logger.debug(`error_message=<${error.message}> | gemini api returned non-json error`);
|
|
39
|
+
return undefined;
|
|
40
|
+
}
|
|
41
|
+
const config = ERROR_STATUS_MAP[status.toUpperCase()];
|
|
42
|
+
if (!config) {
|
|
43
|
+
return undefined;
|
|
44
|
+
}
|
|
45
|
+
// If no message patterns required, status alone determines the error type
|
|
46
|
+
if (!config.messagePatterns) {
|
|
47
|
+
return config.type;
|
|
48
|
+
}
|
|
49
|
+
// Check if message matches any of the patterns
|
|
50
|
+
const lowerMessage = message.toLowerCase();
|
|
51
|
+
for (const pattern of config.messagePatterns) {
|
|
52
|
+
if (lowerMessage.includes(pattern)) {
|
|
53
|
+
return config.type;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
return undefined;
|
|
57
|
+
}
|
|
58
|
+
//# sourceMappingURL=errors.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.js","sourceRoot":"","sources":["../../../../src/models/gemini/errors.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,MAAM,EAAE,MAAM,yBAAyB,CAAA;AAoBhD;;;GAGG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAAsC;IACjE,gBAAgB,EAAE;QAChB,IAAI,EAAE,iBAAiB;QACvB,eAAe,EAAE,IAAI,GAAG,CAAC,CAAC,sCAAsC,CAAC,CAAC;KACnE;CACF,CAAA;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,mBAAmB,CAAC,KAAY;IAC9C,IAAI,CAAC,KAAK,CAAC,OAAO,EAAE,CAAC;QACnB,OAAO,SAAS,CAAA;IAClB,CAAC;IAED,IAAI,MAAc,CAAA;IAClB,IAAI,OAAe,CAAA;IAEnB,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,OAAO,CAAC,CAAA;QACxC,MAAM,GAAG,MAAM,EAAE,KAAK,EAAE,MAAM,IAAI,EAAE,CAAA;QACpC,OAAO,GAAG,MAAM,EAAE,KAAK,EAAE,OAAO,IAAI,EAAE,CAAA;IACxC,CAAC;IAAC,MAAM,CAAC;QACP,MAAM,CAAC,KAAK,CAAC,kBAAkB,KAAK,CAAC,OAAO,wCAAwC,CAAC,CAAA;QACrF,OAAO,SAAS,CAAA;IAClB,CAAC;IAED,MAAM,MAAM,GAAG,gBAAgB,CAAC,MAAM,CAAC,WAAW,EAAE,CAAC,CAAA;IACrD,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,OAAO,SAAS,CAAA;IAClB,CAAC;IAED,0EAA0E;IAC1E,IAAI,CAAC,MAAM,CAAC,eAAe,EAAE,CAAC;QAC5B,OAAO,MAAM,CAAC,IAAI,CAAA;IACpB,CAAC;IAED,+CAA+C;IAC/C,MAAM,YAAY,GAAG,OAAO,CAAC,WAAW,EAAE,CAAA;IAC1C,KAAK,MAAM,OAAO,IAAI,MAAM,CAAC,eAAe,EAAE,CAAC;QAC7C,IAAI,YAAY,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC;YACnC,OAAO,MAAM,CAAC,IAAI,CAAA;QACpB,CAAC;IACH,CAAC;IAED,OAAO,SAAS,CAAA;AAClB,CAAC"}
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Google Gemini model provider implementation.
|
|
3
|
+
*
|
|
4
|
+
* This module provides integration with Google's Gemini API,
|
|
5
|
+
* supporting streaming responses and configurable model parameters.
|
|
6
|
+
*
|
|
7
|
+
* @see https://ai.google.dev/docs
|
|
8
|
+
*/
|
|
9
|
+
import { Model } from '../model.js';
|
|
10
|
+
import type { StreamOptions } from '../model.js';
|
|
11
|
+
import type { Message } from '../../types/messages.js';
|
|
12
|
+
import type { ModelStreamEvent } from '../streaming.js';
|
|
13
|
+
import type { GeminiModelConfig, GeminiModelOptions } from './types.js';
|
|
14
|
+
export type { GeminiModelConfig, GeminiModelOptions };
|
|
15
|
+
/**
|
|
16
|
+
* Google Gemini model provider implementation.
|
|
17
|
+
*
|
|
18
|
+
* Implements the Model interface for Google Gemini using the Generative AI API.
|
|
19
|
+
* Supports streaming responses and comprehensive configuration.
|
|
20
|
+
*
|
|
21
|
+
* @example
|
|
22
|
+
* ```typescript
|
|
23
|
+
* const provider = new GeminiModel({
|
|
24
|
+
* apiKey: 'your-api-key',
|
|
25
|
+
* modelId: 'gemini-2.5-flash',
|
|
26
|
+
* params: { temperature: 0.7, maxOutputTokens: 1024 }
|
|
27
|
+
* })
|
|
28
|
+
*
|
|
29
|
+
* const messages: Message[] = [
|
|
30
|
+
* { role: 'user', content: [{ type: 'textBlock', text: 'Hello!' }] }
|
|
31
|
+
* ]
|
|
32
|
+
*
|
|
33
|
+
* for await (const event of provider.stream(messages)) {
|
|
34
|
+
* if (event.type === 'modelContentBlockDeltaEvent' && event.delta.type === 'textDelta') {
|
|
35
|
+
* process.stdout.write(event.delta.text)
|
|
36
|
+
* }
|
|
37
|
+
* }
|
|
38
|
+
* ```
|
|
39
|
+
*/
|
|
40
|
+
export declare class GeminiModel extends Model<GeminiModelConfig> {
|
|
41
|
+
private _config;
|
|
42
|
+
private _client;
|
|
43
|
+
/**
|
|
44
|
+
* Creates a new GeminiModel instance.
|
|
45
|
+
*
|
|
46
|
+
* @param options - Configuration for model and client
|
|
47
|
+
*
|
|
48
|
+
* @example
|
|
49
|
+
* ```typescript
|
|
50
|
+
* // Minimal configuration with API key
|
|
51
|
+
* const provider = new GeminiModel({
|
|
52
|
+
* apiKey: 'your-api-key'
|
|
53
|
+
* })
|
|
54
|
+
*
|
|
55
|
+
* // With model configuration
|
|
56
|
+
* const provider = new GeminiModel({
|
|
57
|
+
* apiKey: 'your-api-key',
|
|
58
|
+
* modelId: 'gemini-2.5-flash',
|
|
59
|
+
* params: { temperature: 0.8, maxOutputTokens: 2048 }
|
|
60
|
+
* })
|
|
61
|
+
*
|
|
62
|
+
* // Using environment variable for API key
|
|
63
|
+
* const provider = new GeminiModel({
|
|
64
|
+
* modelId: 'gemini-2.5-flash'
|
|
65
|
+
* })
|
|
66
|
+
*
|
|
67
|
+
* // Using a pre-configured client instance
|
|
68
|
+
* const client = new GoogleGenAI({ apiKey: 'your-api-key' })
|
|
69
|
+
* const provider = new GeminiModel({
|
|
70
|
+
* client
|
|
71
|
+
* })
|
|
72
|
+
* ```
|
|
73
|
+
*/
|
|
74
|
+
constructor(options?: GeminiModelOptions);
|
|
75
|
+
/**
|
|
76
|
+
* Updates the model configuration.
|
|
77
|
+
* Merges the provided configuration with existing settings.
|
|
78
|
+
*
|
|
79
|
+
* @param modelConfig - Configuration object with model-specific settings to update
|
|
80
|
+
*
|
|
81
|
+
* @example
|
|
82
|
+
* ```typescript
|
|
83
|
+
* // Update model parameters
|
|
84
|
+
* provider.updateConfig({
|
|
85
|
+
* params: { temperature: 0.9, maxOutputTokens: 2048 }
|
|
86
|
+
* })
|
|
87
|
+
* ```
|
|
88
|
+
*/
|
|
89
|
+
updateConfig(modelConfig: GeminiModelConfig): void;
|
|
90
|
+
/**
|
|
91
|
+
* Retrieves the current model configuration.
|
|
92
|
+
*
|
|
93
|
+
* @returns The current configuration object
|
|
94
|
+
*
|
|
95
|
+
* @example
|
|
96
|
+
* ```typescript
|
|
97
|
+
* const config = provider.getConfig()
|
|
98
|
+
* console.log(config.modelId)
|
|
99
|
+
* ```
|
|
100
|
+
*/
|
|
101
|
+
getConfig(): GeminiModelConfig;
|
|
102
|
+
/**
|
|
103
|
+
* Streams a conversation with the Gemini model.
|
|
104
|
+
* Returns an async iterable that yields streaming events as they occur.
|
|
105
|
+
*
|
|
106
|
+
* @param messages - Array of conversation messages
|
|
107
|
+
* @param options - Optional streaming configuration
|
|
108
|
+
* @returns Async iterable of streaming events
|
|
109
|
+
*
|
|
110
|
+
* @throws \{ContextWindowOverflowError\} When input exceeds the model's context window
|
|
111
|
+
*
|
|
112
|
+
* @example
|
|
113
|
+
* ```typescript
|
|
114
|
+
* const provider = new GeminiModel({ apiKey: 'your-api-key' })
|
|
115
|
+
* const messages: Message[] = [
|
|
116
|
+
* { role: 'user', content: [{ type: 'textBlock', text: 'What is 2+2?' }] }
|
|
117
|
+
* ]
|
|
118
|
+
*
|
|
119
|
+
* for await (const event of provider.stream(messages)) {
|
|
120
|
+
* if (event.type === 'modelContentBlockDeltaEvent' && event.delta.type === 'textDelta') {
|
|
121
|
+
* process.stdout.write(event.delta.text)
|
|
122
|
+
* }
|
|
123
|
+
* }
|
|
124
|
+
* ```
|
|
125
|
+
*/
|
|
126
|
+
stream(messages: Message[], options?: StreamOptions): AsyncIterable<ModelStreamEvent>;
|
|
127
|
+
/**
|
|
128
|
+
* Gets API key from environment variables.
|
|
129
|
+
*/
|
|
130
|
+
private static _getEnvApiKey;
|
|
131
|
+
/**
|
|
132
|
+
* Formats a request for the Gemini API.
|
|
133
|
+
*/
|
|
134
|
+
private _formatRequest;
|
|
135
|
+
}
|
|
136
|
+
//# sourceMappingURL=model.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"model.d.ts","sourceRoot":"","sources":["../../../../src/models/gemini/model.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAGH,OAAO,EAAE,KAAK,EAAE,MAAM,aAAa,CAAA;AACnC,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAA;AAChD,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,yBAAyB,CAAA;AACtD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAA;AAEvD,OAAO,KAAK,EAAE,iBAAiB,EAAE,kBAAkB,EAAqB,MAAM,YAAY,CAAA;AAC1F,YAAY,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,CAAA;AASrD;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,qBAAa,WAAY,SAAQ,KAAK,CAAC,iBAAiB,CAAC;IACvD,OAAO,CAAC,OAAO,CAAmB;IAClC,OAAO,CAAC,OAAO,CAAa;IAE5B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OA8BG;gBACS,OAAO,CAAC,EAAE,kBAAkB;IAwBxC;;;;;;;;;;;;;OAaG;IACH,YAAY,CAAC,WAAW,EAAE,iBAAiB,GAAG,IAAI;IAIlD;;;;;;;;;;OAUG;IACH,SAAS,IAAI,iBAAiB;IAI9B;;;;;;;;;;;;;;;;;;;;;;;OAuBG;IACI,MAAM,CAAC,QAAQ,EAAE,OAAO,EAAE,EAAE,OAAO,CAAC,EAAE,aAAa,GAAG,aAAa,CAAC,gBAAgB,CAAC;IA4C5F;;OAEG;IACH,OAAO,CAAC,MAAM,CAAC,aAAa;IAI5B;;OAEG;IACH,OAAO,CAAC,cAAc;CAoCvB"}
|
|
@@ -0,0 +1,230 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Google Gemini model provider implementation.
|
|
3
|
+
*
|
|
4
|
+
* This module provides integration with Google's Gemini API,
|
|
5
|
+
* supporting streaming responses and configurable model parameters.
|
|
6
|
+
*
|
|
7
|
+
* @see https://ai.google.dev/docs
|
|
8
|
+
*/
|
|
9
|
+
import { GoogleGenAI } from '@google/genai';
|
|
10
|
+
import { Model } from '../model.js';
|
|
11
|
+
import { ContextWindowOverflowError } from '../../errors.js';
|
|
12
|
+
import { classifyGeminiError } from './errors.js';
|
|
13
|
+
import { formatMessages, mapChunkToEvents } from './adapters.js';
|
|
14
|
+
/**
|
|
15
|
+
* Default Gemini model ID.
|
|
16
|
+
*/
|
|
17
|
+
const DEFAULT_GEMINI_MODEL_ID = 'gemini-2.5-flash';
|
|
18
|
+
/**
|
|
19
|
+
* Google Gemini model provider implementation.
|
|
20
|
+
*
|
|
21
|
+
* Implements the Model interface for Google Gemini using the Generative AI API.
|
|
22
|
+
* Supports streaming responses and comprehensive configuration.
|
|
23
|
+
*
|
|
24
|
+
* @example
|
|
25
|
+
* ```typescript
|
|
26
|
+
* const provider = new GeminiModel({
|
|
27
|
+
* apiKey: 'your-api-key',
|
|
28
|
+
* modelId: 'gemini-2.5-flash',
|
|
29
|
+
* params: { temperature: 0.7, maxOutputTokens: 1024 }
|
|
30
|
+
* })
|
|
31
|
+
*
|
|
32
|
+
* const messages: Message[] = [
|
|
33
|
+
* { role: 'user', content: [{ type: 'textBlock', text: 'Hello!' }] }
|
|
34
|
+
* ]
|
|
35
|
+
*
|
|
36
|
+
* for await (const event of provider.stream(messages)) {
|
|
37
|
+
* if (event.type === 'modelContentBlockDeltaEvent' && event.delta.type === 'textDelta') {
|
|
38
|
+
* process.stdout.write(event.delta.text)
|
|
39
|
+
* }
|
|
40
|
+
* }
|
|
41
|
+
* ```
|
|
42
|
+
*/
|
|
43
|
+
export class GeminiModel extends Model {
|
|
44
|
+
_config;
|
|
45
|
+
_client;
|
|
46
|
+
/**
|
|
47
|
+
* Creates a new GeminiModel instance.
|
|
48
|
+
*
|
|
49
|
+
* @param options - Configuration for model and client
|
|
50
|
+
*
|
|
51
|
+
* @example
|
|
52
|
+
* ```typescript
|
|
53
|
+
* // Minimal configuration with API key
|
|
54
|
+
* const provider = new GeminiModel({
|
|
55
|
+
* apiKey: 'your-api-key'
|
|
56
|
+
* })
|
|
57
|
+
*
|
|
58
|
+
* // With model configuration
|
|
59
|
+
* const provider = new GeminiModel({
|
|
60
|
+
* apiKey: 'your-api-key',
|
|
61
|
+
* modelId: 'gemini-2.5-flash',
|
|
62
|
+
* params: { temperature: 0.8, maxOutputTokens: 2048 }
|
|
63
|
+
* })
|
|
64
|
+
*
|
|
65
|
+
* // Using environment variable for API key
|
|
66
|
+
* const provider = new GeminiModel({
|
|
67
|
+
* modelId: 'gemini-2.5-flash'
|
|
68
|
+
* })
|
|
69
|
+
*
|
|
70
|
+
* // Using a pre-configured client instance
|
|
71
|
+
* const client = new GoogleGenAI({ apiKey: 'your-api-key' })
|
|
72
|
+
* const provider = new GeminiModel({
|
|
73
|
+
* client
|
|
74
|
+
* })
|
|
75
|
+
* ```
|
|
76
|
+
*/
|
|
77
|
+
constructor(options) {
|
|
78
|
+
super();
|
|
79
|
+
const { apiKey, client, clientConfig, ...modelConfig } = options || {};
|
|
80
|
+
this._config = modelConfig;
|
|
81
|
+
if (client) {
|
|
82
|
+
this._client = client;
|
|
83
|
+
}
|
|
84
|
+
else {
|
|
85
|
+
const resolvedApiKey = apiKey || GeminiModel._getEnvApiKey();
|
|
86
|
+
if (!resolvedApiKey) {
|
|
87
|
+
throw new Error("Gemini API key is required. Provide it via the 'apiKey' option or set the GEMINI_API_KEY environment variable.");
|
|
88
|
+
}
|
|
89
|
+
this._client = new GoogleGenAI({
|
|
90
|
+
apiKey: resolvedApiKey,
|
|
91
|
+
...clientConfig,
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* Updates the model configuration.
|
|
97
|
+
* Merges the provided configuration with existing settings.
|
|
98
|
+
*
|
|
99
|
+
* @param modelConfig - Configuration object with model-specific settings to update
|
|
100
|
+
*
|
|
101
|
+
* @example
|
|
102
|
+
* ```typescript
|
|
103
|
+
* // Update model parameters
|
|
104
|
+
* provider.updateConfig({
|
|
105
|
+
* params: { temperature: 0.9, maxOutputTokens: 2048 }
|
|
106
|
+
* })
|
|
107
|
+
* ```
|
|
108
|
+
*/
|
|
109
|
+
updateConfig(modelConfig) {
|
|
110
|
+
this._config = { ...this._config, ...modelConfig };
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* Retrieves the current model configuration.
|
|
114
|
+
*
|
|
115
|
+
* @returns The current configuration object
|
|
116
|
+
*
|
|
117
|
+
* @example
|
|
118
|
+
* ```typescript
|
|
119
|
+
* const config = provider.getConfig()
|
|
120
|
+
* console.log(config.modelId)
|
|
121
|
+
* ```
|
|
122
|
+
*/
|
|
123
|
+
getConfig() {
|
|
124
|
+
return this._config;
|
|
125
|
+
}
|
|
126
|
+
/**
|
|
127
|
+
* Streams a conversation with the Gemini model.
|
|
128
|
+
* Returns an async iterable that yields streaming events as they occur.
|
|
129
|
+
*
|
|
130
|
+
* @param messages - Array of conversation messages
|
|
131
|
+
* @param options - Optional streaming configuration
|
|
132
|
+
* @returns Async iterable of streaming events
|
|
133
|
+
*
|
|
134
|
+
* @throws \{ContextWindowOverflowError\} When input exceeds the model's context window
|
|
135
|
+
*
|
|
136
|
+
* @example
|
|
137
|
+
* ```typescript
|
|
138
|
+
* const provider = new GeminiModel({ apiKey: 'your-api-key' })
|
|
139
|
+
* const messages: Message[] = [
|
|
140
|
+
* { role: 'user', content: [{ type: 'textBlock', text: 'What is 2+2?' }] }
|
|
141
|
+
* ]
|
|
142
|
+
*
|
|
143
|
+
* for await (const event of provider.stream(messages)) {
|
|
144
|
+
* if (event.type === 'modelContentBlockDeltaEvent' && event.delta.type === 'textDelta') {
|
|
145
|
+
* process.stdout.write(event.delta.text)
|
|
146
|
+
* }
|
|
147
|
+
* }
|
|
148
|
+
* ```
|
|
149
|
+
*/
|
|
150
|
+
async *stream(messages, options) {
|
|
151
|
+
if (!messages || messages.length === 0) {
|
|
152
|
+
throw new Error('At least one message is required');
|
|
153
|
+
}
|
|
154
|
+
try {
|
|
155
|
+
const params = this._formatRequest(messages, options);
|
|
156
|
+
const stream = await this._client.models.generateContentStream(params);
|
|
157
|
+
const streamState = {
|
|
158
|
+
messageStarted: false,
|
|
159
|
+
textContentBlockStarted: false,
|
|
160
|
+
inputTokens: 0,
|
|
161
|
+
outputTokens: 0,
|
|
162
|
+
};
|
|
163
|
+
for await (const chunk of stream) {
|
|
164
|
+
yield* mapChunkToEvents(chunk, streamState);
|
|
165
|
+
}
|
|
166
|
+
if (streamState.inputTokens > 0 || streamState.outputTokens > 0) {
|
|
167
|
+
yield {
|
|
168
|
+
type: 'modelMetadataEvent',
|
|
169
|
+
usage: {
|
|
170
|
+
inputTokens: streamState.inputTokens,
|
|
171
|
+
outputTokens: streamState.outputTokens,
|
|
172
|
+
totalTokens: streamState.inputTokens + streamState.outputTokens,
|
|
173
|
+
},
|
|
174
|
+
};
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
catch (error) {
|
|
178
|
+
if (!(error instanceof Error)) {
|
|
179
|
+
throw error;
|
|
180
|
+
}
|
|
181
|
+
const errorType = classifyGeminiError(error);
|
|
182
|
+
if (errorType === 'contextOverflow') {
|
|
183
|
+
throw new ContextWindowOverflowError(error.message);
|
|
184
|
+
}
|
|
185
|
+
throw error;
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
/**
|
|
189
|
+
* Gets API key from environment variables.
|
|
190
|
+
*/
|
|
191
|
+
static _getEnvApiKey() {
|
|
192
|
+
return globalThis?.process?.env?.GEMINI_API_KEY;
|
|
193
|
+
}
|
|
194
|
+
/**
|
|
195
|
+
* Formats a request for the Gemini API.
|
|
196
|
+
*/
|
|
197
|
+
_formatRequest(messages, options) {
|
|
198
|
+
const contents = formatMessages(messages);
|
|
199
|
+
const config = {};
|
|
200
|
+
// Add system instruction
|
|
201
|
+
if (options?.systemPrompt !== undefined) {
|
|
202
|
+
if (typeof options.systemPrompt === 'string') {
|
|
203
|
+
if (options.systemPrompt.trim().length > 0) {
|
|
204
|
+
config.systemInstruction = options.systemPrompt;
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
else if (Array.isArray(options.systemPrompt) && options.systemPrompt.length > 0) {
|
|
208
|
+
const textBlocks = [];
|
|
209
|
+
for (const block of options.systemPrompt) {
|
|
210
|
+
if (block.type === 'textBlock') {
|
|
211
|
+
textBlocks.push(block.text);
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
if (textBlocks.length > 0) {
|
|
215
|
+
config.systemInstruction = textBlocks.join('');
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
// Spread params object for forward compatibility
|
|
220
|
+
if (this._config.params) {
|
|
221
|
+
Object.assign(config, this._config.params);
|
|
222
|
+
}
|
|
223
|
+
return {
|
|
224
|
+
model: this._config.modelId ?? DEFAULT_GEMINI_MODEL_ID,
|
|
225
|
+
contents,
|
|
226
|
+
config,
|
|
227
|
+
};
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
//# sourceMappingURL=model.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"model.js","sourceRoot":"","sources":["../../../../src/models/gemini/model.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Type definitions for the Gemini model provider.
|
|
3
|
+
*/
|
|
4
|
+
import type { GoogleGenAI, GoogleGenAIOptions } from '@google/genai';
|
|
5
|
+
import type { BaseModelConfig } from '../model.js';
|
|
6
|
+
/**
|
|
7
|
+
* Configuration interface for Gemini model provider.
|
|
8
|
+
*
|
|
9
|
+
* @example
|
|
10
|
+
* ```typescript
|
|
11
|
+
* const config: GeminiModelConfig = {
|
|
12
|
+
* modelId: 'gemini-2.5-flash',
|
|
13
|
+
* params: { temperature: 0.7, maxOutputTokens: 1024 }
|
|
14
|
+
* }
|
|
15
|
+
* ```
|
|
16
|
+
*
|
|
17
|
+
* @see https://ai.google.dev/api/generate-content#generationconfig
|
|
18
|
+
*/
|
|
19
|
+
export interface GeminiModelConfig extends BaseModelConfig {
|
|
20
|
+
/**
|
|
21
|
+
* Gemini model identifier (e.g., gemini-2.5-flash, gemini-2.5-pro).
|
|
22
|
+
*
|
|
23
|
+
* @defaultValue 'gemini-2.5-flash'
|
|
24
|
+
* @see https://ai.google.dev/gemini-api/docs/models
|
|
25
|
+
*/
|
|
26
|
+
modelId?: string;
|
|
27
|
+
/**
|
|
28
|
+
* Additional parameters to pass to the Gemini API (e.g., temperature, maxOutputTokens).
|
|
29
|
+
*
|
|
30
|
+
* @see https://ai.google.dev/api/generate-content#generationconfig
|
|
31
|
+
*/
|
|
32
|
+
params?: Record<string, unknown>;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Options interface for creating a GeminiModel instance.
|
|
36
|
+
*/
|
|
37
|
+
export interface GeminiModelOptions extends GeminiModelConfig {
|
|
38
|
+
/**
|
|
39
|
+
* Gemini API key (falls back to GEMINI_API_KEY environment variable).
|
|
40
|
+
*/
|
|
41
|
+
apiKey?: string;
|
|
42
|
+
/**
|
|
43
|
+
* Pre-configured Google GenAI client instance.
|
|
44
|
+
* If provided, this client will be used instead of creating a new one.
|
|
45
|
+
*/
|
|
46
|
+
client?: GoogleGenAI;
|
|
47
|
+
/**
|
|
48
|
+
* Additional Google GenAI client configuration.
|
|
49
|
+
* Only used if client is not provided.
|
|
50
|
+
*/
|
|
51
|
+
clientConfig?: Omit<GoogleGenAIOptions, 'apiKey'>;
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Internal state for tracking streaming progress.
|
|
55
|
+
*/
|
|
56
|
+
export interface GeminiStreamState {
|
|
57
|
+
messageStarted: boolean;
|
|
58
|
+
textContentBlockStarted: boolean;
|
|
59
|
+
inputTokens: number;
|
|
60
|
+
outputTokens: number;
|
|
61
|
+
}
|
|
62
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../../src/models/gemini/types.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAA;AACpE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,aAAa,CAAA;AAElD;;;;;;;;;;;;GAYG;AACH,MAAM,WAAW,iBAAkB,SAAQ,eAAe;IACxD;;;;;OAKG;IACH,OAAO,CAAC,EAAE,MAAM,CAAA;IAEhB;;;;OAIG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CACjC;AAED;;GAEG;AACH,MAAM,WAAW,kBAAmB,SAAQ,iBAAiB;IAC3D;;OAEG;IACH,MAAM,CAAC,EAAE,MAAM,CAAA;IAEf;;;OAGG;IACH,MAAM,CAAC,EAAE,WAAW,CAAA;IAEpB;;;OAGG;IACH,YAAY,CAAC,EAAE,IAAI,CAAC,kBAAkB,EAAE,QAAQ,CAAC,CAAA;CAClD;AAED;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC,cAAc,EAAE,OAAO,CAAA;IACvB,uBAAuB,EAAE,OAAO,CAAA;IAChC,WAAW,EAAE,MAAM,CAAA;IACnB,YAAY,EAAE,MAAM,CAAA;CACrB"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../../../src/models/gemini/types.ts"],"names":[],"mappings":"AAAA;;GAEG"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"openai.d.ts","sourceRoot":"","sources":["../../../src/models/openai.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,MAAM,EAAE,EAAE,KAAK,aAAa,EAAE,MAAM,QAAQ,CAAA;AACnD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,eAAe,CAAA;AACjD,OAAO,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAA;AAC1C,OAAO,KAAK,EAAE,eAAe,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAA;AACxE,OAAO,KAAK,EAAE,OAAO,EAAc,MAAM,sBAAsB,CAAA;AAG/D,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAA;
|
|
1
|
+
{"version":3,"file":"openai.d.ts","sourceRoot":"","sources":["../../../src/models/openai.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,MAAM,EAAE,EAAE,KAAK,aAAa,EAAE,MAAM,QAAQ,CAAA;AACnD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,eAAe,CAAA;AACjD,OAAO,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAA;AAC1C,OAAO,KAAK,EAAE,eAAe,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAA;AACxE,OAAO,KAAK,EAAE,OAAO,EAAc,MAAM,sBAAsB,CAAA;AAG/D,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAA;AA0C9D;;;;;;;;;;;;;;GAcG;AACH,MAAM,WAAW,iBAAkB,SAAQ,eAAe;IACxD;;OAEG;IACH,OAAO,CAAC,EAAE,MAAM,CAAA;IAEhB;;;;OAIG;IACH,WAAW,CAAC,EAAE,MAAM,CAAA;IAEpB;;;;OAIG;IACH,SAAS,CAAC,EAAE,MAAM,CAAA;IAElB;;;;OAIG;IACH,IAAI,CAAC,EAAE,MAAM,CAAA;IAEb;;OAEG;IACH,gBAAgB,CAAC,EAAE,MAAM,CAAA;IAEzB;;OAEG;IACH,eAAe,CAAC,EAAE,MAAM,CAAA;IAExB;;;;;;;;;;;;;;OAcG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CACjC;AAED;;GAEG;AACH,MAAM,WAAW,kBAAmB,SAAQ,iBAAiB;IAC3D;;;;;;OAMG;IACH,MAAM,CAAC,EAAE,MAAM,GAAG,YAAY,CAAA;IAE9B;;;OAGG;IACH,MAAM,CAAC,EAAE,MAAM,CAAA;IAEf;;;OAGG;IACH,YAAY,CAAC,EAAE,aAAa,CAAA;CAC7B;AAED;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,qBAAa,WAAY,SAAQ,KAAK,CAAC,iBAAiB,CAAC;IACvD,OAAO,CAAC,OAAO,CAAmB;IAClC,OAAO,CAAC,OAAO,CAAQ;IAEvB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OAuCG;gBACS,OAAO,CAAC,EAAE,kBAAkB;IA+BxC;;;;;;;;;;;;;;OAcG;IACH,YAAY,CAAC,WAAW,EAAE,iBAAiB,GAAG,IAAI;IAIlD;;;;;;;;;;OAUG;IACH,SAAS,IAAI,iBAAiB;IAI9B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OAsCG;IACI,MAAM,CAAC,QAAQ,EAAE,OAAO,EAAE,EAAE,OAAO,CAAC,EAAE,aAAa,GAAG,aAAa,CAAC,gBAAgB,CAAC;IAgF5F;;;;;;OAMG;IACH,OAAO,CAAC,cAAc;IAwHtB;;;;;;OAMG;IACH,OAAO,CAAC,eAAe;IAsOvB;;;;;;;;;;;;OAYG;IACH,OAAO,CAAC,aAAa;IAIrB;;;;;;;OAOG;IACH,OAAO,CAAC,0BAA0B;CAwInC"}
|
|
@@ -8,46 +8,9 @@
|
|
|
8
8
|
*/
|
|
9
9
|
import OpenAI, {} from 'openai';
|
|
10
10
|
import { Model } from '../models/model.js';
|
|
11
|
-
import { encodeBase64 } from '../types/media.js';
|
|
11
|
+
import { encodeBase64, getMimeType } from '../types/media.js';
|
|
12
12
|
import { ContextWindowOverflowError } from '../errors.js';
|
|
13
13
|
import { logger } from '../logging/logger.js';
|
|
14
|
-
/**
|
|
15
|
-
* Browser-compatible MIME type lookup.
|
|
16
|
-
* Maps file extensions to MIME types without using Node.js path module.
|
|
17
|
-
*/
|
|
18
|
-
const mimeTypeLookup = (format) => {
|
|
19
|
-
const mimeTypes = {
|
|
20
|
-
// Video
|
|
21
|
-
mkv: 'video/x-matroska',
|
|
22
|
-
mov: 'video/quicktime',
|
|
23
|
-
mp4: 'application/mp4',
|
|
24
|
-
webm: 'video/webm',
|
|
25
|
-
flv: 'video/x-flv',
|
|
26
|
-
mpeg: 'video/mpeg',
|
|
27
|
-
mpg: 'video/mpeg',
|
|
28
|
-
wmv: 'video/x-ms-wmv',
|
|
29
|
-
'3gp': 'video/3gpp',
|
|
30
|
-
// Images
|
|
31
|
-
png: 'image/png',
|
|
32
|
-
jpg: 'image/jpeg',
|
|
33
|
-
jpeg: 'image/jpeg',
|
|
34
|
-
gif: 'image/gif',
|
|
35
|
-
webp: 'image/webp',
|
|
36
|
-
// Documents
|
|
37
|
-
pdf: 'application/pdf',
|
|
38
|
-
csv: 'text/csv',
|
|
39
|
-
doc: 'application/msword',
|
|
40
|
-
docx: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
|
|
41
|
-
xlsx: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
|
|
42
|
-
xls: 'application/vnd.ms-excel',
|
|
43
|
-
txt: 'text/plain',
|
|
44
|
-
json: 'application/json',
|
|
45
|
-
xml: 'application/xml',
|
|
46
|
-
html: 'text/html',
|
|
47
|
-
md: 'text/markdown',
|
|
48
|
-
};
|
|
49
|
-
return mimeTypes[format.toLowerCase()] || false;
|
|
50
|
-
};
|
|
51
14
|
const DEFAULT_OPENAI_MODEL_ID = 'gpt-4o';
|
|
52
15
|
/**
|
|
53
16
|
* Error message patterns that indicate context window overflow.
|
|
@@ -444,7 +407,7 @@ export class OpenAIModel extends Model {
|
|
|
444
407
|
}
|
|
445
408
|
case 'imageSourceBytes': {
|
|
446
409
|
const base64 = encodeBase64(String.fromCharCode(...imageBlock.source.bytes));
|
|
447
|
-
const mimeType =
|
|
410
|
+
const mimeType = getMimeType(imageBlock.format) || `image/${imageBlock.format}`;
|
|
448
411
|
contentParts.push({
|
|
449
412
|
type: 'image_url',
|
|
450
413
|
image_url: {
|
|
@@ -464,7 +427,7 @@ export class OpenAIModel extends Model {
|
|
|
464
427
|
const docBlock = block;
|
|
465
428
|
switch (docBlock.source.type) {
|
|
466
429
|
case 'documentSourceBytes': {
|
|
467
|
-
const mimeType =
|
|
430
|
+
const mimeType = getMimeType(docBlock.format) || `application/${docBlock.format}`;
|
|
468
431
|
const base64 = encodeBase64(String.fromCharCode(...docBlock.source.bytes));
|
|
469
432
|
const file = {
|
|
470
433
|
type: 'file',
|