centaurus-cli 3.1.1 → 3.1.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/index.js +4 -0
- package/dist/index.js.map +1 -1
- package/dist/ui/components/App.js +2 -2
- package/dist/ui/components/App.js.map +1 -1
- package/dist/ui/components/AuthWelcomeScreen.js +1 -2
- package/dist/ui/components/AuthWelcomeScreen.js.map +1 -1
- package/dist/ui/components/VersionUpdatePrompt.js +31 -2
- package/dist/ui/components/VersionUpdatePrompt.js.map +1 -1
- package/dist/utils/ink-static-render.js +25 -0
- package/dist/utils/ink-static-render.js.map +1 -0
- package/package.json +1 -1
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import React from "react";
|
|
2
2
|
import { Box, Text } from "ink";
|
|
3
|
-
import { WelcomeBanner } from "./WelcomeBanner.js";
|
|
4
3
|
import { SelectPrompt } from "./SelectPrompt.js";
|
|
5
4
|
const AuthWelcomeScreen = ({
|
|
6
5
|
onSignIn,
|
|
@@ -13,7 +12,7 @@ const AuthWelcomeScreen = ({
|
|
|
13
12
|
onExit();
|
|
14
13
|
}
|
|
15
14
|
};
|
|
16
|
-
return /* @__PURE__ */ React.createElement(Box, { flexDirection: "column" }, /* @__PURE__ */ React.createElement(
|
|
15
|
+
return /* @__PURE__ */ React.createElement(Box, { flexDirection: "column" }, /* @__PURE__ */ React.createElement(Box, { flexDirection: "column", marginTop: 1, marginBottom: 1, paddingX: 1 }, /* @__PURE__ */ React.createElement(Box, { marginBottom: 1 }, /* @__PURE__ */ React.createElement(Text, { bold: true, color: "#00ccff" }, "\u{1F510} Authentication Required")), /* @__PURE__ */ React.createElement(Box, { marginBottom: 1 }, /* @__PURE__ */ React.createElement(Text, null, "To use Centaurus CLI, you need to sign in with Google."))), /* @__PURE__ */ React.createElement(Box, { paddingX: 1 }, /* @__PURE__ */ React.createElement(
|
|
17
16
|
SelectPrompt,
|
|
18
17
|
{
|
|
19
18
|
message: "What would you like to do?",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/ui/components/AuthWelcomeScreen.tsx"],"sourcesContent":["import React
|
|
1
|
+
{"version":3,"sources":["../../../src/ui/components/AuthWelcomeScreen.tsx"],"sourcesContent":["import React from 'react';\r\nimport { Box, Text } from 'ink';\r\nimport { SelectPrompt } from './SelectPrompt.js';\r\n\r\ninterface AuthWelcomeScreenProps {\r\n onSignIn: () => void;\r\n onExit: () => void;\r\n}\r\n\r\nexport const AuthWelcomeScreen: React.FC<AuthWelcomeScreenProps> = ({\r\n onSignIn,\r\n onExit,\r\n}) => {\r\n const handleSelect = (value: string) => {\r\n if (value === 'signin') {\r\n onSignIn();\r\n } else {\r\n onExit();\r\n }\r\n };\r\n\r\n return (\r\n <Box flexDirection=\"column\">\r\n {/* Authentication Info */}\r\n <Box flexDirection=\"column\" marginTop={1} marginBottom={1} paddingX={1}>\r\n <Box marginBottom={1}>\r\n <Text bold color=\"#00ccff\">🔐 Authentication Required</Text>\r\n </Box>\r\n\r\n <Box marginBottom={1}>\r\n <Text>\r\n To use Centaurus CLI, you need to sign in with Google.\r\n </Text>\r\n </Box>\r\n </Box>\r\n\r\n {/* Picker */}\r\n <Box paddingX={1}>\r\n <SelectPrompt\r\n message=\"What would you like to do?\"\r\n choices={[\r\n { label: '🔑 Sign in with Google', value: 'signin' },\r\n { label: '❌ Exit', value: 'exit' },\r\n ]}\r\n onSelect={handleSelect}\r\n width={(process.stdout.columns || 120) - 2}\r\n />\r\n </Box>\r\n </Box>\r\n );\r\n};\r\n"],"mappings":"AAAA,OAAO,WAAW;AAClB,SAAS,KAAK,YAAY;AAC1B,SAAS,oBAAoB;AAOtB,MAAM,oBAAsD,CAAC;AAAA,EAClE;AAAA,EACA;AACF,MAAM;AACJ,QAAM,eAAe,CAAC,UAAkB;AACtC,QAAI,UAAU,UAAU;AACtB,eAAS;AAAA,IACX,OAAO;AACL,aAAO;AAAA,IACT;AAAA,EACF;AAEA,SACE,oCAAC,OAAI,eAAc,YAEjB,oCAAC,OAAI,eAAc,UAAS,WAAW,GAAG,cAAc,GAAG,UAAU,KACnE,oCAAC,OAAI,cAAc,KACjB,oCAAC,QAAK,MAAI,MAAC,OAAM,aAAU,mCAA0B,CACvD,GAEA,oCAAC,OAAI,cAAc,KACjB,oCAAC,YAAK,wDAEN,CACF,CACF,GAGA,oCAAC,OAAI,UAAU,KACb;AAAA,IAAC;AAAA;AAAA,MACC,SAAQ;AAAA,MACR,SAAS;AAAA,QACP,EAAE,OAAO,iCAA0B,OAAO,SAAS;AAAA,QACnD,EAAE,OAAO,eAAU,OAAO,OAAO;AAAA,MACnC;AAAA,MACA,UAAU;AAAA,MACV,QAAQ,QAAQ,OAAO,WAAW,OAAO;AAAA;AAAA,EAC3C,CACF,CACF;AAEJ;","names":[]}
|
|
@@ -3,6 +3,32 @@ import { Box, Text, useApp } from "ink";
|
|
|
3
3
|
import Spinner from "ink-spinner";
|
|
4
4
|
import { spawn } from "child_process";
|
|
5
5
|
import { logInfo } from "../../utils/logger.js";
|
|
6
|
+
function writeStaticUpdateHeader(currentVersion, latestVersion) {
|
|
7
|
+
const cols = process.stdout.columns || 80;
|
|
8
|
+
const innerW = Math.max(cols - 4, 40);
|
|
9
|
+
const cyan = "\x1B[36m";
|
|
10
|
+
const green = "\x1B[32m";
|
|
11
|
+
const dim = "\x1B[2m";
|
|
12
|
+
const bold = "\x1B[1m";
|
|
13
|
+
const reset = "\x1B[0m";
|
|
14
|
+
const top = `${cyan}\u256D${"\u2500".repeat(innerW)}\u256E${reset}`;
|
|
15
|
+
const bottom = `${cyan}\u2502${" ".repeat(innerW)}\u2502${reset}`;
|
|
16
|
+
const border = (line) => {
|
|
17
|
+
const plainLen = line.replace(/\x1b\[[0-9;]*m/g, "").length;
|
|
18
|
+
const pad = Math.max(0, innerW - plainLen);
|
|
19
|
+
return `${cyan}\u2502${reset} ${line}${" ".repeat(pad > 0 ? pad - 1 : 0)}${cyan}\u2502${reset}`;
|
|
20
|
+
};
|
|
21
|
+
const lines = [
|
|
22
|
+
top,
|
|
23
|
+
border(`${cyan}${bold}\u{1F680} New Update Available!${reset}`),
|
|
24
|
+
border(""),
|
|
25
|
+
border(`Current: ${dim}${currentVersion}${reset} \u2192 Latest: ${green}${bold}${latestVersion}${reset}`),
|
|
26
|
+
border(""),
|
|
27
|
+
border(`${dim}Please wait while we update Centaurus to the latest version.${reset}`),
|
|
28
|
+
border("")
|
|
29
|
+
];
|
|
30
|
+
process.stdout.write(lines.join("\n") + "\n");
|
|
31
|
+
}
|
|
6
32
|
const VersionUpdatePrompt = ({
|
|
7
33
|
currentVersion,
|
|
8
34
|
latestVersion,
|
|
@@ -11,9 +37,12 @@ const VersionUpdatePrompt = ({
|
|
|
11
37
|
const [status, setStatus] = useState("pending");
|
|
12
38
|
const [errorMessage, setErrorMessage] = useState("");
|
|
13
39
|
const hasStartedRef = useRef(false);
|
|
40
|
+
const headerWrittenRef = useRef(false);
|
|
14
41
|
const { exit } = useApp();
|
|
15
42
|
useEffect(() => {
|
|
16
|
-
|
|
43
|
+
if (headerWrittenRef.current) return;
|
|
44
|
+
headerWrittenRef.current = true;
|
|
45
|
+
writeStaticUpdateHeader(currentVersion, latestVersion);
|
|
17
46
|
}, []);
|
|
18
47
|
useEffect(() => {
|
|
19
48
|
if (hasStartedRef.current) return;
|
|
@@ -83,7 +112,7 @@ const VersionUpdatePrompt = ({
|
|
|
83
112
|
logInfo('User should run "centaurus" to start the updated CLI.');
|
|
84
113
|
process.exit(0);
|
|
85
114
|
};
|
|
86
|
-
return /* @__PURE__ */ React.createElement(Box, { flexDirection: "column"
|
|
115
|
+
return /* @__PURE__ */ React.createElement(Box, { flexDirection: "column" }, status === "pending" && /* @__PURE__ */ React.createElement(Text, { color: "yellow" }, /* @__PURE__ */ React.createElement(Spinner, { type: "dots" }), " Preparing to update..."), status === "installing" && /* @__PURE__ */ React.createElement(Text, { color: "cyan" }, /* @__PURE__ */ React.createElement(Spinner, { type: "dots" }), " Installing update..."), status === "success" && /* @__PURE__ */ React.createElement(Text, { color: "green", bold: true }, "\u2705 Update successful! Restarting Centaurus..."), status === "error" && /* @__PURE__ */ React.createElement(Box, { flexDirection: "column" }, /* @__PURE__ */ React.createElement(Text, { color: "red", bold: true }, "\u274C Update Failed"), /* @__PURE__ */ React.createElement(Text, { color: "yellow" }, errorMessage), /* @__PURE__ */ React.createElement(Text, { dimColor: true }, "Continuing to chat in a few seconds...")));
|
|
87
116
|
};
|
|
88
117
|
export {
|
|
89
118
|
VersionUpdatePrompt
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/ui/components/VersionUpdatePrompt.tsx"],"sourcesContent":["import React, { useState, useEffect, useRef } from 'react';\r\nimport { Box, Text, useApp } from 'ink';\r\nimport Spinner from 'ink-spinner';\r\nimport { spawn } from 'child_process';\r\nimport { logInfo } from '../../utils/logger.js';\r\n\r\ninterface VersionUpdatePromptProps {\r\n currentVersion: string;\r\n latestVersion: string;\r\n onComplete: () => void;\r\n}\r\n\r\ntype UpdateStatus = 'pending' | 'installing' | 'success' | 'error';\r\n\r\nexport const VersionUpdatePrompt: React.FC<VersionUpdatePromptProps> = ({\r\n currentVersion,\r\n latestVersion,\r\n onComplete\r\n}) => {\r\n const [status, setStatus] = useState<UpdateStatus>('pending');\r\n const [errorMessage, setErrorMessage] = useState<string>('');\r\n const hasStartedRef = useRef(false);\r\n const { exit } = useApp();\r\n\r\n //
|
|
1
|
+
{"version":3,"sources":["../../../src/ui/components/VersionUpdatePrompt.tsx"],"sourcesContent":["import React, { useState, useEffect, useRef } from 'react';\r\nimport { Box, Text, useApp } from 'ink';\r\nimport Spinner from 'ink-spinner';\r\nimport { spawn } from 'child_process';\r\nimport { logInfo } from '../../utils/logger.js';\r\n\r\ninterface VersionUpdatePromptProps {\r\n currentVersion: string;\r\n latestVersion: string;\r\n onComplete: () => void;\r\n}\r\n\r\ntype UpdateStatus = 'pending' | 'installing' | 'success' | 'error';\r\n\r\n/**\r\n * Static header block written once to stdout.\r\n * This content never re-renders, avoiding the banner/duplicate flicker\r\n * that happens when Ink redraws on every spinner tick.\r\n */\r\nfunction writeStaticUpdateHeader(currentVersion: string, latestVersion: string): void {\r\n const cols = process.stdout.columns || 80;\r\n const innerW = Math.max(cols - 4, 40);\r\n const cyan = '\\x1b[36m';\r\n const green = '\\x1b[32m';\r\n const dim = '\\x1b[2m';\r\n const bold = '\\x1b[1m';\r\n const reset = '\\x1b[0m';\r\n\r\n const top = `${cyan}╭${'─'.repeat(innerW)}╮${reset}`;\r\n const bottom = `${cyan}│${' '.repeat(innerW)}│${reset}`;\r\n const border = (line: string) => {\r\n // Pad line to fill the box width (accounting for ANSI codes)\r\n const plainLen = line.replace(/\\x1b\\[[0-9;]*m/g, '').length;\r\n const pad = Math.max(0, innerW - plainLen);\r\n return `${cyan}│${reset} ${line}${' '.repeat(pad > 0 ? pad - 1 : 0)}${cyan}│${reset}`;\r\n };\r\n\r\n const lines = [\r\n top,\r\n border(`${cyan}${bold}🚀 New Update Available!${reset}`),\r\n border(''),\r\n border(`Current: ${dim}${currentVersion}${reset} → Latest: ${green}${bold}${latestVersion}${reset}`),\r\n border(''),\r\n border(`${dim}Please wait while we update Centaurus to the latest version.${reset}`),\r\n border(''),\r\n ];\r\n\r\n process.stdout.write(lines.join('\\n') + '\\n');\r\n}\r\n\r\nexport const VersionUpdatePrompt: React.FC<VersionUpdatePromptProps> = ({\r\n currentVersion,\r\n latestVersion,\r\n onComplete\r\n}) => {\r\n const [status, setStatus] = useState<UpdateStatus>('pending');\r\n const [errorMessage, setErrorMessage] = useState<string>('');\r\n const hasStartedRef = useRef(false);\r\n const headerWrittenRef = useRef(false);\r\n const { exit } = useApp();\r\n\r\n // Write static header once — this is outside Ink's render cycle\r\n useEffect(() => {\r\n if (headerWrittenRef.current) return;\r\n headerWrittenRef.current = true;\r\n writeStaticUpdateHeader(currentVersion, latestVersion);\r\n }, []);\r\n\r\n // Auto-start installation after a brief delay\r\n useEffect(() => {\r\n if (hasStartedRef.current) return;\r\n hasStartedRef.current = true;\r\n\r\n const timer = setTimeout(() => {\r\n setStatus('installing');\r\n performUpdate();\r\n }, 1500); // Brief delay so user can see the update notification\r\n\r\n return () => clearTimeout(timer);\r\n }, []);\r\n\r\n const performUpdate = () => {\r\n // Determine the package manager - prefer npm as it's most commonly used\r\n const isWindows = process.platform === 'win32';\r\n const npmCmd = isWindows ? 'npm.cmd' : 'npm';\r\n\r\n const installProcess = spawn(\r\n npmCmd,\r\n ['install', '-g', 'centaurus-cli@latest'],\r\n {\r\n shell: true,\r\n stdio: 'pipe', // Capture output for error handling\r\n detached: false\r\n }\r\n );\r\n\r\n let stderrOutput = '';\r\n let stdoutOutput = '';\r\n\r\n if (installProcess.stdout) {\r\n installProcess.stdout.on('data', (data) => {\r\n stdoutOutput += data.toString();\r\n });\r\n }\r\n\r\n if (installProcess.stderr) {\r\n installProcess.stderr.on('data', (data) => {\r\n stderrOutput += data.toString();\r\n });\r\n }\r\n\r\n installProcess.on('error', (err) => {\r\n setStatus('error');\r\n setErrorMessage(`Failed to start update: ${err.message}`);\r\n });\r\n\r\n installProcess.on('close', (code) => {\r\n if (code === 0) {\r\n setStatus('success');\r\n // Wait a moment so user can see success message, then restart\r\n setTimeout(() => {\r\n restartCLI();\r\n }, 1500);\r\n } else {\r\n setStatus('error');\r\n // Parse common error messages for better user feedback\r\n let friendlyError = 'Update failed. Please try manually: npm install -g centaurus-cli@latest';\r\n\r\n if (stderrOutput.includes('EACCES') || stderrOutput.includes('permission')) {\r\n friendlyError = 'Permission denied. Try running with sudo (Linux/Mac) or as Administrator (Windows).';\r\n } else if (stderrOutput.includes('ENOTFOUND') || stderrOutput.includes('network')) {\r\n friendlyError = 'Network error. Please check your internet connection and try again.';\r\n } else if (stderrOutput.includes('ETIMEOUT')) {\r\n friendlyError = 'Connection timed out. Please check your internet connection and try again.';\r\n }\r\n\r\n setErrorMessage(friendlyError);\r\n\r\n // After showing error, continue to chat after a delay\r\n setTimeout(() => {\r\n onComplete();\r\n }, 5000);\r\n }\r\n });\r\n };\r\n\r\n const restartCLI = () => {\r\n // Exit the Ink app first\r\n exit();\r\n\r\n // Clear screen and show success message\r\n process.stdout.write('\\x1b[2J\\x1b[3J\\x1b[H');\r\n logInfo('Update complete! Centaurus has been updated to the latest version.');\r\n logInfo('User should run \"centaurus\" to start the updated CLI.');\r\n\r\n process.exit(0);\r\n };\r\n\r\n // Only the dynamic status line is rendered via Ink — this is the only part\r\n // that re-renders on spinner ticks, keeping the banner/header stable.\r\n return (\r\n <Box flexDirection=\"column\">\r\n {status === 'pending' && (\r\n <Text color=\"yellow\">\r\n <Spinner type=\"dots\" /> Preparing to update...\r\n </Text>\r\n )}\r\n\r\n {status === 'installing' && (\r\n <Text color=\"cyan\">\r\n <Spinner type=\"dots\" /> Installing update...\r\n </Text>\r\n )}\r\n\r\n {status === 'success' && (\r\n <Text color=\"green\" bold>✅ Update successful! Restarting Centaurus...</Text>\r\n )}\r\n\r\n {status === 'error' && (\r\n <Box flexDirection=\"column\">\r\n <Text color=\"red\" bold>❌ Update Failed</Text>\r\n <Text color=\"yellow\">{errorMessage}</Text>\r\n <Text dimColor>Continuing to chat in a few seconds...</Text>\r\n </Box>\r\n )}\r\n </Box>\r\n );\r\n};\r\n"],"mappings":"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","names":[]}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { render } from "ink";
|
|
2
|
+
import { Writable } from "stream";
|
|
3
|
+
function renderToString(element) {
|
|
4
|
+
let output = "";
|
|
5
|
+
const fakeStdout = new Writable({
|
|
6
|
+
write(chunk, _encoding, callback) {
|
|
7
|
+
output += chunk.toString();
|
|
8
|
+
callback();
|
|
9
|
+
}
|
|
10
|
+
});
|
|
11
|
+
fakeStdout.columns = process.stdout.columns || 120;
|
|
12
|
+
fakeStdout.rows = process.stdout.rows || 40;
|
|
13
|
+
const { unmount, cleanup } = render(element, {
|
|
14
|
+
stdout: fakeStdout,
|
|
15
|
+
patchConsole: false,
|
|
16
|
+
exitOnCtrlC: false
|
|
17
|
+
});
|
|
18
|
+
unmount();
|
|
19
|
+
cleanup();
|
|
20
|
+
return output.replace(/\x1b\[\?25[lh]/g, "").replace(/\x1b\[J/g, "").trimEnd();
|
|
21
|
+
}
|
|
22
|
+
export {
|
|
23
|
+
renderToString
|
|
24
|
+
};
|
|
25
|
+
//# sourceMappingURL=ink-static-render.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/utils/ink-static-render.ts"],"sourcesContent":["/**\r\n * Render an Ink (React) element to a string.\r\n *\r\n * This spins up a short-lived Ink instance whose stdout is a custom\r\n * writable stream that captures output in memory. The instance is\r\n * immediately unmounted so it never enters the event loop, and the\r\n * captured string is returned.\r\n *\r\n * Use this for \"print once\" content (e.g. the welcome banner) that\r\n * should not participate in a later interactive Ink render tree.\r\n */\r\n\r\nimport { render } from 'ink';\r\nimport { Writable } from 'stream';\r\n\r\nexport function renderToString(element: React.ReactElement): string {\r\n let output = '';\r\n\r\n // Create a writable stream that accumulates chunks in memory\r\n const fakeStdout = new Writable({\r\n write(chunk, _encoding, callback) {\r\n output += chunk.toString();\r\n callback();\r\n },\r\n });\r\n\r\n // Ink needs `.columns` on the stream to compute layout widths.\r\n // Mirror the real terminal width.\r\n (fakeStdout as any).columns = process.stdout.columns || 120;\r\n (fakeStdout as any).rows = process.stdout.rows || 40;\r\n\r\n const { unmount, cleanup } = render(element, {\r\n stdout: fakeStdout as any,\r\n patchConsole: false,\r\n exitOnCtrlC: false,\r\n });\r\n\r\n unmount();\r\n cleanup();\r\n\r\n // Ink wraps output in cursor-hide / cursor-show escape sequences\r\n // and may include trailing clear sequences. Strip them so we get\r\n // just the visible content.\r\n return output\r\n .replace(/\\x1b\\[\\?25[lh]/g, '') // cursor hide / show\r\n .replace(/\\x1b\\[J/g, '') // erase-to-end\r\n .trimEnd();\r\n}\r\n"],"mappings":"AAYA,SAAS,cAAc;AACvB,SAAS,gBAAgB;AAElB,SAAS,eAAe,SAAqC;AAChE,MAAI,SAAS;AAGb,QAAM,aAAa,IAAI,SAAS;AAAA,IAC5B,MAAM,OAAO,WAAW,UAAU;AAC9B,gBAAU,MAAM,SAAS;AACzB,eAAS;AAAA,IACb;AAAA,EACJ,CAAC;AAID,EAAC,WAAmB,UAAU,QAAQ,OAAO,WAAW;AACxD,EAAC,WAAmB,OAAO,QAAQ,OAAO,QAAQ;AAElD,QAAM,EAAE,SAAS,QAAQ,IAAI,OAAO,SAAS;AAAA,IACzC,QAAQ;AAAA,IACR,cAAc;AAAA,IACd,aAAa;AAAA,EACjB,CAAC;AAED,UAAQ;AACR,UAAQ;AAKR,SAAO,OACF,QAAQ,mBAAmB,EAAE,EAC7B,QAAQ,YAAY,EAAE,EACtB,QAAQ;AACjB;","names":[]}
|