From 34a8a39a3c39f25eb0269942b98f0b6ca6c11044 Mon Sep 17 00:00:00 2001 From: Anirban Kar Date: Mon, 2 Dec 2024 18:30:21 +0530 Subject: [PATCH 1/4] added artifact bundling for custom long artifacts like uploading folder --- app/components/chat/Artifact.tsx | 13 +++++++++++-- app/components/chat/ImportFolderButton.tsx | 2 +- app/lib/runtime/message-parser.ts | 2 ++ app/lib/stores/workbench.ts | 4 +++- app/types/artifact.ts | 1 + 5 files changed, 18 insertions(+), 4 deletions(-) diff --git a/app/components/chat/Artifact.tsx b/app/components/chat/Artifact.tsx index 682a4c7..f26b1ee 100644 --- a/app/components/chat/Artifact.tsx +++ b/app/components/chat/Artifact.tsx @@ -59,6 +59,14 @@ export const Artifact = memo(({ messageId }: ArtifactProps) => { workbenchStore.showWorkbench.set(!showWorkbench); }} > + {artifact.type == 'bundled' && ( + <> +
+
+
+
+ + )}
{artifact?.title}
Click to open Workbench
@@ -66,7 +74,7 @@ export const Artifact = memo(({ messageId }: ArtifactProps) => {
- {actions.length && ( + {actions.length && artifact.type !== 'bundled' && ( {
- {showActions && actions.length > 0 && ( + {artifact.type !== 'bundled' && showActions && actions.length > 0 && ( { transition={{ duration: 0.15 }} >
+
diff --git a/app/components/chat/ImportFolderButton.tsx b/app/components/chat/ImportFolderButton.tsx index 5f822ee..b28ca51 100644 --- a/app/components/chat/ImportFolderButton.tsx +++ b/app/components/chat/ImportFolderButton.tsx @@ -79,7 +79,7 @@ ${content} role: 'assistant', content: `I'll help you set up these files.${binaryFilesMessage} - + ${fileArtifacts.join('\n\n')} `, id: generateId(), diff --git a/app/lib/runtime/message-parser.ts b/app/lib/runtime/message-parser.ts index 48f3f52..ab6b695 100644 --- a/app/lib/runtime/message-parser.ts +++ b/app/lib/runtime/message-parser.ts @@ -192,6 +192,7 @@ export class StreamingMessageParser { const artifactTag = input.slice(i, openTagEnd + 1); const artifactTitle = this.#extractAttribute(artifactTag, 'title') as string; + const type = this.#extractAttribute(artifactTag, 'type') as string; const artifactId = this.#extractAttribute(artifactTag, 'id') as string; if (!artifactTitle) { @@ -207,6 +208,7 @@ export class StreamingMessageParser { const currentArtifact = { id: artifactId, title: artifactTitle, + type, } satisfies BoltArtifactData; state.currentArtifact = currentArtifact; diff --git a/app/lib/stores/workbench.ts b/app/lib/stores/workbench.ts index cbb3f8a..a1de47e 100644 --- a/app/lib/stores/workbench.ts +++ b/app/lib/stores/workbench.ts @@ -18,6 +18,7 @@ import { extractRelativePath } from '~/utils/diff'; export interface ArtifactState { id: string; title: string; + type?: string; closed: boolean; runner: ActionRunner; } @@ -229,7 +230,7 @@ export class WorkbenchStore { // TODO: what do we wanna do and how do we wanna recover from this? } - addArtifact({ messageId, title, id }: ArtifactCallbackData) { + addArtifact({ messageId, title, id,type }: ArtifactCallbackData) { const artifact = this.#getArtifact(messageId); if (artifact) { @@ -244,6 +245,7 @@ export class WorkbenchStore { id, title, closed: false, + type, runner: new ActionRunner(webcontainer, () => this.boltTerminal), }); } diff --git a/app/types/artifact.ts b/app/types/artifact.ts index e35697a..660729c 100644 --- a/app/types/artifact.ts +++ b/app/types/artifact.ts @@ -1,4 +1,5 @@ export interface BoltArtifactData { id: string; title: string; + type?: string; } From fee629d8cd8b49290564f31a06b9cc86ba12a702 Mon Sep 17 00:00:00 2001 From: Anirban Kar Date: Tue, 3 Dec 2024 11:28:23 +0530 Subject: [PATCH 2/4] fixed test cases --- .../__snapshots__/message-parser.spec.ts.snap | 18 ++++++++++++++++++ app/lib/runtime/message-parser.spec.ts | 6 +++++- app/lib/stores/workbench.ts | 2 +- app/types/artifact.ts | 2 +- 4 files changed, 25 insertions(+), 3 deletions(-) diff --git a/app/lib/runtime/__snapshots__/message-parser.spec.ts.snap b/app/lib/runtime/__snapshots__/message-parser.spec.ts.snap index 1543770..4b60f10 100644 --- a/app/lib/runtime/__snapshots__/message-parser.spec.ts.snap +++ b/app/lib/runtime/__snapshots__/message-parser.spec.ts.snap @@ -29,6 +29,7 @@ exports[`StreamingMessageParser > valid artifacts with actions > should correctl "id": "artifact_1", "messageId": "message_1", "title": "Some title", + "type": undefined, } `; @@ -37,6 +38,7 @@ exports[`StreamingMessageParser > valid artifacts with actions > should correctl "id": "artifact_1", "messageId": "message_1", "title": "Some title", + "type": undefined, } `; @@ -96,6 +98,7 @@ exports[`StreamingMessageParser > valid artifacts with actions > should correctl "id": "artifact_1", "messageId": "message_1", "title": "Some title", + "type": undefined, } `; @@ -104,6 +107,7 @@ exports[`StreamingMessageParser > valid artifacts with actions > should correctl "id": "artifact_1", "messageId": "message_1", "title": "Some title", + "type": undefined, } `; @@ -112,6 +116,7 @@ exports[`StreamingMessageParser > valid artifacts without actions > should corre "id": "artifact_1", "messageId": "message_1", "title": "Some title", + "type": undefined, } `; @@ -120,6 +125,7 @@ exports[`StreamingMessageParser > valid artifacts without actions > should corre "id": "artifact_1", "messageId": "message_1", "title": "Some title", + "type": undefined, } `; @@ -128,6 +134,7 @@ exports[`StreamingMessageParser > valid artifacts without actions > should corre "id": "artifact_1", "messageId": "message_1", "title": "Some title", + "type": "bundled", } `; @@ -136,6 +143,7 @@ exports[`StreamingMessageParser > valid artifacts without actions > should corre "id": "artifact_1", "messageId": "message_1", "title": "Some title", + "type": "bundled", } `; @@ -144,6 +152,7 @@ exports[`StreamingMessageParser > valid artifacts without actions > should corre "id": "artifact_1", "messageId": "message_1", "title": "Some title", + "type": undefined, } `; @@ -152,6 +161,7 @@ exports[`StreamingMessageParser > valid artifacts without actions > should corre "id": "artifact_1", "messageId": "message_1", "title": "Some title", + "type": undefined, } `; @@ -160,6 +170,7 @@ exports[`StreamingMessageParser > valid artifacts without actions > should corre "id": "artifact_1", "messageId": "message_1", "title": "Some title", + "type": undefined, } `; @@ -168,6 +179,7 @@ exports[`StreamingMessageParser > valid artifacts without actions > should corre "id": "artifact_1", "messageId": "message_1", "title": "Some title", + "type": undefined, } `; @@ -176,6 +188,7 @@ exports[`StreamingMessageParser > valid artifacts without actions > should corre "id": "artifact_1", "messageId": "message_1", "title": "Some title", + "type": undefined, } `; @@ -184,6 +197,7 @@ exports[`StreamingMessageParser > valid artifacts without actions > should corre "id": "artifact_1", "messageId": "message_1", "title": "Some title", + "type": undefined, } `; @@ -192,6 +206,7 @@ exports[`StreamingMessageParser > valid artifacts without actions > should corre "id": "artifact_1", "messageId": "message_1", "title": "Some title", + "type": undefined, } `; @@ -200,6 +215,7 @@ exports[`StreamingMessageParser > valid artifacts without actions > should corre "id": "artifact_1", "messageId": "message_1", "title": "Some title", + "type": undefined, } `; @@ -208,6 +224,7 @@ exports[`StreamingMessageParser > valid artifacts without actions > should corre "id": "artifact_1", "messageId": "message_1", "title": "Some title", + "type": undefined, } `; @@ -216,5 +233,6 @@ exports[`StreamingMessageParser > valid artifacts without actions > should corre "id": "artifact_1", "messageId": "message_1", "title": "Some title", + "type": undefined, } `; diff --git a/app/lib/runtime/message-parser.spec.ts b/app/lib/runtime/message-parser.spec.ts index 739604b..4c5ba47 100644 --- a/app/lib/runtime/message-parser.spec.ts +++ b/app/lib/runtime/message-parser.spec.ts @@ -59,7 +59,11 @@ describe('StreamingMessageParser', () => { }, ], [ - ['Some text before foo Some more text'], + [ + 'Some text before foo Some more text', + ], { output: 'Some text before Some more text', callbacks: { onArtifactOpen: 1, onArtifactClose: 1, onActionOpen: 0, onActionClose: 0 }, diff --git a/app/lib/stores/workbench.ts b/app/lib/stores/workbench.ts index 8b13c7b..de3a11e 100644 --- a/app/lib/stores/workbench.ts +++ b/app/lib/stores/workbench.ts @@ -231,7 +231,7 @@ export class WorkbenchStore { // TODO: what do we wanna do and how do we wanna recover from this? } - addArtifact({ messageId, title, id,type }: ArtifactCallbackData) { + addArtifact({ messageId, title, id, type }: ArtifactCallbackData) { const artifact = this.#getArtifact(messageId); if (artifact) { diff --git a/app/types/artifact.ts b/app/types/artifact.ts index 660729c..3a1e6b9 100644 --- a/app/types/artifact.ts +++ b/app/types/artifact.ts @@ -1,5 +1,5 @@ export interface BoltArtifactData { id: string; title: string; - type?: string; + type?: string | undefined; } From 4139dbd0df82397319759ea6d572540dcf4cda52 Mon Sep 17 00:00:00 2001 From: Anirban Kar Date: Tue, 3 Dec 2024 11:28:43 +0530 Subject: [PATCH 3/4] added nvm for husky --- .husky/pre-commit | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.husky/pre-commit b/.husky/pre-commit index 966a4ad..74ea6e6 100644 --- a/.husky/pre-commit +++ b/.husky/pre-commit @@ -2,6 +2,9 @@ echo "🔍 Running pre-commit hook to check the code looks good... 🔍" +export NVM_DIR="$HOME/.nvm" +[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh" # Load nvm if you're using i + if ! pnpm typecheck; then echo "❌ Type checking failed! Please review TypeScript types." echo "Once you're done, don't forget to add your changes to the commit! 🚀" From 417dbcab9be864f9ff42f133bb34c32e81fc476b Mon Sep 17 00:00:00 2001 From: Anirban Kar Date: Fri, 6 Dec 2024 17:14:56 +0530 Subject: [PATCH 4/4] added spinner --- app/components/chat/Artifact.tsx | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/app/components/chat/Artifact.tsx b/app/components/chat/Artifact.tsx index f26b1ee..3ca2508 100644 --- a/app/components/chat/Artifact.tsx +++ b/app/components/chat/Artifact.tsx @@ -28,6 +28,7 @@ interface ArtifactProps { export const Artifact = memo(({ messageId }: ArtifactProps) => { const userToggledActions = useRef(false); const [showActions, setShowActions] = useState(false); + const [allActionFinished, setAllActionFinished] = useState(false); const artifacts = useStore(workbenchStore.artifacts); const artifact = artifacts[messageId]; @@ -47,6 +48,11 @@ export const Artifact = memo(({ messageId }: ArtifactProps) => { if (actions.length && !showActions && !userToggledActions.current) { setShowActions(true); } + + if (actions.length !== 0) { + const finished = !actions.find((action) => action.status !== 'complete'); + setAllActionFinished(finished); + } }, [actions]); return ( @@ -62,7 +68,11 @@ export const Artifact = memo(({ messageId }: ArtifactProps) => { {artifact.type == 'bundled' && ( <>
-
+ {allActionFinished ? ( +
+ ) : ( +
+ )}