kopia lustrzana https://github.com/transitive-bullshit/chatgpt-api
feat: add getEnv function
rodzic
d8fb25f9c2
commit
bbe66bd6fa
44
.eslintrc
44
.eslintrc
|
@ -1,13 +1,7 @@
|
|||
{
|
||||
"parser": "@typescript-eslint/parser",
|
||||
"extends": [
|
||||
"eslint:recommended",
|
||||
"plugin:@typescript-eslint/recommended"
|
||||
],
|
||||
"plugins": [
|
||||
"@typescript-eslint",
|
||||
"eslint-plugin-tsdoc"
|
||||
],
|
||||
"extends": ["eslint:recommended", "plugin:@typescript-eslint/recommended"],
|
||||
"plugins": ["@typescript-eslint", "eslint-plugin-tsdoc"],
|
||||
"root": true,
|
||||
"env": {
|
||||
"browser": false,
|
||||
|
@ -38,47 +32,39 @@
|
|||
"error",
|
||||
{
|
||||
"blankLine": "always",
|
||||
"prev": [
|
||||
"block",
|
||||
"block-like"
|
||||
],
|
||||
"prev": ["block", "block-like"],
|
||||
"next": "*"
|
||||
},
|
||||
{
|
||||
"blankLine": "always",
|
||||
"prev": "*",
|
||||
"next": [
|
||||
"block",
|
||||
"block-like"
|
||||
]
|
||||
"next": ["block", "block-like"]
|
||||
},
|
||||
{
|
||||
"blankLine": "any",
|
||||
"prev": [
|
||||
"singleline-const",
|
||||
"singleline-let",
|
||||
"expression"
|
||||
],
|
||||
"next": [
|
||||
"block",
|
||||
"block-like"
|
||||
]
|
||||
"prev": ["singleline-const", "singleline-let", "expression"],
|
||||
"next": ["block", "block-like"]
|
||||
}
|
||||
],
|
||||
"tsdoc/syntax": "warn"
|
||||
},
|
||||
"overrides": [
|
||||
{
|
||||
"files": [
|
||||
"*.tsx"
|
||||
],
|
||||
"files": ["*.tsx"],
|
||||
"rules": {
|
||||
"no-undef": "off"
|
||||
}
|
||||
},
|
||||
{
|
||||
// disable process.env for framework source files
|
||||
"files": "src/**/*.ts",
|
||||
"rules": {
|
||||
"no-process-env": "error"
|
||||
}
|
||||
}
|
||||
],
|
||||
"settings": {},
|
||||
"globals": {
|
||||
"__DEV__": true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,7 +10,6 @@ import { defaultLogger } from './logger'
|
|||
import { defaultIDGeneratorFn, isFunction, isString } from './utils'
|
||||
|
||||
export class Agentic {
|
||||
// _taskMap: WeakMap<string, BaseTask<any, any>>
|
||||
protected _ky: types.KyInstance
|
||||
protected _logger: types.Logger
|
||||
|
||||
|
@ -103,7 +102,7 @@ export class Agentic {
|
|||
return this._idGeneratorFn
|
||||
}
|
||||
|
||||
openaiChatCompletion<TInput extends types.TaskInput = any>(
|
||||
openaiChatCompletion<TInput extends types.TaskInput = void>(
|
||||
promptOrChatCompletionParams:
|
||||
| types.ChatMessageContent<TInput>
|
||||
| SetOptional<types.OpenAIChatCompletionParamsInput<TInput>, 'model'>,
|
||||
|
@ -148,7 +147,7 @@ export class Agentic {
|
|||
/**
|
||||
* Shortcut for creating an OpenAI chat completion call with the `gpt-3.5-turbo` model.
|
||||
*/
|
||||
gpt3<TInput extends types.TaskInput = any>(
|
||||
gpt3<TInput extends types.TaskInput = void>(
|
||||
promptOrChatCompletionParams:
|
||||
| types.ChatMessageContent<TInput>
|
||||
| SetOptional<types.OpenAIChatCompletionParamsInput<TInput>, 'model'>,
|
||||
|
@ -194,7 +193,7 @@ export class Agentic {
|
|||
/**
|
||||
* Shortcut for creating an OpenAI chat completion call with the `gpt-4` model.
|
||||
*/
|
||||
gpt4<TInput extends types.TaskInput = any>(
|
||||
gpt4<TInput extends types.TaskInput = void>(
|
||||
promptOrChatCompletionParams:
|
||||
| types.ChatMessageContent<TInput>
|
||||
| SetOptional<types.OpenAIChatCompletionParamsInput<TInput>, 'model'>,
|
||||
|
|
|
@ -0,0 +1,15 @@
|
|||
export function getEnv(
|
||||
name: string,
|
||||
defaultValue?: string
|
||||
): string | undefined {
|
||||
try {
|
||||
return (
|
||||
(typeof process !== 'undefined'
|
||||
? // eslint-disable-next-line no-process-env
|
||||
process.env?.[name]
|
||||
: undefined) ?? defaultValue
|
||||
)
|
||||
} catch (e) {
|
||||
return defaultValue
|
||||
}
|
||||
}
|
|
@ -1,6 +1,8 @@
|
|||
import { pino } from 'pino'
|
||||
import pinoPretty from 'pino-pretty'
|
||||
|
||||
import { getEnv } from './env'
|
||||
|
||||
export type Level = 'fatal' | 'error' | 'warn' | 'info' | 'debug' | 'trace'
|
||||
export type LevelWithSilent = Level | 'silent'
|
||||
|
||||
|
@ -103,7 +105,7 @@ export interface Logger {
|
|||
|
||||
export const defaultLogger: Logger = pino(
|
||||
{
|
||||
level: process.env.LOG_LEVEL || 'info'
|
||||
level: getEnv('LOG_LEVEL', 'info')
|
||||
},
|
||||
pinoPretty({
|
||||
sync: true,
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
import logger from 'debug'
|
||||
import { v4 as uuidv4 } from 'uuid'
|
||||
|
||||
import { getEnv } from './env'
|
||||
|
||||
/**
|
||||
* List of events that can occur within the library.
|
||||
*/
|
||||
|
@ -26,14 +28,12 @@ type SeverityType = (typeof Severity)[keyof typeof Severity]
|
|||
* Define minimum LOG_LEVEL, defaulting to Severity.INFO if not provided or if an invalid value is provided. Any events below that level won't be logged to the console.
|
||||
*/
|
||||
let LOG_LEVEL: SeverityType = Severity.INFO
|
||||
const logLevelEnv = getEnv('DEBUG_LOG_LEVEL')
|
||||
|
||||
if (
|
||||
process.env.DEBUG_LOG_LEVEL &&
|
||||
Severity[process.env.DEBUG_LOG_LEVEL.toUpperCase()] !== undefined
|
||||
) {
|
||||
LOG_LEVEL = Severity[process.env.DEBUG_LOG_LEVEL.toUpperCase()]
|
||||
} else if (process.env.DEBUG_LOG_LEVEL) {
|
||||
throw new Error(`Invalid value for LOG_LEVEL: ${process.env.DEBUG_LOG_LEVEL}`)
|
||||
if (logLevelEnv && Severity[logLevelEnv.toUpperCase()] !== undefined) {
|
||||
LOG_LEVEL = Severity[logLevelEnv.toUpperCase()]
|
||||
} else if (logLevelEnv) {
|
||||
throw new Error(`Invalid value for LOG_LEVEL: ${logLevelEnv}`)
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
import defaultKy from 'ky'
|
||||
|
||||
import { getEnv } from '@/env'
|
||||
|
||||
export const BING_API_BASE_URL = 'https://api.bing.microsoft.com'
|
||||
|
||||
export interface BingWebSearchQuery {
|
||||
|
@ -241,7 +243,7 @@ export class BingWebSearchClient {
|
|||
apiBaseUrl: string
|
||||
|
||||
constructor({
|
||||
apiKey = process.env.BING_API_KEY,
|
||||
apiKey = getEnv('BING_API_KEY'),
|
||||
apiBaseUrl = BING_API_BASE_URL,
|
||||
ky = defaultKy
|
||||
}: {
|
||||
|
|
|
@ -2,6 +2,7 @@ import defaultKy from 'ky'
|
|||
import { AbortError } from 'p-retry'
|
||||
import pThrottle from 'p-throttle'
|
||||
|
||||
import { getEnv } from '@/env'
|
||||
import { throttleKy } from '@/utils'
|
||||
|
||||
export const DIFFBOT_API_BASE_URL = 'https://api.diffbot.com'
|
||||
|
@ -334,7 +335,7 @@ export class DiffbotClient {
|
|||
apiKnowledgeGraphBaseUrl: string
|
||||
|
||||
constructor({
|
||||
apiKey = process.env.DIFFBOT_API_KEY,
|
||||
apiKey = getEnv('DIFFBOT_API_KEY'),
|
||||
apiBaseUrl = DIFFBOT_API_BASE_URL,
|
||||
apiKnowledgeGraphBaseUrl = DIFFBOT_KNOWLEDGE_GRAPH_API_BASE_URL,
|
||||
timeoutMs = 30_000,
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
import defaultKy from 'ky'
|
||||
|
||||
import { getEnv } from '@/env'
|
||||
|
||||
export const METAPHOR_API_BASE_URL = 'https://api.metaphor.systems'
|
||||
|
||||
/**
|
||||
|
@ -119,7 +121,7 @@ export class MetaphorClient {
|
|||
readonly apiBaseUrl: string
|
||||
|
||||
constructor({
|
||||
apiKey = process.env.METAPHOR_API_KEY,
|
||||
apiKey = getEnv('METAPHOR_API_KEY'),
|
||||
apiBaseUrl = METAPHOR_API_BASE_URL,
|
||||
ky = defaultKy
|
||||
}: {
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
import defaultKy from 'ky'
|
||||
|
||||
import { getEnv } from '@/env'
|
||||
|
||||
/**
|
||||
* Base URL endpoint for the Novu API.
|
||||
*/
|
||||
|
@ -110,7 +112,7 @@ export class NovuClient {
|
|||
* Novu API client constructor.
|
||||
*/
|
||||
constructor({
|
||||
apiKey = process.env.NOVU_API_KEY,
|
||||
apiKey = getEnv('NOVU_API_KEY'),
|
||||
apiBaseUrl = NOVU_API_BASE_URL,
|
||||
ky = defaultKy
|
||||
}: {
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
import defaultKy from 'ky'
|
||||
|
||||
import { getEnv } from '@/env'
|
||||
|
||||
/**
|
||||
* All types have been exported from the `serpapi` package, which we're
|
||||
* not using directly because it is bloated and has compatibility issues.
|
||||
|
@ -642,7 +644,7 @@ export class SerpAPIClient {
|
|||
params: Partial<SerpAPIParams>
|
||||
|
||||
constructor({
|
||||
apiKey = process.env.SERPAPI_API_KEY ?? process.env.SERP_API_KEY,
|
||||
apiKey = getEnv('SERPAPI_API_KEY') ?? getEnv('SERP_API_KEY'),
|
||||
apiBaseUrl = SERPAPI_BASE_URL,
|
||||
ky = defaultKy,
|
||||
...params
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import defaultKy from 'ky'
|
||||
|
||||
import { getEnv } from '@/env'
|
||||
import { sleep } from '@/utils'
|
||||
|
||||
export const SLACK_API_BASE_URL = 'https://slack.com/api'
|
||||
|
@ -261,9 +262,9 @@ export class SlackClient {
|
|||
protected defaultChannel?: string
|
||||
|
||||
constructor({
|
||||
apiKey = process.env.SLACK_API_KEY,
|
||||
apiKey = getEnv('SLACK_API_KEY'),
|
||||
baseUrl = SLACK_API_BASE_URL,
|
||||
defaultChannel = process.env.SLACK_DEFAULT_CHANNEL,
|
||||
defaultChannel = getEnv('SLACK_DEFAULT_CHANNEL'),
|
||||
ky = defaultKy
|
||||
}: {
|
||||
apiKey?: string
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import defaultKy from 'ky'
|
||||
|
||||
import { DEFAULT_BOT_NAME } from '@/constants'
|
||||
import { getEnv } from '@/env'
|
||||
import { chunkMultipleStrings, chunkString, sleep } from '@/utils'
|
||||
|
||||
export const TWILIO_CONVERSATION_API_BASE_URL =
|
||||
|
@ -208,11 +209,12 @@ export class TwilioConversationClient {
|
|||
defaultRecipientPhoneNumber?: string
|
||||
|
||||
constructor({
|
||||
accountSid = process.env.TWILIO_ACCOUNT_SID,
|
||||
authToken = process.env.TWILIO_AUTH_TOKEN,
|
||||
phoneNumber = process.env.TWILIO_PHONE_NUMBER,
|
||||
defaultRecipientPhoneNumber = process.env
|
||||
.TWILIO_DEFAULT_RECIPIENT_PHONE_NUMBER,
|
||||
accountSid = getEnv('TWILIO_ACCOUNT_SID'),
|
||||
authToken = getEnv('TWILIO_AUTH_TOKEN'),
|
||||
phoneNumber = getEnv('TWILIO_PHONE_NUMBER'),
|
||||
defaultRecipientPhoneNumber = getEnv(
|
||||
'TWILIO_DEFAULT_RECIPIENT_PHONE_NUMBER'
|
||||
),
|
||||
apiBaseUrl = TWILIO_CONVERSATION_API_BASE_URL,
|
||||
botName = DEFAULT_BOT_NAME,
|
||||
ky = defaultKy
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
import defaultKy from 'ky'
|
||||
|
||||
import { getEnv } from '@/env'
|
||||
|
||||
export const WEATHER_API_BASE_URL = 'https://api.weatherapi.com/v1'
|
||||
|
||||
interface CurrentWeatherResponse {
|
||||
|
@ -75,7 +77,7 @@ export class WeatherClient {
|
|||
apiBaseUrl: string
|
||||
|
||||
constructor({
|
||||
apiKey = process.env.WEATHER_API_KEY,
|
||||
apiKey = getEnv('WEATHER_API_KEY'),
|
||||
apiBaseUrl = WEATHER_API_BASE_URL,
|
||||
ky = defaultKy
|
||||
}: {
|
||||
|
|
|
@ -18,8 +18,8 @@ import { defaultIDGeneratorFn, isValidTaskIdentifier } from './utils'
|
|||
*
|
||||
* Examples of tasks include:
|
||||
* - LLM calls
|
||||
* - Chain of LLM calls
|
||||
* - Retrieval task
|
||||
* - Chains of LLM calls
|
||||
* - Retrieval tasks
|
||||
* - API calls
|
||||
* - Native function calls
|
||||
* - Invoking sub-agents
|
||||
|
@ -94,6 +94,10 @@ export abstract class BaseTask<
|
|||
return this
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensures that this task is configured correctly. `validate` will be called
|
||||
* automatically before `task.call` or `task.callWithMetadata` are invoked.
|
||||
*/
|
||||
public validate() {
|
||||
if (!this._agentic) {
|
||||
throw new Error(
|
||||
|
@ -241,6 +245,7 @@ export abstract class BaseTask<
|
|||
(err as any).name === 'TimeoutError'
|
||||
) {
|
||||
// TODO
|
||||
return
|
||||
} else if ((err.cause as any)?.code === 'UND_ERR_HEADERS_TIMEOUT') {
|
||||
// TODO: This is a pretty common OpenAI error, and I think it either has
|
||||
// to do with OpenAI's servers being flaky or the combination of Node.js
|
||||
|
|
Ładowanie…
Reference in New Issue