mirror of
https://github.com/QwenLM/qwen-code.git
synced 2026-05-02 13:40:46 +00:00
feat(channels): add DM pairing flow for sender approval
- Add PairingStore for managing pending requests and approved users - Update SenderGate to support pairing policy with code generation - Add CLI commands: `qwen channel pairing list/approve` - Document pairing flow with rules and usage examples This allows unknown senders to request access via a pairing code that the bot operator approves through the CLI. Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
This commit is contained in:
parent
59ee49e0ab
commit
8753245b5f
9 changed files with 338 additions and 23 deletions
|
|
@ -1,5 +1,21 @@
|
|||
import type { CommandModule, Argv } from 'yargs';
|
||||
import { startCommand } from './channel/start.js';
|
||||
import {
|
||||
pairingListCommand,
|
||||
pairingApproveCommand,
|
||||
} from './channel/pairing.js';
|
||||
|
||||
const pairingCommand: CommandModule = {
|
||||
command: 'pairing',
|
||||
describe: 'Manage DM pairing requests',
|
||||
builder: (yargs: Argv) =>
|
||||
yargs
|
||||
.command(pairingListCommand)
|
||||
.command(pairingApproveCommand)
|
||||
.demandCommand(1, 'You need at least one command before continuing.')
|
||||
.version(false),
|
||||
handler: () => {},
|
||||
};
|
||||
|
||||
export const channelCommand: CommandModule = {
|
||||
command: 'channel',
|
||||
|
|
@ -7,6 +23,7 @@ export const channelCommand: CommandModule = {
|
|||
builder: (yargs: Argv) =>
|
||||
yargs
|
||||
.command(startCommand)
|
||||
.command(pairingCommand)
|
||||
.demandCommand(1, 'You need at least one command before continuing.')
|
||||
.version(false),
|
||||
handler: () => {},
|
||||
|
|
|
|||
66
packages/cli/src/commands/channel/pairing.ts
Normal file
66
packages/cli/src/commands/channel/pairing.ts
Normal file
|
|
@ -0,0 +1,66 @@
|
|||
import type { CommandModule } from 'yargs';
|
||||
import { PairingStore } from '@qwen-code/channel-base';
|
||||
import { writeStderrLine, writeStdoutLine } from '../../utils/stdioHelpers.js';
|
||||
|
||||
export const pairingListCommand: CommandModule<object, { name: string }> = {
|
||||
command: 'list <name>',
|
||||
describe: 'List pending pairing requests for a channel',
|
||||
builder: (yargs) =>
|
||||
yargs.positional('name', {
|
||||
type: 'string',
|
||||
describe: 'Channel name',
|
||||
demandOption: true,
|
||||
}),
|
||||
handler: (argv) => {
|
||||
const store = new PairingStore(argv.name);
|
||||
const pending = store.listPending();
|
||||
|
||||
if (pending.length === 0) {
|
||||
writeStdoutLine('No pending pairing requests.');
|
||||
return;
|
||||
}
|
||||
|
||||
writeStdoutLine(`Pending pairing requests for "${argv.name}":\n`);
|
||||
for (const req of pending) {
|
||||
const ago = Math.round((Date.now() - req.createdAt) / 60000);
|
||||
writeStdoutLine(
|
||||
` Code: ${req.code} Sender: ${req.senderName} (${req.senderId}) ${ago}m ago`,
|
||||
);
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
export const pairingApproveCommand: CommandModule<
|
||||
object,
|
||||
{ name: string; code: string }
|
||||
> = {
|
||||
command: 'approve <name> <code>',
|
||||
describe: 'Approve a pending pairing request',
|
||||
builder: (yargs) =>
|
||||
yargs
|
||||
.positional('name', {
|
||||
type: 'string',
|
||||
describe: 'Channel name',
|
||||
demandOption: true,
|
||||
})
|
||||
.positional('code', {
|
||||
type: 'string',
|
||||
describe: 'Pairing code',
|
||||
demandOption: true,
|
||||
}),
|
||||
handler: (argv) => {
|
||||
const store = new PairingStore(argv.name);
|
||||
const request = store.approve(argv.code);
|
||||
|
||||
if (!request) {
|
||||
writeStderrLine(
|
||||
`No pending request found for code "${argv.code.toUpperCase()}". It may have expired.`,
|
||||
);
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
writeStdoutLine(
|
||||
`Approved: ${request.senderName} (${request.senderId}) can now use channel "${argv.name}".`,
|
||||
);
|
||||
},
|
||||
};
|
||||
Loading…
Add table
Add a link
Reference in a new issue