@xynogen/pix-ssh 0.5.5 → 0.5.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.
Files changed (2) hide show
  1. package/package.json +4 -4
  2. package/src/index.ts +31 -23
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@xynogen/pix-ssh",
3
- "version": "0.5.5",
4
- "description": "Pi tool — ssh_run: run remote commands over SSH with password/key auth and remote sudo",
3
+ "version": "0.5.6",
4
+ "description": "Pi tool \u2014 ssh_run: run remote commands over SSH with password/key auth and remote sudo",
5
5
  "type": "module",
6
6
  "main": "src/index.ts",
7
7
  "scripts": {
@@ -37,8 +37,8 @@
37
37
  "access": "public"
38
38
  },
39
39
  "dependencies": {
40
- "@xynogen/pix-pretty": "^1.25.0",
41
- "@xynogen/pix-runtime": "^0.12.2"
40
+ "@xynogen/pix-pretty": "^1.30.0",
41
+ "@xynogen/pix-runtime": "^0.13.0"
42
42
  },
43
43
  "peerDependencies": {
44
44
  "typebox": "*",
package/src/index.ts CHANGED
@@ -27,24 +27,28 @@
27
27
 
28
28
  import type { AgentToolUpdateCallback, ExtensionAPI } from "@earendil-works/pi-coding-agent";
29
29
  import { Text } from "@earendil-works/pi-tui";
30
- import { FG_DIM, RST, resolveBaseBackground } from "@xynogen/pix-pretty/ansi";
30
+ import { resolveBaseBackground } from "@xynogen/pix-pretty/ansi";
31
+ import { collapsedCommandRow, commandPreview } from "@xynogen/pix-pretty/command-preview";
31
32
  import { MAX_PREVIEW_LINES } from "@xynogen/pix-pretty/config";
32
33
  import { type OverlayResult, showOverlay } from "@xynogen/pix-pretty/gate-overlay";
33
34
  import { icon } from "@xynogen/pix-pretty/icon-catalog";
34
35
  import { renderBashOutput } from "@xynogen/pix-pretty/renderers";
35
36
  import type { RenderContextLike, ThemeLike, ToolResultLike } from "@xynogen/pix-pretty/types";
36
37
  import {
38
+ BODY_PAD,
39
+ bodyLine,
37
40
  dotJoin,
38
41
  fillToolBackground,
42
+ formatCollapsedToolRow,
43
+ formatToolCallTitle,
39
44
  frameToolResult,
40
45
  getErrorMessage,
41
46
  getTextContent,
42
47
  hideCollapsedToolCall,
48
+ moreLines,
43
49
  normalizeLineEndings,
44
- renderCollapsedToolRow,
45
50
  renderToolError,
46
51
  ruleFrame,
47
- sectionRule,
48
52
  termW,
49
53
  unframeToolResult,
50
54
  } from "@xynogen/pix-pretty/utils";
@@ -884,20 +888,23 @@ export default function (pi: ExtensionAPI): void {
884
888
  if (args.action === "info") {
885
889
  text.setText(
886
890
  fillToolBackground(
887
- `${theme.fg("toolTitle", theme.bold("ssh info"))} ${theme.fg("dim", host || "list aliases")}`,
891
+ `${formatToolCallTitle(theme, "ssh info", renderCtx)} ${theme.fg("dim", host || "list aliases")}`,
888
892
  ),
889
893
  );
890
894
  return text;
891
895
  }
892
896
  const operation = normalizeOperation(args);
893
- const command = safeOneLine(operation.command) || "(empty command)";
897
+ const command = operation.command || "(empty command)";
894
898
  const prefix = operation.sudo ? "sudo " : "";
895
- text.setText(
896
- fillToolBackground(
897
- `${theme.fg("toolTitle", theme.bold(operation.action === "file" ? "ssh file" : "ssh"))} ${theme.fg("dim", host)} ${theme.fg("muted", prefix + command)}`,
898
- ),
899
+ return commandPreview(
900
+ `${formatToolCallTitle(theme, operation.action === "file" ? "ssh file" : "ssh", renderCtx)} ${theme.fg("dim", host)}`,
901
+ prefix + command,
902
+ "bash",
903
+ theme,
904
+ renderCtx.state,
905
+ renderCtx.invalidate,
906
+ renderCtx.expanded,
899
907
  );
900
- return text;
901
908
  }) as never,
902
909
 
903
910
  renderResult: ((
@@ -917,7 +924,7 @@ export default function (pi: ExtensionAPI): void {
917
924
  text.setText(renderToolError(getTextContent(result) || "Error", theme));
918
925
  } else {
919
926
  text.setText(
920
- fillToolBackground(` ${theme.fg("muted", getTextContent(result) || "done")}`),
927
+ fillToolBackground(`${BODY_PAD}${theme.fg("muted", getTextContent(result) || "done")}`),
921
928
  );
922
929
  }
923
930
  return isPartial ? text : completed(renderCtx.isError);
@@ -934,21 +941,24 @@ export default function (pi: ExtensionAPI): void {
934
941
  )
935
942
  ) {
936
943
  const status = details.outcome === "success" ? "success" : "error";
937
- text.setText(
938
- renderCollapsedToolRow(
944
+ return collapsedCommandRow(
945
+ formatCollapsedToolRow(
939
946
  theme,
940
947
  "ssh",
941
- `${details.host} ${safeOneLine(details.command)}`,
948
+ details.host,
942
949
  terminalMeta(details),
943
950
  status,
944
- ),
951
+ ).trimEnd(),
952
+ safeOneLine(details.command),
953
+ theme,
945
954
  );
946
- return text;
947
955
  }
948
956
 
949
957
  if (details.outcome === "awaiting-approval" || details.outcome === "running") {
950
958
  text.setText(
951
- fillToolBackground(` ${theme.fg("muted", getTextContent(result) || "working")}`),
959
+ fillToolBackground(
960
+ `${BODY_PAD}${theme.fg("muted", getTextContent(result) || "working")}`,
961
+ ),
952
962
  );
953
963
  return text;
954
964
  }
@@ -958,7 +968,7 @@ export default function (pi: ExtensionAPI): void {
958
968
  text.setText(
959
969
  details.outcome === "error"
960
970
  ? renderToolError(diagnostic, theme)
961
- : fillToolBackground(` ${theme.fg("warning", diagnostic)}`),
971
+ : fillToolBackground(`${BODY_PAD}${theme.fg("warning", diagnostic)}`),
962
972
  );
963
973
  return isPartial ? text : completed(true);
964
974
  }
@@ -970,18 +980,16 @@ export default function (pi: ExtensionAPI): void {
970
980
  const lineCount = lines.length;
971
981
 
972
982
  if (!rendered) {
973
- text.setText(fillToolBackground(` ${summary}`));
983
+ text.setText(fillToolBackground(`${BODY_PAD}${summary}`));
974
984
  return isPartial ? text : completed(details.outcome !== "success");
975
985
  }
976
986
 
977
987
  const maxShow = renderCtx.expanded ? lineCount : MAX_PREVIEW_LINES;
978
988
  const show = lines.slice(0, maxShow);
979
- const footer =
980
- lineCount > maxShow ? [`${FG_DIM} … ${lineCount - maxShow} more lines${RST}`] : [];
989
+ const footer = lineCount > maxShow ? [moreLines(lineCount - maxShow, theme)] : [];
981
990
  const statusKey = details.outcome === "success" ? "success" : "error";
982
991
  const paint = (s: string) => theme.fg(statusKey, s);
983
- const sw = Math.max(8, termW() - 4); // section-rule width inside the 2-space indent
984
- const body = show.map((line) => ` ${sectionRule(line, theme, sw) ?? line}`);
992
+ const body = show.map((line) => bodyLine(line, theme));
985
993
  const out = isPartial ? [...body, ...footer] : ruleFrame(body, footer, termW(), paint);
986
994
  text.setText(fillToolBackground(out.join("\n")));
987
995
  return text;