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 01/11] 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 02/11] 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 03/11] 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 04/11] 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 05/11] 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 06/11] 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 07/11] 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 08/11] 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 From 3b2668fbb370cdeee520cb56e4052ad085d3a5b2 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 21 Jan 2026 03:01:06 +0000 Subject: [PATCH 09/11] Remove unnecessary debug variable in language-model.ts Simplified the code by directly accessing debugLoggers.lm.enabled instead of storing it in an intermediate 'debug' variable that was only used once. Co-authored-by: RodgeFu <6038235+RodgeFu@users.noreply.github.com> --- packages/typespec-vscode/src/lm/language-model.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/packages/typespec-vscode/src/lm/language-model.ts b/packages/typespec-vscode/src/lm/language-model.ts index 064358199f3..a0a186bf1d0 100644 --- a/packages/typespec-vscode/src/lm/language-model.ts +++ b/packages/typespec-vscode/src/lm/language-model.ts @@ -23,8 +23,7 @@ export async function sendLmChatRequest( /** Only for logging purpose */ id?: string, ): Promise { - const debug = debugLoggers.lm; - const logEnabled = debug.enabled; + const logEnabled = debugLoggers.lm.enabled; const lmLog = (item: LogItem) => { if (logEnabled || item.level === "error" || item.level === "warning") { logger.log( From fa371948b085662c7e0290762be21ad9b7ef2f25 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 21 Jan 2026 03:24:24 +0000 Subject: [PATCH 10/11] Revert tspconfig completion to use regular log function Changed provideTspconfigCompletionItems to use 'log' instead of 'logCompileConfig'. The tspconfig completion doesn't need compile config debug logging - it should use the regular log function. Co-authored-by: RodgeFu <6038235+RodgeFu@users.noreply.github.com> --- packages/compiler/src/server/serverlib.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/compiler/src/server/serverlib.ts b/packages/compiler/src/server/serverlib.ts index ea6ee86823b..3ab357174f0 100644 --- a/packages/compiler/src/server/serverlib.ts +++ b/packages/compiler/src/server/serverlib.ts @@ -1138,7 +1138,7 @@ export function createServer( compilerHost, emitterProvider, linterProvider, - log: logCompileConfig, + log, }); return CompletionList.create(items); } From 58fb6953fa04c49cf84eef671b729fb7ab014d23 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 21 Jan 2026 05:30:49 +0000 Subject: [PATCH 11/11] Remove unused logCompileConfig function The logCompileConfig function was no longer used after reverting tspconfig completion to use the regular log function. Removed the orphaned function to clean up the code. Co-authored-by: RodgeFu <6038235+RodgeFu@users.noreply.github.com> --- packages/compiler/src/server/serverlib.ts | 6 ------ 1 file changed, 6 deletions(-) diff --git a/packages/compiler/src/server/serverlib.ts b/packages/compiler/src/server/serverlib.ts index 3ab357174f0..853eb96d140 100644 --- a/packages/compiler/src/server/serverlib.ts +++ b/packages/compiler/src/server/serverlib.ts @@ -1412,12 +1412,6 @@ export function createServer( host.log(log); } - function logCompileConfig(logMessage: ServerLog) { - if (debugLoggers.compileConfig.enabled) { - log(logMessage); - } - } - function sendDiagnostics(document: TextDocument, diagnostics: VSDiagnostic[]) { host.sendDiagnostics({ uri: document.uri,