From 7a783c7c15999caaf5be36f62995a2d699fd2558 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 16 Jan 2026 11:10:17 +0000 Subject: [PATCH 1/8] Initial plan From 8abac8956fddb640f22e815ec6636a43d7881548 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 16 Jan 2026 11:16:22 +0000 Subject: [PATCH 2/8] Add ENABLE_COMPILE_CONFIG_LOGGING environment variable to control debug logs Co-authored-by: RodgeFu <6038235+RodgeFu@users.noreply.github.com> --- .../compiler/src/server/compile-service.ts | 19 ++++++++++++------- packages/compiler/src/server/constants.ts | 1 + .../src/server/entrypoint-resolver.ts | 15 ++++++++++----- packages/compiler/src/server/serverlib.ts | 9 +++++++-- 4 files changed, 30 insertions(+), 14 deletions(-) diff --git a/packages/compiler/src/server/compile-service.ts b/packages/compiler/src/server/compile-service.ts index 2c41249149e..342e009689d 100644 --- a/packages/compiler/src/server/compile-service.ts +++ b/packages/compiler/src/server/compile-service.ts @@ -19,7 +19,7 @@ import { deepClone, distinctArray } from "../utils/misc.js"; import { getLocationInYamlScript } from "../yaml/diagnostics.js"; import { parseYaml } from "../yaml/parser.js"; import { ClientConfigProvider } from "./client-config-provider.js"; -import { serverOptions } from "./constants.js"; +import { ENABLE_COMPILE_CONFIG_LOGGING, serverOptions } from "./constants.js"; import { resolveEntrypointFile } from "./entrypoint-resolver.js"; import { FileService } from "./file-service.js"; import { FileSystemCache } from "./file-system-cache.js"; @@ -90,6 +90,11 @@ export function createCompileService({ const eventListeners = new Map void | Promise>(); const compileManager = new ServerCompileManager(updateManager, compilerHost, log); let configFilePath: string | undefined; + const { getEnvironmentVariable } = serverHost; + const logDebug = + getEnvironmentVariable(ENABLE_COMPILE_CONFIG_LOGGING)?.toLowerCase() === "true" + ? log + : () => {}; return { compile, getScript, on, notifyChange, getMainFileForDocument }; @@ -129,7 +134,7 @@ export function createCompileService({ } const mainFile = await getMainFileForDocument(path); if (mainFile === undefined) { - log({ level: "debug", message: `failed to resolve main file for ${path}` }); + logDebug({ level: "debug", message: `failed to resolve main file for ${path}` }); return undefined; } if (!mainFile.endsWith(".tsp")) { @@ -137,7 +142,7 @@ export function createCompileService({ } const config = await getConfig(mainFile); configFilePath = config.filename; - log({ level: "debug", message: `config resolved`, detail: config }); + logDebug({ level: "debug", message: `config resolved`, detail: config }); const [optionsFromConfig, _] = resolveOptionsFromConfig(config, { cwd: getDirectoryPath(path), }); @@ -217,7 +222,7 @@ export function createCompileService({ ) { // If the file that changed wasn't imported by anything from the main // file, retry using the file itself as the main file. - log({ + logDebug({ level: "debug", message: `target file was not included in compiling, try to compile ${path} as main file directly`, }); @@ -246,7 +251,7 @@ export function createCompileService({ const [yamlScript] = parseYaml(await serverHost.compilerHost.readFile(configFilePath)); const target = getLocationInYamlScript(yamlScript, ["emit", emitterName], "key"); if (target.pos === 0) { - log({ + logDebug({ level: "debug", message: `Unexpected situation, can't find emitter '${emitterName}' in config file '${configFilePath}'`, }); @@ -286,7 +291,7 @@ export function createCompileService({ const lookupDir = entrypointStat.isDirectory() ? mainFile : getDirectoryPath(mainFile); const configPath = await findTypeSpecConfigPath(compilerHost, lookupDir, true); if (!configPath) { - log({ + logDebug({ level: "debug", message: `can't find path with config file, try to use default config`, }); @@ -337,7 +342,7 @@ export function createCompileService({ */ async function getMainFileForDocument(path: string) { if (path.startsWith("untitled:")) { - log({ level: "debug", message: `untitled document treated as its own main file: ${path}` }); + logDebug({ level: "debug", message: `untitled document treated as its own main file: ${path}` }); return path; } diff --git a/packages/compiler/src/server/constants.ts b/packages/compiler/src/server/constants.ts index 1bb0333bd04..e96c3610654 100644 --- a/packages/compiler/src/server/constants.ts +++ b/packages/compiler/src/server/constants.ts @@ -18,3 +18,4 @@ export const Commands = { */ export const ENABLE_SERVER_COMPILE_LOGGING = "ENABLE_SERVER_COMPILE_LOGGING"; export const ENABLE_UPDATE_MANAGER_LOGGING = "ENABLE_UPDATE_MANAGER_LOGGING"; +export const ENABLE_COMPILE_CONFIG_LOGGING = "ENABLE_COMPILE_CONFIG_LOGGING"; diff --git a/packages/compiler/src/server/entrypoint-resolver.ts b/packages/compiler/src/server/entrypoint-resolver.ts index 4865b44d4c6..134f970308d 100644 --- a/packages/compiler/src/server/entrypoint-resolver.ts +++ b/packages/compiler/src/server/entrypoint-resolver.ts @@ -2,7 +2,8 @@ import { formatDiagnostic } from "../core/logger/console-sink.js"; import { getDirectoryPath, joinPaths } from "../core/path-utils.js"; import { SystemHost, Diagnostic as TypeSpecDiagnostic } from "../core/types.js"; import { doIO, loadFile } from "../utils/io.js"; -import { resolveTspMain } from "../utils/misc.js"; +import { getEnvironmentVariable, resolveTspMain } from "../utils/misc.js"; +import { ENABLE_COMPILE_CONFIG_LOGGING } from "./constants.js"; import { FileSystemCache } from "./file-system-cache.js"; import { ServerLog } from "./types.js"; @@ -14,6 +15,10 @@ export async function resolveEntrypointFile( log: (log: ServerLog) => void, ): Promise { const options = { allowFileNotFound: true }; + const logDebug = + getEnvironmentVariable(ENABLE_COMPILE_CONFIG_LOGGING)?.toLowerCase() === "true" + ? log + : () => {}; const pathStat = await doIO(() => host.stat(path), path, logMainFileSearchDiagnostic, options); const isFilePath = pathStat?.isFile() ?? false; @@ -36,14 +41,14 @@ export async function resolveEntrypointFile( const tspMain = resolveTspMain(pkg); if (typeof tspMain === "string") { - log({ + logDebug({ level: "debug", message: `tspMain resolved from package.json (${pkgPath}) as ${tspMain}`, }); const packageJsonEntrypoint = await existingFile(dir, tspMain); if (packageJsonEntrypoint) { - log({ level: "debug", message: `entrypoint file found as ${packageJsonEntrypoint}` }); + logDebug({ level: "debug", message: `entrypoint file found as ${packageJsonEntrypoint}` }); return packageJsonEntrypoint; } } @@ -51,7 +56,7 @@ export async function resolveEntrypointFile( for (const entrypoint of entrypoints) { const candidate = await existingFile(dir, entrypoint); if (candidate) { - log({ + logDebug({ level: "debug", message: `main file found using client provided entrypoint: ${candidate}`, }); @@ -67,7 +72,7 @@ export async function resolveEntrypointFile( dir = parentDir; } - log({ level: "debug", message: `reached directory root, using '${path}' as main file` }); + logDebug({ level: "debug", message: `reached directory root, using '${path}' as main file` }); return isFilePath ? path : undefined; function logMainFileSearchDiagnostic(diagnostic: TypeSpecDiagnostic) { diff --git a/packages/compiler/src/server/serverlib.ts b/packages/compiler/src/server/serverlib.ts index 50ad2b12057..900e3858f83 100644 --- a/packages/compiler/src/server/serverlib.ts +++ b/packages/compiler/src/server/serverlib.ts @@ -104,7 +104,7 @@ import { getSemanticTokens } from "./classify.js"; import { ClientConfigProvider } from "./client-config-provider.js"; import { createCompileService } from "./compile-service.js"; import { resolveCompletion } from "./completion.js"; -import { Commands } from "./constants.js"; +import { Commands, ENABLE_COMPILE_CONFIG_LOGGING } from "./constants.js"; import { convertDiagnosticToLsp } from "./diagnostics.js"; import { createFileService } from "./file-service.js"; import { createFileSystemCache } from "./file-system-cache.js"; @@ -1138,7 +1138,7 @@ export function createServer( compilerHost, emitterProvider, linterProvider, - log, + log: logCompileConfig, }); return CompletionList.create(items); } @@ -1412,6 +1412,11 @@ export function createServer( host.log(log); } + const logCompileConfig = + host.getEnvironmentVariable(ENABLE_COMPILE_CONFIG_LOGGING)?.toLowerCase() === "true" + ? log + : () => {}; + function sendDiagnostics(document: TextDocument, diagnostics: VSDiagnostic[]) { host.sendDiagnostics({ uri: document.uri, From 9750838b8f316cd5a12c31c329fe5e028feb9264 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 16 Jan 2026 11:28:20 +0000 Subject: [PATCH 3/8] Fix JavaScript hoisting issue with logCompileConfig function Co-authored-by: RodgeFu <6038235+RodgeFu@users.noreply.github.com> --- packages/compiler/src/server/compile-service.ts | 3 +-- packages/compiler/src/server/serverlib.ts | 11 ++++++----- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/packages/compiler/src/server/compile-service.ts b/packages/compiler/src/server/compile-service.ts index 342e009689d..cb4a13b85c1 100644 --- a/packages/compiler/src/server/compile-service.ts +++ b/packages/compiler/src/server/compile-service.ts @@ -15,7 +15,7 @@ import { CompilerOptions } from "../core/options.js"; import { parse } from "../core/parser.js"; import { getBaseFileName, getDirectoryPath } from "../core/path-utils.js"; import type { CompilerHost, TypeSpecScriptNode } from "../core/types.js"; -import { deepClone, distinctArray } from "../utils/misc.js"; +import { deepClone, distinctArray, getEnvironmentVariable } from "../utils/misc.js"; import { getLocationInYamlScript } from "../yaml/diagnostics.js"; import { parseYaml } from "../yaml/parser.js"; import { ClientConfigProvider } from "./client-config-provider.js"; @@ -90,7 +90,6 @@ export function createCompileService({ const eventListeners = new Map void | Promise>(); const compileManager = new ServerCompileManager(updateManager, compilerHost, log); let configFilePath: string | undefined; - const { getEnvironmentVariable } = serverHost; const logDebug = getEnvironmentVariable(ENABLE_COMPILE_CONFIG_LOGGING)?.toLowerCase() === "true" ? log diff --git a/packages/compiler/src/server/serverlib.ts b/packages/compiler/src/server/serverlib.ts index 900e3858f83..c000298f875 100644 --- a/packages/compiler/src/server/serverlib.ts +++ b/packages/compiler/src/server/serverlib.ts @@ -99,7 +99,7 @@ import { scaffoldNewProject } from "../init/scaffold.js"; import { typespecVersion } from "../manifest.js"; import { resolveModule, ResolveModuleHost } from "../module-resolver/index.js"; import { listAllFilesInDir } from "../utils/fs-utils.js"; -import { getNormalizedRealPath, resolveTspMain } from "../utils/misc.js"; +import { getEnvironmentVariable, getNormalizedRealPath, resolveTspMain } from "../utils/misc.js"; import { getSemanticTokens } from "./classify.js"; import { ClientConfigProvider } from "./client-config-provider.js"; import { createCompileService } from "./compile-service.js"; @@ -1412,10 +1412,11 @@ export function createServer( host.log(log); } - const logCompileConfig = - host.getEnvironmentVariable(ENABLE_COMPILE_CONFIG_LOGGING)?.toLowerCase() === "true" - ? log - : () => {}; + function logCompileConfig(logMessage: ServerLog) { + if (getEnvironmentVariable(ENABLE_COMPILE_CONFIG_LOGGING)?.toLowerCase() === "true") { + log(logMessage); + } + } function sendDiagnostics(document: TextDocument, diagnostics: VSDiagnostic[]) { host.sendDiagnostics({ From 94bf93fe58e0ef4bc1349f2071175a8dc0bc83b4 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 17 Jan 2026 05:20:28 +0000 Subject: [PATCH 4/8] Refactor to use Node.js DEBUG pattern instead of individual env vars Changed from individual ENABLE_*_LOGGING environment variables to Node.js style DEBUG pattern supporting comma-separated areas and wildcards. Usage examples: DEBUG=typespec:compile DEBUG=typespec:* DEBUG=typespec:compile,typespec:config Debug areas: - typespec:compile (previously ENABLE_SERVER_COMPILE_LOGGING) - typespec:update (previously ENABLE_UPDATE_MANAGER_LOGGING) - typespec:config (previously ENABLE_COMPILE_CONFIG_LOGGING) Co-authored-by: RodgeFu <6038235+RodgeFu@users.noreply.github.com> --- .../compiler/src/server/compile-service.ts | 9 ++-- packages/compiler/src/server/constants.ts | 45 +++++++++++++++++-- .../src/server/entrypoint-resolver.ts | 9 ++-- .../src/server/server-compile-manager.ts | 9 ++-- packages/compiler/src/server/serverlib.ts | 6 +-- .../compiler/src/server/update-manager.ts | 13 +++--- 6 files changed, 60 insertions(+), 31 deletions(-) diff --git a/packages/compiler/src/server/compile-service.ts b/packages/compiler/src/server/compile-service.ts index cb4a13b85c1..2d9ff267005 100644 --- a/packages/compiler/src/server/compile-service.ts +++ b/packages/compiler/src/server/compile-service.ts @@ -15,11 +15,11 @@ import { CompilerOptions } from "../core/options.js"; import { parse } from "../core/parser.js"; import { getBaseFileName, getDirectoryPath } from "../core/path-utils.js"; import type { CompilerHost, TypeSpecScriptNode } from "../core/types.js"; -import { deepClone, distinctArray, getEnvironmentVariable } from "../utils/misc.js"; +import { deepClone, distinctArray } from "../utils/misc.js"; import { getLocationInYamlScript } from "../yaml/diagnostics.js"; import { parseYaml } from "../yaml/parser.js"; import { ClientConfigProvider } from "./client-config-provider.js"; -import { ENABLE_COMPILE_CONFIG_LOGGING, serverOptions } from "./constants.js"; +import { DebugAreas, isDebugEnabled, serverOptions } from "./constants.js"; import { resolveEntrypointFile } from "./entrypoint-resolver.js"; import { FileService } from "./file-service.js"; import { FileSystemCache } from "./file-system-cache.js"; @@ -90,10 +90,7 @@ export function createCompileService({ const eventListeners = new Map void | Promise>(); const compileManager = new ServerCompileManager(updateManager, compilerHost, log); let configFilePath: string | undefined; - const logDebug = - getEnvironmentVariable(ENABLE_COMPILE_CONFIG_LOGGING)?.toLowerCase() === "true" - ? log - : () => {}; + const logDebug = isDebugEnabled(DebugAreas.COMPILE_CONFIG) ? log : () => {}; return { compile, getScript, on, notifyChange, getMainFileForDocument }; diff --git a/packages/compiler/src/server/constants.ts b/packages/compiler/src/server/constants.ts index e96c3610654..c4cf398320e 100644 --- a/packages/compiler/src/server/constants.ts +++ b/packages/compiler/src/server/constants.ts @@ -1,4 +1,5 @@ import { CompilerOptions } from "../core/options.js"; +import { getEnvironmentVariable } from "../utils/misc.js"; export const serverOptions: CompilerOptions = { dryRun: true, @@ -14,8 +15,44 @@ export const Commands = { }; /** - * Environment variables to enable some logging when needed + * Debug areas that can be enabled via DEBUG environment variable. + * Usage: DEBUG=typespec:compile,typespec:config */ -export const ENABLE_SERVER_COMPILE_LOGGING = "ENABLE_SERVER_COMPILE_LOGGING"; -export const ENABLE_UPDATE_MANAGER_LOGGING = "ENABLE_UPDATE_MANAGER_LOGGING"; -export const ENABLE_COMPILE_CONFIG_LOGGING = "ENABLE_COMPILE_CONFIG_LOGGING"; +export const DebugAreas = { + SERVER_COMPILE: "typespec:compile", + UPDATE_MANAGER: "typespec:update", + COMPILE_CONFIG: "typespec:config", +} as const; + +/** + * Check if a debug area is enabled via the DEBUG environment variable. + * Supports Node.js DEBUG pattern with wildcards and comma-separated values. + * Examples: + * DEBUG=typespec:compile + * DEBUG=typespec:* + * DEBUG=typespec:compile,typespec:config + */ +export function isDebugEnabled(area: string): boolean { + const debug = getEnvironmentVariable("DEBUG"); + if (!debug) { + return false; + } + + const areas = debug.split(",").map((a) => a.trim()); + + return areas.some((pattern) => { + // Exact match + if (pattern === area) { + return true; + } + + // Wildcard pattern matching + if (pattern.includes("*")) { + const regexPattern = pattern.replace(/\*/g, ".*"); + const regex = new RegExp(`^${regexPattern}$`); + return regex.test(area); + } + + return false; + }); +} diff --git a/packages/compiler/src/server/entrypoint-resolver.ts b/packages/compiler/src/server/entrypoint-resolver.ts index 134f970308d..ab2162c7fc8 100644 --- a/packages/compiler/src/server/entrypoint-resolver.ts +++ b/packages/compiler/src/server/entrypoint-resolver.ts @@ -2,8 +2,8 @@ import { formatDiagnostic } from "../core/logger/console-sink.js"; import { getDirectoryPath, joinPaths } from "../core/path-utils.js"; import { SystemHost, Diagnostic as TypeSpecDiagnostic } from "../core/types.js"; import { doIO, loadFile } from "../utils/io.js"; -import { getEnvironmentVariable, resolveTspMain } from "../utils/misc.js"; -import { ENABLE_COMPILE_CONFIG_LOGGING } from "./constants.js"; +import { resolveTspMain } from "../utils/misc.js"; +import { DebugAreas, isDebugEnabled } from "./constants.js"; import { FileSystemCache } from "./file-system-cache.js"; import { ServerLog } from "./types.js"; @@ -15,10 +15,7 @@ export async function resolveEntrypointFile( log: (log: ServerLog) => void, ): Promise { const options = { allowFileNotFound: true }; - const logDebug = - getEnvironmentVariable(ENABLE_COMPILE_CONFIG_LOGGING)?.toLowerCase() === "true" - ? log - : () => {}; + const logDebug = isDebugEnabled(DebugAreas.COMPILE_CONFIG) ? log : () => {}; const pathStat = await doIO(() => host.stat(path), path, logMainFileSearchDiagnostic, options); const isFilePath = pathStat?.isFile() ?? false; diff --git a/packages/compiler/src/server/server-compile-manager.ts b/packages/compiler/src/server/server-compile-manager.ts index 552c0551893..c84168e97d2 100644 --- a/packages/compiler/src/server/server-compile-manager.ts +++ b/packages/compiler/src/server/server-compile-manager.ts @@ -9,7 +9,7 @@ import { ServerLog, } from "../index.js"; import { getEnvironmentVariable } from "../utils/misc.js"; -import { ENABLE_SERVER_COMPILE_LOGGING } from "./constants.js"; +import { DebugAreas, isDebugEnabled } from "./constants.js"; import { trackActionFunc } from "./server-track-action-task.js"; import { UpdateManager } from "./update-manager.js"; @@ -45,10 +45,9 @@ export class ServerCompileManager { private compilerHost: CompilerHost, private log: (log: ServerLog) => void, ) { - this.logDebug = - getEnvironmentVariable(ENABLE_SERVER_COMPILE_LOGGING)?.toLowerCase() === "true" - ? (msg) => this.log({ level: "debug", message: msg }) - : () => {}; + this.logDebug = isDebugEnabled(DebugAreas.SERVER_COMPILE) + ? (msg) => this.log({ level: "debug", message: msg }) + : () => {}; } async compile( diff --git a/packages/compiler/src/server/serverlib.ts b/packages/compiler/src/server/serverlib.ts index c000298f875..d8c7ac3b2e4 100644 --- a/packages/compiler/src/server/serverlib.ts +++ b/packages/compiler/src/server/serverlib.ts @@ -99,12 +99,12 @@ import { scaffoldNewProject } from "../init/scaffold.js"; import { typespecVersion } from "../manifest.js"; import { resolveModule, ResolveModuleHost } from "../module-resolver/index.js"; import { listAllFilesInDir } from "../utils/fs-utils.js"; -import { getEnvironmentVariable, getNormalizedRealPath, resolveTspMain } from "../utils/misc.js"; +import { getNormalizedRealPath, resolveTspMain } from "../utils/misc.js"; import { getSemanticTokens } from "./classify.js"; import { ClientConfigProvider } from "./client-config-provider.js"; import { createCompileService } from "./compile-service.js"; import { resolveCompletion } from "./completion.js"; -import { Commands, ENABLE_COMPILE_CONFIG_LOGGING } from "./constants.js"; +import { Commands, DebugAreas, isDebugEnabled } from "./constants.js"; import { convertDiagnosticToLsp } from "./diagnostics.js"; import { createFileService } from "./file-service.js"; import { createFileSystemCache } from "./file-system-cache.js"; @@ -1413,7 +1413,7 @@ export function createServer( } function logCompileConfig(logMessage: ServerLog) { - if (getEnvironmentVariable(ENABLE_COMPILE_CONFIG_LOGGING)?.toLowerCase() === "true") { + if (isDebugEnabled(DebugAreas.COMPILE_CONFIG)) { log(logMessage); } } diff --git a/packages/compiler/src/server/update-manager.ts b/packages/compiler/src/server/update-manager.ts index 0d650dbc359..1b88e622439 100644 --- a/packages/compiler/src/server/update-manager.ts +++ b/packages/compiler/src/server/update-manager.ts @@ -1,7 +1,7 @@ import { TextDocumentIdentifier } from "vscode-languageserver"; import { TextDocument } from "vscode-languageserver-textdocument"; import { getEnvironmentVariable } from "../utils/misc.js"; -import { ENABLE_UPDATE_MANAGER_LOGGING } from "./constants.js"; +import { DebugAreas, isDebugEnabled } from "./constants.js"; import { ServerLog } from "./types.js"; interface PendingUpdate { @@ -43,12 +43,11 @@ export class UpdateManager { log: (sl: ServerLog) => void, getDebounceDelay?: () => number, ) { - this._log = - getEnvironmentVariable(ENABLE_UPDATE_MANAGER_LOGGING)?.toLowerCase() === "true" - ? (sl: ServerLog) => { - log({ ...sl, message: `#FromUpdateManager(${this.name}): ${sl.message}` }); - } - : () => {}; + this._log = isDebugEnabled(DebugAreas.UPDATE_MANAGER) + ? (sl: ServerLog) => { + log({ ...sl, message: `#FromUpdateManager(${this.name}): ${sl.message}` }); + } + : () => {}; // Set the debounce delay function once during construction this.getDebounceDelay = getDebounceDelay ?? this.getAdaptiveDebounceDelay; From b4bcd2dbe31a5ece75a532907fd9eaa33184afca Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 17 Jan 2026 08:12:45 +0000 Subject: [PATCH 5/8] Keep original naming convention for debug areas Changed debug area names to preserve the original convention: - typespec:server_compile (was typespec:compile) - typespec:update_manager (was typespec:update) - typespec:compile_config (was typespec:config) This maintains consistency with the original ENABLE_*_LOGGING variable names. Co-authored-by: RodgeFu <6038235+RodgeFu@users.noreply.github.com> --- packages/compiler/src/server/constants.ts | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/packages/compiler/src/server/constants.ts b/packages/compiler/src/server/constants.ts index c4cf398320e..2dc109aa8ea 100644 --- a/packages/compiler/src/server/constants.ts +++ b/packages/compiler/src/server/constants.ts @@ -16,21 +16,21 @@ export const Commands = { /** * Debug areas that can be enabled via DEBUG environment variable. - * Usage: DEBUG=typespec:compile,typespec:config + * Usage: DEBUG=typespec:server_compile,typespec:compile_config */ export const DebugAreas = { - SERVER_COMPILE: "typespec:compile", - UPDATE_MANAGER: "typespec:update", - COMPILE_CONFIG: "typespec:config", + SERVER_COMPILE: "typespec:server_compile", + UPDATE_MANAGER: "typespec:update_manager", + COMPILE_CONFIG: "typespec:compile_config", } as const; /** * Check if a debug area is enabled via the DEBUG environment variable. * Supports Node.js DEBUG pattern with wildcards and comma-separated values. * Examples: - * DEBUG=typespec:compile + * DEBUG=typespec:server_compile * DEBUG=typespec:* - * DEBUG=typespec:compile,typespec:config + * DEBUG=typespec:server_compile,typespec:compile_config */ export function isDebugEnabled(area: string): boolean { const debug = getEnvironmentVariable("DEBUG"); From 451c4e0b3651cd2270a2cc1904f30c7559e12c91 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 17 Jan 2026 08:21:28 +0000 Subject: [PATCH 6/8] Refactor to use debug npm package and update launch.json comments - Added `debug` package (v4.4.0) as dependency - Added `@types/debug` as dev dependency - Replaced custom isDebugEnabled() with debug package loggers - Updated .vscode/launch.json to document DEBUG env var usage - Removed old ENABLE_*_LOGGING environment variable comments The debug package provides standard Node.js debugging with namespace support, wildcards, and better performance than the custom implementation. Co-authored-by: RodgeFu <6038235+RodgeFu@users.noreply.github.com> --- .vscode/launch.json | 8 ++- packages/compiler/package.json | 2 + .../compiler/src/server/compile-service.ts | 5 +- packages/compiler/src/server/constants.ts | 50 ++++--------------- .../src/server/entrypoint-resolver.ts | 5 +- .../src/server/server-compile-manager.ts | 5 +- packages/compiler/src/server/serverlib.ts | 4 +- .../compiler/src/server/update-manager.ts | 5 +- pnpm-lock.yaml | 6 +++ 9 files changed, 39 insertions(+), 51 deletions(-) diff --git a/.vscode/launch.json b/.vscode/launch.json index ed76356799c..a204103d10c 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -141,8 +141,12 @@ // Set the telemetry key environment variable to use if you dont want to set it in package.json //"TYPESPEC_VSCODE_TELEMETRY_KEY": "{The instrumentation key of your Application Insights}", - //"ENABLE_SERVER_COMPILE_LOGGING": "true", - //"ENABLE_UPDATE_MANAGER_LOGGING": "true", + // Enable debug logging for specific areas using DEBUG environment variable + // Examples: + // "DEBUG": "typespec:server_compile" - Enable server compilation debug logs + // "DEBUG": "typespec:*" - Enable all typespec debug logs + // "DEBUG": "typespec:server_compile,typespec:compile_config" - Enable multiple areas + //"DEBUG": "typespec:server_compile,typespec:update_manager,typespec:compile_config", //"ENABLE_LM_LOGGING": "true", "TYPESPEC_SERVER_NODE_OPTIONS": "--nolazy --inspect-brk=4242", diff --git a/packages/compiler/package.json b/packages/compiler/package.json index bd834faa5fa..cf791847742 100644 --- a/packages/compiler/package.json +++ b/packages/compiler/package.json @@ -109,6 +109,7 @@ "@inquirer/prompts": "^8.0.1", "ajv": "~8.17.1", "change-case": "~5.4.4", + "debug": "~4.4.0", "env-paths": "^3.0.0", "globby": "~16.0.0", "is-unicode-supported": "^2.1.0", @@ -125,6 +126,7 @@ }, "devDependencies": { "@types/babel__code-frame": "~7.0.6", + "@types/debug": "~4.1.12", "@types/mustache": "~4.2.5", "@types/node": "~25.0.2", "@types/semver": "^7.5.8", diff --git a/packages/compiler/src/server/compile-service.ts b/packages/compiler/src/server/compile-service.ts index 2d9ff267005..8db4db2da72 100644 --- a/packages/compiler/src/server/compile-service.ts +++ b/packages/compiler/src/server/compile-service.ts @@ -19,7 +19,7 @@ import { deepClone, distinctArray } from "../utils/misc.js"; import { getLocationInYamlScript } from "../yaml/diagnostics.js"; import { parseYaml } from "../yaml/parser.js"; import { ClientConfigProvider } from "./client-config-provider.js"; -import { DebugAreas, isDebugEnabled, serverOptions } from "./constants.js"; +import { debugLoggers, serverOptions } from "./constants.js"; import { resolveEntrypointFile } from "./entrypoint-resolver.js"; import { FileService } from "./file-service.js"; import { FileSystemCache } from "./file-system-cache.js"; @@ -90,7 +90,8 @@ export function createCompileService({ const eventListeners = new Map void | Promise>(); const compileManager = new ServerCompileManager(updateManager, compilerHost, log); let configFilePath: string | undefined; - const logDebug = isDebugEnabled(DebugAreas.COMPILE_CONFIG) ? log : () => {}; + const debug = debugLoggers.compileConfig; + const logDebug = debug.enabled ? log : () => {}; return { compile, getScript, on, notifyChange, getMainFileForDocument }; diff --git a/packages/compiler/src/server/constants.ts b/packages/compiler/src/server/constants.ts index 2dc109aa8ea..70e99a7b2a8 100644 --- a/packages/compiler/src/server/constants.ts +++ b/packages/compiler/src/server/constants.ts @@ -1,5 +1,5 @@ import { CompilerOptions } from "../core/options.js"; -import { getEnvironmentVariable } from "../utils/misc.js"; +import createDebug from "debug"; export const serverOptions: CompilerOptions = { dryRun: true, @@ -15,44 +15,16 @@ export const Commands = { }; /** - * Debug areas that can be enabled via DEBUG environment variable. + * Debug loggers for different areas. Can be enabled via DEBUG environment variable. * Usage: DEBUG=typespec:server_compile,typespec:compile_config - */ -export const DebugAreas = { - SERVER_COMPILE: "typespec:server_compile", - UPDATE_MANAGER: "typespec:update_manager", - COMPILE_CONFIG: "typespec:compile_config", -} as const; - -/** - * Check if a debug area is enabled via the DEBUG environment variable. - * Supports Node.js DEBUG pattern with wildcards and comma-separated values. + * * Examples: - * DEBUG=typespec:server_compile - * DEBUG=typespec:* - * DEBUG=typespec:server_compile,typespec:compile_config + * DEBUG=typespec:server_compile - Enable server compilation debug logs + * DEBUG=typespec:* - Enable all typespec debug logs + * DEBUG=typespec:server_compile,typespec:compile_config - Enable multiple areas */ -export function isDebugEnabled(area: string): boolean { - const debug = getEnvironmentVariable("DEBUG"); - if (!debug) { - return false; - } - - const areas = debug.split(",").map((a) => a.trim()); - - return areas.some((pattern) => { - // Exact match - if (pattern === area) { - return true; - } - - // Wildcard pattern matching - if (pattern.includes("*")) { - const regexPattern = pattern.replace(/\*/g, ".*"); - const regex = new RegExp(`^${regexPattern}$`); - return regex.test(area); - } - - return false; - }); -} +export const debugLoggers = { + serverCompile: createDebug("typespec:server_compile"), + updateManager: createDebug("typespec:update_manager"), + compileConfig: createDebug("typespec:compile_config"), +} as const; diff --git a/packages/compiler/src/server/entrypoint-resolver.ts b/packages/compiler/src/server/entrypoint-resolver.ts index ab2162c7fc8..0885021f3e2 100644 --- a/packages/compiler/src/server/entrypoint-resolver.ts +++ b/packages/compiler/src/server/entrypoint-resolver.ts @@ -3,7 +3,7 @@ import { getDirectoryPath, joinPaths } from "../core/path-utils.js"; import { SystemHost, Diagnostic as TypeSpecDiagnostic } from "../core/types.js"; import { doIO, loadFile } from "../utils/io.js"; import { resolveTspMain } from "../utils/misc.js"; -import { DebugAreas, isDebugEnabled } from "./constants.js"; +import { debugLoggers } from "./constants.js"; import { FileSystemCache } from "./file-system-cache.js"; import { ServerLog } from "./types.js"; @@ -15,7 +15,8 @@ export async function resolveEntrypointFile( log: (log: ServerLog) => void, ): Promise { const options = { allowFileNotFound: true }; - const logDebug = isDebugEnabled(DebugAreas.COMPILE_CONFIG) ? log : () => {}; + const debug = debugLoggers.compileConfig; + const logDebug = debug.enabled ? log : () => {}; const pathStat = await doIO(() => host.stat(path), path, logMainFileSearchDiagnostic, options); const isFilePath = pathStat?.isFile() ?? false; diff --git a/packages/compiler/src/server/server-compile-manager.ts b/packages/compiler/src/server/server-compile-manager.ts index c84168e97d2..d600c4825d6 100644 --- a/packages/compiler/src/server/server-compile-manager.ts +++ b/packages/compiler/src/server/server-compile-manager.ts @@ -9,7 +9,7 @@ import { ServerLog, } from "../index.js"; import { getEnvironmentVariable } from "../utils/misc.js"; -import { DebugAreas, isDebugEnabled } from "./constants.js"; +import { debugLoggers } from "./constants.js"; import { trackActionFunc } from "./server-track-action-task.js"; import { UpdateManager } from "./update-manager.js"; @@ -45,7 +45,8 @@ export class ServerCompileManager { private compilerHost: CompilerHost, private log: (log: ServerLog) => void, ) { - this.logDebug = isDebugEnabled(DebugAreas.SERVER_COMPILE) + const debug = debugLoggers.serverCompile; + this.logDebug = debug.enabled ? (msg) => this.log({ level: "debug", message: msg }) : () => {}; } diff --git a/packages/compiler/src/server/serverlib.ts b/packages/compiler/src/server/serverlib.ts index d8c7ac3b2e4..ea6ee86823b 100644 --- a/packages/compiler/src/server/serverlib.ts +++ b/packages/compiler/src/server/serverlib.ts @@ -104,7 +104,7 @@ import { getSemanticTokens } from "./classify.js"; import { ClientConfigProvider } from "./client-config-provider.js"; import { createCompileService } from "./compile-service.js"; import { resolveCompletion } from "./completion.js"; -import { Commands, DebugAreas, isDebugEnabled } from "./constants.js"; +import { Commands, debugLoggers } from "./constants.js"; import { convertDiagnosticToLsp } from "./diagnostics.js"; import { createFileService } from "./file-service.js"; import { createFileSystemCache } from "./file-system-cache.js"; @@ -1413,7 +1413,7 @@ export function createServer( } function logCompileConfig(logMessage: ServerLog) { - if (isDebugEnabled(DebugAreas.COMPILE_CONFIG)) { + if (debugLoggers.compileConfig.enabled) { log(logMessage); } } diff --git a/packages/compiler/src/server/update-manager.ts b/packages/compiler/src/server/update-manager.ts index 1b88e622439..d3e1aac41e7 100644 --- a/packages/compiler/src/server/update-manager.ts +++ b/packages/compiler/src/server/update-manager.ts @@ -1,7 +1,7 @@ import { TextDocumentIdentifier } from "vscode-languageserver"; import { TextDocument } from "vscode-languageserver-textdocument"; import { getEnvironmentVariable } from "../utils/misc.js"; -import { DebugAreas, isDebugEnabled } from "./constants.js"; +import { debugLoggers } from "./constants.js"; import { ServerLog } from "./types.js"; interface PendingUpdate { @@ -43,7 +43,8 @@ export class UpdateManager { log: (sl: ServerLog) => void, getDebounceDelay?: () => number, ) { - this._log = isDebugEnabled(DebugAreas.UPDATE_MANAGER) + const debug = debugLoggers.updateManager; + this._log = debug.enabled ? (sl: ServerLog) => { log({ ...sl, message: `#FromUpdateManager(${this.name}): ${sl.message}` }); } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 8af70bccd41..5dc7cd89b01 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -314,6 +314,9 @@ importers: change-case: specifier: ~5.4.4 version: 5.4.4 + debug: + specifier: ~4.4.0 + version: 4.4.3(supports-color@8.1.1) env-paths: specifier: ^3.0.0 version: 3.0.0 @@ -357,6 +360,9 @@ importers: '@types/babel__code-frame': specifier: ~7.0.6 version: 7.0.6 + '@types/debug': + specifier: ~4.1.12 + version: 4.1.12 '@types/mustache': specifier: ~4.2.5 version: 4.2.6 From ca30a7456fd321bd6a15ca6520c33bacb298c964 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 19 Jan 2026 06:20:02 +0000 Subject: [PATCH 7/8] Add documentation comment for ENABLE_LM_LOGGING in launch.json Added a comment to clarify that ENABLE_LM_LOGGING is separate from the DEBUG environment variable logging system and is used specifically for Language Model logging in the typespec-vscode extension. Co-authored-by: RodgeFu <6038235+RodgeFu@users.noreply.github.com> --- .vscode/launch.json | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.vscode/launch.json b/.vscode/launch.json index a204103d10c..fb092407602 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -147,6 +147,8 @@ // "DEBUG": "typespec:*" - Enable all typespec debug logs // "DEBUG": "typespec:server_compile,typespec:compile_config" - Enable multiple areas //"DEBUG": "typespec:server_compile,typespec:update_manager,typespec:compile_config", + + // Enable Language Model logging (separate from DEBUG logging) //"ENABLE_LM_LOGGING": "true", "TYPESPEC_SERVER_NODE_OPTIONS": "--nolazy --inspect-brk=4242", From 42c1d4fb0cbbf70ef17add28010ba8ea60e3f3ad Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 19 Jan 2026 06:29:34 +0000 Subject: [PATCH 8/8] Refactor typespec-vscode to use debug package for LM logging - Added `debug@~4.4.0` as dependency to typespec-vscode - Added `@types/debug@~4.1.12` as dev dependency - Replaced ENABLE_LM_LOGGING with debug logger (typespec:lm) - Updated const.ts to export debugLoggers.lm - Updated language-model.ts to use debugLoggers.lm.enabled - Updated .vscode/launch.json to document DEBUG=typespec:lm usage Language Model logging now follows the same DEBUG pattern as compiler logging, enabling it with DEBUG=typespec:lm or DEBUG=typespec:* Co-authored-by: RodgeFu <6038235+RodgeFu@users.noreply.github.com> --- .vscode/launch.json | 6 ++---- packages/typespec-vscode/package.json | 6 +++++- packages/typespec-vscode/src/const.ts | 11 ++++++++++- packages/typespec-vscode/src/lm/language-model.ts | 5 +++-- pnpm-lock.yaml | 7 +++++++ 5 files changed, 27 insertions(+), 8 deletions(-) diff --git a/.vscode/launch.json b/.vscode/launch.json index fb092407602..384e8a86605 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -144,12 +144,10 @@ // Enable debug logging for specific areas using DEBUG environment variable // Examples: // "DEBUG": "typespec:server_compile" - Enable server compilation debug logs + // "DEBUG": "typespec:lm" - Enable Language Model debug logs // "DEBUG": "typespec:*" - Enable all typespec debug logs // "DEBUG": "typespec:server_compile,typespec:compile_config" - Enable multiple areas - //"DEBUG": "typespec:server_compile,typespec:update_manager,typespec:compile_config", - - // Enable Language Model logging (separate from DEBUG logging) - //"ENABLE_LM_LOGGING": "true", + //"DEBUG": "typespec:server_compile,typespec:update_manager,typespec:compile_config,typespec:lm", "TYPESPEC_SERVER_NODE_OPTIONS": "--nolazy --inspect-brk=4242", "TYPESPEC_DEVELOPMENT_MODE": "true" diff --git a/packages/typespec-vscode/package.json b/packages/typespec-vscode/package.json index 7fb914d9b4f..f31f8da8b3a 100644 --- a/packages/typespec-vscode/package.json +++ b/packages/typespec-vscode/package.json @@ -309,6 +309,10 @@ "vitest": "^4.0.15", "vscode-languageclient": "~9.0.1", "which": "^6.0.0", - "yaml": "~2.8.2" + "yaml": "~2.8.2", + "@types/debug": "~4.1.12" + }, + "dependencies": { + "debug": "~4.4.0" } } diff --git a/packages/typespec-vscode/src/const.ts b/packages/typespec-vscode/src/const.ts index 39df7d9279c..e0726239f8e 100644 --- a/packages/typespec-vscode/src/const.ts +++ b/packages/typespec-vscode/src/const.ts @@ -1,5 +1,14 @@ +import createDebug from "debug"; + export const StartFileName = "main.tsp"; export const TspConfigFileName = "tspconfig.yaml"; export const EmptyGuid = "00000000-0000-0000-0000-000000000000"; -export const ENABLE_LM_LOGGING = "ENABLE_LM_LOGGING"; +/** + * Debug logger for Language Model operations. + * Can be enabled via DEBUG environment variable. + * Usage: DEBUG=typespec:lm + */ +export const debugLoggers = { + lm: createDebug("typespec:lm"), +} as const; diff --git a/packages/typespec-vscode/src/lm/language-model.ts b/packages/typespec-vscode/src/lm/language-model.ts index 3dfb8d581d6..064358199f3 100644 --- a/packages/typespec-vscode/src/lm/language-model.ts +++ b/packages/typespec-vscode/src/lm/language-model.ts @@ -1,6 +1,6 @@ import { inspect } from "util"; import { LanguageModelChat, LanguageModelChatMessage, lm } from "vscode"; -import { ENABLE_LM_LOGGING } from "../const"; +import { debugLoggers } from "../const"; import logger, { LogItem } from "../log/logger"; import { RetryResult, runWithRetry, runWithTimingLog } from "../utils"; @@ -23,7 +23,8 @@ export async function sendLmChatRequest( /** Only for logging purpose */ id?: string, ): Promise { - const logEnabled = process.env[ENABLE_LM_LOGGING] === "true"; + const debug = debugLoggers.lm; + const logEnabled = debug.enabled; const lmLog = (item: LogItem) => { if (logEnabled || item.level === "error" || item.level === "warning") { logger.log( diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 5dc7cd89b01..eaa178f7ede 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -2361,10 +2361,17 @@ importers: version: link:../typespec-vscode packages/typespec-vscode: + dependencies: + debug: + specifier: ~4.4.0 + version: 4.4.3(supports-color@8.1.1) devDependencies: '@types/cross-spawn': specifier: ~6.0.6 version: 6.0.6 + '@types/debug': + specifier: ~4.1.12 + version: 4.1.12 '@types/mocha': specifier: ^10.0.9 version: 10.0.10