Skip to content

Commit 332edd3

Browse files
Stijnusthecodacus
authored andcommitted
fix: settings bugfix error building my application issue #1414 (#1436)
* Fix: error building my application #1414 * fix for vite * Update vite.config.ts * Update root.tsx * fix the root.tsx and the debugtab * lm studio fix and fix for the api key * Update api.enhancer for prompt enhancement * bugfixes * Revert api.enhancer.ts back to original code * Update api.enhancer.ts * Update api.git-proxy.$.ts * Update api.git-proxy.$.ts * Update api.enhancer.ts
1 parent 7045646 commit 332edd3

File tree

18 files changed

+371
-801
lines changed

18 files changed

+371
-801
lines changed

app/components/@settings/tabs/connections/ConnectionsTab.tsx

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,19 @@
11
import { motion } from 'framer-motion';
2-
import { GithubConnection } from './GithubConnection';
3-
import { NetlifyConnection } from './NetlifyConnection';
2+
import React, { Suspense } from 'react';
3+
4+
// Use React.lazy for dynamic imports
5+
const GithubConnection = React.lazy(() => import('./GithubConnection'));
6+
const NetlifyConnection = React.lazy(() => import('./NetlifyConnection'));
7+
8+
// Loading fallback component
9+
const LoadingFallback = () => (
10+
<div className="p-4 bg-white dark:bg-[#0A0A0A] rounded-lg border border-[#E5E5E5] dark:border-[#1A1A1A]">
11+
<div className="flex items-center gap-2 text-bolt-elements-textSecondary">
12+
<div className="i-ph:spinner-gap w-5 h-5 animate-spin" />
13+
<span>Loading connection...</span>
14+
</div>
15+
</div>
16+
);
417

518
export default function ConnectionsTab() {
619
return (
@@ -20,8 +33,12 @@ export default function ConnectionsTab() {
2033
</p>
2134

2235
<div className="grid grid-cols-1 gap-4">
23-
<GithubConnection />
24-
<NetlifyConnection />
36+
<Suspense fallback={<LoadingFallback />}>
37+
<GithubConnection />
38+
</Suspense>
39+
<Suspense fallback={<LoadingFallback />}>
40+
<NetlifyConnection />
41+
</Suspense>
2542
</div>
2643
</div>
2744
);

app/components/@settings/tabs/connections/GithubConnection.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ interface GitHubConnection {
6565
stats?: GitHubStats;
6666
}
6767

68-
export function GithubConnection() {
68+
export default function GithubConnection() {
6969
const [connection, setConnection] = useState<GitHubConnection>({
7070
user: null,
7171
token: '',

app/components/@settings/tabs/connections/NetlifyConnection.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ import {
1313
} from '~/lib/stores/netlify';
1414
import type { NetlifyUser } from '~/types/netlify';
1515

16-
export function NetlifyConnection() {
16+
export default function NetlifyConnection() {
1717
const connection = useStore(netlifyConnection);
1818
const connecting = useStore(isConnecting);
1919
const fetchingStats = useStore(isFetchingStats);

app/lib/hooks/useShortcuts.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ export function useShortcuts(): void {
4141
}
4242

4343
// Debug logging in development only
44-
if (process.env.NODE_ENV === 'development') {
44+
if (import.meta.env.DEV) {
4545
console.log('Key pressed:', {
4646
key: event.key,
4747
code: event.code,

app/lib/modules/llm/providers/lmstudio.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ export default class LMStudioProvider extends BaseProvider {
7575
throw new Error('No baseUrl found for LMStudio provider');
7676
}
7777

78-
const isDocker = process.env.RUNNING_IN_DOCKER === 'true' || serverEnv?.RUNNING_IN_DOCKER === 'true';
78+
const isDocker = process?.env?.RUNNING_IN_DOCKER === 'true' || serverEnv?.RUNNING_IN_DOCKER === 'true';
7979

8080
if (typeof window === 'undefined') {
8181
baseUrl = isDocker ? baseUrl.replace('localhost', 'host.docker.internal') : baseUrl;

app/lib/modules/llm/providers/ollama.ts

Lines changed: 26 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,6 @@ export interface OllamaApiResponse {
2727
models: OllamaModel[];
2828
}
2929

30-
export const DEFAULT_NUM_CTX = process?.env?.DEFAULT_NUM_CTX ? parseInt(process.env.DEFAULT_NUM_CTX, 10) : 32768;
31-
3230
export default class OllamaProvider extends BaseProvider {
3331
name = 'Ollama';
3432
getApiKeyLink = 'https://ollama.com/download';
@@ -41,6 +39,26 @@ export default class OllamaProvider extends BaseProvider {
4139

4240
staticModels: ModelInfo[] = [];
4341

42+
private _convertEnvToRecord(env?: Env): Record<string, string> {
43+
if (!env) {
44+
return {};
45+
}
46+
47+
// Convert Env to a plain object with string values
48+
return Object.entries(env).reduce(
49+
(acc, [key, value]) => {
50+
acc[key] = String(value);
51+
return acc;
52+
},
53+
{} as Record<string, string>,
54+
);
55+
}
56+
57+
getDefaultNumCtx(serverEnv?: Env): number {
58+
const envRecord = this._convertEnvToRecord(serverEnv);
59+
return envRecord.DEFAULT_NUM_CTX ? parseInt(envRecord.DEFAULT_NUM_CTX, 10) : 32768;
60+
}
61+
4462
async getDynamicModels(
4563
apiKeys?: Record<string, string>,
4664
settings?: IProviderSetting,
@@ -81,17 +99,20 @@ export default class OllamaProvider extends BaseProvider {
8199
maxTokenAllowed: 8000,
82100
}));
83101
}
102+
84103
getModelInstance: (options: {
85104
model: string;
86105
serverEnv?: Env;
87106
apiKeys?: Record<string, string>;
88107
providerSettings?: Record<string, IProviderSetting>;
89108
}) => LanguageModelV1 = (options) => {
90109
const { apiKeys, providerSettings, serverEnv, model } = options;
110+
const envRecord = this._convertEnvToRecord(serverEnv);
111+
91112
let { baseUrl } = this.getProviderBaseUrlAndKey({
92113
apiKeys,
93114
providerSettings: providerSettings?.[this.name],
94-
serverEnv: serverEnv as any,
115+
serverEnv: envRecord,
95116
defaultBaseUrlKey: 'OLLAMA_API_BASE_URL',
96117
defaultApiTokenKey: '',
97118
});
@@ -101,14 +122,14 @@ export default class OllamaProvider extends BaseProvider {
101122
throw new Error('No baseUrl found for OLLAMA provider');
102123
}
103124

104-
const isDocker = process?.env?.RUNNING_IN_DOCKER === 'true' || serverEnv?.RUNNING_IN_DOCKER === 'true';
125+
const isDocker = process?.env?.RUNNING_IN_DOCKER === 'true' || envRecord.RUNNING_IN_DOCKER === 'true';
105126
baseUrl = isDocker ? baseUrl.replace('localhost', 'host.docker.internal') : baseUrl;
106127
baseUrl = isDocker ? baseUrl.replace('127.0.0.1', 'host.docker.internal') : baseUrl;
107128

108129
logger.debug('Ollama Base Url used: ', baseUrl);
109130

110131
const ollamaInstance = ollama(model, {
111-
numCtx: DEFAULT_NUM_CTX,
132+
numCtx: this.getDefaultNumCtx(serverEnv),
112133
}) as LanguageModelV1 & { config: any };
113134

114135
ollamaInstance.config.baseURL = `${baseUrl}/api`;

app/root.tsx

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import { createHead } from 'remix-island';
88
import { useEffect } from 'react';
99
import { DndProvider } from 'react-dnd';
1010
import { HTML5Backend } from 'react-dnd-html5-backend';
11+
import { ClientOnly } from 'remix-utils/client-only';
1112

1213
import reactToastifyStyles from 'react-toastify/dist/ReactToastify.css?url';
1314
import globalStyles from './styles/index.scss?url';
@@ -72,11 +73,11 @@ export function Layout({ children }: { children: React.ReactNode }) {
7273
}, [theme]);
7374

7475
return (
75-
<DndProvider backend={HTML5Backend}>
76-
{children}
76+
<>
77+
<ClientOnly>{() => <DndProvider backend={HTML5Backend}>{children}</DndProvider>}</ClientOnly>
7778
<ScrollRestoration />
7879
<Scripts />
79-
</DndProvider>
80+
</>
8081
);
8182
}
8283

app/routes/api.check-env-key.ts

Lines changed: 29 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,41 @@
11
import type { LoaderFunction } from '@remix-run/cloudflare';
2-
import { providerBaseUrlEnvKeys } from '~/utils/constants';
2+
import { LLMManager } from '~/lib/modules/llm/manager';
3+
import { getApiKeysFromCookie } from '~/lib/api/cookies';
34

45
export const loader: LoaderFunction = async ({ context, request }) => {
56
const url = new URL(request.url);
67
const provider = url.searchParams.get('provider');
78

8-
if (!provider || !providerBaseUrlEnvKeys[provider].apiTokenKey) {
9+
if (!provider) {
910
return Response.json({ isSet: false });
1011
}
1112

12-
const envVarName = providerBaseUrlEnvKeys[provider].apiTokenKey;
13-
const isSet = !!(process.env[envVarName] || (context?.cloudflare?.env as Record<string, any>)?.[envVarName]);
13+
const llmManager = LLMManager.getInstance(context?.cloudflare?.env as any);
14+
const providerInstance = llmManager.getProvider(provider);
15+
16+
if (!providerInstance || !providerInstance.config.apiTokenKey) {
17+
return Response.json({ isSet: false });
18+
}
19+
20+
const envVarName = providerInstance.config.apiTokenKey;
21+
22+
// Get API keys from cookie
23+
const cookieHeader = request.headers.get('Cookie');
24+
const apiKeys = getApiKeysFromCookie(cookieHeader);
25+
26+
/*
27+
* Check API key in order of precedence:
28+
* 1. Client-side API keys (from cookies)
29+
* 2. Server environment variables (from Cloudflare env)
30+
* 3. Process environment variables (from .env.local)
31+
* 4. LLMManager environment variables
32+
*/
33+
const isSet = !!(
34+
apiKeys?.[provider] ||
35+
(context?.cloudflare?.env as Record<string, any>)?.[envVarName] ||
36+
process.env[envVarName] ||
37+
llmManager.env[envVarName]
38+
);
1439

1540
return Response.json({ isSet });
1641
};

app/routes/api.deploy.ts

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
import { type ActionFunctionArgs, json } from '@remix-run/cloudflare';
2-
import crypto from 'crypto';
32
import type { NetlifySiteInfo } from '~/types/netlify';
43

54
interface DeployRequestBody {
@@ -8,6 +7,15 @@ interface DeployRequestBody {
87
chatId: string;
98
}
109

10+
async function sha1(message: string) {
11+
const msgBuffer = new TextEncoder().encode(message);
12+
const hashBuffer = await crypto.subtle.digest('SHA-1', msgBuffer);
13+
const hashArray = Array.from(new Uint8Array(hashBuffer));
14+
const hashHex = hashArray.map((b) => b.toString(16).padStart(2, '0')).join('');
15+
16+
return hashHex;
17+
}
18+
1119
export async function action({ request }: ActionFunctionArgs) {
1220
try {
1321
const { siteId, files, token, chatId } = (await request.json()) as DeployRequestBody & { token: string };
@@ -104,7 +112,7 @@ export async function action({ request }: ActionFunctionArgs) {
104112
for (const [filePath, content] of Object.entries(files)) {
105113
// Ensure file path starts with a forward slash
106114
const normalizedPath = filePath.startsWith('/') ? filePath : '/' + filePath;
107-
const hash = crypto.createHash('sha1').update(content).digest('hex');
115+
const hash = await sha1(content);
108116
fileDigests[normalizedPath] = hash;
109117
}
110118

app/routes/api.enhancer.ts

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -95,24 +95,28 @@ async function enhancerAction({ context, request }: ActionFunctionArgs) {
9595
},
9696
});
9797

98+
// Handle streaming errors in a non-blocking way
9899
(async () => {
99-
for await (const part of result.fullStream) {
100-
if (part.type === 'error') {
101-
const error: any = part.error;
102-
logger.error(error);
103-
104-
return;
100+
try {
101+
for await (const part of result.fullStream) {
102+
if (part.type === 'error') {
103+
const error: any = part.error;
104+
logger.error('Streaming error:', error);
105+
break;
106+
}
105107
}
108+
} catch (error) {
109+
logger.error('Error processing stream:', error);
106110
}
107111
})();
108112

113+
// Return the text stream directly since it's already text data
109114
return new Response(result.textStream, {
110115
status: 200,
111116
headers: {
112117
'Content-Type': 'text/event-stream',
113118
Connection: 'keep-alive',
114119
'Cache-Control': 'no-cache',
115-
'Text-Encoding': 'chunked',
116120
},
117121
});
118122
} catch (error: unknown) {

0 commit comments

Comments
 (0)