@browserstack/mcp-server 2.2.5 ā 2.2.6-beta.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +32 -194
- package/dist/lib/accessibility-routing.d.ts +6 -0
- package/dist/lib/accessibility-routing.js +6 -0
- package/dist/server-factory.js +6 -1
- package/dist/tools/accessibility.js +680 -69
- package/dist/tools/accessiblity-utils/app-report-fetcher.d.ts +412 -0
- package/dist/tools/accessiblity-utils/app-report-fetcher.js +926 -0
- package/dist/tools/accessiblity-utils/paginate.d.ts +27 -0
- package/dist/tools/accessiblity-utils/paginate.js +50 -0
- package/dist/tools/accessiblity-utils/report-fetcher.d.ts +116 -7
- package/dist/tools/accessiblity-utils/report-fetcher.js +268 -29
- package/dist/tools/accessiblity-utils/report-parser.d.ts +41 -1
- package/dist/tools/accessiblity-utils/report-parser.js +142 -43
- package/dist/tools/accessiblity-utils/scanner.d.ts +15 -1
- package/dist/tools/accessiblity-utils/scanner.js +3 -4
- package/dist/tools/appautomate-utils/appium-sdk/config-generator.d.ts +2 -0
- package/dist/tools/appautomate-utils/appium-sdk/config-generator.js +15 -5
- package/dist/tools/appautomate-utils/appium-sdk/constants.d.ts +2 -1
- package/dist/tools/appautomate-utils/appium-sdk/constants.js +6 -1
- package/dist/tools/appautomate-utils/appium-sdk/handler.js +12 -1
- package/dist/tools/appautomate-utils/appium-sdk/instructions.d.ts +3 -1
- package/dist/tools/appautomate-utils/appium-sdk/instructions.js +2 -2
- package/dist/tools/appautomate-utils/appium-sdk/languages/accessibility.d.ts +4 -0
- package/dist/tools/appautomate-utils/appium-sdk/languages/accessibility.js +47 -0
- package/dist/tools/appautomate-utils/appium-sdk/languages/nodejs.d.ts +3 -1
- package/dist/tools/appautomate-utils/appium-sdk/languages/nodejs.js +19 -6
- package/dist/tools/appautomate-utils/native-execution/appautomate.d.ts +7 -2
- package/dist/tools/appautomate-utils/native-execution/appautomate.js +15 -12
- package/dist/tools/appautomate-utils/native-execution/constants.d.ts +2 -1
- package/dist/tools/appautomate-utils/native-execution/constants.js +6 -1
- package/dist/tools/appautomate.js +29 -16
- package/dist/tools/testmanagement-utils/create-testrun.d.ts +1 -1
- package/dist/tools/testmanagement-utils/update-testrun.d.ts +1 -1
- package/dist/tools/tool-handoff.d.ts +3 -2
- package/dist/tools/tool-handoff.js +3 -2
- package/package.json +1 -1
- package/dist/tools/accessiblity-utils/accessibility-rag.d.ts +0 -12
- package/dist/tools/accessiblity-utils/accessibility-rag.js +0 -59
|
@@ -38,6 +38,11 @@ export declare function uploadEspressoApp(appPath: string, config: BrowserStackC
|
|
|
38
38
|
export declare function uploadEspressoTestSuite(testSuitePath: string, config: BrowserStackConfig): Promise<string>;
|
|
39
39
|
export declare function uploadXcuiApp(appPath: string, config: BrowserStackConfig): Promise<string>;
|
|
40
40
|
export declare function uploadXcuiTestSuite(testSuitePath: string, config: BrowserStackConfig): Promise<string>;
|
|
41
|
-
|
|
42
|
-
export
|
|
41
|
+
/** What a native build run can be asked for beyond app, suite, devices and project. */
|
|
42
|
+
export interface NativeBuildOptions {
|
|
43
|
+
/** Run App Accessibility checks during the tests (the build API's `accessibility` flag). */
|
|
44
|
+
accessibility?: boolean;
|
|
45
|
+
}
|
|
46
|
+
export declare function triggerEspressoBuild(app_url: string, test_suite_url: string, devices: string[], project: string, config: BrowserStackConfig, options?: NativeBuildOptions): Promise<string>;
|
|
47
|
+
export declare function triggerXcuiBuild(app_url: string, test_suite_url: string, devices: string[], project: string, config: BrowserStackConfig, options?: NativeBuildOptions): Promise<string>;
|
|
43
48
|
export {};
|
|
@@ -138,8 +138,17 @@ export async function uploadXcuiApp(appPath, config) {
|
|
|
138
138
|
export async function uploadXcuiTestSuite(testSuitePath, config) {
|
|
139
139
|
return uploadFileToBrowserStack(testSuitePath, "https://api-cloud.browserstack.com/app-automate/xcuitest/v2/test-suite", "test_suite_url", config, { allowedExtensions: [".zip"] });
|
|
140
140
|
}
|
|
141
|
+
function buildRequestBody(app_url, test_suite_url, devices, project, options) {
|
|
142
|
+
return {
|
|
143
|
+
app: app_url,
|
|
144
|
+
testSuite: test_suite_url,
|
|
145
|
+
devices,
|
|
146
|
+
project,
|
|
147
|
+
...(options.accessibility ? { accessibility: true } : {}),
|
|
148
|
+
};
|
|
149
|
+
}
|
|
141
150
|
// Triggers an Espresso test run on BrowserStack and returns the build_id
|
|
142
|
-
export async function triggerEspressoBuild(app_url, test_suite_url, devices, project, config) {
|
|
151
|
+
export async function triggerEspressoBuild(app_url, test_suite_url, devices, project, config, options = {}) {
|
|
143
152
|
const authHeader = "Basic " + Buffer.from(getBrowserStackAuth(config)).toString("base64");
|
|
144
153
|
const response = await apiClient.post({
|
|
145
154
|
url: "https://api-cloud.browserstack.com/app-automate/espresso/v2/build",
|
|
@@ -148,10 +157,9 @@ export async function triggerEspressoBuild(app_url, test_suite_url, devices, pro
|
|
|
148
157
|
"Content-Type": "application/json",
|
|
149
158
|
},
|
|
150
159
|
body: {
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
project,
|
|
160
|
+
...buildRequestBody(app_url, test_suite_url, devices, project, options),
|
|
161
|
+
// An Espresso build's App Accessibility report is generated through Test Observability.
|
|
162
|
+
...(options.accessibility ? { testObservability: true } : {}),
|
|
155
163
|
},
|
|
156
164
|
});
|
|
157
165
|
if (response.data.build_id) {
|
|
@@ -160,7 +168,7 @@ export async function triggerEspressoBuild(app_url, test_suite_url, devices, pro
|
|
|
160
168
|
throw new Error(`Failed to trigger Espresso build: ${JSON.stringify(response.data)}`);
|
|
161
169
|
}
|
|
162
170
|
// Triggers an XCUITest run on BrowserStack and returns the build_id
|
|
163
|
-
export async function triggerXcuiBuild(app_url, test_suite_url, devices, project, config) {
|
|
171
|
+
export async function triggerXcuiBuild(app_url, test_suite_url, devices, project, config, options = {}) {
|
|
164
172
|
const auth = {
|
|
165
173
|
username: config["browserstack-username"],
|
|
166
174
|
password: config["browserstack-access-key"],
|
|
@@ -172,12 +180,7 @@ export async function triggerXcuiBuild(app_url, test_suite_url, devices, project
|
|
|
172
180
|
Buffer.from(`${auth.username}:${auth.password}`).toString("base64"),
|
|
173
181
|
"Content-Type": "application/json",
|
|
174
182
|
},
|
|
175
|
-
body:
|
|
176
|
-
app: app_url,
|
|
177
|
-
testSuite: test_suite_url,
|
|
178
|
-
devices,
|
|
179
|
-
project,
|
|
180
|
-
},
|
|
183
|
+
body: buildRequestBody(app_url, test_suite_url, devices, project, options),
|
|
181
184
|
});
|
|
182
185
|
if (response.data.build_id) {
|
|
183
186
|
return response.data.build_id;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
2
|
import { AppTestPlatform } from "./types.js";
|
|
3
|
-
export declare const RUN_APP_AUTOMATE_DESCRIPTION = "Execute pre-built native mobile test suites (Espresso for Android, XCUITest for iOS) by direct upload to BrowserStack. ONLY for compiled .apk/.ipa test files. This is NOT for SDK integration or Appium tests. For Appium-based testing with SDK setup, use 'setupBrowserStackAppAutomateTests' instead.";
|
|
3
|
+
export declare const RUN_APP_AUTOMATE_DESCRIPTION = "Execute pre-built native mobile test suites (Espresso for Android, XCUITest for iOS) by direct upload to BrowserStack. ONLY for compiled .apk/.ipa test files. This is NOT for SDK integration or Appium tests. For Appium-based testing with SDK setup, use 'setupBrowserStackAppAutomateTests' instead. Set accessibility: true to also run App Accessibility (WCAG) checks during the tests; the issues are then read with fetchAccessibilityIssues.";
|
|
4
4
|
export declare const MobileDeviceSchema: z.ZodObject<{
|
|
5
5
|
platform: z.ZodEnum<{
|
|
6
6
|
android: "android";
|
|
@@ -22,4 +22,5 @@ export declare const RUN_APP_AUTOMATE_SCHEMA: {
|
|
|
22
22
|
}, z.core.$strip>>>;
|
|
23
23
|
project: z.ZodDefault<z.ZodOptional<z.ZodString>>;
|
|
24
24
|
detectedAutomationFramework: z.ZodEnum<typeof AppTestPlatform>;
|
|
25
|
+
accessibility: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
|
|
25
26
|
};
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
2
|
import { AppTestPlatform } from "./types.js";
|
|
3
|
-
export const RUN_APP_AUTOMATE_DESCRIPTION = `Execute pre-built native mobile test suites (Espresso for Android, XCUITest for iOS) by direct upload to BrowserStack. ONLY for compiled .apk/.ipa test files. This is NOT for SDK integration or Appium tests. For Appium-based testing with SDK setup, use 'setupBrowserStackAppAutomateTests' instead.`;
|
|
3
|
+
export const RUN_APP_AUTOMATE_DESCRIPTION = `Execute pre-built native mobile test suites (Espresso for Android, XCUITest for iOS) by direct upload to BrowserStack. ONLY for compiled .apk/.ipa test files. This is NOT for SDK integration or Appium tests. For Appium-based testing with SDK setup, use 'setupBrowserStackAppAutomateTests' instead. Set accessibility: true to also run App Accessibility (WCAG) checks during the tests; the issues are then read with fetchAccessibilityIssues.`;
|
|
4
4
|
export const MobileDeviceSchema = z.object({
|
|
5
5
|
platform: z
|
|
6
6
|
.enum(["android", "ios"])
|
|
@@ -46,4 +46,9 @@ export const RUN_APP_AUTOMATE_SCHEMA = {
|
|
|
46
46
|
detectedAutomationFramework: z
|
|
47
47
|
.nativeEnum(AppTestPlatform)
|
|
48
48
|
.describe("The automation framework used in the project, such as 'espresso' (Android) or 'xcuitest' (iOS)."),
|
|
49
|
+
accessibility: z
|
|
50
|
+
.boolean()
|
|
51
|
+
.optional()
|
|
52
|
+
.default(false)
|
|
53
|
+
.describe("App Accessibility checks on screens the tests touch (Android 11+, iOS 14+); suite must be built with BrowserStack's SDK."),
|
|
49
54
|
};
|
|
@@ -96,8 +96,26 @@ async function takeAppScreenshot(args) {
|
|
|
96
96
|
}
|
|
97
97
|
}
|
|
98
98
|
}
|
|
99
|
+
/**
|
|
100
|
+
* What a native suite needs for App Accessibility to scan it. The build request's flag
|
|
101
|
+
* turns the checks on, but only a suite built with BrowserStack's instrumentation records
|
|
102
|
+
* scans; without it the run finishes with none, and nothing says why.
|
|
103
|
+
*/
|
|
104
|
+
const NATIVE_ACCESSIBILITY_SETUP = {
|
|
105
|
+
Espresso: "The test suite must be built with BrowserStack's Gradle plugin and SDK, or the run records no scans: classpath 'com.browserstack:gradle-tool:latest.release' in the root build.gradle, id 'com.browserstack.gradle-tool' in the app's plugins, and androidTestImplementation 'com.browserstack:browserstack-java-sdk:latest.release' (1.31.0 or newer). The app also needs internet permission.",
|
|
106
|
+
XCUITest: "The UI test target must embed and initialize the BrowserStack Swift SDK (BrowserstackSwiftSDK.xcframework, or the Swift package), or the run records no scans: set NSPrincipalClass to BrowserstackSwiftSDK.BrowserstackSwiftSDK in the test target's Info.plist, or call BrowserstackSwiftSDK.init() in the test class's init(). Swift 5.4+ and iOS 14+.",
|
|
107
|
+
};
|
|
108
|
+
/** The run's build and, with accessibility on, where its issues are read once it finishes. */
|
|
109
|
+
function runStartedMessage(framework, buildId, accessibility) {
|
|
110
|
+
const link = `https://app-automate.browserstack.com/builds/${buildId}`;
|
|
111
|
+
const a11y = accessibility
|
|
112
|
+
? `\n\nāæ App Accessibility checks are on. ${NATIVE_ACCESSIBILITY_SETUP[framework] ?? ""}\nWhen the build finishes (typically 10ā20 minutes), read the issues with fetchAccessibilityIssues, reportUrl: ${link} ā it maps the build to its accessibility report and waits while the report is still processing.`
|
|
113
|
+
: "";
|
|
114
|
+
return `ā
${framework} run started successfully!\n\nš§ Build ID: ${buildId}\nš View your build: ${link}${a11y}`;
|
|
115
|
+
}
|
|
99
116
|
//Runs AppAutomate tests on BrowserStack by uploading app and test suite, then triggering a test run.
|
|
100
117
|
async function runAppTestsOnBrowserStack(args, config) {
|
|
118
|
+
const accessibility = args.accessibility === true;
|
|
101
119
|
// Validate that either paths or URLs are provided for both app and test suite
|
|
102
120
|
if (!args.browserstackAppUrl && !args.appPath) {
|
|
103
121
|
throw new Error("appPath is required when browserstackAppUrl is not provided");
|
|
@@ -105,8 +123,13 @@ async function runAppTestsOnBrowserStack(args, config) {
|
|
|
105
123
|
if (!args.browserstackTestSuiteUrl && !args.testSuitePath) {
|
|
106
124
|
throw new Error("testSuitePath is required when browserstackTestSuiteUrl is not provided");
|
|
107
125
|
}
|
|
108
|
-
// Validate devices against real BrowserStack device data
|
|
109
|
-
|
|
126
|
+
// Validate devices against real BrowserStack device data, and ask for them as App Automate
|
|
127
|
+
// lists them: a version given as "14" is "14.0" there, and a run asking for "-14" waits for
|
|
128
|
+
// a device that never matches.
|
|
129
|
+
const validated = await validateAppAutomateDevices(args.devices);
|
|
130
|
+
const deviceStrings = args.devices.length > 0
|
|
131
|
+
? validated.map((device) => `${device.deviceName}-${device.osVersion}`)
|
|
132
|
+
: [];
|
|
110
133
|
switch (args.detectedAutomationFramework) {
|
|
111
134
|
case AppTestPlatform.ESPRESSO: {
|
|
112
135
|
try {
|
|
@@ -128,17 +151,12 @@ async function runAppTestsOnBrowserStack(args, config) {
|
|
|
128
151
|
test_suite_url = await uploadEspressoTestSuite(args.testSuitePath, config);
|
|
129
152
|
logger.info(`Test suite uploaded. URL: ${test_suite_url}`);
|
|
130
153
|
}
|
|
131
|
-
|
|
132
|
-
const deviceStrings = args.devices.map((device) => {
|
|
133
|
-
const [, deviceName, osVersion] = device;
|
|
134
|
-
return `${deviceName}-${osVersion}`;
|
|
135
|
-
});
|
|
136
|
-
const build_id = await triggerEspressoBuild(app_url, test_suite_url, deviceStrings, args.project, config);
|
|
154
|
+
const build_id = await triggerEspressoBuild(app_url, test_suite_url, deviceStrings, args.project, config, { accessibility });
|
|
137
155
|
return {
|
|
138
156
|
content: [
|
|
139
157
|
{
|
|
140
158
|
type: "text",
|
|
141
|
-
text:
|
|
159
|
+
text: runStartedMessage("Espresso", build_id, accessibility),
|
|
142
160
|
},
|
|
143
161
|
],
|
|
144
162
|
};
|
|
@@ -168,17 +186,12 @@ async function runAppTestsOnBrowserStack(args, config) {
|
|
|
168
186
|
test_suite_url = await uploadXcuiTestSuite(args.testSuitePath, config);
|
|
169
187
|
logger.info(`Test suite uploaded. URL: ${test_suite_url}`);
|
|
170
188
|
}
|
|
171
|
-
|
|
172
|
-
const deviceStrings = args.devices.map((device) => {
|
|
173
|
-
const [, deviceName, osVersion] = device;
|
|
174
|
-
return `${deviceName}-${osVersion}`;
|
|
175
|
-
});
|
|
176
|
-
const build_id = await triggerXcuiBuild(app_url, test_suite_url, deviceStrings, args.project, config);
|
|
189
|
+
const build_id = await triggerXcuiBuild(app_url, test_suite_url, deviceStrings, args.project, config, { accessibility });
|
|
177
190
|
return {
|
|
178
191
|
content: [
|
|
179
192
|
{
|
|
180
193
|
type: "text",
|
|
181
|
-
text:
|
|
194
|
+
text: runStartedMessage("XCUITest", build_id, accessibility),
|
|
182
195
|
},
|
|
183
196
|
],
|
|
184
197
|
};
|
|
@@ -11,8 +11,8 @@ export declare const CreateTestRunSchema: z.ZodObject<{
|
|
|
11
11
|
description: z.ZodOptional<z.ZodString>;
|
|
12
12
|
run_state: z.ZodOptional<z.ZodEnum<{
|
|
13
13
|
done: "done";
|
|
14
|
-
new_run: "new_run";
|
|
15
14
|
in_progress: "in_progress";
|
|
15
|
+
new_run: "new_run";
|
|
16
16
|
under_review: "under_review";
|
|
17
17
|
rejected: "rejected";
|
|
18
18
|
closed: "closed";
|
|
@@ -11,8 +11,8 @@ export declare const UpdateTestRunSchema: z.ZodObject<{
|
|
|
11
11
|
name: z.ZodOptional<z.ZodString>;
|
|
12
12
|
run_state: z.ZodOptional<z.ZodEnum<{
|
|
13
13
|
done: "done";
|
|
14
|
-
new_run: "new_run";
|
|
15
14
|
in_progress: "in_progress";
|
|
15
|
+
new_run: "new_run";
|
|
16
16
|
under_review: "under_review";
|
|
17
17
|
rejected: "rejected";
|
|
18
18
|
closed: "closed";
|
|
@@ -62,8 +62,9 @@ export declare const NEEDS_BUILD_ID: string;
|
|
|
62
62
|
*/
|
|
63
63
|
export declare const NEEDS_SESSION_ID: string;
|
|
64
64
|
/**
|
|
65
|
-
* A scan run's ids come from startAccessibilityScan
|
|
66
|
-
*
|
|
65
|
+
* A scan run's ids come from startAccessibilityScan; a build's id is printed by the SDK at
|
|
66
|
+
* the end of its run. Nothing here lists builds or reports, but the tool takes a report's
|
|
67
|
+
* dashboard link, or an Automate link, and looks the ids up itself.
|
|
67
68
|
*/
|
|
68
69
|
export declare const NEEDS_A11Y_SCAN_ID = " Ids: startAccessibilityScan or a dashboard link; nothing here lists reports.";
|
|
69
70
|
/** Auth-config ids are not listable by any tool here. */
|
|
@@ -71,8 +71,9 @@ export const NEEDS_BUILD_ID = needsIdFrom("a BrowserStack build id", "getBuildId
|
|
|
71
71
|
export const NEEDS_SESSION_ID = " Requires a session id. listSessions lists them for a build; if you do not have the " +
|
|
72
72
|
"build either, getBuildId or listBuildId resolves one from a project and build name.";
|
|
73
73
|
/**
|
|
74
|
-
* A scan run's ids come from startAccessibilityScan
|
|
75
|
-
*
|
|
74
|
+
* A scan run's ids come from startAccessibilityScan; a build's id is printed by the SDK at
|
|
75
|
+
* the end of its run. Nothing here lists builds or reports, but the tool takes a report's
|
|
76
|
+
* dashboard link, or an Automate link, and looks the ids up itself.
|
|
76
77
|
*/
|
|
77
78
|
export const NEEDS_A11Y_SCAN_ID = " Ids: startAccessibilityScan or a dashboard link; nothing here lists reports.";
|
|
78
79
|
/** Auth-config ids are not listable by any tool here. */
|
package/package.json
CHANGED
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
export interface RAGChunk {
|
|
2
|
-
url: string;
|
|
3
|
-
content: string;
|
|
4
|
-
}
|
|
5
|
-
import { BrowserStackConfig } from "../../lib/types.js";
|
|
6
|
-
export interface AccessibilityRAGResponse {
|
|
7
|
-
content: Array<{
|
|
8
|
-
type: "text";
|
|
9
|
-
text: string;
|
|
10
|
-
}>;
|
|
11
|
-
}
|
|
12
|
-
export declare function queryAccessibilityRAG(userQuery: string, config: BrowserStackConfig): Promise<any>;
|
|
@@ -1,59 +0,0 @@
|
|
|
1
|
-
import { apiClient } from "../../lib/apiClient.js";
|
|
2
|
-
import { wrapUntrusted } from "../../lib/untrusted-content.js";
|
|
3
|
-
import { getBrowserStackAuth } from "../../lib/get-auth.js";
|
|
4
|
-
export async function queryAccessibilityRAG(userQuery, config) {
|
|
5
|
-
const url = "https://accessibility.browserstack.com/api/tcg-proxy/search";
|
|
6
|
-
const authString = getBrowserStackAuth(config);
|
|
7
|
-
const auth = Buffer.from(authString).toString("base64");
|
|
8
|
-
const response = await apiClient.post({
|
|
9
|
-
url,
|
|
10
|
-
headers: {
|
|
11
|
-
"Content-Type": "application/json",
|
|
12
|
-
Authorization: `Basic ${auth}`,
|
|
13
|
-
},
|
|
14
|
-
body: {
|
|
15
|
-
query: userQuery,
|
|
16
|
-
},
|
|
17
|
-
raise_error: false,
|
|
18
|
-
});
|
|
19
|
-
if (!response.ok) {
|
|
20
|
-
const errorText = typeof response.data === "string"
|
|
21
|
-
? response.data
|
|
22
|
-
: JSON.stringify(response.data);
|
|
23
|
-
throw new Error(`RAG endpoint error: ${response.status} ${errorText}`);
|
|
24
|
-
}
|
|
25
|
-
const responseData = response.data;
|
|
26
|
-
if (!responseData.success) {
|
|
27
|
-
throw new Error("Something went wrong: " + responseData.message);
|
|
28
|
-
}
|
|
29
|
-
// Parse the stringified JSON data
|
|
30
|
-
let parsedData;
|
|
31
|
-
try {
|
|
32
|
-
parsedData = JSON.parse(responseData.data);
|
|
33
|
-
}
|
|
34
|
-
catch (err) {
|
|
35
|
-
throw new Error("Failed to parse RAG response data as JSON: " +
|
|
36
|
-
(err instanceof Error ? err.message : String(err)));
|
|
37
|
-
}
|
|
38
|
-
if (!parsedData ||
|
|
39
|
-
!parsedData.data ||
|
|
40
|
-
!Array.isArray(parsedData.data.chunks)) {
|
|
41
|
-
throw new Error("RAG response data is missing expected 'data.chunks' array");
|
|
42
|
-
}
|
|
43
|
-
const chunks = parsedData.data.chunks;
|
|
44
|
-
// Format the response properly
|
|
45
|
-
const instruction = "IMPORTANT: Use ONLY the data provided below to answer the user's accessibility question. Do not use any external knowledge. When answering, you MUST include the relevant BrowserStack documentation links provided in the sources for personalization and further reference.\n\n";
|
|
46
|
-
const formattedChunks = chunks
|
|
47
|
-
.map((chunk, index) => `${index + 1}: Source: ${chunk.url}\n\n${chunk.content}`)
|
|
48
|
-
.join("\n\n---\n\n");
|
|
49
|
-
const formattedResponse = instruction +
|
|
50
|
-
wrapUntrusted("BrowserStack accessibility documentation", formattedChunks);
|
|
51
|
-
return {
|
|
52
|
-
content: [
|
|
53
|
-
{
|
|
54
|
-
type: "text",
|
|
55
|
-
text: formattedResponse,
|
|
56
|
-
},
|
|
57
|
-
],
|
|
58
|
-
};
|
|
59
|
-
}
|