Share this page

# Aviator API Reference

This reference details the Aviator Worfklow API. It provides background information and best practices for working with Aviator workflows.

Applies to: On-premises only. This API is not compatible with SaaS deployments. When invoked from a SaaS tenant, the on-premises Aviator Workflow API fails because it produces output that is incompatible with the GenAI middleware.

In this topic:

> ## Entry Points

> ### TDConnection.Aviator()

Main entry point for creating Aviator workflows.

Copy code

    const aviator = TDConnection.Aviator()

    // Check if enabled (license + feature flag)
    if (aviator.isEnabled()) {
      // Start building a prompt
      const response = await aviator.prompt().instructions('...').send()
    }

Methods:

- `.prompt()` → Returns PromptBuilder
- `.buildFormat()` → Returns OutputFormatBuilder
- `.isEnabled()` → Returns boolean (checks license availability)
- `.setDefaultPersona(text)` → Sets default persona for all prompts
- `.setDefaultLanguage(lang)` → Sets default language
- `.showSuggestionsModal(data, options)` → Show modal with custom data

#### `.isEnabled(): boolean`

Critical for Workflow Scripts - Check if Aviator is licensed and available before using AI features.

Copy code

    // Always check before using Aviator features
    if (!TDConnection.Aviator().isEnabled()) {
      MsgBox('Aviator is not available. Please check your license.')
      return
    }

    // Safe to use Aviator
    const response = await TDConnection.Aviator()
      .prompt()
      .instructions('Generate test cases')
      .send()

Returns:`true` if Aviator is licensed and available, `false` otherwise.

Best Practice: Always wrap Aviator operations with an `isEnabled()` check to gracefully handle unlicensed environments.

### TDConnection.Utils

Utility functions for text processing.

Copy code

    // Strip HTML tags
    TDConnection.Utils.stripHtml('<p>Hello <b>World</b></p>') // 'Hello World'

    // Remove special characters
    TDConnection.Utils.removeSpecialChars('Hello! @World#123') // 'Hello World123'

    // Normalize whitespace
    TDConnection.Utils.normalizeWhitespace('Hello  \n World') // 'Hello World'

    // Get MIME type from filename
    TDConnection.Utils.getMimeType('video.mp4') // 'video/mp4'

    // Clean text for AI prompt (combines stripHtml + normalizeWhitespace)
    TDConnection.Utils.cleanForPrompt('<p>Hello  World</p>') // 'Hello World'

    // Truncate text
    TDConnection.Utils.truncate('Long text here', 8) // 'Long...'

## PromptBuilder API

### Overview

PromptBuilder provides a fluent interface for constructing AI prompts.

### Methods

#### `.persona(text: string): this`

Define the AI's role and expertise.

Copy code

    .persona('You are a senior QA engineer with 10 years of experience in API testing')

#### `.instructions(text: string): this`

Add instructions. Chainable - call multiple times for clarity.

Copy code

    .instructions('Generate test cases for this requirement')
    .instructions('Include both positive and negative scenarios')
    .instructions('Add step-by-step test procedures')

#### `.context(data: object | string): this`

Provide context data for the AI.

Copy code

    // Object context
    .context({
      requirement: 'User Login',
      description: 'Users must authenticate with username/password',
      priority: 'High'
    })

    // String context (wrapped as {content: '...'})
    .context(req.Field('RQ_REQ_COMMENT').Value)

#### `.addContext(key: string, value: any): this`

Add a single context key-value pair.

Copy code

    .addContext('module', 'Authentication')
    .addContext('riskLevel', 'Critical')

#### `.format(schema: OutputFormat): this`

Set the expected output structure.

Copy code

    .format(TDConnection.Formats.TestCases)  // Predefined
    .format(customFormat)                     // Custom

#### `.language(lang: string): this`

Set the response language.

Copy code

    .language('Spanish')
    .language(TDConnection.GetPreferredLanguage())

#### `.maxResults(count: number): this`

Limit the number of results.

Copy code

    .maxResults(5)  // Generate exactly 5 items

#### `.useEntityChildren(): this`

Add instruction to consider child entities when generating content.

Copy code

    // When generating tests, consider sub-requirements for fuller coverage
    .useEntityChildren()

This adds an instruction to the AI to consider hierarchical relationships. When combined with context data, it helps generate more comprehensive results.

Use Case: When generating test cases from a parent requirement, enable this to signal that sub-requirements should be considered for coverage.

Copy code

    // Provide sub-requirements as context and enable the flag
    const subReqs = getSubRequirements(parentReqId)
    await TDConnection.Aviator()
      .prompt()
      .instructions('Generate test cases covering all requirements')
      .context({
        requirement: parentReq,
        subRequirements: subReqs  // Provide the data
      })
      .useEntityChildren()        // Signal to AI to use hierarchical context
      .format(TDConnection.Formats.TestCases)
      .send()

#### `.avoidDuplication(): this`

Add instruction to avoid duplicating existing content.

Copy code

    // When generating new tests, avoid duplicating existing linked tests
    .avoidDuplication()

This adds an instruction to the AI to check for and avoid duplicating existing items. When combined with context about existing items, it helps generate unique results.

Use Case: When generating new test cases, provide existing tests as context to avoid duplicates.

Copy code

    // Provide existing tests as context and enable the flag
    const existingTests = getLinkedTests(reqId)
    await TDConnection.Aviator()
      .prompt()
      .instructions('Generate additional test cases')
      .context({
        requirement: req,
        existingTests: existingTests  // Provide existing items
      })
      .avoidDuplication()             // Signal to AI to avoid duplicates
      .format(TDConnection.Formats.TestCases)
      .send()

#### `.attachment(attachmentObj: any): this`

Add a media attachment (image, video, audio) for the AI to analyze.

Copy code

    // Get attachment from requirement
    const req = TDConnection.ReqFactory.Item(reqId)
    const attachments = req.Attachments.NewList('')
    const firstAttachment = attachments[0]

      // Add attachment to prompt
      .attachment(firstAttachment)

Supported Formats:

Type | Extensions
--- | ---
Images | png, jpg, jpeg, webp, heic, heif, gif, bmp
Video | mp4, mov, avi, webm, mkv, mpeg, wmv, 3gp, flv
Audio | wav, mp3, aac, ogg, flac, aiff, m4a

Example - Generate Tests from Video:

Copy code

    const response = await TDConnection.Aviator()
      .prompt()
      .persona('You are a QA expert analyzing video recordings')
      .instructions('Analyze the video and generate test cases')
      .attachment(videoAttachment)
      .format(TDConnection.Formats.TestCases)
      .send({ loadingTitle: 'Analyzing video...' })

    // Handle size/timeout errors
    if (response.statusCode === 408) {
      MsgBox('Request timed out. Try a shorter video.')
      return
    }
    if (response.statusCode === 413) {
      MsgBox('File too large. Maximum size is 10MB.')
      return
    }

Notes:

- Maximum attachment size: 10MB
- The AI will analyze the media content along with any text context provided
- For defects, you can extract reproduction steps from video recordings

#### `.send(options?: SendOptions): Promise<AviatorResponse>`

Execute the prompt and return a response.

Copy code

    const response = await prompt.send()

    // With loading modal
    const response = await prompt.send({
      showLoading: true,
      loadingTitle: 'Generating Test Cases...'
    })

    // Silent mode (no UI)
    const response = await prompt.send({ showLoading: false })

SendOptions:

Option | Type | Default | Description
--- | --- | --- | ---
`showLoading` | boolean | `true` | Show loading modal
`loadingTitle` | string | `'Processing...'` | Loading modal title

### Prompt Construction Example

Understanding how the API constructs the final prompt:

Your Code:

Copy code

    await TDConnection.Aviator()
      .prompt()
      .persona('You are a senior QA engineer')
      .instructions('Generate test cases')
      .instructions('Include edge cases')
      .context({
        feature: 'Login',
        priority: 'High'
      })
      .format(TDConnection.Formats.TestCases)
      .maxResults(3)
      .send()

Resulting Prompt Sent to AI:

Copy code

    PERSONA:
    You are a senior QA engineer

    INSTRUCTIONS:
    Generate test cases
    Include edge cases

    CONTEXT:
    {
      "feature": "Login",
      "priority": "High"
    }

    OUTPUT FORMAT:
    [
      {
        "name": "string",
        "description": "string",
        "steps": [...]
      }
    ]

    CONSTRAINTS:
    - Generate exactly 3 items
    - Return valid JSON only

How Multiple `.instructions()` Work:

Instructions are concatenated with newlines:

Copy code

    .instructions('First instruction')
    .instructions('Second instruction')

Becomes:

Copy code

    First instruction
    Second instruction

Best Practice: Use multiple `.instructions()` for clarity:

Good instructions:

Copy code

    .instructions('Generate 5 test cases')
    .instructions('Include both happy path and error scenarios')
    .instructions('Add detailed step-by-step instructions')

Less clear intructions:

Copy code

    .instructions('Generate 5 test cases including both happy path and error scenarios with detailed step-by-step instructions')

## AviatorResponse API

### Overview

`AviatorResponse` wraps the AI response with auto-parsing and helper methods.

### Properties

#### `.data: any`

Auto-parsed and normalized response data.

Copy code

    const response = await TDConnection.Aviator().prompt().send()

    console.log(response.data)
    // → [{ name: "Test 1", description: "..." }, ...]

#### `.raw: string`

Original AI response (for debugging).

Copy code

    console.log(response.raw)
    // → "```json\n[{\"title\":\"Test 1\"}]\n```"

### Methods

#### `.isEmpty(): boolean`

Check if the response contains valid data.

Copy code

    if (response.isEmpty()) {
      MsgBox('No results generated.')
      return
    }

#### `.isList(): boolean`

Check if the response is an array.

Copy code

    if (response.isList()) {
      console.log(`Generated ${response.asList().length} items`)
    }

#### `.asList(): array`

Get response as an array (converts if needed).

Copy code

    const items = response.asList()
    items.forEach((item) => console.log(item.name))

#### `.first(): object | null`

Get the first item from the response.

Copy code

    const firstItem = response.first()
    if (firstItem) {
      console.log(`First item: ${firstItem.name}`)
    }

#### `.mapToSuggestions(mapping: SuggestionFieldMapping): this`

Map custom format fields to modal-expected names.

Copy code

    // Your custom format uses 'scenarioTitle' and 'given'
    const selected = await response
      .mapToSuggestions({
        name: 'scenarioTitle', // Map scenarioTitle → name
        description: 'given' // Map given → description
      })
      .showSuggestions({ title: 'BDD Scenarios' })

#### `.showSuggestions(options?: SuggestionsOptions): Promise<array | null>`

Display a modal for user to review and select items.

See ShowSuggestions Modal API for details.

## ShowSuggestions Modal API

### Overview

The ShowSuggestions modal provides a standardized UI for presenting AI-generated suggestions to users for review and selection.

### Two Usage Patterns

#### 1. Chained (Recommended)

Copy code

    const response = await TDConnection.Aviator()
      .prompt()
      .instructions('Generate test cases')
      .format(TDConnection.Formats.TestCases)
      .send()

    const selected = await response.showSuggestions({
      title: 'Generated Test Cases',
      description: 'Select test cases to create'
    })

#### 2. Standalone

Use when you have pre-existing data to display.

Copy code

    const selected = await TDConnection.Aviator().showSuggestionsModal(
      [
        { name: 'Test 1', description: 'Login with valid credentials' },
        { name: 'Test 2', description: 'Login with invalid password' }
      ],
      {
        title: 'Import Test Cases',
        description: 'Select tests to import',
        multiSelect: true
      }
    )

### Modal Options

Option | Type | Default | Description
--- | --- | --- | ---
`title` | string | `'AI Suggestions'` | Modal header title
`description` | string | `'Select items'` | Subtitle/instructions
`multiSelect` | boolean | `true` | Allow multiple selections (checkboxes) vs single (radio)
`buttonLabel` | string | Auto | Custom confirm button text
`allowCustomInput` | boolean | `false` | Allow users to add custom items
`type` | number | Auto | Modal type hint

### Return Values

User confirms selection:

Copy code

    // multiSelect: true
    ;[
      { name: 'Item 1', description: '...', ...otherFields },
      { name: 'Item 2', description: '...', ...otherFields }
    ][
      // multiSelect: false
      { name: 'Selected Item', description: '...', ...otherFields }
    ]

User cancels:

Copy code

    null // or undefined

### Complete Example

Copy code

    const response = await TDConnection.Aviator()
      .prompt()
      .persona('Product Manager')
      .instructions('Generate user stories for the shopping cart feature')
      .format(TDConnection.Formats.UserStories)
      .maxResults(3)
      .send({ loadingTitle: 'Generating user stories...' })

    const selected = await response.showSuggestions({
      title: 'AI-Generated User Stories',
      description: 'Review and select stories to add to the backlog',
      multiSelect: true,
      buttonLabel: 'Add to Backlog',
      allowCustomInput: true
    })

    if (selected?.length > 0) {
      selected.forEach((story) => {
        createUserStory(story.name, story.description)
      })
      MsgBox(`Created ${selected.length} user stories.`)
    }

### Using show suggestions

Use ShowSuggestions when:

- User needs to review AI output before action
- Multiple items generated, user should select
- User might want to edit/customize suggestions
- Operation creates/modifies entities

Do not use ShowSuggestions when:

- Silent background operations (use `.send({ showLoading: false })`)
- Automated batch processes
- Response is simple yes/no or true/false
- User doesn't need to approve the output

### Handling Cancellation

Copy code

    const selected = await response.showSuggestions({ title: 'Items' })

    // Always check for cancellation
    if (!selected || selected.length === 0) {
      MsgBox('No items selected. Operation cancelled.')
      return
    }

    // Safe to proceed
    processSelectedItems(selected)

## Auto-Parsing Pipeline

### Overview

The Aviator API automatically processes AI responses to ensure consistent, usable data structures. This pipeline extracts JSON from markdown, normalizes field names, and validates structure.

### Pipeline Stages

Copy code

    Raw AI Response
        ↓
    1. Markdown Code Block Detection
        ↓
    2. JSON Extraction
        ↓
    3. Field Name Normalization
        ↓
    4. Structure Validation
        ↓
    response.data (Clean, normalized data)

### Stage 1: Markdown Code Block Detection

AI models often wrap JSON in markdown. The parser auto-extracts it:

Raw AI Response:

Copy code

    Here are the test cases:

    ```json
    [{ "title": "Test 1", "reasoning": "Validates login" }]
    ```

    Hope this helps!

Extracted JSON:

Copy code

    [{ "title": "Test 1", "reasoning": "Validates login" }]

Supported Formats:

- ````json ... ````
- ````javascript ... ````
- ```` ... ```` (no language)

### Stage 2: Field Name Normalization

Different AI models use different field names. The parser normalizes them:

Raw AI Response:

Copy code

    [
      { "title": "Login Test", "reasoning": "Verify authentication" },
      { "name": "Logout Test", "description": "Verify logout" }
    ]

Normalized `response.data`:

Copy code

    [
      { "name": "Login Test", "description": "Verify authentication" },
      { "name": "Logout Test", "description": "Verify logout" }
    ]

### Stage 3: Handling Unexpected Formats

#### Scenario: Plain Text Response

AI Returns:

Copy code

    Test 1: Verify login
    Test 2: Verify logout

Normalized:

Copy code

    {
      "content": "Test 1: Verify login\nTest 2: Verify logout"
    }

#### Scenario: Mixed Content

AI Returns:

Copy code

    I've generated these:

    ```json
    [{"name": "Test 1"}]

Let me know!

Copy code

    **Normalized:**
    ```json
    [
      {"name": "Test 1"}
    ]

### Accessing Raw vs Parsed

Copy code

    const response = await TDConnection.Aviator().prompt().send()

    // Parsed and normalized (recommended)
    console.log(response.data)
    // → [{ name: "Test 1", description: "..." }]

    // Original raw response (for debugging)
    console.log(response.raw)
    // → "```json\n[{\"title\":\"Test 1\"}]\n```"

### Error Handling

If parsing fails completely:

Copy code

    // For list formats
    response.data = []
    response.isEmpty() // → true

    // For object formats
    response.data = null
    response.isEmpty() // → true

Always check before processing:

Copy code

    if (response.isEmpty()) {
      MsgBox('AI could not generate valid results. Please try again.')
      return
    }

## Response Normalization Rules

### Overview

The API applies consistent field name mapping to ensure compatibility between different AI outputs and application expectations.

### Field Mapping Table

AI Response Field | Maps To | Priority | Use Case
--- | --- | --- | ---
`title` | `name` | 1 (highest) | Primary identifier
`reasoning` | `description` | 1 | Explanation/rationale
`rationale` | `description` | 2 | Alternative explanation
`reason` | `description` | 3 | Short explanation
`summary` | `description` | 4 | Summary text
`details` | `description` | 5 | Detailed info
`content` | `description` | 6 (fallback) | Generic content

### Priority Rules

When multiple mappable fields exist, highest priority wins:

AI Returns:

Copy code

    {
      "title": "Test Case 1",
      "name": "Other Name",
      "reasoning": "Primary reason",
      "summary": "Summary text"
    }

Normalized To:

Copy code

    {
      "name": "Test Case 1", // title → name (priority 1)
      "description": "Primary reason" // reasoning → description (priority 1)
    }

### Field Preservation

Fields not in the mapping table are preserved as-is:

AI Returns:

Copy code

    {
      "title": "Login Test",
      "reasoning": "Verify auth",
      "priority": "High",
      "customField": "Custom Value"
    }

Normalized:

Copy code

    {
      "name": "Login Test",
      "description": "Verify auth",
      "priority": "High", // Preserved
      "customField": "Custom Value" // Preserved
    }

### Array Normalization

Normalization applies per item independently:

AI Returns:

Copy code

    [
      { "title": "Item 1", "reasoning": "Reason 1" },
      { "name": "Item 2", "description": "Reason 2" },
      { "title": "Item 3", "summary": "Reason 3" }
    ]

Normalized:

Copy code

    [
      { "name": "Item 1", "description": "Reason 1" },
      { "name": "Item 2", "description": "Reason 2" },
      { "name": "Item 3", "description": "Reason 3" }
    ]

### Nested Objects

Normalization is shallow (top-level only):

AI Returns:

Copy code

    {
      "title": "Test Case",
      "steps": [{ "title": "Step 1", "details": "Click login" }]
    }

Normalized:

Copy code

    {
      "name": "Test Case",
      "steps": [
        { "title": "Step 1", "details": "Click login" } // NOT normalized
      ]
    }

For nested normalization, apply manually:

Copy code

    response.data = response.data.map((item) => ({
      ...item,
      steps: item.steps.map((step) => ({
        name: step.title || step.name,
        description: step.details || step.description
      }))
    }))

### Debugging Normalization

Copy code

    const response = await TDConnection.Aviator().prompt().send()

    console.log('Raw:', response.raw)
    console.log('Normalized:', response.data)

    const wasNormalized = JSON.stringify(response.raw) !== JSON.stringify(response.data)
    console.log('Normalization applied:', wasNormalized)

## OutputFormatBuilder

### Overview

Create custom output schemas for specialized AI responses.

### Methods

#### `.addField(name, type, description): this`

Add a field to the schema.

Copy code

    .addField('name', 'string', 'Test case name')
    .addField('priority', 'number', 'Priority level 1-5')
    .addField('tags', 'array', 'List of tags')

Supported Types:

- `string`, `number`, `boolean`, `array`, `object`

#### `.addNestedField(parent, child, type, description): this`

Add a nested field.

Copy code

    .addNestedField('metadata', 'author', 'string', 'Author name')
    .addNestedField('metadata', 'date', 'string', 'Creation date')

#### `.asList(): this`

Set output as an array.

Copy code

    .asList()  // Returns: [{ field1: ..., field2: ... }, ...]

#### `.asObject(): this`

Set output as a single object (default).

Copy code

    .asObject()  // Returns: { field1: ..., field2: ... }

#### `.build(): OutputFormat`

Build and return the format schema.

Copy code

    const format = builder.build()

### Complete Example

Copy code

    const bddFormat = TDConnection.Aviator()
      .buildFormat()
      .addField('scenarioName', 'string', 'Scenario name')
      .addField('given', 'string', 'Given condition')
      .addField('when', 'string', 'When action')
      .addField('then', 'string', 'Then expectation')
      .asList()
      .build()

    const response = await TDConnection.Aviator()
      .prompt()
      .instructions('Generate BDD scenarios')
      .format(bddFormat)
      .send()

    // Map custom fields to modal format
    const selected = await response
      .mapToSuggestions({
        name: 'scenarioName',
        description: 'given'
      })
      .showSuggestions({ title: 'BDD Scenarios' })

## Predefined Formats

### TDConnection.Formats.TestCases

Generates test case objects.

Output Structure:

Copy code

    [
      {
        "name": "string",
        "description": "string",
        "test_type": "string",
        "priority": "string",
        "steps": [
          {
            "stepNumber": "number",
            "description": "string",
            "expected_result": "string"
          }
        ]
      }
    ]

### TDConnection.Formats.UserStories

Generates user story objects.

Output Structure:

Copy code

    [
      {
        "name": "string",
        "description": "string",
        "acceptanceCriteria": ["string"],
        "priority": "string"
      }
    ]

### TDConnection.Formats.ComplianceCheck

Validates compliance.

Output Structure:

Copy code

    {
      "compliant": "boolean",
      "reason": "string",
      "recommendations": ["string"]
    }

### TDConnection.Formats.Defect

Analyzes defects.

Output Structure:

Copy code

    {
      "name": "string",
      "description": "string",
      "severity": "string",
      "rootCause": "string",
      "steps": ["string"]
    }

### TDConnection.Formats.Text

Plain text response.

Output: String or `{ content: "string" }`

### TDConnection.Formats.List

Simple list of strings.

Output:`["string", "string", ...]`

### TDConnection.Formats.JSON

Raw JSON response (no parsing).

Output: AI response as-is

## Utility Functions

### TDConnection.Utils.stripHtml(html: string): string

Remove HTML tags from text.

Copy code

    const clean = TDConnection.Utils.stripHtml('<p>Hello <b>World</b></p>')
    // → "Hello World"

### TDConnection.Utils.normalizeWhitespace(text: string): string

Collapse multiple spaces/newlines.

Copy code

    const clean = TDConnection.Utils.normalizeWhitespace('Hello    World\n\n\nTest')
    // → "Hello World Test"

### TDConnection.Utils.truncate(text: string, maxLength: number): string

Truncate text to max length.

Copy code

    const short = TDConnection.Utils.truncate('Long text here', 10)
    // → "Long text..."

https://admhelp.microfocus.com Application Quality Management 8942
Tips to improve your search results... OpenText™ Application Quality Management Help Center OpenText™ Application Quality Management Help Center OpenText™ Application Quality Management Help 26.1 All View Local Help Center View Online Help Center Version: