fix(core): ask external_directory before session_move leaves the project (#62204)

This commit is contained in:
Aiden Cline 2026-11-05 17:02:16 -06:00 • committed by GitHub
parent 24008abeb3
commit 0dffb96c4b
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 16 additions and 5 deletions

View file

@ -6,6 +6,7 @@ import type { SessionHooks } from "@opencode/plugin/effect/session"
import { Model } from "@opencode/schema/model"
import { AbsolutePath } from "@opencode/schema/schema"
import { Session } from "@opencode/schema/session"
import { FSUtil } from "@opencode/util/fs-util"
import { Effect, Schema } from "effect"
import { toolFailure } from "../runtime.js"
import { FileAccess } from "../../file-access.js"
@ -145,14 +146,26 @@ export const Plugin = {
execute: (input, context) =>
Effect.gen(function* () {
const sessionID = input.sessionID ?? context.sessionID
const session = yield* ctx.session.get({ sessionID })
const directory = AbsolutePath.make(
FileAccess.resolvePath(session.location.directory, input.directory.trim()),
)
// The destination becomes the session's internal directory, so leaving the project
// needs the same approval as reaching outside it. The project's own worktrees don't.
const target = yield* access.resolve({ path: directory, kind: "directory" })
const worktrees = target.externalDirectory
? yield* ctx.worktree.list({ projectID: ctx.location.project.id })
: []
if (!worktrees.some((worktree) => FSUtil.contains(worktree.directory, directory)))
yield* access.authorizeExternal([target], context)
yield* ctx.session.move({
sessionID,
directory: input.directory,
directory,
delivery: "steer",
})
return {
output: { sessionID, directory: input.directory },
content: `Moved session ${sessionID} to ${input.directory}.`,
output: { sessionID, directory },
content: `Moved session ${sessionID} to ${directory}.`,
}
}).pipe(
Effect.mapError(

View file

@ -253,8 +253,6 @@ The `opencode` Code Mode namespace contains session utilities:
Rename this session to "Timeout cleanup", then move it to the new worktree.
```
These utilities do not request a built-in permission action.
### Worktrees
The same namespace manages worktrees for the session's project: