Leon4gr45 commited on
Commit
c52cc9e
·
verified ·
1 Parent(s): 375cedc

Add GitHub upload page with AI assistant for errors

Browse files
app/api/github-upload/route.ts ADDED
@@ -0,0 +1,43 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import { NextRequest, NextResponse } from 'next/server';
2
+ import simpleGit from 'simple-git';
3
+ import fs from 'fs/promises';
4
+ import path from 'path';
5
+
6
+ export async function POST(req: NextRequest) {
7
+ const { repo, branch } = await req.json();
8
+ const blabladorApiKey = process.env.BLABLADOR_API_KEY;
9
+
10
+ if (!githubToken) {
11
+ console.log('GITHUB_TOKEN environment variable is not set. Please set it in the container logs.');
12
+ return NextResponse.json({ error: 'GitHub token is not configured. Please set the GITHUB_TOKEN environment variable.' }, { status: 500 });
13
+ }
14
+
15
+ if (!blabladorApiKey) {
16
+ console.log('BLABLADOR_API_KEY environment variable is not set. Please set it in the container logs.');
17
+ }
18
+
19
+ if (!repo || !branch) {
20
+ return NextResponse.json({ error: 'Repository and branch are required.' }, { status: 400 });
21
+ }
22
+
23
+ const repoUrl = `https://${githubToken}@github.com/${repo}.git`;
24
+ const tmpDir = '/tmp/github-upload';
25
+
26
+ try {
27
+ await fs.rm(tmpDir, { recursive: true, force: true });
28
+ await fs.mkdir(tmpDir, { recursive: true });
29
+
30
+ const git = simpleGit(tmpDir);
31
+ await git.init();
32
+ await fs.cp(process.cwd(), tmpDir, { recursive: true });
33
+ await git.add('.');
34
+ await git.commit('Initial commit');
35
+ await git.addRemote('origin', repoUrl);
36
+ await git.push('origin', `HEAD:refs/heads/${branch}`, ['--force']);
37
+
38
+ return NextResponse.json({ message: 'Successfully uploaded to GitHub.' });
39
+ } catch (error: any) {
40
+ console.error('GitHub upload failed:', error);
41
+ return NextResponse.json({ error: error.message }, { status: 500 });
42
+ }
43
+ }
app/github/page.tsx ADDED
@@ -0,0 +1,153 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ 'use client';
2
+
3
+ import { useState } from 'react';
4
+
5
+ export default function GitHubUpload() {
6
+ const [repo, setRepo] = useState('');
7
+ const [branch, setBranch] = useState('');
8
+ const [loading, setLoading] = useState(false);
9
+ const [error, setError] = useState<string | null>(null);
10
+ const [success, setSuccess] = useState<string | null>(null);
11
+ const [aiResponse, setAiResponse] = useState<string | null>(null);
12
+ const [aiLoading, setAiLoading] = useState(false);
13
+
14
+ const handleUpload = async () => {
15
+ setLoading(true);
16
+ setError(null);
17
+ setSuccess(null);
18
+ setAiResponse(null);
19
+
20
+ const response = await fetch('/api/github-upload', {
21
+ method: 'POST',
22
+ headers: {
23
+ 'Content-Type': 'application/json',
24
+ },
25
+ body: JSON.stringify({ repo, branch }),
26
+ });
27
+
28
+ const result = await response.json();
29
+
30
+ setLoading(false);
31
+
32
+ if (response.ok) {
33
+ setSuccess(result.message);
34
+ } else {
35
+ setError(result.error);
36
+ }
37
+ };
38
+
39
+ const getAiHelp = async () => {
40
+ if (!error) return;
41
+
42
+ setAiLoading(true);
43
+ setAiResponse(null);
44
+
45
+ const response = await fetch('/api/text-generation', {
46
+ method: 'POST',
47
+ headers: {
48
+ 'Content-Type': 'application/json',
49
+ },
50
+ body: JSON.stringify({
51
+ prompt: `I encountered the following error while trying to upload to GitHub: "${error}". Please help me understand and resolve this issue.`,
52
+ model: 'alias-fast', // Or any other suitable model
53
+ }),
54
+ });
55
+
56
+ if (!response.body) {
57
+ setAiLoading(false);
58
+ return;
59
+ }
60
+
61
+ const reader = response.body.getReader();
62
+ const decoder = new TextDecoder();
63
+ let done = false;
64
+ let fullResponse = '';
65
+
66
+ while (!done) {
67
+ const { value, done: readerDone } = await reader.read();
68
+ done = readerDone;
69
+ const chunkValue = decoder.decode(value);
70
+ fullResponse += chunkValue;
71
+ setAiResponse(fullResponse);
72
+ }
73
+
74
+ setAiLoading(false);
75
+ };
76
+
77
+ return (
78
+ <div className="flex flex-col items-center justify-center min-h-screen py-2">
79
+ <main className="flex flex-col items-center justify-center w-full flex-1 px-20 text-center">
80
+ <h1 className="text-4xl font-bold mb-8">
81
+ Upload to GitHub
82
+ </h1>
83
+
84
+ <div className="w-full max-w-xs">
85
+ <div className="mb-4">
86
+ <label className="block text-gray-700 text-sm font-bold mb-2" htmlFor="repo">
87
+ Repository Name (e.g., your-username/your-repo)
88
+ </label>
89
+ <input
90
+ className="shadow appearance-none border rounded w-full py-2 px-3 text-gray-700 leading-tight focus:outline-none focus:shadow-outline"
91
+ id="repo"
92
+ type="text"
93
+ placeholder="your-username/your-repo"
94
+ value={repo}
95
+ onChange={(e) => setRepo(e.target.value)}
96
+ />
97
+ </div>
98
+ <div className="mb-6">
99
+ <label className="block text-gray-700 text-sm font-bold mb-2" htmlFor="branch">
100
+ Branch
101
+ </label>
102
+ <input
103
+ className="shadow appearance-none border rounded w-full py-2 px-3 text-gray-700 mb-3 leading-tight focus:outline-none focus:shadow-outline"
104
+ id="branch"
105
+ type="text"
106
+ placeholder="main"
107
+ value={branch}
108
+ onChange={(e) => setBranch(e.target.value)}
109
+ />
110
+ </div>
111
+ <div className="flex items-center justify-between">
112
+ <button
113
+ className="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded focus:outline-none focus:shadow-outline"
114
+ type="button"
115
+ onClick={handleUpload}
116
+ disabled={loading}
117
+ >
118
+ {loading ? 'Uploading...' : 'Upload'}
119
+ </button>
120
+ </div>
121
+
122
+ {error && (
123
+ <div className="mt-4 text-red-500">
124
+ <p>Upload failed:</p>
125
+ <p>{error}</p>
126
+ <button
127
+ className="mt-2 bg-gray-500 hover:bg-gray-700 text-white font-bold py-2 px-4 rounded focus:outline-none focus:shadow-outline"
128
+ type="button"
129
+ onClick={getAiHelp}
130
+ disabled={aiLoading}
131
+ >
132
+ {aiLoading ? 'Getting help...' : 'Get help from AI assistant'}
133
+ </button>
134
+ </div>
135
+ )}
136
+
137
+ {aiResponse && (
138
+ <div className="mt-4 p-4 border rounded bg-gray-100 text-left">
139
+ <h3 className="font-bold mb-2">AI Assistant says:</h3>
140
+ <p>{aiResponse}</p>
141
+ </div>
142
+ )}
143
+
144
+ {success && (
145
+ <div className="mt-4 text-green-500">
146
+ <p>{success}</p>
147
+ </div>
148
+ )}
149
+ </div>
150
+ </main>
151
+ </div>
152
+ );
153
+ }
package.json CHANGED
@@ -81,7 +81,8 @@
81
  "tailwind-merge": "^3.3.1",
82
  "tailwindcss-animate": "^1.0.7",
83
  "usehooks-ts": "^3.1.1",
84
- "zod": "^3.25.76"
 
85
  },
86
  "devDependencies": {
87
  "@eslint/eslintrc": "^3",
 
81
  "tailwind-merge": "^3.3.1",
82
  "tailwindcss-animate": "^1.0.7",
83
  "usehooks-ts": "^3.1.1",
84
+ "zod": "^3.25.76",
85
+ "simple-git": "^3.22.0"
86
  },
87
  "devDependencies": {
88
  "@eslint/eslintrc": "^3",