@glasstrace/sdk 1.1.0 → 1.1.1

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 (59) hide show
  1. package/dist/{chunk-KE7MCPO5.js → chunk-4EZ6JTDG.js} +2 -2
  2. package/dist/{chunk-67RIOAXV.js → chunk-6RNBUUBR.js} +2 -2
  3. package/dist/{chunk-DXRZKKSO.js → chunk-7SZQN6IU.js} +1 -3
  4. package/dist/chunk-7SZQN6IU.js.map +1 -0
  5. package/dist/{chunk-55FBXXER.js → chunk-DIM4JRXM.js} +2 -2
  6. package/dist/{chunk-UGJ3X4CT.js → chunk-DST4UBXU.js} +2 -2
  7. package/dist/{chunk-DO2YPMQ5.js → chunk-MXDZHFJQ.js} +23 -5
  8. package/dist/chunk-MXDZHFJQ.js.map +1 -0
  9. package/dist/chunk-P22UQ2OJ.js +384 -0
  10. package/dist/chunk-P22UQ2OJ.js.map +1 -0
  11. package/dist/{chunk-HAU66QBQ.js → chunk-P4OYPFQ5.js} +9 -9
  12. package/dist/chunk-P4OYPFQ5.js.map +1 -0
  13. package/dist/{chunk-TQ54WLCZ.js → chunk-X5MAXP5T.js} +2 -1
  14. package/dist/{chunk-ZBTC5QIQ.js → chunk-Y26HJUPD.js} +9 -9
  15. package/dist/{chunk-LU3PPAOQ.js → chunk-ZRDQ6ZKI.js} +474 -93
  16. package/dist/chunk-ZRDQ6ZKI.js.map +1 -0
  17. package/dist/cli/init.cjs +1118 -946
  18. package/dist/cli/init.cjs.map +1 -1
  19. package/dist/cli/init.js +42 -29
  20. package/dist/cli/init.js.map +1 -1
  21. package/dist/cli/mcp-add.cjs +243 -83
  22. package/dist/cli/mcp-add.cjs.map +1 -1
  23. package/dist/cli/mcp-add.d.cts +35 -4
  24. package/dist/cli/mcp-add.d.ts +35 -4
  25. package/dist/cli/mcp-add.js +48 -24
  26. package/dist/cli/mcp-add.js.map +1 -1
  27. package/dist/cli/status.cjs.map +1 -1
  28. package/dist/cli/status.js +3 -1
  29. package/dist/cli/status.js.map +1 -1
  30. package/dist/cli/uninit.cjs +4 -4
  31. package/dist/cli/uninit.cjs.map +1 -1
  32. package/dist/cli/uninit.js +4 -4
  33. package/dist/edge-entry.js +2 -2
  34. package/dist/index.cjs +293 -11
  35. package/dist/index.cjs.map +1 -1
  36. package/dist/index.js +5 -5
  37. package/dist/{monorepo-N5Z63XP7.js → monorepo-GSL6JD3G.js} +5 -3
  38. package/dist/node-entry.cjs +293 -11
  39. package/dist/node-entry.cjs.map +1 -1
  40. package/dist/node-entry.js +7 -7
  41. package/dist/node-subpath.js +3 -3
  42. package/dist/{source-map-uploader-BJIXRLJ6.js → source-map-uploader-DPUUCLNW.js} +3 -3
  43. package/package.json +1 -1
  44. package/dist/chunk-DO2YPMQ5.js.map +0 -1
  45. package/dist/chunk-DXRZKKSO.js.map +0 -1
  46. package/dist/chunk-HAU66QBQ.js.map +0 -1
  47. package/dist/chunk-IP4NMDJK.js +0 -98
  48. package/dist/chunk-IP4NMDJK.js.map +0 -1
  49. package/dist/chunk-LU3PPAOQ.js.map +0 -1
  50. package/dist/chunk-O63DJKIJ.js +0 -460
  51. package/dist/chunk-O63DJKIJ.js.map +0 -1
  52. /package/dist/{chunk-KE7MCPO5.js.map → chunk-4EZ6JTDG.js.map} +0 -0
  53. /package/dist/{chunk-67RIOAXV.js.map → chunk-6RNBUUBR.js.map} +0 -0
  54. /package/dist/{chunk-55FBXXER.js.map → chunk-DIM4JRXM.js.map} +0 -0
  55. /package/dist/{chunk-UGJ3X4CT.js.map → chunk-DST4UBXU.js.map} +0 -0
  56. /package/dist/{chunk-TQ54WLCZ.js.map → chunk-X5MAXP5T.js.map} +0 -0
  57. /package/dist/{chunk-ZBTC5QIQ.js.map → chunk-Y26HJUPD.js.map} +0 -0
  58. /package/dist/{monorepo-N5Z63XP7.js.map → monorepo-GSL6JD3G.js.map} +0 -0
  59. /package/dist/{source-map-uploader-BJIXRLJ6.js.map → source-map-uploader-DPUUCLNW.js.map} +0 -0
package/dist/index.cjs CHANGED
@@ -17006,6 +17006,7 @@ function classifyFetchTarget(url2) {
17006
17006
  init_dist();
17007
17007
  var GLASSTRACE_DIR = ".glasstrace";
17008
17008
  var ANON_KEY_FILE = "anon_key";
17009
+ var CLAIMED_KEY_FILE = "claimed-key";
17009
17010
  var fsPathCache;
17010
17011
  async function loadFsPath() {
17011
17012
  if (fsPathCache !== void 0) return fsPathCache;
@@ -17042,6 +17043,22 @@ async function readAnonKey(projectRoot) {
17042
17043
  }
17043
17044
  return null;
17044
17045
  }
17046
+ async function readClaimedKey(projectRoot) {
17047
+ const root = projectRoot ?? process.cwd();
17048
+ const modules = await loadFsPath();
17049
+ if (!modules) return null;
17050
+ const keyPath = modules.path.join(root, GLASSTRACE_DIR, CLAIMED_KEY_FILE);
17051
+ try {
17052
+ const content = await modules.fs.readFile(keyPath, "utf-8");
17053
+ const trimmed = content.trim();
17054
+ const parsed = DevApiKeySchema.safeParse(trimmed);
17055
+ if (parsed.success) {
17056
+ return parsed.data;
17057
+ }
17058
+ } catch {
17059
+ }
17060
+ return null;
17061
+ }
17045
17062
  async function getOrCreateAnonKey(projectRoot) {
17046
17063
  const root = projectRoot ?? process.cwd();
17047
17064
  const existingKey = await readAnonKey(root);
@@ -17378,8 +17395,259 @@ function sleep(ms, scheduler, signal) {
17378
17395
  });
17379
17396
  }
17380
17397
 
17381
- // src/init-client.ts
17398
+ // src/mcp-runtime.ts
17399
+ var import_node_crypto = require("node:crypto");
17400
+ init_dist();
17401
+ var MCP_ENDPOINT = "https://api.glasstrace.dev/mcp";
17402
+ var fsPathCache2;
17403
+ async function loadFsPath2() {
17404
+ if (fsPathCache2 !== void 0) return fsPathCache2;
17405
+ try {
17406
+ const [fs3, path3] = await Promise.all([
17407
+ import("node:fs/promises"),
17408
+ import("node:path")
17409
+ ]);
17410
+ fsPathCache2 = { fs: fs3, path: path3 };
17411
+ return fsPathCache2;
17412
+ } catch {
17413
+ fsPathCache2 = null;
17414
+ return null;
17415
+ }
17416
+ }
17417
+ function identityFingerprint(token) {
17418
+ return `sha256:${(0, import_node_crypto.createHash)("sha256").update(token).digest("hex")}`;
17419
+ }
17420
+ function mcpConfigMatches(existingContent, expectedContent) {
17421
+ const trimmedExpected = expectedContent.trim();
17422
+ try {
17423
+ const existingParsed = JSON.parse(existingContent);
17424
+ const expectedParsed = JSON.parse(trimmedExpected);
17425
+ return JSON.stringify(canonicalize(existingParsed)) === JSON.stringify(canonicalize(expectedParsed));
17426
+ } catch {
17427
+ }
17428
+ return existingContent.trim() === trimmedExpected;
17429
+ }
17430
+ function canonicalize(value) {
17431
+ if (Array.isArray(value)) {
17432
+ return value.map(canonicalize);
17433
+ }
17434
+ if (value !== null && typeof value === "object") {
17435
+ const obj = value;
17436
+ const sorted = {};
17437
+ for (const key of Object.keys(obj).sort()) {
17438
+ sorted[key] = canonicalize(obj[key]);
17439
+ }
17440
+ return sorted;
17441
+ }
17442
+ return value;
17443
+ }
17444
+ function readEnvLocalApiKey(content) {
17445
+ let last = null;
17446
+ const regex = /^\s*GLASSTRACE_API_KEY\s*=\s*(.*)$/gm;
17447
+ let match;
17448
+ while ((match = regex.exec(content)) !== null) {
17449
+ const raw = match[1].trim();
17450
+ if (raw === "") continue;
17451
+ const unquoted = raw.replace(/^(['"])(.*)\1$/, "$2");
17452
+ if (unquoted === "" || unquoted === "your_key_here") continue;
17453
+ last = unquoted;
17454
+ }
17455
+ return last;
17456
+ }
17457
+ async function resolveEffectiveMcpCredential(projectRoot) {
17458
+ const root = projectRoot ?? process.cwd();
17459
+ const warnings = [];
17460
+ const envLocalKey = await readEnvLocalDevKey(root, warnings);
17461
+ const claimedKey = envLocalKey === null ? await readClaimedKey(root) : null;
17462
+ const anonKey = await readAnonKey(root);
17463
+ let effective = null;
17464
+ if (envLocalKey !== null) {
17465
+ effective = { source: "env-local", key: envLocalKey };
17466
+ } else if (claimedKey !== null) {
17467
+ effective = { source: "claimed-key", key: claimedKey };
17468
+ warnings.push("claimed-key-only");
17469
+ } else if (anonKey !== null) {
17470
+ effective = { source: "anon", key: anonKey };
17471
+ }
17472
+ return { effective, anonKey, warnings };
17473
+ }
17474
+ async function readEnvLocalDevKey(root, warnings) {
17475
+ const modules = await loadFsPath2();
17476
+ if (!modules) return null;
17477
+ const envPath = modules.path.join(root, ".env.local");
17478
+ let content;
17479
+ try {
17480
+ content = await modules.fs.readFile(envPath, "utf-8");
17481
+ } catch {
17482
+ return null;
17483
+ }
17484
+ const raw = readEnvLocalApiKey(content);
17485
+ if (raw === null) return null;
17486
+ const parsed = DevApiKeySchema.safeParse(raw);
17487
+ if (!parsed.success) {
17488
+ warnings.push("malformed-env-local");
17489
+ return null;
17490
+ }
17491
+ return parsed.data;
17492
+ }
17493
+ var MCP_MARKER_FILE = "mcp-connected";
17382
17494
  var GLASSTRACE_DIR2 = ".glasstrace";
17495
+ async function readMcpMarker(projectRoot) {
17496
+ const root = projectRoot ?? process.cwd();
17497
+ const modules = await loadFsPath2();
17498
+ if (!modules) return { status: "absent" };
17499
+ const markerPath = modules.path.join(root, GLASSTRACE_DIR2, MCP_MARKER_FILE);
17500
+ let content;
17501
+ try {
17502
+ content = await modules.fs.readFile(markerPath, "utf-8");
17503
+ } catch {
17504
+ return { status: "absent" };
17505
+ }
17506
+ let parsed;
17507
+ try {
17508
+ parsed = JSON.parse(content);
17509
+ } catch {
17510
+ return { status: "corrupted" };
17511
+ }
17512
+ if (parsed === null || typeof parsed !== "object") {
17513
+ return { status: "corrupted" };
17514
+ }
17515
+ const obj = parsed;
17516
+ const version2 = obj["version"];
17517
+ if (version2 === void 0) {
17518
+ const keyHash = obj["keyHash"];
17519
+ if (typeof keyHash !== "string" || keyHash === "") {
17520
+ return { status: "corrupted" };
17521
+ }
17522
+ return {
17523
+ status: "valid",
17524
+ credentialSource: "anon",
17525
+ credentialHash: keyHash
17526
+ };
17527
+ }
17528
+ if (version2 === 2) {
17529
+ const source = obj["credentialSource"];
17530
+ const hash2 = obj["credentialHash"];
17531
+ if (source !== "env-local" && source !== "claimed-key" && source !== "anon" || typeof hash2 !== "string" || hash2 === "") {
17532
+ return { status: "corrupted" };
17533
+ }
17534
+ return {
17535
+ status: "valid",
17536
+ credentialSource: source,
17537
+ credentialHash: hash2
17538
+ };
17539
+ }
17540
+ if (typeof version2 === "number" && version2 > 2) {
17541
+ return { status: "unknown-version" };
17542
+ }
17543
+ return { status: "corrupted" };
17544
+ }
17545
+ async function writeMcpMarker(projectRoot, target) {
17546
+ const modules = await loadFsPath2();
17547
+ if (!modules) return false;
17548
+ const dirPath = modules.path.join(projectRoot, GLASSTRACE_DIR2);
17549
+ const markerPath = modules.path.join(dirPath, MCP_MARKER_FILE);
17550
+ const state = await readMcpMarker(projectRoot);
17551
+ if (state.status === "valid" && state.credentialSource === target.credentialSource && state.credentialHash === target.credentialHash) {
17552
+ return false;
17553
+ }
17554
+ await modules.fs.mkdir(dirPath, { recursive: true, mode: 448 });
17555
+ const body = JSON.stringify(
17556
+ {
17557
+ version: 2,
17558
+ credentialSource: target.credentialSource,
17559
+ credentialHash: target.credentialHash,
17560
+ configuredAt: (/* @__PURE__ */ new Date()).toISOString()
17561
+ },
17562
+ null,
17563
+ 2
17564
+ );
17565
+ await modules.fs.writeFile(markerPath, body, { mode: 384 });
17566
+ await modules.fs.chmod(markerPath, 384);
17567
+ return true;
17568
+ }
17569
+ var MCP_CONFIG_FILE = "mcp.json";
17570
+ var refreshNudgeEmitted = false;
17571
+ function emitRefreshNudge(persistedSource) {
17572
+ if (refreshNudgeEmitted) return;
17573
+ refreshNudgeEmitted = true;
17574
+ try {
17575
+ if (persistedSource === "claimed-key") {
17576
+ process.stderr.write(
17577
+ "[glasstrace] MCP config refreshed for the new credential. Copy .glasstrace/claimed-key into .env.local so Codex can pick it up on next restart.\n"
17578
+ );
17579
+ } else {
17580
+ process.stderr.write(
17581
+ "[glasstrace] MCP config refreshed for the new credential.\n"
17582
+ );
17583
+ }
17584
+ } catch {
17585
+ }
17586
+ }
17587
+ function genericMcpConfigContent(endpoint, bearer) {
17588
+ return JSON.stringify(
17589
+ {
17590
+ mcpServers: {
17591
+ glasstrace: {
17592
+ url: endpoint,
17593
+ headers: {
17594
+ Authorization: `Bearer ${bearer}`
17595
+ }
17596
+ }
17597
+ }
17598
+ },
17599
+ null,
17600
+ 2
17601
+ );
17602
+ }
17603
+ async function refreshGenericMcpConfigAtRuntime(projectRoot, effective, anonKeyOnDisk) {
17604
+ if (effective === null || effective.source === "anon") {
17605
+ return { action: "skipped-anon-source" };
17606
+ }
17607
+ if (anonKeyOnDisk === null) {
17608
+ return { action: "absent" };
17609
+ }
17610
+ const modules = await loadFsPath2();
17611
+ if (!modules) return { action: "absent" };
17612
+ const dirPath = modules.path.join(projectRoot, GLASSTRACE_DIR2);
17613
+ const configPath = modules.path.join(dirPath, MCP_CONFIG_FILE);
17614
+ const tmpPath = configPath + ".tmp";
17615
+ let existing;
17616
+ try {
17617
+ existing = await modules.fs.readFile(configPath, "utf-8");
17618
+ } catch (err) {
17619
+ const code = err.code;
17620
+ if (code === "ENOENT") {
17621
+ return { action: "absent" };
17622
+ }
17623
+ return { action: "preserved" };
17624
+ }
17625
+ const expectedAnon = genericMcpConfigContent(MCP_ENDPOINT, anonKeyOnDisk);
17626
+ if (!mcpConfigMatches(existing, expectedAnon)) {
17627
+ return { action: "preserved" };
17628
+ }
17629
+ const replacement = genericMcpConfigContent(MCP_ENDPOINT, effective.key);
17630
+ try {
17631
+ await modules.fs.writeFile(tmpPath, replacement, { mode: 384 });
17632
+ await modules.fs.chmod(tmpPath, 384);
17633
+ await modules.fs.rename(tmpPath, configPath);
17634
+ await writeMcpMarker(projectRoot, {
17635
+ credentialSource: effective.source,
17636
+ credentialHash: identityFingerprint(effective.key)
17637
+ });
17638
+ } catch {
17639
+ try {
17640
+ await modules.fs.unlink(tmpPath);
17641
+ } catch {
17642
+ }
17643
+ return { action: "preserved" };
17644
+ }
17645
+ emitRefreshNudge(effective.source);
17646
+ return { action: "rewrote" };
17647
+ }
17648
+
17649
+ // src/init-client.ts
17650
+ var GLASSTRACE_DIR3 = ".glasstrace";
17383
17651
  var CONFIG_FILE = "config";
17384
17652
  var TWENTY_FOUR_HOURS_MS = 24 * 60 * 60 * 1e3;
17385
17653
  var INIT_TIMEOUT_MS = 1e4;
@@ -17416,7 +17684,7 @@ function loadCachedConfig(projectRoot) {
17416
17684
  const modules = loadFsSyncOrNull();
17417
17685
  if (!modules) return null;
17418
17686
  const root = projectRoot ?? process.cwd();
17419
- const configPath = modules.join(root, GLASSTRACE_DIR2, CONFIG_FILE);
17687
+ const configPath = modules.join(root, GLASSTRACE_DIR3, CONFIG_FILE);
17420
17688
  try {
17421
17689
  const content = modules.readFileSync(configPath, "utf-8");
17422
17690
  const parsed = JSON.parse(content);
@@ -17442,7 +17710,7 @@ async function saveCachedConfig(response, projectRoot) {
17442
17710
  const modules = await loadFsPathAsync();
17443
17711
  if (!modules) return;
17444
17712
  const root = projectRoot ?? process.cwd();
17445
- const dirPath = modules.path.join(root, GLASSTRACE_DIR2);
17713
+ const dirPath = modules.path.join(root, GLASSTRACE_DIR3);
17446
17714
  const configPath = modules.path.join(dirPath, CONFIG_FILE);
17447
17715
  const tmpPath = `${configPath}.tmp`;
17448
17716
  try {
@@ -17568,11 +17836,11 @@ async function writeClaimedKey(newApiKey, projectRoot) {
17568
17836
  );
17569
17837
  } catch {
17570
17838
  }
17571
- return;
17839
+ return { persisted: "env-local" };
17572
17840
  }
17573
17841
  let claimedKeyWritten = false;
17574
17842
  try {
17575
- const dirPath = modules.path.join(root, GLASSTRACE_DIR2);
17843
+ const dirPath = modules.path.join(root, GLASSTRACE_DIR3);
17576
17844
  await modules.fs.mkdir(dirPath, { recursive: true, mode: 448 });
17577
17845
  await modules.fs.chmod(dirPath, 448);
17578
17846
  const claimedKeyPath = modules.path.join(dirPath, "claimed-key");
@@ -17591,7 +17859,7 @@ async function writeClaimedKey(newApiKey, projectRoot) {
17591
17859
  );
17592
17860
  } catch {
17593
17861
  }
17594
- return;
17862
+ return { persisted: "claimed-key" };
17595
17863
  }
17596
17864
  }
17597
17865
  try {
@@ -17600,6 +17868,7 @@ async function writeClaimedKey(newApiKey, projectRoot) {
17600
17868
  );
17601
17869
  } catch {
17602
17870
  }
17871
+ return { persisted: "none" };
17603
17872
  }
17604
17873
  async function performInit(config2, anonKey, sdkVersion, healthReport) {
17605
17874
  lastInitSucceeded = false;
@@ -17631,10 +17900,23 @@ async function performInit(config2, anonKey, sdkVersion, healthReport) {
17631
17900
  lastInitSucceeded = true;
17632
17901
  await saveCachedConfig(result);
17633
17902
  if (result.claimResult) {
17903
+ let persisted = "none";
17634
17904
  try {
17635
- await writeClaimedKey(result.claimResult.newApiKey);
17905
+ const w = await writeClaimedKey(result.claimResult.newApiKey);
17906
+ persisted = w.persisted;
17636
17907
  } catch {
17637
17908
  }
17909
+ if (persisted !== "none") {
17910
+ try {
17911
+ const resolved = await resolveEffectiveMcpCredential();
17912
+ await refreshGenericMcpConfigAtRuntime(
17913
+ process.cwd(),
17914
+ resolved.effective,
17915
+ resolved.anonKey
17916
+ );
17917
+ } catch {
17918
+ }
17919
+ }
17638
17920
  return { claimResult: result.claimResult };
17639
17921
  }
17640
17922
  return null;
@@ -21844,7 +22126,7 @@ function registerGlasstrace(options) {
21844
22126
  setCoreState(CoreState.REGISTERING);
21845
22127
  startRuntimeStateWriter({
21846
22128
  projectRoot: process.cwd(),
21847
- sdkVersion: "1.1.0"
22129
+ sdkVersion: "1.1.1"
21848
22130
  });
21849
22131
  const config2 = resolveConfig(options);
21850
22132
  if (config2.verbose) {
@@ -22010,8 +22292,8 @@ async function backgroundInit(config2, anonKeyForInit, generation) {
22010
22292
  if (config2.verbose) {
22011
22293
  console.info("[glasstrace] Background init firing.");
22012
22294
  }
22013
- const healthReport = collectHealthReport("1.1.0");
22014
- const initResult = await performInit(config2, anonKeyForInit, "1.1.0", healthReport);
22295
+ const healthReport = collectHealthReport("1.1.1");
22296
+ const initResult = await performInit(config2, anonKeyForInit, "1.1.1", healthReport);
22015
22297
  if (generation !== registrationGeneration) return;
22016
22298
  const currentState = getCoreState();
22017
22299
  if (currentState === CoreState.SHUTTING_DOWN || currentState === CoreState.SHUTDOWN) {
@@ -22034,7 +22316,7 @@ async function backgroundInit(config2, anonKeyForInit, generation) {
22034
22316
  }
22035
22317
  maybeInstallConsoleCapture();
22036
22318
  if (didLastInitSucceed()) {
22037
- startHeartbeat(config2, anonKeyForInit, "1.1.0", generation, (newApiKey, accountId) => {
22319
+ startHeartbeat(config2, anonKeyForInit, "1.1.1", generation, (newApiKey, accountId) => {
22038
22320
  setAuthState(AuthState.CLAIMING);
22039
22321
  emitLifecycleEvent("auth:claim_started", { accountId });
22040
22322
  setResolvedApiKey(newApiKey);