/**
 * PR5 Tool 类型定义。
 *
 * Tool = 给 agent 调用的能力单元。PR5 day-1 全是 in-process service tool；
 * PR2 阶段 MCP / CLI / Client 工具走 MCP Client 接入（Phase 2）。
 */

export interface ToolDescriptor {
  /** unique tool name，agent prompt 里用这个引用 */
  readonly name: string;
  /** 短描述（给 LLM tool-use 提示用） */
  readonly description: string;
  /** JSON Schema for input args（简化版：name → type） */
  readonly inputSchema: Record<string, { type: 'string' | 'number' | 'boolean'; required?: boolean; description?: string }>;
  /**
   * 可用性表达式（PR5 day-1 极简版）。
   * 例：`{ surface: ['web', 'desktop'] }` → 仅这两个 surface 可见；
   *     `{ permissions: ['knowledge:read'] }` → 用户须有该权限。
   * 都不指定 → 全部 surface / 不检查 permission。
   */
  readonly availability?: {
    surface?: ('web' | 'desktop' | 'mobile' | 'teams' | 'cli')[];
    permissions?: string[];
    /**
     * PR11.3：客户端必须上报的 HostBridge 能力（client: 工具必填）。
     * ToolRegistry 用当前 surface 的默认能力集（∩ org disabledCapabilities）做超集校验，
     * 任一缺失即工具对该 surface 不可见——架构 §1.3.2 "Web 端 capabilities 为空→自动不可见"。
     */
    requiredCapabilities?: import('./host-capability.types').HostCapability[];
  };
  /**
   * PR4.5: 是否是"写动作"（数据库写 / 外部副作用）。
   *   - READ_ONLY mode：writeAction=true 的工具不可见
   *   - Plan mode REQUIRED：writeAction=true 的工具必须先 ExitPlanMode 才能调
   *   - ASK_EVERY_TIME：每次调 writeAction=true 前 Permission ask（PR4.5 future）
   */
  readonly writeAction?: boolean;
  /**
   * PR4.5: 是不是 mode 控制工具本身（EnterPlanMode 等）。
   * 控制工具不受 mode 过滤约束，否则用户无法切回。
   */
  readonly controlTool?: boolean;
  /**
   * PR11.4: 客户端执行工具的派发 key（HostBridge.invoke 的 tool 参数）。
   *
   * 后端 `ToolDescriptor.name`（如 `File.read`）是给 LLM/UI 展示用的人读名；
   * 客户端 dispatcher（如 desktop/src/host-bridge/dispatcher.ts）按内部命名空间用
   * `client:fs.read` 风格 key 路由。两边历史上字面不一致，导致 messages.service 把
   * tool_use → HostBridge.invoke 派发时缺少**显式映射**。
   *
   * 约定：client 系列工具必填；非 client 工具留空。`desktop/scripts/check-capabilities-mirror.ts`
   * 在 CI 上校验 backend 端 `ToolDescriptor.dispatchKey` 值集合与 desktop dispatcher 的
   * `TOOL_TO_CAPABILITY` keys **双向 1:1 相等**（缺一即 fail）。
   */
  readonly dispatchKey?: string;
}

export interface ToolInvocation {
  readonly organizationId: string;
  readonly userId: string;
  readonly sessionId?: string;
  readonly turnId?: string;
  readonly input: Record<string, unknown>;
}

export interface ToolResult {
  readonly ok: boolean;
  readonly output?: unknown;
  readonly errorMessage?: string;
}

export interface AgentTool {
  readonly descriptor: ToolDescriptor;
  invoke(invocation: ToolInvocation): Promise<ToolResult>;
}
