@glasstrace/sdk 1.3.9 → 1.5.0

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 (81) hide show
  1. package/README.md +124 -0
  2. package/dist/capture-error-BmQz7xF6.d.cts +455 -0
  3. package/dist/capture-error-CTgSYxek.d.ts +455 -0
  4. package/dist/{chunk-XS5W3SPL.js → chunk-4WI7B5FQ.js} +91 -5
  5. package/dist/chunk-4WI7B5FQ.js.map +1 -0
  6. package/dist/{chunk-JZ475QRH.js → chunk-D3QXU2VM.js} +22 -191
  7. package/dist/chunk-D3QXU2VM.js.map +1 -0
  8. package/dist/{chunk-GYTCZSAV.js → chunk-MFYOQOD7.js} +2 -2
  9. package/dist/{chunk-4WUHMLMM.js → chunk-MMKFFF2L.js} +2 -2
  10. package/dist/{chunk-JH7EGRC5.js → chunk-N3XIVM2U.js} +158 -12
  11. package/dist/chunk-N3XIVM2U.js.map +1 -0
  12. package/dist/{chunk-FKBCEOJ5.js → chunk-Q42BY5BA.js} +2 -2
  13. package/dist/{chunk-DBKG6SRI.js → chunk-QU26IKIJ.js} +2 -2
  14. package/dist/{chunk-ADUD4PEK.js → chunk-TANUWTFO.js} +3 -3
  15. package/dist/{chunk-LJMZXJ45.js → chunk-YLY7AGLC.js} +9 -6
  16. package/dist/chunk-YLY7AGLC.js.map +1 -0
  17. package/dist/chunk-ZBQQXVHD.js +208 -0
  18. package/dist/chunk-ZBQQXVHD.js.map +1 -0
  19. package/dist/cli/init.cjs +218 -35
  20. package/dist/cli/init.cjs.map +1 -1
  21. package/dist/cli/init.js +69 -12
  22. package/dist/cli/init.js.map +1 -1
  23. package/dist/cli/mcp-add.cjs +57 -26
  24. package/dist/cli/mcp-add.cjs.map +1 -1
  25. package/dist/cli/mcp-add.js +12 -9
  26. package/dist/cli/mcp-add.js.map +1 -1
  27. package/dist/cli/status.cjs +33 -3
  28. package/dist/cli/status.cjs.map +1 -1
  29. package/dist/cli/status.js +12 -3
  30. package/dist/cli/status.js.map +1 -1
  31. package/dist/cli/uninit.cjs +27 -3
  32. package/dist/cli/uninit.cjs.map +1 -1
  33. package/dist/cli/uninit.d.cts +10 -2
  34. package/dist/cli/uninit.d.ts +10 -2
  35. package/dist/cli/uninit.js +4 -3
  36. package/dist/cli/upgrade-instructions.cjs +440 -0
  37. package/dist/cli/upgrade-instructions.cjs.map +1 -0
  38. package/dist/cli/upgrade-instructions.d.cts +48 -0
  39. package/dist/cli/upgrade-instructions.d.ts +48 -0
  40. package/dist/cli/upgrade-instructions.js +80 -0
  41. package/dist/cli/upgrade-instructions.js.map +1 -0
  42. package/dist/cli/validate.cjs +12 -1
  43. package/dist/cli/validate.cjs.map +1 -1
  44. package/dist/cli/validate.js +2 -2
  45. package/dist/{edge-entry-BSKA1l_0.d.ts → edge-entry-AWO70gje.d.ts} +1 -1
  46. package/dist/{edge-entry-DyMWa6JK.d.cts → edge-entry-DaeG7D7S.d.cts} +1 -1
  47. package/dist/edge-entry.cjs +43 -2
  48. package/dist/edge-entry.cjs.map +1 -1
  49. package/dist/edge-entry.d.cts +2 -2
  50. package/dist/edge-entry.d.ts +2 -2
  51. package/dist/edge-entry.js +2 -2
  52. package/dist/index.cjs +594 -64
  53. package/dist/index.cjs.map +1 -1
  54. package/dist/{index.d-Bo_Rxund.d.cts → index.d-Dq33YwFT.d.cts} +91 -1
  55. package/dist/{index.d-Bo_Rxund.d.ts → index.d-Dq33YwFT.d.ts} +91 -1
  56. package/dist/index.d.cts +91 -431
  57. package/dist/index.d.ts +91 -431
  58. package/dist/index.js +291 -6
  59. package/dist/index.js.map +1 -1
  60. package/dist/node-entry.cjs +282 -71
  61. package/dist/node-entry.cjs.map +1 -1
  62. package/dist/node-entry.d.cts +3 -3
  63. package/dist/node-entry.d.ts +3 -3
  64. package/dist/node-entry.js +8 -7
  65. package/dist/node-subpath.cjs +12 -1
  66. package/dist/node-subpath.cjs.map +1 -1
  67. package/dist/node-subpath.d.cts +1 -1
  68. package/dist/node-subpath.d.ts +1 -1
  69. package/dist/node-subpath.js +3 -3
  70. package/dist/{source-map-uploader-FSTHCYDR.js → source-map-uploader-PB3M4PPP.js} +3 -3
  71. package/package.json +1 -1
  72. package/dist/chunk-JH7EGRC5.js.map +0 -1
  73. package/dist/chunk-JZ475QRH.js.map +0 -1
  74. package/dist/chunk-LJMZXJ45.js.map +0 -1
  75. package/dist/chunk-XS5W3SPL.js.map +0 -1
  76. /package/dist/{chunk-GYTCZSAV.js.map → chunk-MFYOQOD7.js.map} +0 -0
  77. /package/dist/{chunk-4WUHMLMM.js.map → chunk-MMKFFF2L.js.map} +0 -0
  78. /package/dist/{chunk-FKBCEOJ5.js.map → chunk-Q42BY5BA.js.map} +0 -0
  79. /package/dist/{chunk-DBKG6SRI.js.map → chunk-QU26IKIJ.js.map} +0 -0
  80. /package/dist/{chunk-ADUD4PEK.js.map → chunk-TANUWTFO.js.map} +0 -0
  81. /package/dist/{source-map-uploader-FSTHCYDR.js.map → source-map-uploader-PB3M4PPP.js.map} +0 -0
@@ -339,10 +339,10 @@ function mergeDefs(...defs) {
339
339
  function cloneDef(schema) {
340
340
  return mergeDefs(schema._zod.def);
341
341
  }
342
- function getElementAtPath(obj, path4) {
343
- if (!path4)
342
+ function getElementAtPath(obj, path5) {
343
+ if (!path5)
344
344
  return obj;
345
- return path4.reduce((acc, key) => acc?.[key], obj);
345
+ return path5.reduce((acc, key) => acc?.[key], obj);
346
346
  }
347
347
  function promiseAllObject(promisesObj) {
348
348
  const keys = Object.keys(promisesObj);
@@ -654,11 +654,11 @@ function aborted(x, startIndex = 0) {
654
654
  }
655
655
  return false;
656
656
  }
657
- function prefixIssues(path4, issues) {
657
+ function prefixIssues(path5, issues) {
658
658
  return issues.map((iss) => {
659
659
  var _a2;
660
660
  (_a2 = iss).path ?? (_a2.path = []);
661
- iss.path.unshift(path4);
661
+ iss.path.unshift(path5);
662
662
  return iss;
663
663
  });
664
664
  }
@@ -901,7 +901,7 @@ function formatError(error48, mapper = (issue2) => issue2.message) {
901
901
  }
902
902
  function treeifyError(error48, mapper = (issue2) => issue2.message) {
903
903
  const result = { errors: [] };
904
- const processError = (error49, path4 = []) => {
904
+ const processError = (error49, path5 = []) => {
905
905
  var _a2, _b;
906
906
  for (const issue2 of error49.issues) {
907
907
  if (issue2.code === "invalid_union" && issue2.errors.length) {
@@ -911,7 +911,7 @@ function treeifyError(error48, mapper = (issue2) => issue2.message) {
911
911
  } else if (issue2.code === "invalid_element") {
912
912
  processError({ issues: issue2.issues }, issue2.path);
913
913
  } else {
914
- const fullpath = [...path4, ...issue2.path];
914
+ const fullpath = [...path5, ...issue2.path];
915
915
  if (fullpath.length === 0) {
916
916
  result.errors.push(mapper(issue2));
917
917
  continue;
@@ -943,8 +943,8 @@ function treeifyError(error48, mapper = (issue2) => issue2.message) {
943
943
  }
944
944
  function toDotPath(_path) {
945
945
  const segs = [];
946
- const path4 = _path.map((seg) => typeof seg === "object" ? seg.key : seg);
947
- for (const seg of path4) {
946
+ const path5 = _path.map((seg) => typeof seg === "object" ? seg.key : seg);
947
+ for (const seg of path5) {
948
948
  if (typeof seg === "number")
949
949
  segs.push(`[${seg}]`);
950
950
  else if (typeof seg === "symbol")
@@ -13708,13 +13708,13 @@ function resolveRef(ref, ctx) {
13708
13708
  if (!ref.startsWith("#")) {
13709
13709
  throw new Error("External $ref is not supported, only local refs (#/...) are allowed");
13710
13710
  }
13711
- const path4 = ref.slice(1).split("/").filter(Boolean);
13712
- if (path4.length === 0) {
13711
+ const path5 = ref.slice(1).split("/").filter(Boolean);
13712
+ if (path5.length === 0) {
13713
13713
  return ctx.rootSchema;
13714
13714
  }
13715
13715
  const defsKey = ctx.version === "draft-2020-12" ? "$defs" : "definitions";
13716
- if (path4[0] === defsKey) {
13717
- const key = path4[1];
13716
+ if (path5[0] === defsKey) {
13717
+ const key = path5[1];
13718
13718
  if (!key || !ctx.defs[key]) {
13719
13719
  throw new Error(`Reference not found: ${ref}`);
13720
13720
  }
@@ -14594,7 +14594,18 @@ var init_dist = __esm({
14594
14594
  fullConsoleOutput: external_exports.boolean(),
14595
14595
  importGraph: external_exports.boolean(),
14596
14596
  consoleErrors: external_exports.boolean().optional().default(false),
14597
- errorResponseBodies: external_exports.boolean().optional().default(false)
14597
+ errorResponseBodies: external_exports.boolean().optional().default(false),
14598
+ /**
14599
+ * Account opt-in for side-effect evidence emission (SDK-049).
14600
+ *
14601
+ * When `false` (default), `recordSideEffect()` is a silent no-op:
14602
+ * no allowlist evaluation runs and no `glasstrace.side_effect.*`
14603
+ * attribute reaches the wire. When `true`, allowlisted side-effect
14604
+ * metadata is attached to the active OTel span subject to the
14605
+ * client-side allowlist enforcement layered with the product's
14606
+ * storage-time filter as defense-in-depth.
14607
+ */
14608
+ sideEffectEvidence: external_exports.boolean().optional().default(false)
14598
14609
  });
14599
14610
  SdkCachedConfigSchema = external_exports.object({
14600
14611
  response: external_exports.record(external_exports.string(), external_exports.unknown()),
@@ -14654,7 +14665,37 @@ var init_dist = __esm({
14654
14665
  TRIGGER_TYPE: "glasstrace.trigger.type",
14655
14666
  ELEMENT_FINGERPRINT: "glasstrace.element.fingerprint",
14656
14667
  ELEMENT_CONFIDENCE: "glasstrace.element.confidence",
14657
- TAB_ID: "glasstrace.tab.id"
14668
+ TAB_ID: "glasstrace.tab.id",
14669
+ // Side-effect evidence (SDK-049 / SCHEMA-036).
14670
+ // Top-level operation attributes attached to the active span when a
14671
+ // side-effect is recorded via `recordSideEffect()`. The wire-string
14672
+ // set aligns verbatim with the product-side filter in
14673
+ // `packages/ingestion/src/services/trace-writer.ts`.
14674
+ SIDE_EFFECT_KIND: "glasstrace.side_effect.kind",
14675
+ SIDE_EFFECT_OPERATION: "glasstrace.side_effect.operation",
14676
+ SIDE_EFFECT_STATUS: "glasstrace.side_effect.status",
14677
+ SIDE_EFFECT_PHASE: "glasstrace.side_effect.phase",
14678
+ // Allowlisted semantic field attributes — one per allowlisted key.
14679
+ // Wire keys are camelCase to match the SCHEMA-036 enum members
14680
+ // exactly; the SDK constant names are SCREAMING_SNAKE per the rest
14681
+ // of GLASSTRACE_ATTRIBUTE_NAMES.
14682
+ SIDE_EFFECT_FIELD_TEMPLATE_KEY: "glasstrace.side_effect.field.templateKey",
14683
+ SIDE_EFFECT_FIELD_PROVIDER_OPERATION: "glasstrace.side_effect.field.providerOperation",
14684
+ SIDE_EFFECT_FIELD_ROLE: "glasstrace.side_effect.field.role",
14685
+ SIDE_EFFECT_FIELD_LOCALE: "glasstrace.side_effect.field.locale",
14686
+ SIDE_EFFECT_FIELD_TIMEZONE: "glasstrace.side_effect.field.timezone",
14687
+ SIDE_EFFECT_FIELD_STATUS: "glasstrace.side_effect.field.status",
14688
+ SIDE_EFFECT_FIELD_PHASE: "glasstrace.side_effect.field.phase",
14689
+ // Omission reason attributes — one per allowlisted reason. The
14690
+ // attribute value carries an integer count; the rejected value is
14691
+ // never echoed.
14692
+ SIDE_EFFECT_OMITTED_PII: "glasstrace.side_effect.omitted.pii",
14693
+ SIDE_EFFECT_OMITTED_SECRET: "glasstrace.side_effect.omitted.secret",
14694
+ SIDE_EFFECT_OMITTED_RAW_PAYLOAD: "glasstrace.side_effect.omitted.raw_payload",
14695
+ SIDE_EFFECT_OMITTED_UNSUPPORTED_KEY: "glasstrace.side_effect.omitted.unsupported_key",
14696
+ SIDE_EFFECT_OMITTED_VALUE_TOO_LONG: "glasstrace.side_effect.omitted.value_too_long",
14697
+ SIDE_EFFECT_OMITTED_NOT_EMITTED: "glasstrace.side_effect.omitted.not_emitted",
14698
+ SIDE_EFFECT_OMITTED_CAPTURE_DISABLED: "glasstrace.side_effect.omitted.capture_disabled"
14658
14699
  };
14659
14700
  DEFAULT_CAPTURE_CONFIG = {
14660
14701
  requestBodies: false,
@@ -14663,7 +14704,8 @@ var init_dist = __esm({
14663
14704
  fullConsoleOutput: false,
14664
14705
  importGraph: false,
14665
14706
  consoleErrors: false,
14666
- errorResponseBodies: false
14707
+ errorResponseBodies: false,
14708
+ sideEffectEvidence: false
14667
14709
  };
14668
14710
  MAX_SOURCE_MAP_FILE_PATH_LENGTH = 512;
14669
14711
  MAX_SOURCE_MAP_FILE_SIZE = 50 * 1024 * 1024;
@@ -16443,10 +16485,10 @@ function sanitize(input) {
16443
16485
  }
16444
16486
  function markerFileExists() {
16445
16487
  try {
16446
- const fs4 = require("node:fs");
16447
- const path4 = require("node:path");
16448
- const markerPath = path4.join(process.cwd(), ".glasstrace", "mcp-connected");
16449
- return fs4.existsSync(markerPath);
16488
+ const fs5 = require("node:fs");
16489
+ const path5 = require("node:path");
16490
+ const markerPath = path5.join(process.cwd(), ".glasstrace", "mcp-connected");
16491
+ return fs5.existsSync(markerPath);
16450
16492
  } catch {
16451
16493
  return false;
16452
16494
  }
@@ -16595,7 +16637,7 @@ __export(source_map_uploader_exports, {
16595
16637
  uploadToBlob: () => uploadToBlob
16596
16638
  });
16597
16639
  async function discoverSourceMapFiles(buildDir) {
16598
- const resolvedDir = path2.resolve(buildDir);
16640
+ const resolvedDir = path3.resolve(buildDir);
16599
16641
  const results = [];
16600
16642
  try {
16601
16643
  await walkDirMetadata(resolvedDir, resolvedDir, results);
@@ -16616,18 +16658,18 @@ async function discoverSourceMapFiles(buildDir) {
16616
16658
  async function walkDirMetadata(baseDir, currentDir, results) {
16617
16659
  let entries;
16618
16660
  try {
16619
- entries = await fs2.readdir(currentDir, { withFileTypes: true });
16661
+ entries = await fs3.readdir(currentDir, { withFileTypes: true });
16620
16662
  } catch {
16621
16663
  return;
16622
16664
  }
16623
16665
  for (const entry of entries) {
16624
- const fullPath = path2.join(currentDir, entry.name);
16666
+ const fullPath = path3.join(currentDir, entry.name);
16625
16667
  if (entry.isDirectory()) {
16626
16668
  await walkDirMetadata(baseDir, fullPath, results);
16627
16669
  } else if (entry.isFile() && entry.name.endsWith(".map")) {
16628
16670
  try {
16629
- const stat2 = await fs2.stat(fullPath);
16630
- const relativePath = path2.relative(baseDir, fullPath).replace(/\\/g, "/");
16671
+ const stat2 = await fs3.stat(fullPath);
16672
+ const relativePath = path3.relative(baseDir, fullPath).replace(/\\/g, "/");
16631
16673
  const compiledPath = relativePath.replace(/\.map$/, "");
16632
16674
  results.push({
16633
16675
  filePath: compiledPath,
@@ -16640,7 +16682,7 @@ async function walkDirMetadata(baseDir, currentDir, results) {
16640
16682
  }
16641
16683
  }
16642
16684
  async function readSourceMapContent(absolutePath) {
16643
- return fs2.readFile(absolutePath, "utf-8");
16685
+ return fs3.readFile(absolutePath, "utf-8");
16644
16686
  }
16645
16687
  async function collectSourceMaps(buildDir) {
16646
16688
  const fileInfos = await discoverSourceMapFiles(buildDir);
@@ -16895,12 +16937,12 @@ async function uploadSourceMapsAuto(apiKey, endpoint, buildHash, maps, options)
16895
16937
  );
16896
16938
  return uploadSourceMaps(apiKey, endpoint, buildHash, maps);
16897
16939
  }
16898
- var fs2, path2, crypto2, import_node_child_process, LARGE_FILE_WARNING_BYTES, PRESIGNED_THRESHOLD_BYTES, _blobClientLoader;
16940
+ var fs3, path3, crypto2, import_node_child_process, LARGE_FILE_WARNING_BYTES, PRESIGNED_THRESHOLD_BYTES, _blobClientLoader;
16899
16941
  var init_source_map_uploader = __esm({
16900
16942
  "src/source-map-uploader.ts"() {
16901
16943
  "use strict";
16902
- fs2 = __toESM(require("node:fs/promises"), 1);
16903
- path2 = __toESM(require("node:path"), 1);
16944
+ fs3 = __toESM(require("node:fs/promises"), 1);
16945
+ path3 = __toESM(require("node:path"), 1);
16904
16946
  crypto2 = __toESM(require("node:crypto"), 1);
16905
16947
  import_node_child_process = require("node:child_process");
16906
16948
  init_console_capture();
@@ -17149,11 +17191,11 @@ var fsPathCache;
17149
17191
  async function loadFsPath() {
17150
17192
  if (fsPathCache !== void 0) return fsPathCache;
17151
17193
  try {
17152
- const [fs4, path4] = await Promise.all([
17194
+ const [fs5, path5] = await Promise.all([
17153
17195
  import("node:fs/promises"),
17154
17196
  import("node:path")
17155
17197
  ]);
17156
- fsPathCache = { fs: fs4, path: path4 };
17198
+ fsPathCache = { fs: fs5, path: path5 };
17157
17199
  return fsPathCache;
17158
17200
  } catch {
17159
17201
  fsPathCache = null;
@@ -17674,35 +17716,35 @@ function atomicWriteFileSync(targetPath, payload, options = {}) {
17674
17716
  function atomicWriteFileSyncWithTmp(targetPath, tmpPath, payload, options = {}) {
17675
17717
  const mode = options.mode ?? 384;
17676
17718
  const encoding = options.encoding ?? "utf-8";
17677
- const fs4 = loadFsSync();
17719
+ const fs5 = loadFsSync();
17678
17720
  let fd = null;
17679
17721
  try {
17680
17722
  if (typeof payload === "string") {
17681
- fs4.writeFileSync(tmpPath, payload, { encoding, mode });
17723
+ fs5.writeFileSync(tmpPath, payload, { encoding, mode });
17682
17724
  } else {
17683
- fs4.writeFileSync(tmpPath, payload, { mode });
17725
+ fs5.writeFileSync(tmpPath, payload, { mode });
17684
17726
  }
17685
- fs4.chmodSync(tmpPath, mode);
17686
- fd = fs4.openSync(tmpPath, "r");
17687
- fs4.fsyncSync(fd);
17688
- fs4.closeSync(fd);
17727
+ fs5.chmodSync(tmpPath, mode);
17728
+ fd = fs5.openSync(tmpPath, "r");
17729
+ fs5.fsyncSync(fd);
17730
+ fs5.closeSync(fd);
17689
17731
  fd = null;
17690
- fs4.renameSync(tmpPath, targetPath);
17732
+ fs5.renameSync(tmpPath, targetPath);
17691
17733
  } catch (err) {
17692
17734
  if (fd !== null) {
17693
17735
  try {
17694
- fs4.closeSync(fd);
17736
+ fs5.closeSync(fd);
17695
17737
  } catch {
17696
17738
  }
17697
17739
  }
17698
- removeTmpResidueSync(fs4, tmpPath);
17740
+ removeTmpResidueSync(fs5, tmpPath);
17699
17741
  throw err;
17700
17742
  }
17701
- fsyncParentDirSyncWithFs(targetPath, fs4);
17743
+ fsyncParentDirSyncWithFs(targetPath, fs5);
17702
17744
  }
17703
- function removeTmpResidueSync(fs4, tmpPath) {
17745
+ function removeTmpResidueSync(fs5, tmpPath) {
17704
17746
  try {
17705
- fs4.unlinkSync(tmpPath);
17747
+ fs5.unlinkSync(tmpPath);
17706
17748
  return;
17707
17749
  } catch (err) {
17708
17750
  const code = errnoCodeOf(err);
@@ -17711,16 +17753,16 @@ function removeTmpResidueSync(fs4, tmpPath) {
17711
17753
  }
17712
17754
  }
17713
17755
  try {
17714
- fs4.rmdirSync(tmpPath);
17756
+ fs5.rmdirSync(tmpPath);
17715
17757
  } catch {
17716
17758
  }
17717
17759
  }
17718
- function fsyncParentDirSyncWithFs(targetPath, fs4) {
17760
+ function fsyncParentDirSyncWithFs(targetPath, fs5) {
17719
17761
  const parent = parentDir(targetPath);
17720
17762
  let fd = null;
17721
17763
  try {
17722
- fd = fs4.openSync(parent, "r");
17723
- fs4.fsyncSync(fd);
17764
+ fd = fs5.openSync(parent, "r");
17765
+ fs5.fsyncSync(fd);
17724
17766
  } catch (err) {
17725
17767
  const code = errnoCodeOf(err);
17726
17768
  if (code !== void 0 && PARENT_FSYNC_SWALLOWED_CODES.has(code)) {
@@ -17730,7 +17772,7 @@ function fsyncParentDirSyncWithFs(targetPath, fs4) {
17730
17772
  } finally {
17731
17773
  if (fd !== null) {
17732
17774
  try {
17733
- fs4.closeSync(fd);
17775
+ fs5.closeSync(fd);
17734
17776
  } catch {
17735
17777
  }
17736
17778
  }
@@ -17751,11 +17793,11 @@ var fsPathCache2;
17751
17793
  async function loadFsPath2() {
17752
17794
  if (fsPathCache2 !== void 0) return fsPathCache2;
17753
17795
  try {
17754
- const [fs4, path4] = await Promise.all([
17796
+ const [fs5, path5] = await Promise.all([
17755
17797
  import("node:fs/promises"),
17756
17798
  import("node:path")
17757
17799
  ]);
17758
- fsPathCache2 = { fs: fs4, path: path4 };
17800
+ fsPathCache2 = { fs: fs5, path: path5 };
17759
17801
  return fsPathCache2;
17760
17802
  } catch {
17761
17803
  fsPathCache2 = null;
@@ -18041,11 +18083,11 @@ var fsPathAsyncCache;
18041
18083
  async function loadFsPathAsync() {
18042
18084
  if (fsPathAsyncCache !== void 0) return fsPathAsyncCache;
18043
18085
  try {
18044
- const [fs4, path4] = await Promise.all([
18086
+ const [fs5, path5] = await Promise.all([
18045
18087
  import("node:fs/promises"),
18046
18088
  import("node:path")
18047
18089
  ]);
18048
- fsPathAsyncCache = { fs: fs4, path: path4 };
18090
+ fsPathAsyncCache = { fs: fs5, path: path5 };
18049
18091
  return fsPathAsyncCache;
18050
18092
  } catch {
18051
18093
  fsPathAsyncCache = null;
@@ -18054,9 +18096,9 @@ async function loadFsPathAsync() {
18054
18096
  }
18055
18097
  function loadFsSyncOrNull() {
18056
18098
  try {
18057
- const fs4 = require("node:fs");
18058
- const path4 = require("node:path");
18059
- return { readFileSync: fs4.readFileSync, join: path4.join };
18099
+ const fs5 = require("node:fs");
18100
+ const path5 = require("node:path");
18101
+ return { readFileSync: fs5.readFileSync, join: path5.join };
18060
18102
  } catch {
18061
18103
  return null;
18062
18104
  }
@@ -20503,7 +20545,7 @@ function appendRootPathToUrlIfNeeded(url2) {
20503
20545
  return void 0;
20504
20546
  }
20505
20547
  }
20506
- function appendResourcePathToUrl(url2, path4) {
20548
+ function appendResourcePathToUrl(url2, path5) {
20507
20549
  try {
20508
20550
  new URL(url2);
20509
20551
  } catch {
@@ -20513,11 +20555,11 @@ function appendResourcePathToUrl(url2, path4) {
20513
20555
  if (!url2.endsWith("/")) {
20514
20556
  url2 = url2 + "/";
20515
20557
  }
20516
- url2 += path4;
20558
+ url2 += path5;
20517
20559
  try {
20518
20560
  new URL(url2);
20519
20561
  } catch {
20520
- diag2.warn(`Configuration: Provided URL appended with '${path4}' is not a valid URL, using 'undefined' instead of '${url2}'`);
20562
+ diag2.warn(`Configuration: Provided URL appended with '${path5}' is not a valid URL, using 'undefined' instead of '${url2}'`);
20521
20563
  return void 0;
20522
20564
  }
20523
20565
  return url2;
@@ -22723,6 +22765,171 @@ function writeStateNow() {
22723
22765
  }
22724
22766
  }
22725
22767
 
22768
+ // src/agent-detection/upgrade-notice.ts
22769
+ var fs2 = __toESM(require("node:fs"), 1);
22770
+ var path2 = __toESM(require("node:path"), 1);
22771
+
22772
+ // src/agent-detection/inject.ts
22773
+ var HTML_START_RE = /^<!--\s*glasstrace:mcp:start(?:\s+v=([^\s>]+))?\s*-->$/;
22774
+ var HTML_END = "<!-- glasstrace:mcp:end -->";
22775
+ var HASH_START_RE = /^#\s*glasstrace:mcp:start(?:\s+v=(\S+))?$/;
22776
+ var HASH_END = "# glasstrace:mcp:end";
22777
+ function parseStartMarkerLine(line) {
22778
+ const trimmed = line.trim();
22779
+ const html = HTML_START_RE.exec(trimmed);
22780
+ if (html !== null) {
22781
+ return { kind: "html", stamp: html[1] ?? null };
22782
+ }
22783
+ const hash2 = HASH_START_RE.exec(trimmed);
22784
+ if (hash2 !== null) {
22785
+ return { kind: "hash", stamp: hash2[1] ?? null };
22786
+ }
22787
+ return null;
22788
+ }
22789
+ function isEndMarker(line) {
22790
+ const trimmed = line.trim();
22791
+ return trimmed === HTML_END || trimmed === HASH_END;
22792
+ }
22793
+ function isEndMarkerLine(line) {
22794
+ return isEndMarker(line);
22795
+ }
22796
+
22797
+ // src/agent-detection/upgrade-notice.ts
22798
+ var warningEmitted = false;
22799
+ var AGENT_INSTRUCTION_FILES = [
22800
+ "CLAUDE.md",
22801
+ "codex.md",
22802
+ ".cursorrules"
22803
+ ];
22804
+ function parseSemver(input) {
22805
+ const plusIdx = input.indexOf("+");
22806
+ const core = plusIdx === -1 ? input : input.slice(0, plusIdx);
22807
+ const m = /^(\d+)\.(\d+)\.(\d+)(?:-([0-9A-Za-z.-]+))?$/.exec(core);
22808
+ if (m === null) return null;
22809
+ return {
22810
+ major: Number(m[1]),
22811
+ minor: Number(m[2]),
22812
+ patch: Number(m[3]),
22813
+ prerelease: m[4] ?? null
22814
+ };
22815
+ }
22816
+ function comparePrerelease(a, b) {
22817
+ const ap = a.split(".");
22818
+ const bp = b.split(".");
22819
+ const len = Math.min(ap.length, bp.length);
22820
+ for (let i = 0; i < len; i++) {
22821
+ const x = ap[i];
22822
+ const y = bp[i];
22823
+ const xNumeric = /^\d+$/.test(x);
22824
+ const yNumeric = /^\d+$/.test(y);
22825
+ if (xNumeric && yNumeric) {
22826
+ const xv = Number(x);
22827
+ const yv = Number(y);
22828
+ if (xv !== yv) return xv < yv ? -1 : 1;
22829
+ } else if (xNumeric) {
22830
+ return -1;
22831
+ } else if (yNumeric) {
22832
+ return 1;
22833
+ } else if (x !== y) {
22834
+ return x < y ? -1 : 1;
22835
+ }
22836
+ }
22837
+ return ap.length - bp.length;
22838
+ }
22839
+ function compareSemver(a, b) {
22840
+ const pa = parseSemver(a);
22841
+ const pb = parseSemver(b);
22842
+ if (pa === null || pb === null) return null;
22843
+ if (pa.major !== pb.major) return pa.major - pb.major;
22844
+ if (pa.minor !== pb.minor) return pa.minor - pb.minor;
22845
+ if (pa.patch !== pb.patch) return pa.patch - pb.patch;
22846
+ if (pa.prerelease === null && pb.prerelease === null) return 0;
22847
+ if (pa.prerelease === null) return 1;
22848
+ if (pb.prerelease === null) return -1;
22849
+ return comparePrerelease(pa.prerelease, pb.prerelease);
22850
+ }
22851
+ function isOptedOut() {
22852
+ const raw = process.env.GLASSTRACE_DISABLE_UPGRADE_NOTICE;
22853
+ if (typeof raw !== "string") return false;
22854
+ const trimmed = raw.trim().toLowerCase();
22855
+ return trimmed === "1" || trimmed === "true" || trimmed === "yes";
22856
+ }
22857
+ function isQuietCiContext() {
22858
+ const stderrIsTty = process.stderr.isTTY === true;
22859
+ if (stderrIsTty) return false;
22860
+ return process.env.CI === "true";
22861
+ }
22862
+ var MAX_AGENT_FILE_BYTES = 5 * 1024 * 1024;
22863
+ function inspectFile(filePath, runningSdkVersion) {
22864
+ let content;
22865
+ try {
22866
+ const stat2 = fs2.statSync(filePath);
22867
+ if (!stat2.isFile()) return "absent";
22868
+ if (stat2.size > MAX_AGENT_FILE_BYTES) return "absent";
22869
+ content = fs2.readFileSync(filePath, "utf-8");
22870
+ } catch {
22871
+ return "absent";
22872
+ }
22873
+ const lines = content.split("\n");
22874
+ let lastStart = null;
22875
+ let foundEnd = false;
22876
+ for (const line of lines) {
22877
+ const parsed = parseStartMarkerLine(line);
22878
+ if (parsed !== null) {
22879
+ lastStart = parsed;
22880
+ continue;
22881
+ }
22882
+ if (lastStart !== null && isEndMarkerLine(line)) {
22883
+ foundEnd = true;
22884
+ break;
22885
+ }
22886
+ }
22887
+ if (lastStart === null || !foundEnd) {
22888
+ return "no-section";
22889
+ }
22890
+ if (lastStart.stamp === null) {
22891
+ return "no-stamp";
22892
+ }
22893
+ const cmp = compareSemver(lastStart.stamp, runningSdkVersion);
22894
+ if (cmp === null) {
22895
+ return "unknown-stamp";
22896
+ }
22897
+ return cmp < 0 ? "stale" : "current";
22898
+ }
22899
+ function maybeWarnStaleAgentInstructions(options) {
22900
+ try {
22901
+ if (warningEmitted) return;
22902
+ if (typeof process === "undefined" || typeof process.versions?.node !== "string" || typeof process.env !== "object" || process.env === null) {
22903
+ return;
22904
+ }
22905
+ if (isOptedOut()) return;
22906
+ if (isQuietCiContext()) return;
22907
+ if (parseSemver(options.sdkVersion) === null) return;
22908
+ const staleFiles = [];
22909
+ for (const fileName of AGENT_INSTRUCTION_FILES) {
22910
+ const fullPath = path2.join(options.projectRoot, fileName);
22911
+ const state = inspectFile(fullPath, options.sdkVersion);
22912
+ if (state === "stale") {
22913
+ staleFiles.push(fileName);
22914
+ }
22915
+ }
22916
+ if (staleFiles.length === 0) return;
22917
+ const fileList = staleFiles.join(", ");
22918
+ const message = `[glasstrace] Glasstrace managed MCP section in ${fileList} was rendered by an older @glasstrace/sdk; run \`npx glasstrace upgrade-instructions\` to refresh (silence with GLASSTRACE_DISABLE_UPGRADE_NOTICE=1).
22919
+ `;
22920
+ warningEmitted = true;
22921
+ if (options.stderrWrite !== void 0) {
22922
+ options.stderrWrite(message);
22923
+ return;
22924
+ }
22925
+ try {
22926
+ process.stderr.write(message);
22927
+ } catch {
22928
+ }
22929
+ } catch {
22930
+ }
22931
+ }
22932
+
22726
22933
  // src/register.ts
22727
22934
  function maskKey(key) {
22728
22935
  if (key.length <= 12) return key.slice(0, 4) + "...";
@@ -22751,9 +22958,13 @@ function registerGlasstrace(options) {
22751
22958
  return;
22752
22959
  }
22753
22960
  setCoreState(CoreState.REGISTERING);
22961
+ maybeWarnStaleAgentInstructions({
22962
+ projectRoot: process.cwd(),
22963
+ sdkVersion: "1.5.0"
22964
+ });
22754
22965
  startRuntimeStateWriter({
22755
22966
  projectRoot: process.cwd(),
22756
- sdkVersion: "1.3.9"
22967
+ sdkVersion: "1.5.0"
22757
22968
  });
22758
22969
  const config2 = resolveConfig(options);
22759
22970
  if (config2.verbose) {
@@ -22920,8 +23131,8 @@ async function backgroundInit(config2, anonKeyForInit, generation) {
22920
23131
  if (config2.verbose) {
22921
23132
  console.info("[glasstrace] Background init firing.");
22922
23133
  }
22923
- const healthReport = collectHealthReport("1.3.9");
22924
- const initResult = await performInit(config2, anonKeyForInit, "1.3.9", healthReport);
23134
+ const healthReport = collectHealthReport("1.5.0");
23135
+ const initResult = await performInit(config2, anonKeyForInit, "1.5.0", healthReport);
22925
23136
  if (generation !== registrationGeneration) return;
22926
23137
  const currentState = getCoreState();
22927
23138
  if (currentState === CoreState.SHUTTING_DOWN || currentState === CoreState.SHUTDOWN) {
@@ -22944,7 +23155,7 @@ async function backgroundInit(config2, anonKeyForInit, generation) {
22944
23155
  }
22945
23156
  maybeInstallConsoleCapture();
22946
23157
  if (didLastInitSucceed()) {
22947
- startHeartbeat(config2, anonKeyForInit, "1.3.9", generation, (newApiKey, accountId) => {
23158
+ startHeartbeat(config2, anonKeyForInit, "1.5.0", generation, (newApiKey, accountId) => {
22948
23159
  setAuthState(AuthState.CLAIMING);
22949
23160
  emitLifecycleEvent("auth:claim_started", { accountId });
22950
23161
  setResolvedApiKey(newApiKey);
@@ -23178,9 +23389,9 @@ function captureError(error48) {
23178
23389
  init_source_map_uploader();
23179
23390
 
23180
23391
  // src/import-graph.ts
23181
- var fs3 = __toESM(require("node:fs/promises"), 1);
23392
+ var fs4 = __toESM(require("node:fs/promises"), 1);
23182
23393
  var fsSync2 = __toESM(require("node:fs"), 1);
23183
- var path3 = __toESM(require("node:path"), 1);
23394
+ var path4 = __toESM(require("node:path"), 1);
23184
23395
  var crypto3 = __toESM(require("node:crypto"), 1);
23185
23396
  init_dist();
23186
23397
  var MAX_TEST_FILES = 5e3;
@@ -23210,7 +23421,7 @@ function loadCustomTestPatterns(projectRoot) {
23210
23421
  "jest.config.mjs"
23211
23422
  ];
23212
23423
  for (const name of configNames) {
23213
- const configPath = path3.join(projectRoot, name);
23424
+ const configPath = path4.join(projectRoot, name);
23214
23425
  let content;
23215
23426
  try {
23216
23427
  content = fsSync2.readFileSync(configPath, "utf-8");
@@ -23267,7 +23478,7 @@ async function walkForTests(baseDir, currentDir, results, testPatterns) {
23267
23478
  }
23268
23479
  let entries;
23269
23480
  try {
23270
- entries = await fs3.readdir(currentDir, { withFileTypes: true });
23481
+ entries = await fs4.readdir(currentDir, { withFileTypes: true });
23271
23482
  } catch {
23272
23483
  return;
23273
23484
  }
@@ -23275,14 +23486,14 @@ async function walkForTests(baseDir, currentDir, results, testPatterns) {
23275
23486
  if (results.length >= MAX_TEST_FILES) {
23276
23487
  return;
23277
23488
  }
23278
- const fullPath = path3.join(currentDir, entry.name);
23489
+ const fullPath = path4.join(currentDir, entry.name);
23279
23490
  if (entry.isDirectory()) {
23280
23491
  if (EXCLUDED_DIRS.has(entry.name)) {
23281
23492
  continue;
23282
23493
  }
23283
23494
  await walkForTests(baseDir, fullPath, results, testPatterns);
23284
23495
  } else if (entry.isFile()) {
23285
- const relativePath = path3.relative(baseDir, fullPath).replace(/\\/g, "/");
23496
+ const relativePath = path4.relative(baseDir, fullPath).replace(/\\/g, "/");
23286
23497
  const isTestFile = testPatterns.some((p) => p.test(entry.name) || p.test(relativePath)) || relativePath.includes("__tests__");
23287
23498
  if (isTestFile && (entry.name.endsWith(".ts") || entry.name.endsWith(".tsx"))) {
23288
23499
  results.push(relativePath);
@@ -23330,9 +23541,9 @@ async function buildImportGraph(projectRoot) {
23330
23541
  const testFiles = await discoverTestFiles(projectRoot);
23331
23542
  const graph = {};
23332
23543
  for (const testFile of testFiles) {
23333
- const fullPath = path3.join(projectRoot, testFile);
23544
+ const fullPath = path4.join(projectRoot, testFile);
23334
23545
  try {
23335
- const content = await fs3.readFile(fullPath, "utf-8");
23546
+ const content = await fs4.readFile(fullPath, "utf-8");
23336
23547
  const imports = extractImports(content);
23337
23548
  graph[testFile] = imports;
23338
23549
  } catch {