SuperCharge Claude Code v1.0.0 - Complete Customization Package

Features:
- 30+ Custom Skills (cognitive, development, UI/UX, autonomous agents)
- RalphLoop autonomous agent integration
- Multi-AI consultation (Qwen)
- Agent management system with sync capabilities
- Custom hooks for session management
- MCP servers integration
- Plugin marketplace setup
- Comprehensive installation script

Components:
- Skills: always-use-superpowers, ralph, brainstorming, ui-ux-pro-max, etc.
- Agents: 100+ agents across engineering, marketing, product, etc.
- Hooks: session-start-superpowers, qwen-consult, ralph-auto-trigger
- Commands: /brainstorm, /write-plan, /execute-plan
- MCP Servers: zai-mcp-server, web-search-prime, web-reader, zread
- Binaries: ralphloop wrapper

Installation: ./supercharge.sh
This commit is contained in:
uroma
2026-01-22 15:35:55 +00:00
Unverified
commit 7a491b1548
1013 changed files with 170070 additions and 0 deletions

View File

@@ -0,0 +1,173 @@
---
name: multi-ai-brainstorm
description: "Multi-AI brainstorming using Qwen coder-model. Collaborate with multiple AI agents (content, seo, smm, pm, code, design, web, app) for expert-level ideation. Use before any creative work for diverse perspectives."
---
# Multi-AI Brainstorm 🧠
> **Powered by Qwen Coder-Model** from PromptArch
> Enables collaborative brainstorming with 8 specialized AI agents
## Overview
This skill transforms Claude into a multi-brain collaboration system, leveraging Qwen's coder-model to provide diverse expert perspectives through specialized AI agents. Each agent brings unique domain expertise to the brainstorming process.
## How It Works
1. **Authentication**: First use will prompt for Qwen API key or OAuth token
2. **Agent Selection**: Choose from 8 specialized AI agents or use all for comprehensive brainstorming
3. **Collaborative Process**: Each agent provides insights from their domain perspective
4. **Synthesis**: Claude synthesizes all perspectives into actionable insights
## Available AI Agents
| Agent | Expertise | Best For |
|-------|-----------|----------|
| **content** | Copywriting & Communication | Blog posts, marketing copy, documentation |
| **seo** | Search Engine Optimization | SEO audits, keyword research, content strategy |
| **smm** | Social Media Marketing | Content calendars, campaign strategies |
| **pm** | Product Management | PRDs, roadmaps, feature prioritization |
| **code** | Software Architecture | Backend logic, algorithms, technical design |
| **design** | UI/UX Design | Mockups, design systems, user flows |
| **web** | Frontend Development | Responsive sites, web apps |
| **app** | Mobile Development | iOS/Android apps, mobile-first design |
## Usage
### Basic Brainstorming
```bash
# Start brainstorming with all agents
/multi-ai-brainstorm "I want to build a collaborative code editor"
# Use specific agents
/multi-ai-brainstorm "mobile app for fitness tracking" --agents design,app,pm
# Deep dive with one agent
/multi-ai-brainstorm "SEO strategy for SaaS product" --agents seo
```
### Configuration
The skill stores credentials in `~/.claude/qwen-credentials.json`:
```json
{
"apiKey": "sk-...",
"endpoint": "https://dashscope-intl.aliyuncs.com/compatible-mode/v1"
}
```
## Agent Prompts
Each agent has specialized system prompts:
### Content Agent
Expert copywriter focused on creating engaging, clear, and persuasive content for various formats and audiences.
### SEO Agent
Search engine optimization specialist with expertise in technical SEO, content strategy, and performance analytics.
### SMM Agent
Social media manager specializing in multi-platform content strategies, community engagement, and viral marketing.
### PM Agent
Product manager experienced in PRD creation, roadmap planning, stakeholder management, and agile methodologies.
### Code Agent
Software architect focused on backend logic, algorithms, API design, and system architecture.
### Design Agent
UI/UX designer specializing in user research, interaction design, visual design systems, and accessibility.
### Web Agent
Frontend developer expert in responsive web design, modern frameworks (React, Vue, Angular), and web performance.
### App Agent
Mobile app developer specializing in iOS/Android development, React Native, Flutter, and mobile-first design patterns.
## Authentication Methods
### 1. API Key (Simple)
```bash
# You'll be prompted for your Qwen API key
# Get your key at: https://help.aliyun.com/zh/dashscope/
```
### 2. OAuth (Recommended - 2000 free daily requests)
```bash
# The skill will open a browser window for OAuth flow
# Or provide the device code manually
```
## Examples
### Product Ideation
```bash
/multi-ai-brainstorm "I want to create a AI-powered task management app" --agents pm,design,code
```
**Output:**
- **PM Agent**: Feature prioritization, user personas, success metrics
- **Design Agent**: UX patterns, visual direction, user flows
- **Code Agent**: Architecture recommendations, tech stack selection
### Content Strategy
```bash
/multi-ai-brainstorm "Blog content strategy for developer tools startup" --agents content,seo,smm
```
**Output:**
- **Content Agent**: Content pillars, editorial calendar, tone guidelines
- **SEO Agent**: Keyword research, on-page optimization, link building
- **SMM Agent**: Social distribution, engagement tactics, viral loops
## Technical Details
**API Endpoint**: Uses PromptArch proxy at `https://www.rommark.dev/tools/promptarch/api/qwen/chat`
**Model**: `coder-model` - Qwen's code-optimized model
**Rate Limits**:
- OAuth: 2000 free daily requests
- API Key: Based on your Qwen account plan
**Streaming**: Supports real-time streaming responses for longer brainstorming sessions
## Tips for Best Results
1. **Be Specific**: More context = better insights from each agent
2. **Combine Agents**: Use complementary agents (e.g., design + pm + code)
3. **Iterate**: Follow up with questions to dive deeper into specific insights
4. **Provide Context**: Share your target audience, constraints, and goals
5. **Use Examples**: Show similar products or content for reference
## Troubleshooting
**"Authentication failed"**
- Check your API key or OAuth token
- Verify endpoint URL is correct
- Try running `/multi-ai-brainstorm --reauth`
**"Agent timeout"**
- Check your internet connection
- The Qwen API might be experiencing high load
- Try again in a few moments
**"Unexpected response format"**
- The API response format may have changed
- Report the issue and include the error message
## Development
**Skill Location**: `~/.claude/skills/multi-ai-brainstorm/`
**Key Files**:
- `SKILL.md` - This file
- `qwen-client.js` - Qwen API client
- `brainstorm-orchestrator.js` - Multi-agent coordination
**Contributing**: Modify the agent prompts in `brainstorm-orchestrator.js` to customize brainstorming behavior.
## License
This skill uses the Qwen API which is subject to Alibaba Cloud's terms of service.

View File

@@ -0,0 +1,310 @@
/**
* Multi-AI Brainstorm Orchestrator
* Coordinates multiple specialized AI agents for collaborative brainstorming
*/
const qwenClient = require('./qwen-client.js');
/**
* Agent System Prompts
*/
const AGENT_SYSTEM_PROMPTS = {
content: `You are an expert Content Specialist and Copywriter. Your role is to provide insights on content creation, messaging, and communication strategies.
Focus on:
- Content tone and voice
- Audience engagement
- Content structure and flow
- Clarity and persuasiveness
- Brand storytelling
Provide practical, actionable content insights.`,
seo: `You are an expert SEO Specialist with deep knowledge of search engine optimization, content strategy, and digital marketing.
Focus on:
- Keyword research and strategy
- On-page and technical SEO
- Content optimization for search
- Link building and authority
- SEO performance metrics
- Competitor SEO analysis
Provide specific, data-driven SEO recommendations.`,
smm: `You are an expert Social Media Manager specializing in multi-platform content strategies, community engagement, and viral marketing.
Focus on:
- Platform-specific content strategies (LinkedIn, Twitter, Instagram, TikTok, etc.)
- Content calendars and scheduling
- Community building and engagement
- Influencer collaboration strategies
- Social media analytics and KPIs
- Viral content mechanics
Provide actionable social media marketing insights.`,
pm: `You are an expert Product Manager with extensive experience in product strategy, PRD creation, roadmap planning, and stakeholder management.
Focus on:
- Product vision and strategy
- Feature prioritization frameworks
- User personas and use cases
- Go-to-market strategies
- Success metrics and KPIs
- Agile development processes
- Stakeholder communication
Provide structured product management insights.`,
code: `You are an expert Software Architect specializing in backend logic, system design, algorithms, and technical implementation.
Focus on:
- System architecture and design patterns
- Algorithm design and optimization
- API design and integration
- Database design and optimization
- Security best practices
- Scalability and performance
- Technology stack recommendations
Provide concrete technical implementation guidance.`,
design: `You are a world-class UI/UX Designer with deep expertise in user research, interaction design, visual design systems, and modern design tools.
Focus on:
- User research and persona development
- Information architecture and navigation
- Visual design systems (color, typography, spacing)
- Interaction design and micro-interactions
- Design trends and best practices
- Accessibility and inclusive design
- Design tools and deliverables
Provide specific, actionable UX recommendations.`,
web: `You are an expert Frontend Developer specializing in responsive web design, modern JavaScript frameworks, and web performance optimization.
Focus on:
- Modern frontend frameworks (React, Vue, Angular, Svelte)
- Responsive design and mobile-first approach
- Web performance optimization
- CSS strategies (Tailwind, CSS-in-JS, styled-components)
- Component libraries and design systems
- Progressive Web Apps
- Browser compatibility
Provide practical frontend development insights.`,
app: `You are an expert Mobile App Developer specializing in iOS and Android development, React Native, Flutter, and mobile-first design patterns.
Focus on:
- Mobile app architecture (native vs cross-platform)
- Platform-specific best practices (iOS, Android)
- Mobile UI/UX patterns
- Performance optimization for mobile
- App store optimization (ASO)
- Mobile-specific constraints and opportunities
- Push notifications and engagement
Provide actionable mobile development insights.`
};
/**
* Available agents
*/
const AVAILABLE_AGENTS = Object.keys(AGENT_SYSTEM_PROMPTS);
/**
* Brainstorm orchestrator class
*/
class BrainstormOrchestrator {
constructor() {
this.agents = AVAILABLE_AGENTS;
}
/**
* Validate agent selection
*/
validateAgents(selectedAgents) {
if (!selectedAgents || selectedAgents.length === 0) {
return this.agents; // Return all agents if none specified
}
const valid = selectedAgents.filter(agent => this.agents.includes(agent));
const invalid = selectedAgents.filter(agent => !this.agents.includes(agent));
if (invalid.length > 0) {
console.warn(`⚠️ Unknown agents ignored: ${invalid.join(', ')}`);
}
return valid.length > 0 ? valid : this.agents;
}
/**
* Generate brainstorming prompt for a specific agent
*/
generateAgentPrompt(topic, agent) {
const systemPrompt = AGENT_SYSTEM_PROMPTS[agent];
return `# Brainstorming Request
**Topic**: ${topic}
**Your Role**: ${agent.toUpperCase()} Specialist
**Instructions**:
1. Analyze this topic from your ${agent} perspective
2. Provide 3-5 unique insights or recommendations
3. Be specific and actionable
4. Consider opportunities, challenges, and best practices
5. Think creatively but stay grounded in practical reality
Format your response as clear bullet points or numbered lists.
`;
}
/**
* Execute brainstorming with multiple agents
*/
async brainstorm(topic, options = {}) {
const {
agents = [],
concurrency = 3
} = options;
const selectedAgents = this.validateAgents(agents);
const results = {};
console.log(`\n🧠 Multi-AI Brainstorming Session`);
console.log(`📝 Topic: ${topic}`);
console.log(`👥 Agents: ${selectedAgents.map(a => a.toUpperCase()).join(', ')}`);
console.log(`\n⏳ Gathering insights...\n`);
// Process agents in batches for controlled concurrency
for (let i = 0; i < selectedAgents.length; i += concurrency) {
const batch = selectedAgents.slice(i, i + concurrency);
const batchPromises = batch.map(async (agent) => {
try {
const userPrompt = this.generateAgentPrompt(topic, agent);
const messages = [
{ role: 'system', content: AGENT_SYSTEM_PROMPTS[agent] },
{ role: 'user', content: userPrompt }
];
const response = await qwenClient.chatCompletion(messages, {
temperature: 0.8,
maxTokens: 1000
});
return { agent, response, success: true };
} catch (error) {
return { agent, error: error.message, success: false };
}
});
const batchResults = await Promise.all(batchPromises);
for (const result of batchResults) {
if (result.success) {
results[result.agent] = result.response;
console.log(`${result.agent.toUpperCase()} Agent: Insights received`);
} else {
console.error(`${result.agent.toUpperCase()} Agent: ${result.error}`);
results[result.agent] = `[Error: ${result.error}]`;
}
}
}
return {
topic,
agents: selectedAgents,
results,
timestamp: new Date().toISOString()
};
}
/**
* Format brainstorming results for display
*/
formatResults(brainstormData) {
let output = `\n${'='.repeat(60)}\n`;
output += `🧠 MULTI-AI BRAINSTORM RESULTS\n`;
output += `${'='.repeat(60)}\n\n`;
output += `📝 Topic: ${brainstormData.topic}\n`;
output += `👥 Agents: ${brainstormData.agents.map(a => a.toUpperCase()).join(', ')}\n`;
output += `🕐 ${new Date(brainstormData.timestamp).toLocaleString()}\n\n`;
for (const agent of brainstormData.agents) {
const response = brainstormData.results[agent];
output += `${'─'.repeat(60)}\n`;
output += `🤖 ${agent.toUpperCase()} AGENT INSIGHTS\n`;
output += `${'─'.repeat(60)}\n\n`;
output += `${response}\n\n`;
}
output += `${'='.repeat(60)}\n`;
output += `✨ Brainstorming complete! Use these insights to inform your project.\n`;
return output;
}
/**
* List available agents
*/
listAgents() {
console.log('\n🤖 Available AI Agents:\n');
const agentDescriptions = {
content: 'Copywriting & Communication',
seo: 'Search Engine Optimization',
smm: 'Social Media Marketing',
pm: 'Product Management',
code: 'Software Architecture',
design: 'UI/UX Design',
web: 'Frontend Development',
app: 'Mobile Development'
};
for (const agent of this.agents) {
const desc = agentDescriptions[agent] || '';
console.log(`${agent.padEnd(10)} - ${desc}`);
}
console.log('');
}
}
/**
* Main brainstorm function
*/
async function multiAIBrainstorm(topic, options = {}) {
// Initialize client
const isInitialized = await qwenClient.initialize();
if (!isInitialized || !qwenClient.isAuthenticated()) {
console.log('\n🔐 Multi-AI Brainstorm requires Qwen API authentication\n');
await qwenClient.promptForCredentials();
}
const orchestrator = new BrainstormOrchestrator();
if (options.listAgents) {
orchestrator.listAgents();
return;
}
// Execute brainstorming
const results = await orchestrator.brainstorm(topic, options);
const formatted = orchestrator.formatResults(results);
console.log(formatted);
return results;
}
module.exports = {
multiAIBrainstorm,
BrainstormOrchestrator,
AVAILABLE_AGENTS
};

View File

@@ -0,0 +1,29 @@
#!/usr/bin/env node
/**
* Simple OAuth + Brainstorm launcher
* Usage: ./brainstorm.js "your topic here"
*/
const { oauthThenBrainstorm } = require('./oauth-then-brainstorm.js');
const topic = process.argv[2];
if (!topic) {
console.log('\n🧠 Multi-AI Brainstorm with Qwen OAuth\n');
console.log('Usage: node brainstorm.js "your topic here"\n');
console.log('Example: node brainstorm.js "I want to build a collaborative code editor"\n');
process.exit(1);
}
console.log('\n🧠 Multi-AI Brainstorm Session');
console.log('Topic: ' + topic);
console.log('Agents: All 8 specialized AI agents\n');
oauthThenBrainstorm(topic)
.then(() => {
console.log('\n✨ Brainstorming session complete!\n');
})
.catch((err) => {
console.error('\n❌ Session failed:', err.message, '\n');
process.exit(1);
});

View File

@@ -0,0 +1,31 @@
/**
* Multi-AI Brainstorm Skill
* Main entry point for collaborative AI brainstorming
*/
const { multiAIBrainstorm, BrainstormOrchestrator, AVAILABLE_AGENTS } = require('./brainstorm-orchestrator');
/**
* Main skill function
* @param {string} topic - The topic to brainstorm
* @param {Object} options - Configuration options
* @param {string[]} options.agents - Array of agent names to use (default: all)
* @param {number} options.concurrency - Number of agents to run in parallel (default: 3)
* @param {boolean} options.listAgents - If true, list available agents and exit
*/
async function run(topic, options = {}) {
try {
const results = await multiAIBrainstorm(topic, options);
return results;
} catch (error) {
console.error('\n❌ Brainstorming failed:', error.message);
throw error;
}
}
module.exports = {
run,
multiAIBrainstorm,
BrainstormOrchestrator,
AVAILABLE_AGENTS
};

View File

@@ -0,0 +1,57 @@
/**
* OAuth-then-Brainstorm Flow
* 1. Shows OAuth URL
* 2. Waits for user authorization
* 3. Automatically proceeds with brainstorming
*/
const qwenClient = require('./qwen-client.js');
const { multiAIBrainstorm } = require('./brainstorm-orchestrator.js');
async function oauthThenBrainstorm(topic, options = {}) {
try {
// Step 1: Initialize client
const isInitialized = await qwenClient.initialize();
if (isInitialized && qwenClient.isAuthenticated()) {
console.log('\n✓ Already authenticated with Qwen OAuth!');
console.log('✓ Proceeding with brainstorming...\n');
await multiAIBrainstorm(topic, options);
return;
}
// Step 2: Perform OAuth flow
console.log('\n🔐 Qwen OAuth Authentication Required\n');
console.log('='.repeat(70));
await qwenClient.performOAuthFlow();
// Step 3: Verify authentication worked
if (!qwenClient.isAuthenticated()) {
throw new Error('OAuth authentication failed');
}
console.log('\n✓ Authentication successful!');
console.log('✓ Proceeding with brainstorming...\n');
// Step 4: Run brainstorming
await multiAIBrainstorm(topic, options);
} catch (error) {
console.error('\n❌ Error:', error.message);
console.error('\nTroubleshooting:');
console.error('- Make sure you clicked "Authorize" in the browser');
console.error('- Check your internet connection');
console.error('- The OAuth URL may have expired (try again)\n');
throw error;
}
}
// Export for use
module.exports = { oauthThenBrainstorm };
// If run directly
if (require.main === module) {
const topic = process.argv[2] || 'test topic';
oauthThenBrainstorm(topic).catch(console.error);
}

View File

@@ -0,0 +1,19 @@
{
"name": "multi-ai-brainstorm",
"version": "1.0.0",
"description": "Multi-AI brainstorming using Qwen coder-model. Collaborate with multiple specialized AI agents for expert-level ideation.",
"main": "brainstorm-orchestrator.js",
"dependencies": {
"node-fetch": "^2.7.0"
},
"keywords": [
"ai",
"brainstorm",
"multi-agent",
"qwen",
"ideation",
"collaboration"
],
"author": "Roman | RyzenAdvanced",
"license": "ISC"
}

View File

@@ -0,0 +1,455 @@
/**
* Qwen API Client for Multi-AI Brainstorm
* Integrates with PromptArch's Qwen OAuth service
*/
const DEFAULT_ENDPOINT = "https://dashscope-intl.aliyuncs.com/compatible-mode/v1";
const PROMPTARCH_PROXY = "https://www.rommark.dev/tools/promptarch/api/qwen/chat";
const CREDENTIALS_PATH = `${process.env.HOME}/.claude/qwen-credentials.json`;
// Qwen OAuth Configuration (from Qwen Code source)
const QWEN_OAUTH_BASE_URL = 'https://chat.qwen.ai';
const QWEN_OAUTH_DEVICE_CODE_ENDPOINT = `${QWEN_OAUTH_BASE_URL}/api/v1/oauth2/device/code`;
const QWEN_OAUTH_TOKEN_ENDPOINT = `${QWEN_OAUTH_BASE_URL}/api/v1/oauth2/token`;
const QWEN_OAUTH_CLIENT_ID = 'f0304373b74a44d2b584a3fb70ca9e56';
const QWEN_OAUTH_SCOPE = 'openid profile email model.completion';
const QWEN_OAUTH_GRANT_TYPE = 'urn:ietf:params:oauth:grant-type:device_code';
/**
* Qwen API Client Class
*/
class QwenClient {
constructor() {
this.apiKey = null;
this.accessToken = null;
this.refreshToken = null;
this.tokenExpiresAt = null;
this.endpoint = DEFAULT_ENDPOINT;
this.model = "coder-model";
}
/**
* Initialize client with credentials
*/
async initialize() {
try {
const fs = require('fs');
if (fs.existsSync(CREDENTIALS_PATH)) {
const credentials = JSON.parse(fs.readFileSync(CREDENTIALS_PATH, 'utf8'));
// Handle both API key and OAuth token credentials
if (credentials.accessToken) {
this.accessToken = credentials.accessToken;
this.refreshToken = credentials.refreshToken;
this.tokenExpiresAt = credentials.tokenExpiresAt;
this.endpoint = credentials.endpoint || DEFAULT_ENDPOINT;
// Check if token needs refresh
if (this.isTokenExpired()) {
await this.refreshAccessToken();
}
return true;
} else if (credentials.apiKey) {
this.apiKey = credentials.apiKey;
this.endpoint = credentials.endpoint || DEFAULT_ENDPOINT;
return true;
}
}
} catch (error) {
// No credentials stored yet
}
return false;
}
/**
* Check if access token is expired
*/
isTokenExpired() {
if (!this.tokenExpiresAt) return false;
// Add 5 minute buffer before expiration
return Date.now() >= (this.tokenExpiresAt - 5 * 60 * 1000);
}
/**
* Prompt user for authentication method
*/
async promptForCredentials() {
const readline = require('readline');
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout
});
return new Promise((resolve, reject) => {
rl.question(
'\n🔐 Choose authentication method:\n' +
' 1. OAuth (Recommended) - Free 2000 requests/day with qwen.ai account\n' +
' 2. API Key - Get it at https://help.aliyun.com/zh/dashscope/\n\n' +
'Enter choice (1 or 2): ',
async (choice) => {
rl.close();
if (choice === '1') {
try {
await this.performOAuthFlow();
resolve(true);
} catch (error) {
reject(error);
}
} else if (choice === '2') {
await this.promptForAPIKey();
resolve(true);
} else {
reject(new Error('Invalid choice. Please enter 1 or 2.'));
}
}
);
});
}
/**
* Prompt user for API key only
*/
async promptForAPIKey() {
const readline = require('readline');
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout
});
return new Promise((resolve, reject) => {
rl.question('Enter your Qwen API key (get it at https://help.aliyun.com/zh/dashscope/): ', (key) => {
if (!key || key.trim().length === 0) {
rl.close();
reject(new Error('API key is required'));
return;
}
this.apiKey = key.trim();
this.saveCredentials();
rl.close();
resolve(true);
});
});
}
/**
* Save credentials to file
*/
saveCredentials() {
try {
const fs = require('fs');
const path = require('path');
const dir = path.dirname(CREDENTIALS_PATH);
if (!fs.existsSync(dir)) {
fs.mkdirSync(dir, { recursive: true });
}
const credentials = {
endpoint: this.endpoint
};
// Save OAuth tokens
if (this.accessToken) {
credentials.accessToken = this.accessToken;
credentials.refreshToken = this.refreshToken;
credentials.tokenExpiresAt = this.tokenExpiresAt;
}
// Save API key
else if (this.apiKey) {
credentials.apiKey = this.apiKey;
}
fs.writeFileSync(
CREDENTIALS_PATH,
JSON.stringify(credentials, null, 2)
);
console.log(`✓ Credentials saved to ${CREDENTIALS_PATH}`);
} catch (error) {
console.warn('Could not save credentials:', error.message);
}
}
/**
* Generate PKCE code verifier and challenge pair
*/
generatePKCEPair() {
const crypto = require('crypto');
const codeVerifier = crypto.randomBytes(32).toString('base64url');
const codeChallenge = crypto.createHash('sha256')
.update(codeVerifier)
.digest('base64url');
return { code_verifier: codeVerifier, code_challenge: codeChallenge };
}
/**
* Convert object to URL-encoded form data
*/
objectToUrlEncoded(data) {
return Object.keys(data)
.map((key) => `${encodeURIComponent(key)}=${encodeURIComponent(data[key])}`)
.join('&');
}
/**
* Perform OAuth 2.0 Device Code Flow (from Qwen Code implementation)
*/
async performOAuthFlow() {
const { exec } = require('child_process');
console.log('\n🔐 Starting Qwen OAuth Device Code Flow...\n');
// Generate PKCE parameters
const { code_verifier, code_challenge } = this.generatePKCEPair();
// Step 1: Request device authorization
console.log('Requesting device authorization...');
const deviceAuthResponse = await fetch(QWEN_OAUTH_DEVICE_CODE_ENDPOINT, {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
'Accept': 'application/json',
},
body: this.objectToUrlEncoded({
client_id: QWEN_OAUTH_CLIENT_ID,
scope: QWEN_OAUTH_SCOPE,
code_challenge: code_challenge,
code_challenge_method: 'S256',
}),
});
if (!deviceAuthResponse.ok) {
const error = await deviceAuthResponse.text();
throw new Error(`Device authorization failed: ${deviceAuthResponse.status} - ${error}`);
}
const deviceAuth = await deviceAuthResponse.json();
if (!deviceAuth.device_code) {
throw new Error('Invalid device authorization response');
}
// Step 2: Display authorization instructions
console.log('\n=== Qwen OAuth Device Authorization ===\n');
console.log('1. Visit this URL in your browser:\n');
console.log(` ${deviceAuth.verification_uri_complete}\n`);
console.log('2. Sign in to your qwen.ai account and authorize\n');
console.log('Waiting for authorization to complete...\n');
// Try to open browser automatically
try {
const openCommand = process.platform === 'darwin' ? 'open' :
process.platform === 'win32' ? 'start' : 'xdg-open';
exec(`${openCommand} "${deviceAuth.verification_uri_complete}"`, (err) => {
if (err) {
console.debug('Could not open browser automatically');
}
});
} catch (err) {
console.debug('Failed to open browser:', err.message);
}
// Step 3: Poll for token
let pollInterval = 2000; // Start with 2 seconds
const maxAttempts = Math.ceil(deviceAuth.expires_in / (pollInterval / 1000));
let attempt = 0;
while (attempt < maxAttempts) {
attempt++;
try {
console.debug(`Polling for token (attempt ${attempt}/${maxAttempts})...`);
const tokenResponse = await fetch(QWEN_OAUTH_TOKEN_ENDPOINT, {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
'Accept': 'application/json',
},
body: this.objectToUrlEncoded({
grant_type: QWEN_OAUTH_GRANT_TYPE,
client_id: QWEN_OAUTH_CLIENT_ID,
device_code: deviceAuth.device_code,
code_verifier: code_verifier,
}),
});
// Check for pending authorization (standard OAuth RFC 8628 response)
if (tokenResponse.status === 400) {
const errorData = await tokenResponse.json();
if (errorData.error === 'authorization_pending') {
// User hasn't authorized yet, continue polling
await new Promise(resolve => setTimeout(resolve, pollInterval));
continue;
}
if (errorData.error === 'slow_down') {
// Polling too frequently, increase interval
pollInterval = Math.min(pollInterval * 1.5, 10000);
await new Promise(resolve => setTimeout(resolve, pollInterval));
continue;
}
// Other 400 errors (authorization_declined, expired_token, etc.)
throw new Error(`Authorization failed: ${errorData.error} - ${errorData.error_description || 'No description'}`);
}
if (!tokenResponse.ok) {
const error = await tokenResponse.text();
throw new Error(`Token request failed: ${tokenResponse.status} - ${error}`);
}
// Success! We have the token
const tokenData = await tokenResponse.json();
if (!tokenData.access_token) {
throw new Error('Token response missing access_token');
}
// Save credentials
this.accessToken = tokenData.access_token;
this.refreshToken = tokenData.refresh_token;
this.tokenExpiresAt = tokenData.expires_in ?
Date.now() + (tokenData.expires_in * 1000) : null;
this.saveCredentials();
console.log('\n✓ OAuth authentication successful!');
console.log('✓ Access token obtained and saved.\n');
return;
} catch (error) {
// Check if this is a fatal error (not pending/slow_down)
if (error.message.includes('Authorization failed') ||
error.message.includes('Token request failed')) {
throw error;
}
// For other errors, wait and retry
await new Promise(resolve => setTimeout(resolve, pollInterval));
}
}
throw new Error('OAuth authentication timeout');
}
/**
* Refresh access token using refresh token
*/
async refreshAccessToken() {
if (!this.refreshToken) {
throw new Error('No refresh token available. Please re-authenticate.');
}
console.log('🔄 Refreshing access token...');
const tokenResponse = await fetch(QWEN_OAUTH_TOKEN_ENDPOINT, {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
body: this.objectToUrlEncoded({
grant_type: 'refresh_token',
refresh_token: this.refreshToken,
client_id: QWEN_OAUTH_CLIENT_ID,
}),
});
if (!tokenResponse.ok) {
const error = await tokenResponse.text();
throw new Error(`Token refresh failed: ${tokenResponse.status} - ${error}`);
}
const tokens = await tokenResponse.json();
this.accessToken = tokens.access_token;
if (tokens.refresh_token) {
this.refreshToken = tokens.refresh_token;
}
this.tokenExpiresAt = tokens.expires_in ?
Date.now() + (tokens.expires_in * 1000) : null;
this.saveCredentials();
console.log('✓ Token refreshed successfully');
}
/**
* Get the authentication key (prefer OAuth access token, fallback to API key)
*/
getAuthKey() {
return this.accessToken || this.apiKey;
}
/**
* Make a chat completion request
*/
async chatCompletion(messages, options = {}) {
const authKey = this.getAuthKey();
if (!authKey) {
throw new Error('Qwen API key not configured. Run /multi-ai-brainstorm first to set up.');
}
// Check if OAuth token needs refresh
if (this.accessToken && this.isTokenExpired()) {
await this.refreshAccessToken();
}
const {
model = this.model,
stream = false,
temperature = 0.7,
maxTokens = 2000
} = options;
const payload = {
model,
messages,
stream,
temperature,
max_tokens: maxTokens
};
try {
const response = await fetch(PROMPTARCH_PROXY, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${authKey}`
},
body: JSON.stringify({
endpoint: this.endpoint,
...payload
})
});
if (!response.ok) {
const error = await response.text();
throw new Error(`Qwen API error (${response.status}): ${error}`);
}
const data = await response.json();
return data.choices?.[0]?.message?.content || '';
} catch (error) {
if (error.message.includes('fetch')) {
throw new Error('Network error. Please check your internet connection.');
}
throw error;
}
}
/**
* Check if client is authenticated
*/
isAuthenticated() {
return !!(this.accessToken || this.apiKey);
}
}
// Singleton instance
const client = new QwenClient();
module.exports = client;