@f5-sales-demo/pi-ai 20.14.0 → 20.15.2

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": "20.14.0",
4
+ "version": "20.15.2",
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.14.0",
49
+ "@f5-sales-demo/pi-utils": "20.15.2",
50
50
  "@google/genai": "^2.15",
51
51
  "@sinclair/typebox": "^0.34",
52
52
  "@smithy/node-http-handler": "^4.4",
@@ -69,6 +69,10 @@ const ANTIGRAVITY_VERTEX_MODELS: Readonly<Record<string, string>> = Object.freez
69
69
  "gemini-3.1-pro-high-vertex": "gemini-3.1-pro-preview",
70
70
  });
71
71
 
72
+ export function resolveAntigravityServingModelId(requestedModelId: string): string {
73
+ return ANTIGRAVITY_VERTEX_MODELS[requestedModelId] ?? requestedModelId;
74
+ }
75
+
72
76
  /**
73
77
  * Build a User-Agent string that identifies as Gemini CLI to unlock higher rate limits.
74
78
  * Uses the same format as the official Gemini CLI (v0.35+):
@@ -477,6 +481,7 @@ export const streamGoogleGeminiCli: StreamFunction<"google-gemini-cli"> = (
477
481
  api: "google-gemini-cli" as Api,
478
482
  provider: model.provider,
479
483
  model: model.id,
484
+ responseAttribution: { requestedModel: model.id },
480
485
  usage: {
481
486
  input: 0,
482
487
  output: 0,
@@ -687,6 +692,14 @@ export const streamGoogleGeminiCli: StreamFunction<"google-gemini-cli"> = (
687
692
  options?.signal,
688
693
  )) {
689
694
  const responseData = chunk.response ?? chunk;
695
+ if (responseData.modelVersion) {
696
+ output.responseAttribution = {
697
+ ...(output.responseAttribution ?? { requestedModel: model.id }),
698
+ responseModel: responseData.modelVersion,
699
+ responseModelSource: "response-body",
700
+ };
701
+ }
702
+ if (responseData.responseId) output.responseId = responseData.responseId;
690
703
 
691
704
  const candidate = responseData.candidates?.[0];
692
705
  if (candidate?.content?.parts) {
@@ -385,6 +385,7 @@ function createAssistantOutput(model: Model<"openai-codex-responses">): Assistan
385
385
  api: "openai-codex-responses" as Api,
386
386
  provider: model.provider,
387
387
  model: model.id,
388
+ responseAttribution: { requestedModel: model.id },
388
389
  usage: createEmptyUsage(),
389
390
  stopReason: "stop",
390
391
  timestamp: Date.now(),
@@ -816,7 +817,8 @@ function handleCodexStreamEvent(args: {
816
817
  }
817
818
 
818
819
  if (eventType === "response.created") {
819
- return handleResponseCreated(runtime, rawEvent);
820
+ handleResponseCreated(model, output, runtime, rawEvent);
821
+ return firstTokenTime;
820
822
  }
821
823
 
822
824
  if (eventType === "response.completed" || eventType === "response.done" || eventType === "response.incomplete") {
@@ -1011,13 +1013,27 @@ function handleOutputItemDone(
1011
1013
  void model;
1012
1014
  }
1013
1015
 
1014
- function handleResponseCreated(runtime: CodexStreamRuntime, rawEvent: Record<string, unknown>): number | undefined {
1015
- const response = (rawEvent as { response?: { id?: string } }).response;
1016
+ function handleResponseCreated(
1017
+ model: Model<"openai-codex-responses">,
1018
+ output: AssistantMessage,
1019
+ runtime: CodexStreamRuntime,
1020
+ rawEvent: Record<string, unknown>,
1021
+ ): void {
1022
+ const response = (rawEvent as { response?: { id?: string; model?: string } }).response;
1023
+ if (typeof response?.id === "string" && response.id.length > 0) {
1024
+ output.responseId = response.id;
1025
+ }
1026
+ if (typeof response?.model === "string" && response.model.length > 0) {
1027
+ output.responseAttribution = {
1028
+ ...(output.responseAttribution ?? { requestedModel: model.id }),
1029
+ responseModel: response.model,
1030
+ responseModelSource: "response-body",
1031
+ };
1032
+ }
1016
1033
  const state = runtime.websocketState;
1017
1034
  if (runtime.transport === "websocket" && state && typeof response?.id === "string" && response.id.length > 0) {
1018
1035
  state.lastResponseId = response.id;
1019
1036
  }
1020
- return undefined;
1021
1037
  }
1022
1038
 
1023
1039
  function handleResponseCompleted(
@@ -1038,6 +1054,7 @@ function handleResponseCompleted(
1038
1054
  input_tokens_details?: { cached_tokens?: number };
1039
1055
  };
1040
1056
  status?: string;
1057
+ model?: string;
1041
1058
  };
1042
1059
  }
1043
1060
  ).response;
@@ -1056,6 +1073,13 @@ function handleResponseCompleted(
1056
1073
  if (typeof response?.id === "string" && response.id.length > 0) {
1057
1074
  output.responseId = response.id;
1058
1075
  }
1076
+ if (typeof response?.model === "string" && response.model.length > 0) {
1077
+ output.responseAttribution = {
1078
+ ...(output.responseAttribution ?? { requestedModel: model.id }),
1079
+ responseModel: response.model,
1080
+ responseModelSource: "response-body",
1081
+ };
1082
+ }
1059
1083
 
1060
1084
  const state = runtime.websocketState;
1061
1085
  if (runtime.transport === "websocket" && state) {
@@ -355,6 +355,8 @@ function getValueAtPointer(root: unknown, pointer: string): unknown {
355
355
  function setValueAtPointer(root: unknown, pointer: string, value: unknown): unknown {
356
356
  if (!pointer) return value;
357
357
  const segments = decodeJsonPointer(pointer);
358
+ const unsafeSegments = new Set(["__proto__", "constructor", "prototype"]);
359
+ if (segments.some(segment => segment.length === 0 || unsafeSegments.has(segment))) return root;
358
360
  let current: unknown = root;
359
361
 
360
362
  // Navigate to the parent of the target location
@@ -363,25 +365,32 @@ function setValueAtPointer(root: unknown, pointer: string, value: unknown): unkn
363
365
  if (current === null || current === undefined) return root;
364
366
  if (Array.isArray(current)) {
365
367
  const arrayIndex = Number(segment);
366
- if (!Number.isInteger(arrayIndex)) return root;
368
+ if (!Number.isInteger(arrayIndex) || arrayIndex < 0 || arrayIndex >= current.length) return root;
367
369
  current = current[arrayIndex];
368
370
  continue;
369
371
  }
370
372
  if (typeof current !== "object") return root;
371
- current = (current as Record<string, unknown>)[segment];
373
+ const record = current as Record<string, unknown>;
374
+ if (!Object.hasOwn(record, segment)) return root;
375
+ current = record[segment];
372
376
  }
373
377
 
374
378
  // Set the value at the final segment
375
379
  const lastSegment = segments[segments.length - 1];
376
380
  if (Array.isArray(current)) {
377
381
  const arrayIndex = Number(lastSegment);
378
- if (!Number.isInteger(arrayIndex)) return root;
379
- current[arrayIndex] = value;
382
+ if (!Number.isInteger(arrayIndex) || arrayIndex < 0 || arrayIndex >= current.length) return root;
383
+ Reflect.set(current, arrayIndex, value);
380
384
  return root;
381
385
  }
382
386
 
383
387
  if (typeof current !== "object" || current === null) return root;
384
- (current as Record<string, unknown>)[lastSegment] = value;
388
+ Object.defineProperty(current, lastSegment, {
389
+ configurable: true,
390
+ enumerable: true,
391
+ value,
392
+ writable: true,
393
+ });
385
394
  return root;
386
395
  }
387
396
 
@@ -559,7 +568,7 @@ function coerceArgsFromErrors(
559
568
  // Silent logger: MCP servers may declare non-standard format keywords (e.g. "uint")
560
569
  // which cause Ajv to emit console.warn() with strict:false — corrupting TUI output.
561
570
  const ajv = new Ajv({
562
- allErrors: true,
571
+ allErrors: false,
563
572
  strict: false,
564
573
  logger: false,
565
574
  });