import { Type } from '@sinclair/typebox';
import { Repository } from 'typeorm';
import type { AnyAgentTool } from '../common.js';
import { textResult } from '../common.js';
import type { CrewRunContext } from '../../service/crew_types.js';
import type { NetaClawCrewRunEntity } from '../../entity/crew_run.js';

/**
 * 升级等待人工介入时，将 resolve 回调存入此 Map。
 * key = runId，外部调用 resolver(userMessage) 即可恢复主 Agent。
 */
export const escalateResolvers = new Map<number, (userMessage: string) => void>();

const EscalateParams = Type.Object({
  reason: Type.String({ description: '升级原因，说明为什么需要人工介入' }),
  summary: Type.Optional(Type.String({ description: '当前进度摘要，方便人工了解上下文' })),
});

/**
 * 创建升级人工工具
 */
export function createEscalateTool(
  ctx: CrewRunContext,
  crewRunRepo: Repository<NetaClawCrewRunEntity>,
): AnyAgentTool {
  return {
    name: 'escalate',
    label: '升级人工',
    description: '当遇到无法自主解决的问题时，暂停执行并请求人工介入。调用后主 Agent 将暂停，等待人工回复后继续。',
    parameters: EscalateParams,
    visibility: 'internal',
    async execute(_id, params) {
      const { reason, summary } = params;

      // 持久化当前对话到 pausedState
      const conversation = ctx.getConversation?.() ?? [];
      await crewRunRepo.update(ctx.runId, {
        status: 'paused',
        pausedState: { conversation, reason, summary } as any,
      });

      // 推送升级事件
      ctx.callbacks.onEscalation(ctx.runId, undefined, reason);
      ctx.callbacks.onRunStatus(ctx.runId, 'paused', `等待人工介入: ${reason}`);

      // 返回一个不 resolve 的 Promise，将 resolve 回调存入 Map
      return new Promise<ReturnType<typeof textResult>>((resolve) => {
        escalateResolvers.set(ctx.runId, (userMessage: string) => {
          escalateResolvers.delete(ctx.runId);
          resolve(textResult(`人工已回复: ${userMessage}`));
        });
      });
    },
  };
}

import { registerSchema } from '../catalog.js';
registerSchema({
  name: 'escalate',
  toolset: 'crew',
  description: '将问题升级给用户或上级 Agent',
  capability: 'text',
  visibility: 'internal',
  isCore: true,
  canDisable: false,
});
