Skip to content

[pull] main from baptisteArno:main #281

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Jul 7, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions .cursor/rules/general.mdc
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
---
alwaysApply: true
---

## Environment

- Always use `bun` as the package manager

## Coding

- Never use `any` type. Always use proper TypeScript types, interfaces, or union types instead.
- Use `satisfies` instead of `as` when possible to make sure we keep strong type-safety.
- Prefer writing long and complex functions that provide good, deep abstraction. These functions should have a TSDoc comment description of what it does in great details. Avoid providing `@param` description, params name should be self-explanatory. In the function itself you can add inline comments only if the code is hard to understand.
- Helper functions should be placed at the bottom of the file.

## Testing

- Use `bun run test` to run the unit test script (which executes `vitest run`)
- We test only complexe and critical functions
- We never use Vitest mocks. We almost always want to modify the function signature to have dependencies as arguments instead.
3 changes: 2 additions & 1 deletion .vscode/extensions.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
"bradlc.vscode-tailwindcss",
"unifiedjs.vscode-mdx",
"Prisma.prisma",
"biomejs.biome"
"biomejs.biome",
"vitest.explorer"
]
}
6 changes: 6 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -39,5 +39,11 @@
"i18n-ally.enabledFrameworks": ["custom"],
"search.exclude": {
"**/deprecated/**": true
},
"vitest.nodeEnv": {
"DATABASE_URL": "postgresql://postgres:[email protected]:5432/typebot",
"ENCRYPTION_SECRET": "dummy_XMHwTK1T5q3XZCgJIeWGCN3T3I",
"NEXTAUTH_URL": "http://localhost:3000",
"NEXT_PUBLIC_VIEWER_URL": "http://localhost:3001"
}
}
7 changes: 7 additions & 0 deletions apps/builder/.cursor/general.mdc
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
alwaysApply: true
---

## Translations

- When introducing new i18n keys, only provide en.json translations. The rest will be translated in Tolgee later on.
7 changes: 3 additions & 4 deletions apps/builder/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,9 @@
"dev": "dotenv -e ./.env -e ../../.env -- next dev -p 3000",
"build": "dotenv -e ./.env -e ../../.env -- next build",
"start": "dotenv -e ./.env -e ../../.env -- next start",
"test": "dotenv -e ./.env -e ../../.env -- playwright test",
"test:show-report": "playwright show-report src/test/reporters",
"test:ui": "dotenv -e ./.env -e ../../.env -- playwright test --ui",
"test:unit": "vitest run"
"test": "dotenv -e ./.env -e ../../.env -- vitest run",
"test:e2e": "dotenv -e ./.env -e ../../.env -- playwright test",
"test:e2e:show-report": "playwright show-report src/test/reporters"
},
"dependencies": {
"@ark-ui/react": "5.7.0",
Expand Down
5 changes: 2 additions & 3 deletions apps/viewer/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,8 @@
"dev": "dotenv -e ./.env -e ../../.env -- next dev -p 3001",
"build": "dotenv -e ./.env -e ../../.env -- next build",
"start": "dotenv -e ./.env -e ../../.env -- next start",
"test": "dotenv -e ./.env -e ../../.env -- playwright test",
"test:report": "playwright show-report",
"test:ui": "dotenv -e ./.env -e ../../.env -- playwright test --ui"
"test:e2e": "dotenv -e ./.env -e ../../.env -- playwright test",
"test:e2e:report": "playwright show-report"
},
"dependencies": {
"@chakra-ui/react": "2.8.2",
Expand Down
2 changes: 1 addition & 1 deletion apps/viewer/src/test/assets/typebots/setVariable.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
"options": {
"isExecutedOnClient": true,
"isCode": true,
"expressionToEvaluate": "document.___location.port",
"expressionToEvaluate": "document.___location.origin",
"variableId": "vggtwtqnbcynlw0b0f52dc6kw"
}
},
Expand Down
5 changes: 4 additions & 1 deletion apps/viewer/src/test/setVariable.spec.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import test, { expect } from "@playwright/test";
import { env } from "@typebot.io/env";
import { createId } from "@typebot.io/lib/createId";
import { importTypebotInDatabase } from "@typebot.io/playwright/databaseActions";
import { getTestAsset } from "./utils/playwright";
Expand All @@ -11,5 +12,7 @@ test("client side exec should work", async ({ page }) => {
});
await page.goto(`/${typebotId}-public`);

await expect(page.getByText("3001")).toBeVisible();
await expect(
page.getByText(new URL(env.NEXT_PUBLIC_VIEWER_URL[0]).origin),
).toBeVisible();
});
7 changes: 5 additions & 2 deletions apps/viewer/src/test/settings.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { createId } from "@paralleldrive/cuid2";
import test, { expect } from "@playwright/test";
import { InputBlockType } from "@typebot.io/blocks-inputs/constants";
import { defaultTextInputOptions } from "@typebot.io/blocks-inputs/text/constants";
import { env } from "@typebot.io/env";
import {
createTypebots,
updateTypebot,
Expand Down Expand Up @@ -84,7 +85,9 @@ test("Hide query params", async ({ page }) => {
]);
await page.goto(`/${typebotId}-public?Name=John`);
await page.waitForTimeout(1000);
expect(page.url()).toEqual(`http://localhost:3001/${typebotId}-public`);
expect(page.url()).toEqual(
`${env.NEXT_PUBLIC_VIEWER_URL[0]}/${typebotId}-public`,
);
await updateTypebot({
id: typebotId,
settings: {
Expand All @@ -94,7 +97,7 @@ test("Hide query params", async ({ page }) => {
await page.goto(`/${typebotId}-public?Name=John`);
await page.waitForTimeout(1000);
expect(page.url()).toEqual(
`http://localhost:3001/${typebotId}-public?Name=John`,
`${env.NEXT_PUBLIC_VIEWER_URL[0]}/${typebotId}-public?Name=John`,
);
});

Expand Down
2 changes: 2 additions & 0 deletions bun.lock
Original file line number Diff line number Diff line change
Expand Up @@ -1320,6 +1320,8 @@
},
"devDependencies": {
"@typebot.io/tsconfig": "workspace:*",
"vite-tsconfig-paths": "5.1.4",
"vitest": "3.2.4",
},
},
"packages/workspaces": {
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
"scripts": {
"postinstall": "turbo run db:generate",
"prepare": "husky",
"pre-commit": "turbo run format-and-lint lint-repo check-broken-links",
"pre-commit": "turbo run format-and-lint lint-repo check-broken-links test",
"format-and-lint": "biome check .",
"format-and-lint:fix": "biome check . --write",
"lint-repo": "sherif -r unordered-dependencies -r packages-without-package-json --ignore-package @typebot.io/legacy --ignore-package bot-engine",
Expand Down
5 changes: 5 additions & 0 deletions packages/ai/src/parseGenerateVariablesOptions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,11 @@ export const variablesToExtractSchema = option
type: option.literal("boolean"),
})
.extend(extractInfoBaseShape),
option
.object({
type: option.literal("array"),
})
.extend(extractInfoBaseShape),
option
.object({
type: option.literal("enum"),
Expand Down
3 changes: 3 additions & 0 deletions packages/ai/src/runGenerateVariables.ts
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,9 @@ const convertVariablesToExtractToSchema = ({
case "boolean":
shape[matchingVariable.name] = z.boolean();
break;
case "array":
shape[matchingVariable.name] = z.array(z.string());
break;
case "enum": {
if (!variableToExtract.values || variableToExtract.values.length === 0)
return;
Expand Down
6 changes: 3 additions & 3 deletions packages/bot-engine/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@
"exports": {
"./*": "./src/*.ts"
},
"scripts": {
"test": "dotenv -e ./.env -e ../../.env -- vitest run"
},
"dependencies": {
"@paralleldrive/cuid2": "2.2.1",
"@planetscale/database": "1.8.0",
Expand Down Expand Up @@ -57,8 +60,5 @@
"@typebot.io/tsconfig": "workspace:*",
"vitest": "3.2.4",
"vite-tsconfig-paths": "5.1.4"
},
"scripts": {
"test:unit": "vitest run"
}
}
2 changes: 1 addition & 1 deletion packages/deprecated/typebot-js/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
"scripts": {
"dev": "tsup --watch",
"build": "tsup",
"test": "bun jest"
"test:unit": "bun jest"
},
"devDependencies": {
"@typebot.io/tsconfig": "workspace:*",
Expand Down
2 changes: 1 addition & 1 deletion packages/embeds/js/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@typebot.io/js",
"version": "0.8.13",
"version": "0.8.14",
"description": "Javascript library to display typebots on your website",
"license": "FSL-1.1-ALv2",
"type": "module",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ import { setGeneralBackground } from "@/utils/setCssVariablesValue";
import { toaster } from "@/utils/toaster";
import { InputBlockType } from "@typebot.io/blocks-inputs/constants";
import type { InputBlock } from "@typebot.io/blocks-inputs/schema";
import type { ClientSideAction } from "@typebot.io/chat-api/clientSideAction";
import type {
ContinueChatResponse,
Message,
Expand Down Expand Up @@ -462,6 +461,25 @@ export const ChatContainer = (props: Props) => {
defaultContainerBackgroundColor) === "transparent",
);

const filteredChunks = createMemo(() =>
chatChunks().filter(hasExecutedInitialClientSideActions),
);

const hideAvatarFlags = createMemo(() => {
const list = filteredChunks();
const sending = isSending();
return list.map((c, idx) => {
const n = list[idx + 1];
return (
((!c.input || c.input?.isHidden) &&
((n?.messages?.length ?? 0) > 0 ||
n?.streamingMessage !== undefined ||
(c.messages.length > 0 && sending))) ??
false
);
});
});

return (
<ChatContainerSizeContext.Provider value={chatContainerSize}>
<div
Expand Down Expand Up @@ -489,12 +507,10 @@ export const ChatContainer = (props: Props) => {
)}
>
<div class="w-full flex flex-col gap-2 @xs:px-5 px-3">
<Index
each={chatChunks().filter(hasExecutedInitialClientSideActions)}
>
{(chunk, index) => (
<Index each={filteredChunks()}>
{(chunk, i) => (
<ChatChunk
index={index}
index={i}
messages={chunk().messages}
input={chunk().input}
theme={mergeThemes(
Expand All @@ -503,13 +519,8 @@ export const ChatContainer = (props: Props) => {
)}
settings={props.initialChatReply.typebot.settings}
context={props.context}
hideAvatar={
(!chunk().input || Boolean(chunk().input?.isHidden)) &&
((chatChunks()[index + 1]?.messages ?? []).length > 0 ||
chatChunks()[index + 1]?.streamingMessage !== undefined ||
(chunk().messages.length > 0 && isSending()))
}
isTransitionDisabled={index !== chatChunks().length - 1}
hideAvatar={hideAvatarFlags()[i]}
isTransitionDisabled={i !== filteredChunks().length - 1}
streamingMessage={chunk().streamingMessage}
onNewBubbleDisplayed={handleNewBubbleDisplayed}
onAllBubblesDisplayed={handleAllBubblesDisplayed}
Expand Down Expand Up @@ -553,24 +564,6 @@ const convertSubmitContentToMessage = (
if (answer.type === "recording") return { type: "audio", url: answer.url };
};

const getNextClientSideActionsBatch = ({
clientSideActions,
lastBubbleBlockId,
}: {
clientSideActions: ClientSideAction[];
lastBubbleBlockId: string | undefined;
}) => {
const actionsBatch: ClientSideAction[] = [];
let currentLastBubbleBlockId = lastBubbleBlockId;
for (const action of clientSideActions) {
if (currentLastBubbleBlockId !== action.lastBubbleBlockId) break;
currentLastBubbleBlockId = action.lastBubbleBlockId;
if (lastBubbleBlockId === action.lastBubbleBlockId)
actionsBatch.push(action);
}
return actionsBatch;
};

const updateIsInputHiddenOnLastChunk = (
chunks: ChatChunkType[],
): ChatChunkType[] => {
Expand Down
2 changes: 1 addition & 1 deletion packages/embeds/react/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@typebot.io/react",
"version": "0.8.13",
"version": "0.8.14",
"description": "Convenient library to display typebots on your React app",
"license": "FSL-1.1-ALv2",
"type": "module",
Expand Down
2 changes: 2 additions & 0 deletions packages/forge/blocks/anthropic/src/constants.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
export const anthropicModels = [
"claude-sonnet-4-0",
"claude-opus-4-0",
"claude-3-7-sonnet-latest",
"claude-3-5-haiku-latest",
"claude-3-5-sonnet-latest",
Expand Down
7 changes: 6 additions & 1 deletion packages/whatsapp/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@
"exports": {
"./*": "./src/*.ts"
},
"scripts": {
"test": "dotenv -e ./.env -e ../../.env -- vitest run"
},
"dependencies": {
"@typebot.io/blocks-core": "workspace:*",
"@typebot.io/bot-engine": "workspace:*",
Expand All @@ -29,6 +32,8 @@
"@typebot.io/runtime-session-store": "workspace:*"
},
"devDependencies": {
"@typebot.io/tsconfig": "workspace:*"
"@typebot.io/tsconfig": "workspace:*",
"vitest": "3.2.4",
"vite-tsconfig-paths": "5.1.4"
}
}
Loading
Loading