// Force strict mode and setup for ESM
"use strict";
import {
  CAP_ESCALATION_LABELS
} from "./chunk-QQDPRDVW.js";
import "./chunk-MLZQVCF3.js";
import {
  BaseDeclarativeTool,
  BaseToolInvocation,
  ToolDisplayNames,
  ToolNames
} from "./chunk-PLY4F7QW.js";
import {
  createDebugLogger
} from "./chunk-C4K3FEQ2.js";
import "./chunk-Z2Z3GUXZ.js";
import {
  init_esbuild_shims
} from "./chunk-A4BMJM77.js";
import {
  __name
} from "./chunk-J2S4EL5Y.js";

// packages/core/src/tools/askUserQuestion.ts
init_esbuild_shims();
var debugLogger = createDebugLogger("ASK_USER_QUESTION");
function parseAnswerQuestionIndex(key, questionCount) {
  const index = Number(key);
  if (!Number.isSafeInteger(index) || index < 0 || index >= questionCount || String(index) !== key) {
    return void 0;
  }
  return index;
}
__name(parseAnswerQuestionIndex, "parseAnswerQuestionIndex");
var askUserQuestionToolDescription = `Use this tool when you need to ask the user questions during execution. This allows you to:
1. Gather user preferences or requirements
2. Clarify ambiguous instructions
3. Get decisions on implementation choices as you work
4. Offer choices to the user about what direction to take.

Usage notes:
- Users will always be able to select "Other" to provide custom text input
- Use multiSelect: true to allow multiple answers to be selected for a question
- If you recommend a specific option, make that the first option in the list and add "(Recommended)" at the end of the label

Plan mode note: In plan mode, use this tool to clarify requirements or choose between approaches BEFORE finalizing your plan. Do NOT use this tool to ask "Is this plan ready?" or "Should I proceed?" - use ExitPlanMode for plan approval.
`;
var askUserQuestionToolSchemaData = {
  name: "ask_user_question",
  description: askUserQuestionToolDescription,
  parametersJsonSchema: {
    $schema: "https://json-schema.org/draft/2020-12/schema",
    type: "object",
    properties: {
      questions: {
        description: "Questions to ask the user (1-4 questions)",
        minItems: 1,
        maxItems: 4,
        type: "array",
        items: {
          type: "object",
          properties: {
            question: {
              description: 'The complete question to ask the user. Should be clear, specific, and end with a question mark. Example: "Which library should we use for date formatting?" If multiSelect is true, phrase it accordingly, e.g. "Which features do you want to enable?"',
              type: "string"
            },
            header: {
              description: 'Very short label displayed as a chip/tag (max 12 chars). Examples: "Auth method", "Library", "Approach".',
              type: "string"
            },
            options: {
              description: "The available choices for this question. Must have 2-4 options. Each option should be a distinct, mutually exclusive choice (unless multiSelect is enabled). There should be no 'Other' option, that will be provided automatically.",
              minItems: 2,
              maxItems: 4,
              type: "array",
              items: {
                type: "object",
                properties: {
                  label: {
                    description: "The display text for this option that the user will see and select. Should be concise (1-5 words) and clearly describe the choice.",
                    type: "string"
                  },
                  description: {
                    description: "Explanation of what this option means or what will happen if chosen. Useful for providing context about trade-offs or implications.",
                    type: "string"
                  }
                },
                required: ["label", "description"],
                additionalProperties: false
              }
            },
            multiSelect: {
              description: "Set to true to allow the user to select multiple options instead of just one. Use when choices are not mutually exclusive.",
              default: false,
              type: "boolean"
            }
          },
          required: ["question", "header", "options"],
          additionalProperties: false
        }
      },
      metadata: {
        description: "Optional metadata for tracking and analytics purposes. Not displayed to user.",
        type: "object",
        properties: {
          source: {
            description: 'Optional identifier for the source of this question (e.g., "remember" for /remember command). Used for analytics tracking.',
            type: "string"
          }
        },
        additionalProperties: false
      }
    },
    required: ["questions"],
    additionalProperties: false
  }
};
var AskUserQuestionToolInvocation = class extends BaseToolInvocation {
  constructor(_config, params) {
    super(params);
    this._config = _config;
  }
  static {
    __name(this, "AskUserQuestionToolInvocation");
  }
  userAnswers = {};
  wasAnswered = false;
  getDescription() {
    const questionCount = this.params.questions.length;
    return `Ask user ${questionCount} question${questionCount > 1 ? "s" : ""}`;
  }
  /**
   * ask_user_question always requires user confirmation so the user can
   * provide answers. In non-interactive mode without ACP support, we skip
   * confirmation (and subsequently skip execution).
   */
  async getDefaultPermission() {
    const isAcpMode = this._config.getExperimentalZedIntegration() || this._config.getInputFormat() === "stream-json" /* STREAM_JSON */;
    if (!this._config.isInteractive() && !isAcpMode) {
      return "allow";
    }
    return "ask";
  }
  async getConfirmationDetails(_abortSignal) {
    const details = {
      type: "ask_user_question",
      title: "Please answer the following question(s):",
      questions: this.params.questions,
      metadata: this.params.metadata,
      onConfirm: /* @__PURE__ */ __name(async (outcome, payload) => {
        switch (outcome) {
          case "proceed_once" /* ProceedOnce */:
          case "proceed_always" /* ProceedAlways */:
            this.wasAnswered = true;
            this.userAnswers = payload?.answers ?? {};
            break;
          case "cancel" /* Cancel */:
            this.wasAnswered = false;
            break;
          default:
            this.wasAnswered = true;
            this.userAnswers = payload?.answers ?? {};
            break;
        }
      }, "onConfirm")
    };
    return details;
  }
  async execute(_signal) {
    try {
      const isAcpMode = this._config.getExperimentalZedIntegration() || this._config.getInputFormat() === "stream-json" /* STREAM_JSON */;
      if (!this._config.isInteractive() && !isAcpMode) {
        const errorMessage = "Cannot ask user questions in non-interactive mode without ACP support. Please run in interactive mode or enable ACP mode to use this tool.";
        return {
          llmContent: errorMessage,
          returnDisplay: errorMessage
        };
      }
      if (!this.wasAnswered) {
        const cancellationMessage = "User declined to answer the questions.";
        return {
          llmContent: cancellationMessage,
          returnDisplay: cancellationMessage
        };
      }
      const answersContent = Object.entries(this.userAnswers).flatMap(([key, value]) => {
        const questionIndex = parseAnswerQuestionIndex(
          key,
          this.params.questions.length
        );
        if (questionIndex === void 0) return [];
        const question = this.params.questions[questionIndex];
        return `**${question.header || `Question ${questionIndex + 1}`}**: ${value}`;
      }).join("\n");
      this.applyPlanGateMetadata();
      const messageBody = answersContent.length > 0 ? answersContent : "No valid answers were provided.";
      const llmMessage = `User has provided the following answers:

${messageBody}`;
      const displayMessage = `User has provided the following answers:

${messageBody}`;
      return {
        llmContent: llmMessage,
        returnDisplay: displayMessage
      };
    } catch (error) {
      const errorMessage = error instanceof Error ? error.message : String(error);
      debugLogger.error(
        `[AskUserQuestionTool] Error executing ask_user_question: ${errorMessage}`
      );
      const errorLlmContent = `Failed to process user answers: ${errorMessage}`;
      return {
        llmContent: errorLlmContent,
        returnDisplay: `Error processing answers: ${errorMessage}`
      };
    }
  }
  /**
   * Updates Plan Approval Gate state based on the metadata.source field
   * and the user's answer. Only acts on recognized gate metadata sources.
   */
  applyPlanGateMetadata() {
    const source = this.params.metadata?.source;
    if (!source) return;
    const gateState = this._config.getPlanGateState();
    if (!gateState) return;
    if (source === "plan_gate_cap") {
      if (!gateState.capEscalationPending) {
        debugLogger.warn(
          "[applyPlanGateMetadata] plan_gate_cap ignored: no cap escalation pending"
        );
        return;
      }
      const firstAnswer = Object.values(this.userAnswers)[0] ?? "";
      if (firstAnswer === CAP_ESCALATION_LABELS.CONTINUE) {
        gateState.gateMode = "uncapped";
      } else if (firstAnswer === CAP_ESCALATION_LABELS.APPROVE) {
        gateState.gateMode = "user_override";
      } else {
        gateState.gateMode = "user_takeover";
      }
      gateState.capEscalationPending = false;
    } else if (source === "plan_gate_needs_user") {
      if (!gateState.needsUserPending) {
        debugLogger.warn(
          "[applyPlanGateMetadata] plan_gate_needs_user ignored: no needs_user pending"
        );
        return;
      }
      if (gateState.gateMode === "capped" || gateState.gateMode === "uncapped") {
        gateState.reviewCount = 0;
      }
      gateState.needsUserPending = false;
    }
  }
};
var AskUserQuestionTool = class _AskUserQuestionTool extends BaseDeclarativeTool {
  constructor(config) {
    super(
      _AskUserQuestionTool.Name,
      ToolDisplayNames.ASK_USER_QUESTION,
      askUserQuestionToolDescription,
      "think" /* Think */,
      askUserQuestionToolSchemaData.parametersJsonSchema,
      true,
      // isOutputMarkdown
      false,
      // canUpdateOutput
      false
      // shouldDefer — kept always-visible so the model reaches for the structured clarification UX instead of asking in plain prose
    );
    this.config = config;
  }
  static {
    __name(this, "AskUserQuestionTool");
  }
  static Name = ToolNames.ASK_USER_QUESTION;
  validateToolParams(params) {
    if (!Array.isArray(params.questions)) {
      return 'Parameter "questions" must be an array.';
    }
    if (params.questions.length < 1 || params.questions.length > 4) {
      return 'Parameter "questions" must contain between 1 and 4 questions.';
    }
    for (let i = 0; i < params.questions.length; i++) {
      const question = params.questions[i];
      if (!question.question || typeof question.question !== "string" || question.question.trim() === "") {
        return `Question ${i + 1}: "question" must be a non-empty string.`;
      }
      if (!question.header || typeof question.header !== "string" || question.header.trim() === "") {
        return `Question ${i + 1}: "header" must be a non-empty string.`;
      }
      if (question.header.length > 12) {
        return `Question ${i + 1}: "header" must be 12 characters or less.`;
      }
      if (!Array.isArray(question.options)) {
        return `Question ${i + 1}: "options" must be an array.`;
      }
      if (question.options.length < 2 || question.options.length > 4) {
        return `Question ${i + 1}: "options" must contain between 2 and 4 options.`;
      }
      for (let j = 0; j < question.options.length; j++) {
        const option = question.options[j];
        if (!option.label || typeof option.label !== "string" || option.label.trim() === "") {
          return `Question ${i + 1}, Option ${j + 1}: "label" must be a non-empty string.`;
        }
        if (!option.description || typeof option.description !== "string" || option.description.trim() === "") {
          return `Question ${i + 1}, Option ${j + 1}: "description" must be a non-empty string.`;
        }
      }
      if (question.multiSelect !== void 0 && typeof question.multiSelect !== "boolean") {
        return `Question ${i + 1}: "multiSelect" must be a boolean.`;
      }
    }
    return null;
  }
  createInvocation(params) {
    return new AskUserQuestionToolInvocation(this.config, params);
  }
};
export {
  AskUserQuestionTool
};
/**
 * @license
 * Copyright 2025 Qwen
 * SPDX-License-Identifier: Apache-2.0
 */
