feat(core): add pinned session move tool (#46862)

Co-authored-by: thdxr <826656+thdxr@users.noreply.github.com>
Co-authored-by: rekram1-node <rekram1-node@users.noreply.github.com>
This commit is contained in:
opencode-agent[bot] 2026-09-02 14:26:45 -05:00 committed by GitHub
parent af332a2363
commit fc051e49ee
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 54 additions and 0 deletions

View file

@ -63,6 +63,7 @@ import { PatchTool } from "../tool/plugin/patch.js"
import { EditTool } from "../tool/plugin/edit.js"
import { GlobTool } from "../tool/plugin/glob.js"
import { GrepTool } from "../tool/plugin/grep.js"
import { OpenCodeTools } from "../tool/plugin/opencode.js"
import { QuestionTool } from "../tool/plugin/question.js"
import { ReadToolFileSystem } from "../tool/read-filesystem.js"
import { ReadTool } from "../tool/plugin/read.js"
@ -204,6 +205,7 @@ const pre = [
EditTool.Plugin,
GlobTool.Plugin,
GrepTool.Plugin,
OpenCodeTools.Plugin,
QuestionTool.Plugin,
ReadTool.Plugin,
ShellTool.Plugin,

View file

@ -0,0 +1,52 @@
export * as OpenCodeTools from "./opencode.js"
import { ToolFailure } from "@opencode-ai/ai"
import type { Context } from "@opencode-ai/plugin/effect/plugin"
import { AbsolutePath } from "@opencode-ai/schema/schema"
import { Session } from "@opencode-ai/schema/session"
import { Effect, Schema } from "effect"
export const MoveInput = Schema.Struct({
sessionID: Schema.optionalKey(Session.ID).annotate({ description: "Omit to move the current session." }),
directory: AbsolutePath.check(Schema.isMinLength(1)).annotate({
description: "Destination directory, relative to the target session's directory or absolute. Supports ~.",
}),
})
const MoveOutput = Schema.Struct({ sessionID: Session.ID, directory: AbsolutePath })
export const Plugin = {
id: "opencode.tools",
effect: Effect.fn("OpenCodeTools.Plugin")(function* (ctx: Context) {
yield* ctx.tool
.transform((draft) => {
draft.namespace({ name: "opencode", description: "OpenCode session and runtime tools." })
draft.add({
name: "session_move",
description:
"Move a session to another directory, or omit sessionID to move the current session. The current session moves at the next safe boundary; do not run destination-dependent tools in the same execute call.",
input: MoveInput,
output: MoveOutput,
options: { namespace: "opencode", codemode: true, pinned: true },
execute: (input, context) =>
Effect.gen(function* () {
const sessionID = input.sessionID ?? context.sessionID
yield* ctx.session.move({
sessionID,
directory: input.directory,
delivery: "steer",
})
return {
output: { sessionID, directory: input.directory },
content: `Moved session ${sessionID} to ${input.directory}.`,
}
}).pipe(
Effect.mapError(
(error) => new ToolFailure({ message: `Unable to move session to ${input.directory}`, error }),
),
),
})
})
.pipe(Effect.orDie)
}),
}