refactor(plugin): name tool execution context (#50195)

This commit is contained in:
Aiden Cline
2026-09-20 11:36:19 -05:00
committed by GitHub
parent e3a3fa7108
commit c555559ac1
3 changed files with 21 additions and 21 deletions
@@ -26,10 +26,10 @@ it.live("Promise tool executors receive interruption through their AbortSignal",
description: "Wait until cancelled",
input: { type: "object", properties: {}, additionalProperties: false },
options: { codemode: false },
execute: (_input, tool) =>
execute: (_input, context) =>
new Promise<never>((_resolve, reject) => {
tool.signal.addEventListener("abort", () => reject(new Error("cancelled")), { once: true })
Effect.runSync(Deferred.succeed(started, tool.signal))
context.signal.addEventListener("abort", () => reject(new Error("cancelled")), { once: true })
Effect.runSync(Deferred.succeed(started, context.signal))
}),
}),
)
+12 -12
View File
@@ -237,26 +237,26 @@ export function fromPromise(plugin: Plugin) {
const VcsEndpoints = ClientApi.groups["server.vcs"].endpoints
const WebSearchEndpoints = ClientApi.groups["server.websearch"].endpoints
const WorktreeEndpoints = ClientApi.groups["server.worktree"].endpoints
const context = yield* Effect.context<Scope.Scope>()
const runtime = yield* Effect.context<Scope.Scope>()
const streams = yield* makeStreams()
// Run a hook registration on the plugin scope and resolve once it is registered.
const register = (effect: Effect.Effect<HostRegistration, never, Scope.Scope>): Promise<Registration> =>
Effect.runPromiseWith(context)(effect).then((registration) => ({
dispose: () => Effect.runPromiseWith(context)(registration.dispose),
Effect.runPromiseWith(runtime)(effect).then((registration) => ({
dispose: () => Effect.runPromiseWith(runtime)(registration.dispose),
}))
const run = <A, E>(effect: Effect.Effect<A, E>) => Effect.runPromiseWith(context)(effect)
const run = <A, E>(effect: Effect.Effect<A, E>) => Effect.runPromiseWith(runtime)(effect)
const promiseExecutor =
(execute: Tool.Info["execute"]): Info["execute"] =>
(input, tool) =>
Effect.runPromiseWith(context)(
(input, context) =>
Effect.runPromiseWith(runtime)(
execute(input, {
...tool,
progress: (update) => Effect.promise(() => tool.progress(update)),
...context,
progress: (update) => Effect.promise(() => context.progress(update)),
}),
{ signal: tool.signal },
{ signal: context.signal },
)
const adaptApiMethod = <PromiseMethod>(
@@ -274,7 +274,7 @@ export function fromPromise(plugin: Plugin) {
const result = yield* method(Object.assign({}, ...decoded) as never)
if (compiled.noContent) return undefined
return yield* compiled.encode(result)
}).pipe(Effect.runPromiseWith(context))) as PromiseMethod
}).pipe(Effect.runPromiseWith(runtime))) as PromiseMethod
}
const transform =
@@ -425,8 +425,8 @@ export function fromPromise(plugin: Plugin) {
),
reload: () => run(host.integration.reload()),
connection: {
active: (id) => Effect.runPromiseWith(context)(host.integration.connection.active(id)),
resolve: (connection) => Effect.runPromiseWith(context)(host.integration.connection.resolve(connection)),
active: (id) => Effect.runPromiseWith(runtime)(host.integration.connection.active(id)),
resolve: (connection) => Effect.runPromiseWith(runtime)(host.integration.connection.resolve(connection)),
},
},
mcp: {
@@ -919,20 +919,20 @@ const registration = await ctx.tool.transform((editor) => {
additionalProperties: false,
},
options: { namespace: "acme", codemode: true },
execute: async (input, tool) => {
await tool.progress({ status: "greeting" })
execute: async (input, context) => {
await context.progress({ status: "greeting" })
return { content: `Hello ${(input as { name: string }).name}!` }
},
})
})
```
Promise tool executors receive `tool.signal`. Pass it to cancellable work such as `fetch` so stopping the Session also
stops the underlying operation.
Promise tool executors receive `context.signal`. Pass it to cancellable work such as `fetch` so stopping the Session
also stops the underlying operation.
```ts
execute: async ({ url }, tool) => {
const response = await fetch(url, { signal: tool.signal })
execute: async ({ url }, context) => {
const response = await fetch(url, { signal: context.signal })
return { content: await response.text() }
}
```