taskair-cli 1.0.5 → 1.0.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.
- package/dist/index.js +309 -129
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -981,6 +981,50 @@ function computeStats() {
|
|
|
981
981
|
};
|
|
982
982
|
}
|
|
983
983
|
|
|
984
|
+
// src/lib/crypto.ts
|
|
985
|
+
import {
|
|
986
|
+
pbkdf2Sync,
|
|
987
|
+
createCipheriv,
|
|
988
|
+
createDecipheriv,
|
|
989
|
+
randomBytes,
|
|
990
|
+
createHash
|
|
991
|
+
} from "crypto";
|
|
992
|
+
var PBKDF2_ITERATIONS = 1e5;
|
|
993
|
+
var KEY_LENGTH = 32;
|
|
994
|
+
var SALT_LENGTH = 16;
|
|
995
|
+
var IV_LENGTH = 16;
|
|
996
|
+
function deriveMasterKey(password, salt) {
|
|
997
|
+
return pbkdf2Sync(password, salt, PBKDF2_ITERATIONS, KEY_LENGTH, "sha256");
|
|
998
|
+
}
|
|
999
|
+
function deriveEncryptionKey(masterKey) {
|
|
1000
|
+
const hash = createHash("sha256");
|
|
1001
|
+
hash.update(masterKey);
|
|
1002
|
+
hash.update("taskair-encryption");
|
|
1003
|
+
return hash.digest();
|
|
1004
|
+
}
|
|
1005
|
+
function encrypt(plaintext, password) {
|
|
1006
|
+
const salt = randomBytes(SALT_LENGTH);
|
|
1007
|
+
const iv = randomBytes(IV_LENGTH);
|
|
1008
|
+
const masterKey = deriveMasterKey(password, salt);
|
|
1009
|
+
const encKey = deriveEncryptionKey(masterKey);
|
|
1010
|
+
const cipher = createCipheriv("aes-256-gcm", encKey, iv);
|
|
1011
|
+
const encrypted = Buffer.concat([
|
|
1012
|
+
cipher.update(plaintext, "utf8"),
|
|
1013
|
+
cipher.final()
|
|
1014
|
+
]);
|
|
1015
|
+
const authTag = cipher.getAuthTag();
|
|
1016
|
+
return {
|
|
1017
|
+
version: "1",
|
|
1018
|
+
salt: salt.toString("base64"),
|
|
1019
|
+
iv: iv.toString("base64"),
|
|
1020
|
+
ciphertext: encrypted.toString("base64"),
|
|
1021
|
+
authTag: authTag.toString("base64")
|
|
1022
|
+
};
|
|
1023
|
+
}
|
|
1024
|
+
function checksum(plaintext) {
|
|
1025
|
+
return createHash("sha256").update(plaintext).digest("hex");
|
|
1026
|
+
}
|
|
1027
|
+
|
|
984
1028
|
// src/commands/add.tsx
|
|
985
1029
|
import { jsx as jsx8, jsxs as jsxs8 } from "react/jsx-runtime";
|
|
986
1030
|
function AddUI({
|
|
@@ -991,32 +1035,72 @@ function AddUI({
|
|
|
991
1035
|
}) {
|
|
992
1036
|
const { exit } = useApp4();
|
|
993
1037
|
const [status, setStatus] = useState6("working");
|
|
1038
|
+
const [syncStatus, setSyncStatus] = useState6("idle");
|
|
1039
|
+
const [syncMessage, setSyncMessage] = useState6("");
|
|
994
1040
|
const [taskId, setTaskId] = useState6("");
|
|
995
1041
|
const [errorMsg, setErrorMsg] = useState6("");
|
|
996
1042
|
useEffect6(() => {
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
|
|
1043
|
+
async function createTaskAndSync() {
|
|
1044
|
+
try {
|
|
1045
|
+
const auth = requireAuth();
|
|
1046
|
+
const task = {
|
|
1047
|
+
id: uuidv42(),
|
|
1048
|
+
description,
|
|
1049
|
+
priority,
|
|
1050
|
+
status: "pending",
|
|
1051
|
+
tags,
|
|
1052
|
+
due_date: due,
|
|
1053
|
+
created_at: (/* @__PURE__ */ new Date()).toISOString(),
|
|
1054
|
+
updated_at: (/* @__PURE__ */ new Date()).toISOString(),
|
|
1055
|
+
device_id: auth.deviceId,
|
|
1056
|
+
vector_clock: { [auth.deviceId]: 1 }
|
|
1057
|
+
};
|
|
1058
|
+
insertTask(task);
|
|
1059
|
+
setTaskId(task.id.slice(0, 8));
|
|
1060
|
+
setStatus("success");
|
|
1061
|
+
setSyncStatus("syncing");
|
|
1062
|
+
const tasks = getAllTasks();
|
|
1063
|
+
const bundle = {
|
|
1064
|
+
tasks,
|
|
1065
|
+
schema_version: "1",
|
|
1066
|
+
exported_at: (/* @__PURE__ */ new Date()).toISOString()
|
|
1067
|
+
};
|
|
1068
|
+
const plaintext = JSON.stringify(bundle);
|
|
1069
|
+
const blobChecksum = checksum(plaintext);
|
|
1070
|
+
const syncPassword = auth.password;
|
|
1071
|
+
if (!syncPassword) {
|
|
1072
|
+
setSyncStatus("failed");
|
|
1073
|
+
setSyncMessage('Encryption password required. Run "taskair sync --password <pwd>".');
|
|
1074
|
+
setTimeout(() => exit(), 3e3);
|
|
1075
|
+
return;
|
|
1076
|
+
}
|
|
1077
|
+
const blob = encrypt(plaintext, syncPassword);
|
|
1078
|
+
const res = await apiUploadSync(
|
|
1079
|
+
auth.apiUrl,
|
|
1080
|
+
auth.accessToken,
|
|
1081
|
+
blob,
|
|
1082
|
+
blobChecksum,
|
|
1083
|
+
auth.deviceId
|
|
1084
|
+
);
|
|
1085
|
+
if (res.success) {
|
|
1086
|
+
clearSyncQueue();
|
|
1087
|
+
setSyncStatus("synced");
|
|
1088
|
+
setTimeout(() => exit(), 2e3);
|
|
1089
|
+
} else if (res.error?.code === "NETWORK_ERROR") {
|
|
1090
|
+
setSyncStatus("offline");
|
|
1091
|
+
setTimeout(() => exit(), 2500);
|
|
1092
|
+
} else {
|
|
1093
|
+
setSyncStatus("failed");
|
|
1094
|
+
setSyncMessage(res.error?.message ?? "Sync failed");
|
|
1095
|
+
setTimeout(() => exit(), 3500);
|
|
1096
|
+
}
|
|
1097
|
+
} catch (e) {
|
|
1098
|
+
setErrorMsg(e.message);
|
|
1099
|
+
setStatus("error");
|
|
1100
|
+
setTimeout(() => exit(e), 2e3);
|
|
1101
|
+
}
|
|
1019
1102
|
}
|
|
1103
|
+
createTaskAndSync();
|
|
1020
1104
|
}, []);
|
|
1021
1105
|
return /* @__PURE__ */ jsxs8(Box8, { flexDirection: "column", padding: 1, children: [
|
|
1022
1106
|
/* @__PURE__ */ jsx8(MiniHeader, {}),
|
|
@@ -1048,14 +1132,13 @@ function AddUI({
|
|
|
1048
1132
|
/* @__PURE__ */ jsx8(Text8, { color: "#7B61FF", children: tags.join(", ") })
|
|
1049
1133
|
] }),
|
|
1050
1134
|
/* @__PURE__ */ jsxs8(Box8, { marginTop: 1, children: [
|
|
1051
|
-
/* @__PURE__ */
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
/* @__PURE__ */
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
"to push to cloud"
|
|
1135
|
+
/* @__PURE__ */ jsx8(Text8, { color: "gray", children: " Sync: " }),
|
|
1136
|
+
syncStatus === "syncing" && /* @__PURE__ */ jsx8(Text8, { color: "magenta", children: "Syncing to cloud (E2E encrypted)..." }),
|
|
1137
|
+
syncStatus === "synced" && /* @__PURE__ */ jsx8(Text8, { color: "green", children: "\u2713 Synced to cloud" }),
|
|
1138
|
+
syncStatus === "offline" && /* @__PURE__ */ jsx8(Text8, { color: "yellow", children: "\u2601 Offline (queued locally)" }),
|
|
1139
|
+
syncStatus === "failed" && /* @__PURE__ */ jsxs8(Text8, { color: "red", children: [
|
|
1140
|
+
"\u2717 ",
|
|
1141
|
+
syncMessage
|
|
1059
1142
|
] })
|
|
1060
1143
|
] })
|
|
1061
1144
|
] })
|
|
@@ -1652,52 +1735,6 @@ function registerStats(program2) {
|
|
|
1652
1735
|
// src/commands/sync.tsx
|
|
1653
1736
|
import React14, { useState as useState11, useEffect as useEffect12 } from "react";
|
|
1654
1737
|
import { Box as Box15, Text as Text15, useApp as useApp10 } from "ink";
|
|
1655
|
-
|
|
1656
|
-
// src/lib/crypto.ts
|
|
1657
|
-
import {
|
|
1658
|
-
pbkdf2Sync,
|
|
1659
|
-
createCipheriv,
|
|
1660
|
-
createDecipheriv,
|
|
1661
|
-
randomBytes,
|
|
1662
|
-
createHash
|
|
1663
|
-
} from "crypto";
|
|
1664
|
-
var PBKDF2_ITERATIONS = 1e5;
|
|
1665
|
-
var KEY_LENGTH = 32;
|
|
1666
|
-
var SALT_LENGTH = 16;
|
|
1667
|
-
var IV_LENGTH = 16;
|
|
1668
|
-
function deriveMasterKey(password, salt) {
|
|
1669
|
-
return pbkdf2Sync(password, salt, PBKDF2_ITERATIONS, KEY_LENGTH, "sha256");
|
|
1670
|
-
}
|
|
1671
|
-
function deriveEncryptionKey(masterKey) {
|
|
1672
|
-
const hash = createHash("sha256");
|
|
1673
|
-
hash.update(masterKey);
|
|
1674
|
-
hash.update("taskair-encryption");
|
|
1675
|
-
return hash.digest();
|
|
1676
|
-
}
|
|
1677
|
-
function encrypt(plaintext, password) {
|
|
1678
|
-
const salt = randomBytes(SALT_LENGTH);
|
|
1679
|
-
const iv = randomBytes(IV_LENGTH);
|
|
1680
|
-
const masterKey = deriveMasterKey(password, salt);
|
|
1681
|
-
const encKey = deriveEncryptionKey(masterKey);
|
|
1682
|
-
const cipher = createCipheriv("aes-256-gcm", encKey, iv);
|
|
1683
|
-
const encrypted = Buffer.concat([
|
|
1684
|
-
cipher.update(plaintext, "utf8"),
|
|
1685
|
-
cipher.final()
|
|
1686
|
-
]);
|
|
1687
|
-
const authTag = cipher.getAuthTag();
|
|
1688
|
-
return {
|
|
1689
|
-
version: "1",
|
|
1690
|
-
salt: salt.toString("base64"),
|
|
1691
|
-
iv: iv.toString("base64"),
|
|
1692
|
-
ciphertext: encrypted.toString("base64"),
|
|
1693
|
-
authTag: authTag.toString("base64")
|
|
1694
|
-
};
|
|
1695
|
-
}
|
|
1696
|
-
function checksum(plaintext) {
|
|
1697
|
-
return createHash("sha256").update(plaintext).digest("hex");
|
|
1698
|
-
}
|
|
1699
|
-
|
|
1700
|
-
// src/commands/sync.tsx
|
|
1701
1738
|
import { Fragment as Fragment5, jsx as jsx15, jsxs as jsxs15 } from "react/jsx-runtime";
|
|
1702
1739
|
function SyncUI({ dryRun, password }) {
|
|
1703
1740
|
const { exit } = useApp10();
|
|
@@ -1874,17 +1911,18 @@ function registerExport(program2) {
|
|
|
1874
1911
|
|
|
1875
1912
|
// src/commands/upgrade.tsx
|
|
1876
1913
|
import React15, { useState as useState12, useEffect as useEffect13 } from "react";
|
|
1877
|
-
import { Box as Box16, Text as Text16 } from "ink";
|
|
1914
|
+
import { Box as Box16, Text as Text16, useApp as useApp11 } from "ink";
|
|
1878
1915
|
import { exec as exec2 } from "child_process";
|
|
1879
1916
|
|
|
1880
1917
|
// src/lib/version.ts
|
|
1881
|
-
var CLI_VERSION = "1.0.
|
|
1918
|
+
var CLI_VERSION = "1.0.6";
|
|
1882
1919
|
|
|
1883
1920
|
// src/commands/upgrade.tsx
|
|
1884
1921
|
import { jsx as jsx16, jsxs as jsxs16 } from "react/jsx-runtime";
|
|
1885
1922
|
function isOutdated(current, latest) {
|
|
1886
|
-
|
|
1887
|
-
const
|
|
1923
|
+
if (!current) return true;
|
|
1924
|
+
const cParts = current.replace(/^v/, "").split(".").map(Number);
|
|
1925
|
+
const lParts = latest.replace(/^v/, "").split(".").map(Number);
|
|
1888
1926
|
for (let i = 0; i < 3; i++) {
|
|
1889
1927
|
const c = cParts[i] ?? 0;
|
|
1890
1928
|
const l = lParts[i] ?? 0;
|
|
@@ -1893,40 +1931,159 @@ function isOutdated(current, latest) {
|
|
|
1893
1931
|
}
|
|
1894
1932
|
return false;
|
|
1895
1933
|
}
|
|
1896
|
-
function UpgradeUI() {
|
|
1897
|
-
const
|
|
1898
|
-
const
|
|
1899
|
-
const
|
|
1934
|
+
function UpgradeUI({ target }) {
|
|
1935
|
+
const { exit } = useApp11();
|
|
1936
|
+
const shouldUpgradeCli = !target || target.toLowerCase() === "cli";
|
|
1937
|
+
const shouldUpgradeMcp = !target || target.toLowerCase() === "mcp";
|
|
1938
|
+
const [cliState, setCliState] = useState12({
|
|
1939
|
+
name: "TaskAir CLI",
|
|
1940
|
+
pkgName: "taskair-cli",
|
|
1941
|
+
current: CLI_VERSION,
|
|
1942
|
+
latest: "",
|
|
1943
|
+
status: shouldUpgradeCli ? "checking" : "up-to-date",
|
|
1944
|
+
errorMsg: ""
|
|
1945
|
+
});
|
|
1946
|
+
const [mcpState, setMcpState] = useState12({
|
|
1947
|
+
name: "TaskAir MCP Server",
|
|
1948
|
+
pkgName: "taskair-mcp",
|
|
1949
|
+
current: "",
|
|
1950
|
+
latest: "",
|
|
1951
|
+
status: shouldUpgradeMcp ? "checking" : "up-to-date",
|
|
1952
|
+
errorMsg: ""
|
|
1953
|
+
});
|
|
1900
1954
|
useEffect13(() => {
|
|
1901
1955
|
async function checkAndUpgrade() {
|
|
1902
|
-
|
|
1903
|
-
|
|
1904
|
-
|
|
1905
|
-
|
|
1956
|
+
const tasks = [];
|
|
1957
|
+
let mcpCurrent = "";
|
|
1958
|
+
if (shouldUpgradeMcp) {
|
|
1959
|
+
mcpCurrent = await new Promise((resolve) => {
|
|
1960
|
+
exec2("npm list -g taskair-mcp --json", (err, stdout) => {
|
|
1961
|
+
if (err) {
|
|
1962
|
+
resolve("");
|
|
1963
|
+
return;
|
|
1964
|
+
}
|
|
1965
|
+
try {
|
|
1966
|
+
const data = JSON.parse(stdout);
|
|
1967
|
+
resolve(data.dependencies?.["taskair-mcp"]?.version || "");
|
|
1968
|
+
} catch {
|
|
1969
|
+
resolve("");
|
|
1970
|
+
}
|
|
1971
|
+
});
|
|
1906
1972
|
});
|
|
1907
|
-
|
|
1908
|
-
|
|
1973
|
+
}
|
|
1974
|
+
let cliLatest = "";
|
|
1975
|
+
if (shouldUpgradeCli) {
|
|
1976
|
+
try {
|
|
1977
|
+
const res = await fetch("https://registry.npmjs.org/taskair-cli/latest", {
|
|
1978
|
+
signal: AbortSignal.timeout(5e3)
|
|
1979
|
+
});
|
|
1980
|
+
if (res.ok) {
|
|
1981
|
+
const data = await res.json();
|
|
1982
|
+
cliLatest = data.version || "";
|
|
1983
|
+
}
|
|
1984
|
+
} catch {
|
|
1985
|
+
cliLatest = "";
|
|
1909
1986
|
}
|
|
1910
|
-
|
|
1911
|
-
|
|
1912
|
-
|
|
1913
|
-
|
|
1914
|
-
|
|
1915
|
-
|
|
1916
|
-
if (error) {
|
|
1917
|
-
setErrorMsg(error.message || stderr || "Failed to install update");
|
|
1918
|
-
setStatus("error");
|
|
1919
|
-
} else {
|
|
1920
|
-
setStatus("success");
|
|
1921
|
-
}
|
|
1987
|
+
}
|
|
1988
|
+
let mcpLatest = "";
|
|
1989
|
+
if (shouldUpgradeMcp) {
|
|
1990
|
+
try {
|
|
1991
|
+
const res = await fetch("https://registry.npmjs.org/taskair-mcp/latest", {
|
|
1992
|
+
signal: AbortSignal.timeout(5e3)
|
|
1922
1993
|
});
|
|
1994
|
+
if (res.ok) {
|
|
1995
|
+
const data = await res.json();
|
|
1996
|
+
mcpLatest = data.version || "";
|
|
1997
|
+
}
|
|
1998
|
+
} catch {
|
|
1999
|
+
mcpLatest = "";
|
|
2000
|
+
}
|
|
2001
|
+
}
|
|
2002
|
+
if (shouldUpgradeCli) {
|
|
2003
|
+
if (!cliLatest) {
|
|
2004
|
+
setCliState((prev) => ({
|
|
2005
|
+
...prev,
|
|
2006
|
+
status: "error",
|
|
2007
|
+
errorMsg: "Could not fetch latest version from registry."
|
|
2008
|
+
}));
|
|
1923
2009
|
} else {
|
|
1924
|
-
|
|
2010
|
+
setCliState((prev) => ({ ...prev, latest: cliLatest }));
|
|
2011
|
+
if (isOutdated(CLI_VERSION, cliLatest)) {
|
|
2012
|
+
setCliState((prev) => ({ ...prev, status: "upgrading" }));
|
|
2013
|
+
tasks.push(new Promise((resolve) => {
|
|
2014
|
+
exec2("npm install -g taskair-cli", (error, stdout, stderr) => {
|
|
2015
|
+
if (error) {
|
|
2016
|
+
setCliState((prev) => ({
|
|
2017
|
+
...prev,
|
|
2018
|
+
status: "error",
|
|
2019
|
+
errorMsg: error.message || stderr || "Failed to install updates"
|
|
2020
|
+
}));
|
|
2021
|
+
} else {
|
|
2022
|
+
setCliState((prev) => ({ ...prev, status: "success" }));
|
|
2023
|
+
}
|
|
2024
|
+
resolve();
|
|
2025
|
+
});
|
|
2026
|
+
}));
|
|
2027
|
+
} else {
|
|
2028
|
+
setCliState((prev) => ({ ...prev, status: "up-to-date" }));
|
|
2029
|
+
}
|
|
2030
|
+
}
|
|
2031
|
+
}
|
|
2032
|
+
if (shouldUpgradeMcp) {
|
|
2033
|
+
if (!mcpLatest) {
|
|
2034
|
+
setMcpState((prev) => ({
|
|
2035
|
+
...prev,
|
|
2036
|
+
status: "error",
|
|
2037
|
+
errorMsg: "Could not fetch latest version from registry."
|
|
2038
|
+
}));
|
|
2039
|
+
} else {
|
|
2040
|
+
setMcpState((prev) => ({ ...prev, latest: mcpLatest, current: mcpCurrent }));
|
|
2041
|
+
const isMcpInstalled = !!mcpCurrent;
|
|
2042
|
+
if (!isMcpInstalled) {
|
|
2043
|
+
if (target === "mcp") {
|
|
2044
|
+
setMcpState((prev) => ({ ...prev, status: "upgrading" }));
|
|
2045
|
+
tasks.push(new Promise((resolve) => {
|
|
2046
|
+
exec2("npm install -g taskair-mcp", (error, stdout, stderr) => {
|
|
2047
|
+
if (error) {
|
|
2048
|
+
setMcpState((prev) => ({
|
|
2049
|
+
...prev,
|
|
2050
|
+
status: "error",
|
|
2051
|
+
errorMsg: error.message || stderr || "Failed to install"
|
|
2052
|
+
}));
|
|
2053
|
+
} else {
|
|
2054
|
+
setMcpState((prev) => ({ ...prev, status: "success" }));
|
|
2055
|
+
}
|
|
2056
|
+
resolve();
|
|
2057
|
+
});
|
|
2058
|
+
}));
|
|
2059
|
+
} else {
|
|
2060
|
+
setMcpState((prev) => ({ ...prev, status: "not-installed" }));
|
|
2061
|
+
}
|
|
2062
|
+
} else if (isOutdated(mcpCurrent, mcpLatest)) {
|
|
2063
|
+
setMcpState((prev) => ({ ...prev, status: "upgrading" }));
|
|
2064
|
+
tasks.push(new Promise((resolve) => {
|
|
2065
|
+
exec2("npm install -g taskair-mcp", (error, stdout, stderr) => {
|
|
2066
|
+
if (error) {
|
|
2067
|
+
setMcpState((prev) => ({
|
|
2068
|
+
...prev,
|
|
2069
|
+
status: "error",
|
|
2070
|
+
errorMsg: error.message || stderr || "Failed to install updates"
|
|
2071
|
+
}));
|
|
2072
|
+
} else {
|
|
2073
|
+
setMcpState((prev) => ({ ...prev, status: "success" }));
|
|
2074
|
+
}
|
|
2075
|
+
resolve();
|
|
2076
|
+
});
|
|
2077
|
+
}));
|
|
2078
|
+
} else {
|
|
2079
|
+
setMcpState((prev) => ({ ...prev, status: "up-to-date" }));
|
|
2080
|
+
}
|
|
1925
2081
|
}
|
|
1926
|
-
} catch (err) {
|
|
1927
|
-
setErrorMsg(err.message || "Network error checking for updates.");
|
|
1928
|
-
setStatus("error");
|
|
1929
2082
|
}
|
|
2083
|
+
if (tasks.length > 0) {
|
|
2084
|
+
await Promise.all(tasks);
|
|
2085
|
+
}
|
|
2086
|
+
setTimeout(() => exit(), 2500);
|
|
1930
2087
|
}
|
|
1931
2088
|
checkAndUpgrade();
|
|
1932
2089
|
}, []);
|
|
@@ -1934,39 +2091,62 @@ function UpgradeUI() {
|
|
|
1934
2091
|
/* @__PURE__ */ jsx16(MiniHeader, {}),
|
|
1935
2092
|
/* @__PURE__ */ jsxs16(Box16, { flexDirection: "column", borderStyle: "round", borderColor: "#7B61FF", paddingX: 2, paddingY: 1, marginTop: 1, children: [
|
|
1936
2093
|
/* @__PURE__ */ jsx16(Box16, { marginBottom: 1, children: /* @__PURE__ */ jsx16(Text16, { color: "cyan", bold: true, children: "\u2726 TaskAir Upgrade" }) }),
|
|
1937
|
-
|
|
1938
|
-
|
|
1939
|
-
/* @__PURE__ */
|
|
1940
|
-
|
|
2094
|
+
shouldUpgradeCli && /* @__PURE__ */ jsxs16(Box16, { flexDirection: "column", marginBottom: 1, children: [
|
|
2095
|
+
/* @__PURE__ */ jsx16(Text16, { bold: true, color: "white", children: "TaskAir CLI:" }),
|
|
2096
|
+
cliState.status === "checking" && /* @__PURE__ */ jsx16(Spinner, { label: `Checking latest version... (Current: v${CLI_VERSION})`, type: "orbit" }),
|
|
2097
|
+
cliState.status === "upgrading" && /* @__PURE__ */ jsx16(Spinner, { label: `Upgrading globally: v${CLI_VERSION} \u2192 v${cliState.latest}...`, type: "star", color: "yellow" }),
|
|
2098
|
+
cliState.status === "success" && /* @__PURE__ */ jsxs16(Text16, { color: "green", children: [
|
|
2099
|
+
"\u2713 Successfully upgraded to v",
|
|
2100
|
+
cliState.latest,
|
|
2101
|
+
"!"
|
|
2102
|
+
] }),
|
|
2103
|
+
cliState.status === "up-to-date" && /* @__PURE__ */ jsxs16(Text16, { color: "gray", children: [
|
|
2104
|
+
"\u2713 Already up to date (v",
|
|
1941
2105
|
CLI_VERSION,
|
|
1942
|
-
"
|
|
1943
|
-
latestVersion
|
|
2106
|
+
")"
|
|
1944
2107
|
] }),
|
|
1945
|
-
|
|
1946
|
-
|
|
1947
|
-
|
|
1948
|
-
|
|
1949
|
-
|
|
1950
|
-
|
|
1951
|
-
|
|
1952
|
-
/* @__PURE__ */ jsx16(StatusBadge, { type: "success", message: `TaskAir CLI is already up to date (v${CLI_VERSION}).` }),
|
|
1953
|
-
/* @__PURE__ */ jsx16(Box16, { marginTop: 1, children: /* @__PURE__ */ jsx16(Text16, { color: "gray", children: "No upgrade required at this time. Blast off! \u{1F680}" }) })
|
|
2108
|
+
cliState.status === "error" && /* @__PURE__ */ jsxs16(Box16, { flexDirection: "column", children: [
|
|
2109
|
+
/* @__PURE__ */ jsxs16(Text16, { color: "red", children: [
|
|
2110
|
+
"\u2717 Upgrade failed: ",
|
|
2111
|
+
cliState.errorMsg
|
|
2112
|
+
] }),
|
|
2113
|
+
/* @__PURE__ */ jsx16(Text16, { color: "gray", dimColor: true, children: "Run manually: npm install -g taskair-cli" })
|
|
2114
|
+
] })
|
|
1954
2115
|
] }),
|
|
1955
|
-
|
|
1956
|
-
/* @__PURE__ */ jsx16(
|
|
1957
|
-
/* @__PURE__ */
|
|
1958
|
-
|
|
1959
|
-
|
|
1960
|
-
|
|
2116
|
+
shouldUpgradeMcp && /* @__PURE__ */ jsxs16(Box16, { flexDirection: "column", children: [
|
|
2117
|
+
/* @__PURE__ */ jsx16(Text16, { bold: true, color: "white", children: "TaskAir MCP Server:" }),
|
|
2118
|
+
mcpState.status === "checking" && /* @__PURE__ */ jsx16(Spinner, { label: `Checking latest version... (Current: ${mcpState.current ? "v" + mcpState.current : "not installed"})`, type: "orbit" }),
|
|
2119
|
+
mcpState.status === "upgrading" && /* @__PURE__ */ jsx16(Spinner, { label: `Upgrading globally: ${mcpState.current ? "v" + mcpState.current : "installing"} \u2192 v${mcpState.latest}...`, type: "star", color: "yellow" }),
|
|
2120
|
+
mcpState.status === "success" && /* @__PURE__ */ jsxs16(Text16, { color: "green", children: [
|
|
2121
|
+
"\u2713 Successfully upgraded to v",
|
|
2122
|
+
mcpState.latest,
|
|
2123
|
+
"!"
|
|
2124
|
+
] }),
|
|
2125
|
+
mcpState.status === "up-to-date" && /* @__PURE__ */ jsxs16(Text16, { color: "gray", children: [
|
|
2126
|
+
"\u2713 Already up to date (v",
|
|
2127
|
+
mcpState.current,
|
|
2128
|
+
")"
|
|
2129
|
+
] }),
|
|
2130
|
+
mcpState.status === "not-installed" && /* @__PURE__ */ jsxs16(Box16, { flexDirection: "column", children: [
|
|
2131
|
+
/* @__PURE__ */ jsx16(Text16, { color: "yellow", children: "\u2601 Not installed globally." }),
|
|
2132
|
+
/* @__PURE__ */ jsx16(Text16, { color: "gray", dimColor: true, children: "Install manually: npm install -g taskair-mcp" }),
|
|
2133
|
+
/* @__PURE__ */ jsx16(Text16, { color: "gray", dimColor: true, children: "Or install now with: taskair upgrade mcp" })
|
|
2134
|
+
] }),
|
|
2135
|
+
mcpState.status === "error" && /* @__PURE__ */ jsxs16(Box16, { flexDirection: "column", children: [
|
|
2136
|
+
/* @__PURE__ */ jsxs16(Text16, { color: "red", children: [
|
|
2137
|
+
"\u2717 Upgrade failed: ",
|
|
2138
|
+
mcpState.errorMsg
|
|
2139
|
+
] }),
|
|
2140
|
+
/* @__PURE__ */ jsx16(Text16, { color: "gray", dimColor: true, children: "Run manually: npm install -g taskair-mcp" })
|
|
1961
2141
|
] })
|
|
1962
2142
|
] })
|
|
1963
2143
|
] })
|
|
1964
2144
|
] });
|
|
1965
2145
|
}
|
|
1966
2146
|
function registerUpgrade(program2) {
|
|
1967
|
-
program2.command("upgrade").description(
|
|
2147
|
+
program2.command("upgrade [target]").description('Upgrade TaskAir CLI and MCP Server. Target can be "cli", "mcp", or omitted to upgrade both.').action(async (target) => {
|
|
1968
2148
|
const { render } = await import("ink");
|
|
1969
|
-
render(React15.createElement(UpgradeUI));
|
|
2149
|
+
render(React15.createElement(UpgradeUI, { target }));
|
|
1970
2150
|
});
|
|
1971
2151
|
}
|
|
1972
2152
|
|