@core-ai/google-genai 0.15.0 → 0.17.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.d.ts CHANGED
@@ -30,7 +30,6 @@ type GoogleReasoningMetadata = {
30
30
  type GoogleModelCapabilities = {
31
31
  reasoning: ModelCapabilities['reasoning'] & {
32
32
  thinkingParam: 'thinkingLevel' | 'thinkingBudget';
33
- canDisableThinking: boolean;
34
33
  };
35
34
  };
36
35
  declare function getGoogleModelCapabilities(modelId: string): GoogleModelCapabilities;
package/dist/index.js CHANGED
@@ -30,25 +30,25 @@ var ALL_EFFORTS = [
30
30
  function createCapabilities(config) {
31
31
  return {
32
32
  reasoning: {
33
- supported: true,
33
+ mode: config.mode,
34
34
  supportedEfforts: ALL_EFFORTS,
35
35
  restrictsSamplingParams: false,
36
- thinkingParam: config.thinkingParam,
37
- canDisableThinking: config.canDisableThinking
36
+ supportedToolChoices: ["auto", "none", "required", "tool"],
37
+ thinkingParam: config.thinkingParam
38
38
  }
39
39
  };
40
40
  }
41
41
  var DEFAULT_CAPABILITIES = createCapabilities({
42
42
  thinkingParam: "thinkingBudget",
43
- canDisableThinking: true
43
+ mode: "optional"
44
44
  });
45
45
  var REQUIRED_THINKING_BUDGET_CAPABILITIES = createCapabilities({
46
46
  thinkingParam: "thinkingBudget",
47
- canDisableThinking: false
47
+ mode: "always-on"
48
48
  });
49
49
  var THINKING_LEVEL_CAPABILITIES = createCapabilities({
50
50
  thinkingParam: "thinkingLevel",
51
- canDisableThinking: false
51
+ mode: "always-on"
52
52
  });
53
53
  var MODEL_CAPABILITIES = {
54
54
  "gemini-3.1-pro": THINKING_LEVEL_CAPABILITIES,
@@ -683,17 +683,133 @@ function mapUsage(response, fallback) {
683
683
 
684
684
  // src/google-error.ts
685
685
  import { ApiError } from "@google/genai";
686
- import { ProviderError } from "@core-ai/core-ai";
686
+ import {
687
+ AbortedError,
688
+ ContextLengthExceededError,
689
+ ModelOverloadedError,
690
+ ProviderError,
691
+ RateLimitError,
692
+ ServiceUnavailableError,
693
+ getErrorMessage,
694
+ getHttpStatusCode,
695
+ getRetryAfterSecondsFromError,
696
+ isAbortErrorByName,
697
+ isRateLimitStatus,
698
+ isTransientUnavailableStatus
699
+ } from "@core-ai/core-ai";
700
+ var OVERLOAD_MESSAGE_ELIGIBLE_STATUS_CODES = /* @__PURE__ */ new Set([500, 502, 503, 504]);
687
701
  function wrapGoogleError(error, provider = "google") {
688
- if (error instanceof ApiError) {
689
- return new ProviderError(error.message, provider, error.status, error);
702
+ if (isGoogleAbortError(error)) {
703
+ return new AbortedError(error, provider);
690
704
  }
691
- return new ProviderError(
692
- error instanceof Error ? error.message : String(error),
693
- provider,
694
- void 0,
695
- error
705
+ const message = getErrorMessage(error);
706
+ const statusCode = error instanceof ApiError ? error.status : getHttpStatusCode(error, ["status"]);
707
+ const body = tryParseGoogleApiErrorBody(message);
708
+ const effectiveHttp = statusCode ?? toNumericHttpCode(body);
709
+ const options = { statusCode: effectiveHttp, cause: error };
710
+ const status = body?.status?.toUpperCase();
711
+ const combinedText = `${body?.message ?? ""} ${message}`;
712
+ const contextLength = getContextLengthDetails(combinedText);
713
+ if (contextLength) {
714
+ return new ContextLengthExceededError(message, provider, {
715
+ ...options,
716
+ ...contextLength
717
+ });
718
+ }
719
+ if (indicatesGoogleOverload(combinedText, effectiveHttp)) {
720
+ return new ModelOverloadedError(message, provider, options);
721
+ }
722
+ if (isGoogleRateLimit(effectiveHttp, status)) {
723
+ return new RateLimitError(message, provider, {
724
+ ...options,
725
+ retryAfterSeconds: getRetryAfterSecondsFromError(error) ?? parseRetryAfterFromMessage(combinedText)
726
+ });
727
+ }
728
+ if (status === "UNAVAILABLE" || isTransientUnavailableStatus(effectiveHttp)) {
729
+ return new ServiceUnavailableError(message, provider, options);
730
+ }
731
+ return new ProviderError(message, provider, options);
732
+ }
733
+ function isGoogleAbortError(error) {
734
+ if (isAbortErrorByName(error)) {
735
+ return true;
736
+ }
737
+ const message = getErrorMessage(error).toLowerCase();
738
+ return message.includes("the operation was aborted") || message.includes("this operation was aborted") || message.includes("request aborted") || message.includes("the request was aborted");
739
+ }
740
+ function isGoogleRateLimit(statusCode, status) {
741
+ return isRateLimitStatus(statusCode) || status === "RESOURCE_EXHAUSTED";
742
+ }
743
+ function indicatesGoogleOverload(text, statusCode) {
744
+ if (statusCode !== void 0 && !OVERLOAD_MESSAGE_ELIGIBLE_STATUS_CODES.has(statusCode)) {
745
+ return false;
746
+ }
747
+ const lower = text.toLowerCase();
748
+ return /\boverloaded\b/.test(lower) || /\bhigh demand\b/.test(lower) || /\bthrottled\b/.test(lower) || /\brunning out of capacity\b/.test(lower) || /\bno capacity available\b/.test(lower);
749
+ }
750
+ function getContextLengthDetails(text) {
751
+ const match = text.match(
752
+ /input token count \((\d+)\) exceeds the maximum number of tokens allowed \((\d+)\)/i
753
+ );
754
+ if (match) {
755
+ const actualTokens = match[1];
756
+ const maxTokens = match[2];
757
+ if (actualTokens !== void 0 && maxTokens !== void 0) {
758
+ return {
759
+ maxTokens: parseInt(maxTokens, 10),
760
+ actualTokens: parseInt(actualTokens, 10)
761
+ };
762
+ }
763
+ }
764
+ const alternate = text.match(
765
+ /input token count is (\d+) but model only supports up to (\d+)/i
696
766
  );
767
+ if (alternate) {
768
+ const actualTokens = alternate[1];
769
+ const maxTokens = alternate[2];
770
+ if (actualTokens !== void 0 && maxTokens !== void 0) {
771
+ return {
772
+ maxTokens: parseInt(maxTokens, 10),
773
+ actualTokens: parseInt(actualTokens, 10)
774
+ };
775
+ }
776
+ }
777
+ if (/exceeds the maximum number of tokens allowed/i.test(text) || /unable to submit request because the input token count/i.test(text)) {
778
+ return {};
779
+ }
780
+ return void 0;
781
+ }
782
+ function tryParseGoogleApiErrorBody(message) {
783
+ const jsonStart = message.indexOf("{");
784
+ const candidate = jsonStart >= 0 ? message.slice(jsonStart) : message;
785
+ try {
786
+ const parsed = JSON.parse(candidate);
787
+ if (parsed && typeof parsed === "object" && "error" in parsed && parsed.error && typeof parsed.error === "object") {
788
+ return parsed.error;
789
+ }
790
+ } catch {
791
+ }
792
+ return null;
793
+ }
794
+ function parseRetryAfterFromMessage(text) {
795
+ const match = text.match(/please retry in (\d+)\s*s/i);
796
+ if (!match?.[1]) {
797
+ return void 0;
798
+ }
799
+ const seconds = parseInt(match[1], 10);
800
+ return Number.isFinite(seconds) ? seconds : void 0;
801
+ }
802
+ function toNumericHttpCode(body) {
803
+ if (body?.code === void 0) {
804
+ return void 0;
805
+ }
806
+ if (typeof body.code === "number" && Number.isFinite(body.code)) {
807
+ return body.code;
808
+ }
809
+ if (typeof body.code === "string" && /^\d+$/.test(body.code)) {
810
+ return parseInt(body.code, 10);
811
+ }
812
+ return void 0;
697
813
  }
698
814
 
699
815
  // src/chat-model.ts
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@core-ai/google-genai",
3
- "version": "0.15.0",
3
+ "version": "0.17.0",
4
4
  "description": "Google GenAI provider package for @core-ai/core-ai",
5
5
  "license": "MIT",
6
6
  "author": "Omnifact (https://omnifact.ai)",
@@ -45,7 +45,7 @@
45
45
  "test:watch": "vitest"
46
46
  },
47
47
  "dependencies": {
48
- "@core-ai/core-ai": "^0.15.0",
48
+ "@core-ai/core-ai": "^0.17.0",
49
49
  "@google/genai": "^1.42.0"
50
50
  },
51
51
  "peerDependencies": {