diff --git a/src/modules/apps/builder/AppBuilder.tsx b/src/modules/apps/builder/AppBuilder.tsx
index cf6cace..e9dc34e 100644
--- a/src/modules/apps/builder/AppBuilder.tsx
+++ b/src/modules/apps/builder/AppBuilder.tsx
@@ -236,7 +236,7 @@ function AppBuilderContent() {
totalCount,
]);
- const handleReportError = useCallback(
+ const handleFixError = useCallback(
async (errorText: string) => {
await sendMessage(
`I have encountered the following error:\n\n\`\`\`error\n${errorText}\n\`\`\`\n\nFix this error please.`,
@@ -352,7 +352,7 @@ function AppBuilderContent() {
diff --git a/src/modules/apps/builder/ArtifactSharedIframe.tsx b/src/modules/apps/builder/ArtifactSharedIframe.tsx
index 58ab9d5..1c82505 100644
--- a/src/modules/apps/builder/ArtifactSharedIframe.tsx
+++ b/src/modules/apps/builder/ArtifactSharedIframe.tsx
@@ -19,7 +19,7 @@ import { createChatCompletion, modulesToPackages } from '@/app/api/apps';
import { ChatCompletionCreateBody } from '@/app/api/apps/types';
import { ApiError } from '@/app/api/errors';
import { useProjectContext } from '@/layout/providers/ProjectProvider';
-import { Theme, useTheme } from '@/layout/providers/ThemeProvider';
+import { useTheme } from '@/layout/providers/ThemeProvider';
import { USERCONTENT_SITE_URL } from '@/utils/constants';
import { removeTrailingSlash } from '@/utils/helpers';
import { Loading } from '@carbon/react';
@@ -29,7 +29,7 @@ import AppPlaceholder from './Placeholder.svg';
interface Props {
sourceCode: string | null;
- onReportError?: (errorText: string) => void;
+ onFixError?: (errorText: string) => void;
}
function getErrorMessage(error: unknown) {
@@ -42,39 +42,35 @@ function getErrorMessage(error: unknown) {
return 'Unknown error when calling LLM function.';
}
-export function ArtifactSharedIframe({ sourceCode, onReportError }: Props) {
+export function ArtifactSharedIframe({ sourceCode, onFixError }: Props) {
const iframeRef = useRef(null);
const [state, setState] = useState(State.LOADING);
const { appliedTheme: theme } = useTheme();
const { project, organization } = useProjectContext();
+ const [iframeLoadCount, setIframeLoadCount] = useState(0);
- const postMessage = (message: PostMessage) => {
+ const postMessage = useCallback((message: PostMessage) => {
+ if(iframeLoadCount === 0) return;
iframeRef.current?.contentWindow?.postMessage(
message,
USERCONTENT_SITE_URL,
);
- };
+ }, [iframeLoadCount])
- const updateTheme = useCallback((theme: Theme) => {
- postMessage({ type: PostMessageType.UPDATE_THEME, theme });
- }, []);
-
- const updateCode = useCallback(
- (code: string | null) => {
- if (!code) {
- return;
- }
-
- postMessage({
- type: PostMessageType.UPDATE_CODE,
+ useEffect(() => {
+ postMessage({
+ type: PostMessageType.UPDATE_STATE,
+ stateChange: {
+ code: sourceCode ?? undefined,
config: {
- can_fix_error: Boolean(onReportError),
+ canFixError: Boolean(onFixError)
},
- code,
- });
- },
- [onReportError],
- );
+ theme: theme ?? 'system',
+ fullscreen: false,
+ ancestorOrigin: window.location.origin,
+ }
+ })
+ }, [sourceCode, onFixError, theme, postMessage]);
const handleMessage = useCallback(
async (event: MessageEvent) => {
@@ -84,15 +80,19 @@ export function ArtifactSharedIframe({ sourceCode, onReportError }: Props) {
return;
}
- if (
- data.type === RecieveMessageType.SCRIPT_RUN_STATE_CHANGED &&
- data.scriptRunState === ScriptRunState.RUNNING
- ) {
+ if (data.type === RecieveMessageType.READY) {
setState(State.READY);
return;
}
if (data.type === RecieveMessageType.REQUEST) {
+ const respond = (payload: unknown = undefined) =>
+ postMessage({
+ type: PostMessageType.RESPONSE,
+ request_id: data.request_id,
+ payload,
+ });
+
try {
switch (data.request_type) {
case 'modules_to_packages':
@@ -101,12 +101,9 @@ export function ArtifactSharedIframe({ sourceCode, onReportError }: Props) {
project.id,
data.payload.modules,
);
- postMessage({
- type: PostMessageType.RESPONSE,
- request_id: data.request_id,
- payload: packagesResponse,
- });
+ respond(packagesResponse);
break;
+
case 'chat_completion':
const response = await createChatCompletion(
organization.id,
@@ -115,49 +112,23 @@ export function ArtifactSharedIframe({ sourceCode, onReportError }: Props) {
);
const message = response?.choices[0]?.message?.content;
if (!message) throw new Error(); // missing completion
- postMessage({
- type: PostMessageType.RESPONSE,
- request_id: data.request_id,
- payload: { message },
- });
+ respond({ message });
+ break;
+
+ case 'fix_error':
+ onFixError?.(data.payload.errorText);
+ respond();
break;
}
} catch (err) {
- postMessage({
- type: PostMessageType.RESPONSE,
- request_id: data.request_id,
- payload: { error: getErrorMessage(err) },
- });
+ respond({ error: getErrorMessage(err) });
}
return;
}
-
- if (data.type === RecieveMessageType.REPORT_ERROR) {
- onReportError?.(data.errorText);
- return;
- }
},
- [project, organization, onReportError],
+ [project, organization, onFixError, postMessage],
);
- const handleIframeLoad = useCallback(() => {
- if (theme) {
- updateTheme(theme);
- }
- }, [theme, updateTheme]);
-
- useEffect(() => {
- if (theme) {
- updateTheme(theme);
- }
- }, [theme, updateTheme]);
-
- useEffect(() => {
- if (state === State.READY) {
- updateCode(sourceCode);
- }
- }, [state, theme, sourceCode, updateCode]);
-
useEffect(() => {
window.addEventListener('message', handleMessage);
@@ -180,7 +151,7 @@ export function ArtifactSharedIframe({ sourceCode, onReportError }: Props) {
'allow-popups-to-escape-sandbox',
].join(' ')}
className={classes.app}
- onLoad={handleIframeLoad}
+ onLoad={() => setIframeLoadCount(i => i + 1)}
/>
{!sourceCode ? (
@@ -188,7 +159,7 @@ export function ArtifactSharedIframe({ sourceCode, onReportError }: Props) {
) : (
- state === State.LOADING && sourceCode &&
+ state === State.LOADING &&
)}
);
@@ -196,15 +167,16 @@ export function ArtifactSharedIframe({ sourceCode, onReportError }: Props) {
type PostMessage =
| {
- type: PostMessageType.UPDATE_CODE;
- code: string;
- config: {
- can_fix_error?: boolean;
- };
- }
- | {
- type: PostMessageType.UPDATE_THEME;
- theme: Theme;
+ type: PostMessageType.UPDATE_STATE;
+ stateChange: Partial<{
+ fullscreen: boolean,
+ theme: 'light' | 'dark' | 'system',
+ code: string,
+ config: {
+ canFixError: boolean
+ },
+ ancestorOrigin: string,
+ }>;
}
| {
type: PostMessageType.RESPONSE;
@@ -213,15 +185,8 @@ type PostMessage =
};
enum PostMessageType {
- UPDATE_CODE = 'bee:updateCode',
- UPDATE_THEME = 'bee:updateTheme',
RESPONSE = 'bee:response',
-}
-
-enum ScriptRunState {
- INITIAL = 'initial',
- NOT_RUNNING = 'notRunning',
- RUNNING = 'running',
+ UPDATE_STATE = 'bee:updateState'
}
enum State {
@@ -230,15 +195,13 @@ enum State {
}
enum RecieveMessageType {
- SCRIPT_RUN_STATE_CHANGED = 'SCRIPT_RUN_STATE_CHANGED',
+ READY = 'bee:ready',
REQUEST = 'bee:request',
- REPORT_ERROR = 'bee:reportError',
}
export type StliteMessage =
| {
- type: RecieveMessageType.SCRIPT_RUN_STATE_CHANGED;
- scriptRunState: ScriptRunState;
+ type: RecieveMessageType.READY;
}
| {
type: RecieveMessageType.REQUEST;
@@ -253,6 +216,8 @@ export type StliteMessage =
payload: ChatCompletionCreateBody;
}
| {
- type: RecieveMessageType.REPORT_ERROR;
- errorText: string;
+ type: RecieveMessageType.REQUEST;
+ request_type: 'fix_error';
+ request_id: string;
+ payload: { errorText: string };
};