refactor(tool): Tool.Context.metadata returns Effect (#21972)

This commit is contained in:
Kit Langton
2026-04-10 23:12:04 -04:00
committed by GitHub
parent 9581bf0670
commit 3dd09147c2
17 changed files with 63 additions and 67 deletions
+1 -1
View File
@@ -158,7 +158,7 @@ async function createToolContext(agent: Agent.Info) {
agent: agent.name, agent: agent.name,
abort: new AbortController().signal, abort: new AbortController().signal,
messages: [], messages: [],
metadata: () => {}, metadata: () => Effect.void,
ask(req: Omit<Permission.Request, "id" | "sessionID" | "tool">) { ask(req: Omit<Permission.Request, "id" | "sessionID" | "tool">) {
return Effect.sync(() => { return Effect.sync(() => {
for (const pattern of req.patterns) { for (const pattern of req.patterns) {
+22 -27
View File
@@ -364,21 +364,19 @@ NOTE: At any point in time through this workflow you should feel free to ask the
agent: input.agent.name, agent: input.agent.name,
messages: input.messages, messages: input.messages,
metadata: (val) => metadata: (val) =>
run.promise( input.processor.updateToolCall(options.toolCallId, (match) => {
input.processor.updateToolCall(options.toolCallId, (match) => { if (!["running", "pending"].includes(match.state.status)) return match
if (!["running", "pending"].includes(match.state.status)) return match return {
return { ...match,
...match, state: {
state: { title: val.title,
title: val.title, metadata: val.metadata,
metadata: val.metadata, status: "running",
status: "running", input: args,
input: args, time: { start: Date.now() },
time: { start: Date.now() }, },
}, }
} }),
}),
),
ask: (req) => ask: (req) =>
permission permission
.ask({ .ask({
@@ -592,17 +590,14 @@ NOTE: At any point in time through this workflow you should feel free to ask the
callID: part.callID, callID: part.callID,
extra: { bypassAgentCheck: true, promptOps }, extra: { bypassAgentCheck: true, promptOps },
messages: msgs, messages: msgs,
metadata(val: { title?: string; metadata?: Record<string, any> }) { metadata: (val: { title?: string; metadata?: Record<string, any> }) =>
return run.promise( Effect.gen(function* () {
Effect.gen(function* () { part = yield* sessions.updatePart({
part = yield* sessions.updatePart({ ...part,
...part, type: "tool",
type: "tool", state: { ...part.state, ...val },
state: { ...part.state, ...val }, } satisfies MessageV2.ToolPart)
} satisfies MessageV2.ToolPart) }),
}),
)
},
ask: (req: any) => ask: (req: any) =>
permission permission
.ask({ .ask({
@@ -1054,7 +1049,7 @@ NOTE: At any point in time through this workflow you should feel free to ask the
messageID: info.id, messageID: info.id,
extra: { bypassCwdCheck: true, ...extra }, extra: { bypassCwdCheck: true, ...extra },
messages: [], messages: [],
metadata: () => {}, metadata: () => Effect.void,
ask: () => Effect.void, ask: () => Effect.void,
}) })
.pipe(Effect.onInterrupt(() => Effect.sync(() => controller.abort()))) .pipe(Effect.onInterrupt(() => Effect.sync(() => controller.abort())))
+10 -11
View File
@@ -385,7 +385,7 @@ export const BashTool = Tool.define(
let expired = false let expired = false
let aborted = false let aborted = false
ctx.metadata({ yield* ctx.metadata({
metadata: { metadata: {
output: "", output: "",
description: input.description, description: input.description,
@@ -397,16 +397,15 @@ export const BashTool = Tool.define(
const handle = yield* spawner.spawn(cmd(input.shell, input.name, input.command, input.cwd, input.env)) const handle = yield* spawner.spawn(cmd(input.shell, input.name, input.command, input.cwd, input.env))
yield* Effect.forkScoped( yield* Effect.forkScoped(
Stream.runForEach(Stream.decodeText(handle.all), (chunk) => Stream.runForEach(Stream.decodeText(handle.all), (chunk) => {
Effect.sync(() => { output += chunk
output += chunk return ctx.metadata({
ctx.metadata({ metadata: {
metadata: { output: preview(output),
output: preview(output), description: input.description,
description: input.description, },
}, })
}) },
}),
), ),
) )
+1 -1
View File
@@ -158,7 +158,7 @@ export const EditTool = Tool.define(
if (change.removed) filediff.deletions += change.count || 0 if (change.removed) filediff.deletions += change.count || 0
} }
ctx.metadata({ yield* ctx.metadata({
metadata: { metadata: {
diff, diff,
filediff, filediff,
+1 -1
View File
@@ -109,7 +109,7 @@ export const TaskTool = Tool.define(
providerID: msg.info.providerID, providerID: msg.info.providerID,
} }
ctx.metadata({ yield* ctx.metadata({
title: params.description, title: params.description,
metadata: { metadata: {
sessionId: nextSession.id, sessionId: nextSession.id,
+1 -1
View File
@@ -22,7 +22,7 @@ export namespace Tool {
callID?: string callID?: string
extra?: { [key: string]: any } extra?: { [key: string]: any }
messages: MessageV2.WithParts[] messages: MessageV2.WithParts[]
metadata(input: { title?: string; metadata?: M }): void metadata(input: { title?: string; metadata?: M }): Effect.Effect<void>
ask(input: Omit<Permission.Request, "id" | "sessionID" | "tool">): Effect.Effect<void> ask(input: Omit<Permission.Request, "id" | "sessionID" | "tool">): Effect.Effect<void>
} }
@@ -22,7 +22,7 @@ const baseCtx = {
agent: "build", agent: "build",
abort: AbortSignal.any([]), abort: AbortSignal.any([]),
messages: [], messages: [],
metadata: () => {}, metadata: () => Effect.void,
} }
type AskInput = { type AskInput = {
+14 -12
View File
@@ -29,7 +29,7 @@ const ctx = {
agent: "build", agent: "build",
abort: AbortSignal.any([]), abort: AbortSignal.any([]),
messages: [], messages: [],
metadata: () => {}, metadata: () => Effect.void,
ask: () => Effect.void, ask: () => Effect.void,
} }
@@ -982,13 +982,14 @@ describe("tool.bash abort", () => {
{ {
...ctx, ...ctx,
abort: controller.signal, abort: controller.signal,
metadata: (input) => { metadata: (input) =>
const output = (input.metadata as { output?: string })?.output Effect.sync(() => {
if (output && output.includes("before") && !controller.signal.aborted) { const output = (input.metadata as { output?: string })?.output
collected.push(output) if (output && output.includes("before") && !controller.signal.aborted) {
controller.abort() collected.push(output)
} controller.abort()
}, }
}),
}, },
), ),
) )
@@ -1074,10 +1075,11 @@ describe("tool.bash abort", () => {
}, },
{ {
...ctx, ...ctx,
metadata: (input) => { metadata: (input) =>
const output = (input.metadata as { output?: string })?.output Effect.sync(() => {
if (output) updates.push(output) const output = (input.metadata as { output?: string })?.output
}, if (output) updates.push(output)
}),
}, },
), ),
) )
+1 -1
View File
@@ -20,7 +20,7 @@ const ctx = {
agent: "build", agent: "build",
abort: AbortSignal.any([]), abort: AbortSignal.any([]),
messages: [], messages: [],
metadata: () => {}, metadata: () => Effect.void,
ask: () => Effect.void, ask: () => Effect.void,
} }
@@ -16,7 +16,7 @@ const baseCtx: Omit<Tool.Context, "ask"> = {
agent: "build", agent: "build",
abort: AbortSignal.any([]), abort: AbortSignal.any([]),
messages: [], messages: [],
metadata: () => {}, metadata: () => Effect.void,
} }
const glob = (p: string) => const glob = (p: string) =>
+1 -1
View File
@@ -20,7 +20,7 @@ const ctx = {
agent: "build", agent: "build",
abort: AbortSignal.any([]), abort: AbortSignal.any([]),
messages: [], messages: [],
metadata: () => {}, metadata: () => Effect.void,
ask: () => Effect.void, ask: () => Effect.void,
} }
+1 -1
View File
@@ -15,7 +15,7 @@ const ctx = {
agent: "test-agent", agent: "test-agent",
abort: AbortSignal.any([]), abort: AbortSignal.any([]),
messages: [], messages: [],
metadata: () => {}, metadata: () => Effect.void,
ask: () => Effect.void, ask: () => Effect.void,
} }
+1 -1
View File
@@ -29,7 +29,7 @@ const ctx = {
agent: "build", agent: "build",
abort: AbortSignal.any([]), abort: AbortSignal.any([]),
messages: [], messages: [],
metadata: () => {}, metadata: () => Effect.void,
ask: () => Effect.void, ask: () => Effect.void,
} }
+1 -1
View File
@@ -19,7 +19,7 @@ const baseCtx: Omit<Tool.Context, "ask"> = {
agent: "build", agent: "build",
abort: AbortSignal.any([]), abort: AbortSignal.any([]),
messages: [], messages: [],
metadata: () => {}, metadata: () => Effect.void,
} }
afterEach(async () => { afterEach(async () => {
+4 -4
View File
@@ -209,7 +209,7 @@ describe("tool.task", () => {
abort: new AbortController().signal, abort: new AbortController().signal,
extra: { promptOps }, extra: { promptOps },
messages: [], messages: [],
metadata() {}, metadata: () => Effect.void,
ask: () => Effect.void, ask: () => Effect.void,
}, },
) )
@@ -247,7 +247,7 @@ describe("tool.task", () => {
abort: new AbortController().signal, abort: new AbortController().signal,
extra: { promptOps, ...extra }, extra: { promptOps, ...extra },
messages: [], messages: [],
metadata() {}, metadata: () => Effect.void,
ask: (input) => ask: (input) =>
Effect.sync(() => { Effect.sync(() => {
calls.push(input) calls.push(input)
@@ -296,7 +296,7 @@ describe("tool.task", () => {
abort: new AbortController().signal, abort: new AbortController().signal,
extra: { promptOps }, extra: { promptOps },
messages: [], messages: [],
metadata() {}, metadata: () => Effect.void,
ask: () => Effect.void, ask: () => Effect.void,
}, },
) )
@@ -335,7 +335,7 @@ describe("tool.task", () => {
abort: new AbortController().signal, abort: new AbortController().signal,
extra: { promptOps }, extra: { promptOps },
messages: [], messages: [],
metadata() {}, metadata: () => Effect.void,
ask: () => Effect.void, ask: () => Effect.void,
}, },
) )
+1 -1
View File
@@ -15,7 +15,7 @@ const ctx = {
agent: "build", agent: "build",
abort: AbortSignal.any([]), abort: AbortSignal.any([]),
messages: [], messages: [],
metadata: () => {}, metadata: () => Effect.void,
ask: () => Effect.void, ask: () => Effect.void,
} }
+1 -1
View File
@@ -22,7 +22,7 @@ const ctx = {
agent: "build", agent: "build",
abort: AbortSignal.any([]), abort: AbortSignal.any([]),
messages: [], messages: [],
metadata: () => {}, metadata: () => Effect.void,
ask: () => Effect.void, ask: () => Effect.void,
} }