Skip to content

Commit 3a566c7

Browse files
mrjasonroyclaude
andcommitted
feat: auto-enable file-generator tool when storage is configured
Automatically enables the file-generator tool by default if file storage (Vercel Blob or S3) is properly configured. This provides a better out-of-box experience while maintaining the ability for users to toggle it off if desired. Changes: - Add isFileStorageConfigured() helper to detect storage setup - Create /api/storage/config endpoint to expose storage status - Add FileStorageInitializer component to auto-enable tool on mount - Update app layout to include storage initializer - Add comment in store about dynamic FileGenerator addition The tool is now enabled by default when: - BLOB_READ_WRITE_TOKEN is set (Vercel Blob), OR - FILE_STORAGE_TYPE=s3 and FILE_STORAGE_S3_BUCKET are set (S3) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]>
1 parent bd8f27e commit 3a566c7

File tree

5 files changed

+86
-0
lines changed

5 files changed

+86
-0
lines changed
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
import { isFileStorageConfigured } from "@/lib/file-storage/is-storage-configured";
2+
import { NextResponse } from "next/server";
3+
4+
export async function GET() {
5+
const configured = isFileStorageConfigured();
6+
return NextResponse.json({ configured });
7+
}

src/app/layout.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import {
99
import { Toaster } from "ui/sonner";
1010
import { NextIntlClientProvider } from "next-intl";
1111
import { getLocale } from "next-intl/server";
12+
import { FileStorageInitializer } from "@/components/file-storage-initializer";
1213
const geistSans = Geist({
1314
variable: "--font-geist-sans",
1415
subsets: ["latin"],
@@ -45,6 +46,7 @@ export default async function RootLayout({
4546
>
4647
<ThemeStyleProvider>
4748
<NextIntlClientProvider>
49+
<FileStorageInitializer />
4850
<div id="root">
4951
{children}
5052
<Toaster richColors />

src/app/store/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,8 @@ const initialState: AppState = {
8888
allowedAppDefaultToolkit: [
8989
AppDefaultToolkit.Code,
9090
AppDefaultToolkit.Visualization,
91+
AppDefaultToolkit.WebSearch,
92+
// FileGenerator will be added dynamically if storage is configured
9193
],
9294
toolPresets: [],
9395
chatModel: undefined,
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
"use client";
2+
3+
import { appStore } from "@/app/store";
4+
import { AppDefaultToolkit } from "@/lib/ai/tools";
5+
import { useEffect } from "react";
6+
import { useShallow } from "zustand/shallow";
7+
8+
/**
9+
* Initializes file-generator tool if file storage is configured.
10+
* This runs once on app mount and adds FileGenerator to the default toolkit.
11+
*/
12+
export function FileStorageInitializer() {
13+
const [allowedAppDefaultToolkit, appStoreMutate] = appStore(
14+
useShallow((state) => [state.allowedAppDefaultToolkit, state.mutate]),
15+
);
16+
17+
useEffect(() => {
18+
// Only run once on mount
19+
const checkStorageAndInit = async () => {
20+
try {
21+
const response = await fetch("/api/storage/config");
22+
const data = await response.json();
23+
24+
if (data.configured) {
25+
// Check if FileGenerator is already in the list
26+
const hasFileGenerator = allowedAppDefaultToolkit?.includes(
27+
AppDefaultToolkit.FileGenerator,
28+
);
29+
30+
if (!hasFileGenerator) {
31+
// Add FileGenerator to the default toolkit
32+
appStoreMutate((prev) => ({
33+
allowedAppDefaultToolkit: [
34+
...(prev.allowedAppDefaultToolkit || []),
35+
AppDefaultToolkit.FileGenerator,
36+
],
37+
}));
38+
}
39+
}
40+
} catch (error) {
41+
console.error("Failed to check file storage config:", error);
42+
}
43+
};
44+
45+
checkStorageAndInit();
46+
// eslint-disable-next-line react-hooks/exhaustive-deps
47+
}, []); // Only run once on mount
48+
49+
return null; // This component doesn't render anything
50+
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
import "server-only";
2+
3+
/**
4+
* Checks if file storage is properly configured.
5+
* Returns true if either Vercel Blob or S3 credentials are available.
6+
*/
7+
export function isFileStorageConfigured(): boolean {
8+
// Check for Vercel Blob token
9+
if (process.env.BLOB_READ_WRITE_TOKEN) {
10+
return true;
11+
}
12+
13+
// Check for S3 configuration
14+
const hasS3Bucket = Boolean(process.env.FILE_STORAGE_S3_BUCKET);
15+
const hasS3Type = process.env.FILE_STORAGE_TYPE === "s3";
16+
17+
// S3 is considered configured if:
18+
// 1. FILE_STORAGE_TYPE is set to "s3" AND bucket is specified
19+
// 2. Will work with either explicit credentials OR IAM role (in AWS environment)
20+
if (hasS3Type && hasS3Bucket) {
21+
return true; // Assume IAM role or credentials are available
22+
}
23+
24+
return false;
25+
}

0 commit comments

Comments
 (0)