@glasstrace/sdk 1.1.2 → 1.1.3

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.
@@ -2,7 +2,7 @@ import {
2
2
  identityFingerprint,
3
3
  readMcpMarker,
4
4
  resolveEffectiveMcpCredential
5
- } from "../chunk-3LILTM3T.js";
5
+ } from "../chunk-TWTWRJ25.js";
6
6
  import "../chunk-X5MAXP5T.js";
7
7
  import "../chunk-NSBPE2FW.js";
8
8
 
package/dist/index.cjs CHANGED
@@ -17398,6 +17398,208 @@ function sleep(ms, scheduler, signal) {
17398
17398
  // src/mcp-runtime.ts
17399
17399
  var import_node_crypto = require("node:crypto");
17400
17400
  init_dist();
17401
+
17402
+ // src/atomic-write.ts
17403
+ function parentDir(filePath) {
17404
+ const lastSlash = filePath.lastIndexOf("/");
17405
+ const lastBackslash = filePath.lastIndexOf("\\");
17406
+ const lastSep = Math.max(lastSlash, lastBackslash);
17407
+ if (lastSep < 0) return ".";
17408
+ if (lastSep === 0) return filePath.slice(0, 1);
17409
+ return filePath.slice(0, lastSep);
17410
+ }
17411
+ var PARENT_FSYNC_SWALLOWED_CODES = /* @__PURE__ */ new Set([
17412
+ "EISDIR",
17413
+ "EINVAL",
17414
+ "EPERM",
17415
+ "ENOTSUP"
17416
+ ]);
17417
+ function errnoCodeOf(err) {
17418
+ if (err === null || typeof err !== "object") return void 0;
17419
+ const code = err.code;
17420
+ return typeof code === "string" ? code : void 0;
17421
+ }
17422
+ function defaultTmpPath(targetPath) {
17423
+ return `${targetPath}.tmp`;
17424
+ }
17425
+ var fsPromisesCache;
17426
+ var fsSyncCache;
17427
+ async function loadFsPromises() {
17428
+ if (fsPromisesCache !== void 0) {
17429
+ if (fsPromisesCache === null) {
17430
+ throw new Error(
17431
+ "node:fs/promises is unavailable in this environment; atomicWriteFile cannot be used here."
17432
+ );
17433
+ }
17434
+ return fsPromisesCache;
17435
+ }
17436
+ try {
17437
+ fsPromisesCache = await import("node:fs/promises");
17438
+ return fsPromisesCache;
17439
+ } catch {
17440
+ fsPromisesCache = null;
17441
+ throw new Error(
17442
+ "node:fs/promises is unavailable in this environment; atomicWriteFile cannot be used here."
17443
+ );
17444
+ }
17445
+ }
17446
+ function loadFsSync() {
17447
+ if (fsSyncCache !== void 0) {
17448
+ if (fsSyncCache === null) {
17449
+ throw new Error(
17450
+ "node:fs is unavailable in this environment; atomicWriteFileSync cannot be used here."
17451
+ );
17452
+ }
17453
+ return fsSyncCache;
17454
+ }
17455
+ try {
17456
+ fsSyncCache = require("node:fs");
17457
+ return fsSyncCache;
17458
+ } catch {
17459
+ fsSyncCache = null;
17460
+ throw new Error(
17461
+ "node:fs is unavailable in this environment; atomicWriteFileSync cannot be used here."
17462
+ );
17463
+ }
17464
+ }
17465
+ async function atomicWriteFile(targetPath, payload, options = {}) {
17466
+ return atomicWriteFileWithTmp(targetPath, defaultTmpPath(targetPath), payload, options);
17467
+ }
17468
+ async function atomicWriteFileWithTmp(targetPath, tmpPath, payload, options = {}) {
17469
+ const mode = options.mode ?? 384;
17470
+ const encoding = options.encoding ?? "utf-8";
17471
+ const fsp = await loadFsPromises();
17472
+ let handle = null;
17473
+ try {
17474
+ if (typeof payload === "string") {
17475
+ await fsp.writeFile(tmpPath, payload, { encoding, mode });
17476
+ } else {
17477
+ await fsp.writeFile(tmpPath, payload, { mode });
17478
+ }
17479
+ await fsp.chmod(tmpPath, mode);
17480
+ handle = await fsp.open(tmpPath, "r");
17481
+ await handle.sync();
17482
+ await handle.close();
17483
+ handle = null;
17484
+ await fsp.rename(tmpPath, targetPath);
17485
+ } catch (err) {
17486
+ if (handle !== null) {
17487
+ try {
17488
+ await handle.close();
17489
+ } catch {
17490
+ }
17491
+ }
17492
+ await removeTmpResidueAsync(fsp, tmpPath);
17493
+ throw err;
17494
+ }
17495
+ await fsyncParentDirAsync(targetPath, fsp);
17496
+ }
17497
+ async function removeTmpResidueAsync(fsp, tmpPath) {
17498
+ try {
17499
+ await fsp.unlink(tmpPath);
17500
+ return;
17501
+ } catch (err) {
17502
+ const code = errnoCodeOf(err);
17503
+ if (code !== "EISDIR" && code !== "EPERM") {
17504
+ return;
17505
+ }
17506
+ }
17507
+ try {
17508
+ await fsp.rmdir(tmpPath);
17509
+ } catch {
17510
+ }
17511
+ }
17512
+ async function fsyncParentDirAsync(targetPath, fsp) {
17513
+ const parent = parentDir(targetPath);
17514
+ let handle = null;
17515
+ try {
17516
+ handle = await fsp.open(parent, "r");
17517
+ await handle.sync();
17518
+ } catch (err) {
17519
+ const code = errnoCodeOf(err);
17520
+ if (code !== void 0 && PARENT_FSYNC_SWALLOWED_CODES.has(code)) {
17521
+ return;
17522
+ }
17523
+ throw err;
17524
+ } finally {
17525
+ if (handle !== null) {
17526
+ try {
17527
+ await handle.close();
17528
+ } catch {
17529
+ }
17530
+ }
17531
+ }
17532
+ }
17533
+ function atomicWriteFileSync(targetPath, payload, options = {}) {
17534
+ atomicWriteFileSyncWithTmp(targetPath, defaultTmpPath(targetPath), payload, options);
17535
+ }
17536
+ function atomicWriteFileSyncWithTmp(targetPath, tmpPath, payload, options = {}) {
17537
+ const mode = options.mode ?? 384;
17538
+ const encoding = options.encoding ?? "utf-8";
17539
+ const fs3 = loadFsSync();
17540
+ let fd = null;
17541
+ try {
17542
+ if (typeof payload === "string") {
17543
+ fs3.writeFileSync(tmpPath, payload, { encoding, mode });
17544
+ } else {
17545
+ fs3.writeFileSync(tmpPath, payload, { mode });
17546
+ }
17547
+ fs3.chmodSync(tmpPath, mode);
17548
+ fd = fs3.openSync(tmpPath, "r");
17549
+ fs3.fsyncSync(fd);
17550
+ fs3.closeSync(fd);
17551
+ fd = null;
17552
+ fs3.renameSync(tmpPath, targetPath);
17553
+ } catch (err) {
17554
+ if (fd !== null) {
17555
+ try {
17556
+ fs3.closeSync(fd);
17557
+ } catch {
17558
+ }
17559
+ }
17560
+ removeTmpResidueSync(fs3, tmpPath);
17561
+ throw err;
17562
+ }
17563
+ fsyncParentDirSyncWithFs(targetPath, fs3);
17564
+ }
17565
+ function removeTmpResidueSync(fs3, tmpPath) {
17566
+ try {
17567
+ fs3.unlinkSync(tmpPath);
17568
+ return;
17569
+ } catch (err) {
17570
+ const code = errnoCodeOf(err);
17571
+ if (code !== "EISDIR" && code !== "EPERM") {
17572
+ return;
17573
+ }
17574
+ }
17575
+ try {
17576
+ fs3.rmdirSync(tmpPath);
17577
+ } catch {
17578
+ }
17579
+ }
17580
+ function fsyncParentDirSyncWithFs(targetPath, fs3) {
17581
+ const parent = parentDir(targetPath);
17582
+ let fd = null;
17583
+ try {
17584
+ fd = fs3.openSync(parent, "r");
17585
+ fs3.fsyncSync(fd);
17586
+ } catch (err) {
17587
+ const code = errnoCodeOf(err);
17588
+ if (code !== void 0 && PARENT_FSYNC_SWALLOWED_CODES.has(code)) {
17589
+ return;
17590
+ }
17591
+ throw err;
17592
+ } finally {
17593
+ if (fd !== null) {
17594
+ try {
17595
+ fs3.closeSync(fd);
17596
+ } catch {
17597
+ }
17598
+ }
17599
+ }
17600
+ }
17601
+
17602
+ // src/mcp-runtime.ts
17401
17603
  var MCP_ENDPOINT = "https://api.glasstrace.dev/mcp";
17402
17604
  var fsPathCache2;
17403
17605
  async function loadFsPath2() {
@@ -17611,7 +17813,6 @@ async function refreshGenericMcpConfigAtRuntime(projectRoot, effective, anonKeyO
17611
17813
  if (!modules) return { action: "absent" };
17612
17814
  const dirPath = modules.path.join(projectRoot, GLASSTRACE_DIR2);
17613
17815
  const configPath = modules.path.join(dirPath, MCP_CONFIG_FILE);
17614
- const tmpPath = configPath + ".tmp";
17615
17816
  let existing;
17616
17817
  try {
17617
17818
  existing = await modules.fs.readFile(configPath, "utf-8");
@@ -17628,18 +17829,12 @@ async function refreshGenericMcpConfigAtRuntime(projectRoot, effective, anonKeyO
17628
17829
  }
17629
17830
  const replacement = genericMcpConfigContent(MCP_ENDPOINT, effective.key);
17630
17831
  try {
17631
- await modules.fs.writeFile(tmpPath, replacement, { mode: 384 });
17632
- await modules.fs.chmod(tmpPath, 384);
17633
- await modules.fs.rename(tmpPath, configPath);
17832
+ await atomicWriteFile(configPath, replacement, { mode: 384 });
17634
17833
  await writeMcpMarker(projectRoot, {
17635
17834
  credentialSource: effective.source,
17636
17835
  credentialHash: identityFingerprint(effective.key)
17637
17836
  });
17638
17837
  } catch {
17639
- try {
17640
- await modules.fs.unlink(tmpPath);
17641
- } catch {
17642
- }
17643
17838
  return { action: "preserved" };
17644
17839
  }
17645
17840
  emitRefreshNudge(effective.source);
@@ -17712,7 +17907,6 @@ async function saveCachedConfig(response, projectRoot) {
17712
17907
  const root = projectRoot ?? process.cwd();
17713
17908
  const dirPath = modules.path.join(root, GLASSTRACE_DIR3);
17714
17909
  const configPath = modules.path.join(dirPath, CONFIG_FILE);
17715
- const tmpPath = `${configPath}.tmp`;
17716
17910
  try {
17717
17911
  await modules.fs.mkdir(dirPath, { recursive: true, mode: 448 });
17718
17912
  await modules.fs.chmod(dirPath, 448);
@@ -17720,20 +17914,10 @@ async function saveCachedConfig(response, projectRoot) {
17720
17914
  response,
17721
17915
  cachedAt: Date.now()
17722
17916
  };
17723
- await modules.fs.writeFile(tmpPath, JSON.stringify(cached2), {
17917
+ await atomicWriteFile(configPath, JSON.stringify(cached2), {
17724
17918
  encoding: "utf-8",
17725
17919
  mode: 384
17726
17920
  });
17727
- try {
17728
- await modules.fs.chmod(tmpPath, 384);
17729
- await modules.fs.rename(tmpPath, configPath);
17730
- } catch (renameErr) {
17731
- try {
17732
- await modules.fs.unlink(tmpPath);
17733
- } catch {
17734
- }
17735
- throw renameErr;
17736
- }
17737
17921
  await modules.fs.chmod(configPath, 384);
17738
17922
  } catch (err) {
17739
17923
  console.warn(
@@ -22211,12 +22395,10 @@ function writeStateNow() {
22211
22395
  };
22212
22396
  const dir = (0, import_node_path.join)(_projectRoot, ".glasstrace");
22213
22397
  const filePath = (0, import_node_path.join)(dir, "runtime-state.json");
22214
- const tmpPath = (0, import_node_path.join)(dir, "runtime-state.json.tmp");
22215
22398
  (0, import_node_fs.mkdirSync)(dir, { recursive: true, mode: 448 });
22216
- (0, import_node_fs.writeFileSync)(tmpPath, JSON.stringify(runtimeState, null, 2) + "\n", {
22399
+ atomicWriteFileSync(filePath, JSON.stringify(runtimeState, null, 2) + "\n", {
22217
22400
  mode: 384
22218
22401
  });
22219
- (0, import_node_fs.renameSync)(tmpPath, filePath);
22220
22402
  } catch (err) {
22221
22403
  sdkLog(
22222
22404
  "warn",
@@ -22255,7 +22437,7 @@ function registerGlasstrace(options) {
22255
22437
  setCoreState(CoreState.REGISTERING);
22256
22438
  startRuntimeStateWriter({
22257
22439
  projectRoot: process.cwd(),
22258
- sdkVersion: "1.1.2"
22440
+ sdkVersion: "1.1.3"
22259
22441
  });
22260
22442
  const config2 = resolveConfig(options);
22261
22443
  if (config2.verbose) {
@@ -22421,8 +22603,8 @@ async function backgroundInit(config2, anonKeyForInit, generation) {
22421
22603
  if (config2.verbose) {
22422
22604
  console.info("[glasstrace] Background init firing.");
22423
22605
  }
22424
- const healthReport = collectHealthReport("1.1.2");
22425
- const initResult = await performInit(config2, anonKeyForInit, "1.1.2", healthReport);
22606
+ const healthReport = collectHealthReport("1.1.3");
22607
+ const initResult = await performInit(config2, anonKeyForInit, "1.1.3", healthReport);
22426
22608
  if (generation !== registrationGeneration) return;
22427
22609
  const currentState = getCoreState();
22428
22610
  if (currentState === CoreState.SHUTTING_DOWN || currentState === CoreState.SHUTDOWN) {
@@ -22445,7 +22627,7 @@ async function backgroundInit(config2, anonKeyForInit, generation) {
22445
22627
  }
22446
22628
  maybeInstallConsoleCapture();
22447
22629
  if (didLastInitSucceed()) {
22448
- startHeartbeat(config2, anonKeyForInit, "1.1.2", generation, (newApiKey, accountId) => {
22630
+ startHeartbeat(config2, anonKeyForInit, "1.1.3", generation, (newApiKey, accountId) => {
22449
22631
  setAuthState(AuthState.CLAIMING);
22450
22632
  emitLifecycleEvent("auth:claim_started", { accountId });
22451
22633
  setResolvedApiKey(newApiKey);