Przeglądaj źródła

feat: add oxlint with correctness defaults (#22682)

Kit Langton 2 dni temu
rodzic
commit
3d6f90cb53
57 zmienionych plików z 165 dodań i 122 usunięć
  1. 10 0
      .oxlintrc.json
  2. 41 0
      bun.lock
  3. 2 0
      package.json
  4. 1 1
      packages/app/src/components/file-tree.tsx
  5. 1 1
      packages/app/src/components/terminal.tsx
  6. 2 2
      packages/app/src/context/global-sync/child-store.ts
  7. 2 2
      packages/app/src/context/layout.tsx
  8. 1 1
      packages/console/app/src/routes/zen/util/handler.ts
  9. 2 6
      packages/console/core/src/key.ts
  10. 1 1
      packages/desktop-electron/src/main/apps.ts
  11. 1 1
      packages/desktop-electron/src/main/shell-env.ts
  12. 1 3
      packages/opencode/script/build.ts
  13. 1 1
      packages/opencode/src/agent/agent.ts
  14. 1 3
      packages/opencode/src/cli/cmd/providers.ts
  15. 1 1
      packages/opencode/src/config/tui.ts
  16. 1 1
      packages/opencode/src/lsp/launch.ts
  17. 2 4
      packages/opencode/src/plugin/cloudflare.ts
  18. 1 1
      packages/opencode/src/plugin/meta.ts
  19. 2 2
      packages/opencode/src/provider/provider.ts
  20. 1 1
      packages/opencode/src/server/instance/session.ts
  21. 1 1
      packages/opencode/src/session/prompt.ts
  22. 1 1
      packages/opencode/src/tool/bash.ts
  23. 1 1
      packages/opencode/test/cli/tui/theme-store.test.ts
  24. 5 5
      packages/opencode/test/plugin/loader-shared.test.ts
  25. 1 1
      packages/opencode/test/plugin/workspace-adaptor.test.ts
  26. 4 4
      packages/shared/src/util/path.ts
  27. 5 5
      packages/ui/src/components/accordion.tsx
  28. 1 1
      packages/ui/src/components/app-icon.tsx
  29. 1 1
      packages/ui/src/components/avatar.tsx
  30. 1 1
      packages/ui/src/components/button.tsx
  31. 4 4
      packages/ui/src/components/card.tsx
  32. 1 1
      packages/ui/src/components/collapsible.tsx
  33. 16 16
      packages/ui/src/components/context-menu.tsx
  34. 1 1
      packages/ui/src/components/dialog.tsx
  35. 3 3
      packages/ui/src/components/dock-surface.tsx
  36. 16 16
      packages/ui/src/components/dropdown-menu.tsx
  37. 1 1
      packages/ui/src/components/file-icon.tsx
  38. 2 2
      packages/ui/src/components/file-ssr.tsx
  39. 1 1
      packages/ui/src/components/file.tsx
  40. 1 1
      packages/ui/src/components/hover-card.tsx
  41. 1 1
      packages/ui/src/components/icon-button.tsx
  42. 1 1
      packages/ui/src/components/icon.tsx
  43. 1 1
      packages/ui/src/components/keybind.tsx
  44. 2 2
      packages/ui/src/components/markdown.tsx
  45. 1 1
      packages/ui/src/components/popover.tsx
  46. 1 1
      packages/ui/src/components/progress-circle.tsx
  47. 1 1
      packages/ui/src/components/progress.tsx
  48. 1 1
      packages/ui/src/components/provider-icon.tsx
  49. 1 1
      packages/ui/src/components/radio-group.tsx
  50. 1 1
      packages/ui/src/components/resize-handle.tsx
  51. 3 3
      packages/ui/src/components/select.tsx
  52. 1 1
      packages/ui/src/components/session-turn.tsx
  53. 1 1
      packages/ui/src/components/spinner.tsx
  54. 1 1
      packages/ui/src/components/sticky-accordion-header.tsx
  55. 4 4
      packages/ui/src/components/tabs.tsx
  56. 1 1
      packages/ui/src/components/tag.tsx
  57. 1 1
      packages/ui/src/components/toast.tsx

+ 10 - 0
.oxlintrc.json

@@ -0,0 +1,10 @@
+{
+  "$schema": "https://raw.githubusercontent.com/nicolo-ribaudo/oxc-project.github.io/refs/heads/json-schema/src/public/.oxlintrc.schema.json",
+  "rules": {
+    // Effect uses `function*` with Effect.gen/Effect.fnUntraced that don't always yield
+    "require-yield": "off",
+    // SolidJS uses `let ref: T | undefined` for JSX ref bindings assigned at runtime
+    "no-unassigned-vars": "off"
+  },
+  "ignorePatterns": ["**/node_modules", "**/dist", "**/.build", "**/.sst", "**/*.d.ts"]
+}

+ 41 - 0
bun.lock

@@ -19,6 +19,7 @@
         "@typescript/native-preview": "catalog:",
         "glob": "13.0.5",
         "husky": "9.1.7",
+        "oxlint": "1.60.0",
         "prettier": "3.6.2",
         "semver": "^7.6.0",
         "sst": "3.18.10",
@@ -1693,6 +1694,44 @@
 
     "@oxc-transform/binding-win32-x64-msvc": ["@oxc-transform/[email protected]", "", { "os": "win32", "cpu": "x64" }, "sha512-0fI0P0W7bSO/GCP/N5dkmtB9vBqCA4ggo1WmXTnxNJVmFFOtcA1vYm1I9jl8fxo+sucW2WnlpnI4fjKdo3JKxA=="],
 
+    "@oxlint/binding-android-arm-eabi": ["@oxlint/[email protected]", "", { "os": "android", "cpu": "arm" }, "sha512-YdeJKaZckDQL1qa62a1aKq/goyq48aX3yOxaaWqWb4sau4Ee4IiLbamftNLU3zbePky6QsDj6thnSSzHRBjDfA=="],
+
+    "@oxlint/binding-android-arm64": ["@oxlint/[email protected]", "", { "os": "android", "cpu": "arm64" }, "sha512-7ANS7PpXCfq84xZQ8E5WPs14gwcuPcl+/8TFNXfpSu0CQBXz3cUo2fDpHT8v8HJN+Ut02eacvMAzTnc9s6X4tw=="],
+
+    "@oxlint/binding-darwin-arm64": ["@oxlint/[email protected]", "", { "os": "darwin", "cpu": "arm64" }, "sha512-pJsgd9AfplLGBm1fIr25V6V14vMrayhx4uIQvlfH7jWs2SZwSrvi3TfgfJySB8T+hvyEH8K2zXljQiUnkgUnfQ=="],
+
+    "@oxlint/binding-darwin-x64": ["@oxlint/[email protected]", "", { "os": "darwin", "cpu": "x64" }, "sha512-Ue1aXHX49ivwflKqGJc7zcd/LeLgbhaTcDCQStgx5x06AXgjEAZmvrlMuIkWd4AL4FHQe6QJ9f33z04Cg448VQ=="],
+
+    "@oxlint/binding-freebsd-x64": ["@oxlint/[email protected]", "", { "os": "freebsd", "cpu": "x64" }, "sha512-YCyQzsQtusQw+gNRW9rRTifSO+Dt/+dtCl2NHoDMZqJlRTEZ/Oht9YnuporI9yiTx7+cB+eqzX3MtHHVHGIWhg=="],
+
+    "@oxlint/binding-linux-arm-gnueabihf": ["@oxlint/[email protected]", "", { "os": "linux", "cpu": "arm" }, "sha512-c7dxM2Zksa45Qw16i2iGY3Fti2NirJ38FrsBsKw+qcJ0OtqTsBgKJLF0xV+yLG56UH01Z8WRPgsw31e0MoRoGQ=="],
+
+    "@oxlint/binding-linux-arm-musleabihf": ["@oxlint/[email protected]", "", { "os": "linux", "cpu": "arm" }, "sha512-ZWALoA42UYqBEP1Tbw9OWURgFGS1nWj2AAvLdY6ZcGx/Gj93qVCBKjcvwXMupZibYwFbi9s/rzqkZseb/6gVtQ=="],
+
+    "@oxlint/binding-linux-arm64-gnu": ["@oxlint/[email protected]", "", { "os": "linux", "cpu": "arm64" }, "sha512-tpy+1w4p9hN5CicMCxqNy6ymfRtV5ayE573vFNjp1k1TN/qhLFgflveZoE/0++RlkHikBz2vY545NWm/hp7big=="],
+
+    "@oxlint/binding-linux-arm64-musl": ["@oxlint/[email protected]", "", { "os": "linux", "cpu": "arm64" }, "sha512-eDYDXZGhQAXyn6GwtwiX/qcLS0HlOLPJ/+iiIY8RYr+3P8oKBmgKxADLlniL6FtWfE7pPk7IGN9/xvDEvDvFeg=="],
+
+    "@oxlint/binding-linux-ppc64-gnu": ["@oxlint/[email protected]", "", { "os": "linux", "cpu": "ppc64" }, "sha512-nxehly5XYBHUWI9VJX1bqCf9j/B43DaK/aS/T1fcxCpX3PA4Rm9BB54nPD1CKayT8xg6REN1ao+01hSRNgy8OA=="],
+
+    "@oxlint/binding-linux-riscv64-gnu": ["@oxlint/[email protected]", "", { "os": "linux", "cpu": "none" }, "sha512-j1qf/NaUfOWQutjeoooNG1Q0zsK0XGmSu1uDLq3cctquRF3j7t9Hxqf/76ehCc5GEUAanth2W4Fa+XT1RFg/nw=="],
+
+    "@oxlint/binding-linux-riscv64-musl": ["@oxlint/[email protected]", "", { "os": "linux", "cpu": "none" }, "sha512-YELKPRefQ/q/h3RUmeRfPCUhh2wBvgV1RyZ/F9M9u8cDyXsQW2ojv1DeWQTt466yczDITjZnIOg/s05pk7Ve2A=="],
+
+    "@oxlint/binding-linux-s390x-gnu": ["@oxlint/[email protected]", "", { "os": "linux", "cpu": "s390x" }, "sha512-JkO3C6Gki7Y6h/MiIkFKvHFOz98/YWvQ4WYbK9DLXACMP2rjULzkeGyAzorJE5S1dzLQGFgeqvN779kSFwoV1g=="],
+
+    "@oxlint/binding-linux-x64-gnu": ["@oxlint/[email protected]", "", { "os": "linux", "cpu": "x64" }, "sha512-XjKHdFVCpZZZSWBCKyyqCq65s2AKXykMXkjLoKYODrD+f5toLhlwsMESscu8FbgnJQ4Y/dpR/zdazsahmgBJIA=="],
+
+    "@oxlint/binding-linux-x64-musl": ["@oxlint/[email protected]", "", { "os": "linux", "cpu": "x64" }, "sha512-js29ZWIuPhNWzY8NC7KoffEMEeWG105vbmm+8EOJsC+T/jHBiKIJEUF78+F/IrgEWMMP9N0kRND4Pp75+xAhKg=="],
+
+    "@oxlint/binding-openharmony-arm64": ["@oxlint/[email protected]", "", { "os": "none", "cpu": "arm64" }, "sha512-H+PUITKHk04stFpWj3x3Kg08Afp/bcXSBi0EhasR5a0Vw7StXHTzdl655PUI0fB4qdh2Wsu6Dsi+3ACxPoyQnA=="],
+
+    "@oxlint/binding-win32-arm64-msvc": ["@oxlint/[email protected]", "", { "os": "win32", "cpu": "arm64" }, "sha512-WA/yc7f7ZfCefBXVzNHn1Ztulb1EFwNBb4jMZ6pjML0zz6pHujlF3Q3jySluz3XHl/GNeMTntG1seUBWVMlMag=="],
+
+    "@oxlint/binding-win32-ia32-msvc": ["@oxlint/[email protected]", "", { "os": "win32", "cpu": "ia32" }, "sha512-33YxL1sqwYNZXtn3MD/4dno6s0xeedXOJlT1WohkVD565WvohClZUr7vwKdAk954n4xiEWJkewiCr+zLeq7AeA=="],
+
+    "@oxlint/binding-win32-x64-msvc": ["@oxlint/[email protected]", "", { "os": "win32", "cpu": "x64" }, "sha512-JOro4ZcfBLamJCyfURQmOQByoorgOdx3ZjAkSqnb/CyG/i+lN3KoV5LAgk5ZAW6DPq7/Cx7n23f8DuTWXTWgyQ=="],
+
     "@pagefind/darwin-arm64": ["@pagefind/[email protected]", "", { "os": "darwin", "cpu": "arm64" }, "sha512-MXpI+7HsAdPkvJ0gk9xj9g541BCqBZOBbdwj9g6lB5LCj6kSV6nqDSjzcAJwvOsfu0fjwvC8hQU+ecfhp+MpiQ=="],
 
     "@pagefind/darwin-x64": ["@pagefind/[email protected]", "", { "os": "darwin", "cpu": "x64" }, "sha512-IojxFWMEJe0RQ7PQ3KXQsPIImNsbpPYpoZ+QUDrL8fAl/O27IX+LVLs74/UzEZy5uA2LD8Nz1AiwKr72vrkZQw=="],
@@ -4073,6 +4112,8 @@
 
     "oxc-transform": ["[email protected]", "", { "optionalDependencies": { "@oxc-transform/binding-android-arm64": "0.96.0", "@oxc-transform/binding-darwin-arm64": "0.96.0", "@oxc-transform/binding-darwin-x64": "0.96.0", "@oxc-transform/binding-freebsd-x64": "0.96.0", "@oxc-transform/binding-linux-arm-gnueabihf": "0.96.0", "@oxc-transform/binding-linux-arm-musleabihf": "0.96.0", "@oxc-transform/binding-linux-arm64-gnu": "0.96.0", "@oxc-transform/binding-linux-arm64-musl": "0.96.0", "@oxc-transform/binding-linux-riscv64-gnu": "0.96.0", "@oxc-transform/binding-linux-s390x-gnu": "0.96.0", "@oxc-transform/binding-linux-x64-gnu": "0.96.0", "@oxc-transform/binding-linux-x64-musl": "0.96.0", "@oxc-transform/binding-wasm32-wasi": "0.96.0", "@oxc-transform/binding-win32-arm64-msvc": "0.96.0", "@oxc-transform/binding-win32-x64-msvc": "0.96.0" } }, "sha512-dQPNIF+gHpSkmC0+Vg9IktNyhcn28Y8R3eTLyzn52UNymkasLicl3sFAtz7oEVuFmCpgGjaUTKkwk+jW2cHpDQ=="],
 
+    "oxlint": ["[email protected]", "", { "optionalDependencies": { "@oxlint/binding-android-arm-eabi": "1.60.0", "@oxlint/binding-android-arm64": "1.60.0", "@oxlint/binding-darwin-arm64": "1.60.0", "@oxlint/binding-darwin-x64": "1.60.0", "@oxlint/binding-freebsd-x64": "1.60.0", "@oxlint/binding-linux-arm-gnueabihf": "1.60.0", "@oxlint/binding-linux-arm-musleabihf": "1.60.0", "@oxlint/binding-linux-arm64-gnu": "1.60.0", "@oxlint/binding-linux-arm64-musl": "1.60.0", "@oxlint/binding-linux-ppc64-gnu": "1.60.0", "@oxlint/binding-linux-riscv64-gnu": "1.60.0", "@oxlint/binding-linux-riscv64-musl": "1.60.0", "@oxlint/binding-linux-s390x-gnu": "1.60.0", "@oxlint/binding-linux-x64-gnu": "1.60.0", "@oxlint/binding-linux-x64-musl": "1.60.0", "@oxlint/binding-openharmony-arm64": "1.60.0", "@oxlint/binding-win32-arm64-msvc": "1.60.0", "@oxlint/binding-win32-ia32-msvc": "1.60.0", "@oxlint/binding-win32-x64-msvc": "1.60.0" }, "peerDependencies": { "oxlint-tsgolint": ">=0.18.0" }, "optionalPeers": ["oxlint-tsgolint"], "bin": { "oxlint": "bin/oxlint" } }, "sha512-tnRzTWiWJ9pg3ftRWnD0+Oqh78L6ZSwcEudvCZaER0PIqiAnNyXj5N1dPwjmNpDalkKS9m/WMLN1CTPUBPmsgw=="],
+
     "p-cancelable": ["[email protected]", "", {}, "sha512-BZOr3nRQHOntUjTrH8+Lh54smKHoHyur8We1V8DSMVrl5A2malOOwuJRnKRDjSnkoeBh4at6BwEnb5I7Jl31wg=="],
 
     "p-defer": ["[email protected]", "", {}, "sha512-ugZxsxmtTln604yeYd29EGrNhazN2lywetzpKhfmQjW/VJmhpDmWbiX+h0zL8V91R0UXkhb3KtPmyq9PZw3aYw=="],

+ 2 - 0
package.json

@@ -11,6 +11,7 @@
     "dev:web": "bun --cwd packages/app dev",
     "dev:console": "ulimit -n 10240 2>/dev/null; bun run --cwd packages/console/app dev",
     "dev:storybook": "bun --cwd packages/storybook storybook",
+    "lint": "oxlint",
     "typecheck": "bun turbo typecheck",
     "postinstall": "bun run --cwd packages/opencode fix-node-pty",
     "prepare": "husky",
@@ -85,6 +86,7 @@
     "@typescript/native-preview": "catalog:",
     "glob": "13.0.5",
     "husky": "9.1.7",
+    "oxlint": "1.60.0",
     "prettier": "3.6.2",
     "semver": "^7.6.0",
     "sst": "3.18.10",

+ 1 - 1
packages/app/src/components/file-tree.tsx

@@ -149,7 +149,7 @@ const FileTreeNode = (
       classList={{
         "w-full min-w-0 h-6 flex items-center justify-start gap-x-1.5 rounded-md px-1.5 py-0 text-left hover:bg-surface-raised-base-hover active:bg-surface-base-active transition-colors cursor-pointer": true,
         "bg-surface-base-active": local.node.path === local.active,
-        ...(local.classList ?? {}),
+        ...local.classList,
         [local.class ?? ""]: !!local.class,
         [local.nodeClass ?? ""]: !!local.nodeClass,
       }}

+ 1 - 1
packages/app/src/components/terminal.tsx

@@ -634,7 +634,7 @@ export const Terminal = (props: TerminalProps) => {
       tabIndex={-1}
       style={{ "background-color": terminalColors().background }}
       classList={{
-        ...(local.classList ?? {}),
+        ...local.classList,
         "select-text": true,
         "size-full px-6 py-3 font-mono relative overflow-hidden": true,
         [local.class ?? ""]: !!local.class,

+ 2 - 2
packages/app/src/context/global-sync/child-store.ts

@@ -243,8 +243,8 @@ export function createChildStoreManager(input: {
     const cached = metaCache.get(directory)
     if (!cached) return
     const previous = store.projectMeta ?? {}
-    const icon = patch.icon ? { ...(previous.icon ?? {}), ...patch.icon } : previous.icon
-    const commands = patch.commands ? { ...(previous.commands ?? {}), ...patch.commands } : previous.commands
+    const icon = patch.icon ? { ...previous.icon, ...patch.icon } : previous.icon
+    const commands = patch.commands ? { ...previous.commands, ...patch.commands } : previous.commands
     const next = {
       ...previous,
       ...patch,

+ 2 - 2
packages/app/src/context/layout.tsx

@@ -344,7 +344,7 @@ export const { use: useLayout, provider: LayoutProvider } = createSimpleContext(
           return
         }
 
-        setStore("sessionView", sessionKey, "scroll", (prev) => ({ ...(prev ?? {}), ...next }))
+        setStore("sessionView", sessionKey, "scroll", (prev) => ({ ...prev, ...next }))
         prune(keep)
       },
     })
@@ -399,7 +399,7 @@ export const { use: useLayout, provider: LayoutProvider } = createSimpleContext(
         local?.icon?.color !== undefined
 
       const base = {
-        ...(metadata ?? {}),
+        ...metadata,
         ...project,
         icon: {
           url: metadata?.icon?.url,

+ 1 - 1
packages/console/app/src/routes/zen/util/handler.ts

@@ -144,7 +144,7 @@ export async function handler(
         providerInfo.modifyBody({
           ...createBodyConverter(opts.format, providerInfo.format)(body),
           model: providerInfo.model,
-          ...(providerInfo.payloadModifier ?? {}),
+          ...providerInfo.payloadModifier,
           ...Object.fromEntries(
             Object.entries(providerInfo.payloadMappings ?? {})
               .map(([k, v]) => [k, input.request.headers.get(v)])

+ 2 - 6
packages/console/core/src/key.ts

@@ -24,11 +24,9 @@ export namespace Key {
         .innerJoin(AuthTable, and(eq(UserTable.accountID, AuthTable.accountID), eq(AuthTable.provider, "email")))
         .where(
           and(
-            ...[
-              eq(KeyTable.workspaceID, Actor.workspace()),
+            eq(KeyTable.workspaceID, Actor.workspace()),
               isNull(KeyTable.timeDeleted),
               ...(Actor.userRole() === "admin" ? [] : [eq(KeyTable.userID, Actor.userID())]),
-            ],
           ),
         )
         .orderBy(sql`${KeyTable.name} DESC`),
@@ -84,11 +82,9 @@ export namespace Key {
         })
         .where(
           and(
-            ...[
-              eq(KeyTable.id, input.id),
+            eq(KeyTable.id, input.id),
               eq(KeyTable.workspaceID, Actor.workspace()),
               ...(Actor.userRole() === "admin" ? [] : [eq(KeyTable.userID, Actor.userID())]),
-            ],
           ),
         ),
     )

+ 1 - 1
packages/desktop-electron/src/main/apps.ts

@@ -20,7 +20,7 @@ export function wslPath(path: string, mode: "windows" | "linux" | null): string
   try {
     if (path.startsWith("~")) {
       const suffix = path.slice(1)
-      const cmd = `wslpath ${flag} \"$HOME${suffix.replace(/\"/g, '\\"')}\"`
+      const cmd = `wslpath ${flag} "$HOME${suffix.replace(/"/g, '\\"')}"`
       const output = execFileSync("wsl", ["-e", "sh", "-lc", cmd])
       return output.toString().trim()
     }

+ 1 - 1
packages/desktop-electron/src/main/shell-env.ts

@@ -82,7 +82,7 @@ export function loadShellEnv(shell: string) {
 
 export function mergeShellEnv(shell: Record<string, string> | null, env: Record<string, string>) {
   return {
-    ...(shell || {}),
+    ...shell,
     ...env,
   }
 }

+ 1 - 3
packages/opencode/script/build.ts

@@ -211,9 +211,7 @@ for (const item of targets) {
       execArgv: [`--user-agent=opencode/${Script.version}`, "--use-system-ca", "--"],
       windows: {},
     },
-    files: {
-      ...(embeddedFileMap ? { "opencode-web-ui.gen.ts": embeddedFileMap } : {}),
-    },
+    files: (embeddedFileMap ? { "opencode-web-ui.gen.ts": embeddedFileMap } : {}),
     entrypoints: [
       "./src/index.ts",
       parserWorker,

+ 1 - 1
packages/opencode/src/agent/agent.ts

@@ -368,7 +368,7 @@ export namespace Agent {
                   )),
               {
                 role: "user",
-                content: `Create an agent configuration based on this request: \"${input.description}\".\n\nIMPORTANT: The following identifiers already exist and must NOT be used: ${existing.map((i) => i.name).join(", ")}\n  Return ONLY the JSON object, no other text, do not wrap in backticks`,
+                content: `Create an agent configuration based on this request: "${input.description}".\n\nIMPORTANT: The following identifiers already exist and must NOT be used: ${existing.map((i) => i.name).join(", ")}\n  Return ONLY the JSON object, no other text, do not wrap in backticks`,
               },
             ],
             model: language,

+ 1 - 3
packages/opencode/src/cli/cmd/providers.ts

@@ -40,12 +40,10 @@ async function handlePluginAuth(plugin: { auth: PluginAuth }, provider: string,
   } else if (plugin.auth.methods.length > 1) {
     const method = await prompts.select({
       message: "Login method",
-      options: [
-        ...plugin.auth.methods.map((x, index) => ({
+      options: plugin.auth.methods.map((x, index) => ({
           label: x.label,
           value: index.toString(),
         })),
-      ],
     })
     if (prompts.isCancel(method)) throw new UI.CancelledError()
     index = parseInt(method)

+ 1 - 1
packages/opencode/src/config/tui.ts

@@ -125,7 +125,7 @@ export namespace TuiConfig {
       }
     }
 
-    const keybinds = { ...(acc.result.keybinds ?? {}) }
+    const keybinds = { ...acc.result.keybinds }
     if (process.platform === "win32") {
       // Native Windows terminals do not support POSIX suspend, so prefer prompt undo.
       keybinds.terminal_suspend = "none"

+ 1 - 1
packages/opencode/src/lsp/launch.ts

@@ -9,7 +9,7 @@ export function spawn(cmd: string, argsOrOpts?: string[] | Process.Options, opts
   const args = Array.isArray(argsOrOpts) ? [...argsOrOpts] : []
   const cfg = Array.isArray(argsOrOpts) ? opts : argsOrOpts
   const proc = Process.spawn([cmd, ...args], {
-    ...(cfg ?? {}),
+    ...cfg,
     stdin: "pipe",
     stdout: "pipe",
     stderr: "pipe",

+ 2 - 4
packages/opencode/src/plugin/cloudflare.ts

@@ -1,8 +1,7 @@
 import type { Hooks, PluginInput } from "@opencode-ai/plugin"
 
 export async function CloudflareWorkersAuthPlugin(_input: PluginInput): Promise<Hooks> {
-  const prompts = [
-    ...(!process.env.CLOUDFLARE_ACCOUNT_ID
+  const prompts = (!process.env.CLOUDFLARE_ACCOUNT_ID
       ? [
           {
             type: "text" as const,
@@ -11,8 +10,7 @@ export async function CloudflareWorkersAuthPlugin(_input: PluginInput): Promise<
             placeholder: "e.g. 1234567890abcdef1234567890abcdef",
           },
         ]
-      : []),
-  ]
+      : [])
 
   return {
     auth: {

+ 1 - 1
packages/opencode/src/plugin/meta.ts

@@ -174,7 +174,7 @@ export namespace PluginMeta {
       const entry = store[id]
       if (!entry) return
       entry.themes = {
-        ...(entry.themes ?? {}),
+        ...entry.themes,
         [name]: theme,
       }
       await Filesystem.writeJson(file, store)

+ 2 - 2
packages/opencode/src/provider/provider.ts

@@ -551,13 +551,13 @@ export namespace Provider {
         const aiGatewayHeaders = {
           "User-Agent": `opencode/${Installation.VERSION} gitlab-ai-provider/${GITLAB_PROVIDER_VERSION} (${os.platform()} ${os.release()}; ${os.arch()})`,
           "anthropic-beta": "context-1m-2025-08-07",
-          ...(providerConfig?.options?.aiGatewayHeaders || {}),
+          ...providerConfig?.options?.aiGatewayHeaders,
         }
 
         const featureFlags = {
           duo_agent_platform_agentic_chat: true,
           duo_agent_platform: true,
-          ...(providerConfig?.options?.featureFlags || {}),
+          ...providerConfig?.options?.featureFlags,
         }
 
         return {

+ 1 - 1
packages/opencode/src/server/instance/session.ts

@@ -695,7 +695,7 @@ export const SessionRoutes = lazy(() =>
           url.searchParams.set("limit", query.limit.toString())
           url.searchParams.set("before", page.cursor)
           c.header("Access-Control-Expose-Headers", "Link, X-Next-Cursor")
-          c.header("Link", `<${url.toString()}>; rel=\"next\"`)
+          c.header("Link", `<${url.toString()}>; rel="next"`)
           c.header("X-Next-Cursor", page.cursor)
         }
         return c.json(page.items)

+ 1 - 1
packages/opencode/src/session/prompt.ts

@@ -497,7 +497,7 @@ NOTE: At any point in time through this workflow you should feel free to ask the
 
                 const truncated = yield* truncate.output(textParts.join("\n\n"), {}, input.agent)
                 const metadata = {
-                  ...(result.metadata ?? {}),
+                  ...result.metadata,
                   truncated: truncated.truncated,
                   ...(truncated.truncated && { outputPath: truncated.outputPath }),
                 }

+ 1 - 1
packages/opencode/src/tool/bash.ts

@@ -176,7 +176,7 @@ function dynamic(text: string, ps: boolean) {
 }
 
 function prefix(text: string) {
-  const match = /[?*\[]/.exec(text)
+  const match = /[?*[]/.exec(text)
   if (!match) return text
   if (match.index === 0) return
   return text.slice(0, match.index)

+ 1 - 1
packages/opencode/test/cli/tui/theme-store.test.ts

@@ -41,7 +41,7 @@ test("hasTheme checks theme presence", () => {
 test("resolveTheme rejects circular color refs", () => {
   const item = structuredClone(DEFAULT_THEMES.opencode)
   item.defs = {
-    ...(item.defs ?? {}),
+    ...item.defs,
     one: "two",
     two: "one",
   }

+ 5 - 5
packages/opencode/test/plugin/loader-shared.test.ts

@@ -48,7 +48,7 @@ describe("plugin.loader.shared", () => {
           file,
           [
             "export default async () => {",
-            `  await Bun.write(${JSON.stringify(mark)}, \"called\")`,
+            `  await Bun.write(${JSON.stringify(mark)}, "called")`,
             "  return {}",
             "}",
             "",
@@ -78,8 +78,8 @@ describe("plugin.loader.shared", () => {
           file,
           [
             "const run = async () => {",
-            `  const text = await Bun.file(${JSON.stringify(mark)}).text().catch(() => \"\")`,
-            `  await Bun.write(${JSON.stringify(mark)}, text + \"1\")`,
+            `  const text = await Bun.file(${JSON.stringify(mark)}).text().catch(() => "")`,
+            `  await Bun.write(${JSON.stringify(mark)}, text + "1")`,
             "  return {}",
             "}",
             "export default run",
@@ -715,7 +715,7 @@ describe("plugin.loader.shared", () => {
             "const plugin = {",
             '  id: "demo.object",',
             "  server: async () => {",
-            `    await Bun.write(${JSON.stringify(mark)}, \"called\")`,
+            `    await Bun.write(${JSON.stringify(mark)}, "called")`,
             "    return {}",
             "  },",
             "}",
@@ -833,7 +833,7 @@ export default {
             "export default {",
             '  id: "demo.pure",',
             "  server: async () => {",
-            `    await Bun.write(${JSON.stringify(mark)}, \"called\")`,
+            `    await Bun.write(${JSON.stringify(mark)}, "called")`,
             "    return {}",
             "  },",
             "}",

+ 1 - 1
packages/opencode/test/plugin/workspace-adaptor.test.ts

@@ -39,7 +39,7 @@ describe("plugin.workspace", () => {
             '    name: "plug",',
             '    description: "plugin workspace adaptor",',
             "    configure(input) {",
-            `      return { ...input, name: \"plug\", branch: \"plug/main\", directory: ${JSON.stringify(space)} }`,
+            `      return { ...input, name: "plug", branch: "plug/main", directory: ${JSON.stringify(space)} }`,
             "    },",
             "    async create(input) {",
             `      await Bun.write(${JSON.stringify(mark)}, JSON.stringify(input))`,

+ 4 - 4
packages/shared/src/util/path.ts

@@ -1,14 +1,14 @@
 export function getFilename(path: string | undefined) {
   if (!path) return ""
-  const trimmed = path.replace(/[\/\\]+$/, "")
-  const parts = trimmed.split(/[\/\\]/)
+  const trimmed = path.replace(/[/\\]+$/, "")
+  const parts = trimmed.split(/[/\\]/)
   return parts[parts.length - 1] ?? ""
 }
 
 export function getDirectory(path: string | undefined) {
   if (!path) return ""
-  const trimmed = path.replace(/[\/\\]+$/, "")
-  const parts = trimmed.split(/[\/\\]/)
+  const trimmed = path.replace(/[/\\]+$/, "")
+  const parts = trimmed.split(/[/\\]/)
   return parts.slice(0, parts.length - 1).join("/") + "/"
 }
 

+ 5 - 5
packages/ui/src/components/accordion.tsx

@@ -15,7 +15,7 @@ function AccordionRoot(props: AccordionProps) {
       {...rest}
       data-component="accordion"
       classList={{
-        ...(split.classList ?? {}),
+        ...split.classList,
         [split.class ?? ""]: !!split.class,
       }}
     />
@@ -29,7 +29,7 @@ function AccordionItem(props: AccordionItemProps) {
       {...rest}
       data-slot="accordion-item"
       classList={{
-        ...(split.classList ?? {}),
+        ...split.classList,
         [split.class ?? ""]: !!split.class,
       }}
     />
@@ -43,7 +43,7 @@ function AccordionHeader(props: ParentProps<AccordionHeaderProps>) {
       {...rest}
       data-slot="accordion-header"
       classList={{
-        ...(split.classList ?? {}),
+        ...split.classList,
         [split.class ?? ""]: !!split.class,
       }}
     >
@@ -59,7 +59,7 @@ function AccordionTrigger(props: ParentProps<AccordionTriggerProps>) {
       {...rest}
       data-slot="accordion-trigger"
       classList={{
-        ...(split.classList ?? {}),
+        ...split.classList,
         [split.class ?? ""]: !!split.class,
       }}
     >
@@ -75,7 +75,7 @@ function AccordionContent(props: ParentProps<AccordionContentProps>) {
       {...rest}
       data-slot="accordion-content"
       classList={{
-        ...(split.classList ?? {}),
+        ...split.classList,
         [split.class ?? ""]: !!split.class,
       }}
     >

+ 1 - 1
packages/ui/src/components/app-icon.tsx

@@ -77,7 +77,7 @@ export const AppIcon: Component<AppIconProps> = (props) => {
       alt={local.alt ?? ""}
       draggable={local.draggable ?? false}
       classList={{
-        ...(local.classList ?? {}),
+        ...local.classList,
         [local.class ?? ""]: !!local.class,
       }}
     />

+ 1 - 1
packages/ui/src/components/avatar.tsx

@@ -38,7 +38,7 @@ export function Avatar(props: AvatarProps) {
       data-size={split.size || "normal"}
       data-has-image={src ? "" : undefined}
       classList={{
-        ...(split.classList ?? {}),
+        ...split.classList,
         [split.class ?? ""]: !!split.class,
       }}
       style={{

+ 1 - 1
packages/ui/src/components/button.tsx

@@ -20,7 +20,7 @@ export function Button(props: ButtonProps) {
       data-variant={split.variant || "secondary"}
       data-icon={split.icon}
       classList={{
-        ...(split.classList ?? {}),
+        ...split.classList,
         [split.class ?? ""]: !!split.class,
       }}
     >

+ 4 - 4
packages/ui/src/components/card.tsx

@@ -53,7 +53,7 @@ export function Card(props: CardProps) {
       data-variant={variant()}
       style={mix(split.style, accent())}
       classList={{
-        ...(split.classList ?? {}),
+        ...split.classList,
         [split.class ?? ""]: !!split.class,
       }}
     >
@@ -76,7 +76,7 @@ export function CardTitle(props: CardTitleProps) {
       {...rest}
       data-slot="card-title"
       classList={{
-        ...(split.classList ?? {}),
+        ...split.classList,
         [split.class ?? ""]: !!split.class,
       }}
     >
@@ -97,7 +97,7 @@ export function CardDescription(props: ComponentProps<"div">) {
       {...rest}
       data-slot="card-description"
       classList={{
-        ...(split.classList ?? {}),
+        ...split.classList,
         [split.class ?? ""]: !!split.class,
       }}
     >
@@ -113,7 +113,7 @@ export function CardActions(props: ComponentProps<"div">) {
       {...rest}
       data-slot="card-actions"
       classList={{
-        ...(split.classList ?? {}),
+        ...split.classList,
         [split.class ?? ""]: !!split.class,
       }}
     >

+ 1 - 1
packages/ui/src/components/collapsible.tsx

@@ -15,7 +15,7 @@ function CollapsibleRoot(props: CollapsibleProps) {
       data-component="collapsible"
       data-variant={local.variant || "normal"}
       classList={{
-        ...(local.classList ?? {}),
+        ...local.classList,
         [local.class ?? ""]: !!local.class,
       }}
       {...others}

+ 16 - 16
packages/ui/src/components/context-menu.tsx

@@ -33,7 +33,7 @@ function ContextMenuTrigger(props: ParentProps<ContextMenuTriggerProps>) {
       {...rest}
       data-slot="context-menu-trigger"
       classList={{
-        ...(local.classList ?? {}),
+        ...local.classList,
         [local.class ?? ""]: !!local.class,
       }}
     >
@@ -49,7 +49,7 @@ function ContextMenuIcon(props: ParentProps<ContextMenuIconProps>) {
       {...rest}
       data-slot="context-menu-icon"
       classList={{
-        ...(local.classList ?? {}),
+        ...local.classList,
         [local.class ?? ""]: !!local.class,
       }}
     >
@@ -69,7 +69,7 @@ function ContextMenuContent(props: ParentProps<ContextMenuContentProps>) {
       {...rest}
       data-component="context-menu-content"
       classList={{
-        ...(local.classList ?? {}),
+        ...local.classList,
         [local.class ?? ""]: !!local.class,
       }}
     >
@@ -85,7 +85,7 @@ function ContextMenuArrow(props: ContextMenuArrowProps) {
       {...rest}
       data-slot="context-menu-arrow"
       classList={{
-        ...(local.classList ?? {}),
+        ...local.classList,
         [local.class ?? ""]: !!local.class,
       }}
     />
@@ -99,7 +99,7 @@ function ContextMenuSeparator(props: ContextMenuSeparatorProps) {
       {...rest}
       data-slot="context-menu-separator"
       classList={{
-        ...(local.classList ?? {}),
+        ...local.classList,
         [local.class ?? ""]: !!local.class,
       }}
     />
@@ -113,7 +113,7 @@ function ContextMenuGroup(props: ParentProps<ContextMenuGroupProps>) {
       {...rest}
       data-slot="context-menu-group"
       classList={{
-        ...(local.classList ?? {}),
+        ...local.classList,
         [local.class ?? ""]: !!local.class,
       }}
     >
@@ -129,7 +129,7 @@ function ContextMenuGroupLabel(props: ParentProps<ContextMenuGroupLabelProps>) {
       {...rest}
       data-slot="context-menu-group-label"
       classList={{
-        ...(local.classList ?? {}),
+        ...local.classList,
         [local.class ?? ""]: !!local.class,
       }}
     >
@@ -145,7 +145,7 @@ function ContextMenuItem(props: ParentProps<ContextMenuItemProps>) {
       {...rest}
       data-slot="context-menu-item"
       classList={{
-        ...(local.classList ?? {}),
+        ...local.classList,
         [local.class ?? ""]: !!local.class,
       }}
     >
@@ -161,7 +161,7 @@ function ContextMenuItemLabel(props: ParentProps<ContextMenuItemLabelProps>) {
       {...rest}
       data-slot="context-menu-item-label"
       classList={{
-        ...(local.classList ?? {}),
+        ...local.classList,
         [local.class ?? ""]: !!local.class,
       }}
     >
@@ -177,7 +177,7 @@ function ContextMenuItemDescription(props: ParentProps<ContextMenuItemDescriptio
       {...rest}
       data-slot="context-menu-item-description"
       classList={{
-        ...(local.classList ?? {}),
+        ...local.classList,
         [local.class ?? ""]: !!local.class,
       }}
     >
@@ -193,7 +193,7 @@ function ContextMenuItemIndicator(props: ParentProps<ContextMenuItemIndicatorPro
       {...rest}
       data-slot="context-menu-item-indicator"
       classList={{
-        ...(local.classList ?? {}),
+        ...local.classList,
         [local.class ?? ""]: !!local.class,
       }}
     >
@@ -209,7 +209,7 @@ function ContextMenuRadioGroup(props: ParentProps<ContextMenuRadioGroupProps>) {
       {...rest}
       data-slot="context-menu-radio-group"
       classList={{
-        ...(local.classList ?? {}),
+        ...local.classList,
         [local.class ?? ""]: !!local.class,
       }}
     >
@@ -225,7 +225,7 @@ function ContextMenuRadioItem(props: ParentProps<ContextMenuRadioItemProps>) {
       {...rest}
       data-slot="context-menu-radio-item"
       classList={{
-        ...(local.classList ?? {}),
+        ...local.classList,
         [local.class ?? ""]: !!local.class,
       }}
     >
@@ -241,7 +241,7 @@ function ContextMenuCheckboxItem(props: ParentProps<ContextMenuCheckboxItemProps
       {...rest}
       data-slot="context-menu-checkbox-item"
       classList={{
-        ...(local.classList ?? {}),
+        ...local.classList,
         [local.class ?? ""]: !!local.class,
       }}
     >
@@ -261,7 +261,7 @@ function ContextMenuSubTrigger(props: ParentProps<ContextMenuSubTriggerProps>) {
       {...rest}
       data-slot="context-menu-sub-trigger"
       classList={{
-        ...(local.classList ?? {}),
+        ...local.classList,
         [local.class ?? ""]: !!local.class,
       }}
     >
@@ -277,7 +277,7 @@ function ContextMenuSubContent(props: ParentProps<ContextMenuSubContentProps>) {
       {...rest}
       data-component="context-menu-sub-content"
       classList={{
-        ...(local.classList ?? {}),
+        ...local.classList,
         [local.class ?? ""]: !!local.class,
       }}
     >

+ 1 - 1
packages/ui/src/components/dialog.tsx

@@ -28,7 +28,7 @@ export function Dialog(props: DialogProps) {
           data-slot="dialog-content"
           data-no-header={!props.title && !props.action ? "" : undefined}
           classList={{
-            ...(props.classList ?? {}),
+            ...props.classList,
             [props.class ?? ""]: !!props.class,
           }}
           onOpenAutoFocus={(e) => {

+ 3 - 3
packages/ui/src/components/dock-surface.tsx

@@ -11,7 +11,7 @@ export function DockShell(props: ComponentProps<"div">) {
       {...rest}
       data-dock-surface="shell"
       classList={{
-        ...(split.classList ?? {}),
+        ...split.classList,
         [split.class ?? ""]: !!split.class,
       }}
     >
@@ -27,7 +27,7 @@ export function DockShellForm(props: ComponentProps<"form">) {
       {...rest}
       data-dock-surface="shell"
       classList={{
-        ...(split.classList ?? {}),
+        ...split.classList,
         [split.class ?? ""]: !!split.class,
       }}
     >
@@ -44,7 +44,7 @@ export function DockTray(props: DockTrayProps) {
       data-dock-surface="tray"
       data-dock-attach={split.attach || "none"}
       classList={{
-        ...(split.classList ?? {}),
+        ...split.classList,
         [split.class ?? ""]: !!split.class,
       }}
     >

+ 16 - 16
packages/ui/src/components/dropdown-menu.tsx

@@ -33,7 +33,7 @@ function DropdownMenuTrigger(props: ParentProps<DropdownMenuTriggerProps>) {
       {...rest}
       data-slot="dropdown-menu-trigger"
       classList={{
-        ...(local.classList ?? {}),
+        ...local.classList,
         [local.class ?? ""]: !!local.class,
       }}
     >
@@ -49,7 +49,7 @@ function DropdownMenuIcon(props: ParentProps<DropdownMenuIconProps>) {
       {...rest}
       data-slot="dropdown-menu-icon"
       classList={{
-        ...(local.classList ?? {}),
+        ...local.classList,
         [local.class ?? ""]: !!local.class,
       }}
     >
@@ -69,7 +69,7 @@ function DropdownMenuContent(props: ParentProps<DropdownMenuContentProps>) {
       {...rest}
       data-component="dropdown-menu-content"
       classList={{
-        ...(local.classList ?? {}),
+        ...local.classList,
         [local.class ?? ""]: !!local.class,
       }}
     >
@@ -85,7 +85,7 @@ function DropdownMenuArrow(props: DropdownMenuArrowProps) {
       {...rest}
       data-slot="dropdown-menu-arrow"
       classList={{
-        ...(local.classList ?? {}),
+        ...local.classList,
         [local.class ?? ""]: !!local.class,
       }}
     />
@@ -99,7 +99,7 @@ function DropdownMenuSeparator(props: DropdownMenuSeparatorProps) {
       {...rest}
       data-slot="dropdown-menu-separator"
       classList={{
-        ...(local.classList ?? {}),
+        ...local.classList,
         [local.class ?? ""]: !!local.class,
       }}
     />
@@ -113,7 +113,7 @@ function DropdownMenuGroup(props: ParentProps<DropdownMenuGroupProps>) {
       {...rest}
       data-slot="dropdown-menu-group"
       classList={{
-        ...(local.classList ?? {}),
+        ...local.classList,
         [local.class ?? ""]: !!local.class,
       }}
     >
@@ -129,7 +129,7 @@ function DropdownMenuGroupLabel(props: ParentProps<DropdownMenuGroupLabelProps>)
       {...rest}
       data-slot="dropdown-menu-group-label"
       classList={{
-        ...(local.classList ?? {}),
+        ...local.classList,
         [local.class ?? ""]: !!local.class,
       }}
     >
@@ -145,7 +145,7 @@ function DropdownMenuItem(props: ParentProps<DropdownMenuItemProps>) {
       {...rest}
       data-slot="dropdown-menu-item"
       classList={{
-        ...(local.classList ?? {}),
+        ...local.classList,
         [local.class ?? ""]: !!local.class,
       }}
     >
@@ -161,7 +161,7 @@ function DropdownMenuItemLabel(props: ParentProps<DropdownMenuItemLabelProps>) {
       {...rest}
       data-slot="dropdown-menu-item-label"
       classList={{
-        ...(local.classList ?? {}),
+        ...local.classList,
         [local.class ?? ""]: !!local.class,
       }}
     >
@@ -177,7 +177,7 @@ function DropdownMenuItemDescription(props: ParentProps<DropdownMenuItemDescript
       {...rest}
       data-slot="dropdown-menu-item-description"
       classList={{
-        ...(local.classList ?? {}),
+        ...local.classList,
         [local.class ?? ""]: !!local.class,
       }}
     >
@@ -193,7 +193,7 @@ function DropdownMenuItemIndicator(props: ParentProps<DropdownMenuItemIndicatorP
       {...rest}
       data-slot="dropdown-menu-item-indicator"
       classList={{
-        ...(local.classList ?? {}),
+        ...local.classList,
         [local.class ?? ""]: !!local.class,
       }}
     >
@@ -209,7 +209,7 @@ function DropdownMenuRadioGroup(props: ParentProps<DropdownMenuRadioGroupProps>)
       {...rest}
       data-slot="dropdown-menu-radio-group"
       classList={{
-        ...(local.classList ?? {}),
+        ...local.classList,
         [local.class ?? ""]: !!local.class,
       }}
     >
@@ -225,7 +225,7 @@ function DropdownMenuRadioItem(props: ParentProps<DropdownMenuRadioItemProps>) {
       {...rest}
       data-slot="dropdown-menu-radio-item"
       classList={{
-        ...(local.classList ?? {}),
+        ...local.classList,
         [local.class ?? ""]: !!local.class,
       }}
     >
@@ -241,7 +241,7 @@ function DropdownMenuCheckboxItem(props: ParentProps<DropdownMenuCheckboxItemPro
       {...rest}
       data-slot="dropdown-menu-checkbox-item"
       classList={{
-        ...(local.classList ?? {}),
+        ...local.classList,
         [local.class ?? ""]: !!local.class,
       }}
     >
@@ -261,7 +261,7 @@ function DropdownMenuSubTrigger(props: ParentProps<DropdownMenuSubTriggerProps>)
       {...rest}
       data-slot="dropdown-menu-sub-trigger"
       classList={{
-        ...(local.classList ?? {}),
+        ...local.classList,
         [local.class ?? ""]: !!local.class,
       }}
     >
@@ -277,7 +277,7 @@ function DropdownMenuSubContent(props: ParentProps<DropdownMenuSubContentProps>)
       {...rest}
       data-component="dropdown-menu-sub-content"
       classList={{
-        ...(local.classList ?? {}),
+        ...local.classList,
         [local.class ?? ""]: !!local.class,
       }}
     >

+ 1 - 1
packages/ui/src/components/file-icon.tsx

@@ -18,7 +18,7 @@ export const FileIcon: Component<FileIconProps> = (props) => {
       data-component="file-icon"
       {...rest}
       classList={{
-        ...(local.classList ?? {}),
+        ...local.classList,
         [local.class ?? ""]: !!local.class,
       }}
     >

+ 2 - 2
packages/ui/src/components/file-ssr.tsx

@@ -99,7 +99,7 @@ function DiffSSRViewer<T>(props: SSRDiffFileProps<T>) {
           {
             ...createDefaultOptions(props.diffStyle),
             ...others,
-            ...(local.preloadedDiff.options ?? {}),
+            ...local.preloadedDiff.options,
           },
           virtualizer,
           virtualMetrics,
@@ -109,7 +109,7 @@ function DiffSSRViewer<T>(props: SSRDiffFileProps<T>) {
           {
             ...createDefaultOptions(props.diffStyle),
             ...others,
-            ...(local.preloadedDiff.options ?? {}),
+            ...local.preloadedDiff.options,
           },
           workerPool,
         )

+ 1 - 1
packages/ui/src/components/file.tsx

@@ -655,7 +655,7 @@ function ViewerShell(props: {
       style={styleVariables}
       class="relative outline-none"
       classList={{
-        ...(props.classList || {}),
+        ...props.classList,
         [props.class ?? ""]: !!props.class,
       }}
       ref={(el) => (props.viewer.wrapper = el)}

+ 1 - 1
packages/ui/src/components/hover-card.tsx

@@ -20,7 +20,7 @@ export function HoverCard(props: HoverCardProps) {
         <Kobalte.Content
           data-component="hover-card-content"
           classList={{
-            ...(local.classList ?? {}),
+            ...local.classList,
             [local.class ?? ""]: !!local.class,
           }}
         >

+ 1 - 1
packages/ui/src/components/icon-button.tsx

@@ -19,7 +19,7 @@ export function IconButton(props: ComponentProps<"button"> & IconButtonProps) {
       data-size={split.size || "normal"}
       data-variant={split.variant || "secondary"}
       classList={{
-        ...(split.classList ?? {}),
+        ...split.classList,
         [split.class ?? ""]: !!split.class,
       }}
     >

+ 1 - 1
packages/ui/src/components/icon.tsx

@@ -117,7 +117,7 @@ export function Icon(props: IconProps) {
       <svg
         data-slot="icon-svg"
         classList={{
-          ...(local.classList || {}),
+          ...local.classList,
           [local.class ?? ""]: !!local.class,
         }}
         fill="none"

+ 1 - 1
packages/ui/src/components/keybind.tsx

@@ -10,7 +10,7 @@ export function Keybind(props: KeybindProps) {
     <span
       data-component="keybind"
       classList={{
-        ...(props.classList ?? {}),
+        ...props.classList,
         [props.class ?? ""]: !!props.class,
       }}
     >

+ 2 - 2
packages/ui/src/components/markdown.tsx

@@ -50,7 +50,7 @@ function escape(text: string) {
     .replace(/&/g, "&amp;")
     .replace(/</g, "&lt;")
     .replace(/>/g, "&gt;")
-    .replace(/\"/g, "&quot;")
+    .replace(/"/g, "&quot;")
     .replace(/'/g, "&#39;")
 }
 
@@ -338,7 +338,7 @@ export function Markdown(
     <div
       data-component="markdown"
       classList={{
-        ...(local.classList ?? {}),
+        ...local.classList,
         [local.class ?? ""]: !!local.class,
       }}
       ref={setRoot}

+ 1 - 1
packages/ui/src/components/popover.tsx

@@ -106,7 +106,7 @@ export function Popover<T extends ValidComponent = "div">(props: PopoverProps<T>
       ref={(el: HTMLElement | undefined) => setState("contentRef", el)}
       data-component="popover-content"
       classList={{
-        ...(local.classList ?? {}),
+        ...local.classList,
         [local.class ?? ""]: !!local.class,
       }}
       style={local.style}

+ 1 - 1
packages/ui/src/components/progress-circle.tsx

@@ -32,7 +32,7 @@ export function ProgressCircle(props: ProgressCircleProps) {
       fill="none"
       data-component="progress-circle"
       classList={{
-        ...(split.classList ?? {}),
+        ...split.classList,
         [split.class ?? ""]: !!split.class,
       }}
     >

+ 1 - 1
packages/ui/src/components/progress.tsx

@@ -15,7 +15,7 @@ export function Progress(props: ProgressProps) {
       {...others}
       data-component="progress"
       classList={{
-        ...(local.classList ?? {}),
+        ...local.classList,
         [local.class ?? ""]: !!local.class,
       }}
     >

+ 1 - 1
packages/ui/src/components/provider-icon.tsx

@@ -15,7 +15,7 @@ export const ProviderIcon: Component<ProviderIconProps> = (props) => {
       data-component="provider-icon"
       {...rest}
       classList={{
-        ...(local.classList ?? {}),
+        ...local.classList,
         [local.class ?? ""]: !!local.class,
       }}
     >

+ 1 - 1
packages/ui/src/components/radio-group.tsx

@@ -56,7 +56,7 @@ export function RadioGroup<T>(props: RadioGroupProps<T>) {
       data-fill={local.fill ? "" : undefined}
       data-pad={local.pad ?? "normal"}
       classList={{
-        ...(local.classList ?? {}),
+        ...local.classList,
         [local.class ?? ""]: !!local.class,
       }}
       value={local.current ? getValue(local.current) : undefined}

+ 1 - 1
packages/ui/src/components/resize-handle.tsx

@@ -73,7 +73,7 @@ export function ResizeHandle(props: ResizeHandleProps) {
       data-direction={local.direction}
       data-edge={local.edge ?? (local.direction === "vertical" ? "start" : "end")}
       classList={{
-        ...(local.classList ?? {}),
+        ...local.classList,
         [local.class ?? ""]: !!local.class,
       }}
       onMouseDown={handleMouseDown}

+ 3 - 3
packages/ui/src/components/select.tsx

@@ -104,7 +104,7 @@ export function Select<T>(props: SelectProps<T> & Omit<ButtonProps, "children">)
           {...itemProps}
           data-slot="select-select-item"
           classList={{
-            ...(local.classList ?? {}),
+            ...local.classList,
             [local.class ?? ""]: !!local.class,
           }}
           onPointerEnter={() => move(itemProps.item.rawValue)}
@@ -141,7 +141,7 @@ export function Select<T>(props: SelectProps<T> & Omit<ButtonProps, "children">)
         variant={props.variant}
         style={local.triggerStyle}
         classList={{
-          ...(local.classList ?? {}),
+          ...local.classList,
           [local.class ?? ""]: !!local.class,
         }}
       >
@@ -160,7 +160,7 @@ export function Select<T>(props: SelectProps<T> & Omit<ButtonProps, "children">)
       <Kobalte.Portal>
         <Kobalte.Content
           classList={{
-            ...(local.classList ?? {}),
+            ...local.classList,
             [local.class ?? ""]: !!local.class,
           }}
           data-component="select-content"

+ 1 - 1
packages/ui/src/components/session-turn.tsx

@@ -110,7 +110,7 @@ function partState(part: PartType, showReasoningSummaries: boolean) {
 function clean(value: string) {
   return value
     .replace(/`([^`]+)`/g, "$1")
-    .replace(/\[([^\]]+)\]\([^\)]+\)/g, "$1")
+    .replace(/\[([^\]]+)\]\([^)]+\)/g, "$1")
     .replace(/[*_~]+/g, "")
     .trim()
 }

+ 1 - 1
packages/ui/src/components/spinner.tsx

@@ -23,7 +23,7 @@ export function Spinner(props: {
       viewBox="0 0 15 15"
       data-component="spinner"
       classList={{
-        ...(props.classList ?? {}),
+        ...props.classList,
         [props.class ?? ""]: !!props.class,
       }}
       fill="currentColor"

+ 1 - 1
packages/ui/src/components/sticky-accordion-header.tsx

@@ -8,7 +8,7 @@ export function StickyAccordionHeader(
     <Accordion.Header
       data-component="sticky-accordion-header"
       classList={{
-        ...(props.classList ?? {}),
+        ...props.classList,
         [props.class ?? ""]: !!props.class,
       }}
     >

+ 4 - 4
packages/ui/src/components/tabs.tsx

@@ -27,7 +27,7 @@ function TabsRoot(props: TabsProps) {
       data-variant={split.variant || "normal"}
       data-orientation={split.orientation || "horizontal"}
       classList={{
-        ...(split.classList ?? {}),
+        ...split.classList,
         [split.class ?? ""]: !!split.class,
       }}
     />
@@ -41,7 +41,7 @@ function TabsList(props: TabsListProps) {
       {...rest}
       data-slot="tabs-list"
       classList={{
-        ...(split.classList ?? {}),
+        ...split.classList,
         [split.class ?? ""]: !!split.class,
       }}
     />
@@ -63,7 +63,7 @@ function TabsTrigger(props: ParentProps<TabsTriggerProps>) {
       data-slot="tabs-trigger-wrapper"
       data-value={props.value}
       classList={{
-        ...(split.classList ?? {}),
+        ...split.classList,
         [split.class ?? ""]: !!split.class,
       }}
       onMouseDown={(e) => {
@@ -104,7 +104,7 @@ function TabsContent(props: ParentProps<TabsContentProps>) {
       {...rest}
       data-slot="tabs-content"
       classList={{
-        ...(split.classList ?? {}),
+        ...split.classList,
         [split.class ?? ""]: !!split.class,
       }}
     >

+ 1 - 1
packages/ui/src/components/tag.tsx

@@ -12,7 +12,7 @@ export function Tag(props: TagProps) {
       data-component="tag"
       data-size={split.size || "normal"}
       classList={{
-        ...(split.classList ?? {}),
+        ...split.classList,
         [split.class ?? ""]: !!split.class,
       }}
     >

+ 1 - 1
packages/ui/src/components/toast.tsx

@@ -30,7 +30,7 @@ function ToastRoot(props: ToastRootComponentProps) {
     <Kobalte
       data-component="toast"
       classList={{
-        ...(props.classList ?? {}),
+        ...props.classList,
         [props.class ?? ""]: !!props.class,
       }}
       {...props}