vibezcheck 0.2.0 → 0.3.0

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/index.mjs CHANGED
@@ -1,3 +1,10 @@
1
+ var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
2
+ get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
3
+ }) : x)(function(x) {
4
+ if (typeof require !== "undefined") return require.apply(this, arguments);
5
+ throw Error('Dynamic require of "' + x + '" is not supported');
6
+ });
7
+
1
8
  // src/index.ts
2
9
  import Stripe5 from "stripe";
3
10
 
@@ -822,6 +829,16 @@ function createMeter(options = {}) {
822
829
  return new VibezMeter(options);
823
830
  }
824
831
 
832
+ // src/types.ts
833
+ var VibezCircuitBreakerError = class extends Error {
834
+ event;
835
+ constructor(event) {
836
+ super(event.message);
837
+ this.name = "VibezCircuitBreakerError";
838
+ this.event = event;
839
+ }
840
+ };
841
+
825
842
  // src/ai-sdk/with-billing.ts
826
843
  function withBilling(model, options = {}) {
827
844
  if (!model || typeof model !== "object") {
@@ -849,6 +866,38 @@ function withBilling(model, options = {}) {
849
866
  cachedTokens: cachedTokens > 0 ? cachedTokens : void 0
850
867
  };
851
868
  const cost = calculateUsageCost(modelId, usage);
869
+ if (options.maxCostPerCallUSD && cost.totalUSD > options.maxCostPerCallUSD) {
870
+ const budgetEvent = {
871
+ reason: "cost_per_call_exceeded",
872
+ limit: options.maxCostPerCallUSD,
873
+ current: cost.totalUSD,
874
+ model: modelId,
875
+ customerId,
876
+ message: `[vibezcheck] Circuit Breaker tripped: Call cost ($${cost.totalUSD.toFixed(4)}) exceeded maxCostPerCallUSD threshold ($${options.maxCostPerCallUSD.toFixed(4)}).`
877
+ };
878
+ if (options.onBudgetExceeded) {
879
+ options.onBudgetExceeded(budgetEvent);
880
+ }
881
+ if (options.throwOnBudgetExceeded) {
882
+ throw new VibezCircuitBreakerError(budgetEvent);
883
+ }
884
+ }
885
+ if (options.maxTokensPerCall && usage.totalTokens > options.maxTokensPerCall) {
886
+ const budgetEvent = {
887
+ reason: "max_tokens_exceeded",
888
+ limit: options.maxTokensPerCall,
889
+ current: usage.totalTokens,
890
+ model: modelId,
891
+ customerId,
892
+ message: `[vibezcheck] Circuit Breaker tripped: Token count (${usage.totalTokens}) exceeded maxTokensPerCall limit (${options.maxTokensPerCall}).`
893
+ };
894
+ if (options.onBudgetExceeded) {
895
+ options.onBudgetExceeded(budgetEvent);
896
+ }
897
+ if (options.throwOnBudgetExceeded) {
898
+ throw new VibezCircuitBreakerError(budgetEvent);
899
+ }
900
+ }
852
901
  const event = {
853
902
  timestamp: (/* @__PURE__ */ new Date()).toISOString(),
854
903
  model: modelId,
@@ -872,18 +921,9 @@ function withBilling(model, options = {}) {
872
921
  options.onUsage(event);
873
922
  }
874
923
  };
875
- return new Proxy(model, {
924
+ const handler = {
876
925
  get(target, prop, receiver) {
877
926
  const originalValue = Reflect.get(target, prop, receiver);
878
- if (prop === "doGenerate" && typeof originalValue === "function") {
879
- return async function(...args) {
880
- const result = await originalValue.apply(target, args);
881
- if (result && result.usage) {
882
- handleUsage(result.usage);
883
- }
884
- return result;
885
- };
886
- }
887
927
  if (prop === "doStream" && typeof originalValue === "function") {
888
928
  return async function(...args) {
889
929
  const result = await originalValue.apply(target, args);
@@ -891,61 +931,86 @@ function withBilling(model, options = {}) {
891
931
  return result;
892
932
  }
893
933
  const originalStream = result.stream;
894
- if (typeof originalStream.getReader === "function") {
895
- const reader = originalStream.getReader();
896
- const transformedStream = new ReadableStream({
897
- async start(controller) {
898
- try {
899
- while (true) {
900
- const { done, value } = await reader.read();
901
- if (done) {
902
- controller.close();
903
- break;
904
- }
905
- if (value && typeof value === "object") {
906
- if (value.type === "finish" && value.usage) {
907
- handleUsage(value.usage);
908
- }
909
- }
910
- controller.enqueue(value);
911
- }
912
- } catch (err) {
913
- controller.error(err);
914
- }
915
- }
916
- });
917
- return {
918
- ...result,
919
- stream: transformedStream
920
- };
921
- }
922
- if (Symbol.asyncIterator in originalStream) {
923
- const wrappedAsyncIterable = {
924
- async *[Symbol.asyncIterator]() {
925
- for await (const chunk of originalStream) {
926
- if (chunk && typeof chunk === "object") {
927
- if (chunk.type === "finish" && chunk.usage) {
928
- handleUsage(chunk.usage);
929
- }
930
- }
931
- yield chunk;
932
- }
934
+ const transformStream = new TransformStream({
935
+ transform(chunk, controller) {
936
+ controller.enqueue(chunk);
937
+ if (chunk.type === "finish" && chunk.usage) {
938
+ handleUsage(chunk.usage);
933
939
  }
934
- };
935
- return {
936
- ...result,
937
- stream: wrappedAsyncIterable
938
- };
940
+ }
941
+ });
942
+ return {
943
+ ...result,
944
+ stream: originalStream.pipeThrough(transformStream)
945
+ };
946
+ };
947
+ }
948
+ if (prop === "doGenerate" && typeof originalValue === "function") {
949
+ return async function(...args) {
950
+ const result = await originalValue.apply(target, args);
951
+ if (result && result.usage) {
952
+ handleUsage(result.usage);
939
953
  }
940
954
  return result;
941
955
  };
942
956
  }
943
957
  return originalValue;
944
958
  }
945
- });
959
+ };
960
+ return new Proxy(model, handler);
946
961
  }
947
962
  var meteredModel = withBilling;
948
963
 
964
+ // src/ai-sdk/declarative.ts
965
+ function createVibezModel(modelOrId, options = {}) {
966
+ if (typeof modelOrId === "object" && modelOrId !== null) {
967
+ return withBilling(modelOrId, options);
968
+ }
969
+ if (typeof modelOrId === "string") {
970
+ const rawId = modelOrId;
971
+ let providerName = "openai";
972
+ let cleanModelId = rawId;
973
+ if (rawId.includes("/")) {
974
+ const parts = rawId.split("/");
975
+ providerName = parts[0].toLowerCase();
976
+ cleanModelId = parts.slice(1).join("/");
977
+ }
978
+ const apiKey = options.apiKey || process.env.AI_GATEWAY_API_KEY || process.env.OPENAI_API_KEY || process.env.ANTHROPIC_API_KEY || process.env.GOOGLE_GENERATIVE_AI_API_KEY;
979
+ const baseURL = options.baseURL || process.env.AI_GATEWAY_BASE_URL || (providerName === "openai" ? "https://api.openai.com/v1" : void 0);
980
+ let baseModelInstance = null;
981
+ try {
982
+ if (providerName === "openai" || providerName === "gateway" || !providerName) {
983
+ const { createOpenAI } = __require("@ai-sdk/openai");
984
+ const openaiProvider = createOpenAI({ apiKey, baseURL });
985
+ baseModelInstance = openaiProvider(cleanModelId);
986
+ } else if (providerName === "anthropic") {
987
+ const { createAnthropic } = __require("@ai-sdk/anthropic");
988
+ const anthropicProvider = createAnthropic({ apiKey, baseURL });
989
+ baseModelInstance = anthropicProvider(cleanModelId);
990
+ } else if (providerName === "google") {
991
+ const { createGoogleGenerativeAI } = __require("@ai-sdk/google");
992
+ const googleProvider = createGoogleGenerativeAI({ apiKey, baseURL });
993
+ baseModelInstance = googleProvider(cleanModelId);
994
+ }
995
+ } catch {
996
+ baseModelInstance = {
997
+ specificationVersion: "v2",
998
+ provider: providerName,
999
+ modelId: cleanModelId
1000
+ };
1001
+ }
1002
+ if (!baseModelInstance) {
1003
+ baseModelInstance = {
1004
+ specificationVersion: "v2",
1005
+ provider: providerName,
1006
+ modelId: cleanModelId
1007
+ };
1008
+ }
1009
+ return withBilling(baseModelInstance, options);
1010
+ }
1011
+ return modelOrId;
1012
+ }
1013
+
949
1014
  // src/customers/manager.ts
950
1015
  import Stripe2 from "stripe";
951
1016
 
@@ -1284,43 +1349,12 @@ var VibezCheckClient = class {
1284
1349
  });
1285
1350
  }
1286
1351
  /**
1287
- * 1-Line Universal Stream Responder for API Routes (Next.js, Express, Hono)
1352
+ * Declarative model resolver for Vercel AI SDK
1288
1353
  */
1289
- async stream(params) {
1290
- const OpenAI = (await import("openai")).default;
1291
- const openai = new OpenAI();
1292
- const responseStream = await openai.chat.completions.create({
1293
- model: params.model,
1294
- messages: params.messages,
1295
- stream: true,
1296
- stream_options: { include_usage: true },
1297
- temperature: params.temperature
1298
- });
1299
- const meteredStream = this.wrapStream(responseStream, {
1300
- customer: params.customer,
1301
- model: params.model
1302
- });
1303
- const encoder = new TextEncoder();
1304
- const readable = new ReadableStream({
1305
- async start(controller) {
1306
- try {
1307
- for await (const chunk of meteredStream) {
1308
- const text = chunk.choices?.[0]?.delta?.content || "";
1309
- if (text) {
1310
- controller.enqueue(encoder.encode(text));
1311
- }
1312
- }
1313
- controller.close();
1314
- } catch (err) {
1315
- controller.error(err);
1316
- }
1317
- }
1318
- });
1319
- return new Response(readable, {
1320
- headers: {
1321
- "Content-Type": "text/plain; charset=utf-8",
1322
- "Transfer-Encoding": "chunked"
1323
- }
1354
+ model(modelOrId, options) {
1355
+ return createVibezModel(modelOrId, {
1356
+ ...options,
1357
+ meter: this.meter
1324
1358
  });
1325
1359
  }
1326
1360
  /**
@@ -1339,9 +1373,20 @@ var VibezCheckClient = class {
1339
1373
  function createVibezCheck(config = {}) {
1340
1374
  return new VibezCheckClient(config);
1341
1375
  }
1342
- var vibezcheck = createVibezCheck;
1343
- var vibescheck = createVibezCheck;
1344
- var vibez = createVibezCheck();
1376
+ function vibezcheck(firstArg, secondArg) {
1377
+ if (typeof firstArg === "string" || firstArg && (firstArg.specificationVersion || firstArg.doGenerate || firstArg.doStream)) {
1378
+ return createVibezModel(firstArg, secondArg);
1379
+ }
1380
+ return new VibezCheckClient(firstArg || {});
1381
+ }
1382
+ vibezcheck.calculateCost = calculateCost;
1383
+ vibezcheck.getModelPricing = getModelPricing;
1384
+ vibezcheck.registerModelPricing = registerModelPricing;
1385
+ vibezcheck.create = createVibezCheck;
1386
+ vibezcheck.withBilling = withBilling;
1387
+ vibezcheck.createMeter = createMeter;
1388
+ var vibez = new VibezCheckClient();
1389
+ var vibescheck = vibezcheck;
1345
1390
  var vibes = vibez;
1346
1391
  export {
1347
1392
  AnthropicStreamAccumulator,
@@ -1352,6 +1397,7 @@ export {
1352
1397
  MODEL_PRICING_TABLE,
1353
1398
  MeterBatcher,
1354
1399
  VibezCheckClient,
1400
+ VibezCircuitBreakerError,
1355
1401
  VibezMeter,
1356
1402
  calculateCost,
1357
1403
  calculateUsageCost,
@@ -1360,6 +1406,7 @@ export {
1360
1406
  createCustomerManager,
1361
1407
  createMeter,
1362
1408
  createVibezCheck,
1409
+ createVibezModel,
1363
1410
  detectAndExtractUsage,
1364
1411
  extractAnthropicResponseUsage,
1365
1412
  extractAuthToken,