md4ai 0.9.8 → 0.9.10
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.bundled.js +92 -20
- package/package.json +1 -1
package/dist/index.bundled.js
CHANGED
|
@@ -1,12 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
var __defProp = Object.defineProperty;
|
|
3
3
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
4
|
-
var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
|
|
5
|
-
get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
|
|
6
|
-
}) : x)(function(x) {
|
|
7
|
-
if (typeof require !== "undefined") return require.apply(this, arguments);
|
|
8
|
-
throw Error('Dynamic require of "' + x + '" is not supported');
|
|
9
|
-
});
|
|
10
4
|
var __esm = (fn, res) => function __init() {
|
|
11
5
|
return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
|
|
12
6
|
};
|
|
@@ -893,20 +887,26 @@ var init_tooling_detector = __esm({
|
|
|
893
887
|
import { readFile as readFile5 } from "node:fs/promises";
|
|
894
888
|
import { join as join7 } from "node:path";
|
|
895
889
|
import { homedir as homedir5 } from "node:os";
|
|
896
|
-
async function
|
|
890
|
+
async function resolveVercelTokenWithSource() {
|
|
897
891
|
const creds = await loadCredentials();
|
|
898
|
-
if (creds?.vercelToken)
|
|
899
|
-
return
|
|
892
|
+
if (creds?.vercelToken) {
|
|
893
|
+
return {
|
|
894
|
+
token: creds.vercelToken,
|
|
895
|
+
source: "md4ai-credentials",
|
|
896
|
+
sourcePath: join7(homedir5(), ".md4ai", "credentials.json")
|
|
897
|
+
};
|
|
898
|
+
}
|
|
900
899
|
const possiblePaths = [
|
|
901
|
-
join7(homedir5(), ".config", "com.vercel.cli", "auth.json"),
|
|
902
|
-
join7(homedir5(), ".local", "share", "com.vercel.cli", "auth.json")
|
|
900
|
+
{ path: join7(homedir5(), ".config", "com.vercel.cli", "auth.json"), source: "vercel-cli-config" },
|
|
901
|
+
{ path: join7(homedir5(), ".local", "share", "com.vercel.cli", "auth.json"), source: "vercel-cli-local-share" }
|
|
903
902
|
];
|
|
904
|
-
for (const authPath of possiblePaths) {
|
|
903
|
+
for (const { path: authPath, source } of possiblePaths) {
|
|
905
904
|
try {
|
|
906
905
|
const data = await readFile5(authPath, "utf-8");
|
|
907
906
|
const parsed = JSON.parse(data);
|
|
908
|
-
if (parsed.token)
|
|
909
|
-
return parsed.token;
|
|
907
|
+
if (parsed.token) {
|
|
908
|
+
return { token: parsed.token, source, sourcePath: authPath };
|
|
909
|
+
}
|
|
910
910
|
} catch {
|
|
911
911
|
}
|
|
912
912
|
}
|
|
@@ -962,7 +962,21 @@ async function fetchVercelEnvVars(projectId, orgId, token) {
|
|
|
962
962
|
});
|
|
963
963
|
if (!res.ok) {
|
|
964
964
|
const body = await res.text().catch(() => "");
|
|
965
|
-
|
|
965
|
+
let errorCode = null;
|
|
966
|
+
let invalidToken = false;
|
|
967
|
+
try {
|
|
968
|
+
const parsed = JSON.parse(body);
|
|
969
|
+
errorCode = parsed.error?.code ?? null;
|
|
970
|
+
invalidToken = parsed.error?.invalidToken === true;
|
|
971
|
+
} catch {
|
|
972
|
+
}
|
|
973
|
+
if (invalidToken || res.status === 401) {
|
|
974
|
+
throw new VercelApiError("Token is invalid or expired", res.status, errorCode, true);
|
|
975
|
+
}
|
|
976
|
+
if (res.status === 403) {
|
|
977
|
+
throw new VercelApiError("Token lacks permission for this project/team", res.status, errorCode, false);
|
|
978
|
+
}
|
|
979
|
+
throw new VercelApiError(`Vercel API ${res.status}: ${body.slice(0, 200)}`, res.status, errorCode, false);
|
|
966
980
|
}
|
|
967
981
|
const data = await res.json();
|
|
968
982
|
const envs = data.envs ?? [];
|
|
@@ -974,9 +988,22 @@ async function fetchVercelEnvVars(projectId, orgId, token) {
|
|
|
974
988
|
// populated later by the scanner
|
|
975
989
|
}));
|
|
976
990
|
}
|
|
991
|
+
var VercelApiError;
|
|
977
992
|
var init_fetch_env_vars = __esm({
|
|
978
993
|
"dist/vercel/fetch-env-vars.js"() {
|
|
979
994
|
"use strict";
|
|
995
|
+
VercelApiError = class extends Error {
|
|
996
|
+
statusCode;
|
|
997
|
+
errorCode;
|
|
998
|
+
isInvalidToken;
|
|
999
|
+
constructor(message, statusCode, errorCode, isInvalidToken) {
|
|
1000
|
+
super(message);
|
|
1001
|
+
this.statusCode = statusCode;
|
|
1002
|
+
this.errorCode = errorCode;
|
|
1003
|
+
this.isInvalidToken = isInvalidToken;
|
|
1004
|
+
this.name = "VercelApiError";
|
|
1005
|
+
}
|
|
1006
|
+
};
|
|
980
1007
|
}
|
|
981
1008
|
});
|
|
982
1009
|
|
|
@@ -1018,18 +1045,48 @@ async function scanEnvManifest(projectRoot) {
|
|
|
1018
1045
|
checkedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
1019
1046
|
};
|
|
1020
1047
|
}
|
|
1048
|
+
function tokenSourceLabel(source) {
|
|
1049
|
+
switch (source) {
|
|
1050
|
+
case "md4ai-credentials":
|
|
1051
|
+
return "md4ai credentials (~/.md4ai/credentials.json)";
|
|
1052
|
+
case "vercel-cli-config":
|
|
1053
|
+
return "Vercel CLI (~/.config/com.vercel.cli/auth.json)";
|
|
1054
|
+
case "vercel-cli-local-share":
|
|
1055
|
+
return "Vercel CLI (~/.local/share/com.vercel.cli/auth.json)";
|
|
1056
|
+
}
|
|
1057
|
+
}
|
|
1058
|
+
function tokenFixInstructions(source) {
|
|
1059
|
+
switch (source) {
|
|
1060
|
+
case "md4ai-credentials":
|
|
1061
|
+
return [
|
|
1062
|
+
"Generate a new token at https://vercel.com/account/tokens",
|
|
1063
|
+
"Then run: md4ai config set vercel-token <new-token>"
|
|
1064
|
+
];
|
|
1065
|
+
case "vercel-cli-config":
|
|
1066
|
+
case "vercel-cli-local-share":
|
|
1067
|
+
return [
|
|
1068
|
+
"Re-authenticate the Vercel CLI: npx vercel login",
|
|
1069
|
+
"Ensure you log into the correct team account",
|
|
1070
|
+
"Or set a dedicated token: md4ai config set vercel-token <token>"
|
|
1071
|
+
];
|
|
1072
|
+
}
|
|
1073
|
+
}
|
|
1021
1074
|
async function checkVercelEnvVars(projectRoot, variables) {
|
|
1022
|
-
const
|
|
1023
|
-
if (!
|
|
1075
|
+
const tokenResult = await resolveVercelTokenWithSource();
|
|
1076
|
+
if (!tokenResult) {
|
|
1024
1077
|
console.log(chalk8.dim(" Vercel checks skipped (no token configured)"));
|
|
1078
|
+
console.log(chalk8.dim(" To enable: md4ai config set vercel-token <token>"));
|
|
1079
|
+
console.log(chalk8.dim(" Generate a token at https://vercel.com/account/tokens"));
|
|
1025
1080
|
return null;
|
|
1026
1081
|
}
|
|
1082
|
+
const { token, source } = tokenResult;
|
|
1027
1083
|
const projects = await discoverVercelProjects(projectRoot);
|
|
1028
1084
|
if (projects.length === 0)
|
|
1029
1085
|
return null;
|
|
1030
1086
|
console.log(chalk8.dim(` Checking ${projects.length} Vercel project(s)...`));
|
|
1031
1087
|
const discovered = [];
|
|
1032
1088
|
const manifestVarNames = new Set(variables.map((v) => v.name));
|
|
1089
|
+
let tokenErrorShown = false;
|
|
1033
1090
|
for (const proj of projects) {
|
|
1034
1091
|
try {
|
|
1035
1092
|
const vars = await fetchVercelEnvVars(proj.projectId, proj.orgId, token);
|
|
@@ -1050,7 +1107,22 @@ async function checkVercelEnvVars(projectRoot, variables) {
|
|
|
1050
1107
|
}
|
|
1051
1108
|
console.log(chalk8.dim(` ${proj.projectName}: ${vars.length} var(s)`));
|
|
1052
1109
|
} catch (err) {
|
|
1053
|
-
|
|
1110
|
+
if (err instanceof VercelApiError && err.isInvalidToken && !tokenErrorShown) {
|
|
1111
|
+
tokenErrorShown = true;
|
|
1112
|
+
console.log(chalk8.red(` ${proj.projectName}: Token is invalid or expired`));
|
|
1113
|
+
console.log(chalk8.yellow(` Token source: ${tokenSourceLabel(source)}`));
|
|
1114
|
+
console.log(chalk8.yellow(" To fix:"));
|
|
1115
|
+
for (const step of tokenFixInstructions(source)) {
|
|
1116
|
+
console.log(chalk8.yellow(` \u2192 ${step}`));
|
|
1117
|
+
}
|
|
1118
|
+
} else if (err instanceof VercelApiError && err.statusCode === 403) {
|
|
1119
|
+
console.log(chalk8.yellow(` ${proj.projectName}: ${err.message}`));
|
|
1120
|
+
console.log(chalk8.dim(` Token source: ${tokenSourceLabel(source)}`));
|
|
1121
|
+
console.log(chalk8.dim(" Ensure the token has access to this team/project"));
|
|
1122
|
+
console.log(chalk8.dim(" Check: https://vercel.com/account/tokens"));
|
|
1123
|
+
} else {
|
|
1124
|
+
console.log(chalk8.yellow(` ${proj.projectName}: ${err instanceof Error ? err.message : "API error"}`));
|
|
1125
|
+
}
|
|
1054
1126
|
}
|
|
1055
1127
|
}
|
|
1056
1128
|
return discovered.length > 0 ? discovered : null;
|
|
@@ -1651,7 +1723,7 @@ var CURRENT_VERSION;
|
|
|
1651
1723
|
var init_check_update = __esm({
|
|
1652
1724
|
"dist/check-update.js"() {
|
|
1653
1725
|
"use strict";
|
|
1654
|
-
CURRENT_VERSION = true ? "0.9.
|
|
1726
|
+
CURRENT_VERSION = true ? "0.9.10" : "0.0.0-dev";
|
|
1655
1727
|
}
|
|
1656
1728
|
});
|
|
1657
1729
|
|
|
@@ -2261,6 +2333,7 @@ var init_read_configs = __esm({
|
|
|
2261
2333
|
|
|
2262
2334
|
// dist/mcp/scan-processes.js
|
|
2263
2335
|
import { execFileSync as execFileSync4 } from "node:child_process";
|
|
2336
|
+
import { readlinkSync } from "node:fs";
|
|
2264
2337
|
function parsePsOutput(output) {
|
|
2265
2338
|
const lines = output.trim().split("\n").slice(1);
|
|
2266
2339
|
const entries = [];
|
|
@@ -2350,7 +2423,6 @@ function getProcessTable() {
|
|
|
2350
2423
|
}
|
|
2351
2424
|
}
|
|
2352
2425
|
function detectSessionCwds(processes) {
|
|
2353
|
-
const { readlinkSync } = __require("node:fs");
|
|
2354
2426
|
const cwdByTty = /* @__PURE__ */ new Map();
|
|
2355
2427
|
const claudeProcs = processes.filter((p) => {
|
|
2356
2428
|
const lower = p.args.toLowerCase();
|