mirror of
https://github.com/QwenLM/qwen-code.git
synced 2026-04-28 11:41:04 +00:00
* feat(vscode): add native context menu copy actions for webview chat Add three right-click context menu items to the chat message area using VSCode's native webview/context API: - Copy Message: copies the right-clicked message's raw markdown content - Copy All Messages: copies the full conversation in markdown format - Copy Last Reply: copies the last assistant response Implementation details: - Commands registered in package.json with webview/context menu entries - Clipboard writes go through extension host (vscode.env.clipboard) for reliability in webview sandbox - Message identification via data-msg-idx stamped after render - Tool-call outputs supported including diff format (git diff style) - i18n support via package.nls.json (English) and package.nls.zh-cn.json - Menu only shown in message area (not input box or empty state) Closes #3052 * fix(vscode): wrap tool-call content text in code blocks for copy * fix(vscode): only wrap tool-call content in code blocks for Copy All, not single Copy Message * fix(vscode): route copy commands to the right-clicked webview and use dynamic code fences * fix(vscode): use childIndexMap for copy-message routing and extract shared message handling Replace the wrapper-div approach (which broke CSS layout) with a render-time childIndexMap that maps DOM child positions to allMessages indices. This avoids both the useLayoutEffect index-drift bug and the wrapper-div CSS side effects. - Remove data-msg-idx wrapper divs; messages render directly as container children, preserving original [&>*] CSS layout - Build childIndexMap during MessageList render, skipping null items (empty AssistantMessage, hidden tool calls via shouldShowToolCall) - findMessageIndex walks up from click target to container's direct child, then maps through childIndexMap - Filter hidden tool calls and empty content in copyAllMessages - Extract handleCommonWebviewMessage to deduplicate routing logic across sidebar, editor panel, and restored panel handlers - Clear lastContextMenuProvider on dispose to prevent memory leaks * fix(vscode): handle image messages in copy and resolve intermittent copy failure - Copy Message on image messages now outputs markdown format  instead of empty string - Copy All Messages includes image messages as  instead of skipping them - Copy Last Reply skips empty assistant placeholders during streaming - Resolve intermittent copy failure by pre-resolving message index on right-click instead of storing a DOM element reference that can become stale after React re-renders
311 lines
8.5 KiB
JSON
311 lines
8.5 KiB
JSON
{
|
|
"name": "qwen-code-vscode-ide-companion",
|
|
"displayName": "Qwen Code Companion",
|
|
"description": "Enable Qwen Code with direct access to your VS Code workspace.",
|
|
"version": "0.15.2",
|
|
"publisher": "qwenlm",
|
|
"icon": "assets/icon.png",
|
|
"repository": {
|
|
"type": "git",
|
|
"url": "https://github.com/QwenLM/qwen-code.git",
|
|
"directory": "packages/vscode-ide-companion"
|
|
},
|
|
"engines": {
|
|
"vscode": "^1.85.0"
|
|
},
|
|
"license": "LICENSE",
|
|
"preview": true,
|
|
"categories": [
|
|
"AI"
|
|
],
|
|
"keywords": [
|
|
"qwen-code",
|
|
"qwen code",
|
|
"qwen",
|
|
"qwen code",
|
|
"cli",
|
|
"ide integration",
|
|
"ide companion"
|
|
],
|
|
"activationEvents": [
|
|
"onStartupFinished",
|
|
"onView:qwen-code.chatView.sidebar",
|
|
"onView:qwen-code.chatView.secondary",
|
|
"onCommand:qwen-code.openChat",
|
|
"onCommand:qwen-code.focusChat",
|
|
"onCommand:qwen-code.newConversation",
|
|
"onCommand:qwen-code.showLogs"
|
|
],
|
|
"contributes": {
|
|
"jsonValidation": [
|
|
{
|
|
"fileMatch": "**/.qwen/settings.json",
|
|
"url": "./schemas/settings.schema.json"
|
|
}
|
|
],
|
|
"viewsContainers": {
|
|
"activitybar": [
|
|
{
|
|
"id": "qwen-code-sidebar",
|
|
"title": "Qwen Code",
|
|
"icon": "assets/sidebar-icon.svg",
|
|
"when": "!qwen-code:supportsSecondarySidebar"
|
|
}
|
|
],
|
|
"secondarySidebar": [
|
|
{
|
|
"id": "qwen-code-secondary",
|
|
"title": "Qwen Code",
|
|
"icon": "assets/sidebar-icon.svg",
|
|
"when": "qwen-code:supportsSecondarySidebar"
|
|
}
|
|
]
|
|
},
|
|
"views": {
|
|
"qwen-code-sidebar": [
|
|
{
|
|
"type": "webview",
|
|
"id": "qwen-code.chatView.sidebar",
|
|
"name": "Qwen Code",
|
|
"icon": "assets/sidebar-icon.svg",
|
|
"when": "!qwen-code:supportsSecondarySidebar"
|
|
}
|
|
],
|
|
"qwen-code-secondary": [
|
|
{
|
|
"type": "webview",
|
|
"id": "qwen-code.chatView.secondary",
|
|
"name": "Qwen Code",
|
|
"icon": "assets/sidebar-icon.svg",
|
|
"when": "qwen-code:supportsSecondarySidebar"
|
|
}
|
|
]
|
|
},
|
|
"languages": [
|
|
{
|
|
"id": "qwen-diff-editable"
|
|
}
|
|
],
|
|
"commands": [
|
|
{
|
|
"command": "qwen.diff.accept",
|
|
"title": "Qwen Code: Accept Current Diff",
|
|
"icon": "$(check)"
|
|
},
|
|
{
|
|
"command": "qwen.diff.cancel",
|
|
"title": "Qwen Code: Close Diff Editor",
|
|
"icon": "$(close)"
|
|
},
|
|
{
|
|
"command": "qwen-code.runQwenCode",
|
|
"title": "Qwen Code: Run"
|
|
},
|
|
{
|
|
"command": "qwen-code.showNotices",
|
|
"title": "Qwen Code: View Third-Party Notices"
|
|
},
|
|
{
|
|
"command": "qwen-code.openChat",
|
|
"title": "Qwen Code: Open",
|
|
"icon": "./assets/icon.png"
|
|
},
|
|
{
|
|
"command": "qwen-code.auth",
|
|
"title": "Qwen Code: Auth"
|
|
},
|
|
{
|
|
"command": "qwen-code.focusChat",
|
|
"title": "Qwen Code: Focus Chat View"
|
|
},
|
|
{
|
|
"command": "qwen-code.newConversation",
|
|
"title": "Qwen Code: New Conversation"
|
|
},
|
|
{
|
|
"command": "qwen-code.showLogs",
|
|
"title": "Qwen Code: Show Logs"
|
|
},
|
|
{
|
|
"command": "qwen-code.copyMessage",
|
|
"title": "%qwen-code.copyMessage.title%"
|
|
},
|
|
{
|
|
"command": "qwen-code.copyAllMessages",
|
|
"title": "%qwen-code.copyAllMessages.title%"
|
|
},
|
|
{
|
|
"command": "qwen-code.copyLastReply",
|
|
"title": "%qwen-code.copyLastReply.title%"
|
|
}
|
|
],
|
|
"menus": {
|
|
"commandPalette": [
|
|
{
|
|
"command": "qwen.diff.accept",
|
|
"when": "qwen.diff.isVisible"
|
|
},
|
|
{
|
|
"command": "qwen.diff.cancel",
|
|
"when": "qwen.diff.isVisible"
|
|
},
|
|
{
|
|
"command": "qwen-code.auth"
|
|
},
|
|
{
|
|
"command": "qwen-code.copyMessage",
|
|
"when": "false"
|
|
},
|
|
{
|
|
"command": "qwen-code.copyAllMessages",
|
|
"when": "false"
|
|
},
|
|
{
|
|
"command": "qwen-code.copyLastReply",
|
|
"when": "false"
|
|
}
|
|
],
|
|
"webview/context": [
|
|
{
|
|
"command": "qwen-code.copyMessage",
|
|
"when": "webviewSection == 'chat-messages'",
|
|
"group": "9_cutcopypaste@1"
|
|
},
|
|
{
|
|
"command": "qwen-code.copyAllMessages",
|
|
"when": "webviewSection == 'chat-messages'",
|
|
"group": "9_cutcopypaste@2"
|
|
},
|
|
{
|
|
"command": "qwen-code.copyLastReply",
|
|
"when": "webviewSection == 'chat-messages'",
|
|
"group": "9_cutcopypaste@3"
|
|
}
|
|
],
|
|
"editor/title": [
|
|
{
|
|
"command": "qwen.diff.accept",
|
|
"when": "qwen.diff.isVisible",
|
|
"group": "navigation"
|
|
},
|
|
{
|
|
"command": "qwen.diff.cancel",
|
|
"when": "qwen.diff.isVisible",
|
|
"group": "navigation"
|
|
},
|
|
{
|
|
"command": "qwen-code.openChat",
|
|
"group": "navigation"
|
|
}
|
|
]
|
|
},
|
|
"configuration": {
|
|
"title": "Qwen Code",
|
|
"properties": {
|
|
"qwen-code.provider": {
|
|
"order": 0,
|
|
"type": "string",
|
|
"enum": [
|
|
"coding-plan",
|
|
"api-key"
|
|
],
|
|
"enumDescriptions": [
|
|
"Alibaba Cloud Coding Plan — configurable from VS Code Settings",
|
|
"Configured via Qwen Code: Auth or the onboarding button"
|
|
],
|
|
"default": "coding-plan",
|
|
"markdownDescription": "**Coding Plan**: enter API Key + Region here to sync `~/.qwen/settings.json`.\n\n**API Key**: use **Qwen Code: Auth** or the onboarding button to configure ModelStudio or custom OpenAI-compatible providers."
|
|
},
|
|
"qwen-code.apiKey": {
|
|
"order": 1,
|
|
"type": "string",
|
|
"default": "",
|
|
"markdownDescription": "API key used for **Coding Plan** settings sync. For **API Key** providers, configure the full provider details through **Qwen Code: Auth**."
|
|
},
|
|
"qwen-code.codingPlanRegion": {
|
|
"order": 2,
|
|
"type": "string",
|
|
"enum": [
|
|
"china",
|
|
"global"
|
|
],
|
|
"enumDescriptions": [
|
|
"China — 阿里云百炼 (aliyun.com)",
|
|
"Global — Alibaba Cloud (alibabacloud.com)"
|
|
],
|
|
"default": "china",
|
|
"markdownDescription": "Region for Coding Plan. _(Only used when Provider is `coding-plan`)_"
|
|
}
|
|
}
|
|
},
|
|
"keybindings": [
|
|
{
|
|
"command": "qwen.diff.accept",
|
|
"key": "ctrl+s",
|
|
"when": "qwen.diff.isVisible"
|
|
},
|
|
{
|
|
"command": "qwen.diff.accept",
|
|
"key": "cmd+s",
|
|
"when": "qwen.diff.isVisible"
|
|
},
|
|
{
|
|
"command": "qwen-code.focusChat",
|
|
"key": "ctrl+shift+l",
|
|
"mac": "cmd+shift+l"
|
|
}
|
|
]
|
|
},
|
|
"main": "./dist/extension.cjs",
|
|
"type": "module",
|
|
"scripts": {
|
|
"prepackage": "node ./scripts/prepackage.js",
|
|
"build": "npm run build:dev",
|
|
"build:dev": "npm run check-types && npm run lint && node esbuild.js",
|
|
"build:prod": "node esbuild.js --production",
|
|
"generate:notices": "node ./scripts/generate-notices.js",
|
|
"prepare": "npm run generate:notices",
|
|
"check-types": "tsc --noEmit",
|
|
"lint": "eslint src",
|
|
"watch": "npm-run-all2 -p watch:*",
|
|
"watch:esbuild": "node esbuild.js --watch",
|
|
"watch:tsc": "tsc --noEmit --watch --project tsconfig.json",
|
|
"package": "vsce package --no-dependencies",
|
|
"test": "vitest run",
|
|
"test:ci": "vitest run --coverage",
|
|
"validate:notices": "node ./scripts/validate-notices.js"
|
|
},
|
|
"devDependencies": {
|
|
"@types/cors": "^2.8.19",
|
|
"@types/express": "^5.0.3",
|
|
"@types/markdown-it": "^14.1.2",
|
|
"@types/node": "20.x",
|
|
"@types/react": "^19.2.10",
|
|
"@types/react-dom": "^19.2.3",
|
|
"@types/semver": "^7.7.1",
|
|
"@types/vscode": "^1.85.0",
|
|
"@typescript-eslint/eslint-plugin": "^8.31.1",
|
|
"@typescript-eslint/parser": "^8.31.1",
|
|
"autoprefixer": "^10.4.22",
|
|
"esbuild": "^0.25.3",
|
|
"eslint": "^9.25.1",
|
|
"eslint-plugin-react-hooks": "^5.2.0",
|
|
"npm-run-all2": "^8.0.2",
|
|
"postcss": "^8.5.6",
|
|
"tailwindcss": "^3.4.18",
|
|
"typescript": "^5.8.3",
|
|
"vitest": "^3.2.4"
|
|
},
|
|
"dependencies": {
|
|
"@agentclientprotocol/sdk": "^0.14.1",
|
|
"@qwen-code/webui": "*",
|
|
"@modelcontextprotocol/sdk": "^1.25.1",
|
|
"cors": "^2.8.5",
|
|
"express": "^5.1.0",
|
|
"markdown-it": "^14.1.0",
|
|
"react": "^19.2.4",
|
|
"react-dom": "^19.2.4",
|
|
"semver": "^7.7.2",
|
|
"zod": "^3.25.76"
|
|
}
|
|
}
|