geminisdk 0.1.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/README.md +129 -0
- package/dist/chunk-Y4MC6YDW.mjs +135 -0
- package/dist/index.d.mts +511 -0
- package/dist/index.d.ts +511 -0
- package/dist/index.js +1696 -0
- package/dist/index.mjs +1480 -0
- package/dist/types-ADTG4FSI.mjs +46 -0
- package/package.json +60 -0
- package/src/auth.ts +293 -0
- package/src/backend.ts +615 -0
- package/src/client.ts +230 -0
- package/src/exceptions.ts +289 -0
- package/src/index.ts +148 -0
- package/src/session.ts +380 -0
- package/src/tools.ts +127 -0
- package/src/types.ts +352 -0
package/src/client.ts
ADDED
|
@@ -0,0 +1,230 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* GeminiSDK Client - Main entry point for the Gemini SDK.
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import { GeminiOAuthManager } from './auth.js';
|
|
6
|
+
import { GeminiBackend } from './backend.js';
|
|
7
|
+
import { SessionNotFoundError } from './exceptions.js';
|
|
8
|
+
import { GeminiSession } from './session.js';
|
|
9
|
+
import {
|
|
10
|
+
ConnectionState,
|
|
11
|
+
GEMINI_CLI_MODELS,
|
|
12
|
+
GeminiClientOptions,
|
|
13
|
+
ModelInfo,
|
|
14
|
+
SessionConfig,
|
|
15
|
+
SessionMetadata,
|
|
16
|
+
} from './types.js';
|
|
17
|
+
|
|
18
|
+
// Simple UUID generator
|
|
19
|
+
function generateUUID(): string {
|
|
20
|
+
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (c) => {
|
|
21
|
+
const r = (Math.random() * 16) | 0;
|
|
22
|
+
const v = c === 'x' ? r : (r & 0x3) | 0x8;
|
|
23
|
+
return v.toString(16);
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export class GeminiClient {
|
|
28
|
+
private _options: GeminiClientOptions;
|
|
29
|
+
private _state: ConnectionState = 'disconnected';
|
|
30
|
+
private _backend: GeminiBackend | null = null;
|
|
31
|
+
private _oauthManager: GeminiOAuthManager | null = null;
|
|
32
|
+
private _sessions: Map<string, GeminiSession> = new Map();
|
|
33
|
+
private _started = false;
|
|
34
|
+
private _autoRefreshInterval: ReturnType<typeof setInterval> | null = null;
|
|
35
|
+
|
|
36
|
+
constructor(options: GeminiClientOptions = {}) {
|
|
37
|
+
this._options = options;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
get options(): GeminiClientOptions {
|
|
41
|
+
return this._options;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
get state(): ConnectionState {
|
|
45
|
+
return this._state;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
public async start(): Promise<void> {
|
|
49
|
+
if (this._started) return;
|
|
50
|
+
|
|
51
|
+
this._state = 'connecting';
|
|
52
|
+
|
|
53
|
+
try {
|
|
54
|
+
this._oauthManager = new GeminiOAuthManager(
|
|
55
|
+
this._options.oauthPath,
|
|
56
|
+
this._options.clientId,
|
|
57
|
+
this._options.clientSecret
|
|
58
|
+
);
|
|
59
|
+
|
|
60
|
+
this._backend = new GeminiBackend({
|
|
61
|
+
timeout: this._options.timeout ?? 720000,
|
|
62
|
+
oauthPath: this._options.oauthPath,
|
|
63
|
+
clientId: this._options.clientId,
|
|
64
|
+
clientSecret: this._options.clientSecret,
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
await this._oauthManager.ensureAuthenticated();
|
|
68
|
+
|
|
69
|
+
this._state = 'connected';
|
|
70
|
+
this._started = true;
|
|
71
|
+
|
|
72
|
+
if (this._options.autoRefresh !== false) {
|
|
73
|
+
this.startAutoRefresh();
|
|
74
|
+
}
|
|
75
|
+
} catch (e) {
|
|
76
|
+
this._state = 'error';
|
|
77
|
+
throw e;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
private startAutoRefresh(): void {
|
|
82
|
+
if (this._autoRefreshInterval) return;
|
|
83
|
+
|
|
84
|
+
this._autoRefreshInterval = setInterval(async () => {
|
|
85
|
+
try {
|
|
86
|
+
if (this._oauthManager) {
|
|
87
|
+
await this._oauthManager.ensureAuthenticated();
|
|
88
|
+
}
|
|
89
|
+
} catch (e) {
|
|
90
|
+
// Ignore background refresh errors
|
|
91
|
+
}
|
|
92
|
+
}, 30000);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
public async stop(): Promise<void> {
|
|
96
|
+
if (this._autoRefreshInterval) {
|
|
97
|
+
clearInterval(this._autoRefreshInterval);
|
|
98
|
+
this._autoRefreshInterval = null;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
for (const session of this._sessions.values()) {
|
|
102
|
+
try {
|
|
103
|
+
await session.destroy();
|
|
104
|
+
} catch (e) {
|
|
105
|
+
console.warn('Error destroying session:', e);
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
this._sessions.clear();
|
|
109
|
+
|
|
110
|
+
if (this._backend) {
|
|
111
|
+
await this._backend.close();
|
|
112
|
+
this._backend = null;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
this._oauthManager = null;
|
|
116
|
+
this._state = 'disconnected';
|
|
117
|
+
this._started = false;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
public async close(): Promise<void> {
|
|
121
|
+
await this.stop();
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
public async createSession(config: SessionConfig = {}): Promise<GeminiSession> {
|
|
125
|
+
if (!this._started) {
|
|
126
|
+
await this.start();
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
if (!this._backend) {
|
|
130
|
+
throw new Error('Client not connected. Call start() first.');
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
const sessionId = config.sessionId ?? generateUUID();
|
|
134
|
+
const model = config.model ?? 'gemini-2.5-pro';
|
|
135
|
+
|
|
136
|
+
const session = new GeminiSession({
|
|
137
|
+
sessionId,
|
|
138
|
+
model,
|
|
139
|
+
backend: this._backend,
|
|
140
|
+
tools: config.tools,
|
|
141
|
+
systemMessage: config.systemMessage,
|
|
142
|
+
generationConfig: config.generationConfig,
|
|
143
|
+
thinkingConfig: config.thinkingConfig,
|
|
144
|
+
streaming: config.streaming ?? true,
|
|
145
|
+
});
|
|
146
|
+
|
|
147
|
+
this._sessions.set(sessionId, session);
|
|
148
|
+
return session;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
public async getSession(sessionId: string): Promise<GeminiSession> {
|
|
152
|
+
const session = this._sessions.get(sessionId);
|
|
153
|
+
if (!session) {
|
|
154
|
+
throw new SessionNotFoundError(sessionId);
|
|
155
|
+
}
|
|
156
|
+
return session;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
public async listSessions(): Promise<SessionMetadata[]> {
|
|
160
|
+
const result: SessionMetadata[] = [];
|
|
161
|
+
for (const session of this._sessions.values()) {
|
|
162
|
+
result.push({
|
|
163
|
+
sessionId: session.sessionId,
|
|
164
|
+
startTime: session.startTime.toISOString(),
|
|
165
|
+
modifiedTime: session.modifiedTime.toISOString(),
|
|
166
|
+
model: session.model,
|
|
167
|
+
});
|
|
168
|
+
}
|
|
169
|
+
return result;
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
public async deleteSession(sessionId: string): Promise<void> {
|
|
173
|
+
const session = this._sessions.get(sessionId);
|
|
174
|
+
if (session) {
|
|
175
|
+
await session.destroy();
|
|
176
|
+
this._sessions.delete(sessionId);
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
public getState(): ConnectionState {
|
|
181
|
+
return this._state;
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
public async getAuthStatus(): Promise<{ authenticated: boolean; tokenType?: string; expiresAt?: number }> {
|
|
185
|
+
if (!this._oauthManager) {
|
|
186
|
+
return { authenticated: false };
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
try {
|
|
190
|
+
const credentials = await this._oauthManager.getCredentials();
|
|
191
|
+
return {
|
|
192
|
+
authenticated: true,
|
|
193
|
+
tokenType: credentials.tokenType,
|
|
194
|
+
expiresAt: credentials.expiryDate,
|
|
195
|
+
};
|
|
196
|
+
} catch {
|
|
197
|
+
return { authenticated: false };
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
public async listModels(): Promise<ModelInfo[]> {
|
|
202
|
+
const models: ModelInfo[] = [];
|
|
203
|
+
|
|
204
|
+
for (const [modelId, info] of Object.entries(GEMINI_CLI_MODELS)) {
|
|
205
|
+
models.push({
|
|
206
|
+
id: modelId,
|
|
207
|
+
name: info.name,
|
|
208
|
+
capabilities: {
|
|
209
|
+
supports: {
|
|
210
|
+
vision: false,
|
|
211
|
+
tools: info.supportsNativeTools,
|
|
212
|
+
thinking: info.supportsThinking,
|
|
213
|
+
},
|
|
214
|
+
limits: {
|
|
215
|
+
maxContextWindowTokens: info.contextWindow,
|
|
216
|
+
maxPromptTokens: info.contextWindow,
|
|
217
|
+
},
|
|
218
|
+
},
|
|
219
|
+
});
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
return models;
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
public async refreshAuth(): Promise<void> {
|
|
226
|
+
if (this._oauthManager) {
|
|
227
|
+
await this._oauthManager.ensureAuthenticated(true);
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
}
|
|
@@ -0,0 +1,289 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Custom exceptions for GeminiSDK TypeScript
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
export interface ErrorDetails {
|
|
6
|
+
[key: string]: unknown;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export class GeminiSDKError extends Error {
|
|
10
|
+
public readonly details: ErrorDetails;
|
|
11
|
+
|
|
12
|
+
constructor(message: string, details: ErrorDetails = {}) {
|
|
13
|
+
super(message);
|
|
14
|
+
this.name = 'GeminiSDKError';
|
|
15
|
+
this.details = details;
|
|
16
|
+
Object.setPrototypeOf(this, new.target.prototype);
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export class AuthenticationError extends GeminiSDKError {
|
|
21
|
+
constructor(message = 'Authentication failed', details: ErrorDetails = {}) {
|
|
22
|
+
super(message, details);
|
|
23
|
+
this.name = 'AuthenticationError';
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export class CredentialsNotFoundError extends AuthenticationError {
|
|
28
|
+
public readonly credentialPath: string;
|
|
29
|
+
|
|
30
|
+
constructor(credentialPath: string, message?: string) {
|
|
31
|
+
const msg =
|
|
32
|
+
message ??
|
|
33
|
+
`Gemini OAuth credentials not found at ${credentialPath}. ` +
|
|
34
|
+
'Please login using the Gemini CLI first: gemini auth login';
|
|
35
|
+
super(msg, { credentialPath });
|
|
36
|
+
this.name = 'CredentialsNotFoundError';
|
|
37
|
+
this.credentialPath = credentialPath;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export class TokenRefreshError extends AuthenticationError {
|
|
42
|
+
public readonly statusCode?: number;
|
|
43
|
+
public readonly responseBody?: string;
|
|
44
|
+
|
|
45
|
+
constructor(
|
|
46
|
+
message = 'Failed to refresh access token',
|
|
47
|
+
statusCode?: number,
|
|
48
|
+
responseBody?: string
|
|
49
|
+
) {
|
|
50
|
+
const details: ErrorDetails = {};
|
|
51
|
+
if (statusCode !== undefined) details['statusCode'] = statusCode;
|
|
52
|
+
if (responseBody !== undefined) details['responseBody'] = responseBody;
|
|
53
|
+
super(message, details);
|
|
54
|
+
this.name = 'TokenRefreshError';
|
|
55
|
+
this.statusCode = statusCode;
|
|
56
|
+
this.responseBody = responseBody;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
export class TokenExpiredError extends AuthenticationError {
|
|
61
|
+
constructor(message = 'Access token has expired') {
|
|
62
|
+
super(message);
|
|
63
|
+
this.name = 'TokenExpiredError';
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
export class ConnectionError extends GeminiSDKError {
|
|
68
|
+
public readonly endpoint?: string;
|
|
69
|
+
|
|
70
|
+
constructor(
|
|
71
|
+
message = 'Failed to connect to Gemini API',
|
|
72
|
+
endpoint?: string,
|
|
73
|
+
details: ErrorDetails = {}
|
|
74
|
+
) {
|
|
75
|
+
if (endpoint) details['endpoint'] = endpoint;
|
|
76
|
+
super(message, details);
|
|
77
|
+
this.name = 'ConnectionError';
|
|
78
|
+
this.endpoint = endpoint;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
export class APIError extends GeminiSDKError {
|
|
83
|
+
public readonly statusCode: number;
|
|
84
|
+
public readonly responseBody?: string;
|
|
85
|
+
public readonly endpoint?: string;
|
|
86
|
+
|
|
87
|
+
constructor(
|
|
88
|
+
message: string,
|
|
89
|
+
statusCode: number,
|
|
90
|
+
responseBody?: string,
|
|
91
|
+
endpoint?: string
|
|
92
|
+
) {
|
|
93
|
+
const details: ErrorDetails = { statusCode };
|
|
94
|
+
if (responseBody !== undefined) details['responseBody'] = responseBody;
|
|
95
|
+
if (endpoint !== undefined) details['endpoint'] = endpoint;
|
|
96
|
+
super(message, details);
|
|
97
|
+
this.name = 'APIError';
|
|
98
|
+
this.statusCode = statusCode;
|
|
99
|
+
this.responseBody = responseBody;
|
|
100
|
+
this.endpoint = endpoint;
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
export class RateLimitError extends APIError {
|
|
105
|
+
public readonly retryAfter?: number;
|
|
106
|
+
|
|
107
|
+
constructor(
|
|
108
|
+
message = 'Rate limit exceeded',
|
|
109
|
+
statusCode = 429,
|
|
110
|
+
retryAfter?: number,
|
|
111
|
+
responseBody?: string
|
|
112
|
+
) {
|
|
113
|
+
super(message, statusCode, responseBody);
|
|
114
|
+
this.name = 'RateLimitError';
|
|
115
|
+
this.retryAfter = retryAfter;
|
|
116
|
+
if (retryAfter !== undefined) this.details['retryAfter'] = retryAfter;
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
export class QuotaExceededError extends APIError {
|
|
121
|
+
public readonly resetTime?: string;
|
|
122
|
+
|
|
123
|
+
constructor(
|
|
124
|
+
message = 'Quota exceeded',
|
|
125
|
+
statusCode = 429,
|
|
126
|
+
resetTime?: string,
|
|
127
|
+
responseBody?: string
|
|
128
|
+
) {
|
|
129
|
+
super(message, statusCode, responseBody);
|
|
130
|
+
this.name = 'QuotaExceededError';
|
|
131
|
+
this.resetTime = resetTime;
|
|
132
|
+
if (resetTime !== undefined) this.details['resetTime'] = resetTime;
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
export class PermissionDeniedError extends APIError {
|
|
137
|
+
constructor(
|
|
138
|
+
message = 'Permission denied',
|
|
139
|
+
statusCode = 403,
|
|
140
|
+
responseBody?: string
|
|
141
|
+
) {
|
|
142
|
+
super(message, statusCode, responseBody);
|
|
143
|
+
this.name = 'PermissionDeniedError';
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
export class NotFoundError extends APIError {
|
|
148
|
+
public readonly resource?: string;
|
|
149
|
+
|
|
150
|
+
constructor(
|
|
151
|
+
message = 'Resource not found',
|
|
152
|
+
statusCode = 404,
|
|
153
|
+
resource?: string,
|
|
154
|
+
responseBody?: string
|
|
155
|
+
) {
|
|
156
|
+
super(message, statusCode, responseBody);
|
|
157
|
+
this.name = 'NotFoundError';
|
|
158
|
+
this.resource = resource;
|
|
159
|
+
if (resource !== undefined) this.details['resource'] = resource;
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
export class SessionError extends GeminiSDKError {
|
|
164
|
+
public readonly sessionId?: string;
|
|
165
|
+
|
|
166
|
+
constructor(message: string, sessionId?: string, details: ErrorDetails = {}) {
|
|
167
|
+
if (sessionId) details['sessionId'] = sessionId;
|
|
168
|
+
super(message, details);
|
|
169
|
+
this.name = 'SessionError';
|
|
170
|
+
this.sessionId = sessionId;
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
export class SessionNotFoundError extends SessionError {
|
|
175
|
+
constructor(sessionId: string) {
|
|
176
|
+
super(`Session not found: ${sessionId}`, sessionId);
|
|
177
|
+
this.name = 'SessionNotFoundError';
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
export class SessionClosedError extends SessionError {
|
|
182
|
+
constructor(sessionId?: string) {
|
|
183
|
+
super('Session is closed', sessionId);
|
|
184
|
+
this.name = 'SessionClosedError';
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
export class ToolError extends GeminiSDKError {
|
|
189
|
+
public readonly toolName?: string;
|
|
190
|
+
|
|
191
|
+
constructor(message: string, toolName?: string, details: ErrorDetails = {}) {
|
|
192
|
+
if (toolName) details['toolName'] = toolName;
|
|
193
|
+
super(message, details);
|
|
194
|
+
this.name = 'ToolError';
|
|
195
|
+
this.toolName = toolName;
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
export class ToolNotFoundError extends ToolError {
|
|
200
|
+
constructor(toolName: string) {
|
|
201
|
+
super(`Tool not found: ${toolName}`, toolName);
|
|
202
|
+
this.name = 'ToolNotFoundError';
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
export class ToolExecutionError extends ToolError {
|
|
207
|
+
public readonly originalError?: Error;
|
|
208
|
+
|
|
209
|
+
constructor(message: string, toolName: string, originalError?: Error) {
|
|
210
|
+
const details: ErrorDetails = {};
|
|
211
|
+
if (originalError) details['originalError'] = originalError.message;
|
|
212
|
+
super(message, toolName, details);
|
|
213
|
+
this.name = 'ToolExecutionError';
|
|
214
|
+
this.originalError = originalError;
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
export class ValidationError extends GeminiSDKError {
|
|
219
|
+
public readonly field?: string;
|
|
220
|
+
public readonly value?: unknown;
|
|
221
|
+
|
|
222
|
+
constructor(message: string, field?: string, value?: unknown) {
|
|
223
|
+
const details: ErrorDetails = {};
|
|
224
|
+
if (field !== undefined) details['field'] = field;
|
|
225
|
+
if (value !== undefined) details['value'] = String(value);
|
|
226
|
+
super(message, details);
|
|
227
|
+
this.name = 'ValidationError';
|
|
228
|
+
this.field = field;
|
|
229
|
+
this.value = value;
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
export class ConfigurationError extends GeminiSDKError {
|
|
234
|
+
public readonly configKey?: string;
|
|
235
|
+
|
|
236
|
+
constructor(message: string, configKey?: string) {
|
|
237
|
+
const details: ErrorDetails = {};
|
|
238
|
+
if (configKey) details['configKey'] = configKey;
|
|
239
|
+
super(message, details);
|
|
240
|
+
this.name = 'ConfigurationError';
|
|
241
|
+
this.configKey = configKey;
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
export class StreamError extends GeminiSDKError {
|
|
246
|
+
public readonly partialContent?: string;
|
|
247
|
+
|
|
248
|
+
constructor(message: string, partialContent?: string) {
|
|
249
|
+
const details: ErrorDetails = {};
|
|
250
|
+
if (partialContent) details['partialContent'] = partialContent.slice(0, 500);
|
|
251
|
+
super(message, details);
|
|
252
|
+
this.name = 'StreamError';
|
|
253
|
+
this.partialContent = partialContent;
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
export class CancellationError extends GeminiSDKError {
|
|
258
|
+
constructor(message = 'Operation was cancelled') {
|
|
259
|
+
super(message);
|
|
260
|
+
this.name = 'CancellationError';
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
export class TimeoutError extends GeminiSDKError {
|
|
265
|
+
public readonly timeout?: number;
|
|
266
|
+
|
|
267
|
+
constructor(message = 'Operation timed out', timeout?: number) {
|
|
268
|
+
const details: ErrorDetails = {};
|
|
269
|
+
if (timeout !== undefined) details['timeout'] = timeout;
|
|
270
|
+
super(message, details);
|
|
271
|
+
this.name = 'TimeoutError';
|
|
272
|
+
this.timeout = timeout;
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
export class OnboardingError extends GeminiSDKError {
|
|
277
|
+
public readonly tierId?: string;
|
|
278
|
+
|
|
279
|
+
constructor(
|
|
280
|
+
message = 'Failed to complete Gemini Code Assist onboarding',
|
|
281
|
+
tierId?: string
|
|
282
|
+
) {
|
|
283
|
+
const details: ErrorDetails = {};
|
|
284
|
+
if (tierId) details['tierId'] = tierId;
|
|
285
|
+
super(message, details);
|
|
286
|
+
this.name = 'OnboardingError';
|
|
287
|
+
this.tierId = tierId;
|
|
288
|
+
}
|
|
289
|
+
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* GeminiSDK TypeScript - A TypeScript SDK for Google Gemini Code Assist API.
|
|
3
|
+
*
|
|
4
|
+
* This SDK provides a high-level interface for interacting with the Gemini
|
|
5
|
+
* Code Assist API, supporting OAuth authentication, streaming responses,
|
|
6
|
+
* tool calling, and session management.
|
|
7
|
+
*
|
|
8
|
+
* @example
|
|
9
|
+
* ```typescript
|
|
10
|
+
* import { GeminiClient, EventType } from 'geminisdk';
|
|
11
|
+
*
|
|
12
|
+
* async function main() {
|
|
13
|
+
* const client = new GeminiClient();
|
|
14
|
+
* await client.start();
|
|
15
|
+
*
|
|
16
|
+
* const session = await client.createSession({
|
|
17
|
+
* model: 'gemini-2.5-pro',
|
|
18
|
+
* streaming: true,
|
|
19
|
+
* });
|
|
20
|
+
*
|
|
21
|
+
* session.on((event) => {
|
|
22
|
+
* if (event.type === EventType.ASSISTANT_MESSAGE_DELTA) {
|
|
23
|
+
* process.stdout.write((event.data as any).deltaContent);
|
|
24
|
+
* }
|
|
25
|
+
* });
|
|
26
|
+
*
|
|
27
|
+
* await session.send({ prompt: 'What is TypeScript?' });
|
|
28
|
+
* await client.close();
|
|
29
|
+
* }
|
|
30
|
+
*
|
|
31
|
+
* main();
|
|
32
|
+
* ```
|
|
33
|
+
*/
|
|
34
|
+
|
|
35
|
+
export const VERSION = '0.1.1';
|
|
36
|
+
|
|
37
|
+
// Client
|
|
38
|
+
export { GeminiClient } from './client.js';
|
|
39
|
+
|
|
40
|
+
// Session
|
|
41
|
+
export { GeminiSession } from './session.js';
|
|
42
|
+
|
|
43
|
+
// Backend
|
|
44
|
+
export { GeminiBackend } from './backend.js';
|
|
45
|
+
|
|
46
|
+
// Authentication
|
|
47
|
+
export { GeminiOAuthManager } from './auth.js';
|
|
48
|
+
|
|
49
|
+
// Tools
|
|
50
|
+
export {
|
|
51
|
+
ToolRegistry,
|
|
52
|
+
createTool,
|
|
53
|
+
defineTool,
|
|
54
|
+
getDefaultRegistry,
|
|
55
|
+
registerTool,
|
|
56
|
+
} from './tools.js';
|
|
57
|
+
|
|
58
|
+
// Types
|
|
59
|
+
export {
|
|
60
|
+
// Connection
|
|
61
|
+
ConnectionState,
|
|
62
|
+
LogLevel,
|
|
63
|
+
Role,
|
|
64
|
+
// OAuth
|
|
65
|
+
GeminiOAuthCredentials,
|
|
66
|
+
// Models
|
|
67
|
+
GeminiModelInfo,
|
|
68
|
+
ModelVisionLimits,
|
|
69
|
+
ModelLimits,
|
|
70
|
+
ModelSupports,
|
|
71
|
+
ModelCapabilities,
|
|
72
|
+
ModelInfo,
|
|
73
|
+
// Messages
|
|
74
|
+
ContentPart,
|
|
75
|
+
Message,
|
|
76
|
+
Attachment,
|
|
77
|
+
// Tools
|
|
78
|
+
FunctionCall,
|
|
79
|
+
ToolCall,
|
|
80
|
+
ToolInvocation,
|
|
81
|
+
ToolResultType,
|
|
82
|
+
ToolResult,
|
|
83
|
+
ToolHandler,
|
|
84
|
+
Tool,
|
|
85
|
+
// Generation
|
|
86
|
+
GenerationConfig,
|
|
87
|
+
ThinkingConfig,
|
|
88
|
+
// Request/Response
|
|
89
|
+
MessageOptions,
|
|
90
|
+
LLMUsage,
|
|
91
|
+
LLMChunk,
|
|
92
|
+
// Session
|
|
93
|
+
SessionConfig,
|
|
94
|
+
SessionMetadata,
|
|
95
|
+
// Client
|
|
96
|
+
GeminiClientOptions,
|
|
97
|
+
// Events
|
|
98
|
+
EventType,
|
|
99
|
+
SessionEvent,
|
|
100
|
+
SessionEventHandler,
|
|
101
|
+
// Constants
|
|
102
|
+
GEMINI_OAUTH_REDIRECT_URI,
|
|
103
|
+
GEMINI_OAUTH_BASE_URL,
|
|
104
|
+
GEMINI_OAUTH_TOKEN_ENDPOINT,
|
|
105
|
+
GEMINI_OAUTH_AUTH_ENDPOINT,
|
|
106
|
+
GEMINI_OAUTH_CLIENT_ID,
|
|
107
|
+
GEMINI_OAUTH_CLIENT_SECRET,
|
|
108
|
+
GEMINI_OAUTH_SCOPES,
|
|
109
|
+
GEMINI_CODE_ASSIST_ENDPOINT,
|
|
110
|
+
GEMINI_CODE_ASSIST_API_VERSION,
|
|
111
|
+
GEMINI_DIR,
|
|
112
|
+
GEMINI_CREDENTIAL_FILENAME,
|
|
113
|
+
GEMINI_ENV_FILENAME,
|
|
114
|
+
TOKEN_REFRESH_BUFFER_MS,
|
|
115
|
+
HTTP_OK,
|
|
116
|
+
HTTP_UNAUTHORIZED,
|
|
117
|
+
HTTP_FORBIDDEN,
|
|
118
|
+
GEMINI_CLI_MODELS,
|
|
119
|
+
getGeminiCliCredentialPath,
|
|
120
|
+
getGeminiCliEnvPath,
|
|
121
|
+
} from './types.js';
|
|
122
|
+
|
|
123
|
+
// Exceptions
|
|
124
|
+
export {
|
|
125
|
+
GeminiSDKError,
|
|
126
|
+
AuthenticationError,
|
|
127
|
+
CredentialsNotFoundError,
|
|
128
|
+
TokenRefreshError,
|
|
129
|
+
TokenExpiredError,
|
|
130
|
+
ConnectionError,
|
|
131
|
+
APIError,
|
|
132
|
+
RateLimitError,
|
|
133
|
+
QuotaExceededError,
|
|
134
|
+
PermissionDeniedError,
|
|
135
|
+
NotFoundError,
|
|
136
|
+
SessionError,
|
|
137
|
+
SessionNotFoundError,
|
|
138
|
+
SessionClosedError,
|
|
139
|
+
ToolError,
|
|
140
|
+
ToolNotFoundError,
|
|
141
|
+
ToolExecutionError,
|
|
142
|
+
ValidationError,
|
|
143
|
+
ConfigurationError,
|
|
144
|
+
StreamError,
|
|
145
|
+
CancellationError,
|
|
146
|
+
TimeoutError,
|
|
147
|
+
OnboardingError,
|
|
148
|
+
} from './exceptions.js';
|