diff --git a/packages/core/src/tool/plugin/opencode.ts b/packages/core/src/tool/plugin/opencode.ts index 94ca72cc983..bfd091e1cdb 100644 --- a/packages/core/src/tool/plugin/opencode.ts +++ b/packages/core/src/tool/plugin/opencode.ts @@ -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( diff --git a/services/www/src/docs/content/tools.mdx b/services/www/src/docs/content/tools.mdx index 25ee3b0d6c9..2277ba6faa6 100644 --- a/services/www/src/docs/content/tools.mdx +++ b/services/www/src/docs/content/tools.mdx @@ -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: