mirror of
https://github.com/anomalyco/opencode.git
synced 2026-07-21 18:26:09 +00:00
mini: fix shell tool output display (#37711)
This commit is contained in:
@@ -2,6 +2,7 @@ import type { EventSubscribeOutput, OpenCodeClient } from "@opencode-ai/client/p
|
||||
import { SessionMessage } from "@opencode-ai/schema/session-message"
|
||||
import { EOL } from "node:os"
|
||||
import { readFile } from "node:fs/promises"
|
||||
import { toolOutputText } from "./tool"
|
||||
import { UI } from "./ui"
|
||||
import type { MiniToolPart } from "./types"
|
||||
|
||||
@@ -274,10 +275,7 @@ export async function runNonInteractivePrompt(input: Input) {
|
||||
state: {
|
||||
status: "completed",
|
||||
input: current.input,
|
||||
output: event.data.content
|
||||
.filter((item) => item.type === "text")
|
||||
.map((item) => item.text)
|
||||
.join("\n"),
|
||||
output: toolOutputText(current.tool, event.data.content),
|
||||
title: current.tool,
|
||||
metadata: {
|
||||
structured: event.data.structured,
|
||||
|
||||
@@ -23,6 +23,7 @@ import type {
|
||||
} from "@opencode-ai/client/promise"
|
||||
import { Locale } from "@opencode-ai/tui/util/locale"
|
||||
import type { FooterSubagentDetail, FooterSubagentState, FooterSubagentTab, MiniToolPart, StreamCommit } from "./types"
|
||||
import { toolOutputText } from "./tool"
|
||||
|
||||
const CHILD_MESSAGE_LIMIT = 80
|
||||
const CHILD_FRAME_LIMIT = 80
|
||||
@@ -32,10 +33,6 @@ const FALLBACK_LABEL = "Subagent"
|
||||
|
||||
type V2Event = EventSubscribeOutput
|
||||
|
||||
export function outputText(content: ReadonlyArray<{ type: string; text?: string }>) {
|
||||
return content.flatMap((item) => (item.type === "text" && item.text ? [item.text] : [])).join("\n")
|
||||
}
|
||||
|
||||
export function miniTool(input: {
|
||||
sessionID: string
|
||||
messageID: string
|
||||
@@ -82,7 +79,7 @@ export function miniTool(input: {
|
||||
state: {
|
||||
status: "completed",
|
||||
input: tool.state.input,
|
||||
output: outputText(tool.state.content),
|
||||
output: toolOutputText(tool.name, tool.state.content),
|
||||
title: tool.name,
|
||||
metadata: {
|
||||
structured: tool.state.structured,
|
||||
|
||||
@@ -177,6 +177,12 @@ function text(v: unknown): string {
|
||||
return typeof v === "string" ? v : ""
|
||||
}
|
||||
|
||||
export function toolOutputText(name: string, content: ReadonlyArray<{ type: string; text?: string }>) {
|
||||
// V2 shell content appends model-only status after the user-visible command output.
|
||||
if (name === "shell") return content.find((item) => item.type === "text")?.text ?? ""
|
||||
return content.flatMap((item) => (item.type === "text" && item.text ? [item.text] : [])).join("\n")
|
||||
}
|
||||
|
||||
function num(v: unknown): number | undefined {
|
||||
if (typeof v !== "number" || !Number.isFinite(v)) {
|
||||
return undefined
|
||||
|
||||
@@ -2,7 +2,7 @@ import { describe, expect, test } from "bun:test"
|
||||
import { InstallationVersion } from "@opencode-ai/core/installation/version"
|
||||
import path from "node:path"
|
||||
import { mergeInteractiveInput, mergeNonInteractiveInput, parseRunModel, pickRunModel } from "../src/mini"
|
||||
import { toolInlineInfo, toolView } from "../src/mini/tool"
|
||||
import { toolInlineInfo, toolOutputText, toolView } from "../src/mini/tool"
|
||||
|
||||
async function cli(args: string[]) {
|
||||
const child = Bun.spawn([process.execPath, "run", "src/index.ts", ...args], {
|
||||
@@ -36,6 +36,24 @@ describe("mini command", () => {
|
||||
expect(toolInlineInfo(part)).toMatchObject({ icon: "$", title: "pwd", mode: "block" })
|
||||
})
|
||||
|
||||
test("uses non-empty V2 shell output without the model-facing status", () => {
|
||||
expect(
|
||||
toolOutputText("shell", [
|
||||
{ type: "text", text: "mini-output\n" },
|
||||
{ type: "text", text: "Command exited with code 0." },
|
||||
]),
|
||||
).toBe("mini-output\n")
|
||||
})
|
||||
|
||||
test("keeps empty V2 shell output empty", () => {
|
||||
expect(
|
||||
toolOutputText("shell", [
|
||||
{ type: "text", text: "" },
|
||||
{ type: "text", text: "Command exited with code 0." },
|
||||
]),
|
||||
).toBe("")
|
||||
})
|
||||
|
||||
test("uses piped stdin as the initial prompt", () => {
|
||||
expect(mergeInteractiveInput("from stdin", undefined)).toBe("from stdin")
|
||||
expect(mergeInteractiveInput("from stdin", "from flag")).toBe("from stdin\nfrom flag")
|
||||
|
||||
Reference in New Issue
Block a user