arc402-cli 0.9.0 → 0.9.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/tui/App.d.ts.map +1 -1
- package/dist/tui/App.js +8 -32
- package/dist/tui/App.js.map +1 -1
- package/dist/tui/Header.d.ts.map +1 -1
- package/dist/tui/Header.js +2 -2
- package/dist/tui/Header.js.map +1 -1
- package/dist/tui/Viewport.d.ts.map +1 -1
- package/dist/tui/Viewport.js +5 -14
- package/dist/tui/Viewport.js.map +1 -1
- package/dist/tui/useCommand.d.ts +3 -2
- package/dist/tui/useCommand.d.ts.map +1 -1
- package/dist/tui/useCommand.js +89 -7
- package/dist/tui/useCommand.js.map +1 -1
- package/package.json +1 -1
- package/src/tui/App.tsx +14 -39
- package/src/tui/Header.tsx +9 -15
- package/src/tui/Viewport.tsx +7 -16
- package/src/tui/useCommand.ts +98 -8
package/dist/tui/App.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"App.d.ts","sourceRoot":"","sources":["../../src/tui/App.tsx"],"names":[],"mappings":"AAmBA,UAAU,QAAQ;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED;;GAEG;AACH,wBAAgB,GAAG,CAAC,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,EAAE,QAAQ,
|
|
1
|
+
{"version":3,"file":"App.d.ts","sourceRoot":"","sources":["../../src/tui/App.tsx"],"names":[],"mappings":"AAmBA,UAAU,QAAQ;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED;;GAEG;AACH,wBAAgB,GAAG,CAAC,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,EAAE,QAAQ,2CAgNlE"}
|
package/dist/tui/App.js
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { useState, useCallback } from "react";
|
|
3
3
|
import { createRequire } from "node:module";
|
|
4
|
-
import { Box, Text,
|
|
4
|
+
import { Box, Text, useApp, useInput, useStdout } from "ink";
|
|
5
|
+
import { Header } from "./Header.js";
|
|
5
6
|
import { Viewport } from "./Viewport.js";
|
|
6
7
|
import { Footer } from "./Footer.js";
|
|
7
8
|
import { InputLine } from "./InputLine.js";
|
|
@@ -11,7 +12,6 @@ import { useScroll } from "./useScroll.js";
|
|
|
11
12
|
import { useNotifications } from "./useNotifications.js";
|
|
12
13
|
import { ToastContainer } from "./components/Toast.js";
|
|
13
14
|
import { createProgram } from "../program.js";
|
|
14
|
-
import { getBannerArt, getStatusItems } from "../ui/banner.js";
|
|
15
15
|
import chalk from "chalk";
|
|
16
16
|
const pkg = createRequire(import.meta.url)("../../package.json");
|
|
17
17
|
const BUILTIN_CMDS = ["help", "exit", "quit", "clear", "status"];
|
|
@@ -20,30 +20,7 @@ const BUILTIN_CMDS = ["help", "exit", "quit", "clear", "status"];
|
|
|
20
20
|
*/
|
|
21
21
|
export function App({ version, network, wallet, balance }) {
|
|
22
22
|
const { exit } = useApp();
|
|
23
|
-
|
|
24
|
-
const [bannerData] = useState(() => {
|
|
25
|
-
const { artLines, subtitle, separator } = getBannerArt();
|
|
26
|
-
const statusItems = getStatusItems({ network, wallet, balance });
|
|
27
|
-
// Build static items: art lines + subtitle + separator + status + help hint
|
|
28
|
-
const items = [];
|
|
29
|
-
artLines.forEach((line, i) => items.push({ id: `art-${i}`, text: line }));
|
|
30
|
-
items.push({ id: "blank-1", text: "" });
|
|
31
|
-
items.push({ id: "subtitle", text: subtitle });
|
|
32
|
-
items.push({ id: "separator", text: separator });
|
|
33
|
-
if (statusItems.length > 0) {
|
|
34
|
-
items.push({ id: "blank-2", text: "" });
|
|
35
|
-
// Status items as a single formatted line for <Static>
|
|
36
|
-
// (FlexWrap rendering happens in the Header component for non-Static contexts)
|
|
37
|
-
const statusLine = statusItems
|
|
38
|
-
.map((s) => `\x1b[2m${s.label}\x1b[22m ${s.value}`)
|
|
39
|
-
.join(" ");
|
|
40
|
-
items.push({ id: "status", text: ` ${statusLine}` });
|
|
41
|
-
}
|
|
42
|
-
items.push({ id: "blank-3", text: "" });
|
|
43
|
-
items.push({ id: "hint", text: " \x1b[2mType 'help' to get started\x1b[22m" });
|
|
44
|
-
items.push({ id: "blank-4", text: "" });
|
|
45
|
-
return items;
|
|
46
|
-
});
|
|
23
|
+
const { stdout } = useStdout();
|
|
47
24
|
const [outputBuffer, setOutputBuffer] = useState([
|
|
48
25
|
chalk.dim(" Type 'help' to see available commands"),
|
|
49
26
|
"",
|
|
@@ -51,11 +28,9 @@ export function App({ version, network, wallet, balance }) {
|
|
|
51
28
|
const [isProcessing, setIsProcessing] = useState(false);
|
|
52
29
|
const { execute, isRunning } = useCommand();
|
|
53
30
|
const { send, isSending } = useChat();
|
|
54
|
-
// Approximate viewport height for scroll management
|
|
55
|
-
const
|
|
56
|
-
const
|
|
57
|
-
const rows = process.stdout.rows ?? 24;
|
|
58
|
-
const viewportHeight = Math.max(1, rows - HEADER_ROWS - FOOTER_ROWS);
|
|
31
|
+
// Approximate viewport height for scroll management (used by useScroll)
|
|
32
|
+
const rows = stdout?.rows ?? process.stdout.rows ?? 24;
|
|
33
|
+
const viewportHeight = Math.max(1, rows - 18);
|
|
59
34
|
const { scrollOffset, isAutoScroll, scrollUp, scrollDown, snapToBottom } = useScroll(viewportHeight);
|
|
60
35
|
const { toasts, dismiss: dismissToast } = useNotifications();
|
|
61
36
|
// Get top-level command names for dispatch detection
|
|
@@ -183,6 +158,7 @@ export function App({ version, network, wallet, balance }) {
|
|
|
183
158
|
setIsProcessing(false);
|
|
184
159
|
}, [appendLine, execute, send, snapToBottom, topCmds, network, wallet, balance, exit]);
|
|
185
160
|
const isDisabled = isProcessing || isRunning || isSending;
|
|
186
|
-
|
|
161
|
+
const cols = Math.min(stdout?.columns ?? process.stdout.columns ?? 80, 120);
|
|
162
|
+
return (_jsxs(Box, { flexDirection: "column", height: "100%", children: [_jsx(Header, { version: version, network: network, wallet: wallet, balance: balance }), _jsx(Box, { flexShrink: 0, children: _jsx(Text, { dimColor: true, children: "─".repeat(cols) }) }), _jsx(Viewport, { lines: outputBuffer, scrollOffset: scrollOffset, isAutoScroll: isAutoScroll }), _jsx(ToastContainer, { toasts: toasts, onDismiss: dismissToast }), _jsx(Box, { flexShrink: 0, children: _jsx(Text, { dimColor: true, children: "─".repeat(cols) }) }), _jsx(Footer, { children: _jsx(InputLine, { onSubmit: handleCommand, isDisabled: isDisabled }) })] }));
|
|
187
163
|
}
|
|
188
164
|
//# sourceMappingURL=App.js.map
|
package/dist/tui/App.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"App.js","sourceRoot":"","sources":["../../src/tui/App.tsx"],"names":[],"mappings":";AAAA,OAAc,EAAE,QAAQ,EAAE,WAAW,EAAa,MAAM,OAAO,CAAC;AAChE,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,EAAE,GAAG,EAAE,IAAI,EAAE,MAAM,EAAE,
|
|
1
|
+
{"version":3,"file":"App.js","sourceRoot":"","sources":["../../src/tui/App.tsx"],"names":[],"mappings":"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"}
|
package/dist/tui/Header.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Header.d.ts","sourceRoot":"","sources":["../../src/tui/Header.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAK1B,UAAU,WAAW;IACnB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED;;;GAGG;AACH,eAAO,MAAM,MAAM,
|
|
1
|
+
{"version":3,"file":"Header.d.ts","sourceRoot":"","sources":["../../src/tui/Header.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAK1B,UAAU,WAAW;IACnB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED;;;GAGG;AACH,eAAO,MAAM,MAAM,yCA4BjB,CAAC"}
|
package/dist/tui/Header.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { jsx as _jsx, jsxs as _jsxs
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import React from "react";
|
|
3
3
|
import { Box, Text } from "ink";
|
|
4
4
|
import { getBannerArt, getStatusItems } from "../ui/banner.js";
|
|
@@ -9,6 +9,6 @@ import { getBannerArt, getStatusItems } from "../ui/banner.js";
|
|
|
9
9
|
export const Header = React.memo(function Header({ network, wallet, balance, }) {
|
|
10
10
|
const { artLines, subtitle, separator } = getBannerArt();
|
|
11
11
|
const statusItems = getStatusItems({ network, wallet, balance });
|
|
12
|
-
return (_jsxs(Box, { flexDirection: "column", children: [artLines.map((line, i) => (_jsx(Text, { children: line }, i))), _jsx(Text, { children: "" }), _jsx(Text, { children: subtitle }), _jsx(Text, { children: separator }), statusItems.length > 0 && (
|
|
12
|
+
return (_jsxs(Box, { flexDirection: "column", flexShrink: 0, children: [artLines.map((line, i) => (_jsx(Text, { children: line }, i))), _jsx(Text, { children: "" }), _jsx(Text, { children: subtitle }), _jsx(Text, { children: separator }), statusItems.length > 0 && (_jsx(Box, { flexWrap: "wrap", columnGap: 2, children: statusItems.map((item) => (_jsxs(Box, { children: [_jsx(Text, { dimColor: true, children: item.label }), _jsxs(Text, { children: [" ", item.value] })] }, item.label))) }))] }));
|
|
13
13
|
});
|
|
14
14
|
//# sourceMappingURL=Header.js.map
|
package/dist/tui/Header.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Header.js","sourceRoot":"","sources":["../../src/tui/Header.tsx"],"names":[],"mappings":";AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,GAAG,EAAE,IAAI,EAAE,MAAM,KAAK,CAAC;AAChC,OAAO,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAU/D;;;GAGG;AACH,MAAM,CAAC,MAAM,MAAM,GAAG,KAAK,CAAC,IAAI,CAAC,SAAS,MAAM,CAAC,EAC/C,OAAO,EACP,MAAM,EACN,OAAO,GACK;IACZ,MAAM,EAAE,QAAQ,EAAE,QAAQ,EAAE,SAAS,EAAE,GAAG,YAAY,EAAE,CAAC;IACzD,MAAM,WAAW,GAAG,cAAc,CAAC,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC,CAAC;IAEjE,OAAO,CACL,MAAC,GAAG,IAAC,aAAa,EAAC,QAAQ,
|
|
1
|
+
{"version":3,"file":"Header.js","sourceRoot":"","sources":["../../src/tui/Header.tsx"],"names":[],"mappings":";AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,GAAG,EAAE,IAAI,EAAE,MAAM,KAAK,CAAC;AAChC,OAAO,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAU/D;;;GAGG;AACH,MAAM,CAAC,MAAM,MAAM,GAAG,KAAK,CAAC,IAAI,CAAC,SAAS,MAAM,CAAC,EAC/C,OAAO,EACP,MAAM,EACN,OAAO,GACK;IACZ,MAAM,EAAE,QAAQ,EAAE,QAAQ,EAAE,SAAS,EAAE,GAAG,YAAY,EAAE,CAAC;IACzD,MAAM,WAAW,GAAG,cAAc,CAAC,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC,CAAC;IAEjE,OAAO,CACL,MAAC,GAAG,IAAC,aAAa,EAAC,QAAQ,EAAC,UAAU,EAAE,CAAC,aACtC,QAAQ,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC,EAAE,EAAE,CAAC,CACzB,KAAC,IAAI,cAAU,IAAI,IAAR,CAAC,CAAe,CAC5B,CAAC,EACF,KAAC,IAAI,cAAE,EAAE,GAAQ,EACjB,KAAC,IAAI,cAAE,QAAQ,GAAQ,EACvB,KAAC,IAAI,cAAE,SAAS,GAAQ,EACvB,WAAW,CAAC,MAAM,GAAG,CAAC,IAAI,CACzB,KAAC,GAAG,IAAC,QAAQ,EAAC,MAAM,EAAC,SAAS,EAAE,CAAC,YAC9B,WAAW,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CACzB,MAAC,GAAG,eACF,KAAC,IAAI,IAAC,QAAQ,kBAAE,IAAI,CAAC,KAAK,GAAQ,EAClC,MAAC,IAAI,qBAAI,IAAI,CAAC,KAAK,IAAQ,KAFnB,IAAI,CAAC,KAAK,CAGd,CACP,CAAC,GACE,CACP,IACG,CACP,CAAC;AACJ,CAAC,CAAC,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Viewport.d.ts","sourceRoot":"","sources":["../../src/tui/Viewport.tsx"],"names":[],"mappings":"AAGA,UAAU,aAAa;IACrB,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,YAAY,EAAE,MAAM,CAAC;IACrB,YAAY,EAAE,OAAO,CAAC;CACvB;AAED;;;;;GAKG;AACH,wBAAgB,QAAQ,CAAC,EAAE,KAAK,EAAE,YAAY,EAAE,YAAY,EAAE,EAAE,aAAa,
|
|
1
|
+
{"version":3,"file":"Viewport.d.ts","sourceRoot":"","sources":["../../src/tui/Viewport.tsx"],"names":[],"mappings":"AAGA,UAAU,aAAa;IACrB,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,YAAY,EAAE,MAAM,CAAC;IACrB,YAAY,EAAE,OAAO,CAAC;CACvB;AAED;;;;;GAKG;AACH,wBAAgB,QAAQ,CAAC,EAAE,KAAK,EAAE,YAAY,EAAE,YAAY,EAAE,EAAE,aAAa,2CA6C5E"}
|
package/dist/tui/Viewport.js
CHANGED
|
@@ -9,13 +9,10 @@ import { Box, Text, useStdout } from "ink";
|
|
|
9
9
|
export function Viewport({ lines, scrollOffset, isAutoScroll }) {
|
|
10
10
|
const { stdout } = useStdout();
|
|
11
11
|
const termRows = stdout?.rows ?? 24;
|
|
12
|
-
//
|
|
13
|
-
//
|
|
14
|
-
//
|
|
15
|
-
|
|
16
|
-
const HEADER_ROWS = 15; // approximate
|
|
17
|
-
const FOOTER_ROWS = 1;
|
|
18
|
-
const viewportHeight = Math.max(1, termRows - HEADER_ROWS - FOOTER_ROWS);
|
|
12
|
+
// Approximate viewport height for scroll slicing.
|
|
13
|
+
// The actual flex layout handles visual sizing; this is for computing
|
|
14
|
+
// which lines to show in the scroll window.
|
|
15
|
+
const viewportHeight = Math.max(1, termRows - 18);
|
|
19
16
|
// Compute the window slice
|
|
20
17
|
// scrollOffset=0 → show last viewportHeight lines
|
|
21
18
|
// scrollOffset=N → show lines ending viewportHeight+N from end
|
|
@@ -33,13 +30,7 @@ export function Viewport({ lines, scrollOffset, isAutoScroll }) {
|
|
|
33
30
|
startIdx = Math.max(0, endIdx - viewportHeight);
|
|
34
31
|
}
|
|
35
32
|
const visibleLines = lines.slice(startIdx, endIdx);
|
|
36
|
-
// Pad with empty lines if fewer than viewportHeight
|
|
37
|
-
const padCount = Math.max(0, viewportHeight - visibleLines.length);
|
|
38
|
-
const paddedLines = [
|
|
39
|
-
...Array(padCount).fill(""),
|
|
40
|
-
...visibleLines,
|
|
41
|
-
];
|
|
42
33
|
const canScrollDown = scrollOffset > 0;
|
|
43
|
-
return (_jsxs(Box, { flexDirection: "column", flexGrow: 1, children: [_jsx(Box, { flexDirection: "column",
|
|
34
|
+
return (_jsxs(Box, { flexDirection: "column", flexGrow: 1, children: [_jsx(Box, { flexDirection: "column", children: visibleLines.map((line, i) => (_jsx(Text, { children: line }, i))) }), _jsx(Box, { flexGrow: 1 }), " ", canScrollDown && !isAutoScroll && (_jsx(Box, { justifyContent: "flex-end", children: _jsx(Text, { dimColor: true, children: "\u2193 more" }) }))] }));
|
|
44
35
|
}
|
|
45
36
|
//# sourceMappingURL=Viewport.js.map
|
package/dist/tui/Viewport.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Viewport.js","sourceRoot":"","sources":["../../src/tui/Viewport.tsx"],"names":[],"mappings":";AACA,OAAO,EAAE,GAAG,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,KAAK,CAAC;AAQ3C;;;;;GAKG;AACH,MAAM,UAAU,QAAQ,CAAC,EAAE,KAAK,EAAE,YAAY,EAAE,YAAY,EAAiB;IAC3E,MAAM,EAAE,MAAM,EAAE,GAAG,SAAS,EAAE,CAAC;IAC/B,MAAM,QAAQ,GAAG,MAAM,EAAE,IAAI,IAAI,EAAE,CAAC;IAEpC,
|
|
1
|
+
{"version":3,"file":"Viewport.js","sourceRoot":"","sources":["../../src/tui/Viewport.tsx"],"names":[],"mappings":";AACA,OAAO,EAAE,GAAG,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,KAAK,CAAC;AAQ3C;;;;;GAKG;AACH,MAAM,UAAU,QAAQ,CAAC,EAAE,KAAK,EAAE,YAAY,EAAE,YAAY,EAAiB;IAC3E,MAAM,EAAE,MAAM,EAAE,GAAG,SAAS,EAAE,CAAC;IAC/B,MAAM,QAAQ,GAAG,MAAM,EAAE,IAAI,IAAI,EAAE,CAAC;IAEpC,kDAAkD;IAClD,sEAAsE;IACtE,4CAA4C;IAC5C,MAAM,cAAc,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,QAAQ,GAAG,EAAE,CAAC,CAAC;IAElD,2BAA2B;IAC3B,kDAAkD;IAClD,+DAA+D;IAC/D,MAAM,UAAU,GAAG,KAAK,CAAC,MAAM,CAAC;IAChC,IAAI,MAAc,CAAC;IACnB,IAAI,QAAgB,CAAC;IAErB,IAAI,YAAY,KAAK,CAAC,EAAE,CAAC;QACvB,gCAAgC;QAChC,MAAM,GAAG,UAAU,CAAC;QACpB,QAAQ,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,MAAM,GAAG,cAAc,CAAC,CAAC;IAClD,CAAC;SAAM,CAAC;QACN,8CAA8C;QAC9C,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,UAAU,GAAG,YAAY,CAAC,CAAC;QAChD,QAAQ,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,MAAM,GAAG,cAAc,CAAC,CAAC;IAClD,CAAC;IAED,MAAM,YAAY,GAAG,KAAK,CAAC,KAAK,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;IAEnD,MAAM,aAAa,GAAG,YAAY,GAAG,CAAC,CAAC;IAEvC,OAAO,CACL,MAAC,GAAG,IAAC,aAAa,EAAC,QAAQ,EAAC,QAAQ,EAAE,CAAC,aACrC,KAAC,GAAG,IAAC,aAAa,EAAC,QAAQ,YACxB,YAAY,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC,EAAE,EAAE,CAAC,CAC7B,KAAC,IAAI,cAAU,IAAI,IAAR,CAAC,CAAe,CAC5B,CAAC,GACE,EACN,KAAC,GAAG,IAAC,QAAQ,EAAE,CAAC,GAAI,QACnB,aAAa,IAAI,CAAC,YAAY,IAAI,CACjC,KAAC,GAAG,IAAC,cAAc,EAAC,UAAU,YAC5B,KAAC,IAAI,IAAC,QAAQ,kCAAc,GACxB,CACP,IACG,CACP,CAAC;AACJ,CAAC"}
|
package/dist/tui/useCommand.d.ts
CHANGED
|
@@ -4,8 +4,9 @@ interface UseCommandResult {
|
|
|
4
4
|
}
|
|
5
5
|
/**
|
|
6
6
|
* Dispatches parsed commands to the commander program.
|
|
7
|
-
*
|
|
8
|
-
*
|
|
7
|
+
* Interactive commands (WalletConnect, prompts) spawn a child process
|
|
8
|
+
* because Ink holds stdin in raw mode.
|
|
9
|
+
* Non-interactive commands run in-process with stdout monkey-patching.
|
|
9
10
|
*/
|
|
10
11
|
export declare function useCommand(): UseCommandResult;
|
|
11
12
|
export {};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useCommand.d.ts","sourceRoot":"","sources":["../../src/tui/useCommand.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"useCommand.d.ts","sourceRoot":"","sources":["../../src/tui/useCommand.ts"],"names":[],"mappings":"AAsCA,UAAU,gBAAgB;IACxB,OAAO,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC1E,SAAS,EAAE,OAAO,CAAC;CACpB;AAED;;;;;GAKG;AACH,wBAAgB,UAAU,IAAI,gBAAgB,CAuJ7C"}
|
package/dist/tui/useCommand.js
CHANGED
|
@@ -1,16 +1,87 @@
|
|
|
1
1
|
import { useState, useCallback } from "react";
|
|
2
|
+
import { spawn } from "node:child_process";
|
|
2
3
|
import { createProgram } from "../program.js";
|
|
3
4
|
import chalk from "chalk";
|
|
4
5
|
import { c } from "../ui/colors.js";
|
|
6
|
+
const INTERACTIVE_COMMANDS = new Set([
|
|
7
|
+
"wallet deploy",
|
|
8
|
+
"wallet set-guardian",
|
|
9
|
+
"wallet unfreeze",
|
|
10
|
+
"wallet authorize-machine-key",
|
|
11
|
+
"wallet revoke-machine-key",
|
|
12
|
+
"wallet set-passkey",
|
|
13
|
+
"wallet set-interceptor",
|
|
14
|
+
"wallet set-velocity-limit",
|
|
15
|
+
"wallet upgrade-registry",
|
|
16
|
+
"wallet execute-registry-upgrade",
|
|
17
|
+
"wallet cancel-registry-upgrade",
|
|
18
|
+
"wallet register-policy",
|
|
19
|
+
"wallet whitelist-contract",
|
|
20
|
+
"wallet governance setup",
|
|
21
|
+
"wallet policy set-limit",
|
|
22
|
+
"wallet policy set-daily-limit",
|
|
23
|
+
"wallet policy set",
|
|
24
|
+
"wallet import",
|
|
25
|
+
"config init",
|
|
26
|
+
]);
|
|
27
|
+
function isInteractiveCommand(input) {
|
|
28
|
+
const trimmed = input.trim();
|
|
29
|
+
for (const cmd of INTERACTIVE_COMMANDS) {
|
|
30
|
+
if (trimmed === cmd || trimmed.startsWith(cmd + " ")) {
|
|
31
|
+
return true;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
return false;
|
|
35
|
+
}
|
|
5
36
|
/**
|
|
6
37
|
* Dispatches parsed commands to the commander program.
|
|
7
|
-
*
|
|
8
|
-
*
|
|
38
|
+
* Interactive commands (WalletConnect, prompts) spawn a child process
|
|
39
|
+
* because Ink holds stdin in raw mode.
|
|
40
|
+
* Non-interactive commands run in-process with stdout monkey-patching.
|
|
9
41
|
*/
|
|
10
42
|
export function useCommand() {
|
|
11
43
|
const [isRunning, setIsRunning] = useState(false);
|
|
12
|
-
const
|
|
13
|
-
|
|
44
|
+
const executeInteractive = useCallback((input, onLine) => {
|
|
45
|
+
return new Promise((resolve) => {
|
|
46
|
+
const tokens = parseTokens(input);
|
|
47
|
+
const child = spawn(process.execPath, [process.argv[1], ...tokens], {
|
|
48
|
+
stdio: ["inherit", "pipe", "pipe"],
|
|
49
|
+
env: { ...process.env, ARC402_NO_TUI: "1", FORCE_COLOR: "1" },
|
|
50
|
+
cwd: process.cwd(),
|
|
51
|
+
});
|
|
52
|
+
let stdoutRemainder = "";
|
|
53
|
+
let stderrRemainder = "";
|
|
54
|
+
child.stdout?.on("data", (chunk) => {
|
|
55
|
+
stdoutRemainder += chunk.toString("utf8");
|
|
56
|
+
const lines = stdoutRemainder.split("\n");
|
|
57
|
+
stdoutRemainder = lines.pop() ?? "";
|
|
58
|
+
for (const line of lines)
|
|
59
|
+
onLine(line);
|
|
60
|
+
});
|
|
61
|
+
child.stderr?.on("data", (chunk) => {
|
|
62
|
+
stderrRemainder += chunk.toString("utf8");
|
|
63
|
+
const lines = stderrRemainder.split("\n");
|
|
64
|
+
stderrRemainder = lines.pop() ?? "";
|
|
65
|
+
for (const line of lines)
|
|
66
|
+
onLine(line);
|
|
67
|
+
});
|
|
68
|
+
child.on("close", (code) => {
|
|
69
|
+
if (stdoutRemainder.trim())
|
|
70
|
+
onLine(stdoutRemainder);
|
|
71
|
+
if (stderrRemainder.trim())
|
|
72
|
+
onLine(stderrRemainder);
|
|
73
|
+
if (code !== 0 && code !== null) {
|
|
74
|
+
onLine(` ${c.failure} ${chalk.red(`Command exited with code ${code}`)}`);
|
|
75
|
+
}
|
|
76
|
+
resolve();
|
|
77
|
+
});
|
|
78
|
+
child.on("error", (err) => {
|
|
79
|
+
onLine(` ${c.failure} ${chalk.red(`Failed to spawn: ${err.message}`)}`);
|
|
80
|
+
resolve();
|
|
81
|
+
});
|
|
82
|
+
});
|
|
83
|
+
}, []);
|
|
84
|
+
const executeInProcess = useCallback(async (input, onLine) => {
|
|
14
85
|
// Capture stdout/stderr
|
|
15
86
|
const originalStdoutWrite = process.stdout.write.bind(process.stdout);
|
|
16
87
|
const originalStderrWrite = process.stderr.write.bind(process.stderr);
|
|
@@ -30,13 +101,11 @@ export function useCommand() {
|
|
|
30
101
|
: Buffer.from(chunk).toString("utf8");
|
|
31
102
|
captureBuffer += str;
|
|
32
103
|
flushBuffer();
|
|
33
|
-
// call callback if provided
|
|
34
104
|
const callback = typeof encodingOrCb === "function" ? encodingOrCb : cb;
|
|
35
105
|
if (callback)
|
|
36
106
|
callback();
|
|
37
107
|
return true;
|
|
38
108
|
};
|
|
39
|
-
// Monkey-patch (cast through unknown to bypass strict overload checking)
|
|
40
109
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
41
110
|
process.stdout.write = capturedWrite;
|
|
42
111
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
@@ -81,9 +150,22 @@ export function useCommand() {
|
|
|
81
150
|
process.stdout.write = originalStdoutWrite;
|
|
82
151
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
83
152
|
process.stderr.write = originalStderrWrite;
|
|
84
|
-
setIsRunning(false);
|
|
85
153
|
}
|
|
86
154
|
}, []);
|
|
155
|
+
const execute = useCallback(async (input, onLine) => {
|
|
156
|
+
setIsRunning(true);
|
|
157
|
+
try {
|
|
158
|
+
if (isInteractiveCommand(input)) {
|
|
159
|
+
await executeInteractive(input, onLine);
|
|
160
|
+
}
|
|
161
|
+
else {
|
|
162
|
+
await executeInProcess(input, onLine);
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
finally {
|
|
166
|
+
setIsRunning(false);
|
|
167
|
+
}
|
|
168
|
+
}, [executeInteractive, executeInProcess]);
|
|
87
169
|
return { execute, isRunning };
|
|
88
170
|
}
|
|
89
171
|
// Shell-style tokenizer
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useCommand.js","sourceRoot":"","sources":["../../src/tui/useCommand.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,WAAW,EAAE,MAAM,OAAO,CAAC;AAC9C,OAAO,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAC9C,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,CAAC,EAAE,MAAM,iBAAiB,CAAC;
|
|
1
|
+
{"version":3,"file":"useCommand.js","sourceRoot":"","sources":["../../src/tui/useCommand.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
package/src/tui/App.tsx
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import React, { useState, useCallback, useEffect } from "react";
|
|
2
2
|
import { createRequire } from "node:module";
|
|
3
|
-
import { Box, Text,
|
|
3
|
+
import { Box, Text, useApp, useInput, useStdout } from "ink";
|
|
4
|
+
import { Header } from "./Header.js";
|
|
4
5
|
import { Viewport } from "./Viewport.js";
|
|
5
6
|
import { Footer } from "./Footer.js";
|
|
6
7
|
import { InputLine } from "./InputLine.js";
|
|
@@ -10,7 +11,6 @@ import { useScroll } from "./useScroll.js";
|
|
|
10
11
|
import { useNotifications } from "./useNotifications.js";
|
|
11
12
|
import { ToastContainer } from "./components/Toast.js";
|
|
12
13
|
import { createProgram } from "../program.js";
|
|
13
|
-
import { getBannerArt, getStatusItems } from "../ui/banner.js";
|
|
14
14
|
import chalk from "chalk";
|
|
15
15
|
|
|
16
16
|
const pkg = createRequire(import.meta.url)("../../package.json") as { version: string };
|
|
@@ -30,30 +30,7 @@ interface AppProps {
|
|
|
30
30
|
export function App({ version, network, wallet, balance }: AppProps) {
|
|
31
31
|
const { exit } = useApp();
|
|
32
32
|
|
|
33
|
-
|
|
34
|
-
const [bannerData] = useState(() => {
|
|
35
|
-
const { artLines, subtitle, separator } = getBannerArt();
|
|
36
|
-
const statusItems = getStatusItems({ network, wallet, balance });
|
|
37
|
-
// Build static items: art lines + subtitle + separator + status + help hint
|
|
38
|
-
const items: { id: string; text: string }[] = [];
|
|
39
|
-
artLines.forEach((line, i) => items.push({ id: `art-${i}`, text: line }));
|
|
40
|
-
items.push({ id: "blank-1", text: "" });
|
|
41
|
-
items.push({ id: "subtitle", text: subtitle });
|
|
42
|
-
items.push({ id: "separator", text: separator });
|
|
43
|
-
if (statusItems.length > 0) {
|
|
44
|
-
items.push({ id: "blank-2", text: "" });
|
|
45
|
-
// Status items as a single formatted line for <Static>
|
|
46
|
-
// (FlexWrap rendering happens in the Header component for non-Static contexts)
|
|
47
|
-
const statusLine = statusItems
|
|
48
|
-
.map((s) => `\x1b[2m${s.label}\x1b[22m ${s.value}`)
|
|
49
|
-
.join(" ");
|
|
50
|
-
items.push({ id: "status", text: ` ${statusLine}` });
|
|
51
|
-
}
|
|
52
|
-
items.push({ id: "blank-3", text: "" });
|
|
53
|
-
items.push({ id: "hint", text: " \x1b[2mType 'help' to get started\x1b[22m" });
|
|
54
|
-
items.push({ id: "blank-4", text: "" });
|
|
55
|
-
return items;
|
|
56
|
-
});
|
|
33
|
+
const { stdout } = useStdout();
|
|
57
34
|
|
|
58
35
|
const [outputBuffer, setOutputBuffer] = useState<string[]>([
|
|
59
36
|
chalk.dim(" Type 'help' to see available commands"),
|
|
@@ -64,11 +41,9 @@ export function App({ version, network, wallet, balance }: AppProps) {
|
|
|
64
41
|
const { execute, isRunning } = useCommand();
|
|
65
42
|
const { send, isSending } = useChat();
|
|
66
43
|
|
|
67
|
-
// Approximate viewport height for scroll management
|
|
68
|
-
const
|
|
69
|
-
const
|
|
70
|
-
const rows = process.stdout.rows ?? 24;
|
|
71
|
-
const viewportHeight = Math.max(1, rows - HEADER_ROWS - FOOTER_ROWS);
|
|
44
|
+
// Approximate viewport height for scroll management (used by useScroll)
|
|
45
|
+
const rows = stdout?.rows ?? process.stdout.rows ?? 24;
|
|
46
|
+
const viewportHeight = Math.max(1, rows - 18);
|
|
72
47
|
|
|
73
48
|
const { scrollOffset, isAutoScroll, scrollUp, scrollDown, snapToBottom } =
|
|
74
49
|
useScroll(viewportHeight);
|
|
@@ -227,16 +202,16 @@ export function App({ version, network, wallet, balance }: AppProps) {
|
|
|
227
202
|
|
|
228
203
|
const isDisabled = isProcessing || isRunning || isSending;
|
|
229
204
|
|
|
205
|
+
const cols = Math.min(stdout?.columns ?? process.stdout.columns ?? 80, 120);
|
|
206
|
+
|
|
230
207
|
return (
|
|
231
208
|
<Box flexDirection="column" height="100%">
|
|
232
|
-
{/* BANNER —
|
|
233
|
-
<
|
|
234
|
-
{(item) => <Text key={item.id}>{item.text}</Text>}
|
|
235
|
-
</Static>
|
|
209
|
+
{/* BANNER — memoized, participates in flex layout */}
|
|
210
|
+
<Header version={version} network={network} wallet={wallet} balance={balance} />
|
|
236
211
|
|
|
237
212
|
{/* Separator */}
|
|
238
|
-
<Box>
|
|
239
|
-
<Text dimColor>{"─".repeat(
|
|
213
|
+
<Box flexShrink={0}>
|
|
214
|
+
<Text dimColor>{"─".repeat(cols)}</Text>
|
|
240
215
|
</Box>
|
|
241
216
|
|
|
242
217
|
{/* VIEWPORT — fills remaining space */}
|
|
@@ -250,8 +225,8 @@ export function App({ version, network, wallet, balance }: AppProps) {
|
|
|
250
225
|
<ToastContainer toasts={toasts} onDismiss={dismissToast} />
|
|
251
226
|
|
|
252
227
|
{/* Bottom separator */}
|
|
253
|
-
<Box>
|
|
254
|
-
<Text dimColor>{"─".repeat(
|
|
228
|
+
<Box flexShrink={0}>
|
|
229
|
+
<Text dimColor>{"─".repeat(cols)}</Text>
|
|
255
230
|
</Box>
|
|
256
231
|
|
|
257
232
|
{/* FOOTER — fixed, input pinned */}
|
package/src/tui/Header.tsx
CHANGED
|
@@ -23,7 +23,7 @@ export const Header = React.memo(function Header({
|
|
|
23
23
|
const statusItems = getStatusItems({ network, wallet, balance });
|
|
24
24
|
|
|
25
25
|
return (
|
|
26
|
-
<Box flexDirection="column">
|
|
26
|
+
<Box flexDirection="column" flexShrink={0}>
|
|
27
27
|
{artLines.map((line, i) => (
|
|
28
28
|
<Text key={i}>{line}</Text>
|
|
29
29
|
))}
|
|
@@ -31,21 +31,15 @@ export const Header = React.memo(function Header({
|
|
|
31
31
|
<Text>{subtitle}</Text>
|
|
32
32
|
<Text>{separator}</Text>
|
|
33
33
|
{statusItems.length > 0 && (
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
<
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
))}
|
|
43
|
-
</Box>
|
|
44
|
-
</>
|
|
34
|
+
<Box flexWrap="wrap" columnGap={2}>
|
|
35
|
+
{statusItems.map((item) => (
|
|
36
|
+
<Box key={item.label}>
|
|
37
|
+
<Text dimColor>{item.label}</Text>
|
|
38
|
+
<Text> {item.value}</Text>
|
|
39
|
+
</Box>
|
|
40
|
+
))}
|
|
41
|
+
</Box>
|
|
45
42
|
)}
|
|
46
|
-
<Text>{""}</Text>
|
|
47
|
-
<Text dimColor>{" Type 'help' to get started"}</Text>
|
|
48
|
-
<Text>{""}</Text>
|
|
49
43
|
</Box>
|
|
50
44
|
);
|
|
51
45
|
});
|
package/src/tui/Viewport.tsx
CHANGED
|
@@ -17,13 +17,10 @@ export function Viewport({ lines, scrollOffset, isAutoScroll }: ViewportProps) {
|
|
|
17
17
|
const { stdout } = useStdout();
|
|
18
18
|
const termRows = stdout?.rows ?? 24;
|
|
19
19
|
|
|
20
|
-
//
|
|
21
|
-
//
|
|
22
|
-
//
|
|
23
|
-
|
|
24
|
-
const HEADER_ROWS = 15; // approximate
|
|
25
|
-
const FOOTER_ROWS = 1;
|
|
26
|
-
const viewportHeight = Math.max(1, termRows - HEADER_ROWS - FOOTER_ROWS);
|
|
20
|
+
// Approximate viewport height for scroll slicing.
|
|
21
|
+
// The actual flex layout handles visual sizing; this is for computing
|
|
22
|
+
// which lines to show in the scroll window.
|
|
23
|
+
const viewportHeight = Math.max(1, termRows - 18);
|
|
27
24
|
|
|
28
25
|
// Compute the window slice
|
|
29
26
|
// scrollOffset=0 → show last viewportHeight lines
|
|
@@ -44,22 +41,16 @@ export function Viewport({ lines, scrollOffset, isAutoScroll }: ViewportProps) {
|
|
|
44
41
|
|
|
45
42
|
const visibleLines = lines.slice(startIdx, endIdx);
|
|
46
43
|
|
|
47
|
-
// Pad with empty lines if fewer than viewportHeight
|
|
48
|
-
const padCount = Math.max(0, viewportHeight - visibleLines.length);
|
|
49
|
-
const paddedLines = [
|
|
50
|
-
...Array(padCount).fill(""),
|
|
51
|
-
...visibleLines,
|
|
52
|
-
];
|
|
53
|
-
|
|
54
44
|
const canScrollDown = scrollOffset > 0;
|
|
55
45
|
|
|
56
46
|
return (
|
|
57
47
|
<Box flexDirection="column" flexGrow={1}>
|
|
58
|
-
<Box flexDirection="column"
|
|
59
|
-
{
|
|
48
|
+
<Box flexDirection="column">
|
|
49
|
+
{visibleLines.map((line, i) => (
|
|
60
50
|
<Text key={i}>{line}</Text>
|
|
61
51
|
))}
|
|
62
52
|
</Box>
|
|
53
|
+
<Box flexGrow={1} /> {/* spacer — pushes content up, scroll indicator down */}
|
|
63
54
|
{canScrollDown && !isAutoScroll && (
|
|
64
55
|
<Box justifyContent="flex-end">
|
|
65
56
|
<Text dimColor>↓ more</Text>
|
package/src/tui/useCommand.ts
CHANGED
|
@@ -1,8 +1,41 @@
|
|
|
1
1
|
import { useState, useCallback } from "react";
|
|
2
|
+
import { spawn } from "node:child_process";
|
|
2
3
|
import { createProgram } from "../program.js";
|
|
3
4
|
import chalk from "chalk";
|
|
4
5
|
import { c } from "../ui/colors.js";
|
|
5
6
|
|
|
7
|
+
const INTERACTIVE_COMMANDS = new Set([
|
|
8
|
+
"wallet deploy",
|
|
9
|
+
"wallet set-guardian",
|
|
10
|
+
"wallet unfreeze",
|
|
11
|
+
"wallet authorize-machine-key",
|
|
12
|
+
"wallet revoke-machine-key",
|
|
13
|
+
"wallet set-passkey",
|
|
14
|
+
"wallet set-interceptor",
|
|
15
|
+
"wallet set-velocity-limit",
|
|
16
|
+
"wallet upgrade-registry",
|
|
17
|
+
"wallet execute-registry-upgrade",
|
|
18
|
+
"wallet cancel-registry-upgrade",
|
|
19
|
+
"wallet register-policy",
|
|
20
|
+
"wallet whitelist-contract",
|
|
21
|
+
"wallet governance setup",
|
|
22
|
+
"wallet policy set-limit",
|
|
23
|
+
"wallet policy set-daily-limit",
|
|
24
|
+
"wallet policy set",
|
|
25
|
+
"wallet import",
|
|
26
|
+
"config init",
|
|
27
|
+
]);
|
|
28
|
+
|
|
29
|
+
function isInteractiveCommand(input: string): boolean {
|
|
30
|
+
const trimmed = input.trim();
|
|
31
|
+
for (const cmd of INTERACTIVE_COMMANDS) {
|
|
32
|
+
if (trimmed === cmd || trimmed.startsWith(cmd + " ")) {
|
|
33
|
+
return true;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
return false;
|
|
37
|
+
}
|
|
38
|
+
|
|
6
39
|
interface UseCommandResult {
|
|
7
40
|
execute: (input: string, onLine: (line: string) => void) => Promise<void>;
|
|
8
41
|
isRunning: boolean;
|
|
@@ -10,16 +43,61 @@ interface UseCommandResult {
|
|
|
10
43
|
|
|
11
44
|
/**
|
|
12
45
|
* Dispatches parsed commands to the commander program.
|
|
13
|
-
*
|
|
14
|
-
*
|
|
46
|
+
* Interactive commands (WalletConnect, prompts) spawn a child process
|
|
47
|
+
* because Ink holds stdin in raw mode.
|
|
48
|
+
* Non-interactive commands run in-process with stdout monkey-patching.
|
|
15
49
|
*/
|
|
16
50
|
export function useCommand(): UseCommandResult {
|
|
17
51
|
const [isRunning, setIsRunning] = useState(false);
|
|
18
52
|
|
|
19
|
-
const
|
|
20
|
-
|
|
21
|
-
|
|
53
|
+
const executeInteractive = useCallback(
|
|
54
|
+
(input: string, onLine: (line: string) => void): Promise<void> => {
|
|
55
|
+
return new Promise((resolve) => {
|
|
56
|
+
const tokens = parseTokens(input);
|
|
57
|
+
|
|
58
|
+
const child = spawn(process.execPath, [process.argv[1], ...tokens], {
|
|
59
|
+
stdio: ["inherit", "pipe", "pipe"],
|
|
60
|
+
env: { ...process.env, ARC402_NO_TUI: "1", FORCE_COLOR: "1" },
|
|
61
|
+
cwd: process.cwd(),
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
let stdoutRemainder = "";
|
|
65
|
+
let stderrRemainder = "";
|
|
66
|
+
|
|
67
|
+
child.stdout?.on("data", (chunk: Buffer) => {
|
|
68
|
+
stdoutRemainder += chunk.toString("utf8");
|
|
69
|
+
const lines = stdoutRemainder.split("\n");
|
|
70
|
+
stdoutRemainder = lines.pop() ?? "";
|
|
71
|
+
for (const line of lines) onLine(line);
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
child.stderr?.on("data", (chunk: Buffer) => {
|
|
75
|
+
stderrRemainder += chunk.toString("utf8");
|
|
76
|
+
const lines = stderrRemainder.split("\n");
|
|
77
|
+
stderrRemainder = lines.pop() ?? "";
|
|
78
|
+
for (const line of lines) onLine(line);
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
child.on("close", (code) => {
|
|
82
|
+
if (stdoutRemainder.trim()) onLine(stdoutRemainder);
|
|
83
|
+
if (stderrRemainder.trim()) onLine(stderrRemainder);
|
|
84
|
+
if (code !== 0 && code !== null) {
|
|
85
|
+
onLine(` ${c.failure} ${chalk.red(`Command exited with code ${code}`)}`);
|
|
86
|
+
}
|
|
87
|
+
resolve();
|
|
88
|
+
});
|
|
22
89
|
|
|
90
|
+
child.on("error", (err) => {
|
|
91
|
+
onLine(` ${c.failure} ${chalk.red(`Failed to spawn: ${err.message}`)}`);
|
|
92
|
+
resolve();
|
|
93
|
+
});
|
|
94
|
+
});
|
|
95
|
+
},
|
|
96
|
+
[]
|
|
97
|
+
);
|
|
98
|
+
|
|
99
|
+
const executeInProcess = useCallback(
|
|
100
|
+
async (input: string, onLine: (line: string) => void): Promise<void> => {
|
|
23
101
|
// Capture stdout/stderr
|
|
24
102
|
const originalStdoutWrite = process.stdout.write.bind(process.stdout);
|
|
25
103
|
const originalStderrWrite = process.stderr.write.bind(process.stderr);
|
|
@@ -46,14 +124,12 @@ export function useCommand(): UseCommandResult {
|
|
|
46
124
|
: Buffer.from(chunk).toString("utf8");
|
|
47
125
|
captureBuffer += str;
|
|
48
126
|
flushBuffer();
|
|
49
|
-
// call callback if provided
|
|
50
127
|
const callback =
|
|
51
128
|
typeof encodingOrCb === "function" ? encodingOrCb : cb;
|
|
52
129
|
if (callback) callback();
|
|
53
130
|
return true;
|
|
54
131
|
};
|
|
55
132
|
|
|
56
|
-
// Monkey-patch (cast through unknown to bypass strict overload checking)
|
|
57
133
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
58
134
|
(process.stdout as any).write = capturedWrite;
|
|
59
135
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
@@ -100,11 +176,25 @@ export function useCommand(): UseCommandResult {
|
|
|
100
176
|
(process.stdout as any).write = originalStdoutWrite;
|
|
101
177
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
102
178
|
(process.stderr as any).write = originalStderrWrite;
|
|
179
|
+
}
|
|
180
|
+
},
|
|
181
|
+
[]
|
|
182
|
+
);
|
|
103
183
|
|
|
184
|
+
const execute = useCallback(
|
|
185
|
+
async (input: string, onLine: (line: string) => void): Promise<void> => {
|
|
186
|
+
setIsRunning(true);
|
|
187
|
+
try {
|
|
188
|
+
if (isInteractiveCommand(input)) {
|
|
189
|
+
await executeInteractive(input, onLine);
|
|
190
|
+
} else {
|
|
191
|
+
await executeInProcess(input, onLine);
|
|
192
|
+
}
|
|
193
|
+
} finally {
|
|
104
194
|
setIsRunning(false);
|
|
105
195
|
}
|
|
106
196
|
},
|
|
107
|
-
[]
|
|
197
|
+
[executeInteractive, executeInProcess]
|
|
108
198
|
);
|
|
109
199
|
|
|
110
200
|
return { execute, isRunning };
|