@oh-my-pi/pi-coding-agent 3.14.0 → 3.15.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +89 -0
- package/docs/theme.md +38 -5
- package/examples/sdk/11-sessions.ts +2 -2
- package/package.json +7 -4
- package/src/cli/file-processor.ts +51 -2
- package/src/cli/plugin-cli.ts +25 -19
- package/src/cli/update-cli.ts +4 -3
- package/src/core/agent-session.ts +31 -4
- package/src/core/compaction/branch-summarization.ts +4 -32
- package/src/core/compaction/compaction.ts +6 -84
- package/src/core/compaction/utils.ts +2 -3
- package/src/core/custom-tools/types.ts +2 -0
- package/src/core/export-html/index.ts +1 -1
- package/src/core/hooks/tool-wrapper.ts +0 -1
- package/src/core/hooks/types.ts +2 -2
- package/src/core/plugins/doctor.ts +9 -1
- package/src/core/sdk.ts +2 -1
- package/src/core/session-manager.ts +518 -40
- package/src/core/settings-manager.ts +174 -0
- package/src/core/system-prompt.ts +9 -14
- package/src/core/title-generator.ts +2 -8
- package/src/core/tools/ask.ts +19 -37
- package/src/core/tools/bash.ts +2 -37
- package/src/core/tools/edit.ts +2 -9
- package/src/core/tools/exa/render.ts +52 -48
- package/src/core/tools/find.ts +10 -8
- package/src/core/tools/grep.ts +45 -17
- package/src/core/tools/ls.ts +22 -2
- package/src/core/tools/lsp/clients/biome-client.ts +207 -0
- package/src/core/tools/lsp/clients/index.ts +49 -0
- package/src/core/tools/lsp/clients/lsp-linter-client.ts +98 -0
- package/src/core/tools/lsp/config.ts +3 -0
- package/src/core/tools/lsp/index.ts +107 -55
- package/src/core/tools/lsp/render.ts +192 -79
- package/src/core/tools/lsp/types.ts +27 -0
- package/src/core/tools/lsp/utils.ts +62 -22
- package/src/core/tools/notebook.ts +9 -1
- package/src/core/tools/output.ts +37 -14
- package/src/core/tools/read.ts +349 -34
- package/src/core/tools/renderers.ts +290 -89
- package/src/core/tools/review.ts +12 -5
- package/src/core/tools/task/agents.ts +5 -5
- package/src/core/tools/task/commands.ts +3 -3
- package/src/core/tools/task/executor.ts +33 -1
- package/src/core/tools/task/index.ts +93 -6
- package/src/core/tools/task/render.ts +147 -66
- package/src/core/tools/task/types.ts +14 -9
- package/src/core/tools/web-fetch.ts +242 -103
- package/src/core/tools/web-search/index.ts +64 -20
- package/src/core/tools/web-search/providers/exa.ts +68 -172
- package/src/core/tools/web-search/render.ts +264 -74
- package/src/core/tools/write.ts +2 -8
- package/src/main.ts +10 -6
- package/src/modes/cleanup.ts +23 -0
- package/src/modes/index.ts +9 -4
- package/src/modes/interactive/components/bash-execution.ts +6 -3
- package/src/modes/interactive/components/branch-summary-message.ts +1 -1
- package/src/modes/interactive/components/compaction-summary-message.ts +1 -1
- package/src/modes/interactive/components/dynamic-border.ts +1 -1
- package/src/modes/interactive/components/extensions/extension-dashboard.ts +4 -5
- package/src/modes/interactive/components/extensions/extension-list.ts +18 -16
- package/src/modes/interactive/components/extensions/inspector-panel.ts +8 -8
- package/src/modes/interactive/components/hook-editor.ts +1 -0
- package/src/modes/interactive/components/hook-message.ts +2 -2
- package/src/modes/interactive/components/hook-selector.ts +1 -1
- package/src/modes/interactive/components/model-selector.ts +22 -9
- package/src/modes/interactive/components/oauth-selector.ts +20 -4
- package/src/modes/interactive/components/plugin-settings.ts +4 -2
- package/src/modes/interactive/components/session-selector.ts +9 -6
- package/src/modes/interactive/components/settings-defs.ts +285 -1
- package/src/modes/interactive/components/settings-selector.ts +176 -3
- package/src/modes/interactive/components/status-line/index.ts +4 -0
- package/src/modes/interactive/components/status-line/presets.ts +94 -0
- package/src/modes/interactive/components/status-line/segments.ts +350 -0
- package/src/modes/interactive/components/status-line/separators.ts +55 -0
- package/src/modes/interactive/components/status-line/types.ts +81 -0
- package/src/modes/interactive/components/status-line-segment-editor.ts +357 -0
- package/src/modes/interactive/components/status-line.ts +172 -223
- package/src/modes/interactive/components/tool-execution.ts +446 -211
- package/src/modes/interactive/components/tree-selector.ts +17 -6
- package/src/modes/interactive/components/ttsr-notification.ts +4 -4
- package/src/modes/interactive/components/welcome.ts +27 -19
- package/src/modes/interactive/interactive-mode.ts +99 -13
- package/src/modes/interactive/theme/dark.json +3 -2
- package/src/modes/interactive/theme/defaults/alabaster.json +99 -0
- package/src/modes/interactive/theme/defaults/amethyst.json +103 -0
- package/src/modes/interactive/theme/defaults/anthracite.json +100 -0
- package/src/modes/interactive/theme/defaults/basalt.json +90 -0
- package/src/modes/interactive/theme/defaults/birch.json +101 -0
- package/src/modes/interactive/theme/defaults/dark-abyss.json +97 -0
- package/src/modes/interactive/theme/defaults/dark-arctic.json +111 -0
- package/src/modes/interactive/theme/defaults/dark-aurora.json +94 -0
- package/src/modes/interactive/theme/defaults/dark-catppuccin.json +106 -0
- package/src/modes/interactive/theme/defaults/dark-cavern.json +97 -0
- package/src/modes/interactive/theme/defaults/dark-copper.json +94 -0
- package/src/modes/interactive/theme/defaults/dark-cosmos.json +96 -0
- package/src/modes/interactive/theme/defaults/dark-cyberpunk.json +109 -0
- package/src/modes/interactive/theme/defaults/dark-dracula.json +105 -0
- package/src/modes/interactive/theme/defaults/dark-eclipse.json +97 -0
- package/src/modes/interactive/theme/defaults/dark-ember.json +94 -0
- package/src/modes/interactive/theme/defaults/dark-equinox.json +96 -0
- package/src/modes/interactive/theme/defaults/dark-forest.json +103 -0
- package/src/modes/interactive/theme/defaults/dark-github.json +112 -0
- package/src/modes/interactive/theme/defaults/dark-gruvbox.json +119 -0
- package/src/modes/interactive/theme/defaults/dark-lavender.json +94 -0
- package/src/modes/interactive/theme/defaults/dark-lunar.json +95 -0
- package/src/modes/interactive/theme/defaults/dark-midnight.json +94 -0
- package/src/modes/interactive/theme/defaults/dark-monochrome.json +101 -0
- package/src/modes/interactive/theme/defaults/dark-monokai.json +105 -0
- package/src/modes/interactive/theme/defaults/dark-nebula.json +96 -0
- package/src/modes/interactive/theme/defaults/dark-nord.json +104 -0
- package/src/modes/interactive/theme/defaults/dark-ocean.json +108 -0
- package/src/modes/interactive/theme/defaults/dark-one.json +107 -0
- package/src/modes/interactive/theme/defaults/dark-rainforest.json +97 -0
- package/src/modes/interactive/theme/defaults/dark-reef.json +97 -0
- package/src/modes/interactive/theme/defaults/dark-retro.json +99 -0
- package/src/modes/interactive/theme/defaults/dark-rose-pine.json +95 -0
- package/src/modes/interactive/theme/defaults/dark-sakura.json +94 -0
- package/src/modes/interactive/theme/defaults/dark-slate.json +94 -0
- package/src/modes/interactive/theme/defaults/dark-solarized.json +96 -0
- package/src/modes/interactive/theme/defaults/dark-solstice.json +96 -0
- package/src/modes/interactive/theme/defaults/dark-starfall.json +97 -0
- package/src/modes/interactive/theme/defaults/dark-sunset.json +106 -0
- package/src/modes/interactive/theme/defaults/dark-swamp.json +96 -0
- package/src/modes/interactive/theme/defaults/dark-synthwave.json +102 -0
- package/src/modes/interactive/theme/defaults/dark-taiga.json +97 -0
- package/src/modes/interactive/theme/defaults/dark-terminal.json +94 -0
- package/src/modes/interactive/theme/defaults/dark-tokyo-night.json +108 -0
- package/src/modes/interactive/theme/defaults/dark-tundra.json +97 -0
- package/src/modes/interactive/theme/defaults/dark-twilight.json +97 -0
- package/src/modes/interactive/theme/defaults/dark-volcanic.json +97 -0
- package/src/modes/interactive/theme/defaults/graphite.json +99 -0
- package/src/modes/interactive/theme/defaults/index.ts +195 -0
- package/src/modes/interactive/theme/defaults/light-arctic.json +106 -0
- package/src/modes/interactive/theme/defaults/light-aurora-day.json +97 -0
- package/src/modes/interactive/theme/defaults/light-canyon.json +97 -0
- package/src/modes/interactive/theme/defaults/light-catppuccin.json +105 -0
- package/src/modes/interactive/theme/defaults/light-cirrus.json +96 -0
- package/src/modes/interactive/theme/defaults/light-coral.json +94 -0
- package/src/modes/interactive/theme/defaults/light-cyberpunk.json +103 -0
- package/src/modes/interactive/theme/defaults/light-dawn.json +96 -0
- package/src/modes/interactive/theme/defaults/light-dunes.json +97 -0
- package/src/modes/interactive/theme/defaults/light-eucalyptus.json +94 -0
- package/src/modes/interactive/theme/defaults/light-forest.json +107 -0
- package/src/modes/interactive/theme/defaults/light-frost.json +94 -0
- package/src/modes/interactive/theme/defaults/light-github.json +114 -0
- package/src/modes/interactive/theme/defaults/light-glacier.json +97 -0
- package/src/modes/interactive/theme/defaults/light-gruvbox.json +115 -0
- package/src/modes/interactive/theme/defaults/light-haze.json +96 -0
- package/src/modes/interactive/theme/defaults/light-honeycomb.json +94 -0
- package/src/modes/interactive/theme/defaults/light-lagoon.json +97 -0
- package/src/modes/interactive/theme/defaults/light-lavender.json +94 -0
- package/src/modes/interactive/theme/defaults/light-meadow.json +97 -0
- package/src/modes/interactive/theme/defaults/light-mint.json +94 -0
- package/src/modes/interactive/theme/defaults/light-monochrome.json +100 -0
- package/src/modes/interactive/theme/defaults/light-ocean.json +106 -0
- package/src/modes/interactive/theme/defaults/light-one.json +105 -0
- package/src/modes/interactive/theme/defaults/light-opal.json +97 -0
- package/src/modes/interactive/theme/defaults/light-orchard.json +97 -0
- package/src/modes/interactive/theme/defaults/light-paper.json +94 -0
- package/src/modes/interactive/theme/defaults/light-prism.json +96 -0
- package/src/modes/interactive/theme/defaults/light-retro.json +105 -0
- package/src/modes/interactive/theme/defaults/light-sand.json +94 -0
- package/src/modes/interactive/theme/defaults/light-savanna.json +97 -0
- package/src/modes/interactive/theme/defaults/light-solarized.json +101 -0
- package/src/modes/interactive/theme/defaults/light-soleil.json +96 -0
- package/src/modes/interactive/theme/defaults/light-sunset.json +106 -0
- package/src/modes/interactive/theme/defaults/light-synthwave.json +105 -0
- package/src/modes/interactive/theme/defaults/light-tokyo-night.json +118 -0
- package/src/modes/interactive/theme/defaults/light-wetland.json +97 -0
- package/src/modes/interactive/theme/defaults/light-zenith.json +95 -0
- package/src/modes/interactive/theme/defaults/limestone.json +100 -0
- package/src/modes/interactive/theme/defaults/mahogany.json +104 -0
- package/src/modes/interactive/theme/defaults/marble.json +99 -0
- package/src/modes/interactive/theme/defaults/obsidian.json +90 -0
- package/src/modes/interactive/theme/defaults/onyx.json +90 -0
- package/src/modes/interactive/theme/defaults/pearl.json +99 -0
- package/src/modes/interactive/theme/defaults/porcelain.json +90 -0
- package/src/modes/interactive/theme/defaults/quartz.json +102 -0
- package/src/modes/interactive/theme/defaults/sandstone.json +101 -0
- package/src/modes/interactive/theme/defaults/titanium.json +89 -0
- package/src/modes/interactive/theme/light.json +3 -2
- package/src/modes/interactive/theme/theme-schema.json +120 -4
- package/src/modes/interactive/theme/theme.ts +1228 -14
- package/src/prompts/branch-summary-preamble.md +3 -0
- package/src/prompts/branch-summary.md +28 -0
- package/src/prompts/compaction-summary.md +34 -0
- package/src/prompts/compaction-turn-prefix.md +16 -0
- package/src/prompts/compaction-update-summary.md +41 -0
- package/src/prompts/init.md +30 -0
- package/src/{core/tools/task/bundled-agents → prompts}/reviewer.md +6 -0
- package/src/prompts/summarization-system.md +3 -0
- package/src/prompts/system-prompt.md +27 -0
- package/src/{core/tools/task/bundled-agents → prompts}/task.md +2 -0
- package/src/prompts/title-system.md +8 -0
- package/src/prompts/tools/ask.md +24 -0
- package/src/prompts/tools/bash.md +23 -0
- package/src/prompts/tools/edit.md +9 -0
- package/src/prompts/tools/find.md +6 -0
- package/src/prompts/tools/grep.md +12 -0
- package/src/prompts/tools/lsp.md +14 -0
- package/src/prompts/tools/output.md +23 -0
- package/src/prompts/tools/read.md +25 -0
- package/src/prompts/tools/web-fetch.md +8 -0
- package/src/prompts/tools/web-search.md +10 -0
- package/src/prompts/tools/write.md +10 -0
- package/src/commands/init.md +0 -20
- /package/src/{core/tools/task/bundled-commands → prompts}/architect-plan.md +0 -0
- /package/src/{core/tools/task/bundled-agents → prompts}/browser.md +0 -0
- /package/src/{core/tools/task/bundled-agents → prompts}/explore.md +0 -0
- /package/src/{core/tools/task/bundled-commands → prompts}/implement-with-critic.md +0 -0
- /package/src/{core/tools/task/bundled-commands → prompts}/implement.md +0 -0
- /package/src/{core/tools/task/bundled-agents → prompts}/plan.md +0 -0
|
@@ -22,13 +22,6 @@ import { renderWebFetchCall, renderWebFetchResult, type WebFetchToolDetails } fr
|
|
|
22
22
|
import { renderWebSearchCall, renderWebSearchResult, type WebSearchRenderDetails } from "./web-search/render";
|
|
23
23
|
|
|
24
24
|
// Tree drawing characters
|
|
25
|
-
const TREE_MID = "├─";
|
|
26
|
-
const TREE_END = "└─";
|
|
27
|
-
|
|
28
|
-
// Icons
|
|
29
|
-
const ICON_SUCCESS = "●";
|
|
30
|
-
const ICON_WARNING = "●";
|
|
31
|
-
const ICON_ERROR = "●";
|
|
32
25
|
|
|
33
26
|
interface ToolRenderer<TArgs = any, TDetails = any> {
|
|
34
27
|
renderCall(args: TArgs, theme: Theme): Component;
|
|
@@ -86,29 +79,43 @@ const grepRenderer: ToolRenderer<GrepArgs, GrepToolDetails> = {
|
|
|
86
79
|
|
|
87
80
|
// Error case
|
|
88
81
|
if (details?.error) {
|
|
89
|
-
return new Text(`${theme.
|
|
82
|
+
return new Text(`${theme.styledSymbol("status.error", "error")} ${theme.fg("error", details.error)}`, 0, 0);
|
|
90
83
|
}
|
|
91
84
|
|
|
92
|
-
// Check for detailed rendering data - fall back to
|
|
85
|
+
// Check for detailed rendering data - fall back to structured output if not available
|
|
93
86
|
const hasDetailedData = details?.matchCount !== undefined || details?.fileCount !== undefined;
|
|
94
87
|
|
|
95
88
|
if (!hasDetailedData) {
|
|
96
|
-
// Fall back to showing raw text content
|
|
97
89
|
const textContent = result.content?.find((c) => c.type === "text")?.text;
|
|
98
90
|
if (!textContent || textContent === "No matches found") {
|
|
99
|
-
return new Text(
|
|
91
|
+
return new Text(
|
|
92
|
+
`${theme.styledSymbol("status.warning", "warning")} ${theme.fg("muted", "No matches found")}`,
|
|
93
|
+
0,
|
|
94
|
+
0,
|
|
95
|
+
);
|
|
100
96
|
}
|
|
101
97
|
|
|
102
|
-
|
|
103
|
-
const lines = textContent.split("\n");
|
|
98
|
+
const lines = textContent.split("\n").filter((line) => line.trim() !== "");
|
|
104
99
|
const maxLines = expanded ? lines.length : 10;
|
|
105
100
|
const displayLines = lines.slice(0, maxLines);
|
|
106
101
|
const remaining = lines.length - maxLines;
|
|
107
102
|
|
|
108
|
-
let text = `${theme.
|
|
109
|
-
|
|
103
|
+
let text = `${theme.styledSymbol("status.success", "success")} ${theme.fg("toolTitle", "grep")} ${theme.fg(
|
|
104
|
+
"dim",
|
|
105
|
+
`${lines.length} item${lines.length !== 1 ? "s" : ""}`,
|
|
106
|
+
)}`;
|
|
107
|
+
|
|
108
|
+
for (let i = 0; i < displayLines.length; i++) {
|
|
109
|
+
const isLast = i === displayLines.length - 1 && remaining === 0;
|
|
110
|
+
const branch = isLast ? theme.tree.last : theme.tree.branch;
|
|
111
|
+
text += `\n ${theme.fg("dim", branch)} ${theme.fg("toolOutput", displayLines[i])}`;
|
|
112
|
+
}
|
|
113
|
+
|
|
110
114
|
if (remaining > 0) {
|
|
111
|
-
text += `\n${theme.fg("
|
|
115
|
+
text += `\n ${theme.fg("dim", theme.tree.last)} ${theme.fg(
|
|
116
|
+
"muted",
|
|
117
|
+
`${theme.format.ellipsis} ${remaining} more items`,
|
|
118
|
+
)}`;
|
|
112
119
|
}
|
|
113
120
|
return new Text(text, 0, 0);
|
|
114
121
|
}
|
|
@@ -121,11 +128,15 @@ const grepRenderer: ToolRenderer<GrepArgs, GrepToolDetails> = {
|
|
|
121
128
|
|
|
122
129
|
// No matches
|
|
123
130
|
if (matchCount === 0) {
|
|
124
|
-
return new Text(
|
|
131
|
+
return new Text(
|
|
132
|
+
`${theme.styledSymbol("status.warning", "warning")} ${theme.fg("muted", "No matches found")}`,
|
|
133
|
+
0,
|
|
134
|
+
0,
|
|
135
|
+
);
|
|
125
136
|
}
|
|
126
137
|
|
|
127
138
|
// Build summary
|
|
128
|
-
const icon = theme.
|
|
139
|
+
const icon = theme.styledSymbol("status.success", "success");
|
|
129
140
|
let summary: string;
|
|
130
141
|
if (mode === "files_with_matches") {
|
|
131
142
|
summary = `${fileCount} file${fileCount !== 1 ? "s" : ""}`;
|
|
@@ -140,22 +151,56 @@ const grepRenderer: ToolRenderer<GrepArgs, GrepToolDetails> = {
|
|
|
140
151
|
}
|
|
141
152
|
|
|
142
153
|
const expandHint = expanded ? "" : theme.fg("dim", " (Ctrl+O to expand)");
|
|
143
|
-
|
|
154
|
+
const scopeLabel = details?.scopePath ? ` ${theme.fg("muted", `in ${details.scopePath}`)}` : "";
|
|
155
|
+
let text = `${icon} ${theme.fg("toolTitle", "grep")} ${theme.fg("dim", summary)}${scopeLabel}${expandHint}`;
|
|
156
|
+
|
|
157
|
+
const truncationReasons: string[] = [];
|
|
158
|
+
if (details?.matchLimitReached) {
|
|
159
|
+
truncationReasons.push(`limit ${details.matchLimitReached} matches`);
|
|
160
|
+
}
|
|
161
|
+
if (details?.headLimitReached) {
|
|
162
|
+
truncationReasons.push(`head limit ${details.headLimitReached}`);
|
|
163
|
+
}
|
|
164
|
+
if (details?.truncation?.truncated) {
|
|
165
|
+
truncationReasons.push("size limit");
|
|
166
|
+
}
|
|
167
|
+
if (details?.linesTruncated) {
|
|
168
|
+
truncationReasons.push("line length");
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
const fileEntries: Array<{ path: string; count?: number }> = details?.fileMatches?.length
|
|
172
|
+
? details.fileMatches.map((entry) => ({ path: entry.path, count: entry.count }))
|
|
173
|
+
: files.map((path) => ({ path }));
|
|
144
174
|
|
|
145
175
|
// Show file tree if we have files
|
|
146
|
-
if (
|
|
147
|
-
const maxFiles = expanded ?
|
|
176
|
+
if (fileEntries.length > 0) {
|
|
177
|
+
const maxFiles = expanded ? fileEntries.length : Math.min(fileEntries.length, 8);
|
|
148
178
|
for (let i = 0; i < maxFiles; i++) {
|
|
149
|
-
const
|
|
150
|
-
const
|
|
151
|
-
|
|
179
|
+
const entry = fileEntries[i];
|
|
180
|
+
const isLast = i === maxFiles - 1 && (expanded || fileEntries.length <= 8);
|
|
181
|
+
const branch = isLast ? theme.tree.last : theme.tree.branch;
|
|
182
|
+
const countLabel =
|
|
183
|
+
entry.count !== undefined
|
|
184
|
+
? ` ${theme.fg("dim", `(${entry.count} match${entry.count !== 1 ? "es" : ""})`)}`
|
|
185
|
+
: "";
|
|
186
|
+
text += `\n ${theme.fg("dim", branch)} ${theme.fg("accent", entry.path)}${countLabel}`;
|
|
152
187
|
}
|
|
153
188
|
|
|
154
|
-
if (!expanded &&
|
|
155
|
-
text += `\n ${theme.fg("dim",
|
|
189
|
+
if (!expanded && fileEntries.length > 8) {
|
|
190
|
+
text += `\n ${theme.fg("dim", theme.tree.last)} ${theme.fg(
|
|
191
|
+
"muted",
|
|
192
|
+
`${theme.format.ellipsis} ${fileEntries.length - 8} more files`,
|
|
193
|
+
)}`;
|
|
156
194
|
}
|
|
157
195
|
}
|
|
158
196
|
|
|
197
|
+
if (truncationReasons.length > 0) {
|
|
198
|
+
text += `\n ${theme.fg("dim", theme.tree.last)} ${theme.fg(
|
|
199
|
+
"warning",
|
|
200
|
+
`truncated: ${truncationReasons.join(", ")}`,
|
|
201
|
+
)}`;
|
|
202
|
+
}
|
|
203
|
+
|
|
159
204
|
return new Text(text, 0, 0);
|
|
160
205
|
},
|
|
161
206
|
};
|
|
@@ -195,7 +240,7 @@ const findRenderer: ToolRenderer<FindArgs, FindToolDetails> = {
|
|
|
195
240
|
|
|
196
241
|
// Error case
|
|
197
242
|
if (details?.error) {
|
|
198
|
-
return new Text(`${theme.
|
|
243
|
+
return new Text(`${theme.styledSymbol("status.error", "error")} ${theme.fg("error", details.error)}`, 0, 0);
|
|
199
244
|
}
|
|
200
245
|
|
|
201
246
|
// Check for detailed rendering data - fall back to parsing raw output if not available
|
|
@@ -206,7 +251,11 @@ const findRenderer: ToolRenderer<FindArgs, FindToolDetails> = {
|
|
|
206
251
|
|
|
207
252
|
if (!hasDetailedData) {
|
|
208
253
|
if (!textContent || textContent.includes("No files matching") || textContent.trim() === "") {
|
|
209
|
-
return new Text(
|
|
254
|
+
return new Text(
|
|
255
|
+
`${theme.styledSymbol("status.warning", "warning")} ${theme.fg("muted", "No files found")}`,
|
|
256
|
+
0,
|
|
257
|
+
0,
|
|
258
|
+
);
|
|
210
259
|
}
|
|
211
260
|
|
|
212
261
|
// Parse the raw output as file list
|
|
@@ -215,17 +264,20 @@ const findRenderer: ToolRenderer<FindArgs, FindToolDetails> = {
|
|
|
215
264
|
const displayLines = lines.slice(0, maxLines);
|
|
216
265
|
const remaining = lines.length - maxLines;
|
|
217
266
|
|
|
218
|
-
let text = `${theme.
|
|
267
|
+
let text = `${theme.styledSymbol("status.success", "success")} ${theme.fg("toolTitle", "find")} ${theme.fg(
|
|
219
268
|
"dim",
|
|
220
269
|
`${lines.length} file${lines.length !== 1 ? "s" : ""}`,
|
|
221
270
|
)}`;
|
|
222
271
|
for (let i = 0; i < displayLines.length; i++) {
|
|
223
272
|
const isLast = i === displayLines.length - 1 && remaining === 0;
|
|
224
|
-
const branch = isLast ?
|
|
273
|
+
const branch = isLast ? theme.tree.last : theme.tree.branch;
|
|
225
274
|
text += `\n ${theme.fg("dim", branch)} ${theme.fg("accent", displayLines[i])}`;
|
|
226
275
|
}
|
|
227
276
|
if (remaining > 0) {
|
|
228
|
-
text += `\n ${theme.fg("dim",
|
|
277
|
+
text += `\n ${theme.fg("dim", theme.tree.last)} ${theme.fg(
|
|
278
|
+
"muted",
|
|
279
|
+
`${theme.format.ellipsis} ${remaining} more files`,
|
|
280
|
+
)}`;
|
|
229
281
|
}
|
|
230
282
|
return new Text(text, 0, 0);
|
|
231
283
|
}
|
|
@@ -236,11 +288,15 @@ const findRenderer: ToolRenderer<FindArgs, FindToolDetails> = {
|
|
|
236
288
|
|
|
237
289
|
// No matches
|
|
238
290
|
if (fileCount === 0) {
|
|
239
|
-
return new Text(
|
|
291
|
+
return new Text(
|
|
292
|
+
`${theme.styledSymbol("status.warning", "warning")} ${theme.fg("muted", "No files found")}`,
|
|
293
|
+
0,
|
|
294
|
+
0,
|
|
295
|
+
);
|
|
240
296
|
}
|
|
241
297
|
|
|
242
298
|
// Build summary
|
|
243
|
-
const icon = theme.
|
|
299
|
+
const icon = theme.styledSymbol("status.success", "success");
|
|
244
300
|
let summary = `${fileCount} file${fileCount !== 1 ? "s" : ""}`;
|
|
245
301
|
|
|
246
302
|
if (truncated) {
|
|
@@ -248,22 +304,41 @@ const findRenderer: ToolRenderer<FindArgs, FindToolDetails> = {
|
|
|
248
304
|
}
|
|
249
305
|
|
|
250
306
|
const expandHint = expanded ? "" : theme.fg("dim", " (Ctrl+O to expand)");
|
|
251
|
-
|
|
307
|
+
const scopeLabel = details?.scopePath ? ` ${theme.fg("muted", `in ${details.scopePath}`)}` : "";
|
|
308
|
+
let text = `${icon} ${theme.fg("toolTitle", "find")} ${theme.fg("dim", summary)}${scopeLabel}${expandHint}`;
|
|
309
|
+
|
|
310
|
+
const truncationReasons: string[] = [];
|
|
311
|
+
if (details?.resultLimitReached) {
|
|
312
|
+
truncationReasons.push(`limit ${details.resultLimitReached} results`);
|
|
313
|
+
}
|
|
314
|
+
if (details?.truncation?.truncated) {
|
|
315
|
+
truncationReasons.push("size limit");
|
|
316
|
+
}
|
|
252
317
|
|
|
253
318
|
// Show file tree if we have files
|
|
254
319
|
if (files.length > 0) {
|
|
255
320
|
const maxFiles = expanded ? files.length : Math.min(files.length, 8);
|
|
256
321
|
for (let i = 0; i < maxFiles; i++) {
|
|
257
322
|
const isLast = i === maxFiles - 1 && (expanded || files.length <= 8);
|
|
258
|
-
const branch = isLast ?
|
|
323
|
+
const branch = isLast ? theme.tree.last : theme.tree.branch;
|
|
259
324
|
text += `\n ${theme.fg("dim", branch)} ${theme.fg("accent", files[i])}`;
|
|
260
325
|
}
|
|
261
326
|
|
|
262
327
|
if (!expanded && files.length > 8) {
|
|
263
|
-
text += `\n ${theme.fg("dim",
|
|
328
|
+
text += `\n ${theme.fg("dim", theme.tree.last)} ${theme.fg(
|
|
329
|
+
"muted",
|
|
330
|
+
`${theme.format.ellipsis} ${files.length - 8} more files`,
|
|
331
|
+
)}`;
|
|
264
332
|
}
|
|
265
333
|
}
|
|
266
334
|
|
|
335
|
+
if (truncationReasons.length > 0) {
|
|
336
|
+
text += `\n ${theme.fg("dim", theme.tree.last)} ${theme.fg(
|
|
337
|
+
"warning",
|
|
338
|
+
`truncated: ${truncationReasons.join(", ")}`,
|
|
339
|
+
)}`;
|
|
340
|
+
}
|
|
341
|
+
|
|
267
342
|
return new Text(text, 0, 0);
|
|
268
343
|
},
|
|
269
344
|
};
|
|
@@ -280,6 +355,37 @@ interface NotebookArgs {
|
|
|
280
355
|
content?: string;
|
|
281
356
|
}
|
|
282
357
|
|
|
358
|
+
function normalizeCellLines(lines: string[]): string[] {
|
|
359
|
+
return lines.map((line) => (line.endsWith("\n") ? line.slice(0, -1) : line));
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
function renderCellPreview(lines: string[], expanded: boolean, theme: Theme): string {
|
|
363
|
+
const normalized = normalizeCellLines(lines);
|
|
364
|
+
if (normalized.length === 0) {
|
|
365
|
+
return `\n ${theme.fg("dim", theme.tree.last)} ${theme.fg("muted", "(empty cell)")}`;
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
const maxLines = expanded ? normalized.length : Math.min(normalized.length, 6);
|
|
369
|
+
let text = "";
|
|
370
|
+
|
|
371
|
+
for (let i = 0; i < maxLines; i++) {
|
|
372
|
+
const isLast = i === maxLines - 1 && (expanded || normalized.length <= maxLines);
|
|
373
|
+
const branch = isLast ? theme.tree.last : theme.tree.branch;
|
|
374
|
+
const line = normalized[i];
|
|
375
|
+
text += `\n ${theme.fg("dim", branch)} ${theme.fg("toolOutput", line)}`;
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
const remaining = normalized.length - maxLines;
|
|
379
|
+
if (remaining > 0) {
|
|
380
|
+
text += `\n ${theme.fg("dim", theme.tree.last)} ${theme.fg(
|
|
381
|
+
"muted",
|
|
382
|
+
`${theme.format.ellipsis} ${remaining} more lines`,
|
|
383
|
+
)}`;
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
return text;
|
|
387
|
+
}
|
|
388
|
+
|
|
283
389
|
const notebookRenderer: ToolRenderer<NotebookArgs, NotebookToolDetails> = {
|
|
284
390
|
renderCall(args, theme) {
|
|
285
391
|
let text = theme.fg("toolTitle", theme.bold("notebook "));
|
|
@@ -297,22 +403,25 @@ const notebookRenderer: ToolRenderer<NotebookArgs, NotebookToolDetails> = {
|
|
|
297
403
|
return new Text(text, 0, 0);
|
|
298
404
|
},
|
|
299
405
|
|
|
300
|
-
renderResult(result,
|
|
406
|
+
renderResult(result, { expanded }, theme) {
|
|
301
407
|
const details = result.details;
|
|
302
408
|
|
|
303
409
|
// Error case - check for error in content
|
|
304
410
|
const content = result.content?.[0];
|
|
305
411
|
if (content?.type === "text" && content.text?.startsWith("Error:")) {
|
|
306
|
-
return new Text(`${theme.
|
|
412
|
+
return new Text(`${theme.styledSymbol("status.error", "error")} ${theme.fg("error", content.text)}`, 0, 0);
|
|
307
413
|
}
|
|
308
414
|
|
|
309
415
|
const action = details?.action ?? "edit";
|
|
310
416
|
const cellIndex = details?.cellIndex;
|
|
311
417
|
const cellType = details?.cellType;
|
|
312
418
|
const totalCells = details?.totalCells;
|
|
419
|
+
const cellSource = details?.cellSource;
|
|
420
|
+
const lineCount = cellSource?.length;
|
|
421
|
+
const canExpand = cellSource !== undefined && cellSource.length > 6;
|
|
313
422
|
|
|
314
423
|
// Build summary
|
|
315
|
-
const icon = theme.
|
|
424
|
+
const icon = theme.styledSymbol("status.success", "success");
|
|
316
425
|
let summary: string;
|
|
317
426
|
|
|
318
427
|
switch (action) {
|
|
@@ -326,11 +435,22 @@ const notebookRenderer: ToolRenderer<NotebookArgs, NotebookToolDetails> = {
|
|
|
326
435
|
summary = `Edited ${cellType || "cell"} at index ${cellIndex}`;
|
|
327
436
|
}
|
|
328
437
|
|
|
438
|
+
if (lineCount !== undefined) {
|
|
439
|
+
summary += ` (${lineCount} line${lineCount !== 1 ? "s" : ""})`;
|
|
440
|
+
}
|
|
441
|
+
|
|
329
442
|
if (totalCells !== undefined) {
|
|
330
443
|
summary += ` (${totalCells} total)`;
|
|
331
444
|
}
|
|
332
445
|
|
|
333
|
-
|
|
446
|
+
const expandHint = !expanded && canExpand ? theme.fg("dim", " (Ctrl+O to expand)") : "";
|
|
447
|
+
let text = `${icon} ${theme.fg("toolTitle", "notebook")} ${theme.fg("dim", summary)}${expandHint}`;
|
|
448
|
+
|
|
449
|
+
if (cellSource) {
|
|
450
|
+
text += renderCellPreview(cellSource, expanded, theme);
|
|
451
|
+
}
|
|
452
|
+
|
|
453
|
+
return new Text(text, 0, 0);
|
|
334
454
|
},
|
|
335
455
|
};
|
|
336
456
|
|
|
@@ -355,9 +475,8 @@ const askRenderer: ToolRenderer<AskArgs, AskToolDetails> = {
|
|
|
355
475
|
|
|
356
476
|
if (args.options?.length) {
|
|
357
477
|
for (const opt of args.options) {
|
|
358
|
-
text += `\n${theme.fg("dim",
|
|
478
|
+
text += `\n${theme.fg("dim", ` ${theme.checkbox.unchecked} `)}${theme.fg("muted", opt.label)}`;
|
|
359
479
|
}
|
|
360
|
-
text += `\n${theme.fg("dim", " ○ ")}${theme.fg("muted", "Other (custom input)")}`;
|
|
361
480
|
}
|
|
362
481
|
|
|
363
482
|
return new Text(text, 0, 0);
|
|
@@ -370,26 +489,33 @@ const askRenderer: ToolRenderer<AskArgs, AskToolDetails> = {
|
|
|
370
489
|
return new Text(txt?.type === "text" && txt.text ? txt.text : "", 0, 0);
|
|
371
490
|
}
|
|
372
491
|
|
|
373
|
-
|
|
492
|
+
const hasSelection = details.customInput || details.selectedOptions.length > 0;
|
|
493
|
+
const statusIcon = hasSelection
|
|
494
|
+
? theme.styledSymbol("status.success", "success")
|
|
495
|
+
: theme.styledSymbol("status.warning", "warning");
|
|
496
|
+
|
|
497
|
+
let text = `${statusIcon} ${theme.fg("toolTitle", "ask")} ${theme.fg("accent", details.question)}`;
|
|
374
498
|
|
|
375
499
|
if (details.customInput) {
|
|
376
|
-
|
|
377
|
-
|
|
500
|
+
text += `\n ${theme.fg("dim", theme.tree.last)} ${theme.styledSymbol(
|
|
501
|
+
"status.success",
|
|
502
|
+
"success",
|
|
503
|
+
)} ${theme.fg("toolOutput", details.customInput)}`;
|
|
378
504
|
} else if (details.selectedOptions.length > 0) {
|
|
379
|
-
// Show only selected options
|
|
380
505
|
const selected = details.selectedOptions;
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
text += `\n${theme.fg("dim", ` ${branch} `)}${theme.fg("success", selected[i])}`;
|
|
389
|
-
}
|
|
506
|
+
for (let i = 0; i < selected.length; i++) {
|
|
507
|
+
const isLast = i === selected.length - 1;
|
|
508
|
+
const branch = isLast ? theme.tree.last : theme.tree.branch;
|
|
509
|
+
text += `\n ${theme.fg("dim", branch)} ${theme.fg(
|
|
510
|
+
"success",
|
|
511
|
+
theme.checkbox.checked,
|
|
512
|
+
)} ${theme.fg("toolOutput", selected[i])}`;
|
|
390
513
|
}
|
|
391
514
|
} else {
|
|
392
|
-
text += `\n${theme.fg("dim",
|
|
515
|
+
text += `\n ${theme.fg("dim", theme.tree.last)} ${theme.styledSymbol(
|
|
516
|
+
"status.warning",
|
|
517
|
+
"warning",
|
|
518
|
+
)} ${theme.fg("warning", "Cancelled")}`;
|
|
393
519
|
}
|
|
394
520
|
|
|
395
521
|
return new Text(text, 0, 0);
|
|
@@ -433,6 +559,22 @@ function formatBytes(bytes: number): string {
|
|
|
433
559
|
return `${(bytes / (1024 * 1024)).toFixed(1)}M`;
|
|
434
560
|
}
|
|
435
561
|
|
|
562
|
+
function truncateLine(text: string, maxLen: number, ellipsis: string): string {
|
|
563
|
+
if (text.length <= maxLen) return text;
|
|
564
|
+
const sliceLen = Math.max(0, maxLen - ellipsis.length);
|
|
565
|
+
return `${text.slice(0, sliceLen)}${ellipsis}`;
|
|
566
|
+
}
|
|
567
|
+
|
|
568
|
+
type OutputEntry = OutputToolDetails["outputs"][number];
|
|
569
|
+
|
|
570
|
+
function formatOutputMeta(entry: OutputEntry, theme: Theme): string {
|
|
571
|
+
const metaParts = [`${entry.lineCount} lines, ${formatBytes(entry.charCount)}`];
|
|
572
|
+
if (entry.provenance) {
|
|
573
|
+
metaParts.push(`agent ${entry.provenance.agent}(${entry.provenance.index})`);
|
|
574
|
+
}
|
|
575
|
+
return theme.fg("dim", metaParts.join(theme.sep.dot));
|
|
576
|
+
}
|
|
577
|
+
|
|
436
578
|
const outputRenderer: ToolRenderer<OutputArgs, OutputToolDetails> = {
|
|
437
579
|
renderCall(args, theme) {
|
|
438
580
|
const ids = args.ids?.join(", ") ?? "?";
|
|
@@ -446,7 +588,7 @@ const outputRenderer: ToolRenderer<OutputArgs, OutputToolDetails> = {
|
|
|
446
588
|
|
|
447
589
|
// Error case: some IDs not found
|
|
448
590
|
if (details?.notFound?.length) {
|
|
449
|
-
let text = `${theme.
|
|
591
|
+
let text = `${theme.styledSymbol("status.error", "error")} Not found: ${details.notFound.join(", ")}`;
|
|
450
592
|
if (details.availableIds?.length) {
|
|
451
593
|
text += `\n${theme.fg("dim", "Available:")} ${details.availableIds.join(", ")}`;
|
|
452
594
|
} else {
|
|
@@ -459,35 +601,47 @@ const outputRenderer: ToolRenderer<OutputArgs, OutputToolDetails> = {
|
|
|
459
601
|
|
|
460
602
|
// No session case
|
|
461
603
|
if (outputs.length === 0) {
|
|
462
|
-
const textContent = result.content?.find((c
|
|
604
|
+
const textContent = result.content?.find((c) => c.type === "text")?.text;
|
|
463
605
|
return new Text(
|
|
464
|
-
`${theme.
|
|
606
|
+
`${theme.styledSymbol("status.warning", "warning")} ${theme.fg("muted", textContent || "No outputs")}`,
|
|
465
607
|
0,
|
|
466
608
|
0,
|
|
467
609
|
);
|
|
468
610
|
}
|
|
469
611
|
|
|
470
|
-
// Success:
|
|
471
|
-
if (outputs.length === 1) {
|
|
472
|
-
const o = outputs[0];
|
|
473
|
-
const summary = `read ${o.id}.out.md (${o.lineCount} lines, ${formatBytes(o.charCount)})`;
|
|
474
|
-
return new Text(`${theme.fg("success", ICON_SUCCESS)} ${theme.fg("dim", summary)}`, 0, 0);
|
|
475
|
-
}
|
|
476
|
-
|
|
477
|
-
// Success: multiple outputs (tree display)
|
|
612
|
+
// Success: summary + tree display
|
|
478
613
|
const expandHint = expanded ? "" : theme.fg("dim", " (Ctrl+O to expand)");
|
|
479
|
-
|
|
614
|
+
const icon = theme.styledSymbol("status.success", "success");
|
|
615
|
+
const summary = `read ${outputs.length} output${outputs.length !== 1 ? "s" : ""}`;
|
|
616
|
+
let text = `${icon} ${theme.fg("toolTitle", "output")} ${theme.fg("dim", summary)}${expandHint}`;
|
|
480
617
|
|
|
618
|
+
const previewLimit = expanded ? 3 : 1;
|
|
481
619
|
const maxOutputs = expanded ? outputs.length : Math.min(outputs.length, 5);
|
|
482
620
|
for (let i = 0; i < maxOutputs; i++) {
|
|
483
621
|
const o = outputs[i];
|
|
484
622
|
const isLast = i === maxOutputs - 1 && (expanded || outputs.length <= 5);
|
|
485
|
-
const branch = isLast ?
|
|
486
|
-
text += `\n ${theme.fg("dim", branch)} ${theme.fg("accent", o.id)} ${
|
|
623
|
+
const branch = isLast ? theme.tree.last : theme.tree.branch;
|
|
624
|
+
text += `\n ${theme.fg("dim", branch)} ${theme.fg("accent", o.id)} ${formatOutputMeta(o, theme)}`;
|
|
625
|
+
|
|
626
|
+
const previewLines = o.previewLines ?? [];
|
|
627
|
+
const shownPreview = previewLines.slice(0, previewLimit);
|
|
628
|
+
if (shownPreview.length > 0) {
|
|
629
|
+
const childPrefix = isLast ? " " : ` ${theme.fg("dim", theme.tree.vertical)} `;
|
|
630
|
+
for (const line of shownPreview) {
|
|
631
|
+
const previewText = truncateLine(line, 80, theme.format.ellipsis);
|
|
632
|
+
text += `\n${childPrefix}${theme.fg("dim", theme.tree.hook)} ${theme.fg("muted", "preview:")} ${theme.fg(
|
|
633
|
+
"toolOutput",
|
|
634
|
+
previewText,
|
|
635
|
+
)}`;
|
|
636
|
+
}
|
|
637
|
+
}
|
|
487
638
|
}
|
|
488
639
|
|
|
489
640
|
if (!expanded && outputs.length > 5) {
|
|
490
|
-
text += `\n ${theme.fg("dim",
|
|
641
|
+
text += `\n ${theme.fg("dim", theme.tree.last)} ${theme.fg(
|
|
642
|
+
"muted",
|
|
643
|
+
`${theme.format.ellipsis} ${outputs.length - 5} more outputs`,
|
|
644
|
+
)}`;
|
|
491
645
|
}
|
|
492
646
|
|
|
493
647
|
return new Text(text, 0, 0);
|
|
@@ -524,41 +678,88 @@ const lsRenderer: ToolRenderer<LsArgs, LsToolDetails> = {
|
|
|
524
678
|
|
|
525
679
|
renderResult(result, { expanded }, theme) {
|
|
526
680
|
const details = result.details;
|
|
527
|
-
const textContent = result.content?.find((c: any) => c.type === "text")?.text;
|
|
681
|
+
const textContent = result.content?.find((c: any) => c.type === "text")?.text ?? "";
|
|
528
682
|
|
|
529
|
-
if (
|
|
530
|
-
|
|
683
|
+
if (
|
|
684
|
+
(!textContent || textContent.trim() === "" || textContent.trim() === "(empty directory)") &&
|
|
685
|
+
(!details?.entries || details.entries.length === 0)
|
|
686
|
+
) {
|
|
687
|
+
return new Text(
|
|
688
|
+
`${theme.styledSymbol("status.warning", "warning")} ${theme.fg("muted", "Empty directory")}`,
|
|
689
|
+
0,
|
|
690
|
+
0,
|
|
691
|
+
);
|
|
692
|
+
}
|
|
693
|
+
|
|
694
|
+
let entries: string[] = details?.entries ? [...details.entries] : [];
|
|
695
|
+
if (entries.length === 0) {
|
|
696
|
+
const rawLines = textContent.split("\n").filter((l: string) => l.trim());
|
|
697
|
+
entries = rawLines.filter((line) => !/^\[.*\]$/.test(line.trim()));
|
|
698
|
+
}
|
|
699
|
+
|
|
700
|
+
if (entries.length === 0) {
|
|
701
|
+
return new Text(
|
|
702
|
+
`${theme.styledSymbol("status.warning", "warning")} ${theme.fg("muted", "Empty directory")}`,
|
|
703
|
+
0,
|
|
704
|
+
0,
|
|
705
|
+
);
|
|
706
|
+
}
|
|
707
|
+
|
|
708
|
+
let dirCount = details?.dirCount;
|
|
709
|
+
let fileCount = details?.fileCount;
|
|
710
|
+
if (dirCount === undefined || fileCount === undefined) {
|
|
711
|
+
dirCount = 0;
|
|
712
|
+
fileCount = 0;
|
|
713
|
+
for (const entry of entries) {
|
|
714
|
+
if (entry.endsWith("/")) {
|
|
715
|
+
dirCount += 1;
|
|
716
|
+
} else {
|
|
717
|
+
fileCount += 1;
|
|
718
|
+
}
|
|
719
|
+
}
|
|
531
720
|
}
|
|
532
721
|
|
|
533
|
-
const
|
|
534
|
-
const
|
|
535
|
-
|
|
722
|
+
const truncated = Boolean(details?.truncation?.truncated || details?.entryLimitReached);
|
|
723
|
+
const icon = truncated
|
|
724
|
+
? theme.styledSymbol("status.warning", "warning")
|
|
725
|
+
: theme.styledSymbol("status.success", "success");
|
|
536
726
|
|
|
537
|
-
const
|
|
538
|
-
const
|
|
727
|
+
const dirLabel = `${dirCount} dir${dirCount !== 1 ? "s" : ""}`;
|
|
728
|
+
const fileLabel = `${fileCount} file${fileCount !== 1 ? "s" : ""}`;
|
|
729
|
+
let text = `${icon} ${theme.fg("toolTitle", "ls")} ${theme.fg("dim", `${dirLabel}, ${fileLabel}`)}`;
|
|
539
730
|
|
|
540
|
-
let summary = `${dirs.length} dir${dirs.length !== 1 ? "s" : ""}, ${files.length} file${
|
|
541
|
-
files.length !== 1 ? "s" : ""
|
|
542
|
-
}`;
|
|
543
731
|
if (truncated) {
|
|
544
|
-
|
|
732
|
+
const reasonParts: string[] = [];
|
|
733
|
+
if (details?.entryLimitReached) {
|
|
734
|
+
reasonParts.push(`entry limit ${details.entryLimitReached}`);
|
|
735
|
+
}
|
|
736
|
+
if (details?.truncation?.truncated) {
|
|
737
|
+
reasonParts.push(`output cap ${formatBytes(details.truncation.maxBytes)}`);
|
|
738
|
+
}
|
|
739
|
+
const reasonText = reasonParts.length > 0 ? `truncated: ${reasonParts.join(", ")}` : "truncated";
|
|
740
|
+
text += ` ${theme.fg("warning", `(${reasonText})`)}`;
|
|
545
741
|
}
|
|
546
742
|
|
|
547
|
-
|
|
548
|
-
|
|
743
|
+
if (!expanded) {
|
|
744
|
+
text += `\n${theme.fg("dim", `${theme.nav.expand} Ctrl+O to expand list`)}`;
|
|
745
|
+
}
|
|
549
746
|
|
|
550
747
|
const maxEntries = expanded ? entries.length : Math.min(entries.length, 12);
|
|
551
748
|
for (let i = 0; i < maxEntries; i++) {
|
|
552
749
|
const entry = entries[i];
|
|
553
750
|
const isLast = i === maxEntries - 1 && (expanded || entries.length <= 12);
|
|
554
|
-
const branch = isLast ?
|
|
751
|
+
const branch = isLast ? theme.tree.last : theme.tree.branch;
|
|
555
752
|
const isDir = entry.endsWith("/");
|
|
556
|
-
const
|
|
557
|
-
|
|
753
|
+
const entryIcon = isDir ? theme.fg("accent", theme.icon.folder) : theme.fg("muted", theme.icon.file);
|
|
754
|
+
const entryColor = isDir ? "accent" : "toolOutput";
|
|
755
|
+
text += `\n ${theme.fg("dim", branch)} ${entryIcon} ${theme.fg(entryColor, entry)}`;
|
|
558
756
|
}
|
|
559
757
|
|
|
560
758
|
if (!expanded && entries.length > 12) {
|
|
561
|
-
text += `\n ${theme.fg("dim",
|
|
759
|
+
text += `\n ${theme.fg("dim", theme.tree.last)} ${theme.fg(
|
|
760
|
+
"muted",
|
|
761
|
+
`${theme.format.ellipsis} ${entries.length - 12} more entries`,
|
|
762
|
+
)}`;
|
|
562
763
|
}
|
|
563
764
|
|
|
564
765
|
return new Text(text, 0, 0);
|
package/src/core/tools/review.ts
CHANGED
|
@@ -10,6 +10,7 @@ import type { Component } from "@oh-my-pi/pi-tui";
|
|
|
10
10
|
import { Container, Spacer, Text } from "@oh-my-pi/pi-tui";
|
|
11
11
|
import { Type } from "@sinclair/typebox";
|
|
12
12
|
import type { Theme } from "../../modes/interactive/theme/theme";
|
|
13
|
+
import { theme } from "../../modes/interactive/theme/theme";
|
|
13
14
|
|
|
14
15
|
const PRIORITY_LABELS: Record<number, string> = {
|
|
15
16
|
0: "P0",
|
|
@@ -101,7 +102,7 @@ export const reportFindingTool: AgentTool<typeof ReportFindingParams, ReportFind
|
|
|
101
102
|
const location = `${details.file_path}:${details.line_start}${details.line_end !== details.line_start ? `-${details.line_end}` : ""}`;
|
|
102
103
|
|
|
103
104
|
return new Text(
|
|
104
|
-
`${theme.fg("success",
|
|
105
|
+
`${theme.fg("success", theme.status.success)} ${theme.fg(color, `[${priority}]`)} ${theme.fg("dim", location)}`,
|
|
105
106
|
0,
|
|
106
107
|
0,
|
|
107
108
|
);
|
|
@@ -140,7 +141,7 @@ export const submitReviewTool: AgentTool<typeof SubmitReviewParams, SubmitReview
|
|
|
140
141
|
const { overall_correctness, explanation, confidence } = params;
|
|
141
142
|
|
|
142
143
|
let summary = `## Review Summary\n\n`;
|
|
143
|
-
summary += `**Verdict:** ${overall_correctness === "correct" ?
|
|
144
|
+
summary += `**Verdict:** ${overall_correctness === "correct" ? `${theme.status.success} Patch is correct` : `${theme.status.error} Patch is incorrect`}\n`;
|
|
144
145
|
summary += `**Confidence:** ${(confidence * 100).toFixed(0)}%\n\n`;
|
|
145
146
|
summary += explanation;
|
|
146
147
|
|
|
@@ -169,7 +170,7 @@ export const submitReviewTool: AgentTool<typeof SubmitReviewParams, SubmitReview
|
|
|
169
170
|
|
|
170
171
|
const container = new Container();
|
|
171
172
|
const verdictColor = details.overall_correctness === "correct" ? "success" : "error";
|
|
172
|
-
const verdictIcon = details.overall_correctness === "correct" ?
|
|
173
|
+
const verdictIcon = details.overall_correctness === "correct" ? theme.status.success : theme.status.error;
|
|
173
174
|
|
|
174
175
|
container.addChild(
|
|
175
176
|
new Text(
|
|
@@ -239,7 +240,13 @@ subprocessToolRegistry.register<ReportFindingDetails>("report_finding", {
|
|
|
239
240
|
}
|
|
240
241
|
|
|
241
242
|
if (allData.length > displayCount) {
|
|
242
|
-
container.addChild(
|
|
243
|
+
container.addChild(
|
|
244
|
+
new Text(
|
|
245
|
+
theme.fg("dim", ` ${theme.format.ellipsis} ${allData.length - displayCount} more findings`),
|
|
246
|
+
0,
|
|
247
|
+
0,
|
|
248
|
+
),
|
|
249
|
+
);
|
|
243
250
|
}
|
|
244
251
|
|
|
245
252
|
return container;
|
|
@@ -255,7 +262,7 @@ subprocessToolRegistry.register<SubmitReviewDetails>("submit_review", {
|
|
|
255
262
|
|
|
256
263
|
renderInline: (data, theme) => {
|
|
257
264
|
const verdictColor = data.overall_correctness === "correct" ? "success" : "error";
|
|
258
|
-
const verdictIcon = data.overall_correctness === "correct" ?
|
|
265
|
+
const verdictIcon = data.overall_correctness === "correct" ? theme.status.success : theme.status.error;
|
|
259
266
|
return new Text(
|
|
260
267
|
`${theme.fg(verdictColor, verdictIcon)} Review: ${theme.fg(verdictColor, data.overall_correctness)} (${(data.confidence * 100).toFixed(0)}%)`,
|
|
261
268
|
0,
|