Fix linting issues

This commit is contained in:
Oliver Jägle 2024-11-21 22:27:29 +01:00
parent fe3e2ebddf
commit 7d8f811886
No known key found for this signature in database
GPG Key ID: 866E2BD1777473E9
11 changed files with 65 additions and 46 deletions

View File

@ -10,6 +10,7 @@ interface APIKeyManagerProps {
labelForGetApiKey?: string;
}
// eslint-disable-next-line @typescript-eslint/naming-convention
export const APIKeyManager: React.FC<APIKeyManagerProps> = ({ provider, apiKey, setApiKey }) => {
const [isEditing, setIsEditing] = useState(false);
const [tempKey, setTempKey] = useState(apiKey);

View File

@ -9,7 +9,7 @@ import { Menu } from '~/components/sidebar/Menu.client';
import { IconButton } from '~/components/ui/IconButton';
import { Workbench } from '~/components/workbench/Workbench.client';
import { classNames } from '~/utils/classNames';
import { MODEL_LIST, DEFAULT_PROVIDER, PROVIDER_LIST, initializeModelList } from '~/utils/constants';
import { MODEL_LIST, PROVIDER_LIST, initializeModelList } from '~/utils/constants';
import { Messages } from './Messages.client';
import { SendButton } from './SendButton.client';
import { useState } from 'react';
@ -27,22 +27,25 @@ const EXAMPLE_PROMPTS = [
{ text: 'How do I center a div?' },
];
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const providerList = PROVIDER_LIST;
// @ts-ignore TODO: Introduce proper types
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const ModelSelector = ({ model, setModel, provider, setProvider, modelList, providerList, apiKeys }) => {
return (
<div className="mb-2 flex gap-2 flex-col sm:flex-row">
<select
value={provider?.name}
onChange={(e) => {
setProvider(providerList.find((p) => p.name === e.target.value));
setProvider(providerList.find((p: ProviderInfo) => p.name === e.target.value));
const firstModel = [...modelList].find((m) => m.provider == e.target.value);
setModel(firstModel ? firstModel.name : '');
}}
className="flex-1 p-2 rounded-lg border border-bolt-elements-borderColor bg-bolt-elements-prompt-background text-bolt-elements-textPrimary focus:outline-none focus:ring-2 focus:ring-bolt-elements-focus transition-all"
>
{providerList.map((provider) => (
{providerList.map((provider: ProviderInfo) => (
<option key={provider.name} value={provider.name}>
{provider.name}
</option>

View File

@ -2,7 +2,6 @@ import { motion, type Variants } from 'framer-motion';
import { useCallback, useEffect, useRef, useState } from 'react';
import { toast } from 'react-toastify';
import { Dialog, DialogButton, DialogDescription, DialogRoot, DialogTitle } from '~/components/ui/Dialog';
import { IconButton } from '~/components/ui/IconButton';
import { ThemeSwitch } from '~/components/ui/ThemeSwitch';
import { db, deleteById, getAll, chatId, type ChatHistoryItem, useChatHistory } from '~/lib/persistence';
import { cubicEasingFn } from '~/utils/easings';

View File

@ -52,7 +52,7 @@ export function getBaseURL(cloudflareEnv: Env, provider: string) {
return env.OPENAI_LIKE_API_BASE_URL || cloudflareEnv.OPENAI_LIKE_API_BASE_URL;
case 'LMStudio':
return env.LMSTUDIO_API_BASE_URL || cloudflareEnv.LMSTUDIO_API_BASE_URL || 'http://localhost:1234';
case 'Ollama':
case 'Ollama': {
let baseUrl = env.OLLAMA_API_BASE_URL || cloudflareEnv.OLLAMA_API_BASE_URL || 'http://localhost:11434';
if (env.RUNNING_IN_DOCKER === 'true') {
@ -60,6 +60,7 @@ export function getBaseURL(cloudflareEnv: Env, provider: string) {
}
return baseUrl;
}
default:
return '';
}

View File

@ -11,14 +11,14 @@ import { createOpenRouter } from '@openrouter/ai-sdk-provider';
import { createMistral } from '@ai-sdk/mistral';
import { createCohere } from '@ai-sdk/cohere';
export function getAnthropicModel(apiKey: string, model: string) {
export function getAnthropicModel(apiKey: string | undefined, model: string) {
const anthropic = createAnthropic({
apiKey,
});
return anthropic(model);
}
export function getOpenAILikeModel(baseURL: string, apiKey: string, model: string) {
export function getOpenAILikeModel(baseURL: string, apiKey: string | undefined, model: string) {
const openai = createOpenAI({
baseURL,
apiKey,
@ -27,7 +27,7 @@ export function getOpenAILikeModel(baseURL: string, apiKey: string, model: strin
return openai(model);
}
export function getCohereAIModel(apiKey: string, model: string) {
export function getCohereAIModel(apiKey: string | undefined, model: string) {
const cohere = createCohere({
apiKey,
});
@ -35,7 +35,7 @@ export function getCohereAIModel(apiKey: string, model: string) {
return cohere(model);
}
export function getOpenAIModel(apiKey: string, model: string) {
export function getOpenAIModel(apiKey: string | undefined, model: string) {
const openai = createOpenAI({
apiKey,
});
@ -43,7 +43,7 @@ export function getOpenAIModel(apiKey: string, model: string) {
return openai(model);
}
export function getMistralModel(apiKey: string, model: string) {
export function getMistralModel(apiKey: string | undefined, model: string) {
const mistral = createMistral({
apiKey,
});
@ -51,7 +51,7 @@ export function getMistralModel(apiKey: string, model: string) {
return mistral(model);
}
export function getGoogleModel(apiKey: string, model: string) {
export function getGoogleModel(apiKey: string | undefined, model: string) {
const google = createGoogleGenerativeAI({
apiKey,
});
@ -59,7 +59,7 @@ export function getGoogleModel(apiKey: string, model: string) {
return google(model);
}
export function getGroqModel(apiKey: string, model: string) {
export function getGroqModel(apiKey: string | undefined, model: string) {
const openai = createOpenAI({
baseURL: 'https://api.groq.com/openai/v1',
apiKey,
@ -68,7 +68,7 @@ export function getGroqModel(apiKey: string, model: string) {
return openai(model);
}
export function getHuggingFaceModel(apiKey: string, model: string) {
export function getHuggingFaceModel(apiKey: string | undefined, model: string) {
const openai = createOpenAI({
baseURL: 'https://api-inference.huggingface.co/v1/',
apiKey,
@ -78,16 +78,16 @@ export function getHuggingFaceModel(apiKey: string, model: string) {
}
export function getOllamaModel(baseURL: string, model: string) {
const Ollama = ollama(model, {
const ollamaInstance = ollama(model, {
numCtx: 32768,
});
Ollama.config.baseURL = `${baseURL}/api`;
ollamaInstance.config.baseURL = `${baseURL}/api`;
return Ollama;
return ollamaInstance;
}
export function getDeepseekModel(apiKey: string, model: string) {
export function getDeepseekModel(apiKey: string | undefined, model: string) {
const openai = createOpenAI({
baseURL: 'https://api.deepseek.com/beta',
apiKey,
@ -96,7 +96,7 @@ export function getDeepseekModel(apiKey: string, model: string) {
return openai(model);
}
export function getOpenRouterModel(apiKey: string, model: string) {
export function getOpenRouterModel(apiKey: string | undefined, model: string) {
const openRouter = createOpenRouter({
apiKey,
});
@ -113,7 +113,7 @@ export function getLMStudioModel(baseURL: string, model: string) {
return lmstudio(model);
}
export function getXAIModel(apiKey: string, model: string) {
export function getXAIModel(apiKey: string | undefined, model: string) {
const openai = createOpenAI({
baseURL: 'https://api.x.ai/v1',
apiKey,

View File

@ -110,6 +110,7 @@ export function useChatHistory() {
toast.success('Chat duplicated successfully');
} catch (error) {
toast.error('Failed to duplicate chat');
console.log(error);
}
},
};

View File

@ -1,11 +1,10 @@
import { WebContainer, type WebContainerProcess } from '@webcontainer/api';
import { WebContainer } from '@webcontainer/api';
import { atom, map, type MapStore } from 'nanostores';
import * as nodePath from 'node:path';
import type { BoltAction } from '~/types/actions';
import { createScopedLogger } from '~/utils/logger';
import { unreachable } from '~/utils/unreachable';
import type { ActionCallbackData } from './message-parser';
import type { ITerminal } from '~/types/terminal';
import type { BoltShell } from '~/utils/shell';
const logger = createScopedLogger('ActionRunner');
@ -94,9 +93,10 @@ export class ActionRunner {
this.#updateAction(actionId, { ...action, ...data.action, executed: !isStreaming });
// eslint-disable-next-line consistent-return
return (this.#currentExecutionPromise = this.#currentExecutionPromise
.then(() => {
return this.#executeAction(actionId, isStreaming);
this.#executeAction(actionId, isStreaming);
})
.catch((error) => {
console.error('Action failed:', error);
@ -127,12 +127,11 @@ export class ActionRunner {
/*
* adding a delay to avoid any race condition between 2 start actions
* i am up for a better approch
* i am up for a better approach
*/
await new Promise((resolve) => setTimeout(resolve, 2000));
return;
break;
}
}

View File

@ -13,7 +13,6 @@ import JSZip from 'jszip';
import { saveAs } from 'file-saver';
import { Octokit, type RestEndpointMethodTypes } from '@octokit/rest';
import * as nodePath from 'node:path';
import type { WebContainerProcess } from '@webcontainer/api';
import { extractRelativePath } from '~/utils/diff';
export interface ArtifactState {
@ -42,7 +41,6 @@ export class WorkbenchStore {
unsavedFiles: WritableAtom<Set<string>> = import.meta.hot?.data.unsavedFiles ?? atom(new Set<string>());
modifiedFiles = new Set<string>();
artifactIdList: string[] = [];
#boltTerminal: { terminal: ITerminal; process: WebContainerProcess } | undefined;
#globalExecutionQueue = Promise.resolve();
constructor() {
if (import.meta.hot) {
@ -439,6 +437,8 @@ export class WorkbenchStore {
});
return { path: extractRelativePath(filePath), sha: blob.sha };
}
return null;
}),
);

View File

@ -192,7 +192,7 @@ const PROVIDER_LIST: ProviderInfo[] = [
{ name: 'deepseek-coder', label: 'Deepseek-Coder', provider: 'Deepseek', maxTokenAllowed: 8000 },
{ name: 'deepseek-chat', label: 'Deepseek-Chat', provider: 'Deepseek', maxTokenAllowed: 8000 },
],
getApiKeyLink: 'https://platform.deepseek.com/api_keys',
getApiKeyLink: 'https://platform.deepseek.com/apiKeys',
},
{
name: 'Mistral',
@ -242,8 +242,8 @@ const getOllamaBaseUrl = () => {
async function getOllamaModels(): Promise<ModelInfo[]> {
try {
const base_url = getOllamaBaseUrl();
const response = await fetch(`${base_url}/api/tags`);
const baseUrl = getOllamaBaseUrl();
const response = await fetch(`${baseUrl}/api/tags`);
const data = (await response.json()) as OllamaApiResponse;
return data.models.map((model: OllamaModel) => ({
@ -252,6 +252,7 @@ async function getOllamaModels(): Promise<ModelInfo[]> {
provider: 'Ollama',
maxTokenAllowed: 8000,
}));
// eslint-disable-next-line @typescript-eslint/no-unused-vars
} catch (e) {
return [];
}
@ -259,16 +260,16 @@ async function getOllamaModels(): Promise<ModelInfo[]> {
async function getOpenAILikeModels(): Promise<ModelInfo[]> {
try {
const base_url = import.meta.env.OPENAI_LIKE_API_BASE_URL || '';
const baseUrl = import.meta.env.OPENAI_LIKE_API_BASE_URL || '';
if (!base_url) {
if (!baseUrl) {
return [];
}
const api_key = import.meta.env.OPENAI_LIKE_API_KEY ?? '';
const response = await fetch(`${base_url}/models`, {
const apiKey = import.meta.env.OPENAI_LIKE_API_KEY ?? '';
const response = await fetch(`${baseUrl}/models`, {
headers: {
Authorization: `Bearer ${api_key}`,
Authorization: `Bearer ${apiKey}`,
},
});
const res = (await response.json()) as any;
@ -278,6 +279,7 @@ async function getOpenAILikeModels(): Promise<ModelInfo[]> {
label: model.id,
provider: 'OpenAILike',
}));
// eslint-disable-next-line @typescript-eslint/no-unused-vars
} catch (e) {
return [];
}
@ -318,8 +320,8 @@ async function getOpenRouterModels(): Promise<ModelInfo[]> {
async function getLMStudioModels(): Promise<ModelInfo[]> {
try {
const base_url = import.meta.env.LMSTUDIO_API_BASE_URL || 'http://localhost:1234';
const response = await fetch(`${base_url}/v1/models`);
const baseUrl = import.meta.env.LMSTUDIO_API_BASE_URL || 'http://localhost:1234';
const response = await fetch(`${baseUrl}/v1/models`);
const data = (await response.json()) as any;
return data.data.map((model: any) => ({
@ -327,6 +329,7 @@ async function getLMStudioModels(): Promise<ModelInfo[]> {
label: model.id,
provider: 'LMStudio',
}));
// eslint-disable-next-line @typescript-eslint/no-unused-vars
} catch (e) {
return [];
}

View File

@ -52,6 +52,8 @@ export async function newShellProcess(webcontainer: WebContainer, terminal: ITer
return process;
}
export type ExecutionResult = { output: string; exitCode: number } | undefined;
export class BoltShell {
#initialized: (() => void) | undefined;
#readyPromise: Promise<void>;
@ -61,36 +63,39 @@ export class BoltShell {
executionState = atom<{ sessionId: string; active: boolean; executionPrms?: Promise<any> } | undefined>();
#outputStream: ReadableStreamDefaultReader<string> | undefined;
#shellInputStream: WritableStreamDefaultWriter<string> | undefined;
constructor() {
this.#readyPromise = new Promise((resolve) => {
this.#initialized = resolve;
});
}
ready() {
return this.#readyPromise;
}
async init(webcontainer: WebContainer, terminal: ITerminal) {
this.#webcontainer = webcontainer;
this.#terminal = terminal;
const callback = (data: string) => {
console.log(data);
};
const { process, output } = await this.newBoltShellProcess(webcontainer, terminal);
this.#process = process;
this.#outputStream = output.getReader();
await this.waitTillOscCode('interactive');
this.#initialized?.();
}
get terminal() {
return this.#terminal;
}
get process() {
return this.#process;
}
async executeCommand(sessionId: string, command: string) {
async executeCommand(sessionId: string, command: string): Promise<ExecutionResult> {
if (!this.process || !this.terminal) {
return;
return undefined;
}
const state = this.executionState.get();
@ -109,14 +114,15 @@ export class BoltShell {
this.terminal.input(command.trim() + '\n');
//wait for the execution to finish
const executionPrms = this.getCurrentExecutionResult();
this.executionState.set({ sessionId, active: true, executionPrms });
const executionPromise = this.getCurrentExecutionResult();
this.executionState.set({ sessionId, active: true, executionPrms: executionPromise });
const resp = await executionPrms;
const resp = await executionPromise;
this.executionState.set({ sessionId, active: false });
return resp;
}
async newBoltShellProcess(webcontainer: WebContainer, terminal: ITerminal) {
const args: string[] = [];
@ -167,10 +173,12 @@ export class BoltShell {
return { process, output: internalOutput };
}
async getCurrentExecutionResult() {
async getCurrentExecutionResult(): Promise<ExecutionResult> {
const { output, exitCode } = await this.waitTillOscCode('exit');
return { output, exitCode };
}
async waitTillOscCode(waitCode: string) {
let fullOutput = '';
let exitCode: number = 0;
@ -192,7 +200,7 @@ export class BoltShell {
fullOutput += text;
// Check if command completion signal with exit code
const [, osc, , pid, code] = text.match(/\x1b\]654;([^\x07=]+)=?((-?\d+):(\d+))?\x07/) || [];
const [, osc, , , code] = text.match(/\x1b\]654;([^\x07=]+)=?((-?\d+):(\d+))?\x07/) || [];
if (osc === 'exit') {
exitCode = parseInt(code, 10);
@ -206,6 +214,7 @@ export class BoltShell {
return { output: fullOutput, exitCode };
}
}
export function newBoltShellProcess() {
return new BoltShell();
}

View File

@ -9,4 +9,7 @@ interface Env {
OPENAI_LIKE_API_BASE_URL: string;
DEEPSEEK_API_KEY: string;
LMSTUDIO_API_BASE_URL: string;
GOOGLE_GENERATIVE_AI_API_KEY: string;
MISTRAL_API_KEY: string;
XAI_API_KEY: string;
}