@glasstrace/sdk 0.14.1 → 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-ERGEG4ZQ.js → chunk-2LDBR3F3.js} +16 -3
- package/dist/chunk-2LDBR3F3.js.map +1 -0
- 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 +123 -47
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +45 -5
- package/dist/index.d.ts +45 -5
- package/dist/index.js +109 -46
- package/dist/index.js.map +1 -1
- package/dist/{source-map-uploader-W6VPGY26.js → source-map-uploader-3GWUQDTS.js} +6 -2
- package/package.json +6 -4
- package/dist/chunk-ARAOZCZT.js.map +0 -1
- package/dist/chunk-ERGEG4ZQ.js.map +0 -1
- package/dist/chunk-WV3NIPWJ.js.map +0 -1
- /package/dist/{source-map-uploader-W6VPGY26.js.map → source-map-uploader-3GWUQDTS.js.map} +0 -0
package/dist/cli/mcp-add.js
CHANGED
|
@@ -3,14 +3,16 @@ import {
|
|
|
3
3
|
generateInfoSection,
|
|
4
4
|
generateMcpConfig,
|
|
5
5
|
injectInfoSection,
|
|
6
|
-
scaffoldMcpMarker,
|
|
7
6
|
updateGitignore,
|
|
8
7
|
writeMcpConfig
|
|
9
|
-
} from "../chunk-
|
|
8
|
+
} from "../chunk-ZNOD6FC7.js";
|
|
10
9
|
import {
|
|
11
10
|
readAnonKey
|
|
12
11
|
} from "../chunk-ECEN724Y.js";
|
|
13
12
|
import "../chunk-YMEXDDTA.js";
|
|
13
|
+
import {
|
|
14
|
+
scaffoldMcpMarker
|
|
15
|
+
} from "../chunk-A2AZL6MZ.js";
|
|
14
16
|
import {
|
|
15
17
|
MCP_ENDPOINT,
|
|
16
18
|
formatAgentName
|
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\";\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":[]}
|
|
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/cli/uninit.cjs
CHANGED
|
@@ -41,16 +41,39 @@ __export(uninit_exports, {
|
|
|
41
41
|
runUninit: () => runUninit,
|
|
42
42
|
skipString: () => skipString,
|
|
43
43
|
unwrapCJSExport: () => unwrapCJSExport,
|
|
44
|
-
unwrapExport: () => unwrapExport
|
|
44
|
+
unwrapExport: () => unwrapExport,
|
|
45
|
+
writeShutdownMarker: () => writeShutdownMarker
|
|
45
46
|
});
|
|
46
47
|
module.exports = __toCommonJS(uninit_exports);
|
|
47
|
-
var
|
|
48
|
+
var fs2 = __toESM(require("fs"), 1);
|
|
48
49
|
var os = __toESM(require("os"), 1);
|
|
49
|
-
var
|
|
50
|
+
var path2 = __toESM(require("path"), 1);
|
|
50
51
|
|
|
51
52
|
// src/cli/constants.ts
|
|
52
53
|
var NEXT_CONFIG_NAMES = ["next.config.ts", "next.config.js", "next.config.mjs"];
|
|
53
54
|
|
|
55
|
+
// src/cli/scaffolder.ts
|
|
56
|
+
var import_node_crypto = require("crypto");
|
|
57
|
+
var fs = __toESM(require("fs"), 1);
|
|
58
|
+
var path = __toESM(require("path"), 1);
|
|
59
|
+
function readEnvLocalApiKey(content) {
|
|
60
|
+
let last = null;
|
|
61
|
+
const regex = /^\s*GLASSTRACE_API_KEY\s*=\s*(.*)$/gm;
|
|
62
|
+
let match;
|
|
63
|
+
while ((match = regex.exec(content)) !== null) {
|
|
64
|
+
const raw = match[1].trim();
|
|
65
|
+
if (raw === "") continue;
|
|
66
|
+
const unquoted = raw.replace(/^(['"])(.*)\1$/, "$2");
|
|
67
|
+
if (unquoted === "" || unquoted === "your_key_here") continue;
|
|
68
|
+
last = unquoted;
|
|
69
|
+
}
|
|
70
|
+
return last;
|
|
71
|
+
}
|
|
72
|
+
function isDevApiKey(value) {
|
|
73
|
+
if (value === null || value === void 0) return false;
|
|
74
|
+
return value.trim().startsWith("gt_dev_");
|
|
75
|
+
}
|
|
76
|
+
|
|
54
77
|
// src/cli/uninit.ts
|
|
55
78
|
var MCP_CONFIG_FILES = [".mcp.json", ".cursor/mcp.json", ".gemini/settings.json"];
|
|
56
79
|
var AGENT_INFO_FILES = [
|
|
@@ -357,20 +380,83 @@ function processTomlMcpConfig(content) {
|
|
|
357
380
|
}
|
|
358
381
|
return { action: "removed-section", content: result + "\n" };
|
|
359
382
|
}
|
|
383
|
+
function writeShutdownMarker(projectRoot) {
|
|
384
|
+
const dirPath = path2.join(projectRoot, ".glasstrace");
|
|
385
|
+
if (!fs2.existsSync(dirPath)) {
|
|
386
|
+
return false;
|
|
387
|
+
}
|
|
388
|
+
const markerPath = path2.join(dirPath, "shutdown-requested");
|
|
389
|
+
const tmpPath = `${markerPath}.tmp`;
|
|
390
|
+
const body = JSON.stringify({ requestedAt: (/* @__PURE__ */ new Date()).toISOString() });
|
|
391
|
+
try {
|
|
392
|
+
fs2.writeFileSync(tmpPath, body, { encoding: "utf-8", mode: 384 });
|
|
393
|
+
try {
|
|
394
|
+
fs2.chmodSync(tmpPath, 384);
|
|
395
|
+
} catch {
|
|
396
|
+
}
|
|
397
|
+
fs2.renameSync(tmpPath, markerPath);
|
|
398
|
+
return true;
|
|
399
|
+
} catch {
|
|
400
|
+
try {
|
|
401
|
+
fs2.unlinkSync(tmpPath);
|
|
402
|
+
} catch {
|
|
403
|
+
}
|
|
404
|
+
return false;
|
|
405
|
+
}
|
|
406
|
+
}
|
|
407
|
+
async function defaultPrompt(question, defaultValue) {
|
|
408
|
+
if (!process.stdin.isTTY) return defaultValue;
|
|
409
|
+
const readline = await import("readline");
|
|
410
|
+
const rl = readline.createInterface({
|
|
411
|
+
input: process.stdin,
|
|
412
|
+
output: process.stdout
|
|
413
|
+
});
|
|
414
|
+
return new Promise((resolve) => {
|
|
415
|
+
const suffix = defaultValue ? " [Y/n] " : " [y/N] ";
|
|
416
|
+
rl.question(question + suffix, (answer) => {
|
|
417
|
+
rl.close();
|
|
418
|
+
const trimmed = answer.trim().toLowerCase();
|
|
419
|
+
if (trimmed === "") {
|
|
420
|
+
resolve(defaultValue);
|
|
421
|
+
return;
|
|
422
|
+
}
|
|
423
|
+
resolve(trimmed === "y" || trimmed === "yes");
|
|
424
|
+
});
|
|
425
|
+
});
|
|
426
|
+
}
|
|
360
427
|
async function runUninit(options) {
|
|
361
428
|
const { projectRoot, dryRun } = options;
|
|
429
|
+
const force = options.force === true;
|
|
430
|
+
const prompt = options.prompt ?? defaultPrompt;
|
|
362
431
|
const summary = [];
|
|
363
432
|
const warnings = [];
|
|
364
433
|
const errors = [];
|
|
365
434
|
const prefix = dryRun ? "[dry run] " : "";
|
|
435
|
+
try {
|
|
436
|
+
if (!dryRun) {
|
|
437
|
+
const markerWritten = writeShutdownMarker(projectRoot);
|
|
438
|
+
if (markerWritten) {
|
|
439
|
+
summary.push("Wrote .glasstrace/shutdown-requested marker");
|
|
440
|
+
}
|
|
441
|
+
} else {
|
|
442
|
+
const dirPath = path2.join(projectRoot, ".glasstrace");
|
|
443
|
+
if (fs2.existsSync(dirPath)) {
|
|
444
|
+
summary.push(`${prefix}Would write .glasstrace/shutdown-requested marker`);
|
|
445
|
+
}
|
|
446
|
+
}
|
|
447
|
+
} catch (err) {
|
|
448
|
+
warnings.push(
|
|
449
|
+
`Shutdown marker write failed: ${err instanceof Error ? err.message : String(err)}`
|
|
450
|
+
);
|
|
451
|
+
}
|
|
366
452
|
try {
|
|
367
453
|
let configHandled = false;
|
|
368
454
|
for (const name of NEXT_CONFIG_NAMES) {
|
|
369
|
-
const configPath =
|
|
370
|
-
if (!
|
|
455
|
+
const configPath = path2.join(projectRoot, name);
|
|
456
|
+
if (!fs2.existsSync(configPath)) {
|
|
371
457
|
continue;
|
|
372
458
|
}
|
|
373
|
-
const content =
|
|
459
|
+
const content = fs2.readFileSync(configPath, "utf-8");
|
|
374
460
|
if (!content.includes("withGlasstraceConfig")) {
|
|
375
461
|
continue;
|
|
376
462
|
}
|
|
@@ -380,7 +466,7 @@ async function runUninit(options) {
|
|
|
380
466
|
const cleaned = removeGlasstraceConfigImport(unwrapResult.content);
|
|
381
467
|
const final = cleanLeadingBlankLines(cleaned);
|
|
382
468
|
if (!dryRun) {
|
|
383
|
-
|
|
469
|
+
fs2.writeFileSync(configPath, final, "utf-8");
|
|
384
470
|
}
|
|
385
471
|
summary.push(`${prefix}Unwrapped withGlasstraceConfig from ${name}`);
|
|
386
472
|
configHandled = true;
|
|
@@ -401,20 +487,20 @@ async function runUninit(options) {
|
|
|
401
487
|
);
|
|
402
488
|
}
|
|
403
489
|
try {
|
|
404
|
-
const instrPath =
|
|
405
|
-
if (
|
|
406
|
-
const content =
|
|
490
|
+
const instrPath = path2.join(projectRoot, "instrumentation.ts");
|
|
491
|
+
if (fs2.existsSync(instrPath)) {
|
|
492
|
+
const content = fs2.readFileSync(instrPath, "utf-8");
|
|
407
493
|
if (content.includes("registerGlasstrace") || content.includes("@glasstrace/sdk")) {
|
|
408
494
|
if (isInitCreatedInstrumentation(content)) {
|
|
409
495
|
if (!dryRun) {
|
|
410
|
-
|
|
496
|
+
fs2.unlinkSync(instrPath);
|
|
411
497
|
}
|
|
412
498
|
summary.push(`${prefix}Deleted instrumentation.ts (init-created)`);
|
|
413
499
|
} else {
|
|
414
500
|
const cleaned = removeRegisterGlasstrace(content);
|
|
415
501
|
if (cleaned !== content) {
|
|
416
502
|
if (!dryRun) {
|
|
417
|
-
|
|
503
|
+
fs2.writeFileSync(instrPath, cleaned, "utf-8");
|
|
418
504
|
}
|
|
419
505
|
summary.push(
|
|
420
506
|
`${prefix}Removed registerGlasstrace() from instrumentation.ts`
|
|
@@ -429,10 +515,10 @@ async function runUninit(options) {
|
|
|
429
515
|
);
|
|
430
516
|
}
|
|
431
517
|
try {
|
|
432
|
-
const glasstraceDir =
|
|
433
|
-
if (
|
|
518
|
+
const glasstraceDir = path2.join(projectRoot, ".glasstrace");
|
|
519
|
+
if (fs2.existsSync(glasstraceDir)) {
|
|
434
520
|
if (!dryRun) {
|
|
435
|
-
|
|
521
|
+
fs2.rmSync(glasstraceDir, { recursive: true, force: true });
|
|
436
522
|
}
|
|
437
523
|
summary.push(`${prefix}Removed .glasstrace/ directory`);
|
|
438
524
|
}
|
|
@@ -442,26 +528,60 @@ async function runUninit(options) {
|
|
|
442
528
|
);
|
|
443
529
|
}
|
|
444
530
|
try {
|
|
445
|
-
const envPath =
|
|
446
|
-
if (
|
|
447
|
-
const content =
|
|
448
|
-
const
|
|
449
|
-
const
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
if (
|
|
456
|
-
|
|
457
|
-
fs.unlinkSync(envPath);
|
|
458
|
-
}
|
|
459
|
-
summary.push(`${prefix}Deleted .env.local (no remaining entries)`);
|
|
531
|
+
const envPath = path2.join(projectRoot, ".env.local");
|
|
532
|
+
if (fs2.existsSync(envPath)) {
|
|
533
|
+
const content = fs2.readFileSync(envPath, "utf-8");
|
|
534
|
+
const existingKey = readEnvLocalApiKey(content);
|
|
535
|
+
const hasDevKey = isDevApiKey(existingKey);
|
|
536
|
+
let proceed = true;
|
|
537
|
+
let devKeyPath = "none";
|
|
538
|
+
if (hasDevKey) {
|
|
539
|
+
if (dryRun) {
|
|
540
|
+
devKeyPath = "dry-run-preview";
|
|
541
|
+
} else if (force) {
|
|
542
|
+
devKeyPath = "force-bypass";
|
|
460
543
|
} else {
|
|
461
|
-
|
|
462
|
-
|
|
544
|
+
const confirmed = await prompt(
|
|
545
|
+
".env.local contains a claimed Glasstrace developer API key (gt_dev_...). Removing it will require you to re-authenticate. Continue?",
|
|
546
|
+
false
|
|
547
|
+
);
|
|
548
|
+
proceed = confirmed;
|
|
549
|
+
if (confirmed) devKeyPath = "interactive-confirmed";
|
|
550
|
+
}
|
|
551
|
+
}
|
|
552
|
+
if (!proceed) {
|
|
553
|
+
warnings.push(
|
|
554
|
+
"Preserved GLASSTRACE_API_KEY in .env.local (claimed dev key; re-run with --force to remove)"
|
|
555
|
+
);
|
|
556
|
+
} else {
|
|
557
|
+
const lines = content.split("\n");
|
|
558
|
+
const filtered = lines.filter((line) => {
|
|
559
|
+
const trimmed = line.trim();
|
|
560
|
+
return !(/^\s*#?\s*GLASSTRACE_API_KEY\s*=/.test(trimmed) || /^\s*#?\s*GLASSTRACE_COVERAGE_MAP\s*=/.test(trimmed));
|
|
561
|
+
});
|
|
562
|
+
if (filtered.length !== lines.length) {
|
|
563
|
+
const result = filtered.join("\n");
|
|
564
|
+
if (result.trim().length === 0) {
|
|
565
|
+
if (!dryRun) {
|
|
566
|
+
fs2.unlinkSync(envPath);
|
|
567
|
+
}
|
|
568
|
+
summary.push(`${prefix}Deleted .env.local (no remaining entries)`);
|
|
569
|
+
} else {
|
|
570
|
+
if (!dryRun) {
|
|
571
|
+
fs2.writeFileSync(envPath, result, "utf-8");
|
|
572
|
+
}
|
|
573
|
+
let devKeyAnnotation = "";
|
|
574
|
+
if (devKeyPath === "interactive-confirmed") {
|
|
575
|
+
devKeyAnnotation = " (dev key confirmed)";
|
|
576
|
+
} else if (devKeyPath === "force-bypass") {
|
|
577
|
+
devKeyAnnotation = " (dev key removed via --force)";
|
|
578
|
+
} else if (devKeyPath === "dry-run-preview") {
|
|
579
|
+
devKeyAnnotation = " (dev key would be removed; real run would require confirmation)";
|
|
580
|
+
}
|
|
581
|
+
summary.push(
|
|
582
|
+
`${prefix}Removed GLASSTRACE entries from .env.local${devKeyAnnotation}`
|
|
583
|
+
);
|
|
463
584
|
}
|
|
464
|
-
summary.push(`${prefix}Removed GLASSTRACE entries from .env.local`);
|
|
465
585
|
}
|
|
466
586
|
}
|
|
467
587
|
}
|
|
@@ -471,9 +591,9 @@ async function runUninit(options) {
|
|
|
471
591
|
);
|
|
472
592
|
}
|
|
473
593
|
try {
|
|
474
|
-
const gitignorePath =
|
|
475
|
-
if (
|
|
476
|
-
const content =
|
|
594
|
+
const gitignorePath = path2.join(projectRoot, ".gitignore");
|
|
595
|
+
if (fs2.existsSync(gitignorePath)) {
|
|
596
|
+
const content = fs2.readFileSync(gitignorePath, "utf-8");
|
|
477
597
|
const lines = content.split("\n");
|
|
478
598
|
const mcpGitignoreEntries = /* @__PURE__ */ new Set([
|
|
479
599
|
".glasstrace/",
|
|
@@ -489,12 +609,12 @@ async function runUninit(options) {
|
|
|
489
609
|
const result = filtered.join("\n");
|
|
490
610
|
if (result.trim().length === 0) {
|
|
491
611
|
if (!dryRun) {
|
|
492
|
-
|
|
612
|
+
fs2.unlinkSync(gitignorePath);
|
|
493
613
|
}
|
|
494
614
|
summary.push(`${prefix}Deleted .gitignore (no remaining entries)`);
|
|
495
615
|
} else {
|
|
496
616
|
if (!dryRun) {
|
|
497
|
-
|
|
617
|
+
fs2.writeFileSync(gitignorePath, result, "utf-8");
|
|
498
618
|
}
|
|
499
619
|
summary.push(`${prefix}Removed Glasstrace entries from .gitignore`);
|
|
500
620
|
}
|
|
@@ -507,63 +627,63 @@ async function runUninit(options) {
|
|
|
507
627
|
}
|
|
508
628
|
try {
|
|
509
629
|
for (const configFile of MCP_CONFIG_FILES) {
|
|
510
|
-
const configPath =
|
|
511
|
-
if (!
|
|
630
|
+
const configPath = path2.join(projectRoot, configFile);
|
|
631
|
+
if (!fs2.existsSync(configPath)) {
|
|
512
632
|
continue;
|
|
513
633
|
}
|
|
514
|
-
const content =
|
|
634
|
+
const content = fs2.readFileSync(configPath, "utf-8");
|
|
515
635
|
const result = processJsonMcpConfig(content);
|
|
516
636
|
if (result.action === "deleted") {
|
|
517
637
|
if (!dryRun) {
|
|
518
|
-
|
|
638
|
+
fs2.unlinkSync(configPath);
|
|
519
639
|
}
|
|
520
640
|
summary.push(`${prefix}Deleted ${configFile}`);
|
|
521
641
|
} else if (result.action === "removed-key" && result.content !== void 0) {
|
|
522
642
|
if (!dryRun) {
|
|
523
|
-
|
|
643
|
+
fs2.writeFileSync(configPath, result.content, "utf-8");
|
|
524
644
|
}
|
|
525
645
|
summary.push(`${prefix}Removed glasstrace from ${configFile}`);
|
|
526
646
|
}
|
|
527
647
|
}
|
|
528
|
-
const codexConfigPath =
|
|
529
|
-
if (
|
|
530
|
-
const content =
|
|
648
|
+
const codexConfigPath = path2.join(projectRoot, ".codex", "config.toml");
|
|
649
|
+
if (fs2.existsSync(codexConfigPath)) {
|
|
650
|
+
const content = fs2.readFileSync(codexConfigPath, "utf-8");
|
|
531
651
|
const tomlResult = processTomlMcpConfig(content);
|
|
532
652
|
if (tomlResult.action === "deleted") {
|
|
533
653
|
if (!dryRun) {
|
|
534
|
-
|
|
654
|
+
fs2.unlinkSync(codexConfigPath);
|
|
535
655
|
}
|
|
536
656
|
summary.push(`${prefix}Deleted .codex/config.toml`);
|
|
537
657
|
} else if (tomlResult.action === "removed-section" && tomlResult.content !== void 0) {
|
|
538
658
|
if (!dryRun) {
|
|
539
|
-
|
|
659
|
+
fs2.writeFileSync(codexConfigPath, tomlResult.content, "utf-8");
|
|
540
660
|
}
|
|
541
661
|
summary.push(`${prefix}Removed glasstrace from .codex/config.toml`);
|
|
542
662
|
}
|
|
543
663
|
}
|
|
544
|
-
const hasWindsurfMarkers =
|
|
664
|
+
const hasWindsurfMarkers = fs2.existsSync(path2.join(projectRoot, ".windsurfrules")) || fs2.existsSync(path2.join(projectRoot, ".windsurf"));
|
|
545
665
|
if (hasWindsurfMarkers) {
|
|
546
|
-
const windsurfConfigPath =
|
|
666
|
+
const windsurfConfigPath = path2.join(
|
|
547
667
|
os.homedir(),
|
|
548
668
|
".codeium",
|
|
549
669
|
"windsurf",
|
|
550
670
|
"mcp_config.json"
|
|
551
671
|
);
|
|
552
|
-
if (
|
|
553
|
-
const content =
|
|
672
|
+
if (fs2.existsSync(windsurfConfigPath)) {
|
|
673
|
+
const content = fs2.readFileSync(windsurfConfigPath, "utf-8");
|
|
554
674
|
const windsurfResult = processJsonMcpConfig(content);
|
|
555
675
|
const home = os.homedir();
|
|
556
676
|
const displayPath = windsurfConfigPath.startsWith(home) ? "~" + windsurfConfigPath.slice(home.length) : windsurfConfigPath;
|
|
557
677
|
if (windsurfResult.action === "deleted") {
|
|
558
678
|
if (!dryRun) {
|
|
559
|
-
|
|
679
|
+
fs2.unlinkSync(windsurfConfigPath);
|
|
560
680
|
}
|
|
561
681
|
summary.push(
|
|
562
682
|
`${prefix}Deleted global Windsurf config (${displayPath})`
|
|
563
683
|
);
|
|
564
684
|
} else if (windsurfResult.action === "removed-key" && windsurfResult.content !== void 0) {
|
|
565
685
|
if (!dryRun) {
|
|
566
|
-
|
|
686
|
+
fs2.writeFileSync(windsurfConfigPath, windsurfResult.content, "utf-8");
|
|
567
687
|
}
|
|
568
688
|
summary.push(
|
|
569
689
|
`${prefix}Removed glasstrace from global Windsurf config (${displayPath})`
|
|
@@ -578,21 +698,21 @@ async function runUninit(options) {
|
|
|
578
698
|
}
|
|
579
699
|
try {
|
|
580
700
|
for (const infoFile of AGENT_INFO_FILES) {
|
|
581
|
-
const filePath =
|
|
582
|
-
if (!
|
|
701
|
+
const filePath = path2.join(projectRoot, infoFile);
|
|
702
|
+
if (!fs2.existsSync(filePath)) {
|
|
583
703
|
continue;
|
|
584
704
|
}
|
|
585
|
-
const content =
|
|
705
|
+
const content = fs2.readFileSync(filePath, "utf-8");
|
|
586
706
|
const result = removeMarkerSection(content);
|
|
587
707
|
if (result.removed) {
|
|
588
708
|
if (result.content.trim().length === 0) {
|
|
589
709
|
if (!dryRun) {
|
|
590
|
-
|
|
710
|
+
fs2.unlinkSync(filePath);
|
|
591
711
|
}
|
|
592
712
|
summary.push(`${prefix}Deleted ${infoFile} (only contained Glasstrace section)`);
|
|
593
713
|
} else {
|
|
594
714
|
if (!dryRun) {
|
|
595
|
-
|
|
715
|
+
fs2.writeFileSync(filePath, result.content, "utf-8");
|
|
596
716
|
}
|
|
597
717
|
summary.push(`${prefix}Removed Glasstrace section from ${infoFile}`);
|
|
598
718
|
}
|
|
@@ -621,6 +741,7 @@ async function runUninit(options) {
|
|
|
621
741
|
runUninit,
|
|
622
742
|
skipString,
|
|
623
743
|
unwrapCJSExport,
|
|
624
|
-
unwrapExport
|
|
744
|
+
unwrapExport,
|
|
745
|
+
writeShutdownMarker
|
|
625
746
|
});
|
|
626
747
|
//# sourceMappingURL=uninit.cjs.map
|