@f5-sales-demo/pi-ai 21.5.2 → 21.5.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/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "type": "module",
3
3
  "name": "@f5-sales-demo/pi-ai",
4
- "version": "21.5.2",
4
+ "version": "21.5.5",
5
5
  "description": "Unified LLM API with automatic model discovery and provider configuration",
6
6
  "homepage": "https://github.com/f5-sales-demo/xcsh",
7
7
  "author": "Can Boluk",
@@ -46,7 +46,7 @@
46
46
  "@anthropic-ai/sdk": "^0.115",
47
47
  "@aws-sdk/client-bedrock-runtime": "^3",
48
48
  "@bufbuild/protobuf": "^2.11",
49
- "@f5-sales-demo/pi-utils": "21.5.2",
49
+ "@f5-sales-demo/pi-utils": "21.5.5",
50
50
  "@google/genai": "^2.15",
51
51
  "@sinclair/typebox": "^0.34",
52
52
  "@smithy/node-http-handler": "^4.4",
@@ -39,7 +39,7 @@ import {
39
39
  export interface GoogleVertexOptions extends StreamOptions {
40
40
  /** OAuth bearer token from the isolated Vertex credential namespace. */
41
41
  apiKey?: string;
42
- toolChoice?: "auto" | "none" | "any";
42
+ toolChoice?: "auto" | "none" | "any" | { name: string };
43
43
  thinking?: {
44
44
  enabled: boolean;
45
45
  budgetTokens?: number; // -1 for dynamic, 0 to disable
@@ -516,9 +516,11 @@ export function buildGoogleVertexParams(
516
516
  };
517
517
 
518
518
  if (context.tools && context.tools.length > 0 && options.toolChoice) {
519
+ const forcedToolName = typeof options.toolChoice === "string" ? undefined : options.toolChoice.name;
519
520
  config.toolConfig = {
520
521
  functionCallingConfig: {
521
- mode: mapToolChoice(options.toolChoice),
522
+ mode: mapToolChoice(typeof options.toolChoice === "string" ? options.toolChoice : "any"),
523
+ ...(forcedToolName && { allowedFunctionNames: [forcedToolName] }),
522
524
  },
523
525
  };
524
526
  } else {
package/src/stream.ts CHANGED
@@ -339,9 +339,7 @@ export function mapAnthropicToolChoice(choice?: ToolChoice): AnthropicOptions["t
339
339
  return undefined;
340
340
  }
341
341
 
342
- function mapGoogleToolChoice(
343
- choice?: ToolChoice,
344
- ): GoogleOptions["toolChoice"] | GoogleGeminiCliOptions["toolChoice"] | GoogleVertexOptions["toolChoice"] {
342
+ function mapGoogleToolChoice(choice?: ToolChoice): GoogleOptions["toolChoice"] | GoogleGeminiCliOptions["toolChoice"] {
345
343
  if (!choice) return undefined;
346
344
  if (typeof choice === "string") {
347
345
  if (choice === "required") return "any";
@@ -351,6 +349,17 @@ function mapGoogleToolChoice(
351
349
  return "any";
352
350
  }
353
351
 
352
+ function mapGoogleVertexToolChoice(choice?: ToolChoice): GoogleVertexOptions["toolChoice"] {
353
+ if (!choice) return undefined;
354
+ if (typeof choice === "string") {
355
+ if (choice === "required") return "any";
356
+ if (choice === "auto" || choice === "none" || choice === "any") return choice;
357
+ return undefined;
358
+ }
359
+ const name = choice.type === "function" && "function" in choice ? choice.function.name : choice.name;
360
+ return name ? { name } : undefined;
361
+ }
362
+
354
363
  function mapOpenAiToolChoice(choice?: ToolChoice): OpenAICompletionsOptions["toolChoice"] {
355
364
  if (!choice) return undefined;
356
365
  if (typeof choice === "string") {
@@ -637,7 +646,7 @@ export function mapOptionsForApi<TApi extends Api>(
637
646
  return castApi<"google-vertex">({
638
647
  ...vertexBase,
639
648
  thinking: { enabled: false },
640
- toolChoice: mapGoogleToolChoice(options?.toolChoice),
649
+ toolChoice: mapGoogleVertexToolChoice(options?.toolChoice),
641
650
  });
642
651
  }
643
652
 
@@ -652,7 +661,7 @@ export function mapOptionsForApi<TApi extends Api>(
652
661
  enabled: true,
653
662
  level: mapEffortToGoogleThinkingLevel(geminiModel, effort),
654
663
  },
655
- toolChoice: mapGoogleToolChoice(options?.toolChoice),
664
+ toolChoice: mapGoogleVertexToolChoice(options?.toolChoice),
656
665
  });
657
666
  }
658
667
 
@@ -662,7 +671,7 @@ export function mapOptionsForApi<TApi extends Api>(
662
671
  enabled: true,
663
672
  budgetTokens: getGoogleBudget(geminiModel, effort, options?.thinkingBudgets),
664
673
  },
665
- toolChoice: mapGoogleToolChoice(options?.toolChoice),
674
+ toolChoice: mapGoogleVertexToolChoice(options?.toolChoice),
666
675
  });
667
676
  }
668
677
 
@@ -29,12 +29,6 @@ const SCOPES = [
29
29
 
30
30
  const AUTH_URL = "https://accounts.google.com/o/oauth2/v2/auth";
31
31
  const TOKEN_URL = "https://oauth2.googleapis.com/token";
32
- // Split the licensed public desktop identifier so secret scanners do not mistake
33
- // the complete client ID for a user credential.
34
- const VERTEX_CLIENT_ID =
35
- decode("ODg0MzU0OTE5MDUyLTM2dHJjMWpqYjN0Z3VpYWMzMm92NmNvZA==") +
36
- decode("MjY4YzVibGguYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20=");
37
- const VERTEX_CLIENT_SECRET = decode("R09DU1BYLTlZUVdwRjdS") + decode("V0RDMFFUZGotWXhLTXdSMFp0c1g=");
38
32
  const VERTEX_AUTH_URL = "https://accounts.google.com/o/oauth2/auth";
39
33
  export const VERTEX_OAUTH_REDIRECT_URI = "https://antigravity.google/oauth-callback";
40
34
  const VERTEX_OAUTH_TIMEOUT_MS = 15 * 60 * 1000;
@@ -47,6 +41,23 @@ const PROJECT_ID_PATTERN = /^[a-z][a-z0-9-]{4,28}[a-z0-9]$/;
47
41
  const PROJECT_NUMBER_PATTERN = /^\d{12}$/;
48
42
  const ANTIGRAVITY_CLI_TOKEN_PATH = join(homedir(), ".gemini", "antigravity-cli", "antigravity-oauth-token");
49
43
 
44
+ declare const PI_VERTEX_OAUTH_CLIENT_ID: string | undefined;
45
+ declare const PI_VERTEX_OAUTH_CLIENT_SECRET: string | undefined;
46
+
47
+ function resolveVertexOAuthClient(): { clientId: string; clientSecret: string } {
48
+ const compiledClientId = typeof PI_VERTEX_OAUTH_CLIENT_ID === "string" ? PI_VERTEX_OAUTH_CLIENT_ID.trim() : "";
49
+ const compiledClientSecret =
50
+ typeof PI_VERTEX_OAUTH_CLIENT_SECRET === "string" ? PI_VERTEX_OAUTH_CLIENT_SECRET.trim() : "";
51
+ const clientId = compiledClientId || Bun.env.XCSH_VERTEX_OAUTH_CLIENT_ID?.trim();
52
+ const clientSecret = compiledClientSecret || Bun.env.XCSH_VERTEX_OAUTH_CLIENT_SECRET?.trim();
53
+ if (!clientId || !clientSecret) {
54
+ throw new Error(
55
+ "Corporate Vertex OAuth credentials are unavailable in this build. Install an official xcsh binary or provide the licensed build credentials when running from source.",
56
+ );
57
+ }
58
+ return { clientId, clientSecret };
59
+ }
60
+
50
61
  interface LoadCodeAssistPayload {
51
62
  cloudaicompanionProject?: string | { id?: string };
52
63
  currentTier?: { id?: string };
@@ -442,12 +453,13 @@ export async function exchangeVertexOAuthCode(
442
453
  verifier: string,
443
454
  fetchImpl: typeof fetch = fetch,
444
455
  ): Promise<OAuthCredentials> {
456
+ const { clientId, clientSecret } = resolveVertexOAuthClient();
445
457
  const tokenResponse = await fetchImpl(TOKEN_URL, {
446
458
  method: "POST",
447
459
  headers: { "Content-Type": "application/x-www-form-urlencoded" },
448
460
  body: new URLSearchParams({
449
- client_id: VERTEX_CLIENT_ID,
450
- client_secret: VERTEX_CLIENT_SECRET,
461
+ client_id: clientId,
462
+ client_secret: clientSecret,
451
463
  code,
452
464
  code_verifier: verifier,
453
465
  grant_type: "authorization_code",
@@ -470,9 +482,10 @@ export async function exchangeVertexOAuthCode(
470
482
  }
471
483
 
472
484
  export function createVertexAuthorizationUrl(state: string, challenge: string): string {
485
+ const { clientId } = resolveVertexOAuthClient();
473
486
  const params = new URLSearchParams({
474
487
  access_type: "offline",
475
- client_id: VERTEX_CLIENT_ID,
488
+ client_id: clientId,
476
489
  code_challenge: challenge,
477
490
  code_challenge_method: "S256",
478
491
  prompt: "consent",
@@ -539,12 +552,13 @@ export async function refreshVertexWithAntigravityOAuth(
539
552
  refreshToken: string,
540
553
  fetchImpl: typeof fetch = fetch,
541
554
  ): Promise<OAuthCredentials> {
555
+ const { clientId, clientSecret } = resolveVertexOAuthClient();
542
556
  const response = await fetchImpl(TOKEN_URL, {
543
557
  method: "POST",
544
558
  headers: { "Content-Type": "application/x-www-form-urlencoded" },
545
559
  body: new URLSearchParams({
546
- client_id: VERTEX_CLIENT_ID,
547
- client_secret: VERTEX_CLIENT_SECRET,
560
+ client_id: clientId,
561
+ client_secret: clientSecret,
548
562
  refresh_token: refreshToken,
549
563
  grant_type: "refresh_token",
550
564
  }),