Compare commits
16 Commits
ready/ui-m
...
codenomad/
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0e5695a903 | ||
|
|
77103b7292 | ||
|
|
b14a144ddc | ||
|
|
8ac67311d8 | ||
|
|
0c97db393c | ||
|
|
614c300d2f | ||
|
|
e6ca4bd43d | ||
|
|
84f81cf829 | ||
|
|
3760ba2d7f | ||
|
|
09e7a3f8da | ||
|
|
c55d56c94b | ||
|
|
cc53123bcd | ||
|
|
d64027d43d | ||
|
|
6b7162f50f | ||
|
|
5fd985f0c2 | ||
|
|
2a438b2bb3 |
3
package-lock.json
generated
3
package-lock.json
generated
@@ -12092,7 +12092,8 @@
|
||||
"shiki": "^3.13.0",
|
||||
"solid-js": "^1.8.0",
|
||||
"solid-toast": "^0.5.0",
|
||||
"tauri-plugin-keepawake-api": "^0.1.0"
|
||||
"tauri-plugin-keepawake-api": "^0.1.0",
|
||||
"yaml": "^2.4.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@vite-pwa/assets-generator": "^1.0.2",
|
||||
|
||||
@@ -30,7 +30,8 @@
|
||||
"shiki": "^3.13.0",
|
||||
"solid-js": "^1.8.0",
|
||||
"solid-toast": "^0.5.0",
|
||||
"tauri-plugin-keepawake-api": "^0.1.0"
|
||||
"tauri-plugin-keepawake-api": "^0.1.0",
|
||||
"yaml": "^2.4.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@vite-pwa/assets-generator": "^1.0.2",
|
||||
|
||||
@@ -72,6 +72,7 @@ const App: Component = () => {
|
||||
setToolOutputExpansion,
|
||||
setDiagnosticsExpansion,
|
||||
setThinkingBlocksExpansion,
|
||||
setToolInputsVisibility,
|
||||
} = useConfig()
|
||||
const [escapeInDebounce, setEscapeInDebounce] = createSignal(false)
|
||||
interface LaunchErrorState {
|
||||
@@ -402,6 +403,7 @@ const App: Component = () => {
|
||||
setToolOutputExpansion,
|
||||
setDiagnosticsExpansion,
|
||||
setThinkingBlocksExpansion,
|
||||
setToolInputsVisibility,
|
||||
handleNewInstanceRequest,
|
||||
handleCloseInstance,
|
||||
handleNewSession,
|
||||
|
||||
@@ -625,7 +625,7 @@ const InstanceShell2: Component<InstanceShellProps> = (props) => {
|
||||
<div class="flex flex-wrap items-center justify-center gap-1">
|
||||
<button
|
||||
type="button"
|
||||
class="connection-status-button px-2 py-0.5 text-xs"
|
||||
class="connection-status-button command-palette-button px-2 py-0.5 text-xs"
|
||||
onClick={handleCommandPaletteClick}
|
||||
aria-label={t("instanceShell.commandPalette.openAriaLabel")}
|
||||
style={{ flex: "0 0 auto", width: "auto" }}
|
||||
@@ -721,7 +721,7 @@ const InstanceShell2: Component<InstanceShellProps> = (props) => {
|
||||
<div class="session-toolbar-center flex items-center justify-center gap-2 min-w-[160px]">
|
||||
<button
|
||||
type="button"
|
||||
class="connection-status-button px-2 py-0.5 text-xs"
|
||||
class="connection-status-button command-palette-button px-2 py-0.5 text-xs"
|
||||
onClick={handleCommandPaletteClick}
|
||||
aria-label={t("instanceShell.commandPalette.openAriaLabel")}
|
||||
style={{ flex: "0 0 auto", width: "auto" }}
|
||||
|
||||
@@ -51,7 +51,7 @@ export default function MessageListHeader(props: MessageListHeaderProps) {
|
||||
<div class="connection-status-shortcut-action">
|
||||
<button
|
||||
type="button"
|
||||
class="connection-status-button"
|
||||
class="connection-status-button command-palette-button"
|
||||
onClick={props.onCommandPalette}
|
||||
aria-label={t("messageListHeader.commandPalette.ariaLabel")}
|
||||
>
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { createSignal, Show, createEffect, createMemo, onCleanup } from "solid-js"
|
||||
import { Copy } from "lucide-solid"
|
||||
import { ArrowRightSquare, Check, Copy, Hourglass, Loader2, XCircle } from "lucide-solid"
|
||||
import { stringify as stringifyYaml } from "yaml"
|
||||
import { messageStoreBus } from "../stores/message-v2/bus"
|
||||
import { useTheme } from "../lib/theme"
|
||||
import { useGlobalCache } from "../lib/hooks/use-global-cache"
|
||||
@@ -27,7 +28,17 @@ import type {
|
||||
ToolRendererContext,
|
||||
ToolScrollHelpers,
|
||||
} from "./tool-call/types"
|
||||
import { getRelativePath, getToolIcon, getToolName, isToolStateCompleted, isToolStateError, isToolStateRunning, getDefaultToolAction } from "./tool-call/utils"
|
||||
import {
|
||||
ensureMarkdownContent,
|
||||
getRelativePath,
|
||||
getToolIcon,
|
||||
getToolName,
|
||||
isToolStateCompleted,
|
||||
isToolStateError,
|
||||
isToolStateRunning,
|
||||
getDefaultToolAction,
|
||||
readToolStatePayload,
|
||||
} from "./tool-call/utils"
|
||||
import { resolveTitleForTool } from "./tool-call/tool-title"
|
||||
import { getLogger } from "../lib/logger"
|
||||
|
||||
@@ -155,12 +166,33 @@ export default function ToolCall(props: ToolCallProps) {
|
||||
const prefExpanded = toolOutputDefaultExpanded()
|
||||
const toolName = toolCallMemo()?.tool || ""
|
||||
if (toolName === "read") {
|
||||
const state = toolState()
|
||||
if (state?.status === "error") {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
return prefExpanded
|
||||
})
|
||||
|
||||
const [userExpanded, setUserExpanded] = createSignal<boolean | null>(null)
|
||||
const toolInputsVisibility = createMemo(() => preferences().toolInputsVisibility || "collapsed")
|
||||
const [toolInputVisibilityOverride, setToolInputVisibilityOverride] = createSignal<"hidden" | "expanded" | null>(null)
|
||||
const effectiveToolInputsVisibility = createMemo(() => toolInputVisibilityOverride() ?? toolInputsVisibility())
|
||||
const isToolInputVisible = createMemo(() => effectiveToolInputsVisibility() !== "hidden")
|
||||
const inputDefaultExpanded = createMemo(() => effectiveToolInputsVisibility() === "expanded")
|
||||
const [inputSectionOverride, setInputSectionOverride] = createSignal<boolean | null>(null)
|
||||
const [outputSectionOverride, setOutputSectionOverride] = createSignal<boolean | null>(null)
|
||||
const inputSectionExpanded = () => {
|
||||
const override = inputSectionOverride()
|
||||
if (override !== null) return override
|
||||
return inputDefaultExpanded()
|
||||
}
|
||||
const outputSectionExpanded = () => {
|
||||
const override = outputSectionOverride()
|
||||
if (override !== null) return override
|
||||
return true
|
||||
}
|
||||
|
||||
const isPermissionActive = createMemo(() => {
|
||||
const pending = pendingPermission()
|
||||
@@ -183,6 +215,35 @@ export default function ToolCall(props: ToolCallProps) {
|
||||
return defaultExpandedForTool()
|
||||
}
|
||||
|
||||
const toolInput = createMemo(() => {
|
||||
const state = toolState()
|
||||
return readToolStatePayload(state).input
|
||||
})
|
||||
|
||||
const hasToolInput = createMemo(() => {
|
||||
const input = toolInput()
|
||||
return input && Object.keys(input).length > 0
|
||||
})
|
||||
|
||||
const toolInputMarkdown = createMemo(() => {
|
||||
const input = toolInput()
|
||||
if (!input || Object.keys(input).length === 0) return null
|
||||
|
||||
try {
|
||||
const yamlText = stringifyYaml(input)
|
||||
return ensureMarkdownContent(yamlText, "yaml", true)
|
||||
} catch (error) {
|
||||
log.error("Failed to convert tool call input to YAML", error)
|
||||
try {
|
||||
const jsonText = JSON.stringify(input, null, 2)
|
||||
return ensureMarkdownContent(jsonText, "json", true)
|
||||
} catch (nestedError) {
|
||||
log.error("Failed to stringify tool call input", nestedError)
|
||||
return null
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
const permissionDetails = createMemo(() => pendingPermission()?.permission)
|
||||
const questionDetails = createMemo(() => pendingQuestion()?.request)
|
||||
|
||||
@@ -515,13 +576,13 @@ export default function ToolCall(props: ToolCallProps) {
|
||||
const status = toolState()?.status || ""
|
||||
switch (status) {
|
||||
case "pending":
|
||||
return "⏸"
|
||||
return <Hourglass class="w-4 h-4" />
|
||||
case "running":
|
||||
return "⏳"
|
||||
return <Loader2 class="w-4 h-4 animate-spin" />
|
||||
case "completed":
|
||||
return "✓"
|
||||
return <Check class="w-4 h-4" />
|
||||
case "error":
|
||||
return "✗"
|
||||
return <XCircle class="w-4 h-4" />
|
||||
default:
|
||||
return ""
|
||||
}
|
||||
@@ -548,6 +609,25 @@ export default function ToolCall(props: ToolCallProps) {
|
||||
})
|
||||
}
|
||||
|
||||
createEffect(() => {
|
||||
// When global preference changes, reset per-tool-call overrides so palette changes apply.
|
||||
toolInputsVisibility()
|
||||
setToolInputVisibilityOverride(null)
|
||||
setInputSectionOverride(null)
|
||||
setOutputSectionOverride(null)
|
||||
})
|
||||
|
||||
const handleToggleInputVisibility = (event: MouseEvent) => {
|
||||
event.preventDefault()
|
||||
event.stopPropagation()
|
||||
if (!expanded()) {
|
||||
toggle()
|
||||
}
|
||||
|
||||
const currentlyVisible = isToolInputVisible()
|
||||
setToolInputVisibilityOverride(currentlyVisible ? "hidden" : "expanded")
|
||||
}
|
||||
|
||||
const renderer = createMemo(() => resolveToolRenderer(toolName()))
|
||||
|
||||
const { renderAnsiContent } = createAnsiContentRenderer({
|
||||
@@ -789,6 +869,23 @@ export default function ToolCall(props: ToolCallProps) {
|
||||
</span>
|
||||
</button>
|
||||
|
||||
<Show when={hasToolInput()}>
|
||||
<button
|
||||
type="button"
|
||||
class="tool-call-header-input"
|
||||
onClick={handleToggleInputVisibility}
|
||||
aria-pressed={isToolInputVisible()}
|
||||
aria-label={
|
||||
isToolInputVisible()
|
||||
? t("toolCall.header.hideInputAriaLabel")
|
||||
: t("toolCall.header.showInputAriaLabel")
|
||||
}
|
||||
title={isToolInputVisible() ? t("toolCall.header.hideInputTitle") : t("toolCall.header.showInputTitle")}
|
||||
>
|
||||
<ArrowRightSquare class="w-3.5 h-3.5" />
|
||||
</button>
|
||||
</Show>
|
||||
|
||||
<button
|
||||
type="button"
|
||||
class="tool-call-header-copy"
|
||||
@@ -806,19 +903,79 @@ export default function ToolCall(props: ToolCallProps) {
|
||||
|
||||
{expanded() && (
|
||||
<div class="tool-call-details">
|
||||
{renderToolBody()}
|
||||
|
||||
{renderError()}
|
||||
|
||||
{renderPermissionBlock()}
|
||||
{renderQuestionBlock()}
|
||||
|
||||
<Show when={status() === "pending" && !pendingPermission()}>
|
||||
<div class="tool-call-pending-message">
|
||||
<span class="spinner-small"></span>
|
||||
<span>{t("toolCall.pending.waitingToRun")}</span>
|
||||
<Show
|
||||
when={isToolInputVisible() && hasToolInput()}
|
||||
fallback={
|
||||
<>
|
||||
{renderToolBody()}
|
||||
{renderError()}
|
||||
|
||||
<Show when={status() === "pending" && !pendingPermission()}>
|
||||
<div class="tool-call-pending-message">
|
||||
<span class="spinner-small"></span>
|
||||
<span>{t("toolCall.pending.waitingToRun")}</span>
|
||||
</div>
|
||||
</Show>
|
||||
</>
|
||||
}
|
||||
>
|
||||
<div class="tool-call-io-sections">
|
||||
<div class="tool-call-io-section">
|
||||
<button
|
||||
type="button"
|
||||
class="tool-call-io-toggle"
|
||||
aria-expanded={inputSectionExpanded()}
|
||||
onClick={() => setInputSectionOverride((prev) => {
|
||||
const current = prev === null ? inputSectionExpanded() : prev
|
||||
return !current
|
||||
})}
|
||||
>
|
||||
<span class="tool-call-io-title">{t("toolCall.io.input")}</span>
|
||||
</button>
|
||||
|
||||
<Show when={inputSectionExpanded()}>
|
||||
<div class="tool-call-io-body">
|
||||
{(() => {
|
||||
const content = toolInputMarkdown()
|
||||
if (!content) return null
|
||||
return renderMarkdownContent({ content, cacheKey: "input" })
|
||||
})()}
|
||||
</div>
|
||||
</Show>
|
||||
</div>
|
||||
|
||||
<div class="tool-call-io-section">
|
||||
<button
|
||||
type="button"
|
||||
class="tool-call-io-toggle"
|
||||
aria-expanded={outputSectionExpanded()}
|
||||
onClick={() => setOutputSectionOverride((prev) => {
|
||||
const current = prev === null ? outputSectionExpanded() : prev
|
||||
return !current
|
||||
})}
|
||||
>
|
||||
<span class="tool-call-io-title">{t("toolCall.io.output")}</span>
|
||||
</button>
|
||||
|
||||
<Show when={outputSectionExpanded()}>
|
||||
<div class="tool-call-io-body">
|
||||
{renderToolBody()}
|
||||
{renderError()}
|
||||
|
||||
<Show when={status() === "pending" && !pendingPermission()}>
|
||||
<div class="tool-call-pending-message">
|
||||
<span class="spinner-small"></span>
|
||||
<span>{t("toolCall.pending.waitingToRun")}</span>
|
||||
</div>
|
||||
</Show>
|
||||
</div>
|
||||
</Show>
|
||||
</div>
|
||||
</div>
|
||||
</Show>
|
||||
|
||||
{renderPermissionBlock()}
|
||||
{renderQuestionBlock()}
|
||||
</div>
|
||||
)}
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { createSignal, onMount } from "solid-js"
|
||||
import type { Accessor } from "solid-js"
|
||||
import type { Preferences, ExpansionPreference } from "../../stores/preferences"
|
||||
import type { Preferences, ExpansionPreference, ToolInputsVisibilityPreference } from "../../stores/preferences"
|
||||
import { createCommandRegistry, type Command } from "../commands"
|
||||
import { instances, activeInstanceId, setActiveInstanceId } from "../../stores/instances"
|
||||
import type { ClientPart, MessageInfo } from "../../types/message"
|
||||
@@ -38,6 +38,7 @@ export interface UseCommandsOptions {
|
||||
setToolOutputExpansion: (mode: ExpansionPreference) => void
|
||||
setDiagnosticsExpansion: (mode: ExpansionPreference) => void
|
||||
setThinkingBlocksExpansion: (mode: ExpansionPreference) => void
|
||||
setToolInputsVisibility: (mode: ToolInputsVisibilityPreference) => void
|
||||
handleNewInstanceRequest: () => void
|
||||
handleCloseInstance: (instanceId: string) => Promise<void>
|
||||
handleNewSession: (instanceId: string) => Promise<void>
|
||||
@@ -551,6 +552,29 @@ export function useCommands(options: UseCommandsOptions) {
|
||||
},
|
||||
})
|
||||
|
||||
commandRegistry.register({
|
||||
id: "tool-inputs-visibility",
|
||||
label: () => {
|
||||
const mode = options.preferences().toolInputsVisibility || "hidden"
|
||||
const state =
|
||||
mode === "expanded"
|
||||
? tGlobal("commands.common.expanded")
|
||||
: mode === "collapsed"
|
||||
? tGlobal("commands.common.collapsed")
|
||||
: tGlobal("commands.common.hidden")
|
||||
return tGlobal("commands.toolInputsVisibility.label", { state })
|
||||
},
|
||||
description: () => tGlobal("commands.toolInputsVisibility.description"),
|
||||
category: "System",
|
||||
keywords: () => splitKeywords("commands.toolInputsVisibility.keywords"),
|
||||
action: () => {
|
||||
const mode = options.preferences().toolInputsVisibility || "hidden"
|
||||
const next: ToolInputsVisibilityPreference =
|
||||
mode === "hidden" ? "collapsed" : mode === "collapsed" ? "expanded" : "hidden"
|
||||
options.setToolInputsVisibility(next)
|
||||
},
|
||||
})
|
||||
|
||||
commandRegistry.register({
|
||||
id: "token-usage-visibility",
|
||||
label: () => {
|
||||
|
||||
@@ -130,6 +130,10 @@ export const commandMessages = {
|
||||
"commands.diagnosticsDefault.description": "Toggle default expansion for diagnostics output",
|
||||
"commands.diagnosticsDefault.keywords": "diagnostics, expand, collapse",
|
||||
|
||||
"commands.toolInputsVisibility.label": "Tool Inputs Visibility · {state}",
|
||||
"commands.toolInputsVisibility.description": "Set default visibility for tool call input arguments",
|
||||
"commands.toolInputsVisibility.keywords": "tool, inputs, arguments, visibility, hide, show, expand, collapse",
|
||||
|
||||
"commands.tokenUsageDisplay.label": "Token Usage Display · {state}",
|
||||
"commands.tokenUsageDisplay.description": "Show or hide token and cost stats for assistant messages",
|
||||
"commands.tokenUsageDisplay.keywords": "token, usage, cost, stats",
|
||||
|
||||
@@ -5,6 +5,14 @@ export const toolCallMessages = {
|
||||
"toolCall.header.copyTitle": "Copy tool call title",
|
||||
"toolCall.header.copyAriaLabel": "Copy tool call title",
|
||||
|
||||
"toolCall.header.showInputTitle": "Show Tool Arguments",
|
||||
"toolCall.header.showInputAriaLabel": "Show Tool Arguments",
|
||||
"toolCall.header.hideInputTitle": "Hide Tool Arguments",
|
||||
"toolCall.header.hideInputAriaLabel": "Hide Tool Arguments",
|
||||
|
||||
"toolCall.io.input": "Tool Input",
|
||||
"toolCall.io.output": "Tool Output",
|
||||
|
||||
"toolCall.diff.label": "Diff",
|
||||
"toolCall.diff.label.withPath": "Diff · {path}",
|
||||
"toolCall.diff.viewMode.ariaLabel": "Diff view mode",
|
||||
|
||||
@@ -130,6 +130,10 @@ export const commandMessages = {
|
||||
"commands.diagnosticsDefault.description": "Alternar la expansión por defecto de la salida de diagnósticos",
|
||||
"commands.diagnosticsDefault.keywords": "diagnósticos, expandir, colapsar",
|
||||
|
||||
"commands.toolInputsVisibility.label": "Visibilidad de entradas de herramientas · {state}",
|
||||
"commands.toolInputsVisibility.description": "Configurar la visibilidad por defecto de los argumentos de entrada de llamadas de herramienta",
|
||||
"commands.toolInputsVisibility.keywords": "herramienta, entradas, argumentos, visibilidad, ocultar, mostrar, expandir, colapsar",
|
||||
|
||||
"commands.tokenUsageDisplay.label": "Mostrar uso de tokens · {state}",
|
||||
"commands.tokenUsageDisplay.description": "Mostrar u ocultar estadísticas de tokens y costo en los mensajes del asistente",
|
||||
"commands.tokenUsageDisplay.keywords": "token, uso, costo, estadísticas",
|
||||
|
||||
@@ -5,6 +5,14 @@ export const toolCallMessages = {
|
||||
"toolCall.header.copyTitle": "Copy tool call title",
|
||||
"toolCall.header.copyAriaLabel": "Copy tool call title",
|
||||
|
||||
"toolCall.header.showInputTitle": "Show Tool Arguments",
|
||||
"toolCall.header.showInputAriaLabel": "Show Tool Arguments",
|
||||
"toolCall.header.hideInputTitle": "Hide Tool Arguments",
|
||||
"toolCall.header.hideInputAriaLabel": "Hide Tool Arguments",
|
||||
|
||||
"toolCall.io.input": "Tool Input",
|
||||
"toolCall.io.output": "Tool Output",
|
||||
|
||||
"toolCall.diff.label": "Diff",
|
||||
"toolCall.diff.label.withPath": "Diff · {path}",
|
||||
"toolCall.diff.viewMode.ariaLabel": "Modo de vista de diff",
|
||||
|
||||
@@ -130,6 +130,10 @@ export const commandMessages = {
|
||||
"commands.diagnosticsDefault.description": "Choisir l'ouverture par défaut de la sortie des diagnostics",
|
||||
"commands.diagnosticsDefault.keywords": "diagnostics, développer, réduire",
|
||||
|
||||
"commands.toolInputsVisibility.label": "Visibilité des entrées d'outil · {state}",
|
||||
"commands.toolInputsVisibility.description": "Définir la visibilité par défaut des arguments d'entrée des appels d'outil",
|
||||
"commands.toolInputsVisibility.keywords": "outil, entrées, arguments, visibilité, masquer, afficher, développer, réduire",
|
||||
|
||||
"commands.tokenUsageDisplay.label": "Affichage de l'usage des tokens · {state}",
|
||||
"commands.tokenUsageDisplay.description": "Afficher ou masquer les stats de tokens et de coût pour les messages de l'assistant",
|
||||
"commands.tokenUsageDisplay.keywords": "token, usage, coût, stats",
|
||||
|
||||
@@ -5,6 +5,14 @@ export const toolCallMessages = {
|
||||
"toolCall.header.copyTitle": "Copy tool call title",
|
||||
"toolCall.header.copyAriaLabel": "Copy tool call title",
|
||||
|
||||
"toolCall.header.showInputTitle": "Show Tool Arguments",
|
||||
"toolCall.header.showInputAriaLabel": "Show Tool Arguments",
|
||||
"toolCall.header.hideInputTitle": "Hide Tool Arguments",
|
||||
"toolCall.header.hideInputAriaLabel": "Hide Tool Arguments",
|
||||
|
||||
"toolCall.io.input": "Tool Input",
|
||||
"toolCall.io.output": "Tool Output",
|
||||
|
||||
"toolCall.diff.label": "Diff",
|
||||
"toolCall.diff.label.withPath": "Diff · {path}",
|
||||
"toolCall.diff.viewMode.ariaLabel": "Mode d'affichage du diff",
|
||||
|
||||
@@ -130,6 +130,10 @@ export const commandMessages = {
|
||||
"commands.diagnosticsDefault.description": "診断出力を既定で展開するか切り替え",
|
||||
"commands.diagnosticsDefault.keywords": "診断, 展開, 折りたたみ, diagnostics, expand, collapse",
|
||||
|
||||
"commands.toolInputsVisibility.label": "ツール入力の表示 · {state}",
|
||||
"commands.toolInputsVisibility.description": "ツール呼び出しの入力引数の既定の表示状態を設定します",
|
||||
"commands.toolInputsVisibility.keywords": "ツール, 入力, 引数, 表示, 非表示, 展開, 折りたたみ, tool, inputs, arguments, visibility, hide, show, expand, collapse",
|
||||
|
||||
"commands.tokenUsageDisplay.label": "トークン使用量表示 · {state}",
|
||||
"commands.tokenUsageDisplay.description": "アシスタントメッセージのトークン/コスト統計を表示/非表示",
|
||||
"commands.tokenUsageDisplay.keywords": "トークン, 使用量, コスト, 統計, token, usage, cost, stats",
|
||||
|
||||
@@ -5,6 +5,14 @@ export const toolCallMessages = {
|
||||
"toolCall.header.copyTitle": "Copy tool call title",
|
||||
"toolCall.header.copyAriaLabel": "Copy tool call title",
|
||||
|
||||
"toolCall.header.showInputTitle": "Show Tool Arguments",
|
||||
"toolCall.header.showInputAriaLabel": "Show Tool Arguments",
|
||||
"toolCall.header.hideInputTitle": "Hide Tool Arguments",
|
||||
"toolCall.header.hideInputAriaLabel": "Hide Tool Arguments",
|
||||
|
||||
"toolCall.io.input": "Tool Input",
|
||||
"toolCall.io.output": "Tool Output",
|
||||
|
||||
"toolCall.diff.label": "Diff",
|
||||
"toolCall.diff.label.withPath": "Diff · {path}",
|
||||
"toolCall.diff.viewMode.ariaLabel": "diff 表示モード",
|
||||
|
||||
@@ -130,6 +130,10 @@ export const commandMessages = {
|
||||
"commands.diagnosticsDefault.description": "Переключить, разворачивать ли вывод диагностики по умолчанию",
|
||||
"commands.diagnosticsDefault.keywords": "diagnostics, развернуть, свернуть",
|
||||
|
||||
"commands.toolInputsVisibility.label": "Видимость входных данных инструмента · {state}",
|
||||
"commands.toolInputsVisibility.description": "Установить видимость аргументов входа вызовов инструментов по умолчанию",
|
||||
"commands.toolInputsVisibility.keywords": "инструмент, вход, аргументы, видимость, скрыть, показать, раскрыть, свернуть, tool, inputs, arguments, visibility, hide, show, expand, collapse",
|
||||
|
||||
"commands.tokenUsageDisplay.label": "Отображение token-статистики · {state}",
|
||||
"commands.tokenUsageDisplay.description": "Показать или скрыть статистику token и стоимости для сообщений ассистента",
|
||||
"commands.tokenUsageDisplay.keywords": "token, usage, cost, статистика",
|
||||
|
||||
@@ -5,6 +5,14 @@ export const toolCallMessages = {
|
||||
"toolCall.header.copyTitle": "Copy tool call title",
|
||||
"toolCall.header.copyAriaLabel": "Copy tool call title",
|
||||
|
||||
"toolCall.header.showInputTitle": "Show Tool Arguments",
|
||||
"toolCall.header.showInputAriaLabel": "Show Tool Arguments",
|
||||
"toolCall.header.hideInputTitle": "Hide Tool Arguments",
|
||||
"toolCall.header.hideInputAriaLabel": "Hide Tool Arguments",
|
||||
|
||||
"toolCall.io.input": "Tool Input",
|
||||
"toolCall.io.output": "Tool Output",
|
||||
|
||||
"toolCall.diff.label": "Diff",
|
||||
"toolCall.diff.label.withPath": "Diff · {path}",
|
||||
"toolCall.diff.viewMode.ariaLabel": "Режим просмотра diff",
|
||||
|
||||
@@ -130,6 +130,10 @@ export const commandMessages = {
|
||||
"commands.diagnosticsDefault.description": "切换诊断输出是否默认展开",
|
||||
"commands.diagnosticsDefault.keywords": "diagnostics, expand, collapse, 诊断, 展开, 折叠",
|
||||
|
||||
"commands.toolInputsVisibility.label": "工具输入可见性 · {state}",
|
||||
"commands.toolInputsVisibility.description": "设置工具调用输入参数的默认可见性",
|
||||
"commands.toolInputsVisibility.keywords": "工具, 输入, 参数, 可见性, 隐藏, 显示, 展开, 折叠, tool, inputs, arguments, visibility, hide, show, expand, collapse",
|
||||
|
||||
"commands.tokenUsageDisplay.label": "Token 使用显示 · {state}",
|
||||
"commands.tokenUsageDisplay.description": "显示或隐藏助手消息的 token 和费用统计",
|
||||
"commands.tokenUsageDisplay.keywords": "token, usage, cost, stats, 令牌, 用量, 费用, 统计",
|
||||
|
||||
@@ -5,6 +5,14 @@ export const toolCallMessages = {
|
||||
"toolCall.header.copyTitle": "Copy tool call title",
|
||||
"toolCall.header.copyAriaLabel": "Copy tool call title",
|
||||
|
||||
"toolCall.header.showInputTitle": "Show Tool Arguments",
|
||||
"toolCall.header.showInputAriaLabel": "Show Tool Arguments",
|
||||
"toolCall.header.hideInputTitle": "Hide Tool Arguments",
|
||||
"toolCall.header.hideInputAriaLabel": "Hide Tool Arguments",
|
||||
|
||||
"toolCall.io.input": "Tool Input",
|
||||
"toolCall.io.output": "Tool Output",
|
||||
|
||||
"toolCall.diff.label": "Diff",
|
||||
"toolCall.diff.label.withPath": "Diff · {path}",
|
||||
"toolCall.diff.viewMode.ariaLabel": "Diff 视图模式",
|
||||
|
||||
@@ -25,6 +25,7 @@ export interface ModelPreference {
|
||||
|
||||
export type DiffViewMode = "split" | "unified"
|
||||
export type ExpansionPreference = "expanded" | "collapsed"
|
||||
export type ToolInputsVisibilityPreference = "hidden" | "collapsed" | "expanded"
|
||||
export type ListeningMode = "local" | "all"
|
||||
|
||||
export interface UiSettings {
|
||||
@@ -37,6 +38,7 @@ export interface UiSettings {
|
||||
diffViewMode: DiffViewMode
|
||||
toolOutputExpansion: ExpansionPreference
|
||||
diagnosticsExpansion: ExpansionPreference
|
||||
toolInputsVisibility: ToolInputsVisibilityPreference
|
||||
showUsageMetrics: boolean
|
||||
autoCleanupBlankSessions: boolean
|
||||
|
||||
@@ -108,6 +110,7 @@ const defaultUiSettings: UiSettings = {
|
||||
diffViewMode: "split",
|
||||
toolOutputExpansion: "expanded",
|
||||
diagnosticsExpansion: "expanded",
|
||||
toolInputsVisibility: "collapsed",
|
||||
showUsageMetrics: true,
|
||||
autoCleanupBlankSessions: true,
|
||||
|
||||
@@ -130,6 +133,10 @@ function normalizeUiSettings(input?: Partial<UiSettings> | null): UiSettings {
|
||||
diffViewMode: sanitized.diffViewMode ?? defaultUiSettings.diffViewMode,
|
||||
toolOutputExpansion: sanitized.toolOutputExpansion ?? defaultUiSettings.toolOutputExpansion,
|
||||
diagnosticsExpansion: sanitized.diagnosticsExpansion ?? defaultUiSettings.diagnosticsExpansion,
|
||||
toolInputsVisibility:
|
||||
sanitized.toolInputsVisibility === "hidden" || sanitized.toolInputsVisibility === "collapsed" || sanitized.toolInputsVisibility === "expanded"
|
||||
? sanitized.toolInputsVisibility
|
||||
: defaultUiSettings.toolInputsVisibility,
|
||||
showUsageMetrics: sanitized.showUsageMetrics ?? defaultUiSettings.showUsageMetrics,
|
||||
autoCleanupBlankSessions: sanitized.autoCleanupBlankSessions ?? defaultUiSettings.autoCleanupBlankSessions,
|
||||
osNotificationsEnabled: sanitized.osNotificationsEnabled ?? defaultUiSettings.osNotificationsEnabled,
|
||||
@@ -439,6 +446,11 @@ function setDiagnosticsExpansion(mode: ExpansionPreference): void {
|
||||
updateUiSettings({ diagnosticsExpansion: mode })
|
||||
}
|
||||
|
||||
function setToolInputsVisibility(mode: ToolInputsVisibilityPreference): void {
|
||||
if (preferences().toolInputsVisibility === mode) return
|
||||
updateUiSettings({ toolInputsVisibility: mode })
|
||||
}
|
||||
|
||||
function setThinkingBlocksExpansion(mode: ExpansionPreference): void {
|
||||
if (preferences().thinkingBlocksExpansion === mode) return
|
||||
updateUiSettings({ thinkingBlocksExpansion: mode })
|
||||
@@ -536,6 +548,7 @@ interface ConfigContextValue {
|
||||
setToolOutputExpansion: typeof setToolOutputExpansion
|
||||
setDiagnosticsExpansion: typeof setDiagnosticsExpansion
|
||||
setThinkingBlocksExpansion: typeof setThinkingBlocksExpansion
|
||||
setToolInputsVisibility: typeof setToolInputsVisibility
|
||||
|
||||
// instance scoped
|
||||
setAgentModelPreference: typeof setAgentModelPreference
|
||||
@@ -579,6 +592,7 @@ const configContextValue: ConfigContextValue = {
|
||||
setToolOutputExpansion,
|
||||
setDiagnosticsExpansion,
|
||||
setThinkingBlocksExpansion,
|
||||
setToolInputsVisibility,
|
||||
setAgentModelPreference,
|
||||
getAgentModelPreference,
|
||||
}
|
||||
|
||||
@@ -130,6 +130,17 @@
|
||||
color: var(--text-primary);
|
||||
}
|
||||
|
||||
/* Make the command palette trigger stand out in the header. */
|
||||
.connection-status-button.command-palette-button {
|
||||
border-color: var(--accent-primary);
|
||||
background-color: var(--surface-secondary);
|
||||
}
|
||||
|
||||
.connection-status-button.command-palette-button:hover {
|
||||
border-color: var(--accent-primary);
|
||||
background-color: var(--surface-hover);
|
||||
}
|
||||
|
||||
.connection-status-button:hover {
|
||||
background-color: var(--surface-hover);
|
||||
}
|
||||
|
||||
@@ -87,6 +87,7 @@
|
||||
@apply flex items-stretch w-full;
|
||||
background-color: transparent;
|
||||
color: var(--text-primary);
|
||||
border-bottom: 1px solid var(--tool-call-border-color);
|
||||
}
|
||||
|
||||
.tool-call-header:hover {
|
||||
@@ -127,11 +128,30 @@
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.tool-call-header-input {
|
||||
@apply inline-flex items-center justify-center;
|
||||
background-color: transparent;
|
||||
border: none;
|
||||
color: var(--text-secondary);
|
||||
padding: 0 0.5rem;
|
||||
border-radius: 0;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.tool-call-header-copy:hover {
|
||||
background-color: transparent;
|
||||
color: var(--text-primary);
|
||||
}
|
||||
|
||||
.tool-call-header-input:hover {
|
||||
background-color: transparent;
|
||||
color: var(--text-primary);
|
||||
}
|
||||
|
||||
.tool-call-header-input[aria-pressed="true"] {
|
||||
color: var(--text-primary);
|
||||
}
|
||||
|
||||
.tool-call-header-status {
|
||||
@apply inline-flex items-center justify-center;
|
||||
font-size: 0.95rem;
|
||||
@@ -213,6 +233,63 @@
|
||||
font-size: var(--font-size-xs);
|
||||
}
|
||||
|
||||
|
||||
.tool-call-io-sections {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: var(--space-xs);
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.tool-call-io-section {
|
||||
border: 1px solid var(--tool-call-border-color);
|
||||
overflow: hidden;
|
||||
background-color: transparent;
|
||||
border-radius: 0;
|
||||
}
|
||||
|
||||
.tool-call-io-toggle {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: flex-start;
|
||||
gap: 0.75rem;
|
||||
padding: 0.5rem;
|
||||
background-color: var(--surface-secondary);
|
||||
border: none;
|
||||
border-bottom: 1px solid var(--tool-call-border-color);
|
||||
width: 100%;
|
||||
text-align: left;
|
||||
font-size: 0.875rem;
|
||||
font-weight: normal;
|
||||
color: var(--text-primary);
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.tool-call-io-toggle::before {
|
||||
content: "▶";
|
||||
font-size: 11px;
|
||||
margin-right: 0.35rem;
|
||||
color: var(--text-secondary);
|
||||
}
|
||||
|
||||
.tool-call-io-toggle[aria-expanded="true"]::before {
|
||||
content: "▼";
|
||||
}
|
||||
|
||||
.tool-call-io-title {
|
||||
font-weight: inherit;
|
||||
color: inherit;
|
||||
}
|
||||
|
||||
.tool-call-io-body {
|
||||
background-color: var(--surface-code);
|
||||
}
|
||||
|
||||
/* IO sections provide the outer frame; avoid double borders on markdown frames. */
|
||||
.tool-call-io-body .tool-call-markdown {
|
||||
border: none;
|
||||
}
|
||||
|
||||
.tool-call-markdown {
|
||||
background-color: var(--surface-code);
|
||||
/* Keep a visible frame around the scroll viewport (not the content). */
|
||||
|
||||
Reference in New Issue
Block a user