diff --git a/apps/desktop/package.json b/apps/desktop/package.json
index 1acc35d37..fe8e749a3 100644
--- a/apps/desktop/package.json
+++ b/apps/desktop/package.json
@@ -9,7 +9,7 @@
"dev:electron": "bun run scripts/dev-electron.mjs",
"build": "tsdown",
"start": "bun run scripts/start-electron.mjs",
- "typecheck": "tsc --noEmit",
+ "typecheck": "bunx tsc@5.7.3 --noEmit",
"test": "vitest run --passWithNoTests",
"smoke-test": "node scripts/smoke-test.mjs",
"release-smoke": "node ../../scripts/release-smoke.ts"
diff --git a/apps/marketing/package.json b/apps/marketing/package.json
index 882effbd3..78bddc3c4 100644
--- a/apps/marketing/package.json
+++ b/apps/marketing/package.json
@@ -10,7 +10,7 @@
"preview": "next start",
"start": "next start",
"lint": "eslint .",
- "typecheck": "tsc --noEmit"
+ "typecheck": "bunx tsc@5.7.3 --noEmit"
},
"dependencies": {
"@hookform/resolvers": "^3.10.0",
diff --git a/apps/mobile/package.json b/apps/mobile/package.json
index 87bfb8299..caa5993ca 100644
--- a/apps/mobile/package.json
+++ b/apps/mobile/package.json
@@ -5,7 +5,7 @@
"type": "module",
"scripts": {
"build": "bun run scripts/build-mobile-shell.mjs",
- "typecheck": "tsc --noEmit",
+ "typecheck": "bunx tsc@5.7.3 --noEmit",
"test": "vitest run --passWithNoTests",
"sync": "cap sync",
"open:ios": "cap open ios",
diff --git a/apps/server/package.json b/apps/server/package.json
index d9801b1fb..5ee5f7a6d 100644
--- a/apps/server/package.json
+++ b/apps/server/package.json
@@ -19,7 +19,7 @@
"build": "node scripts/cli.ts build",
"start": "node dist/index.mjs",
"prepare": "node -e \"process.exit(process.env.CI ? 0 : 1)\" || (node ../../scripts/patch-effect-language-service.ts && node ../../scripts/patch-effect-smol-peer-installs.mjs)",
- "typecheck": "tsc --noEmit",
+ "typecheck": "bunx tsc@5.7.3 --noEmit",
"test": "vitest run"
},
"dependencies": {
diff --git a/apps/server/src/api/authRouter.ts b/apps/server/src/api/authRouter.ts
index 0d04fc96e..c7f9cd29f 100644
--- a/apps/server/src/api/authRouter.ts
+++ b/apps/server/src/api/authRouter.ts
@@ -26,7 +26,7 @@ function respondJson(
): void {
res.writeHead(statusCode, {
"Content-Type": "application/json",
- ...(headers ?? {}),
+ ...headers,
});
res.end(JSON.stringify(body));
}
@@ -52,7 +52,9 @@ function mergeAnthropicBetaHeader(value: string | null): string {
return parts.join(",");
}
-async function readJsonRequestBody(req: http.IncomingMessage): Promise | null> {
+async function readJsonRequestBody(
+ req: http.IncomingMessage,
+): Promise | null> {
const chunks: Buffer[] = [];
for await (const chunk of req) {
chunks.push(typeof chunk === "string" ? Buffer.from(chunk) : Buffer.from(chunk));
diff --git a/apps/server/src/api/router.test.ts b/apps/server/src/api/router.test.ts
index 7c5fbb89b..c507bb8d6 100644
--- a/apps/server/src/api/router.test.ts
+++ b/apps/server/src/api/router.test.ts
@@ -87,21 +87,24 @@ describe("createApiRouter", () => {
tokenManager,
});
- await withServer((req, res) => {
- const url = new URL(req.url ?? "/", "http://127.0.0.1");
- void tryHandleApiRequest(req, res, url);
- }, async (baseUrl) => {
- const response = await request(baseUrl, "/api/pairing?ttl=300");
- const body = JSON.parse(response.body) as {
- pairingUrl: string;
- serverUrl: string;
- expiresAt: string;
- };
- expect(response.statusCode).toBe(200);
- expect(body.serverUrl).toBe("http://127.0.0.1:31337");
- expect(body.pairingUrl).toContain("okcode://pair?server=");
- expect(body.expiresAt).toMatch(/^\d{4}-\d{2}-\d{2}T/);
- });
+ await withServer(
+ (req, res) => {
+ const url = new URL(req.url ?? "/", "http://127.0.0.1");
+ void tryHandleApiRequest(req, res, url);
+ },
+ async (baseUrl) => {
+ const response = await request(baseUrl, "/api/pairing?ttl=300");
+ const body = JSON.parse(response.body) as {
+ pairingUrl: string;
+ serverUrl: string;
+ expiresAt: string;
+ };
+ expect(response.statusCode).toBe(200);
+ expect(body.serverUrl).toBe("http://127.0.0.1:31337");
+ expect(body.pairingUrl).toContain("okcode://pair?server=");
+ expect(body.expiresAt).toMatch(/^\d{4}-\d{2}-\d{2}T/);
+ },
+ );
});
it("proxies Anthropic message requests with the Claude Code envelope", async () => {
@@ -142,49 +145,50 @@ describe("createApiRouter", () => {
anthropicBaseUrl: `http://127.0.0.1:${upstreamAddress.port}`,
});
- await withServer((req, res) => {
- const url = new URL(req.url ?? "/", "http://127.0.0.1");
- void tryHandleApiRequest(req, res, url);
- }, async (baseUrl) => {
- const response = await request(baseUrl, "/api/auth/anthropic/v1/messages", {
- method: "POST",
- headers: {
- "Content-Type": "application/json",
- "x-api-key": "test-key",
- "anthropic-version": "2023-06-01",
- "anthropic-beta": "tools-2024-04-04",
- },
- body: JSON.stringify({
+ await withServer(
+ (req, res) => {
+ const url = new URL(req.url ?? "/", "http://127.0.0.1");
+ void tryHandleApiRequest(req, res, url);
+ },
+ async (baseUrl) => {
+ const response = await request(baseUrl, "/api/auth/anthropic/v1/messages", {
+ method: "POST",
+ headers: {
+ "Content-Type": "application/json",
+ "x-api-key": "test-key",
+ "anthropic-version": "2023-06-01",
+ "anthropic-beta": "tools-2024-04-04",
+ },
+ body: JSON.stringify({
+ model: "claude-sonnet-4-20250514",
+ max_tokens: 64,
+ system: "Original system prompt",
+ messages: [{ role: "user", content: "Hello" }],
+ stream: true,
+ }),
+ });
+
+ expect(response.statusCode).toBe(200);
+ expect(JSON.parse(response.body)).toEqual({ ok: true, proxied: true });
+ expect(upstreamHeaders?.["x-api-key"]).toBe("test-key");
+ expect(upstreamHeaders?.["anthropic-version"]).toBe("2023-06-01");
+ expect(upstreamHeaders?.["anthropic-beta"]).toBe("claude-code-20250219,tools-2024-04-04");
+ expect(upstreamBody).toMatchObject({
model: "claude-sonnet-4-20250514",
- max_tokens: 64,
- system: "Original system prompt",
- messages: [{ role: "user", content: "Hello" }],
stream: true,
- }),
- });
-
- expect(response.statusCode).toBe(200);
- expect(JSON.parse(response.body)).toEqual({ ok: true, proxied: true });
- expect(upstreamHeaders?.["x-api-key"]).toBe("test-key");
- expect(upstreamHeaders?.["anthropic-version"]).toBe("2023-06-01");
- expect(upstreamHeaders?.["anthropic-beta"]).toBe(
- "claude-code-20250219,tools-2024-04-04",
- );
- expect(upstreamBody).toMatchObject({
- model: "claude-sonnet-4-20250514",
- stream: true,
- });
- expect(upstreamBody?.system).toEqual([
- {
- type: "text",
- text: "You are Claude Code, Anthropic's official CLI for Claude.",
- },
- {
- type: "text",
- text: "Original system prompt",
- },
- ]);
- });
+ });
+ expect(upstreamBody?.system).toEqual([
+ {
+ type: "text",
+ text: "You are Claude Code, Anthropic's official CLI for Claude.",
+ },
+ {
+ type: "text",
+ text: "Original system prompt",
+ },
+ ]);
+ },
+ );
});
it("returns a JSON 404 for unknown API routes", async () => {
@@ -195,13 +199,16 @@ describe("createApiRouter", () => {
tokenManager: new TokenManager(undefined),
});
- await withServer((req, res) => {
- const url = new URL(req.url ?? "/", "http://127.0.0.1");
- void tryHandleApiRequest(req, res, url);
- }, async (baseUrl) => {
- const response = await request(baseUrl, "/api/unknown");
- expect(response.statusCode).toBe(404);
- expect(JSON.parse(response.body)).toEqual({ error: "Not Found" });
- });
+ await withServer(
+ (req, res) => {
+ const url = new URL(req.url ?? "/", "http://127.0.0.1");
+ void tryHandleApiRequest(req, res, url);
+ },
+ async (baseUrl) => {
+ const response = await request(baseUrl, "/api/unknown");
+ expect(response.statusCode).toBe(404);
+ expect(JSON.parse(response.body)).toEqual({ error: "Not Found" });
+ },
+ );
});
});
diff --git a/apps/server/src/openclaw/GatewayClient.ts b/apps/server/src/openclaw/GatewayClient.ts
index 734bbee23..3bff51c5f 100644
--- a/apps/server/src/openclaw/GatewayClient.ts
+++ b/apps/server/src/openclaw/GatewayClient.ts
@@ -466,7 +466,7 @@ export class OpenclawGatewayClient {
if (frame.type === "event" && typeof frame.event === "string") {
let matchedWaiter = false;
- for (const waiter of [...this.pendingEventWaiters]) {
+ for (const waiter of this.pendingEventWaiters) {
if (waiter.eventName === frame.event) {
matchedWaiter = true;
this.pendingEventWaiters.delete(waiter);
diff --git a/apps/server/src/persistence/Layers/OpenclawGatewayConfig.ts b/apps/server/src/persistence/Layers/OpenclawGatewayConfig.ts
index 26ec67d32..310e0939d 100644
--- a/apps/server/src/persistence/Layers/OpenclawGatewayConfig.ts
+++ b/apps/server/src/persistence/Layers/OpenclawGatewayConfig.ts
@@ -68,7 +68,7 @@ function normalizeScopes(scopes: ReadonlyArray | undefined): string[] {
unique.add(trimmed);
}
}
- return [...unique].sort((left, right) => left.localeCompare(right));
+ return [...unique].toSorted((left, right) => left.localeCompare(right));
}
function fromGeneratedIdentity(identity: ReturnType) {
diff --git a/apps/server/src/sme/authValidation.ts b/apps/server/src/sme/authValidation.ts
index 3dfc18f99..20cadfbe5 100644
--- a/apps/server/src/sme/authValidation.ts
+++ b/apps/server/src/sme/authValidation.ts
@@ -18,11 +18,6 @@ import {
const OPENAI_MODEL_PROVIDERS = new Set(["openai"]);
-function normalizeOptionalValue(value: string | undefined | null): string | null {
- const trimmed = value?.trim();
- return trimmed && trimmed.length > 0 ? trimmed : null;
-}
-
export function getAllowedSmeAuthMethods(provider: ProviderKind): readonly SmeAuthMethod[] {
switch (provider) {
case "claudeAgent":
diff --git a/apps/server/src/wsServer.ts b/apps/server/src/wsServer.ts
index 8aa9df6f0..066c855b0 100644
--- a/apps/server/src/wsServer.ts
+++ b/apps/server/src/wsServer.ts
@@ -647,7 +647,7 @@ export const createServer = Effect.fn(function* (): Effect.fn.Return<
});
// HTTP server — serves static files or redirects to Vite dev server
- const httpServer = http.createServer((req, res) => {
+ const httpServer = http.createServer(async (req, res) => {
const respond = (
statusCode: number,
headers: Record,
@@ -660,7 +660,7 @@ export const createServer = Effect.fn(function* (): Effect.fn.Return<
void Effect.runPromise(
Effect.gen(function* () {
const url = new URL(req.url ?? "/", `http://localhost:${port}`);
- if (await tryHandleApiRequest(req, res, url)) {
+ if (yield* Effect.promise(() => tryHandleApiRequest(req, res, url))) {
return;
}
diff --git a/apps/web/package.json b/apps/web/package.json
index 68cbcbada..f9fd93111 100644
--- a/apps/web/package.json
+++ b/apps/web/package.json
@@ -8,7 +8,7 @@
"build": "vite build",
"prepare": "node -e \"process.exit(process.env.CI ? 0 : 1)\" || node ../../scripts/patch-effect-language-service.ts",
"preview": "vite preview",
- "typecheck": "tsc --noEmit",
+ "typecheck": "bunx tsc@5.7.3 --noEmit",
"test": "vitest run --passWithNoTests",
"test:browser": "node ../../scripts/run-browser-tests.mjs vitest.browser.config.ts",
"test:browser:install": "playwright install --with-deps chromium"
diff --git a/apps/web/src/components/settings/SettingsRouteContext.tsx b/apps/web/src/components/settings/SettingsRouteContext.tsx
index b83e77fd9..0967140d1 100644
--- a/apps/web/src/components/settings/SettingsRouteContext.tsx
+++ b/apps/web/src/components/settings/SettingsRouteContext.tsx
@@ -106,6 +106,7 @@ export function SettingsRouteContextProvider({ children }: { children: ReactNode
? ["PR request changes button"]
: []),
...(settings.timestampFormat !== defaults.timestampFormat ? ["Time format"] : []),
+ ...(settings.locale !== defaults.locale ? ["Language"] : []),
...(settings.showStitchBorder !== defaults.showStitchBorder ? ["Stitch border"] : []),
...(settings.enableAssistantStreaming !== defaults.enableAssistantStreaming
? ["Assistant output"]
diff --git a/apps/web/src/components/settings/SettingsShell.tsx b/apps/web/src/components/settings/SettingsShell.tsx
index ede0e4555..eabba642f 100644
--- a/apps/web/src/components/settings/SettingsShell.tsx
+++ b/apps/web/src/components/settings/SettingsShell.tsx
@@ -17,6 +17,7 @@ import { Button } from "../ui/button";
import { Select, SelectItem, SelectPopup, SelectTrigger, SelectValue } from "../ui/select";
import { SidebarInset, SidebarTrigger } from "../ui/sidebar";
import { cn } from "../../lib/utils";
+import { useT } from "../../i18n/useI18n";
export type SettingsSectionId =
| "general"
@@ -104,6 +105,7 @@ export function SettingsShell({
children: ReactNode;
}) {
const navigate = useNavigate();
+ const { t } = useT();
const activeItemLabel = useMemo(
() => SETTINGS_NAV_ITEMS.find((item) => item.id === activeItem)?.label ?? "Settings",
[activeItem],
@@ -142,7 +144,7 @@ export function SettingsShell({
disabled={changedSettingLabels.length === 0}
onClick={() => void onRestoreDefaults()}
>
- Restore defaults
+ {t("common.actions.restoreDefaults")}
@@ -163,7 +165,7 @@ export function SettingsShell({
disabled={changedSettingLabels.length === 0}
onClick={() => void onRestoreDefaults()}
>
- Restore defaults
+ {t("common.actions.restoreDefaults")}
diff --git a/apps/web/src/components/ui/sidebar.tsx b/apps/web/src/components/ui/sidebar.tsx
index 1c4fa8e06..063b5868b 100644
--- a/apps/web/src/components/ui/sidebar.tsx
+++ b/apps/web/src/components/ui/sidebar.tsx
@@ -38,6 +38,10 @@ type SidebarContextProps = {
toggleSidebar: () => void;
};
+type CookieStoreLike = {
+ set(options: { expires: number; name: string; path: string; value: string }): Promise;
+};
+
type SidebarResizableOptions = {
maxWidth?: number;
minWidth?: number;
@@ -147,7 +151,9 @@ function SidebarProvider({
}
// This sets the cookie to keep the sidebar state.
- await cookieStore.set({
+ const cookieStore = (globalThis as typeof globalThis & { cookieStore?: CookieStoreLike })
+ .cookieStore;
+ await cookieStore?.set({
expires: Date.now() + SIDEBAR_COOKIE_MAX_AGE * 1000,
name: SIDEBAR_COOKIE_NAME,
path: "/",
diff --git a/apps/web/src/routes/__root.tsx b/apps/web/src/routes/__root.tsx
index cc3b14515..6c37aec6f 100644
--- a/apps/web/src/routes/__root.tsx
+++ b/apps/web/src/routes/__root.tsx
@@ -33,6 +33,7 @@ import { MobileConnectionBanner } from "../components/mobile/MobileConnectionBan
import { MobilePairingScreen } from "../components/mobile/MobilePairingScreen";
import { useMobilePairingState } from "../hooks/useMobilePairingState";
import { I18nProvider } from "../i18n/I18nProvider";
+import { useT } from "../i18n/useI18n";
import { VoodooStitches } from "../components/VoodooStitches";
export const Route = createRootRouteWithContext<{
@@ -57,13 +58,16 @@ function RootRouteView() {
}
function RootRouteContent() {
+ const { t } = useT();
const { isMobileShell, isLoading, pairingState } = useMobilePairingState();
if (isMobileShell && isLoading) {
return (
-
Restoring mobile pairing...
+
+ {t("root.loading.restoringMobilePairing")}
+
);
@@ -78,7 +82,7 @@ function RootRouteContent() {
- Connecting to {APP_DISPLAY_NAME} server...
+ {t("root.loading.connectingServer", { appName: APP_DISPLAY_NAME })}
@@ -107,6 +111,7 @@ function RootRouteErrorView({ error, reset }: ErrorComponentProps) {
}
function RootRouteErrorContent({ error, reset }: ErrorComponentProps) {
+ const { t } = useT();
const message = errorMessage(error);
const details = errorDetails(error);
@@ -122,23 +127,23 @@ function RootRouteErrorContent({ error, reset }: ErrorComponentProps) {
{APP_DISPLAY_NAME}
- Something went wrong.
+ {t("root.error.title")}
{message}
- Show error details
- Hide error details
+ {t("root.error.showDetails")}
+ {t("root.error.hideDetails")}
{details}
diff --git a/apps/web/src/routes/_chat.settings.index.tsx b/apps/web/src/routes/_chat.settings.index.tsx
index 8cc09865f..2db0bdde6 100644
--- a/apps/web/src/routes/_chat.settings.index.tsx
+++ b/apps/web/src/routes/_chat.settings.index.tsx
@@ -77,12 +77,19 @@ import {
getProviderStatusDescription,
getProviderStatusHeading,
} from "../components/chat/providerStatusPresentation";
+import { APP_LOCALE_PREFERENCES } from "../i18n/types";
+import { useT } from "../i18n/useI18n";
-const TIMESTAMP_FORMAT_LABELS = {
- locale: "System default",
- "12-hour": "12-hour",
- "24-hour": "24-hour",
-} as const;
+const TIMESTAMP_FORMAT_OPTIONS = [
+ { value: "locale", labelKey: "settings.general.timeFormat.option.locale" },
+ { value: "12-hour", labelKey: "settings.general.timeFormat.option.12Hour" },
+ { value: "24-hour", labelKey: "settings.general.timeFormat.option.24Hour" },
+] as const;
+
+const LANGUAGE_OPTIONS = APP_LOCALE_PREFERENCES.map((value) => ({
+ value,
+ labelKey: `settings.general.language.option.${value}` as const,
+}));
const PR_REVIEW_REQUEST_CHANGES_TONE_OPTIONS: ReadonlyArray<{
value: PrReviewRequestChangesTone;
@@ -435,6 +442,7 @@ function BuildInfoBlock({ label, buildInfo }: { label: string; buildInfo: BuildM
}
function SettingsRouteView() {
+ const { t } = useT();
const navigate = useNavigate();
const {
settingsState: { settings, defaults, updateSettings },
@@ -709,6 +717,15 @@ function SettingsRouteView() {
[settings, updateSettings],
);
+ const languageOptionLabel = (value: (typeof APP_LOCALE_PREFERENCES)[number]) =>
+ t(`settings.general.language.option.${value}`);
+
+ const timestampFormatOptionLabel = (value: (typeof TIMESTAMP_FORMAT_OPTIONS)[number]["value"]) =>
+ t(
+ TIMESTAMP_FORMAT_OPTIONS.find((option) => option.value === value)?.labelKey ??
+ "settings.general.timeFormat.option.locale",
+ );
+
return (
+
+ updateSettings({
+ locale: defaults.locale,
+ })
+ }
+ />
+ ) : null
+ }
+ control={
+
+ }
+ />
+
{
- if (value !== "locale" && value !== "12-hour" && value !== "24-hour") {
+ if (!TIMESTAMP_FORMAT_OPTIONS.some((option) => option.value === value)) {
return;
}
updateSettings({
- timestampFormat: value,
+ timestampFormat: value as (typeof TIMESTAMP_FORMAT_OPTIONS)[number]["value"],
});
}}
>
- {TIMESTAMP_FORMAT_LABELS[settings.timestampFormat]}
+
+ {timestampFormatOptionLabel(settings.timestampFormat)}
+
-
- {TIMESTAMP_FORMAT_LABELS.locale}
-
-
- {TIMESTAMP_FORMAT_LABELS["12-hour"]}
-
-
- {TIMESTAMP_FORMAT_LABELS["24-hour"]}
-
+ {TIMESTAMP_FORMAT_OPTIONS.map((option) => (
+
+ {timestampFormatOptionLabel(option.value)}
+
+ ))}
}
diff --git a/package.json b/package.json
index d34a8da54..655aa5a6e 100644
--- a/package.json
+++ b/package.json
@@ -35,13 +35,13 @@
"build": "turbo run build",
"build:marketing": "turbo run build --filter=@okcode/marketing",
"build:desktop": "turbo run build --filter=@okcode/desktop --filter=okcodes",
- "typecheck": "turbo run typecheck",
- "lint": "oxlint --report-unused-disable-directives",
+ "typecheck": "bunx turbo run typecheck",
+ "lint": "bunx oxlint --report-unused-disable-directives",
"test": "turbo run test",
"test:desktop-smoke": "turbo run smoke-test --filter=@okcode/desktop",
"test:desktop-release-smoke": "turbo run release-smoke --filter=@okcode/desktop",
- "fmt": "oxfmt",
- "fmt:check": "oxfmt --check",
+ "fmt": "bunx oxfmt",
+ "fmt:check": "bunx oxfmt --check",
"build:contracts": "turbo run build --filter=@okcode/contracts",
"dist:desktop:artifact": "node scripts/build-desktop-artifact.ts",
"dist:desktop:dmg": "node scripts/build-desktop-artifact.ts --platform mac --target dmg",
diff --git a/packages/contracts/package.json b/packages/contracts/package.json
index 9d6bbfcf3..c05f516cf 100644
--- a/packages/contracts/package.json
+++ b/packages/contracts/package.json
@@ -20,7 +20,7 @@
"dev": "tsdown src/index.ts --format esm,cjs --dts --watch --clean",
"build": "tsdown src/index.ts --format esm,cjs --dts --clean",
"prepare": "node -e \"process.exit(process.env.CI ? 0 : 1)\" || node ../../scripts/patch-effect-language-service.ts",
- "typecheck": "tsc --noEmit",
+ "typecheck": "bunx tsc@5.7.3 --noEmit",
"test": "vitest run"
},
"dependencies": {
diff --git a/packages/contracts/src/orchestration.ts b/packages/contracts/src/orchestration.ts
index c765ffbb4..e7154983b 100644
--- a/packages/contracts/src/orchestration.ts
+++ b/packages/contracts/src/orchestration.ts
@@ -746,7 +746,7 @@ export type ProjectDeletedReason = typeof ProjectDeletedReason.Type;
export const ProjectDeletedPayload = Schema.Struct({
projectId: ProjectId,
deletedAt: IsoDateTime,
- reason: ProjectDeletedReason.pipe(Schema.withDecodingDefault(() => "manual")),
+ reason: ProjectDeletedReason.pipe(Schema.withDecodingDefault(() => "manual" as const)),
});
export const ThreadCreatedPayload = Schema.Struct({
@@ -771,7 +771,7 @@ export type ThreadDeletedReason = typeof ThreadDeletedReason.Type;
export const ThreadDeletedPayload = Schema.Struct({
threadId: ThreadId,
deletedAt: IsoDateTime,
- reason: ThreadDeletedReason.pipe(Schema.withDecodingDefault(() => "manual")),
+ reason: ThreadDeletedReason.pipe(Schema.withDecodingDefault(() => "manual" as const)),
});
export const ThreadMetaUpdatedPayload = Schema.Struct({
diff --git a/packages/shared/package.json b/packages/shared/package.json
index 5951bd026..21aa7fe1b 100644
--- a/packages/shared/package.json
+++ b/packages/shared/package.json
@@ -63,7 +63,7 @@
},
"scripts": {
"prepare": "node -e \"process.exit(process.env.CI ? 0 : 1)\" || node ../../scripts/patch-effect-language-service.ts",
- "typecheck": "tsc --noEmit",
+ "typecheck": "bunx tsc@5.7.3 --noEmit",
"test": "vitest run"
},
"dependencies": {