fix(core): return content-only Code Mode results (#41954)
Co-authored-by: Aiden Cline <rekram1-node@users.noreply.github.com>
This commit is contained in:
committed by
GitHub
parent
b990f9a5c1
commit
1da591b84d
@@ -75,7 +75,9 @@ export const create = (
|
||||
const outputFileParts = outputFiles(content)
|
||||
if (outputFileParts.length > 0)
|
||||
yield* Ref.update(files, (items) => [...items, { index, files: outputFileParts }])
|
||||
return executed.output
|
||||
if (executed.output !== undefined) return executed.output
|
||||
const text = content.flatMap((part) => (part.type === "text" ? [part.text] : [])).join("\n")
|
||||
return text === "" ? null : text
|
||||
}),
|
||||
{
|
||||
onToolCallStart: ({ index, name, input }) => {
|
||||
@@ -155,7 +157,7 @@ function runtime(
|
||||
tools[path] = Tool.make({
|
||||
description: child.description,
|
||||
input: child.inputSchema,
|
||||
output: child.outputSchema,
|
||||
output: child.outputSchema ?? Schema.NullOr(Schema.String),
|
||||
execute: (input) => executeTool(name, registration, input),
|
||||
})
|
||||
}
|
||||
|
||||
@@ -248,6 +248,12 @@ const mcp = Layer.mock(MCP.Service, {
|
||||
required: ["ok"],
|
||||
},
|
||||
}),
|
||||
new MCP.Tool({
|
||||
server: MCP.ServerName.make("demo"),
|
||||
name: "status",
|
||||
description: "Status",
|
||||
inputSchema: { type: "object", properties: {} },
|
||||
}),
|
||||
new MCP.Tool({
|
||||
server: MCP.ServerName.make("direct"),
|
||||
name: "lookup",
|
||||
@@ -290,6 +296,13 @@ const mcp = Layer.mock(MCP.Service, {
|
||||
{ type: "media", data: "aGVsbG8=", mimeType: "image/png" },
|
||||
],
|
||||
})
|
||||
if (input.name === "status")
|
||||
return new MCP.ToolResult({
|
||||
server: MCP.ServerName.make(input.server),
|
||||
tool: input.name,
|
||||
isError: false,
|
||||
content: [{ type: "text", text: "hello" }],
|
||||
})
|
||||
return new MCP.ToolResult({
|
||||
server: MCP.ServerName.make(input.server),
|
||||
tool: input.name,
|
||||
@@ -984,6 +997,31 @@ it.effect("advertises MCP output schemas to Code Mode", () =>
|
||||
}),
|
||||
)
|
||||
|
||||
it.effect("returns content-only MCP results through Code Mode", () =>
|
||||
Effect.gen(function* () {
|
||||
assertion = yield* Deferred.make<Permission.AssertInput>()
|
||||
decision = Effect.void
|
||||
const registry = yield* Tool.Service
|
||||
const toolSet = yield* waitForCodeModeTool(registry, "demo.status")
|
||||
|
||||
const execution = yield* toolSet.execute({
|
||||
sessionID: Session.ID.make("ses_mcp_content_only"),
|
||||
...toolIdentity,
|
||||
call: {
|
||||
type: "tool-call",
|
||||
id: "call_mcp_content_only",
|
||||
name: "execute",
|
||||
input: { code: "return await tools.demo.status({})" },
|
||||
},
|
||||
})
|
||||
|
||||
expect(execution).toMatchObject({
|
||||
output: { output: "hello", toolCalls: [{ tool: "demo.status", status: "completed" }] },
|
||||
content: [{ type: "text", text: "hello" }],
|
||||
})
|
||||
}),
|
||||
)
|
||||
|
||||
it.effect("advertises MCP tools directly when Code Mode is disabled for the server", () =>
|
||||
Effect.gen(function* () {
|
||||
const registry = yield* Tool.Service
|
||||
|
||||
@@ -393,4 +393,45 @@ describe("fromPromise", () => {
|
||||
expect(progress).toEqual([{ phase: "greeting" }])
|
||||
}),
|
||||
)
|
||||
|
||||
it.effect("returns content-only plugin results through Code Mode", () =>
|
||||
Effect.gen(function* () {
|
||||
const plugins = yield* Plugin.Service
|
||||
const registry = yield* Tool.Service
|
||||
const host = yield* PluginHost.make(plugins)
|
||||
const promisePlugin = define({
|
||||
id: "content-only-tool",
|
||||
setup: async (ctx) => {
|
||||
await ctx.tool.transform((tools) => {
|
||||
tools.add({
|
||||
name: "demo_status",
|
||||
description: "Returns a status string",
|
||||
input: Schema.Struct({}),
|
||||
execute: async () => ({ content: [{ type: "text", text: "hello" }] }),
|
||||
options: { codemode: true },
|
||||
})
|
||||
})
|
||||
},
|
||||
})
|
||||
|
||||
yield* PluginPromise.fromPromise(promisePlugin).effect(host)
|
||||
|
||||
const toolSet = yield* registry.snapshot()
|
||||
const throughCodeMode = yield* toolSet.execute({
|
||||
sessionID: Session.ID.make("ses_content_only_tool"),
|
||||
agent: Agent.ID.make("build"),
|
||||
messageID: SessionMessage.ID.make("msg_content_only_tool"),
|
||||
call: {
|
||||
type: "tool-call",
|
||||
id: "call_content_only_tool",
|
||||
name: "execute",
|
||||
input: { code: "return await tools.demo_status({})" },
|
||||
},
|
||||
})
|
||||
expect(throughCodeMode).toMatchObject({
|
||||
output: { output: "hello", toolCalls: [{ tool: "demo_status", status: "completed" }] },
|
||||
content: [{ type: "text", text: "hello" }],
|
||||
})
|
||||
}),
|
||||
)
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user