mirror of
https://github.com/QwenLM/qwen-code.git
synced 2026-05-15 01:04:44 +00:00
* fix(core): address post-merge monitor tool and UI routing issues - Guard token bucket against clock drift after system suspend/resume (negative elapsed resets lastRefill instead of starving the bucket) - Add debugLogger.warn for AST read-only check failures in monitor getConfirmationDetails (previously silent catch) - Consolidate SHELL_TOOL_NAMES: export from rule-parser.ts, import in permission-manager.ts (removes identical SHELL_LIKE_TOOLS duplicate) - Extract hasBlockingBackgroundWork/resetBackgroundStateForSessionSwitch to shared backgroundWorkUtils.ts (removes identical copies in clearCommand.ts and useResumeCommand.ts) - Consolidate getToolCallComponent routing into packages/webui (removes near-identical copies in ChatViewer.tsx and vscode-ide-companion, adds missing web_search compat alias to VSCode path) - Add test for droppedLines count in terminal notification text - Add test for exit(null, null) settlement (externally killed process) 🤖 Generated with [Qwen Code](https://github.com/QwenLM/qwen-code) * fix(core,cli,vscode): address PR #3792 review feedback - Add debugLogger.warn for clock-drift guard (observability for throttle bucket resets after suspend/resume) - Add test for clock-drift recovery (elapsed < 0 bucket reset) - Add test for AST parse failure catch path (mockRejectedValueOnce) - Forward isFirst/isLast props through VSCode ToolCallRouter (fixes timeline connector rendering) - Add test for shell running branch in hasBlockingBackgroundWork 🤖 Generated with [Qwen Code](https://github.com/QwenLM/qwen-code) * fix(core,vscode): address follow-up review comments - Fix React.FC missing import: use `import type { FC } from 'react'` instead of `React.FC` (original file had this import before refactor) - Tighten clock-drift test: emit while clock is in the past to confirm guard resets lastRefill, then verify refill at the new reference point 🤖 Generated with [Qwen Code](https://github.com/QwenLM/qwen-code) * fix(core,cli): adopt review feedback — ReadonlySet + hasRunningEntries - Type SHELL_TOOL_NAMES as ReadonlySet<string> to prevent accidental mutation of permission-critical set - Use BackgroundShellRegistry.hasRunningEntries() instead of getAll().some() for zero-allocation short-circuit check - Update clearCommand test mocks to include hasRunningEntries 🤖 Generated with [Qwen Code](https://github.com/QwenLM/qwen-code) * fix(core,webui,vscode): address remaining PR #3792 review comments - Merge AgentToolCall + isAgentExecutionToolCall into single import in routing.ts (comment 3178280762) - Use real getToolCallComponent via vi.importActual in VSCode test mock so routing logic is validated, not a parallel mock that can drift (comment 3178280775) - Validate isFirst/isLast forwarding in VSCode test mock via data attributes (comment 3178346891) - Add comment documenting debugLogger.warn no-op tradeoff for clock drift guard (comment 3178346889) 🤖 Generated with [Qwen Code](https://github.com/QwenLM/qwen-code) * test(webui): add unit test for getToolCallComponent routing Covers all 8 component branches including the web_search compatibility alias, agent execution detection, case-insensitive matching, and fallback to GenericToolCall. 🤖 Generated with [Qwen Code](https://github.com/QwenLM/qwen-code) * fix(cli): add missing hasRunningEntries to useResumeCommand test mocks The backgroundWorkUtils refactor replaced getAll().some() with hasRunningEntries(), but the test mocks in useResumeCommand.test.ts were not updated, causing CI failures. 🤖 Generated with [Qoder Code](https://github.com/QwenLM/qwen-code) * test(cli): add unit tests for backgroundWorkUtils shared utility Cover hasBlockingBackgroundWork (6 cases including short-circuit behaviour) and resetBackgroundStateForSessionSwitch (1 case verifying all three registries are reset). 🤖 Generated with [Qoder Code](https://github.com/QwenLM/qwen-code) --------- Co-authored-by: jinye.djy <jinye.djy@alibaba-inc.com> |
||
|---|---|---|
| .. | ||
| .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