mirror of
https://github.com/QwenLM/qwen-code.git
synced 2026-04-28 03:30:40 +00:00
Some checks are pending
Qwen Code CI / Lint (push) Waiting to run
Qwen Code CI / Test (push) Blocked by required conditions
Qwen Code CI / Test-1 (push) Blocked by required conditions
Qwen Code CI / Test-2 (push) Blocked by required conditions
Qwen Code CI / Test-3 (push) Blocked by required conditions
Qwen Code CI / Test-4 (push) Blocked by required conditions
Qwen Code CI / Test-5 (push) Blocked by required conditions
Qwen Code CI / Test-6 (push) Blocked by required conditions
Qwen Code CI / Test-7 (push) Blocked by required conditions
Qwen Code CI / Test-8 (push) Blocked by required conditions
Qwen Code CI / Post Coverage Comment (push) Blocked by required conditions
Qwen Code CI / CodeQL (push) Waiting to run
E2E Tests / E2E Test (Linux) - sandbox:docker (push) Waiting to run
E2E Tests / E2E Test (Linux) - sandbox:none (push) Waiting to run
E2E Tests / E2E Test - macOS (push) Waiting to run
* refactor(core): move codingPlan constants from cli to core package Extract Coding Plan region configs, model templates, and utility functions into packages/core/src/constants/ so both CLI and VSCode extension can import from a shared source of truth. * refactor(cli): import codingPlan constants from core instead of local path Update all CLI files to import CodingPlanRegion, CODING_PLAN_ENV_KEY, and related utilities from @qwen-code/qwen-code-core, replacing the local ../../constants/codingPlan.js imports. * feat(vscode-ide-companion): replace login flow with provider setup via VSCode Settings Replace the OAuth-based login command with a settings-driven provider configuration flow. Users now configure Coding Plan or API Key providers through VSCode Settings (qwen-code.*), which auto-syncs to ~/.qwen/settings.json. - Rename login command to auth, opening VSCode Settings panel - Add /auth2 interactive flow (QuickPick + InputBox) - Add ProviderSetupForm onboarding component with inline config - Add bidirectional sync between VSCode settings and ~/.qwen/settings.json - Add settingsWriter service for direct settings.json read/write - Add VSCode configuration schema (provider, apiKey, region, model, etc.) - Update all login/session messages to use auth terminology * refactor(vscode-ide-companion): rename auth2→auth, remove dead code, fix sync guard - Rename auth2 to auth for all message types, handlers, and slash command - Remove unused InfoBanner.tsx (128 lines, no references) - Remove dead openProviderSettings handler (no callers) - Remove redundant qwen-code.baseUrl VSCode setting (already in modelProviders) - Replace unreliable setTimeout(500) sync guard with await Promise.all + finally - Clean up old authHandler/setAuthHandler in favor of authInteractiveHandler * refactor(vscode-ide-companion): remove dead VSCode Settings plumbing, simplify sync - Remove qwen-code.modelProviders and qwen-code.model from package.json (model switching handled by chat UI's /model command, not VSCode Settings) - Remove connectWithSettings message handler and plumbing (no webview component sends this message type) - Remove handleConnectWithSettings method from WebViewProvider - Simplify syncVSCodeSettingsToQwenConfig: only sync provider/apiKey/region - Simplify syncQwenConfigToVSCodeSettings: only populate provider/apiKey/region - Simplify QwenSettingsForVSCode interface: remove modelProviders and model - Improve Onboarding UI: logo above card, better hierarchy, arrow icon on button * fix(vscode-ide-companion): add missing vscode.workspace mock in test Add onDidChangeConfiguration and getConfiguration to the vscode.workspace mock in WebViewProvider.test.ts to fix CI test failures. * fix(vscode-ide-companion): clean up stale coding plan state, add auth cancel handling, add tests - Clear CODING_PLAN_ENV_KEY and codingPlan metadata when switching to api-key mode - Add authCancelled notification when QuickPick/InputBox is dismissed - ProviderSetupForm resets button state on authCancelled - syncVSCodeSettingsToQwenConfig returns false for api-key mode (no-op) - Fix Onboarding vertical centering (flex-1 min-h-0) - Import from @qwen-code/qwen-code-core top-level instead of deep paths - Add tests: settingsWriter, ProviderSetupForm cancel, AuthMessageHandler cancel, WebViewProvider sync - Fix redundant ternary in pick() helper * fix(vscode-ide-companion): force center Onboarding against parent override Parent container uses [&>*]:items-start and [&>*]:text-left which overrides Tailwind classes. Use inline style for alignItems/justifyContent/textAlign to ensure Onboarding is always centered both horizontally and vertically. * fix(vscode-ide-companion): bundle onboarding logo * test(vscode-ide-companion): add png loader to bundle test * fix(vscode-ide-companion/webview): avoid redundant auth sync reconnects * fix(vscode-ide-companion/webview): fix auth sync typecheck * docs(vscode-ide-companion): clarify auth restoration flow * fix(webui): use bracket access for permission drawer plan content * fix(vscode-ide-companion): guard authSuccess emission on actual auth state After reconnecting in handleAuthInteractive, doInitializeAgentConnection may return without throwing even when credentials are rejected (it sends authState:false internally and returns early). Previously we unconditionally emitted authSuccess, which contradicted the failed auth state and could briefly show a success toast before re-opening the auth flow. Now we check this.authState after reconnection: only emit authSuccess when authentication actually succeeded, otherwise emit authError with a clear credentials message. Addresses review feedback from PR #3398. * fix(vscode): address auth setup review feedback * fix(vscode-ide-companion): guard concurrent auth flows, merge model providers - Add authFlowActive mutex and autoAuthTimer to WebViewProvider so startInteractiveAuth() cancels the deferred auto-auth timeout, preventing two overlapping QuickPick flows from a single command. - Change writeModelProvidersConfig() to merge new entries with existing non-target models (different envKey) instead of replacing the entire array, preserving unrelated providers like Coding Plan. * fix(vscode-ide-companion): handle apiKey clearing as de-auth signal, fix auto-auth race, clean imports - Add clearPersistedAuth() to settingsWriter.ts: removes selectedType, API keys, and coding plan metadata from ~/.qwen/settings.json - Config change handler now detects empty apiKey with active agent and triggers de-auth: clear credentials, disconnect, update authState - Auto-auth timer callback now properly sets authFlowActive mutex to prevent concurrent auth flows with startInteractiveAuth() - Add test covering the de-auth path (clearPersistedAuth + disconnect) - Fix import formatting in 7 CLI files (spacing, trailing commas) - Remove duplicate comment in attemptAuthStateRestoration() * fix(vscode-ide-companion): scope de-auth to apiKey changes only The previous de-auth logic triggered on any auth-related setting change where syncVSCodeSettingsToQwenConfig() returned false. For api-key providers this is the normal path (interactive auth owns config), so changing codingPlanRegion or provider would incorrectly wipe OPENAI_API_KEY. Now the de-auth branch only fires when e.affectsConfiguration('qwen-code.apiKey') is true AND the value is empty, preventing false-positive credential clearing. Add regression test: non-apiKey setting changes on an api-key provider must not trigger clearPersistedAuth or disconnect. * fix(vscode-ide-companion): add disconnect to mock type to fix CI typecheck The hoisted mockQwenAgentManagerInstances type was missing the disconnect property, causing TS2339 in the de-auth test assertions.
171 lines
4 KiB
TypeScript
171 lines
4 KiB
TypeScript
/**
|
|
* @license
|
|
* Copyright 2025 Qwen Team
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
*
|
|
* VSCode Platform Provider - Adapts VSCode API to PlatformContext
|
|
* This allows webui components to work with VSCode's messaging system
|
|
*/
|
|
|
|
import { useMemo, useCallback, useEffect, useRef } from 'react';
|
|
import type { FC, ReactNode } from 'react';
|
|
import { PlatformProvider } from '@qwen-code/webui';
|
|
import type { PlatformContextValue } from '@qwen-code/webui';
|
|
import { useVSCode } from '../hooks/useVSCode.js';
|
|
import { generateIconUrl } from '../utils/resourceUrl.js';
|
|
|
|
/**
|
|
* Props for VSCodePlatformProvider
|
|
*/
|
|
interface VSCodePlatformProviderProps {
|
|
children: ReactNode;
|
|
}
|
|
|
|
/**
|
|
* VSCodePlatformProvider - Provides platform context for VSCode extension
|
|
*
|
|
* This component bridges the VSCode API with the platform-agnostic webui components.
|
|
* It wraps children with PlatformProvider and provides VSCode-specific implementations.
|
|
*/
|
|
export const VSCodePlatformProvider: FC<VSCodePlatformProviderProps> = ({
|
|
children,
|
|
}) => {
|
|
const vscode = useVSCode();
|
|
const messageHandlersRef = useRef<Set<(message: unknown) => void>>(new Set());
|
|
|
|
// Set up message listener
|
|
useEffect(() => {
|
|
const handleMessage = (event: MessageEvent) => {
|
|
messageHandlersRef.current.forEach((handler) => {
|
|
handler(event.data);
|
|
});
|
|
};
|
|
|
|
window.addEventListener('message', handleMessage);
|
|
return () => window.removeEventListener('message', handleMessage);
|
|
}, []);
|
|
|
|
// Open file handler
|
|
const openFile = useCallback(
|
|
(path: string) => {
|
|
vscode.postMessage({
|
|
type: 'openFile',
|
|
data: { path },
|
|
});
|
|
},
|
|
[vscode],
|
|
);
|
|
|
|
// Open diff handler
|
|
const openDiff = useCallback(
|
|
(
|
|
path: string,
|
|
oldText: string | null | undefined,
|
|
newText: string | undefined,
|
|
) => {
|
|
vscode.postMessage({
|
|
type: 'openDiff',
|
|
data: {
|
|
path,
|
|
oldText: oldText ?? '',
|
|
newText: newText ?? '',
|
|
},
|
|
});
|
|
},
|
|
[vscode],
|
|
);
|
|
|
|
// Open temp file handler
|
|
const openTempFile = useCallback(
|
|
(content: string, fileName: string = 'temp') => {
|
|
vscode.postMessage({
|
|
type: 'createAndOpenTempFile',
|
|
data: {
|
|
content,
|
|
fileName,
|
|
},
|
|
});
|
|
},
|
|
[vscode],
|
|
);
|
|
|
|
// Attach file handler
|
|
const attachFile = useCallback(() => {
|
|
vscode.postMessage({
|
|
type: 'attachFile',
|
|
data: {},
|
|
});
|
|
}, [vscode]);
|
|
|
|
// Auth handler
|
|
const login = useCallback(() => {
|
|
vscode.postMessage({
|
|
type: 'auth',
|
|
data: {},
|
|
});
|
|
}, [vscode]);
|
|
|
|
// Copy to clipboard handler
|
|
const copyToClipboard = useCallback(async (text: string) => {
|
|
try {
|
|
await navigator.clipboard.writeText(text);
|
|
} catch (err) {
|
|
console.error('Failed to copy to clipboard:', err);
|
|
}
|
|
}, []);
|
|
|
|
// Get resource URL handler (for icons and other assets)
|
|
const getResourceUrl = useCallback(
|
|
(resourceName: string) => generateIconUrl(resourceName) || undefined,
|
|
[],
|
|
);
|
|
|
|
// Subscribe to messages
|
|
const onMessage = useCallback((handler: (message: unknown) => void) => {
|
|
messageHandlersRef.current.add(handler);
|
|
return () => {
|
|
messageHandlersRef.current.delete(handler);
|
|
};
|
|
}, []);
|
|
|
|
// Build platform context value
|
|
const platformValue = useMemo<PlatformContextValue>(
|
|
() => ({
|
|
platform: 'vscode',
|
|
postMessage: vscode.postMessage,
|
|
onMessage,
|
|
openFile,
|
|
openDiff,
|
|
openTempFile,
|
|
attachFile,
|
|
login,
|
|
copyToClipboard,
|
|
getResourceUrl,
|
|
features: {
|
|
canOpenFile: true,
|
|
canOpenDiff: true,
|
|
canOpenTempFile: true,
|
|
canAttachFile: true,
|
|
canLogin: true,
|
|
canCopy: true,
|
|
},
|
|
}),
|
|
[
|
|
vscode.postMessage,
|
|
onMessage,
|
|
openFile,
|
|
openDiff,
|
|
openTempFile,
|
|
attachFile,
|
|
login,
|
|
copyToClipboard,
|
|
getResourceUrl,
|
|
],
|
|
);
|
|
|
|
return (
|
|
<PlatformProvider value={platformValue}>
|
|
{children as React.ReactNode}
|
|
</PlatformProvider>
|
|
);
|
|
};
|