Ctrl K
ComunidadGuías…

src/runner/stop.ts

Rama main · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
import { readHumanReplies } from './human-feedback.ts';
import { parsePRTask } from './command.ts';
import type { HumanReply } from '../github/comments.ts';

export class TaskStopped extends Error {
  constructor(message = '人类请求 /stop:任务已暂停。当前没有可用的 Agent 收尾说明,以下报告由 Harness 可观测证据补充。') { super(message); }
}

// Consume the existing durable comment inbox, avoiding signals to recycled PIDs.
// An /close arriving during an active task must never destroy the workspace underneath it:
// the optional onClose callback lets the owning worker refuse it deterministically (no model).
export function watchStop(path: string, bot: string, handled: () => number[], onClose?: (comment: HumanReply) => Promise<void>) {
  const controller = new AbortController();
  let request: HumanReply | undefined;
  let pending: Promise<void> | undefined;
  let refusing: Promise<void> | undefined;
  const check = async () => {
    if (request) return;
    pending ??= (async () => {
      const replies = await readHumanReplies(path);
      const unhandled = () => replies.filter(c => !handled().includes(c.comment_id));
      request = unhandled().find(c => parsePRTask(c.body, bot) === 'stop');
      if (request) { controller.abort(new TaskStopped()); return; }
      const close = onClose ? unhandled().find(c => parsePRTask(c.body, bot) === 'close') : undefined;
      if (close && onClose && !refusing) refusing = onClose(close).finally(() => { refusing = undefined; });
    })().finally(() => { pending = undefined; });
    await pending;
  };
  const timer = setInterval(() => { void check().catch(() => {}); }, 250);
  timer.unref();
  return { signal: controller.signal, request: () => request, check,
    async guard() { await check(); if (controller.signal.aborted) throw controller.signal.reason; },
    async close() { clearInterval(timer); await pending; await refusing?.catch(() => {}); } };
}