Skip to content

Commit 05a5f85

Browse files
authored
Merge pull request #504 from thecodacus/bundle-artifact
feat(UI): added artifact bundling for custom long artifacts like uploading folder
2 parents f562984 + 417dbca commit 05a5f85

File tree

7 files changed

+51
-5
lines changed

7 files changed

+51
-5
lines changed

app/components/chat/Artifact.tsx

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ interface ArtifactProps {
2828
export const Artifact = memo(({ messageId }: ArtifactProps) => {
2929
const userToggledActions = useRef(false);
3030
const [showActions, setShowActions] = useState(false);
31+
const [allActionFinished, setAllActionFinished] = useState(false);
3132

3233
const artifacts = useStore(workbenchStore.artifacts);
3334
const artifact = artifacts[messageId];
@@ -47,6 +48,11 @@ export const Artifact = memo(({ messageId }: ArtifactProps) => {
4748
if (actions.length && !showActions && !userToggledActions.current) {
4849
setShowActions(true);
4950
}
51+
52+
if (actions.length !== 0) {
53+
const finished = !actions.find((action) => action.status !== 'complete');
54+
setAllActionFinished(finished);
55+
}
5056
}, [actions]);
5157

5258
return (
@@ -59,14 +65,26 @@ export const Artifact = memo(({ messageId }: ArtifactProps) => {
5965
workbenchStore.showWorkbench.set(!showWorkbench);
6066
}}
6167
>
68+
{artifact.type == 'bundled' && (
69+
<>
70+
<div className="p-4">
71+
{allActionFinished ? (
72+
<div className={'i-ph:files-light'} style={{ fontSize: '2rem' }}></div>
73+
) : (
74+
<div className={'i-svg-spinners:90-ring-with-bg'} style={{ fontSize: '2rem' }}></div>
75+
)}
76+
</div>
77+
<div className="bg-bolt-elements-artifacts-borderColor w-[1px]" />
78+
</>
79+
)}
6280
<div className="px-5 p-3.5 w-full text-left">
6381
<div className="w-full text-bolt-elements-textPrimary font-medium leading-5 text-sm">{artifact?.title}</div>
6482
<div className="w-full w-full text-bolt-elements-textSecondary text-xs mt-0.5">Click to open Workbench</div>
6583
</div>
6684
</button>
6785
<div className="bg-bolt-elements-artifacts-borderColor w-[1px]" />
6886
<AnimatePresence>
69-
{actions.length && (
87+
{actions.length && artifact.type !== 'bundled' && (
7088
<motion.button
7189
initial={{ width: 0 }}
7290
animate={{ width: 'auto' }}
@@ -83,7 +101,7 @@ export const Artifact = memo(({ messageId }: ArtifactProps) => {
83101
</AnimatePresence>
84102
</div>
85103
<AnimatePresence>
86-
{showActions && actions.length > 0 && (
104+
{artifact.type !== 'bundled' && showActions && actions.length > 0 && (
87105
<motion.div
88106
className="actions"
89107
initial={{ height: 0 }}
@@ -92,6 +110,7 @@ export const Artifact = memo(({ messageId }: ArtifactProps) => {
92110
transition={{ duration: 0.15 }}
93111
>
94112
<div className="bg-bolt-elements-artifacts-borderColor h-[1px]" />
113+
95114
<div className="p-5 text-left bg-bolt-elements-actions-background">
96115
<ActionList actions={actions} />
97116
</div>

app/components/chat/ImportFolderButton.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ ${content}
7979
role: 'assistant',
8080
content: `I'll help you set up these files.${binaryFilesMessage}
8181
82-
<boltArtifact id="imported-files" title="Imported Files">
82+
<boltArtifact id="imported-files" title="Imported Files" type="bundled">
8383
${fileArtifacts.join('\n\n')}
8484
</boltArtifact>`,
8585
id: generateId(),

app/lib/runtime/__snapshots__/message-parser.spec.ts.snap

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ exports[`StreamingMessageParser > valid artifacts with actions > should correctl
2929
"id": "artifact_1",
3030
"messageId": "message_1",
3131
"title": "Some title",
32+
"type": undefined,
3233
}
3334
`;
3435

@@ -37,6 +38,7 @@ exports[`StreamingMessageParser > valid artifacts with actions > should correctl
3738
"id": "artifact_1",
3839
"messageId": "message_1",
3940
"title": "Some title",
41+
"type": undefined,
4042
}
4143
`;
4244

@@ -96,6 +98,7 @@ exports[`StreamingMessageParser > valid artifacts with actions > should correctl
9698
"id": "artifact_1",
9799
"messageId": "message_1",
98100
"title": "Some title",
101+
"type": undefined,
99102
}
100103
`;
101104

@@ -104,6 +107,7 @@ exports[`StreamingMessageParser > valid artifacts with actions > should correctl
104107
"id": "artifact_1",
105108
"messageId": "message_1",
106109
"title": "Some title",
110+
"type": undefined,
107111
}
108112
`;
109113

@@ -112,6 +116,7 @@ exports[`StreamingMessageParser > valid artifacts without actions > should corre
112116
"id": "artifact_1",
113117
"messageId": "message_1",
114118
"title": "Some title",
119+
"type": undefined,
115120
}
116121
`;
117122

@@ -120,6 +125,7 @@ exports[`StreamingMessageParser > valid artifacts without actions > should corre
120125
"id": "artifact_1",
121126
"messageId": "message_1",
122127
"title": "Some title",
128+
"type": undefined,
123129
}
124130
`;
125131

@@ -128,6 +134,7 @@ exports[`StreamingMessageParser > valid artifacts without actions > should corre
128134
"id": "artifact_1",
129135
"messageId": "message_1",
130136
"title": "Some title",
137+
"type": "bundled",
131138
}
132139
`;
133140

@@ -136,6 +143,7 @@ exports[`StreamingMessageParser > valid artifacts without actions > should corre
136143
"id": "artifact_1",
137144
"messageId": "message_1",
138145
"title": "Some title",
146+
"type": "bundled",
139147
}
140148
`;
141149

@@ -144,6 +152,7 @@ exports[`StreamingMessageParser > valid artifacts without actions > should corre
144152
"id": "artifact_1",
145153
"messageId": "message_1",
146154
"title": "Some title",
155+
"type": undefined,
147156
}
148157
`;
149158

@@ -152,6 +161,7 @@ exports[`StreamingMessageParser > valid artifacts without actions > should corre
152161
"id": "artifact_1",
153162
"messageId": "message_1",
154163
"title": "Some title",
164+
"type": undefined,
155165
}
156166
`;
157167

@@ -160,6 +170,7 @@ exports[`StreamingMessageParser > valid artifacts without actions > should corre
160170
"id": "artifact_1",
161171
"messageId": "message_1",
162172
"title": "Some title",
173+
"type": undefined,
163174
}
164175
`;
165176

@@ -168,6 +179,7 @@ exports[`StreamingMessageParser > valid artifacts without actions > should corre
168179
"id": "artifact_1",
169180
"messageId": "message_1",
170181
"title": "Some title",
182+
"type": undefined,
171183
}
172184
`;
173185

@@ -176,6 +188,7 @@ exports[`StreamingMessageParser > valid artifacts without actions > should corre
176188
"id": "artifact_1",
177189
"messageId": "message_1",
178190
"title": "Some title",
191+
"type": undefined,
179192
}
180193
`;
181194

@@ -184,6 +197,7 @@ exports[`StreamingMessageParser > valid artifacts without actions > should corre
184197
"id": "artifact_1",
185198
"messageId": "message_1",
186199
"title": "Some title",
200+
"type": undefined,
187201
}
188202
`;
189203

@@ -192,6 +206,7 @@ exports[`StreamingMessageParser > valid artifacts without actions > should corre
192206
"id": "artifact_1",
193207
"messageId": "message_1",
194208
"title": "Some title",
209+
"type": undefined,
195210
}
196211
`;
197212

@@ -200,6 +215,7 @@ exports[`StreamingMessageParser > valid artifacts without actions > should corre
200215
"id": "artifact_1",
201216
"messageId": "message_1",
202217
"title": "Some title",
218+
"type": undefined,
203219
}
204220
`;
205221

@@ -208,6 +224,7 @@ exports[`StreamingMessageParser > valid artifacts without actions > should corre
208224
"id": "artifact_1",
209225
"messageId": "message_1",
210226
"title": "Some title",
227+
"type": undefined,
211228
}
212229
`;
213230

@@ -216,5 +233,6 @@ exports[`StreamingMessageParser > valid artifacts without actions > should corre
216233
"id": "artifact_1",
217234
"messageId": "message_1",
218235
"title": "Some title",
236+
"type": undefined,
219237
}
220238
`;

app/lib/runtime/message-parser.spec.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,11 @@ describe('StreamingMessageParser', () => {
5959
},
6060
],
6161
[
62-
['Some text before <boltArti', 'fact', ' title="Some title" id="artifact_1">foo</boltArtifact> Some more text'],
62+
[
63+
'Some text before <boltArti',
64+
'fact',
65+
' title="Some title" id="artifact_1" type="bundled" >foo</boltArtifact> Some more text',
66+
],
6367
{
6468
output: 'Some text before Some more text',
6569
callbacks: { onArtifactOpen: 1, onArtifactClose: 1, onActionOpen: 0, onActionClose: 0 },

app/lib/runtime/message-parser.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -192,6 +192,7 @@ export class StreamingMessageParser {
192192
const artifactTag = input.slice(i, openTagEnd + 1);
193193

194194
const artifactTitle = this.#extractAttribute(artifactTag, 'title') as string;
195+
const type = this.#extractAttribute(artifactTag, 'type') as string;
195196
const artifactId = this.#extractAttribute(artifactTag, 'id') as string;
196197

197198
if (!artifactTitle) {
@@ -207,6 +208,7 @@ export class StreamingMessageParser {
207208
const currentArtifact = {
208209
id: artifactId,
209210
title: artifactTitle,
211+
type,
210212
} satisfies BoltArtifactData;
211213

212214
state.currentArtifact = currentArtifact;

app/lib/stores/workbench.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import { description } from '~/lib/persistence';
1919
export interface ArtifactState {
2020
id: string;
2121
title: string;
22+
type?: string;
2223
closed: boolean;
2324
runner: ActionRunner;
2425
}
@@ -230,7 +231,7 @@ export class WorkbenchStore {
230231
// TODO: what do we wanna do and how do we wanna recover from this?
231232
}
232233

233-
addArtifact({ messageId, title, id }: ArtifactCallbackData) {
234+
addArtifact({ messageId, title, id, type }: ArtifactCallbackData) {
234235
const artifact = this.#getArtifact(messageId);
235236

236237
if (artifact) {
@@ -245,6 +246,7 @@ export class WorkbenchStore {
245246
id,
246247
title,
247248
closed: false,
249+
type,
248250
runner: new ActionRunner(webcontainer, () => this.boltTerminal),
249251
});
250252
}

app/types/artifact.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
export interface BoltArtifactData {
22
id: string;
33
title: string;
4+
type?: string | undefined;
45
}

0 commit comments

Comments
 (0)