@oh-my-pi/pi-coding-agent 16.0.4 → 16.0.6
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 +94 -0
- package/dist/cli.js +2027 -1396
- package/dist/types/advisor/advise-tool.d.ts +31 -19
- package/dist/types/autoresearch/tools/init-experiment.d.ts +13 -17
- package/dist/types/autoresearch/tools/log-experiment.d.ts +17 -19
- package/dist/types/autoresearch/tools/run-experiment.d.ts +3 -4
- package/dist/types/autoresearch/tools/update-notes.d.ts +4 -5
- package/dist/types/cli/args.d.ts +1 -0
- package/dist/types/cli/bench-cli.d.ts +6 -0
- package/dist/types/cli/ttsr-cli.d.ts +39 -0
- package/dist/types/commands/launch.d.ts +3 -0
- package/dist/types/commands/ttsr.d.ts +57 -0
- package/dist/types/commit/agentic/tools/analyze-file.d.ts +4 -5
- package/dist/types/commit/agentic/tools/git-file-diff.d.ts +4 -5
- package/dist/types/commit/agentic/tools/git-hunk.d.ts +5 -6
- package/dist/types/commit/agentic/tools/git-overview.d.ts +4 -5
- package/dist/types/commit/agentic/tools/propose-changelog.d.ts +23 -24
- package/dist/types/commit/agentic/tools/propose-commit.d.ts +11 -32
- package/dist/types/commit/agentic/tools/recent-commits.d.ts +3 -4
- package/dist/types/commit/agentic/tools/schemas.d.ts +6 -27
- package/dist/types/commit/agentic/tools/split-commit.d.ts +28 -49
- package/dist/types/commit/changelog/generate.d.ts +12 -13
- package/dist/types/commit/shared-llm.d.ts +10 -37
- package/dist/types/config/config-file.d.ts +4 -4
- package/dist/types/config/keybindings.d.ts +5 -0
- package/dist/types/config/models-config-schema.d.ts +625 -990
- package/dist/types/config/models-config.d.ts +229 -217
- package/dist/types/config/settings-schema.d.ts +144 -25
- package/dist/types/edit/hashline/params.d.ts +7 -11
- package/dist/types/edit/index.d.ts +2 -1
- package/dist/types/edit/modes/apply-patch.d.ts +4 -5
- package/dist/types/edit/modes/patch.d.ts +15 -24
- package/dist/types/edit/modes/replace.d.ts +16 -17
- package/dist/types/eval/js/index.d.ts +1 -0
- package/dist/types/extensibility/custom-commands/types.d.ts +6 -3
- package/dist/types/extensibility/custom-tools/types.d.ts +8 -5
- package/dist/types/extensibility/extensions/runner.d.ts +5 -2
- package/dist/types/extensibility/extensions/types.d.ts +14 -10
- package/dist/types/extensibility/hooks/types.d.ts +7 -4
- package/dist/types/extensibility/legacy-pi-ai-shim.d.ts +13 -5
- package/dist/types/extensibility/legacy-pi-coding-agent-shim.d.ts +17 -0
- package/dist/types/extensibility/shared-events.d.ts +22 -1
- package/dist/types/extensibility/typebox.d.ts +80 -58
- package/dist/types/goals/tools/goal-tool.d.ts +11 -24
- package/dist/types/index.d.ts +2 -0
- package/dist/types/lsp/index.d.ts +11 -26
- package/dist/types/lsp/types.d.ts +12 -28
- package/dist/types/main.d.ts +1 -0
- package/dist/types/mcp/client.d.ts +8 -0
- package/dist/types/modes/components/btw-panel.d.ts +1 -0
- package/dist/types/modes/components/custom-editor.d.ts +3 -1
- package/dist/types/modes/components/status-line/component.d.ts +1 -1
- package/dist/types/modes/components/status-line/context-thresholds.d.ts +0 -1
- package/dist/types/modes/controllers/btw-controller.d.ts +2 -0
- package/dist/types/modes/controllers/input-controller.d.ts +1 -0
- package/dist/types/modes/interactive-mode.d.ts +3 -0
- package/dist/types/modes/rpc/rpc-types.d.ts +1 -1
- package/dist/types/modes/setup-wizard/index.d.ts +1 -0
- package/dist/types/modes/setup-wizard/startup-splash.d.ts +7 -0
- package/dist/types/modes/theme/theme.d.ts +1 -1
- package/dist/types/modes/types.d.ts +3 -0
- package/dist/types/modes/utils/context-usage.d.ts +12 -0
- package/dist/types/sdk.d.ts +8 -1
- package/dist/types/session/agent-session.d.ts +24 -0
- package/dist/types/session/session-persistence.d.ts +4 -0
- package/dist/types/startup-splash.d.ts +12 -0
- package/dist/types/task/types.d.ts +47 -48
- package/dist/types/tools/ask.d.ts +26 -27
- package/dist/types/tools/ast-edit.d.ts +17 -17
- package/dist/types/tools/ast-grep.d.ts +12 -13
- package/dist/types/tools/bash.d.ts +20 -17
- package/dist/types/tools/browser.d.ts +46 -71
- package/dist/types/tools/checkpoint.d.ts +14 -15
- package/dist/types/tools/debug.d.ts +82 -145
- package/dist/types/tools/eval.d.ts +30 -40
- package/dist/types/tools/find.d.ts +17 -18
- package/dist/types/tools/gh.d.ts +49 -78
- package/dist/types/tools/image-gen.d.ts +20 -36
- package/dist/types/tools/inspect-image.d.ts +10 -11
- package/dist/types/tools/irc.d.ts +22 -33
- package/dist/types/tools/job.d.ts +11 -12
- package/dist/types/tools/learn.d.ts +21 -28
- package/dist/types/tools/manage-skill.d.ts +13 -22
- package/dist/types/tools/memory-edit.d.ts +15 -24
- package/dist/types/tools/memory-recall.d.ts +7 -8
- package/dist/types/tools/memory-reflect.d.ts +9 -10
- package/dist/types/tools/memory-retain.d.ts +13 -14
- package/dist/types/tools/read.d.ts +8 -8
- package/dist/types/tools/resolve.d.ts +11 -18
- package/dist/types/tools/review.d.ts +9 -15
- package/dist/types/tools/search-tool-bm25.d.ts +9 -10
- package/dist/types/tools/search.d.ts +16 -17
- package/dist/types/tools/ssh.d.ts +14 -15
- package/dist/types/tools/todo.d.ts +27 -43
- package/dist/types/tools/tts.d.ts +8 -9
- package/dist/types/tools/write.d.ts +9 -10
- package/dist/types/tui/code-cell.d.ts +2 -0
- package/dist/types/tui/index.d.ts +1 -0
- package/dist/types/tui/width-aware-text.d.ts +23 -0
- package/dist/types/utils/image-vision-fallback.d.ts +28 -0
- package/dist/types/utils/markit.d.ts +10 -1
- package/dist/types/web/search/index.d.ts +17 -28
- package/dist/types/web/search/providers/base.d.ts +1 -0
- package/dist/types/web/search/providers/gemini.d.ts +1 -0
- package/dist/types/web/search/providers/perplexity.d.ts +0 -2
- package/dist/types/web/search/types.d.ts +32 -26
- package/package.json +14 -13
- package/scripts/omp +1 -1
- package/src/advisor/__tests__/advisor.test.ts +103 -1
- package/src/advisor/advise-tool.ts +47 -11
- package/src/autoresearch/tools/init-experiment.ts +13 -16
- package/src/autoresearch/tools/log-experiment.ts +15 -18
- package/src/autoresearch/tools/run-experiment.ts +3 -3
- package/src/autoresearch/tools/update-notes.ts +4 -4
- package/src/cli/args.ts +1 -0
- package/src/cli/bench-cli.ts +30 -7
- package/src/cli/flag-tables.ts +8 -0
- package/src/cli/ttsr-cli.ts +995 -0
- package/src/cli-commands.ts +1 -0
- package/src/cli.ts +7 -1
- package/src/collab/host.ts +2 -2
- package/src/commands/launch.ts +3 -0
- package/src/commands/ttsr.ts +125 -0
- package/src/commit/agentic/tools/analyze-file.ts +4 -4
- package/src/commit/agentic/tools/git-file-diff.ts +4 -4
- package/src/commit/agentic/tools/git-hunk.ts +7 -5
- package/src/commit/agentic/tools/git-overview.ts +4 -4
- package/src/commit/agentic/tools/propose-changelog.ts +18 -15
- package/src/commit/agentic/tools/propose-commit.ts +6 -6
- package/src/commit/agentic/tools/recent-commits.ts +3 -3
- package/src/commit/agentic/tools/schemas.ts +8 -20
- package/src/commit/agentic/tools/split-commit.ts +19 -23
- package/src/commit/analysis/summary.ts +7 -5
- package/src/commit/changelog/generate.ts +15 -11
- package/src/commit/shared-llm.ts +17 -24
- package/src/config/config-file.ts +13 -15
- package/src/config/keybindings.ts +6 -0
- package/src/config/models-config-schema.ts +206 -179
- package/src/config/settings-schema.ts +118 -2
- package/src/discovery/builtin-rules/index.ts +2 -0
- package/src/discovery/builtin-rules/ts-import-type.md +2 -2
- package/src/discovery/builtin-rules/ts-no-any.md +11 -2
- package/src/discovery/builtin-rules/ts-no-inline-cast-access.md +55 -0
- package/src/edit/hashline/params.ts +12 -11
- package/src/edit/index.ts +5 -4
- package/src/edit/modes/apply-patch.ts +4 -4
- package/src/edit/modes/patch.ts +15 -18
- package/src/edit/modes/replace.ts +13 -17
- package/src/edit/renderer.ts +0 -1
- package/src/eval/agent-bridge.ts +11 -13
- package/src/eval/completion-bridge.ts +25 -17
- package/src/eval/js/context-manager.ts +17 -2
- package/src/eval/js/index.ts +1 -1
- package/src/eval/py/executor.ts +2 -2
- package/src/eval/py/runner.py +44 -0
- package/src/extensibility/custom-commands/loader.ts +5 -3
- package/src/extensibility/custom-commands/types.ts +6 -3
- package/src/extensibility/custom-tools/loader.ts +4 -2
- package/src/extensibility/custom-tools/types.ts +8 -5
- package/src/extensibility/extensions/loader.ts +4 -2
- package/src/extensibility/extensions/runner.ts +20 -2
- package/src/extensibility/extensions/types.ts +22 -8
- package/src/extensibility/hooks/loader.ts +5 -2
- package/src/extensibility/hooks/types.ts +7 -4
- package/src/extensibility/legacy-pi-ai-shim.ts +42 -5
- package/src/extensibility/legacy-pi-coding-agent-shim.ts +113 -0
- package/src/extensibility/plugins/legacy-pi-compat.ts +13 -13
- package/src/extensibility/shared-events.ts +24 -0
- package/src/extensibility/tool-proxy.ts +4 -1
- package/src/extensibility/typebox.ts +778 -251
- package/src/goals/guided-setup.ts +12 -3
- package/src/goals/tools/goal-tool.ts +6 -6
- package/src/index.ts +2 -0
- package/src/internal-urls/docs-index.generated.ts +15 -13
- package/src/lsp/types.ts +13 -27
- package/src/main.ts +29 -21
- package/src/mcp/client.ts +38 -13
- package/src/mcp/render.ts +102 -89
- package/src/modes/components/agent-hub.ts +11 -4
- package/src/modes/components/branch-summary-message.ts +1 -0
- package/src/modes/components/btw-panel.ts +5 -1
- package/src/modes/components/collab-prompt-message.ts +9 -7
- package/src/modes/components/compaction-summary-message.ts +1 -0
- package/src/modes/components/custom-editor.ts +18 -0
- package/src/modes/components/custom-message.ts +1 -0
- package/src/modes/components/footer.ts +6 -5
- package/src/modes/components/hook-message.ts +1 -0
- package/src/modes/components/read-tool-group.ts +9 -3
- package/src/modes/components/skill-message.ts +1 -0
- package/src/modes/components/status-line/component.ts +139 -15
- package/src/modes/components/status-line/context-thresholds.ts +0 -1
- package/src/modes/components/todo-reminder.ts +1 -0
- package/src/modes/components/tool-execution.ts +17 -10
- package/src/modes/components/ttsr-notification.ts +1 -0
- package/src/modes/components/user-message.ts +6 -6
- package/src/modes/controllers/btw-controller.ts +69 -1
- package/src/modes/controllers/event-controller.ts +2 -7
- package/src/modes/controllers/input-controller.ts +29 -0
- package/src/modes/controllers/selector-controller.ts +10 -3
- package/src/modes/interactive-mode.ts +42 -10
- package/src/modes/rpc/rpc-types.ts +1 -1
- package/src/modes/setup-wizard/index.ts +1 -0
- package/src/modes/setup-wizard/scenes/sign-in.ts +77 -5
- package/src/modes/setup-wizard/startup-splash.ts +107 -0
- package/src/modes/theme/theme.ts +133 -143
- package/src/modes/types.ts +3 -0
- package/src/modes/utils/context-usage.ts +37 -20
- package/src/modes/utils/hotkeys-markdown.ts +1 -0
- package/src/prompts/system/system-prompt.md +1 -0
- package/src/prompts/tools/image-attachment-describe-system.md +8 -0
- package/src/prompts/tools/image-attachment-describe.md +10 -0
- package/src/sdk.ts +35 -22
- package/src/session/agent-session.ts +715 -255
- package/src/session/session-history-format.ts +11 -2
- package/src/session/session-loader.ts +19 -32
- package/src/session/session-persistence.ts +27 -11
- package/src/session/snapcompact-inline.ts +1 -1
- package/src/slash-commands/builtin-registry.ts +4 -11
- package/src/ssh/connection-manager.ts +3 -2
- package/src/startup-splash.ts +19 -0
- package/src/task/executor.ts +12 -7
- package/src/task/types.ts +44 -41
- package/src/tool-discovery/tool-index.ts +17 -4
- package/src/tools/ask.ts +14 -14
- package/src/tools/ast-edit.ts +17 -14
- package/src/tools/ast-grep.ts +10 -9
- package/src/tools/bash.ts +15 -10
- package/src/tools/browser/launch.ts +13 -0
- package/src/tools/browser.ts +26 -32
- package/src/tools/checkpoint.ts +7 -7
- package/src/tools/debug.ts +72 -69
- package/src/tools/eval.ts +18 -19
- package/src/tools/find.ts +20 -13
- package/src/tools/gh.ts +29 -49
- package/src/tools/image-gen.ts +94 -57
- package/src/tools/inspect-image.ts +8 -9
- package/src/tools/irc.ts +12 -12
- package/src/tools/job.ts +6 -6
- package/src/tools/learn.ts +11 -14
- package/src/tools/manage-skill.ts +19 -23
- package/src/tools/memory-edit.ts +8 -8
- package/src/tools/memory-recall.ts +4 -4
- package/src/tools/memory-reflect.ts +5 -5
- package/src/tools/memory-retain.ts +9 -11
- package/src/tools/puppeteer/02_stealth_hairline.txt +1 -1
- package/src/tools/puppeteer/04_stealth_iframe.txt +4 -4
- package/src/tools/puppeteer/05_stealth_webgl.txt +1 -1
- package/src/tools/puppeteer/10_stealth_plugins.txt +6 -4
- package/src/tools/puppeteer/12_stealth_codecs.txt +2 -2
- package/src/tools/puppeteer/13_stealth_worker.txt +1 -1
- package/src/tools/read.ts +197 -19
- package/src/tools/report-tool-issue.ts +6 -6
- package/src/tools/resolve.ts +6 -6
- package/src/tools/review.ts +10 -12
- package/src/tools/search-tool-bm25.ts +5 -5
- package/src/tools/search.ts +20 -29
- package/src/tools/ssh.ts +8 -8
- package/src/tools/todo.ts +16 -19
- package/src/tools/tts.ts +16 -15
- package/src/tools/write.ts +5 -5
- package/src/tui/code-cell.ts +44 -3
- package/src/tui/index.ts +1 -0
- package/src/tui/width-aware-text.ts +58 -0
- package/src/utils/image-vision-fallback.ts +197 -0
- package/src/utils/markit.ts +17 -2
- package/src/web/search/index.ts +21 -9
- package/src/web/search/providers/base.ts +1 -0
- package/src/web/search/providers/gemini.ts +56 -18
- package/src/web/search/providers/perplexity.ts +373 -126
- package/src/web/search/types.ts +28 -48
|
@@ -4,6 +4,7 @@ import { stripVTControlCharacters } from "node:util";
|
|
|
4
4
|
import { ThinkingLevel } from "@oh-my-pi/pi-agent-core";
|
|
5
5
|
import { type Component, padding, truncateToWidth, visibleWidth } from "@oh-my-pi/pi-tui";
|
|
6
6
|
import { formatNumber, getProjectDir } from "@oh-my-pi/pi-utils";
|
|
7
|
+
import { settings } from "../../config/settings";
|
|
7
8
|
import { theme } from "../../modes/theme/theme";
|
|
8
9
|
import type { AgentSession } from "../../session/agent-session";
|
|
9
10
|
import { shortenPath } from "../../tools/render-utils";
|
|
@@ -58,6 +59,8 @@ export class FooterComponent implements Component {
|
|
|
58
59
|
this.#gitWatcher = null;
|
|
59
60
|
}
|
|
60
61
|
|
|
62
|
+
if (!settings.get("git.enabled")) return;
|
|
63
|
+
|
|
61
64
|
void git.head
|
|
62
65
|
.resolve(getProjectDir())
|
|
63
66
|
.then(head => {
|
|
@@ -102,6 +105,7 @@ export class FooterComponent implements Component {
|
|
|
102
105
|
* Returns null if not in a git repo, branch name otherwise.
|
|
103
106
|
*/
|
|
104
107
|
#getCurrentBranch(): string | null {
|
|
108
|
+
if (!settings.get("git.enabled")) return null;
|
|
105
109
|
if (this.#cachedBranch !== undefined) {
|
|
106
110
|
return this.#cachedBranch;
|
|
107
111
|
}
|
|
@@ -182,11 +186,8 @@ export class FooterComponent implements Component {
|
|
|
182
186
|
// Colorize context percentage based on usage
|
|
183
187
|
let contextPercentStr: string;
|
|
184
188
|
const autoIndicator = this.#autoCompactEnabled ? " (auto)" : "";
|
|
185
|
-
const contextPercentDisplay = `${formatContextUsage(
|
|
186
|
-
|
|
187
|
-
contextWindow,
|
|
188
|
-
)}${autoIndicator}`;
|
|
189
|
-
if (contextUsage?.percent !== null && contextUsage?.percent !== undefined) {
|
|
189
|
+
const contextPercentDisplay = `${formatContextUsage(contextPercentValue, contextWindow)}${autoIndicator}`;
|
|
190
|
+
if (contextUsage) {
|
|
190
191
|
const color = getContextUsageThemeColor(getContextUsageLevel(contextPercentValue, contextWindow));
|
|
191
192
|
contextPercentStr =
|
|
192
193
|
color === "statusLineContext" ? contextPercentDisplay : theme.fg(color, contextPercentDisplay);
|
|
@@ -57,6 +57,7 @@ type ReadToolResultDetails = {
|
|
|
57
57
|
displayContent?: {
|
|
58
58
|
text?: string;
|
|
59
59
|
startLine?: number;
|
|
60
|
+
lineNumbers?: Array<number | null>;
|
|
60
61
|
};
|
|
61
62
|
meta?: {
|
|
62
63
|
source?: {
|
|
@@ -86,6 +87,8 @@ type ReadEntry = {
|
|
|
86
87
|
correctedFrom?: string;
|
|
87
88
|
contentText?: string;
|
|
88
89
|
conflictCount?: number;
|
|
90
|
+
codeStartLine?: number;
|
|
91
|
+
codeLineNumbers?: Array<number | null>;
|
|
89
92
|
};
|
|
90
93
|
|
|
91
94
|
/** Number of code lines to show in collapsed preview mode */
|
|
@@ -379,11 +382,12 @@ export class ReadToolGroupComponent extends Container implements ToolExecutionHa
|
|
|
379
382
|
entry.status = result.isError ? "error" : suffixResolution ? "warning" : "success";
|
|
380
383
|
// Store clean display content for preview/expanded display when the read
|
|
381
384
|
// tool provides it; fall back to model-facing text for legacy results.
|
|
382
|
-
const displayContent =
|
|
383
|
-
typeof details?.displayContent?.text === "string" ? details.displayContent.text : undefined;
|
|
385
|
+
const displayContent = details?.displayContent;
|
|
384
386
|
const textContent = result.content?.find(c => c.type === "text")?.text;
|
|
385
387
|
if (displayContent !== undefined || textContent !== undefined) {
|
|
386
|
-
entry.contentText = displayContent ?? textContent;
|
|
388
|
+
entry.contentText = displayContent?.text ?? textContent;
|
|
389
|
+
entry.codeStartLine = displayContent?.startLine;
|
|
390
|
+
entry.codeLineNumbers = displayContent?.lineNumbers;
|
|
387
391
|
}
|
|
388
392
|
this.#updateDisplay();
|
|
389
393
|
}
|
|
@@ -636,6 +640,8 @@ export class ReadToolGroupComponent extends Container implements ToolExecutionHa
|
|
|
636
640
|
status: entry.status === "success" ? "complete" : entry.status,
|
|
637
641
|
expanded,
|
|
638
642
|
codeMaxLines: expanded ? undefined : COLLAPSED_PREVIEW_LINES,
|
|
643
|
+
codeStartLine: entry.codeStartLine,
|
|
644
|
+
codeLineNumbers: entry.codeLineNumbers,
|
|
639
645
|
width,
|
|
640
646
|
},
|
|
641
647
|
theme,
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import * as fs from "node:fs";
|
|
2
2
|
import * as path from "node:path";
|
|
3
3
|
import type { AgentMessage } from "@oh-my-pi/pi-agent-core";
|
|
4
|
+
import type { AssistantMessage } from "@oh-my-pi/pi-ai";
|
|
4
5
|
import { type Component, truncateToWidth, visibleWidth } from "@oh-my-pi/pi-tui";
|
|
5
6
|
import { getProjectDir } from "@oh-my-pi/pi-utils";
|
|
6
7
|
import { $ } from "bun";
|
|
@@ -55,21 +56,70 @@ function messageFingerprint(msg: AgentMessage): string {
|
|
|
55
56
|
}
|
|
56
57
|
}
|
|
57
58
|
} else if (role === "assistant") {
|
|
59
|
+
const assistantMsg = msg as AssistantMessage;
|
|
60
|
+
const usageExt = assistantMsg.usage as unknown as { promptTokensDetails?: unknown };
|
|
61
|
+
const usageTotal = assistantMsg.usage?.totalTokens ?? 0;
|
|
62
|
+
const promptBuckets = usageExt?.promptTokensDetails ? 1 : 0;
|
|
63
|
+
const stopReason = assistantMsg.stopReason ?? "";
|
|
64
|
+
|
|
65
|
+
let signatureLen = 0;
|
|
66
|
+
let redactedLen = 0;
|
|
67
|
+
const msgExt = assistantMsg as unknown as {
|
|
68
|
+
thinkingSignature?: string;
|
|
69
|
+
textSignature?: string;
|
|
70
|
+
thoughtSignature?: string;
|
|
71
|
+
redactedThinking?: { data?: string };
|
|
72
|
+
};
|
|
73
|
+
const thinkingSignature = msgExt.thinkingSignature;
|
|
74
|
+
if (typeof thinkingSignature === "string") {
|
|
75
|
+
signatureLen += thinkingSignature.length;
|
|
76
|
+
}
|
|
77
|
+
const textSignature = msgExt.textSignature;
|
|
78
|
+
if (typeof textSignature === "string") {
|
|
79
|
+
signatureLen += textSignature.length;
|
|
80
|
+
}
|
|
81
|
+
const thoughtSignature = msgExt.thoughtSignature;
|
|
82
|
+
if (typeof thoughtSignature === "string") {
|
|
83
|
+
signatureLen += thoughtSignature.length;
|
|
84
|
+
}
|
|
85
|
+
const redactedData = msgExt.redactedThinking?.data;
|
|
86
|
+
if (typeof redactedData === "string") {
|
|
87
|
+
redactedLen += redactedData.length;
|
|
88
|
+
}
|
|
89
|
+
|
|
58
90
|
const content = (msg as { content?: unknown }).content;
|
|
59
91
|
if (Array.isArray(content)) {
|
|
60
92
|
blocks = content.length;
|
|
61
93
|
for (const block of content) {
|
|
62
94
|
if (!block || typeof block !== "object") continue;
|
|
63
|
-
const b = block as {
|
|
95
|
+
const b = block as {
|
|
96
|
+
type?: string;
|
|
97
|
+
text?: string;
|
|
98
|
+
thinking?: string;
|
|
99
|
+
thinkingSignature?: string;
|
|
100
|
+
signature?: string;
|
|
101
|
+
textSignature?: string;
|
|
102
|
+
thoughtSignature?: string;
|
|
103
|
+
data?: string;
|
|
104
|
+
name?: string;
|
|
105
|
+
arguments?: unknown;
|
|
106
|
+
};
|
|
64
107
|
if (b.type === "text" && typeof b.text === "string") textLen += b.text.length;
|
|
65
|
-
else if (b.type === "thinking"
|
|
66
|
-
|
|
108
|
+
else if (b.type === "thinking") {
|
|
109
|
+
if (typeof b.thinking === "string") textLen += b.thinking.length;
|
|
110
|
+
if (typeof b.thinkingSignature === "string") signatureLen += b.thinkingSignature.length;
|
|
111
|
+
if (typeof b.signature === "string") signatureLen += b.signature.length;
|
|
112
|
+
if (typeof b.textSignature === "string") signatureLen += b.textSignature.length;
|
|
113
|
+
if (typeof b.thoughtSignature === "string") signatureLen += b.thoughtSignature.length;
|
|
114
|
+
} else if (b.type === "redactedThinking" && typeof b.data === "string") {
|
|
115
|
+
redactedLen += b.data.length;
|
|
116
|
+
} else if (b.type === "toolCall") {
|
|
67
117
|
if (typeof b.name === "string") textLen += b.name.length;
|
|
68
|
-
// Argument bytes vary; a length proxy is enough to detect in-place edits.
|
|
69
118
|
textLen += b.arguments === undefined ? 0 : JSON.stringify(b.arguments).length;
|
|
70
119
|
}
|
|
71
120
|
}
|
|
72
121
|
}
|
|
122
|
+
return `${role}:${ts}:${textLen}:${blocks}:${images}:${signatureLen}:${redactedLen}:${usageTotal}:${promptBuckets}:${stopReason}`;
|
|
73
123
|
} else if (role === "toolResult" || role === "hookMessage") {
|
|
74
124
|
const content = (msg as { content?: unknown }).content;
|
|
75
125
|
if (typeof content === "string") {
|
|
@@ -95,8 +145,12 @@ interface ContextUsageMemo {
|
|
|
95
145
|
length: number;
|
|
96
146
|
lastFingerprint: string | undefined;
|
|
97
147
|
modelContextWindow: number;
|
|
98
|
-
|
|
148
|
+
contextUsageRevision: number;
|
|
149
|
+
usedTokens: number;
|
|
99
150
|
contextWindow: number;
|
|
151
|
+
systemPromptRef: readonly string[] | undefined;
|
|
152
|
+
toolsRef: readonly any[] | undefined;
|
|
153
|
+
skillsRef: readonly any[] | undefined;
|
|
100
154
|
}
|
|
101
155
|
|
|
102
156
|
const EMPTY_MESSAGES: readonly AgentMessage[] = [];
|
|
@@ -104,6 +158,16 @@ const EMPTY_MESSAGES: readonly AgentMessage[] = [];
|
|
|
104
158
|
function hasContextSegment(segments: readonly StatusLineSegmentId[]): boolean {
|
|
105
159
|
return segments.includes("context_pct") || segments.includes("context_total");
|
|
106
160
|
}
|
|
161
|
+
function hasGitSegment(segments: readonly StatusLineSegmentId[]): boolean {
|
|
162
|
+
return segments.includes("git");
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
function hasPrSegment(segments: readonly StatusLineSegmentId[]): boolean {
|
|
166
|
+
return segments.includes("pr");
|
|
167
|
+
}
|
|
168
|
+
function hasGitBackedSegment(segments: readonly StatusLineSegmentId[]): boolean {
|
|
169
|
+
return hasGitSegment(segments) || hasPrSegment(segments);
|
|
170
|
+
}
|
|
107
171
|
|
|
108
172
|
// ═══════════════════════════════════════════════════════════════════════════
|
|
109
173
|
// StatusLineComponent
|
|
@@ -117,6 +181,7 @@ export class StatusLineComponent implements Component {
|
|
|
117
181
|
#cachedBranchCwd: string | undefined = undefined;
|
|
118
182
|
#gitWatcher: fs.FSWatcher | null = null;
|
|
119
183
|
#onBranchChange: (() => void) | null = null;
|
|
184
|
+
#disposed = false;
|
|
120
185
|
#autoCompactEnabled: boolean = true;
|
|
121
186
|
#hookStatuses: Map<string, string> = new Map();
|
|
122
187
|
#subagentCount: number = 0;
|
|
@@ -166,6 +231,15 @@ export class StatusLineComponent implements Component {
|
|
|
166
231
|
transparent: settings.get("statusLine.transparent"),
|
|
167
232
|
};
|
|
168
233
|
}
|
|
234
|
+
#gitEnabled(): boolean {
|
|
235
|
+
return settings.get("git.enabled");
|
|
236
|
+
}
|
|
237
|
+
#hasGitBackedSegment(): boolean {
|
|
238
|
+
const effectiveSettings = this.#resolveSettings();
|
|
239
|
+
return (
|
|
240
|
+
hasGitBackedSegment(effectiveSettings.leftSegments) || hasGitBackedSegment(effectiveSettings.rightSegments)
|
|
241
|
+
);
|
|
242
|
+
}
|
|
169
243
|
|
|
170
244
|
/**
|
|
171
245
|
* Re-point the status line at another session (focus proxy). Invalidate: model/context/usage all derive
|
|
@@ -183,6 +257,7 @@ export class StatusLineComponent implements Component {
|
|
|
183
257
|
updateSettings(settings: StatusLineSettings): void {
|
|
184
258
|
this.#settings = settings;
|
|
185
259
|
this.#effectiveSettings = undefined;
|
|
260
|
+
if (this.#onBranchChange) this.#setupGitWatcher();
|
|
186
261
|
}
|
|
187
262
|
|
|
188
263
|
getEffectiveSettingsForTest(): EffectiveStatusLineSettings {
|
|
@@ -241,6 +316,11 @@ export class StatusLineComponent implements Component {
|
|
|
241
316
|
this.#gitWatcher = null;
|
|
242
317
|
}
|
|
243
318
|
|
|
319
|
+
if (!this.#gitEnabled() || !this.#hasGitBackedSegment()) {
|
|
320
|
+
this.#invalidateGitCaches();
|
|
321
|
+
return;
|
|
322
|
+
}
|
|
323
|
+
|
|
244
324
|
const repository = git.repo.resolveSync(getProjectDir());
|
|
245
325
|
if (!repository) return;
|
|
246
326
|
|
|
@@ -250,6 +330,7 @@ export class StatusLineComponent implements Component {
|
|
|
250
330
|
|
|
251
331
|
try {
|
|
252
332
|
this.#gitWatcher = fs.watch(watchPath, () => {
|
|
333
|
+
if (this.#disposed) return;
|
|
253
334
|
this.#invalidateGitCaches();
|
|
254
335
|
if (this.#onBranchChange) {
|
|
255
336
|
this.#onBranchChange();
|
|
@@ -261,6 +342,8 @@ export class StatusLineComponent implements Component {
|
|
|
261
342
|
}
|
|
262
343
|
|
|
263
344
|
dispose(): void {
|
|
345
|
+
this.#disposed = true;
|
|
346
|
+
this.#onBranchChange = null;
|
|
264
347
|
if (this.#gitWatcher) {
|
|
265
348
|
this.#gitWatcher.close();
|
|
266
349
|
this.#gitWatcher = null;
|
|
@@ -286,6 +369,8 @@ export class StatusLineComponent implements Component {
|
|
|
286
369
|
this.#cachedPrContext = undefined;
|
|
287
370
|
}
|
|
288
371
|
#getCurrentBranch(): string | null {
|
|
372
|
+
if (!this.#gitEnabled()) return null;
|
|
373
|
+
|
|
289
374
|
const cwd = getProjectDir();
|
|
290
375
|
if (this.#cachedBranch !== undefined && this.#cachedBranchCwd === cwd) {
|
|
291
376
|
return this.#cachedBranch;
|
|
@@ -310,6 +395,7 @@ export class StatusLineComponent implements Component {
|
|
|
310
395
|
this.#defaultBranch = "main";
|
|
311
396
|
(async () => {
|
|
312
397
|
const resolved = await git.branch.default(getProjectDir());
|
|
398
|
+
if (this.#disposed) return;
|
|
313
399
|
if (resolved) {
|
|
314
400
|
this.#defaultBranch = resolved;
|
|
315
401
|
if (this.#onBranchChange) {
|
|
@@ -322,6 +408,7 @@ export class StatusLineComponent implements Component {
|
|
|
322
408
|
}
|
|
323
409
|
|
|
324
410
|
#getGitStatus(): { staged: number; unstaged: number; untracked: number } | null {
|
|
411
|
+
if (!this.#gitEnabled()) return null;
|
|
325
412
|
if (this.#gitStatusInFlight || Date.now() - this.#gitStatusLastFetch < 1000) {
|
|
326
413
|
return this.#cachedGitStatus;
|
|
327
414
|
}
|
|
@@ -343,6 +430,8 @@ export class StatusLineComponent implements Component {
|
|
|
343
430
|
}
|
|
344
431
|
|
|
345
432
|
#lookupPr(): { number: number; url: string } | null {
|
|
433
|
+
if (!this.#gitEnabled()) return null;
|
|
434
|
+
|
|
346
435
|
const branch = this.#getCurrentBranch();
|
|
347
436
|
const currentContext = branch ? createPrCacheContext(branch, this.#cachedBranchRepoId ?? null) : null;
|
|
348
437
|
|
|
@@ -376,6 +465,7 @@ export class StatusLineComponent implements Component {
|
|
|
376
465
|
try {
|
|
377
466
|
// Requires `gh repo set-default` to be configured; fails gracefully if not
|
|
378
467
|
const result = await $`gh pr view --json number,url`.quiet().nothrow();
|
|
468
|
+
if (this.#disposed) return;
|
|
379
469
|
if (result.exitCode !== 0) {
|
|
380
470
|
setCachedPr(null);
|
|
381
471
|
return;
|
|
@@ -387,10 +477,11 @@ export class StatusLineComponent implements Component {
|
|
|
387
477
|
setCachedPr(null);
|
|
388
478
|
}
|
|
389
479
|
} catch {
|
|
480
|
+
if (this.#disposed) return;
|
|
390
481
|
setCachedPr(null);
|
|
391
482
|
} finally {
|
|
392
483
|
this.#prLookupInFlight = false;
|
|
393
|
-
if (this.#onBranchChange) {
|
|
484
|
+
if (!this.#disposed && this.#onBranchChange) {
|
|
394
485
|
this.#onBranchChange();
|
|
395
486
|
}
|
|
396
487
|
}
|
|
@@ -515,11 +606,19 @@ export class StatusLineComponent implements Component {
|
|
|
515
606
|
* (right after compaction, before the next response). Exposed (non-private)
|
|
516
607
|
* for unit tests and the collab host's state broadcast.
|
|
517
608
|
*/
|
|
518
|
-
getCachedContextBreakdown(): { usedTokens: number
|
|
609
|
+
getCachedContextBreakdown(): { usedTokens: number; contextWindow: number } {
|
|
519
610
|
const messages = this.session.messages ?? EMPTY_MESSAGES;
|
|
520
611
|
const modelContextWindow = this.session.model?.contextWindow ?? 0;
|
|
521
612
|
const length = messages.length;
|
|
522
613
|
const lastFingerprint = length > 0 ? messageFingerprint(messages[length - 1]!) : undefined;
|
|
614
|
+
// Bumps when the in-flight pending snapshot is set/cleared. Without it a
|
|
615
|
+
// value computed mid-turn (estimate of the active tail) would survive after
|
|
616
|
+
// the turn ends/aborts, since clearing the snapshot touches no message.
|
|
617
|
+
const contextUsageRevision = this.session.contextUsageRevision ?? 0;
|
|
618
|
+
|
|
619
|
+
const systemPrompt = this.session.systemPrompt;
|
|
620
|
+
const tools = this.session.agent?.state?.tools;
|
|
621
|
+
const skills = this.session.skills;
|
|
523
622
|
|
|
524
623
|
const cache = this.#contextUsageCache;
|
|
525
624
|
if (
|
|
@@ -527,21 +626,29 @@ export class StatusLineComponent implements Component {
|
|
|
527
626
|
cache.messagesRef === messages &&
|
|
528
627
|
cache.length === length &&
|
|
529
628
|
cache.lastFingerprint === lastFingerprint &&
|
|
530
|
-
cache.modelContextWindow === modelContextWindow
|
|
629
|
+
cache.modelContextWindow === modelContextWindow &&
|
|
630
|
+
cache.contextUsageRevision === contextUsageRevision &&
|
|
631
|
+
cache.systemPromptRef === systemPrompt &&
|
|
632
|
+
cache.toolsRef === tools &&
|
|
633
|
+
cache.skillsRef === skills
|
|
531
634
|
) {
|
|
532
635
|
return { usedTokens: cache.usedTokens, contextWindow: cache.contextWindow };
|
|
533
636
|
}
|
|
534
637
|
|
|
535
638
|
const usage = this.session.getContextUsage();
|
|
536
|
-
const usedTokens = usage?.tokens ??
|
|
639
|
+
const usedTokens = usage?.tokens ?? 0;
|
|
537
640
|
const contextWindow = usage?.contextWindow ?? modelContextWindow;
|
|
538
641
|
this.#contextUsageCache = {
|
|
539
642
|
messagesRef: messages,
|
|
540
643
|
length,
|
|
541
644
|
lastFingerprint,
|
|
542
645
|
modelContextWindow,
|
|
646
|
+
contextUsageRevision,
|
|
543
647
|
usedTokens,
|
|
544
648
|
contextWindow,
|
|
649
|
+
systemPromptRef: systemPrompt,
|
|
650
|
+
toolsRef: tools,
|
|
651
|
+
skillsRef: skills,
|
|
545
652
|
};
|
|
546
653
|
return { usedTokens, contextWindow };
|
|
547
654
|
}
|
|
@@ -550,6 +657,8 @@ export class StatusLineComponent implements Component {
|
|
|
550
657
|
width: number,
|
|
551
658
|
segmentOptions: StatusLineSettings["segmentOptions"],
|
|
552
659
|
includeContext: boolean,
|
|
660
|
+
includeGit: boolean,
|
|
661
|
+
includePr: boolean,
|
|
553
662
|
): SegmentContext {
|
|
554
663
|
const state = this.session.state;
|
|
555
664
|
|
|
@@ -575,8 +684,7 @@ export class StatusLineComponent implements Component {
|
|
|
575
684
|
if (includeContext) {
|
|
576
685
|
const breakdown = this.getCachedContextBreakdown();
|
|
577
686
|
contextWindow = breakdown.contextWindow || contextWindow;
|
|
578
|
-
contextPercent =
|
|
579
|
-
breakdown.usedTokens === null ? null : contextWindow > 0 ? (breakdown.usedTokens / contextWindow) * 100 : 0;
|
|
687
|
+
contextPercent = contextWindow > 0 ? (breakdown.usedTokens / contextWindow) * 100 : 0;
|
|
580
688
|
}
|
|
581
689
|
|
|
582
690
|
// Collab guest: context comes from the host's state frames — the local
|
|
@@ -587,6 +695,10 @@ export class StatusLineComponent implements Component {
|
|
|
587
695
|
contextPercent = collabState.contextUsage.percent ?? contextPercent;
|
|
588
696
|
}
|
|
589
697
|
|
|
698
|
+
const gitBranch = includeGit || includePr ? this.#getCurrentBranch() : null;
|
|
699
|
+
const gitStatus = includeGit ? this.#getGitStatus() : null;
|
|
700
|
+
const gitPr = includePr ? this.#lookupPr() : null;
|
|
701
|
+
|
|
590
702
|
return {
|
|
591
703
|
session: this.session,
|
|
592
704
|
focusedAgentId: this.#focusedAgentId,
|
|
@@ -603,9 +715,9 @@ export class StatusLineComponent implements Component {
|
|
|
603
715
|
subagentCount: this.#subagentCount,
|
|
604
716
|
sessionStartTime: this.#sessionStartTime,
|
|
605
717
|
git: {
|
|
606
|
-
branch:
|
|
607
|
-
status:
|
|
608
|
-
pr:
|
|
718
|
+
branch: gitBranch,
|
|
719
|
+
status: gitStatus,
|
|
720
|
+
pr: gitPr,
|
|
609
721
|
},
|
|
610
722
|
usage: this.#cachedUsage,
|
|
611
723
|
};
|
|
@@ -656,7 +768,19 @@ export class StatusLineComponent implements Component {
|
|
|
656
768
|
const effectiveSettings = this.#resolveSettings();
|
|
657
769
|
const includeContext =
|
|
658
770
|
hasContextSegment(effectiveSettings.leftSegments) || hasContextSegment(effectiveSettings.rightSegments);
|
|
659
|
-
const
|
|
771
|
+
const gitEnabled = this.#gitEnabled();
|
|
772
|
+
const includeGit =
|
|
773
|
+
gitEnabled &&
|
|
774
|
+
(hasGitSegment(effectiveSettings.leftSegments) || hasGitSegment(effectiveSettings.rightSegments));
|
|
775
|
+
const includePr =
|
|
776
|
+
gitEnabled && (hasPrSegment(effectiveSettings.leftSegments) || hasPrSegment(effectiveSettings.rightSegments));
|
|
777
|
+
const ctx = this.#buildSegmentContext(
|
|
778
|
+
width,
|
|
779
|
+
effectiveSettings.segmentOptions,
|
|
780
|
+
includeContext,
|
|
781
|
+
includeGit,
|
|
782
|
+
includePr,
|
|
783
|
+
);
|
|
660
784
|
const separatorDef = getSeparator(effectiveSettings.separator ?? "powerline-thin", theme);
|
|
661
785
|
|
|
662
786
|
// `transparent` reuses the empty-string sentinel (`\x1b[49m`) so the bar
|
|
@@ -58,7 +58,6 @@ export function getContextUsageLevel(contextPercent: number, contextWindow: numb
|
|
|
58
58
|
/**
|
|
59
59
|
* Format context usage as `<percent>%/<window>` (e.g. `5.1%/1M`), matching the
|
|
60
60
|
* status line's context gauge so subagent and footer renderers stay in sync.
|
|
61
|
-
* A `null`/`undefined` percent (unknown, e.g. right after compaction) renders as `?`.
|
|
62
61
|
*/
|
|
63
62
|
export function formatContextUsage(contextPercent: number | null | undefined, contextWindow: number): string {
|
|
64
63
|
const pct = contextPercent === null || contextPercent === undefined ? "?" : `${contextPercent.toFixed(1)}%`;
|
|
@@ -34,7 +34,7 @@ import {
|
|
|
34
34
|
import { formatExpandHint, replaceTabs, resolveImageOptions, truncateToWidth } from "../../tools/render-utils";
|
|
35
35
|
import { toolRenderers } from "../../tools/renderers";
|
|
36
36
|
import { TODO_STRIKE_TOTAL_FRAMES } from "../../tools/todo";
|
|
37
|
-
import { isFramedBlockComponent, renderStatusLine } from "../../tui";
|
|
37
|
+
import { isFramedBlockComponent, renderStatusLine, WidthAwareText } from "../../tui";
|
|
38
38
|
import { sanitizeWithOptionalSixelPassthrough } from "../../utils/sixel";
|
|
39
39
|
import { renderDiff } from "./diff";
|
|
40
40
|
|
|
@@ -169,7 +169,7 @@ let toolExecutionInstanceSeq = 0;
|
|
|
169
169
|
*/
|
|
170
170
|
export class ToolExecutionComponent extends Container implements NativeScrollbackLiveRegion {
|
|
171
171
|
#contentBox: Box; // Used for custom tools and bash visual truncation
|
|
172
|
-
#contentText:
|
|
172
|
+
#contentText: WidthAwareText; // Generic fallback (no custom/built-in renderer)
|
|
173
173
|
#multiFileBoxes: (Box | Spacer)[] = []; // Extra boxes for multi-file edit results
|
|
174
174
|
#imageComponents: Image[] = [];
|
|
175
175
|
#imageSpacers: Spacer[] = [];
|
|
@@ -272,6 +272,7 @@ export class ToolExecutionComponent extends Container implements NativeScrollbac
|
|
|
272
272
|
this.#ui = ui;
|
|
273
273
|
this.#cwd = cwd;
|
|
274
274
|
this.#args = args;
|
|
275
|
+
this.#editMode = resolveEditModeForTool(toolName, tool);
|
|
275
276
|
|
|
276
277
|
// Always create both - contentBox for custom tools/bash/tools with renderers, contentText for other built-ins.
|
|
277
278
|
// paddingY is 1 so background-tinted blocks (custom/extension tools and the
|
|
@@ -279,7 +280,7 @@ export class ToolExecutionComponent extends Container implements NativeScrollbac
|
|
|
279
280
|
// strips PLAIN-blank edges, so framed/minimal blocks (no bg set) drop these
|
|
280
281
|
// lines and keep their tight spacing — only tinted lines survive.
|
|
281
282
|
this.#contentBox = new Box(0, 1);
|
|
282
|
-
this.#contentText = new
|
|
283
|
+
this.#contentText = new WidthAwareText(contentWidth => this.#formatToolExecution(contentWidth), 1, 1);
|
|
283
284
|
|
|
284
285
|
// Use Box for custom tools or built-in tools that have renderers
|
|
285
286
|
const hasRenderer = toolName in toolRenderers;
|
|
@@ -289,8 +290,9 @@ export class ToolExecutionComponent extends Container implements NativeScrollbac
|
|
|
289
290
|
} else {
|
|
290
291
|
this.addChild(this.#contentText);
|
|
291
292
|
}
|
|
292
|
-
|
|
293
|
-
|
|
293
|
+
// Tool blocks are visually distinct cards (background-tinted or framed),
|
|
294
|
+
// so keep their horizontal padding even when the user enables tight layout.
|
|
295
|
+
this.setIgnoreTight(true);
|
|
294
296
|
|
|
295
297
|
this.#updateDisplay();
|
|
296
298
|
this.#editDiffInFlight = this.#runPreviewDiff();
|
|
@@ -922,9 +924,11 @@ export class ToolExecutionComponent extends Container implements NativeScrollbac
|
|
|
922
924
|
}
|
|
923
925
|
}
|
|
924
926
|
} else {
|
|
925
|
-
//
|
|
927
|
+
// Generic fallback (no custom/built-in renderer). WidthAwareText
|
|
928
|
+
// reformats at render time so output fills the actual terminal width
|
|
929
|
+
// instead of a fixed column cap.
|
|
926
930
|
this.#contentText.setCustomBgFn(stateBgFn);
|
|
927
|
-
this.#contentText.
|
|
931
|
+
this.#contentText.invalidate();
|
|
928
932
|
}
|
|
929
933
|
|
|
930
934
|
// Handle images (same for both custom and built-in)
|
|
@@ -1076,14 +1080,17 @@ export class ToolExecutionComponent extends Container implements NativeScrollbac
|
|
|
1076
1080
|
/**
|
|
1077
1081
|
* Format a generic tool execution (fallback for tools without custom renderers)
|
|
1078
1082
|
*/
|
|
1079
|
-
#formatToolExecution(): string {
|
|
1083
|
+
#formatToolExecution(contentWidth: number): string {
|
|
1080
1084
|
const lines: string[] = [];
|
|
1081
1085
|
const icon = this.#isPartial ? "pending" : this.#result?.isError ? "error" : "done";
|
|
1082
1086
|
lines.push(renderStatusLine({ icon, title: this.#toolLabel }, theme));
|
|
1083
1087
|
|
|
1084
1088
|
const argsObject = this.#args && typeof this.#args === "object" ? (this.#args as Record<string, unknown>) : null;
|
|
1085
1089
|
if (!this.#expanded && argsObject && Object.keys(argsObject).length > 0) {
|
|
1086
|
-
|
|
1090
|
+
// Budget the inline preview against the render width, leaving room for
|
|
1091
|
+
// the ` └─ ` connector prefix instead of a fixed cap.
|
|
1092
|
+
const inlineBudget = Math.max(20, contentWidth - Bun.stringWidth(theme.tree.last) - 2);
|
|
1093
|
+
const preview = formatArgsInline(argsObject, inlineBudget);
|
|
1087
1094
|
if (preview) {
|
|
1088
1095
|
lines.push(` ${theme.fg("dim", theme.tree.last)} ${theme.fg("dim", preview)}`);
|
|
1089
1096
|
}
|
|
@@ -1143,7 +1150,7 @@ export class ToolExecutionComponent extends Container implements NativeScrollbac
|
|
|
1143
1150
|
const displayLines = outputLines.slice(0, maxOutputLines);
|
|
1144
1151
|
|
|
1145
1152
|
for (const line of displayLines) {
|
|
1146
|
-
lines.push(theme.fg("toolOutput", truncateToWidth(replaceTabs(line),
|
|
1153
|
+
lines.push(theme.fg("toolOutput", truncateToWidth(replaceTabs(line), contentWidth)));
|
|
1147
1154
|
}
|
|
1148
1155
|
|
|
1149
1156
|
if (outputLines.length > maxOutputLines) {
|
|
@@ -25,6 +25,7 @@ export class TtsrNotificationComponent extends Container {
|
|
|
25
25
|
|
|
26
26
|
// Use inverse warning color for yellow background effect
|
|
27
27
|
this.#box = new Box(1, 1, t => theme.inverse(theme.fg("warning", t)));
|
|
28
|
+
this.#box.setIgnoreTight(true);
|
|
28
29
|
this.addChild(this.#box);
|
|
29
30
|
|
|
30
31
|
this.#rebuild();
|
|
@@ -42,12 +42,12 @@ export class UserMessageComponent extends Container {
|
|
|
42
42
|
? imageReferenceHyperlink(label, index, imageLinks, imageLabel)
|
|
43
43
|
: theme.fg("accent", `\x1b[1m${label}\x1b[22m`),
|
|
44
44
|
});
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
);
|
|
45
|
+
const md = new Markdown(text, 1, 1, getMarkdownTheme(), {
|
|
46
|
+
bgColor,
|
|
47
|
+
color,
|
|
48
|
+
});
|
|
49
|
+
md.setIgnoreTight(true);
|
|
50
|
+
this.addChild(md);
|
|
51
51
|
}
|
|
52
52
|
|
|
53
53
|
override render(width: number): readonly string[] {
|