@glasstrace/sdk 1.4.0 → 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 (43) hide show
  1. package/README.md +56 -0
  2. package/dist/{chunk-JZ475QRH.js → chunk-D3QXU2VM.js} +22 -191
  3. package/dist/chunk-D3QXU2VM.js.map +1 -0
  4. package/dist/{chunk-VQDYXXVS.js → chunk-N3XIVM2U.js} +154 -8
  5. package/dist/chunk-N3XIVM2U.js.map +1 -0
  6. package/dist/{chunk-VJQIFY33.js → chunk-YLY7AGLC.js} +7 -4
  7. package/dist/chunk-YLY7AGLC.js.map +1 -0
  8. package/dist/chunk-ZBQQXVHD.js +208 -0
  9. package/dist/chunk-ZBQQXVHD.js.map +1 -0
  10. package/dist/cli/init.cjs +206 -34
  11. package/dist/cli/init.cjs.map +1 -1
  12. package/dist/cli/init.js +65 -8
  13. package/dist/cli/init.js.map +1 -1
  14. package/dist/cli/mcp-add.cjs +45 -25
  15. package/dist/cli/mcp-add.cjs.map +1 -1
  16. package/dist/cli/mcp-add.js +10 -7
  17. package/dist/cli/mcp-add.js.map +1 -1
  18. package/dist/cli/status.cjs +33 -3
  19. package/dist/cli/status.cjs.map +1 -1
  20. package/dist/cli/status.js +12 -3
  21. package/dist/cli/status.js.map +1 -1
  22. package/dist/cli/uninit.cjs +27 -3
  23. package/dist/cli/uninit.cjs.map +1 -1
  24. package/dist/cli/uninit.d.cts +10 -2
  25. package/dist/cli/uninit.d.ts +10 -2
  26. package/dist/cli/uninit.js +2 -1
  27. package/dist/cli/upgrade-instructions.cjs +440 -0
  28. package/dist/cli/upgrade-instructions.cjs.map +1 -0
  29. package/dist/cli/upgrade-instructions.d.cts +48 -0
  30. package/dist/cli/upgrade-instructions.d.ts +48 -0
  31. package/dist/cli/upgrade-instructions.js +80 -0
  32. package/dist/cli/upgrade-instructions.js.map +1 -0
  33. package/dist/index.cjs +229 -60
  34. package/dist/index.cjs.map +1 -1
  35. package/dist/index.js +2 -1
  36. package/dist/index.js.map +1 -1
  37. package/dist/node-entry.cjs +237 -68
  38. package/dist/node-entry.cjs.map +1 -1
  39. package/dist/node-entry.js +2 -1
  40. package/package.json +1 -1
  41. package/dist/chunk-JZ475QRH.js.map +0 -1
  42. package/dist/chunk-VJQIFY33.js.map +0 -1
  43. package/dist/chunk-VQDYXXVS.js.map +0 -1
package/dist/cli/init.cjs CHANGED
@@ -15403,28 +15403,38 @@ function generateMcpConfig(agent, endpoint, bearer) {
15403
15403
  }
15404
15404
  }
15405
15405
  }
15406
- function htmlMarkers() {
15406
+ function htmlMarkers(sdkVersion) {
15407
15407
  return {
15408
- start: "<!-- glasstrace:mcp:start -->",
15408
+ start: `<!-- glasstrace:mcp:start v=${sdkVersion} -->`,
15409
15409
  end: "<!-- glasstrace:mcp:end -->"
15410
15410
  };
15411
15411
  }
15412
- function hashMarkers() {
15412
+ function hashMarkers(sdkVersion) {
15413
15413
  return {
15414
- start: "# glasstrace:mcp:start",
15414
+ start: `# glasstrace:mcp:start v=${sdkVersion}`,
15415
15415
  end: "# glasstrace:mcp:end"
15416
15416
  };
15417
15417
  }
15418
- function generateInfoSection(agent, endpoint) {
15418
+ function generateInfoSection(agent, endpoint, sdkVersion) {
15419
15419
  if (!endpoint || endpoint.trim() === "") {
15420
15420
  throw new Error("endpoint must not be empty");
15421
15421
  }
15422
+ if (!sdkVersion || sdkVersion.trim() === "") {
15423
+ throw new Error("sdkVersion must not be empty");
15424
+ }
15425
+ if (!SDK_VERSION_STAMP_PATTERN.test(sdkVersion)) {
15426
+ throw new Error(
15427
+ "sdkVersion must match [A-Za-z0-9.+\\-]+ (semver-shaped, no whitespace, no angle brackets)"
15428
+ );
15429
+ }
15422
15430
  const content = [
15423
15431
  "",
15424
15432
  "## Glasstrace MCP Integration",
15425
15433
  "",
15426
15434
  `Glasstrace is configured as an MCP server at: ${endpoint}`,
15427
15435
  "",
15436
+ "Glasstrace MCP is available when runtime evidence would materially reduce uncertainty. Use it when there is a failing request, stack trace, unclear runtime behavior, race/data-flow symptom, side effect, or performance issue that source inspection alone does not explain. For a current error, `get_latest_error` or `get_error_list` is usually the cheapest orientation call. For a known route/procedure with no exact error, use `find_trace_candidates` and follow returned exact `get_trace` or `get_root_cause` arguments only if the candidates look relevant. Do not call trace tools for trivial source-local fixes. Treat **no candidates** or **no_traces_found** as a scoped retrieval result, not proof the bug is absent.",
15437
+ "",
15428
15438
  "Available tools:",
15429
15439
  "- `get_latest_error` - Get the most recent error trace from the current session",
15430
15440
  "- `find_trace_candidates` - First-contact route/procedure/URL candidate selection when you have a route fragment, tRPC procedure, method, status, or rough recent activity window but not the exact trace ID. Returns candidate traces plus suggested `get_trace` / `get_root_cause` follow-up call arguments. Candidate discovery, not root-cause proof.",
@@ -15434,24 +15444,24 @@ function generateInfoSection(agent, endpoint) {
15434
15444
  "- `get_test_suggestions` - Get test suggestions based on recent errors",
15435
15445
  "- `get_session_timeline` - Get the timeline of all traces in the current session",
15436
15446
  "",
15437
- "To reconfigure, run: `npx glasstrace mcp add`",
15447
+ "To refresh this managed section after a `@glasstrace/sdk` upgrade, run: `npx glasstrace upgrade-instructions`. To reconfigure MCP credentials, run: `npx glasstrace mcp add`.",
15438
15448
  ""
15439
15449
  ].join("\n");
15440
15450
  switch (agent.name) {
15441
15451
  case "claude": {
15442
- const m = htmlMarkers();
15452
+ const m = htmlMarkers(sdkVersion);
15443
15453
  return `${m.start}
15444
15454
  ${content}${m.end}
15445
15455
  `;
15446
15456
  }
15447
15457
  case "codex": {
15448
- const m = htmlMarkers();
15458
+ const m = htmlMarkers(sdkVersion);
15449
15459
  return `${m.start}
15450
15460
  ${content}${m.end}
15451
15461
  `;
15452
15462
  }
15453
15463
  case "cursor": {
15454
- const m = hashMarkers();
15464
+ const m = hashMarkers(sdkVersion);
15455
15465
  return `${m.start}
15456
15466
  ${content}${m.end}
15457
15467
  `;
@@ -15466,13 +15476,34 @@ ${content}${m.end}
15466
15476
  }
15467
15477
  }
15468
15478
  }
15479
+ var SDK_VERSION_STAMP_PATTERN;
15469
15480
  var init_configs = __esm({
15470
15481
  "src/agent-detection/configs.ts"() {
15471
15482
  "use strict";
15483
+ SDK_VERSION_STAMP_PATTERN = /^[A-Za-z0-9.+-]+$/;
15472
15484
  }
15473
15485
  });
15474
15486
 
15475
15487
  // src/agent-detection/inject.ts
15488
+ function parseStartMarkerLine(line) {
15489
+ const trimmed = line.trim();
15490
+ const html = HTML_START_RE.exec(trimmed);
15491
+ if (html !== null) {
15492
+ return { kind: "html", stamp: html[1] ?? null };
15493
+ }
15494
+ const hash2 = HASH_START_RE.exec(trimmed);
15495
+ if (hash2 !== null) {
15496
+ return { kind: "hash", stamp: hash2[1] ?? null };
15497
+ }
15498
+ return null;
15499
+ }
15500
+ function isEndMarker(line) {
15501
+ const trimmed = line.trim();
15502
+ return trimmed === HTML_END || trimmed === HASH_END;
15503
+ }
15504
+ function isEndMarkerLine(line) {
15505
+ return isEndMarker(line);
15506
+ }
15476
15507
  function isPermissionError(err) {
15477
15508
  const code = err.code;
15478
15509
  return code === "EACCES" || code === "EPERM" || code === "EROFS";
@@ -15514,22 +15545,14 @@ async function writeMcpConfig(agent, content, projectRoot) {
15514
15545
  }
15515
15546
  function findMarkerBoundaries(lines) {
15516
15547
  let startIdx = -1;
15517
- let endIdx = -1;
15518
15548
  for (let i = 0; i < lines.length; i++) {
15519
- const trimmed = lines[i].trim();
15520
- if (trimmed === HTML_START || trimmed === HASH_START) {
15549
+ if (parseStartMarkerLine(lines[i]) !== null) {
15521
15550
  startIdx = i;
15522
- } else if (trimmed === HTML_END || trimmed === HASH_END) {
15523
- if (startIdx !== -1) {
15524
- endIdx = i;
15525
- break;
15526
- }
15551
+ } else if (startIdx !== -1 && isEndMarker(lines[i])) {
15552
+ return { startIdx, endIdx: i };
15527
15553
  }
15528
15554
  }
15529
- if (startIdx === -1 || endIdx === -1) {
15530
- return null;
15531
- }
15532
- return { startIdx, endIdx };
15555
+ return null;
15533
15556
  }
15534
15557
  async function injectInfoSection(agent, content, projectRoot) {
15535
15558
  if (agent.infoFilePath === null) {
@@ -15596,6 +15619,17 @@ async function injectInfoSection(agent, content, projectRoot) {
15596
15619
  throw err;
15597
15620
  }
15598
15621
  }
15622
+ async function hasManagedSection(filePath) {
15623
+ let content;
15624
+ try {
15625
+ content = await (0, import_promises2.readFile)(filePath, "utf-8");
15626
+ } catch (err) {
15627
+ const code = err.code;
15628
+ if (code === "ENOENT") return false;
15629
+ throw err;
15630
+ }
15631
+ return findMarkerBoundaries(content.split("\n")) !== null;
15632
+ }
15599
15633
  async function updateGitignore(paths, projectRoot) {
15600
15634
  const gitignorePath = (0, import_node_path2.join)(projectRoot, ".gitignore");
15601
15635
  const relativePaths = paths.filter((p) => !(0, import_node_path2.isAbsolute)(p));
@@ -15642,15 +15676,15 @@ async function updateGitignore(paths, projectRoot) {
15642
15676
  throw err;
15643
15677
  }
15644
15678
  }
15645
- var import_promises2, import_node_path2, HTML_START, HTML_END, HASH_START, HASH_END;
15679
+ var import_promises2, import_node_path2, HTML_START_RE, HTML_END, HASH_START_RE, HASH_END;
15646
15680
  var init_inject = __esm({
15647
15681
  "src/agent-detection/inject.ts"() {
15648
15682
  "use strict";
15649
15683
  import_promises2 = require("node:fs/promises");
15650
15684
  import_node_path2 = require("node:path");
15651
- HTML_START = "<!-- glasstrace:mcp:start -->";
15685
+ HTML_START_RE = /^<!--\s*glasstrace:mcp:start(?:\s+v=([^\s>]+))?\s*-->$/;
15652
15686
  HTML_END = "<!-- glasstrace:mcp:end -->";
15653
- HASH_START = "# glasstrace:mcp:start";
15687
+ HASH_START_RE = /^#\s*glasstrace:mcp:start(?:\s+v=(\S+))?$/;
15654
15688
  HASH_END = "# glasstrace:mcp:end";
15655
15689
  }
15656
15690
  });
@@ -16350,10 +16384,9 @@ function removeMarkerSection(content) {
16350
16384
  let startIdx = -1;
16351
16385
  let endIdx = -1;
16352
16386
  for (let i = 0; i < lines.length; i++) {
16353
- const trimmed = lines[i].trim();
16354
- if (trimmed === "<!-- glasstrace:mcp:start -->" || trimmed === "# glasstrace:mcp:start") {
16387
+ if (parseStartMarkerLine(lines[i]) !== null) {
16355
16388
  startIdx = i;
16356
- } else if ((trimmed === "<!-- glasstrace:mcp:end -->" || trimmed === "# glasstrace:mcp:end") && startIdx !== -1) {
16389
+ } else if (isEndMarkerLine(lines[i]) && startIdx !== -1) {
16357
16390
  endIdx = i;
16358
16391
  break;
16359
16392
  }
@@ -16805,6 +16838,7 @@ var init_uninit = __esm({
16805
16838
  init_mcp_runtime();
16806
16839
  init_atomic_write();
16807
16840
  init_discovery_file();
16841
+ init_inject();
16808
16842
  MCP_CONFIG_FILES = [".mcp.json", ".cursor/mcp.json", ".gemini/settings.json"];
16809
16843
  AGENT_INFO_FILES = [
16810
16844
  "CLAUDE.md",
@@ -16960,10 +16994,11 @@ async function mcpAdd(options) {
16960
16994
  const bearer = resolved.effective.key;
16961
16995
  for (const agent of targetAgents) {
16962
16996
  const name = formatAgentName(agent.name);
16997
+ const sdkVersion = true ? "1.5.0" : "0.0.0-dev";
16963
16998
  if (agent.name !== "generic") {
16964
16999
  const cliSuccess = await registerViaCli(agent, bearer);
16965
17000
  if (cliSuccess) {
16966
- const infoContent = generateInfoSection(agent, MCP_ENDPOINT);
17001
+ const infoContent = generateInfoSection(agent, MCP_ENDPOINT, sdkVersion);
16967
17002
  if (infoContent !== "") {
16968
17003
  await injectInfoSection(agent, infoContent, projectRoot);
16969
17004
  }
@@ -16981,7 +17016,7 @@ async function mcpAdd(options) {
16981
17016
  const configContent = generateMcpConfig(agent, MCP_ENDPOINT, bearer);
16982
17017
  await writeMcpConfig(agent, configContent, projectRoot);
16983
17018
  if (fs6.existsSync(agent.mcpConfigPath)) {
16984
- const infoContent = generateInfoSection(agent, MCP_ENDPOINT);
17019
+ const infoContent = generateInfoSection(agent, MCP_ENDPOINT, sdkVersion);
16985
17020
  if (infoContent !== "") {
16986
17021
  await injectInfoSection(agent, infoContent, projectRoot);
16987
17022
  }
@@ -17201,6 +17236,82 @@ var init_validate = __esm({
17201
17236
  }
17202
17237
  });
17203
17238
 
17239
+ // src/cli/upgrade-instructions.ts
17240
+ var upgrade_instructions_exports = {};
17241
+ __export(upgrade_instructions_exports, {
17242
+ runUpgradeInstructions: () => runUpgradeInstructions
17243
+ });
17244
+ function formatPathForOutput(filePath, projectRoot) {
17245
+ const rel = (0, import_node_path3.relative)(projectRoot, filePath);
17246
+ if (rel === "" || rel.startsWith("..") || (0, import_node_path3.isAbsolute)(rel)) {
17247
+ return filePath;
17248
+ }
17249
+ return rel;
17250
+ }
17251
+ async function runUpgradeInstructions(options) {
17252
+ const refreshed = [];
17253
+ const skipped = [];
17254
+ const warnings = [];
17255
+ const errors = [];
17256
+ let agents;
17257
+ try {
17258
+ agents = await detectAgents(options.projectRoot);
17259
+ } catch (err) {
17260
+ errors.push(
17261
+ `Failed to detect agents: ${err instanceof Error ? err.message : String(err)}`
17262
+ );
17263
+ return { exitCode: 1, refreshed, skipped, warnings, errors };
17264
+ }
17265
+ const sdkVersion = true ? "1.5.0" : "0.0.0-dev";
17266
+ for (const agent of agents) {
17267
+ if (agent.infoFilePath === null) {
17268
+ continue;
17269
+ }
17270
+ const displayPath = formatPathForOutput(
17271
+ agent.infoFilePath,
17272
+ options.projectRoot
17273
+ );
17274
+ let containsSection;
17275
+ try {
17276
+ containsSection = await hasManagedSection(agent.infoFilePath);
17277
+ } catch (err) {
17278
+ warnings.push(
17279
+ `Could not inspect ${displayPath}: ${err instanceof Error ? err.message : String(err)}`
17280
+ );
17281
+ continue;
17282
+ }
17283
+ if (!containsSection) {
17284
+ skipped.push(displayPath);
17285
+ continue;
17286
+ }
17287
+ const content = generateInfoSection(agent, MCP_ENDPOINT, sdkVersion);
17288
+ if (content === "") {
17289
+ continue;
17290
+ }
17291
+ try {
17292
+ await injectInfoSection(agent, content, options.projectRoot);
17293
+ refreshed.push(displayPath);
17294
+ } catch (err) {
17295
+ errors.push(
17296
+ `Failed to refresh ${displayPath}: ${err instanceof Error ? err.message : String(err)}`
17297
+ );
17298
+ }
17299
+ }
17300
+ const exitCode = errors.length === 0 ? 0 : 1;
17301
+ return { exitCode, refreshed, skipped, warnings, errors };
17302
+ }
17303
+ var import_node_path3;
17304
+ var init_upgrade_instructions = __esm({
17305
+ "src/cli/upgrade-instructions.ts"() {
17306
+ "use strict";
17307
+ import_node_path3 = require("node:path");
17308
+ init_mcp_runtime();
17309
+ init_detect();
17310
+ init_configs();
17311
+ init_inject();
17312
+ }
17313
+ });
17314
+
17204
17315
  // src/cli/status.ts
17205
17316
  var status_exports = {};
17206
17317
  __export(status_exports, {
@@ -17297,9 +17408,14 @@ function checkAgents(root) {
17297
17408
  for (const name of AGENT_INFO_FILES2) {
17298
17409
  try {
17299
17410
  const content = fs8.readFileSync(path8.join(root, name), "utf-8");
17300
- const hasHtmlMarkers = content.includes("<!-- glasstrace:mcp:start -->") && content.includes("<!-- glasstrace:mcp:end -->");
17301
- const hasHashMarkers = content.includes("# glasstrace:mcp:start") && content.includes("# glasstrace:mcp:end");
17302
- if (hasHtmlMarkers || hasHashMarkers) {
17411
+ let hasStart = false;
17412
+ let hasEnd = false;
17413
+ for (const line of content.split("\n")) {
17414
+ if (parseStartMarkerLine(line) !== null) hasStart = true;
17415
+ else if (isEndMarkerLine(line)) hasEnd = true;
17416
+ if (hasStart && hasEnd) break;
17417
+ }
17418
+ if (hasStart && hasEnd) {
17303
17419
  found.push(name);
17304
17420
  }
17305
17421
  } catch {
@@ -17376,6 +17492,7 @@ var init_status = __esm({
17376
17492
  fs8 = __toESM(require("node:fs"), 1);
17377
17493
  path8 = __toESM(require("node:path"), 1);
17378
17494
  init_constants();
17495
+ init_inject();
17379
17496
  MCP_JSON_FILES = [".mcp.json", ".cursor/mcp.json", ".gemini/settings.json", ".glasstrace/mcp.json"];
17380
17497
  MCP_TOML_FILES = [".codex/config.toml"];
17381
17498
  AGENT_INFO_FILES2 = [
@@ -18781,7 +18898,12 @@ Then add this as the first statement in your register() function:
18781
18898
  }
18782
18899
  anyConfigWritten = true;
18783
18900
  anyConfigRewrittenWithBearer = true;
18784
- const infoContent = generateInfoSection(agent, MCP_ENDPOINT);
18901
+ const sdkVersionForInject = true ? "1.5.0" : "0.0.0-dev";
18902
+ const infoContent = generateInfoSection(
18903
+ agent,
18904
+ MCP_ENDPOINT,
18905
+ sdkVersionForInject
18906
+ );
18785
18907
  if (infoContent !== "") {
18786
18908
  await injectInfoSection(agent, infoContent, projectRoot);
18787
18909
  }
@@ -18879,7 +19001,7 @@ async function verifyAnonKeyRegistration(projectRoot) {
18879
19001
  }
18880
19002
  const baseConfig = resolveConfig({ apiKey: devKey });
18881
19003
  const config2 = { ...baseConfig, apiKey: devKey };
18882
- const sdkVersion = true ? "1.4.0" : "0.0.0-dev";
19004
+ const sdkVersion = true ? "1.5.0" : "0.0.0-dev";
18883
19005
  const result = await verifyInitReachable(config2, anonKey, sdkVersion);
18884
19006
  if (result.ok) {
18885
19007
  return { outcome: "verified" };
@@ -19068,6 +19190,55 @@ Usage: glasstrace mcp add [--force] [--dry-run]
19068
19190
  }).catch((err) => {
19069
19191
  process.stderr.write(
19070
19192
  `Fatal error: ${err instanceof Error ? err.message : String(err)}
19193
+ `
19194
+ );
19195
+ process.exit(1);
19196
+ });
19197
+ } else if (subcommand === "upgrade-instructions") {
19198
+ Promise.all([
19199
+ Promise.resolve().then(() => (init_upgrade_instructions(), upgrade_instructions_exports)),
19200
+ Promise.resolve().then(() => (init_monorepo(), monorepo_exports))
19201
+ ]).then(([{ runUpgradeInstructions: runUpgradeInstructions2 }, { resolveProjectRoot: resolve2 }]) => {
19202
+ let projectRoot = process.cwd();
19203
+ try {
19204
+ projectRoot = resolve2(projectRoot).projectRoot;
19205
+ } catch {
19206
+ }
19207
+ return runUpgradeInstructions2({ projectRoot });
19208
+ }).then((result) => {
19209
+ for (const err of result.errors) {
19210
+ process.stderr.write(`Error: ${err}
19211
+ `);
19212
+ }
19213
+ for (const warn of result.warnings) {
19214
+ process.stderr.write(`Warning: ${warn}
19215
+ `);
19216
+ }
19217
+ if (result.refreshed.length > 0) {
19218
+ process.stderr.write("\nRefreshed agent instruction files:\n");
19219
+ for (const file2 of result.refreshed) {
19220
+ process.stderr.write(` - ${file2}
19221
+ `);
19222
+ }
19223
+ }
19224
+ if (result.skipped.length > 0) {
19225
+ process.stderr.write(
19226
+ "\nSkipped (no Glasstrace managed section present):\n"
19227
+ );
19228
+ for (const file2 of result.skipped) {
19229
+ process.stderr.write(` - ${file2}
19230
+ `);
19231
+ }
19232
+ }
19233
+ if (result.refreshed.length === 0 && result.skipped.length === 0 && result.errors.length === 0) {
19234
+ process.stderr.write(
19235
+ "\nNo agent instruction files detected with a Glasstrace managed section. Run `npx glasstrace init` or `npx glasstrace mcp add` to install one.\n"
19236
+ );
19237
+ }
19238
+ process.exit(result.exitCode);
19239
+ }).catch((err) => {
19240
+ process.stderr.write(
19241
+ `Fatal error: ${err instanceof Error ? err.message : String(err)}
19071
19242
  `
19072
19243
  );
19073
19244
  process.exit(1);
@@ -19121,6 +19292,7 @@ Usage:
19121
19292
  glasstrace uninit [--dry-run] [--force]
19122
19293
  glasstrace status [--json]
19123
19294
  glasstrace mcp add [--force] [--dry-run]
19295
+ glasstrace upgrade-instructions
19124
19296
  `
19125
19297
  );
19126
19298
  process.exit(1);