diff options
Diffstat (limited to 'packages/opencode/test/tool/bash.test.ts')
| -rw-r--r-- | packages/opencode/test/tool/bash.test.ts | 162 |
1 files changed, 81 insertions, 81 deletions
diff --git a/packages/opencode/test/tool/bash.test.ts b/packages/opencode/test/tool/bash.test.ts index 15518fa57..54e615408 100644 --- a/packages/opencode/test/tool/bash.test.ts +++ b/packages/opencode/test/tool/bash.test.ts @@ -30,7 +30,7 @@ const ctx = { abort: AbortSignal.any([]), messages: [], metadata: () => {}, - ask: async () => {}, + ask: () => Effect.void, } Shell.acceptable.reset() @@ -109,10 +109,11 @@ const each = (name: string, fn: (item: { label: string; shell: string }) => Prom const capture = (requests: Array<Omit<Permission.Request, "id" | "sessionID" | "tool">>, stop?: Error) => ({ ...ctx, - ask: async (req: Omit<Permission.Request, "id" | "sessionID" | "tool">) => { - requests.push(req) - if (stop) throw stop - }, + ask: (req: Omit<Permission.Request, "id" | "sessionID" | "tool">) => + Effect.sync(() => { + requests.push(req) + if (stop) throw stop + }), }) const mustTruncate = (result: { @@ -131,13 +132,13 @@ describe("tool.bash", () => { directory: projectRoot, fn: async () => { const bash = await initBash() - const result = await bash.execute( + const result = await Effect.runPromise(bash.execute( { command: "echo test", description: "Echo test message", }, ctx, - ) + )) expect(result.metadata.exit).toBe(0) expect(result.metadata.output).toContain("test") }, @@ -153,13 +154,13 @@ describe("tool.bash permissions", () => { fn: async () => { const bash = await initBash() const requests: Array<Omit<Permission.Request, "id" | "sessionID" | "tool">> = [] - await bash.execute( + await Effect.runPromise(bash.execute( { command: "echo hello", description: "Echo hello", }, capture(requests), - ) + )) expect(requests.length).toBe(1) expect(requests[0].permission).toBe("bash") expect(requests[0].patterns).toContain("echo hello") @@ -174,13 +175,13 @@ describe("tool.bash permissions", () => { fn: async () => { const bash = await initBash() const requests: Array<Omit<Permission.Request, "id" | "sessionID" | "tool">> = [] - await bash.execute( + await Effect.runPromise(bash.execute( { command: "echo foo && echo bar", description: "Echo twice", }, capture(requests), - ) + )) expect(requests.length).toBe(1) expect(requests[0].permission).toBe("bash") expect(requests[0].patterns).toContain("echo foo") @@ -198,13 +199,13 @@ describe("tool.bash permissions", () => { fn: async () => { const bash = await initBash() const requests: Array<Omit<Permission.Request, "id" | "sessionID" | "tool">> = [] - await bash.execute( + await Effect.runPromise(bash.execute( { command: "Write-Host foo; if ($?) { Write-Host bar }", description: "Check PowerShell conditional", }, capture(requests), - ) + )) const bashReq = requests.find((r) => r.permission === "bash") expect(bashReq).toBeDefined() expect(bashReq!.patterns).toContain("Write-Host foo") @@ -226,13 +227,13 @@ describe("tool.bash permissions", () => { const file = process.platform === "win32" ? `${process.env.WINDIR!.replaceAll("\\", "/")}/*` : "/etc/*" const want = process.platform === "win32" ? glob(path.join(process.env.WINDIR!, "*")) : "/etc/*" await expect( - bash.execute( + Effect.runPromise(bash.execute( { command: `cat ${file}`, description: "Read wildcard path", }, capture(requests, err), - ), + )), ).rejects.toThrow(err.message) const extDirReq = requests.find((r) => r.permission === "external_directory") expect(extDirReq).toBeDefined() @@ -257,13 +258,13 @@ describe("tool.bash permissions", () => { const bash = await initBash() const file = path.join(outerTmp.path, "outside.txt").replaceAll("\\", "/") const requests: Array<Omit<Permission.Request, "id" | "sessionID" | "tool">> = [] - await bash.execute( + await Effect.runPromise(bash.execute( { command: `echo $(cat "${file}")`, description: "Read nested bash file", }, capture(requests), - ) + )) const extDirReq = requests.find((r) => r.permission === "external_directory") const bashReq = requests.find((r) => r.permission === "bash") expect(extDirReq).toBeDefined() @@ -289,13 +290,13 @@ describe("tool.bash permissions", () => { const err = new Error("stop after permission") const requests: Array<Omit<Permission.Request, "id" | "sessionID" | "tool">> = [] await expect( - bash.execute( + Effect.runPromise(bash.execute( { command: `Copy-Item -PassThru "${process.env.WINDIR!.replaceAll("\\", "/")}/win.ini" ./out`, description: "Copy Windows ini", }, capture(requests, err), - ), + )), ).rejects.toThrow(err.message) const extDirReq = requests.find((r) => r.permission === "external_directory") expect(extDirReq).toBeDefined() @@ -316,13 +317,13 @@ describe("tool.bash permissions", () => { const bash = await initBash() const requests: Array<Omit<Permission.Request, "id" | "sessionID" | "tool">> = [] const file = `${process.env.WINDIR!.replaceAll("\\", "/")}/win.ini` - await bash.execute( + await Effect.runPromise(bash.execute( { command: `Write-Output $(Get-Content ${file})`, description: "Read nested PowerShell file", }, capture(requests), - ) + )) const extDirReq = requests.find((r) => r.permission === "external_directory") const bashReq = requests.find((r) => r.permission === "bash") expect(extDirReq).toBeDefined() @@ -347,13 +348,13 @@ describe("tool.bash permissions", () => { const err = new Error("stop after permission") const requests: Array<Omit<Permission.Request, "id" | "sessionID" | "tool">> = [] await expect( - bash.execute( + Effect.runPromise(bash.execute( { command: 'Get-Content "C:../outside.txt"', description: "Read drive-relative file", }, capture(requests, err), - ), + )), ).rejects.toThrow(err.message) expect(requests[0]?.permission).toBe("external_directory") if (requests[0]?.permission !== "external_directory") return @@ -375,13 +376,13 @@ describe("tool.bash permissions", () => { const err = new Error("stop after permission") const requests: Array<Omit<Permission.Request, "id" | "sessionID" | "tool">> = [] await expect( - bash.execute( + Effect.runPromise(bash.execute( { command: 'Get-Content "$HOME/.ssh/config"', description: "Read home config", }, capture(requests, err), - ), + )), ).rejects.toThrow(err.message) expect(requests[0]?.permission).toBe("external_directory") if (requests[0]?.permission !== "external_directory") return @@ -404,13 +405,13 @@ describe("tool.bash permissions", () => { const err = new Error("stop after permission") const requests: Array<Omit<Permission.Request, "id" | "sessionID" | "tool">> = [] await expect( - bash.execute( + Effect.runPromise(bash.execute( { command: 'Get-Content "$PWD/../outside.txt"', description: "Read pwd-relative file", }, capture(requests, err), - ), + )), ).rejects.toThrow(err.message) expect(requests[0]?.permission).toBe("external_directory") if (requests[0]?.permission !== "external_directory") return @@ -432,13 +433,13 @@ describe("tool.bash permissions", () => { const err = new Error("stop after permission") const requests: Array<Omit<Permission.Request, "id" | "sessionID" | "tool">> = [] await expect( - bash.execute( + Effect.runPromise(bash.execute( { command: 'Get-Content "$PSHOME/outside.txt"', description: "Read pshome file", }, capture(requests, err), - ), + )), ).rejects.toThrow(err.message) expect(requests[0]?.permission).toBe("external_directory") if (requests[0]?.permission !== "external_directory") return @@ -465,13 +466,13 @@ describe("tool.bash permissions", () => { const requests: Array<Omit<Permission.Request, "id" | "sessionID" | "tool">> = [] const root = path.parse(process.env.WINDIR!).root.replace(/[\\/]+$/, "") await expect( - bash.execute( + Effect.runPromise(bash.execute( { command: `Get-Content -Path "${root}$env:${key}\\Windows\\win.ini"`, description: "Read Windows ini with missing env", }, capture(requests, err), - ), + )), ).rejects.toThrow(err.message) const extDirReq = requests.find((r) => r.permission === "external_directory") expect(extDirReq).toBeDefined() @@ -495,13 +496,13 @@ describe("tool.bash permissions", () => { fn: async () => { const bash = await initBash() const requests: Array<Omit<Permission.Request, "id" | "sessionID" | "tool">> = [] - await bash.execute( + await Effect.runPromise(bash.execute( { command: "Get-Content $env:WINDIR/win.ini", description: "Read Windows ini from env", }, capture(requests), - ) + )) const extDirReq = requests.find((r) => r.permission === "external_directory") expect(extDirReq).toBeDefined() expect(extDirReq!.patterns).toContain( @@ -524,13 +525,13 @@ describe("tool.bash permissions", () => { const err = new Error("stop after permission") const requests: Array<Omit<Permission.Request, "id" | "sessionID" | "tool">> = [] await expect( - bash.execute( + Effect.runPromise(bash.execute( { command: `Get-Content -Path FileSystem::${process.env.WINDIR!.replaceAll("\\", "/")}/win.ini`, description: "Read Windows ini from FileSystem provider", }, capture(requests, err), - ), + )), ).rejects.toThrow(err.message) expect(requests[0]?.permission).toBe("external_directory") if (requests[0]?.permission !== "external_directory") return @@ -554,13 +555,13 @@ describe("tool.bash permissions", () => { const err = new Error("stop after permission") const requests: Array<Omit<Permission.Request, "id" | "sessionID" | "tool">> = [] await expect( - bash.execute( + Effect.runPromise(bash.execute( { command: "Get-Content ${env:WINDIR}/win.ini", description: "Read Windows ini from braced env", }, capture(requests, err), - ), + )), ).rejects.toThrow(err.message) expect(requests[0]?.permission).toBe("external_directory") if (requests[0]?.permission !== "external_directory") return @@ -582,13 +583,13 @@ describe("tool.bash permissions", () => { fn: async () => { const bash = await initBash() const requests: Array<Omit<Permission.Request, "id" | "sessionID" | "tool">> = [] - await bash.execute( + await Effect.runPromise(bash.execute( { command: "Set-Location C:/Windows", description: "Change location", }, capture(requests), - ) + )) const extDirReq = requests.find((r) => r.permission === "external_directory") const bashReq = requests.find((r) => r.permission === "bash") expect(extDirReq).toBeDefined() @@ -611,13 +612,13 @@ describe("tool.bash permissions", () => { fn: async () => { const bash = await initBash() const requests: Array<Omit<Permission.Request, "id" | "sessionID" | "tool">> = [] - await bash.execute( + await Effect.runPromise(bash.execute( { command: "Write-Output ('a' * 3)", description: "Write repeated text", }, capture(requests), - ) + )) const bashReq = requests.find((r) => r.permission === "bash") expect(bashReq).toBeDefined() expect(bashReq!.patterns).not.toContain("a * 3") @@ -638,13 +639,13 @@ describe("tool.bash permissions", () => { const err = new Error("stop after permission") const requests: Array<Omit<Permission.Request, "id" | "sessionID" | "tool">> = [] await expect( - bash.execute( + Effect.runPromise(bash.execute( { command: "cd ../", description: "Change to parent directory", }, capture(requests, err), - ), + )), ).rejects.toThrow(err.message) const extDirReq = requests.find((r) => r.permission === "external_directory") expect(extDirReq).toBeDefined() @@ -661,14 +662,14 @@ describe("tool.bash permissions", () => { const err = new Error("stop after permission") const requests: Array<Omit<Permission.Request, "id" | "sessionID" | "tool">> = [] await expect( - bash.execute( + Effect.runPromise(bash.execute( { command: "echo ok", workdir: os.tmpdir(), description: "Echo from temp dir", }, capture(requests, err), - ), + )), ).rejects.toThrow(err.message) const extDirReq = requests.find((r) => r.permission === "external_directory") expect(extDirReq).toBeDefined() @@ -691,14 +692,14 @@ describe("tool.bash permissions", () => { for (const dir of forms(outerTmp.path)) { const requests: Array<Omit<Permission.Request, "id" | "sessionID" | "tool">> = [] await expect( - bash.execute( + Effect.runPromise(bash.execute( { command: "echo ok", workdir: dir, description: "Echo from external dir", }, capture(requests, err), - ), + )), ).rejects.toThrow(err.message) const extDirReq = requests.find((r) => r.permission === "external_directory") @@ -724,14 +725,14 @@ describe("tool.bash permissions", () => { const requests: Array<Omit<Permission.Request, "id" | "sessionID" | "tool">> = [] const want = glob(path.join(os.tmpdir(), "*")) await expect( - bash.execute( + Effect.runPromise(bash.execute( { command: "echo ok", workdir: "/tmp", description: "Echo from Git Bash tmp", }, capture(requests, err), - ), + )), ).rejects.toThrow(err.message) expect(requests[0]).toMatchObject({ permission: "external_directory", @@ -754,13 +755,13 @@ describe("tool.bash permissions", () => { const requests: Array<Omit<Permission.Request, "id" | "sessionID" | "tool">> = [] const want = glob(path.join(os.tmpdir(), "*")) await expect( - bash.execute( + Effect.runPromise(bash.execute( { command: "cat /tmp/opencode-does-not-exist", description: "Read Git Bash tmp file", }, capture(requests, err), - ), + )), ).rejects.toThrow(err.message) expect(requests[0]).toMatchObject({ permission: "external_directory", @@ -789,13 +790,13 @@ describe("tool.bash permissions", () => { const requests: Array<Omit<Permission.Request, "id" | "sessionID" | "tool">> = [] const filepath = path.join(outerTmp.path, "outside.txt") await expect( - bash.execute( + Effect.runPromise(bash.execute( { command: `cat ${filepath}`, description: "Read external file", }, capture(requests, err), - ), + )), ).rejects.toThrow(err.message) const extDirReq = requests.find((r) => r.permission === "external_directory") const expected = glob(path.join(outerTmp.path, "*")) @@ -817,13 +818,13 @@ describe("tool.bash permissions", () => { fn: async () => { const bash = await initBash() const requests: Array<Omit<Permission.Request, "id" | "sessionID" | "tool">> = [] - await bash.execute( + await Effect.runPromise(bash.execute( { command: `rm -rf ${path.join(tmp.path, "nested")}`, description: "Remove nested dir", }, capture(requests), - ) + )) const extDirReq = requests.find((r) => r.permission === "external_directory") expect(extDirReq).toBeUndefined() }, @@ -837,13 +838,13 @@ describe("tool.bash permissions", () => { fn: async () => { const bash = await initBash() const requests: Array<Omit<Permission.Request, "id" | "sessionID" | "tool">> = [] - await bash.execute( + await Effect.runPromise(bash.execute( { command: "git log --oneline -5", description: "Git log", }, capture(requests), - ) + )) expect(requests.length).toBe(1) expect(requests[0].always.length).toBeGreaterThan(0) expect(requests[0].always.some((item) => item.endsWith("*"))).toBe(true) @@ -858,13 +859,13 @@ describe("tool.bash permissions", () => { fn: async () => { const bash = await initBash() const requests: Array<Omit<Permission.Request, "id" | "sessionID" | "tool">> = [] - await bash.execute( + await Effect.runPromise(bash.execute( { command: "cd .", description: "Stay in current directory", }, capture(requests), - ) + )) const bashReq = requests.find((r) => r.permission === "bash") expect(bashReq).toBeUndefined() }, @@ -880,10 +881,10 @@ describe("tool.bash permissions", () => { const err = new Error("stop after permission") const requests: Array<Omit<Permission.Request, "id" | "sessionID" | "tool">> = [] await expect( - bash.execute( + Effect.runPromise(bash.execute( { command: "echo test > output.txt", description: "Redirect test output" }, capture(requests, err), - ), + )), ).rejects.toThrow(err.message) const bashReq = requests.find((r) => r.permission === "bash") expect(bashReq).toBeDefined() @@ -899,7 +900,7 @@ describe("tool.bash permissions", () => { fn: async () => { const bash = await initBash() const requests: Array<Omit<Permission.Request, "id" | "sessionID" | "tool">> = [] - await bash.execute({ command: "ls -la", description: "List" }, capture(requests)) + await Effect.runPromise(bash.execute({ command: "ls -la", description: "List" }, capture(requests))) const bashReq = requests.find((r) => r.permission === "bash") expect(bashReq).toBeDefined() expect(bashReq!.always[0]).toBe("ls *") @@ -916,7 +917,7 @@ describe("tool.bash abort", () => { const bash = await initBash() const controller = new AbortController() const collected: string[] = [] - const result = bash.execute( + const res = await Effect.runPromise(bash.execute( { command: `echo before && sleep 30`, description: "Long running command", @@ -932,8 +933,7 @@ describe("tool.bash abort", () => { } }, }, - ) - const res = await result + )) expect(res.output).toContain("before") expect(res.output).toContain("User aborted the command") expect(collected.length).toBeGreaterThan(0) @@ -946,14 +946,14 @@ describe("tool.bash abort", () => { directory: projectRoot, fn: async () => { const bash = await initBash() - const result = await bash.execute( + const result = await Effect.runPromise(bash.execute( { command: `echo started && sleep 60`, description: "Timeout test", timeout: 500, }, ctx, - ) + )) expect(result.output).toContain("started") expect(result.output).toContain("bash tool terminated command after exceeding timeout") }, @@ -965,13 +965,13 @@ describe("tool.bash abort", () => { directory: projectRoot, fn: async () => { const bash = await initBash() - const result = await bash.execute( + const result = await Effect.runPromise(bash.execute( { command: `echo stdout_msg && echo stderr_msg >&2`, description: "Stderr test", }, ctx, - ) + )) expect(result.output).toContain("stdout_msg") expect(result.output).toContain("stderr_msg") expect(result.metadata.exit).toBe(0) @@ -984,13 +984,13 @@ describe("tool.bash abort", () => { directory: projectRoot, fn: async () => { const bash = await initBash() - const result = await bash.execute( + const result = await Effect.runPromise(bash.execute( { command: `exit 42`, description: "Non-zero exit", }, ctx, - ) + )) expect(result.metadata.exit).toBe(42) }, }) @@ -1002,7 +1002,7 @@ describe("tool.bash abort", () => { fn: async () => { const bash = await initBash() const updates: string[] = [] - const result = await bash.execute( + const result = await Effect.runPromise(bash.execute( { command: `echo first && sleep 0.1 && echo second`, description: "Streaming test", @@ -1014,7 +1014,7 @@ describe("tool.bash abort", () => { if (output) updates.push(output) }, }, - ) + )) expect(result.output).toContain("first") expect(result.output).toContain("second") expect(updates.length).toBeGreaterThan(1) @@ -1030,13 +1030,13 @@ describe("tool.bash truncation", () => { fn: async () => { const bash = await initBash() const lineCount = Truncate.MAX_LINES + 500 - const result = await bash.execute( + const result = await Effect.runPromise(bash.execute( { command: fill("lines", lineCount), description: "Generate lines exceeding limit", }, ctx, - ) + )) mustTruncate(result) expect(result.output).toContain("truncated") expect(result.output).toContain("The tool call succeeded but the output was truncated") @@ -1050,13 +1050,13 @@ describe("tool.bash truncation", () => { fn: async () => { const bash = await initBash() const byteCount = Truncate.MAX_BYTES + 10000 - const result = await bash.execute( + const result = await Effect.runPromise(bash.execute( { command: fill("bytes", byteCount), description: "Generate bytes exceeding limit", }, ctx, - ) + )) mustTruncate(result) expect(result.output).toContain("truncated") expect(result.output).toContain("The tool call succeeded but the output was truncated") @@ -1069,13 +1069,13 @@ describe("tool.bash truncation", () => { directory: projectRoot, fn: async () => { const bash = await initBash() - const result = await bash.execute( + const result = await Effect.runPromise(bash.execute( { command: "echo hello", description: "Echo hello", }, ctx, - ) + )) expect((result.metadata as { truncated?: boolean }).truncated).toBe(false) expect(result.output).toContain("hello") }, @@ -1088,13 +1088,13 @@ describe("tool.bash truncation", () => { fn: async () => { const bash = await initBash() const lineCount = Truncate.MAX_LINES + 100 - const result = await bash.execute( + const result = await Effect.runPromise(bash.execute( { command: fill("lines", lineCount), description: "Generate lines for file check", }, ctx, - ) + )) mustTruncate(result) const filepath = (result.metadata as { outputPath?: string }).outputPath |
