@nghyane/arcane 0.1.13 → 0.1.15
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 +28 -0
- package/package.json +21 -70
- package/scripts/format-prompts.ts +1 -3
- package/src/cli/args.ts +2 -7
- package/src/cli/config-cli.ts +1 -1
- package/src/cli/plugin-cli.ts +1 -1
- package/src/cli/setup-cli.ts +1 -1
- package/src/cli/update-cli.ts +1 -1
- package/src/cli/web-search-cli.ts +1 -1
- package/src/cli.ts +0 -1
- package/src/commands/config.ts +1 -1
- package/src/commands/grep.ts +1 -1
- package/src/commands/jupyter.ts +1 -1
- package/src/commands/plugin.ts +1 -1
- package/src/commands/setup.ts +1 -1
- package/src/commands/shell.ts +1 -1
- package/src/commands/ssh.ts +1 -1
- package/src/commands/stats.ts +1 -1
- package/src/commands/update.ts +1 -1
- package/src/config/model-registry.ts +3 -4
- package/src/config/model-resolver.ts +36 -9
- package/src/config/prompt-templates.ts +1 -9
- package/src/config/settings-schema.ts +32 -88
- package/src/config/settings.ts +3 -4
- package/src/debug/index.ts +1 -1
- package/src/debug/log-formatting.ts +1 -1
- package/src/debug/log-viewer.ts +2 -2
- package/src/discovery/helpers.ts +13 -3
- package/src/exa/index.ts +1 -35
- package/src/exa/render.ts +30 -190
- package/src/export/html/index.ts +1 -1
- package/src/extensibility/custom-tools/loader.ts +1 -1
- package/src/extensibility/custom-tools/types.ts +5 -1
- package/src/extensibility/custom-tools/wrapper.ts +1 -1
- package/src/extensibility/extensions/runner.ts +1 -1
- package/src/extensibility/extensions/types.ts +1 -1
- package/src/extensibility/extensions/wrapper.ts +7 -15
- package/src/extensibility/hooks/runner.ts +1 -1
- package/src/extensibility/hooks/types.ts +1 -1
- package/src/extensibility/plugins/doctor.ts +1 -1
- package/src/index.ts +13 -13
- package/src/lsp/index.ts +77 -24
- package/src/lsp/render.ts +34 -583
- package/src/lsp/types.ts +3 -3
- package/src/lsp/utils.ts +1 -1
- package/src/main.ts +1 -1
- package/src/mcp/tool-bridge.ts +1 -24
- package/src/modes/components/assistant-message.ts +7 -7
- package/src/modes/components/bash-execution.ts +50 -112
- package/src/modes/components/bordered-loader.ts +1 -1
- package/src/modes/components/branch-summary-message.ts +16 -10
- package/src/modes/components/compaction-summary-message.ts +20 -12
- package/src/modes/components/context-group.ts +106 -0
- package/src/modes/components/custom-message.ts +4 -5
- package/src/modes/components/diff.ts +2 -2
- package/src/modes/components/dynamic-border.ts +1 -1
- package/src/modes/components/extensions/extension-dashboard.ts +1 -1
- package/src/modes/components/extensions/extension-list.ts +1 -1
- package/src/modes/components/extensions/inspector-panel.ts +1 -1
- package/src/modes/components/footer.ts +2 -2
- package/src/modes/components/history-search.ts +1 -1
- package/src/modes/components/hook-editor.ts +1 -1
- package/src/modes/components/hook-input.ts +1 -1
- package/src/modes/components/hook-message.ts +4 -5
- package/src/modes/components/hook-selector.ts +1 -1
- package/src/modes/components/index.ts +0 -2
- package/src/modes/components/keybinding-hints.ts +1 -1
- package/src/modes/components/login-dialog.ts +1 -1
- package/src/modes/components/mcp-add-wizard.ts +1 -1
- package/src/modes/components/model-selector.ts +1 -1
- package/src/modes/components/oauth-selector.ts +1 -1
- package/src/modes/components/plugin-settings.ts +1 -1
- package/src/modes/components/python-execution.ts +51 -91
- package/src/modes/components/queue-mode-selector.ts +1 -1
- package/src/modes/components/session-selector.ts +1 -1
- package/src/modes/components/settings-defs.ts +5 -10
- package/src/modes/components/settings-selector.ts +1 -1
- package/src/modes/components/show-images-selector.ts +1 -1
- package/src/modes/components/skill-message.ts +4 -4
- package/src/modes/components/status-line/segments.ts +2 -2
- package/src/modes/components/status-line/separators.ts +1 -1
- package/src/modes/components/status-line-segment-editor.ts +1 -1
- package/src/modes/components/status-line.ts +1 -1
- package/src/modes/components/theme-selector.ts +1 -1
- package/src/modes/components/thinking-selector.ts +1 -1
- package/src/modes/components/todo-display.ts +2 -4
- package/src/modes/components/todo-reminder.ts +4 -4
- package/src/modes/components/tool-execution.ts +118 -440
- package/src/modes/components/tool-image-display.ts +107 -0
- package/src/modes/components/tree-selector.ts +2 -2
- package/src/modes/components/ttsr-notification.ts +4 -17
- package/src/modes/components/user-message-selector.ts +1 -1
- package/src/modes/components/user-message.ts +9 -10
- package/src/modes/components/welcome.ts +1 -1
- package/src/modes/controllers/command-controller.ts +1 -1
- package/src/modes/controllers/event-controller.ts +58 -187
- package/src/modes/controllers/extension-ui-controller.ts +1 -1
- package/src/modes/controllers/input-controller.ts +3 -1
- package/src/modes/controllers/mcp-command-controller.ts +1 -1
- package/src/modes/controllers/selector-controller.ts +3 -26
- package/src/modes/controllers/ssh-command-controller.ts +1 -1
- package/src/modes/interactive-mode.ts +3 -7
- package/src/modes/print-mode.ts +5 -5
- package/src/modes/rpc/rpc-mode.ts +1 -1
- package/src/modes/types.ts +1 -2
- package/src/modes/utils/ui-helpers.ts +34 -32
- package/src/patch/edit-tool.ts +742 -0
- package/src/patch/index.ts +32 -898
- package/src/patch/schemas.ts +208 -0
- package/src/patch/shared.ts +83 -151
- package/src/prompts/agents/explore.md +22 -37
- package/src/prompts/agents/init.md +1 -1
- package/src/prompts/agents/librarian.md +29 -20
- package/src/prompts/agents/oracle.md +9 -2
- package/src/prompts/agents/reviewer.md +14 -48
- package/src/prompts/agents/task.md +16 -8
- package/src/prompts/compaction/branch-summary.md +4 -1
- package/src/prompts/compaction/compaction-summary.md +4 -1
- package/src/prompts/system/subagent-system-prompt.md +1 -1
- package/src/prompts/system/system-prompt.md +162 -178
- package/src/prompts/system/verification-reminder.md +6 -0
- package/src/sdk.ts +0 -9
- package/src/session/agent-session.ts +244 -1459
- package/src/session/model-controller.ts +406 -0
- package/src/session/retry-utils.ts +71 -0
- package/src/session/session-manager.ts +22 -186
- package/src/session/session-types.ts +312 -0
- package/src/session/stats.ts +387 -0
- package/src/session/streaming-edit.ts +258 -0
- package/src/session/ttsr.ts +213 -0
- package/src/slash-commands/builtin-registry.ts +0 -8
- package/src/stt/recorder.ts +2 -2
- package/src/system-prompt.ts +1 -14
- package/src/task/agents.ts +7 -33
- package/src/task/executor.ts +50 -438
- package/src/task/index.ts +104 -71
- package/src/task/progress-tracker.ts +390 -0
- package/src/task/render.ts +371 -187
- package/src/task/subprocess-tool-registry.ts +1 -1
- package/src/task/types.ts +14 -47
- package/src/tools/ask.ts +31 -42
- package/src/tools/bash-interactive.ts +2 -2
- package/src/tools/bash-interceptor.ts +2 -2
- package/src/tools/bash-normalize.ts +1 -1
- package/src/tools/bash-skill-urls.ts +2 -2
- package/src/tools/bash.ts +87 -136
- package/src/tools/browser.ts +54 -84
- package/src/tools/create-tools.ts +186 -0
- package/src/tools/default-renderer.ts +104 -0
- package/src/tools/explore.ts +11 -10
- package/src/tools/fetch.ts +24 -114
- package/src/tools/find.ts +48 -132
- package/src/tools/gemini-image.ts +5 -15
- package/src/tools/github.ts +450 -0
- package/src/tools/grep.ts +43 -179
- package/src/tools/index.ts +35 -198
- package/src/tools/json-tree.ts +3 -3
- package/src/tools/librarian.ts +18 -18
- package/src/tools/list-limit.ts +2 -2
- package/src/tools/notebook.ts +35 -87
- package/src/tools/oracle.ts +25 -25
- package/src/tools/output-meta.ts +89 -4
- package/src/tools/output-utils.ts +2 -2
- package/src/tools/python.ts +86 -637
- package/src/tools/read.ts +36 -119
- package/src/tools/reviewer-tool.ts +19 -21
- package/src/tools/search-code.ts +128 -0
- package/src/tools/ssh.ts +67 -126
- package/src/tools/subagent-tool.ts +197 -123
- package/src/tools/todo-write.ts +15 -31
- package/src/tools/tool-errors.ts +0 -30
- package/src/tools/undo-edit.ts +30 -67
- package/src/tools/write.ts +78 -127
- package/src/tui/code-cell.ts +4 -4
- package/src/tui/file-list.ts +2 -2
- package/src/tui/output-block.ts +1 -1
- package/src/tui/status-line.ts +1 -1
- package/src/tui/tree-list.ts +2 -2
- package/src/tui/types.ts +1 -1
- package/src/tui/utils.ts +1 -1
- package/src/{tools → ui}/render-utils.ts +87 -126
- package/src/utils/external-editor.ts +4 -4
- package/src/utils/file-mentions.ts +1 -1
- package/src/utils/index.ts +30 -0
- package/src/utils/tools-manager.ts +9 -19
- package/src/web/github-client.ts +290 -0
- package/src/web/scrapers/github.ts +11 -62
- package/src/web/search/auth.ts +1 -3
- package/src/web/search/index.ts +82 -46
- package/src/web/search/provider.ts +11 -16
- package/src/web/search/providers/grep.ts +160 -0
- package/src/web/search/render.ts +48 -235
- package/src/web/search/types.ts +1 -1
- package/src/commands/commit.ts +0 -36
- package/src/commit/agentic/agent.ts +0 -311
- package/src/commit/agentic/fallback.ts +0 -96
- package/src/commit/agentic/index.ts +0 -359
- package/src/commit/agentic/prompts/analyze-file.md +0 -22
- package/src/commit/agentic/prompts/session-user.md +0 -25
- package/src/commit/agentic/prompts/split-confirm.md +0 -1
- package/src/commit/agentic/prompts/system.md +0 -38
- package/src/commit/agentic/state.ts +0 -69
- package/src/commit/agentic/tools/analyze-file.ts +0 -118
- package/src/commit/agentic/tools/git-file-diff.ts +0 -194
- package/src/commit/agentic/tools/git-hunk.ts +0 -50
- package/src/commit/agentic/tools/git-overview.ts +0 -84
- package/src/commit/agentic/tools/index.ts +0 -56
- package/src/commit/agentic/tools/propose-changelog.ts +0 -128
- package/src/commit/agentic/tools/propose-commit.ts +0 -154
- package/src/commit/agentic/tools/recent-commits.ts +0 -81
- package/src/commit/agentic/tools/split-commit.ts +0 -280
- package/src/commit/agentic/topo-sort.ts +0 -44
- package/src/commit/agentic/trivial.ts +0 -51
- package/src/commit/agentic/validation.ts +0 -200
- package/src/commit/analysis/conventional.ts +0 -165
- package/src/commit/analysis/index.ts +0 -4
- package/src/commit/analysis/scope.ts +0 -242
- package/src/commit/analysis/summary.ts +0 -112
- package/src/commit/analysis/validation.ts +0 -66
- package/src/commit/changelog/detect.ts +0 -37
- package/src/commit/changelog/generate.ts +0 -110
- package/src/commit/changelog/index.ts +0 -234
- package/src/commit/changelog/parse.ts +0 -44
- package/src/commit/cli.ts +0 -93
- package/src/commit/git/diff.ts +0 -148
- package/src/commit/git/errors.ts +0 -9
- package/src/commit/git/index.ts +0 -211
- package/src/commit/git/operations.ts +0 -54
- package/src/commit/index.ts +0 -5
- package/src/commit/map-reduce/index.ts +0 -64
- package/src/commit/map-reduce/map-phase.ts +0 -178
- package/src/commit/map-reduce/reduce-phase.ts +0 -145
- package/src/commit/map-reduce/utils.ts +0 -9
- package/src/commit/message.ts +0 -11
- package/src/commit/model-selection.ts +0 -69
- package/src/commit/pipeline.ts +0 -243
- package/src/commit/prompts/analysis-system.md +0 -148
- package/src/commit/prompts/analysis-user.md +0 -38
- package/src/commit/prompts/changelog-system.md +0 -50
- package/src/commit/prompts/changelog-user.md +0 -18
- package/src/commit/prompts/file-observer-system.md +0 -24
- package/src/commit/prompts/file-observer-user.md +0 -8
- package/src/commit/prompts/reduce-system.md +0 -50
- package/src/commit/prompts/reduce-user.md +0 -17
- package/src/commit/prompts/summary-retry.md +0 -3
- package/src/commit/prompts/summary-system.md +0 -38
- package/src/commit/prompts/summary-user.md +0 -13
- package/src/commit/prompts/types-description.md +0 -2
- package/src/commit/types.ts +0 -109
- package/src/commit/utils/exclusions.ts +0 -42
- package/src/mcp/render.ts +0 -123
- package/src/modes/components/agent-dashboard.ts +0 -1130
- package/src/modes/components/codemode-group.ts +0 -369
- package/src/modes/components/read-tool-group.ts +0 -119
- package/src/modes/components/visual-truncate.ts +0 -63
- package/src/prompts/system/subagent-user-prompt.md +0 -8
- package/src/prompts/tools/ask.md +0 -44
- package/src/prompts/tools/bash.md +0 -24
- package/src/prompts/tools/browser.md +0 -33
- package/src/prompts/tools/calculator.md +0 -12
- package/src/prompts/tools/explore.md +0 -29
- package/src/prompts/tools/fetch.md +0 -16
- package/src/prompts/tools/find.md +0 -18
- package/src/prompts/tools/gemini-image.md +0 -23
- package/src/prompts/tools/grep.md +0 -28
- package/src/prompts/tools/hashline.md +0 -232
- package/src/prompts/tools/librarian.md +0 -24
- package/src/prompts/tools/lsp.md +0 -28
- package/src/prompts/tools/oracle.md +0 -26
- package/src/prompts/tools/patch.md +0 -74
- package/src/prompts/tools/python.md +0 -66
- package/src/prompts/tools/read.md +0 -36
- package/src/prompts/tools/replace.md +0 -38
- package/src/prompts/tools/reviewer.md +0 -41
- package/src/prompts/tools/ssh.md +0 -51
- package/src/prompts/tools/task-summary.md +0 -28
- package/src/prompts/tools/task.md +0 -146
- package/src/prompts/tools/todo-write.md +0 -65
- package/src/prompts/tools/undo-edit.md +0 -7
- package/src/prompts/tools/web-search.md +0 -19
- package/src/prompts/tools/write.md +0 -18
- package/src/task/batch.ts +0 -102
- package/src/task/discovery.ts +0 -126
- package/src/task/parallel.ts +0 -84
- package/src/task/template.ts +0 -32
- package/src/tools/calculator.ts +0 -537
- package/src/tools/jtd-to-typescript.ts +0 -198
- package/src/tools/renderers.ts +0 -60
- package/src/tools/tool-result.ts +0 -86
- /package/src/{modes/theme → theme}/dark.json +0 -0
- /package/src/{modes/theme → theme}/defaults/dark-catppuccin.json +0 -0
- /package/src/{modes/theme → theme}/defaults/dark-dracula.json +0 -0
- /package/src/{modes/theme → theme}/defaults/dark-gruvbox.json +0 -0
- /package/src/{modes/theme → theme}/defaults/dark-solarized.json +0 -0
- /package/src/{modes/theme → theme}/defaults/dark-tokyo-night.json +0 -0
- /package/src/{modes/theme → theme}/defaults/index.ts +0 -0
- /package/src/{modes/theme → theme}/defaults/light-catppuccin.json +0 -0
- /package/src/{modes/theme → theme}/defaults/light-github.json +0 -0
- /package/src/{modes/theme → theme}/defaults/light-solarized.json +0 -0
- /package/src/{modes/theme → theme}/light.json +0 -0
- /package/src/{modes/theme → theme}/mermaid-cache.ts +0 -0
- /package/src/{modes/theme → theme}/theme-schema.json +0 -0
- /package/src/{modes/theme → theme}/theme.ts +0 -0
package/src/tools/write.ts
CHANGED
|
@@ -9,29 +9,28 @@ import type { Component } from "@nghyane/arcane-tui";
|
|
|
9
9
|
import { Text } from "@nghyane/arcane-tui";
|
|
10
10
|
import { untilAborted } from "@nghyane/arcane-utils";
|
|
11
11
|
import { type Static, Type } from "@sinclair/typebox";
|
|
12
|
-
import { renderPromptTemplate } from "../config/prompt-templates";
|
|
13
12
|
import type { RenderResultOptions } from "../extensibility/custom-tools/types";
|
|
14
13
|
import { createLspWritethrough, type FileDiagnosticsResult, type WritethroughCallback, writethroughNoop } from "../lsp";
|
|
15
|
-
import { getLanguageFromPath, type Theme } from "../modes/theme/theme";
|
|
16
|
-
import writeDescription from "../prompts/tools/write.md" with { type: "text" };
|
|
17
14
|
import type { ToolSession } from "../sdk";
|
|
18
|
-
import {
|
|
19
|
-
import {
|
|
20
|
-
import { type OutputMeta, outputMeta } from "./output-meta";
|
|
21
|
-
import { resolveToCwd } from "./path-utils";
|
|
15
|
+
import { getLanguageFromPath, type Theme } from "../theme/theme";
|
|
16
|
+
import { renderStatusLine } from "../tui";
|
|
22
17
|
import {
|
|
18
|
+
formatClickHint,
|
|
23
19
|
formatDiagnostics,
|
|
24
|
-
formatExpandHint,
|
|
25
|
-
formatMoreItems,
|
|
26
20
|
formatStatusIcon,
|
|
21
|
+
PREVIEW_LIMITS,
|
|
27
22
|
replaceTabs,
|
|
28
23
|
shortenPath,
|
|
29
|
-
|
|
30
|
-
|
|
24
|
+
TRUNCATE_LENGTHS,
|
|
25
|
+
truncateToWidth,
|
|
26
|
+
} from "../ui/render-utils";
|
|
27
|
+
import { invalidateFsScanAfterWrite } from "./fs-cache-invalidation";
|
|
28
|
+
import { type OutputMeta, outputMeta } from "./output-meta";
|
|
29
|
+
import { resolveToCwd } from "./path-utils";
|
|
31
30
|
|
|
32
31
|
const writeSchema = Type.Object({
|
|
33
|
-
path: Type.String({ description: "
|
|
34
|
-
content: Type.String({ description: "
|
|
32
|
+
path: Type.String({ description: "File path (relative or absolute)" }),
|
|
33
|
+
content: Type.String({ description: "Complete file content to write" }),
|
|
35
34
|
});
|
|
36
35
|
|
|
37
36
|
export type WriteToolInput = Static<typeof writeSchema>;
|
|
@@ -69,10 +68,10 @@ type WriteParams = WriteToolInput;
|
|
|
69
68
|
*
|
|
70
69
|
* Creates or overwrites files with optional LSP formatting and diagnostics.
|
|
71
70
|
*/
|
|
72
|
-
export class WriteTool implements AgentTool<typeof writeSchema, WriteToolDetails> {
|
|
71
|
+
export class WriteTool implements AgentTool<typeof writeSchema, WriteToolDetails, Theme> {
|
|
73
72
|
readonly name = "write";
|
|
74
73
|
readonly label = "Write";
|
|
75
|
-
|
|
74
|
+
description = "Create a new file";
|
|
76
75
|
readonly parameters = writeSchema;
|
|
77
76
|
readonly nonAbortable = true;
|
|
78
77
|
readonly concurrency = "exclusive";
|
|
@@ -86,7 +85,6 @@ export class WriteTool implements AgentTool<typeof writeSchema, WriteToolDetails
|
|
|
86
85
|
this.#writethrough = enableLsp
|
|
87
86
|
? createLspWritethrough(session.cwd, { enableFormat, enableDiagnostics })
|
|
88
87
|
: writethroughNoop;
|
|
89
|
-
this.description = renderPromptTemplate(writeDescription);
|
|
90
88
|
}
|
|
91
89
|
|
|
92
90
|
async execute(
|
|
@@ -122,73 +120,8 @@ export class WriteTool implements AgentTool<typeof writeSchema, WriteToolDetails
|
|
|
122
120
|
};
|
|
123
121
|
});
|
|
124
122
|
}
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
// =============================================================================
|
|
128
|
-
// TUI Renderer
|
|
129
|
-
// =============================================================================
|
|
130
|
-
|
|
131
|
-
interface WriteRenderArgs {
|
|
132
|
-
path?: string;
|
|
133
|
-
file_path?: string;
|
|
134
|
-
content?: string;
|
|
135
|
-
}
|
|
136
123
|
|
|
137
|
-
const WRITE_PREVIEW_LINES = 6;
|
|
138
|
-
const WRITE_STREAMING_PREVIEW_LINES = 12;
|
|
139
|
-
|
|
140
|
-
function countLines(text: string): number {
|
|
141
|
-
if (!text) return 0;
|
|
142
|
-
return text.split("\n").length;
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
function formatMetadataLine(lineCount: number | null, language: string | undefined, uiTheme: Theme): string {
|
|
146
|
-
const icon = uiTheme.getLangIcon(language);
|
|
147
|
-
if (lineCount !== null) {
|
|
148
|
-
return uiTheme.fg("dim", `${icon} ${lineCount} lines`);
|
|
149
|
-
}
|
|
150
|
-
return uiTheme.fg("dim", `${icon}`);
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
function formatStreamingContent(content: string, uiTheme: Theme, ui: ToolUIKit): string {
|
|
154
|
-
if (!content) return "";
|
|
155
|
-
const lines = content.split("\n");
|
|
156
|
-
const displayLines = lines.slice(-WRITE_STREAMING_PREVIEW_LINES);
|
|
157
|
-
const hidden = lines.length - displayLines.length;
|
|
158
|
-
|
|
159
|
-
let text = "\n\n";
|
|
160
|
-
if (hidden > 0) {
|
|
161
|
-
text += uiTheme.fg("dim", `… (${hidden} earlier lines)\n`);
|
|
162
|
-
}
|
|
163
|
-
for (const line of displayLines) {
|
|
164
|
-
text += `${uiTheme.fg("toolOutput", ui.truncate(replaceTabs(line), 80))}\n`;
|
|
165
|
-
}
|
|
166
|
-
text += uiTheme.fg("dim", `… (streaming)`);
|
|
167
|
-
return text;
|
|
168
|
-
}
|
|
169
|
-
|
|
170
|
-
function renderContentPreview(content: string, expanded: boolean, uiTheme: Theme, ui: ToolUIKit): string {
|
|
171
|
-
if (!content) return "";
|
|
172
|
-
const lines = content.split("\n");
|
|
173
|
-
const maxLines = expanded ? lines.length : Math.min(lines.length, WRITE_PREVIEW_LINES);
|
|
174
|
-
const displayLines = expanded ? lines : lines.slice(-maxLines);
|
|
175
|
-
const hidden = lines.length - displayLines.length;
|
|
176
|
-
|
|
177
|
-
let text = "\n\n";
|
|
178
|
-
for (const line of displayLines) {
|
|
179
|
-
text += `${uiTheme.fg("toolOutput", ui.truncate(replaceTabs(line), 80))}\n`;
|
|
180
|
-
}
|
|
181
|
-
if (!expanded && hidden > 0) {
|
|
182
|
-
const hint = formatExpandHint(uiTheme, expanded, hidden > 0);
|
|
183
|
-
const moreLine = `${formatMoreItems(hidden, "line")}${hint ? ` ${hint}` : ""}`;
|
|
184
|
-
text += uiTheme.fg("dim", moreLine);
|
|
185
|
-
}
|
|
186
|
-
return text;
|
|
187
|
-
}
|
|
188
|
-
|
|
189
|
-
export const writeToolRenderer = {
|
|
190
124
|
renderCall(args: WriteRenderArgs, options: RenderResultOptions, uiTheme: Theme): Component {
|
|
191
|
-
const ui = new ToolUIKit(uiTheme);
|
|
192
125
|
const rawPath = args.file_path || args.path || "";
|
|
193
126
|
const filePath = shortenPath(rawPath);
|
|
194
127
|
const lang = getLanguageFromPath(rawPath) ?? "text";
|
|
@@ -197,17 +130,18 @@ export const writeToolRenderer = {
|
|
|
197
130
|
const spinner =
|
|
198
131
|
options?.spinnerFrame !== undefined ? formatStatusIcon("running", uiTheme, options.spinnerFrame) : "";
|
|
199
132
|
|
|
200
|
-
|
|
133
|
+
const title = uiTheme.fg("toolTitle", uiTheme.bold("Write"));
|
|
134
|
+
let text = `${title} ${spinner ? `${spinner} ` : ""}${langIcon} ${pathDisplay}`;
|
|
201
135
|
|
|
202
136
|
if (!args.content) {
|
|
203
137
|
return new Text(text, 0, 0);
|
|
204
138
|
}
|
|
205
139
|
|
|
206
140
|
// Show streaming preview of content (tail)
|
|
207
|
-
text += formatStreamingContent(args.content, uiTheme
|
|
141
|
+
text += formatStreamingContent(args.content, uiTheme);
|
|
208
142
|
|
|
209
143
|
return new Text(text, 0, 0);
|
|
210
|
-
}
|
|
144
|
+
}
|
|
211
145
|
|
|
212
146
|
renderResult(
|
|
213
147
|
result: { content: Array<{ type: string; text?: string }>; details?: WriteToolDetails },
|
|
@@ -215,60 +149,77 @@ export const writeToolRenderer = {
|
|
|
215
149
|
uiTheme: Theme,
|
|
216
150
|
args?: WriteRenderArgs,
|
|
217
151
|
): Component {
|
|
218
|
-
const ui = new ToolUIKit(uiTheme);
|
|
219
152
|
const rawPath = args?.file_path || args?.path || "";
|
|
220
153
|
const filePath = shortenPath(rawPath);
|
|
221
154
|
const fileContent = args?.content || "";
|
|
222
155
|
const lang = getLanguageFromPath(rawPath);
|
|
223
|
-
const langIcon = uiTheme.fg("muted", uiTheme.getLangIcon(lang));
|
|
224
|
-
const pathDisplay = filePath ? uiTheme.fg("accent", filePath) : uiTheme.fg("toolOutput", "…");
|
|
225
156
|
const lineCount = countLines(fileContent);
|
|
157
|
+
const diagnostics = result.details?.diagnostics;
|
|
158
|
+
|
|
159
|
+
const meta: string[] = [];
|
|
160
|
+
if (lineCount > 0) meta.push(`${lineCount} lines`);
|
|
161
|
+
if (lang) meta.push(lang);
|
|
226
162
|
|
|
227
|
-
// Build header with status icon
|
|
228
163
|
const header = renderStatusLine(
|
|
229
|
-
{
|
|
230
|
-
icon: "success",
|
|
231
|
-
title: "Write",
|
|
232
|
-
description: `${langIcon} ${pathDisplay}`,
|
|
233
|
-
},
|
|
164
|
+
{ icon: "success", title: "Write", description: filePath || "file", meta },
|
|
234
165
|
uiTheme,
|
|
235
166
|
);
|
|
236
|
-
const metadataLine = formatMetadataLine(lineCount, lang ?? "text", uiTheme);
|
|
237
|
-
const diagnostics = result.details?.diagnostics;
|
|
238
167
|
|
|
239
|
-
|
|
168
|
+
// Tree-style content preview
|
|
169
|
+
const lines = fileContent ? fileContent.split("\n") : [];
|
|
170
|
+
const expanded = options.expanded;
|
|
171
|
+
const displayLines = expanded ? lines : lines.slice(-PREVIEW_LIMITS.WRITE_TAIL);
|
|
172
|
+
const skipped = lines.length - displayLines.length;
|
|
173
|
+
|
|
174
|
+
const bodyLines: string[] = [];
|
|
175
|
+
if (displayLines.length > 0) {
|
|
176
|
+
if (skipped > 0) {
|
|
177
|
+
bodyLines.push(uiTheme.fg("dim", `… ${skipped} more lines`));
|
|
178
|
+
}
|
|
179
|
+
for (let i = 0; i < displayLines.length; i++) {
|
|
180
|
+
bodyLines.push(uiTheme.fg("toolOutput", replaceTabs(displayLines[i])));
|
|
181
|
+
}
|
|
182
|
+
if (!expanded && skipped > 0) {
|
|
183
|
+
bodyLines.push(formatClickHint(uiTheme));
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
if (diagnostics) {
|
|
188
|
+
const diagText = formatDiagnostics(diagnostics, expanded, uiTheme, (fp: string) =>
|
|
189
|
+
uiTheme.getLangIcon(getLanguageFromPath(fp)),
|
|
190
|
+
);
|
|
191
|
+
if (diagText.trim()) bodyLines.push(diagText.trim());
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
const all = bodyLines.length > 0 ? [header, ...bodyLines] : [header];
|
|
195
|
+
return new Text(all.join("\n"), 0, 0);
|
|
196
|
+
}
|
|
197
|
+
}
|
|
240
198
|
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
199
|
+
interface WriteRenderArgs {
|
|
200
|
+
path?: string;
|
|
201
|
+
file_path?: string;
|
|
202
|
+
content?: string;
|
|
203
|
+
}
|
|
246
204
|
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
205
|
+
function countLines(text: string): number {
|
|
206
|
+
if (!text) return 0;
|
|
207
|
+
return text.split("\n").length;
|
|
208
|
+
}
|
|
250
209
|
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
const diagLines = diagText.split("\n");
|
|
257
|
-
const firstNonEmpty = diagLines.findIndex(line => line.trim());
|
|
258
|
-
if (firstNonEmpty >= 0) {
|
|
259
|
-
text += `\n${diagLines.slice(firstNonEmpty).join("\n")}`;
|
|
260
|
-
}
|
|
261
|
-
}
|
|
262
|
-
}
|
|
210
|
+
function formatStreamingContent(content: string, uiTheme: Theme): string {
|
|
211
|
+
if (!content) return "";
|
|
212
|
+
const lines = content.split("\n");
|
|
213
|
+
const displayLines = lines.slice(-PREVIEW_LIMITS.EXPANDED_LINES);
|
|
214
|
+
const hidden = lines.length - displayLines.length;
|
|
263
215
|
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
};
|
|
216
|
+
let text = "\n\n";
|
|
217
|
+
if (hidden > 0) {
|
|
218
|
+
text += uiTheme.fg("dim", `… (${hidden} earlier lines)\n`);
|
|
219
|
+
}
|
|
220
|
+
for (const line of displayLines) {
|
|
221
|
+
text += `${uiTheme.fg("toolOutput", truncateToWidth(replaceTabs(line), TRUNCATE_LENGTHS.CONTENT))}\n`;
|
|
222
|
+
}
|
|
223
|
+
text += uiTheme.fg("dim", `… (streaming)`);
|
|
224
|
+
return text;
|
|
225
|
+
}
|
package/src/tui/code-cell.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Render a code cell with optional output section.
|
|
3
3
|
*/
|
|
4
|
-
import { highlightCode, type Theme } from "../
|
|
5
|
-
import {
|
|
4
|
+
import { highlightCode, type Theme } from "../theme/theme";
|
|
5
|
+
import { formatClickHint, formatDuration, formatMoreItems, replaceTabs } from "../ui/render-utils";
|
|
6
6
|
import { renderOutputBlock } from "./output-block";
|
|
7
7
|
import type { State } from "./types";
|
|
8
8
|
import { getStateIcon } from "./utils";
|
|
@@ -78,7 +78,7 @@ export function renderCodeCell(options: CodeCellOptions, theme: Theme): string[]
|
|
|
78
78
|
const codeLines = rawCodeLines.slice(0, maxCodeLines);
|
|
79
79
|
const hiddenCodeLines = rawCodeLines.length - codeLines.length;
|
|
80
80
|
if (hiddenCodeLines > 0) {
|
|
81
|
-
const hint =
|
|
81
|
+
const hint = formatClickHint(theme, expanded, hiddenCodeLines > 0);
|
|
82
82
|
const moreLine = `${formatMoreItems(hiddenCodeLines, "line")}${hint ? ` ${hint}` : ""}`;
|
|
83
83
|
codeLines.push(theme.fg("dim", moreLine));
|
|
84
84
|
}
|
|
@@ -93,7 +93,7 @@ export function renderCodeCell(options: CodeCellOptions, theme: Theme): string[]
|
|
|
93
93
|
outputLines.push(...displayLines);
|
|
94
94
|
const remaining = rawLines.length - maxLines;
|
|
95
95
|
if (remaining > 0) {
|
|
96
|
-
const hint =
|
|
96
|
+
const hint = formatClickHint(theme, expanded, remaining > 0);
|
|
97
97
|
const moreLine = `${formatMoreItems(remaining, "line")}${hint ? ` ${hint}` : ""}`;
|
|
98
98
|
outputLines.push(theme.fg("dim", moreLine));
|
|
99
99
|
}
|
package/src/tui/file-list.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Render file listings with optional icons and metadata.
|
|
3
3
|
*/
|
|
4
|
-
import type { Theme } from "../
|
|
5
|
-
import { getLanguageFromPath } from "../
|
|
4
|
+
import type { Theme } from "../theme/theme";
|
|
5
|
+
import { getLanguageFromPath } from "../theme/theme";
|
|
6
6
|
import { renderTreeList } from "./tree-list";
|
|
7
7
|
|
|
8
8
|
export interface FileEntry {
|
package/src/tui/output-block.ts
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* Bordered output container with optional header and sections.
|
|
3
3
|
*/
|
|
4
4
|
import { padding, visibleWidth } from "@nghyane/arcane-tui";
|
|
5
|
-
import type { Theme } from "../
|
|
5
|
+
import type { Theme } from "../theme/theme";
|
|
6
6
|
import type { State } from "./types";
|
|
7
7
|
import type { RenderCache } from "./utils";
|
|
8
8
|
import { getStateBgColor, Hasher, padToWidth, truncateToWidth } from "./utils";
|
package/src/tui/status-line.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Standardized status header rendering for tool output.
|
|
3
3
|
*/
|
|
4
|
-
import type { Theme, ThemeColor } from "../
|
|
4
|
+
import type { Theme, ThemeColor } from "../theme/theme";
|
|
5
5
|
import type { IconType } from "./types";
|
|
6
6
|
import { getStateIcon } from "./utils";
|
|
7
7
|
|
package/src/tui/tree-list.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Hierarchical tree list rendering helper.
|
|
3
3
|
*/
|
|
4
|
-
import type { Theme } from "../
|
|
5
|
-
import { formatMoreItems, replaceTabs } from "../
|
|
4
|
+
import type { Theme } from "../theme/theme";
|
|
5
|
+
import { formatMoreItems, replaceTabs } from "../ui/render-utils";
|
|
6
6
|
import type { TreeContext } from "./types";
|
|
7
7
|
import { getTreeBranch, getTreeContinuePrefix } from "./utils";
|
|
8
8
|
|
package/src/tui/types.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Shared types for TUI rendering components.
|
|
3
3
|
*/
|
|
4
|
-
import type { Theme } from "../
|
|
4
|
+
import type { Theme } from "../theme/theme";
|
|
5
5
|
|
|
6
6
|
export type State = "pending" | "running" | "success" | "error" | "warning";
|
|
7
7
|
export type IconType = "success" | "error" | "running" | "pending" | "warning" | "info";
|
package/src/tui/utils.ts
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* Shared helpers for tool-rendered UI components.
|
|
3
3
|
*/
|
|
4
4
|
import { padding, visibleWidth } from "@nghyane/arcane-tui";
|
|
5
|
-
import type { Theme, ThemeBg } from "../
|
|
5
|
+
import type { Theme, ThemeBg } from "../theme/theme";
|
|
6
6
|
import type { IconType, State } from "./types";
|
|
7
7
|
|
|
8
8
|
export { Ellipsis, truncateToWidth } from "@nghyane/arcane-tui";
|
|
@@ -6,10 +6,69 @@
|
|
|
6
6
|
*/
|
|
7
7
|
import * as os from "node:os";
|
|
8
8
|
import { type Ellipsis, truncateToWidth } from "@nghyane/arcane-tui";
|
|
9
|
-
import type { Theme } from "../
|
|
9
|
+
import type { Theme } from "../theme/theme";
|
|
10
10
|
|
|
11
11
|
export { Ellipsis, replaceTabs, truncateToWidth } from "@nghyane/arcane-tui";
|
|
12
12
|
|
|
13
|
+
// =============================================================================
|
|
14
|
+
// Tool Tiers
|
|
15
|
+
// =============================================================================
|
|
16
|
+
|
|
17
|
+
export type ToolTier = "quiet" | "action" | "interactive" | "subagent" | "default";
|
|
18
|
+
|
|
19
|
+
const TOOL_TIERS: Record<string, ToolTier> = {
|
|
20
|
+
// Quiet — dim, 1 line, no expand
|
|
21
|
+
read: "quiet",
|
|
22
|
+
grep: "quiet",
|
|
23
|
+
find: "quiet",
|
|
24
|
+
fetch: "quiet",
|
|
25
|
+
search_code: "quiet",
|
|
26
|
+
lsp: "quiet",
|
|
27
|
+
browser: "quiet",
|
|
28
|
+
github: "quiet",
|
|
29
|
+
notebook: "quiet",
|
|
30
|
+
undo_edit: "quiet",
|
|
31
|
+
generate_image: "quiet",
|
|
32
|
+
|
|
33
|
+
// Action — normal color, show output, some expandable
|
|
34
|
+
bash: "action",
|
|
35
|
+
ssh: "action",
|
|
36
|
+
python: "action",
|
|
37
|
+
edit: "action",
|
|
38
|
+
write: "action",
|
|
39
|
+
web_search: "action",
|
|
40
|
+
exa_search: "action",
|
|
41
|
+
exa_search_deep: "action",
|
|
42
|
+
exa_search_code: "action",
|
|
43
|
+
exa_crawl: "action",
|
|
44
|
+
exa_company: "action",
|
|
45
|
+
exa_linkedin: "action",
|
|
46
|
+
exa_researcher_start: "action",
|
|
47
|
+
exa_researcher_poll: "action",
|
|
48
|
+
|
|
49
|
+
// Interactive — inline result, no expand
|
|
50
|
+
ask: "interactive",
|
|
51
|
+
todo_write: "interactive",
|
|
52
|
+
|
|
53
|
+
// Subagent — tool history + conclusion
|
|
54
|
+
task: "subagent",
|
|
55
|
+
explore: "subagent",
|
|
56
|
+
librarian: "subagent",
|
|
57
|
+
oracle: "subagent",
|
|
58
|
+
code_review: "subagent",
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
export function getToolTier(toolName: string): ToolTier {
|
|
62
|
+
return TOOL_TIERS[toolName] ?? "default";
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/** Tools that gather context (read-only information retrieval). Grouped into context batches. */
|
|
66
|
+
const CONTEXT_TOOLS = new Set(["read", "grep", "find", "fetch", "search_code", "lsp", "notebook"]);
|
|
67
|
+
|
|
68
|
+
export function isContextTool(toolName: string): boolean {
|
|
69
|
+
return CONTEXT_TOOLS.has(toolName);
|
|
70
|
+
}
|
|
71
|
+
|
|
13
72
|
// =============================================================================
|
|
14
73
|
// Standardized Display Constants
|
|
15
74
|
// =============================================================================
|
|
@@ -23,13 +82,23 @@ export const PREVIEW_LIMITS = {
|
|
|
23
82
|
/** Items (files, results) shown in collapsed view */
|
|
24
83
|
COLLAPSED_ITEMS: 8,
|
|
25
84
|
/** Output preview lines in collapsed view */
|
|
26
|
-
OUTPUT_COLLAPSED:
|
|
85
|
+
OUTPUT_COLLAPSED: 4,
|
|
27
86
|
/** Output preview lines in expanded view */
|
|
28
|
-
OUTPUT_EXPANDED:
|
|
87
|
+
OUTPUT_EXPANDED: 12,
|
|
29
88
|
/** Max hunks shown when collapsed (edit tool) */
|
|
30
89
|
DIFF_COLLAPSED_HUNKS: 8,
|
|
31
90
|
/** Max diff lines shown when collapsed (edit tool) */
|
|
32
|
-
DIFF_COLLAPSED_LINES:
|
|
91
|
+
DIFF_COLLAPSED_LINES: 20,
|
|
92
|
+
/** Tail lines for write tool collapsed view */
|
|
93
|
+
WRITE_TAIL: 6,
|
|
94
|
+
/** Streaming preview lines (edit/write) */
|
|
95
|
+
STREAMING_PREVIEW: 6,
|
|
96
|
+
/** Subagent tool history entries when streaming */
|
|
97
|
+
SUBAGENT_STREAMING_TOOLS: 4,
|
|
98
|
+
/** Subagent tool history entries when collapsed */
|
|
99
|
+
SUBAGENT_COLLAPSED_TOOLS: 3,
|
|
100
|
+
/** Subagent conclusion lines when collapsed */
|
|
101
|
+
SUBAGENT_CONCLUSION: 6,
|
|
33
102
|
} as const;
|
|
34
103
|
|
|
35
104
|
/** Truncation lengths for different content types */
|
|
@@ -44,11 +113,12 @@ export const TRUNCATE_LENGTHS = {
|
|
|
44
113
|
LINE: 110,
|
|
45
114
|
/** Very short (task previews, badges) */
|
|
46
115
|
SHORT: 40,
|
|
116
|
+
/** Subagent error messages */
|
|
117
|
+
SUBAGENT_ERROR: 70,
|
|
118
|
+
/** Subagent tool args preview */
|
|
119
|
+
TOOL_ARGS: 50,
|
|
47
120
|
} as const;
|
|
48
121
|
|
|
49
|
-
/** Standard expand hint text */
|
|
50
|
-
export const EXPAND_HINT = "(Ctrl+O for more)";
|
|
51
|
-
|
|
52
122
|
// =============================================================================
|
|
53
123
|
// Text Truncation Utilities
|
|
54
124
|
// =============================================================================
|
|
@@ -167,16 +237,6 @@ export function formatStatusIcon(status: ToolUIStatus, theme: Theme, spinnerFram
|
|
|
167
237
|
}
|
|
168
238
|
}
|
|
169
239
|
|
|
170
|
-
/**
|
|
171
|
-
* Format the expand hint with proper theming.
|
|
172
|
-
* Returns empty string if already expanded or there is nothing more to show.
|
|
173
|
-
*/
|
|
174
|
-
export function formatExpandHint(theme: Theme, expanded?: boolean, hasMore?: boolean): string {
|
|
175
|
-
if (expanded) return "";
|
|
176
|
-
if (hasMore === false) return "";
|
|
177
|
-
return theme.fg("dim", wrapBrackets(EXPAND_HINT, theme));
|
|
178
|
-
}
|
|
179
|
-
|
|
180
240
|
/**
|
|
181
241
|
* Format a badge like [done] or [failed] with brackets and color.
|
|
182
242
|
*/
|
|
@@ -195,16 +255,14 @@ export function formatMoreItems(remaining: number, itemType: string): string {
|
|
|
195
255
|
return `… ${safeRemaining} more ${pluralize(itemType, safeRemaining)}`;
|
|
196
256
|
}
|
|
197
257
|
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
export function
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
export function formatTruncationSuffix(truncated: boolean, theme: Theme): string {
|
|
207
|
-
return truncated ? theme.fg("warning", " (truncated)") : "";
|
|
258
|
+
/**
|
|
259
|
+
* Render a subtle "click to expand" hint for truncated content.
|
|
260
|
+
* Returns empty string if already expanded or nothing to expand.
|
|
261
|
+
*/
|
|
262
|
+
export function formatClickHint(theme: Theme, expanded?: boolean, hasMore?: boolean): string {
|
|
263
|
+
if (expanded) return "";
|
|
264
|
+
if (hasMore === false) return "";
|
|
265
|
+
return theme.fg("dim", wrapBrackets("click to expand", theme));
|
|
208
266
|
}
|
|
209
267
|
|
|
210
268
|
export function formatErrorMessage(message: string | undefined, theme: Theme): string {
|
|
@@ -216,110 +274,13 @@ export function formatEmptyMessage(message: string, theme: Theme): string {
|
|
|
216
274
|
return `${theme.styledSymbol("status.warning", "warning")} ${theme.fg("muted", message)}`;
|
|
217
275
|
}
|
|
218
276
|
|
|
219
|
-
|
|
220
|
-
// Tool UI Kit
|
|
221
|
-
// =============================================================================
|
|
222
|
-
|
|
223
|
-
export type ToolUIStatus = "success" | "error" | "warning" | "info" | "pending" | "running" | "aborted";
|
|
277
|
+
type ToolUIStatus = "success" | "error" | "warning" | "info" | "pending" | "running" | "aborted";
|
|
224
278
|
export type ToolUIColor = "success" | "error" | "warning" | "accent" | "muted";
|
|
225
279
|
|
|
226
|
-
export interface ToolUITitleOptions {
|
|
227
|
-
bold?: boolean;
|
|
228
|
-
}
|
|
229
|
-
|
|
230
280
|
// =============================================================================
|
|
231
281
|
// Diagnostic Formatting
|
|
232
282
|
// =============================================================================
|
|
233
283
|
|
|
234
|
-
export class ToolUIKit {
|
|
235
|
-
constructor(public theme: Theme) {}
|
|
236
|
-
|
|
237
|
-
title(label: string, options?: ToolUITitleOptions): string {
|
|
238
|
-
const content = options?.bold === false ? label : this.theme.bold(label);
|
|
239
|
-
return this.theme.fg("toolTitle", content);
|
|
240
|
-
}
|
|
241
|
-
|
|
242
|
-
meta(meta: string[]): string {
|
|
243
|
-
return formatMeta(meta, this.theme);
|
|
244
|
-
}
|
|
245
|
-
|
|
246
|
-
count(label: string, count: number): string {
|
|
247
|
-
return formatCount(label, count);
|
|
248
|
-
}
|
|
249
|
-
|
|
250
|
-
moreItems(remaining: number, itemType: string): string {
|
|
251
|
-
return formatMoreItems(remaining, itemType);
|
|
252
|
-
}
|
|
253
|
-
|
|
254
|
-
expandHint(expanded: boolean, hasMore: boolean): string {
|
|
255
|
-
return formatExpandHint(this.theme, expanded, hasMore);
|
|
256
|
-
}
|
|
257
|
-
|
|
258
|
-
scope(scopePath?: string): string {
|
|
259
|
-
return formatScope(scopePath, this.theme);
|
|
260
|
-
}
|
|
261
|
-
|
|
262
|
-
truncationSuffix(truncated: boolean): string {
|
|
263
|
-
return formatTruncationSuffix(truncated, this.theme);
|
|
264
|
-
}
|
|
265
|
-
|
|
266
|
-
errorMessage(message: string | undefined): string {
|
|
267
|
-
return formatErrorMessage(message, this.theme);
|
|
268
|
-
}
|
|
269
|
-
|
|
270
|
-
emptyMessage(message: string): string {
|
|
271
|
-
return formatEmptyMessage(message, this.theme);
|
|
272
|
-
}
|
|
273
|
-
|
|
274
|
-
badge(label: string, color: ToolUIColor): string {
|
|
275
|
-
return formatBadge(label, color, this.theme);
|
|
276
|
-
}
|
|
277
|
-
|
|
278
|
-
statusIcon(status: ToolUIStatus, spinnerFrame?: number): string {
|
|
279
|
-
return formatStatusIcon(status, this.theme, spinnerFrame);
|
|
280
|
-
}
|
|
281
|
-
|
|
282
|
-
wrapBrackets(text: string): string {
|
|
283
|
-
return wrapBrackets(text, this.theme);
|
|
284
|
-
}
|
|
285
|
-
|
|
286
|
-
truncate(text: string, maxLen: number): string {
|
|
287
|
-
return truncateToWidth(text, maxLen);
|
|
288
|
-
}
|
|
289
|
-
|
|
290
|
-
previewLines(text: string, maxLines: number, maxLineLen: number): string[] {
|
|
291
|
-
return getPreviewLines(text, maxLines, maxLineLen);
|
|
292
|
-
}
|
|
293
|
-
|
|
294
|
-
formatBytes(bytes: number): string {
|
|
295
|
-
return formatBytes(bytes);
|
|
296
|
-
}
|
|
297
|
-
|
|
298
|
-
formatTokens(tokens: number): string {
|
|
299
|
-
return formatTokens(tokens);
|
|
300
|
-
}
|
|
301
|
-
|
|
302
|
-
formatDuration(ms: number): string {
|
|
303
|
-
return formatDuration(ms);
|
|
304
|
-
}
|
|
305
|
-
|
|
306
|
-
formatAge(ageSeconds: number | null | undefined): string {
|
|
307
|
-
return formatAge(ageSeconds);
|
|
308
|
-
}
|
|
309
|
-
|
|
310
|
-
formatDiagnostics(
|
|
311
|
-
diag: { errored: boolean; summary: string; messages: string[] },
|
|
312
|
-
expanded: boolean,
|
|
313
|
-
getLangIcon: (filePath: string) => string,
|
|
314
|
-
): string {
|
|
315
|
-
return formatDiagnostics(diag, expanded, this.theme, getLangIcon);
|
|
316
|
-
}
|
|
317
|
-
|
|
318
|
-
formatDiffStats(added: number, removed: number, hunks: number): string {
|
|
319
|
-
return formatDiffStats(added, removed, hunks, this.theme);
|
|
320
|
-
}
|
|
321
|
-
}
|
|
322
|
-
|
|
323
284
|
interface ParsedDiagnostic {
|
|
324
285
|
filePath: string;
|
|
325
286
|
line: number;
|
|
@@ -477,7 +438,7 @@ export function formatDiagnostics(
|
|
|
477
438
|
output += `\n ${theme.fg("dim", theme.tree.last)} ${theme.fg(
|
|
478
439
|
"muted",
|
|
479
440
|
`… ${remaining} more`,
|
|
480
|
-
)} ${
|
|
441
|
+
)} ${formatClickHint(theme)}`;
|
|
481
442
|
}
|
|
482
443
|
|
|
483
444
|
return output;
|
|
@@ -40,10 +40,10 @@ export async function openInEditor(
|
|
|
40
40
|
const stdio = options?.stdio ?? ["inherit", "inherit", "inherit"];
|
|
41
41
|
|
|
42
42
|
const child = spawn(editor, [...editorArgs, tmpFile], { stdio });
|
|
43
|
-
const
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
43
|
+
const { promise: exitPromise, resolve, reject } = Promise.withResolvers<number>();
|
|
44
|
+
child.once("exit", (code, signal) => resolve(code ?? (signal ? -1 : 0)));
|
|
45
|
+
child.once("error", error => reject(error));
|
|
46
|
+
const exitCode = await exitPromise;
|
|
47
47
|
|
|
48
48
|
if (exitCode === 0) {
|
|
49
49
|
return (await Bun.file(tmpFile).text()).replace(/\n$/, "");
|
|
@@ -18,7 +18,7 @@ import {
|
|
|
18
18
|
truncateStringToBytesFromStart,
|
|
19
19
|
} from "../session/streaming-output";
|
|
20
20
|
import { resolveReadPath } from "../tools/path-utils";
|
|
21
|
-
import { formatAge } from "../
|
|
21
|
+
import { formatAge } from "../ui/render-utils";
|
|
22
22
|
import { fuzzyMatch } from "./fuzzy";
|
|
23
23
|
import { formatDimensionNote, resizeImage } from "./image-resize";
|
|
24
24
|
import { detectSupportedImageMimeTypeFromFile } from "./mime";
|