diff --git a/packages/kilo-sandbox/src/mutation-worker.ts b/packages/kilo-sandbox/src/mutation-worker.ts index 965cabf109c..f29909b893e 100644 --- a/packages/kilo-sandbox/src/mutation-worker.ts +++ b/packages/kilo-sandbox/src/mutation-worker.ts @@ -120,4 +120,6 @@ const response: Response = await read() (value) => ({ ok: true, value }), (cause) => ({ ok: false, error: failure(cause) }), ) -process.stdout.write(JSON.stringify(response)) +await new Promise((resolve, reject) => { + process.stdout.write(JSON.stringify(response), (error) => (error ? reject(error) : resolve())) +}) diff --git a/packages/kilo-sandbox/test/filesystem.test.ts b/packages/kilo-sandbox/test/filesystem.test.ts index e0281dee6e6..6eb9bba3ba5 100644 --- a/packages/kilo-sandbox/test/filesystem.test.ts +++ b/packages/kilo-sandbox/test/filesystem.test.ts @@ -125,6 +125,7 @@ describe("sandbox FileSystem", () => { const symbolic = path.join(base, "symbolic.bin") const streamed = path.join(base, "streamed.bin") const time = new Date("2024-01-02T03:04:05.000Z") + const copiedTime = new Date("2023-02-03T04:05:06.000Z") await execute( run( makeProfile(allowed), @@ -137,7 +138,9 @@ describe("sandbox FileSystem", () => { yield* fs.truncate(source, 3) yield* fs.utimes(source, time, time) yield* fs.copyFile(source, copy) - yield* fs.writeFileString(path.join(tree, "value.txt"), "tree") + const value = path.join(tree, "value.txt") + yield* fs.writeFileString(value, "tree") + yield* fs.utimes(value, copiedTime, copiedTime) yield* fs.copy(tree, copied, { overwrite: true, preserveTimestamps: true }) yield* fs.link(source, hard) yield* fs.symlink("source.bin", symbolic) @@ -155,8 +158,10 @@ describe("sandbox FileSystem", () => { expect([...(await readFile(streamed))]).toEqual([1, 2, 3, 4]) expect(await readFile(path.join(copied, "value.txt"), "utf8")).toBe("tree") const info = await stat(source) + const copiedInfo = await stat(path.join(copied, "value.txt")) expect(info.mode & 0o777).toBe(0o640) expect(info.mtime.getTime()).toBe(time.getTime()) + expect(copiedInfo.mtime.getTime()).toBe(copiedTime.getTime()) }, ) diff --git a/packages/opencode/test/kilocode/sandbox/session-tools.test.ts b/packages/opencode/test/kilocode/sandbox/session-tools.test.ts index 88b1dfa3c90..4740bba61c3 100644 --- a/packages/opencode/test/kilocode/sandbox/session-tools.test.ts +++ b/packages/opencode/test/kilocode/sandbox/session-tools.test.ts @@ -149,6 +149,7 @@ const registry = Layer.effect( }), ).pipe(Layer.provideMerge(base)) const it = testEffect(registry) +const mac = process.platform === "darwin" && existsSync("/usr/bin/sandbox-exec") ? it.live : it.live.skip function resolve(ctx: InstanceContext) { return SessionTools.resolve({ @@ -220,7 +221,7 @@ function fixture() { }) } -it.live("confines model-originated file mutations to the active worktree", () => +mac("confines model-originated file mutations to the active worktree", () => Effect.gen(function* () { const dirs = yield* fixture() const tools = yield* resolve(dirs.ctx) @@ -279,7 +280,7 @@ it.live("confines model-originated file mutations to the active worktree", () => }), ) -it.live("keeps model-originated file mutations writable in a local checkout", () => +mac("keeps model-originated file mutations writable in a local checkout", () => Effect.gen(function* () { const dirs = yield* fixture() const ctx = context(dirs.local, dirs.main, [dirs.a, dirs.b]) @@ -295,7 +296,7 @@ it.live("keeps model-originated file mutations writable in a local checkout", () }), ) -it.live("keeps concurrent session profiles call-local", () => +mac("keeps concurrent session profiles call-local", () => Effect.gen(function* () { const dirs = yield* fixture() const left = yield* resolve(context(dirs.a, dirs.main, [dirs.a, dirs.b])) @@ -327,8 +328,6 @@ it.live("keeps concurrent session profiles call-local", () => }), ) -const mac = process.platform === "darwin" && existsSync("/usr/bin/sandbox-exec") ? it.live : it.live.skip - mac("confines a model-originated sandboxed process to the active worktree", () => Effect.gen(function* () { const dirs = yield* fixture()