Skip to content

Commit e9af97e

Browse files
committed
fix
1 parent 3588063 commit e9af97e

2 files changed

Lines changed: 25 additions & 15 deletions

File tree

packages/opencode/src/session/prompt.ts

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -36,14 +36,15 @@ import { NamedError } from "@opencode-ai/util/error"
3636
import { SessionProcessor } from "./processor"
3737
import { Tool } from "@/tool/tool"
3838
import { Permission } from "@/permission"
39+
import { Instance } from "@/project/instance"
3940
import { SessionStatus } from "./status"
4041
import { LLM } from "./llm"
4142
import { Shell } from "@/shell/shell"
4243
import { AppFileSystem } from "@/filesystem"
4344
import { Truncate } from "@/tool/truncate"
4445
import { decodeDataUrl } from "@/util/data-url"
4546
import { Process } from "@/util/process"
46-
import { Cause, Effect, Exit, Layer, Option, Scope, Context } from "effect"
47+
import { Cause, Effect, Exit, Fiber, Layer, Option, Scope, Context } from "effect"
4748
import { EffectLogger } from "@/effect/logger"
4849
import { InstanceState } from "@/effect/instance-state"
4950
import { makeRuntime } from "@/effect/run-service"
@@ -807,7 +808,7 @@ NOTE: At any point in time through this workflow you should feel free to ask the
807808

808809
return yield* Effect.gen(function* () {
809810
try {
810-
const cfg = yield* Effect.promise(() => SandboxSpawn.settings())
811+
const cfg = yield* Effect.promise(Instance.bind(() => SandboxSpawn.settings()))
811812
const blocked = SandboxSpawn.excludedText(input.command, cfg.excluded_commands)
812813
if (blocked) {
813814
throw new SandboxSpawn.CommandError(blocked.command, blocked.rule)
@@ -901,7 +902,7 @@ NOTE: At any point in time through this workflow you should feel free to ask the
901902
})
902903
const exit = yield* Effect.gen(function* () {
903904
const handle = yield* spawner.spawn(proc)
904-
yield* Effect.forkScoped(
905+
const stdout = yield* Effect.forkScoped(
905906
Stream.runForEach(Stream.decodeText(handle.stdout), (chunk) =>
906907
Effect.sync(() => {
907908
output += chunk
@@ -912,7 +913,7 @@ NOTE: At any point in time through this workflow you should feel free to ask the
912913
}),
913914
),
914915
)
915-
yield* Effect.forkScoped(
916+
const err = yield* Effect.forkScoped(
916917
Stream.runForEach(Stream.decodeText(handle.stderr), (chunk) =>
917918
Effect.sync(() => {
918919
stderr += chunk
@@ -924,7 +925,11 @@ NOTE: At any point in time through this workflow you should feel free to ask the
924925
}),
925926
),
926927
)
927-
return yield* handle.exitCode
928+
929+
const code = yield* handle.exitCode
930+
yield* Fiber.await(stdout)
931+
yield* Fiber.await(err)
932+
return code
928933
}).pipe(
929934
Effect.scoped,
930935
Effect.onInterrupt(() =>

packages/opencode/src/tool/bash.ts

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ import { Shell } from "@/shell/shell"
1616
import { BashArity } from "@/permission/arity"
1717
import { Truncate } from "./truncate"
1818
import { Plugin } from "@/plugin"
19-
import { Cause, Effect, Exit, Stream } from "effect"
19+
import { Cause, Effect, Exit, Fiber, Stream } from "effect"
2020
import { ChildProcess } from "effect/unstable/process"
2121
import { ChildProcessSpawner } from "effect/unstable/process/ChildProcessSpawner"
2222
import { SandboxSpawn } from "@/sandbox/spawn"
@@ -385,7 +385,6 @@ export const BashTool = Tool.define(
385385
const spawner = yield* ChildProcessSpawner
386386
const fs = yield* AppFileSystem.Service
387387
const plugin = yield* Plugin.Service
388-
const sandbox = yield* Effect.promise(() => SandboxSpawn.settings())
389388

390389
const cygpath = Effect.fn("BashTool.cygpath")(function* (shell: string, text: string) {
391390
const lines = yield* spawner
@@ -498,6 +497,7 @@ export const BashTool = Tool.define(
498497
)
499498

500499
const exec = Effect.fnUntraced(function* (proc: ReturnType<typeof ChildProcess.make>) {
500+
let stdout = ""
501501
let stderr = ""
502502
let expired = false
503503
let aborted = false
@@ -506,8 +506,9 @@ export const BashTool = Tool.define(
506506
Effect.gen(function* () {
507507
const handle = yield* spawner.spawn(proc)
508508

509-
yield* Effect.forkScoped(
509+
const out = yield* Effect.forkScoped(
510510
Stream.runForEach(Stream.decodeText(handle.stdout), (chunk) => {
511+
stdout += chunk
511512
output += chunk
512513
return ctx.metadata({
513514
metadata: {
@@ -517,7 +518,7 @@ export const BashTool = Tool.define(
517518
})
518519
}),
519520
)
520-
yield* Effect.forkScoped(
521+
const err = yield* Effect.forkScoped(
521522
Stream.runForEach(Stream.decodeText(handle.stderr), (chunk) => {
522523
stderr += chunk
523524
output += chunk
@@ -529,7 +530,6 @@ export const BashTool = Tool.define(
529530
})
530531
}),
531532
)
532-
533533
const abort = Effect.callback<void>((resume) => {
534534
if (ctx.abort.aborted) return resume(Effect.void)
535535
const handler = () => resume(Effect.void)
@@ -554,6 +554,9 @@ export const BashTool = Tool.define(
554554
yield* handle.kill({ forceKillAfter: "3 seconds" }).pipe(Effect.orDie)
555555
}
556556

557+
yield* Fiber.await(out)
558+
yield* Fiber.await(err)
559+
557560
return exit.kind === "exit" ? exit.code : null
558561
}),
559562
).pipe(Effect.orDie)
@@ -682,24 +685,26 @@ export const BashTool = Tool.define(
682685
Effect.sync(() => {
683686
const shell = Shell.acceptable()
684687
const name = Shell.name(shell)
688+
let dir = process.cwd()
689+
try {
690+
dir = Instance.directory
691+
} catch {}
685692
const chain =
686693
name === "powershell"
687694
? "If the commands depend on each other and must run sequentially, avoid '&&' in this shell because Windows PowerShell 5.1 does not support it. Use PowerShell conditionals such as `cmd1; if ($?) { cmd2 }` when later commands must depend on earlier success."
688695
: "If the commands depend on each other and must run sequentially, use a single Bash call with '&&' to chain them together (e.g., `git add . && git commit -m \"message\" && git push`). For instance, if one operation must complete before another starts (like mkdir before cp, Write before Bash for git operations, or git add before git commit), run these operations sequentially instead."
689696
log.info("bash tool using shell", { shell })
690697

691698
return {
692-
description: DESCRIPTION.replaceAll("${directory}", Instance.directory)
699+
description: DESCRIPTION.replaceAll("${directory}", dir)
693700
.replaceAll("${os}", process.platform)
694701
.replaceAll("${shell}", name)
695702
.replaceAll("${chaining}", chain)
696703
.replaceAll("${maxLines}", String(Truncate.MAX_LINES))
697704
.replaceAll("${maxBytes}", String(Truncate.MAX_BYTES))
698705
.replaceAll(
699706
"${unsandboxed}",
700-
sandbox.allow_unsandboxed_retry
701-
? "\n\nIf you know a command needs to run outside the sandbox before the first attempt, put `# opencode:unsandboxed <reason>` on the first non-empty line of the command. This asks for the separate `bash:unsandboxed` permission before execution while keeping the normal bash tool schema unchanged."
702-
: "",
707+
"\n\nIf sandbox settings allow unsandboxed retries and you know a command needs to run outside the sandbox before the first attempt, put `# opencode:unsandboxed <reason>` on the first non-empty line of the command. This asks for the separate `bash:unsandboxed` permission before execution while keeping the normal bash tool schema unchanged.",
703708
),
704709
parameters: Parameters,
705710
execute: (params: z.infer<typeof Parameters>, ctx: Tool.Context) =>
@@ -713,7 +718,7 @@ export const BashTool = Tool.define(
713718
throw new Error(`Invalid timeout value: ${params.timeout}. Timeout must be a positive number.`)
714719
}
715720
const timeout = params.timeout ?? DEFAULT_TIMEOUT
716-
const cfg = yield* Effect.promise(() => SandboxSpawn.settings())
721+
const cfg = yield* Effect.promise(Instance.bind(() => SandboxSpawn.settings()))
717722
const ps = PS.has(name)
718723
const root = yield* parse(command, ps)
719724
const scan = yield* collect(root, cwd, ps, shell, cfg.excluded_commands)

0 commit comments

Comments
 (0)