Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: upload files or folders to chat from local #162

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
59 changes: 59 additions & 0 deletions app/components/chat/Chat.client.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,65 @@ export const ChatImpl = memo(({ initialMessages, storeMessageHistory }: ChatProp

const TEXTAREA_MAX_HEIGHT = chatStarted ? 400 : 200;

const addCustomFile = async () => {
const input = document.createElement('input');
input.type = 'file';

input.onchange = async (e) => {
const file = e.target.files[0];
const randomID = Math.random().toString(36).substring(2, 15);
const fileName = file.name;

const content = await file.text();

const newMessage = {
id: randomID,
role: 'assistant',
content: `File Added: ${fileName} <boltArtifact id="${randomID}" title="${fileName}">\n <boltAction type="file" filePath="${fileName}">\n ${content}\n </boltAction>\n</boltArtifact>`,
createdAt: Date.now(),
};

messages.push(newMessage);
await storeMessageHistory(messages);
parseMessages(messages, false);
};

input.click();
};
workbenchStore.addCustomFile = addCustomFile;

const addCustomFolder = async () => {
const input = document.createElement('input');
input.type = 'file';
input.webkitdirectory = true;
input.multiple = true;

input.onchange = async (e) => {
const files = Array.from(e.target.files);

for (const file of files) {
const randomID = Math.random().toString(36).substring(2, 15);
const fileName = file.name;

const content = await file.text();

const newMessage = {
id: randomID,
role: 'assistant',
content: `File Added: ${fileName} <boltArtifact id="${randomID}" title="${fileName}">\n <boltAction type="file" filePath="${fileName}">\n ${content}\n </boltAction>\n</boltArtifact>`,
createdAt: Date.now(),
};

messages.push(newMessage);
await storeMessageHistory(messages);
parseMessages(messages, false);
}
};

input.click();
};
workbenchStore.addCustomFolder = addCustomFolder;

useEffect(() => {
chatStore.setKey('started', initialMessages.length > 0);
}, []);
Expand Down
18 changes: 18 additions & 0 deletions app/components/workbench/EditorPanel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,24 @@ export const EditorPanel = memo(
<div className="i-ph:tree-structure-duotone shrink-0" />
Files
</PanelHeader>
<PanelHeader>
<button
className="bg-transparent flex gap-2 items-center text-nowrap"
onClick={workbenchStore.addCustomFile}
>
<div className="i-ph:file-arrow-up-duotone shrink-0" />
<span>Upload File</span>
</button>
</PanelHeader>
<PanelHeader>
<button
className="bg-transparent flex gap-2 items-center text-nowrap"
onClick={workbenchStore.addCustomFolder}
>
<div className="i-ph:folder-plus-duotone shrink-0" />
<span>Upload Folder</span>
</button>
</PanelHeader>
<FileTree
className="h-full"
files={files}
Expand Down
36 changes: 22 additions & 14 deletions app/lib/stores/workbench.ts
Original file line number Diff line number Diff line change
Expand Up @@ -336,20 +336,20 @@ export class WorkbenchStore {
}

async pushToGitHub(repoName: string, githubUsername: string, ghToken: string) {

try {
// Get the GitHub auth token from environment variables
const githubToken = ghToken;

const owner = githubUsername;

if (!githubToken) {
throw new Error('GitHub token is not set in environment variables');
}

// Initialize Octokit with the auth token
const octokit = new Octokit({ auth: githubToken });

// Check if the repository already exists before creating it
let repo
try {
Expand All @@ -368,13 +368,13 @@ export class WorkbenchStore {
throw error; // Some other error occurred
}
}

// Get all files
const files = this.files.get();
if (!files || Object.keys(files).length === 0) {
throw new Error('No files found to push');
}

// Create blobs for each file
const blobs = await Promise.all(
Object.entries(files).map(async ([filePath, dirent]) => {
Expand All @@ -389,21 +389,21 @@ export class WorkbenchStore {
}
})
);

const validBlobs = blobs.filter(Boolean); // Filter out any undefined blobs

if (validBlobs.length === 0) {
throw new Error('No valid files to push');
}

// Get the latest commit SHA (assuming main branch, update dynamically if needed)
const { data: ref } = await octokit.git.getRef({
owner: repo.owner.login,
repo: repo.name,
ref: `heads/${repo.default_branch || 'main'}`, // Handle dynamic branch
});
const latestCommitSha = ref.object.sha;

// Create a new tree
const { data: newTree } = await octokit.git.createTree({
owner: repo.owner.login,
Expand All @@ -416,7 +416,7 @@ export class WorkbenchStore {
sha: blob!.sha,
})),
});

// Create a new commit
const { data: newCommit } = await octokit.git.createCommit({
owner: repo.owner.login,
Expand All @@ -425,20 +425,28 @@ export class WorkbenchStore {
tree: newTree.sha,
parents: [latestCommitSha],
});

// Update the reference
await octokit.git.updateRef({
owner: repo.owner.login,
repo: repo.name,
ref: `heads/${repo.default_branch || 'main'}`, // Handle dynamic branch
sha: newCommit.sha,
});

alert(`Repository created and code pushed: ${repo.html_url}`);
} catch (error) {
console.error('Error pushing to GitHub:', error instanceof Error ? error.message : String(error));
}
}

addCustomFile: () => void = () => {
return;
};

addCustomFolder: () => void = () => {
return;
};
}

export const workbenchStore = new WorkbenchStore();
Loading