@glasstrace/sdk 0.14.2 → 0.15.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.
- package/dist/chunk-A2AZL6MZ.js +309 -0
- package/dist/chunk-A2AZL6MZ.js.map +1 -0
- package/dist/{chunk-ARAOZCZT.js → chunk-ROFOJQWN.js} +118 -16
- package/dist/chunk-ROFOJQWN.js.map +1 -0
- package/dist/{chunk-WV3NIPWJ.js → chunk-ZNOD6FC7.js} +18 -276
- package/dist/chunk-ZNOD6FC7.js.map +1 -0
- package/dist/cli/init.cjs +458 -115
- package/dist/cli/init.cjs.map +1 -1
- package/dist/cli/init.d.cts +33 -1
- package/dist/cli/init.d.ts +33 -1
- package/dist/cli/init.js +144 -42
- package/dist/cli/init.js.map +1 -1
- package/dist/cli/mcp-add.cjs.map +1 -1
- package/dist/cli/mcp-add.js +4 -2
- package/dist/cli/mcp-add.js.map +1 -1
- package/dist/cli/uninit.cjs +181 -60
- package/dist/cli/uninit.cjs.map +1 -1
- package/dist/cli/uninit.d.cts +38 -8
- package/dist/cli/uninit.d.ts +38 -8
- package/dist/cli/uninit.js +6 -3
- package/dist/cli/validate.cjs +135 -0
- package/dist/cli/validate.cjs.map +1 -0
- package/dist/cli/validate.d.cts +60 -0
- package/dist/cli/validate.d.ts +60 -0
- package/dist/cli/validate.js +103 -0
- package/dist/cli/validate.js.map +1 -0
- package/dist/index.cjs +76 -39
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +9 -3
- package/dist/index.d.ts +9 -3
- package/dist/index.js +76 -39
- package/dist/index.js.map +1 -1
- package/package.json +6 -4
- package/dist/chunk-ARAOZCZT.js.map +0 -1
- package/dist/chunk-WV3NIPWJ.js.map +0 -1
package/dist/index.d.cts
CHANGED
|
@@ -278,9 +278,15 @@ declare function getOrCreateAnonKey(projectRoot?: string): Promise<AnonApiKey>;
|
|
|
278
278
|
*/
|
|
279
279
|
declare function loadCachedConfig(projectRoot?: string): SdkInitResponse | null;
|
|
280
280
|
/**
|
|
281
|
-
* Persists the init response to `.glasstrace/config
|
|
282
|
-
* Silently skipped when `node:fs` is
|
|
283
|
-
* On I/O failure, logs a warning
|
|
281
|
+
* Persists the init response to `.glasstrace/config` using atomic
|
|
282
|
+
* write-temp + rename semantics. Silently skipped when `node:fs` is
|
|
283
|
+
* unavailable (non-Node environments). On I/O failure, logs a warning.
|
|
284
|
+
*
|
|
285
|
+
* Atomicity: the payload is written to `.glasstrace/config.tmp` and then
|
|
286
|
+
* renamed into place. `rename` is atomic on POSIX filesystems, so readers
|
|
287
|
+
* either see the previous valid config or the new valid config — never a
|
|
288
|
+
* truncated or partially-written file (DISC-1247 Scenario 5). If the
|
|
289
|
+
* rename fails, the temp file is cleaned up on a best-effort basis.
|
|
284
290
|
*/
|
|
285
291
|
declare function saveCachedConfig(response: SdkInitResponse, projectRoot?: string): Promise<void>;
|
|
286
292
|
/**
|
package/dist/index.d.ts
CHANGED
|
@@ -278,9 +278,15 @@ declare function getOrCreateAnonKey(projectRoot?: string): Promise<AnonApiKey>;
|
|
|
278
278
|
*/
|
|
279
279
|
declare function loadCachedConfig(projectRoot?: string): SdkInitResponse | null;
|
|
280
280
|
/**
|
|
281
|
-
* Persists the init response to `.glasstrace/config
|
|
282
|
-
* Silently skipped when `node:fs` is
|
|
283
|
-
* On I/O failure, logs a warning
|
|
281
|
+
* Persists the init response to `.glasstrace/config` using atomic
|
|
282
|
+
* write-temp + rename semantics. Silently skipped when `node:fs` is
|
|
283
|
+
* unavailable (non-Node environments). On I/O failure, logs a warning.
|
|
284
|
+
*
|
|
285
|
+
* Atomicity: the payload is written to `.glasstrace/config.tmp` and then
|
|
286
|
+
* renamed into place. `rename` is atomic on POSIX filesystems, so readers
|
|
287
|
+
* either see the previous valid config or the new valid config — never a
|
|
288
|
+
* truncated or partially-written file (DISC-1247 Scenario 5). If the
|
|
289
|
+
* rename fails, the temp file is cleaned up on a best-effort basis.
|
|
284
290
|
*/
|
|
285
291
|
declare function saveCachedConfig(response: SdkInitResponse, projectRoot?: string): Promise<void>;
|
|
286
292
|
/**
|
package/dist/index.js
CHANGED
|
@@ -304,6 +304,7 @@ async function saveCachedConfig(response, projectRoot) {
|
|
|
304
304
|
const root = projectRoot ?? process.cwd();
|
|
305
305
|
const dirPath = modules.path.join(root, GLASSTRACE_DIR);
|
|
306
306
|
const configPath = modules.path.join(dirPath, CONFIG_FILE);
|
|
307
|
+
const tmpPath = `${configPath}.tmp`;
|
|
307
308
|
try {
|
|
308
309
|
await modules.fs.mkdir(dirPath, { recursive: true, mode: 448 });
|
|
309
310
|
await modules.fs.chmod(dirPath, 448);
|
|
@@ -311,7 +312,20 @@ async function saveCachedConfig(response, projectRoot) {
|
|
|
311
312
|
response,
|
|
312
313
|
cachedAt: Date.now()
|
|
313
314
|
};
|
|
314
|
-
await modules.fs.writeFile(
|
|
315
|
+
await modules.fs.writeFile(tmpPath, JSON.stringify(cached), {
|
|
316
|
+
encoding: "utf-8",
|
|
317
|
+
mode: 384
|
|
318
|
+
});
|
|
319
|
+
try {
|
|
320
|
+
await modules.fs.chmod(tmpPath, 384);
|
|
321
|
+
await modules.fs.rename(tmpPath, configPath);
|
|
322
|
+
} catch (renameErr) {
|
|
323
|
+
try {
|
|
324
|
+
await modules.fs.unlink(tmpPath);
|
|
325
|
+
} catch {
|
|
326
|
+
}
|
|
327
|
+
throw renameErr;
|
|
328
|
+
}
|
|
315
329
|
await modules.fs.chmod(configPath, 384);
|
|
316
330
|
} catch (err) {
|
|
317
331
|
console.warn(
|
|
@@ -4430,7 +4444,6 @@ async function configureOtel(config, sessionManager) {
|
|
|
4430
4444
|
await provider.shutdown();
|
|
4431
4445
|
}
|
|
4432
4446
|
});
|
|
4433
|
-
registerSignalHandlers();
|
|
4434
4447
|
registerBeforeExitTrigger();
|
|
4435
4448
|
const prismaModule = await tryImport("@prisma/instrumentation");
|
|
4436
4449
|
if (prismaModule) {
|
|
@@ -4485,12 +4498,15 @@ var HEARTBEAT_INTERVAL_MS = 5 * 60 * 1e3;
|
|
|
4485
4498
|
var BACKOFF_BASE_MS = HEARTBEAT_INTERVAL_MS;
|
|
4486
4499
|
var BACKOFF_MAX_MS = 30 * 60 * 1e3;
|
|
4487
4500
|
var BACKOFF_JITTER = 0.2;
|
|
4501
|
+
var HEARTBEAT_SHUTDOWN_PRIORITY = 10;
|
|
4502
|
+
var SHUTDOWN_MARKER_RELPATH = ".glasstrace/shutdown-requested";
|
|
4488
4503
|
var heartbeatTimer = null;
|
|
4489
4504
|
var heartbeatGeneration = 0;
|
|
4490
4505
|
var backoffAttempts = 0;
|
|
4491
4506
|
var backoffUntil = 0;
|
|
4492
4507
|
var tickInProgress = false;
|
|
4493
|
-
var
|
|
4508
|
+
var shutdownHookRegistered = false;
|
|
4509
|
+
var shutdownFired = false;
|
|
4494
4510
|
function startHeartbeat(config, anonKey, sdkVersion, generation, onClaimTransition) {
|
|
4495
4511
|
if (heartbeatTimer !== null) return;
|
|
4496
4512
|
heartbeatGeneration = generation;
|
|
@@ -4498,7 +4514,7 @@ function startHeartbeat(config, anonKey, sdkVersion, generation, onClaimTransiti
|
|
|
4498
4514
|
void heartbeatTick(config, anonKey, sdkVersion, generation, onClaimTransition);
|
|
4499
4515
|
}, HEARTBEAT_INTERVAL_MS);
|
|
4500
4516
|
heartbeatTimer.unref();
|
|
4501
|
-
|
|
4517
|
+
registerHeartbeatShutdownHook(config, anonKey, sdkVersion);
|
|
4502
4518
|
if (config.verbose) {
|
|
4503
4519
|
sdkLog("info", "[glasstrace] Heartbeat started (5-minute interval).");
|
|
4504
4520
|
}
|
|
@@ -4508,7 +4524,26 @@ function stopHeartbeat() {
|
|
|
4508
4524
|
clearInterval(heartbeatTimer);
|
|
4509
4525
|
heartbeatTimer = null;
|
|
4510
4526
|
}
|
|
4511
|
-
|
|
4527
|
+
}
|
|
4528
|
+
function checkShutdownMarker(projectRoot) {
|
|
4529
|
+
let fsSync = null;
|
|
4530
|
+
let pathSync = null;
|
|
4531
|
+
try {
|
|
4532
|
+
fsSync = __require("fs");
|
|
4533
|
+
pathSync = __require("path");
|
|
4534
|
+
} catch {
|
|
4535
|
+
return { triggered: false };
|
|
4536
|
+
}
|
|
4537
|
+
const root = projectRoot ?? (typeof process !== "undefined" ? process.cwd() : ".");
|
|
4538
|
+
const markerPath = pathSync.join(root, SHUTDOWN_MARKER_RELPATH);
|
|
4539
|
+
if (!fsSync.existsSync(markerPath)) return { triggered: false };
|
|
4540
|
+
try {
|
|
4541
|
+
fsSync.unlinkSync(markerPath);
|
|
4542
|
+
} catch {
|
|
4543
|
+
}
|
|
4544
|
+
const shutdown = executeShutdown().catch(() => {
|
|
4545
|
+
});
|
|
4546
|
+
return { triggered: true, shutdown };
|
|
4512
4547
|
}
|
|
4513
4548
|
async function heartbeatTick(config, anonKey, sdkVersion, generation, onClaimTransition) {
|
|
4514
4549
|
if (tickInProgress) return;
|
|
@@ -4518,6 +4553,14 @@ async function heartbeatTick(config, anonKey, sdkVersion, generation, onClaimTra
|
|
|
4518
4553
|
stopHeartbeat();
|
|
4519
4554
|
return;
|
|
4520
4555
|
}
|
|
4556
|
+
const markerResult = checkShutdownMarker();
|
|
4557
|
+
if (markerResult.triggered) {
|
|
4558
|
+
stopHeartbeat();
|
|
4559
|
+
if (markerResult.shutdown) {
|
|
4560
|
+
await markerResult.shutdown;
|
|
4561
|
+
}
|
|
4562
|
+
return;
|
|
4563
|
+
}
|
|
4521
4564
|
if (Date.now() < backoffUntil) {
|
|
4522
4565
|
if (config.verbose) {
|
|
4523
4566
|
sdkLog("info", "[glasstrace] Heartbeat skipped (rate-limit backoff).");
|
|
@@ -4552,35 +4595,26 @@ async function heartbeatTick(config, anonKey, sdkVersion, generation, onClaimTra
|
|
|
4552
4595
|
tickInProgress = false;
|
|
4553
4596
|
}
|
|
4554
4597
|
}
|
|
4555
|
-
function
|
|
4556
|
-
if (
|
|
4557
|
-
|
|
4558
|
-
|
|
4559
|
-
|
|
4560
|
-
|
|
4561
|
-
|
|
4562
|
-
|
|
4563
|
-
|
|
4564
|
-
|
|
4565
|
-
|
|
4598
|
+
function registerHeartbeatShutdownHook(config, anonKey, sdkVersion) {
|
|
4599
|
+
if (shutdownHookRegistered) return;
|
|
4600
|
+
shutdownHookRegistered = true;
|
|
4601
|
+
registerShutdownHook({
|
|
4602
|
+
name: "heartbeat-final-report",
|
|
4603
|
+
priority: HEARTBEAT_SHUTDOWN_PRIORITY,
|
|
4604
|
+
fn: async () => {
|
|
4605
|
+
if (shutdownFired) return;
|
|
4606
|
+
shutdownFired = true;
|
|
4607
|
+
if (heartbeatTimer !== null) {
|
|
4608
|
+
clearInterval(heartbeatTimer);
|
|
4609
|
+
heartbeatTimer = null;
|
|
4610
|
+
}
|
|
4611
|
+
try {
|
|
4612
|
+
const healthReport = collectHealthReport(sdkVersion);
|
|
4613
|
+
await performInit(config, anonKey, sdkVersion, healthReport);
|
|
4614
|
+
} catch {
|
|
4615
|
+
}
|
|
4566
4616
|
}
|
|
4567
|
-
|
|
4568
|
-
void performInit(config, anonKey, sdkVersion, healthReport).catch(() => {
|
|
4569
|
-
}).finally(() => {
|
|
4570
|
-
removeShutdownHandlers();
|
|
4571
|
-
process.kill(process.pid, signal);
|
|
4572
|
-
});
|
|
4573
|
-
};
|
|
4574
|
-
_shutdownHandler = handler;
|
|
4575
|
-
process.once("SIGTERM", _shutdownHandler);
|
|
4576
|
-
process.once("SIGINT", _shutdownHandler);
|
|
4577
|
-
}
|
|
4578
|
-
function removeShutdownHandlers() {
|
|
4579
|
-
if (_shutdownHandler && typeof process !== "undefined") {
|
|
4580
|
-
process.removeListener("SIGTERM", _shutdownHandler);
|
|
4581
|
-
process.removeListener("SIGINT", _shutdownHandler);
|
|
4582
|
-
_shutdownHandler = null;
|
|
4583
|
-
}
|
|
4617
|
+
});
|
|
4584
4618
|
}
|
|
4585
4619
|
|
|
4586
4620
|
// src/runtime-state.ts
|
|
@@ -4681,7 +4715,7 @@ function registerGlasstrace(options) {
|
|
|
4681
4715
|
setCoreState(CoreState.REGISTERING);
|
|
4682
4716
|
startRuntimeStateWriter({
|
|
4683
4717
|
projectRoot: process.cwd(),
|
|
4684
|
-
sdkVersion: "0.
|
|
4718
|
+
sdkVersion: "0.15.1"
|
|
4685
4719
|
});
|
|
4686
4720
|
const config = resolveConfig(options);
|
|
4687
4721
|
if (config.verbose) {
|
|
@@ -4697,6 +4731,11 @@ function registerGlasstrace(options) {
|
|
|
4697
4731
|
if (config.verbose) {
|
|
4698
4732
|
console.info("[glasstrace] Not production-disabled.");
|
|
4699
4733
|
}
|
|
4734
|
+
const existingProbe = trace.getTracerProvider().getTracer("glasstrace-probe");
|
|
4735
|
+
const anotherProviderRegistered = existingProbe.constructor.name !== "ProxyTracer";
|
|
4736
|
+
if (!anotherProviderRegistered) {
|
|
4737
|
+
registerSignalHandlers();
|
|
4738
|
+
}
|
|
4700
4739
|
const anonymous = isAnonymousMode(config);
|
|
4701
4740
|
let effectiveKey = config.apiKey;
|
|
4702
4741
|
initAuthState(anonymous ? AuthState.ANONYMOUS : AuthState.AUTHENTICATED);
|
|
@@ -4727,8 +4766,6 @@ function registerGlasstrace(options) {
|
|
|
4727
4766
|
}
|
|
4728
4767
|
setCoreState(CoreState.KEY_PENDING);
|
|
4729
4768
|
const currentGeneration = registrationGeneration;
|
|
4730
|
-
const existingProbe = trace.getTracerProvider().getTracer("glasstrace-probe");
|
|
4731
|
-
const anotherProviderRegistered = existingProbe.constructor.name !== "ProxyTracer";
|
|
4732
4769
|
if (anotherProviderRegistered) {
|
|
4733
4770
|
if (config.verbose) {
|
|
4734
4771
|
console.info("[glasstrace] Another OTel provider detected \u2014 using existing context manager.");
|
|
@@ -4843,8 +4880,8 @@ async function backgroundInit(config, anonKeyForInit, generation) {
|
|
|
4843
4880
|
if (config.verbose) {
|
|
4844
4881
|
console.info("[glasstrace] Background init firing.");
|
|
4845
4882
|
}
|
|
4846
|
-
const healthReport = collectHealthReport("0.
|
|
4847
|
-
const initResult = await performInit(config, anonKeyForInit, "0.
|
|
4883
|
+
const healthReport = collectHealthReport("0.15.1");
|
|
4884
|
+
const initResult = await performInit(config, anonKeyForInit, "0.15.1", healthReport);
|
|
4848
4885
|
if (generation !== registrationGeneration) return;
|
|
4849
4886
|
const currentState = getCoreState();
|
|
4850
4887
|
if (currentState === CoreState.SHUTTING_DOWN || currentState === CoreState.SHUTDOWN) {
|
|
@@ -4867,7 +4904,7 @@ async function backgroundInit(config, anonKeyForInit, generation) {
|
|
|
4867
4904
|
}
|
|
4868
4905
|
maybeInstallConsoleCapture();
|
|
4869
4906
|
if (didLastInitSucceed()) {
|
|
4870
|
-
startHeartbeat(config, anonKeyForInit, "0.
|
|
4907
|
+
startHeartbeat(config, anonKeyForInit, "0.15.1", generation, (newApiKey, accountId) => {
|
|
4871
4908
|
setAuthState(AuthState.CLAIMING);
|
|
4872
4909
|
emitLifecycleEvent("auth:claim_started", { accountId });
|
|
4873
4910
|
setResolvedApiKey(newApiKey);
|