File size: 2,921 Bytes
c7052c4
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
import {
  ANTHROPIC,
  COHERE,
  GOOGLE,
  GOOGLE_VERTEX_AI,
  PERPLEXITY_AI,
  DEEPINFRA,
  SAMBANOVA,
} from './globals';
import { Environment } from './utils/env';

export const getStreamModeSplitPattern = (proxyProvider: string, requestURL: string) => {
  let splitPattern: SplitPatternType = '\n\n';

  if (proxyProvider === ANTHROPIC && requestURL.endsWith('/complete')) {
    splitPattern = '\r\n\r\n';
  }

  if (proxyProvider === COHERE) {
    splitPattern = requestURL.includes('/chat') ? '\n\n' : '\n';
  }

  if (proxyProvider === GOOGLE) {
    splitPattern = '\r\n';
  }

  // In Vertex Anthropic and LLama have \n\n as the pattern only Gemini has \r\n\r\n
  if (proxyProvider === GOOGLE_VERTEX_AI && requestURL.includes('/publishers/google')) {
    splitPattern = '\r\n\r\n';
  }

  if (proxyProvider === PERPLEXITY_AI) {
    splitPattern = '\r\n\r\n';
  }

  if (proxyProvider === DEEPINFRA) {
    splitPattern = '\n';
  }

  if (proxyProvider === SAMBANOVA) {
    splitPattern = '\n';
  }

  return splitPattern;
};
export type SplitPatternType = '\n\n' | '\r\n\r\n' | '\n' | '\r\n';

export function convertKeysToCamelCase(
  obj: Record<string, any>,
  parentKeysToPreserve: string[] = [],
): Record<string, any> {
  if (typeof obj !== 'object' || obj === null) {
    return obj; // Return unchanged for non-objects or null
  }

  if (Array.isArray(obj)) {
    // If it's an array, recursively convert each element
    return obj.map((item) => convertKeysToCamelCase(item, parentKeysToPreserve));
  }

  return Object.keys(obj).reduce((result: any, key: string) => {
    const value = obj[key];
    const camelCaseKey = toCamelCase(key);
    const isParentKeyToPreserve = parentKeysToPreserve.includes(key);
    if (typeof value === 'object' && !isParentKeyToPreserve) {
      // Recursively convert child objects
      result[camelCaseKey] = convertKeysToCamelCase(value, parentKeysToPreserve);
    } else {
      // Add key in camelCase to the result
      result[camelCaseKey] = value;
    }

    return result;
  }, {});

  function toCamelCase(snakeCase: string): string {
    return snakeCase.replace(/(_\w)/g, (match) => match[1].toUpperCase());
  }
}

export const parseStringToArray = (value?: string) => {
  if (!value) {
    return [];
  }
  const parts = value.split(',').map((val) => val.trim());
  return parts;
};

export const getCORSValues = () => {
  const isCorsEnabled = Environment({}).ENABLE_CORS === 'true';

  const allowedOrigins = parseStringToArray(Environment({}).CORS_ALLOWED_ORIGINS);
  const allowedMethods = parseStringToArray(Environment({}).CORS_ALLOWED_METHODS);
  const allowedHeaders = parseStringToArray(Environment({}).CORS_ALLOWED_HEADERS);
  const allowedExposeHeaders = parseStringToArray(Environment({}).CORS_ALLOWED_EXPOSE_HEADERS);

  return {
    allowedOrigins,
    allowedMethods,
    allowedHeaders,
    allowedExposeHeaders,
    isCorsEnabled,
  };
};