mirror of
https://github.com/QwenLM/qwen-code.git
synced 2025-12-19 09:33:53 +00:00
chore(vscode-ide-companion): revert some log util, will continue next time
This commit is contained in:
@@ -8,11 +8,7 @@ import * as vscode from 'vscode';
|
||||
import { IDEServer } from './ide-server.js';
|
||||
import semver from 'semver';
|
||||
import { DiffContentProvider, DiffManager } from './diff-manager.js';
|
||||
import {
|
||||
createLogger,
|
||||
getConsoleLogger,
|
||||
initSharedConsoleLogger,
|
||||
} from './utils/logger.js';
|
||||
import { createLogger } from './utils/logger.js';
|
||||
import {
|
||||
detectIdeFromEnv,
|
||||
IDE_DEFINITIONS,
|
||||
@@ -109,8 +105,6 @@ async function checkForUpdates(
|
||||
|
||||
export async function activate(context: vscode.ExtensionContext) {
|
||||
logger = vscode.window.createOutputChannel('Qwen Code Companion');
|
||||
initSharedConsoleLogger(context);
|
||||
const consoleLog = getConsoleLogger();
|
||||
log = createLogger(context, logger);
|
||||
log('Extension activated');
|
||||
|
||||
@@ -148,18 +142,18 @@ export async function activate(context: vscode.ExtensionContext) {
|
||||
webviewPanel: vscode.WebviewPanel,
|
||||
state: unknown,
|
||||
) {
|
||||
consoleLog(
|
||||
console.log(
|
||||
'[Extension] Deserializing WebView panel with state:',
|
||||
state,
|
||||
);
|
||||
|
||||
// Create a new provider for the restored panel
|
||||
const provider = createWebViewProvider();
|
||||
consoleLog('[Extension] Provider created for deserialization');
|
||||
console.log('[Extension] Provider created for deserialization');
|
||||
|
||||
// Restore state if available BEFORE restoring the panel
|
||||
if (state && typeof state === 'object') {
|
||||
consoleLog('[Extension] Restoring state:', state);
|
||||
console.log('[Extension] Restoring state:', state);
|
||||
provider.restoreState(
|
||||
state as {
|
||||
conversationId: string | null;
|
||||
@@ -167,11 +161,11 @@ export async function activate(context: vscode.ExtensionContext) {
|
||||
},
|
||||
);
|
||||
} else {
|
||||
consoleLog('[Extension] No state to restore or invalid state');
|
||||
console.log('[Extension] No state to restore or invalid state');
|
||||
}
|
||||
|
||||
await provider.restorePanel(webviewPanel);
|
||||
consoleLog('[Extension] Panel restore completed');
|
||||
console.log('[Extension] Panel restore completed');
|
||||
|
||||
log('WebView panel restored from serialization');
|
||||
},
|
||||
@@ -212,6 +206,7 @@ export async function activate(context: vscode.ExtensionContext) {
|
||||
} catch (err) {
|
||||
console.warn('[Extension] Auto-allow on diff.accept failed:', err);
|
||||
}
|
||||
console.log('[Extension] Diff accepted');
|
||||
}),
|
||||
vscode.commands.registerCommand('qwen.diff.cancel', (uri?: vscode.Uri) => {
|
||||
const docUri = uri ?? vscode.window.activeTextEditor?.document.uri;
|
||||
@@ -228,6 +223,7 @@ export async function activate(context: vscode.ExtensionContext) {
|
||||
} catch (err) {
|
||||
console.warn('[Extension] Auto-reject on diff.cancel failed:', err);
|
||||
}
|
||||
console.log('[Extension] Diff cancelled');
|
||||
})),
|
||||
vscode.commands.registerCommand('qwen.diff.closeAll', async () => {
|
||||
try {
|
||||
|
||||
@@ -31,6 +31,7 @@ export class AcpConnection {
|
||||
private child: ChildProcess | null = null;
|
||||
private pendingRequests = new Map<number, PendingRequest<unknown>>();
|
||||
private nextRequestId = { value: 0 };
|
||||
|
||||
// Deduplicate concurrent authenticate calls (across retry paths)
|
||||
private static authInFlight: Promise<AcpResponse> | null = null;
|
||||
// Remember the working dir provided at connect() so later ACP calls
|
||||
|
||||
@@ -5,7 +5,6 @@
|
||||
*/
|
||||
|
||||
import type * as vscode from 'vscode';
|
||||
import { createConsoleLogger, getConsoleLogger } from '../utils/logger.js';
|
||||
|
||||
interface AuthState {
|
||||
isAuthenticated: boolean;
|
||||
@@ -22,7 +21,6 @@ export class AuthStateManager {
|
||||
private static context: vscode.ExtensionContext | null = null;
|
||||
private static readonly AUTH_STATE_KEY = 'qwen.authState';
|
||||
private static readonly AUTH_CACHE_DURATION = 24 * 60 * 60 * 1000; // 24 hours
|
||||
private static consoleLog: (...args: unknown[]) => void = getConsoleLogger();
|
||||
// Deduplicate concurrent auth flows (e.g., multiple tabs prompting login)
|
||||
private static authFlowInFlight: Promise<unknown> | null = null;
|
||||
private constructor() {}
|
||||
@@ -38,10 +36,6 @@ export class AuthStateManager {
|
||||
// If a context is provided, update the static context
|
||||
if (context) {
|
||||
AuthStateManager.context = context;
|
||||
AuthStateManager.consoleLog = createConsoleLogger(
|
||||
context,
|
||||
'AuthStateManager',
|
||||
);
|
||||
}
|
||||
|
||||
return AuthStateManager.instance;
|
||||
@@ -76,19 +70,17 @@ export class AuthStateManager {
|
||||
const state = await this.getAuthState();
|
||||
|
||||
if (!state) {
|
||||
AuthStateManager.consoleLog(
|
||||
'[AuthStateManager] No cached auth state found',
|
||||
);
|
||||
console.log('[AuthStateManager] No cached auth state found');
|
||||
return false;
|
||||
}
|
||||
|
||||
AuthStateManager.consoleLog('[AuthStateManager] Found cached auth state:', {
|
||||
console.log('[AuthStateManager] Found cached auth state:', {
|
||||
workingDir: state.workingDir,
|
||||
authMethod: state.authMethod,
|
||||
timestamp: new Date(state.timestamp).toISOString(),
|
||||
isAuthenticated: state.isAuthenticated,
|
||||
});
|
||||
AuthStateManager.consoleLog('[AuthStateManager] Checking against:', {
|
||||
console.log('[AuthStateManager] Checking against:', {
|
||||
workingDir,
|
||||
authMethod,
|
||||
});
|
||||
@@ -99,8 +91,8 @@ export class AuthStateManager {
|
||||
now - state.timestamp > AuthStateManager.AUTH_CACHE_DURATION;
|
||||
|
||||
if (isExpired) {
|
||||
AuthStateManager.consoleLog('[AuthStateManager] Cached auth expired');
|
||||
AuthStateManager.consoleLog(
|
||||
console.log('[AuthStateManager] Cached auth expired');
|
||||
console.log(
|
||||
'[AuthStateManager] Cache age:',
|
||||
Math.floor((now - state.timestamp) / 1000 / 60),
|
||||
'minutes',
|
||||
@@ -114,29 +106,15 @@ export class AuthStateManager {
|
||||
state.workingDir === workingDir && state.authMethod === authMethod;
|
||||
|
||||
if (!isSameContext) {
|
||||
AuthStateManager.consoleLog(
|
||||
'[AuthStateManager] Working dir or auth method changed',
|
||||
);
|
||||
AuthStateManager.consoleLog(
|
||||
'[AuthStateManager] Cached workingDir:',
|
||||
state.workingDir,
|
||||
);
|
||||
AuthStateManager.consoleLog(
|
||||
'[AuthStateManager] Current workingDir:',
|
||||
workingDir,
|
||||
);
|
||||
AuthStateManager.consoleLog(
|
||||
'[AuthStateManager] Cached authMethod:',
|
||||
state.authMethod,
|
||||
);
|
||||
AuthStateManager.consoleLog(
|
||||
'[AuthStateManager] Current authMethod:',
|
||||
authMethod,
|
||||
);
|
||||
console.log('[AuthStateManager] Working dir or auth method changed');
|
||||
console.log('[AuthStateManager] Cached workingDir:', state.workingDir);
|
||||
console.log('[AuthStateManager] Current workingDir:', workingDir);
|
||||
console.log('[AuthStateManager] Cached authMethod:', state.authMethod);
|
||||
console.log('[AuthStateManager] Current authMethod:', authMethod);
|
||||
return false;
|
||||
}
|
||||
|
||||
AuthStateManager.consoleLog('[AuthStateManager] Valid cached auth found');
|
||||
console.log('[AuthStateManager] Valid cached auth found');
|
||||
return state.isAuthenticated;
|
||||
}
|
||||
|
||||
@@ -146,10 +124,7 @@ export class AuthStateManager {
|
||||
*/
|
||||
async debugAuthState(): Promise<void> {
|
||||
const state = await this.getAuthState();
|
||||
AuthStateManager.consoleLog(
|
||||
'[AuthStateManager] DEBUG - Current auth state:',
|
||||
state,
|
||||
);
|
||||
console.log('[AuthStateManager] DEBUG - Current auth state:', state);
|
||||
|
||||
if (state) {
|
||||
const now = Date.now();
|
||||
@@ -157,16 +132,9 @@ export class AuthStateManager {
|
||||
const isExpired =
|
||||
now - state.timestamp > AuthStateManager.AUTH_CACHE_DURATION;
|
||||
|
||||
AuthStateManager.consoleLog(
|
||||
'[AuthStateManager] DEBUG - Auth state age:',
|
||||
age,
|
||||
'minutes',
|
||||
);
|
||||
AuthStateManager.consoleLog(
|
||||
'[AuthStateManager] DEBUG - Auth state expired:',
|
||||
isExpired,
|
||||
);
|
||||
AuthStateManager.consoleLog(
|
||||
console.log('[AuthStateManager] DEBUG - Auth state age:', age, 'minutes');
|
||||
console.log('[AuthStateManager] DEBUG - Auth state expired:', isExpired);
|
||||
console.log(
|
||||
'[AuthStateManager] DEBUG - Auth state valid:',
|
||||
state.isAuthenticated,
|
||||
);
|
||||
@@ -191,7 +159,7 @@ export class AuthStateManager {
|
||||
timestamp: Date.now(),
|
||||
};
|
||||
|
||||
AuthStateManager.consoleLog('[AuthStateManager] Saving auth state:', {
|
||||
console.log('[AuthStateManager] Saving auth state:', {
|
||||
workingDir,
|
||||
authMethod,
|
||||
timestamp: new Date(state.timestamp).toISOString(),
|
||||
@@ -201,14 +169,11 @@ export class AuthStateManager {
|
||||
AuthStateManager.AUTH_STATE_KEY,
|
||||
state,
|
||||
);
|
||||
AuthStateManager.consoleLog('[AuthStateManager] Auth state saved');
|
||||
console.log('[AuthStateManager] Auth state saved');
|
||||
|
||||
// Verify the state was saved correctly
|
||||
const savedState = await this.getAuthState();
|
||||
AuthStateManager.consoleLog(
|
||||
'[AuthStateManager] Verified saved state:',
|
||||
savedState,
|
||||
);
|
||||
console.log('[AuthStateManager] Verified saved state:', savedState);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -222,9 +187,9 @@ export class AuthStateManager {
|
||||
);
|
||||
}
|
||||
|
||||
AuthStateManager.consoleLog('[AuthStateManager] Clearing auth state');
|
||||
console.log('[AuthStateManager] Clearing auth state');
|
||||
const currentState = await this.getAuthState();
|
||||
AuthStateManager.consoleLog(
|
||||
console.log(
|
||||
'[AuthStateManager] Current state before clearing:',
|
||||
currentState,
|
||||
);
|
||||
@@ -233,14 +198,11 @@ export class AuthStateManager {
|
||||
AuthStateManager.AUTH_STATE_KEY,
|
||||
undefined,
|
||||
);
|
||||
AuthStateManager.consoleLog('[AuthStateManager] Auth state cleared');
|
||||
console.log('[AuthStateManager] Auth state cleared');
|
||||
|
||||
// Verify the state was cleared
|
||||
const newState = await this.getAuthState();
|
||||
AuthStateManager.consoleLog(
|
||||
'[AuthStateManager] State after clearing:',
|
||||
newState,
|
||||
);
|
||||
console.log('[AuthStateManager] State after clearing:', newState);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -249,15 +211,17 @@ export class AuthStateManager {
|
||||
private async getAuthState(): Promise<AuthState | undefined> {
|
||||
// Ensure we have a valid context
|
||||
if (!AuthStateManager.context) {
|
||||
AuthStateManager.consoleLog(
|
||||
console.log(
|
||||
'[AuthStateManager] No context available for getting auth state',
|
||||
);
|
||||
return undefined;
|
||||
}
|
||||
|
||||
return AuthStateManager.context.globalState.get<AuthState>(
|
||||
const a = AuthStateManager.context.globalState.get<AuthState>(
|
||||
AuthStateManager.AUTH_STATE_KEY,
|
||||
);
|
||||
console.log('[AuthStateManager] Auth state:', a);
|
||||
return a;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -23,7 +23,6 @@ import { QwenSessionUpdateHandler } from './qwenSessionUpdateHandler.js';
|
||||
import { CliContextManager } from '../cli/cliContextManager.js';
|
||||
import { authMethod } from '../types/acpTypes.js';
|
||||
import { MIN_CLI_VERSION_FOR_SESSION_METHODS } from '../cli/cliVersionManager.js';
|
||||
import { getConsoleLogger } from '../utils/logger.js';
|
||||
|
||||
export type { ChatMessage, PlanEntry, ToolCallUpdateData };
|
||||
|
||||
@@ -51,10 +50,8 @@ export class QwenAgentManager {
|
||||
|
||||
// Callback storage
|
||||
private callbacks: QwenAgentCallbacks = {};
|
||||
private consoleLog: (...args: unknown[]) => void;
|
||||
|
||||
constructor(consoleLogger = getConsoleLogger()) {
|
||||
this.consoleLog = consoleLogger;
|
||||
constructor() {
|
||||
this.connection = new AcpConnection();
|
||||
this.sessionReader = new QwenSessionReader();
|
||||
this.sessionManager = new QwenSessionManager();
|
||||
@@ -81,7 +78,7 @@ export class QwenAgentManager {
|
||||
).update;
|
||||
const text = update?.content?.text || '';
|
||||
if (update?.sessionUpdate === 'user_message_chunk' && text) {
|
||||
this.consoleLog(
|
||||
console.log(
|
||||
'[QwenAgentManager] Rehydration: routing user message chunk',
|
||||
);
|
||||
this.callbacks.onMessage?.({
|
||||
@@ -92,7 +89,7 @@ export class QwenAgentManager {
|
||||
return;
|
||||
}
|
||||
if (update?.sessionUpdate === 'agent_message_chunk' && text) {
|
||||
this.consoleLog(
|
||||
console.log(
|
||||
'[QwenAgentManager] Rehydration: routing agent message chunk',
|
||||
);
|
||||
this.callbacks.onMessage?.({
|
||||
@@ -103,7 +100,7 @@ export class QwenAgentManager {
|
||||
return;
|
||||
}
|
||||
// For other types during rehydration, fall through to normal handler
|
||||
this.consoleLog(
|
||||
console.log(
|
||||
'[QwenAgentManager] Rehydration: non-text update, forwarding to handler',
|
||||
);
|
||||
}
|
||||
@@ -262,7 +259,7 @@ export class QwenAgentManager {
|
||||
* @returns Session list
|
||||
*/
|
||||
async getSessionList(): Promise<Array<Record<string, unknown>>> {
|
||||
this.consoleLog(
|
||||
console.log(
|
||||
'[QwenAgentManager] Getting session list with version-aware strategy',
|
||||
);
|
||||
|
||||
@@ -270,7 +267,7 @@ export class QwenAgentManager {
|
||||
const cliContextManager = CliContextManager.getInstance();
|
||||
const supportsSessionList = cliContextManager.supportsSessionList();
|
||||
|
||||
this.consoleLog(
|
||||
console.log(
|
||||
'[QwenAgentManager] CLI supports session/list:',
|
||||
supportsSessionList,
|
||||
);
|
||||
@@ -278,14 +275,11 @@ export class QwenAgentManager {
|
||||
// Try ACP method first if supported
|
||||
if (supportsSessionList) {
|
||||
try {
|
||||
this.consoleLog(
|
||||
console.log(
|
||||
'[QwenAgentManager] Attempting to get session list via ACP method',
|
||||
);
|
||||
const response = await this.connection.listSessions();
|
||||
this.consoleLog(
|
||||
'[QwenAgentManager] ACP session list response:',
|
||||
response,
|
||||
);
|
||||
console.log('[QwenAgentManager] ACP session list response:', response);
|
||||
|
||||
// sendRequest resolves with the JSON-RPC "result" directly
|
||||
// Newer CLI returns an object: { items: [...], nextCursor?, hasMore }
|
||||
@@ -303,7 +297,7 @@ export class QwenAgentManager {
|
||||
: [];
|
||||
}
|
||||
|
||||
this.consoleLog(
|
||||
console.log(
|
||||
'[QwenAgentManager] Sessions retrieved via ACP:',
|
||||
res,
|
||||
items.length,
|
||||
@@ -322,7 +316,7 @@ export class QwenAgentManager {
|
||||
cwd: item.cwd,
|
||||
}));
|
||||
|
||||
this.consoleLog(
|
||||
console.log(
|
||||
'[QwenAgentManager] Sessions retrieved via ACP:',
|
||||
sessions.length,
|
||||
);
|
||||
@@ -338,11 +332,9 @@ export class QwenAgentManager {
|
||||
|
||||
// Always fall back to file system method
|
||||
try {
|
||||
this.consoleLog(
|
||||
'[QwenAgentManager] Getting session list from file system',
|
||||
);
|
||||
console.log('[QwenAgentManager] Getting session list from file system');
|
||||
const sessions = await this.sessionReader.getAllSessions(undefined, true);
|
||||
this.consoleLog(
|
||||
console.log(
|
||||
'[QwenAgentManager] Session list from file system (all projects):',
|
||||
sessions.length,
|
||||
);
|
||||
@@ -360,7 +352,7 @@ export class QwenAgentManager {
|
||||
}),
|
||||
);
|
||||
|
||||
this.consoleLog(
|
||||
console.log(
|
||||
'[QwenAgentManager] Sessions retrieved from file system:',
|
||||
result.length,
|
||||
);
|
||||
@@ -500,7 +492,7 @@ export class QwenAgentManager {
|
||||
const item = list.find(
|
||||
(s) => s.sessionId === sessionId || s.id === sessionId,
|
||||
);
|
||||
this.consoleLog(
|
||||
console.log(
|
||||
'[QwenAgentManager] Session list item for filePath lookup:',
|
||||
item,
|
||||
);
|
||||
@@ -571,7 +563,7 @@ export class QwenAgentManager {
|
||||
}
|
||||
}
|
||||
// Simple linear reconstruction: filter user/assistant and sort by timestamp
|
||||
this.consoleLog(
|
||||
console.log(
|
||||
'[QwenAgentManager] JSONL records read:',
|
||||
records.length,
|
||||
filePath,
|
||||
@@ -728,7 +720,7 @@ export class QwenAgentManager {
|
||||
// Handle other types if needed
|
||||
}
|
||||
|
||||
this.consoleLog(
|
||||
console.log(
|
||||
'[QwenAgentManager] JSONL messages reconstructed:',
|
||||
msgs.length,
|
||||
);
|
||||
@@ -866,7 +858,7 @@ export class QwenAgentManager {
|
||||
tag: string,
|
||||
): Promise<{ success: boolean; message?: string }> {
|
||||
try {
|
||||
this.consoleLog(
|
||||
console.log(
|
||||
'[QwenAgentManager] Saving session via /chat save command:',
|
||||
sessionId,
|
||||
'with tag:',
|
||||
@@ -877,9 +869,7 @@ export class QwenAgentManager {
|
||||
// The CLI will handle this as a special command
|
||||
await this.connection.sendPrompt(`/chat save "${tag}"`);
|
||||
|
||||
this.consoleLog(
|
||||
'[QwenAgentManager] /chat save command sent successfully',
|
||||
);
|
||||
console.log('[QwenAgentManager] /chat save command sent successfully');
|
||||
return {
|
||||
success: true,
|
||||
message: `Session saved with tag: ${tag}`,
|
||||
@@ -926,14 +916,14 @@ export class QwenAgentManager {
|
||||
conversationId: string,
|
||||
): Promise<{ success: boolean; tag?: string; message?: string }> {
|
||||
try {
|
||||
this.consoleLog('[QwenAgentManager] ===== CHECKPOINT SAVE START =====');
|
||||
this.consoleLog('[QwenAgentManager] Conversation ID:', conversationId);
|
||||
this.consoleLog('[QwenAgentManager] Message count:', messages.length);
|
||||
this.consoleLog(
|
||||
console.log('[QwenAgentManager] ===== CHECKPOINT SAVE START =====');
|
||||
console.log('[QwenAgentManager] Conversation ID:', conversationId);
|
||||
console.log('[QwenAgentManager] Message count:', messages.length);
|
||||
console.log(
|
||||
'[QwenAgentManager] Current working dir:',
|
||||
this.currentWorkingDir,
|
||||
);
|
||||
this.consoleLog(
|
||||
console.log(
|
||||
'[QwenAgentManager] Current session ID (from CLI):',
|
||||
this.currentSessionId,
|
||||
);
|
||||
@@ -1010,11 +1000,11 @@ export class QwenAgentManager {
|
||||
try {
|
||||
// Route upcoming session/update messages as discrete messages for replay
|
||||
this.rehydratingSessionId = sessionId;
|
||||
this.consoleLog(
|
||||
console.log(
|
||||
'[QwenAgentManager] Rehydration start for session:',
|
||||
sessionId,
|
||||
);
|
||||
this.consoleLog(
|
||||
console.log(
|
||||
'[QwenAgentManager] Attempting session/load via ACP for session:',
|
||||
sessionId,
|
||||
);
|
||||
@@ -1022,7 +1012,7 @@ export class QwenAgentManager {
|
||||
sessionId,
|
||||
cwdOverride,
|
||||
);
|
||||
this.consoleLog(
|
||||
console.log(
|
||||
'[QwenAgentManager] Session load succeeded. Response:',
|
||||
JSON.stringify(response).substring(0, 200),
|
||||
);
|
||||
@@ -1062,10 +1052,7 @@ export class QwenAgentManager {
|
||||
throw error;
|
||||
} finally {
|
||||
// End rehydration routing regardless of outcome
|
||||
this.consoleLog(
|
||||
'[QwenAgentManager] Rehydration end for session:',
|
||||
sessionId,
|
||||
);
|
||||
console.log('[QwenAgentManager] Rehydration end for session:', sessionId);
|
||||
this.rehydratingSessionId = null;
|
||||
}
|
||||
}
|
||||
@@ -1078,7 +1065,7 @@ export class QwenAgentManager {
|
||||
* @returns Loaded session messages or null
|
||||
*/
|
||||
async loadSession(sessionId: string): Promise<ChatMessage[] | null> {
|
||||
this.consoleLog(
|
||||
console.log(
|
||||
'[QwenAgentManager] Loading session with version-aware strategy:',
|
||||
sessionId,
|
||||
);
|
||||
@@ -1087,7 +1074,7 @@ export class QwenAgentManager {
|
||||
const cliContextManager = CliContextManager.getInstance();
|
||||
const supportsSessionLoad = cliContextManager.supportsSessionLoad();
|
||||
|
||||
this.consoleLog(
|
||||
console.log(
|
||||
'[QwenAgentManager] CLI supports session/load:',
|
||||
supportsSessionLoad,
|
||||
);
|
||||
@@ -1095,13 +1082,11 @@ export class QwenAgentManager {
|
||||
// Try ACP method first if supported
|
||||
if (supportsSessionLoad) {
|
||||
try {
|
||||
this.consoleLog(
|
||||
console.log(
|
||||
'[QwenAgentManager] Attempting to load session via ACP method',
|
||||
);
|
||||
await this.loadSessionViaAcp(sessionId);
|
||||
this.consoleLog(
|
||||
'[QwenAgentManager] Session loaded successfully via ACP',
|
||||
);
|
||||
console.log('[QwenAgentManager] Session loaded successfully via ACP');
|
||||
|
||||
// After loading via ACP, we still need to get messages from file system
|
||||
// In future, we might get them directly from the ACP response
|
||||
@@ -1115,11 +1100,11 @@ export class QwenAgentManager {
|
||||
|
||||
// Always fall back to file system method
|
||||
try {
|
||||
this.consoleLog(
|
||||
console.log(
|
||||
'[QwenAgentManager] Loading session messages from file system',
|
||||
);
|
||||
const messages = await this.loadSessionMessagesFromFile(sessionId);
|
||||
this.consoleLog(
|
||||
console.log(
|
||||
'[QwenAgentManager] Session messages loaded successfully from file system',
|
||||
);
|
||||
return messages;
|
||||
@@ -1142,7 +1127,7 @@ export class QwenAgentManager {
|
||||
sessionId: string,
|
||||
): Promise<ChatMessage[] | null> {
|
||||
try {
|
||||
this.consoleLog(
|
||||
console.log(
|
||||
'[QwenAgentManager] Loading session from file system:',
|
||||
sessionId,
|
||||
);
|
||||
@@ -1154,7 +1139,7 @@ export class QwenAgentManager {
|
||||
);
|
||||
|
||||
if (!session) {
|
||||
this.consoleLog(
|
||||
console.log(
|
||||
'[QwenAgentManager] Session not found in file system:',
|
||||
sessionId,
|
||||
);
|
||||
@@ -1209,7 +1194,7 @@ export class QwenAgentManager {
|
||||
return this.sessionCreateInFlight;
|
||||
}
|
||||
|
||||
this.consoleLog('[QwenAgentManager] Creating new session...');
|
||||
console.log('[QwenAgentManager] Creating new session...');
|
||||
// Prefer the provided authStateManager, otherwise fall back to the one
|
||||
// remembered during connect(). This prevents accidental re-auth in
|
||||
// fallback paths (e.g. session switching) when the handler didn't pass it.
|
||||
@@ -1250,7 +1235,7 @@ export class QwenAgentManager {
|
||||
}
|
||||
}
|
||||
const newSessionId = this.connection.currentSessionId;
|
||||
this.consoleLog(
|
||||
console.log(
|
||||
'[QwenAgentManager] New session created with ID:',
|
||||
newSessionId,
|
||||
);
|
||||
@@ -1276,7 +1261,7 @@ export class QwenAgentManager {
|
||||
* Cancel current prompt
|
||||
*/
|
||||
async cancelCurrentPrompt(): Promise<void> {
|
||||
this.consoleLog('[QwenAgentManager] Cancelling current prompt');
|
||||
console.log('[QwenAgentManager] Cancelling current prompt');
|
||||
await this.connection.cancelSession();
|
||||
}
|
||||
|
||||
|
||||
@@ -6,11 +6,6 @@
|
||||
|
||||
import * as vscode from 'vscode';
|
||||
|
||||
type ConsoleLogger = (...args: unknown[]) => void;
|
||||
|
||||
// Shared console logger instance, initialized during extension activation.
|
||||
let sharedConsoleLogger: ConsoleLogger = () => {};
|
||||
|
||||
export function createLogger(
|
||||
context: vscode.ExtensionContext,
|
||||
logger: vscode.OutputChannel,
|
||||
@@ -21,40 +16,3 @@ export function createLogger(
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a dev-only logger that writes to the VS Code console (Developer Tools).
|
||||
*/
|
||||
export function createConsoleLogger(
|
||||
context: vscode.ExtensionContext,
|
||||
scope?: string,
|
||||
): ConsoleLogger {
|
||||
return (...args: unknown[]) => {
|
||||
if (context.extensionMode !== vscode.ExtensionMode.Development) {
|
||||
return;
|
||||
}
|
||||
if (scope) {
|
||||
console.log(`[${scope}]`, ...args);
|
||||
return;
|
||||
}
|
||||
console.log(...args);
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the shared console logger so other modules can import it without
|
||||
* threading the extension context everywhere.
|
||||
*/
|
||||
export function initSharedConsoleLogger(
|
||||
context: vscode.ExtensionContext,
|
||||
scope?: string,
|
||||
) {
|
||||
sharedConsoleLogger = createConsoleLogger(context, scope);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the shared console logger (no-op until initialized).
|
||||
*/
|
||||
export function getConsoleLogger(): ConsoleLogger {
|
||||
return sharedConsoleLogger;
|
||||
}
|
||||
|
||||
@@ -45,11 +45,9 @@ import { FileIcon, UserIcon } from './components/icons/index.js';
|
||||
import { ApprovalMode, NEXT_APPROVAL_MODE } from '../types/acpTypes.js';
|
||||
import type { ApprovalModeValue } from '../types/acpTypes.js';
|
||||
import type { PlanEntry } from '../types/chatTypes.js';
|
||||
import { createWebviewConsoleLogger } from './utils/logger.js';
|
||||
|
||||
export const App: React.FC = () => {
|
||||
const vscode = useVSCode();
|
||||
const consoleLog = useMemo(() => createWebviewConsoleLogger('App'), []);
|
||||
|
||||
// Core hooks
|
||||
const sessionManagement = useSessionManagement(vscode);
|
||||
@@ -542,7 +540,7 @@ export const App: React.FC = () => {
|
||||
);
|
||||
}, [messageHandling.messages, inProgressToolCalls, completedToolCalls]);
|
||||
|
||||
consoleLog('[App] Rendering messages:', allMessages);
|
||||
console.log('[App] Rendering messages:', allMessages);
|
||||
|
||||
// Render all messages and tool calls
|
||||
const renderMessages = useCallback<() => React.ReactNode>(
|
||||
|
||||
@@ -16,7 +16,6 @@ import { WebViewContent } from '../webview/WebViewContent.js';
|
||||
import { CliInstaller } from '../cli/cliInstaller.js';
|
||||
import { getFileName } from './utils/webviewUtils.js';
|
||||
import { authMethod, type ApprovalModeValue } from '../types/acpTypes.js';
|
||||
import { createConsoleLogger } from '../utils/logger.js';
|
||||
|
||||
export class WebViewProvider {
|
||||
private panelManager: PanelManager;
|
||||
@@ -33,15 +32,12 @@ export class WebViewProvider {
|
||||
private pendingPermissionResolve: ((optionId: string) => void) | null = null;
|
||||
// Track current ACP mode id to influence permission/diff behavior
|
||||
private currentModeId: ApprovalModeValue | null = null;
|
||||
private consoleLog: (...args: unknown[]) => void;
|
||||
|
||||
constructor(
|
||||
context: vscode.ExtensionContext,
|
||||
private extensionUri: vscode.Uri,
|
||||
) {
|
||||
const agentConsoleLogger = createConsoleLogger(context, 'QwenAgentManager');
|
||||
this.consoleLog = createConsoleLogger(context, 'WebViewProvider');
|
||||
this.agentManager = new QwenAgentManager(agentConsoleLogger);
|
||||
this.agentManager = new QwenAgentManager();
|
||||
this.conversationStore = new ConversationStore(context);
|
||||
this.authStateManager = AuthStateManager.getInstance(context);
|
||||
this.panelManager = new PanelManager(extensionUri, () => {
|
||||
@@ -384,7 +380,7 @@ export class WebViewProvider {
|
||||
|
||||
// Set up state serialization
|
||||
newPanel.onDidChangeViewState(() => {
|
||||
this.consoleLog(
|
||||
console.log(
|
||||
'[WebViewProvider] Panel view state changed, triggering serialization check',
|
||||
);
|
||||
});
|
||||
@@ -514,7 +510,7 @@ export class WebViewProvider {
|
||||
}
|
||||
|
||||
// Attempt to restore authentication state and initialize connection
|
||||
this.consoleLog(
|
||||
console.log(
|
||||
'[WebViewProvider] Attempting to restore auth state and connection...',
|
||||
);
|
||||
await this.attemptAuthStateRestoration();
|
||||
@@ -536,26 +532,23 @@ export class WebViewProvider {
|
||||
workingDir,
|
||||
authMethod,
|
||||
);
|
||||
this.consoleLog(
|
||||
'[WebViewProvider] Has valid cached auth:',
|
||||
hasValidAuth,
|
||||
);
|
||||
console.log('[WebViewProvider] Has valid cached auth:', hasValidAuth);
|
||||
|
||||
if (hasValidAuth) {
|
||||
this.consoleLog(
|
||||
console.log(
|
||||
'[WebViewProvider] Valid auth found, attempting connection...',
|
||||
);
|
||||
// Try to connect with cached auth
|
||||
await this.initializeAgentConnection();
|
||||
} else {
|
||||
this.consoleLog(
|
||||
console.log(
|
||||
'[WebViewProvider] No valid auth found, rendering empty conversation',
|
||||
);
|
||||
// Render the chat UI immediately without connecting
|
||||
await this.initializeEmptyConversation();
|
||||
}
|
||||
} else {
|
||||
this.consoleLog(
|
||||
console.log(
|
||||
'[WebViewProvider] No auth state manager, rendering empty conversation',
|
||||
);
|
||||
await this.initializeEmptyConversation();
|
||||
@@ -585,11 +578,11 @@ export class WebViewProvider {
|
||||
const workspaceFolder = vscode.workspace.workspaceFolders?.[0];
|
||||
const workingDir = workspaceFolder?.uri.fsPath || process.cwd();
|
||||
|
||||
this.consoleLog(
|
||||
console.log(
|
||||
'[WebViewProvider] Starting initialization, workingDir:',
|
||||
workingDir,
|
||||
);
|
||||
this.consoleLog(
|
||||
console.log(
|
||||
'[WebViewProvider] AuthStateManager available:',
|
||||
!!this.authStateManager,
|
||||
);
|
||||
@@ -598,10 +591,10 @@ export class WebViewProvider {
|
||||
const cliDetection = await CliDetector.detectQwenCli();
|
||||
|
||||
if (!cliDetection.isInstalled) {
|
||||
this.consoleLog(
|
||||
console.log(
|
||||
'[WebViewProvider] Qwen CLI not detected, skipping agent connection',
|
||||
);
|
||||
this.consoleLog(
|
||||
console.log(
|
||||
'[WebViewProvider] CLI detection error:',
|
||||
cliDetection.error,
|
||||
);
|
||||
@@ -612,20 +605,20 @@ export class WebViewProvider {
|
||||
// Initialize empty conversation (can still browse history)
|
||||
await this.initializeEmptyConversation();
|
||||
} else {
|
||||
this.consoleLog(
|
||||
console.log(
|
||||
'[WebViewProvider] Qwen CLI detected, attempting connection...',
|
||||
);
|
||||
this.consoleLog('[WebViewProvider] CLI path:', cliDetection.cliPath);
|
||||
this.consoleLog('[WebViewProvider] CLI version:', cliDetection.version);
|
||||
console.log('[WebViewProvider] CLI path:', cliDetection.cliPath);
|
||||
console.log('[WebViewProvider] CLI version:', cliDetection.version);
|
||||
|
||||
try {
|
||||
this.consoleLog('[WebViewProvider] Connecting to agent...');
|
||||
this.consoleLog(
|
||||
console.log('[WebViewProvider] Connecting to agent...');
|
||||
console.log(
|
||||
'[WebViewProvider] Using authStateManager:',
|
||||
!!this.authStateManager,
|
||||
);
|
||||
const authInfo = await this.authStateManager.getAuthInfo();
|
||||
this.consoleLog('[WebViewProvider] Auth cache status:', authInfo);
|
||||
console.log('[WebViewProvider] Auth cache status:', authInfo);
|
||||
|
||||
// Pass the detected CLI path to ensure we use the correct installation
|
||||
await this.agentManager.connect(
|
||||
@@ -633,7 +626,7 @@ export class WebViewProvider {
|
||||
this.authStateManager,
|
||||
cliDetection.cliPath,
|
||||
);
|
||||
this.consoleLog('[WebViewProvider] Agent connected successfully');
|
||||
console.log('[WebViewProvider] Agent connected successfully');
|
||||
this.agentInitialized = true;
|
||||
|
||||
// Load messages from the current Qwen session
|
||||
@@ -674,8 +667,8 @@ export class WebViewProvider {
|
||||
* Called when user explicitly uses /login command
|
||||
*/
|
||||
async forceReLogin(): Promise<void> {
|
||||
this.consoleLog('[WebViewProvider] Force re-login requested');
|
||||
this.consoleLog(
|
||||
console.log('[WebViewProvider] Force re-login requested');
|
||||
console.log(
|
||||
'[WebViewProvider] Current authStateManager:',
|
||||
!!this.authStateManager,
|
||||
);
|
||||
@@ -694,23 +687,20 @@ export class WebViewProvider {
|
||||
// Clear existing auth cache
|
||||
if (this.authStateManager) {
|
||||
await this.authStateManager.clearAuthState();
|
||||
this.consoleLog('[WebViewProvider] Auth cache cleared');
|
||||
console.log('[WebViewProvider] Auth cache cleared');
|
||||
} else {
|
||||
this.consoleLog('[WebViewProvider] No authStateManager to clear');
|
||||
console.log('[WebViewProvider] No authStateManager to clear');
|
||||
}
|
||||
|
||||
// Disconnect existing connection if any
|
||||
if (this.agentInitialized) {
|
||||
try {
|
||||
this.agentManager.disconnect();
|
||||
this.consoleLog(
|
||||
console.log(
|
||||
'[WebViewProvider] Existing connection disconnected',
|
||||
);
|
||||
} catch (_error) {
|
||||
this.consoleLog(
|
||||
'[WebViewProvider] Error disconnecting:',
|
||||
_error,
|
||||
);
|
||||
console.log('[WebViewProvider] Error disconnecting:', _error);
|
||||
}
|
||||
this.agentInitialized = false;
|
||||
}
|
||||
@@ -724,7 +714,7 @@ export class WebViewProvider {
|
||||
|
||||
// Reinitialize connection (will trigger fresh authentication)
|
||||
await this.doInitializeAgentConnection();
|
||||
this.consoleLog(
|
||||
console.log(
|
||||
'[WebViewProvider] Force re-login completed successfully',
|
||||
);
|
||||
|
||||
@@ -733,9 +723,7 @@ export class WebViewProvider {
|
||||
const workspaceFolder = vscode.workspace.workspaceFolders?.[0];
|
||||
const workingDir = workspaceFolder?.uri.fsPath || process.cwd();
|
||||
await this.authStateManager.saveAuthState(workingDir, authMethod);
|
||||
this.consoleLog(
|
||||
'[WebViewProvider] Auth state saved after re-login',
|
||||
);
|
||||
console.log('[WebViewProvider] Auth state saved after re-login');
|
||||
}
|
||||
|
||||
// Send success notification to WebView
|
||||
@@ -772,15 +760,15 @@ export class WebViewProvider {
|
||||
* Called when restoring WebView after VSCode restart
|
||||
*/
|
||||
async refreshConnection(): Promise<void> {
|
||||
this.consoleLog('[WebViewProvider] Refresh connection requested');
|
||||
console.log('[WebViewProvider] Refresh connection requested');
|
||||
|
||||
// Disconnect existing connection if any
|
||||
if (this.agentInitialized) {
|
||||
try {
|
||||
this.agentManager.disconnect();
|
||||
this.consoleLog('[WebViewProvider] Existing connection disconnected');
|
||||
console.log('[WebViewProvider] Existing connection disconnected');
|
||||
} catch (_error) {
|
||||
this.consoleLog('[WebViewProvider] Error disconnecting:', _error);
|
||||
console.log('[WebViewProvider] Error disconnecting:', _error);
|
||||
}
|
||||
this.agentInitialized = false;
|
||||
}
|
||||
@@ -791,7 +779,7 @@ export class WebViewProvider {
|
||||
// Reinitialize connection (will use cached auth if available)
|
||||
try {
|
||||
await this.initializeAgentConnection();
|
||||
this.consoleLog(
|
||||
console.log(
|
||||
'[WebViewProvider] Connection refresh completed successfully',
|
||||
);
|
||||
|
||||
@@ -821,7 +809,7 @@ export class WebViewProvider {
|
||||
*/
|
||||
private async loadCurrentSessionMessages(): Promise<void> {
|
||||
try {
|
||||
this.consoleLog(
|
||||
console.log(
|
||||
'[WebViewProvider] Initializing with new session (skipping restoration)',
|
||||
);
|
||||
|
||||
@@ -835,12 +823,12 @@ export class WebViewProvider {
|
||||
workingDir,
|
||||
this.authStateManager,
|
||||
);
|
||||
this.consoleLog('[WebViewProvider] ACP session created successfully');
|
||||
console.log('[WebViewProvider] ACP session created successfully');
|
||||
|
||||
// Ensure auth state is saved after successful session creation
|
||||
if (this.authStateManager) {
|
||||
await this.authStateManager.saveAuthState(workingDir, authMethod);
|
||||
this.consoleLog(
|
||||
console.log(
|
||||
'[WebViewProvider] Auth state saved after session creation',
|
||||
);
|
||||
}
|
||||
@@ -854,7 +842,7 @@ export class WebViewProvider {
|
||||
);
|
||||
}
|
||||
} else {
|
||||
this.consoleLog(
|
||||
console.log(
|
||||
'[WebViewProvider] Existing ACP session detected, skipping new session creation',
|
||||
);
|
||||
}
|
||||
@@ -878,14 +866,14 @@ export class WebViewProvider {
|
||||
*/
|
||||
private async initializeEmptyConversation(): Promise<void> {
|
||||
try {
|
||||
this.consoleLog('[WebViewProvider] Initializing empty conversation');
|
||||
console.log('[WebViewProvider] Initializing empty conversation');
|
||||
const newConv = await this.conversationStore.createConversation();
|
||||
this.messageHandler.setCurrentConversationId(newConv.id);
|
||||
this.sendMessageToWebView({
|
||||
type: 'conversationLoaded',
|
||||
data: newConv,
|
||||
});
|
||||
this.consoleLog(
|
||||
console.log(
|
||||
'[WebViewProvider] Empty conversation initialized:',
|
||||
this.messageHandler.getCurrentConversationId(),
|
||||
);
|
||||
@@ -1009,7 +997,7 @@ export class WebViewProvider {
|
||||
* Call this when auth cache is cleared to force re-authentication
|
||||
*/
|
||||
resetAgentState(): void {
|
||||
this.consoleLog('[WebViewProvider] Resetting agent state');
|
||||
console.log('[WebViewProvider] Resetting agent state');
|
||||
this.agentInitialized = false;
|
||||
// Disconnect existing connection
|
||||
this.agentManager.disconnect();
|
||||
@@ -1019,7 +1007,7 @@ export class WebViewProvider {
|
||||
* Clear authentication cache for this WebViewProvider instance
|
||||
*/
|
||||
async clearAuthCache(): Promise<void> {
|
||||
this.consoleLog('[WebViewProvider] Clearing auth cache for this instance');
|
||||
console.log('[WebViewProvider] Clearing auth cache for this instance');
|
||||
if (this.authStateManager) {
|
||||
await this.authStateManager.clearAuthState();
|
||||
this.resetAgentState();
|
||||
@@ -1031,8 +1019,8 @@ export class WebViewProvider {
|
||||
* This sets up the panel with all event listeners
|
||||
*/
|
||||
async restorePanel(panel: vscode.WebviewPanel): Promise<void> {
|
||||
this.consoleLog('[WebViewProvider] Restoring WebView panel');
|
||||
this.consoleLog(
|
||||
console.log('[WebViewProvider] Restoring WebView panel');
|
||||
console.log(
|
||||
'[WebViewProvider] Current authStateManager in restore:',
|
||||
!!this.authStateManager,
|
||||
);
|
||||
@@ -1163,10 +1151,10 @@ export class WebViewProvider {
|
||||
// Capture the tab reference on restore
|
||||
this.panelManager.captureTab();
|
||||
|
||||
this.consoleLog('[WebViewProvider] Panel restored successfully');
|
||||
console.log('[WebViewProvider] Panel restored successfully');
|
||||
|
||||
// Attempt to restore authentication state and initialize connection
|
||||
this.consoleLog(
|
||||
console.log(
|
||||
'[WebViewProvider] Attempting to restore auth state and connection after restore...',
|
||||
);
|
||||
await this.attemptAuthStateRestoration();
|
||||
@@ -1180,12 +1168,12 @@ export class WebViewProvider {
|
||||
conversationId: string | null;
|
||||
agentInitialized: boolean;
|
||||
} {
|
||||
this.consoleLog('[WebViewProvider] Getting state for serialization');
|
||||
this.consoleLog(
|
||||
console.log('[WebViewProvider] Getting state for serialization');
|
||||
console.log(
|
||||
'[WebViewProvider] Current conversationId:',
|
||||
this.messageHandler.getCurrentConversationId(),
|
||||
);
|
||||
this.consoleLog(
|
||||
console.log(
|
||||
'[WebViewProvider] Current agentInitialized:',
|
||||
this.agentInitialized,
|
||||
);
|
||||
@@ -1193,7 +1181,7 @@ export class WebViewProvider {
|
||||
conversationId: this.messageHandler.getCurrentConversationId(),
|
||||
agentInitialized: this.agentInitialized,
|
||||
};
|
||||
this.consoleLog('[WebViewProvider] Returning state:', state);
|
||||
console.log('[WebViewProvider] Returning state:', state);
|
||||
return state;
|
||||
}
|
||||
|
||||
@@ -1211,10 +1199,10 @@ export class WebViewProvider {
|
||||
conversationId: string | null;
|
||||
agentInitialized: boolean;
|
||||
}): void {
|
||||
this.consoleLog('[WebViewProvider] Restoring state:', state);
|
||||
console.log('[WebViewProvider] Restoring state:', state);
|
||||
this.messageHandler.setCurrentConversationId(state.conversationId);
|
||||
this.agentInitialized = state.agentInitialized;
|
||||
this.consoleLog(
|
||||
console.log(
|
||||
'[WebViewProvider] State restored. agentInitialized:',
|
||||
this.agentInitialized,
|
||||
);
|
||||
|
||||
@@ -61,25 +61,6 @@ export const safeTitle = (title: unknown): string => {
|
||||
return '';
|
||||
};
|
||||
|
||||
/**
|
||||
* Get icon emoji for a given tool kind
|
||||
*/
|
||||
export const getKindIcon = (kind: string): string => {
|
||||
const kindMap: Record<string, string> = {
|
||||
edit: '✏️',
|
||||
write: '✏️',
|
||||
read: '📖',
|
||||
execute: '⚡',
|
||||
fetch: '🌐',
|
||||
delete: '🗑️',
|
||||
move: '📦',
|
||||
search: '🔍',
|
||||
think: '💭',
|
||||
diff: '📝',
|
||||
};
|
||||
return kindMap[kind.toLowerCase()] || '🔧';
|
||||
};
|
||||
|
||||
/**
|
||||
* Check if a tool call should be displayed
|
||||
* Hides internal tool calls
|
||||
|
||||
@@ -14,7 +14,6 @@ import type {
|
||||
import type { ToolCallUpdate } from '../../types/chatTypes.js';
|
||||
import type { ApprovalModeValue } from '../../types/acpTypes.js';
|
||||
import type { PlanEntry } from '../../types/chatTypes.js';
|
||||
import { createWebviewConsoleLogger } from '../utils/logger.js';
|
||||
|
||||
interface UseWebViewMessagesProps {
|
||||
// Session management
|
||||
@@ -130,7 +129,6 @@ export const useWebViewMessages = ({
|
||||
}: UseWebViewMessagesProps) => {
|
||||
// VS Code API for posting messages back to the extension host
|
||||
const vscode = useVSCode();
|
||||
const consoleLog = useRef(createWebviewConsoleLogger('WebViewMessages'));
|
||||
// Track active long-running tool calls (execute/bash/command) so we can
|
||||
// keep the bottom "waiting" message visible until all of them complete.
|
||||
const activeExecToolCallsRef = useRef<Set<string>>(new Set());
|
||||
@@ -753,10 +751,7 @@ export const useWebViewMessages = ({
|
||||
path: string;
|
||||
}>;
|
||||
if (files) {
|
||||
consoleLog.current(
|
||||
'[WebView] Received workspaceFiles:',
|
||||
files.length,
|
||||
);
|
||||
console.log('[WebView] Received workspaceFiles:', files.length);
|
||||
handlers.fileContext.setWorkspaceFiles(files);
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -1,25 +0,0 @@
|
||||
/**
|
||||
* @license
|
||||
* Copyright 2025 Qwen Team
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
/**
|
||||
* Creates a dev-only console logger for the WebView bundle.
|
||||
* In production builds it becomes a no-op to avoid noisy logs.
|
||||
*/
|
||||
export function createWebviewConsoleLogger(scope?: string) {
|
||||
return (...args: unknown[]) => {
|
||||
const env = (globalThis as { process?: { env?: Record<string, string> } })
|
||||
.process?.env;
|
||||
const isProduction = env?.NODE_ENV === 'production';
|
||||
if (isProduction) {
|
||||
return;
|
||||
}
|
||||
if (scope) {
|
||||
console.log(`[${scope}]`, ...args);
|
||||
return;
|
||||
}
|
||||
console.log(...args);
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user