fix(acp): clean read tool display content (#30569)
This commit is contained in:
@@ -98,12 +98,14 @@ export function toLocations(toolName: string, input: ToolInput): ToolCallLocatio
|
||||
}
|
||||
|
||||
export function completedToolContent(toolName: string, state: CompletedToolState): ToolCallContent[] {
|
||||
const text =
|
||||
toolName.toLocaleLowerCase() === "read" ? (readDisplayText(state.metadata) ?? state.output) : state.output
|
||||
const content: ToolCallContent[] = [
|
||||
{
|
||||
type: "content",
|
||||
content: {
|
||||
type: "text",
|
||||
text: state.output,
|
||||
text,
|
||||
},
|
||||
},
|
||||
]
|
||||
@@ -288,6 +290,18 @@ function diffContent(input: ToolInput): ToolCallContent[] {
|
||||
]
|
||||
}
|
||||
|
||||
function readDisplayText(metadata: unknown) {
|
||||
if (!metadata || typeof metadata !== "object") return undefined
|
||||
const display = (metadata as Record<string, unknown>).display
|
||||
if (!display || typeof display !== "object") return undefined
|
||||
const info = display as Record<string, unknown>
|
||||
if (info.type === "file") return stringValue(info.text)
|
||||
if (info.type === "directory" && Array.isArray(info.entries)) {
|
||||
return info.entries.filter((item): item is string => typeof item === "string").join("\n")
|
||||
}
|
||||
return undefined
|
||||
}
|
||||
|
||||
function dataUrlImage(attachment: ToolAttachment) {
|
||||
const match = stringValue(attachment.url)?.match(/^data:([^;,]+)(?:;[^,]*)*;base64,(.*)$/)
|
||||
const mime = match?.[1] ?? stringValue(attachment.mime)
|
||||
|
||||
@@ -36,7 +36,37 @@ export const Parameters = Schema.Struct({
|
||||
}),
|
||||
})
|
||||
|
||||
export const ReadTool = Tool.define(
|
||||
type Display =
|
||||
| {
|
||||
type: "directory"
|
||||
path: string
|
||||
entries: string[]
|
||||
offset: number
|
||||
totalEntries: number
|
||||
truncated: boolean
|
||||
}
|
||||
| {
|
||||
type: "file"
|
||||
path: string
|
||||
text: string
|
||||
lineStart: number
|
||||
lineEnd: number
|
||||
totalLines: number
|
||||
truncated: boolean
|
||||
}
|
||||
|
||||
type Metadata = {
|
||||
preview: string
|
||||
truncated: boolean
|
||||
loaded: string[]
|
||||
display?: Display
|
||||
}
|
||||
|
||||
export const ReadTool = Tool.define<
|
||||
typeof Parameters,
|
||||
Metadata,
|
||||
FSUtil.Service | Instruction.Service | LSP.Service | Reference.Service | Scope.Scope
|
||||
>(
|
||||
"read",
|
||||
Effect.gen(function* () {
|
||||
const fs = yield* FSUtil.Service
|
||||
@@ -200,7 +230,7 @@ export const ReadTool = Tool.define(
|
||||
|
||||
const run = Effect.fn("ReadTool.execute")(function* (
|
||||
params: Schema.Schema.Type<typeof Parameters>,
|
||||
ctx: Tool.Context,
|
||||
ctx: Tool.Context<Metadata>,
|
||||
) {
|
||||
const instance = yield* InstanceState.context
|
||||
let filepath = params.filePath
|
||||
@@ -258,6 +288,14 @@ export const ReadTool = Tool.define(
|
||||
preview: sliced.slice(0, 20).join("\n"),
|
||||
truncated,
|
||||
loaded: [] as string[],
|
||||
display: {
|
||||
type: "directory" as const,
|
||||
path: filepath,
|
||||
entries: sliced,
|
||||
offset,
|
||||
totalEntries: items.length,
|
||||
truncated,
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
@@ -328,6 +366,15 @@ export const ReadTool = Tool.define(
|
||||
preview: file.raw.slice(0, 20).join("\n"),
|
||||
truncated,
|
||||
loaded: loaded.map((item) => item.filepath),
|
||||
display: {
|
||||
type: "file" as const,
|
||||
path: filepath,
|
||||
text: file.raw.join("\n"),
|
||||
lineStart: file.offset,
|
||||
lineEnd: last,
|
||||
totalLines: file.count,
|
||||
truncated,
|
||||
},
|
||||
},
|
||||
}
|
||||
})
|
||||
@@ -335,7 +382,7 @@ export const ReadTool = Tool.define(
|
||||
return {
|
||||
description: DESCRIPTION,
|
||||
parameters: Parameters,
|
||||
execute: (params: Schema.Schema.Type<typeof Parameters>, ctx: Tool.Context) =>
|
||||
execute: (params: Schema.Schema.Type<typeof Parameters>, ctx: Tool.Context<Metadata>) =>
|
||||
run(params, ctx).pipe(Effect.orDie),
|
||||
}
|
||||
}),
|
||||
|
||||
Reference in New Issue
Block a user