authorgravatar for 142208891+realhasanshoaib@users.noreply.github.comHasan Shoaib <142208891+realhasanshoaib@users.noreply.github.com> 2026-10-11 11:28:42+04:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2026-10-11 02:28:42-05:00
log5584d21688fc0e4cf6cd8057167df2514b759d3b
tree35adb9d4905af84e796272da364a6b12800862ff
parent4b6d9a09f80c4e782bdcf27ed1ef5c4f8fdd98db
signature Signed by PGP key B5690EEEBB952194

fix(server): update fff to stop runaway watcher rescans (#14543)

Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Co-authored-by: Yash Singh <saiansh2525@gmail.com>

8 files changed, 140 insertions(+), 99 deletions(-)

apps/server/package.json+1-1
......@@ -33,7 +33,7 @@
3333 "@cursor/sdk": "1.0.35",
3434 "@effect/platform-node": "catalog:",
3535 "@effect/platform-node-shared": "catalog:",
36 "@ff-labs/fff-node": "0.9.4",
36 "@ff-labs/fff-node": "0.11.0",
3737 "@muse-code/sdk": "1.4.2",
3838 "@napi-rs/keyring": "^1.3.0",
3939 "@opencode-ai/sdk": "^1.3.15",
apps/server/src/workspace/WorkspaceEntries.test.ts+36
......@@ -192,6 +192,42 @@ it.layer(layerTest, { excludeTestServices: true })("WorkspaceEntries", (it) => {
192192 60_000,
193193 );
194194
195 it.effect("includes images and other binary files in non-git workspace indexes", () =>
196 Effect.gen(function* () {
197 const cwd = yield* makeTempDir();
198 const imagePaths = ["photo.png", "photo.jpg", "photo.jpeg"];
199 const binaryPaths = [...imagePaths, "document.pdf", "archive.zip", "data.bin"];
200 for (const filePath of binaryPaths) {
201 yield* writeTextFile(cwd, filePath, "\0binary contents\n");
202 }
203 yield* writeTextFile(cwd, "notes.txt", "plain text\n");
204
205 const workspaceEntries = yield* WorkspaceEntries.WorkspaceEntries;
206 const expectedPaths = [...binaryPaths, "notes.txt"].toSorted();
207 const listed = yield* workspaceEntries.list({ cwd });
208 expect(listed.entries.map((entry) => entry.path).toSorted()).toEqual(expectedPaths);
209 expect(listed.truncated).toBe(false);
210
211 const searched = yield* workspaceEntries.search({
212 cwd,
213 query: "",
214 limit: 100,
215 kind: "file",
216 });
217 expect(searched.entries.map((entry) => entry.path).toSorted()).toEqual(expectedPaths);
218 expect(searched.truncated).toBe(false);
219
220 const images = yield* workspaceEntries.search({
221 cwd,
222 query: "",
223 limit: 100,
224 imageOnly: true,
225 });
226 expect(images.entries.map((entry) => entry.path).toSorted()).toEqual(imagePaths.toSorted());
227 expect(images.truncated).toBe(false);
228 }),
229 );
230
195231 it.effect("returns the complete cached workspace index", () =>
196232 Effect.gen(function* () {
197233 const cwd = yield* makeTempDir();
patches/@ff-labs__fff-node@0.11.0.patch created+52
......@@ -0,0 +1,52 @@
1diff --git a/package.json b/package.json
2index e000a78..8432546 100644
3--- a/package.json
4+++ b/package.json
5@@ -11,7 +11,7 @@
6 ".": {
7 "types": "./dist/index.d.ts",
8 "import": "./dist/index.js",
9- "require": "./dist/index.cjs",
10+ "require": "./dist/index.js",
11 "default": "./dist/index.js"
12 },
13 "./package.json": "./package.json"
14diff --git a/dist/index.js b/dist/index.js
15index 7c1d722..1d0bc27 100644
16--- a/dist/index.js
17+++ b/dist/index.js
18@@ -1,7 +1,7 @@
19 // src/binary.ts
20 import { existsSync, readFileSync } from "fs";
21 import { createRequire } from "module";
22-import { dirname, join } from "path";
23+import { dirname, join, sep } from "path";
24 import { fileURLToPath } from "url";
25
26 // src/platform.ts
27@@ -120,6 +120,16 @@ function getPackageDir() {
28 function binaryExists() {
29 return findBinary() !== null;
30 }
31+function resolveUnpackedAsarPath(binaryPath) {
32+ const pathSegments = binaryPath.split(sep);
33+ const asarIndex = pathSegments.findLastIndex((segment) => segment.endsWith(".asar"));
34+ if (asarIndex === -1) {
35+ return binaryPath;
36+ }
37+ pathSegments[asarIndex] = `${pathSegments[asarIndex]}.unpacked`;
38+ const unpackedPath = pathSegments.join(sep);
39+ return existsSync(unpackedPath) ? unpackedPath : binaryPath;
40+}
41 function resolveFromNpmPackage() {
42 const packageName = getNpmPackageName();
43 try {
44@@ -128,7 +138,7 @@ function resolveFromNpmPackage() {
45 const packageDir = dirname(packageJsonPath);
46 const binaryPath = join(packageDir, getLibFilename());
47 if (existsSync(binaryPath)) {
48- return binaryPath;
49+ return resolveUnpackedAsarPath(binaryPath);
50 }
51 } catch {
52 }
patches/@ff-labs__fff-node@0.9.4.patch deleted-53
......@@ -1,53 +0,0 @@
1diff --git a/dist/src/binary.js b/dist/src/binary.js
2index ee181aef5007e4bf34a49479c089ca30f73a320b..327e2c55c83cc4c50d396a3109190ef10af75ca7 100644
3--- a/dist/src/binary.js
4+++ b/dist/src/binary.js
5@@ -7,7 +7,7 @@
6 */
7 import { existsSync, readFileSync } from "node:fs";
8 import { createRequire } from "node:module";
9-import { dirname, join } from "node:path";
10+import { dirname, join, sep } from "node:path";
11 import { fileURLToPath } from "node:url";
12 import { getLibFilename, getNpmPackageName } from "./platform.js";
13 /**
14@@ -46,6 +46,16 @@ function getPackageDir() {
15 // Fallback: assume we're one level deep in src/
16 return dirname(currentDir);
17 }
18+function resolveUnpackedAsarPath(binaryPath) {
19+ const pathSegments = binaryPath.split(sep);
20+ const asarIndex = pathSegments.findLastIndex((segment) => segment.endsWith(".asar"));
21+ if (asarIndex === -1) {
22+ return binaryPath;
23+ }
24+ pathSegments[asarIndex] = `${pathSegments[asarIndex]}.unpacked`;
25+ const unpackedPath = pathSegments.join(sep);
26+ return existsSync(unpackedPath) ? unpackedPath : binaryPath;
27+}
28 /**
29 * Check if the binary exists in any known location
30 */
31@@ -69,7 +77,7 @@ function resolveFromNpmPackage() {
32 const packageDir = dirname(packageJsonPath);
33 const binaryPath = join(packageDir, getLibFilename());
34 if (existsSync(binaryPath)) {
35- return binaryPath;
36+ return resolveUnpackedAsarPath(binaryPath);
37 }
38 }
39 catch {
40diff --git a/package.json b/package.json
41--- a/package.json
42+++ b/package.json
43@@ -8,8 +8,9 @@
44 "types": "dist/src/index.d.ts",
45 "exports": {
46 ".": {
47+ "types": "./dist/src/index.d.ts",
48 "import": "./dist/src/index.js",
49- "types": "./dist/src/index.d.ts"
50+ "require": "./dist/src/index.js"
51 }
52 },
53 "files": [
pnpm-lock.yaml+48-39
......@@ -146,7 +146,7 @@ patchedDependencies:
146146 '@clerk/expo@4.6.8': b8b22ab733de5bea846ad9e88046c10582352fe9ad86f314f368b2a823f0f281
147147 '@effect/vitest@4.0.2': 595b7d26fb635caba9c3d39fcb189bb78a000192f8d3b60ead7174b310d1ade9
148148 '@expo/metro-config@58.0.6': 90fa980e8b6480631fb2fbb04559834e3c612db40c550cd828f11be297d8d760
149 '@ff-labs/fff-node@0.9.4': c4e3cc2420ceb9dc650f9d189e9c24baf7e83f342998bacda5f459a4ce7927a8
149 '@ff-labs/fff-node@0.11.0': 8956d6ed6938a1bce69b2d0b067ff258dd9ca753c5bbe7006f7b68f760ea3ad2
150150 '@legendapp/list@3.3.5': 680cc6a5c5b4a4032e467e7b3fde22f89a84c0ee2e6eac6fda737d6277cc0806
151151 '@opencode/client@2.0.23': f725d6e6d9af0d56dc6ed71b863518fbfc751af1773cff2311209d2c404cf4cd
152152 '@opencode/protocol@2.0.23': 17a82f6c2c98fd0371e786c211a4fbdaaba403577a25733e5e99a0c25a16a685
......@@ -613,8 +613,8 @@ importers:
613613 specifier: 4.0.2
614614 version: 4.0.2(bufferutil@4.1.0)(effect@4.0.2(patch_hash=ec61ee307eaec3e17f757e0e6a16296ea4b7a8c3188df0c6ec5e66301fd78688))(utf-8-validate@6.0.6)
615615 '@ff-labs/fff-node':
616 specifier: 0.9.4
617 version: 0.9.4(patch_hash=c4e3cc2420ceb9dc650f9d189e9c24baf7e83f342998bacda5f459a4ce7927a8)
616 specifier: 0.11.0
617 version: 0.11.0(patch_hash=8956d6ed6938a1bce69b2d0b067ff258dd9ca753c5bbe7006f7b68f760ea3ad2)
618618 '@muse-code/sdk':
619619 specifier: 1.4.2
620620 version: 1.4.2(@types/node@24.12.4)
......@@ -3815,55 +3815,60 @@ packages:
38153815 resolution: {integrity: sha512-4aQzz9vgxcNXFfo/iyNgDDYfsU5XGKKxWxZopw0cVotHiW+U8IJbIxMaxsINs6bHhtkG3StKNPcOrn3eBuxKPw==}
38163816 hasBin: true
38173817
3818 '@ff-labs/fff-bin-darwin-arm64@0.9.4':
3819 resolution: {integrity: sha512-xyivu2xB++O5xXDx5Qm50JsU2aXt8YgXlGVhH/HE7UMYDrE6L6f1RYdYs8Y0bn0D3D0+bFBrN5ELPszK9E4Wbw==}
3818 '@ff-labs/fff-bin-android-arm64@0.11.0':
3819 resolution: {integrity: sha512-7CmURAtJg1xCETKE8d46CUpeql9tpdsdbyoNCrNRkH+t608jMy+mLQxmyw7cBDOI0ljg5BaffxGZfOS2E6kasA==}
3820 cpu: [arm64]
3821 os: [android]
3822
3823 '@ff-labs/fff-bin-darwin-arm64@0.11.0':
3824 resolution: {integrity: sha512-C2VLBldxqNhTMtp1/NXULdEWpqfUKugP9E8BOMUDPw5qZH/YGC0tZQmeOlQUYOSScFQOiXZLJGXJMp3Uk+FGxg==}
38203825 cpu: [arm64]
38213826 os: [darwin]
38223827
3823 '@ff-labs/fff-bin-darwin-x64@0.9.4':
3824 resolution: {integrity: sha512-xLooAhCnTDCipPSMMZz7kGF3lhRHx6aP5fb6DJ0Ipyw/w/UWJb+xITJFszUl/QnIBoJ/qjDc93/FZMo1dk6gVA==}
3828 '@ff-labs/fff-bin-darwin-x64@0.11.0':
3829 resolution: {integrity: sha512-DOnG46YoSOR8SxNVMMe+xhPS2JjFUigMS2r0M4oCGfHDaWVY2mnYK/g1YxrAeJS3cRGO5N8Aj4RP1zq5Z2f6jQ==}
38253830 cpu: [x64]
38263831 os: [darwin]
38273832
3828 '@ff-labs/fff-bin-linux-arm64-gnu@0.9.4':
3829 resolution: {integrity: sha512-m5+8vA+1veaUUWonwva1WsU6m1HRm8CpYUzr06KDB65mewlmPbqz7+Fh7hjEfiD8C4mHVHe6RysULvAH1yhsdw==}
3833 '@ff-labs/fff-bin-linux-arm64-gnu@0.11.0':
3834 resolution: {integrity: sha512-wOTyNzovqN1+Kg3kPqfKqZ2+A262Um4bHrEIeAwKU9R7YoyMXI9oo6DTbEl2ullF3G01FaBt/PPHOZYi1q8ubw==}
38303835 cpu: [arm64]
38313836 os: [linux]
38323837 libc: [glibc]
38333838
3834 '@ff-labs/fff-bin-linux-arm64-musl@0.9.4':
3835 resolution: {integrity: sha512-EMeWm7CSTVkizy4ZEzUkLDP024tVcbCUthduuIhekFQRDsiaAze0YboIylWb9HBHJCZlCCoZrWAl4nnJbsX7AA==}
3839 '@ff-labs/fff-bin-linux-arm64-musl@0.11.0':
3840 resolution: {integrity: sha512-dtVOgT/mKN4VTqOh4i3AWjc3Kd9uDX9xz9YsiPs33lNXpEi/x68qynuaqb7JM7x/eD/nYrsJRsb5ivtH1D6nrQ==}
38363841 cpu: [arm64]
38373842 os: [linux]
38383843 libc: [musl]
38393844
3840 '@ff-labs/fff-bin-linux-x64-gnu@0.9.4':
3841 resolution: {integrity: sha512-pglE0uLkhnlE6bStXqfgUjYTSj+2sVwXaPfoA0QksidAsQor6NRt8004mygzC9DPubgHq5B9QezPfEwigKaP9Q==}
3845 '@ff-labs/fff-bin-linux-x64-gnu@0.11.0':
3846 resolution: {integrity: sha512-MJ1AJz9c5kxdTiIhmlEwA+hw57vBDoa+VQSr4F+1inaEiFDtem7EnXE1P8Bdhf4okGM557mCXgRrvCt4kM5pSg==}
38423847 cpu: [x64]
38433848 os: [linux]
38443849 libc: [glibc]
38453850
3846 '@ff-labs/fff-bin-linux-x64-musl@0.9.4':
3847 resolution: {integrity: sha512-VNKxgl8qs3aTfXViX7lqRK1aLu311h8dtBFqG4Scv+9Oi7WprybUp5L7IZ8sxKERaDAaiJMXHodXa1c90QdK8w==}
3851 '@ff-labs/fff-bin-linux-x64-musl@0.11.0':
3852 resolution: {integrity: sha512-UjqEBtZphjH6MTK18kTlA+5ccUAu3PBATerAKh9otEWbLCwqpFV0ke8LON2+UavaO5+VhBUCk7Zi97AOQhn/9Q==}
38483853 cpu: [x64]
38493854 os: [linux]
38503855 libc: [musl]
38513856
3852 '@ff-labs/fff-bin-win32-arm64@0.9.4':
3853 resolution: {integrity: sha512-uFEt0aNL54vQxq1ivjxRuo+thnhS4wLqa4INl4VXnXJUmwB42XXxD+gsj7vzhBLLx4cFf0aWgy/+TVDR8yjZtQ==}
3857 '@ff-labs/fff-bin-win32-arm64@0.11.0':
3858 resolution: {integrity: sha512-IF54PgYYi+AsCGseNG5kYpMqkwTmp/9bB8zvndp6tXZp4xLQ4G6x/NgHgM4vyK85Sv3FWr6Sf4OZQhP4mSSipA==}
38543859 cpu: [arm64]
38553860 os: [win32]
38563861
3857 '@ff-labs/fff-bin-win32-x64@0.9.4':
3858 resolution: {integrity: sha512-Yd2Eyxj+slWv+0QDW9/xBpu9FXq+hwD0rXQD5184/88d+xwWCLKhEP2w8I6OO9XCg+kLT79UJb+k0WwXUtBtMw==}
3862 '@ff-labs/fff-bin-win32-x64@0.11.0':
3863 resolution: {integrity: sha512-NFnFcueeRZ+QHvBg/k3KhduH20zFRCGqPHqjslk/3H0CHOMyP5AMTbscNwn5TZUhMutIRCfFzVI7mm+oU8jvCQ==}
38593864 cpu: [x64]
38603865 os: [win32]
38613866
3862 '@ff-labs/fff-node@0.9.4':
3863 resolution: {integrity: sha512-yUphwzcVBuNrg1iEAE5XVPOWfCLuq/BE1scUxtHMmLo+e1KuKWBRgSKFXGjNBfL8lV3c5VGwIgK66aBqmhqVBQ==}
3867 '@ff-labs/fff-node@0.11.0':
3868 resolution: {integrity: sha512-/7fX4kgy28pFZghxuXCAcIPQKb2+VqVirpFcDqMKgrFLTz56tVzHjOkFSdKGq7fa6wRb6eS5Dg9SaX1qyCcKxQ==}
38643869 engines: {node: '>=18.0.0'}
38653870 cpu: [x64, arm64]
3866 os: [darwin, linux, win32]
3871 os: [darwin, linux, win32, android]
38673872
38683873 '@floating-ui/core@1.7.5':
38693874 resolution: {integrity: sha512-1Ih4WTWyw0+lKyFMcBHGbb5U5FtuHJuujoyyr5zTaWS5EYMeT6Jb2AuDeftsCsEuchO+mM2ij5+q9crhydzLhQ==}
......@@ -14721,42 +14726,46 @@ snapshots:
1472114726 chalk: 4.1.2
1472214727 js-yaml: 4.3.2
1472314728
14724 '@ff-labs/fff-bin-darwin-arm64@0.9.4':
14729 '@ff-labs/fff-bin-android-arm64@0.11.0':
14730 optional: true
14731
14732 '@ff-labs/fff-bin-darwin-arm64@0.11.0':
1472514733 optional: true
1472614734
14727 '@ff-labs/fff-bin-darwin-x64@0.9.4':
14735 '@ff-labs/fff-bin-darwin-x64@0.11.0':
1472814736 optional: true
1472914737
14730 '@ff-labs/fff-bin-linux-arm64-gnu@0.9.4':
14738 '@ff-labs/fff-bin-linux-arm64-gnu@0.11.0':
1473114739 optional: true
1473214740
14733 '@ff-labs/fff-bin-linux-arm64-musl@0.9.4':
14741 '@ff-labs/fff-bin-linux-arm64-musl@0.11.0':
1473414742 optional: true
1473514743
14736 '@ff-labs/fff-bin-linux-x64-gnu@0.9.4':
14744 '@ff-labs/fff-bin-linux-x64-gnu@0.11.0':
1473714745 optional: true
1473814746
14739 '@ff-labs/fff-bin-linux-x64-musl@0.9.4':
14747 '@ff-labs/fff-bin-linux-x64-musl@0.11.0':
1474014748 optional: true
1474114749
14742 '@ff-labs/fff-bin-win32-arm64@0.9.4':
14750 '@ff-labs/fff-bin-win32-arm64@0.11.0':
1474314751 optional: true
1474414752
14745 '@ff-labs/fff-bin-win32-x64@0.9.4':
14753 '@ff-labs/fff-bin-win32-x64@0.11.0':
1474614754 optional: true
1474714755
14748 '@ff-labs/fff-node@0.9.4(patch_hash=c4e3cc2420ceb9dc650f9d189e9c24baf7e83f342998bacda5f459a4ce7927a8)':
14756 '@ff-labs/fff-node@0.11.0(patch_hash=8956d6ed6938a1bce69b2d0b067ff258dd9ca753c5bbe7006f7b68f760ea3ad2)':
1474914757 dependencies:
1475014758 ffi-rs: 1.3.2
1475114759 optionalDependencies:
14752 '@ff-labs/fff-bin-darwin-arm64': 0.9.4
14753 '@ff-labs/fff-bin-darwin-x64': 0.9.4
14754 '@ff-labs/fff-bin-linux-arm64-gnu': 0.9.4
14755 '@ff-labs/fff-bin-linux-arm64-musl': 0.9.4
14756 '@ff-labs/fff-bin-linux-x64-gnu': 0.9.4
14757 '@ff-labs/fff-bin-linux-x64-musl': 0.9.4
14758 '@ff-labs/fff-bin-win32-arm64': 0.9.4
14759 '@ff-labs/fff-bin-win32-x64': 0.9.4
14760 '@ff-labs/fff-bin-android-arm64': 0.11.0
14761 '@ff-labs/fff-bin-darwin-arm64': 0.11.0
14762 '@ff-labs/fff-bin-darwin-x64': 0.11.0
14763 '@ff-labs/fff-bin-linux-arm64-gnu': 0.11.0
14764 '@ff-labs/fff-bin-linux-arm64-musl': 0.11.0
14765 '@ff-labs/fff-bin-linux-x64-gnu': 0.11.0
14766 '@ff-labs/fff-bin-linux-x64-musl': 0.11.0
14767 '@ff-labs/fff-bin-win32-arm64': 0.11.0
14768 '@ff-labs/fff-bin-win32-x64': 0.11.0
1476014769
1476114770 '@floating-ui/core@1.7.5':
1476214771 dependencies:
pnpm-workspace.yaml+1-1
......@@ -292,7 +292,7 @@ patchedDependencies:
292292 "@expo/metro-config@58.0.6": patches/@expo__metro-config@58.0.6.patch
293293 expo-sharing@58.0.13: patches/expo-sharing@58.0.13.patch
294294 expo-widgets@58.0.11: patches/expo-widgets@58.0.11.patch
295 "@ff-labs/fff-node@0.9.4": patches/@ff-labs__fff-node@0.9.4.patch
295 "@ff-labs/fff-node@0.11.0": patches/@ff-labs__fff-node@0.11.0.patch
296296 "@legendapp/list@3.3.5": patches/@legendapp__list@3.3.5.patch
297297 "@opencode/client@2.0.23": patches/@opencode__client@2.0.23.patch
298298 "@opencode/protocol@2.0.23": patches/@opencode__protocol@2.0.23.patch
scripts/build-desktop-artifact.test.ts+1-1
......@@ -1527,7 +1527,7 @@ it.layer(NodeServices.layer)("build-desktop-artifact", (it) => {
15271527 primaryProbe.args[4],
15281528 path.join(
15291529 fixture.packagedAppDir,
1530 "resources/server.asar/node_modules/@ff-labs/fff-node/dist/src/index.js",
1530 "resources/server.asar/node_modules/@ff-labs/fff-node/dist/index.js",
15311531 ),
15321532 );
15331533 assert.equal(primaryProbe.options.cwd, fixture.packagedAppDir);
scripts/build-desktop-artifact.ts+1-4
......@@ -3236,10 +3236,7 @@ export const verifyWindowsPrimaryFffNativeLoad = Effect.fn(
32363236 const probeRoot = yield* fs.makeTempDirectoryScoped({
32373237 prefix: "t3code-windows-primary-native-probe-",
32383238 });
3239 const fffEntryPath = path.join(
3240 input.asarPath,
3241 "node_modules/@ff-labs/fff-node/dist/src/index.js",
3242 );
3239 const fffEntryPath = path.join(input.asarPath, "node_modules/@ff-labs/fff-node/dist/index.js");
32433240 const probeEnv = { ...process.env };
32443241 delete probeEnv.ELECTRON_NO_ASAR;
32453242 delete probeEnv.NODE_OPTIONS;