/** * assign-task skill * 分析任務,判斷目標 VPS,呼叫 dispatch-webhook 執行 */ import { randomUUID } from 'crypto'; // 任務分派規則 const DISPATCH_RULES = [ { target: 'vps-a', label: 'VPS-A (Claude Code)', model: 'Claude Code Opus', keywords: ['主要專案', '核心功能', '架構', 'code review', 'review', '審查', 'API', '後端', 'backend'], }, { target: 'vps-b', label: 'VPS-B (OpenCode)', model: 'OpenCode Codex', keywords: ['腳本', 'script', '工具', 'tool', '文件', 'doc', 'readme', '實驗', '前端', 'frontend', 'react', 'vue'], }, ]; function determineTarget(description: string): typeof DISPATCH_RULES[0] { const lower = description.toLowerCase(); for (const rule of DISPATCH_RULES) { if (rule.keywords.some(k => lower.includes(k.toLowerCase()))) { return rule; } } // 預設分派到 VPS-A return DISPATCH_RULES[0]; } function determinePriority(description: string): string { const lower = description.toLowerCase(); if (lower.includes('緊急') || lower.includes('urgent') || lower.includes('asap')) return 'high'; if (lower.includes('之後') || lower.includes('有空') || lower.includes('低優先')) return 'low'; return 'normal'; } export async function handler(ctx: any) { const { message, env, callSkill } = ctx; const description = message.text || message.content || ''; if (!description) { return { reply: '❌ 請描述你想要執行的任務。' }; } const taskId = randomUUID(); const target = determineTarget(description); const priority = determinePriority(description); // 建立任務 payload const task = { task_id: taskId, type: 'project_development', description: description.slice(0, 2000), priority, target: target.target, callback_url: `${env.CALLBACK_BASE_URL || 'https://oclaw.nature.edu.kg/webhook/callback'}`, created_at: new Date().toISOString(), }; // 呼叫 dispatch-webhook skill let dispatchResult; try { dispatchResult = await callSkill('dispatch-webhook', { target: target.target, payload: task, webhookUrl: target.target === 'vps-a' ? env.VPS_A_WEBHOOK_URL : env.VPS_B_WEBHOOK_URL, webhookToken: target.target === 'vps-a' ? env.VPS_A_WEBHOOK_TOKEN : env.VPS_B_WEBHOOK_TOKEN, }); } catch (err: any) { return { reply: `❌ Webhook 發送失敗:${err.message}\n\nTask ID: \`${taskId}\`(可稍後重試)`, }; } const priorityLabel = { high: '🔴 緊急', normal: '🟡 一般', low: '🟢 低優先' }[priority] || priority; return { reply: `✅ 任務已分派 📋 **任務摘要**:${description.slice(0, 100)}${description.length > 100 ? '...' : ''} 🎯 **分派目標**:${target.label} 🤖 **執行模型**:${target.model} ⚡ **優先級**:${priorityLabel} 🆔 **Task ID**:\`${taskId}\` 執行中,完成後會通知你。`, metadata: { taskId, target: target.target, priority }, }; }