From 59afe6addf009792ba221f188d45face643f2807 Mon Sep 17 00:00:00 2001 From: Yuhan Lei Date: Thu, 23 Apr 2026 02:11:35 +0800 Subject: [PATCH 1/2] fix(desktop): avoid main util ts import --- .../src/main/attachment-mime.test.ts | 40 +++++++++++++++++++ .../src/main/attachment-mime.ts | 16 ++++++++ packages/desktop-electron/src/main/ipc.ts | 8 +--- 3 files changed, 57 insertions(+), 7 deletions(-) create mode 100644 packages/desktop-electron/src/main/attachment-mime.test.ts create mode 100644 packages/desktop-electron/src/main/attachment-mime.ts diff --git a/packages/desktop-electron/src/main/attachment-mime.test.ts b/packages/desktop-electron/src/main/attachment-mime.test.ts new file mode 100644 index 000000000..e9de03763 --- /dev/null +++ b/packages/desktop-electron/src/main/attachment-mime.test.ts @@ -0,0 +1,40 @@ +import { describe, expect, test } from "bun:test" + +import { IMAGE_EXTS } from "@opencode-ai/util/file-extensions" + +import { attachmentPathMime, MIME_BY_EXTENSION } from "./attachment-mime" + +describe("attachmentPathMime", () => { + test("returns MIME types for direct attachment files", () => { + expect(attachmentPathMime("/tmp/image.gif")).toBe("image/gif") + expect(attachmentPathMime("/tmp/image.jpeg")).toBe("image/jpeg") + expect(attachmentPathMime("/tmp/image.png")).toBe("image/png") + expect(attachmentPathMime("/tmp/image.JPG")).toBe("image/jpeg") + expect(attachmentPathMime("/tmp/image.webp")).toBe("image/webp") + expect(attachmentPathMime("/tmp/document.pdf")).toBe("application/pdf") + }) + + test("returns MIME types using an injected extension reader", () => { + const extname = (filepath: string) => filepath.slice(filepath.lastIndexOf(".")) + + expect(attachmentPathMime("C:\\tmp\\image.PNG", extname)).toBe("image/png") + }) + + test("keeps image MIME entries in sync with the renderer contract", () => { + const imageEntries = [...MIME_BY_EXTENSION.entries()] + .filter(([extension]) => extension !== "pdf") + .sort(([left], [right]) => left.localeCompare(right)) + + const rendererImageEntries = [...IMAGE_EXTS.entries()].sort(([left], [right]) => left.localeCompare(right)) + + expect(imageEntries).toEqual(rendererImageEntries) + }) + + test("returns undefined for unsupported extensions", () => { + expect(attachmentPathMime("/tmp/archive.zip")).toBeUndefined() + }) + + test("returns undefined for missing extensions", () => { + expect(attachmentPathMime("/tmp/no-extension")).toBeUndefined() + }) +}) diff --git a/packages/desktop-electron/src/main/attachment-mime.ts b/packages/desktop-electron/src/main/attachment-mime.ts new file mode 100644 index 000000000..96feb66ad --- /dev/null +++ b/packages/desktop-electron/src/main/attachment-mime.ts @@ -0,0 +1,16 @@ +import path from "node:path" + +// Keep image entries in sync with packages/util/src/file-extensions.ts::IMAGE_EXTS. +export const MIME_BY_EXTENSION = new Map([ + ["gif", "image/gif"], + ["jpeg", "image/jpeg"], + ["jpg", "image/jpeg"], + ["pdf", "application/pdf"], + ["png", "image/png"], + ["webp", "image/webp"], +]) + +export function attachmentPathMime(filepath: string, extname = path.extname) { + const suffix = extname(filepath).slice(1).toLowerCase() + return MIME_BY_EXTENSION.get(suffix) +} diff --git a/packages/desktop-electron/src/main/ipc.ts b/packages/desktop-electron/src/main/ipc.ts index 84cb6366b..748019de1 100644 --- a/packages/desktop-electron/src/main/ipc.ts +++ b/packages/desktop-electron/src/main/ipc.ts @@ -3,7 +3,6 @@ import path from "node:path" import { execFile } from "node:child_process" import { BrowserWindow, Notification, app, clipboard, dialog, ipcMain, shell } from "electron" import type { IpcMainEvent, IpcMainInvokeEvent } from "electron" -import { IMAGE_EXTS } from "@opencode-ai/util/file-extensions" import type { DesktopContext, @@ -14,6 +13,7 @@ import type { UpdateInfo, WslConfig, } from "../preload/types" +import { attachmentPathMime } from "./attachment-mime" import { getStore } from "./store" import { setTitlebar } from "./windows" @@ -34,12 +34,6 @@ function normalizeAttachmentPath(filepath: unknown) { return path.resolve(filepath) } -function attachmentPathMime(filepath: string) { - const suffix = path.extname(filepath).slice(1).toLowerCase() - if (suffix === "pdf") return "application/pdf" - return IMAGE_EXTS.get(suffix) -} - type Deps = { killSidecar: () => void awaitInitialization: (sendStep: (step: InitStep) => void) => Promise From 7baf949e717fbcce682f78374c3b5f8eed4519e9 Mon Sep 17 00:00:00 2001 From: Yuhan Lei Date: Thu, 23 Apr 2026 02:14:02 +0800 Subject: [PATCH 2/2] chore(release): bump version to v0.2.7 --- bun.lock | 8 ++++---- packages/app/package.json | 2 +- packages/desktop-electron/package.json | 2 +- packages/opencode/package.json | 2 +- packages/util/package.json | 2 +- 5 files changed, 8 insertions(+), 8 deletions(-) diff --git a/bun.lock b/bun.lock index 486c07c10..afc0a383b 100644 --- a/bun.lock +++ b/bun.lock @@ -26,7 +26,7 @@ }, "packages/app": { "name": "@opencode-ai/app", - "version": "0.2.6", + "version": "0.2.7", "dependencies": { "@kobalte/core": "catalog:", "@opencode-ai/sdk": "workspace:*", @@ -80,7 +80,7 @@ }, "packages/desktop-electron": { "name": "@opencode-ai/desktop-electron", - "version": "0.2.6", + "version": "0.2.7", "dependencies": { "@opencode-ai/util": "workspace:*", "effect": "catalog:", @@ -141,7 +141,7 @@ }, "packages/opencode": { "name": "opencode", - "version": "0.2.6", + "version": "0.2.7", "bin": { "opencode": "./bin/opencode", }, @@ -384,7 +384,7 @@ }, "packages/util": { "name": "@opencode-ai/util", - "version": "0.2.6", + "version": "0.2.7", "dependencies": { "@opencode-ai/shared": "workspace:*", "zod": "catalog:", diff --git a/packages/app/package.json b/packages/app/package.json index 8341a4cec..6fc6e358b 100644 --- a/packages/app/package.json +++ b/packages/app/package.json @@ -1,6 +1,6 @@ { "name": "@opencode-ai/app", - "version": "0.2.6", + "version": "0.2.7", "description": "", "type": "module", "exports": { diff --git a/packages/desktop-electron/package.json b/packages/desktop-electron/package.json index 19b8e81a5..48e484f34 100644 --- a/packages/desktop-electron/package.json +++ b/packages/desktop-electron/package.json @@ -1,7 +1,7 @@ { "name": "@opencode-ai/desktop-electron", "private": true, - "version": "0.2.6", + "version": "0.2.7", "type": "module", "license": "Apache-2.0", "homepage": "https://pawwork.ai", diff --git a/packages/opencode/package.json b/packages/opencode/package.json index 8740bb122..9aa4ebf1f 100644 --- a/packages/opencode/package.json +++ b/packages/opencode/package.json @@ -1,6 +1,6 @@ { "$schema": "https://json.schemastore.org/package.json", - "version": "0.2.6", + "version": "0.2.7", "name": "opencode", "type": "module", "license": "Apache-2.0", diff --git a/packages/util/package.json b/packages/util/package.json index 02ea683cd..b670f6403 100644 --- a/packages/util/package.json +++ b/packages/util/package.json @@ -1,6 +1,6 @@ { "name": "@opencode-ai/util", - "version": "0.2.6", + "version": "0.2.7", "private": true, "type": "module", "license": "Apache-2.0",