mirror of
https://github.com/QwenLM/qwen-code.git
synced 2026-04-28 11:41:04 +00:00
feat(channels): make plugin-example package publishable
- Update channel-base to use built dist/ output with proper exports - Add README with quick start guide and usage instructions - Add qwen-extension.json manifest for extension discovery - Add start-server CLI for running the mock WebSocket server - Update dependencies from local file: to npm version This enables the plugin-example package to be published and installed as a standalone extension for testing the channel plugin system. Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
This commit is contained in:
parent
987eebd1c4
commit
c97c548acb
7 changed files with 180 additions and 9 deletions
2
package-lock.json
generated
2
package-lock.json
generated
|
|
@ -18994,7 +18994,7 @@
|
|||
"name": "@qwen-code/channel-plugin-example",
|
||||
"version": "0.1.0",
|
||||
"dependencies": {
|
||||
"@qwen-code/channel-base": "file:../base",
|
||||
"@qwen-code/channel-base": "^0.1.0",
|
||||
"ws": "^8.18.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
|
|
|||
|
|
@ -3,10 +3,19 @@
|
|||
"version": "0.1.0",
|
||||
"description": "Base channel infrastructure for Qwen Code",
|
||||
"type": "module",
|
||||
"main": "src/index.ts",
|
||||
"types": "src/index.ts",
|
||||
"main": "dist/index.js",
|
||||
"types": "dist/index.d.ts",
|
||||
"exports": {
|
||||
".": "./src/index.ts"
|
||||
".": {
|
||||
"types": "./dist/index.d.ts",
|
||||
"default": "./dist/index.js"
|
||||
}
|
||||
},
|
||||
"files": [
|
||||
"dist"
|
||||
],
|
||||
"scripts": {
|
||||
"build": "tsc --build"
|
||||
},
|
||||
"dependencies": {
|
||||
"@agentclientprotocol/sdk": "^0.14.1"
|
||||
|
|
|
|||
97
packages/channels/plugin-example/README.md
Normal file
97
packages/channels/plugin-example/README.md
Normal file
|
|
@ -0,0 +1,97 @@
|
|||
# @qwen-code/channel-plugin-example
|
||||
|
||||
A reference channel plugin for Qwen Code. It connects to a WebSocket server and routes messages through the full channel pipeline (access control, session routing, agent bridge).
|
||||
|
||||
Use this package to:
|
||||
|
||||
- **Try out the channel plugin system** — install it as an extension and run it with the built-in mock server
|
||||
- **Use it as a starting point** — fork the source to build your own channel adapter (see the [Channel Plugin Developer Guide](../../docs/developers/channel-plugins.md))
|
||||
|
||||
## Quick start
|
||||
|
||||
### 1. Install the package
|
||||
|
||||
```bash
|
||||
npm install @qwen-code/channel-plugin-example
|
||||
```
|
||||
|
||||
### 2. Link it as a Qwen Code extension
|
||||
|
||||
The package ships a `qwen-extension.json` manifest, so it works as an extension out of the box:
|
||||
|
||||
```bash
|
||||
qwen extensions link ./node_modules/@qwen-code/channel-plugin-example
|
||||
```
|
||||
|
||||
### 3. Configure the channel
|
||||
|
||||
Add a channel entry to `~/.qwen/settings.json`:
|
||||
|
||||
```json
|
||||
{
|
||||
"channels": {
|
||||
"my-plugin-test": {
|
||||
"type": "plugin-example",
|
||||
"serverWsUrl": "ws://localhost:9201",
|
||||
"senderPolicy": "open",
|
||||
"sessionScope": "user",
|
||||
"cwd": "/path/to/your/project"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 4. Start the mock server
|
||||
|
||||
```bash
|
||||
npx qwen-channel-plugin-example-server
|
||||
```
|
||||
|
||||
The server prints the HTTP and WebSocket URLs. You can customize ports with environment variables:
|
||||
|
||||
```bash
|
||||
HTTP_PORT=8080 WS_PORT=8081 npx qwen-channel-plugin-example-server
|
||||
```
|
||||
|
||||
### 5. Start the channel
|
||||
|
||||
In a separate terminal:
|
||||
|
||||
```bash
|
||||
qwen channel start my-plugin-test
|
||||
```
|
||||
|
||||
### 6. Send a message
|
||||
|
||||
```bash
|
||||
curl -sX POST http://localhost:9200/message \
|
||||
-H 'Content-Type: application/json' \
|
||||
-d '{"senderId":"user1","senderName":"Tester","text":"What is 2+2?"}'
|
||||
```
|
||||
|
||||
You should get a JSON response with the agent's reply.
|
||||
|
||||
## How it works
|
||||
|
||||
```
|
||||
Mock Server (HTTP + WS)
|
||||
↕ WebSocket
|
||||
MockPluginChannel (this package)
|
||||
→ Envelope → ChannelBase.handleInbound()
|
||||
→ SenderGate → SessionRouter → AcpBridge.prompt()
|
||||
→ qwen-code agent → model API
|
||||
← response
|
||||
← sendMessage() → WebSocket → Mock Server
|
||||
← HTTP response
|
||||
```
|
||||
|
||||
## Building your own channel
|
||||
|
||||
See `src/MockPluginChannel.ts` for a working example. The key points:
|
||||
|
||||
1. Extend `ChannelBase` and implement `connect()`, `sendMessage()`, `disconnect()`
|
||||
2. Build an `Envelope` from incoming platform messages and call `this.handleInbound(envelope)`
|
||||
3. Export a `plugin` object conforming to `ChannelPlugin`
|
||||
4. Add a `qwen-extension.json` manifest
|
||||
|
||||
Full guide: [Channel Plugin Developer Guide](../../docs/developers/channel-plugins.md)
|
||||
|
|
@ -2,13 +2,27 @@
|
|||
"name": "@qwen-code/channel-plugin-example",
|
||||
"version": "0.1.0",
|
||||
"type": "module",
|
||||
"main": "src/index.ts",
|
||||
"types": "src/index.ts",
|
||||
"main": "dist/index.js",
|
||||
"types": "dist/index.d.ts",
|
||||
"exports": {
|
||||
".": "./src/index.ts"
|
||||
".": {
|
||||
"types": "./dist/index.d.ts",
|
||||
"default": "./dist/index.js"
|
||||
}
|
||||
},
|
||||
"files": [
|
||||
"dist",
|
||||
"src",
|
||||
"qwen-extension.json"
|
||||
],
|
||||
"bin": {
|
||||
"qwen-channel-plugin-example-server": "dist/start-server.js"
|
||||
},
|
||||
"scripts": {
|
||||
"build": "tsc --build"
|
||||
},
|
||||
"dependencies": {
|
||||
"@qwen-code/channel-base": "file:../base",
|
||||
"@qwen-code/channel-base": "^0.1.0",
|
||||
"ws": "^8.18.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
|
|
|||
10
packages/channels/plugin-example/qwen-extension.json
Normal file
10
packages/channels/plugin-example/qwen-extension.json
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
{
|
||||
"name": "qwen-channel-plugin-example",
|
||||
"version": "0.1.0",
|
||||
"channels": {
|
||||
"plugin-example": {
|
||||
"entry": "dist/index.js",
|
||||
"displayName": "Plugin Example Channel"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -12,5 +12,10 @@ export const plugin: ChannelPlugin = {
|
|||
displayName: 'Plugin Example',
|
||||
requiredConfigFields: ['serverWsUrl'],
|
||||
createChannel: (name, config, bridge, options) =>
|
||||
new MockPluginChannel(name, config as MockPluginConfig, bridge, options),
|
||||
new MockPluginChannel(
|
||||
name,
|
||||
config as typeof config & { serverWsUrl: string },
|
||||
bridge,
|
||||
options,
|
||||
),
|
||||
};
|
||||
|
|
|
|||
36
packages/channels/plugin-example/src/start-server.ts
Normal file
36
packages/channels/plugin-example/src/start-server.ts
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
#!/usr/bin/env node
|
||||
/* eslint-disable no-console */
|
||||
/**
|
||||
* Start the mock WebSocket server for testing the plugin-example channel.
|
||||
*
|
||||
* Usage:
|
||||
* npx qwen-channel-plugin-example-server
|
||||
* # or
|
||||
* node node_modules/@qwen-code/channel-plugin-example/dist/start-server.js
|
||||
*
|
||||
* Environment variables:
|
||||
* HTTP_PORT (default: 9200)
|
||||
* WS_PORT (default: 9201)
|
||||
*/
|
||||
import { createMockServer } from './mock-server.js';
|
||||
|
||||
const httpPort = parseInt(process.env['HTTP_PORT'] || '9200', 10);
|
||||
const wsPort = parseInt(process.env['WS_PORT'] || '9201', 10);
|
||||
|
||||
const server = await createMockServer({ httpPort, wsPort });
|
||||
|
||||
console.log(`Mock server running:`);
|
||||
console.log(` HTTP: http://localhost:${server.httpPort}`);
|
||||
console.log(` WS: ws://localhost:${server.wsPort}`);
|
||||
console.log();
|
||||
console.log(`Send a test message:`);
|
||||
console.log(` curl -sX POST http://localhost:${server.httpPort}/message \\`);
|
||||
console.log(` -H 'Content-Type: application/json' \\`);
|
||||
console.log(
|
||||
` -d '{"senderId":"user1","senderName":"Tester","text":"Hello"}'`,
|
||||
);
|
||||
|
||||
process.on('SIGINT', async () => {
|
||||
await server.close();
|
||||
process.exit(0);
|
||||
});
|
||||
Loading…
Add table
Add a link
Reference in a new issue