import { type Tool } from '@modelcontextprotocol/sdk/types.js';

export const TOOL_NAMES = {
  BROWSER: {
    GET_WINDOWS_AND_TABS: 'get_windows_and_tabs',
    SEARCH_TABS_CONTENT: 'search_tabs_content',
    NAVIGATE: 'chrome_navigate',
    SCREENSHOT: 'chrome_screenshot',
    CLOSE_TABS: 'chrome_close_tabs',
    SWITCH_TAB: 'chrome_switch_tab',
    WEB_FETCHER: 'chrome_get_web_content',
    CLICK: 'chrome_click_element',
    FILL: 'chrome_fill_or_select',
    REQUEST_ELEMENT_SELECTION: 'chrome_request_element_selection',
    GET_INTERACTIVE_ELEMENTS: 'chrome_get_interactive_elements',
    NETWORK_CAPTURE: 'chrome_network_capture',
    // Legacy tool names (kept for internal use, not exposed in TOOL_SCHEMAS)
    NETWORK_CAPTURE_START: 'chrome_network_capture_start',
    NETWORK_CAPTURE_STOP: 'chrome_network_capture_stop',
    NETWORK_REQUEST: 'chrome_network_request',
    NETWORK_DEBUGGER_START: 'chrome_network_debugger_start',
    NETWORK_DEBUGGER_STOP: 'chrome_network_debugger_stop',
    KEYBOARD: 'chrome_keyboard',
    HISTORY: 'chrome_history',
    BOOKMARK_SEARCH: 'chrome_bookmark_search',
    BOOKMARK_ADD: 'chrome_bookmark_add',
    BOOKMARK_DELETE: 'chrome_bookmark_delete',
    INJECT_SCRIPT: 'chrome_inject_script',
    SEND_COMMAND_TO_INJECT_SCRIPT: 'chrome_send_command_to_inject_script',
    JAVASCRIPT: 'chrome_javascript',
    CONSOLE: 'chrome_console',
    FILE_UPLOAD: 'chrome_upload_file',
    READ_PAGE: 'chrome_read_page',
    COMPUTER: 'chrome_computer',
    HANDLE_DIALOG: 'chrome_handle_dialog',
    HANDLE_DOWNLOAD: 'chrome_handle_download',
    USERSCRIPT: 'chrome_userscript',
    PERFORMANCE_START_TRACE: 'performance_start_trace',
    PERFORMANCE_STOP_TRACE: 'performance_stop_trace',
    PERFORMANCE_ANALYZE_INSIGHT: 'performance_analyze_insight',
    GIF_RECORDER: 'chrome_gif_recorder',
  },
  RECORD_REPLAY: {
    FLOW_RUN: 'record_replay_flow_run',
    RUN_CANCEL: 'record_replay_run_cancel',
    LIST_PUBLISHED: 'record_replay_list_published',
    RECORDING_START: 'recording_start',
    RECORDING_STOP: 'recording_stop',
    RECORDING_STATUS: 'recording_status',
    FLOW_ANALYZE: 'flow_analyze',
    FLOW_UPDATE: 'flow_update',
    WORKFLOW_DESCRIBE: 'workflow_describe',
    WORKFLOW_DEBUG_VIEW: 'workflow_debug_view',
    WORKFLOW_REPAIR: 'workflow_repair',
    WORKFLOW_REPAIR_ROLLBACK: 'workflow_repair_rollback',
    WORKFLOW_STABILIZE: 'workflow_stabilize',
    WORKFLOW_MIGRATE: 'workflow_migrate',
    WORKFLOW_APPROVAL_STORE: 'workflow_approval_store',
    WORKFLOW_RELEASE_READINESS: 'workflow_release_readiness',
    WORKFLOW_PUBLISH: 'workflow_publish',
    WORKFLOW_UNPUBLISH: 'workflow_unpublish',
  },
};

export const TOOL_SCHEMAS: Tool[] = [
  {
    name: TOOL_NAMES.BROWSER.GET_WINDOWS_AND_TABS,
    description:
      'Get all currently open browser windows and tabs. Non-public tab URLs and titles are redacted.',
    inputSchema: {
      type: 'object',
      properties: {},
      required: [],
    },
  },
  {
    name: TOOL_NAMES.RECORD_REPLAY.RECORDING_START,
    description:
      'Start recording user interactions on an HTTP(S) browser tab. If tabId is omitted, uses the active tab.',
    inputSchema: {
      type: 'object',
      properties: {
        tabId: {
          type: 'number',
          description: 'Optional target HTTP(S) tab ID to record on.',
        },
        name: {
          type: 'string',
          description: 'Optional flow name used for the newly recorded flow.',
        },
      },
      required: [],
    },
  },
  {
    name: TOOL_NAMES.RECORD_REPLAY.RECORDING_STOP,
    description:
      'Stop the active recording session and persist the recorded flow. Optionally rename the flow.',
    inputSchema: {
      type: 'object',
      properties: {
        name: {
          type: 'string',
          description: 'Optional flow name to apply before saving.',
        },
        description: {
          type: 'string',
          description: 'Optional flow description to apply before saving.',
        },
      },
      required: [],
    },
  },
  {
    name: TOOL_NAMES.RECORD_REPLAY.RECORDING_STATUS,
    description: 'Get the current recording status and session snapshot.',
    inputSchema: {
      type: 'object',
      properties: {},
      required: [],
    },
  },
  {
    name: TOOL_NAMES.RECORD_REPLAY.FLOW_ANALYZE,
    description:
      'Analyze a recorded flow and return optimization hints plus a minimized public flow view (summary structure, sanitized variables, and safe metadata only).',
    inputSchema: {
      type: 'object',
      properties: {
        flowId: {
          type: 'string',
          description: 'Flow ID to analyze.',
        },
      },
      required: ['flowId'],
    },
  },
  {
    name: TOOL_NAMES.RECORD_REPLAY.RUN_CANCEL,
    description:
      'Cancel a queued, running, or paused record/replay run by runId. Queued runs are canceled immediately; active runs receive a cancel request and can optionally be waited to terminal state.',
    inputSchema: {
      type: 'object',
      additionalProperties: false,
      properties: {
        runId: {
          type: 'string',
          description: 'Run ID to cancel.',
        },
        reason: {
          type: 'string',
          description:
            'Optional cancellation reason recorded in the run.canceled event.',
        },
        waitForTerminal: {
          type: 'boolean',
          default: true,
          description:
            'Wait briefly for a running/paused run to reach canceled terminal state.',
        },
        timeoutMs: {
          type: 'number',
          minimum: 100,
          maximum: 30000,
          default: 5000,
          description: 'Maximum wait time when waitForTerminal is true.',
        },
      },
      required: ['runId'],
    },
  },
  {
    name: TOOL_NAMES.RECORD_REPLAY.FLOW_UPDATE,
    description:
      'Update a flow using partial fields such as nodes, edges, variables or metadata.',
    inputSchema: {
      type: 'object',
      properties: {
        flowId: {
          type: 'string',
          description: 'Flow ID to update.',
        },
        name: {
          type: 'string',
          description: 'Optional new flow name.',
        },
        description: {
          type: 'string',
          description: 'Optional new flow description.',
        },
        nodes: {
          type: 'array',
          description: 'Optional replacement nodes array.',
          items: { type: 'object' },
        },
        edges: {
          type: 'array',
          description: 'Optional replacement edges array.',
          items: { type: 'object' },
        },
        variables: {
          type: 'array',
          description:
            'Optional replacement V3 variables array. Each item should use `name` plus optional `label`, `description`, `default`, `required`, `sensitive`, `kind`, `options`, `item`, and `scope` (`flow` or `run`). Legacy `key`, `type`, and `rules` inputs may be normalized but are deprecated.',
          items: {
            type: 'object',
            properties: {
              name: { type: 'string' },
              key: { type: 'string' },
              label: { type: 'string' },
              description: { type: 'string' },
              default: {},
              required: { type: 'boolean' },
              sensitive: { type: 'boolean' },
              kind: {
                type: 'string',
                enum: ['string', 'number', 'boolean', 'json', 'enum', 'array'],
              },
              type: {
                type: 'string',
                enum: ['string', 'number', 'boolean', 'json', 'enum', 'array'],
                description: 'Legacy alias for `kind`.',
              },
              options: {
                type: 'array',
                description: 'Allowed values when `kind` is `enum`.',
                items: {},
              },
              item: {
                type: 'string',
                enum: ['string', 'number', 'boolean', 'json'],
                description: 'Array item type when `kind` is `array`.',
              },
              rules: {
                type: 'object',
                description:
                  'Legacy compatibility wrapper for `required` and enum `options`.',
                properties: {
                  required: { type: 'boolean' },
                  enum: {
                    type: 'array',
                    items: {},
                  },
                },
              },
              scope: { type: 'string', enum: ['flow', 'run'] },
            },
          },
        },
        applyParameterSuggestions: {
          type: 'boolean',
          description:
            'If true, applies flow.meta.recording.parameterSuggestions to nodes and auto-adds missing variables.',
        },
        requireCurrentRevision: {
          type: 'string',
          description:
            'Optional workflow revision guard. When provided, the update is rejected if the current workflow revision differs.',
        },
      },
      required: ['flowId'],
    },
  },
  {
    name: TOOL_NAMES.RECORD_REPLAY.WORKFLOW_DESCRIBE,
    description:
      'Describe a recorded or published workflow for agent use, including parameter schema, example args, background support, side-effect summary, outputs, and quality hints.',
    inputSchema: {
      type: 'object',
      properties: {
        flowId: {
          type: 'string',
          description:
            'Flow ID to describe. Either flowId or workflow is required.',
        },
        workflow: {
          type: 'string',
          description:
            'Published workflow slug to describe. Either workflow or flowId is required.',
        },
      },
      required: [],
    },
  },
  {
    name: TOOL_NAMES.RECORD_REPLAY.WORKFLOW_DEBUG_VIEW,
    description:
      'Return a safe debug view for a recorded or published workflow, including descriptor metadata, sanitized node configs, quality hints, and recent run events.',
    inputSchema: {
      type: 'object',
      properties: {
        flowId: {
          type: 'string',
          description:
            'Flow ID to inspect. Either flowId or workflow is required.',
        },
        workflow: {
          type: 'string',
          description:
            'Published workflow slug to inspect. Either workflow or flowId is required.',
        },
        runId: {
          type: 'string',
          description: 'Optional specific run ID to include in the debug view.',
        },
        nodeId: {
          type: 'string',
          description:
            'Optional node ID filter for returned events and artifacts.',
        },
        includeRuns: {
          type: 'boolean',
          default: true,
          description: 'Include recent run summaries and selected events.',
        },
        maxRuns: {
          type: 'number',
          minimum: 0,
          maximum: 10,
          description:
            'Maximum recent runs to include when runId is omitted. Default: 3.',
        },
        maxEventsPerRun: {
          type: 'number',
          minimum: 0,
          maximum: 100,
          description: 'Maximum recent events to include per run. Default: 40.',
        },
        maxEvents: {
          type: 'number',
          minimum: 0,
          maximum: 100,
          description: 'Alias for maxEventsPerRun. Default: 40.',
        },
        includeArtifacts: {
          type: 'boolean',
          default: true,
          description:
            'Include persisted debug artifact metadata for returned runs.',
        },
        includeArtifactData: {
          type: 'boolean',
          description:
            'Explicitly request screenshot base64 data for returned artifacts. Low-confidence or truncated artifacts are never inlined.',
        },
        maxArtifactDataBytes: {
          type: 'number',
          minimum: 0,
          maximum: 8388608,
          description:
            'Maximum artifact payload size to inline when includeArtifactData is true. Default: 2097152.',
        },
        cleanupArtifacts: {
          type: 'boolean',
          default: false,
          description:
            'Delete persisted artifacts for the specified runId before returning the debug view. Requires runId.',
        },
      },
      required: [],
    },
  },
  {
    name: TOOL_NAMES.RECORD_REPLAY.WORKFLOW_REPAIR,
    description:
      'Diagnose workflow replay stability and optionally apply low-risk repair actions such as parameterizing recorded literals, adding timeout/failure screenshots, and scoping retry to safe read/query steps.',
    inputSchema: {
      type: 'object',
      properties: {
        flowId: {
          type: 'string',
          description:
            'Flow ID to repair. Either flowId or workflow is required.',
        },
        workflow: {
          type: 'string',
          description:
            'Published workflow slug to repair. Either workflow or flowId is required.',
        },
        runId: {
          type: 'string',
          description: 'Optional recent run ID to use as failure context.',
        },
        apply: {
          type: 'boolean',
          default: false,
          description:
            'When true, apply safe automatic repairs. Default false returns recommendations only.',
        },
        dryRun: {
          type: 'boolean',
          default: false,
          description: 'When true, never writes changes even if apply is true.',
        },
        applyParameterSuggestions: {
          type: 'boolean',
          default: true,
          description:
            'Apply recorded parameter suggestions when apply is true. Converts supported literal fill/navigate values into variables.',
        },
        applyDefaultStabilityPolicy: {
          type: 'boolean',
          default: true,
          description:
            'Add missing timeout/on-failure screenshots and side-effect-scoped retry for safe read/query nodes when apply is true.',
        },
        maxRuns: {
          type: 'number',
          minimum: 0,
          maximum: 10,
          description:
            'Maximum recent runs to inspect when runId is omitted. Default: 3.',
        },
        maxEventsPerRun: {
          type: 'number',
          minimum: 0,
          maximum: 100,
          description: 'Maximum recent events to inspect per run. Default: 40.',
        },
      },
      required: [],
    },
  },
  {
    name: TOOL_NAMES.RECORD_REPLAY.WORKFLOW_REPAIR_ROLLBACK,
    description:
      'Rollback a previously applied workflow repair using the stored pre-repair workflow snapshot. Rollback restores the workflow definition only; external side effects are not reversed.',
    inputSchema: {
      type: 'object',
      additionalProperties: false,
      properties: {
        flowId: {
          type: 'string',
          description:
            'Flow ID to rollback. Exactly one of flowId or workflow is required.',
        },
        workflow: {
          type: 'string',
          description:
            'Published workflow slug to rollback. Exactly one of workflow or flowId is required.',
        },
        repairRevision: {
          type: 'string',
          description:
            'Optional repair revision to rollback. Defaults to the latest repair history entry with a rollback snapshot.',
        },
        requireCurrentRevision: {
          type: 'string',
          description:
            'Optional guard revision. If provided, rollback is rejected unless the current workflow revision matches.',
        },
        dryRun: {
          type: 'boolean',
          default: false,
          description:
            'Inspect the selected rollback snapshot without writing changes.',
        },
        force: {
          type: 'boolean',
          default: false,
          description:
            'Allow rollback even when the workflow revision has changed since the selected repair was applied.',
        },
      },
      oneOf: [{ required: ['flowId'] }, { required: ['workflow'] }],
      allOf: [
        {
          not: {
            required: ['flowId', 'workflow'],
          },
        },
      ],
      required: [],
    },
  },
  {
    name: TOOL_NAMES.RECORD_REPLAY.WORKFLOW_STABILIZE,
    description:
      'Analyze workflow stability, risk, debug capability, and repair recommendations. Dangerous or unknown workflows default to analyze-only unless a trusted approval policy exists.',
    inputSchema: {
      type: 'object',
      additionalProperties: false,
      properties: {
        flowId: {
          type: 'string',
          description:
            'Draft or recorded flow ID to stabilize. Exactly one of flowId or workflow is required.',
        },
        workflow: {
          type: 'string',
          description:
            'Published workflow slug to stabilize. Exactly one of workflow or flowId is required.',
        },
        args: {
          type: 'object',
          description: 'Workflow variable values keyed by variable name.',
          additionalProperties: true,
        },
        startUrl: {
          type: 'string',
          description:
            'Optional http(s) URL used as the validation start point.',
        },
        tabId: {
          type: 'number',
          description:
            'Explicit tab to bind diagnostic runs to. Cannot be combined with tabTarget=new.',
        },
        tabTarget: {
          type: 'string',
          enum: ['current', 'new'],
          default: 'current',
        },
        background: {
          type: 'boolean',
          default: false,
        },
        iterations: {
          type: 'number',
          minimum: 1,
          maximum: 10,
          default: 3,
        },
        minPassRate: {
          type: 'number',
          minimum: 0,
          maximum: 1,
          default: 1,
        },
        apply: {
          type: 'boolean',
          default: false,
        },
        dryRun: {
          type: 'boolean',
          default: false,
        },
        stopOnDangerousSideEffects: {
          type: 'boolean',
          description:
            'Compatibility alias. Prefer safety.executionMode and safety.maxDangerousRuns.',
        },
        repair: {
          type: 'object',
          additionalProperties: false,
          properties: {
            parameterize: { type: 'boolean', default: true },
            defaultStabilityPolicy: { type: 'boolean', default: true },
            selectors: { type: 'boolean', default: true },
            waits: { type: 'boolean', default: true },
            assertions: { type: 'boolean', default: true },
          },
        },
        safety: {
          type: 'object',
          additionalProperties: false,
          properties: {
            executionMode: {
              type: 'string',
              enum: [
                'auto',
                'analyzeOnly',
                'sandboxReplay',
                'userApprovedReplay',
              ],
              default: 'auto',
            },
            allowExternalSideEffects: { type: 'boolean', default: false },
            maxDangerousRuns: {
              type: 'number',
              minimum: 0,
              maximum: 3,
              default: 0,
            },
            requireRevision: { type: 'string' },
            allowedHosts: { type: 'array', items: { type: 'string' } },
            testEnvironment: {
              type: 'object',
              additionalProperties: false,
              properties: {
                name: { type: 'string' },
                origins: { type: 'array', items: { type: 'string' } },
                pathPrefixes: { type: 'array', items: { type: 'string' } },
                accountLabel: { type: 'string' },
                allowedExternalDestinations: {
                  type: 'array',
                  items: { type: 'string' },
                },
              },
            },
            authorization: {
              type: 'object',
              additionalProperties: false,
              properties: {
                approvalId: { type: 'string' },
                approvedBy: { type: 'string', enum: ['user', 'ui', 'policy'] },
                approvedAt: { type: 'string' },
              },
            },
            resetWorkflow: {
              type: 'string',
              description: 'Compatibility alias for safety.reset.workflow.',
            },
            reset: {
              type: 'object',
              additionalProperties: false,
              properties: {
                workflow: { type: 'string' },
                args: { type: 'object', additionalProperties: true },
                maxRuns: { type: 'number', minimum: 0, maximum: 3, default: 1 },
                requireStable: { type: 'boolean', default: true },
              },
            },
            segments: {
              type: 'object',
              additionalProperties: false,
              properties: {
                mode: {
                  type: 'string',
                  enum: ['none', 'stopBeforeDangerous', 'explicit'],
                  default: 'none',
                },
                stopBeforeNodeId: { type: 'string' },
                endNodeId: { type: 'string' },
              },
            },
            nodeRiskOverrides: {
              type: 'object',
              patternProperties: {
                '^[A-Za-z0-9_.:-]+$': {
                  type: 'string',
                  enum: ['safe', 'idempotent', 'dangerous'],
                },
              },
              additionalProperties: false,
            },
          },
        },
        debug: {
          type: 'object',
          additionalProperties: false,
          properties: {
            captureArtifacts: {
              type: 'string',
              enum: ['none', 'failureOnly', 'all'],
              default: 'failureOnly',
            },
            keepTabOpenOnFailure: { type: 'boolean', default: false },
            domSnapshot: {
              type: 'string',
              enum: ['none', 'failureTargetSlice', 'accessibilitySlice'],
              default: 'none',
            },
            maxEventsPerRun: {
              type: 'number',
              minimum: 0,
              maximum: 100,
              default: 40,
            },
            artifactTtlMs: { type: 'number', minimum: 1000 },
            maxArtifactBytes: { type: 'number', minimum: 0 },
          },
        },
        tab: {
          type: 'object',
          additionalProperties: false,
          properties: {
            ownership: {
              type: 'string',
              enum: ['owned', 'current'],
              default: 'owned',
            },
            allowFocusChange: { type: 'boolean', default: false },
            cleanup: {
              type: 'string',
              enum: ['always', 'onSuccess', 'manual'],
              default: 'always',
            },
          },
        },
      },
      oneOf: [
        { required: ['flowId'], not: { required: ['workflow'] } },
        { required: ['workflow'], not: { required: ['flowId'] } },
      ],
      allOf: [
        {
          not: {
            required: ['apply', 'dryRun'],
            properties: {
              apply: { const: true },
              dryRun: { const: true },
            },
          },
        },
        {
          not: {
            required: ['tabId', 'tabTarget'],
            properties: {
              tabTarget: { const: 'new' },
            },
          },
        },
      ],
    },
  },
  {
    name: TOOL_NAMES.RECORD_REPLAY.WORKFLOW_MIGRATE,
    description:
      'Dry-run, apply, or rollback workflow schema/runtime metadata migrations. Reports per-flow compatibility, quality staleness, and audit/rollback information without executing workflows.',
    inputSchema: {
      type: 'object',
      properties: {
        flowId: {
          type: 'string',
          description:
            'Flow ID to migrate. Exactly one of flowId, workflow, or all=true is required.',
        },
        workflow: {
          type: 'string',
          description:
            'Published workflow slug to migrate. Exactly one of workflow, flowId, or all=true is required.',
        },
        all: {
          type: 'boolean',
          default: false,
          description:
            'Inspect or migrate all stored workflows. Cannot be used for rollback.',
        },
        dryRun: {
          type: 'boolean',
          default: true,
          description: 'Return the migration report without writing changes.',
        },
        apply: {
          type: 'boolean',
          default: false,
          description:
            'Persist the reported migration changes. Cannot be true when dryRun is true.',
        },
        rollbackMigrationId: {
          type: 'string',
          description:
            'Rollback a previously applied migration on a single flow/workflow using the audit rollback snapshot.',
        },
      },
      oneOf: [
        {
          required: ['flowId'],
          not: { anyOf: [{ required: ['workflow'] }, { required: ['all'] }] },
        },
        {
          required: ['workflow'],
          not: { anyOf: [{ required: ['flowId'] }, { required: ['all'] }] },
        },
        {
          required: ['all'],
          properties: { all: { const: true } },
          not: {
            anyOf: [
              { required: ['flowId'] },
              { required: ['workflow'] },
              { required: ['rollbackMigrationId'] },
            ],
          },
        },
      ],
      allOf: [
        {
          not: {
            required: ['apply', 'dryRun'],
            properties: {
              apply: { const: true },
              dryRun: { const: true },
            },
          },
        },
      ],
      additionalProperties: false,
    },
  },
  {
    name: TOOL_NAMES.RECORD_REPLAY.WORKFLOW_APPROVAL_STORE,
    description:
      'Inspect or revoke trusted workflow approval records. This tool cannot create approvals; approval creation must come from UI/user confirmation or a preconfigured policy store.',
    inputSchema: {
      type: 'object',
      properties: {
        operation: {
          type: 'string',
          enum: ['list', 'get', 'revoke'],
          default: 'list',
        },
        approvalId: {
          type: 'string',
          description: 'Approval ID required for get and revoke operations.',
        },
        includeRevoked: {
          type: 'boolean',
          default: false,
          description: 'Include revoked records when listing approvals.',
        },
        reason: {
          type: 'string',
          description: 'Optional reason recorded when revoking an approval.',
        },
      },
      allOf: [
        {
          if: {
            properties: { operation: { enum: ['get', 'revoke'] } },
          },
          then: {
            required: ['approvalId'],
          },
        },
      ],
      additionalProperties: false,
    },
  },
  {
    name: TOOL_NAMES.RECORD_REPLAY.WORKFLOW_RELEASE_READINESS,
    description:
      'Build and persist a local release readiness checklist for workflow features, including SLO conclusions, sample-size warnings, runtime metrics, audit evidence, rollback evidence, and default-on gating.',
    inputSchema: {
      type: 'object',
      additionalProperties: false,
      properties: {
        flowId: {
          type: 'string',
          description:
            'Optional single flow ID to assess. Mutually exclusive with workflow and all=true.',
        },
        workflow: {
          type: 'string',
          description:
            'Optional published workflow slug to assess. Mutually exclusive with flowId and all=true.',
        },
        all: {
          type: 'boolean',
          default: true,
          description:
            'Assess all stored workflows when no flowId or workflow is provided.',
        },
        publishedOnly: {
          type: 'boolean',
          default: false,
          description:
            'When true, only published workflows are included in all-scope reports.',
        },
        releaseId: {
          type: 'string',
          description:
            'Optional release/checklist identifier. Generated when omitted.',
        },
        defaultOn: {
          type: 'boolean',
          default: false,
          description:
            'Evaluate the stricter default-on gate. Unmet checklist items become blocked.',
        },
        persist: {
          type: 'boolean',
          default: true,
          description:
            'Persist the generated checklist snapshot to the local release checklist store.',
        },
        minSafeWorkflowCount: {
          type: 'number',
          minimum: 1,
          maximum: 10000,
          default: 30,
          description:
            'Minimum safe/idempotent workflow sample count required before default-on SLO claims.',
        },
        minValidationRuns: {
          type: 'number',
          minimum: 1,
          maximum: 100000,
          default: 100,
          description:
            'Minimum counted validation run sample required before default-on SLO claims.',
        },
        minReliability: {
          type: 'number',
          minimum: 0,
          maximum: 1,
          default: 0.99,
          description: 'Minimum published workflow reliability threshold.',
        },
        minTokenReduction: {
          type: 'number',
          minimum: 0,
          maximum: 1,
          default: 0.7,
          description:
            'Minimum paired transcript token reduction required for the token SLO.',
        },
        maxFalseRepairRate: {
          type: 'number',
          minimum: 0,
          maximum: 1,
          default: 0.01,
          description: 'Maximum allowed false repair rate.',
        },
        evidence: {
          type: 'object',
          additionalProperties: false,
          properties: {
            pairedTokenBaselineCount: { type: 'number', minimum: 0 },
            averageTokenReduction: { type: 'number', minimum: 0, maximum: 1 },
            safetyReviewCompleted: { type: 'boolean', default: false },
            browserE2eCompleted: { type: 'boolean', default: false },
            chaosUpgradeCompleted: { type: 'boolean', default: false },
            docsUpdated: { type: 'boolean', default: false },
            killSwitchVerified: { type: 'boolean', default: false },
            links: {
              type: 'array',
              items: { type: 'string' },
              description:
                'Optional local file paths, run IDs, or issue links supporting the checklist.',
            },
          },
        },
      },
      allOf: [
        {
          not: {
            anyOf: [
              { required: ['flowId', 'workflow'] },
              {
                required: ['flowId', 'all'],
                properties: { all: { const: true } },
              },
              {
                required: ['workflow', 'all'],
                properties: { all: { const: true } },
              },
            ],
          },
        },
      ],
      required: [],
    },
  },
  {
    name: TOOL_NAMES.RECORD_REPLAY.FLOW_RUN,
    description:
      'Run a recorded flow by ID with optional variables and run options. Returns a standardized run result.',
    inputSchema: {
      type: 'object',
      properties: {
        flowId: { type: 'string', description: 'ID of the flow to run' },
        requireRevision: {
          type: 'string',
          description:
            'Optional descriptor revision guard. If provided, the run is rejected before replay when the current workflow revision differs.',
        },
        args: {
          type: 'object',
          description:
            'Variable values for the flow (flat object of key/value). Sensitive values may be passed as { "secretRef": "..." } so plaintext is injected only at runtime. Use workflow_describe or record_replay_list_published to inspect the parameter schema and example args.',
        },
        tabId: {
          type: 'number',
          description:
            'Explicit tab to bind the run to. Overrides `tabTarget`.',
        },
        tabTarget: {
          type: 'string',
          description: "Target tab: 'current' or 'new' (default: current)",
          enum: ['current', 'new'],
        },
        background: {
          type: 'boolean',
          description:
            'Run without activating/focusing target tabs or windows where Chrome APIs allow it. Default: false. When the user has enabled MCP Background Mode, this defaults to true and an explicit false is ignored.',
        },
        refresh: {
          type: 'boolean',
          description: 'Refresh before running (default false)',
        },
        timeoutMs: {
          type: 'number',
          description: 'Global timeout in ms (optional)',
        },
        startUrl: {
          type: 'string',
          description:
            'Optional start URL to open before running. Only http:// and https:// URLs are allowed.',
        },
      },
      required: ['flowId'],
    },
  },
  {
    name: TOOL_NAMES.RECORD_REPLAY.LIST_PUBLISHED,
    description:
      'List published flows available as dynamic tools, including parameter schema, example args, background support, side-effect metadata, and outputs.',
    inputSchema: {
      type: 'object',
      properties: {},
      required: [],
    },
  },
  {
    name: TOOL_NAMES.RECORD_REPLAY.WORKFLOW_PUBLISH,
    description:
      'Publish a stabilized workflow as a callable MCP workflow slug after validating slug, schema, side effects, revision, background support, and quality gate.',
    inputSchema: {
      type: 'object',
      additionalProperties: false,
      properties: {
        flowId: {
          type: 'string',
          description: 'Draft or recorded flow ID to publish.',
        },
        slug: {
          type: 'string',
          description:
            'Optional published workflow slug. Defaults to an existing slug or a normalized flow name.',
        },
        description: {
          type: 'string',
          description:
            'Optional public workflow description for descriptors and lists.',
        },
        category: {
          type: 'string',
          description: 'Optional public category label for workflow discovery.',
        },
        requireStable: {
          type: 'boolean',
          default: true,
          description:
            'Require a current stable quality record for the resulting descriptor revision. Default true.',
        },
        requireVerified: {
          type: 'boolean',
          default: false,
          description:
            'Require verified quality with a normal or strong business oracle. Implies requireStable.',
        },
        allowUnverified: {
          type: 'boolean',
          default: false,
          description:
            'Explicit warning mode for publishing without requireStable. Required when requireStable is false.',
        },
        minStabilityScore: {
          type: 'number',
          minimum: 0,
          maximum: 1,
          description:
            'Optional minimum stability score for the publish quality gate.',
        },
        minValidationRuns: {
          type: 'number',
          minimum: 1,
          maximum: 100,
          description:
            'Optional minimum counted validation run count for the publish quality gate.',
        },
        minPassRate: {
          type: 'number',
          minimum: 0,
          maximum: 1,
          description:
            'Optional minimum passRate for the publish quality gate. Default: 1.',
        },
        allowWeakOracle: {
          type: 'boolean',
          default: false,
          description:
            'Allow weak verification oracles to satisfy requireVerified. The response remains marked with warnings.',
        },
      },
      required: ['flowId'],
    },
  },
  {
    name: TOOL_NAMES.RECORD_REPLAY.WORKFLOW_UNPUBLISH,
    description:
      'Unpublish a workflow slug or flow ID while preserving quality and repair history. The workflow remains stored as a draft.',
    inputSchema: {
      type: 'object',
      additionalProperties: false,
      properties: {
        flowId: {
          type: 'string',
          description:
            'Flow ID to unpublish. Exactly one of flowId or workflow is required.',
        },
        workflow: {
          type: 'string',
          description:
            'Published workflow slug to unpublish. Exactly one of workflow or flowId is required.',
        },
      },
      oneOf: [{ required: ['flowId'] }, { required: ['workflow'] }],
      allOf: [
        {
          not: {
            required: ['flowId', 'workflow'],
          },
        },
      ],
      required: [],
    },
  },
  {
    name: TOOL_NAMES.BROWSER.PERFORMANCE_START_TRACE,
    description:
      'Starts a performance trace recording on the selected HTTP(S) page. Optionally reloads the page and/or auto-stops after a short duration.',
    inputSchema: {
      type: 'object',
      properties: {
        reload: {
          type: 'boolean',
          description:
            'Determines if, once tracing has started, the page should be automatically reloaded (ignore cache).',
        },
        autoStop: {
          type: 'boolean',
          description:
            'Determines if the trace should be automatically stopped (default false).',
        },
        durationMs: {
          type: 'number',
          description:
            'Auto-stop duration in milliseconds when autoStop is true (default 5000).',
        },
      },
      required: [],
    },
  },
  {
    name: TOOL_NAMES.BROWSER.PERFORMANCE_STOP_TRACE,
    description:
      'Stops the active performance trace recording on the selected HTTP(S) page.',
    inputSchema: {
      type: 'object',
      properties: {
        saveToDownloads: {
          type: 'boolean',
          description:
            'Whether to save the trace as a JSON file in Downloads (default true).',
        },
        filenamePrefix: {
          type: 'string',
          description:
            'Optional filename prefix for the downloaded trace JSON.',
        },
      },
      required: [],
    },
  },
  {
    name: TOOL_NAMES.BROWSER.PERFORMANCE_ANALYZE_INSIGHT,
    description:
      'Provides a lightweight summary of the last recorded trace for an HTTP(S) page. For deep insights (CWV, breakdowns), integrate native-side DevTools trace engine.',
    inputSchema: {
      type: 'object',
      properties: {
        insightName: {
          type: 'string',
          description:
            'Optional insight name for future deep analysis (e.g., "DocumentLatency"). Currently informational only.',
        },
        timeoutMs: {
          type: 'number',
          description:
            'Timeout for deep analysis via native host (milliseconds). Default 60000. Increase for large traces.',
        },
      },
      required: [],
    },
  },
  {
    name: TOOL_NAMES.BROWSER.READ_PAGE,
    description:
      'Get an accessibility tree representation of visible elements on the current HTTP(S) page. Only returns elements that are visible in the viewport. Optionally filter for only interactive elements.\nTip: If the returned elements do not include the specific element you need, use the computer tool\'s screenshot (action="screenshot") to capture the element\'s on-screen coordinates, then operate by coordinates.',
    inputSchema: {
      type: 'object',
      properties: {
        filter: {
          type: 'string',
          description:
            'Filter elements: "interactive" for such as  buttons/links/inputs only (default: all visible elements)',
        },
        depth: {
          type: 'number',
          description:
            'Maximum DOM depth to traverse (integer >= 0). Lower values reduce output size and can improve performance.',
        },
        refId: {
          type: 'string',
          description:
            'Focus on the subtree rooted at this element refId (e.g., "ref_12"). The refId must come from a recent chrome_read_page response in the same tab (refs may expire).',
        },
        tabId: {
          type: 'number',
          description: 'Target an existing tab by ID (default: active tab).',
        },
        windowId: {
          type: 'number',
          description:
            'Target window ID to pick active tab when tabId is omitted.',
        },
        background: {
          type: 'boolean',
          description:
            'Read without activating/focusing the target tab. Default: false. When the user has enabled MCP Background Mode in the extension popup, this defaults to true and an explicit false is ignored. The accessibility tree helper now falls back to the document client size when a tab has no live viewport, so background tabs return a usable tree.',
        },
      },
      required: [],
    },
  },
  {
    name: TOOL_NAMES.BROWSER.COMPUTER,
    description:
      "Use a mouse and keyboard to interact with an HTTP(S) browser tab, and take screenshots.\n* Whenever you intend to click on an element like an icon, you should consult a read_page to determine the ref of the element before moving the cursor.\n* If you tried clicking on a program or link but it failed to load, even after waiting, try screenshot and then adjusting your click location so that the tip of the cursor visually falls on the element that you want to click.\n* Make sure to click any buttons, links, icons, etc with the cursor tip in the center of the element. Don't click boxes on their edges unless asked.",
    inputSchema: {
      type: 'object',
      properties: {
        tabId: {
          type: 'number',
          description: 'Target tab ID (default: active tab)',
        },
        background: {
          type: 'boolean',
          description:
            'Avoid focusing/activating tab/window for certain operations (best-effort). Default: false. When the user has enabled MCP Background Mode, this defaults to true and an explicit false is ignored.',
        },
        action: {
          type: 'string',
          description:
            'Action to perform: left_click | right_click | double_click | triple_click | left_click_drag | scroll | scroll_to | type | key | fill | fill_form | hover | wait | resize_page | zoom | screenshot. All page-targeting actions are only supported on HTTP(S) pages; `resize_page` and pure timer waits are exempt.',
        },
        ref: {
          type: 'string',
          description:
            'Element ref from chrome_read_page. For click/scroll/scroll_to/key/type and drag end when provided; takes precedence over coordinates.',
        },
        coordinates: {
          type: 'object',
          properties: {
            x: { type: 'number', description: 'X coordinate' },
            y: { type: 'number', description: 'Y coordinate' },
          },
          description:
            'Coordinates for actions (in screenshot space if a recent screenshot was taken, otherwise viewport). Required for click/scroll and as end point for drag.',
        },
        startCoordinates: {
          type: 'object',
          properties: {
            x: { type: 'number' },
            y: { type: 'number' },
          },
          description: 'Starting coordinates for drag action',
        },
        startRef: {
          type: 'string',
          description:
            'Drag start ref from chrome_read_page (alternative to startCoordinates).',
        },
        scrollDirection: {
          type: 'string',
          description: 'Scroll direction: up | down | left | right',
        },
        scrollAmount: {
          type: 'number',
          description: 'Scroll ticks (1-10), default 3',
        },
        text: {
          type: 'string',
          description:
            'Text to type (for action=type) or keys/chords separated by space (for action=key, e.g. "Backspace Enter" or "cmd+a")',
        },
        repeat: {
          type: 'number',
          description:
            'For action=key: number of times to repeat the key sequence (integer 1-100, default 1).',
        },
        modifiers: {
          type: 'object',
          description:
            'Modifier keys for click actions (left_click/right_click/double_click/triple_click).',
          properties: {
            altKey: { type: 'boolean' },
            ctrlKey: { type: 'boolean' },
            metaKey: { type: 'boolean' },
            shiftKey: { type: 'boolean' },
          },
        },
        region: {
          type: 'object',
          description:
            'For action=zoom on an HTTP(S) page: rectangular region to capture (x0,y0)-(x1,y1) in viewport pixels (or screenshot-space if a recent screenshot context exists).',
          properties: {
            x0: { type: 'number' },
            y0: { type: 'number' },
            x1: { type: 'number' },
            y1: { type: 'number' },
          },
          required: ['x0', 'y0', 'x1', 'y1'],
        },
        // For action=fill
        selector: {
          type: 'string',
          description: 'CSS selector for fill (alternative to ref).',
        },
        value: {
          oneOf: [{ type: 'string' }, { type: 'boolean' }, { type: 'number' }],
          description:
            'Value to set for action=fill (string | boolean | number)',
        },
        elements: {
          type: 'array',
          description:
            'For action=fill_form: list of elements to fill (ref + value)',
          items: {
            type: 'object',
            properties: {
              ref: {
                type: 'string',
                description: 'Element ref from chrome_read_page',
              },
              value: {
                type: 'string',
                description: 'Value to set (stringified if non-string)',
              },
            },
            required: ['ref', 'value'],
          },
        },
        width: {
          type: 'number',
          description: 'For action=resize_page: viewport width',
        },
        height: {
          type: 'number',
          description: 'For action=resize_page: viewport height',
        },
        appear: {
          type: 'boolean',
          description:
            'For action=wait with text: whether to wait for the text to appear (true, default) or disappear (false)',
        },
        timeout: {
          type: 'number',
          description:
            'For action=wait with text: timeout in milliseconds (default 10000, max 120000)',
        },
        duration: {
          type: 'number',
          description: 'Seconds to wait for action=wait (max 30s)',
        },
      },
      required: ['action'],
    },
  },
  // {
  //   name: TOOL_NAMES.BROWSER.USERSCRIPT,
  //   description:
  //     'Unified userscript tool (create/list/get/enable/disable/update/remove/send_command/export). Paste JS/CSS/Tampermonkey script and the system will auto-select the best strategy (insertCSS / persistent script in ISOLATED or MAIN world / once by CDP) with CSP-aware fallbacks.',
  //   inputSchema: {
  //     type: 'object',
  //     properties: {
  //       action: {
  //         type: 'string',
  //         description:
  //           'Operation to perform',
  //         enum: [
  //           'create',
  //           'list',
  //           'get',
  //           'enable',
  //           'disable',
  //           'update',
  //           'remove',
  //           'send_command',
  //           'export',
  //         ],
  //       },
  //       args: {
  //         type: 'object',
  //         description:
  //           'Arguments for the specified action.\n- create: { script (required), name?, description?, matches?: string[], excludes?: string[], persist?: boolean (default true), runAt?: "document_start"|"document_end"|"document_idle"|"auto", world?: "auto"|"ISOLATED"|"MAIN", allFrames?: boolean (default true), mode?: "auto"|"css"|"persistent"|"once", dnrFallback?: boolean (default true), tags?: string[] }\n- list: { query?: string, status?: "enabled"|"disabled", domain?: string }\n- get: { id (required) }\n- enable/disable: { id (required) }\n- update: { id (required), script?, name?, description?, matches?, excludes?, runAt?, world?, allFrames?, persist?, dnrFallback?, tags? }\n- remove: { id (required) }\n- send_command: { id (required), payload?: string, tabId?: number }\n- export: {}\nTip: For a one-off execution that returns a value, use create with args.mode="once". The returned value is included as onceResult in the tool response.',
  //         properties: {
  //           // Common identifiers
  //           id: { type: 'string', description: 'Userscript id (for get/enable/disable/update/remove/send_command)' },
  //           // Create / Update fields
  //           script: { type: 'string', description: 'JS/CSS/Tampermonkey script source (required for create)' },
  //           name: { type: 'string', description: 'Userscript name (optional)' },
  //           description: { type: 'string', description: 'Userscript description (optional)' },
  //           matches: {
  //             type: 'array',
  //             items: { type: 'string' },
  //             description: 'Match patterns for pages to apply to (e.g., https://*.example.com/*)'
  //           },
  //           excludes: {
  //             type: 'array',
  //             items: { type: 'string' },
  //             description: 'Exclude patterns'
  //           },
  //           persist: { type: 'boolean', description: 'Persist userscript for matched pages (default true)' },
  //           runAt: {
  //             type: 'string',
  //             description: 'Injection timing',
  //             enum: ['document_start', 'document_end', 'document_idle', 'auto'],
  //           },
  //           world: {
  //             type: 'string',
  //             description: 'Execution world',
  //             enum: ['auto', 'ISOLATED', 'MAIN'],
  //           },
  //           allFrames: { type: 'boolean', description: 'Inject into all frames (default true)' },
  //           mode: {
  //             type: 'string',
  //             description:
  //               'Injection strategy: auto | css | persistent | once. Use once to evaluate immediately (no persistence) and include the return value in onceResult.',
  //             enum: ['auto', 'css', 'persistent', 'once'],
  //           },
  //           dnrFallback: { type: 'boolean', description: 'Use DNR fallback when needed (default true)' },
  //           tags: { type: 'array', items: { type: 'string' }, description: 'Custom tags' },
  //           // List filters
  //           query: { type: 'string', description: 'Search by name/description (list action)' },
  //           status: { type: 'string', enum: ['enabled', 'disabled'], description: 'Filter by status (list action)' },
  //           domain: { type: 'string', description: 'Filter by domain (list action)' },
  //           // Send command
  //           payload: { type: 'string', description: 'Arbitrary payload (stringified) for send_command' },
  //           tabId: { type: 'number', description: 'Target tab for send_command (default active tab)' },
  //         },
  //       },
  //     },
  //     required: ['action'],
  //   },
  // },
  {
    name: TOOL_NAMES.BROWSER.NAVIGATE,
    description:
      'Open a URL in a new tab (default), navigate the user\'s current tab, open a new window, refresh the current HTTP(S) tab, or navigate browser history (back/forward) on an HTTP(S) tab. Defaults to opening URLs in a brand-new tab so the user\'s existing tabs are never clobbered; pass openMode="current_tab" only for explicit in-place navigation.',
    inputSchema: {
      type: 'object',
      properties: {
        url: {
          type: 'string',
          description:
            'URL to navigate to. Only http:// and https:// URLs are allowed. Special values: "back" or "forward" navigate browser history in the target tab.',
        },
        openMode: {
          type: 'string',
          enum: ['current_tab', 'new_tab', 'new_window'],
          description:
            'How to open the URL. Defaults to "new_tab" so the user\'s existing tabs are preserved. Pick a mode based on user intent:\n- "new_tab" (default): use for "open / show me / pull up / let\'s look at X" style requests, or when starting a new browsing task. Always safe when unsure.\n- "current_tab": use ONLY when the user explicitly says things like "in this tab", "navigate to", "go to", "load X here", or when you are following up on a previously returned tabId for the same in-progress task on that page.\n- "new_window": use only when the user explicitly asks for a separate window.',
        },
        newTab: {
          type: 'boolean',
          description:
            'Compatibility alias for openMode="new_tab". When true, always creates a fresh tab and never reuses an existing tab.',
        },
        newWindow: {
          type: 'boolean',
          description:
            'Compatibility alias for openMode="new_window". When true, always creates a new window for the URL.',
        },
        tabId: {
          type: 'number',
          description:
            'Target an existing tab by ID. Only consumed when openMode="current_tab" (selects which tab to navigate in-place); ignored for "new_tab" / "new_window". Passing tabId alone no longer forces in-place navigation — combine it with openMode="current_tab" if that is your intent.',
        },
        windowId: {
          type: 'number',
          description:
            'Target window ID. Used to choose the active tab when openMode="current_tab", or to choose which window receives a forced new tab.',
        },
        background: {
          type: 'boolean',
          description:
            'Perform the operation without stealing focus (do not activate the tab or focus the window). Default: false. When the user has enabled MCP Background Mode, this defaults to true and an explicit false is ignored.',
        },
        width: {
          type: 'number',
          description:
            'Window width in pixels (default: 1280). Only honoured when openMode="new_window" or newWindow=true. Passing width/height alone no longer auto-creates a new window.',
        },
        height: {
          type: 'number',
          description:
            'Window height in pixels (default: 720). Only honoured when openMode="new_window" or newWindow=true. Passing width/height alone no longer auto-creates a new window.',
        },
        refresh: {
          type: 'boolean',
          description:
            'Refresh the current active HTTP(S) tab instead of navigating to a URL. When true, the url parameter is ignored. Defaults to false',
        },
      },
      required: [],
    },
  },
  {
    name: TOOL_NAMES.BROWSER.SCREENSHOT,
    description:
      '[Prefer read_page over taking a screenshot and Prefer chrome_computer] Take a screenshot of the current HTTP(S) page or a specific element. For new usage, use chrome_computer with action="screenshot". Use this tool if you need advanced options.',
    inputSchema: {
      type: 'object',
      properties: {
        name: {
          type: 'string',
          description: 'Name for the screenshot, if saving as PNG',
        },
        selector: {
          type: 'string',
          description: 'CSS selector for element to screenshot',
        },
        tabId: {
          type: 'number',
          description: 'Target tab ID to capture from (default: active tab).',
        },
        windowId: {
          type: 'number',
          description:
            'Target window ID to pick active tab from when tabId is not provided.',
        },
        background: {
          type: 'boolean',
          description:
            'Attempt capture without bringing tab/window to foreground. CDP-based capture is used for simple viewport captures. For element/full-page capture, the tab may still be made active in its window without focusing the window. Default: false. When the user has enabled MCP Background Mode, this defaults to true for viewport captures and an explicit false is ignored (full-page/selector captures still need foreground today).',
        },
        width: {
          type: 'number',
          description: 'Width in pixels (default: 800)',
        },
        height: {
          type: 'number',
          description: 'Height in pixels (default: 600)',
        },
        storeBase64: {
          type: 'boolean',
          description:
            'return screenshot in base64 format (default: false) if you want to see the page, recommend set this to be true',
        },
        fullPage: {
          type: 'boolean',
          description: 'Store screenshot of the entire page (default: true)',
        },
        savePng: {
          type: 'boolean',
          description:
            'Save screenshot as PNG file (default: true)，if you want to see the page, recommend set this to be false, and set storeBase64 to be true',
        },
      },
      required: [],
    },
  },
  {
    name: TOOL_NAMES.BROWSER.CLOSE_TABS,
    description: 'Close one or more HTTP(S) browser tabs',
    inputSchema: {
      type: 'object',
      properties: {
        tabIds: {
          type: 'array',
          items: { type: 'number' },
          description:
            'Array of HTTP(S) tab IDs to close. If not provided, will close the active HTTP(S) tab.',
        },
        url: {
          type: 'string',
          description:
            'Close tabs matching this HTTP(S) URL. Can be used instead of tabIds.',
        },
        tabId: {
          type: 'number',
          description:
            'Target HTTP(S) tab ID to close when tabIds/url are omitted (default: current active tab).',
        },
        windowId: {
          type: 'number',
          description:
            'Window ID to select the active HTTP(S) tab from when tabId/tabIds/url are omitted.',
        },
      },
      required: [],
    },
  },
  {
    name: TOOL_NAMES.BROWSER.SWITCH_TAB,
    description: 'Switch to a specific HTTP(S) browser tab',
    inputSchema: {
      type: 'object',
      properties: {
        tabId: {
          type: 'number',
          description: 'The ID of the target HTTP(S) tab to switch to.',
        },
        windowId: {
          type: 'number',
          description: 'The ID of the window where the tab is located.',
        },
        background: {
          type: 'boolean',
          description:
            'Select the target tab for subsequent tool calls without activating the tab or focusing the window. Default: false. When the user has enabled MCP Background Mode, this defaults to true and an explicit false is ignored (the tab remains in the background).',
        },
      },
      required: ['tabId'],
    },
  },
  {
    name: TOOL_NAMES.BROWSER.WEB_FETCHER,
    description: 'Fetch content from an HTTP(S) web page',
    inputSchema: {
      type: 'object',
      properties: {
        url: {
          type: 'string',
          description:
            'HTTP(S) URL to fetch content from. If not provided, uses the current active tab',
        },
        tabId: {
          type: 'number',
          description: 'Target an existing tab by ID (default: active tab).',
        },
        background: {
          type: 'boolean',
          description:
            'Do not activate tab/focus window while fetching (default: false). When the user has enabled MCP Background Mode, this defaults to true and an explicit false is ignored.',
        },
        htmlContent: {
          type: 'boolean',
          description:
            'Get the visible HTML content of the page. If true, textContent will be ignored (default: false)',
        },
        textContent: {
          type: 'boolean',
          description:
            'Get the visible text content of the page with metadata. Ignored if htmlContent is true (default: true)',
        },

        selector: {
          type: 'string',
          description:
            'CSS selector to get content from a specific element. If provided, only content from this element will be returned',
        },
      },
      required: [],
    },
  },
  {
    name: TOOL_NAMES.BROWSER.NETWORK_REQUEST,
    description:
      'Send a network request from an HTTP(S) browser page with cookies and other browser context. The target tab/page must be HTTP(S). Absolute target URLs and attachment fileUrl values must use HTTP(S).',
    inputSchema: {
      type: 'object',
      properties: {
        url: {
          type: 'string',
          description:
            'Target URL to send the request to. Absolute URLs must use HTTP(S); relative URLs resolve against the current HTTP(S) page context.',
        },
        method: {
          type: 'string',
          description: 'HTTP method to use (default: GET)',
        },
        headers: {
          type: 'object',
          description: 'Headers to include in the request',
        },
        body: {
          type: 'string',
          description: 'Body of the request (for POST, PUT, etc.)',
        },
        timeout: {
          type: 'number',
          description: 'Timeout in milliseconds (default: 30000)',
        },
        formData: {
          type: 'object',
          description:
            'Multipart/form-data descriptor. If provided, overrides body and builds FormData with optional file attachments. Shape: { fields?: Record<string,string|number|boolean>, files?: Array<{ name: string, fileUrl?: string, base64Data?: string, filename?: string, contentType?: string }> }. Also supports a compact array form: [ [name, fileSpec, filename?], ... ] where fileSpec may be url: or base64:. Absolute fileUrl/url: attachment sources must use HTTP(S).',
        },
      },
      required: ['url'],
    },
  },
  {
    name: TOOL_NAMES.BROWSER.NETWORK_CAPTURE,
    description:
      'Unified network capture tool for HTTP(S) pages. Use action="start" to begin capturing, action="stop" to end and retrieve results. Set needResponseBody=true to capture response bodies (uses Debugger API, may conflict with DevTools). Default mode uses webRequest API (lightweight, no debugger conflict, but no response body).',
    inputSchema: {
      type: 'object',
      properties: {
        action: {
          type: 'string',
          enum: ['start', 'stop'],
          description:
            'Action to perform: "start" begins capture, "stop" ends and returns results',
        },
        needResponseBody: {
          type: 'boolean',
          description:
            'When true, captures response body using Debugger API (default: false). Only use when you need to inspect response content.',
        },
        url: {
          type: 'string',
          description:
            'HTTP(S) URL to capture network requests from. For action="start". If not provided, uses the current active tab.',
        },
        maxCaptureTime: {
          type: 'number',
          description: 'Maximum capture time in milliseconds (default: 180000)',
        },
        inactivityTimeout: {
          type: 'number',
          description:
            'Stop after inactivity in milliseconds (default: 60000). Set 0 to disable.',
        },
        includeStatic: {
          type: 'boolean',
          description:
            'Include static resources like images/scripts/styles (default: false)',
        },
        tabId: {
          type: 'number',
          description:
            'Target tab ID for start/stop operations. For action="start", captures this HTTP(S) tab when provided. For action="stop", stops capture for this tab when provided.',
        },
        windowId: {
          type: 'number',
          description:
            'Window ID used to resolve active tab when tabId is omitted (for both start and stop actions).',
        },
        background: {
          type: 'boolean',
          description:
            'For action="start": avoid activating/focusing the tab/window when possible (default: false). When the user has enabled MCP Background Mode, this defaults to true and an explicit false is ignored.',
        },
        all: {
          type: 'boolean',
          description:
            'For action="stop": when true, stop all active captures instead of a single tab (default: false).',
        },
      },
      required: ['action'],
    },
  },
  {
    name: TOOL_NAMES.BROWSER.HANDLE_DOWNLOAD,
    description:
      'Wait for a browser download and return sanitized details (id, filename basename, public source url when available, state, size). Local download paths and non-public source URLs are redacted.',
    inputSchema: {
      type: 'object',
      properties: {
        filenameContains: {
          type: 'string',
          description: 'Filter by substring in filename or URL',
        },
        timeoutMs: {
          type: 'number',
          description: 'Timeout in ms (default 60000, max 300000)',
        },
        waitForComplete: {
          type: 'boolean',
          description: 'Wait until completed (default true)',
        },
      },
      required: [],
    },
  },
  {
    name: TOOL_NAMES.BROWSER.HISTORY,
    description:
      'Retrieve and search HTTP(S) browsing history from Chrome. Non-public entries are filtered out.',
    inputSchema: {
      type: 'object',
      properties: {
        text: {
          type: 'string',
          description:
            'Text to search for in history URLs and titles. Leave empty to retrieve all history entries within the time range.',
        },
        startTime: {
          type: 'string',
          description:
            'Start time as a date string. Supports ISO format (e.g., "2023-10-01", "2023-10-01T14:30:00"), relative times (e.g., "1 day ago", "2 weeks ago", "3 months ago", "1 year ago"), and special keywords ("now", "today", "yesterday"). Default: 24 hours ago',
        },
        endTime: {
          type: 'string',
          description:
            'End time as a date string. Supports ISO format (e.g., "2023-10-31", "2023-10-31T14:30:00"), relative times (e.g., "1 day ago", "2 weeks ago", "3 months ago", "1 year ago"), and special keywords ("now", "today", "yesterday"). Default: current time',
        },
        maxResults: {
          type: 'number',
          description:
            'Maximum number of history entries to return. Use this to limit results for performance or to focus on the most relevant entries. (default: 100)',
        },
        excludeCurrentTabs: {
          type: 'boolean',
          description:
            "When set to true, filters out URLs that are currently open in any browser tab. Useful for finding pages you've visited but don't have open anymore. (default: false)",
        },
      },
      required: [],
    },
  },
  {
    name: TOOL_NAMES.BROWSER.BOOKMARK_SEARCH,
    description:
      'Search Chrome bookmarks by title and URL. Only HTTP(S) bookmarks are returned.',
    inputSchema: {
      type: 'object',
      properties: {
        query: {
          type: 'string',
          description:
            'Search query to match against bookmark titles and URLs. Leave empty to retrieve all bookmarks.',
        },
        maxResults: {
          type: 'number',
          description: 'Maximum number of bookmarks to return (default: 50)',
        },
        folderPath: {
          type: 'string',
          description:
            'Optional folder path or ID to limit search to a specific bookmark folder. Can be a path string (e.g., "Work/Projects") or a folder ID.',
        },
      },
      required: [],
    },
  },
  {
    name: TOOL_NAMES.BROWSER.BOOKMARK_ADD,
    description: 'Add a new HTTP(S) bookmark to Chrome',
    inputSchema: {
      type: 'object',
      properties: {
        url: {
          type: 'string',
          description:
            'HTTP(S) URL to bookmark. If not provided, uses the current active tab URL.',
        },
        title: {
          type: 'string',
          description:
            'Title for the bookmark. If not provided, uses the page title from the URL.',
        },
        parentId: {
          type: 'string',
          description:
            'Parent folder path or ID to add the bookmark to. Can be a path string (e.g., "Work/Projects") or a folder ID. If not provided, adds to the "Bookmarks Bar" folder.',
        },
        createFolder: {
          type: 'boolean',
          description:
            'Whether to create the parent folder if it does not exist (default: false)',
        },
        tabId: {
          type: 'number',
          description:
            'Target HTTP(S) tab ID to read URL/title from when url is omitted (default: active tab).',
        },
        windowId: {
          type: 'number',
          description:
            'Window ID used to resolve active tab when url/tabId are omitted (default: current window).',
        },
      },
      required: [],
    },
  },
  {
    name: TOOL_NAMES.BROWSER.BOOKMARK_DELETE,
    description: 'Delete an HTTP(S) bookmark from Chrome',
    inputSchema: {
      type: 'object',
      properties: {
        bookmarkId: {
          type: 'string',
          description:
            'ID of the bookmark to delete. Either bookmarkId or url must be provided.',
        },
        url: {
          type: 'string',
          description:
            'HTTP(S) URL of the bookmark to delete. Used if bookmarkId is not provided.',
        },
        title: {
          type: 'string',
          description:
            'Title of the bookmark to help with matching when deleting by URL.',
        },
      },
      required: [],
    },
  },
  // {
  //   name: TOOL_NAMES.BROWSER.SEARCH_TABS_CONTENT,
  //   description:
  //     'search for related content from the currently open tab and return the corresponding web pages.',
  //   inputSchema: {
  //     type: 'object',
  //     properties: {
  //       query: {
  //         type: 'string',
  //         description: 'the query to search for related content.',
  //       },
  //     },
  //     required: ['query'],
  //   },
  // },
  // {
  //   name: TOOL_NAMES.BROWSER.INJECT_SCRIPT,
  //   description:
  //     'inject the user-specified content script into the webpage. By default, inject into the currently active tab',
  //   inputSchema: {
  //     type: 'object',
  //     properties: {
  //       url: {
  //         type: 'string',
  //         description:
  //           'If a URL is specified, inject the script into the webpage corresponding to the URL.',
  //       },
  //       tabId: {
  //         type: 'number',
  //         description:
  //           'Target an existing tab by ID to inject into. Overrides url/active tab selection when provided.',
  //       },
  //       windowId: {
  //         type: 'number',
  //         description:
  //           'Target window ID for selecting active tab or creating new tab when url is provided and tabId is omitted.',
  //       },
  //       background: {
  //         type: 'boolean',
  //         description:
  //           'Do not activate tab/focus window during injection when true (default: false).',
  //       },
  //       type: {
  //         type: 'string',
  //         description:
  //           'the javaScript world for a script to execute within. must be ISOLATED or MAIN',
  //       },
  //       jsScript: {
  //         type: 'string',
  //         description: 'the content script to inject',
  //       },
  //     },
  //     required: ['type', 'jsScript'],
  //   },
  // },
  // {
  //   name: TOOL_NAMES.BROWSER.SEND_COMMAND_TO_INJECT_SCRIPT,
  //   description:
  //     'if the script injected using chrome_inject_script listens for user-defined events, this tool can be used to trigger those events',
  //   inputSchema: {
  //     type: 'object',
  //     properties: {
  //       tabId: {
  //         type: 'number',
  //         description:
  //           'the tab where you previously injected the script(if not provided,  use the currently active tab)',
  //       },
  //       eventName: {
  //         type: 'string',
  //         description: 'the eventName your injected content script listen for',
  //       },
  //       payload: {
  //         type: 'string',
  //         description: 'the payload passed to event, must be a json string',
  //       },
  //     },
  //     required: ['eventName'],
  //   },
  // },
  {
    name: TOOL_NAMES.BROWSER.JAVASCRIPT,
    description:
      'Execute JavaScript code in an HTTP(S) browser tab and return the result. Uses CDP Runtime.evaluate with awaitPromise and returnByValue; automatically falls back to chrome.scripting.executeScript if the debugger is busy. Output is sanitized (sensitive data redacted) and truncated by default.',
    inputSchema: {
      type: 'object',
      properties: {
        code: {
          type: 'string',
          description:
            'JavaScript code to execute. Runs inside an async function body, so top-level await and "return ..." are supported.',
        },
        tabId: {
          type: 'number',
          description:
            'Target HTTP(S) tab ID. If omitted, uses the current active tab.',
        },
        timeoutMs: {
          type: 'number',
          description: 'Execution timeout in milliseconds (default: 15000).',
        },
        maxOutputBytes: {
          type: 'number',
          description:
            'Maximum output size in bytes after sanitization (default: 51200). Output exceeding this limit will be truncated.',
        },
      },
      required: ['code'],
    },
  },
  {
    name: TOOL_NAMES.BROWSER.CLICK,
    description:
      'Click on an element in an HTTP(S) web page. Supports multiple targeting methods: CSS selector, XPath, element ref (from chrome_read_page), or viewport coordinates. More focused than chrome_computer for simple click operations.',
    inputSchema: {
      type: 'object',
      properties: {
        selector: {
          type: 'string',
          description: 'CSS selector or XPath for the element to click.',
        },
        selectorType: {
          type: 'string',
          enum: ['css', 'xpath'],
          description: 'Type of selector (default: "css").',
        },
        ref: {
          type: 'string',
          description:
            'Element ref from chrome_read_page (takes precedence over selector).',
        },
        coordinates: {
          type: 'object',
          description: 'Viewport coordinates to click at.',
          properties: {
            x: { type: 'number' },
            y: { type: 'number' },
          },
          required: ['x', 'y'],
        },
        double: {
          type: 'boolean',
          description: 'Perform double click when true (default: false).',
        },
        button: {
          type: 'string',
          enum: ['left', 'right', 'middle'],
          description: 'Mouse button to click (default: "left").',
        },
        modifiers: {
          type: 'object',
          description: 'Modifier keys to hold during click.',
          properties: {
            altKey: { type: 'boolean' },
            ctrlKey: { type: 'boolean' },
            metaKey: { type: 'boolean' },
            shiftKey: { type: 'boolean' },
          },
        },
        waitForNavigation: {
          type: 'boolean',
          description:
            'Wait for navigation to complete after click (default: false).',
        },
        background: {
          type: 'boolean',
          description:
            'Click without activating/focusing the target tab. Default: false for reliable viewport coordinates. When the user has enabled MCP Background Mode, this defaults to true and an explicit false is ignored.',
        },
        timeout: {
          type: 'number',
          description: 'Timeout in milliseconds for waiting (default: 5000).',
        },
        tabId: {
          type: 'number',
          description:
            'Target HTTP(S) tab ID. If omitted, uses the current active tab.',
        },
        windowId: {
          type: 'number',
          description:
            'Window ID to select the active HTTP(S) tab from (when tabId is omitted).',
        },
        frameId: {
          type: 'number',
          description: 'Target frame ID for iframe support.',
        },
      },
      required: [],
    },
  },
  {
    name: TOOL_NAMES.BROWSER.FILL,
    description:
      'Fill or select a form element on an HTTP(S) web page. Supports input, textarea, select, checkbox, and radio elements. Use CSS selector, XPath, or element ref to target the element.',
    inputSchema: {
      type: 'object',
      properties: {
        selector: {
          type: 'string',
          description: 'CSS selector or XPath for the form element.',
        },
        selectorType: {
          type: 'string',
          enum: ['css', 'xpath'],
          description: 'Type of selector (default: "css").',
        },
        ref: {
          type: 'string',
          description:
            'Element ref from chrome_read_page (takes precedence over selector).',
        },
        value: {
          type: ['string', 'number', 'boolean'],
          description:
            'Value to fill. For text inputs: string. For checkboxes/radios: boolean. For selects: option value or text.',
        },
        tabId: {
          type: 'number',
          description:
            'Target HTTP(S) tab ID. If omitted, uses the current active tab.',
        },
        windowId: {
          type: 'number',
          description:
            'Window ID to select the active HTTP(S) tab from (when tabId is omitted).',
        },
        frameId: {
          type: 'number',
          description: 'Target frame ID for iframe support.',
        },
        background: {
          type: 'boolean',
          description:
            'Fill without activating/focusing the target tab. Default: false for reliable focus and DOM interaction. When the user has enabled MCP Background Mode, this defaults to true and an explicit false is ignored.',
        },
      },
      required: ['value'],
    },
  },
  {
    name: TOOL_NAMES.BROWSER.REQUEST_ELEMENT_SELECTION,
    description:
      'Request the user to manually select one or more elements on the current HTTP(S) page. Use this as a human-in-the-loop fallback when you cannot reliably locate the target element after approximately 3 attempts using chrome_read_page combined with chrome_click_element/chrome_fill_or_select/chrome_computer. The user will see a panel with instructions and can click on the requested elements. Returns element refs compatible with chrome_click_element/chrome_fill_or_select (including iframe frameId for cross-frame support).',
    inputSchema: {
      type: 'object',
      properties: {
        requests: {
          type: 'array',
          description:
            'A list of element selection requests. Each request produces exactly one picked element. The user will see these requests in a panel and select each element by clicking on the page.',
          minItems: 1,
          items: {
            type: 'object',
            properties: {
              id: {
                type: 'string',
                description:
                  'Optional stable request id for correlation. If omitted, an id is auto-generated (e.g., "req_1").',
              },
              name: {
                type: 'string',
                description:
                  'Short label shown to the user describing what element to select (e.g., "Login button", "Email input field").',
              },
              description: {
                type: 'string',
                description:
                  'Optional longer instruction shown to the user with more context (e.g., "Click on the primary login button in the top-right corner").',
              },
            },
            required: ['name'],
          },
        },
        timeoutMs: {
          type: 'number',
          description:
            'Timeout in milliseconds for the user to complete all selections. Default: 180000 (3 minutes). Maximum: 600000 (10 minutes).',
        },
        tabId: {
          type: 'number',
          description:
            'Target HTTP(S) tab ID. If omitted, uses the current active tab.',
        },
        windowId: {
          type: 'number',
          description:
            'Window ID to select the active HTTP(S) tab from (when tabId is omitted).',
        },
      },
      required: ['requests'],
    },
  },
  {
    name: TOOL_NAMES.BROWSER.KEYBOARD,
    description:
      'Simulate keyboard input on an HTTP(S) web page. Supports single keys (Enter, Tab, Escape), key combinations (Ctrl+C, Ctrl+V), and text input. Can target a specific element or send to the focused element.',
    inputSchema: {
      type: 'object',
      properties: {
        keys: {
          type: 'string',
          description:
            'Keys or key combinations to simulate. Examples: "Enter", "Tab", "Ctrl+C", "Shift+Tab", "Hello World".',
        },
        selector: {
          type: 'string',
          description:
            'CSS selector or XPath for target element to receive keyboard events.',
        },
        selectorType: {
          type: 'string',
          enum: ['css', 'xpath'],
          description: 'Type of selector (default: "css").',
        },
        delay: {
          type: 'number',
          description:
            'Delay between keystrokes in milliseconds (default: 50).',
        },
        tabId: {
          type: 'number',
          description:
            'Target HTTP(S) tab ID. If omitted, uses the current active tab.',
        },
        windowId: {
          type: 'number',
          description:
            'Window ID to select the active HTTP(S) tab from (when tabId is omitted).',
        },
        frameId: {
          type: 'number',
          description: 'Target frame ID for iframe support.',
        },
        background: {
          type: 'boolean',
          description:
            'Send keys without activating/focusing the target tab. Default: false so keyboard input reaches the expected page. When the user has enabled MCP Background Mode, this defaults to true and an explicit false is ignored.',
        },
      },
      required: ['keys'],
    },
  },
  {
    name: TOOL_NAMES.BROWSER.CONSOLE,
    description:
      'Capture console output from an HTTP(S) browser tab. Supports snapshot mode (default; one-time capture with ~2s wait) and buffer mode (persistent per-tab buffer you can read/clear instantly without waiting).',
    inputSchema: {
      type: 'object',
      properties: {
        url: {
          type: 'string',
          description:
            'HTTP(S) URL to navigate to and capture console from. If not provided, uses the current active tab',
        },
        tabId: {
          type: 'number',
          description:
            'Target an existing HTTP(S) tab by ID (default: active tab).',
        },
        windowId: {
          type: 'number',
          description:
            'Target window ID to pick active tab when tabId is omitted.',
        },
        background: {
          type: 'boolean',
          description:
            'Do not activate tab/focus window when capturing via CDP. Default: false. When the user has enabled MCP Background Mode, this defaults to true and an explicit false is ignored.',
        },
        includeExceptions: {
          type: 'boolean',
          description:
            'Include uncaught exceptions in the output (default: true)',
        },
        maxMessages: {
          type: 'number',
          description:
            'Maximum number of console messages to capture in snapshot mode (default: 100). If limit is provided, it takes precedence.',
        },
        mode: {
          type: 'string',
          enum: ['snapshot', 'buffer'],
          description:
            'Console capture mode: snapshot (default; waits ~2s for messages) or buffer (persistent per-tab buffer; reads from memory instantly).',
        },
        buffer: {
          type: 'boolean',
          description: 'Alias for mode="buffer" (default: false).',
        },
        clear: {
          type: 'boolean',
          description:
            'Buffer mode only: clear the buffered logs for this tab before reading (default: false). Use clearAfterRead instead to clear after reading (mcp-tools.js style).',
        },
        clearAfterRead: {
          type: 'boolean',
          description:
            'Buffer mode only: clear the buffered logs for this tab AFTER reading, to avoid duplicate messages on subsequent calls (default: false). This matches mcp-tools.js behavior.',
        },
        pattern: {
          type: 'string',
          description:
            'Optional regex filter applied to message/exception text. Supports /pattern/flags syntax.',
        },
        onlyErrors: {
          type: 'boolean',
          description:
            'Only return error-level console messages (and exceptions when includeExceptions=true). Default: false.',
        },
        limit: {
          type: 'number',
          description:
            'Limit returned console messages. In snapshot mode this is an alias for maxMessages; in buffer mode it limits returned messages from the buffer.',
        },
      },
      required: [],
    },
  },
  {
    name: TOOL_NAMES.BROWSER.FILE_UPLOAD,
    description:
      'Upload files to file input elements on an HTTP(S) page using Chrome DevTools Protocol. Local file paths are not accepted; provide an http(s) fileUrl or base64Data.',
    inputSchema: {
      type: 'object',
      properties: {
        tabId: {
          type: 'number',
          description: 'Target HTTP(S) tab ID (default: active tab)',
        },
        windowId: {
          type: 'number',
          description:
            'Target window ID to pick the active HTTP(S) tab when tabId is omitted',
        },
        selector: {
          type: 'string',
          description:
            'CSS selector for the file input element (input[type="file"]) on the target HTTP(S) page',
        },
        fileUrl: {
          type: 'string',
          description: 'HTTP(S) URL to download file from before uploading',
        },
        base64Data: {
          type: 'string',
          description: 'Base64 encoded file data to upload',
        },
        fileName: {
          type: 'string',
          description:
            'Optional filename when using base64 or URL (default: "uploaded-file")',
        },
        multiple: {
          type: 'boolean',
          description:
            'Whether the input accepts multiple files (default: false)',
        },
      },
      required: ['selector'],
    },
  },
  {
    name: TOOL_NAMES.BROWSER.HANDLE_DIALOG,
    description:
      'Handle JavaScript dialogs (alert/confirm/prompt) on an HTTP(S) browser tab via CDP',
    inputSchema: {
      type: 'object',
      properties: {
        action: { type: 'string', description: 'accept | dismiss' },
        promptText: {
          type: 'string',
          description: 'Optional prompt text when accepting a prompt',
        },
        tabId: {
          type: 'number',
          description:
            'Target HTTP(S) tab ID. If omitted, uses the current active tab.',
        },
        windowId: {
          type: 'number',
          description:
            'Window ID to select the active HTTP(S) tab from when tabId is omitted.',
        },
      },
      required: ['action'],
    },
  },
  {
    name: TOOL_NAMES.BROWSER.GIF_RECORDER,
    description:
      'Record browser tab activity as an animated GIF on an HTTP(S) page.\n\nModes:\n- Fixed FPS mode (action="start"): Captures frames at regular intervals. Good for animations/videos.\n- Auto-capture mode (action="auto_start"): Captures frames automatically when chrome_computer or chrome_navigate actions succeed. Better for interaction recordings with natural pacing.\n\nUse "stop" to end recording and save the GIF.',
    inputSchema: {
      type: 'object',
      properties: {
        action: {
          type: 'string',
          enum: [
            'start',
            'stop',
            'status',
            'auto_start',
            'capture',
            'clear',
            'export',
          ],
          description:
            'Action to perform:\n- "start": Begin fixed-FPS recording (captures frames at regular intervals)\n- "auto_start": Begin auto-capture mode (frames captured on tool actions)\n- "stop": End recording and save GIF\n- "status": Get current recording state\n- "capture": Manually trigger a frame capture in auto mode\n- "clear": Clear all recording state and cached GIF without saving\n- "export": Export the last recorded GIF (download or drag&drop upload)',
        },
        tabId: {
          type: 'number',
          description:
            'Target HTTP(S) tab ID (default: active tab). Used with "start"/"auto_start" for recording, and with "export" (download=false) for drag&drop upload target.',
        },
        fps: {
          type: 'number',
          description:
            'Frames per second for fixed-FPS mode (1-30, default: 5). Higher values = smoother but larger file.',
        },
        durationMs: {
          type: 'number',
          description:
            'Maximum recording duration in milliseconds (default: 5000, max: 60000). Only for fixed-FPS mode.',
        },
        maxFrames: {
          type: 'number',
          description:
            'Maximum number of frames to capture (default: 50 for fixed-FPS, 100 for auto mode, max: 300).',
        },
        width: {
          type: 'number',
          description: 'Output GIF width in pixels (default: 800, max: 1920).',
        },
        height: {
          type: 'number',
          description: 'Output GIF height in pixels (default: 600, max: 1080).',
        },
        maxColors: {
          type: 'number',
          description:
            'Maximum colors in palette (default: 256). Lower values = smaller file size.',
        },
        filename: {
          type: 'string',
          description:
            'Output filename (without extension). Defaults to timestamped name.',
        },
        captureDelayMs: {
          type: 'number',
          description:
            'Auto-capture mode only: Delay in ms after action before capturing frame (default: 150). Allows UI to stabilize.',
        },
        frameDelayCs: {
          type: 'number',
          description:
            'Auto-capture mode only: Display duration per frame in centiseconds (default: 20 = 200ms per frame).',
        },
        annotation: {
          type: 'string',
          description:
            'Auto-capture mode only (action="capture"): Optional text label to render on the captured frame.',
        },
        download: {
          type: 'boolean',
          description:
            'Export action only: Set to true (default) to download the GIF, or false to upload via drag&drop on an HTTP(S) page.',
        },
        coordinates: {
          type: 'object',
          description:
            'Export action only (when download=false): Target coordinates for drag&drop upload.',
          properties: {
            x: { type: 'number' },
            y: { type: 'number' },
          },
          required: ['x', 'y'],
        },
        ref: {
          type: 'string',
          description:
            'Export action only (when download=false): Element ref from chrome_read_page for drag&drop target.',
        },
        selector: {
          type: 'string',
          description:
            'Export action only (when download=false): CSS selector for drag&drop target element.',
        },
        enhancedRendering: {
          type: 'object',
          description:
            'Auto-capture mode only: Configure visual overlays for recorded actions (click indicators, drag paths, labels). Pass `true` to enable all defaults.',
          properties: {
            clickIndicators: {
              oneOf: [
                { type: 'boolean' },
                {
                  type: 'object',
                  properties: {
                    enabled: {
                      type: 'boolean',
                      description: 'Enable click indicators (default: true)',
                    },
                    color: {
                      type: 'string',
                      description:
                        'CSS color for click indicator (default: "rgba(255, 87, 34, 0.8)")',
                    },
                    radius: {
                      type: 'number',
                      description: 'Initial radius in px (default: 20)',
                    },
                    animationDurationMs: {
                      type: 'number',
                      description: 'Animation duration in ms (default: 400)',
                    },
                    animationFrames: {
                      type: 'number',
                      description: 'Number of animation frames (default: 3)',
                    },
                    animationIntervalMs: {
                      type: 'number',
                      description:
                        'Interval between animation frames in ms (default: 80)',
                    },
                  },
                },
              ],
              description:
                'Click indicator overlay config (true for defaults, or object for custom).',
            },
            dragPaths: {
              oneOf: [
                { type: 'boolean' },
                {
                  type: 'object',
                  properties: {
                    enabled: {
                      type: 'boolean',
                      description: 'Enable drag path rendering (default: true)',
                    },
                    color: {
                      type: 'string',
                      description:
                        'CSS color for drag path (default: "rgba(33, 150, 243, 0.7)")',
                    },
                    lineWidth: {
                      type: 'number',
                      description: 'Line width in px (default: 3)',
                    },
                    lineDash: {
                      type: 'array',
                      items: { type: 'number' },
                      description: 'Dash pattern (default: [6, 4])',
                    },
                    arrowSize: {
                      type: 'number',
                      description: 'Arrow head size in px (default: 10)',
                    },
                  },
                },
              ],
              description:
                'Drag path overlay config (true for defaults, or object for custom).',
            },
            labels: {
              oneOf: [
                { type: 'boolean' },
                {
                  type: 'object',
                  properties: {
                    enabled: {
                      type: 'boolean',
                      description: 'Enable action labels (default: true)',
                    },
                    font: {
                      type: 'string',
                      description:
                        'Font for labels (default: "bold 12px sans-serif")',
                    },
                    textColor: {
                      type: 'string',
                      description: 'Text color (default: "#fff")',
                    },
                    bgColor: {
                      type: 'string',
                      description:
                        'Background color (default: "rgba(0,0,0,0.7)")',
                    },
                    padding: {
                      type: 'number',
                      description: 'Padding in px (default: 4)',
                    },
                    borderRadius: {
                      type: 'number',
                      description: 'Border radius in px (default: 4)',
                    },
                    offset: {
                      type: 'object',
                      properties: {
                        x: { type: 'number' },
                        y: { type: 'number' },
                      },
                      description:
                        'Offset from action position (default: {x: 10, y: -20})',
                    },
                  },
                },
              ],
              description:
                'Action label overlay config (true for defaults, or object for custom).',
            },
            durationMs: {
              type: 'number',
              description:
                'How long overlays remain visible in ms (default: 1500).',
            },
          },
        },
      },
      required: ['action'],
    },
  },
];
