diff --git a/apps/server/package.json b/apps/server/package.json index 1147b5e06233..cc1bddb2ee6d 100644 --- a/apps/server/package.json +++ b/apps/server/package.json @@ -33,7 +33,7 @@ "@cursor/sdk": "1.0.35", "@effect/platform-node": "catalog:", "@effect/platform-node-shared": "catalog:", - "@ff-labs/fff-node": "0.9.4", + "@ff-labs/fff-node": "0.11.0", "@muse-code/sdk": "1.4.2", "@napi-rs/keyring": "^1.3.0", "@opencode-ai/sdk": "^1.3.15", diff --git a/apps/server/src/workspace/WorkspaceEntries.test.ts b/apps/server/src/workspace/WorkspaceEntries.test.ts index e827ae920985..454392357fb5 100644 --- a/apps/server/src/workspace/WorkspaceEntries.test.ts +++ b/apps/server/src/workspace/WorkspaceEntries.test.ts @@ -192,6 +192,42 @@ it.layer(layerTest, { excludeTestServices: true })("WorkspaceEntries", (it) => { 60_000, ); + it.effect("includes images and other binary files in non-git workspace indexes", () => + Effect.gen(function* () { + const cwd = yield* makeTempDir(); + const imagePaths = ["photo.png", "photo.jpg", "photo.jpeg"]; + const binaryPaths = [...imagePaths, "document.pdf", "archive.zip", "data.bin"]; + for (const filePath of binaryPaths) { + yield* writeTextFile(cwd, filePath, "\0binary contents\n"); + } + yield* writeTextFile(cwd, "notes.txt", "plain text\n"); + + const workspaceEntries = yield* WorkspaceEntries.WorkspaceEntries; + const expectedPaths = [...binaryPaths, "notes.txt"].toSorted(); + const listed = yield* workspaceEntries.list({ cwd }); + expect(listed.entries.map((entry) => entry.path).toSorted()).toEqual(expectedPaths); + expect(listed.truncated).toBe(false); + + const searched = yield* workspaceEntries.search({ + cwd, + query: "", + limit: 100, + kind: "file", + }); + expect(searched.entries.map((entry) => entry.path).toSorted()).toEqual(expectedPaths); + expect(searched.truncated).toBe(false); + + const images = yield* workspaceEntries.search({ + cwd, + query: "", + limit: 100, + imageOnly: true, + }); + expect(images.entries.map((entry) => entry.path).toSorted()).toEqual(imagePaths.toSorted()); + expect(images.truncated).toBe(false); + }), + ); + it.effect("returns the complete cached workspace index", () => Effect.gen(function* () { const cwd = yield* makeTempDir(); diff --git a/patches/@ff-labs__fff-node@0.11.0.patch b/patches/@ff-labs__fff-node@0.11.0.patch new file mode 100644 index 000000000000..d3db21525440 --- /dev/null +++ b/patches/@ff-labs__fff-node@0.11.0.patch @@ -0,0 +1,52 @@ +diff --git a/package.json b/package.json +index e000a78..8432546 100644 +--- a/package.json ++++ b/package.json +@@ -11,7 +11,7 @@ + ".": { + "types": "./dist/index.d.ts", + "import": "./dist/index.js", +- "require": "./dist/index.cjs", ++ "require": "./dist/index.js", + "default": "./dist/index.js" + }, + "./package.json": "./package.json" +diff --git a/dist/index.js b/dist/index.js +index 7c1d722..1d0bc27 100644 +--- a/dist/index.js ++++ b/dist/index.js +@@ -1,7 +1,7 @@ + // src/binary.ts + import { existsSync, readFileSync } from "fs"; + import { createRequire } from "module"; +-import { dirname, join } from "path"; ++import { dirname, join, sep } from "path"; + import { fileURLToPath } from "url"; + + // src/platform.ts +@@ -120,6 +120,16 @@ function getPackageDir() { + function binaryExists() { + return findBinary() !== null; + } ++function resolveUnpackedAsarPath(binaryPath) { ++ const pathSegments = binaryPath.split(sep); ++ const asarIndex = pathSegments.findLastIndex((segment) => segment.endsWith(".asar")); ++ if (asarIndex === -1) { ++ return binaryPath; ++ } ++ pathSegments[asarIndex] = `${pathSegments[asarIndex]}.unpacked`; ++ const unpackedPath = pathSegments.join(sep); ++ return existsSync(unpackedPath) ? unpackedPath : binaryPath; ++} + function resolveFromNpmPackage() { + const packageName = getNpmPackageName(); + try { +@@ -128,7 +138,7 @@ function resolveFromNpmPackage() { + const packageDir = dirname(packageJsonPath); + const binaryPath = join(packageDir, getLibFilename()); + if (existsSync(binaryPath)) { +- return binaryPath; ++ return resolveUnpackedAsarPath(binaryPath); + } + } catch { + } diff --git a/patches/@ff-labs__fff-node@0.9.4.patch b/patches/@ff-labs__fff-node@0.9.4.patch deleted file mode 100644 index 04c2a803056c..000000000000 --- a/patches/@ff-labs__fff-node@0.9.4.patch +++ /dev/null @@ -1,53 +0,0 @@ -diff --git a/dist/src/binary.js b/dist/src/binary.js -index ee181aef5007e4bf34a49479c089ca30f73a320b..327e2c55c83cc4c50d396a3109190ef10af75ca7 100644 ---- a/dist/src/binary.js -+++ b/dist/src/binary.js -@@ -7,7 +7,7 @@ - */ - import { existsSync, readFileSync } from "node:fs"; - import { createRequire } from "node:module"; --import { dirname, join } from "node:path"; -+import { dirname, join, sep } from "node:path"; - import { fileURLToPath } from "node:url"; - import { getLibFilename, getNpmPackageName } from "./platform.js"; - /** -@@ -46,6 +46,16 @@ function getPackageDir() { - // Fallback: assume we're one level deep in src/ - return dirname(currentDir); - } -+function resolveUnpackedAsarPath(binaryPath) { -+ const pathSegments = binaryPath.split(sep); -+ const asarIndex = pathSegments.findLastIndex((segment) => segment.endsWith(".asar")); -+ if (asarIndex === -1) { -+ return binaryPath; -+ } -+ pathSegments[asarIndex] = `${pathSegments[asarIndex]}.unpacked`; -+ const unpackedPath = pathSegments.join(sep); -+ return existsSync(unpackedPath) ? unpackedPath : binaryPath; -+} - /** - * Check if the binary exists in any known location - */ -@@ -69,7 +77,7 @@ function resolveFromNpmPackage() { - const packageDir = dirname(packageJsonPath); - const binaryPath = join(packageDir, getLibFilename()); - if (existsSync(binaryPath)) { -- return binaryPath; -+ return resolveUnpackedAsarPath(binaryPath); - } - } - catch { -diff --git a/package.json b/package.json ---- a/package.json -+++ b/package.json -@@ -8,8 +8,9 @@ - "types": "dist/src/index.d.ts", - "exports": { - ".": { -+ "types": "./dist/src/index.d.ts", - "import": "./dist/src/index.js", -- "types": "./dist/src/index.d.ts" -+ "require": "./dist/src/index.js" - } - }, - "files": [ diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index b151892fbae4..7e6efe075030 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -146,7 +146,7 @@ patchedDependencies: '@clerk/expo@4.6.8': b8b22ab733de5bea846ad9e88046c10582352fe9ad86f314f368b2a823f0f281 '@effect/vitest@4.0.2': 595b7d26fb635caba9c3d39fcb189bb78a000192f8d3b60ead7174b310d1ade9 '@expo/metro-config@58.0.6': 90fa980e8b6480631fb2fbb04559834e3c612db40c550cd828f11be297d8d760 - '@ff-labs/fff-node@0.9.4': c4e3cc2420ceb9dc650f9d189e9c24baf7e83f342998bacda5f459a4ce7927a8 + '@ff-labs/fff-node@0.11.0': 8956d6ed6938a1bce69b2d0b067ff258dd9ca753c5bbe7006f7b68f760ea3ad2 '@legendapp/list@3.3.5': 680cc6a5c5b4a4032e467e7b3fde22f89a84c0ee2e6eac6fda737d6277cc0806 '@opencode/client@2.0.23': f725d6e6d9af0d56dc6ed71b863518fbfc751af1773cff2311209d2c404cf4cd '@opencode/protocol@2.0.23': 17a82f6c2c98fd0371e786c211a4fbdaaba403577a25733e5e99a0c25a16a685 @@ -613,8 +613,8 @@ importers: specifier: 4.0.2 version: 4.0.2(bufferutil@4.1.0)(effect@4.0.2(patch_hash=ec61ee307eaec3e17f757e0e6a16296ea4b7a8c3188df0c6ec5e66301fd78688))(utf-8-validate@6.0.6) '@ff-labs/fff-node': - specifier: 0.9.4 - version: 0.9.4(patch_hash=c4e3cc2420ceb9dc650f9d189e9c24baf7e83f342998bacda5f459a4ce7927a8) + specifier: 0.11.0 + version: 0.11.0(patch_hash=8956d6ed6938a1bce69b2d0b067ff258dd9ca753c5bbe7006f7b68f760ea3ad2) '@muse-code/sdk': specifier: 1.4.2 version: 1.4.2(@types/node@24.12.4) @@ -3815,55 +3815,60 @@ packages: resolution: {integrity: sha512-4aQzz9vgxcNXFfo/iyNgDDYfsU5XGKKxWxZopw0cVotHiW+U8IJbIxMaxsINs6bHhtkG3StKNPcOrn3eBuxKPw==} hasBin: true - '@ff-labs/fff-bin-darwin-arm64@0.9.4': - resolution: {integrity: sha512-xyivu2xB++O5xXDx5Qm50JsU2aXt8YgXlGVhH/HE7UMYDrE6L6f1RYdYs8Y0bn0D3D0+bFBrN5ELPszK9E4Wbw==} + '@ff-labs/fff-bin-android-arm64@0.11.0': + resolution: {integrity: sha512-7CmURAtJg1xCETKE8d46CUpeql9tpdsdbyoNCrNRkH+t608jMy+mLQxmyw7cBDOI0ljg5BaffxGZfOS2E6kasA==} + cpu: [arm64] + os: [android] + + '@ff-labs/fff-bin-darwin-arm64@0.11.0': + resolution: {integrity: sha512-C2VLBldxqNhTMtp1/NXULdEWpqfUKugP9E8BOMUDPw5qZH/YGC0tZQmeOlQUYOSScFQOiXZLJGXJMp3Uk+FGxg==} cpu: [arm64] os: [darwin] - '@ff-labs/fff-bin-darwin-x64@0.9.4': - resolution: {integrity: sha512-xLooAhCnTDCipPSMMZz7kGF3lhRHx6aP5fb6DJ0Ipyw/w/UWJb+xITJFszUl/QnIBoJ/qjDc93/FZMo1dk6gVA==} + '@ff-labs/fff-bin-darwin-x64@0.11.0': + resolution: {integrity: sha512-DOnG46YoSOR8SxNVMMe+xhPS2JjFUigMS2r0M4oCGfHDaWVY2mnYK/g1YxrAeJS3cRGO5N8Aj4RP1zq5Z2f6jQ==} cpu: [x64] os: [darwin] - '@ff-labs/fff-bin-linux-arm64-gnu@0.9.4': - resolution: {integrity: sha512-m5+8vA+1veaUUWonwva1WsU6m1HRm8CpYUzr06KDB65mewlmPbqz7+Fh7hjEfiD8C4mHVHe6RysULvAH1yhsdw==} + '@ff-labs/fff-bin-linux-arm64-gnu@0.11.0': + resolution: {integrity: sha512-wOTyNzovqN1+Kg3kPqfKqZ2+A262Um4bHrEIeAwKU9R7YoyMXI9oo6DTbEl2ullF3G01FaBt/PPHOZYi1q8ubw==} cpu: [arm64] os: [linux] libc: [glibc] - '@ff-labs/fff-bin-linux-arm64-musl@0.9.4': - resolution: {integrity: sha512-EMeWm7CSTVkizy4ZEzUkLDP024tVcbCUthduuIhekFQRDsiaAze0YboIylWb9HBHJCZlCCoZrWAl4nnJbsX7AA==} + '@ff-labs/fff-bin-linux-arm64-musl@0.11.0': + resolution: {integrity: sha512-dtVOgT/mKN4VTqOh4i3AWjc3Kd9uDX9xz9YsiPs33lNXpEi/x68qynuaqb7JM7x/eD/nYrsJRsb5ivtH1D6nrQ==} cpu: [arm64] os: [linux] libc: [musl] - '@ff-labs/fff-bin-linux-x64-gnu@0.9.4': - resolution: {integrity: sha512-pglE0uLkhnlE6bStXqfgUjYTSj+2sVwXaPfoA0QksidAsQor6NRt8004mygzC9DPubgHq5B9QezPfEwigKaP9Q==} + '@ff-labs/fff-bin-linux-x64-gnu@0.11.0': + resolution: {integrity: sha512-MJ1AJz9c5kxdTiIhmlEwA+hw57vBDoa+VQSr4F+1inaEiFDtem7EnXE1P8Bdhf4okGM557mCXgRrvCt4kM5pSg==} cpu: [x64] os: [linux] libc: [glibc] - '@ff-labs/fff-bin-linux-x64-musl@0.9.4': - resolution: {integrity: sha512-VNKxgl8qs3aTfXViX7lqRK1aLu311h8dtBFqG4Scv+9Oi7WprybUp5L7IZ8sxKERaDAaiJMXHodXa1c90QdK8w==} + '@ff-labs/fff-bin-linux-x64-musl@0.11.0': + resolution: {integrity: sha512-UjqEBtZphjH6MTK18kTlA+5ccUAu3PBATerAKh9otEWbLCwqpFV0ke8LON2+UavaO5+VhBUCk7Zi97AOQhn/9Q==} cpu: [x64] os: [linux] libc: [musl] - '@ff-labs/fff-bin-win32-arm64@0.9.4': - resolution: {integrity: sha512-uFEt0aNL54vQxq1ivjxRuo+thnhS4wLqa4INl4VXnXJUmwB42XXxD+gsj7vzhBLLx4cFf0aWgy/+TVDR8yjZtQ==} + '@ff-labs/fff-bin-win32-arm64@0.11.0': + resolution: {integrity: sha512-IF54PgYYi+AsCGseNG5kYpMqkwTmp/9bB8zvndp6tXZp4xLQ4G6x/NgHgM4vyK85Sv3FWr6Sf4OZQhP4mSSipA==} cpu: [arm64] os: [win32] - '@ff-labs/fff-bin-win32-x64@0.9.4': - resolution: {integrity: sha512-Yd2Eyxj+slWv+0QDW9/xBpu9FXq+hwD0rXQD5184/88d+xwWCLKhEP2w8I6OO9XCg+kLT79UJb+k0WwXUtBtMw==} + '@ff-labs/fff-bin-win32-x64@0.11.0': + resolution: {integrity: sha512-NFnFcueeRZ+QHvBg/k3KhduH20zFRCGqPHqjslk/3H0CHOMyP5AMTbscNwn5TZUhMutIRCfFzVI7mm+oU8jvCQ==} cpu: [x64] os: [win32] - '@ff-labs/fff-node@0.9.4': - resolution: {integrity: sha512-yUphwzcVBuNrg1iEAE5XVPOWfCLuq/BE1scUxtHMmLo+e1KuKWBRgSKFXGjNBfL8lV3c5VGwIgK66aBqmhqVBQ==} + '@ff-labs/fff-node@0.11.0': + resolution: {integrity: sha512-/7fX4kgy28pFZghxuXCAcIPQKb2+VqVirpFcDqMKgrFLTz56tVzHjOkFSdKGq7fa6wRb6eS5Dg9SaX1qyCcKxQ==} engines: {node: '>=18.0.0'} cpu: [x64, arm64] - os: [darwin, linux, win32] + os: [darwin, linux, win32, android] '@floating-ui/core@1.7.5': resolution: {integrity: sha512-1Ih4WTWyw0+lKyFMcBHGbb5U5FtuHJuujoyyr5zTaWS5EYMeT6Jb2AuDeftsCsEuchO+mM2ij5+q9crhydzLhQ==} @@ -14721,42 +14726,46 @@ snapshots: chalk: 4.1.2 js-yaml: 4.3.2 - '@ff-labs/fff-bin-darwin-arm64@0.9.4': + '@ff-labs/fff-bin-android-arm64@0.11.0': + optional: true + + '@ff-labs/fff-bin-darwin-arm64@0.11.0': optional: true - '@ff-labs/fff-bin-darwin-x64@0.9.4': + '@ff-labs/fff-bin-darwin-x64@0.11.0': optional: true - '@ff-labs/fff-bin-linux-arm64-gnu@0.9.4': + '@ff-labs/fff-bin-linux-arm64-gnu@0.11.0': optional: true - '@ff-labs/fff-bin-linux-arm64-musl@0.9.4': + '@ff-labs/fff-bin-linux-arm64-musl@0.11.0': optional: true - '@ff-labs/fff-bin-linux-x64-gnu@0.9.4': + '@ff-labs/fff-bin-linux-x64-gnu@0.11.0': optional: true - '@ff-labs/fff-bin-linux-x64-musl@0.9.4': + '@ff-labs/fff-bin-linux-x64-musl@0.11.0': optional: true - '@ff-labs/fff-bin-win32-arm64@0.9.4': + '@ff-labs/fff-bin-win32-arm64@0.11.0': optional: true - '@ff-labs/fff-bin-win32-x64@0.9.4': + '@ff-labs/fff-bin-win32-x64@0.11.0': optional: true - '@ff-labs/fff-node@0.9.4(patch_hash=c4e3cc2420ceb9dc650f9d189e9c24baf7e83f342998bacda5f459a4ce7927a8)': + '@ff-labs/fff-node@0.11.0(patch_hash=8956d6ed6938a1bce69b2d0b067ff258dd9ca753c5bbe7006f7b68f760ea3ad2)': dependencies: ffi-rs: 1.3.2 optionalDependencies: - '@ff-labs/fff-bin-darwin-arm64': 0.9.4 - '@ff-labs/fff-bin-darwin-x64': 0.9.4 - '@ff-labs/fff-bin-linux-arm64-gnu': 0.9.4 - '@ff-labs/fff-bin-linux-arm64-musl': 0.9.4 - '@ff-labs/fff-bin-linux-x64-gnu': 0.9.4 - '@ff-labs/fff-bin-linux-x64-musl': 0.9.4 - '@ff-labs/fff-bin-win32-arm64': 0.9.4 - '@ff-labs/fff-bin-win32-x64': 0.9.4 + '@ff-labs/fff-bin-android-arm64': 0.11.0 + '@ff-labs/fff-bin-darwin-arm64': 0.11.0 + '@ff-labs/fff-bin-darwin-x64': 0.11.0 + '@ff-labs/fff-bin-linux-arm64-gnu': 0.11.0 + '@ff-labs/fff-bin-linux-arm64-musl': 0.11.0 + '@ff-labs/fff-bin-linux-x64-gnu': 0.11.0 + '@ff-labs/fff-bin-linux-x64-musl': 0.11.0 + '@ff-labs/fff-bin-win32-arm64': 0.11.0 + '@ff-labs/fff-bin-win32-x64': 0.11.0 '@floating-ui/core@1.7.5': dependencies: diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml index 59358907b7c4..edbfad72d8e6 100644 --- a/pnpm-workspace.yaml +++ b/pnpm-workspace.yaml @@ -292,7 +292,7 @@ patchedDependencies: "@expo/metro-config@58.0.6": patches/@expo__metro-config@58.0.6.patch expo-sharing@58.0.13: patches/expo-sharing@58.0.13.patch expo-widgets@58.0.11: patches/expo-widgets@58.0.11.patch - "@ff-labs/fff-node@0.9.4": patches/@ff-labs__fff-node@0.9.4.patch + "@ff-labs/fff-node@0.11.0": patches/@ff-labs__fff-node@0.11.0.patch "@legendapp/list@3.3.5": patches/@legendapp__list@3.3.5.patch "@opencode/client@2.0.23": patches/@opencode__client@2.0.23.patch "@opencode/protocol@2.0.23": patches/@opencode__protocol@2.0.23.patch diff --git a/scripts/build-desktop-artifact.test.ts b/scripts/build-desktop-artifact.test.ts index b17c51ce2dba..434f7a886a3d 100644 --- a/scripts/build-desktop-artifact.test.ts +++ b/scripts/build-desktop-artifact.test.ts @@ -1527,7 +1527,7 @@ it.layer(NodeServices.layer)("build-desktop-artifact", (it) => { primaryProbe.args[4], path.join( fixture.packagedAppDir, - "resources/server.asar/node_modules/@ff-labs/fff-node/dist/src/index.js", + "resources/server.asar/node_modules/@ff-labs/fff-node/dist/index.js", ), ); assert.equal(primaryProbe.options.cwd, fixture.packagedAppDir); diff --git a/scripts/build-desktop-artifact.ts b/scripts/build-desktop-artifact.ts index 837308f3b1f4..c4ca2e6dd7dc 100644 --- a/scripts/build-desktop-artifact.ts +++ b/scripts/build-desktop-artifact.ts @@ -3236,10 +3236,7 @@ export const verifyWindowsPrimaryFffNativeLoad = Effect.fn( const probeRoot = yield* fs.makeTempDirectoryScoped({ prefix: "t3code-windows-primary-native-probe-", }); - const fffEntryPath = path.join( - input.asarPath, - "node_modules/@ff-labs/fff-node/dist/src/index.js", - ); + const fffEntryPath = path.join(input.asarPath, "node_modules/@ff-labs/fff-node/dist/index.js"); const probeEnv = { ...process.env }; delete probeEnv.ELECTRON_NO_ASAR; delete probeEnv.NODE_OPTIONS;