@kalaa/node 1.0.9 → 1.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.
Files changed (2) hide show
  1. package/costmeter.js +48 -0
  2. package/package.json +1 -1
package/costmeter.js CHANGED
@@ -479,6 +479,54 @@ function patchAnthropicModule() {
479
479
  // per-instance in the Models constructor, not on Models.prototype. Prototype
480
480
  // patching is a no-op here; we wrap the instance's own methods instead, right
481
481
  // after GoogleGenAI's constructor creates them.
482
+ function patchGeminiModule() {
483
+ patchGeminiLegacy();
484
+ patchGeminiUnified();
485
+ }
486
+
487
+ function patchGeminiLegacy() {
488
+ let Mod;
489
+ try { Mod = require('@google/generative-ai'); } catch { return; }
490
+ const GoogleGenerativeAI = Mod.GoogleGenerativeAI;
491
+ if (!GoogleGenerativeAI || GoogleGenerativeAI.__cm_patched) return;
492
+
493
+ let GenerativeModel;
494
+ try {
495
+ const probe = new GoogleGenerativeAI('cm_probe');
496
+ const model = probe.getGenerativeModel({ model: 'gemini-1.5-flash' });
497
+ GenerativeModel = Object.getPrototypeOf(model).constructor;
498
+ } catch (e) {
499
+ log('gemini (legacy) probe failed:', e.message);
500
+ return;
501
+ }
502
+
503
+ if (GenerativeModel?.prototype?.generateContent && !GenerativeModel.prototype.generateContent.__cm) {
504
+ const orig = GenerativeModel.prototype.generateContent;
505
+ const wrapped = async function (params, ...rest) {
506
+ const t0 = Date.now();
507
+ const modelName = (this.model || 'gemini').replace(/^models\//, '');
508
+ let _user, clean = params;
509
+ if (params && typeof params === 'object' && !Array.isArray(params) && '_user' in params) {
510
+ ({ _user, ...clean } = params);
511
+ }
512
+ try {
513
+ const resp = await orig.call(this, clean, ...rest);
514
+ const usage = resp?.response?.usageMetadata || {};
515
+ track({ provider: 'gemini', model: modelName, usage, latencyMs: Date.now() - t0, endUser: _user });
516
+ return resp;
517
+ } catch (err) {
518
+ track({ provider: 'gemini', model: modelName, usage: {}, latencyMs: Date.now() - t0, status: 'error', meta: { error: String(err.message).slice(0, 200) }, endUser: _user });
519
+ throw err;
520
+ }
521
+ };
522
+ wrapped.__cm = true;
523
+ GenerativeModel.prototype.generateContent = wrapped;
524
+ }
525
+
526
+ GoogleGenerativeAI.__cm_patched = true;
527
+ log('gemini (legacy @google/generative-ai) module patched (prototype-level)');
528
+ }
529
+
482
530
  function patchGeminiUnified() {
483
531
  let Mod;
484
532
  try { Mod = require('@google/genai'); } catch { return; } // not installed, skip
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kalaa/node",
3
- "version": "1.0.9",
3
+ "version": "1.1.1",
4
4
  "description": "Drop-in AI cost tracking for Node.js and TypeScript. Auto-instruments OpenAI, Anthropic, and Gemini at the class level, with zero code at each call site.",
5
5
  "main": "costmeter.js",
6
6
  "types": "costmeter.d.ts",