fourmis-agents-sdk 0.2.3 → 0.2.5
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/agents/index.js +549 -2
- package/dist/agents/tools.js +549 -2
- package/dist/api.d.ts.map +1 -1
- package/dist/api.js +588 -28
- package/dist/auth/gemini-oauth.d.ts +23 -0
- package/dist/auth/gemini-oauth.d.ts.map +1 -0
- package/dist/auth/gemini-oauth.js +110 -0
- package/dist/index.js +588 -28
- package/dist/mcp/client.d.ts.map +1 -1
- package/dist/mcp/client.js +7 -2
- package/dist/mcp/index.js +7 -2
- package/dist/providers/anthropic.js +61 -0
- package/dist/providers/gemini.d.ts +39 -0
- package/dist/providers/gemini.d.ts.map +1 -0
- package/dist/providers/gemini.js +710 -0
- package/dist/providers/openai.js +61 -0
- package/dist/providers/registry.d.ts.map +1 -1
- package/dist/providers/registry.js +549 -0
- package/dist/tools/index.d.ts.map +1 -1
- package/dist/tools/index.js +0 -2
- package/dist/utils/cost.d.ts +13 -0
- package/dist/utils/cost.d.ts.map +1 -1
- package/dist/utils/cost.js +66 -0
- package/package.json +2 -1
package/dist/providers/openai.js
CHANGED
|
@@ -450,6 +450,67 @@ function findOpenAIPricing(model) {
|
|
|
450
450
|
}
|
|
451
451
|
return bestPricing;
|
|
452
452
|
}
|
|
453
|
+
var GEMINI_PRICING = {
|
|
454
|
+
"gemini-2.5-pro": {
|
|
455
|
+
inputPerMillion: 1.25,
|
|
456
|
+
outputPerMillion: 10,
|
|
457
|
+
cacheReadPerMillion: 0.315
|
|
458
|
+
},
|
|
459
|
+
"gemini-2.5-flash": {
|
|
460
|
+
inputPerMillion: 0.15,
|
|
461
|
+
outputPerMillion: 0.6,
|
|
462
|
+
cacheReadPerMillion: 0.0375
|
|
463
|
+
},
|
|
464
|
+
"gemini-2.5-flash-lite": {
|
|
465
|
+
inputPerMillion: 0.075,
|
|
466
|
+
outputPerMillion: 0.3
|
|
467
|
+
},
|
|
468
|
+
"gemini-2.0-flash": {
|
|
469
|
+
inputPerMillion: 0.1,
|
|
470
|
+
outputPerMillion: 0.4,
|
|
471
|
+
cacheReadPerMillion: 0.025
|
|
472
|
+
},
|
|
473
|
+
"gemini-2.0-flash-lite": {
|
|
474
|
+
inputPerMillion: 0.075,
|
|
475
|
+
outputPerMillion: 0.3
|
|
476
|
+
}
|
|
477
|
+
};
|
|
478
|
+
var GEMINI_CONTEXT_WINDOWS = {
|
|
479
|
+
"gemini-2.5-pro": 1048576,
|
|
480
|
+
"gemini-2.5-flash": 1048576,
|
|
481
|
+
"gemini-2.5-flash-lite": 1048576,
|
|
482
|
+
"gemini-2.0-flash": 1048576,
|
|
483
|
+
"gemini-2.0-flash-lite": 1048576
|
|
484
|
+
};
|
|
485
|
+
var GEMINI_MAX_OUTPUT = {
|
|
486
|
+
"gemini-2.5-pro": 65536,
|
|
487
|
+
"gemini-2.5-flash": 65536,
|
|
488
|
+
"gemini-2.5-flash-lite": 65536,
|
|
489
|
+
"gemini-2.0-flash": 8192,
|
|
490
|
+
"gemini-2.0-flash-lite": 8192
|
|
491
|
+
};
|
|
492
|
+
function calculateGeminiCost(model, usage) {
|
|
493
|
+
const pricing = findGeminiPricing(model);
|
|
494
|
+
if (!pricing)
|
|
495
|
+
return 0;
|
|
496
|
+
const inputCost = usage.inputTokens / 1e6 * pricing.inputPerMillion;
|
|
497
|
+
const outputCost = usage.outputTokens / 1e6 * pricing.outputPerMillion;
|
|
498
|
+
const cacheReadCost = usage.cacheReadInputTokens / 1e6 * (pricing.cacheReadPerMillion ?? pricing.inputPerMillion);
|
|
499
|
+
return inputCost + outputCost + cacheReadCost;
|
|
500
|
+
}
|
|
501
|
+
function findGeminiPricing(model) {
|
|
502
|
+
if (GEMINI_PRICING[model])
|
|
503
|
+
return GEMINI_PRICING[model];
|
|
504
|
+
let bestKey = "";
|
|
505
|
+
let bestPricing;
|
|
506
|
+
for (const [key, pricing] of Object.entries(GEMINI_PRICING)) {
|
|
507
|
+
if (model.startsWith(key) && key.length > bestKey.length) {
|
|
508
|
+
bestKey = key;
|
|
509
|
+
bestPricing = pricing;
|
|
510
|
+
}
|
|
511
|
+
}
|
|
512
|
+
return bestPricing;
|
|
513
|
+
}
|
|
453
514
|
|
|
454
515
|
// src/providers/openai.ts
|
|
455
516
|
import OpenAI from "openai";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../../src/providers/registry.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../../src/providers/registry.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAOlD,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,eAAe,GAAG,IAAI,CAE7E;AAED,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE;IAAE,MAAM,CAAC,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,eAAe,CAiC1G;AAED,wBAAgB,aAAa,IAAI,MAAM,EAAE,CAExC"}
|
|
@@ -299,6 +299,95 @@ async function openBrowser(url) {
|
|
|
299
299
|
var CLIENT_ID = "app_EMoamEEZ73f0CkXaXp7hrann", AUTHORIZE_URL = "https://auth.openai.com/oauth/authorize", TOKEN_URL = "https://auth.openai.com/oauth/token", REDIRECT_URI = "http://localhost:1455/auth/callback", SCOPE = "openid profile email offline_access", CALLBACK_PORT = 1455;
|
|
300
300
|
var init_openai_oauth = () => {};
|
|
301
301
|
|
|
302
|
+
// src/auth/gemini-oauth.ts
|
|
303
|
+
var exports_gemini_oauth = {};
|
|
304
|
+
__export(exports_gemini_oauth, {
|
|
305
|
+
loadTokensSync: () => loadTokensSync2,
|
|
306
|
+
loadTokens: () => loadTokens2,
|
|
307
|
+
isLoggedIn: () => isLoggedIn2,
|
|
308
|
+
getValidToken: () => getValidToken2
|
|
309
|
+
});
|
|
310
|
+
import { readFileSync as readFileSync2, writeFileSync as writeFileSync2, existsSync as existsSync2 } from "fs";
|
|
311
|
+
import { join as join2 } from "path";
|
|
312
|
+
import { homedir as homedir2 } from "os";
|
|
313
|
+
function getHome2() {
|
|
314
|
+
return process.env.HOME ?? homedir2();
|
|
315
|
+
}
|
|
316
|
+
function tokenPath2() {
|
|
317
|
+
return join2(getHome2(), ".gemini", "oauth_creds.json");
|
|
318
|
+
}
|
|
319
|
+
function loadTokens2() {
|
|
320
|
+
const p = tokenPath2();
|
|
321
|
+
try {
|
|
322
|
+
const raw = readFileSync2(p, "utf-8");
|
|
323
|
+
const data = JSON.parse(raw);
|
|
324
|
+
if (data.access_token && data.refresh_token) {
|
|
325
|
+
return data;
|
|
326
|
+
}
|
|
327
|
+
} catch {}
|
|
328
|
+
return null;
|
|
329
|
+
}
|
|
330
|
+
function loadTokensSync2() {
|
|
331
|
+
return loadTokens2();
|
|
332
|
+
}
|
|
333
|
+
function saveTokens2(tokens) {
|
|
334
|
+
const p = tokenPath2();
|
|
335
|
+
const dir = join2(getHome2(), ".gemini");
|
|
336
|
+
if (!existsSync2(dir)) {
|
|
337
|
+
const { mkdirSync: mkdirSync2 } = __require("fs");
|
|
338
|
+
mkdirSync2(dir, { recursive: true });
|
|
339
|
+
}
|
|
340
|
+
writeFileSync2(p, JSON.stringify(tokens, null, 2), { mode: 384 });
|
|
341
|
+
}
|
|
342
|
+
async function refreshAccessToken2(refreshToken) {
|
|
343
|
+
const res = await fetch(GOOGLE_TOKEN_URL, {
|
|
344
|
+
method: "POST",
|
|
345
|
+
headers: { "Content-Type": "application/x-www-form-urlencoded" },
|
|
346
|
+
body: new URLSearchParams({
|
|
347
|
+
grant_type: "refresh_token",
|
|
348
|
+
client_id: GEMINI_CLIENT_ID,
|
|
349
|
+
client_secret: GEMINI_CLIENT_SECRET,
|
|
350
|
+
refresh_token: refreshToken
|
|
351
|
+
})
|
|
352
|
+
});
|
|
353
|
+
if (!res.ok) {
|
|
354
|
+
const text = await res.text();
|
|
355
|
+
throw new Error(`Gemini token refresh failed (${res.status}): ${text}`);
|
|
356
|
+
}
|
|
357
|
+
return res.json();
|
|
358
|
+
}
|
|
359
|
+
async function getValidToken2() {
|
|
360
|
+
const tokens = loadTokens2();
|
|
361
|
+
if (!tokens)
|
|
362
|
+
return null;
|
|
363
|
+
const expiresAt = tokens.expires_at ?? tokens.expiry_date;
|
|
364
|
+
const needsRefresh = expiresAt ? expiresAt <= Date.now() + 300000 : true;
|
|
365
|
+
if (needsRefresh) {
|
|
366
|
+
try {
|
|
367
|
+
const fresh = await refreshAccessToken2(tokens.refresh_token);
|
|
368
|
+
const expiryMs = Date.now() + fresh.expires_in * 1000;
|
|
369
|
+
const updated = {
|
|
370
|
+
access_token: fresh.access_token,
|
|
371
|
+
refresh_token: fresh.refresh_token ?? tokens.refresh_token,
|
|
372
|
+
token_type: fresh.token_type ?? "Bearer",
|
|
373
|
+
expires_in: fresh.expires_in,
|
|
374
|
+
expires_at: expiryMs,
|
|
375
|
+
expiry_date: expiryMs
|
|
376
|
+
};
|
|
377
|
+
saveTokens2(updated);
|
|
378
|
+
return { accessToken: updated.access_token };
|
|
379
|
+
} catch {
|
|
380
|
+
return { accessToken: tokens.access_token };
|
|
381
|
+
}
|
|
382
|
+
}
|
|
383
|
+
return { accessToken: tokens.access_token };
|
|
384
|
+
}
|
|
385
|
+
function isLoggedIn2() {
|
|
386
|
+
return loadTokens2() !== null;
|
|
387
|
+
}
|
|
388
|
+
var GEMINI_CLIENT_ID = "681255809395-oo8ft2oprdrnp9e3aqf6av3hmdib135j.apps.googleusercontent.com", GEMINI_CLIENT_SECRET = "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", GOOGLE_TOKEN_URL = "https://oauth2.googleapis.com/token";
|
|
389
|
+
var init_gemini_oauth = () => {};
|
|
390
|
+
|
|
302
391
|
// src/utils/cost.ts
|
|
303
392
|
var ANTHROPIC_PRICING = {
|
|
304
393
|
"claude-opus-4-6": {
|
|
@@ -450,6 +539,67 @@ function findOpenAIPricing(model) {
|
|
|
450
539
|
}
|
|
451
540
|
return bestPricing;
|
|
452
541
|
}
|
|
542
|
+
var GEMINI_PRICING = {
|
|
543
|
+
"gemini-2.5-pro": {
|
|
544
|
+
inputPerMillion: 1.25,
|
|
545
|
+
outputPerMillion: 10,
|
|
546
|
+
cacheReadPerMillion: 0.315
|
|
547
|
+
},
|
|
548
|
+
"gemini-2.5-flash": {
|
|
549
|
+
inputPerMillion: 0.15,
|
|
550
|
+
outputPerMillion: 0.6,
|
|
551
|
+
cacheReadPerMillion: 0.0375
|
|
552
|
+
},
|
|
553
|
+
"gemini-2.5-flash-lite": {
|
|
554
|
+
inputPerMillion: 0.075,
|
|
555
|
+
outputPerMillion: 0.3
|
|
556
|
+
},
|
|
557
|
+
"gemini-2.0-flash": {
|
|
558
|
+
inputPerMillion: 0.1,
|
|
559
|
+
outputPerMillion: 0.4,
|
|
560
|
+
cacheReadPerMillion: 0.025
|
|
561
|
+
},
|
|
562
|
+
"gemini-2.0-flash-lite": {
|
|
563
|
+
inputPerMillion: 0.075,
|
|
564
|
+
outputPerMillion: 0.3
|
|
565
|
+
}
|
|
566
|
+
};
|
|
567
|
+
var GEMINI_CONTEXT_WINDOWS = {
|
|
568
|
+
"gemini-2.5-pro": 1048576,
|
|
569
|
+
"gemini-2.5-flash": 1048576,
|
|
570
|
+
"gemini-2.5-flash-lite": 1048576,
|
|
571
|
+
"gemini-2.0-flash": 1048576,
|
|
572
|
+
"gemini-2.0-flash-lite": 1048576
|
|
573
|
+
};
|
|
574
|
+
var GEMINI_MAX_OUTPUT = {
|
|
575
|
+
"gemini-2.5-pro": 65536,
|
|
576
|
+
"gemini-2.5-flash": 65536,
|
|
577
|
+
"gemini-2.5-flash-lite": 65536,
|
|
578
|
+
"gemini-2.0-flash": 8192,
|
|
579
|
+
"gemini-2.0-flash-lite": 8192
|
|
580
|
+
};
|
|
581
|
+
function calculateGeminiCost(model, usage) {
|
|
582
|
+
const pricing = findGeminiPricing(model);
|
|
583
|
+
if (!pricing)
|
|
584
|
+
return 0;
|
|
585
|
+
const inputCost = usage.inputTokens / 1e6 * pricing.inputPerMillion;
|
|
586
|
+
const outputCost = usage.outputTokens / 1e6 * pricing.outputPerMillion;
|
|
587
|
+
const cacheReadCost = usage.cacheReadInputTokens / 1e6 * (pricing.cacheReadPerMillion ?? pricing.inputPerMillion);
|
|
588
|
+
return inputCost + outputCost + cacheReadCost;
|
|
589
|
+
}
|
|
590
|
+
function findGeminiPricing(model) {
|
|
591
|
+
if (GEMINI_PRICING[model])
|
|
592
|
+
return GEMINI_PRICING[model];
|
|
593
|
+
let bestKey = "";
|
|
594
|
+
let bestPricing;
|
|
595
|
+
for (const [key, pricing] of Object.entries(GEMINI_PRICING)) {
|
|
596
|
+
if (model.startsWith(key) && key.length > bestKey.length) {
|
|
597
|
+
bestKey = key;
|
|
598
|
+
bestPricing = pricing;
|
|
599
|
+
}
|
|
600
|
+
}
|
|
601
|
+
return bestPricing;
|
|
602
|
+
}
|
|
453
603
|
|
|
454
604
|
// src/providers/anthropic.ts
|
|
455
605
|
import Anthropic from "@anthropic-ai/sdk";
|
|
@@ -1086,6 +1236,398 @@ function loadTokensSync() {
|
|
|
1086
1236
|
return null;
|
|
1087
1237
|
}
|
|
1088
1238
|
|
|
1239
|
+
// src/providers/gemini.ts
|
|
1240
|
+
import { GoogleGenAI } from "@google/genai";
|
|
1241
|
+
var CODE_ASSIST_ENDPOINT = "https://cloudcode-pa.googleapis.com";
|
|
1242
|
+
var CODE_ASSIST_API_VERSION = "v1internal";
|
|
1243
|
+
|
|
1244
|
+
class GeminiAdapter {
|
|
1245
|
+
name = "gemini";
|
|
1246
|
+
client = null;
|
|
1247
|
+
oauthMode;
|
|
1248
|
+
currentAccessToken;
|
|
1249
|
+
projectId;
|
|
1250
|
+
constructor(options) {
|
|
1251
|
+
const key = options?.apiKey ?? process.env.GEMINI_API_KEY;
|
|
1252
|
+
if (key) {
|
|
1253
|
+
this.oauthMode = false;
|
|
1254
|
+
this.client = new GoogleGenAI({ apiKey: key });
|
|
1255
|
+
} else {
|
|
1256
|
+
const tokens = loadTokensSync3();
|
|
1257
|
+
if (tokens) {
|
|
1258
|
+
this.oauthMode = true;
|
|
1259
|
+
this.currentAccessToken = tokens.access_token;
|
|
1260
|
+
} else {
|
|
1261
|
+
this.oauthMode = false;
|
|
1262
|
+
this.client = new GoogleGenAI({ apiKey: "" });
|
|
1263
|
+
}
|
|
1264
|
+
}
|
|
1265
|
+
}
|
|
1266
|
+
async* chat(request) {
|
|
1267
|
+
if (this.oauthMode) {
|
|
1268
|
+
yield* this.chatCodeAssist(request);
|
|
1269
|
+
} else {
|
|
1270
|
+
yield* this.chatSdk(request);
|
|
1271
|
+
}
|
|
1272
|
+
}
|
|
1273
|
+
calculateCost(model, usage) {
|
|
1274
|
+
return calculateGeminiCost(model, usage);
|
|
1275
|
+
}
|
|
1276
|
+
getContextWindow(model) {
|
|
1277
|
+
return GEMINI_CONTEXT_WINDOWS[model] ?? 1048576;
|
|
1278
|
+
}
|
|
1279
|
+
supportsFeature(feature) {
|
|
1280
|
+
switch (feature) {
|
|
1281
|
+
case "streaming":
|
|
1282
|
+
case "tool_calling":
|
|
1283
|
+
case "image_input":
|
|
1284
|
+
case "structured_output":
|
|
1285
|
+
case "thinking":
|
|
1286
|
+
case "pdf_input":
|
|
1287
|
+
return true;
|
|
1288
|
+
default:
|
|
1289
|
+
return false;
|
|
1290
|
+
}
|
|
1291
|
+
}
|
|
1292
|
+
async* chatSdk(request) {
|
|
1293
|
+
const contents = this.convertMessages(request.messages);
|
|
1294
|
+
const tools = request.tools ? this.convertTools(request.tools) : undefined;
|
|
1295
|
+
const maxTokens = request.maxTokens ?? GEMINI_MAX_OUTPUT[request.model] ?? 65536;
|
|
1296
|
+
const config = {
|
|
1297
|
+
maxOutputTokens: maxTokens,
|
|
1298
|
+
abortSignal: request.signal ?? undefined
|
|
1299
|
+
};
|
|
1300
|
+
if (request.systemPrompt) {
|
|
1301
|
+
config.systemInstruction = request.systemPrompt;
|
|
1302
|
+
}
|
|
1303
|
+
if (request.temperature !== undefined) {
|
|
1304
|
+
config.temperature = request.temperature;
|
|
1305
|
+
}
|
|
1306
|
+
if (tools) {
|
|
1307
|
+
config.tools = [{ functionDeclarations: tools }];
|
|
1308
|
+
}
|
|
1309
|
+
const stream = await this.client.models.generateContentStream({
|
|
1310
|
+
model: request.model,
|
|
1311
|
+
contents,
|
|
1312
|
+
config
|
|
1313
|
+
});
|
|
1314
|
+
let hasToolCalls = false;
|
|
1315
|
+
for await (const chunk of stream) {
|
|
1316
|
+
if (chunk.usageMetadata) {
|
|
1317
|
+
const u = chunk.usageMetadata;
|
|
1318
|
+
const cached = u.cachedContentTokenCount ?? 0;
|
|
1319
|
+
yield {
|
|
1320
|
+
type: "usage",
|
|
1321
|
+
usage: {
|
|
1322
|
+
inputTokens: (u.promptTokenCount ?? 0) - cached,
|
|
1323
|
+
outputTokens: u.candidatesTokenCount ?? 0,
|
|
1324
|
+
cacheReadInputTokens: cached,
|
|
1325
|
+
cacheCreationInputTokens: 0
|
|
1326
|
+
}
|
|
1327
|
+
};
|
|
1328
|
+
}
|
|
1329
|
+
const candidate = chunk.candidates?.[0];
|
|
1330
|
+
if (!candidate?.content?.parts)
|
|
1331
|
+
continue;
|
|
1332
|
+
for (const part of candidate.content.parts) {
|
|
1333
|
+
if (part.text) {
|
|
1334
|
+
if (part.thought) {
|
|
1335
|
+
yield { type: "thinking_delta", text: part.text };
|
|
1336
|
+
} else {
|
|
1337
|
+
yield { type: "text_delta", text: part.text };
|
|
1338
|
+
}
|
|
1339
|
+
}
|
|
1340
|
+
if (part.functionCall) {
|
|
1341
|
+
hasToolCalls = true;
|
|
1342
|
+
yield {
|
|
1343
|
+
type: "tool_call",
|
|
1344
|
+
id: part.functionCall.id ?? crypto.randomUUID(),
|
|
1345
|
+
name: part.functionCall.name ?? "",
|
|
1346
|
+
input: part.functionCall.args ?? {}
|
|
1347
|
+
};
|
|
1348
|
+
}
|
|
1349
|
+
}
|
|
1350
|
+
if (candidate.finishReason) {
|
|
1351
|
+
yield {
|
|
1352
|
+
type: "done",
|
|
1353
|
+
stopReason: this.mapFinishReason(candidate.finishReason, hasToolCalls)
|
|
1354
|
+
};
|
|
1355
|
+
return;
|
|
1356
|
+
}
|
|
1357
|
+
}
|
|
1358
|
+
yield { type: "done", stopReason: hasToolCalls ? "tool_use" : "end_turn" };
|
|
1359
|
+
}
|
|
1360
|
+
async* chatCodeAssist(request) {
|
|
1361
|
+
await this.refreshTokenIfNeeded();
|
|
1362
|
+
await this.ensureProjectId();
|
|
1363
|
+
const contents = this.convertMessages(request.messages);
|
|
1364
|
+
const tools = request.tools ? this.convertTools(request.tools) : undefined;
|
|
1365
|
+
const maxTokens = request.maxTokens ?? GEMINI_MAX_OUTPUT[request.model] ?? 65536;
|
|
1366
|
+
const generationConfig = {
|
|
1367
|
+
maxOutputTokens: maxTokens
|
|
1368
|
+
};
|
|
1369
|
+
if (request.temperature !== undefined) {
|
|
1370
|
+
generationConfig.temperature = request.temperature;
|
|
1371
|
+
}
|
|
1372
|
+
const innerRequest = {
|
|
1373
|
+
contents,
|
|
1374
|
+
generationConfig
|
|
1375
|
+
};
|
|
1376
|
+
if (request.systemPrompt) {
|
|
1377
|
+
innerRequest.systemInstruction = {
|
|
1378
|
+
parts: [{ text: request.systemPrompt }]
|
|
1379
|
+
};
|
|
1380
|
+
}
|
|
1381
|
+
if (tools) {
|
|
1382
|
+
innerRequest.tools = [{ functionDeclarations: tools }];
|
|
1383
|
+
}
|
|
1384
|
+
const body = {
|
|
1385
|
+
model: request.model,
|
|
1386
|
+
project: this.projectId,
|
|
1387
|
+
request: innerRequest
|
|
1388
|
+
};
|
|
1389
|
+
const url = `${CODE_ASSIST_ENDPOINT}/${CODE_ASSIST_API_VERSION}:streamGenerateContent?alt=sse`;
|
|
1390
|
+
const res = await fetch(url, {
|
|
1391
|
+
method: "POST",
|
|
1392
|
+
headers: {
|
|
1393
|
+
"Content-Type": "application/json",
|
|
1394
|
+
Authorization: `Bearer ${this.currentAccessToken}`
|
|
1395
|
+
},
|
|
1396
|
+
body: JSON.stringify(body),
|
|
1397
|
+
signal: request.signal ?? undefined
|
|
1398
|
+
});
|
|
1399
|
+
if (!res.ok) {
|
|
1400
|
+
const text = await res.text();
|
|
1401
|
+
throw new Error(`Gemini Code Assist API error (${res.status}): ${text}`);
|
|
1402
|
+
}
|
|
1403
|
+
yield* this.parseSSEStream(res);
|
|
1404
|
+
}
|
|
1405
|
+
async* parseSSEStream(res) {
|
|
1406
|
+
const reader = res.body.getReader();
|
|
1407
|
+
const decoder = new TextDecoder;
|
|
1408
|
+
let buffer = "";
|
|
1409
|
+
let hasToolCalls = false;
|
|
1410
|
+
let dataLines = [];
|
|
1411
|
+
while (true) {
|
|
1412
|
+
const { done, value } = await reader.read();
|
|
1413
|
+
if (done)
|
|
1414
|
+
break;
|
|
1415
|
+
buffer += decoder.decode(value, { stream: true });
|
|
1416
|
+
const lines = buffer.split(`
|
|
1417
|
+
`);
|
|
1418
|
+
buffer = lines.pop() || "";
|
|
1419
|
+
for (const line of lines) {
|
|
1420
|
+
if (line.startsWith("data: ")) {
|
|
1421
|
+
dataLines.push(line.slice(6));
|
|
1422
|
+
} else if (line.trim() === "" && dataLines.length > 0) {
|
|
1423
|
+
const json = dataLines.join(`
|
|
1424
|
+
`);
|
|
1425
|
+
dataLines = [];
|
|
1426
|
+
let obj;
|
|
1427
|
+
try {
|
|
1428
|
+
obj = JSON.parse(json);
|
|
1429
|
+
} catch {
|
|
1430
|
+
continue;
|
|
1431
|
+
}
|
|
1432
|
+
const response = obj.response ?? obj;
|
|
1433
|
+
const candidate = response?.candidates?.[0];
|
|
1434
|
+
if (candidate?.content?.parts) {
|
|
1435
|
+
for (const part of candidate.content.parts) {
|
|
1436
|
+
if (part.text) {
|
|
1437
|
+
if (part.thought) {
|
|
1438
|
+
yield { type: "thinking_delta", text: part.text };
|
|
1439
|
+
} else {
|
|
1440
|
+
yield { type: "text_delta", text: part.text };
|
|
1441
|
+
}
|
|
1442
|
+
}
|
|
1443
|
+
if (part.functionCall) {
|
|
1444
|
+
hasToolCalls = true;
|
|
1445
|
+
yield {
|
|
1446
|
+
type: "tool_call",
|
|
1447
|
+
id: part.functionCall.id ?? crypto.randomUUID(),
|
|
1448
|
+
name: part.functionCall.name ?? "",
|
|
1449
|
+
input: part.functionCall.args ?? {}
|
|
1450
|
+
};
|
|
1451
|
+
}
|
|
1452
|
+
}
|
|
1453
|
+
}
|
|
1454
|
+
if (response?.usageMetadata) {
|
|
1455
|
+
const u = response.usageMetadata;
|
|
1456
|
+
const cached = u.cachedContentTokenCount ?? 0;
|
|
1457
|
+
yield {
|
|
1458
|
+
type: "usage",
|
|
1459
|
+
usage: {
|
|
1460
|
+
inputTokens: (u.promptTokenCount ?? 0) - cached,
|
|
1461
|
+
outputTokens: u.candidatesTokenCount ?? 0,
|
|
1462
|
+
cacheReadInputTokens: cached,
|
|
1463
|
+
cacheCreationInputTokens: 0
|
|
1464
|
+
}
|
|
1465
|
+
};
|
|
1466
|
+
}
|
|
1467
|
+
if (candidate?.finishReason) {
|
|
1468
|
+
yield {
|
|
1469
|
+
type: "done",
|
|
1470
|
+
stopReason: this.mapFinishReason(candidate.finishReason, hasToolCalls)
|
|
1471
|
+
};
|
|
1472
|
+
return;
|
|
1473
|
+
}
|
|
1474
|
+
}
|
|
1475
|
+
}
|
|
1476
|
+
}
|
|
1477
|
+
if (dataLines.length > 0) {
|
|
1478
|
+
const json = dataLines.join(`
|
|
1479
|
+
`);
|
|
1480
|
+
try {
|
|
1481
|
+
const obj = JSON.parse(json);
|
|
1482
|
+
const response = obj.response ?? obj;
|
|
1483
|
+
const candidate = response?.candidates?.[0];
|
|
1484
|
+
if (candidate?.finishReason) {
|
|
1485
|
+
yield {
|
|
1486
|
+
type: "done",
|
|
1487
|
+
stopReason: this.mapFinishReason(candidate.finishReason, hasToolCalls)
|
|
1488
|
+
};
|
|
1489
|
+
return;
|
|
1490
|
+
}
|
|
1491
|
+
} catch {}
|
|
1492
|
+
}
|
|
1493
|
+
yield { type: "done", stopReason: hasToolCalls ? "tool_use" : "end_turn" };
|
|
1494
|
+
}
|
|
1495
|
+
async refreshTokenIfNeeded() {
|
|
1496
|
+
if (!this.oauthMode)
|
|
1497
|
+
return;
|
|
1498
|
+
try {
|
|
1499
|
+
const { getValidToken: getValidToken3 } = await Promise.resolve().then(() => (init_gemini_oauth(), exports_gemini_oauth));
|
|
1500
|
+
const result = await getValidToken3();
|
|
1501
|
+
if (result && result.accessToken !== this.currentAccessToken) {
|
|
1502
|
+
this.currentAccessToken = result.accessToken;
|
|
1503
|
+
}
|
|
1504
|
+
} catch {}
|
|
1505
|
+
}
|
|
1506
|
+
async ensureProjectId() {
|
|
1507
|
+
if (this.projectId)
|
|
1508
|
+
return;
|
|
1509
|
+
this.projectId = process.env.GOOGLE_CLOUD_PROJECT ?? process.env.GOOGLE_CLOUD_PROJECT_ID ?? undefined;
|
|
1510
|
+
if (this.projectId)
|
|
1511
|
+
return;
|
|
1512
|
+
try {
|
|
1513
|
+
const res = await fetch(`${CODE_ASSIST_ENDPOINT}/${CODE_ASSIST_API_VERSION}:loadCodeAssist`, {
|
|
1514
|
+
method: "POST",
|
|
1515
|
+
headers: {
|
|
1516
|
+
"Content-Type": "application/json",
|
|
1517
|
+
Authorization: `Bearer ${this.currentAccessToken}`
|
|
1518
|
+
},
|
|
1519
|
+
body: JSON.stringify({
|
|
1520
|
+
metadata: {
|
|
1521
|
+
ideType: "IDE_UNSPECIFIED",
|
|
1522
|
+
platform: "PLATFORM_UNSPECIFIED",
|
|
1523
|
+
pluginType: "GEMINI"
|
|
1524
|
+
}
|
|
1525
|
+
})
|
|
1526
|
+
});
|
|
1527
|
+
if (res.ok) {
|
|
1528
|
+
const data = await res.json();
|
|
1529
|
+
this.projectId = data.cloudaicompanionProject;
|
|
1530
|
+
}
|
|
1531
|
+
} catch {}
|
|
1532
|
+
}
|
|
1533
|
+
convertMessages(messages) {
|
|
1534
|
+
const result = [];
|
|
1535
|
+
for (const msg of messages) {
|
|
1536
|
+
if (typeof msg.content === "string") {
|
|
1537
|
+
result.push({
|
|
1538
|
+
role: msg.role === "assistant" ? "model" : "user",
|
|
1539
|
+
parts: [{ text: msg.content }]
|
|
1540
|
+
});
|
|
1541
|
+
continue;
|
|
1542
|
+
}
|
|
1543
|
+
if (msg.role === "assistant") {
|
|
1544
|
+
const parts = [];
|
|
1545
|
+
for (const block of msg.content) {
|
|
1546
|
+
if (block.type === "text") {
|
|
1547
|
+
parts.push({ text: block.text });
|
|
1548
|
+
} else if (block.type === "tool_use") {
|
|
1549
|
+
parts.push({
|
|
1550
|
+
functionCall: {
|
|
1551
|
+
name: block.name,
|
|
1552
|
+
args: block.input
|
|
1553
|
+
}
|
|
1554
|
+
});
|
|
1555
|
+
}
|
|
1556
|
+
}
|
|
1557
|
+
if (parts.length > 0) {
|
|
1558
|
+
result.push({ role: "model", parts });
|
|
1559
|
+
}
|
|
1560
|
+
} else {
|
|
1561
|
+
const textParts = [];
|
|
1562
|
+
const functionResponseParts = [];
|
|
1563
|
+
for (const block of msg.content) {
|
|
1564
|
+
if (block.type === "text") {
|
|
1565
|
+
textParts.push({ text: block.text });
|
|
1566
|
+
} else if (block.type === "tool_result") {
|
|
1567
|
+
functionResponseParts.push({
|
|
1568
|
+
functionResponse: {
|
|
1569
|
+
name: findToolName(messages, block.tool_use_id) ?? "unknown",
|
|
1570
|
+
response: { result: block.content }
|
|
1571
|
+
}
|
|
1572
|
+
});
|
|
1573
|
+
}
|
|
1574
|
+
}
|
|
1575
|
+
if (functionResponseParts.length > 0) {
|
|
1576
|
+
result.push({ role: "user", parts: functionResponseParts });
|
|
1577
|
+
}
|
|
1578
|
+
if (textParts.length > 0) {
|
|
1579
|
+
result.push({ role: "user", parts: textParts });
|
|
1580
|
+
}
|
|
1581
|
+
}
|
|
1582
|
+
}
|
|
1583
|
+
return result;
|
|
1584
|
+
}
|
|
1585
|
+
convertTools(tools) {
|
|
1586
|
+
return tools.map((tool) => ({
|
|
1587
|
+
name: tool.name,
|
|
1588
|
+
description: tool.description,
|
|
1589
|
+
parameters: tool.inputSchema
|
|
1590
|
+
}));
|
|
1591
|
+
}
|
|
1592
|
+
mapFinishReason(reason, hasToolCalls) {
|
|
1593
|
+
if (hasToolCalls)
|
|
1594
|
+
return "tool_use";
|
|
1595
|
+
switch (reason) {
|
|
1596
|
+
case "STOP":
|
|
1597
|
+
return "end_turn";
|
|
1598
|
+
case "MAX_TOKENS":
|
|
1599
|
+
return "max_tokens";
|
|
1600
|
+
default:
|
|
1601
|
+
return "end_turn";
|
|
1602
|
+
}
|
|
1603
|
+
}
|
|
1604
|
+
}
|
|
1605
|
+
function findToolName(messages, toolUseId) {
|
|
1606
|
+
for (const msg of messages) {
|
|
1607
|
+
if (msg.role !== "assistant" || typeof msg.content === "string")
|
|
1608
|
+
continue;
|
|
1609
|
+
for (const block of msg.content) {
|
|
1610
|
+
if (block.type === "tool_use" && block.id === toolUseId) {
|
|
1611
|
+
return block.name;
|
|
1612
|
+
}
|
|
1613
|
+
}
|
|
1614
|
+
}
|
|
1615
|
+
return;
|
|
1616
|
+
}
|
|
1617
|
+
function loadTokensSync3() {
|
|
1618
|
+
const home = process.env.HOME ?? __require("os").homedir();
|
|
1619
|
+
const path = `${home}/.gemini/oauth_creds.json`;
|
|
1620
|
+
try {
|
|
1621
|
+
const fs = __require("fs");
|
|
1622
|
+
const raw = fs.readFileSync(path, "utf-8");
|
|
1623
|
+
const data = JSON.parse(raw);
|
|
1624
|
+
if (data.access_token && data.refresh_token) {
|
|
1625
|
+
return data;
|
|
1626
|
+
}
|
|
1627
|
+
} catch {}
|
|
1628
|
+
return null;
|
|
1629
|
+
}
|
|
1630
|
+
|
|
1089
1631
|
// src/providers/registry.ts
|
|
1090
1632
|
var providers = new Map;
|
|
1091
1633
|
function registerProvider(name, adapter) {
|
|
@@ -1111,6 +1653,13 @@ function getProvider(name, options) {
|
|
|
1111
1653
|
}
|
|
1112
1654
|
return adapter;
|
|
1113
1655
|
}
|
|
1656
|
+
if (name === "gemini") {
|
|
1657
|
+
const adapter = new GeminiAdapter(options);
|
|
1658
|
+
if (!options?.apiKey && !options?.baseUrl) {
|
|
1659
|
+
providers.set(name, adapter);
|
|
1660
|
+
}
|
|
1661
|
+
return adapter;
|
|
1662
|
+
}
|
|
1114
1663
|
throw new Error(`Unknown provider: "${name}". Register it with registerProvider() first.`);
|
|
1115
1664
|
}
|
|
1116
1665
|
function listProviders() {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/tools/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAC7C,YAAY,EAAE,kBAAkB,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AACjF,OAAO,EAAE,OAAO,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AACzD,OAAO,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AACrC,OAAO,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AACrC,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AACvC,OAAO,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AACrC,OAAO,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AACrC,OAAO,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AAErC,OAAO,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAkB7C;;GAEG;AACH,wBAAgB,iBAAiB,CAC/B,SAAS,EAAE,MAAM,EAAE,EACnB,YAAY,CAAC,EAAE,MAAM,EAAE,EACvB,eAAe,CAAC,EAAE,MAAM,EAAE,GACzB,YAAY,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/tools/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAC7C,YAAY,EAAE,kBAAkB,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AACjF,OAAO,EAAE,OAAO,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AACzD,OAAO,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AACrC,OAAO,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AACrC,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AACvC,OAAO,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AACrC,OAAO,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AACrC,OAAO,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AAErC,OAAO,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAkB7C;;GAEG;AACH,wBAAgB,iBAAiB,CAC/B,SAAS,EAAE,MAAM,EAAE,EACnB,YAAY,CAAC,EAAE,MAAM,EAAE,EACvB,eAAe,CAAC,EAAE,MAAM,EAAE,GACzB,YAAY,CAad"}
|
package/dist/tools/index.js
CHANGED
|
@@ -570,8 +570,6 @@ var ALL_TOOLS = {
|
|
|
570
570
|
function buildToolRegistry(toolNames, allowedTools, disallowedTools) {
|
|
571
571
|
const registry = new ToolRegistry;
|
|
572
572
|
for (const name of toolNames) {
|
|
573
|
-
if (allowedTools && !allowedTools.includes(name))
|
|
574
|
-
continue;
|
|
575
573
|
if (disallowedTools?.includes(name))
|
|
576
574
|
continue;
|
|
577
575
|
const tool = ALL_TOOLS[name];
|
package/dist/utils/cost.d.ts
CHANGED
|
@@ -32,4 +32,17 @@ export declare function calculateOpenAICost(model: string, usage: {
|
|
|
32
32
|
cacheCreationInputTokens: number;
|
|
33
33
|
}): number;
|
|
34
34
|
export declare function findOpenAIPricing(model: string): ModelPricing | undefined;
|
|
35
|
+
export declare const GEMINI_PRICING: Record<string, ModelPricing>;
|
|
36
|
+
export declare const GEMINI_CONTEXT_WINDOWS: Record<string, number>;
|
|
37
|
+
export declare const GEMINI_MAX_OUTPUT: Record<string, number>;
|
|
38
|
+
/**
|
|
39
|
+
* Calculate cost for a Gemini model and token usage.
|
|
40
|
+
*/
|
|
41
|
+
export declare function calculateGeminiCost(model: string, usage: {
|
|
42
|
+
inputTokens: number;
|
|
43
|
+
outputTokens: number;
|
|
44
|
+
cacheReadInputTokens: number;
|
|
45
|
+
cacheCreationInputTokens: number;
|
|
46
|
+
}): number;
|
|
47
|
+
export declare function findGeminiPricing(model: string): ModelPricing | undefined;
|
|
35
48
|
//# sourceMappingURL=cost.d.ts.map
|
package/dist/utils/cost.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cost.d.ts","sourceRoot":"","sources":["../../src/utils/cost.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,MAAM,MAAM,YAAY,GAAG;IACzB,eAAe,EAAE,MAAM,CAAC;IACxB,gBAAgB,EAAE,MAAM,CAAC;IACzB,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,oBAAoB,CAAC,EAAE,MAAM,CAAC;CAC/B,CAAC;AAEF,eAAO,MAAM,iBAAiB,EAAE,MAAM,CAAC,MAAM,EAAE,YAAY,CAmC1D,CAAC;AAEF,eAAO,MAAM,yBAAyB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAM5D,CAAC;AAEF,eAAO,MAAM,oBAAoB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAMvD,CAAC;AAEF;;GAEG;AACH,wBAAgB,sBAAsB,CACpC,KAAK,EAAE,MAAM,EACb,KAAK,EAAE;IAAE,WAAW,EAAE,MAAM,CAAC;IAAC,YAAY,EAAE,MAAM,CAAC;IAAC,oBAAoB,EAAE,MAAM,CAAC;IAAC,wBAAwB,EAAE,MAAM,CAAA;CAAE,GACnH,MAAM,CAUR;AAkBD,eAAO,MAAM,cAAc,EAAE,MAAM,CAAC,MAAM,EAAE,YAAY,CAyCvD,CAAC;AAEF,eAAO,MAAM,sBAAsB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CASzD,CAAC;AAEF,eAAO,MAAM,iBAAiB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CASpD,CAAC;AAEF;;GAEG;AACH,wBAAgB,mBAAmB,CACjC,KAAK,EAAE,MAAM,EACb,KAAK,EAAE;IAAE,WAAW,EAAE,MAAM,CAAC;IAAC,YAAY,EAAE,MAAM,CAAC;IAAC,oBAAoB,EAAE,MAAM,CAAC;IAAC,wBAAwB,EAAE,MAAM,CAAA;CAAE,GACnH,MAAM,CASR;AAED,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,MAAM,GAAG,YAAY,GAAG,SAAS,CAgBzE"}
|
|
1
|
+
{"version":3,"file":"cost.d.ts","sourceRoot":"","sources":["../../src/utils/cost.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,MAAM,MAAM,YAAY,GAAG;IACzB,eAAe,EAAE,MAAM,CAAC;IACxB,gBAAgB,EAAE,MAAM,CAAC;IACzB,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,oBAAoB,CAAC,EAAE,MAAM,CAAC;CAC/B,CAAC;AAEF,eAAO,MAAM,iBAAiB,EAAE,MAAM,CAAC,MAAM,EAAE,YAAY,CAmC1D,CAAC;AAEF,eAAO,MAAM,yBAAyB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAM5D,CAAC;AAEF,eAAO,MAAM,oBAAoB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAMvD,CAAC;AAEF;;GAEG;AACH,wBAAgB,sBAAsB,CACpC,KAAK,EAAE,MAAM,EACb,KAAK,EAAE;IAAE,WAAW,EAAE,MAAM,CAAC;IAAC,YAAY,EAAE,MAAM,CAAC;IAAC,oBAAoB,EAAE,MAAM,CAAC;IAAC,wBAAwB,EAAE,MAAM,CAAA;CAAE,GACnH,MAAM,CAUR;AAkBD,eAAO,MAAM,cAAc,EAAE,MAAM,CAAC,MAAM,EAAE,YAAY,CAyCvD,CAAC;AAEF,eAAO,MAAM,sBAAsB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CASzD,CAAC;AAEF,eAAO,MAAM,iBAAiB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CASpD,CAAC;AAEF;;GAEG;AACH,wBAAgB,mBAAmB,CACjC,KAAK,EAAE,MAAM,EACb,KAAK,EAAE;IAAE,WAAW,EAAE,MAAM,CAAC;IAAC,YAAY,EAAE,MAAM,CAAC;IAAC,oBAAoB,EAAE,MAAM,CAAC;IAAC,wBAAwB,EAAE,MAAM,CAAA;CAAE,GACnH,MAAM,CASR;AAED,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,MAAM,GAAG,YAAY,GAAG,SAAS,CAgBzE;AAID,eAAO,MAAM,cAAc,EAAE,MAAM,CAAC,MAAM,EAAE,YAAY,CAwBvD,CAAC;AAEF,eAAO,MAAM,sBAAsB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAMzD,CAAC;AAEF,eAAO,MAAM,iBAAiB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAMpD,CAAC;AAEF;;GAEG;AACH,wBAAgB,mBAAmB,CACjC,KAAK,EAAE,MAAM,EACb,KAAK,EAAE;IAAE,WAAW,EAAE,MAAM,CAAC;IAAC,YAAY,EAAE,MAAM,CAAC;IAAC,oBAAoB,EAAE,MAAM,CAAC;IAAC,wBAAwB,EAAE,MAAM,CAAA;CAAE,GACnH,MAAM,CASR;AAED,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,MAAM,GAAG,YAAY,GAAG,SAAS,CAezE"}
|