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.
Entry Points
TDConnection.Aviator()
Main entry point for creating Aviator workflows.
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.
// 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.
// 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.
.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.
.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.
// 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.
.addContext('module', 'Authentication')
.addContext('riskLevel', 'Critical')
.format(schema: OutputFormat): this
Set the expected output structure.
.format(TDConnection.Formats.TestCases) // Predefined
.format(customFormat) // Custom
.language(lang: string): this
Set the response language.
.language('Spanish')
.language(TDConnection.GetPreferredLanguage())
.maxResults(count: number): this
Limit the number of results.
.maxResults(5) // Generate exactly 5 items
.useEntityChildren(): this
Add instruction to consider child entities when generating content.
// 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.
// 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.
// 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.
// 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.
// 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:
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.
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:
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:
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:
.instructions('First instruction')
.instructions('Second instruction')
Becomes:
First instruction
Second instruction
Best Practice: Use multiple .instructions() for clarity:
Good instructions:
.instructions('Generate 5 test cases')
.instructions('Include both happy path and error scenarios')
.instructions('Add detailed step-by-step instructions')
Less clear intructions:
.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.
const response = await TDConnection.Aviator().prompt().send()
console.log(response.data)
// → [{ name: "Test 1", description: "..." }, ...]
.raw: string
Original AI response (for debugging).
console.log(response.raw)
// → "```json\n[{\"title\":\"Test 1\"}]\n```"
Methods
.isEmpty(): boolean
Check if the response contains valid data.
if (response.isEmpty()) {
MsgBox('No results generated.')
return
}
.isList(): boolean
Check if the response is an array.
if (response.isList()) {
console.log(`Generated ${response.asList().length} items`)
}
.asList(): array
Get response as an array (converts if needed).
const items = response.asList()
items.forEach((item) => console.log(item.name))
.first(): object | null
Get the first item from the response.
const firstItem = response.first()
if (firstItem) {
console.log(`First item: ${firstItem.name}`)
}
.mapToSuggestions(mapping: SuggestionFieldMapping): this
Map custom format fields to modal-expected names.
// 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)
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.
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:
// multiSelect: true
;[
{ name: 'Item 1', description: '...', ...otherFields },
{ name: 'Item 2', description: '...', ...otherFields }
][
// multiSelect: false
{ name: 'Selected Item', description: '...', ...otherFields }
]
User cancels:
null // or undefined
Complete Example
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
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
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:
Here are the test cases:
```json
[{ "title": "Test 1", "reasoning": "Validates login" }]
```
Hope this helps!
Extracted JSON:
[{ "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:
[
{ "title": "Login Test", "reasoning": "Verify authentication" },
{ "name": "Logout Test", "description": "Verify logout" }
]
Normalized response.data:
[
{ "name": "Login Test", "description": "Verify authentication" },
{ "name": "Logout Test", "description": "Verify logout" }
]
Stage 3: Handling Unexpected Formats
Scenario: Plain Text Response
AI Returns:
Test 1: Verify login
Test 2: Verify logout
Normalized:
{
"content": "Test 1: Verify login\nTest 2: Verify logout"
}
Scenario: Mixed Content
AI Returns:
I've generated these:
```json
[{"name": "Test 1"}]
Let me know!
**Normalized:**
```json
[
{"name": "Test 1"}
]
Accessing Raw vs Parsed
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:
// For list formats
response.data = []
response.isEmpty() // → true
// For object formats
response.data = null
response.isEmpty() // → true
Always check before processing:
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:
{
"title": "Test Case 1",
"name": "Other Name",
"reasoning": "Primary reason",
"summary": "Summary text"
}
Normalized To:
{
"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:
{
"title": "Login Test",
"reasoning": "Verify auth",
"priority": "High",
"customField": "Custom Value"
}
Normalized:
{
"name": "Login Test",
"description": "Verify auth",
"priority": "High", // Preserved
"customField": "Custom Value" // Preserved
}
Array Normalization
Normalization applies per item independently:
AI Returns:
[
{ "title": "Item 1", "reasoning": "Reason 1" },
{ "name": "Item 2", "description": "Reason 2" },
{ "title": "Item 3", "summary": "Reason 3" }
]
Normalized:
[
{ "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:
{
"title": "Test Case",
"steps": [{ "title": "Step 1", "details": "Click login" }]
}
Normalized:
{
"name": "Test Case",
"steps": [
{ "title": "Step 1", "details": "Click login" } // NOT normalized
]
}
For nested normalization, apply manually:
response.data = response.data.map((item) => ({
...item,
steps: item.steps.map((step) => ({
name: step.title || step.name,
description: step.details || step.description
}))
}))
Debugging Normalization
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.
.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.
.addNestedField('metadata', 'author', 'string', 'Author name')
.addNestedField('metadata', 'date', 'string', 'Creation date')
.asList(): this
Set output as an array.
.asList() // Returns: [{ field1: ..., field2: ... }, ...]
.asObject(): this
Set output as a single object (default).
.asObject() // Returns: { field1: ..., field2: ... }
.build(): OutputFormat
Build and return the format schema.
const format = builder.build()
Complete Example
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:
[
{
"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:
[
{
"name": "string",
"description": "string",
"acceptanceCriteria": ["string"],
"priority": "string"
}
]
TDConnection.Formats.ComplianceCheck
Validates compliance.
Output Structure:
{
"compliant": "boolean",
"reason": "string",
"recommendations": ["string"]
}
TDConnection.Formats.Defect
Analyzes defects.
Output Structure:
{
"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.
const clean = TDConnection.Utils.stripHtml('<p>Hello <b>World</b></p>')
// → "Hello World"
TDConnection.Utils.normalizeWhitespace(text: string): string
Collapse multiple spaces/newlines.
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.
const short = TDConnection.Utils.truncate('Long text here', 10)
// → "Long text..."

