Skip to content

Commit b9601b2

Browse files
author
Arne Durr
committed
Merge branch 'main' of https://github.com/D-Byte/bolt.new-any-llm into main
2 parents 277082a + f69054a commit b9601b2

File tree

10 files changed

+427
-825
lines changed

10 files changed

+427
-825
lines changed

.github/workflows/commit.yaml

+1-1
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ jobs:
2828
2929
- name: Update commit file
3030
run: |
31-
echo "{ \"commit\": \"$COMMIT_HASH\" , \"version\": \"$CURRENT_VERSION\" }" > app/commit.json
31+
echo "{ \"commit\": \"$COMMIT_HASH\", \"version\": \"$CURRENT_VERSION\" }" > app/commit.json
3232
3333
- name: Commit and push the update
3434
run: |

.github/workflows/semantic-pr.yaml

+32
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
name: Semantic Pull Request
2+
on:
3+
pull_request_target:
4+
types: [opened, reopened, edited, synchronize]
5+
permissions:
6+
pull-requests: read
7+
jobs:
8+
main:
9+
name: Validate PR Title
10+
runs-on: ubuntu-latest
11+
steps:
12+
# https://github.com/amannn/action-semantic-pull-request/releases/tag/v5.5.3
13+
- uses: amannn/action-semantic-pull-request@0723387faaf9b38adef4775cd42cfd5155ed6017
14+
env:
15+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
16+
with:
17+
subjectPattern: ^(?![A-Z]).+$
18+
subjectPatternError: |
19+
The subject "{subject}" found in the pull request title "{title}"
20+
didn't match the configured pattern. Please ensure that the subject
21+
doesn't start with an uppercase character.
22+
types: |
23+
fix
24+
feat
25+
chore
26+
build
27+
ci
28+
perf
29+
docs
30+
refactor
31+
revert
32+
test

.github/workflows/update-stable.yml

+2-2
Original file line numberDiff line numberDiff line change
@@ -161,12 +161,12 @@ jobs:
161161
- name: Get the latest commit hash and version tag
162162
run: |
163163
echo "COMMIT_HASH=$(git rev-parse HEAD)" >> $GITHUB_ENV
164-
echo "CURRENT_VERSION=$(node -p "require('./package.json').version")" >> $GITHUB_ENV
164+
echo "NEW_VERSION=${{ steps.bump_version.outputs.new_version }}" >> $GITHUB_ENV
165165
166166
- name: Commit and Tag Release
167167
run: |
168168
git pull
169-
echo "{ \"commit\": \"$COMMIT_HASH\" , \"version\": \"$CURRENT_VERSION\" }" > app/commit.json
169+
echo "{ \"commit\": \"$COMMIT_HASH\", \"version\": \"$NEW_VERSION\" }" > app/commit.json
170170
git add package.json pnpm-lock.yaml changelog.md app/commit.json
171171
git commit -m "chore: release version ${{ steps.bump_version.outputs.new_version }}"
172172
git tag "v${{ steps.bump_version.outputs.new_version }}"

app/commit.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
{ "commit": "0b473658465ac1f65ac4ee80b22101cd1f59183f" , "version": "0.0.1" }
1+
{ "commit": "0ee373629789f01fb9f54f6747735b51a94a5562", "version": "0.0.2" }

app/components/settings/connections/ConnectionsTab.tsx

+116-19
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,93 @@
1-
import React, { useState } from 'react';
1+
import React, { useState, useEffect } from 'react';
22
import { toast } from 'react-toastify';
33
import Cookies from 'js-cookie';
44
import { logStore } from '~/lib/stores/logs';
55

6+
interface GitHubUserResponse {
7+
login: string;
8+
id: number;
9+
[key: string]: any; // for other properties we don't explicitly need
10+
}
11+
612
export default function ConnectionsTab() {
713
const [githubUsername, setGithubUsername] = useState(Cookies.get('githubUsername') || '');
814
const [githubToken, setGithubToken] = useState(Cookies.get('githubToken') || '');
15+
const [isConnected, setIsConnected] = useState(false);
16+
const [isVerifying, setIsVerifying] = useState(false);
17+
18+
useEffect(() => {
19+
// Check if credentials exist and verify them
20+
if (githubUsername && githubToken) {
21+
verifyGitHubCredentials();
22+
}
23+
}, []);
24+
25+
const verifyGitHubCredentials = async () => {
26+
setIsVerifying(true);
27+
28+
try {
29+
const response = await fetch('https://api.github.com/user', {
30+
headers: {
31+
Authorization: `Bearer ${githubToken}`,
32+
},
33+
});
34+
35+
if (response.ok) {
36+
const data = (await response.json()) as GitHubUserResponse;
37+
38+
if (data.login === githubUsername) {
39+
setIsConnected(true);
40+
return true;
41+
}
42+
}
43+
44+
setIsConnected(false);
45+
46+
return false;
47+
} catch (error) {
48+
console.error('Error verifying GitHub credentials:', error);
49+
setIsConnected(false);
950

10-
const handleSaveConnection = () => {
11-
Cookies.set('githubUsername', githubUsername);
12-
Cookies.set('githubToken', githubToken);
13-
logStore.logSystem('GitHub connection settings updated', {
14-
username: githubUsername,
15-
hasToken: !!githubToken,
16-
});
17-
toast.success('GitHub credentials saved successfully!');
18-
Cookies.set('git:github.com', JSON.stringify({ username: githubToken, password: 'x-oauth-basic' }));
51+
return false;
52+
} finally {
53+
setIsVerifying(false);
54+
}
55+
};
56+
57+
const handleSaveConnection = async () => {
58+
if (!githubUsername || !githubToken) {
59+
toast.error('Please provide both GitHub username and token');
60+
return;
61+
}
62+
63+
setIsVerifying(true);
64+
65+
const isValid = await verifyGitHubCredentials();
66+
67+
if (isValid) {
68+
Cookies.set('githubUsername', githubUsername);
69+
Cookies.set('githubToken', githubToken);
70+
logStore.logSystem('GitHub connection settings updated', {
71+
username: githubUsername,
72+
hasToken: !!githubToken,
73+
});
74+
toast.success('GitHub credentials verified and saved successfully!');
75+
Cookies.set('git:github.com', JSON.stringify({ username: githubToken, password: 'x-oauth-basic' }));
76+
setIsConnected(true);
77+
} else {
78+
toast.error('Invalid GitHub credentials. Please check your username and token.');
79+
}
80+
};
81+
82+
const handleDisconnect = () => {
83+
Cookies.remove('githubUsername');
84+
Cookies.remove('githubToken');
85+
Cookies.remove('git:github.com');
86+
setGithubUsername('');
87+
setGithubToken('');
88+
setIsConnected(false);
89+
logStore.logSystem('GitHub connection removed');
90+
toast.success('GitHub connection removed successfully!');
1991
};
2092

2193
return (
@@ -28,7 +100,8 @@ export default function ConnectionsTab() {
28100
type="text"
29101
value={githubUsername}
30102
onChange={(e) => setGithubUsername(e.target.value)}
31-
className="w-full bg-white dark:bg-bolt-elements-background-depth-4 relative px-2 py-1.5 rounded-md focus:outline-none placeholder-bolt-elements-textTertiary text-bolt-elements-textPrimary dark:text-bolt-elements-textPrimary border border-bolt-elements-borderColor"
103+
disabled={isVerifying}
104+
className="w-full bg-white dark:bg-bolt-elements-background-depth-4 relative px-2 py-1.5 rounded-md focus:outline-none placeholder-bolt-elements-textTertiary text-bolt-elements-textPrimary dark:text-bolt-elements-textPrimary border border-bolt-elements-borderColor disabled:opacity-50"
32105
/>
33106
</div>
34107
<div className="flex-1">
@@ -37,17 +110,41 @@ export default function ConnectionsTab() {
37110
type="password"
38111
value={githubToken}
39112
onChange={(e) => setGithubToken(e.target.value)}
40-
className="w-full bg-white dark:bg-bolt-elements-background-depth-4 relative px-2 py-1.5 rounded-md focus:outline-none placeholder-bolt-elements-textTertiary text-bolt-elements-textPrimary dark:text-bolt-elements-textPrimary border border-bolt-elements-borderColor"
113+
disabled={isVerifying}
114+
className="w-full bg-white dark:bg-bolt-elements-background-depth-4 relative px-2 py-1.5 rounded-md focus:outline-none placeholder-bolt-elements-textTertiary text-bolt-elements-textPrimary dark:text-bolt-elements-textPrimary border border-bolt-elements-borderColor disabled:opacity-50"
41115
/>
42116
</div>
43117
</div>
44-
<div className="flex mb-4">
45-
<button
46-
onClick={handleSaveConnection}
47-
className="bg-bolt-elements-button-primary-background rounded-lg px-4 py-2 mr-2 transition-colors duration-200 hover:bg-bolt-elements-button-primary-backgroundHover text-bolt-elements-button-primary-text"
48-
>
49-
Save Connection
50-
</button>
118+
<div className="flex mb-4 items-center">
119+
{!isConnected ? (
120+
<button
121+
onClick={handleSaveConnection}
122+
disabled={isVerifying || !githubUsername || !githubToken}
123+
className="bg-bolt-elements-button-primary-background rounded-lg px-4 py-2 mr-2 transition-colors duration-200 hover:bg-bolt-elements-button-primary-backgroundHover text-bolt-elements-button-primary-text disabled:opacity-50 disabled:cursor-not-allowed flex items-center"
124+
>
125+
{isVerifying ? (
126+
<>
127+
<div className="i-ph:spinner animate-spin mr-2" />
128+
Verifying...
129+
</>
130+
) : (
131+
'Connect'
132+
)}
133+
</button>
134+
) : (
135+
<button
136+
onClick={handleDisconnect}
137+
className="bg-bolt-elements-button-danger-background rounded-lg px-4 py-2 mr-2 transition-colors duration-200 hover:bg-bolt-elements-button-danger-backgroundHover text-bolt-elements-button-danger-text"
138+
>
139+
Disconnect
140+
</button>
141+
)}
142+
{isConnected && (
143+
<span className="text-sm text-green-600 flex items-center">
144+
<div className="i-ph:check-circle mr-1" />
145+
Connected to GitHub
146+
</span>
147+
)}
51148
</div>
52149
</div>
53150
);

app/components/settings/features/FeaturesTab.tsx

+3-1
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,9 @@ export default function FeaturesTab() {
6565
className="flex-1 p-2 ml-auto rounded-lg border border-bolt-elements-borderColor bg-bolt-elements-prompt-background text-bolt-elements-textPrimary focus:outline-none focus:ring-2 focus:ring-bolt-elements-focus transition-all text-sm min-w-[100px]"
6666
>
6767
{PromptLibrary.getList().map((x) => (
68-
<option value={x.id}>{x.label}</option>
68+
<option key={x.id} value={x.id}>
69+
{x.label}
70+
</option>
6971
))}
7072
</select>
7173
</div>

app/components/sidebar/HistoryItem.tsx

+29-22
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import * as Dialog from '@radix-ui/react-dialog';
44
import { type ChatHistoryItem } from '~/lib/persistence';
55
import WithTooltip from '~/components/ui/Tooltip';
66
import { useEditChatDescription } from '~/lib/hooks';
7+
import { forwardRef, type ForwardedRef } from 'react';
78

89
interface HistoryItemProps {
910
item: ChatHistoryItem;
@@ -103,25 +104,31 @@ export function HistoryItem({ item, onDelete, onDuplicate, exportChat }: History
103104
);
104105
}
105106

106-
const ChatActionButton = ({
107-
toolTipContent,
108-
icon,
109-
className,
110-
onClick,
111-
}: {
112-
toolTipContent: string;
113-
icon: string;
114-
className?: string;
115-
onClick: (event: React.MouseEvent<HTMLButtonElement, MouseEvent>) => void;
116-
btnTitle?: string;
117-
}) => {
118-
return (
119-
<WithTooltip tooltip={toolTipContent}>
120-
<button
121-
type="button"
122-
className={`scale-110 mr-2 hover:text-bolt-elements-item-contentAccent ${icon} ${className ? className : ''}`}
123-
onClick={onClick}
124-
/>
125-
</WithTooltip>
126-
);
127-
};
107+
const ChatActionButton = forwardRef(
108+
(
109+
{
110+
toolTipContent,
111+
icon,
112+
className,
113+
onClick,
114+
}: {
115+
toolTipContent: string;
116+
icon: string;
117+
className?: string;
118+
onClick: (event: React.MouseEvent<HTMLButtonElement, MouseEvent>) => void;
119+
btnTitle?: string;
120+
},
121+
ref: ForwardedRef<HTMLButtonElement>,
122+
) => {
123+
return (
124+
<WithTooltip tooltip={toolTipContent}>
125+
<button
126+
ref={ref}
127+
type="button"
128+
className={`scale-110 mr-2 hover:text-bolt-elements-item-contentAccent ${icon} ${className ? className : ''}`}
129+
onClick={onClick}
130+
/>
131+
</WithTooltip>
132+
);
133+
},
134+
);

app/lib/runtime/action-runner.ts

+4-3
Original file line numberDiff line numberDiff line change
@@ -202,8 +202,9 @@ export class ActionRunner {
202202
}
203203

204204
const webcontainer = await this.#webcontainer;
205+
const relativePath = nodePath.relative(webcontainer.workdir, action.filePath);
205206

206-
let folder = nodePath.dirname(action.filePath);
207+
let folder = nodePath.dirname(relativePath);
207208

208209
// remove trailing slashes
209210
folder = folder.replace(/\/+$/g, '');
@@ -218,8 +219,8 @@ export class ActionRunner {
218219
}
219220

220221
try {
221-
await webcontainer.fs.writeFile(action.filePath, action.content);
222-
logger.debug(`File written ${action.filePath}`);
222+
await webcontainer.fs.writeFile(relativePath, action.content);
223+
logger.debug(`File written ${relativePath}`);
223224
} catch (error) {
224225
logger.error('Failed to write file\n\n', error);
225226
}

0 commit comments

Comments
 (0)