chore: generate
This commit is contained in:
@@ -4,7 +4,10 @@ import { Effect } from "effect"
|
|||||||
import fs from "fs/promises"
|
import fs from "fs/promises"
|
||||||
import path from "path"
|
import path from "path"
|
||||||
|
|
||||||
const it = process.platform === "win32" ? (await import("../lib/effect")).testEffect((await import("../../src/file")).File.defaultLayer) : undefined
|
const it =
|
||||||
|
process.platform === "win32"
|
||||||
|
? (await import("../lib/effect")).testEffect((await import("../../src/file")).File.defaultLayer)
|
||||||
|
: undefined
|
||||||
|
|
||||||
describe("file fsmonitor", () => {
|
describe("file fsmonitor", () => {
|
||||||
if (!it) {
|
if (!it) {
|
||||||
|
|||||||
@@ -106,13 +106,15 @@ describe("File.list path traversal protection", () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
describe("containsPath", () => {
|
describe("containsPath", () => {
|
||||||
it.instance("returns true for path inside directory", () =>
|
it.instance(
|
||||||
Effect.gen(function* () {
|
"returns true for path inside directory",
|
||||||
const test = yield* TestInstance
|
() =>
|
||||||
const ctx = yield* InstanceState.context
|
Effect.gen(function* () {
|
||||||
expect(containsPath(path.join(test.directory, "foo.txt"), ctx)).toBe(true)
|
const test = yield* TestInstance
|
||||||
expect(containsPath(path.join(test.directory, "src", "file.ts"), ctx)).toBe(true)
|
const ctx = yield* InstanceState.context
|
||||||
}),
|
expect(containsPath(path.join(test.directory, "foo.txt"), ctx)).toBe(true)
|
||||||
|
expect(containsPath(path.join(test.directory, "src", "file.ts"), ctx)).toBe(true)
|
||||||
|
}),
|
||||||
{ git: true },
|
{ git: true },
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -135,32 +137,38 @@ describe("containsPath", () => {
|
|||||||
{ git: true },
|
{ git: true },
|
||||||
)
|
)
|
||||||
|
|
||||||
it.instance("returns false for path outside both directory and worktree", () =>
|
it.instance(
|
||||||
Effect.gen(function* () {
|
"returns false for path outside both directory and worktree",
|
||||||
const ctx = yield* InstanceState.context
|
() =>
|
||||||
expect(containsPath("/etc/passwd", ctx)).toBe(false)
|
Effect.gen(function* () {
|
||||||
expect(containsPath("/tmp/other-project", ctx)).toBe(false)
|
const ctx = yield* InstanceState.context
|
||||||
}),
|
expect(containsPath("/etc/passwd", ctx)).toBe(false)
|
||||||
|
expect(containsPath("/tmp/other-project", ctx)).toBe(false)
|
||||||
|
}),
|
||||||
{ git: true },
|
{ git: true },
|
||||||
)
|
)
|
||||||
|
|
||||||
it.instance("returns false for path with .. escaping worktree", () =>
|
it.instance(
|
||||||
Effect.gen(function* () {
|
"returns false for path with .. escaping worktree",
|
||||||
const test = yield* TestInstance
|
() =>
|
||||||
const ctx = yield* InstanceState.context
|
Effect.gen(function* () {
|
||||||
expect(containsPath(path.join(test.directory, "..", "escape.txt"), ctx)).toBe(false)
|
const test = yield* TestInstance
|
||||||
}),
|
const ctx = yield* InstanceState.context
|
||||||
|
expect(containsPath(path.join(test.directory, "..", "escape.txt"), ctx)).toBe(false)
|
||||||
|
}),
|
||||||
{ git: true },
|
{ git: true },
|
||||||
)
|
)
|
||||||
|
|
||||||
it.instance("handles directory === worktree (running from repo root)", () =>
|
it.instance(
|
||||||
Effect.gen(function* () {
|
"handles directory === worktree (running from repo root)",
|
||||||
const test = yield* TestInstance
|
() =>
|
||||||
const ctx = yield* InstanceState.context
|
Effect.gen(function* () {
|
||||||
expect(ctx.directory).toBe(ctx.worktree)
|
const test = yield* TestInstance
|
||||||
expect(containsPath(path.join(test.directory, "file.txt"), ctx)).toBe(true)
|
const ctx = yield* InstanceState.context
|
||||||
expect(containsPath("/etc/passwd", ctx)).toBe(false)
|
expect(ctx.directory).toBe(ctx.worktree)
|
||||||
}),
|
expect(containsPath(path.join(test.directory, "file.txt"), ctx)).toBe(true)
|
||||||
|
expect(containsPath("/etc/passwd", ctx)).toBe(false)
|
||||||
|
}),
|
||||||
{ git: true },
|
{ git: true },
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -37,7 +37,9 @@ describe("session.list", () => {
|
|||||||
yield* Effect.promise(() => mkdir(path.join(test.directory, "packages", "app"), { recursive: true }))
|
yield* Effect.promise(() => mkdir(path.join(test.directory, "packages", "app"), { recursive: true }))
|
||||||
|
|
||||||
const root = yield* withSession({ title: "root" })
|
const root = yield* withSession({ title: "root" })
|
||||||
const parent = yield* withSession({ title: "parent" }).pipe(provideInstance(path.join(test.directory, "packages")))
|
const parent = yield* withSession({ title: "parent" }).pipe(
|
||||||
|
provideInstance(path.join(test.directory, "packages")),
|
||||||
|
)
|
||||||
const current = yield* withSession({ title: "current" }).pipe(
|
const current = yield* withSession({ title: "current" }).pipe(
|
||||||
provideInstance(path.join(test.directory, "packages", "opencode")),
|
provideInstance(path.join(test.directory, "packages", "opencode")),
|
||||||
)
|
)
|
||||||
@@ -64,7 +66,9 @@ describe("session.list", () => {
|
|||||||
yield* Effect.promise(() => mkdir(path.join(test.directory, "packages", "app"), { recursive: true }))
|
yield* Effect.promise(() => mkdir(path.join(test.directory, "packages", "app"), { recursive: true }))
|
||||||
|
|
||||||
const root = yield* withSession({ title: "root" })
|
const root = yield* withSession({ title: "root" })
|
||||||
const parent = yield* withSession({ title: "parent" }).pipe(provideInstance(path.join(test.directory, "packages")))
|
const parent = yield* withSession({ title: "parent" }).pipe(
|
||||||
|
provideInstance(path.join(test.directory, "packages")),
|
||||||
|
)
|
||||||
const current = yield* withSession({ title: "current" }).pipe(
|
const current = yield* withSession({ title: "current" }).pipe(
|
||||||
provideInstance(path.join(test.directory, "packages", "opencode")),
|
provideInstance(path.join(test.directory, "packages", "opencode")),
|
||||||
)
|
)
|
||||||
@@ -72,11 +76,9 @@ describe("session.list", () => {
|
|||||||
provideInstance(path.join(test.directory, "packages", "app")),
|
provideInstance(path.join(test.directory, "packages", "app")),
|
||||||
)
|
)
|
||||||
|
|
||||||
const ids = (
|
const ids = (yield* SessionNs.Service.use((session) =>
|
||||||
yield* SessionNs.Service.use((session) =>
|
session.list({ directory: path.join(test.directory, "packages", "opencode") }),
|
||||||
session.list({ directory: path.join(test.directory, "packages", "opencode") }),
|
)).map((session) => session.id)
|
||||||
)
|
|
||||||
).map((session) => session.id)
|
|
||||||
expect(ids).not.toContain(root.id)
|
expect(ids).not.toContain(root.id)
|
||||||
expect(ids).not.toContain(parent.id)
|
expect(ids).not.toContain(parent.id)
|
||||||
expect(ids).toContain(current.id)
|
expect(ids).toContain(current.id)
|
||||||
@@ -109,14 +111,12 @@ describe("session.list", () => {
|
|||||||
provideInstance(path.join(test.directory, "packages", "app")),
|
provideInstance(path.join(test.directory, "packages", "app")),
|
||||||
)
|
)
|
||||||
|
|
||||||
const pathIDs = (
|
const pathIDs = (yield* SessionNs.Service.use((session) =>
|
||||||
yield* SessionNs.Service.use((session) =>
|
session.list({
|
||||||
session.list({
|
directory: path.join(test.directory, "packages", "app"),
|
||||||
directory: path.join(test.directory, "packages", "app"),
|
path: "packages/opencode/src",
|
||||||
path: "packages/opencode/src",
|
}),
|
||||||
}),
|
)).map((session) => session.id)
|
||||||
)
|
|
||||||
).map((session) => session.id)
|
|
||||||
expect(pathIDs).not.toContain(parent.id)
|
expect(pathIDs).not.toContain(parent.id)
|
||||||
expect(pathIDs).toContain(current.id)
|
expect(pathIDs).toContain(current.id)
|
||||||
expect(pathIDs).toContain(deeper.id)
|
expect(pathIDs).toContain(deeper.id)
|
||||||
@@ -131,7 +131,9 @@ describe("session.list", () => {
|
|||||||
Effect.gen(function* () {
|
Effect.gen(function* () {
|
||||||
Flag.OPENCODE_EXPERIMENTAL_WORKSPACES = false
|
Flag.OPENCODE_EXPERIMENTAL_WORKSPACES = false
|
||||||
const test = yield* TestInstance
|
const test = yield* TestInstance
|
||||||
yield* Effect.promise(() => mkdir(path.join(test.directory, "packages", "opencode", "src"), { recursive: true }))
|
yield* Effect.promise(() =>
|
||||||
|
mkdir(path.join(test.directory, "packages", "opencode", "src"), { recursive: true }),
|
||||||
|
)
|
||||||
yield* Effect.promise(() => mkdir(path.join(test.directory, "packages", "app"), { recursive: true }))
|
yield* Effect.promise(() => mkdir(path.join(test.directory, "packages", "app"), { recursive: true }))
|
||||||
|
|
||||||
const current = yield* withSession({ title: "legacy-current" }).pipe(
|
const current = yield* withSession({ title: "legacy-current" }).pipe(
|
||||||
@@ -142,20 +144,22 @@ describe("session.list", () => {
|
|||||||
)
|
)
|
||||||
|
|
||||||
yield* Effect.sync(() =>
|
yield* Effect.sync(() =>
|
||||||
Database.use((db) => db.update(SessionTable).set({ path: null }).where(eq(SessionTable.id, current.id)).run()),
|
Database.use((db) =>
|
||||||
|
db.update(SessionTable).set({ path: null }).where(eq(SessionTable.id, current.id)).run(),
|
||||||
|
),
|
||||||
)
|
)
|
||||||
yield* Effect.sync(() =>
|
yield* Effect.sync(() =>
|
||||||
Database.use((db) => db.update(SessionTable).set({ path: null }).where(eq(SessionTable.id, sibling.id)).run()),
|
Database.use((db) =>
|
||||||
|
db.update(SessionTable).set({ path: null }).where(eq(SessionTable.id, sibling.id)).run(),
|
||||||
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
const pathIDs = (
|
const pathIDs = (yield* SessionNs.Service.use((session) =>
|
||||||
yield* SessionNs.Service.use((session) =>
|
session.list({
|
||||||
session.list({
|
directory: path.join(test.directory, "packages", "opencode", "src"),
|
||||||
directory: path.join(test.directory, "packages", "opencode", "src"),
|
path: "packages/opencode/src",
|
||||||
path: "packages/opencode/src",
|
}),
|
||||||
}),
|
)).map((session) => session.id)
|
||||||
)
|
|
||||||
).map((session) => session.id)
|
|
||||||
expect(pathIDs).toContain(current.id)
|
expect(pathIDs).toContain(current.id)
|
||||||
expect(pathIDs).not.toContain(sibling.id)
|
expect(pathIDs).not.toContain(sibling.id)
|
||||||
}),
|
}),
|
||||||
|
|||||||
@@ -212,7 +212,8 @@ describe("tool.apply_patch freeform", () => {
|
|||||||
const target = path.join(test.directory, "example.cs")
|
const target = path.join(test.directory, "example.cs")
|
||||||
yield* writeText(target, `${bom}using System;\n\nclass Test {}\n`)
|
yield* writeText(target, `${bom}using System;\n\nclass Test {}\n`)
|
||||||
|
|
||||||
const patchText = "*** Begin Patch\n*** Update File: example.cs\n@@\n class Test {}\n+class Next {}\n*** End Patch"
|
const patchText =
|
||||||
|
"*** Begin Patch\n*** Update File: example.cs\n@@\n class Test {}\n+class Next {}\n*** End Patch"
|
||||||
|
|
||||||
yield* execute({ patchText }, ctx)
|
yield* execute({ patchText }, ctx)
|
||||||
|
|
||||||
@@ -320,7 +321,10 @@ describe("tool.apply_patch freeform", () => {
|
|||||||
const { ctx } = makeCtx()
|
const { ctx } = makeCtx()
|
||||||
const patchText = "*** Begin Patch\n*** Update File: missing.txt\n@@\n-nope\n+better\n*** End Patch"
|
const patchText = "*** Begin Patch\n*** Update File: missing.txt\n@@\n-nope\n+better\n*** End Patch"
|
||||||
|
|
||||||
yield* expectFailure(execute({ patchText }, ctx), "apply_patch verification failed: Failed to read file to update")
|
yield* expectFailure(
|
||||||
|
execute({ patchText }, ctx),
|
||||||
|
"apply_patch verification failed: Failed to read file to update",
|
||||||
|
)
|
||||||
}),
|
}),
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -518,7 +522,8 @@ EOF`
|
|||||||
|
|
||||||
// Patch uses ASCII equivalents - should match via normalized pass
|
// Patch uses ASCII equivalents - should match via normalized pass
|
||||||
// The replacement uses ASCII quotes from the patch (not preserving Unicode)
|
// The replacement uses ASCII quotes from the patch (not preserving Unicode)
|
||||||
const patchText = '*** Begin Patch\n*** Update File: unicode.txt\n@@\n-He said "hello"\n+He said "hi"\n*** End Patch'
|
const patchText =
|
||||||
|
'*** Begin Patch\n*** Update File: unicode.txt\n@@\n-He said "hello"\n+He said "hi"\n*** End Patch'
|
||||||
|
|
||||||
yield* execute({ patchText }, ctx)
|
yield* execute({ patchText }, ctx)
|
||||||
// Result has ASCII quotes because that's what the patch specifies
|
// Result has ASCII quotes because that's what the patch specifies
|
||||||
|
|||||||
Reference in New Issue
Block a user