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.
@@ -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;AAMlD,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,CAyB1G;AAED,wBAAgB,aAAa,IAAI,MAAM,EAAE,CAExC"}
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,CAed"}
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"}
@@ -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];
@@ -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
@@ -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"}