From cc764efbfacccf08b48bcca7ef34f5a1e795d1ca Mon Sep 17 00:00:00 2001 From: Johhan Santana Date: Mon, 25 Nov 2024 12:42:26 -0400 Subject: [PATCH] =?UTF-8?q?=F0=9F=9A=80=20feat(cli):=20add=20support=20for?= =?UTF-8?q?=20multiple=20AI=20providers=20with=20dynamic=20API=20key=20ret?= =?UTF-8?q?rieval?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This update introduces the ability to select between OpenAI and OpenRouter as AI providers. The user is prompted to enter their API key based on the selected provider. Additionally, the model path can be specified for OpenRouter, enhancing flexibility in AI interactions. --- bun.lockb | Bin 293725 -> 293888 bytes src/cli.ts | 101 ++++++++++++++++++++++++++++++++++++----------------- 2 files changed, 68 insertions(+), 33 deletions(-) diff --git a/bun.lockb b/bun.lockb index 36aa13750f86d6ce9cc5cde23021c4a50bf92a3f..ef55d4265b539acfe9decdf6c60c9bd8c23f644f 100755 GIT binary patch delta 29245 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 diff --git a/src/cli.ts b/src/cli.ts index 40f94e9..74d7768 100755 --- a/src/cli.ts +++ b/src/cli.ts @@ -46,38 +46,73 @@ console.log( console.log() -const OPENAI_API_KEY = - process.env.OPENAI_API_KEY || - ((await text({ - message: dedent` - Please provide your OpenAI API key. - - To skip this message, set ${chalk.bold('OPENAI_API_KEY')} env variable, and run again. - - You can do it in three ways: - - by creating an ${chalk.bold('.env.local')} file (make sure to ${chalk.bold('.gitignore')} it) - ${chalk.gray(`\`\`\` - OPENAI_API_KEY= - \`\`\` - `)} - - by passing it inline: - ${chalk.gray(`\`\`\` - OPENAI_API_KEY= npx cali - \`\`\` - `)} - - by setting it as an env variable in your shell (e.g. in ~/.zshrc or ~/.bashrc): - ${chalk.gray(`\`\`\` - export OPENAI_API_KEY= - \`\`\` - `)} - `, - })) as string) - -const AI_MODEL = process.env.AI_MODEL || 'gpt-4o' - -const openai = createOpenAI({ - apiKey: OPENAI_API_KEY, -}) +const PROVIDER = (await select({ + message: 'Select your AI provider:', + options: [ + { value: 'openai', label: 'OpenAI' }, + { value: 'openrouter', label: 'OpenRouter' }, + ], +})) as string + +let apiKey: string +let model: string +let client: ReturnType + +if (PROVIDER === 'openai') { + apiKey = + process.env.OPENAI_API_KEY || + ((await text({ + message: dedent` + Please provide your OpenAI API key. + + To skip this message, set ${chalk.bold('OPENAI_API_KEY')} env variable, and run again. + + You can do it in three ways: + - by creating an ${chalk.bold('.env.local')} file (make sure to ${chalk.bold('.gitignore')} it) + ${chalk.gray(`\`\`\` + OPENAI_API_KEY= + \`\`\` + `)} + - by passing it inline: + ${chalk.gray(`\`\`\` + OPENAI_API_KEY= npx cali + \`\`\` + `)} + - by setting it as an env variable in your shell (e.g. in ~/.zshrc or ~/.bashrc): + ${chalk.gray(`\`\`\` + export OPENAI_API_KEY= + \`\`\` + `)} + `, + })) as string) + + model = process.env.AI_MODEL || 'gpt-4' + + client = createOpenAI({ + apiKey, + }) +} else { + apiKey = + process.env.OPENROUTER_API_KEY || + ((await text({ + message: 'Please provide your OpenRouter API key:', + })) as string) + + const modelPath = (await text({ + message: 'Enter the model path (e.g., anthropic/claude-3-sonnet):', + })) as string + + model = modelPath + + client = createOpenAI({ + apiKey, + baseURL: 'https://openrouter.ai/api/v1', + headers: { + 'HTTP-Referer': 'https://github.com/callstackincubator/cali', + 'X-Title': 'Cali - React Native AI Agent', + }, + }) +} const question = (await text({ message: 'What do you want to do today?', @@ -108,7 +143,7 @@ while (true) { s.start(chalk.gray('Thinking...')) const response = await generateText({ - model: openai(AI_MODEL), + model: client(model), system: reactNativePrompt, tools, maxSteps: 10,