Long Task Handler

v1.0.0

自动识别并后台执行预计超30秒的长任务,定期推送进度反馈,避免阻塞和任务堆积,支持超时及完成通知管理。

0· 122·0 current·0 all-time
Security Scan
VirusTotalVirusTotal
Benign
View report →
OpenClawOpenClaw
Benign
high confidence
Purpose & Capability
Name/description, SKILL.md instructions, _meta.json and task-manager.js all align: the skill manages background execution, polling, progress notifications and a small local task state. The declared required tools (exec, process, message, sessions_spawn) match its behavior.
Instruction Scope
Instructions remain within the stated purpose (assess tasks, start background exec, poll progress, notify). They also instruct sending command output to a messaging channel (examples use 'feishu') and spawning isolated child agents (sessions_spawn). These are expected for this skill but mean command outputs may be posted to external channels and child agents will execute tasks — the SKILL.md does not add sanitization or explicit access controls for sensitive outputs.
Install Mechanism
No remote installs or downloads; this is instruction-only with a single local JS module. No extract-from-URL or external package installs are present.
Credentials
The skill declares no required environment variables or credentials. It uses platform tools (message, exec, process, sessions_spawn) as expected. One minor note: messaging examples reference 'feishu' channel but no channel credentials are requested (likely handled by the platform's message tool).
Persistence & Privilege
always:false (normal). The skill writes a local task-state.json in its directory to persist tasks and supports archiving logs — this is reasonable for its purpose. Because it can spawn child sessions and post outputs to messaging channels, enabling it increases the scope of what background code the agent will run and where outputs may be sent; that raises operational considerations but not an incoherence.
Assessment
This skill appears coherent for running and monitoring long-running commands, but review and operationalize before enabling: 1) Inspect the code (task-manager.js) — it persists state to task-state.json in the skill directory and exposes a CLI for listing/cleanup. 2) Confirm where notifications go (example uses 'feishu') and who has access to that channel — command output may contain sensitive data. 3) Limit blast radius: set conservative defaultTimeoutSeconds, maxConcurrentLongTasks, and pollInterval to avoid resource exhaustion. 4) Decide who may invoke the skill (restrict to trusted users) because it will execute user-provided commands in background and can spawn child sessions. 5) If you need stronger guarantees, run the skill in a sandboxed agent environment and review messaging/archiving retention (autoArchive, archiveAfterMinutes). 6) No extra credentials are requested by the skill, but verify your platform's message/exec/process/session tools don't implicitly expose secrets when forwarding output. If you want, I can point out specific lines in task-manager.js to review or suggest additional safeguards to add.

Like a lobster shell, security has layers — review code before you run it.

latestvk976pcjv4qcjj8tsrkh55g1cjh83z2he
122downloads
0stars
1versions
Updated 2w ago
v1.0.0
MIT-0

Long Task Handler - 长任务处理技能

触发条件

当用户任务符合以下特征时激活此技能:

  1. 预计耗时 > 30 秒 的任务(编译、部署、大数据处理、模型训练等)
  2. 需要进度反馈 的任务(用户需要知道进展)
  3. 可能阻塞队列 的任务(会影响其他用户请求)
  4. 用户明确要求"后台运行"、"别阻塞"、"慢慢跑"等

触发关键词:

  • "长任务"、"耗时"、"后台运行"、"别等我"
  • "跑完告诉我"、"有进展通知我"
  • 编译、部署、训练、处理大量数据等场景

核心机制

1. 任务分流架构

用户请求 → 立即确认 → 后台 exec → 定期轮询 → 进展推送 → 完成通知
            ↓           ↓          ↓          ↓          ↓
         (1 秒内)   (不阻塞)   (30 秒间隔)  (实时)    (自动)

2. 三层处理策略

任务类型处理方式工具
短任务 (<30 秒)直接执行exec 前台
中长任务 (30 秒 -5 分)后台执行 + 定期轮询exec background + process poll
长任务 (>5 分)子代理隔离 + 进度推送sessions_spawn + message

执行流程

Step 1: 任务评估

function assessTask(command) {
  // 预估耗时因素
  const longTaskIndicators = [
    /compile|build|deploy/i,
    /train|fine-tune/i,
    /process.*data|migration/i,
    /export|backup.*large/i,
    /\b(ffmpeg|docker|webpack|tsc)\b/,
    /test.*--coverage|--all/i,
  ];
  
  // 检查是否有超时/后台标记
  const hasTimeout = /--timeout|-t\s*\d+/.test(command);
  const isBackground = /&$|nohup|background/.test(command);
  
  // 返回评估结果
  return {
    estimatedDuration: 'short' | 'medium' | 'long',
    shouldBackground: boolean,
    needsProgressReporting: boolean
  };
}

Step 2: 立即确认

必须在 5 秒内给用户确认回复:

🫡 收到!这个任务预计需要 X 分钟,我会在后台运行。

任务:[任务简述]
预计耗时:X 分钟
通知方式:每 30 秒报告进展,完成后立即通知

你可以继续问我其他问题,不用等这个任务完成~

Step 3: 后台启动

const { sessionId } = await exec({
  command: taskCommand,
  background: true,
  yieldMs: 2000,      // 2 秒后切到后台
  timeout: timeoutSeconds || 3600,  // 默认 1 小时超时
  workdir: workspaceDir
});

Step 4: 进度监控循环

const monitorProgress = async (sessionId, options = {}) => {
  const {
    pollIntervalMs = 30000,  // 30 秒轮询
    reportNoChange = false,   // 无变化是否报告
    maxSilentMinutes = 5      // 最大静默时间
  } = options;
  
  let lastOutput = '';
  let silentSince = Date.now();
  
  const interval = setInterval(async () => {
    const result = await process({
      action: 'poll',
      sessionId
    });
    
    // 检查是否有新输出
    if (result.output && result.output !== lastOutput) {
      const newLines = result.output.slice(lastOutput.length);
      if (newLines.trim()) {
        await message({
          channel: 'feishu',
          message: `📊 任务进展:\n\`\`\`\n${newLines.slice(-500)}\n\`\`\``
        });
        lastOutput = result.output;
        silentSince = Date.now();
      }
    }
    
    // 检查静默超时
    if (Date.now() - silentSince > maxSilentMinutes * 60000) {
      await message({
        message: `⚠️ 任务已静默运行 ${maxSilentMinutes} 分钟,仍在进行中...`
      });
      silentSince = Date.now();  // 重置计时
    }
    
    // 检查是否完成
    if (result.exitCode !== null) {
      clearInterval(interval);
      await notifyCompletion(sessionId, result);
    }
  }, pollIntervalMs);
  
  return interval;
};

Step 5: 完成通知

const notifyCompletion = async (sessionId, result) => {
  const fullLog = await process({
    action: 'log',
    sessionId,
    limit: 100
  });
  
  const status = result.exitCode === 0 ? '✅' : '❌';
  const duration = formatDuration(result.durationMs);
  
  await message({
    channel: 'feishu',
    message: `${status} **任务完成!**
    
耗时:${duration}
退出码:${result.exitCode}

${result.exitCode === 0 ? '🎉 一切顺利!' : '⚠️ 任务失败,请检查日志'}

${fullLog.output ? '最近输出:\n```\n' + fullLog.output.slice(-1000) + '\n```' : ''}`
  });
};

配置参数

openclaw.json 中添加:

{
  skills: {
    "long-task-handler": {
      enabled: true,
      defaultTimeoutSeconds: 3600,    // 默认 1 小时超时
      pollIntervalSeconds: 30,        // 轮询间隔
      progressReportThreshold: 30,    // 超过 30 秒的任务才报告进展
      maxConcurrentLongTasks: 3,      // 最多并行长任务数
      notifyOnExit: true,             // 完成时自动通知
      autoArchive: true,              // 完成后归档日志
      archiveAfterMinutes: 60         // 多少分钟后归档
    }
  },
  tools: {
    exec: {
      backgroundMs: 5000,
      timeoutSec: 3600,
      notifyOnExit: true,
      notifyOnExitEmptySuccess: false
    }
  }
}

使用示例

示例 1: 编译项目

用户:编译整个项目,有点大

助手:🫡 收到!编译大项目预计需要 3-5 分钟,我会在后台运行。

任务:编译项目
预计耗时:3-5 分钟
通知方式:每 30 秒报告进展,完成后立即通知

你可以继续问我其他问题,不用等这个任务完成~

[后台启动 exec: npm run build]
[30 秒后] 📊 任务进展:

Building modules... ✓ Compiled 234 files in 45s


[60 秒后] 📊 任务进展:

Optimizing assets... ✓ Bundle size: 2.3MB


[完成] ✅ **任务完成!**
耗时:2 分 34 秒
退出码:0
🎉 一切顺利!

示例 2: 数据迁移

用户:把数据库迁移到新服务器,数据量大概 10GB

助手:🫡 收到!10GB 数据迁移预计需要 15-30 分钟,我会在后台运行。

任务:数据库迁移 (10GB)
预计耗时:15-30 分钟
通知方式:每 60 秒报告进展,完成后立即通知

你可以继续问我其他问题,不用等这个任务完成~

[启动 sessions_spawn 子代理处理]
...

示例 3: 模型训练

用户:用这个数据集 fine-tune 模型,跑 100 个 epoch

助手:🫡 收到!模型训练是长任务,预计需要 2-4 小时,我会用独立子代理运行。

任务:Fine-tune 模型 (100 epochs)
预计耗时:2-4 小时
通知方式:每 5 分钟报告训练进度,完成后立即通知

你可以继续问我其他问题,不用等这个任务完成~

[启动独立子代理,完全隔离]
...

错误处理

任务超时

if (result.timedOut) {
  await message({
    message: `⏰ **任务超时!**
    
运行超过 ${timeoutSeconds} 秒,已自动终止。

可能原因:
- 任务确实需要更长时间
- 任务卡死或进入死循环
- 资源不足 (内存/CPU)

建议:
1. 检查日志确认卡在哪里
2. 如需更长时间,用 --timeout 参数指定
3. 考虑优化任务或分批处理`
  });
}

任务失败

if (result.exitCode !== 0) {
  const errorLog = await process({
    action: 'log',
    sessionId,
    offset: -50,  // 最后 50 行
    limit: 50
  });
  
  await message({
    message: `❌ **任务失败!**
    
退出码:${result.exitCode}
错误摘要:\n\`\`\`\n${errorLog.output.slice(-500)}\n\`\`\`

需要我帮你分析问题原因吗?`
  });
}

队列积压

当检测到多个长任务排队时:

const runningTasks = await process({ action: 'list' });
if (runningTasks.length >= maxConcurrentLongTasks) {
  await message({
    message: `⚠️ 当前有 ${runningTasks.length} 个长任务正在运行。
    
新任务已加入队列,会在第 ${runningTasks.length + 1} 顺位执行。

使用 \`/tasks\` 查看队列状态`
  });
}

相关命令

/tasks - 查看任务列表

📋 当前任务列表

运行中:
1. [sessionId: abc123] npm run build - 运行 2 分钟
2. [sessionId: def456] data-migration - 运行 15 分钟

等待中:
1. [queued] model-training - 排队第 1 位

已完成 (最近 1 小时):
1. [✅] test-suite - 耗时 5 分 23 秒

/task <id> log - 查看任务日志

📄 任务日志 [abc123]

[17:30:00] Starting build...
[17:30:15] Compiled 100 files
[17:30:45] Compiled 234 files
[17:31:00] Optimizing...
[17:32:34] Build complete!

/task <id> kill - 终止任务

⏹️ 任务 [abc123] 已终止

退出码:SIGTERM
运行时长:2 分 34 秒

最佳实践

✅ 推荐

  1. 立即确认 - 5 秒内回复,让用户知道任务已接收
  2. 预估时间 - 给出合理的时间预期
  3. 定期反馈 - 30-60 秒报告一次,避免用户焦虑
  4. 隔离长任务 - >5 分钟的任务用子代理
  5. 超时保护 - 设置合理 timeout,避免无限运行
  6. 日志归档 - 完成后保留日志供查阅

❌ 避免

  1. 沉默运行 - 几分钟没反馈,用户不知道在干嘛
  2. 阻塞队列 - 长任务占用主线程,其他用户等不了
  3. 无超时 - 卡死的任务永远跑不完
  4. 日志丢失 - 完成后没地方看输出
  5. 过度报告 - 每秒都发,骚扰用户

技能元数据

  • 名称: Long Task Handler
  • 版本: 1.0.0
  • 作者: Frankie 助理
  • 创建日期: 2026-03-31
  • 依赖工具: exec, process, message, sessions_spawn
  • 适用渠道: 所有渠道 (feishu, discord, telegram, etc.)

激活检查清单

收到任务时快速判断:

  • 任务是否涉及编译/部署/迁移/训练?
  • 数据量是否 > 1GB 或文件数 > 1000?
  • 是否包含已知慢命令 (docker build, webpack, tsc, ffmpeg)?
  • 用户是否暗示"慢慢跑"、"不急"、"后台弄"?
  • 是否有超时/进度参数?

3 个以上 ✅ → 激活长任务处理机制

Comments

Loading comments...