@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.
Files changed (66) hide show
  1. package/README.md +78 -1
  2. package/dist/{chunk-55FBXXER.js → chunk-2M57EO6U.js} +2 -2
  3. package/dist/chunk-3LILTM3T.js +384 -0
  4. package/dist/chunk-3LILTM3T.js.map +1 -0
  5. package/dist/{chunk-KE7MCPO5.js → chunk-4EZ6JTDG.js} +2 -2
  6. package/dist/{chunk-67RIOAXV.js → chunk-6RNBUUBR.js} +2 -2
  7. package/dist/{chunk-DO2YPMQ5.js → chunk-C567H5EQ.js} +23 -5
  8. package/dist/chunk-C567H5EQ.js.map +1 -0
  9. package/dist/{chunk-UGJ3X4CT.js → chunk-DST4UBXU.js} +2 -2
  10. package/dist/{chunk-DXRZKKSO.js → chunk-NB7GJE4S.js} +2 -4
  11. package/dist/chunk-NB7GJE4S.js.map +1 -0
  12. package/dist/{chunk-HAU66QBQ.js → chunk-P4OYPFQ5.js} +9 -9
  13. package/dist/chunk-P4OYPFQ5.js.map +1 -0
  14. package/dist/{chunk-LU3PPAOQ.js → chunk-UJ2JC7PZ.js} +4 -4
  15. package/dist/chunk-UJ2JC7PZ.js.map +1 -0
  16. package/dist/{chunk-TQ54WLCZ.js → chunk-X5MAXP5T.js} +2 -1
  17. package/dist/{chunk-ZBTC5QIQ.js → chunk-Z35HKVSO.js} +137 -10
  18. package/dist/chunk-Z35HKVSO.js.map +1 -0
  19. package/dist/cli/init.cjs +1313 -1118
  20. package/dist/cli/init.cjs.map +1 -1
  21. package/dist/cli/init.js +456 -72
  22. package/dist/cli/init.js.map +1 -1
  23. package/dist/cli/mcp-add.cjs +257 -85
  24. package/dist/cli/mcp-add.cjs.map +1 -1
  25. package/dist/cli/mcp-add.d.cts +35 -4
  26. package/dist/cli/mcp-add.d.ts +35 -4
  27. package/dist/cli/mcp-add.js +61 -25
  28. package/dist/cli/mcp-add.js.map +1 -1
  29. package/dist/cli/status.cjs.map +1 -1
  30. package/dist/cli/status.js +1 -1
  31. package/dist/cli/uninit.cjs +1 -1
  32. package/dist/cli/uninit.cjs.map +1 -1
  33. package/dist/cli/uninit.js +4 -4
  34. package/dist/cli/validate.cjs +14162 -2
  35. package/dist/cli/validate.cjs.map +1 -1
  36. package/dist/cli/validate.d.cts +7 -3
  37. package/dist/cli/validate.d.ts +7 -3
  38. package/dist/cli/validate.js +25 -2
  39. package/dist/cli/validate.js.map +1 -1
  40. package/dist/edge-entry.js +2 -2
  41. package/dist/index.cjs +423 -12
  42. package/dist/index.cjs.map +1 -1
  43. package/dist/index.js +5 -5
  44. package/dist/{monorepo-N5Z63XP7.js → monorepo-PFVNPQ6X.js} +3 -3
  45. package/dist/node-entry.cjs +423 -12
  46. package/dist/node-entry.cjs.map +1 -1
  47. package/dist/node-entry.js +7 -7
  48. package/dist/node-subpath.js +3 -3
  49. package/dist/{source-map-uploader-BJIXRLJ6.js → source-map-uploader-DPUUCLNW.js} +3 -3
  50. package/package.json +1 -1
  51. package/dist/chunk-DO2YPMQ5.js.map +0 -1
  52. package/dist/chunk-DXRZKKSO.js.map +0 -1
  53. package/dist/chunk-HAU66QBQ.js.map +0 -1
  54. package/dist/chunk-IP4NMDJK.js +0 -98
  55. package/dist/chunk-IP4NMDJK.js.map +0 -1
  56. package/dist/chunk-LU3PPAOQ.js.map +0 -1
  57. package/dist/chunk-O63DJKIJ.js +0 -460
  58. package/dist/chunk-O63DJKIJ.js.map +0 -1
  59. package/dist/chunk-ZBTC5QIQ.js.map +0 -1
  60. /package/dist/{chunk-55FBXXER.js.map → chunk-2M57EO6U.js.map} +0 -0
  61. /package/dist/{chunk-KE7MCPO5.js.map → chunk-4EZ6JTDG.js.map} +0 -0
  62. /package/dist/{chunk-67RIOAXV.js.map → chunk-6RNBUUBR.js.map} +0 -0
  63. /package/dist/{chunk-UGJ3X4CT.js.map → chunk-DST4UBXU.js.map} +0 -0
  64. /package/dist/{chunk-TQ54WLCZ.js.map → chunk-X5MAXP5T.js.map} +0 -0
  65. /package/dist/{monorepo-N5Z63XP7.js.map → monorepo-PFVNPQ6X.js.map} +0 -0
  66. /package/dist/{source-map-uploader-BJIXRLJ6.js.map → source-map-uploader-DPUUCLNW.js.map} +0 -0
@@ -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 fs2 = __toESM(require("node:fs"), 1);
38
- var path2 = __toESM(require("node:path"), 1);
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, path3) {
809
- if (!path3)
812
+ function getElementAtPath(obj, path2) {
813
+ if (!path2)
810
814
  return obj;
811
- return path3.reduce((acc, key) => acc?.[key], obj);
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(path3, issues) {
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(path3);
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, path3 = []) => {
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 = [...path3, ...issue2.path];
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 path3 = _path.map((seg) => typeof seg === "object" ? seg.key : seg);
1424
- for (const seg of path3) {
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 path3 = ref.slice(1).split("/").filter(Boolean);
13402
- if (path3.length === 0) {
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 (path3[0] === defsKey) {
13407
- const key = path3[1];
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 [fs3, path3] = await Promise.all([
14013
+ const [fs2, path2] = await Promise.all([
14009
14014
  import("node:fs/promises"),
14010
14015
  import("node:path")
14011
14016
  ]);
14012
- fsPathCache = { fs: fs3, path: path3 };
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(path3, mode = import_node_fs.constants.R_OK) {
14260
+ async function pathExists(path2, mode = import_node_fs.constants.R_OK) {
14090
14261
  try {
14091
- await (0, import_promises.access)(path3, mode);
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, anonKey) {
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 (!anonKey || anonKey.trim() === "") {
14200
- throw new Error("anonKey must not be empty");
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 ${anonKey}`
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 ${anonKey}`
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 ${anonKey}`
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 ${anonKey}`
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 ${anonKey}`
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, anonKey) {
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 ${anonKey}` }
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 && fs2.existsSync(configPath)) {
14615
- const content = fs2.readFileSync(configPath, "utf-8");
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
- fs2.writeFileSync(
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 ${anonKey}`,
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 anonKey = await readAnonKey(projectRoot);
14656
- if (anonKey === null) {
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
- const markerPath = path2.join(projectRoot, ".glasstrace", "mcp-connected");
14664
- if (fs2.existsSync(markerPath) && !force) {
14665
- return {
14666
- exitCode: 0,
14667
- results: [],
14668
- messages: ["MCP already configured. Use --force to reconfigure."]
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 targetAgents = detectedNonGeneric.length > 0 ? detectedNonGeneric : agents.filter((a) => a.name === "generic");
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, anonKey);
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, anonKey);
14878
+ const configContent = generateMcpConfig(agent, MCP_ENDPOINT, bearer);
14722
14879
  await writeMcpConfig(agent, configContent, projectRoot);
14723
- if (fs2.existsSync(agent.mcpConfigPath)) {
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 scaffoldMcpMarker(projectRoot, anonKey);
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