@glasstrace/sdk 1.1.0 → 1.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/README.md +78 -1
- package/dist/{chunk-55FBXXER.js → chunk-2M57EO6U.js} +2 -2
- package/dist/chunk-3LILTM3T.js +384 -0
- package/dist/chunk-3LILTM3T.js.map +1 -0
- package/dist/{chunk-KE7MCPO5.js → chunk-4EZ6JTDG.js} +2 -2
- package/dist/{chunk-67RIOAXV.js → chunk-6RNBUUBR.js} +2 -2
- package/dist/{chunk-DO2YPMQ5.js → chunk-C567H5EQ.js} +23 -5
- package/dist/chunk-C567H5EQ.js.map +1 -0
- package/dist/{chunk-UGJ3X4CT.js → chunk-DST4UBXU.js} +2 -2
- package/dist/{chunk-DXRZKKSO.js → chunk-NB7GJE4S.js} +2 -4
- package/dist/chunk-NB7GJE4S.js.map +1 -0
- package/dist/{chunk-HAU66QBQ.js → chunk-P4OYPFQ5.js} +9 -9
- package/dist/chunk-P4OYPFQ5.js.map +1 -0
- package/dist/{chunk-LU3PPAOQ.js → chunk-UJ2JC7PZ.js} +4 -4
- package/dist/chunk-UJ2JC7PZ.js.map +1 -0
- package/dist/{chunk-TQ54WLCZ.js → chunk-X5MAXP5T.js} +2 -1
- package/dist/{chunk-ZBTC5QIQ.js → chunk-Z35HKVSO.js} +137 -10
- package/dist/chunk-Z35HKVSO.js.map +1 -0
- package/dist/cli/init.cjs +1313 -1118
- package/dist/cli/init.cjs.map +1 -1
- package/dist/cli/init.js +456 -72
- package/dist/cli/init.js.map +1 -1
- package/dist/cli/mcp-add.cjs +257 -85
- package/dist/cli/mcp-add.cjs.map +1 -1
- package/dist/cli/mcp-add.d.cts +35 -4
- package/dist/cli/mcp-add.d.ts +35 -4
- package/dist/cli/mcp-add.js +61 -25
- package/dist/cli/mcp-add.js.map +1 -1
- package/dist/cli/status.cjs.map +1 -1
- package/dist/cli/status.js +1 -1
- package/dist/cli/uninit.cjs +1 -1
- package/dist/cli/uninit.cjs.map +1 -1
- package/dist/cli/uninit.js +4 -4
- package/dist/cli/validate.cjs +14162 -2
- package/dist/cli/validate.cjs.map +1 -1
- package/dist/cli/validate.d.cts +7 -3
- package/dist/cli/validate.d.ts +7 -3
- package/dist/cli/validate.js +25 -2
- package/dist/cli/validate.js.map +1 -1
- package/dist/edge-entry.js +2 -2
- package/dist/index.cjs +423 -12
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +5 -5
- package/dist/{monorepo-N5Z63XP7.js → monorepo-PFVNPQ6X.js} +3 -3
- package/dist/node-entry.cjs +423 -12
- package/dist/node-entry.cjs.map +1 -1
- package/dist/node-entry.js +7 -7
- package/dist/node-subpath.js +3 -3
- package/dist/{source-map-uploader-BJIXRLJ6.js → source-map-uploader-DPUUCLNW.js} +3 -3
- package/package.json +1 -1
- package/dist/chunk-DO2YPMQ5.js.map +0 -1
- package/dist/chunk-DXRZKKSO.js.map +0 -1
- package/dist/chunk-HAU66QBQ.js.map +0 -1
- package/dist/chunk-IP4NMDJK.js +0 -98
- package/dist/chunk-IP4NMDJK.js.map +0 -1
- package/dist/chunk-LU3PPAOQ.js.map +0 -1
- package/dist/chunk-O63DJKIJ.js +0 -460
- package/dist/chunk-O63DJKIJ.js.map +0 -1
- package/dist/chunk-ZBTC5QIQ.js.map +0 -1
- /package/dist/{chunk-55FBXXER.js.map → chunk-2M57EO6U.js.map} +0 -0
- /package/dist/{chunk-KE7MCPO5.js.map → chunk-4EZ6JTDG.js.map} +0 -0
- /package/dist/{chunk-67RIOAXV.js.map → chunk-6RNBUUBR.js.map} +0 -0
- /package/dist/{chunk-UGJ3X4CT.js.map → chunk-DST4UBXU.js.map} +0 -0
- /package/dist/{chunk-TQ54WLCZ.js.map → chunk-X5MAXP5T.js.map} +0 -0
- /package/dist/{monorepo-N5Z63XP7.js.map → monorepo-PFVNPQ6X.js.map} +0 -0
- /package/dist/{source-map-uploader-BJIXRLJ6.js.map → source-map-uploader-DPUUCLNW.js.map} +0 -0
package/dist/cli/mcp-add.cjs
CHANGED
|
@@ -30,14 +30,18 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
30
30
|
// src/cli/mcp-add.ts
|
|
31
31
|
var mcp_add_exports = {};
|
|
32
32
|
__export(mcp_add_exports, {
|
|
33
|
-
mcpAdd: () => mcpAdd
|
|
33
|
+
mcpAdd: () => mcpAdd,
|
|
34
|
+
registerViaCli: () => registerViaCli
|
|
34
35
|
});
|
|
35
36
|
module.exports = __toCommonJS(mcp_add_exports);
|
|
36
37
|
var import_node_child_process2 = require("node:child_process");
|
|
37
|
-
var
|
|
38
|
-
var
|
|
38
|
+
var fs = __toESM(require("node:fs"), 1);
|
|
39
|
+
var path = __toESM(require("node:path"), 1);
|
|
39
40
|
var import_node_util = require("node:util");
|
|
40
41
|
|
|
42
|
+
// src/mcp-runtime.ts
|
|
43
|
+
var import_node_crypto = require("node:crypto");
|
|
44
|
+
|
|
41
45
|
// ../../node_modules/zod/v4/classic/external.js
|
|
42
46
|
var external_exports = {};
|
|
43
47
|
__export(external_exports, {
|
|
@@ -805,10 +809,10 @@ function mergeDefs(...defs) {
|
|
|
805
809
|
function cloneDef(schema) {
|
|
806
810
|
return mergeDefs(schema._zod.def);
|
|
807
811
|
}
|
|
808
|
-
function getElementAtPath(obj,
|
|
809
|
-
if (!
|
|
812
|
+
function getElementAtPath(obj, path2) {
|
|
813
|
+
if (!path2)
|
|
810
814
|
return obj;
|
|
811
|
-
return
|
|
815
|
+
return path2.reduce((acc, key) => acc?.[key], obj);
|
|
812
816
|
}
|
|
813
817
|
function promiseAllObject(promisesObj) {
|
|
814
818
|
const keys = Object.keys(promisesObj);
|
|
@@ -1191,11 +1195,11 @@ function aborted(x, startIndex = 0) {
|
|
|
1191
1195
|
}
|
|
1192
1196
|
return false;
|
|
1193
1197
|
}
|
|
1194
|
-
function prefixIssues(
|
|
1198
|
+
function prefixIssues(path2, issues) {
|
|
1195
1199
|
return issues.map((iss) => {
|
|
1196
1200
|
var _a2;
|
|
1197
1201
|
(_a2 = iss).path ?? (_a2.path = []);
|
|
1198
|
-
iss.path.unshift(
|
|
1202
|
+
iss.path.unshift(path2);
|
|
1199
1203
|
return iss;
|
|
1200
1204
|
});
|
|
1201
1205
|
}
|
|
@@ -1378,7 +1382,7 @@ function formatError(error48, mapper = (issue2) => issue2.message) {
|
|
|
1378
1382
|
}
|
|
1379
1383
|
function treeifyError(error48, mapper = (issue2) => issue2.message) {
|
|
1380
1384
|
const result = { errors: [] };
|
|
1381
|
-
const processError = (error49,
|
|
1385
|
+
const processError = (error49, path2 = []) => {
|
|
1382
1386
|
var _a2, _b;
|
|
1383
1387
|
for (const issue2 of error49.issues) {
|
|
1384
1388
|
if (issue2.code === "invalid_union" && issue2.errors.length) {
|
|
@@ -1388,7 +1392,7 @@ function treeifyError(error48, mapper = (issue2) => issue2.message) {
|
|
|
1388
1392
|
} else if (issue2.code === "invalid_element") {
|
|
1389
1393
|
processError({ issues: issue2.issues }, issue2.path);
|
|
1390
1394
|
} else {
|
|
1391
|
-
const fullpath = [...
|
|
1395
|
+
const fullpath = [...path2, ...issue2.path];
|
|
1392
1396
|
if (fullpath.length === 0) {
|
|
1393
1397
|
result.errors.push(mapper(issue2));
|
|
1394
1398
|
continue;
|
|
@@ -1420,8 +1424,8 @@ function treeifyError(error48, mapper = (issue2) => issue2.message) {
|
|
|
1420
1424
|
}
|
|
1421
1425
|
function toDotPath(_path) {
|
|
1422
1426
|
const segs = [];
|
|
1423
|
-
const
|
|
1424
|
-
for (const seg of
|
|
1427
|
+
const path2 = _path.map((seg) => typeof seg === "object" ? seg.key : seg);
|
|
1428
|
+
for (const seg of path2) {
|
|
1425
1429
|
if (typeof seg === "number")
|
|
1426
1430
|
segs.push(`[${seg}]`);
|
|
1427
1431
|
else if (typeof seg === "symbol")
|
|
@@ -13398,13 +13402,13 @@ function resolveRef(ref, ctx) {
|
|
|
13398
13402
|
if (!ref.startsWith("#")) {
|
|
13399
13403
|
throw new Error("External $ref is not supported, only local refs (#/...) are allowed");
|
|
13400
13404
|
}
|
|
13401
|
-
const
|
|
13402
|
-
if (
|
|
13405
|
+
const path2 = ref.slice(1).split("/").filter(Boolean);
|
|
13406
|
+
if (path2.length === 0) {
|
|
13403
13407
|
return ctx.rootSchema;
|
|
13404
13408
|
}
|
|
13405
13409
|
const defsKey = ctx.version === "draft-2020-12" ? "$defs" : "definitions";
|
|
13406
|
-
if (
|
|
13407
|
-
const key =
|
|
13410
|
+
if (path2[0] === defsKey) {
|
|
13411
|
+
const key = path2[1];
|
|
13408
13412
|
if (!key || !ctx.defs[key]) {
|
|
13409
13413
|
throw new Error(`Reference not found: ${ref}`);
|
|
13410
13414
|
}
|
|
@@ -14001,15 +14005,16 @@ var K = new Uint32Array([
|
|
|
14001
14005
|
// src/anon-key.ts
|
|
14002
14006
|
var GLASSTRACE_DIR = ".glasstrace";
|
|
14003
14007
|
var ANON_KEY_FILE = "anon_key";
|
|
14008
|
+
var CLAIMED_KEY_FILE = "claimed-key";
|
|
14004
14009
|
var fsPathCache;
|
|
14005
14010
|
async function loadFsPath() {
|
|
14006
14011
|
if (fsPathCache !== void 0) return fsPathCache;
|
|
14007
14012
|
try {
|
|
14008
|
-
const [
|
|
14013
|
+
const [fs2, path2] = await Promise.all([
|
|
14009
14014
|
import("node:fs/promises"),
|
|
14010
14015
|
import("node:path")
|
|
14011
14016
|
]);
|
|
14012
|
-
fsPathCache = { fs:
|
|
14017
|
+
fsPathCache = { fs: fs2, path: path2 };
|
|
14013
14018
|
return fsPathCache;
|
|
14014
14019
|
} catch {
|
|
14015
14020
|
fsPathCache = null;
|
|
@@ -14037,6 +14042,172 @@ async function readAnonKey(projectRoot) {
|
|
|
14037
14042
|
}
|
|
14038
14043
|
return null;
|
|
14039
14044
|
}
|
|
14045
|
+
async function readClaimedKey(projectRoot) {
|
|
14046
|
+
const root = projectRoot ?? process.cwd();
|
|
14047
|
+
const modules = await loadFsPath();
|
|
14048
|
+
if (!modules) return null;
|
|
14049
|
+
const keyPath = modules.path.join(root, GLASSTRACE_DIR, CLAIMED_KEY_FILE);
|
|
14050
|
+
try {
|
|
14051
|
+
const content = await modules.fs.readFile(keyPath, "utf-8");
|
|
14052
|
+
const trimmed = content.trim();
|
|
14053
|
+
const parsed = DevApiKeySchema.safeParse(trimmed);
|
|
14054
|
+
if (parsed.success) {
|
|
14055
|
+
return parsed.data;
|
|
14056
|
+
}
|
|
14057
|
+
} catch {
|
|
14058
|
+
}
|
|
14059
|
+
return null;
|
|
14060
|
+
}
|
|
14061
|
+
|
|
14062
|
+
// src/mcp-runtime.ts
|
|
14063
|
+
var MCP_ENDPOINT = "https://api.glasstrace.dev/mcp";
|
|
14064
|
+
var fsPathCache2;
|
|
14065
|
+
async function loadFsPath2() {
|
|
14066
|
+
if (fsPathCache2 !== void 0) return fsPathCache2;
|
|
14067
|
+
try {
|
|
14068
|
+
const [fs2, path2] = await Promise.all([
|
|
14069
|
+
import("node:fs/promises"),
|
|
14070
|
+
import("node:path")
|
|
14071
|
+
]);
|
|
14072
|
+
fsPathCache2 = { fs: fs2, path: path2 };
|
|
14073
|
+
return fsPathCache2;
|
|
14074
|
+
} catch {
|
|
14075
|
+
fsPathCache2 = null;
|
|
14076
|
+
return null;
|
|
14077
|
+
}
|
|
14078
|
+
}
|
|
14079
|
+
function identityFingerprint(token) {
|
|
14080
|
+
return `sha256:${(0, import_node_crypto.createHash)("sha256").update(token).digest("hex")}`;
|
|
14081
|
+
}
|
|
14082
|
+
function readEnvLocalApiKey(content) {
|
|
14083
|
+
let last = null;
|
|
14084
|
+
const regex = /^\s*GLASSTRACE_API_KEY\s*=\s*(.*)$/gm;
|
|
14085
|
+
let match;
|
|
14086
|
+
while ((match = regex.exec(content)) !== null) {
|
|
14087
|
+
const raw = match[1].trim();
|
|
14088
|
+
if (raw === "") continue;
|
|
14089
|
+
const unquoted = raw.replace(/^(['"])(.*)\1$/, "$2");
|
|
14090
|
+
if (unquoted === "" || unquoted === "your_key_here") continue;
|
|
14091
|
+
last = unquoted;
|
|
14092
|
+
}
|
|
14093
|
+
return last;
|
|
14094
|
+
}
|
|
14095
|
+
function isAnonApiKey(value) {
|
|
14096
|
+
if (value === null || value === void 0) return false;
|
|
14097
|
+
return AnonApiKeySchema.safeParse(value).success;
|
|
14098
|
+
}
|
|
14099
|
+
async function resolveEffectiveMcpCredential(projectRoot) {
|
|
14100
|
+
const root = projectRoot ?? process.cwd();
|
|
14101
|
+
const warnings = [];
|
|
14102
|
+
const envLocalKey = await readEnvLocalDevKey(root, warnings);
|
|
14103
|
+
const claimedKey = envLocalKey === null ? await readClaimedKey(root) : null;
|
|
14104
|
+
const anonKey = await readAnonKey(root);
|
|
14105
|
+
let effective = null;
|
|
14106
|
+
if (envLocalKey !== null) {
|
|
14107
|
+
effective = { source: "env-local", key: envLocalKey };
|
|
14108
|
+
} else if (claimedKey !== null) {
|
|
14109
|
+
effective = { source: "claimed-key", key: claimedKey };
|
|
14110
|
+
warnings.push("claimed-key-only");
|
|
14111
|
+
} else if (anonKey !== null) {
|
|
14112
|
+
effective = { source: "anon", key: anonKey };
|
|
14113
|
+
}
|
|
14114
|
+
return { effective, anonKey, warnings };
|
|
14115
|
+
}
|
|
14116
|
+
async function readEnvLocalDevKey(root, warnings) {
|
|
14117
|
+
const modules = await loadFsPath2();
|
|
14118
|
+
if (!modules) return null;
|
|
14119
|
+
const envPath = modules.path.join(root, ".env.local");
|
|
14120
|
+
let content;
|
|
14121
|
+
try {
|
|
14122
|
+
content = await modules.fs.readFile(envPath, "utf-8");
|
|
14123
|
+
} catch {
|
|
14124
|
+
return null;
|
|
14125
|
+
}
|
|
14126
|
+
const raw = readEnvLocalApiKey(content);
|
|
14127
|
+
if (raw === null) return null;
|
|
14128
|
+
const parsed = DevApiKeySchema.safeParse(raw);
|
|
14129
|
+
if (!parsed.success) {
|
|
14130
|
+
warnings.push("malformed-env-local");
|
|
14131
|
+
return null;
|
|
14132
|
+
}
|
|
14133
|
+
return parsed.data;
|
|
14134
|
+
}
|
|
14135
|
+
var MCP_MARKER_FILE = "mcp-connected";
|
|
14136
|
+
var GLASSTRACE_DIR2 = ".glasstrace";
|
|
14137
|
+
async function readMcpMarker(projectRoot) {
|
|
14138
|
+
const root = projectRoot ?? process.cwd();
|
|
14139
|
+
const modules = await loadFsPath2();
|
|
14140
|
+
if (!modules) return { status: "absent" };
|
|
14141
|
+
const markerPath = modules.path.join(root, GLASSTRACE_DIR2, MCP_MARKER_FILE);
|
|
14142
|
+
let content;
|
|
14143
|
+
try {
|
|
14144
|
+
content = await modules.fs.readFile(markerPath, "utf-8");
|
|
14145
|
+
} catch {
|
|
14146
|
+
return { status: "absent" };
|
|
14147
|
+
}
|
|
14148
|
+
let parsed;
|
|
14149
|
+
try {
|
|
14150
|
+
parsed = JSON.parse(content);
|
|
14151
|
+
} catch {
|
|
14152
|
+
return { status: "corrupted" };
|
|
14153
|
+
}
|
|
14154
|
+
if (parsed === null || typeof parsed !== "object") {
|
|
14155
|
+
return { status: "corrupted" };
|
|
14156
|
+
}
|
|
14157
|
+
const obj = parsed;
|
|
14158
|
+
const version2 = obj["version"];
|
|
14159
|
+
if (version2 === void 0) {
|
|
14160
|
+
const keyHash = obj["keyHash"];
|
|
14161
|
+
if (typeof keyHash !== "string" || keyHash === "") {
|
|
14162
|
+
return { status: "corrupted" };
|
|
14163
|
+
}
|
|
14164
|
+
return {
|
|
14165
|
+
status: "valid",
|
|
14166
|
+
credentialSource: "anon",
|
|
14167
|
+
credentialHash: keyHash
|
|
14168
|
+
};
|
|
14169
|
+
}
|
|
14170
|
+
if (version2 === 2) {
|
|
14171
|
+
const source = obj["credentialSource"];
|
|
14172
|
+
const hash2 = obj["credentialHash"];
|
|
14173
|
+
if (source !== "env-local" && source !== "claimed-key" && source !== "anon" || typeof hash2 !== "string" || hash2 === "") {
|
|
14174
|
+
return { status: "corrupted" };
|
|
14175
|
+
}
|
|
14176
|
+
return {
|
|
14177
|
+
status: "valid",
|
|
14178
|
+
credentialSource: source,
|
|
14179
|
+
credentialHash: hash2
|
|
14180
|
+
};
|
|
14181
|
+
}
|
|
14182
|
+
if (typeof version2 === "number" && version2 > 2) {
|
|
14183
|
+
return { status: "unknown-version" };
|
|
14184
|
+
}
|
|
14185
|
+
return { status: "corrupted" };
|
|
14186
|
+
}
|
|
14187
|
+
async function writeMcpMarker(projectRoot, target) {
|
|
14188
|
+
const modules = await loadFsPath2();
|
|
14189
|
+
if (!modules) return false;
|
|
14190
|
+
const dirPath = modules.path.join(projectRoot, GLASSTRACE_DIR2);
|
|
14191
|
+
const markerPath = modules.path.join(dirPath, MCP_MARKER_FILE);
|
|
14192
|
+
const state = await readMcpMarker(projectRoot);
|
|
14193
|
+
if (state.status === "valid" && state.credentialSource === target.credentialSource && state.credentialHash === target.credentialHash) {
|
|
14194
|
+
return false;
|
|
14195
|
+
}
|
|
14196
|
+
await modules.fs.mkdir(dirPath, { recursive: true, mode: 448 });
|
|
14197
|
+
const body = JSON.stringify(
|
|
14198
|
+
{
|
|
14199
|
+
version: 2,
|
|
14200
|
+
credentialSource: target.credentialSource,
|
|
14201
|
+
credentialHash: target.credentialHash,
|
|
14202
|
+
configuredAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
14203
|
+
},
|
|
14204
|
+
null,
|
|
14205
|
+
2
|
|
14206
|
+
);
|
|
14207
|
+
await modules.fs.writeFile(markerPath, body, { mode: 384 });
|
|
14208
|
+
await modules.fs.chmod(markerPath, 384);
|
|
14209
|
+
return true;
|
|
14210
|
+
}
|
|
14040
14211
|
|
|
14041
14212
|
// src/agent-detection/detect.ts
|
|
14042
14213
|
var import_node_child_process = require("node:child_process");
|
|
@@ -14086,9 +14257,9 @@ var AGENT_RULES = [
|
|
|
14086
14257
|
registrationCommand: "npx glasstrace mcp add --agent windsurf"
|
|
14087
14258
|
}
|
|
14088
14259
|
];
|
|
14089
|
-
async function pathExists(
|
|
14260
|
+
async function pathExists(path2, mode = import_node_fs.constants.R_OK) {
|
|
14090
14261
|
try {
|
|
14091
|
-
await (0, import_promises.access)(
|
|
14262
|
+
await (0, import_promises.access)(path2, mode);
|
|
14092
14263
|
return true;
|
|
14093
14264
|
} catch {
|
|
14094
14265
|
return false;
|
|
@@ -14192,12 +14363,12 @@ async function detectAgents(projectRoot) {
|
|
|
14192
14363
|
}
|
|
14193
14364
|
|
|
14194
14365
|
// src/agent-detection/configs.ts
|
|
14195
|
-
function generateMcpConfig(agent, endpoint,
|
|
14366
|
+
function generateMcpConfig(agent, endpoint, bearer) {
|
|
14196
14367
|
if (!endpoint || endpoint.trim() === "") {
|
|
14197
14368
|
throw new Error("endpoint must not be empty");
|
|
14198
14369
|
}
|
|
14199
|
-
if (!
|
|
14200
|
-
throw new Error("
|
|
14370
|
+
if (!bearer || bearer.trim() === "") {
|
|
14371
|
+
throw new Error("bearer must not be empty");
|
|
14201
14372
|
}
|
|
14202
14373
|
switch (agent.name) {
|
|
14203
14374
|
case "claude":
|
|
@@ -14208,7 +14379,7 @@ function generateMcpConfig(agent, endpoint, anonKey) {
|
|
|
14208
14379
|
type: "http",
|
|
14209
14380
|
url: endpoint,
|
|
14210
14381
|
headers: {
|
|
14211
|
-
Authorization: `Bearer ${
|
|
14382
|
+
Authorization: `Bearer ${bearer}`
|
|
14212
14383
|
}
|
|
14213
14384
|
}
|
|
14214
14385
|
}
|
|
@@ -14232,7 +14403,7 @@ function generateMcpConfig(agent, endpoint, anonKey) {
|
|
|
14232
14403
|
glasstrace: {
|
|
14233
14404
|
httpUrl: endpoint,
|
|
14234
14405
|
headers: {
|
|
14235
|
-
Authorization: `Bearer ${
|
|
14406
|
+
Authorization: `Bearer ${bearer}`
|
|
14236
14407
|
}
|
|
14237
14408
|
}
|
|
14238
14409
|
}
|
|
@@ -14247,7 +14418,7 @@ function generateMcpConfig(agent, endpoint, anonKey) {
|
|
|
14247
14418
|
glasstrace: {
|
|
14248
14419
|
url: endpoint,
|
|
14249
14420
|
headers: {
|
|
14250
|
-
Authorization: `Bearer ${
|
|
14421
|
+
Authorization: `Bearer ${bearer}`
|
|
14251
14422
|
}
|
|
14252
14423
|
}
|
|
14253
14424
|
}
|
|
@@ -14262,7 +14433,7 @@ function generateMcpConfig(agent, endpoint, anonKey) {
|
|
|
14262
14433
|
glasstrace: {
|
|
14263
14434
|
serverUrl: endpoint,
|
|
14264
14435
|
headers: {
|
|
14265
|
-
Authorization: `Bearer ${
|
|
14436
|
+
Authorization: `Bearer ${bearer}`
|
|
14266
14437
|
}
|
|
14267
14438
|
}
|
|
14268
14439
|
}
|
|
@@ -14277,7 +14448,7 @@ function generateMcpConfig(agent, endpoint, anonKey) {
|
|
|
14277
14448
|
glasstrace: {
|
|
14278
14449
|
url: endpoint,
|
|
14279
14450
|
headers: {
|
|
14280
|
-
Authorization: `Bearer ${
|
|
14451
|
+
Authorization: `Bearer ${bearer}`
|
|
14281
14452
|
}
|
|
14282
14453
|
}
|
|
14283
14454
|
}
|
|
@@ -14531,13 +14702,7 @@ async function updateGitignore(paths, projectRoot) {
|
|
|
14531
14702
|
}
|
|
14532
14703
|
}
|
|
14533
14704
|
|
|
14534
|
-
// src/cli/scaffolder.ts
|
|
14535
|
-
var import_node_crypto = require("node:crypto");
|
|
14536
|
-
var fs = __toESM(require("node:fs"), 1);
|
|
14537
|
-
var path = __toESM(require("node:path"), 1);
|
|
14538
|
-
|
|
14539
14705
|
// src/cli/constants.ts
|
|
14540
|
-
var MCP_ENDPOINT = "https://api.glasstrace.dev/mcp";
|
|
14541
14706
|
function formatAgentName(name) {
|
|
14542
14707
|
const displayNames = {
|
|
14543
14708
|
claude: "Claude Code",
|
|
@@ -14545,52 +14710,27 @@ function formatAgentName(name) {
|
|
|
14545
14710
|
gemini: "Gemini",
|
|
14546
14711
|
cursor: "Cursor",
|
|
14547
14712
|
windsurf: "Windsurf",
|
|
14548
|
-
generic: "Generic"
|
|
14713
|
+
generic: "Generic helper"
|
|
14549
14714
|
};
|
|
14550
14715
|
return displayNames[name];
|
|
14551
14716
|
}
|
|
14552
14717
|
|
|
14553
|
-
// src/cli/scaffolder.ts
|
|
14554
|
-
function identityFingerprint(token) {
|
|
14555
|
-
return `sha256:${(0, import_node_crypto.createHash)("sha256").update(token).digest("hex")}`;
|
|
14556
|
-
}
|
|
14557
|
-
async function scaffoldMcpMarker(projectRoot, anonKey) {
|
|
14558
|
-
const dirPath = path.join(projectRoot, ".glasstrace");
|
|
14559
|
-
const markerPath = path.join(dirPath, "mcp-connected");
|
|
14560
|
-
const keyHash = identityFingerprint(anonKey);
|
|
14561
|
-
if (fs.existsSync(markerPath)) {
|
|
14562
|
-
try {
|
|
14563
|
-
const existing = JSON.parse(fs.readFileSync(markerPath, "utf-8"));
|
|
14564
|
-
if (existing.keyHash === keyHash) {
|
|
14565
|
-
return false;
|
|
14566
|
-
}
|
|
14567
|
-
} catch {
|
|
14568
|
-
}
|
|
14569
|
-
}
|
|
14570
|
-
fs.mkdirSync(dirPath, { recursive: true, mode: 448 });
|
|
14571
|
-
const marker = JSON.stringify(
|
|
14572
|
-
{ keyHash, configuredAt: (/* @__PURE__ */ new Date()).toISOString() },
|
|
14573
|
-
null,
|
|
14574
|
-
2
|
|
14575
|
-
);
|
|
14576
|
-
fs.writeFileSync(markerPath, marker, { mode: 384 });
|
|
14577
|
-
fs.chmodSync(markerPath, 384);
|
|
14578
|
-
return true;
|
|
14579
|
-
}
|
|
14580
|
-
|
|
14581
14718
|
// src/cli/mcp-add.ts
|
|
14582
14719
|
var execFileAsync = (0, import_node_util.promisify)(import_node_child_process2.execFile);
|
|
14583
|
-
async function registerViaCli(agent,
|
|
14720
|
+
async function registerViaCli(agent, bearer) {
|
|
14584
14721
|
if (!agent.cliAvailable) {
|
|
14585
14722
|
return false;
|
|
14586
14723
|
}
|
|
14724
|
+
if (agent.name !== "codex" && !isAnonApiKey(bearer)) {
|
|
14725
|
+
return false;
|
|
14726
|
+
}
|
|
14587
14727
|
try {
|
|
14588
14728
|
switch (agent.name) {
|
|
14589
14729
|
case "claude": {
|
|
14590
14730
|
const payload = JSON.stringify({
|
|
14591
14731
|
type: "http",
|
|
14592
14732
|
url: MCP_ENDPOINT,
|
|
14593
|
-
headers: { Authorization: `Bearer ${
|
|
14733
|
+
headers: { Authorization: `Bearer ${bearer}` }
|
|
14594
14734
|
});
|
|
14595
14735
|
await execFileAsync("claude", [
|
|
14596
14736
|
"mcp",
|
|
@@ -14611,11 +14751,11 @@ async function registerViaCli(agent, anonKey) {
|
|
|
14611
14751
|
MCP_ENDPOINT
|
|
14612
14752
|
]);
|
|
14613
14753
|
const configPath = agent.mcpConfigPath;
|
|
14614
|
-
if (configPath !== null &&
|
|
14615
|
-
const content =
|
|
14754
|
+
if (configPath !== null && fs.existsSync(configPath)) {
|
|
14755
|
+
const content = fs.readFileSync(configPath, "utf-8");
|
|
14616
14756
|
if (!content.includes("bearer_token_env_var")) {
|
|
14617
14757
|
const appendContent = content.endsWith("\n") ? "" : "\n";
|
|
14618
|
-
|
|
14758
|
+
fs.writeFileSync(
|
|
14619
14759
|
configPath,
|
|
14620
14760
|
content + appendContent + 'bearer_token_env_var = "GLASSTRACE_API_KEY"\n',
|
|
14621
14761
|
"utf-8"
|
|
@@ -14634,7 +14774,7 @@ async function registerViaCli(agent, anonKey) {
|
|
|
14634
14774
|
"--transport",
|
|
14635
14775
|
"http",
|
|
14636
14776
|
"--header",
|
|
14637
|
-
`Authorization: Bearer ${
|
|
14777
|
+
`Authorization: Bearer ${bearer}`,
|
|
14638
14778
|
"glasstrace",
|
|
14639
14779
|
MCP_ENDPOINT
|
|
14640
14780
|
]);
|
|
@@ -14647,35 +14787,51 @@ async function registerViaCli(agent, anonKey) {
|
|
|
14647
14787
|
return false;
|
|
14648
14788
|
}
|
|
14649
14789
|
}
|
|
14790
|
+
async function markerMatchesEffective(projectRoot, effective) {
|
|
14791
|
+
const state = await readMcpMarker(projectRoot);
|
|
14792
|
+
if (state.status !== "valid") return false;
|
|
14793
|
+
return state.credentialHash === identityFingerprint(effective.key);
|
|
14794
|
+
}
|
|
14650
14795
|
async function mcpAdd(options) {
|
|
14651
14796
|
const force = options?.force ?? false;
|
|
14652
14797
|
const dryRun = options?.dryRun ?? false;
|
|
14653
14798
|
const projectRoot = process.cwd();
|
|
14654
14799
|
const messages = [];
|
|
14655
|
-
const
|
|
14656
|
-
if (
|
|
14800
|
+
const resolved = await resolveEffectiveMcpCredential(projectRoot);
|
|
14801
|
+
if (resolved.effective === null) {
|
|
14657
14802
|
return {
|
|
14658
14803
|
exitCode: 1,
|
|
14659
14804
|
results: [],
|
|
14660
14805
|
messages: ["Error: Run `glasstrace init` first to generate an API key."]
|
|
14661
14806
|
};
|
|
14662
14807
|
}
|
|
14663
|
-
|
|
14664
|
-
|
|
14665
|
-
|
|
14666
|
-
|
|
14667
|
-
|
|
14668
|
-
|
|
14669
|
-
|
|
14808
|
+
if (resolved.warnings.includes("claimed-key-only")) {
|
|
14809
|
+
messages.push(
|
|
14810
|
+
"Note: dev key was loaded from .glasstrace/claimed-key. Copy it into .env.local so your app and Codex pick it up automatically."
|
|
14811
|
+
);
|
|
14812
|
+
}
|
|
14813
|
+
const markerPath = path.join(projectRoot, ".glasstrace", "mcp-connected");
|
|
14814
|
+
if (fs.existsSync(markerPath) && !force) {
|
|
14815
|
+
if (await markerMatchesEffective(projectRoot, resolved.effective)) {
|
|
14816
|
+
return {
|
|
14817
|
+
exitCode: 0,
|
|
14818
|
+
results: [],
|
|
14819
|
+
messages: ["MCP already configured. Use --force to reconfigure."]
|
|
14820
|
+
};
|
|
14821
|
+
}
|
|
14822
|
+
messages.push(
|
|
14823
|
+
"Detected a credential change since MCP was last configured. Refreshing MCP config so queries use the current account credential."
|
|
14824
|
+
);
|
|
14670
14825
|
}
|
|
14671
14826
|
const agents = await detectAgents(projectRoot);
|
|
14672
14827
|
const detectedNonGeneric = agents.filter((a) => a.name !== "generic");
|
|
14673
|
-
const
|
|
14828
|
+
const genericAgent = agents.find((a) => a.name === "generic");
|
|
14829
|
+
const targetAgents = genericAgent ? [...detectedNonGeneric, genericAgent] : detectedNonGeneric;
|
|
14674
14830
|
if (dryRun) {
|
|
14675
14831
|
messages.push("Dry run: would perform the following actions:", "");
|
|
14676
14832
|
for (const agent of targetAgents) {
|
|
14677
14833
|
const name = formatAgentName(agent.name);
|
|
14678
|
-
if (agent.cliAvailable) {
|
|
14834
|
+
if (agent.cliAvailable && resolved.effective.source === "anon") {
|
|
14679
14835
|
messages.push(
|
|
14680
14836
|
` ${name}: Register via CLI (${agent.name} mcp add)`
|
|
14681
14837
|
);
|
|
@@ -14698,10 +14854,11 @@ async function mcpAdd(options) {
|
|
|
14698
14854
|
return { exitCode: 0, results: [], messages };
|
|
14699
14855
|
}
|
|
14700
14856
|
const results = [];
|
|
14857
|
+
const bearer = resolved.effective.key;
|
|
14701
14858
|
for (const agent of targetAgents) {
|
|
14702
14859
|
const name = formatAgentName(agent.name);
|
|
14703
14860
|
if (agent.name !== "generic") {
|
|
14704
|
-
const cliSuccess = await registerViaCli(agent,
|
|
14861
|
+
const cliSuccess = await registerViaCli(agent, bearer);
|
|
14705
14862
|
if (cliSuccess) {
|
|
14706
14863
|
const infoContent = generateInfoSection(agent, MCP_ENDPOINT);
|
|
14707
14864
|
if (infoContent !== "") {
|
|
@@ -14718,9 +14875,9 @@ async function mcpAdd(options) {
|
|
|
14718
14875
|
}
|
|
14719
14876
|
if (agent.mcpConfigPath !== null) {
|
|
14720
14877
|
try {
|
|
14721
|
-
const configContent = generateMcpConfig(agent, MCP_ENDPOINT,
|
|
14878
|
+
const configContent = generateMcpConfig(agent, MCP_ENDPOINT, bearer);
|
|
14722
14879
|
await writeMcpConfig(agent, configContent, projectRoot);
|
|
14723
|
-
if (
|
|
14880
|
+
if (fs.existsSync(agent.mcpConfigPath)) {
|
|
14724
14881
|
const infoContent = generateInfoSection(agent, MCP_ENDPOINT);
|
|
14725
14882
|
if (infoContent !== "") {
|
|
14726
14883
|
await injectInfoSection(agent, infoContent, projectRoot);
|
|
@@ -14763,7 +14920,10 @@ async function mcpAdd(options) {
|
|
|
14763
14920
|
);
|
|
14764
14921
|
const anySuccess = results.some((r) => r.success);
|
|
14765
14922
|
if (anySuccess) {
|
|
14766
|
-
await
|
|
14923
|
+
await writeMcpMarker(projectRoot, {
|
|
14924
|
+
credentialSource: resolved.effective.source,
|
|
14925
|
+
credentialHash: identityFingerprint(resolved.effective.key)
|
|
14926
|
+
});
|
|
14767
14927
|
}
|
|
14768
14928
|
messages.push("", "MCP registration summary:");
|
|
14769
14929
|
for (const result of results) {
|
|
@@ -14775,6 +14935,17 @@ async function mcpAdd(options) {
|
|
|
14775
14935
|
" No agents detected. Place agent marker files (e.g., CLAUDE.md, .cursor/) in your project."
|
|
14776
14936
|
);
|
|
14777
14937
|
}
|
|
14938
|
+
const detectedNonGenericResults = results.filter(
|
|
14939
|
+
(r) => detectedNonGeneric.some((a) => a.name === r.agent)
|
|
14940
|
+
);
|
|
14941
|
+
const allDetectedNonGenericFailed = detectedNonGeneric.length > 0 && !detectedNonGenericResults.some((r) => r.success);
|
|
14942
|
+
if (allDetectedNonGenericFailed) {
|
|
14943
|
+
messages.push(
|
|
14944
|
+
"",
|
|
14945
|
+
"All detected agent registrations failed. Check errors above."
|
|
14946
|
+
);
|
|
14947
|
+
return { exitCode: 1, results, messages };
|
|
14948
|
+
}
|
|
14778
14949
|
if (!anySuccess && results.length > 0) {
|
|
14779
14950
|
messages.push(
|
|
14780
14951
|
"",
|
|
@@ -14789,6 +14960,7 @@ async function mcpAdd(options) {
|
|
|
14789
14960
|
}
|
|
14790
14961
|
// Annotate the CommonJS export names for ESM import in node:
|
|
14791
14962
|
0 && (module.exports = {
|
|
14792
|
-
mcpAdd
|
|
14963
|
+
mcpAdd,
|
|
14964
|
+
registerViaCli
|
|
14793
14965
|
});
|
|
14794
14966
|
//# sourceMappingURL=mcp-add.cjs.map
|