mirror of
https://github.com/QwenLM/qwen-code.git
synced 2026-04-28 03:30:40 +00:00
* feat(web-search): add GLM (ZhipuAI) web search provider - Add GlmProvider class implementing BaseWebSearchProvider using the ZhipuAI Web Search API (https://open.bigmodel.cn/api/paas/v4/web_search) - Support multiple search engines: search_std, search_pro, search_pro_sogou, search_pro_quark - Support optional config: maxResults, searchIntent, searchRecencyFilter, contentSize, searchDomainFilter - Truncate query to 70 characters per API limit - Register 'glm' in the provider discriminated union (types.ts) and createProvider() switch (index.ts) - Add GlmProviderConfig to settingsSchema, ConfigParams, and Config class - Add --glm-api-key CLI flag and GLM_API_KEY env var support in webSearch.ts - Forward GLM_API_KEY in sandbox environment - Update provider priority list: Tavily > Google > GLM > DashScope - Add 17 unit tests for GlmProvider and 4 integration tests in index.test.ts - Update docs/developers/tools/web-search.md with GLM configuration, env vars, CLI args, pricing, and corrected DashScope billing info - Fix stale OAuth/free-tier references in web-search.md Closes #3496 * docs(web-search): fix DashScope note and add GLM server-side limitations * fix(web-search): make DashScope provider work with standard API key, remove qwen-oauth dependency - DashScopeProvider.isAvailable() now checks config.apiKey instead of authType - Remove OAuth credential file reading and resource_url requirement - Use standard DashScope endpoint: dashscope.aliyuncs.com/api/v1/indices/plugin/web_search - Read DASHSCOPE_API_KEY env var and --dashscope-api-key CLI flag - Forward DASHSCOPE_API_KEY into sandbox environment - Update integration test to detect DASHSCOPE_API_KEY - Update docs to reflect new API key based configuration * feat(web-search): remove built-in web search tool The web_search tool and all related provider implementations are removed. Web search functionality will be provided via MCP integrations instead, which is the direction the broader agent ecosystem is moving. Removed: - packages/core/src/tools/web-search/ (entire directory) - packages/cli/src/config/webSearch.ts - integration-tests/cli/web_search.test.ts - ToolNames.WEB_SEARCH, ToolErrorCode.WEB_SEARCH_FAILED - webSearch config in ConfigParams, Config class, settingsSchema - CLI options: --tavily-api-key, --google-api-key, --google-search-engine-id, --glm-api-key, --dashscope-api-key, --web-search-default - Sandbox env forwarding for TAVILY/GLM/DASHSCOPE/GOOGLE search keys - web_search from rule-parser, permission-manager, speculation gate, microcompact tool set, and builtin-agents tool list * fix: remove websearch reference * docs: remove websearch tool * docs: add break change guide * fix review |
||
|---|---|---|
| .. | ||
| .storybook | ||
| docs | ||
| examples | ||
| scripts | ||
| src | ||
| .npmignore | ||
| package.json | ||
| postcss.config.cjs | ||
| README.md | ||
| tailwind.config.cjs | ||
| tailwind.preset.cjs | ||
| tsconfig.json | ||
| vite.config.ts | ||
@qwen-code/webui
A shared React component library for Qwen Code applications, providing cross-platform UI components with consistent styling and behavior.
Features
- Cross-platform support: Components work seamlessly across VS Code extension, web, and other platforms
- Platform Context: Abstraction layer for platform-specific capabilities
- Tailwind CSS: Shared styling preset for consistent design
- TypeScript: Full type definitions for all components
- Storybook: Interactive component documentation and development
- Multiple Build Formats: Supports ESM, CJS, and UMD formats for different environments
- CDN Usage: Can be loaded directly in browsers via CDN
Installation
npm install @qwen-code/webui
CDN Usage
You can also use this library directly in the browser via CDN:
Option 1: With JSX Support (using Babel)
<!DOCTYPE html>
<html>
<head>
<!-- Load React -->
<script
crossorigin
src="https://unpkg.com/react@18/umd/react.production.min.js"
></script>
<script
crossorigin
src="https://unpkg.com/react-dom@18/umd/react-dom.production.min.js"
></script>
<!-- Load Babel Standalone for JSX processing -->
<script src="https://unpkg.com/@babel/standalone@7.23.6/babel.min.js"></script>
<!-- Manually create the jsxRuntime object to satisfy the dependency -->
<script>
// Provide a minimal JSX runtime for builds that expect react/jsx-runtime globals.
const withKey = (props, key) =>
key == null ? props : Object.assign({}, props, { key });
const jsx = (type, props, key) =>
React.createElement(type, withKey(props, key));
const jsxRuntime = {
Fragment: React.Fragment,
jsx,
jsxs: jsx,
jsxDEV: jsx,
};
window.ReactJSXRuntime = jsxRuntime;
window['react/jsx-runtime'] = jsxRuntime;
window['react/jsx-dev-runtime'] = jsxRuntime;
</script>
<!-- Load the webui library -->
<script src="https://unpkg.com/@qwen-code/webui@0.1.0-beta.2/dist/index.umd.js"></script>
<!-- Load the CSS -->
<link
rel="stylesheet"
href="https://unpkg.com/@qwen-code/webui@0.1.0-beta.2/dist/styles.css"
/>
</head>
<body>
<div id="root"></div>
<script type="text/babel">
// Access components from the global QwenCodeWebUI object
const { ChatViewer } = QwenCodeWebUI;
// Use the components with JSX support
const App = () => (
<ChatViewer messages={/* your messages */} />
);
ReactDOM.render(<App />, document.getElementById('root'));
</script>
</body>
</html>
Option 2: Without JSX (using React.createElement directly)
<!DOCTYPE html>
<html>
<head>
<!-- Load React -->
<script
crossorigin
src="https://unpkg.com/react@18/umd/react.production.min.js"
></script>
<script
crossorigin
src="https://unpkg.com/react-dom@18/umd/react-dom.production.min.js"
></script>
<!-- Manually create the jsxRuntime object to satisfy the dependency -->
<script>
// Provide a minimal JSX runtime for builds that expect react/jsx-runtime globals.
const withKey = (props, key) =>
key == null ? props : Object.assign({}, props, { key });
const jsx = (type, props, key) =>
React.createElement(type, withKey(props, key));
const jsxRuntime = {
Fragment: React.Fragment,
jsx,
jsxs: jsx,
jsxDEV: jsx,
};
window.ReactJSXRuntime = jsxRuntime;
window['react/jsx-runtime'] = jsxRuntime;
window['react/jsx-dev-runtime'] = jsxRuntime;
</script>
<!-- Load the webui library -->
<script src="https://unpkg.com/@qwen-code/webui@0.1.0-beta.2/dist/index.umd.js"></script>
<!-- Load the CSS -->
<link
rel="stylesheet"
href="https://unpkg.com/@qwen-code/webui@0.1.0-beta.2/dist/styles.css"
/>
</head>
<body>
<div id="root"></div>
<script>
// Access components from the global QwenCodeWebUI object
const { ChatViewer } = QwenCodeWebUI;
// Use the components with React.createElement (no JSX)
const App = React.createElement(ChatViewer, {
messages: [
/* your messages */
],
});
ReactDOM.render(App, document.getElementById('root'));
</script>
</body>
</html>
For a complete working example, see examples/cdn-usage-demo.html.
Quick Start
import { Button, Input, Tooltip } from '@qwen-code/webui';
import { PlatformProvider } from '@qwen-code/webui/context';
function App() {
return (
<PlatformProvider value={platformContext}>
<Button variant="primary" onClick={handleClick}>
Click me
</Button>
</PlatformProvider>
);
}
Components
UI Components
Button
import { Button } from '@qwen-code/webui';
<Button variant="primary" size="md" loading={false}>
Submit
</Button>;
Props:
variant: 'primary' | 'secondary' | 'danger' | 'ghost' | 'outline'size: 'sm' | 'md' | 'lg'loading: booleanleftIcon: ReactNoderightIcon: ReactNodefullWidth: boolean
Input
import { Input } from '@qwen-code/webui';
<Input
label="Email"
placeholder="Enter email"
error={hasError}
errorMessage="Invalid email"
/>;
Props:
size: 'sm' | 'md' | 'lg'error: booleanerrorMessage: stringlabel: stringhelperText: stringleftElement: ReactNoderightElement: ReactNode
Tooltip
import { Tooltip } from '@qwen-code/webui';
<Tooltip content="Helpful tip">
<span>Hover me</span>
</Tooltip>;
Icons
import { FileIcon, FolderIcon, CheckIcon } from '@qwen-code/webui/icons';
<FileIcon size={16} className="text-gray-500" />;
Available icon categories:
- FileIcons: FileIcon, FolderIcon, SaveDocumentIcon
- StatusIcons: CheckIcon, ErrorIcon, WarningIcon, LoadingIcon
- NavigationIcons: ArrowLeftIcon, ArrowRightIcon, ChevronIcon
- EditIcons: EditIcon, DeleteIcon, CopyIcon
- SpecialIcons: SendIcon, StopIcon, CloseIcon
Layout Components
Container: Main layout wrapperHeader: Application headerFooter: Application footerSidebar: Side navigationMain: Main content area
Message Components
Message: Chat message displayMessageList: List of messagesMessageInput: Message input fieldWaitingMessage: Loading/waiting stateInterruptedMessage: Interrupted state display
Platform Context
The Platform Context provides an abstraction layer for platform-specific capabilities:
import { PlatformProvider, usePlatform } from '@qwen-code/webui/context';
const platformContext = {
postMessage: (message) => vscode.postMessage(message),
onMessage: (handler) => {
window.addEventListener('message', handler);
return () => window.removeEventListener('message', handler);
},
openFile: (path) => {
/* platform-specific */
},
platform: 'vscode',
};
function App() {
return (
<PlatformProvider value={platformContext}>
<YourApp />
</PlatformProvider>
);
}
function Component() {
const { postMessage, platform } = usePlatform();
// Use platform capabilities
}
Tailwind Preset
Use the shared Tailwind preset for consistent styling:
// tailwind.config.js
module.exports = {
presets: [require('@qwen-code/webui/tailwind.preset.cjs')],
// your customizations
};
Development
Running Storybook
cd packages/webui
npm run storybook
Building
npm run build
Type Checking
npm run typecheck
Project Structure
packages/webui/
├── src/
│ ├── components/
│ │ ├── icons/ # Icon components
│ │ ├── layout/ # Layout components
│ │ ├── messages/ # Message components
│ │ └── ui/ # UI primitives
│ ├── context/ # Platform context
│ ├── hooks/ # Custom hooks
│ └── types/ # Type definitions
├── .storybook/ # Storybook config
├── tailwind.preset.cjs # Shared Tailwind preset
└── vite.config.ts # Build configuration
License
Apache-2.0