Skip to content

Commit

Permalink
feat: improvement upload files and complete folders to chat from local
Browse files Browse the repository at this point in the history
Added ability to upload local files directly into the chat interface
Added support for uploading folders with original foldername
Integrated file contents seamlessly into the chat history
Real-time parsing and display of uploaded files in the workbench

Thanks to muzafferkadir
  • Loading branch information
Stijnus committed Nov 5, 2024
1 parent 7bb967a commit ad17cd0
Show file tree
Hide file tree
Showing 2 changed files with 50 additions and 48 deletions.
39 changes: 22 additions & 17 deletions app/components/chat/Chat.client.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -131,24 +131,29 @@ export const ChatImpl = memo(({ initialMessages, storeMessageHistory }: ChatProp

input.onchange = async (e) => {
const files = Array.from(e.target.files);
const randomID = Math.random().toString(36).substring(2, 15);

// Get folder name from first file's path
const folderName = files[0].webkitRelativePath.split('/')[0];

// Create one message for the entire folder
const newMessage = {
id: randomID,
role: 'assistant',
content: `Folder Added: ${folderName} <boltArtifact id="${randomID}" title="${folderName}">
${files.map(file => {
const relativePath = file.webkitRelativePath;
return `<boltAction type="file" filePath="${relativePath}">
${file.text()}
</boltAction>`;
}).join('\n')}
</boltArtifact>`,
createdAt: Date.now()
};

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);
}
messages.push(newMessage);
await storeMessageHistory(messages);
parseMessages(messages, false);
};

input.click();
Expand Down
59 changes: 28 additions & 31 deletions app/lib/stores/workbench.ts
Original file line number Diff line number Diff line change
Expand Up @@ -336,36 +336,33 @@ 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');
if (!ghToken) {
throw new Error('GitHub token is not set');
}

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

// Check if the repository already exists before creating it
let repo
// Check if repository exists or create it
let repoData;
try {
repo = await octokit.repos.get({ owner: owner, repo: repoName });
const { data } = await octokit.repos.get({
owner,
repo: repoName
});
repoData = data;
} catch (error) {
if (error instanceof Error && 'status' in error && error.status === 404) {
// Repository doesn't exist, so create a new one
const { data: newRepo } = await octokit.repos.createForAuthenticatedUser({
const { data } = await octokit.repos.createForAuthenticatedUser({
name: repoName,
private: false,
auto_init: true,
});
repo = newRepo;
repoData = data;
} else {
console.log('cannot create repo!');
throw error; // Some other error occurred
throw error;
}
}

Expand All @@ -380,8 +377,8 @@ export class WorkbenchStore {
Object.entries(files).map(async ([filePath, dirent]) => {
if (dirent?.type === 'file' && dirent.content) {
const { data: blob } = await octokit.git.createBlob({
owner: repo.owner.login,
repo: repo.name,
owner,
repo: repoName,
content: Buffer.from(dirent.content).toString('base64'),
encoding: 'base64',
});
Expand All @@ -390,24 +387,24 @@ export class WorkbenchStore {
})
);

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

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

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

// Create a new tree
const { data: newTree } = await octokit.git.createTree({
owner: repo.owner.login,
repo: repo.name,
owner,
repo: repoName,
base_tree: latestCommitSha,
tree: validBlobs.map((blob) => ({
path: blob!.path,
Expand All @@ -419,22 +416,22 @@ export class WorkbenchStore {

// Create a new commit
const { data: newCommit } = await octokit.git.createCommit({
owner: repo.owner.login,
repo: repo.name,
owner,
repo: repoName,
message: 'Initial commit from your app',
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
owner,
repo: repoName,
ref: 'heads/main',
sha: newCommit.sha,
});

alert(`Repository created and code pushed: ${repo.html_url}`);
alert(`Repository created and code pushed: https://github.com/${owner}/${repoName}`);
} catch (error) {
console.error('Error pushing to GitHub:', error instanceof Error ? error.message : String(error));
}
Expand Down

0 comments on commit ad17cd0

Please sign in to comment.