@glasstrace/sdk 0.7.0 → 0.7.2
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-PLJVIWHN.js → chunk-CNNEPHWN.js} +18 -2
- package/dist/chunk-CNNEPHWN.js.map +1 -0
- package/dist/cli/init.cjs +22 -24
- package/dist/cli/init.cjs.map +1 -1
- package/dist/cli/init.js +3 -13
- package/dist/cli/init.js.map +1 -1
- package/dist/cli/mcp-add.cjs +4 -2
- package/dist/cli/mcp-add.cjs.map +1 -1
- package/dist/cli/mcp-add.js +3 -13
- package/dist/cli/mcp-add.js.map +1 -1
- package/dist/index.cjs +105 -37
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +5 -1
- package/dist/index.d.ts +5 -1
- package/dist/index.js +107 -39
- package/dist/index.js.map +1 -1
- package/package.json +1 -6
- package/dist/chunk-PLJVIWHN.js.map +0 -1
package/dist/cli/mcp-add.js
CHANGED
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
import {
|
|
2
|
+
MCP_ENDPOINT,
|
|
2
3
|
detectAgents,
|
|
4
|
+
formatAgentName,
|
|
3
5
|
generateInfoSection,
|
|
4
6
|
generateMcpConfig,
|
|
5
7
|
injectInfoSection,
|
|
6
8
|
scaffoldMcpMarker,
|
|
7
9
|
updateGitignore,
|
|
8
10
|
writeMcpConfig
|
|
9
|
-
} from "../chunk-
|
|
11
|
+
} from "../chunk-CNNEPHWN.js";
|
|
10
12
|
import {
|
|
11
13
|
readAnonKey
|
|
12
14
|
} from "../chunk-QW6W4CSA.js";
|
|
@@ -18,18 +20,6 @@ import * as fs from "fs";
|
|
|
18
20
|
import * as path from "path";
|
|
19
21
|
import { promisify } from "util";
|
|
20
22
|
var execFileAsync = promisify(execFileCb);
|
|
21
|
-
var MCP_ENDPOINT = "https://api.glasstrace.dev/mcp";
|
|
22
|
-
function formatAgentName(name) {
|
|
23
|
-
const displayNames = {
|
|
24
|
-
claude: "Claude Code",
|
|
25
|
-
codex: "Codex",
|
|
26
|
-
gemini: "Gemini",
|
|
27
|
-
cursor: "Cursor",
|
|
28
|
-
windsurf: "Windsurf",
|
|
29
|
-
generic: "Generic"
|
|
30
|
-
};
|
|
31
|
-
return displayNames[name];
|
|
32
|
-
}
|
|
33
23
|
async function registerViaCli(agent, anonKey) {
|
|
34
24
|
if (!agent.cliAvailable) {
|
|
35
25
|
return false;
|
package/dist/cli/mcp-add.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/cli/mcp-add.ts"],"sourcesContent":["import { execFile as execFileCb } from \"node:child_process\";\nimport * as fs from \"node:fs\";\nimport * as path from \"node:path\";\nimport { promisify } from \"node:util\";\nimport { readAnonKey } from \"../anon-key.js\";\nimport { detectAgents } from \"../agent-detection/detect.js\";\nimport { generateMcpConfig, generateInfoSection } from \"../agent-detection/configs.js\";\nimport {\n writeMcpConfig,\n injectInfoSection,\n updateGitignore,\n} from \"../agent-detection/inject.js\";\nimport { scaffoldMcpMarker } from \"./scaffolder.js\";\nimport type { DetectedAgent } from \"../agent-detection/detect.js\";\n\nconst execFileAsync = promisify(execFileCb);\n\n/** Glasstrace MCP endpoint for agent configuration. */\nconst MCP_ENDPOINT = \"https://api.glasstrace.dev/mcp\";\n\n/** Maps internal agent name to a human-readable display name. */\nfunction formatAgentName(name: DetectedAgent[\"name\"]): string {\n const displayNames: Record<DetectedAgent[\"name\"], string> = {\n claude: \"Claude Code\",\n codex: \"Codex\",\n gemini: \"Gemini\",\n cursor: \"Cursor\",\n windsurf: \"Windsurf\",\n generic: \"Generic\",\n };\n return displayNames[name];\n}\n\n/** Options for the mcp add command. */\nexport interface McpAddOptions {\n force?: boolean;\n dryRun?: boolean;\n}\n\n/** Result of the mcp add command. */\nexport interface McpAddResult {\n exitCode: number;\n results: AgentResult[];\n messages: string[];\n}\n\n/**\n * Result of a single agent registration attempt.\n */\ninterface AgentResult {\n agent: DetectedAgent[\"name\"];\n success: boolean;\n method: \"cli\" | \"file\" | \"skipped\";\n message: string;\n}\n\n/**\n * Attempts CLI-based MCP registration for agents that support it.\n * Returns true if the CLI command succeeded.\n *\n * Note: anonymous keys are passed in process arguments for CLI registration.\n * This is acceptable because anon keys are non-secret identifiers (not\n * credentials) designed for semi-public use. They identify a project\n * but cannot be used to access user data.\n */\nasync function registerViaCli(\n agent: DetectedAgent,\n anonKey: string,\n): Promise<boolean> {\n if (!agent.cliAvailable) {\n return false;\n }\n\n try {\n switch (agent.name) {\n case \"claude\": {\n const payload = JSON.stringify({\n type: \"http\",\n url: MCP_ENDPOINT,\n headers: { Authorization: `Bearer ${anonKey}` },\n });\n await execFileAsync(\"claude\", [\n \"mcp\",\n \"add-json\",\n \"glasstrace\",\n payload,\n \"--scope\",\n \"project\",\n ]);\n return true;\n }\n\n case \"codex\": {\n await execFileAsync(\"codex\", [\n \"mcp\",\n \"add\",\n \"glasstrace\",\n \"--url\",\n MCP_ENDPOINT,\n ]);\n // Ensure .codex/config.toml has bearer_token_env_var\n const configPath = agent.mcpConfigPath;\n if (configPath !== null && fs.existsSync(configPath)) {\n const content = fs.readFileSync(configPath, \"utf-8\");\n if (!content.includes(\"bearer_token_env_var\")) {\n const appendContent =\n content.endsWith(\"\\n\") ? \"\" : \"\\n\";\n fs.writeFileSync(\n configPath,\n content +\n appendContent +\n 'bearer_token_env_var = \"GLASSTRACE_API_KEY\"\\n',\n \"utf-8\",\n );\n }\n }\n process.stderr.write(\n \" Note: Set GLASSTRACE_API_KEY environment variable for Codex authentication.\\n\",\n );\n return true;\n }\n\n case \"gemini\": {\n await execFileAsync(\"gemini\", [\n \"mcp\",\n \"add\",\n \"--transport\",\n \"http\",\n \"--header\",\n `Authorization: Bearer ${anonKey}`,\n \"glasstrace\",\n MCP_ENDPOINT,\n ]);\n return true;\n }\n\n default:\n return false;\n }\n } catch {\n return false;\n }\n}\n\n/**\n * Registers the Glasstrace MCP server with detected AI coding agents.\n *\n * For each agent, attempts native CLI registration first, then falls back\n * to file-based configuration. Creates a marker file on success to enable\n * idempotent re-runs.\n *\n * Returns a structured result instead of calling process.exit(), so the\n * CLI entry point can decide how to handle the outcome.\n *\n * @param options - Control flags for force and dry-run modes.\n */\nexport async function mcpAdd(options?: McpAddOptions): Promise<McpAddResult> {\n const force = options?.force ?? false;\n const dryRun = options?.dryRun ?? false;\n const projectRoot = process.cwd();\n const messages: string[] = [];\n\n // Step 1: Read anon key\n const anonKey = await readAnonKey(projectRoot);\n if (anonKey === null) {\n return {\n exitCode: 1,\n results: [],\n messages: [\"Error: Run `glasstrace init` first to generate an API key.\"],\n };\n }\n\n // Step 2: Check marker file\n const markerPath = path.join(projectRoot, \".glasstrace\", \"mcp-connected\");\n if (fs.existsSync(markerPath) && !force) {\n return {\n exitCode: 0,\n results: [],\n messages: [\"MCP already configured. Use --force to reconfigure.\"],\n };\n }\n\n // Step 3: Detect agents\n const agents = await detectAgents(projectRoot);\n const detectedNonGeneric = agents.filter((a) => a.name !== \"generic\");\n\n // If no specific agents found, include the generic fallback so the command\n // still produces a usable .glasstrace/mcp.json (matching init behavior).\n const targetAgents =\n detectedNonGeneric.length > 0\n ? detectedNonGeneric\n : agents.filter((a) => a.name === \"generic\");\n\n if (dryRun) {\n messages.push(\"Dry run: would perform the following actions:\", \"\");\n for (const agent of targetAgents) {\n const name = formatAgentName(agent.name);\n if (agent.cliAvailable) {\n messages.push(\n ` ${name}: Register via CLI (${agent.name} mcp add)`,\n );\n } else if (agent.mcpConfigPath !== null) {\n messages.push(\n ` ${name}: Write config to ${agent.mcpConfigPath}`,\n );\n }\n if (agent.infoFilePath !== null) {\n messages.push(\n ` ${name}: Inject info section into ${agent.infoFilePath}`,\n );\n }\n }\n messages.push(\n \"\",\n \" Update .gitignore with MCP config paths\",\n \" Create .glasstrace/mcp-connected marker\",\n );\n return { exitCode: 0, results: [], messages };\n }\n\n // Step 4: Register with each agent\n const results: AgentResult[] = [];\n\n for (const agent of targetAgents) {\n const name = formatAgentName(agent.name);\n\n // Try CLI registration first (not applicable for generic)\n if (agent.name !== \"generic\") {\n const cliSuccess = await registerViaCli(agent, anonKey);\n if (cliSuccess) {\n // Still inject info section if applicable\n const infoContent = generateInfoSection(agent, MCP_ENDPOINT);\n if (infoContent !== \"\") {\n await injectInfoSection(agent, infoContent, projectRoot);\n }\n results.push({\n agent: agent.name,\n success: true,\n method: \"cli\",\n message: `${name}: Registered via CLI`,\n });\n continue;\n }\n }\n\n // Fall back to file-based config\n if (agent.mcpConfigPath !== null) {\n try {\n const configContent = generateMcpConfig(agent, MCP_ENDPOINT, anonKey);\n await writeMcpConfig(agent, configContent, projectRoot);\n\n // Verify the config was written (writeMcpConfig swallows permission errors)\n if (fs.existsSync(agent.mcpConfigPath)) {\n const infoContent = generateInfoSection(agent, MCP_ENDPOINT);\n if (infoContent !== \"\") {\n await injectInfoSection(agent, infoContent, projectRoot);\n }\n results.push({\n agent: agent.name,\n success: true,\n method: \"file\",\n message: `${name}: Configured via ${agent.mcpConfigPath}`,\n });\n continue;\n }\n\n // writeMcpConfig returned without throwing but file doesn't exist\n // (permission denied handled gracefully inside writeMcpConfig)\n results.push({\n agent: agent.name,\n success: false,\n method: \"file\",\n message: `${name}: Failed to write config to ${agent.mcpConfigPath} (permission denied)`,\n });\n continue;\n } catch (err) {\n results.push({\n agent: agent.name,\n success: false,\n method: \"file\",\n message: `${name}: Failed - ${err instanceof Error ? err.message : String(err)}`,\n });\n continue;\n }\n }\n\n results.push({\n agent: agent.name,\n success: false,\n method: \"skipped\",\n message: `${name}: No registration method available`,\n });\n }\n\n // Step 5: Update gitignore\n await updateGitignore(\n [\".mcp.json\", \".cursor/mcp.json\", \".gemini/settings.json\", \".codex/config.toml\"],\n projectRoot,\n );\n\n // Step 6: Create marker file if at least one succeeded\n const anySuccess = results.some((r) => r.success);\n\n if (anySuccess) {\n await scaffoldMcpMarker(projectRoot, anonKey);\n }\n\n // Step 7: Build summary messages\n messages.push(\"\", \"MCP registration summary:\");\n for (const result of results) {\n const icon = result.success ? \"+\" : \"-\";\n messages.push(` [${icon}] ${result.message}`);\n }\n\n if (results.length === 0) {\n messages.push(\n \" No agents detected. Place agent marker files (e.g., CLAUDE.md, .cursor/) in your project.\",\n );\n }\n\n if (!anySuccess && results.length > 0) {\n messages.push(\n \"\",\n \"All agent registrations failed. Check errors above.\",\n );\n return { exitCode: 1, results, messages };\n }\n\n if (anySuccess) {\n messages.push(\"\", \"MCP registration complete.\");\n }\n\n return { exitCode: 0, results, messages };\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../src/cli/mcp-add.ts"],"sourcesContent":["import { execFile as execFileCb } from \"node:child_process\";\nimport * as fs from \"node:fs\";\nimport * as path from \"node:path\";\nimport { promisify } from \"node:util\";\nimport { readAnonKey } from \"../anon-key.js\";\nimport { detectAgents } from \"../agent-detection/detect.js\";\nimport { generateMcpConfig, generateInfoSection } from \"../agent-detection/configs.js\";\nimport {\n writeMcpConfig,\n injectInfoSection,\n updateGitignore,\n} from \"../agent-detection/inject.js\";\nimport { scaffoldMcpMarker } from \"./scaffolder.js\";\nimport type { DetectedAgent } from \"../agent-detection/detect.js\";\nimport { MCP_ENDPOINT, formatAgentName } from \"./constants.js\";\n\nconst execFileAsync = promisify(execFileCb);\n\n/** Options for the mcp add command. */\nexport interface McpAddOptions {\n force?: boolean;\n dryRun?: boolean;\n}\n\n/** Result of the mcp add command. */\nexport interface McpAddResult {\n exitCode: number;\n results: AgentResult[];\n messages: string[];\n}\n\n/**\n * Result of a single agent registration attempt.\n */\ninterface AgentResult {\n agent: DetectedAgent[\"name\"];\n success: boolean;\n method: \"cli\" | \"file\" | \"skipped\";\n message: string;\n}\n\n/**\n * Attempts CLI-based MCP registration for agents that support it.\n * Returns true if the CLI command succeeded.\n *\n * Note: anonymous keys are passed in process arguments for CLI registration.\n * This is acceptable because anon keys are non-secret identifiers (not\n * credentials) designed for semi-public use. They identify a project\n * but cannot be used to access user data.\n */\nasync function registerViaCli(\n agent: DetectedAgent,\n anonKey: string,\n): Promise<boolean> {\n if (!agent.cliAvailable) {\n return false;\n }\n\n try {\n switch (agent.name) {\n case \"claude\": {\n const payload = JSON.stringify({\n type: \"http\",\n url: MCP_ENDPOINT,\n headers: { Authorization: `Bearer ${anonKey}` },\n });\n await execFileAsync(\"claude\", [\n \"mcp\",\n \"add-json\",\n \"glasstrace\",\n payload,\n \"--scope\",\n \"project\",\n ]);\n return true;\n }\n\n case \"codex\": {\n await execFileAsync(\"codex\", [\n \"mcp\",\n \"add\",\n \"glasstrace\",\n \"--url\",\n MCP_ENDPOINT,\n ]);\n // Ensure .codex/config.toml has bearer_token_env_var\n const configPath = agent.mcpConfigPath;\n if (configPath !== null && fs.existsSync(configPath)) {\n const content = fs.readFileSync(configPath, \"utf-8\");\n if (!content.includes(\"bearer_token_env_var\")) {\n const appendContent =\n content.endsWith(\"\\n\") ? \"\" : \"\\n\";\n fs.writeFileSync(\n configPath,\n content +\n appendContent +\n 'bearer_token_env_var = \"GLASSTRACE_API_KEY\"\\n',\n \"utf-8\",\n );\n }\n }\n process.stderr.write(\n \" Note: Set GLASSTRACE_API_KEY environment variable for Codex authentication.\\n\",\n );\n return true;\n }\n\n case \"gemini\": {\n await execFileAsync(\"gemini\", [\n \"mcp\",\n \"add\",\n \"--transport\",\n \"http\",\n \"--header\",\n `Authorization: Bearer ${anonKey}`,\n \"glasstrace\",\n MCP_ENDPOINT,\n ]);\n return true;\n }\n\n default:\n return false;\n }\n } catch {\n return false;\n }\n}\n\n/**\n * Registers the Glasstrace MCP server with detected AI coding agents.\n *\n * For each agent, attempts native CLI registration first, then falls back\n * to file-based configuration. Creates a marker file on success to enable\n * idempotent re-runs.\n *\n * Returns a structured result instead of calling process.exit(), so the\n * CLI entry point can decide how to handle the outcome.\n *\n * @param options - Control flags for force and dry-run modes.\n */\nexport async function mcpAdd(options?: McpAddOptions): Promise<McpAddResult> {\n const force = options?.force ?? false;\n const dryRun = options?.dryRun ?? false;\n const projectRoot = process.cwd();\n const messages: string[] = [];\n\n // Step 1: Read anon key\n const anonKey = await readAnonKey(projectRoot);\n if (anonKey === null) {\n return {\n exitCode: 1,\n results: [],\n messages: [\"Error: Run `glasstrace init` first to generate an API key.\"],\n };\n }\n\n // Step 2: Check marker file\n const markerPath = path.join(projectRoot, \".glasstrace\", \"mcp-connected\");\n if (fs.existsSync(markerPath) && !force) {\n return {\n exitCode: 0,\n results: [],\n messages: [\"MCP already configured. Use --force to reconfigure.\"],\n };\n }\n\n // Step 3: Detect agents\n const agents = await detectAgents(projectRoot);\n const detectedNonGeneric = agents.filter((a) => a.name !== \"generic\");\n\n // If no specific agents found, include the generic fallback so the command\n // still produces a usable .glasstrace/mcp.json (matching init behavior).\n const targetAgents =\n detectedNonGeneric.length > 0\n ? detectedNonGeneric\n : agents.filter((a) => a.name === \"generic\");\n\n if (dryRun) {\n messages.push(\"Dry run: would perform the following actions:\", \"\");\n for (const agent of targetAgents) {\n const name = formatAgentName(agent.name);\n if (agent.cliAvailable) {\n messages.push(\n ` ${name}: Register via CLI (${agent.name} mcp add)`,\n );\n } else if (agent.mcpConfigPath !== null) {\n messages.push(\n ` ${name}: Write config to ${agent.mcpConfigPath}`,\n );\n }\n if (agent.infoFilePath !== null) {\n messages.push(\n ` ${name}: Inject info section into ${agent.infoFilePath}`,\n );\n }\n }\n messages.push(\n \"\",\n \" Update .gitignore with MCP config paths\",\n \" Create .glasstrace/mcp-connected marker\",\n );\n return { exitCode: 0, results: [], messages };\n }\n\n // Step 4: Register with each agent\n const results: AgentResult[] = [];\n\n for (const agent of targetAgents) {\n const name = formatAgentName(agent.name);\n\n // Try CLI registration first (not applicable for generic)\n if (agent.name !== \"generic\") {\n const cliSuccess = await registerViaCli(agent, anonKey);\n if (cliSuccess) {\n // Still inject info section if applicable\n const infoContent = generateInfoSection(agent, MCP_ENDPOINT);\n if (infoContent !== \"\") {\n await injectInfoSection(agent, infoContent, projectRoot);\n }\n results.push({\n agent: agent.name,\n success: true,\n method: \"cli\",\n message: `${name}: Registered via CLI`,\n });\n continue;\n }\n }\n\n // Fall back to file-based config\n if (agent.mcpConfigPath !== null) {\n try {\n const configContent = generateMcpConfig(agent, MCP_ENDPOINT, anonKey);\n await writeMcpConfig(agent, configContent, projectRoot);\n\n // Verify the config was written (writeMcpConfig swallows permission errors)\n if (fs.existsSync(agent.mcpConfigPath)) {\n const infoContent = generateInfoSection(agent, MCP_ENDPOINT);\n if (infoContent !== \"\") {\n await injectInfoSection(agent, infoContent, projectRoot);\n }\n results.push({\n agent: agent.name,\n success: true,\n method: \"file\",\n message: `${name}: Configured via ${agent.mcpConfigPath}`,\n });\n continue;\n }\n\n // writeMcpConfig returned without throwing but file doesn't exist\n // (permission denied handled gracefully inside writeMcpConfig)\n results.push({\n agent: agent.name,\n success: false,\n method: \"file\",\n message: `${name}: Failed to write config to ${agent.mcpConfigPath} (permission denied)`,\n });\n continue;\n } catch (err) {\n results.push({\n agent: agent.name,\n success: false,\n method: \"file\",\n message: `${name}: Failed - ${err instanceof Error ? err.message : String(err)}`,\n });\n continue;\n }\n }\n\n results.push({\n agent: agent.name,\n success: false,\n method: \"skipped\",\n message: `${name}: No registration method available`,\n });\n }\n\n // Step 5: Update gitignore\n await updateGitignore(\n [\".mcp.json\", \".cursor/mcp.json\", \".gemini/settings.json\", \".codex/config.toml\"],\n projectRoot,\n );\n\n // Step 6: Create marker file if at least one succeeded\n const anySuccess = results.some((r) => r.success);\n\n if (anySuccess) {\n await scaffoldMcpMarker(projectRoot, anonKey);\n }\n\n // Step 7: Build summary messages\n messages.push(\"\", \"MCP registration summary:\");\n for (const result of results) {\n const icon = result.success ? \"+\" : \"-\";\n messages.push(` [${icon}] ${result.message}`);\n }\n\n if (results.length === 0) {\n messages.push(\n \" No agents detected. Place agent marker files (e.g., CLAUDE.md, .cursor/) in your project.\",\n );\n }\n\n if (!anySuccess && results.length > 0) {\n messages.push(\n \"\",\n \"All agent registrations failed. Check errors above.\",\n );\n return { exitCode: 1, results, messages };\n }\n\n if (anySuccess) {\n messages.push(\"\", \"MCP registration complete.\");\n }\n\n return { exitCode: 0, results, messages };\n}\n"],"mappings":"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","names":[]}
|
package/dist/index.cjs
CHANGED
|
@@ -15821,6 +15821,7 @@ var CONFIG_FILE = "config";
|
|
|
15821
15821
|
var TWENTY_FOUR_HOURS_MS = 24 * 60 * 60 * 1e3;
|
|
15822
15822
|
var INIT_TIMEOUT_MS = 1e4;
|
|
15823
15823
|
var currentConfig = null;
|
|
15824
|
+
var configCacheChecked = false;
|
|
15824
15825
|
var rateLimitBackoff = false;
|
|
15825
15826
|
function loadCachedConfig(projectRoot) {
|
|
15826
15827
|
const root = projectRoot ?? process.cwd();
|
|
@@ -15850,12 +15851,14 @@ async function saveCachedConfig(response, projectRoot) {
|
|
|
15850
15851
|
const dirPath = (0, import_node_path2.join)(root, GLASSTRACE_DIR2);
|
|
15851
15852
|
const configPath = (0, import_node_path2.join)(dirPath, CONFIG_FILE);
|
|
15852
15853
|
try {
|
|
15853
|
-
await (0, import_promises2.mkdir)(dirPath, { recursive: true });
|
|
15854
|
+
await (0, import_promises2.mkdir)(dirPath, { recursive: true, mode: 448 });
|
|
15855
|
+
await (0, import_promises2.chmod)(dirPath, 448);
|
|
15854
15856
|
const cached2 = {
|
|
15855
15857
|
response,
|
|
15856
15858
|
cachedAt: Date.now()
|
|
15857
15859
|
};
|
|
15858
|
-
await (0, import_promises2.writeFile)(configPath, JSON.stringify(cached2), "utf-8");
|
|
15860
|
+
await (0, import_promises2.writeFile)(configPath, JSON.stringify(cached2), { encoding: "utf-8", mode: 384 });
|
|
15861
|
+
await (0, import_promises2.chmod)(configPath, 384);
|
|
15859
15862
|
} catch (err) {
|
|
15860
15863
|
console.warn(
|
|
15861
15864
|
`[glasstrace] Failed to cache config to ${configPath}: ${err instanceof Error ? err.message : String(err)}`
|
|
@@ -15908,6 +15911,78 @@ async function sendInitRequest(config2, anonKey, sdkVersion, importGraph, health
|
|
|
15908
15911
|
const body = await response.json();
|
|
15909
15912
|
return SdkInitResponseSchema.parse(body);
|
|
15910
15913
|
}
|
|
15914
|
+
async function writeClaimedKey(newApiKey, projectRoot) {
|
|
15915
|
+
const root = projectRoot ?? process.cwd();
|
|
15916
|
+
const envLocalPath = (0, import_node_path2.join)(root, ".env.local");
|
|
15917
|
+
let envLocalWritten = false;
|
|
15918
|
+
try {
|
|
15919
|
+
let content;
|
|
15920
|
+
try {
|
|
15921
|
+
content = await (0, import_promises2.readFile)(envLocalPath, "utf-8");
|
|
15922
|
+
if (/^GLASSTRACE_API_KEY=.*/m.test(content)) {
|
|
15923
|
+
content = content.replace(
|
|
15924
|
+
/^GLASSTRACE_API_KEY=.*$/gm,
|
|
15925
|
+
`GLASSTRACE_API_KEY=${newApiKey}`
|
|
15926
|
+
);
|
|
15927
|
+
} else {
|
|
15928
|
+
if (content.length > 0 && !content.endsWith("\n")) {
|
|
15929
|
+
content += "\n";
|
|
15930
|
+
}
|
|
15931
|
+
content += `GLASSTRACE_API_KEY=${newApiKey}
|
|
15932
|
+
`;
|
|
15933
|
+
}
|
|
15934
|
+
} catch (readErr) {
|
|
15935
|
+
const code = readErr instanceof Error ? readErr.code : void 0;
|
|
15936
|
+
if (code !== "ENOENT") {
|
|
15937
|
+
throw readErr;
|
|
15938
|
+
}
|
|
15939
|
+
content = `GLASSTRACE_API_KEY=${newApiKey}
|
|
15940
|
+
`;
|
|
15941
|
+
}
|
|
15942
|
+
await (0, import_promises2.writeFile)(envLocalPath, content, { encoding: "utf-8", mode: 384 });
|
|
15943
|
+
await (0, import_promises2.chmod)(envLocalPath, 384);
|
|
15944
|
+
envLocalWritten = true;
|
|
15945
|
+
} catch {
|
|
15946
|
+
}
|
|
15947
|
+
if (envLocalWritten) {
|
|
15948
|
+
try {
|
|
15949
|
+
process.stderr.write(
|
|
15950
|
+
"[glasstrace] Account claimed! API key written to .env.local. Restart your dev server to use it.\n"
|
|
15951
|
+
);
|
|
15952
|
+
} catch {
|
|
15953
|
+
}
|
|
15954
|
+
return;
|
|
15955
|
+
}
|
|
15956
|
+
let claimedKeyWritten = false;
|
|
15957
|
+
try {
|
|
15958
|
+
const dirPath = (0, import_node_path2.join)(root, GLASSTRACE_DIR2);
|
|
15959
|
+
await (0, import_promises2.mkdir)(dirPath, { recursive: true, mode: 448 });
|
|
15960
|
+
await (0, import_promises2.chmod)(dirPath, 448);
|
|
15961
|
+
const claimedKeyPath = (0, import_node_path2.join)(dirPath, "claimed-key");
|
|
15962
|
+
await (0, import_promises2.writeFile)(claimedKeyPath, newApiKey, {
|
|
15963
|
+
encoding: "utf-8",
|
|
15964
|
+
mode: 384
|
|
15965
|
+
});
|
|
15966
|
+
await (0, import_promises2.chmod)(claimedKeyPath, 384);
|
|
15967
|
+
claimedKeyWritten = true;
|
|
15968
|
+
} catch {
|
|
15969
|
+
}
|
|
15970
|
+
if (claimedKeyWritten) {
|
|
15971
|
+
try {
|
|
15972
|
+
process.stderr.write(
|
|
15973
|
+
"[glasstrace] Account claimed! API key written to .glasstrace/claimed-key. Copy it to your .env.local file.\n"
|
|
15974
|
+
);
|
|
15975
|
+
} catch {
|
|
15976
|
+
}
|
|
15977
|
+
return;
|
|
15978
|
+
}
|
|
15979
|
+
try {
|
|
15980
|
+
process.stderr.write(
|
|
15981
|
+
"[glasstrace] Account claimed but could not write key to disk. Visit your dashboard settings to rotate and retrieve a new API key.\n"
|
|
15982
|
+
);
|
|
15983
|
+
} catch {
|
|
15984
|
+
}
|
|
15985
|
+
}
|
|
15911
15986
|
async function performInit(config2, anonKey, sdkVersion) {
|
|
15912
15987
|
if (rateLimitBackoff) {
|
|
15913
15988
|
rateLimitBackoff = false;
|
|
@@ -15936,14 +16011,8 @@ async function performInit(config2, anonKey, sdkVersion) {
|
|
|
15936
16011
|
await saveCachedConfig(result);
|
|
15937
16012
|
if (result.claimResult) {
|
|
15938
16013
|
try {
|
|
15939
|
-
|
|
15940
|
-
|
|
15941
|
-
`
|
|
15942
|
-
);
|
|
15943
|
-
} catch (logErr) {
|
|
15944
|
-
console.warn(
|
|
15945
|
-
`[glasstrace] Failed to write claim migration message: ${logErr instanceof Error ? logErr.message : String(logErr)}`
|
|
15946
|
-
);
|
|
16014
|
+
await writeClaimedKey(result.claimResult.newApiKey);
|
|
16015
|
+
} catch {
|
|
15947
16016
|
}
|
|
15948
16017
|
return { claimResult: result.claimResult };
|
|
15949
16018
|
}
|
|
@@ -15994,9 +16063,13 @@ function getActiveConfig() {
|
|
|
15994
16063
|
if (currentConfig) {
|
|
15995
16064
|
return currentConfig.config;
|
|
15996
16065
|
}
|
|
15997
|
-
|
|
15998
|
-
|
|
15999
|
-
|
|
16066
|
+
if (!configCacheChecked) {
|
|
16067
|
+
configCacheChecked = true;
|
|
16068
|
+
const cached2 = loadCachedConfig();
|
|
16069
|
+
if (cached2) {
|
|
16070
|
+
currentConfig = cached2;
|
|
16071
|
+
return cached2.config;
|
|
16072
|
+
}
|
|
16000
16073
|
}
|
|
16001
16074
|
return { ...DEFAULT_CAPTURE_CONFIG };
|
|
16002
16075
|
}
|
|
@@ -19223,15 +19296,7 @@ function registerGlasstrace(options) {
|
|
|
19223
19296
|
() => Promise.resolve(anonKey),
|
|
19224
19297
|
() => sessionManager.getSessionId(getResolvedApiKey())
|
|
19225
19298
|
);
|
|
19226
|
-
|
|
19227
|
-
console.info("[glasstrace] Background init firing.");
|
|
19228
|
-
}
|
|
19229
|
-
const initResult = await performInit(config2, anonKey, "0.7.0");
|
|
19230
|
-
if (initResult?.claimResult) {
|
|
19231
|
-
setResolvedApiKey(initResult.claimResult.newApiKey);
|
|
19232
|
-
notifyApiKeyResolved();
|
|
19233
|
-
}
|
|
19234
|
-
maybeInstallConsoleCapture();
|
|
19299
|
+
await backgroundInit(config2, anonKey, currentGeneration);
|
|
19235
19300
|
} catch (err) {
|
|
19236
19301
|
console.warn(
|
|
19237
19302
|
`[glasstrace] Background init failed: ${err instanceof Error ? err.message : String(err)}`
|
|
@@ -19247,15 +19312,7 @@ function registerGlasstrace(options) {
|
|
|
19247
19312
|
notifyApiKeyResolved();
|
|
19248
19313
|
effectiveKey = anonKey;
|
|
19249
19314
|
if (currentGeneration !== registrationGeneration) return;
|
|
19250
|
-
|
|
19251
|
-
console.info("[glasstrace] Background init firing.");
|
|
19252
|
-
}
|
|
19253
|
-
const initResult = await performInit(config2, anonKey, "0.7.0");
|
|
19254
|
-
if (initResult?.claimResult) {
|
|
19255
|
-
setResolvedApiKey(initResult.claimResult.newApiKey);
|
|
19256
|
-
notifyApiKeyResolved();
|
|
19257
|
-
}
|
|
19258
|
-
maybeInstallConsoleCapture();
|
|
19315
|
+
await backgroundInit(config2, anonKey, currentGeneration);
|
|
19259
19316
|
} catch (err) {
|
|
19260
19317
|
console.warn(
|
|
19261
19318
|
`[glasstrace] Background init failed: ${err instanceof Error ? err.message : String(err)}`
|
|
@@ -19273,11 +19330,7 @@ function registerGlasstrace(options) {
|
|
|
19273
19330
|
} catch {
|
|
19274
19331
|
}
|
|
19275
19332
|
if (currentGeneration !== registrationGeneration) return;
|
|
19276
|
-
|
|
19277
|
-
console.info("[glasstrace] Background init firing.");
|
|
19278
|
-
}
|
|
19279
|
-
await performInit(config2, anonKeyForInit, "0.7.0");
|
|
19280
|
-
maybeInstallConsoleCapture();
|
|
19333
|
+
await backgroundInit(config2, anonKeyForInit, currentGeneration);
|
|
19281
19334
|
} catch (err) {
|
|
19282
19335
|
console.warn(
|
|
19283
19336
|
`[glasstrace] Background init failed: ${err instanceof Error ? err.message : String(err)}`
|
|
@@ -19294,6 +19347,18 @@ function registerGlasstrace(options) {
|
|
|
19294
19347
|
);
|
|
19295
19348
|
}
|
|
19296
19349
|
}
|
|
19350
|
+
async function backgroundInit(config2, anonKeyForInit, generation) {
|
|
19351
|
+
if (config2.verbose) {
|
|
19352
|
+
console.info("[glasstrace] Background init firing.");
|
|
19353
|
+
}
|
|
19354
|
+
const initResult = await performInit(config2, anonKeyForInit, "0.7.2");
|
|
19355
|
+
if (generation !== registrationGeneration) return;
|
|
19356
|
+
if (initResult?.claimResult) {
|
|
19357
|
+
setResolvedApiKey(initResult.claimResult.newApiKey);
|
|
19358
|
+
notifyApiKeyResolved();
|
|
19359
|
+
}
|
|
19360
|
+
maybeInstallConsoleCapture();
|
|
19361
|
+
}
|
|
19297
19362
|
function getDiscoveryHandler() {
|
|
19298
19363
|
return discoveryHandler;
|
|
19299
19364
|
}
|
|
@@ -19351,7 +19416,7 @@ async function walkDir(baseDir, currentDir, results) {
|
|
|
19351
19416
|
}
|
|
19352
19417
|
async function computeBuildHash(maps) {
|
|
19353
19418
|
try {
|
|
19354
|
-
const sha = (0, import_node_child_process.
|
|
19419
|
+
const sha = (0, import_node_child_process.execFileSync)("git", ["rev-parse", "HEAD"], { encoding: "utf-8" }).trim();
|
|
19355
19420
|
if (sha) {
|
|
19356
19421
|
return sha;
|
|
19357
19422
|
}
|
|
@@ -19656,6 +19721,9 @@ function captureError(error48) {
|
|
|
19656
19721
|
};
|
|
19657
19722
|
if (error48 instanceof Error) {
|
|
19658
19723
|
attributes["error.type"] = error48.constructor.name;
|
|
19724
|
+
if (error48.stack) {
|
|
19725
|
+
attributes["error.stack"] = error48.stack;
|
|
19726
|
+
}
|
|
19659
19727
|
}
|
|
19660
19728
|
span.addEvent("glasstrace.error", attributes);
|
|
19661
19729
|
maybeShowMcpNudge(String(error48));
|