@glasstrace/sdk 0.15.1 → 0.16.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.
- package/README.md +84 -1
- package/dist/adapters/drizzle.js +2 -5
- package/dist/adapters/drizzle.js.map +1 -1
- package/dist/{chunk-PD2SKFQQ.js → chunk-55FBXXER.js} +4 -8
- package/dist/{chunk-PD2SKFQQ.js.map → chunk-55FBXXER.js.map} +1 -1
- package/dist/chunk-5C2TJFLB.js +851 -0
- package/dist/chunk-5C2TJFLB.js.map +1 -0
- package/dist/{chunk-YMEXDDTA.js → chunk-7JBKXSBU.js} +3 -99
- package/dist/chunk-7JBKXSBU.js.map +1 -0
- package/dist/{chunk-2LDBR3F3.js → chunk-BANTDXUT.js} +15 -74
- package/dist/chunk-BANTDXUT.js.map +1 -0
- package/dist/{chunk-ZNOD6FC7.js → chunk-CTJI2YKA.js} +8 -15
- package/dist/{chunk-ZNOD6FC7.js.map → chunk-CTJI2YKA.js.map} +1 -1
- package/dist/{chunk-WK7MPK2T.js → chunk-DQ25VOKK.js} +1 -89
- package/dist/chunk-DQ25VOKK.js.map +1 -0
- package/dist/{chunk-BL3YDC6V.js → chunk-DXRZKKSO.js} +1 -6
- package/dist/{chunk-BL3YDC6V.js.map → chunk-DXRZKKSO.js.map} +1 -1
- package/dist/{chunk-BGZ7J74D.js → chunk-NSBPE2FW.js} +2 -16
- package/dist/{chunk-A2AZL6MZ.js → chunk-O63DJKIJ.js} +169 -18
- package/dist/chunk-O63DJKIJ.js.map +1 -0
- package/dist/{chunk-ECEN724Y.js → chunk-TM5NKZTO.js} +4 -8
- package/dist/{chunk-ECEN724Y.js.map → chunk-TM5NKZTO.js.map} +1 -1
- package/dist/chunk-VUZCLMIX.js +57 -0
- package/dist/chunk-VUZCLMIX.js.map +1 -0
- package/dist/{chunk-OSXIUKD5.js → chunk-WZXVS2EO.js} +1 -6
- package/dist/{chunk-OSXIUKD5.js.map → chunk-WZXVS2EO.js.map} +1 -1
- package/dist/{chunk-ROFOJQWN.js → chunk-XNDHQN4S.js} +7 -11
- package/dist/{chunk-ROFOJQWN.js.map → chunk-XNDHQN4S.js.map} +1 -1
- package/dist/cli/init.cjs +673 -161
- package/dist/cli/init.cjs.map +1 -1
- package/dist/cli/init.d.cts +54 -1
- package/dist/cli/init.d.ts +54 -1
- package/dist/cli/init.js +146 -37
- package/dist/cli/init.js.map +1 -1
- package/dist/cli/mcp-add.cjs +16 -16
- package/dist/cli/mcp-add.cjs.map +1 -1
- package/dist/cli/mcp-add.js +10 -13
- package/dist/cli/mcp-add.js.map +1 -1
- package/dist/cli/status.cjs +2 -2
- package/dist/cli/status.js +4 -7
- package/dist/cli/status.js.map +1 -1
- package/dist/cli/uninit.cjs +56 -59
- package/dist/cli/uninit.cjs.map +1 -1
- package/dist/cli/uninit.js +4 -4
- package/dist/cli/validate.cjs +2 -2
- package/dist/cli/validate.js +3 -6
- package/dist/cli/validate.js.map +1 -1
- package/dist/{esm-MDK7CZID.js → esm-KBPHCVB4.js} +3 -3
- package/dist/{getMachineId-bsd-4NIRBWME.js → getMachineId-bsd-345PYXFX.js} +4 -7
- package/dist/{getMachineId-bsd-4NIRBWME.js.map → getMachineId-bsd-345PYXFX.js.map} +1 -1
- package/dist/{getMachineId-darwin-2XNOCCJQ.js → getMachineId-darwin-5L2D25AD.js} +4 -7
- package/dist/{getMachineId-darwin-2XNOCCJQ.js.map → getMachineId-darwin-5L2D25AD.js.map} +1 -1
- package/dist/{getMachineId-linux-V6YSQEY7.js → getMachineId-linux-KJR4P5HN.js} +3 -6
- package/dist/{getMachineId-linux-V6YSQEY7.js.map → getMachineId-linux-KJR4P5HN.js.map} +1 -1
- package/dist/{getMachineId-unsupported-4FKBJNVO.js → getMachineId-unsupported-NDNXDYDY.js} +3 -6
- package/dist/{getMachineId-unsupported-4FKBJNVO.js.map → getMachineId-unsupported-NDNXDYDY.js.map} +1 -1
- package/dist/{getMachineId-win-WLRZBKVG.js → getMachineId-win-T7PJNJXG.js} +4 -7
- package/dist/{getMachineId-win-WLRZBKVG.js.map → getMachineId-win-T7PJNJXG.js.map} +1 -1
- package/dist/index.cjs +449 -461
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +38 -3
- package/dist/index.d.ts +38 -3
- package/dist/index.js +195 -701
- package/dist/index.js.map +1 -1
- package/dist/{monorepo-YILKGQXQ.js → monorepo-N5Z63XP7.js} +4 -4
- package/dist/{source-map-uploader-3GWUQDTS.js → source-map-uploader-MUZPI2S5.js} +5 -4
- package/dist/source-map-uploader-MUZPI2S5.js.map +1 -0
- package/package.json +1 -1
- package/dist/chunk-2LDBR3F3.js.map +0 -1
- package/dist/chunk-A2AZL6MZ.js.map +0 -1
- package/dist/chunk-BGZ7J74D.js.map +0 -1
- package/dist/chunk-UPS5BGER.js +0 -182
- package/dist/chunk-UPS5BGER.js.map +0 -1
- package/dist/chunk-WK7MPK2T.js.map +0 -1
- package/dist/chunk-YMEXDDTA.js.map +0 -1
- /package/dist/{esm-MDK7CZID.js.map → chunk-NSBPE2FW.js.map} +0 -0
- /package/dist/{monorepo-YILKGQXQ.js.map → esm-KBPHCVB4.js.map} +0 -0
- /package/dist/{source-map-uploader-3GWUQDTS.js.map → monorepo-N5Z63XP7.js.map} +0 -0
package/dist/cli/init.d.cts
CHANGED
|
@@ -61,6 +61,15 @@ type CompletedStep = "instrumentation" | "next-config" | "env-local" | "gitignor
|
|
|
61
61
|
*/
|
|
62
62
|
interface RollbackState {
|
|
63
63
|
steps: CompletedStep[];
|
|
64
|
+
/**
|
|
65
|
+
* Absolute path of the instrumentation file that the scaffolder
|
|
66
|
+
* wrote to. May be either `{root}/instrumentation.ts` or
|
|
67
|
+
* `{root}/src/instrumentation.ts` depending on the project layout
|
|
68
|
+
* (DISC-493 Issue 1). When absent, rollback falls back to the
|
|
69
|
+
* root path for backward compatibility with callers that do not
|
|
70
|
+
* populate this field.
|
|
71
|
+
*/
|
|
72
|
+
instrumentationPath?: string;
|
|
64
73
|
/** Original instrumentation.ts content saved before injection.
|
|
65
74
|
* When present, rollback restores this instead of using removeRegisterGlasstrace. */
|
|
66
75
|
originalInstrumentationContent?: string;
|
|
@@ -78,5 +87,49 @@ declare function rollbackSteps(steps: CompletedStep[], projectRoot: string, stat
|
|
|
78
87
|
* bottom calls this function and translates the result to process.exit().
|
|
79
88
|
*/
|
|
80
89
|
declare function runInit(options: InitOptions): Promise<InitResult>;
|
|
90
|
+
/**
|
|
91
|
+
* Outcome of {@link verifyAnonKeyRegistration}:
|
|
92
|
+
*
|
|
93
|
+
* - `"verified"` — the server registered the anon key (HTTP 2xx with a
|
|
94
|
+
* schema-valid response body).
|
|
95
|
+
* - `"skipped"` — no anon key was on disk, so no verification request
|
|
96
|
+
* was sent. Typically means MCP auto-configuration failed earlier
|
|
97
|
+
* (warnings were already emitted) — distinct from a verification
|
|
98
|
+
* success.
|
|
99
|
+
* - `"failed"` — the verification request was sent and failed.
|
|
100
|
+
* `error` is a user-facing message distinguishing the failure class
|
|
101
|
+
* (`fetch failed: ...`, `server rejected the key ...`, or
|
|
102
|
+
* `server returned malformed response ...`) with no anon key bytes.
|
|
103
|
+
*/
|
|
104
|
+
type VerifyAnonKeyOutcome = {
|
|
105
|
+
outcome: "verified";
|
|
106
|
+
} | {
|
|
107
|
+
outcome: "skipped";
|
|
108
|
+
} | {
|
|
109
|
+
outcome: "failed";
|
|
110
|
+
error: string;
|
|
111
|
+
};
|
|
112
|
+
/**
|
|
113
|
+
* Verifies that the anonymous key written by init is registered
|
|
114
|
+
* server-side. Called at the end of the scaffold flow so that when it
|
|
115
|
+
* fails, the user sees an actionable error rather than a misleading
|
|
116
|
+
* "initialized successfully" followed by silent MCP authentication
|
|
117
|
+
* failures (DISC-494).
|
|
118
|
+
*
|
|
119
|
+
* Returns a discriminated outcome so the CLI can distinguish a genuine
|
|
120
|
+
* verification pass from the "no anon key on disk" skip case. On
|
|
121
|
+
* failure the error message distinguishes three classes:
|
|
122
|
+
* - "fetch failed" — transport error (DNS, TCP, TLS, timeout)
|
|
123
|
+
* - "server rejected the key" — HTTP 4xx/5xx
|
|
124
|
+
* - "server returned malformed response" — HTTP 2xx with unparseable
|
|
125
|
+
* body
|
|
126
|
+
*
|
|
127
|
+
* The anon key is NEVER included in the returned message. Callers
|
|
128
|
+
* (the CLI entry point) render it verbatim to stderr via the errors
|
|
129
|
+
* array and exit non-zero.
|
|
130
|
+
*
|
|
131
|
+
* @internal Exported for testability.
|
|
132
|
+
*/
|
|
133
|
+
declare function verifyAnonKeyRegistration(projectRoot: string): Promise<VerifyAnonKeyOutcome>;
|
|
81
134
|
|
|
82
|
-
export { type InitOptions, type InitResult, decideMcpConfigAction, meetsNodeVersion, rollbackSteps, runInit };
|
|
135
|
+
export { type InitOptions, type InitResult, type VerifyAnonKeyOutcome, decideMcpConfigAction, meetsNodeVersion, rollbackSteps, runInit, verifyAnonKeyRegistration };
|
package/dist/cli/init.d.ts
CHANGED
|
@@ -61,6 +61,15 @@ type CompletedStep = "instrumentation" | "next-config" | "env-local" | "gitignor
|
|
|
61
61
|
*/
|
|
62
62
|
interface RollbackState {
|
|
63
63
|
steps: CompletedStep[];
|
|
64
|
+
/**
|
|
65
|
+
* Absolute path of the instrumentation file that the scaffolder
|
|
66
|
+
* wrote to. May be either `{root}/instrumentation.ts` or
|
|
67
|
+
* `{root}/src/instrumentation.ts` depending on the project layout
|
|
68
|
+
* (DISC-493 Issue 1). When absent, rollback falls back to the
|
|
69
|
+
* root path for backward compatibility with callers that do not
|
|
70
|
+
* populate this field.
|
|
71
|
+
*/
|
|
72
|
+
instrumentationPath?: string;
|
|
64
73
|
/** Original instrumentation.ts content saved before injection.
|
|
65
74
|
* When present, rollback restores this instead of using removeRegisterGlasstrace. */
|
|
66
75
|
originalInstrumentationContent?: string;
|
|
@@ -78,5 +87,49 @@ declare function rollbackSteps(steps: CompletedStep[], projectRoot: string, stat
|
|
|
78
87
|
* bottom calls this function and translates the result to process.exit().
|
|
79
88
|
*/
|
|
80
89
|
declare function runInit(options: InitOptions): Promise<InitResult>;
|
|
90
|
+
/**
|
|
91
|
+
* Outcome of {@link verifyAnonKeyRegistration}:
|
|
92
|
+
*
|
|
93
|
+
* - `"verified"` — the server registered the anon key (HTTP 2xx with a
|
|
94
|
+
* schema-valid response body).
|
|
95
|
+
* - `"skipped"` — no anon key was on disk, so no verification request
|
|
96
|
+
* was sent. Typically means MCP auto-configuration failed earlier
|
|
97
|
+
* (warnings were already emitted) — distinct from a verification
|
|
98
|
+
* success.
|
|
99
|
+
* - `"failed"` — the verification request was sent and failed.
|
|
100
|
+
* `error` is a user-facing message distinguishing the failure class
|
|
101
|
+
* (`fetch failed: ...`, `server rejected the key ...`, or
|
|
102
|
+
* `server returned malformed response ...`) with no anon key bytes.
|
|
103
|
+
*/
|
|
104
|
+
type VerifyAnonKeyOutcome = {
|
|
105
|
+
outcome: "verified";
|
|
106
|
+
} | {
|
|
107
|
+
outcome: "skipped";
|
|
108
|
+
} | {
|
|
109
|
+
outcome: "failed";
|
|
110
|
+
error: string;
|
|
111
|
+
};
|
|
112
|
+
/**
|
|
113
|
+
* Verifies that the anonymous key written by init is registered
|
|
114
|
+
* server-side. Called at the end of the scaffold flow so that when it
|
|
115
|
+
* fails, the user sees an actionable error rather than a misleading
|
|
116
|
+
* "initialized successfully" followed by silent MCP authentication
|
|
117
|
+
* failures (DISC-494).
|
|
118
|
+
*
|
|
119
|
+
* Returns a discriminated outcome so the CLI can distinguish a genuine
|
|
120
|
+
* verification pass from the "no anon key on disk" skip case. On
|
|
121
|
+
* failure the error message distinguishes three classes:
|
|
122
|
+
* - "fetch failed" — transport error (DNS, TCP, TLS, timeout)
|
|
123
|
+
* - "server rejected the key" — HTTP 4xx/5xx
|
|
124
|
+
* - "server returned malformed response" — HTTP 2xx with unparseable
|
|
125
|
+
* body
|
|
126
|
+
*
|
|
127
|
+
* The anon key is NEVER included in the returned message. Callers
|
|
128
|
+
* (the CLI entry point) render it verbatim to stderr via the errors
|
|
129
|
+
* array and exit non-zero.
|
|
130
|
+
*
|
|
131
|
+
* @internal Exported for testability.
|
|
132
|
+
*/
|
|
133
|
+
declare function verifyAnonKeyRegistration(projectRoot: string): Promise<VerifyAnonKeyOutcome>;
|
|
81
134
|
|
|
82
|
-
export { type InitOptions, type InitResult, decideMcpConfigAction, meetsNodeVersion, rollbackSteps, runInit };
|
|
135
|
+
export { type InitOptions, type InitResult, type VerifyAnonKeyOutcome, decideMcpConfigAction, meetsNodeVersion, rollbackSteps, runInit, verifyAnonKeyRegistration };
|
package/dist/cli/init.js
CHANGED
|
@@ -1,17 +1,21 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
resolveProjectRoot
|
|
4
|
-
} from "../chunk-
|
|
4
|
+
} from "../chunk-55FBXXER.js";
|
|
5
5
|
import {
|
|
6
|
-
buildImportGraph
|
|
7
|
-
|
|
6
|
+
buildImportGraph,
|
|
7
|
+
verifyInitReachable
|
|
8
|
+
} from "../chunk-5C2TJFLB.js";
|
|
9
|
+
import {
|
|
10
|
+
resolveConfig
|
|
11
|
+
} from "../chunk-VUZCLMIX.js";
|
|
8
12
|
import {
|
|
9
13
|
isInitCreatedInstrumentation,
|
|
10
14
|
removeGlasstraceConfigImport,
|
|
11
15
|
removeRegisterGlasstrace,
|
|
12
16
|
unwrapCJSExport,
|
|
13
17
|
unwrapExport
|
|
14
|
-
} from "../chunk-
|
|
18
|
+
} from "../chunk-XNDHQN4S.js";
|
|
15
19
|
import {
|
|
16
20
|
detectAgents,
|
|
17
21
|
generateInfoSection,
|
|
@@ -19,37 +23,35 @@ import {
|
|
|
19
23
|
injectInfoSection,
|
|
20
24
|
updateGitignore,
|
|
21
25
|
writeMcpConfig
|
|
22
|
-
} from "../chunk-
|
|
26
|
+
} from "../chunk-CTJI2YKA.js";
|
|
23
27
|
import {
|
|
24
28
|
getOrCreateAnonKey,
|
|
25
29
|
readAnonKey
|
|
26
|
-
} from "../chunk-
|
|
27
|
-
import "../chunk-
|
|
30
|
+
} from "../chunk-TM5NKZTO.js";
|
|
31
|
+
import "../chunk-7JBKXSBU.js";
|
|
28
32
|
import {
|
|
29
33
|
addCoverageMapEnv,
|
|
30
34
|
isDevApiKey,
|
|
31
35
|
mcpConfigMatches,
|
|
32
36
|
readEnvLocalApiKey,
|
|
37
|
+
resolveInstrumentationTarget,
|
|
33
38
|
scaffoldEnvLocal,
|
|
34
39
|
scaffoldGitignore,
|
|
35
40
|
scaffoldInstrumentation,
|
|
36
41
|
scaffoldMcpMarker,
|
|
37
42
|
scaffoldNextConfig
|
|
38
|
-
} from "../chunk-
|
|
43
|
+
} from "../chunk-O63DJKIJ.js";
|
|
39
44
|
import {
|
|
40
45
|
MCP_ENDPOINT,
|
|
41
46
|
NEXT_CONFIG_NAMES,
|
|
42
47
|
formatAgentName
|
|
43
|
-
} from "../chunk-
|
|
44
|
-
import
|
|
45
|
-
init_esm_shims
|
|
46
|
-
} from "../chunk-BGZ7J74D.js";
|
|
48
|
+
} from "../chunk-DXRZKKSO.js";
|
|
49
|
+
import "../chunk-NSBPE2FW.js";
|
|
47
50
|
|
|
48
51
|
// src/cli/init.ts
|
|
49
|
-
|
|
50
|
-
import * as
|
|
51
|
-
import * as
|
|
52
|
-
import * as readline from "readline";
|
|
52
|
+
import * as fs from "node:fs";
|
|
53
|
+
import * as path from "node:path";
|
|
54
|
+
import * as readline from "node:readline";
|
|
53
55
|
function meetsNodeVersion(minMajor) {
|
|
54
56
|
const [major] = process.versions.node.split(".").map(Number);
|
|
55
57
|
return major >= minMajor;
|
|
@@ -108,7 +110,7 @@ async function rollbackSteps(steps, projectRoot, state) {
|
|
|
108
110
|
try {
|
|
109
111
|
switch (step) {
|
|
110
112
|
case "instrumentation": {
|
|
111
|
-
const instrPath = path.join(projectRoot, "instrumentation.ts");
|
|
113
|
+
const instrPath = state?.instrumentationPath ?? path.join(projectRoot, "instrumentation.ts");
|
|
112
114
|
if (fs.existsSync(instrPath)) {
|
|
113
115
|
const content = fs.readFileSync(instrPath, "utf-8");
|
|
114
116
|
if (isInitCreatedInstrumentation(content)) {
|
|
@@ -211,32 +213,76 @@ async function runInit(options) {
|
|
|
211
213
|
}
|
|
212
214
|
const rollbackState = { steps: [] };
|
|
213
215
|
try {
|
|
214
|
-
const
|
|
215
|
-
if (
|
|
216
|
-
rollbackState.
|
|
216
|
+
const preResolved = resolveInstrumentationTarget(projectRoot);
|
|
217
|
+
if (!preResolved.conflict && preResolved.target !== null) {
|
|
218
|
+
rollbackState.instrumentationPath = preResolved.target;
|
|
219
|
+
if (fs.existsSync(preResolved.target)) {
|
|
220
|
+
rollbackState.originalInstrumentationContent = fs.readFileSync(
|
|
221
|
+
preResolved.target,
|
|
222
|
+
"utf-8"
|
|
223
|
+
);
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
const instrResult = await scaffoldInstrumentation(projectRoot, {
|
|
227
|
+
// `--yes` implies non-interactive automation and must not hang on a
|
|
228
|
+
// merge confirmation prompt. `--force` skips the prompt explicitly
|
|
229
|
+
// (DISC-1247 Scenario 2c parity).
|
|
230
|
+
force: options.force === true || options.yes
|
|
231
|
+
});
|
|
232
|
+
if (instrResult.filePath !== void 0) {
|
|
233
|
+
rollbackState.instrumentationPath = instrResult.filePath;
|
|
217
234
|
}
|
|
218
|
-
const
|
|
235
|
+
const relativePath = instrResult.filePath !== void 0 ? path.relative(projectRoot, instrResult.filePath) : "instrumentation.ts";
|
|
219
236
|
switch (instrResult.action) {
|
|
220
237
|
case "created":
|
|
221
|
-
summary.push(
|
|
238
|
+
summary.push(`Created ${relativePath}`);
|
|
222
239
|
rollbackState.steps.push("instrumentation");
|
|
223
240
|
break;
|
|
224
241
|
case "injected":
|
|
225
|
-
summary.push(
|
|
242
|
+
summary.push(`Added registerGlasstrace() to existing ${relativePath}`);
|
|
243
|
+
rollbackState.steps.push("instrumentation");
|
|
244
|
+
break;
|
|
245
|
+
case "appended":
|
|
246
|
+
summary.push(
|
|
247
|
+
`Appended register() with registerGlasstrace() to ${relativePath}`
|
|
248
|
+
);
|
|
226
249
|
rollbackState.steps.push("instrumentation");
|
|
227
250
|
break;
|
|
228
251
|
case "already-registered":
|
|
229
|
-
summary.push(
|
|
252
|
+
summary.push(`Skipped ${relativePath} (registerGlasstrace already present)`);
|
|
253
|
+
break;
|
|
254
|
+
case "skipped":
|
|
255
|
+
warnings.push(
|
|
256
|
+
`Preserved ${relativePath} (merge declined; re-run with --force to apply the merge without prompting)`
|
|
257
|
+
);
|
|
230
258
|
break;
|
|
259
|
+
case "conflict": {
|
|
260
|
+
const primary = instrResult.filePath !== void 0 ? path.relative(projectRoot, instrResult.filePath) : "src/instrumentation.ts";
|
|
261
|
+
const competing = instrResult.conflictingPath !== void 0 ? path.relative(projectRoot, instrResult.conflictingPath) : "instrumentation.ts";
|
|
262
|
+
await rollbackSteps(rollbackState.steps, projectRoot, rollbackState);
|
|
263
|
+
errors.push(
|
|
264
|
+
`Both ${primary} and ${competing} exist. Next.js's loader behavior is undefined when both are present.
|
|
265
|
+
Merge your instrumentation into ${primary} and remove ${competing}, then re-run init.`
|
|
266
|
+
);
|
|
267
|
+
return { exitCode: 1, summary, warnings, errors };
|
|
268
|
+
}
|
|
231
269
|
case "unrecognized":
|
|
232
270
|
warnings.push(
|
|
233
|
-
|
|
271
|
+
`${relativePath} exists but has no recognizable register() function.
|
|
272
|
+
Add this import at the top of your file:
|
|
273
|
+
|
|
274
|
+
import { registerGlasstrace } from "@glasstrace/sdk";
|
|
275
|
+
|
|
276
|
+
Then add this as the first statement in your register() function:
|
|
277
|
+
|
|
278
|
+
registerGlasstrace();
|
|
279
|
+
`
|
|
234
280
|
);
|
|
235
281
|
break;
|
|
236
282
|
}
|
|
237
283
|
} catch (err) {
|
|
238
284
|
await rollbackSteps(rollbackState.steps, projectRoot, rollbackState);
|
|
239
|
-
errors.push(`Failed to write instrumentation
|
|
285
|
+
errors.push(`Failed to write instrumentation file: ${err instanceof Error ? err.message : String(err)}`);
|
|
240
286
|
return { exitCode: 1, summary, warnings, errors };
|
|
241
287
|
}
|
|
242
288
|
try {
|
|
@@ -429,8 +475,64 @@ async function runInit(options) {
|
|
|
429
475
|
warnings.push(`Import graph scan failed: ${err instanceof Error ? err.message : String(err)}. You can run it later.`);
|
|
430
476
|
}
|
|
431
477
|
}
|
|
478
|
+
const skipVerify = process.env["GLASSTRACE_SKIP_INIT_VERIFY"] === "1" || process.env["GLASSTRACE_SKIP_INIT_VERIFY"] === "true" || process.env["VITEST"] === "true";
|
|
479
|
+
if (!skipVerify && !isCI) {
|
|
480
|
+
const verifyResult = await verifyAnonKeyRegistration(projectRoot);
|
|
481
|
+
if (verifyResult.outcome === "failed") {
|
|
482
|
+
errors.push(verifyResult.error);
|
|
483
|
+
return { exitCode: 2, summary, warnings, errors };
|
|
484
|
+
}
|
|
485
|
+
if (verifyResult.outcome === "verified") {
|
|
486
|
+
summary.push("Verified anon key registration with Glasstrace API");
|
|
487
|
+
} else {
|
|
488
|
+
summary.push("Skipped anon key verification (no anon key on disk)");
|
|
489
|
+
}
|
|
490
|
+
}
|
|
432
491
|
return { exitCode: 0, summary, warnings, errors };
|
|
433
492
|
}
|
|
493
|
+
async function verifyAnonKeyRegistration(projectRoot) {
|
|
494
|
+
const anonKey = await readAnonKey(projectRoot);
|
|
495
|
+
if (anonKey === null) {
|
|
496
|
+
return { outcome: "skipped" };
|
|
497
|
+
}
|
|
498
|
+
let devKey;
|
|
499
|
+
try {
|
|
500
|
+
const envPath = path.join(projectRoot, ".env.local");
|
|
501
|
+
if (fs.existsSync(envPath)) {
|
|
502
|
+
const envContent = fs.readFileSync(envPath, "utf-8");
|
|
503
|
+
const effective = readEnvLocalApiKey(envContent);
|
|
504
|
+
if (effective !== null && isDevApiKey(effective)) {
|
|
505
|
+
devKey = effective;
|
|
506
|
+
}
|
|
507
|
+
}
|
|
508
|
+
} catch {
|
|
509
|
+
}
|
|
510
|
+
const baseConfig = resolveConfig({ apiKey: devKey });
|
|
511
|
+
const config = { ...baseConfig, apiKey: devKey };
|
|
512
|
+
const sdkVersion = true ? "0.16.0" : "0.0.0-dev";
|
|
513
|
+
const result = await verifyInitReachable(config, anonKey, sdkVersion);
|
|
514
|
+
if (result.ok) {
|
|
515
|
+
return { outcome: "verified" };
|
|
516
|
+
}
|
|
517
|
+
const hint = "Run 'npx glasstrace status' or 'npx glasstrace doctor' to diagnose.";
|
|
518
|
+
switch (result.reason) {
|
|
519
|
+
case "transport":
|
|
520
|
+
return {
|
|
521
|
+
outcome: "failed",
|
|
522
|
+
error: `Glasstrace init verification failed: fetch failed: ${result.detail}. ${hint}`
|
|
523
|
+
};
|
|
524
|
+
case "rejected":
|
|
525
|
+
return {
|
|
526
|
+
outcome: "failed",
|
|
527
|
+
error: `Glasstrace init verification failed: server rejected the key (HTTP ${result.status}). ${hint}`
|
|
528
|
+
};
|
|
529
|
+
case "malformed":
|
|
530
|
+
return {
|
|
531
|
+
outcome: "failed",
|
|
532
|
+
error: `Glasstrace init verification failed: server returned malformed response. ${hint}`
|
|
533
|
+
};
|
|
534
|
+
}
|
|
535
|
+
}
|
|
434
536
|
function parseArgs(argv) {
|
|
435
537
|
const args = argv.slice(2);
|
|
436
538
|
let yes = false;
|
|
@@ -538,19 +640,25 @@ Usage: glasstrace mcp add [--force] [--dry-run]
|
|
|
538
640
|
}
|
|
539
641
|
}
|
|
540
642
|
if (result.summary.length > 0) {
|
|
541
|
-
|
|
643
|
+
if (result.exitCode === 0) {
|
|
644
|
+
process.stderr.write("\nGlasstrace initialized successfully!\n\n");
|
|
645
|
+
} else {
|
|
646
|
+
process.stderr.write("\nGlasstrace init completed with errors.\n\n");
|
|
647
|
+
}
|
|
542
648
|
for (const line of result.summary) {
|
|
543
649
|
process.stderr.write(` - ${line}
|
|
544
650
|
`);
|
|
545
651
|
}
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
652
|
+
if (result.exitCode === 0) {
|
|
653
|
+
process.stderr.write("\nNext steps:\n");
|
|
654
|
+
process.stderr.write(" 1. Start your Next.js dev server\n");
|
|
655
|
+
process.stderr.write(
|
|
656
|
+
" 2. Glasstrace works immediately in anonymous mode\n"
|
|
657
|
+
);
|
|
658
|
+
process.stderr.write(
|
|
659
|
+
" 3. To link to your account, set GLASSTRACE_API_KEY in .env.local\n\n"
|
|
660
|
+
);
|
|
661
|
+
}
|
|
554
662
|
}
|
|
555
663
|
process.exit(result.exitCode);
|
|
556
664
|
}).catch((err) => {
|
|
@@ -597,7 +705,7 @@ Usage: glasstrace mcp add [--force] [--dry-run]
|
|
|
597
705
|
} else if (subcommand === "status") {
|
|
598
706
|
const remainingArgs = process.argv.slice(3);
|
|
599
707
|
const json = remainingArgs.includes("--json");
|
|
600
|
-
Promise.all([import("./status.js"), import("../monorepo-
|
|
708
|
+
Promise.all([import("./status.js"), import("../monorepo-N5Z63XP7.js")]).then(([{ runStatus }, { resolveProjectRoot: resolve }]) => {
|
|
601
709
|
let projectRoot = process.cwd();
|
|
602
710
|
try {
|
|
603
711
|
projectRoot = resolve(projectRoot).projectRoot;
|
|
@@ -652,6 +760,7 @@ export {
|
|
|
652
760
|
decideMcpConfigAction,
|
|
653
761
|
meetsNodeVersion,
|
|
654
762
|
rollbackSteps,
|
|
655
|
-
runInit
|
|
763
|
+
runInit,
|
|
764
|
+
verifyAnonKeyRegistration
|
|
656
765
|
};
|
|
657
766
|
//# sourceMappingURL=init.js.map
|