@aexol/spectral 0.7.8 → 0.8.2
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/dist/agent/agents.js +4 -4
- package/dist/agent/index.js +8 -8
- package/dist/cli.js +1 -1
- package/dist/commands/serve.js +1 -1
- package/dist/extensions/kanban-bridge.js +668 -0
- package/dist/extensions/spectral-vision-fallback.js +84 -46
- package/dist/mcp/agent-dir.js +1 -1
- package/dist/mcp/config.js +3 -3
- package/dist/mcp/init.js +1 -9
- package/dist/mcp/sampling-handler.js +1 -1
- package/dist/mcp/server-manager.js +5 -1
- package/dist/memory/commands/status.js +1 -1
- package/dist/memory/compaction.js +2 -2
- package/dist/memory/config.js +3 -3
- package/dist/memory/debug-log.js +1 -1
- package/dist/memory/index.js +2 -0
- package/dist/memory/observer.js +2 -2
- package/dist/memory/tokens.js +1 -1
- package/dist/memory/tools/read-project-observations.js +2 -2
- package/dist/memory/tools/recall-observation.js +2 -2
- package/dist/memory/tools/write-project-observation.js +60 -0
- package/dist/relay/auto-research.js +57 -23
- package/dist/relay/dispatcher.js +28 -2
- package/dist/relay/models-fetch.js +2 -2
- package/dist/{pi → sdk}/ai/env-api-keys.js +9 -49
- package/dist/{pi → sdk}/ai/utils/oauth/anthropic.js +1 -1
- package/dist/{pi → sdk}/ai/utils/oauth/openai-codex.js +1 -1
- package/dist/{pi → sdk}/coding-agent/config.js +11 -78
- package/dist/{pi → sdk}/coding-agent/core/agent-session.js +2 -0
- package/dist/{pi → sdk}/coding-agent/core/compaction/compaction.js +161 -5
- package/dist/{pi → sdk}/coding-agent/core/extensions/loader.js +2 -35
- package/dist/{pi → sdk}/coding-agent/core/extensions/runner.js +1 -2
- package/dist/{pi → sdk}/coding-agent/core/model-registry.js +11 -4
- package/dist/sdk/coding-agent/core/model-resolver-utils.js +8 -0
- package/dist/{pi → sdk}/coding-agent/core/model-resolver.js +1 -1
- package/dist/{pi → sdk}/coding-agent/core/package-manager.js +5 -5
- package/dist/{pi → sdk}/coding-agent/core/resource-loader.js +1 -1
- package/dist/{pi → sdk}/coding-agent/core/sdk.js +1 -1
- package/dist/{pi → sdk}/coding-agent/core/session-manager.js +4 -4
- package/dist/{pi → sdk}/coding-agent/core/settings-manager.js +1 -170
- package/dist/{pi → sdk}/coding-agent/core/system-prompt.js +3 -1
- package/dist/{pi → sdk}/coding-agent/core/telemetry.js +1 -1
- package/dist/sdk/coding-agent/core/theme.js +202 -0
- package/dist/{pi → sdk}/coding-agent/core/tools/bash.js +17 -18
- package/dist/{pi → sdk}/coding-agent/core/tools/edit.js +7 -8
- package/dist/{pi → sdk}/coding-agent/core/tools/find.js +9 -13
- package/dist/{pi → sdk}/coding-agent/core/tools/grep.js +10 -14
- package/dist/{pi → sdk}/coding-agent/core/tools/ls.js +9 -10
- package/dist/{pi → sdk}/coding-agent/core/tools/read.js +15 -25
- package/dist/{pi/coding-agent/modes/interactive/components/diff.js → sdk/coding-agent/core/tools/render-diff.js} +18 -31
- package/dist/{pi → sdk}/coding-agent/core/tools/write.js +10 -11
- package/dist/{pi → sdk}/coding-agent/index.js +7 -5
- package/dist/{pi → sdk}/coding-agent/migrations.js +3 -3
- package/dist/{pi → sdk}/coding-agent/modes/index.js +0 -1
- package/dist/{pi → sdk}/coding-agent/modes/rpc/rpc-mode.js +2 -2
- package/dist/{pi → sdk}/coding-agent/utils/photon.js +2 -10
- package/dist/sdk/coding-agent/utils/pi-user-agent.js +3 -0
- package/dist/{pi → sdk}/coding-agent/utils/tools-manager.js +1 -1
- package/dist/{pi → sdk}/coding-agent/utils/version-check.js +2 -2
- package/dist/{pi → sdk}/coding-agent/utils/windows-self-update.js +1 -1
- package/dist/server/{pi-bridge.js → agent-bridge.js} +114 -97
- package/dist/server/handlers/sessions.js +21 -0
- package/dist/server/session-stream.js +5 -5
- package/package.json +6 -3
- package/dist/pi/coding-agent/bun/cli.js +0 -7
- package/dist/pi/coding-agent/bun/restore-sandbox-env.js +0 -31
- package/dist/pi/coding-agent/cli/args.js +0 -340
- package/dist/pi/coding-agent/cli/file-processor.js +0 -82
- package/dist/pi/coding-agent/cli/initial-message.js +0 -21
- package/dist/pi/coding-agent/core/footer-data-provider.js +0 -309
- package/dist/pi/coding-agent/modes/interactive/components/keybinding-hints.js +0 -35
- package/dist/pi/coding-agent/modes/interactive/components/visual-truncate.js +0 -26
- package/dist/pi/coding-agent/modes/interactive/interactive-mode.js +0 -3
- package/dist/pi/coding-agent/modes/interactive/theme/theme.js +0 -1022
- package/dist/pi/coding-agent/utils/pi-user-agent.js +0 -4
- /package/dist/{pi → sdk}/agent-core/agent-loop.js +0 -0
- /package/dist/{pi → sdk}/agent-core/agent.js +0 -0
- /package/dist/{pi → sdk}/agent-core/harness/agent-harness.js +0 -0
- /package/dist/{pi → sdk}/agent-core/harness/compaction/branch-summarization.js +0 -0
- /package/dist/{pi → sdk}/agent-core/harness/compaction/compaction.js +0 -0
- /package/dist/{pi → sdk}/agent-core/harness/compaction/utils.js +0 -0
- /package/dist/{pi → sdk}/agent-core/harness/env/nodejs.js +0 -0
- /package/dist/{pi → sdk}/agent-core/harness/messages.js +0 -0
- /package/dist/{pi → sdk}/agent-core/harness/prompt-templates.js +0 -0
- /package/dist/{pi → sdk}/agent-core/harness/session/jsonl-repo.js +0 -0
- /package/dist/{pi → sdk}/agent-core/harness/session/jsonl-storage.js +0 -0
- /package/dist/{pi → sdk}/agent-core/harness/session/memory-repo.js +0 -0
- /package/dist/{pi → sdk}/agent-core/harness/session/memory-storage.js +0 -0
- /package/dist/{pi → sdk}/agent-core/harness/session/repo-utils.js +0 -0
- /package/dist/{pi → sdk}/agent-core/harness/session/session.js +0 -0
- /package/dist/{pi → sdk}/agent-core/harness/session/uuid.js +0 -0
- /package/dist/{pi → sdk}/agent-core/harness/skills.js +0 -0
- /package/dist/{pi → sdk}/agent-core/harness/system-prompt.js +0 -0
- /package/dist/{pi → sdk}/agent-core/harness/types.js +0 -0
- /package/dist/{pi → sdk}/agent-core/harness/utils/shell-output.js +0 -0
- /package/dist/{pi → sdk}/agent-core/harness/utils/truncate.js +0 -0
- /package/dist/{pi → sdk}/agent-core/index.js +0 -0
- /package/dist/{pi → sdk}/agent-core/node.js +0 -0
- /package/dist/{pi → sdk}/agent-core/proxy.js +0 -0
- /package/dist/{pi → sdk}/agent-core/types.js +0 -0
- /package/dist/{pi → sdk}/ai/api-registry.js +0 -0
- /package/dist/{pi → sdk}/ai/cli.js +0 -0
- /package/dist/{pi → sdk}/ai/image-models.generated.js +0 -0
- /package/dist/{pi → sdk}/ai/image-models.js +0 -0
- /package/dist/{pi → sdk}/ai/images-api-registry.js +0 -0
- /package/dist/{pi → sdk}/ai/images.js +0 -0
- /package/dist/{pi → sdk}/ai/index.js +0 -0
- /package/dist/{pi → sdk}/ai/models.generated.js +0 -0
- /package/dist/{pi → sdk}/ai/models.js +0 -0
- /package/dist/{pi → sdk}/ai/oauth.js +0 -0
- /package/dist/{pi → sdk}/ai/providers/anthropic.js +0 -0
- /package/dist/{pi → sdk}/ai/providers/faux.js +0 -0
- /package/dist/{pi → sdk}/ai/providers/github-copilot-headers.js +0 -0
- /package/dist/{pi → sdk}/ai/providers/openai-completions.js +0 -0
- /package/dist/{pi → sdk}/ai/providers/openai-prompt-cache.js +0 -0
- /package/dist/{pi → sdk}/ai/providers/register-builtins.js +0 -0
- /package/dist/{pi → sdk}/ai/providers/simple-options.js +0 -0
- /package/dist/{pi → sdk}/ai/providers/transform-messages.js +0 -0
- /package/dist/{pi → sdk}/ai/session-resources.js +0 -0
- /package/dist/{pi → sdk}/ai/stream.js +0 -0
- /package/dist/{pi → sdk}/ai/types.js +0 -0
- /package/dist/{pi → sdk}/ai/utils/diagnostics.js +0 -0
- /package/dist/{pi → sdk}/ai/utils/event-stream.js +0 -0
- /package/dist/{pi → sdk}/ai/utils/hash.js +0 -0
- /package/dist/{pi → sdk}/ai/utils/headers.js +0 -0
- /package/dist/{pi → sdk}/ai/utils/json-parse.js +0 -0
- /package/dist/{pi → sdk}/ai/utils/node-http-proxy.js +0 -0
- /package/dist/{pi → sdk}/ai/utils/oauth/device-code.js +0 -0
- /package/dist/{pi → sdk}/ai/utils/oauth/github-copilot.js +0 -0
- /package/dist/{pi → sdk}/ai/utils/oauth/index.js +0 -0
- /package/dist/{pi → sdk}/ai/utils/oauth/oauth-page.js +0 -0
- /package/dist/{pi → sdk}/ai/utils/oauth/pkce.js +0 -0
- /package/dist/{pi → sdk}/ai/utils/oauth/types.js +0 -0
- /package/dist/{pi → sdk}/ai/utils/overflow.js +0 -0
- /package/dist/{pi → sdk}/ai/utils/sanitize-unicode.js +0 -0
- /package/dist/{pi → sdk}/ai/utils/typebox-helpers.js +0 -0
- /package/dist/{pi → sdk}/ai/utils/validation.js +0 -0
- /package/dist/{pi → sdk}/coding-agent/cli.js +0 -0
- /package/dist/{pi → sdk}/coding-agent/core/agent-session-runtime.js +0 -0
- /package/dist/{pi → sdk}/coding-agent/core/agent-session-services.js +0 -0
- /package/dist/{pi → sdk}/coding-agent/core/auth-guidance.js +0 -0
- /package/dist/{pi → sdk}/coding-agent/core/auth-storage.js +0 -0
- /package/dist/{pi → sdk}/coding-agent/core/bash-executor.js +0 -0
- /package/dist/{pi → sdk}/coding-agent/core/compaction/branch-summarization.js +0 -0
- /package/dist/{pi → sdk}/coding-agent/core/compaction/index.js +0 -0
- /package/dist/{pi → sdk}/coding-agent/core/compaction/utils.js +0 -0
- /package/dist/{pi → sdk}/coding-agent/core/defaults.js +0 -0
- /package/dist/{pi → sdk}/coding-agent/core/diagnostics.js +0 -0
- /package/dist/{pi → sdk}/coding-agent/core/event-bus.js +0 -0
- /package/dist/{pi → sdk}/coding-agent/core/exec.js +0 -0
- /package/dist/{pi → sdk}/coding-agent/core/extensions/index.js +0 -0
- /package/dist/{pi → sdk}/coding-agent/core/extensions/types.js +0 -0
- /package/dist/{pi → sdk}/coding-agent/core/extensions/wrapper.js +0 -0
- /package/dist/{pi → sdk}/coding-agent/core/http-dispatcher.js +0 -0
- /package/dist/{pi → sdk}/coding-agent/core/index.js +0 -0
- /package/dist/{pi → sdk}/coding-agent/core/keybindings.js +0 -0
- /package/dist/{pi → sdk}/coding-agent/core/messages.js +0 -0
- /package/dist/{pi → sdk}/coding-agent/core/output-guard.js +0 -0
- /package/dist/{pi → sdk}/coding-agent/core/prompt-templates.js +0 -0
- /package/dist/{pi → sdk}/coding-agent/core/provider-display-names.js +0 -0
- /package/dist/{pi → sdk}/coding-agent/core/resolve-config-value.js +0 -0
- /package/dist/{pi → sdk}/coding-agent/core/session-cwd.js +0 -0
- /package/dist/{pi → sdk}/coding-agent/core/skills.js +0 -0
- /package/dist/{pi → sdk}/coding-agent/core/slash-commands.js +0 -0
- /package/dist/{pi → sdk}/coding-agent/core/source-info.js +0 -0
- /package/dist/{pi → sdk}/coding-agent/core/timings.js +0 -0
- /package/dist/{pi → sdk}/coding-agent/core/tools/edit-diff.js +0 -0
- /package/dist/{pi → sdk}/coding-agent/core/tools/file-mutation-queue.js +0 -0
- /package/dist/{pi → sdk}/coding-agent/core/tools/index.js +0 -0
- /package/dist/{pi → sdk}/coding-agent/core/tools/output-accumulator.js +0 -0
- /package/dist/{pi → sdk}/coding-agent/core/tools/path-utils.js +0 -0
- /package/dist/{pi → sdk}/coding-agent/core/tools/render-utils.js +0 -0
- /package/dist/{pi → sdk}/coding-agent/core/tools/tool-definition-wrapper.js +0 -0
- /package/dist/{pi → sdk}/coding-agent/core/tools/truncate.js +0 -0
- /package/dist/{pi → sdk}/coding-agent/main.js +0 -0
- /package/dist/{pi → sdk}/coding-agent/modes/print-mode.js +0 -0
- /package/dist/{pi → sdk}/coding-agent/modes/rpc/jsonl.js +0 -0
- /package/dist/{pi → sdk}/coding-agent/modes/rpc/rpc-client.js +0 -0
- /package/dist/{pi → sdk}/coding-agent/modes/rpc/rpc-types.js +0 -0
- /package/dist/{pi → sdk}/coding-agent/utils/ansi.js +0 -0
- /package/dist/{pi → sdk}/coding-agent/utils/changelog.js +0 -0
- /package/dist/{pi → sdk}/coding-agent/utils/child-process.js +0 -0
- /package/dist/{pi → sdk}/coding-agent/utils/clipboard-image.js +0 -0
- /package/dist/{pi → sdk}/coding-agent/utils/clipboard-native.js +0 -0
- /package/dist/{pi → sdk}/coding-agent/utils/clipboard.js +0 -0
- /package/dist/{pi → sdk}/coding-agent/utils/exif-orientation.js +0 -0
- /package/dist/{pi → sdk}/coding-agent/utils/frontmatter.js +0 -0
- /package/dist/{pi → sdk}/coding-agent/utils/fs-watch.js +0 -0
- /package/dist/{pi → sdk}/coding-agent/utils/git.js +0 -0
- /package/dist/{pi → sdk}/coding-agent/utils/html.js +0 -0
- /package/dist/{pi → sdk}/coding-agent/utils/image-convert.js +0 -0
- /package/dist/{pi → sdk}/coding-agent/utils/image-resize.js +0 -0
- /package/dist/{pi → sdk}/coding-agent/utils/mime.js +0 -0
- /package/dist/{pi → sdk}/coding-agent/utils/paths.js +0 -0
- /package/dist/{pi → sdk}/coding-agent/utils/shell.js +0 -0
- /package/dist/{pi → sdk}/coding-agent/utils/sleep.js +0 -0
- /package/dist/{pi → sdk}/coding-agent/utils/syntax-highlight.js +0 -0
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Minimal shared theme for syntax highlighting and extension API compatibility.
|
|
3
|
+
*
|
|
4
|
+
* This replaces the interactive/mode TUI theme system with a stripped-down
|
|
5
|
+
* version that supports the core utilities used by the serve/relay path:
|
|
6
|
+
* - getLanguageFromPath(): maps file extensions to highlight.js language IDs
|
|
7
|
+
* - highlightCode(): syntax-highlights code blocks
|
|
8
|
+
* - loadThemeFromPath(): loads a theme JSON file from disk
|
|
9
|
+
* - Theme class: used by resource-loader and extension types
|
|
10
|
+
*
|
|
11
|
+
* All ANSI color formatting (theme.fg(), theme.bold(), etc.) is removed —
|
|
12
|
+
* tool output is plain text for LLM consumption in serve/relay mode.
|
|
13
|
+
*/
|
|
14
|
+
import * as fs from "node:fs";
|
|
15
|
+
import { highlight, supportsLanguage } from "../utils/syntax-highlight.js";
|
|
16
|
+
// ============================================================================
|
|
17
|
+
// Language detection
|
|
18
|
+
// ============================================================================
|
|
19
|
+
const extToLang = {
|
|
20
|
+
ts: "typescript",
|
|
21
|
+
tsx: "typescript",
|
|
22
|
+
js: "javascript",
|
|
23
|
+
jsx: "javascript",
|
|
24
|
+
mjs: "javascript",
|
|
25
|
+
cjs: "javascript",
|
|
26
|
+
py: "python",
|
|
27
|
+
rb: "ruby",
|
|
28
|
+
rs: "rust",
|
|
29
|
+
go: "go",
|
|
30
|
+
java: "java",
|
|
31
|
+
kt: "kotlin",
|
|
32
|
+
swift: "swift",
|
|
33
|
+
c: "c",
|
|
34
|
+
h: "c",
|
|
35
|
+
cpp: "cpp",
|
|
36
|
+
cc: "cpp",
|
|
37
|
+
cxx: "cpp",
|
|
38
|
+
hpp: "cpp",
|
|
39
|
+
cs: "csharp",
|
|
40
|
+
php: "php",
|
|
41
|
+
sh: "bash",
|
|
42
|
+
bash: "bash",
|
|
43
|
+
zsh: "bash",
|
|
44
|
+
fish: "fish",
|
|
45
|
+
ps1: "powershell",
|
|
46
|
+
sql: "sql",
|
|
47
|
+
html: "html",
|
|
48
|
+
htm: "html",
|
|
49
|
+
css: "css",
|
|
50
|
+
scss: "scss",
|
|
51
|
+
sass: "sass",
|
|
52
|
+
less: "less",
|
|
53
|
+
json: "json",
|
|
54
|
+
yaml: "yaml",
|
|
55
|
+
yml: "yaml",
|
|
56
|
+
toml: "toml",
|
|
57
|
+
xml: "xml",
|
|
58
|
+
md: "markdown",
|
|
59
|
+
markdown: "markdown",
|
|
60
|
+
dockerfile: "dockerfile",
|
|
61
|
+
makefile: "makefile",
|
|
62
|
+
cmake: "cmake",
|
|
63
|
+
lua: "lua",
|
|
64
|
+
perl: "perl",
|
|
65
|
+
r: "r",
|
|
66
|
+
scala: "scala",
|
|
67
|
+
clj: "clojure",
|
|
68
|
+
ex: "elixir",
|
|
69
|
+
exs: "elixir",
|
|
70
|
+
erl: "erlang",
|
|
71
|
+
hs: "haskell",
|
|
72
|
+
ml: "ocaml",
|
|
73
|
+
vim: "vim",
|
|
74
|
+
graphql: "graphql",
|
|
75
|
+
proto: "protobuf",
|
|
76
|
+
tf: "hcl",
|
|
77
|
+
hcl: "hcl",
|
|
78
|
+
};
|
|
79
|
+
export function getLanguageFromPath(filePath) {
|
|
80
|
+
const ext = filePath.split(".").pop()?.toLowerCase();
|
|
81
|
+
if (!ext)
|
|
82
|
+
return undefined;
|
|
83
|
+
return extToLang[ext];
|
|
84
|
+
}
|
|
85
|
+
// ============================================================================
|
|
86
|
+
// Syntax highlighting
|
|
87
|
+
// ============================================================================
|
|
88
|
+
/** Identity formatter — returns text as-is (no ANSI styling in serve mode). */
|
|
89
|
+
function identity(text) {
|
|
90
|
+
return text;
|
|
91
|
+
}
|
|
92
|
+
const neutralHighlightTheme = {
|
|
93
|
+
keyword: identity,
|
|
94
|
+
built_in: identity,
|
|
95
|
+
literal: identity,
|
|
96
|
+
number: identity,
|
|
97
|
+
string: identity,
|
|
98
|
+
comment: identity,
|
|
99
|
+
function: identity,
|
|
100
|
+
title: identity,
|
|
101
|
+
class: identity,
|
|
102
|
+
type: identity,
|
|
103
|
+
attr: identity,
|
|
104
|
+
variable: identity,
|
|
105
|
+
params: identity,
|
|
106
|
+
operator: identity,
|
|
107
|
+
punctuation: identity,
|
|
108
|
+
};
|
|
109
|
+
/**
|
|
110
|
+
* Highlight code with syntax coloring based on file extension or language.
|
|
111
|
+
* In serve mode, returns plain text (no ANSI coloring for LLM consumption).
|
|
112
|
+
*/
|
|
113
|
+
export function highlightCode(code, lang) {
|
|
114
|
+
const validLang = lang && supportsLanguage(lang) ? lang : undefined;
|
|
115
|
+
if (!validLang) {
|
|
116
|
+
return code.split("\n");
|
|
117
|
+
}
|
|
118
|
+
try {
|
|
119
|
+
return highlight(code, {
|
|
120
|
+
language: validLang,
|
|
121
|
+
ignoreIllegals: true,
|
|
122
|
+
theme: neutralHighlightTheme,
|
|
123
|
+
}).split("\n");
|
|
124
|
+
}
|
|
125
|
+
catch {
|
|
126
|
+
return code.split("\n");
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
// ============================================================================
|
|
130
|
+
// Theme loading (for resource-loader)
|
|
131
|
+
// ============================================================================
|
|
132
|
+
/** Resolve built-in theme directory using config path helpers. */
|
|
133
|
+
function getThemesDir() {
|
|
134
|
+
try {
|
|
135
|
+
// This function is exported from config.ts and uses the actual package directory
|
|
136
|
+
const { getThemesDir: fn } = require("../../config.js");
|
|
137
|
+
return fn();
|
|
138
|
+
}
|
|
139
|
+
catch {
|
|
140
|
+
// Fallback: themes were in modes/interactive/theme/, try to find them
|
|
141
|
+
try {
|
|
142
|
+
const { join } = require("node:path");
|
|
143
|
+
const { existsSync } = require("node:fs");
|
|
144
|
+
const packageDir = join(__dirname, "../../..");
|
|
145
|
+
for (const base of ["src", "dist"]) {
|
|
146
|
+
const candidates = [
|
|
147
|
+
join(packageDir, base, "modes", "interactive", "theme"),
|
|
148
|
+
];
|
|
149
|
+
for (const dir of candidates) {
|
|
150
|
+
if (existsSync(dir))
|
|
151
|
+
return dir;
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
catch {
|
|
156
|
+
// ignore
|
|
157
|
+
}
|
|
158
|
+
return __dirname;
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
function getBuiltinThemes() {
|
|
162
|
+
const themesDir = getThemesDir();
|
|
163
|
+
if (!themesDir)
|
|
164
|
+
return {};
|
|
165
|
+
try {
|
|
166
|
+
const { join } = require("node:path");
|
|
167
|
+
const { readFileSync } = require("node:fs");
|
|
168
|
+
return {
|
|
169
|
+
dark: JSON.parse(readFileSync(join(themesDir, "dark.json"), "utf-8")),
|
|
170
|
+
light: JSON.parse(readFileSync(join(themesDir, "light.json"), "utf-8")),
|
|
171
|
+
};
|
|
172
|
+
}
|
|
173
|
+
catch {
|
|
174
|
+
return {};
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
export function loadThemeFromPath(themePath) {
|
|
178
|
+
const content = fs.readFileSync(themePath, "utf-8");
|
|
179
|
+
const json = JSON.parse(content);
|
|
180
|
+
return {
|
|
181
|
+
name: json.name,
|
|
182
|
+
sourcePath: themePath,
|
|
183
|
+
};
|
|
184
|
+
}
|
|
185
|
+
// ============================================================================
|
|
186
|
+
// Registered themes (for extension API compatibility)
|
|
187
|
+
// ============================================================================
|
|
188
|
+
const registeredThemes = new Map();
|
|
189
|
+
export function setRegisteredThemes(themes) {
|
|
190
|
+
registeredThemes.clear();
|
|
191
|
+
for (const t of themes) {
|
|
192
|
+
if (t.name) {
|
|
193
|
+
registeredThemes.set(t.name, t);
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
export function getAvailableThemes() {
|
|
198
|
+
return Array.from(new Set([
|
|
199
|
+
...Object.keys(getBuiltinThemes()),
|
|
200
|
+
...registeredThemes.keys(),
|
|
201
|
+
])).sort();
|
|
202
|
+
}
|
|
@@ -1,12 +1,10 @@
|
|
|
1
1
|
import { existsSync } from "node:fs";
|
|
2
2
|
import { spawn } from "child_process";
|
|
3
3
|
import { Type } from "typebox";
|
|
4
|
-
import { keyHint } from "../../modes/interactive/components/keybinding-hints.js";
|
|
5
|
-
import { theme } from "../../modes/interactive/theme/theme.js";
|
|
6
4
|
import { waitForChildProcess } from "../../utils/child-process.js";
|
|
7
5
|
import { getShellConfig, getShellEnv, killProcessTree, trackDetachedChildPid, untrackDetachedChildPid, } from "../../utils/shell.js";
|
|
8
6
|
import { OutputAccumulator } from "./output-accumulator.js";
|
|
9
|
-
import { getTextOutput,
|
|
7
|
+
import { getTextOutput, str } from "./render-utils.js";
|
|
10
8
|
import { wrapToolDefinition } from "./tool-definition-wrapper.js";
|
|
11
9
|
import { DEFAULT_MAX_BYTES, DEFAULT_MAX_LINES, formatSize } from "./truncate.js";
|
|
12
10
|
const bashSchema = Type.Object({
|
|
@@ -103,12 +101,17 @@ const BASH_UPDATE_THROTTLE_MS = 100;
|
|
|
103
101
|
function formatDuration(ms) {
|
|
104
102
|
return `${(ms / 1000).toFixed(1)}s`;
|
|
105
103
|
}
|
|
104
|
+
function plainText(s) { return s; }
|
|
105
|
+
const noopTheme = {
|
|
106
|
+
fg: (_name, text) => text,
|
|
107
|
+
bold: plainText,
|
|
108
|
+
};
|
|
106
109
|
function formatBashCall(args) {
|
|
107
110
|
const command = str(args?.command);
|
|
108
111
|
const timeout = args?.timeout;
|
|
109
|
-
const timeoutSuffix = timeout ?
|
|
110
|
-
const commandDisplay = command === null ?
|
|
111
|
-
return
|
|
112
|
+
const timeoutSuffix = timeout ? ` (timeout ${timeout}s)` : "";
|
|
113
|
+
const commandDisplay = command === null ? "[invalid]" : command || "...";
|
|
114
|
+
return `$ ${commandDisplay}${timeoutSuffix}`;
|
|
112
115
|
}
|
|
113
116
|
function formatBashResult(result, options, showImages, startedAt, endedAt) {
|
|
114
117
|
let output = getTextOutput(result, showImages).trim();
|
|
@@ -122,24 +125,20 @@ function formatBashResult(result, options, showImages, startedAt, endedAt) {
|
|
|
122
125
|
}
|
|
123
126
|
const parts = [];
|
|
124
127
|
if (output) {
|
|
125
|
-
const styledOutput = output
|
|
126
|
-
.split("\n")
|
|
127
|
-
.map((line) => theme.fg("toolOutput", line))
|
|
128
|
-
.join("\n");
|
|
129
128
|
if (options.expanded) {
|
|
130
|
-
parts.push(`\n${
|
|
129
|
+
parts.push(`\n${output}`);
|
|
131
130
|
}
|
|
132
131
|
else {
|
|
133
|
-
const
|
|
134
|
-
if (
|
|
135
|
-
const hint =
|
|
132
|
+
const lines = output.split("\n");
|
|
133
|
+
if (lines.length > BASH_PREVIEW_LINES) {
|
|
134
|
+
const hint = `... (${lines.length - BASH_PREVIEW_LINES} earlier lines)`;
|
|
136
135
|
parts.push("");
|
|
137
136
|
parts.push(hint);
|
|
138
|
-
parts.push(...
|
|
137
|
+
parts.push(...lines.slice(-BASH_PREVIEW_LINES));
|
|
139
138
|
}
|
|
140
139
|
else {
|
|
141
140
|
parts.push("");
|
|
142
|
-
parts.push(...
|
|
141
|
+
parts.push(...lines);
|
|
143
142
|
}
|
|
144
143
|
}
|
|
145
144
|
}
|
|
@@ -156,12 +155,12 @@ function formatBashResult(result, options, showImages, startedAt, endedAt) {
|
|
|
156
155
|
warnings.push(`Truncated: ${truncation.outputLines} lines shown (${formatSize(truncation.maxBytes ?? DEFAULT_MAX_BYTES)} limit)`);
|
|
157
156
|
}
|
|
158
157
|
}
|
|
159
|
-
parts.push(`\n
|
|
158
|
+
parts.push(`\n[${warnings.join(". ")}]`);
|
|
160
159
|
}
|
|
161
160
|
if (startedAt !== undefined) {
|
|
162
161
|
const label = options.isPartial ? "Elapsed" : "Took";
|
|
163
162
|
const endTime = endedAt ?? Date.now();
|
|
164
|
-
parts.push(`\n${
|
|
163
|
+
parts.push(`\n${label} ${formatDuration(endTime - startedAt)}`);
|
|
165
164
|
}
|
|
166
165
|
return parts.join("");
|
|
167
166
|
}
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { constants } from "fs";
|
|
2
2
|
import { access as fsAccess, readFile as fsReadFile, writeFile as fsWriteFile } from "fs/promises";
|
|
3
3
|
import { Type } from "typebox";
|
|
4
|
-
import { renderDiff } from "
|
|
4
|
+
import { renderDiff } from "./render-diff.js";
|
|
5
5
|
import { applyEditsToNormalizedContent, detectLineEnding, generateDiffString, generateUnifiedPatch, normalizeToLF, restoreLineEndings, stripBom, } from "./edit-diff.js";
|
|
6
6
|
import { withFileMutationQueue } from "./file-mutation-queue.js";
|
|
7
7
|
import { resolveToCwd } from "./path-utils.js";
|
|
8
|
-
import {
|
|
8
|
+
import { shortenPath, str } from "./render-utils.js";
|
|
9
9
|
import { wrapToolDefinition } from "./tool-definition-wrapper.js";
|
|
10
10
|
const replaceEditSchema = Type.Object({
|
|
11
11
|
oldText: Type.String({
|
|
@@ -53,14 +53,13 @@ function validateEditInput(input) {
|
|
|
53
53
|
}
|
|
54
54
|
return { path: input.path, edits: input.edits };
|
|
55
55
|
}
|
|
56
|
-
function formatEditCall(args,
|
|
57
|
-
const invalidArg = invalidArgText(theme);
|
|
56
|
+
function formatEditCall(args, _theme) {
|
|
58
57
|
const rawPath = str(args?.file_path ?? args?.path);
|
|
59
58
|
const path = rawPath !== null ? shortenPath(rawPath) : null;
|
|
60
|
-
const pathDisplay = path === null ?
|
|
61
|
-
return
|
|
59
|
+
const pathDisplay = path === null ? "[invalid]" : path || "...";
|
|
60
|
+
return `edit ${pathDisplay}`;
|
|
62
61
|
}
|
|
63
|
-
function formatEditResult(args, result,
|
|
62
|
+
function formatEditResult(args, result, _theme, isError) {
|
|
64
63
|
const rawPath = str(args?.file_path ?? args?.path);
|
|
65
64
|
if (isError) {
|
|
66
65
|
const errorText = result.content
|
|
@@ -70,7 +69,7 @@ function formatEditResult(args, result, theme, isError) {
|
|
|
70
69
|
if (!errorText) {
|
|
71
70
|
return undefined;
|
|
72
71
|
}
|
|
73
|
-
return
|
|
72
|
+
return errorText;
|
|
74
73
|
}
|
|
75
74
|
const resultDiff = result.details?.diff;
|
|
76
75
|
if (resultDiff) {
|
|
@@ -3,10 +3,9 @@ import { spawn } from "child_process";
|
|
|
3
3
|
import { existsSync } from "fs";
|
|
4
4
|
import path from "path";
|
|
5
5
|
import { Type } from "typebox";
|
|
6
|
-
import { keyHint } from "../../modes/interactive/components/keybinding-hints.js";
|
|
7
6
|
import { ensureTool } from "../../utils/tools-manager.js";
|
|
8
7
|
import { resolveToCwd } from "./path-utils.js";
|
|
9
|
-
import { getTextOutput,
|
|
8
|
+
import { getTextOutput, shortenPath, str } from "./render-utils.js";
|
|
10
9
|
import { wrapToolDefinition } from "./tool-definition-wrapper.js";
|
|
11
10
|
import { DEFAULT_MAX_BYTES, formatSize, truncateHead } from "./truncate.js";
|
|
12
11
|
function toPosixPath(value) {
|
|
@@ -25,22 +24,19 @@ const defaultFindOperations = {
|
|
|
25
24
|
// This is a placeholder. Actual fd execution happens in execute() when no custom glob is provided.
|
|
26
25
|
glob: () => [],
|
|
27
26
|
};
|
|
28
|
-
function formatFindCall(args,
|
|
27
|
+
function formatFindCall(args, _theme) {
|
|
29
28
|
const pattern = str(args?.pattern);
|
|
30
29
|
const rawPath = str(args?.path);
|
|
31
30
|
const path = rawPath !== null ? shortenPath(rawPath || ".") : null;
|
|
32
31
|
const limit = args?.limit;
|
|
33
|
-
const invalidArg =
|
|
34
|
-
let text =
|
|
35
|
-
" " +
|
|
36
|
-
(pattern === null ? invalidArg : theme.fg("accent", pattern || "")) +
|
|
37
|
-
theme.fg("toolOutput", ` in ${path === null ? invalidArg : path}`);
|
|
32
|
+
const invalidArg = "[invalid]";
|
|
33
|
+
let text = `find ${pattern === null ? invalidArg : pattern || ""} in ${path === null ? invalidArg : path}`;
|
|
38
34
|
if (limit !== undefined) {
|
|
39
|
-
text +=
|
|
35
|
+
text += ` (limit ${limit})`;
|
|
40
36
|
}
|
|
41
37
|
return text;
|
|
42
38
|
}
|
|
43
|
-
function formatFindResult(result, options,
|
|
39
|
+
function formatFindResult(result, options, _theme, showImages) {
|
|
44
40
|
const output = getTextOutput(result, showImages).trim();
|
|
45
41
|
let text = "";
|
|
46
42
|
if (output) {
|
|
@@ -48,9 +44,9 @@ function formatFindResult(result, options, theme, showImages) {
|
|
|
48
44
|
const maxLines = options.expanded ? lines.length : 20;
|
|
49
45
|
const displayLines = lines.slice(0, maxLines);
|
|
50
46
|
const remaining = lines.length - maxLines;
|
|
51
|
-
text += `\n${displayLines.
|
|
47
|
+
text += `\n${displayLines.join("\n")}`;
|
|
52
48
|
if (remaining > 0) {
|
|
53
|
-
text +=
|
|
49
|
+
text += `\n... (${remaining} more lines)`;
|
|
54
50
|
}
|
|
55
51
|
}
|
|
56
52
|
const resultLimit = result.details?.resultLimitReached;
|
|
@@ -61,7 +57,7 @@ function formatFindResult(result, options, theme, showImages) {
|
|
|
61
57
|
warnings.push(`${resultLimit} results limit`);
|
|
62
58
|
if (truncation?.truncated)
|
|
63
59
|
warnings.push(`${formatSize(truncation.maxBytes ?? DEFAULT_MAX_BYTES)} limit`);
|
|
64
|
-
text += `\n
|
|
60
|
+
text += `\n[Truncated: ${warnings.join(", ")}]`;
|
|
65
61
|
}
|
|
66
62
|
return text;
|
|
67
63
|
}
|
|
@@ -3,10 +3,9 @@ import { spawn } from "child_process";
|
|
|
3
3
|
import { readFileSync, statSync } from "fs";
|
|
4
4
|
import path from "path";
|
|
5
5
|
import { Type } from "typebox";
|
|
6
|
-
import { keyHint } from "../../modes/interactive/components/keybinding-hints.js";
|
|
7
6
|
import { ensureTool } from "../../utils/tools-manager.js";
|
|
8
7
|
import { resolveToCwd } from "./path-utils.js";
|
|
9
|
-
import { getTextOutput,
|
|
8
|
+
import { getTextOutput, shortenPath, str } from "./render-utils.js";
|
|
10
9
|
import { wrapToolDefinition } from "./tool-definition-wrapper.js";
|
|
11
10
|
import { DEFAULT_MAX_BYTES, formatSize, GREP_MAX_LINE_LENGTH, truncateHead, truncateLine, } from "./truncate.js";
|
|
12
11
|
const grepSchema = Type.Object({
|
|
@@ -23,24 +22,21 @@ const defaultGrepOperations = {
|
|
|
23
22
|
isDirectory: (p) => statSync(p).isDirectory(),
|
|
24
23
|
readFile: (p) => readFileSync(p, "utf-8"),
|
|
25
24
|
};
|
|
26
|
-
function formatGrepCall(args,
|
|
25
|
+
function formatGrepCall(args, _theme) {
|
|
27
26
|
const pattern = str(args?.pattern);
|
|
28
27
|
const rawPath = str(args?.path);
|
|
29
28
|
const path = rawPath !== null ? shortenPath(rawPath || ".") : null;
|
|
30
29
|
const glob = str(args?.glob);
|
|
31
30
|
const limit = args?.limit;
|
|
32
|
-
const invalidArg =
|
|
33
|
-
let text =
|
|
34
|
-
" " +
|
|
35
|
-
(pattern === null ? invalidArg : theme.fg("accent", `/${pattern || ""}/`)) +
|
|
36
|
-
theme.fg("toolOutput", ` in ${path === null ? invalidArg : path}`);
|
|
31
|
+
const invalidArg = "[invalid]";
|
|
32
|
+
let text = `grep ${pattern === null ? invalidArg : `/${pattern || ""}/`} in ${path === null ? invalidArg : path}`;
|
|
37
33
|
if (glob)
|
|
38
|
-
text +=
|
|
34
|
+
text += ` (${glob})`;
|
|
39
35
|
if (limit !== undefined)
|
|
40
|
-
text +=
|
|
36
|
+
text += ` limit ${limit}`;
|
|
41
37
|
return text;
|
|
42
38
|
}
|
|
43
|
-
function formatGrepResult(result, options,
|
|
39
|
+
function formatGrepResult(result, options, _theme, showImages) {
|
|
44
40
|
const output = getTextOutput(result, showImages).trim();
|
|
45
41
|
let text = "";
|
|
46
42
|
if (output) {
|
|
@@ -48,9 +44,9 @@ function formatGrepResult(result, options, theme, showImages) {
|
|
|
48
44
|
const maxLines = options.expanded ? lines.length : 15;
|
|
49
45
|
const displayLines = lines.slice(0, maxLines);
|
|
50
46
|
const remaining = lines.length - maxLines;
|
|
51
|
-
text += `\n${displayLines.
|
|
47
|
+
text += `\n${displayLines.join("\n")}`;
|
|
52
48
|
if (remaining > 0) {
|
|
53
|
-
text +=
|
|
49
|
+
text += `\n... (${remaining} more lines)`;
|
|
54
50
|
}
|
|
55
51
|
}
|
|
56
52
|
const matchLimit = result.details?.matchLimitReached;
|
|
@@ -64,7 +60,7 @@ function formatGrepResult(result, options, theme, showImages) {
|
|
|
64
60
|
warnings.push(`${formatSize(truncation.maxBytes ?? DEFAULT_MAX_BYTES)} limit`);
|
|
65
61
|
if (linesTruncated)
|
|
66
62
|
warnings.push("some lines truncated");
|
|
67
|
-
text += `\n
|
|
63
|
+
text += `\n[Truncated: ${warnings.join(", ")}]`;
|
|
68
64
|
}
|
|
69
65
|
return text;
|
|
70
66
|
}
|
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
import { existsSync, readdirSync, statSync } from "fs";
|
|
2
2
|
import nodePath from "path";
|
|
3
3
|
import { Type } from "typebox";
|
|
4
|
-
import { keyHint } from "../../modes/interactive/components/keybinding-hints.js";
|
|
5
4
|
import { resolveToCwd } from "./path-utils.js";
|
|
6
|
-
import { getTextOutput,
|
|
5
|
+
import { getTextOutput, shortenPath, str } from "./render-utils.js";
|
|
7
6
|
import { wrapToolDefinition } from "./tool-definition-wrapper.js";
|
|
8
7
|
import { DEFAULT_MAX_BYTES, formatSize, truncateHead } from "./truncate.js";
|
|
9
8
|
const lsSchema = Type.Object({
|
|
@@ -16,18 +15,18 @@ const defaultLsOperations = {
|
|
|
16
15
|
stat: statSync,
|
|
17
16
|
readdir: readdirSync,
|
|
18
17
|
};
|
|
19
|
-
function formatLsCall(args,
|
|
18
|
+
function formatLsCall(args, _theme) {
|
|
20
19
|
const rawPath = str(args?.path);
|
|
21
20
|
const path = rawPath !== null ? shortenPath(rawPath || ".") : null;
|
|
22
21
|
const limit = args?.limit;
|
|
23
|
-
const invalidArg =
|
|
24
|
-
let text =
|
|
22
|
+
const invalidArg = "[invalid]";
|
|
23
|
+
let text = `ls ${path === null ? invalidArg : path}`;
|
|
25
24
|
if (limit !== undefined) {
|
|
26
|
-
text +=
|
|
25
|
+
text += ` (limit ${limit})`;
|
|
27
26
|
}
|
|
28
27
|
return text;
|
|
29
28
|
}
|
|
30
|
-
function formatLsResult(result, options,
|
|
29
|
+
function formatLsResult(result, options, _theme, showImages) {
|
|
31
30
|
const output = getTextOutput(result, showImages).trim();
|
|
32
31
|
let text = "";
|
|
33
32
|
if (output) {
|
|
@@ -35,9 +34,9 @@ function formatLsResult(result, options, theme, showImages) {
|
|
|
35
34
|
const maxLines = options.expanded ? lines.length : 20;
|
|
36
35
|
const displayLines = lines.slice(0, maxLines);
|
|
37
36
|
const remaining = lines.length - maxLines;
|
|
38
|
-
text += `\n${displayLines.
|
|
37
|
+
text += `\n${displayLines.join("\n")}`;
|
|
39
38
|
if (remaining > 0) {
|
|
40
|
-
text +=
|
|
39
|
+
text += `\n... (${remaining} more lines)`;
|
|
41
40
|
}
|
|
42
41
|
}
|
|
43
42
|
const entryLimit = result.details?.entryLimitReached;
|
|
@@ -48,7 +47,7 @@ function formatLsResult(result, options, theme, showImages) {
|
|
|
48
47
|
warnings.push(`${entryLimit} entries limit`);
|
|
49
48
|
if (truncation?.truncated)
|
|
50
49
|
warnings.push(`${formatSize(truncation.maxBytes ?? DEFAULT_MAX_BYTES)} limit`);
|
|
51
|
-
text += `\n
|
|
50
|
+
text += `\n[Truncated: ${warnings.join(", ")}]`;
|
|
52
51
|
}
|
|
53
52
|
return text;
|
|
54
53
|
}
|
|
@@ -3,13 +3,12 @@ import { constants } from "fs";
|
|
|
3
3
|
import { access as fsAccess, readFile as fsReadFile } from "fs/promises";
|
|
4
4
|
import { Type } from "typebox";
|
|
5
5
|
import { getReadmePath } from "../../config.js";
|
|
6
|
-
import {
|
|
7
|
-
import { getLanguageFromPath, highlightCode } from "../../modes/interactive/theme/theme.js";
|
|
6
|
+
import { getLanguageFromPath, highlightCode } from "../theme.js";
|
|
8
7
|
import { formatDimensionNote, resizeImage } from "../../utils/image-resize.js";
|
|
9
8
|
import { detectSupportedImageMimeTypeFromFile } from "../../utils/mime.js";
|
|
10
9
|
import { formatPathRelativeToCwdOrAbsolute } from "../../utils/paths.js";
|
|
11
10
|
import { resolveReadPath } from "./path-utils.js";
|
|
12
|
-
import { getTextOutput,
|
|
11
|
+
import { getTextOutput, replaceTabs, shortenPath, str } from "./render-utils.js";
|
|
13
12
|
import { wrapToolDefinition } from "./tool-definition-wrapper.js";
|
|
14
13
|
import { DEFAULT_MAX_BYTES, DEFAULT_MAX_LINES, formatSize, truncateHead } from "./truncate.js";
|
|
15
14
|
const readSchema = Type.Object({
|
|
@@ -23,19 +22,18 @@ const defaultReadOperations = {
|
|
|
23
22
|
access: (path) => fsAccess(path, constants.R_OK),
|
|
24
23
|
detectImageMimeType: detectSupportedImageMimeTypeFromFile,
|
|
25
24
|
};
|
|
26
|
-
function formatReadLineRange(args,
|
|
25
|
+
function formatReadLineRange(args, _theme) {
|
|
27
26
|
if (args?.offset === undefined && args?.limit === undefined)
|
|
28
27
|
return "";
|
|
29
28
|
const startLine = args.offset ?? 1;
|
|
30
29
|
const endLine = args.limit !== undefined ? startLine + args.limit - 1 : "";
|
|
31
|
-
return
|
|
30
|
+
return `:${startLine}${endLine ? `-${endLine}` : ""}`;
|
|
32
31
|
}
|
|
33
|
-
function formatReadCall(args,
|
|
32
|
+
function formatReadCall(args, _theme) {
|
|
34
33
|
const rawPath = str(args?.file_path ?? args?.path);
|
|
35
34
|
const path = rawPath !== null ? shortenPath(rawPath) : null;
|
|
36
|
-
const
|
|
37
|
-
|
|
38
|
-
return `${theme.fg("toolTitle", theme.bold("read"))} ${pathDisplay}${formatReadLineRange(args, theme)}`;
|
|
35
|
+
const pathDisplay = path === null ? "[invalid]" : path || "...";
|
|
36
|
+
return `read ${pathDisplay}${formatReadLineRange(args)}`;
|
|
39
37
|
}
|
|
40
38
|
function trimTrailingEmptyLines(lines) {
|
|
41
39
|
let end = lines.length;
|
|
@@ -85,19 +83,11 @@ function getCompactReadClassification(args, cwd) {
|
|
|
85
83
|
}
|
|
86
84
|
return undefined;
|
|
87
85
|
}
|
|
88
|
-
function formatCompactReadCall(classification, args,
|
|
89
|
-
const expandHint = theme.fg("dim", ` (${keyText("app.tools.expand")} to expand)`);
|
|
86
|
+
function formatCompactReadCall(classification, args, _theme) {
|
|
90
87
|
if (classification.kind === "skill") {
|
|
91
|
-
return
|
|
92
|
-
theme.fg("customMessageText", classification.label) +
|
|
93
|
-
formatReadLineRange(args, theme) +
|
|
94
|
-
expandHint);
|
|
88
|
+
return `[skill] ${classification.label}${formatReadLineRange(args)}`;
|
|
95
89
|
}
|
|
96
|
-
return
|
|
97
|
-
" " +
|
|
98
|
-
theme.fg("accent", classification.label) +
|
|
99
|
-
formatReadLineRange(args, theme) +
|
|
100
|
-
expandHint);
|
|
90
|
+
return `read ${classification.kind} ${classification.label}${formatReadLineRange(args)}`;
|
|
101
91
|
}
|
|
102
92
|
function formatReadResult(args, result, options, theme, showImages, cwd, isError) {
|
|
103
93
|
if (!options.expanded && !isError && getCompactReadClassification(args, cwd)) {
|
|
@@ -111,20 +101,20 @@ function formatReadResult(args, result, options, theme, showImages, cwd, isError
|
|
|
111
101
|
const maxLines = options.expanded ? lines.length : 10;
|
|
112
102
|
const displayLines = lines.slice(0, maxLines);
|
|
113
103
|
const remaining = lines.length - maxLines;
|
|
114
|
-
let text = `\n${displayLines.map((line) =>
|
|
104
|
+
let text = `\n${displayLines.map((line) => replaceTabs(line)).join("\n")}`;
|
|
115
105
|
if (remaining > 0) {
|
|
116
|
-
text +=
|
|
106
|
+
text += `\n... (${remaining} more lines)`;
|
|
117
107
|
}
|
|
118
108
|
const truncation = result.details?.truncation;
|
|
119
109
|
if (truncation?.truncated) {
|
|
120
110
|
if (truncation.firstLineExceedsLimit) {
|
|
121
|
-
text += `\n
|
|
111
|
+
text += `\n[First line exceeds ${formatSize(truncation.maxBytes ?? DEFAULT_MAX_BYTES)} limit]`;
|
|
122
112
|
}
|
|
123
113
|
else if (truncation.truncatedBy === "lines") {
|
|
124
|
-
text += `\n
|
|
114
|
+
text += `\n[Truncated: showing ${truncation.outputLines} of ${truncation.totalLines} lines (${truncation.maxLines ?? DEFAULT_MAX_LINES} line limit)]`;
|
|
125
115
|
}
|
|
126
116
|
else {
|
|
127
|
-
text += `\n
|
|
117
|
+
text += `\n[Truncated: ${truncation.outputLines} lines shown (${formatSize(truncation.maxBytes ?? DEFAULT_MAX_BYTES)} limit)]`;
|
|
128
118
|
}
|
|
129
119
|
}
|
|
130
120
|
return text;
|