@f5xc-salesdemos/xcsh 19.43.0 → 19.43.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"type": "module",
|
|
3
3
|
"name": "@f5xc-salesdemos/xcsh",
|
|
4
|
-
"version": "19.43.
|
|
4
|
+
"version": "19.43.1",
|
|
5
5
|
"description": "Coding agent CLI with read, bash, edit, write tools and session management",
|
|
6
6
|
"homepage": "https://github.com/f5xc-salesdemos/xcsh",
|
|
7
7
|
"author": "Can Boluk",
|
|
@@ -52,13 +52,13 @@
|
|
|
52
52
|
"dependencies": {
|
|
53
53
|
"@agentclientprotocol/sdk": "0.16.1",
|
|
54
54
|
"@mozilla/readability": "^0.6",
|
|
55
|
-
"@f5xc-salesdemos/xcsh-stats": "19.43.
|
|
56
|
-
"@f5xc-salesdemos/pi-agent-core": "19.43.
|
|
57
|
-
"@f5xc-salesdemos/pi-ai": "19.43.
|
|
58
|
-
"@f5xc-salesdemos/pi-natives": "19.43.
|
|
59
|
-
"@f5xc-salesdemos/pi-resource-management": "19.43.
|
|
60
|
-
"@f5xc-salesdemos/pi-tui": "19.43.
|
|
61
|
-
"@f5xc-salesdemos/pi-utils": "19.43.
|
|
55
|
+
"@f5xc-salesdemos/xcsh-stats": "19.43.1",
|
|
56
|
+
"@f5xc-salesdemos/pi-agent-core": "19.43.1",
|
|
57
|
+
"@f5xc-salesdemos/pi-ai": "19.43.1",
|
|
58
|
+
"@f5xc-salesdemos/pi-natives": "19.43.1",
|
|
59
|
+
"@f5xc-salesdemos/pi-resource-management": "19.43.1",
|
|
60
|
+
"@f5xc-salesdemos/pi-tui": "19.43.1",
|
|
61
|
+
"@f5xc-salesdemos/pi-utils": "19.43.1",
|
|
62
62
|
"@sinclair/typebox": "^0.34",
|
|
63
63
|
"@xterm/headless": "^6.0",
|
|
64
64
|
"ajv": "^8.20",
|
|
@@ -17,17 +17,17 @@ export interface BuildInfo {
|
|
|
17
17
|
}
|
|
18
18
|
|
|
19
19
|
export const BUILD_INFO: BuildInfo = {
|
|
20
|
-
"version": "19.43.
|
|
21
|
-
"commit": "
|
|
22
|
-
"shortCommit": "
|
|
20
|
+
"version": "19.43.1",
|
|
21
|
+
"commit": "5b36c788a2d9ad0fb4a7da83458621d0e995a05a",
|
|
22
|
+
"shortCommit": "5b36c78",
|
|
23
23
|
"branch": "main",
|
|
24
|
-
"tag": "v19.43.
|
|
25
|
-
"commitDate": "2026-06-
|
|
26
|
-
"buildDate": "2026-06-
|
|
24
|
+
"tag": "v19.43.1",
|
|
25
|
+
"commitDate": "2026-06-24T15:09:09Z",
|
|
26
|
+
"buildDate": "2026-06-24T15:34:16.139Z",
|
|
27
27
|
"dirty": true,
|
|
28
28
|
"prNumber": "",
|
|
29
29
|
"repoUrl": "https://github.com/f5xc-salesdemos/xcsh",
|
|
30
30
|
"repoSlug": "f5xc-salesdemos/xcsh",
|
|
31
|
-
"commitUrl": "https://github.com/f5xc-salesdemos/xcsh/commit/
|
|
32
|
-
"releaseUrl": "https://github.com/f5xc-salesdemos/xcsh/releases/tag/v19.43.
|
|
31
|
+
"commitUrl": "https://github.com/f5xc-salesdemos/xcsh/commit/5b36c788a2d9ad0fb4a7da83458621d0e995a05a",
|
|
32
|
+
"releaseUrl": "https://github.com/f5xc-salesdemos/xcsh/releases/tag/v19.43.1"
|
|
33
33
|
};
|
package/src/modes/theme/theme.ts
CHANGED
|
@@ -10,13 +10,15 @@ import {
|
|
|
10
10
|
supportsLanguage as nativeSupportsLanguage,
|
|
11
11
|
} from "@f5xc-salesdemos/pi-natives";
|
|
12
12
|
import type { EditorTheme, MarkdownTheme, SelectListTheme, SymbolTheme } from "@f5xc-salesdemos/pi-tui";
|
|
13
|
-
import { adjustHsv, getCustomThemesDir, isEnoent, logger } from "@f5xc-salesdemos/pi-utils";
|
|
13
|
+
import { adjustHsv, detectDiagramType, getCustomThemesDir, isEnoent, logger } from "@f5xc-salesdemos/pi-utils";
|
|
14
14
|
import { type Static, Type } from "@sinclair/typebox";
|
|
15
15
|
import { TypeCompiler } from "@sinclair/typebox/compiler";
|
|
16
16
|
import chalk from "chalk";
|
|
17
|
+
import { buildMermaidBlockOptions, diagramTypeLabel } from "../../tools/mermaid-renderer";
|
|
18
|
+
import { renderOutputBlock } from "../../tui";
|
|
17
19
|
// Embed theme JSON files at build time
|
|
18
20
|
import { defaultThemes } from "./defaults";
|
|
19
|
-
import { getMermaidAscii, mermaidThemeSignature } from "./mermaid-cache";
|
|
21
|
+
import { getMermaidAscii, mermaidThemeSignature, renderMermaidThemed } from "./mermaid-cache";
|
|
20
22
|
|
|
21
23
|
export { getLanguageFromPath } from "../../utils/lang-from-path";
|
|
22
24
|
|
|
@@ -2510,6 +2512,14 @@ export function getMarkdownTheme(): MarkdownTheme {
|
|
|
2510
2512
|
strikethrough: (text: string) => chalk.strikethrough(text),
|
|
2511
2513
|
symbols: getSymbolTheme(),
|
|
2512
2514
|
getMermaidAscii: (hash: bigint | number) => getMermaidAscii(hash, mermaidThemeSignature(theme)),
|
|
2515
|
+
renderMermaidBlock: (source: string, width: number): string[] | null => {
|
|
2516
|
+
const diagram = renderMermaidThemed(source, theme);
|
|
2517
|
+
if (!diagram) return null;
|
|
2518
|
+
return renderOutputBlock(
|
|
2519
|
+
buildMermaidBlockOptions(diagram, { width, theme, typeLabel: diagramTypeLabel(detectDiagramType(source)) }),
|
|
2520
|
+
theme,
|
|
2521
|
+
);
|
|
2522
|
+
},
|
|
2513
2523
|
highlightCode: (code: string, lang?: string): string[] => {
|
|
2514
2524
|
const validLang = lang && nativeSupportsLanguage(lang) ? lang : undefined;
|
|
2515
2525
|
try {
|
|
@@ -1,18 +1,18 @@
|
|
|
1
|
-
/** TUI renderer for the render_mermaid tool —
|
|
1
|
+
/** TUI renderer for the render_mermaid tool — single F5-framed, themed, colorized diagram. */
|
|
2
2
|
import type { Component } from "@f5xc-salesdemos/pi-tui";
|
|
3
|
-
import { Text } from "@f5xc-salesdemos/pi-tui";
|
|
3
|
+
import { Text, visibleWidth } from "@f5xc-salesdemos/pi-tui";
|
|
4
4
|
import { detectDiagramType, type MermaidDiagramType } from "@f5xc-salesdemos/pi-utils";
|
|
5
5
|
import type { RenderResultOptions } from "../extensibility/custom-tools/types";
|
|
6
6
|
import { renderMermaidThemed } from "../modes/theme/mermaid-cache";
|
|
7
7
|
import type { Theme } from "../modes/theme/theme";
|
|
8
|
-
import { CachedOutputBlock, F5_TOOL_BORDER_COLOR, renderStatusLine } from "../tui";
|
|
8
|
+
import { CachedOutputBlock, F5_TOOL_BORDER_COLOR, type OutputBlockOptions, renderStatusLine } from "../tui";
|
|
9
9
|
import type { RenderMermaidToolDetails } from "./render-mermaid";
|
|
10
|
-
import {
|
|
10
|
+
import { formatErrorMessage, replaceTabs } from "./render-utils";
|
|
11
11
|
|
|
12
12
|
const TOOL_TITLE = "Mermaid";
|
|
13
13
|
|
|
14
|
-
/** Human-friendly caption for the diagram
|
|
15
|
-
function diagramTypeLabel(type: MermaidDiagramType): string {
|
|
14
|
+
/** Human-friendly caption for the diagram type, shown in the F5 frame header. */
|
|
15
|
+
export function diagramTypeLabel(type: MermaidDiagramType): string {
|
|
16
16
|
switch (type) {
|
|
17
17
|
case "flowchart":
|
|
18
18
|
return "flowchart";
|
|
@@ -31,6 +31,41 @@ function diagramTypeLabel(type: MermaidDiagramType): string {
|
|
|
31
31
|
}
|
|
32
32
|
}
|
|
33
33
|
|
|
34
|
+
/**
|
|
35
|
+
* Build the F5 output-block options that frame a themed/colored mermaid diagram.
|
|
36
|
+
* Shared by the render_mermaid tool result AND inline ```mermaid markdown blocks, so
|
|
37
|
+
* every mermaid render gets the SAME single F5 frame — and the diagram is clipped
|
|
38
|
+
* (wrapContent: false), never wrapped, so a wide diagram can't reflow or overflow.
|
|
39
|
+
*/
|
|
40
|
+
export function buildMermaidBlockOptions(
|
|
41
|
+
diagramText: string,
|
|
42
|
+
opts: { width: number; theme: Theme; typeLabel: string; artifactId?: string },
|
|
43
|
+
): OutputBlockOptions {
|
|
44
|
+
// Unlabeled section: the header already reads "Mermaid · <type>", so a "Diagram"
|
|
45
|
+
// bar would be redundant. The diagram keeps its own colors; we only normalize tabs.
|
|
46
|
+
const lines = diagramText.split("\n").map(line => replaceTabs(line));
|
|
47
|
+
const meta = opts.artifactId ? [opts.theme.fg("dim", `artifact:${opts.artifactId.slice(0, 8)}`)] : undefined;
|
|
48
|
+
const header = renderStatusLine(
|
|
49
|
+
{ title: TOOL_TITLE, titleColor: "dim", description: opts.theme.fg("muted", opts.typeLabel), meta },
|
|
50
|
+
opts.theme,
|
|
51
|
+
);
|
|
52
|
+
// Size the frame SNUGLY to the diagram (+ one space of padding each side), capped at
|
|
53
|
+
// the available width and kept wide enough for the header caption — so the diagram
|
|
54
|
+
// feels enclosed in a small padded frame instead of spanning the whole terminal
|
|
55
|
+
// (tiny diagram) or clipping against the right border (wide diagram).
|
|
56
|
+
const maxDiagramWidth = lines.reduce((max, line) => Math.max(max, visibleWidth(line)), 0);
|
|
57
|
+
const desired = Math.max(maxDiagramWidth + 4, visibleWidth(header) + 8);
|
|
58
|
+
const width = Math.min(opts.width, Math.max(1, desired));
|
|
59
|
+
return {
|
|
60
|
+
header,
|
|
61
|
+
state: "success",
|
|
62
|
+
sections: [{ lines }],
|
|
63
|
+
width,
|
|
64
|
+
borderColor: F5_TOOL_BORDER_COLOR,
|
|
65
|
+
wrapContent: false,
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
|
|
34
69
|
type MermaidRenderArgs = {
|
|
35
70
|
mermaid?: string;
|
|
36
71
|
};
|
|
@@ -50,63 +85,36 @@ export const mermaidRenderer = {
|
|
|
50
85
|
details?: RenderMermaidToolDetails;
|
|
51
86
|
isError?: boolean;
|
|
52
87
|
},
|
|
53
|
-
|
|
88
|
+
_options: RenderResultOptions,
|
|
54
89
|
uiTheme: Theme,
|
|
55
90
|
args?: MermaidRenderArgs,
|
|
56
91
|
): Component {
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
if (isError) {
|
|
92
|
+
if (result.isError === true) {
|
|
60
93
|
const errorText = result.content?.find(c => c.type === "text")?.text;
|
|
61
94
|
return new Text(formatErrorMessage(errorText, uiTheme), 0, 0);
|
|
62
95
|
}
|
|
63
96
|
|
|
64
|
-
const sections: Array<{ label?: string; lines: string[] }> = [];
|
|
65
|
-
const meta: string[] = [];
|
|
66
97
|
const rawText = result.content?.find(c => c.type === "text")?.text ?? "";
|
|
67
|
-
|
|
68
98
|
// Strip artifact reference from the plain result text (fallback path).
|
|
69
99
|
const artifactIdx = rawText.indexOf("\n\nSaved artifact:");
|
|
70
100
|
const plainText = artifactIdx >= 0 ? rawText.slice(0, artifactIdx) : rawText;
|
|
71
101
|
|
|
72
|
-
// Prefer re-rendering from the original source:
|
|
73
|
-
// per-role-colored, node-tinted diagram. Fall back to the plain result text.
|
|
102
|
+
// Prefer re-rendering from the original source: themed, per-node-tinted, colored.
|
|
74
103
|
const source = args?.mermaid?.trim();
|
|
75
104
|
const diagramText = (source ? renderMermaidThemed(source, uiTheme) : null) ?? plainText;
|
|
76
|
-
const
|
|
77
|
-
|
|
78
|
-
// Keep the diagram's own colors — do NOT recolor each line a flat tool color.
|
|
79
|
-
// Show the FULL diagram: truncating a diagram with "… N more lines" defeats the purpose.
|
|
80
|
-
const diagramLines = diagramText.split("\n").map(line => replaceTabs(line));
|
|
81
|
-
addSection(sections, "Diagram", diagramLines, uiTheme);
|
|
82
|
-
|
|
83
|
-
if (result.details?.artifactId) {
|
|
84
|
-
meta.push(uiTheme.fg("dim", `artifact:${result.details.artifactId.slice(0, 8)}`));
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
const header = renderStatusLine(
|
|
88
|
-
{
|
|
89
|
-
title: TOOL_TITLE,
|
|
90
|
-
titleColor: "dim",
|
|
91
|
-
description: uiTheme.fg("muted", caption),
|
|
92
|
-
meta: meta.length > 0 ? meta : undefined,
|
|
93
|
-
},
|
|
94
|
-
uiTheme,
|
|
95
|
-
);
|
|
105
|
+
const typeLabel = source ? diagramTypeLabel(detectDiagramType(source)) : "diagram";
|
|
106
|
+
const artifactId = result.details?.artifactId;
|
|
96
107
|
|
|
97
|
-
const
|
|
108
|
+
const block = new CachedOutputBlock();
|
|
98
109
|
return {
|
|
99
110
|
render(width: number): string[] {
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
// Clip, don't wrap: a diagram is a fixed grid — word-wrapping reflows it
|
|
103
|
-
// and breaks alignment. Wide diagrams are truncated to the block width.
|
|
104
|
-
{ header, state, sections, width, borderColor: F5_TOOL_BORDER_COLOR, wrapContent: false },
|
|
111
|
+
return block.render(
|
|
112
|
+
buildMermaidBlockOptions(diagramText, { width, theme: uiTheme, typeLabel, artifactId }),
|
|
105
113
|
uiTheme,
|
|
106
114
|
);
|
|
107
115
|
},
|
|
108
116
|
invalidate() {
|
|
109
|
-
|
|
117
|
+
block.invalidate();
|
|
110
118
|
},
|
|
111
119
|
};
|
|
112
120
|
},
|