diff --git a/CHANGELOG.md b/CHANGELOG.md index a337f1b0f..763de4ccc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,11 +2,12 @@ Docs: https://docs.clawd.bot -## 2026.1.17-2 (Unreleased) +## 2026.1.17-2 ### Changes ### Fixes +- Tools: show exec elevated flag before the command and keep it outside markdown in tool summaries. - Memory: split overly long lines to keep embeddings under token limits. ## 2026.1.17-1 diff --git a/src/auto-reply/tool-meta.test.ts b/src/auto-reply/tool-meta.test.ts index 1006416fd..16dab8d0f 100644 --- a/src/auto-reply/tool-meta.test.ts +++ b/src/auto-reply/tool-meta.test.ts @@ -42,6 +42,16 @@ describe("tool meta formatting", () => { expect(out).toContain("`~/dir/a.txt`"); }); + it("keeps exec flags outside markdown and moves them to the front", () => { + vi.stubEnv("HOME", "/Users/test"); + const out = formatToolAggregate( + "exec", + ["cd /Users/test/dir && gemini 2>&1 · elevated"], + { markdown: true }, + ); + expect(out).toBe("🛠️ exec: elevated · `cd ~/dir && gemini 2>&1`"); + }); + it("formats prefixes with default labels", () => { vi.stubEnv("HOME", "/Users/test"); expect(formatToolPrefix(undefined, undefined)).toBe("🧩 tool"); diff --git a/src/auto-reply/tool-meta.ts b/src/auto-reply/tool-meta.ts index de4deae61..aaf527ada 100644 --- a/src/auto-reply/tool-meta.ts +++ b/src/auto-reply/tool-meta.ts @@ -60,7 +60,7 @@ export function formatToolAggregate( const allSegments = [...rawSegments, ...segments]; const meta = allSegments.join("; "); - return `${prefix}: ${maybeWrapMarkdown(meta, options?.markdown)}`; + return `${prefix}: ${formatMetaForDisplay(toolName, meta, options?.markdown)}`; } export function formatToolPrefix(toolName?: string, meta?: string) { @@ -69,6 +69,40 @@ export function formatToolPrefix(toolName?: string, meta?: string) { return formatToolSummary(display); } +function formatMetaForDisplay( + toolName: string | undefined, + meta: string, + markdown?: boolean, +): string { + const normalized = (toolName ?? "").trim().toLowerCase(); + if (normalized === "exec" || normalized === "bash") { + const { flags, body } = splitExecFlags(meta); + if (flags.length > 0) { + if (!body) return flags.join(" · "); + return `${flags.join(" · ")} · ${maybeWrapMarkdown(body, markdown)}`; + } + } + return maybeWrapMarkdown(meta, markdown); +} + +function splitExecFlags(meta: string): { flags: string[]; body: string } { + const parts = meta + .split(" · ") + .map((part) => part.trim()) + .filter(Boolean); + if (parts.length === 0) return { flags: [], body: "" }; + const flags: string[] = []; + const bodyParts: string[] = []; + for (const part of parts) { + if (part === "elevated" || part === "pty") { + flags.push(part); + continue; + } + bodyParts.push(part); + } + return { flags, body: bodyParts.join(" · ") }; +} + function isPathLike(value: string): boolean { if (!value) return false; if (value.includes(" ")) return false;