Compare commits

..

12 Commits

Author SHA1 Message Date
root
9d8c4055ca Initial bolt.diy deployment
Some checks failed
CI/CD / Test (push) Has been cancelled
CI/CD / Docker Build Validation (push) Has been cancelled
Docker Publish / docker-build-publish (push) Has been cancelled
Code Quality / Quality Analysis (push) Has been cancelled
Code Quality / Accessibility Tests (push) Has been cancelled
Code Quality / Performance Audit (push) Has been cancelled
Code Quality / PR Size Check (push) Has been cancelled
Security Analysis / CodeQL Analysis (javascript) (push) Has been cancelled
Security Analysis / CodeQL Analysis (typescript) (push) Has been cancelled
Security Analysis / Dependency Vulnerability Scan (push) Has been cancelled
Security Analysis / Secrets Detection (push) Has been cancelled
Update Stable Branch / prepare-release (push) Has been cancelled
2025-12-11 17:01:27 +00:00
Stijnus
3f6050b227 Update Docker instructions and dev dependencies (#2032)
Expanded and clarified Docker usage instructions in README.md, including environment variable setup and workflow details. Updated @cloudflare/workers-types and wrangler dev dependencies in package.json to newer versions.
2025-10-23 17:44:23 +02:00
Richard McSharry | Code Monkey
5f925566c4 fix: for more stable broadcast channels on CF workers (#2007) 2025-10-23 17:02:19 +02:00
Stijnus
983b3025a5 Merge pull request #2019 from Stijnus/fix/toast-messages-z-index-deployment
fix: toast message visibility and deployment success notifications
2025-10-23 15:05:54 +02:00
Stijnus
49850d9253 fix: resolve critical Docker configuration issues (#2020)
* fix: update Docker workflow to use correct target stage name

- Change target from bolt-ai-production to runtime
- Matches the actual stage name in the new Dockerfile structure
- Fixes CI failure: target stage 'bolt-ai-production' could not be found

* fix: resolve critical Docker configuration issues

This commit fixes multiple critical Docker configuration issues that prevented successful builds:

**Dockerfile Issues Fixed:**
- Replace incomplete runtime stage with proper production stage using Wrangler
- Add missing environment variables for all API providers (DeepSeek, LMStudio, Mistral, Perplexity, OpenAI-like)
- Use correct port (5173) instead of 3000 to match Wrangler configuration
- Add proper bindings.sh script copying and execution permissions
- Configure Wrangler metrics and proper startup command

**Docker Compose Issues Fixed:**
- Add missing `context` and `dockerfile` fields to app-dev service
- Fix target name from `bolt-ai-development` to `development`

**Package.json Issues Fixed:**
- Update dockerbuild script to use correct target name `development`

**Testing:**
-  Both `pnpm run dockerbuild` and `pnpm run dockerbuild:prod` now work
-  All environment variables properly configured
-  Docker images build successfully with proper Wrangler integration

Resolves Docker build failures and enables proper containerized deployment.

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>

* Update Dockerfile

* fix: update GitHub workflow Docker targets to match Dockerfile stage names

Update ci.yaml and docker.yaml workflows to use correct Docker target stage name 'bolt-ai-production' instead of 'runtime'.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>

* Refactor Dockerfile for optimized production build

Adds git installation for build/runtime scripts and introduces a separate prod-deps stage to prune dependencies before final production image. Updates file copy sources to use prod-deps stage, improving build efficiency and image size.

---------

Co-authored-by: Claude <noreply@anthropic.com>
2025-10-23 14:50:43 +02:00
Stijnus
1a55bd5866 Merge pull request #2030 from Stijnus/BOLTDIY_Supabase_fix
fix: refactor localStorage access for Supabase state
2025-10-23 14:49:33 +02:00
Stijnus
f138b9c088 Refactor localStorage access for Supabase state
Replaces direct localStorage usage with a safe 'storage' variable that checks for globalThis and method existence. This improves compatibility with environments where localStorage may not be available, such as server-side rendering.
2025-10-23 14:40:54 +02:00
Stijnus
4e37f5a80c fix: resolve toast message visibility and deployment success notifications
## Issues Fixed
- Toast messages appearing in background/blurred due to z-index conflicts
- Missing success toast notifications for deployment completions
- Scoped ToastContainer limiting toast visibility to chat component only

## Changes Made

### Global Toast System
- Move ToastContainer from Chat.client.tsx to root.tsx for global availability
- Add highest z-index (1000) to ensure toasts appear above all UI elements
- Remove duplicate ToastContainer from chat component

### Z-Index System Updates
- Add .z-toast class with z-index: $zIndexMax + 1 (1000)
- Apply toast z-index to .Toastify__toast-container in toast.scss
- Ensure proper layering hierarchy for all toast messages

### Deployment Success Notifications
- Add missing toast.success() calls to all deployment services:
  - NetlifyDeploy: "🚀 Netlify deployment completed successfully!"
  - VercelDeploy: "🚀 Vercel deployment completed successfully!"
  - GitHubDeploy: "🚀 GitHub deployment preparation completed successfully!"
  - GitLabDeploy: "🚀 GitLab deployment preparation completed successfully!"

## Result
- All toast messages now appear in foreground with proper z-index
- Deployment success notifications are clearly visible to users
- Consistent toast behavior across the entire application
- No more blurred or background toast messages

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-09-29 14:05:22 +02:00
Stijnus
d34852c227 Merge branch 'stackblitz-labs:main' into main 2025-09-16 16:10:42 +02:00
Stijnus
cb3c536c5d feat: auto-enable local providers when configured via environment variables (#1881) (#2002)
* fix: update Docker workflow to use correct target stage name

- Change target from bolt-ai-production to runtime
- Matches the actual stage name in the new Dockerfile structure
- Fixes CI failure: target stage 'bolt-ai-production' could not be found

* feat: auto-enable local providers when configured via environment variables (#1881)

- Add server-side API endpoint `/api/configured-providers` to detect environment-configured providers
- Auto-enable Ollama, LMStudio, and OpenAILike providers when their environment variables are set
- Filter out placeholder values (like "your_*_here") to only detect real configuration
- Preserve user preferences: auto-enabling only applies on first load or previously auto-enabled providers
- Track auto-enabled vs manually-enabled providers in localStorage for proper user choice handling
- Solve issue where Ollama appears configured server-side but disabled in UI

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>

---------

Co-authored-by: Claude <noreply@anthropic.com>
2025-09-16 16:10:12 +02:00
Stijnus
b32c4081ec Merge branch 'stackblitz-labs:main' into main 2025-09-16 12:03:22 +02:00
Stijnus
583dfbda53 fix: update Docker workflow to use correct target stage name
- Change target from bolt-ai-production to runtime
- Matches the actual stage name in the new Dockerfile structure
- Fixes CI failure: target stage 'bolt-ai-production' could not be found
2025-09-16 11:39:39 +02:00
21 changed files with 35394 additions and 208 deletions

View File

@@ -74,7 +74,7 @@ jobs:
- name: Validate Docker production build
run: |
echo "🐳 Testing Docker production target..."
docker build --target runtime . --no-cache --progress=plain
docker build --target bolt-ai-production . --no-cache --progress=plain
echo "✅ Production target builds successfully"
- name: Validate Docker development build

View File

@@ -57,7 +57,7 @@ jobs:
with:
context: .
platforms: linux/amd64,linux/arm64
target: runtime
target: bolt-ai-production
push: true
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}

View File

@@ -9,6 +9,10 @@ ENV CI=true
# Use pnpm
RUN corepack enable && corepack prepare pnpm@9.15.9 --activate
# Ensure git is available for build and runtime scripts
RUN apt-get update && apt-get install -y --no-install-recommends git \
&& rm -rf /var/lib/apt/lists/*
# Accept (optional) build-time public URL for Remix/Vite (Coolify can pass it)
ARG VITE_PUBLIC_APP_URL
ENV VITE_PUBLIC_APP_URL=${VITE_PUBLIC_APP_URL}
@@ -25,68 +29,75 @@ RUN pnpm install --offline --frozen-lockfile
# Build the Remix app (SSR + client)
RUN NODE_OPTIONS=--max-old-space-size=4096 pnpm run build
# ---- production dependencies stage ----
FROM build AS prod-deps
# Keep only production deps for runtime
RUN pnpm prune --prod --ignore-scripts
# ---- runtime stage ----
FROM node:22-bookworm-slim AS runtime
# ---- production stage ----
FROM prod-deps AS bolt-ai-production
WORKDIR /app
ENV NODE_ENV=production
ENV PORT=3000
ENV PORT=5173
ENV HOST=0.0.0.0
# Install curl so Coolifys healthcheck works inside the image
# Non-sensitive build arguments
ARG VITE_LOG_LEVEL=debug
ARG DEFAULT_NUM_CTX
# Set non-sensitive environment variables
ENV WRANGLER_SEND_METRICS=false \
VITE_LOG_LEVEL=${VITE_LOG_LEVEL} \
DEFAULT_NUM_CTX=${DEFAULT_NUM_CTX} \
RUNNING_IN_DOCKER=true
# Note: API keys should be provided at runtime via docker run -e or docker-compose
# Example: docker run -e OPENAI_API_KEY=your_key_here ...
# Install curl for healthchecks and copy bindings script
RUN apt-get update && apt-get install -y --no-install-recommends curl \
&& rm -rf /var/lib/apt/lists/*
# Copy only what we need to run
COPY --from=build /app/build /app/build
COPY --from=build /app/node_modules /app/node_modules
COPY --from=build /app/package.json /app/package.json
# Copy built files and scripts
COPY --from=prod-deps /app/build /app/build
COPY --from=prod-deps /app/node_modules /app/node_modules
COPY --from=prod-deps /app/package.json /app/package.json
COPY --from=prod-deps /app/bindings.sh /app/bindings.sh
EXPOSE 3000
# Pre-configure wrangler to disable metrics
RUN mkdir -p /root/.config/.wrangler && \
echo '{"enabled":false}' > /root/.config/.wrangler/metrics.json
# Healthcheck for Coolify
# Make bindings script executable
RUN chmod +x /app/bindings.sh
EXPOSE 5173
# Healthcheck for deployment platforms
HEALTHCHECK --interval=10s --timeout=3s --start-period=5s --retries=5 \
CMD curl -fsS http://localhost:3000/ || exit 1
CMD curl -fsS http://localhost:5173/ || exit 1
# Start the Remix server
CMD ["node", "build/server/index.js"]
# Start using dockerstart script with Wrangler
CMD ["pnpm", "run", "dockerstart"]
# ---- development stage ----
FROM build AS development
# Define environment variables for development
ARG GROQ_API_KEY
ARG HuggingFace_API_KEY
ARG OPENAI_API_KEY
ARG ANTHROPIC_API_KEY
ARG OPEN_ROUTER_API_KEY
ARG GOOGLE_GENERATIVE_AI_API_KEY
ARG OLLAMA_API_BASE_URL
ARG XAI_API_KEY
ARG TOGETHER_API_KEY
ARG TOGETHER_API_BASE_URL
# Non-sensitive development arguments
ARG VITE_LOG_LEVEL=debug
ARG DEFAULT_NUM_CTX
ENV GROQ_API_KEY=${GROQ_API_KEY} \
HuggingFace_API_KEY=${HuggingFace_API_KEY} \
OPENAI_API_KEY=${OPENAI_API_KEY} \
ANTHROPIC_API_KEY=${ANTHROPIC_API_KEY} \
OPEN_ROUTER_API_KEY=${OPEN_ROUTER_API_KEY} \
GOOGLE_GENERATIVE_AI_API_KEY=${GOOGLE_GENERATIVE_AI_API_KEY} \
OLLAMA_API_BASE_URL=${OLLAMA_API_BASE_URL} \
XAI_API_KEY=${XAI_API_KEY} \
TOGETHER_API_KEY=${TOGETHER_API_KEY} \
TOGETHER_API_BASE_URL=${TOGETHER_API_BASE_URL} \
AWS_BEDROCK_CONFIG=${AWS_BEDROCK_CONFIG} \
VITE_LOG_LEVEL=${VITE_LOG_LEVEL} \
# Set non-sensitive environment variables for development
ENV VITE_LOG_LEVEL=${VITE_LOG_LEVEL} \
DEFAULT_NUM_CTX=${DEFAULT_NUM_CTX} \
RUNNING_IN_DOCKER=true
# Note: API keys should be provided at runtime via docker run -e or docker-compose
# Example: docker run -e OPENAI_API_KEY=your_key_here ...
RUN mkdir -p /app/run
CMD ["pnpm", "run", "dev", "--host"]

View File

@@ -154,29 +154,52 @@ You have two options for running Bolt.DIY: directly on your machine or using Doc
### Option 2: Using Docker
This option requires some familiarity with Docker but provides a more isolated environment.
This option requires Docker and is great when you want an isolated environment or to mirror the production image.
#### Additional Prerequisite
- Install Docker: [Download Docker](https://www.docker.com/)
#### Steps:
#### Steps
1. **Build the Docker Image**:
1. **Prepare Environment Variables**
Copy the provided examples and add your provider keys:
```bash
# Using npm script:
npm run dockerbuild
# OR using direct Docker command:
docker build . --target bolt-ai-development
cp .env.example .env
cp .env.example .env.local
```
2. **Run the Container**:
The runtime scripts inside the container source `.env` and `.env.local`, so keep any API keys you need in one of those files.
2. **Build an Image**
```bash
# Development image (bind-mounts your local source when run)
pnpm run dockerbuild
# ≈ docker build -t bolt-ai:development -t bolt-ai:latest --target development .
# Production image (self-contained build artifacts)
pnpm run dockerbuild:prod
# ≈ docker build -t bolt-ai:production -t bolt-ai:latest --target bolt-ai-production .
```
3. **Run the Container**
```bash
# Development workflow with hot reload
docker compose --profile development up
# Production-style container using composed services
docker compose --profile production up
# One-off production container (exposes the app on port 5173)
docker run --rm -p 5173:5173 --env-file .env.local bolt-ai:latest
```
When the container starts it runs `pnpm run dockerstart`, which in turn executes `bindings.sh` to pass Cloudflare bindings through Wrangler. You can override this command in `docker-compose.yaml` if you need a different startup routine.
### Option 3: Desktop Application (Electron)
For users who prefer a native desktop experience, bolt.diy is also available as an Electron desktop application:

View File

@@ -3,7 +3,7 @@ import type { Message } from 'ai';
import { useChat } from '@ai-sdk/react';
import { useAnimate } from 'framer-motion';
import { memo, useCallback, useEffect, useRef, useState } from 'react';
import { cssTransition, toast, ToastContainer } from 'react-toastify';
import { toast } from 'react-toastify';
import { useMessageParser, usePromptEnhancer, useShortcuts } from '~/lib/hooks';
import { description, useChatHistory } from '~/lib/persistence';
import { chatStore } from '~/lib/stores/chat';
@@ -29,11 +29,6 @@ import type { TextUIPart, FileUIPart, Attachment } from '@ai-sdk/ui-utils';
import { useMCPStore } from '~/lib/stores/mcp';
import type { LlmErrorAlertType } from '~/types/actions';
const toastAnimation = cssTransition({
enter: 'animated fadeInRight',
exit: 'animated fadeOutRight',
});
const logger = createScopedLogger('Chat');
export function Chat() {
@@ -56,34 +51,6 @@ export function Chat() {
importChat={importChat}
/>
)}
<ToastContainer
closeButton={({ closeToast }) => {
return (
<button className="Toastify__close-button" onClick={closeToast}>
<div className="i-ph:x text-lg" />
</button>
);
}}
icon={({ type }) => {
/**
* @todo Handle more types if we need them. This may require extra color palettes.
*/
switch (type) {
case 'success': {
return <div className="i-ph:check-bold text-bolt-elements-icon-success text-2xl" />;
}
case 'error': {
return <div className="i-ph:warning-circle-bold text-bolt-elements-icon-error text-2xl" />;
}
}
return undefined;
}}
position="bottom-right"
pauseOnFocusLoss
transition={toastAnimation}
autoClose={3000}
/>
</>
);
}

View File

@@ -145,6 +145,9 @@ export function useGitHubDeploy() {
source: 'github',
});
// Show success toast notification
toast.success(`🚀 GitHub deployment preparation completed successfully!`);
return {
success: true,
files: fileContents,

View File

@@ -145,6 +145,9 @@ export function useGitLabDeploy() {
source: 'gitlab',
});
// Show success toast notification
toast.success(`🚀 GitLab deployment preparation completed successfully!`);
return {
success: true,
files: fileContents,

View File

@@ -224,6 +224,9 @@ export function useNetlifyDeploy() {
source: 'netlify',
});
// Show success toast notification
toast.success(`🚀 Netlify deployment completed successfully!`);
return true;
} catch (error) {
console.error('Deploy error:', error);

View File

@@ -213,6 +213,9 @@ export function useVercelDeploy() {
source: 'vercel',
});
// Show success toast notification
toast.success(`🚀 Vercel deployment completed successfully!`);
return true;
} catch (err) {
console.error('Vercel deploy error:', err);

View File

@@ -20,20 +20,21 @@ const PREVIEW_CHANNEL = 'preview-updates';
export class PreviewsStore {
#availablePreviews = new Map<number, PreviewInfo>();
#webcontainer: Promise<WebContainer>;
#broadcastChannel: BroadcastChannel;
#broadcastChannel?: BroadcastChannel;
#lastUpdate = new Map<string, number>();
#watchedFiles = new Set<string>();
#refreshTimeouts = new Map<string, NodeJS.Timeout>();
#REFRESH_DELAY = 300;
#storageChannel: BroadcastChannel;
#storageChannel?: BroadcastChannel;
previews = atom<PreviewInfo[]>([]);
constructor(webcontainerPromise: Promise<WebContainer>) {
this.#webcontainer = webcontainerPromise;
this.#broadcastChannel = new BroadcastChannel(PREVIEW_CHANNEL);
this.#storageChannel = new BroadcastChannel('storage-sync-channel');
this.#broadcastChannel = this.#maybeCreateChannel(PREVIEW_CHANNEL);
this.#storageChannel = this.#maybeCreateChannel('storage-sync-channel');
if (this.#broadcastChannel) {
// Listen for preview updates from other tabs
this.#broadcastChannel.onmessage = (event) => {
const { type, previewId } = event.data;
@@ -48,7 +49,9 @@ export class PreviewsStore {
}
}
};
}
if (this.#storageChannel) {
// Listen for storage sync messages
this.#storageChannel.onmessage = (event) => {
const { storage, source } = event.data;
@@ -57,6 +60,7 @@ export class PreviewsStore {
this._syncStorage(storage);
}
};
}
// Override localStorage setItem to catch all changes
if (typeof window !== 'undefined') {
@@ -71,6 +75,29 @@ export class PreviewsStore {
this.#init();
}
#maybeCreateChannel(name: string): BroadcastChannel | undefined {
if (typeof globalThis === 'undefined') {
return undefined;
}
const globalBroadcastChannel = (
globalThis as typeof globalThis & {
BroadcastChannel?: typeof BroadcastChannel;
}
).BroadcastChannel;
if (typeof globalBroadcastChannel !== 'function') {
return undefined;
}
try {
return new globalBroadcastChannel(name);
} catch (error) {
console.warn('[Preview] BroadcastChannel unavailable:', error);
return undefined;
}
}
// Generate a unique ID for this tab
private _getTabId(): string {
if (typeof window !== 'undefined') {
@@ -130,7 +157,7 @@ export class PreviewsStore {
}
}
this.#storageChannel.postMessage({
this.#storageChannel?.postMessage({
type: 'storage-sync',
storage,
source: this._getTabId(),
@@ -192,7 +219,7 @@ export class PreviewsStore {
const timestamp = Date.now();
this.#lastUpdate.set(previewId, timestamp);
this.#broadcastChannel.postMessage({
this.#broadcastChannel?.postMessage({
type: 'state-change',
previewId,
timestamp,
@@ -204,7 +231,7 @@ export class PreviewsStore {
const timestamp = Date.now();
this.#lastUpdate.set(previewId, timestamp);
this.#broadcastChannel.postMessage({
this.#broadcastChannel?.postMessage({
type: 'file-change',
previewId,
timestamp,
@@ -219,7 +246,7 @@ export class PreviewsStore {
const timestamp = Date.now();
this.#lastUpdate.set(previewId, timestamp);
this.#broadcastChannel.postMessage({
this.#broadcastChannel?.postMessage({
type: 'file-change',
previewId,
timestamp,

View File

@@ -52,11 +52,37 @@ export const shortcutsStore = map<Shortcuts>({
// Create a single key for provider settings
const PROVIDER_SETTINGS_KEY = 'provider_settings';
const AUTO_ENABLED_KEY = 'auto_enabled_providers';
// Add this helper function at the top of the file
const isBrowser = typeof window !== 'undefined';
// Initialize provider settings from both localStorage and defaults
// Interface for configured provider info from server
interface ConfiguredProvider {
name: string;
isConfigured: boolean;
configMethod: 'environment' | 'none';
}
// Fetch configured providers from server
const fetchConfiguredProviders = async (): Promise<ConfiguredProvider[]> => {
try {
const response = await fetch('/api/configured-providers');
if (!response.ok) {
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
}
const data = (await response.json()) as { providers?: ConfiguredProvider[] };
return data.providers || [];
} catch (error) {
console.error('Error fetching configured providers:', error);
return [];
}
};
// Initialize provider settings from both localStorage and server-detected configuration
const getInitialProviderSettings = (): ProviderSetting => {
const initialSettings: ProviderSetting = {};
@@ -92,8 +118,84 @@ const getInitialProviderSettings = (): ProviderSetting => {
return initialSettings;
};
// Auto-enable providers that are configured on the server
const autoEnableConfiguredProviders = async () => {
if (!isBrowser) {
return;
}
try {
const configuredProviders = await fetchConfiguredProviders();
const currentSettings = providersStore.get();
const savedSettings = localStorage.getItem(PROVIDER_SETTINGS_KEY);
const autoEnabledProviders = localStorage.getItem(AUTO_ENABLED_KEY);
// Track which providers were auto-enabled to avoid overriding user preferences
const previouslyAutoEnabled = autoEnabledProviders ? JSON.parse(autoEnabledProviders) : [];
const newlyAutoEnabled: string[] = [];
let hasChanges = false;
configuredProviders.forEach(({ name, isConfigured, configMethod }) => {
if (isConfigured && configMethod === 'environment' && LOCAL_PROVIDERS.includes(name)) {
const currentProvider = currentSettings[name];
if (currentProvider) {
/*
* Only auto-enable if:
* 1. Provider is not already enabled, AND
* 2. Either we haven't saved settings yet (first time) OR provider was previously auto-enabled
*/
const hasUserSettings = savedSettings !== null;
const wasAutoEnabled = previouslyAutoEnabled.includes(name);
const shouldAutoEnable = !currentProvider.settings.enabled && (!hasUserSettings || wasAutoEnabled);
if (shouldAutoEnable) {
currentSettings[name] = {
...currentProvider,
settings: {
...currentProvider.settings,
enabled: true,
},
};
newlyAutoEnabled.push(name);
hasChanges = true;
}
}
}
});
if (hasChanges) {
// Update the store
providersStore.set(currentSettings);
// Save to localStorage
localStorage.setItem(PROVIDER_SETTINGS_KEY, JSON.stringify(currentSettings));
// Update the auto-enabled providers list
const allAutoEnabled = [...new Set([...previouslyAutoEnabled, ...newlyAutoEnabled])];
localStorage.setItem(AUTO_ENABLED_KEY, JSON.stringify(allAutoEnabled));
console.log(`Auto-enabled providers: ${newlyAutoEnabled.join(', ')}`);
}
} catch (error) {
console.error('Error auto-enabling configured providers:', error);
}
};
export const providersStore = map<ProviderSetting>(getInitialProviderSettings());
// Export the auto-enable function for use in components
export const initializeProviders = autoEnableConfiguredProviders;
// Initialize providers when the module loads (in browser only)
if (isBrowser) {
// Use a small delay to ensure DOM and other resources are ready
setTimeout(() => {
autoEnableConfiguredProviders();
}, 100);
}
// Create a function to update provider settings that handles both store and persistence
export const updateProviderSettings = (provider: string, settings: ProviderSetting) => {
const currentSettings = providersStore.get();
@@ -113,6 +215,37 @@ export const updateProviderSettings = (provider: string, settings: ProviderSetti
// Save to localStorage
const allSettings = providersStore.get();
localStorage.setItem(PROVIDER_SETTINGS_KEY, JSON.stringify(allSettings));
// If this is a local provider, update the auto-enabled tracking
if (LOCAL_PROVIDERS.includes(provider) && updatedProvider.settings.enabled !== undefined) {
updateAutoEnabledTracking(provider, updatedProvider.settings.enabled);
}
};
// Update auto-enabled tracking when user manually changes provider settings
const updateAutoEnabledTracking = (providerName: string, isEnabled: boolean) => {
if (!isBrowser) {
return;
}
try {
const autoEnabledProviders = localStorage.getItem(AUTO_ENABLED_KEY);
const currentAutoEnabled = autoEnabledProviders ? JSON.parse(autoEnabledProviders) : [];
if (isEnabled) {
// If user enables provider, add to auto-enabled list (for future detection)
if (!currentAutoEnabled.includes(providerName)) {
currentAutoEnabled.push(providerName);
localStorage.setItem(AUTO_ENABLED_KEY, JSON.stringify(currentAutoEnabled));
}
} else {
// If user disables provider, remove from auto-enabled list (respect user choice)
const updatedAutoEnabled = currentAutoEnabled.filter((name: string) => name !== providerName);
localStorage.setItem(AUTO_ENABLED_KEY, JSON.stringify(updatedAutoEnabled));
}
} catch (error) {
console.error('Error updating auto-enabled tracking:', error);
}
};
export const isDebugMode = atom(false);

View File

@@ -51,8 +51,15 @@ export interface SupabaseConnectionState {
credentials?: SupabaseCredentials;
}
const savedConnection = typeof localStorage !== 'undefined' ? localStorage.getItem('supabase_connection') : null;
const savedCredentials = typeof localStorage !== 'undefined' ? localStorage.getItem('supabaseCredentials') : null;
const storage =
typeof globalThis !== 'undefined' &&
typeof globalThis.localStorage !== 'undefined' &&
typeof globalThis.localStorage.getItem === 'function'
? globalThis.localStorage
: null;
const savedConnection = storage ? storage.getItem('supabase_connection') : null;
const savedCredentials = storage ? storage.getItem('supabaseCredentials') : null;
const initialState: SupabaseConnectionState = savedConnection
? JSON.parse(savedConnection)
@@ -75,14 +82,14 @@ if (savedCredentials && !initialState.credentials) {
export const supabaseConnection = atom<SupabaseConnectionState>(initialState);
if (initialState.token && !initialState.stats) {
fetchSupabaseStats(initialState.token).catch(console.error);
}
export const isConnecting = atom(false);
export const isFetchingStats = atom(false);
export const isFetchingApiKeys = atom(false);
if (initialState.token && !initialState.stats) {
fetchSupabaseStats(initialState.token).catch(console.error);
}
export function updateSupabaseConnection(connection: Partial<SupabaseConnectionState>) {
const currentState = supabaseConnection.get();
@@ -123,16 +130,16 @@ export function updateSupabaseConnection(connection: Partial<SupabaseConnectionS
* Always save the connection state to localStorage to persist across chats
*/
if (connection.user || connection.token || connection.selectedProjectId !== undefined || connection.credentials) {
localStorage.setItem('supabase_connection', JSON.stringify(newState));
storage?.setItem('supabase_connection', JSON.stringify(newState));
if (newState.credentials) {
localStorage.setItem('supabaseCredentials', JSON.stringify(newState.credentials));
storage?.setItem('supabaseCredentials', JSON.stringify(newState.credentials));
} else {
localStorage.removeItem('supabaseCredentials');
storage?.removeItem('supabaseCredentials');
}
} else {
localStorage.removeItem('supabase_connection');
localStorage.removeItem('supabaseCredentials');
storage?.removeItem('supabase_connection');
storage?.removeItem('supabaseCredentials');
}
}

View File

@@ -9,6 +9,7 @@ import { useEffect } from 'react';
import { DndProvider } from 'react-dnd';
import { HTML5Backend } from 'react-dnd-html5-backend';
import { ClientOnly } from 'remix-utils/client-only';
import { cssTransition, ToastContainer } from 'react-toastify';
import reactToastifyStyles from 'react-toastify/dist/ReactToastify.css?url';
import globalStyles from './styles/index.scss?url';
@@ -16,6 +17,11 @@ import xtermStyles from '@xterm/xterm/css/xterm.css?url';
import 'virtual:uno.css';
const toastAnimation = cssTransition({
enter: 'animated fadeInRight',
exit: 'animated fadeOutRight',
});
export const links: LinksFunction = () => [
{
rel: 'icon',
@@ -75,6 +81,31 @@ export function Layout({ children }: { children: React.ReactNode }) {
return (
<>
<ClientOnly>{() => <DndProvider backend={HTML5Backend}>{children}</DndProvider>}</ClientOnly>
<ToastContainer
closeButton={({ closeToast }) => {
return (
<button className="Toastify__close-button" onClick={closeToast}>
<div className="i-ph:x text-lg" />
</button>
);
}}
icon={({ type }) => {
switch (type) {
case 'success': {
return <div className="i-ph:check-bold text-bolt-elements-icon-success text-2xl" />;
}
case 'error': {
return <div className="i-ph:warning-circle-bold text-bolt-elements-icon-error text-2xl" />;
}
}
return undefined;
}}
position="bottom-right"
pauseOnFocusLoss
transition={toastAnimation}
autoClose={3000}
/>
<ScrollRestoration />
<Scripts />
</>

View File

@@ -0,0 +1,110 @@
import type { LoaderFunction } from '@remix-run/cloudflare';
import { json } from '@remix-run/cloudflare';
import { LLMManager } from '~/lib/modules/llm/manager';
import { LOCAL_PROVIDERS } from '~/lib/stores/settings';
interface ConfiguredProvider {
name: string;
isConfigured: boolean;
configMethod: 'environment' | 'none';
}
interface ConfiguredProvidersResponse {
providers: ConfiguredProvider[];
}
/**
* API endpoint that detects which providers are configured via environment variables
* This helps auto-enable providers that have been set up by the user
*/
export const loader: LoaderFunction = async ({ context }) => {
try {
const llmManager = LLMManager.getInstance(context?.cloudflare?.env as any);
const configuredProviders: ConfiguredProvider[] = [];
// Check each local provider for environment configuration
for (const providerName of LOCAL_PROVIDERS) {
const providerInstance = llmManager.getProvider(providerName);
let isConfigured = false;
let configMethod: 'environment' | 'none' = 'none';
if (providerInstance) {
const config = providerInstance.config;
/*
* Check if required environment variables are set
* For providers with baseUrlKey (Ollama, LMStudio, OpenAILike)
*/
if (config.baseUrlKey) {
const baseUrlEnvVar = config.baseUrlKey;
const cloudflareEnv = (context?.cloudflare?.env as Record<string, any>)?.[baseUrlEnvVar];
const processEnv = process.env[baseUrlEnvVar];
const managerEnv = llmManager.env[baseUrlEnvVar];
const envBaseUrl = cloudflareEnv || processEnv || managerEnv;
/*
* Only consider configured if environment variable is explicitly set
* Don't count default config.baseUrl values or placeholder values
*/
const isValidEnvValue =
envBaseUrl &&
typeof envBaseUrl === 'string' &&
envBaseUrl.trim().length > 0 &&
!envBaseUrl.includes('your_') && // Filter out placeholder values like "your_openai_like_base_url_here"
!envBaseUrl.includes('_here') &&
envBaseUrl.startsWith('http'); // Must be a valid URL
if (isValidEnvValue) {
isConfigured = true;
configMethod = 'environment';
}
}
// For providers that might need API keys as well (check this separately, not as fallback)
if (config.apiTokenKey && !isConfigured) {
const apiTokenEnvVar = config.apiTokenKey;
const envApiToken =
(context?.cloudflare?.env as Record<string, any>)?.[apiTokenEnvVar] ||
process.env[apiTokenEnvVar] ||
llmManager.env[apiTokenEnvVar];
// Only consider configured if API key is set and not a placeholder
const isValidApiToken =
envApiToken &&
typeof envApiToken === 'string' &&
envApiToken.trim().length > 0 &&
!envApiToken.includes('your_') && // Filter out placeholder values
!envApiToken.includes('_here') &&
envApiToken.length > 10; // API keys are typically longer than 10 chars
if (isValidApiToken) {
isConfigured = true;
configMethod = 'environment';
}
}
}
configuredProviders.push({
name: providerName,
isConfigured,
configMethod,
});
}
return json<ConfiguredProvidersResponse>({
providers: configuredProviders,
});
} catch (error) {
console.error('Error detecting configured providers:', error);
// Return default state on error
return json<ConfiguredProvidersResponse>({
providers: LOCAL_PROVIDERS.map((name) => ({
name,
isConfigured: false,
configMethod: 'none' as const,
})),
});
}
};

View File

@@ -46,8 +46,10 @@ export default function WebContainerPreview() {
}, [previewId, previewUrl]);
useEffect(() => {
// Initialize broadcast channel
broadcastChannelRef.current = new BroadcastChannel(PREVIEW_CHANNEL);
const supportsBroadcastChannel = typeof window !== 'undefined' && typeof window.BroadcastChannel === 'function';
if (supportsBroadcastChannel) {
broadcastChannelRef.current = new window.BroadcastChannel(PREVIEW_CHANNEL);
// Listen for preview updates
broadcastChannelRef.current.onmessage = (event) => {
@@ -57,6 +59,9 @@ export default function WebContainerPreview() {
}
}
};
} else {
broadcastChannelRef.current = undefined;
}
// Construct the WebContainer preview URL
const url = `https://${previewId}.local-credentialless.webcontainer-api.io`;

View File

@@ -1,3 +1,9 @@
@use '../z-index';
.Toastify__toast-container {
@extend .z-toast;
}
.Toastify__toast {
--at-apply: shadow-md;

View File

@@ -31,3 +31,7 @@ $zIndexMax: 999;
.z-max {
z-index: $zIndexMax;
}
.z-toast {
z-index: $zIndexMax + 1;
}

View File

@@ -38,7 +38,9 @@ services:
app-dev:
image: bolt-ai:development
build:
target: bolt-ai-development
context: .
dockerfile: Dockerfile
target: development
env_file:
- '.env'
- '.env.local'

34848
package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -24,7 +24,7 @@
"dockerstart": "bindings=$(./bindings.sh) && wrangler pages dev ./build/client $bindings --ip 0.0.0.0 --port 5173 --no-show-interactive-dev-session",
"dockerrun": "docker run -it -d --name bolt-ai-live -p 5173:5173 --env-file .env.local bolt-ai",
"dockerbuild:prod": "docker build -t bolt-ai:production -t bolt-ai:latest --target bolt-ai-production .",
"dockerbuild": "docker build -t bolt-ai:development -t bolt-ai:latest --target bolt-ai-development .",
"dockerbuild": "docker build -t bolt-ai:development -t bolt-ai:latest --target development .",
"typecheck": "tsc",
"typegen": "wrangler types",
"preview": "pnpm run build && pnpm run start",
@@ -161,7 +161,7 @@
},
"devDependencies": {
"@blitz/eslint-plugin": "0.1.0",
"@cloudflare/workers-types": "^4.20241127.0",
"@cloudflare/workers-types": "^4.20251011.0",
"@electron/notarize": "^2.5.0",
"@iconify-json/ph": "^1.2.1",
"@iconify/types": "^2.0.0",
@@ -204,7 +204,7 @@
"vite-plugin-optimize-css-modules": "^1.1.0",
"vite-tsconfig-paths": "^4.3.2",
"vitest": "^2.1.7",
"wrangler": "^4.5.1"
"wrangler": "^4.44.0"
},
"resolutions": {
"@typescript-eslint/utils": "^8.0.0-alpha.30"

152
pnpm-lock.yaml generated
View File

@@ -157,10 +157,10 @@ importers:
version: 1.2.7(@types/react-dom@18.3.7(@types/react@18.3.23))(@types/react@18.3.23)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
'@remix-run/cloudflare':
specifier: ^2.15.2
version: 2.16.8(@cloudflare/workers-types@4.20250722.0)(typescript@5.8.3)
version: 2.16.8(@cloudflare/workers-types@4.20251014.0)(typescript@5.8.3)
'@remix-run/cloudflare-pages':
specifier: ^2.15.2
version: 2.16.8(@cloudflare/workers-types@4.20250722.0)(typescript@5.8.3)
version: 2.16.8(@cloudflare/workers-types@4.20251014.0)(typescript@5.8.3)
'@remix-run/node':
specifier: ^2.15.2
version: 2.16.8(typescript@5.8.3)
@@ -322,7 +322,7 @@ importers:
version: 0.2.0(@remix-run/react@2.16.8(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.8.3))(@remix-run/server-runtime@2.16.8(typescript@5.8.3))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
remix-utils:
specifier: ^7.7.0
version: 7.7.0(@remix-run/cloudflare@2.16.8(@cloudflare/workers-types@4.20250722.0)(typescript@5.8.3))(@remix-run/node@2.16.8(typescript@5.8.3))(@remix-run/react@2.16.8(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.8.3))(@remix-run/router@1.23.0)(react@18.3.1)(zod@3.25.76)
version: 7.7.0(@remix-run/cloudflare@2.16.8(@cloudflare/workers-types@4.20251014.0)(typescript@5.8.3))(@remix-run/node@2.16.8(typescript@5.8.3))(@remix-run/react@2.16.8(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.8.3))(@remix-run/router@1.23.0)(react@18.3.1)(zod@3.25.76)
rollup-plugin-node-polyfills:
specifier: ^0.2.1
version: 0.2.1
@@ -352,8 +352,8 @@ importers:
specifier: 0.1.0
version: 0.1.0(jiti@1.21.7)(prettier@3.6.2)(typescript@5.8.3)
'@cloudflare/workers-types':
specifier: ^4.20241127.0
version: 4.20250722.0
specifier: ^4.20251011.0
version: 4.20251014.0
'@electron/notarize':
specifier: ^2.5.0
version: 2.5.0
@@ -365,7 +365,7 @@ importers:
version: 2.0.0
'@remix-run/dev':
specifier: ^2.15.2
version: 2.16.8(@remix-run/react@2.16.8(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.8.3))(@remix-run/serve@2.16.8(typescript@5.8.3))(@types/node@24.1.0)(sass-embedded@1.89.2)(typescript@5.8.3)(vite@5.4.19(@types/node@24.1.0)(sass-embedded@1.89.2))(wrangler@4.25.1(@cloudflare/workers-types@4.20250722.0))
version: 2.16.8(@remix-run/react@2.16.8(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.8.3))(@remix-run/serve@2.16.8(typescript@5.8.3))(@types/node@24.1.0)(sass-embedded@1.89.2)(typescript@5.8.3)(vite@5.4.19(@types/node@24.1.0)(sass-embedded@1.89.2))(wrangler@4.44.0(@cloudflare/workers-types@4.20251014.0))
'@remix-run/serve':
specifier: ^2.15.2
version: 2.16.8(typescript@5.8.3)
@@ -419,7 +419,7 @@ importers:
version: 33.4.11
electron-builder:
specifier: ^26.0.12
version: 26.0.12(electron-builder-squirrel-windows@26.0.12(dmg-builder@26.0.12))
version: 26.0.12(electron-builder-squirrel-windows@26.0.12)
eslint-config-prettier:
specifier: ^10.1.1
version: 10.1.8(eslint@9.31.0(jiti@1.21.7))
@@ -481,8 +481,8 @@ importers:
specifier: ^2.1.7
version: 2.1.9(@types/node@24.1.0)(jsdom@26.1.0)(sass-embedded@1.89.2)
wrangler:
specifier: ^4.5.1
version: 4.25.1(@cloudflare/workers-types@4.20250722.0)
specifier: ^4.44.0
version: 4.44.0(@cloudflare/workers-types@4.20251014.0)
packages:
@@ -954,47 +954,47 @@ packages:
resolution: {integrity: sha512-+tv3z+SPp+gqTIcImN9o0hqE9xyfQjI1XD9pL6NuKjua9B1y7mNYv0S9cP+QEbA4ppVgGZEmKOvHX5G5Ei1CVA==}
engines: {node: '>=18.0.0'}
'@cloudflare/unenv-preset@2.3.3':
resolution: {integrity: sha512-/M3MEcj3V2WHIRSW1eAQBPRJ6JnGQHc6JKMAPLkDb7pLs3m6X9ES/+K3ceGqxI6TKeF32AWAi7ls0AYzVxCP0A==}
'@cloudflare/unenv-preset@2.7.8':
resolution: {integrity: sha512-Ky929MfHh+qPhwCapYrRPwPVHtA2Ioex/DbGZyskGyNRDe9Ru3WThYZivyNVaPy5ergQSgMs9OKrM9Ajtz9F6w==}
peerDependencies:
unenv: 2.0.0-rc.17
workerd: ^1.20250508.0
unenv: 2.0.0-rc.21
workerd: ^1.20250927.0
peerDependenciesMeta:
workerd:
optional: true
'@cloudflare/workerd-darwin-64@1.20250712.0':
resolution: {integrity: sha512-M6S6a/LQ0Jb0R+g0XhlYi1adGifvYmxA5mD/i9TuZZgjs2bIm5ELuka/n3SCnI98ltvlx3HahRaHagAtOilsFg==}
'@cloudflare/workerd-darwin-64@1.20251011.0':
resolution: {integrity: sha512-0DirVP+Z82RtZLlK2B+VhLOkk+ShBqDYO/jhcRw4oVlp0TOvk3cOVZChrt3+y3NV8Y/PYgTEywzLKFSziK4wCg==}
engines: {node: '>=16'}
cpu: [x64]
os: [darwin]
'@cloudflare/workerd-darwin-arm64@1.20250712.0':
resolution: {integrity: sha512-7sFzn6rvAcnLy7MktFL42dYtzL0Idw/kiUmNf2P3TvsBRoShhLK5ZKhbw+NAhvU8e4pXWm5lkE0XmpieA0zNjw==}
'@cloudflare/workerd-darwin-arm64@1.20251011.0':
resolution: {integrity: sha512-1WuFBGwZd15p4xssGN/48OE2oqokIuc51YvHvyNivyV8IYnAs3G9bJNGWth1X7iMDPe4g44pZrKhRnISS2+5dA==}
engines: {node: '>=16'}
cpu: [arm64]
os: [darwin]
'@cloudflare/workerd-linux-64@1.20250712.0':
resolution: {integrity: sha512-EFRrGe/bqK7NHtht7vNlbrDpfvH3eRvtJOgsTpEQEysDjVmlK6pVJxSnLy9Hg1zlLY15IfhfGC+K2qisseHGJQ==}
'@cloudflare/workerd-linux-64@1.20251011.0':
resolution: {integrity: sha512-BccMiBzFlWZyFghIw2szanmYJrJGBGHomw2y/GV6pYXChFzMGZkeCEMfmCyJj29xczZXxcZmUVJxNy4eJxO8QA==}
engines: {node: '>=16'}
cpu: [x64]
os: [linux]
'@cloudflare/workerd-linux-arm64@1.20250712.0':
resolution: {integrity: sha512-rG8JUleddhUHQVwpXOYv0VbL0S9kOtR9PNKecgVhFpxEhC8aTeg2HNBBjo8st7IfcUvY8WaW3pD3qdAMZ05UwQ==}
'@cloudflare/workerd-linux-arm64@1.20251011.0':
resolution: {integrity: sha512-79o/216lsbAbKEVDZYXR24ivEIE2ysDL9jvo0rDTkViLWju9dAp3CpyetglpJatbSi3uWBPKZBEOqN68zIjVsQ==}
engines: {node: '>=16'}
cpu: [arm64]
os: [linux]
'@cloudflare/workerd-windows-64@1.20250712.0':
resolution: {integrity: sha512-qS8H5RCYwE21Om9wo5/F807ClBJIfknhuLBj16eYxvJcj9JqgAKWi12BGgjyGxHuJJjeoQ63lr4wHAdbFntDDg==}
'@cloudflare/workerd-windows-64@1.20251011.0':
resolution: {integrity: sha512-RIXUQRchFdqEvaUqn1cXZXSKjpqMaSaVAkI5jNZ8XzAw/bw2bcdOVUtakrflgxDprltjFb0PTNtuss1FKtH9Jg==}
engines: {node: '>=16'}
cpu: [x64]
os: [win32]
'@cloudflare/workers-types@4.20250722.0':
resolution: {integrity: sha512-pTY+A07DTSacgUBYcVEEb78/KG7THdcRpPqXLeH/A/LHHobAddgN4zyXBldsoZuzy7bD9tZYJW+wkcyR4k7fDA==}
'@cloudflare/workers-types@4.20251014.0':
resolution: {integrity: sha512-tEW98J/kOa0TdylIUOrLKRdwkUw0rvvYVlo+Ce0mqRH3c8kSoxLzUH9gfCvwLe0M89z1RkzFovSKAW2Nwtyn3w==}
'@codemirror/autocomplete@6.18.6':
resolution: {integrity: sha512-PHHBXFomUs5DF+9tCOM/UoW6XQ4R44lLNNhRaW9PKPTU0D7lIjRg3ElxaJnTwsl/oHiR93WSXDBrekhoUGCPtg==}
@@ -6068,8 +6068,8 @@ packages:
resolution: {integrity: sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==}
engines: {node: '>=4'}
miniflare@4.20250712.1:
resolution: {integrity: sha512-46gB3FGPOsy+EpFGufjhr8agYycO/55d6l0y7hNJ13NcTVwrObMg/0HmI3pC5yQj0974IVXzBgUfDBMAX6thow==}
miniflare@4.20251011.0:
resolution: {integrity: sha512-DlZ7vR5q/RE9eLsxsrXzfSZIF2f6O5k0YsFrSKhWUtdefyGtJt4sSpR6V+Af/waaZ6+zIFy9lsknHBCm49sEYA==}
engines: {node: '>=18.0.0'}
hasBin: true
@@ -7765,12 +7765,12 @@ packages:
resolution: {integrity: sha512-gBLkYIlEnSp8pFbT64yFgGE6UIB9tAkhukC23PmMDCe5Nd+cRqKxSjw5y54MK2AZMgZfJWMaNE4nYUHgi1XEOw==}
engines: {node: '>=18.17'}
undici@7.12.0:
resolution: {integrity: sha512-GrKEsc3ughskmGA9jevVlIOPMiiAHJ4OFUtaAH+NhfTUSiZ1wMPIQqQvAJUrJspFXJt3EBWgpAeoHEDVT1IBug==}
undici@7.14.0:
resolution: {integrity: sha512-Vqs8HTzjpQXZeXdpsfChQTlafcMQaaIwnGwLam1wudSSjlJeQ3bw1j+TLPePgrCnCpUXx7Ba5Pdpf5OBih62NQ==}
engines: {node: '>=20.18.1'}
unenv@2.0.0-rc.17:
resolution: {integrity: sha512-B06u0wXkEd+o5gOCMl/ZHl5cfpYbDZKAT+HWTL+Hws6jWu7dCiqBBXXXzMFcFVJb8D4ytAnYmxJA83uwOQRSsg==}
unenv@2.0.0-rc.21:
resolution: {integrity: sha512-Wj7/AMtE9MRnAXa6Su3Lk0LNCfqDYgfwVjwRFVum9U7wsto1imuHqk4kTm7Jni+5A0Hn7dttL6O/zjvUvoo+8A==}
unified@10.1.2:
resolution: {integrity: sha512-pUSWAi/RAnVy1Pif2kAoeWNBa3JVrx0MId2LASj8G+7AiHWoKZNTomq6LG326T68U7/e263X6fTdcXIy7XnF7Q==}
@@ -8137,17 +8137,17 @@ packages:
resolution: {integrity: sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==}
engines: {node: '>=0.10.0'}
workerd@1.20250712.0:
resolution: {integrity: sha512-7h+k1OxREpiZW0849g0uQNexRWMcs5i5gUGhJzCY8nIx6Tv4D/ndlXJ47lEFj7/LQdp165IL9dM2D5uDiedZrg==}
workerd@1.20251011.0:
resolution: {integrity: sha512-Dq35TLPEJAw7BuYQMkN3p9rge34zWMU2Gnd4DSJFeVqld4+DAO2aPG7+We2dNIAyM97S8Y9BmHulbQ00E0HC7Q==}
engines: {node: '>=16'}
hasBin: true
wrangler@4.25.1:
resolution: {integrity: sha512-4Tlg+jmqxCX3xFm+Nz1b4jHHY9iOu1EyJ17SSCCJ6MGp+FCGtXgr+CynT94+MP0v/qKQUkMKjoeJ5FNDunZ9cA==}
wrangler@4.44.0:
resolution: {integrity: sha512-BLOUigckcWZ0r4rm7b5PuaTpb9KP9as0XeCRSJ8kqcNgXcKoUD3Ij8FlPvN25KybLnFnetaO0ZdfRYUPWle4qw==}
engines: {node: '>=18.0.0'}
hasBin: true
peerDependencies:
'@cloudflare/workers-types': ^4.20250712.0
'@cloudflare/workers-types': ^4.20251011.0
peerDependenciesMeta:
'@cloudflare/workers-types':
optional: true
@@ -9104,28 +9104,28 @@ snapshots:
dependencies:
mime: 3.0.0
'@cloudflare/unenv-preset@2.3.3(unenv@2.0.0-rc.17)(workerd@1.20250712.0)':
'@cloudflare/unenv-preset@2.7.8(unenv@2.0.0-rc.21)(workerd@1.20251011.0)':
dependencies:
unenv: 2.0.0-rc.17
unenv: 2.0.0-rc.21
optionalDependencies:
workerd: 1.20250712.0
workerd: 1.20251011.0
'@cloudflare/workerd-darwin-64@1.20250712.0':
'@cloudflare/workerd-darwin-64@1.20251011.0':
optional: true
'@cloudflare/workerd-darwin-arm64@1.20250712.0':
'@cloudflare/workerd-darwin-arm64@1.20251011.0':
optional: true
'@cloudflare/workerd-linux-64@1.20250712.0':
'@cloudflare/workerd-linux-64@1.20251011.0':
optional: true
'@cloudflare/workerd-linux-arm64@1.20250712.0':
'@cloudflare/workerd-linux-arm64@1.20251011.0':
optional: true
'@cloudflare/workerd-windows-64@1.20250712.0':
'@cloudflare/workerd-windows-64@1.20251011.0':
optional: true
'@cloudflare/workers-types@4.20250722.0': {}
'@cloudflare/workers-types@4.20251014.0': {}
'@codemirror/autocomplete@6.18.6':
dependencies:
@@ -10765,22 +10765,22 @@ snapshots:
dependencies:
react: 18.3.1
'@remix-run/cloudflare-pages@2.16.8(@cloudflare/workers-types@4.20250722.0)(typescript@5.8.3)':
'@remix-run/cloudflare-pages@2.16.8(@cloudflare/workers-types@4.20251014.0)(typescript@5.8.3)':
dependencies:
'@cloudflare/workers-types': 4.20250722.0
'@remix-run/cloudflare': 2.16.8(@cloudflare/workers-types@4.20250722.0)(typescript@5.8.3)
'@cloudflare/workers-types': 4.20251014.0
'@remix-run/cloudflare': 2.16.8(@cloudflare/workers-types@4.20251014.0)(typescript@5.8.3)
optionalDependencies:
typescript: 5.8.3
'@remix-run/cloudflare@2.16.8(@cloudflare/workers-types@4.20250722.0)(typescript@5.8.3)':
'@remix-run/cloudflare@2.16.8(@cloudflare/workers-types@4.20251014.0)(typescript@5.8.3)':
dependencies:
'@cloudflare/kv-asset-handler': 0.1.3
'@cloudflare/workers-types': 4.20250722.0
'@cloudflare/workers-types': 4.20251014.0
'@remix-run/server-runtime': 2.16.8(typescript@5.8.3)
optionalDependencies:
typescript: 5.8.3
'@remix-run/dev@2.16.8(@remix-run/react@2.16.8(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.8.3))(@remix-run/serve@2.16.8(typescript@5.8.3))(@types/node@24.1.0)(sass-embedded@1.89.2)(typescript@5.8.3)(vite@5.4.19(@types/node@24.1.0)(sass-embedded@1.89.2))(wrangler@4.25.1(@cloudflare/workers-types@4.20250722.0))':
'@remix-run/dev@2.16.8(@remix-run/react@2.16.8(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.8.3))(@remix-run/serve@2.16.8(typescript@5.8.3))(@types/node@24.1.0)(sass-embedded@1.89.2)(typescript@5.8.3)(vite@5.4.19(@types/node@24.1.0)(sass-embedded@1.89.2))(wrangler@4.44.0(@cloudflare/workers-types@4.20251014.0))':
dependencies:
'@babel/core': 7.28.0
'@babel/generator': 7.28.0
@@ -10843,7 +10843,7 @@ snapshots:
'@remix-run/serve': 2.16.8(typescript@5.8.3)
typescript: 5.8.3
vite: 5.4.19(@types/node@24.1.0)(sass-embedded@1.89.2)
wrangler: 4.25.1(@cloudflare/workers-types@4.20250722.0)
wrangler: 4.44.0(@cloudflare/workers-types@4.20251014.0)
transitivePeerDependencies:
- '@types/node'
- babel-plugin-macros
@@ -12074,7 +12074,7 @@ snapshots:
app-builder-bin@5.0.0-alpha.12: {}
app-builder-lib@26.0.12(dmg-builder@26.0.12(electron-builder-squirrel-windows@26.0.12))(electron-builder-squirrel-windows@26.0.12(dmg-builder@26.0.12)):
app-builder-lib@26.0.12(dmg-builder@26.0.12)(electron-builder-squirrel-windows@26.0.12):
dependencies:
'@develar/schema-utils': 2.6.5
'@electron/asar': 3.2.18
@@ -12887,7 +12887,7 @@ snapshots:
dmg-builder@26.0.12(electron-builder-squirrel-windows@26.0.12):
dependencies:
app-builder-lib: 26.0.12(dmg-builder@26.0.12(electron-builder-squirrel-windows@26.0.12))(electron-builder-squirrel-windows@26.0.12(dmg-builder@26.0.12))
app-builder-lib: 26.0.12(dmg-builder@26.0.12)(electron-builder-squirrel-windows@26.0.12)
builder-util: 26.0.11
builder-util-runtime: 9.3.1
fs-extra: 10.1.0
@@ -12966,7 +12966,7 @@ snapshots:
electron-builder-squirrel-windows@26.0.12(dmg-builder@26.0.12):
dependencies:
app-builder-lib: 26.0.12(dmg-builder@26.0.12(electron-builder-squirrel-windows@26.0.12))(electron-builder-squirrel-windows@26.0.12(dmg-builder@26.0.12))
app-builder-lib: 26.0.12(dmg-builder@26.0.12)(electron-builder-squirrel-windows@26.0.12)
builder-util: 26.0.11
electron-winstaller: 5.4.0
transitivePeerDependencies:
@@ -12974,9 +12974,9 @@ snapshots:
- dmg-builder
- supports-color
electron-builder@26.0.12(electron-builder-squirrel-windows@26.0.12(dmg-builder@26.0.12)):
electron-builder@26.0.12(electron-builder-squirrel-windows@26.0.12):
dependencies:
app-builder-lib: 26.0.12(dmg-builder@26.0.12(electron-builder-squirrel-windows@26.0.12))(electron-builder-squirrel-windows@26.0.12(dmg-builder@26.0.12))
app-builder-lib: 26.0.12(dmg-builder@26.0.12)(electron-builder-squirrel-windows@26.0.12)
builder-util: 26.0.11
builder-util-runtime: 9.3.1
chalk: 4.1.2
@@ -15269,7 +15269,7 @@ snapshots:
min-indent@1.0.1: {}
miniflare@4.20250712.1:
miniflare@4.20251011.0:
dependencies:
'@cspotcode/source-map-support': 0.8.1
acorn: 8.14.0
@@ -15278,8 +15278,8 @@ snapshots:
glob-to-regexp: 0.4.1
sharp: 0.33.5
stoppable: 1.1.0
undici: 7.12.0
workerd: 1.20250712.0
undici: 7.14.0
workerd: 1.20251011.0
ws: 8.18.0
youch: 4.1.0-beta.10
zod: 3.22.3
@@ -16229,11 +16229,11 @@ snapshots:
react: 18.3.1
react-dom: 18.3.1(react@18.3.1)
remix-utils@7.7.0(@remix-run/cloudflare@2.16.8(@cloudflare/workers-types@4.20250722.0)(typescript@5.8.3))(@remix-run/node@2.16.8(typescript@5.8.3))(@remix-run/react@2.16.8(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.8.3))(@remix-run/router@1.23.0)(react@18.3.1)(zod@3.25.76):
remix-utils@7.7.0(@remix-run/cloudflare@2.16.8(@cloudflare/workers-types@4.20251014.0)(typescript@5.8.3))(@remix-run/node@2.16.8(typescript@5.8.3))(@remix-run/react@2.16.8(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.8.3))(@remix-run/router@1.23.0)(react@18.3.1)(zod@3.25.76):
dependencies:
type-fest: 4.41.0
optionalDependencies:
'@remix-run/cloudflare': 2.16.8(@cloudflare/workers-types@4.20250722.0)(typescript@5.8.3)
'@remix-run/cloudflare': 2.16.8(@cloudflare/workers-types@4.20251014.0)(typescript@5.8.3)
'@remix-run/node': 2.16.8(typescript@5.8.3)
'@remix-run/react': 2.16.8(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.8.3)
'@remix-run/router': 1.23.0
@@ -17072,9 +17072,9 @@ snapshots:
undici@6.21.3: {}
undici@7.12.0: {}
undici@7.14.0: {}
unenv@2.0.0-rc.17:
unenv@2.0.0-rc.21:
dependencies:
defu: 6.1.4
exsolve: 1.0.7
@@ -17522,26 +17522,26 @@ snapshots:
word-wrap@1.2.5: {}
workerd@1.20250712.0:
workerd@1.20251011.0:
optionalDependencies:
'@cloudflare/workerd-darwin-64': 1.20250712.0
'@cloudflare/workerd-darwin-arm64': 1.20250712.0
'@cloudflare/workerd-linux-64': 1.20250712.0
'@cloudflare/workerd-linux-arm64': 1.20250712.0
'@cloudflare/workerd-windows-64': 1.20250712.0
'@cloudflare/workerd-darwin-64': 1.20251011.0
'@cloudflare/workerd-darwin-arm64': 1.20251011.0
'@cloudflare/workerd-linux-64': 1.20251011.0
'@cloudflare/workerd-linux-arm64': 1.20251011.0
'@cloudflare/workerd-windows-64': 1.20251011.0
wrangler@4.25.1(@cloudflare/workers-types@4.20250722.0):
wrangler@4.44.0(@cloudflare/workers-types@4.20251014.0):
dependencies:
'@cloudflare/kv-asset-handler': 0.4.0
'@cloudflare/unenv-preset': 2.3.3(unenv@2.0.0-rc.17)(workerd@1.20250712.0)
'@cloudflare/unenv-preset': 2.7.8(unenv@2.0.0-rc.21)(workerd@1.20251011.0)
blake3-wasm: 2.1.5
esbuild: 0.25.4
miniflare: 4.20250712.1
miniflare: 4.20251011.0
path-to-regexp: 6.3.0
unenv: 2.0.0-rc.17
workerd: 1.20250712.0
unenv: 2.0.0-rc.21
workerd: 1.20251011.0
optionalDependencies:
'@cloudflare/workers-types': 4.20250722.0
'@cloudflare/workers-types': 4.20251014.0
fsevents: 2.3.3
transitivePeerDependencies:
- bufferutil