@hydra-acp/cli 0.1.0 → 0.1.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.
Files changed (3) hide show
  1. package/README.md +0 -0
  2. package/dist/cli.js +104 -12
  3. package/package.json +5 -1
package/README.md CHANGED
Binary file
package/dist/cli.js CHANGED
@@ -1807,6 +1807,8 @@ var init_picker = __esm({
1807
1807
  });
1808
1808
 
1809
1809
  // src/tui/screen.ts
1810
+ import stringWidth from "string-width";
1811
+ import wrapAnsi from "wrap-ansi";
1810
1812
  function computePromptVisualRows(buffer, room) {
1811
1813
  const rows = [];
1812
1814
  for (let i = 0; i < buffer.length; i++) {
@@ -1933,6 +1935,15 @@ function writeStyled(term, text, style) {
1933
1935
  term.noFormat(text);
1934
1936
  }
1935
1937
  }
1938
+ function wrapAnsiBody(text, width) {
1939
+ if (width <= 0) {
1940
+ return [text];
1941
+ }
1942
+ if (text.length === 0) {
1943
+ return [""];
1944
+ }
1945
+ return wrapAnsi(text, width, { hard: true, trim: false }).split("\n");
1946
+ }
1936
1947
  function wrap(text, width) {
1937
1948
  if (width <= 0) {
1938
1949
  return [text];
@@ -2902,7 +2913,7 @@ var init_screen = __esm({
2902
2913
  for (const line of lines) {
2903
2914
  const prefix = line.prefix ?? "";
2904
2915
  const room = Math.max(1, width - prefix.length);
2905
- const chunks = wrap(line.body, room);
2916
+ const chunks = line.ansi ? wrapAnsiBody(line.body, room) : wrap(line.body, room);
2906
2917
  for (let i = 0; i < chunks.length; i++) {
2907
2918
  const chunk = chunks[i] ?? "";
2908
2919
  const wrappedLine = {
@@ -2918,6 +2929,9 @@ var init_screen = __esm({
2918
2929
  if (line.fillRow) {
2919
2930
  wrappedLine.fillRow = true;
2920
2931
  }
2932
+ if (line.ansi) {
2933
+ wrappedLine.ansi = true;
2934
+ }
2921
2935
  out.push(wrappedLine);
2922
2936
  }
2923
2937
  }
@@ -2928,15 +2942,16 @@ var init_screen = __esm({
2928
2942
  writeStyled(this.term, line.prefix, line.prefixStyle ?? line.bodyStyle);
2929
2943
  }
2930
2944
  const remaining = Math.max(0, width - (line.prefix?.length ?? 0));
2931
- const bodyText = truncate(line.body, remaining);
2945
+ const bodyText = line.ansi ? line.body : truncate(line.body, remaining);
2932
2946
  writeStyled(this.term, bodyText, line.bodyStyle);
2933
2947
  if (line.fillRow) {
2934
- const pad = remaining - bodyText.length;
2948
+ const visible = line.ansi ? stringWidth(bodyText) : bodyText.length;
2949
+ const pad = remaining - visible;
2935
2950
  if (pad > 0) {
2936
2951
  writeStyled(this.term, " ".repeat(pad), line.bodyStyle);
2937
2952
  }
2938
2953
  }
2939
- if (line.body.includes("^")) {
2954
+ if (line.ansi || line.body.includes("^")) {
2940
2955
  this.term.styleReset();
2941
2956
  }
2942
2957
  }
@@ -3530,6 +3545,8 @@ var init_render_update = __esm({
3530
3545
  });
3531
3546
 
3532
3547
  // src/tui/format.ts
3548
+ import chalk from "chalk";
3549
+ import { highlight, supportsLanguage } from "cli-highlight";
3533
3550
  function formatEvent(event) {
3534
3551
  switch (event.kind) {
3535
3552
  case "user-text":
@@ -3581,19 +3598,42 @@ function parseAgentMarkdown(text) {
3581
3598
  const out = [];
3582
3599
  const lines = text.split("\n");
3583
3600
  let inCode = false;
3601
+ let codeLang = "";
3602
+ let codeBuffer = [];
3603
+ const flushCode = () => {
3604
+ if (codeBuffer.length === 0) {
3605
+ return;
3606
+ }
3607
+ const highlighted = highlightFencedBlock(codeLang, codeBuffer);
3608
+ for (const piece of highlighted) {
3609
+ const entry = {
3610
+ prefix: " ",
3611
+ body: piece.body,
3612
+ bodyStyle: "code",
3613
+ fillRow: true
3614
+ };
3615
+ if (piece.ansi) {
3616
+ entry.ansi = true;
3617
+ }
3618
+ out.push(entry);
3619
+ }
3620
+ codeBuffer = [];
3621
+ codeLang = "";
3622
+ };
3584
3623
  for (const line of lines) {
3585
- const fence = line.match(/^\s*```\s*\w*\s*$/);
3624
+ const fence = line.match(/^\s*```\s*(\w*)\s*$/);
3586
3625
  if (fence) {
3587
- inCode = !inCode;
3626
+ if (!inCode) {
3627
+ inCode = true;
3628
+ codeLang = fence[1] ?? "";
3629
+ } else {
3630
+ flushCode();
3631
+ inCode = false;
3632
+ }
3588
3633
  continue;
3589
3634
  }
3590
3635
  if (inCode) {
3591
- out.push({
3592
- prefix: " ",
3593
- body: line,
3594
- bodyStyle: "code",
3595
- fillRow: true
3596
- });
3636
+ codeBuffer.push(line);
3597
3637
  continue;
3598
3638
  }
3599
3639
  const heading = line.match(/^(#{1,6})\s+(.*)$/);
@@ -3637,8 +3677,34 @@ function parseAgentMarkdown(text) {
3637
3677
  bodyStyle: "agent"
3638
3678
  });
3639
3679
  }
3680
+ if (inCode) {
3681
+ flushCode();
3682
+ }
3640
3683
  return out;
3641
3684
  }
3685
+ function highlightFencedBlock(lang, lines) {
3686
+ if (lang.length === 0 || !supportsLanguage(lang)) {
3687
+ return lines.map((body) => ({ body, ansi: false }));
3688
+ }
3689
+ let highlighted;
3690
+ try {
3691
+ highlighted = highlight(lines.join("\n"), {
3692
+ language: lang,
3693
+ theme: HIGHLIGHT_THEME,
3694
+ ignoreIllegals: true
3695
+ });
3696
+ } catch {
3697
+ return lines.map((body) => ({ body, ansi: false }));
3698
+ }
3699
+ const out = highlighted.split("\n");
3700
+ if (out.length !== lines.length) {
3701
+ return lines.map((body) => ({ body, ansi: false }));
3702
+ }
3703
+ return out.map((body, i) => ({
3704
+ body,
3705
+ ansi: body !== lines[i]
3706
+ }));
3707
+ }
3642
3708
  function formatBlock(text, prefix, bodyStyle, prefixStyle, sentBy, fillRow) {
3643
3709
  const lines = text.split("\n");
3644
3710
  const out = [];
@@ -3750,9 +3816,35 @@ function toolStatusStyle(status) {
3750
3816
  return "tool-status-pending";
3751
3817
  }
3752
3818
  }
3819
+ var highlightChalk, HIGHLIGHT_THEME;
3753
3820
  var init_format = __esm({
3754
3821
  "src/tui/format.ts"() {
3755
3822
  "use strict";
3823
+ highlightChalk = new chalk.Instance({ level: 3 });
3824
+ HIGHLIGHT_THEME = {
3825
+ keyword: highlightChalk.blueBright,
3826
+ built_in: highlightChalk.cyan,
3827
+ type: highlightChalk.cyanBright,
3828
+ literal: highlightChalk.blue,
3829
+ number: highlightChalk.greenBright,
3830
+ string: highlightChalk.yellow,
3831
+ regexp: highlightChalk.red,
3832
+ comment: highlightChalk.gray,
3833
+ function: highlightChalk.yellow,
3834
+ title: highlightChalk.yellow,
3835
+ class: highlightChalk.yellowBright,
3836
+ attr: highlightChalk.cyan,
3837
+ attribute: highlightChalk.cyan,
3838
+ variable: highlightChalk.white,
3839
+ params: highlightChalk.white,
3840
+ meta: highlightChalk.magenta,
3841
+ symbol: highlightChalk.magenta,
3842
+ addition: highlightChalk.greenBright,
3843
+ deletion: highlightChalk.redBright,
3844
+ section: highlightChalk.cyan,
3845
+ tag: highlightChalk.cyan,
3846
+ name: highlightChalk.cyanBright
3847
+ };
3756
3848
  }
3757
3849
  });
3758
3850
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hydra-acp/cli",
3
- "version": "0.1.0",
3
+ "version": "0.1.1",
4
4
  "description": "Multi-client ACP session daemon: spawn agents, attach over WSS, multiplex sessions across editors.",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -52,11 +52,15 @@
52
52
  },
53
53
  "dependencies": {
54
54
  "@fastify/websocket": "^11.0.0",
55
+ "chalk": "^4.1.2",
56
+ "cli-highlight": "^2.1.11",
55
57
  "fastify": "^5.0.0",
56
58
  "nanoid": "^5.0.0",
57
59
  "pino": "^9.14.0",
58
60
  "pino-roll": "^4.0.0",
61
+ "string-width": "^8.2.1",
59
62
  "terminal-kit": "^3.1.2",
63
+ "wrap-ansi": "^10.0.0",
60
64
  "ws": "^8.18.0",
61
65
  "zod": "^3.23.0"
62
66
  },