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

View File

@@ -158,7 +158,7 @@ async function createToolContext(agent: Agent.Info) {
agent: agent.name,
abort: new AbortController().signal,
messages: [],
metadata: () => {},
metadata: () => Effect.void,
ask(req: Omit<Permission.Request, "id" | "sessionID" | "tool">) {
return Effect.sync(() => {
for (const pattern of req.patterns) {

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,
messages: input.messages,
metadata: (val) =>
run.promise(
input.processor.updateToolCall(options.toolCallId, (match) => {
if (!["running", "pending"].includes(match.state.status)) return match
return {
...match,
state: {
title: val.title,
metadata: val.metadata,
status: "running",
input: args,
time: { start: Date.now() },
},
}
}),
),
input.processor.updateToolCall(options.toolCallId, (match) => {
if (!["running", "pending"].includes(match.state.status)) return match
return {
...match,
state: {
title: val.title,
metadata: val.metadata,
status: "running",
input: args,
time: { start: Date.now() },
},
}
}),
ask: (req) =>
permission
.ask({
@@ -592,17 +590,14 @@ NOTE: At any point in time through this workflow you should feel free to ask the
callID: part.callID,
extra: { bypassAgentCheck: true, promptOps },
messages: msgs,
metadata(val: { title?: string; metadata?: Record<string, any> }) {
return run.promise(
Effect.gen(function* () {
part = yield* sessions.updatePart({
...part,
type: "tool",
state: { ...part.state, ...val },
} satisfies MessageV2.ToolPart)
}),
)
},
metadata: (val: { title?: string; metadata?: Record<string, any> }) =>
Effect.gen(function* () {
part = yield* sessions.updatePart({
...part,
type: "tool",
state: { ...part.state, ...val },
} satisfies MessageV2.ToolPart)
}),
ask: (req: any) =>
permission
.ask({
@@ -1054,7 +1049,7 @@ NOTE: At any point in time through this workflow you should feel free to ask the
messageID: info.id,
extra: { bypassCwdCheck: true, ...extra },
messages: [],
metadata: () => {},
metadata: () => Effect.void,
ask: () => Effect.void,
})
.pipe(Effect.onInterrupt(() => Effect.sync(() => controller.abort())))

View File

@@ -385,7 +385,7 @@ export const BashTool = Tool.define(
let expired = false
let aborted = false
ctx.metadata({
yield* ctx.metadata({
metadata: {
output: "",
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))
yield* Effect.forkScoped(
Stream.runForEach(Stream.decodeText(handle.all), (chunk) =>
Effect.sync(() => {
output += chunk
ctx.metadata({
metadata: {
output: preview(output),
description: input.description,
},
})
}),
Stream.runForEach(Stream.decodeText(handle.all), (chunk) => {
output += chunk
return ctx.metadata({
metadata: {
output: preview(output),
description: input.description,
},
})
},
),
)

View File

@@ -158,7 +158,7 @@ export const EditTool = Tool.define(
if (change.removed) filediff.deletions += change.count || 0
}
ctx.metadata({
yield* ctx.metadata({
metadata: {
diff,
filediff,

View File

@@ -109,7 +109,7 @@ export const TaskTool = Tool.define(
providerID: msg.info.providerID,
}
ctx.metadata({
yield* ctx.metadata({
title: params.description,
metadata: {
sessionId: nextSession.id,

View File

@@ -22,7 +22,7 @@ export namespace Tool {
callID?: string
extra?: { [key: string]: any }
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>
}

View File

@@ -22,7 +22,7 @@ const baseCtx = {
agent: "build",
abort: AbortSignal.any([]),
messages: [],
metadata: () => {},
metadata: () => Effect.void,
}
type AskInput = {

View File

@@ -29,7 +29,7 @@ const ctx = {
agent: "build",
abort: AbortSignal.any([]),
messages: [],
metadata: () => {},
metadata: () => Effect.void,
ask: () => Effect.void,
}
@@ -982,13 +982,14 @@ describe("tool.bash abort", () => {
{
...ctx,
abort: controller.signal,
metadata: (input) => {
const output = (input.metadata as { output?: string })?.output
if (output && output.includes("before") && !controller.signal.aborted) {
collected.push(output)
controller.abort()
}
},
metadata: (input) =>
Effect.sync(() => {
const output = (input.metadata as { output?: string })?.output
if (output && output.includes("before") && !controller.signal.aborted) {
collected.push(output)
controller.abort()
}
}),
},
),
)
@@ -1074,10 +1075,11 @@ describe("tool.bash abort", () => {
},
{
...ctx,
metadata: (input) => {
const output = (input.metadata as { output?: string })?.output
if (output) updates.push(output)
},
metadata: (input) =>
Effect.sync(() => {
const output = (input.metadata as { output?: string })?.output
if (output) updates.push(output)
}),
},
),
)

View File

@@ -20,7 +20,7 @@ const ctx = {
agent: "build",
abort: AbortSignal.any([]),
messages: [],
metadata: () => {},
metadata: () => Effect.void,
ask: () => Effect.void,
}

View File

@@ -16,7 +16,7 @@ const baseCtx: Omit<Tool.Context, "ask"> = {
agent: "build",
abort: AbortSignal.any([]),
messages: [],
metadata: () => {},
metadata: () => Effect.void,
}
const glob = (p: string) =>

View File

@@ -20,7 +20,7 @@ const ctx = {
agent: "build",
abort: AbortSignal.any([]),
messages: [],
metadata: () => {},
metadata: () => Effect.void,
ask: () => Effect.void,
}

View File

@@ -15,7 +15,7 @@ const ctx = {
agent: "test-agent",
abort: AbortSignal.any([]),
messages: [],
metadata: () => {},
metadata: () => Effect.void,
ask: () => Effect.void,
}

View File

@@ -29,7 +29,7 @@ const ctx = {
agent: "build",
abort: AbortSignal.any([]),
messages: [],
metadata: () => {},
metadata: () => Effect.void,
ask: () => Effect.void,
}

View File

@@ -19,7 +19,7 @@ const baseCtx: Omit<Tool.Context, "ask"> = {
agent: "build",
abort: AbortSignal.any([]),
messages: [],
metadata: () => {},
metadata: () => Effect.void,
}
afterEach(async () => {

View File

@@ -209,7 +209,7 @@ describe("tool.task", () => {
abort: new AbortController().signal,
extra: { promptOps },
messages: [],
metadata() {},
metadata: () => Effect.void,
ask: () => Effect.void,
},
)
@@ -247,7 +247,7 @@ describe("tool.task", () => {
abort: new AbortController().signal,
extra: { promptOps, ...extra },
messages: [],
metadata() {},
metadata: () => Effect.void,
ask: (input) =>
Effect.sync(() => {
calls.push(input)
@@ -296,7 +296,7 @@ describe("tool.task", () => {
abort: new AbortController().signal,
extra: { promptOps },
messages: [],
metadata() {},
metadata: () => Effect.void,
ask: () => Effect.void,
},
)
@@ -335,7 +335,7 @@ describe("tool.task", () => {
abort: new AbortController().signal,
extra: { promptOps },
messages: [],
metadata() {},
metadata: () => Effect.void,
ask: () => Effect.void,
},
)

View File

@@ -15,7 +15,7 @@ const ctx = {
agent: "build",
abort: AbortSignal.any([]),
messages: [],
metadata: () => {},
metadata: () => Effect.void,
ask: () => Effect.void,
}

View File

@@ -22,7 +22,7 @@ const ctx = {
agent: "build",
abort: AbortSignal.any([]),
messages: [],
metadata: () => {},
metadata: () => Effect.void,
ask: () => Effect.void,
}