@f5-sales-demo/pi-ai 20.4.4 → 20.4.6

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/CHANGELOG.md CHANGED
@@ -17,6 +17,7 @@
17
17
  ### Fixed
18
18
 
19
19
  - Preserved native Gemini finish reasons in Google provider errors instead of reporting an unknown error ([#2874](https://github.com/f5-sales-demo/xcsh/issues/2874))
20
+ - Resolved Vertex AI projects directly from the active gcloud configuration before invoking gcloud, so Gemini authentication remains usable when the local gcloud Python launcher is broken ([#2996](https://github.com/f5-sales-demo/xcsh/issues/2996))
20
21
 
21
22
  <!-- markdownlint-disable MD024 -->
22
23
  <!-- textlint-disable terminology -->
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "type": "module",
3
3
  "name": "@f5-sales-demo/pi-ai",
4
- "version": "20.4.4",
4
+ "version": "20.4.6",
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": "20.4.4",
49
+ "@f5-sales-demo/pi-utils": "20.4.6",
50
50
  "@google/genai": "^2.15",
51
51
  "@sinclair/typebox": "^0.34",
52
52
  "@smithy/node-http-handler": "^4.4",
@@ -362,6 +362,13 @@ function applyAnthropicCatalogPolicy(model: ApiModel<Api>, parsedModel: Anthropi
362
362
  }
363
363
 
364
364
  function applyOpenAICatalogPolicy(model: ApiModel<Api>, parsedModel: OpenAIModel): void {
365
+ // LiteLLM's GPT-5.6 Sol route accepts image input, but upstream catalog
366
+ // metadata currently reports text only. Keep this correction exact so other
367
+ // providers and GPT-5.6 variants retain their advertised capabilities.
368
+ if (model.provider === "litellm" && model.id === "gpt-5.6-sol") {
369
+ model.input = ["text", "image"];
370
+ }
371
+
365
372
  // Codex models: 400K figure includes output budget; input window is 272K.
366
373
  if (parsedModel.variant.startsWith("codex") && parsedModel.variant !== "codex-spark") {
367
374
  model.contextWindow = 272000;
package/src/models.json CHANGED
@@ -16599,7 +16599,8 @@
16599
16599
  "baseUrl": "http://localhost:4000/v1",
16600
16600
  "reasoning": true,
16601
16601
  "input": [
16602
- "text"
16602
+ "text",
16603
+ "image"
16603
16604
  ],
16604
16605
  "cost": {
16605
16606
  "input": 0,
@@ -1,3 +1,4 @@
1
+ import * as fs from "node:fs/promises";
1
2
  import * as os from "node:os";
2
3
  import * as path from "node:path";
3
4
  import { $env, $which, isEnoent } from "@f5-sales-demo/pi-utils";
@@ -46,6 +47,7 @@ export interface GoogleVertexOptions extends StreamOptions {
46
47
 
47
48
  export interface GoogleVertexProjectRuntime {
48
49
  readAdcProject(): Promise<string | undefined>;
50
+ readLocalConfigProject?(): Promise<string | undefined>;
49
51
  findGcloud(): string | null;
50
52
  readConfiguredProject(gcloud: string): Promise<string | undefined>;
51
53
  }
@@ -359,6 +361,7 @@ function resolveApiKey(options?: GoogleVertexOptions): string | undefined {
359
361
 
360
362
  const defaultProjectRuntime: GoogleVertexProjectRuntime = {
361
363
  readAdcProject,
364
+ readLocalConfigProject: readConfiguredGcloudProject,
362
365
  findGcloud: () => $which("gcloud"),
363
366
  readConfiguredProject: async gcloud => {
364
367
  const result = await $`${gcloud} config get-value project`.quiet().nothrow();
@@ -370,6 +373,50 @@ const defaultProjectRuntime: GoogleVertexProjectRuntime = {
370
373
  },
371
374
  };
372
375
 
376
+ function parseGcloudCoreProject(content: string): string | undefined {
377
+ let inCoreSection = false;
378
+ for (const rawLine of content.split(/\r?\n/)) {
379
+ const line = rawLine.trim();
380
+ if (!line || line.startsWith("#") || line.startsWith(";")) continue;
381
+ const section = line.match(/^\[([^\]]+)]$/);
382
+ if (section) {
383
+ inCoreSection = section[1].trim() === "core";
384
+ continue;
385
+ }
386
+ if (!inCoreSection) continue;
387
+ const property = line.match(/^project\s*=\s*(.+)$/);
388
+ if (!property) continue;
389
+ const project = property[1].trim();
390
+ return project && project !== "(unset)" ? project : undefined;
391
+ }
392
+ return undefined;
393
+ }
394
+
395
+ /** Read the active gcloud project's INI file without requiring gcloud's Python launcher. */
396
+ export async function readConfiguredGcloudProject(
397
+ configDirectory: string = $env.CLOUDSDK_CONFIG || path.join(os.homedir(), ".config", "gcloud"),
398
+ ): Promise<string | undefined> {
399
+ let configurationName = $env.CLOUDSDK_ACTIVE_CONFIG_NAME?.trim();
400
+ if (!configurationName) {
401
+ try {
402
+ configurationName = (await fs.readFile(path.join(configDirectory, "active_config"), "utf8")).trim();
403
+ } catch {
404
+ configurationName = "default";
405
+ }
406
+ }
407
+ if (!/^[A-Za-z0-9_-]+$/.test(configurationName)) return undefined;
408
+
409
+ try {
410
+ const content = await fs.readFile(
411
+ path.join(configDirectory, "configurations", `config_${configurationName}`),
412
+ "utf8",
413
+ );
414
+ return parseGcloudCoreProject(content);
415
+ } catch {
416
+ return undefined;
417
+ }
418
+ }
419
+
373
420
  export async function resolveGoogleVertexProject(
374
421
  options?: GoogleVertexOptions,
375
422
  runtime: GoogleVertexProjectRuntime = defaultProjectRuntime,
@@ -380,6 +427,9 @@ export async function resolveGoogleVertexProject(
380
427
  const adcProject = await runtime.readAdcProject();
381
428
  if (adcProject) return adcProject;
382
429
 
430
+ const localConfigProject = await runtime.readLocalConfigProject?.();
431
+ if (localConfigProject) return localConfigProject;
432
+
383
433
  const gcloud = runtime.findGcloud();
384
434
  if (gcloud) {
385
435
  const configuredProject = await runtime.readConfiguredProject(gcloud);