@cotestdev/ai-runner-fake 0.0.1
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/dist/agents/logger.d.ts +7 -0
- package/dist/agents/logger.d.ts.map +1 -0
- package/dist/agents/logger.js +22 -0
- package/dist/agents/logger.js.map +1 -0
- package/dist/agents/playwright-executor.d.ts +26 -0
- package/dist/agents/playwright-executor.d.ts.map +1 -0
- package/dist/agents/playwright-executor.js +289 -0
- package/dist/agents/playwright-executor.js.map +1 -0
- package/dist/agents/tools/playwright-backend-adapter.d.ts +33 -0
- package/dist/agents/tools/playwright-backend-adapter.d.ts.map +1 -0
- package/dist/agents/tools/playwright-backend-adapter.js +147 -0
- package/dist/agents/tools/playwright-backend-adapter.js.map +1 -0
- package/dist/agents/types.d.ts +55 -0
- package/dist/agents/types.d.ts.map +1 -0
- package/dist/agents/types.js +6 -0
- package/dist/agents/types.js.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +7 -0
- package/dist/index.js.map +1 -0
- package/dist/runner.d.ts +23 -0
- package/dist/runner.d.ts.map +1 -0
- package/dist/runner.js +86 -0
- package/dist/runner.js.map +1 -0
- package/dist/tools/index.d.ts +16 -0
- package/dist/tools/index.d.ts.map +1 -0
- package/dist/tools/index.js +35 -0
- package/dist/tools/index.js.map +1 -0
- package/dist/tools/playwright-groups.d.ts +19 -0
- package/dist/tools/playwright-groups.d.ts.map +1 -0
- package/dist/tools/playwright-groups.js +50 -0
- package/dist/tools/playwright-groups.js.map +1 -0
- package/dist/types/external.d.ts +6 -0
- package/dist/types/external.d.ts.map +1 -0
- package/dist/types/external.js +7 -0
- package/dist/types/external.js.map +1 -0
- package/dist/types/index.d.ts +95 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +7 -0
- package/dist/types/index.js.map +1 -0
- package/package.json +33 -0
- package/src/index.ts +4 -0
- package/src/runner.ts +112 -0
- package/tsconfig.json +24 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../../src/agents/logger.ts"],"names":[],"mappings":"AACA,qBAAa,MAAM;IAEf,OAAO,CAAC,MAAM,CAAa;IAG3B,GAAG,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,cAAc,EAAE,GAAG,EAAE;IAK7C,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,cAAc,EAAE,GAAG,EAAE;IAK9C,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,cAAc,EAAE,GAAG,EAAE;CAGlD"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.Logger = void 0;
|
|
4
|
+
class Logger {
|
|
5
|
+
constructor() {
|
|
6
|
+
this.prefix = '[Agent]';
|
|
7
|
+
}
|
|
8
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
9
|
+
log(message, ...optionalParams) {
|
|
10
|
+
console.log(`${this.prefix} ${message}`, ...optionalParams);
|
|
11
|
+
}
|
|
12
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
13
|
+
warn(message, ...optionalParams) {
|
|
14
|
+
console.warn(`${this.prefix} ${message}`, ...optionalParams);
|
|
15
|
+
}
|
|
16
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
17
|
+
error(message, ...optionalParams) {
|
|
18
|
+
console.error(`${this.prefix} ${message}`, ...optionalParams);
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
exports.Logger = Logger;
|
|
22
|
+
//# sourceMappingURL=logger.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logger.js","sourceRoot":"","sources":["../../src/agents/logger.ts"],"names":[],"mappings":";;;AACA,MAAa,MAAM;IAAnB;QAEY,WAAM,GAAG,SAAS,CAAC;IAgB/B,CAAC;IAdG,8DAA8D;IAC9D,GAAG,CAAC,OAAe,EAAE,GAAG,cAAqB;QACzC,OAAO,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC,MAAM,IAAI,OAAO,EAAE,EAAE,GAAG,cAAc,CAAC,CAAC;IAChE,CAAC;IAED,8DAA8D;IAC9D,IAAI,CAAC,OAAe,EAAE,GAAG,cAAqB;QAC1C,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,MAAM,IAAI,OAAO,EAAE,EAAE,GAAG,cAAc,CAAC,CAAC;IACjE,CAAC;IAED,8DAA8D;IAC9D,KAAK,CAAC,OAAe,EAAE,GAAG,cAAqB;QAC3C,OAAO,CAAC,KAAK,CAAC,GAAG,IAAI,CAAC,MAAM,IAAI,OAAO,EAAE,EAAE,GAAG,cAAc,CAAC,CAAC;IAClE,CAAC;CACJ;AAlBD,wBAkBC"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Playwright Executor - Uses LangChain's createAgent API to implement ReAct loop
|
|
3
|
+
*/
|
|
4
|
+
import type { HealContext } from '../types';
|
|
5
|
+
import { PlaywrightAgentState } from './types';
|
|
6
|
+
export declare class PlaywrightExecutor {
|
|
7
|
+
private state;
|
|
8
|
+
private signal;
|
|
9
|
+
constructor(state: PlaywrightAgentState, signal: AbortSignal);
|
|
10
|
+
private createPlaywrightTools;
|
|
11
|
+
/**
|
|
12
|
+
* Update original script and save to database (heal mode)
|
|
13
|
+
*/
|
|
14
|
+
private updateOriginalScript;
|
|
15
|
+
execute(context: HealContext): Promise<void>;
|
|
16
|
+
private buildSystemPrompt;
|
|
17
|
+
private getSnapshotContext;
|
|
18
|
+
private buildUserMessage;
|
|
19
|
+
/**
|
|
20
|
+
* Extract and normalize content from model response
|
|
21
|
+
* Handles string, array (ContentBlock[]), and other types
|
|
22
|
+
* Following LangChain.js best practices
|
|
23
|
+
*/
|
|
24
|
+
private extractContent;
|
|
25
|
+
}
|
|
26
|
+
//# sourceMappingURL=playwright-executor.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"playwright-executor.d.ts","sourceRoot":"","sources":["../../src/agents/playwright-executor.ts"],"names":[],"mappings":"AAAA;;GAEG;AAKH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AAE5C,OAAO,EAAE,oBAAoB,EAAE,MAAM,SAAS,CAAC;AAG/C,qBAAa,kBAAkB;IAC7B,OAAO,CAAC,KAAK,CAAuB;IACpC,OAAO,CAAC,MAAM,CAAc;gBAEhB,KAAK,EAAE,oBAAoB,EAAE,MAAM,EAAE,WAAW;YAK9C,qBAAqB;IAuFnC;;OAEG;IACH,OAAO,CAAC,oBAAoB;IAKtB,OAAO,CAAC,OAAO,EAAE,WAAW;IA0DlC,OAAO,CAAC,iBAAiB;YAkBX,kBAAkB;IA0BhC,OAAO,CAAC,gBAAgB;IAmBxB;;;;SAIK;IACL,OAAO,CAAC,cAAc;CAuCvB"}
|
|
@@ -0,0 +1,289 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Playwright Executor - Uses LangChain's createAgent API to implement ReAct loop
|
|
4
|
+
*/
|
|
5
|
+
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
6
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
7
|
+
if (k2 === undefined) k2 = k;
|
|
8
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
9
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
10
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
11
|
+
}
|
|
12
|
+
Object.defineProperty(o, k2, desc);
|
|
13
|
+
}) : (function(o, m, k, k2) {
|
|
14
|
+
if (k2 === undefined) k2 = k;
|
|
15
|
+
o[k2] = m[k];
|
|
16
|
+
}));
|
|
17
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
18
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
19
|
+
}) : function(o, v) {
|
|
20
|
+
o["default"] = v;
|
|
21
|
+
});
|
|
22
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
23
|
+
var ownKeys = function(o) {
|
|
24
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
25
|
+
var ar = [];
|
|
26
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
27
|
+
return ar;
|
|
28
|
+
};
|
|
29
|
+
return ownKeys(o);
|
|
30
|
+
};
|
|
31
|
+
return function (mod) {
|
|
32
|
+
if (mod && mod.__esModule) return mod;
|
|
33
|
+
var result = {};
|
|
34
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
35
|
+
__setModuleDefault(result, mod);
|
|
36
|
+
return result;
|
|
37
|
+
};
|
|
38
|
+
})();
|
|
39
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
40
|
+
exports.PlaywrightExecutor = void 0;
|
|
41
|
+
const langchain_1 = require("langchain");
|
|
42
|
+
const tools_1 = require("@langchain/core/tools");
|
|
43
|
+
const zod_1 = __importStar(require("zod"));
|
|
44
|
+
class PlaywrightExecutor {
|
|
45
|
+
constructor(state, signal) {
|
|
46
|
+
this.state = state;
|
|
47
|
+
this.signal = signal;
|
|
48
|
+
}
|
|
49
|
+
async createPlaywrightTools(healContext) {
|
|
50
|
+
const standardTools = this.state.playwrightGroup.getDefaultTools();
|
|
51
|
+
const playwrightToolGroups = this.state.playwrightGroup.getNonDefaultGroupInfo();
|
|
52
|
+
const getToolGroupsTool = {
|
|
53
|
+
name: "get_tools",
|
|
54
|
+
description: "Get available tools in a group.",
|
|
55
|
+
schema: zod_1.default.object({
|
|
56
|
+
group_name: zod_1.default.string().describe("The name of the tool group."),
|
|
57
|
+
}),
|
|
58
|
+
func: async (param) => {
|
|
59
|
+
if (!param.group_name)
|
|
60
|
+
throw new Error('Missing group_name parameter');
|
|
61
|
+
return JSON.stringify(playwrightToolGroups[param.group_name]);
|
|
62
|
+
},
|
|
63
|
+
};
|
|
64
|
+
const callToolTool = {
|
|
65
|
+
name: "call_tool",
|
|
66
|
+
description: "Call a tool in a group by name.",
|
|
67
|
+
schema: zod_1.default.object({
|
|
68
|
+
group_name: zod_1.default.string().describe("Tool group name."),
|
|
69
|
+
tool_name: zod_1.default.string().describe("Tool name."),
|
|
70
|
+
args: zod_1.default.object().describe("Tool parameters."),
|
|
71
|
+
}),
|
|
72
|
+
func: async (param) => {
|
|
73
|
+
const { group_name, tool_name, args } = param;
|
|
74
|
+
if (!group_name || !tool_name)
|
|
75
|
+
throw new Error('Missing group_name or tool_name parameter');
|
|
76
|
+
return await this.state.playwrightGroup.callTool(tool_name, args);
|
|
77
|
+
},
|
|
78
|
+
};
|
|
79
|
+
const finishTool = {
|
|
80
|
+
name: "finish_test",
|
|
81
|
+
description: "Call this tool ONLY when the step goal has been fully achieved or failed. After calling this, no more tools should be called.",
|
|
82
|
+
schema: zod_1.default.object({
|
|
83
|
+
isSuccess: zod_1.default.boolean().describe("Whether the step goal was successfully achieved."),
|
|
84
|
+
error: zod_1.default.string().optional().describe("Reason if the step goal fails to fully achieve, otherwise leave empty."),
|
|
85
|
+
variables: zod_1.default.record(zod_1.default.string(), zod_1.default.any()).describe(`
|
|
86
|
+
Key-value variables to assign in the test context to use in subsequent steps.
|
|
87
|
+
- The variable names should be consistent with those in the original test script
|
|
88
|
+
- Avoid conflicts with existing variable names
|
|
89
|
+
- Only include variables that have been changed or newly assigned in the fix
|
|
90
|
+
- The value should be NON-OBJECT types (string, number, boolean, etc.)
|
|
91
|
+
- If subsequent steps get a variable using 'runner.get', make sure to extract and provide the ACTUAL VALUE from test or page context
|
|
92
|
+
`),
|
|
93
|
+
repairedScript: zod_1.default.string().optional().describe(`
|
|
94
|
+
The complete fixed test script, leave empty if the step fails:
|
|
95
|
+
- Keep original runner.set, runner.get, runner.reuseTest calls for the steps fixed if possible and ensure no semantic changes
|
|
96
|
+
- MUST return The COMPLETE fixed test script
|
|
97
|
+
- ONLY apply fixes relevant to the current step and any necessary previous steps
|
|
98
|
+
- Do NOT wrap in closures or test body - write direct code using runner API
|
|
99
|
+
- Add a 'FIXED' comment for the step code being fixed
|
|
100
|
+
- Example:
|
|
101
|
+
\`\`\`typescript
|
|
102
|
+
// FIXED
|
|
103
|
+
await runner.runStep('Click button', async () => {
|
|
104
|
+
await page.click('#button');
|
|
105
|
+
});
|
|
106
|
+
\`\`\`
|
|
107
|
+
`),
|
|
108
|
+
}),
|
|
109
|
+
func: async (params) => {
|
|
110
|
+
healContext.success = params.isSuccess;
|
|
111
|
+
healContext.healError = params.error;
|
|
112
|
+
if (healContext.success) {
|
|
113
|
+
if (params.variables) {
|
|
114
|
+
for (const [key, value] of Object.entries(params.variables)) {
|
|
115
|
+
this.state.variables.set(key, value);
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
this.state.originalScript = params.repairedScript;
|
|
119
|
+
this.updateOriginalScript(params.repairedScript);
|
|
120
|
+
}
|
|
121
|
+
return 'Test step finished.';
|
|
122
|
+
},
|
|
123
|
+
};
|
|
124
|
+
return [
|
|
125
|
+
...standardTools,
|
|
126
|
+
new tools_1.DynamicStructuredTool(getToolGroupsTool),
|
|
127
|
+
new tools_1.DynamicStructuredTool(callToolTool),
|
|
128
|
+
new tools_1.DynamicStructuredTool(finishTool)
|
|
129
|
+
];
|
|
130
|
+
}
|
|
131
|
+
/**
|
|
132
|
+
* Update original script and save to database (heal mode)
|
|
133
|
+
*/
|
|
134
|
+
updateOriginalScript(script) {
|
|
135
|
+
this.state.storageService.saveTestScript(this.state.testCaseId, script);
|
|
136
|
+
this.state.logger.log('Script fixed');
|
|
137
|
+
}
|
|
138
|
+
async execute(context) {
|
|
139
|
+
const page = this.state.page;
|
|
140
|
+
if (!page)
|
|
141
|
+
throw new Error('Missing page object');
|
|
142
|
+
// Check if already aborted
|
|
143
|
+
if (this.signal.aborted) {
|
|
144
|
+
throw new Error('Execution aborted');
|
|
145
|
+
}
|
|
146
|
+
const tools = await this.createPlaywrightTools(context);
|
|
147
|
+
const agent = (0, langchain_1.createAgent)({
|
|
148
|
+
model: this.state.model,
|
|
149
|
+
tools: tools,
|
|
150
|
+
systemPrompt: this.buildSystemPrompt(),
|
|
151
|
+
});
|
|
152
|
+
const snapshot = await this.getSnapshotContext();
|
|
153
|
+
const inputStream = {
|
|
154
|
+
messages: [{
|
|
155
|
+
role: 'user',
|
|
156
|
+
content: this.buildUserMessage(context)
|
|
157
|
+
},
|
|
158
|
+
...snapshot || [],]
|
|
159
|
+
};
|
|
160
|
+
const stream = await agent.stream(inputStream, {
|
|
161
|
+
recursionLimit: 25,
|
|
162
|
+
streamMode: 'updates',
|
|
163
|
+
});
|
|
164
|
+
for await (const event of stream) {
|
|
165
|
+
// Check for abort signal
|
|
166
|
+
if (this.signal.aborted) {
|
|
167
|
+
throw new Error('Execution aborted');
|
|
168
|
+
}
|
|
169
|
+
// Process AI messages (thoughts and tool calls)
|
|
170
|
+
const messages = event.model_request?.messages || event.messages;
|
|
171
|
+
if (messages?.[0]?.type === 'ai') {
|
|
172
|
+
const aiMsg = messages[0];
|
|
173
|
+
const content = this.extractContent(aiMsg.content);
|
|
174
|
+
// Record thought
|
|
175
|
+
if (content) {
|
|
176
|
+
this.state.logger.log(`${content}`);
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
// Process tool results
|
|
180
|
+
const toolMsg = event.tools?.messages?.[0];
|
|
181
|
+
if (toolMsg?.type === 'tool') {
|
|
182
|
+
const output = this.extractContent(toolMsg.content);
|
|
183
|
+
this.state.logger.log(`✅ Result [${toolMsg.name}]:`, output.length > 300 ? output.substring(0, 100) + '...' : output);
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
buildSystemPrompt() {
|
|
188
|
+
return `
|
|
189
|
+
You are a Playwright test expert, skilled at analyzing and fixing errors in browser automation tests.
|
|
190
|
+
|
|
191
|
+
## ** Critial Rules **
|
|
192
|
+
- You MUST run the step using tools first before fixing the script
|
|
193
|
+
- When you step finishes or fails, you MUST call 'finish_test' tool and set the 'isSuccess' parameter correctly.
|
|
194
|
+
- Analyze the current step code, errors and page context and what variables are being set
|
|
195
|
+
- Make sure the fixed code is concise and consistent with the original code in logic and style
|
|
196
|
+
- CRITICAL: When calling 'finish_test', analyze the full test script to identify variables defined in the current step that are used in subsequent steps
|
|
197
|
+
|
|
198
|
+
## ** Constraints **
|
|
199
|
+
- NEVER set 'isSuccess' to true if the step goal is not fully achieved
|
|
200
|
+
- Fail the step fast and DON'T do unnecessary or unreansonable retries
|
|
201
|
+
- Always check if variables assigned in the current step are referenced in later steps - if so, extract their actual values and include in 'variables'
|
|
202
|
+
`.trim();
|
|
203
|
+
}
|
|
204
|
+
async getSnapshotContext() {
|
|
205
|
+
const snapshot = await this.state.adapter.callTool('browser_snapshot', {});
|
|
206
|
+
if (snapshot.isError) {
|
|
207
|
+
this.state.logger.warn(`Failed to get browser snapshot: ${snapshot.error}`);
|
|
208
|
+
return undefined;
|
|
209
|
+
}
|
|
210
|
+
const callId = zod_1.uuid.toString();
|
|
211
|
+
const aiMessage = new langchain_1.AIMessage({
|
|
212
|
+
tool_calls: [
|
|
213
|
+
{
|
|
214
|
+
name: 'browser_snapshot',
|
|
215
|
+
id: callId,
|
|
216
|
+
args: {},
|
|
217
|
+
},
|
|
218
|
+
]
|
|
219
|
+
});
|
|
220
|
+
const toolMessage = new langchain_1.ToolMessage({
|
|
221
|
+
content: snapshot.content,
|
|
222
|
+
tool_call_id: callId,
|
|
223
|
+
name: 'browser_snapshot',
|
|
224
|
+
status: 'success',
|
|
225
|
+
});
|
|
226
|
+
return [aiMessage, toolMessage];
|
|
227
|
+
}
|
|
228
|
+
buildUserMessage(context) {
|
|
229
|
+
const variableList = Object.keys(this.state.variables).length > 0
|
|
230
|
+
? Object.keys(this.state.variables).map(v => ` - ${v}: ${JSON.stringify(this.state.variables.get(v))}`).join('\n')
|
|
231
|
+
: undefined;
|
|
232
|
+
return `
|
|
233
|
+
## Step Description: ${context.stepDescription}
|
|
234
|
+
|
|
235
|
+
${variableList ? `## Variables in Context\n${variableList}` : ''}
|
|
236
|
+
|
|
237
|
+
## Stacktrace
|
|
238
|
+
${context.stackTrace}
|
|
239
|
+
|
|
240
|
+
## Full Test Script
|
|
241
|
+
\`\`\`typescript
|
|
242
|
+
${this.state.originalScript}
|
|
243
|
+
\`\`\`
|
|
244
|
+
`.trim();
|
|
245
|
+
}
|
|
246
|
+
/**
|
|
247
|
+
* Extract and normalize content from model response
|
|
248
|
+
* Handles string, array (ContentBlock[]), and other types
|
|
249
|
+
* Following LangChain.js best practices
|
|
250
|
+
*/
|
|
251
|
+
extractContent(content) {
|
|
252
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
253
|
+
const asAny = content;
|
|
254
|
+
if (asAny.content) {
|
|
255
|
+
content = asAny.content;
|
|
256
|
+
}
|
|
257
|
+
// If string, return as-is
|
|
258
|
+
if (typeof content === 'string') {
|
|
259
|
+
return content;
|
|
260
|
+
}
|
|
261
|
+
// If array (ContentBlock[]), extract text content
|
|
262
|
+
if (Array.isArray(content)) {
|
|
263
|
+
const content0 = content[0];
|
|
264
|
+
if (typeof content0 === 'string') {
|
|
265
|
+
return content0;
|
|
266
|
+
}
|
|
267
|
+
if (typeof content0 === 'object' && content0 !== null) {
|
|
268
|
+
// Handle text blocks
|
|
269
|
+
if ('text' in content0) {
|
|
270
|
+
return content0.text;
|
|
271
|
+
}
|
|
272
|
+
// Handle other block types by converting to string
|
|
273
|
+
return JSON.stringify(content0);
|
|
274
|
+
}
|
|
275
|
+
return String(content0);
|
|
276
|
+
}
|
|
277
|
+
// If object, try to extract text field or convert to string
|
|
278
|
+
if (typeof content === 'object' && content !== null) {
|
|
279
|
+
if ('text' in content) {
|
|
280
|
+
return content;
|
|
281
|
+
}
|
|
282
|
+
return content;
|
|
283
|
+
}
|
|
284
|
+
// Fallback: convert to string
|
|
285
|
+
return String(content);
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
exports.PlaywrightExecutor = PlaywrightExecutor;
|
|
289
|
+
//# sourceMappingURL=playwright-executor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"playwright-executor.js","sourceRoot":"","sources":["../../src/agents/playwright-executor.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Playwright Backend 工具适配器 - 新方案
|
|
3
|
+
*
|
|
4
|
+
* 基于 BrowserServerBackend 的伪实例实现
|
|
5
|
+
* 参考:playwright/lib/mcp/test/browserBackend.js
|
|
6
|
+
*
|
|
7
|
+
* 这个方案的优势:
|
|
8
|
+
* 1. 直接使用 Playwright 官方的 BrowserServerBackend 类
|
|
9
|
+
* 2. 直接导入官方的 identityFactory,完全复用
|
|
10
|
+
* 3. 获得完整的官方工具功能,包括 Response、Context 等
|
|
11
|
+
* 4. 无需手动适配 Context 和 Response
|
|
12
|
+
* 5. 自动跟随 Playwright 更新
|
|
13
|
+
*/
|
|
14
|
+
import { DynamicStructuredTool } from '@langchain/core/tools';
|
|
15
|
+
import type { BrowserContext } from 'playwright';
|
|
16
|
+
export declare class PlaywrightBackendAdapter {
|
|
17
|
+
private backend;
|
|
18
|
+
private tools;
|
|
19
|
+
static create(browserContext: BrowserContext): Promise<PlaywrightBackendAdapter>;
|
|
20
|
+
getTools(): DynamicStructuredTool[];
|
|
21
|
+
callTool(name: string, params: any): Promise<any>;
|
|
22
|
+
/**
|
|
23
|
+
* 官方的 identityFactory 函数
|
|
24
|
+
* 参考:playwright/lib/mcp/test/browserBackend.js 第 94-104 行
|
|
25
|
+
*
|
|
26
|
+
* 注意:官方文件中定义了这个函数但没有导出,所以我们在这里复制一份
|
|
27
|
+
*/
|
|
28
|
+
private identityFactory;
|
|
29
|
+
private loadPlaywrightMCPModules;
|
|
30
|
+
private getBackend;
|
|
31
|
+
private getPlaywrightBackendToolsFromContext;
|
|
32
|
+
}
|
|
33
|
+
//# sourceMappingURL=playwright-backend-adapter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"playwright-backend-adapter.d.ts","sourceRoot":"","sources":["../../../src/agents/tools/playwright-backend-adapter.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,EAAE,qBAAqB,EAAE,MAAM,uBAAuB,CAAC;AAC9D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAMjD,qBAAa,wBAAwB;IAEnC,OAAO,CAAC,OAAO,CAA2C;IAC1D,OAAO,CAAC,KAAK,CAA+B;WAE/B,MAAM,CAAC,cAAc,EAAE,cAAc,GAAG,OAAO,CAAC,wBAAwB,CAAC;IAOtF,QAAQ,IAAI,qBAAqB,EAAE;IAK7B,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG;IAQxC;;;;;OAKG;IAEH,OAAO,CAAC,eAAe;IAgBvB,OAAO,CAAC,wBAAwB;YAelB,UAAU;YA4BV,oCAAoC;CAsBnD"}
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Playwright Backend 工具适配器 - 新方案
|
|
4
|
+
*
|
|
5
|
+
* 基于 BrowserServerBackend 的伪实例实现
|
|
6
|
+
* 参考:playwright/lib/mcp/test/browserBackend.js
|
|
7
|
+
*
|
|
8
|
+
* 这个方案的优势:
|
|
9
|
+
* 1. 直接使用 Playwright 官方的 BrowserServerBackend 类
|
|
10
|
+
* 2. 直接导入官方的 identityFactory,完全复用
|
|
11
|
+
* 3. 获得完整的官方工具功能,包括 Response、Context 等
|
|
12
|
+
* 4. 无需手动适配 Context 和 Response
|
|
13
|
+
* 5. 自动跟随 Playwright 更新
|
|
14
|
+
*/
|
|
15
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
16
|
+
if (k2 === undefined) k2 = k;
|
|
17
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
18
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
19
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
20
|
+
}
|
|
21
|
+
Object.defineProperty(o, k2, desc);
|
|
22
|
+
}) : (function(o, m, k, k2) {
|
|
23
|
+
if (k2 === undefined) k2 = k;
|
|
24
|
+
o[k2] = m[k];
|
|
25
|
+
}));
|
|
26
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
27
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
28
|
+
}) : function(o, v) {
|
|
29
|
+
o["default"] = v;
|
|
30
|
+
});
|
|
31
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
32
|
+
var ownKeys = function(o) {
|
|
33
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
34
|
+
var ar = [];
|
|
35
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
36
|
+
return ar;
|
|
37
|
+
};
|
|
38
|
+
return ownKeys(o);
|
|
39
|
+
};
|
|
40
|
+
return function (mod) {
|
|
41
|
+
if (mod && mod.__esModule) return mod;
|
|
42
|
+
var result = {};
|
|
43
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
44
|
+
__setModuleDefault(result, mod);
|
|
45
|
+
return result;
|
|
46
|
+
};
|
|
47
|
+
})();
|
|
48
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
49
|
+
exports.PlaywrightBackendAdapter = void 0;
|
|
50
|
+
const tools_1 = require("@langchain/core/tools");
|
|
51
|
+
const path = __importStar(require("path"));
|
|
52
|
+
class PlaywrightBackendAdapter {
|
|
53
|
+
constructor() {
|
|
54
|
+
this.tools = [];
|
|
55
|
+
}
|
|
56
|
+
static async create(browserContext) {
|
|
57
|
+
const adapter = new PlaywrightBackendAdapter();
|
|
58
|
+
adapter.backend = await adapter.getBackend(browserContext);
|
|
59
|
+
adapter.tools = await adapter.getPlaywrightBackendToolsFromContext();
|
|
60
|
+
return adapter;
|
|
61
|
+
}
|
|
62
|
+
getTools() {
|
|
63
|
+
return this.tools;
|
|
64
|
+
}
|
|
65
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
66
|
+
async callTool(name, params) {
|
|
67
|
+
return await this.backend.callTool(name, params);
|
|
68
|
+
}
|
|
69
|
+
// ============================================================================
|
|
70
|
+
// 动态加载 Playwright 官方模块
|
|
71
|
+
// ============================================================================
|
|
72
|
+
/**
|
|
73
|
+
* 官方的 identityFactory 函数
|
|
74
|
+
* 参考:playwright/lib/mcp/test/browserBackend.js 第 94-104 行
|
|
75
|
+
*
|
|
76
|
+
* 注意:官方文件中定义了这个函数但没有导出,所以我们在这里复制一份
|
|
77
|
+
*/
|
|
78
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
79
|
+
identityFactory(browserContext) {
|
|
80
|
+
return {
|
|
81
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
82
|
+
createContext: async (clientInfo, abortSignal) => {
|
|
83
|
+
void clientInfo;
|
|
84
|
+
void abortSignal;
|
|
85
|
+
return {
|
|
86
|
+
browserContext,
|
|
87
|
+
close: async () => {
|
|
88
|
+
// 不关闭 context,因为它是外部的
|
|
89
|
+
}
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
loadPlaywrightMCPModules() {
|
|
95
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
96
|
+
const playwrightRoot = path.dirname(require.resolve('playwright'));
|
|
97
|
+
return {
|
|
98
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
99
|
+
BrowserServerBackend: require(path.join(playwrightRoot, 'lib', 'mcp', 'browser', 'browserServerBackend.js')).BrowserServerBackend,
|
|
100
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
101
|
+
defaultConfig: require(path.join(playwrightRoot, 'lib', 'mcp', 'browser', 'config.js')).defaultConfig,
|
|
102
|
+
// 使用本地定义的 identityFactory(因为官方没有导出)
|
|
103
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
104
|
+
identityFactory: this.identityFactory,
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
async getBackend(browserContext) {
|
|
108
|
+
// 加载 Playwright 模块(包括官方的 identityFactory)
|
|
109
|
+
const { BrowserServerBackend, defaultConfig, identityFactory } = this.loadPlaywrightMCPModules();
|
|
110
|
+
// 使用官方的 identityFactory(参考 browserBackend.js 第 34 行)
|
|
111
|
+
const factory = identityFactory(browserContext);
|
|
112
|
+
// 创建 Backend 实例
|
|
113
|
+
const backend = new BrowserServerBackend({ ...defaultConfig, capabilities: ['core', 'core-tabs',] }, factory);
|
|
114
|
+
// 初始化 Backend
|
|
115
|
+
await backend.initialize({
|
|
116
|
+
name: 'ai-runner',
|
|
117
|
+
version: '1.0.0',
|
|
118
|
+
roots: [],
|
|
119
|
+
});
|
|
120
|
+
return backend;
|
|
121
|
+
}
|
|
122
|
+
// ============================================================================
|
|
123
|
+
// 工具转换函数
|
|
124
|
+
// ============================================================================
|
|
125
|
+
// export type ToolCapability = 'core' | 'core-tabs' | 'core-install' | 'vision' | 'pdf' | 'testing' | 'tracing';
|
|
126
|
+
async getPlaywrightBackendToolsFromContext() {
|
|
127
|
+
// 列出所有工具
|
|
128
|
+
const toolList = await this.backend.listTools();
|
|
129
|
+
// 转换为 LangChain 工具
|
|
130
|
+
const tools = [];
|
|
131
|
+
for (const mcpTool of toolList) {
|
|
132
|
+
const tool = new tools_1.DynamicStructuredTool({
|
|
133
|
+
name: mcpTool.name,
|
|
134
|
+
description: mcpTool.description,
|
|
135
|
+
schema: mcpTool.inputSchema,
|
|
136
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
137
|
+
func: async (input) => {
|
|
138
|
+
return await this.backend.callTool(mcpTool.name, input);
|
|
139
|
+
}
|
|
140
|
+
});
|
|
141
|
+
tools.push(tool);
|
|
142
|
+
}
|
|
143
|
+
return tools;
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
exports.PlaywrightBackendAdapter = PlaywrightBackendAdapter;
|
|
147
|
+
//# sourceMappingURL=playwright-backend-adapter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"playwright-backend-adapter.js","sourceRoot":"","sources":["../../../src/agents/tools/playwright-backend-adapter.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Playwright Agent Type Definitions
|
|
3
|
+
*/
|
|
4
|
+
import type { ModelConfig } from '../types/external';
|
|
5
|
+
import type { ReActStep } from '../types';
|
|
6
|
+
import { BrowserContext, Page } from '@playwright/test';
|
|
7
|
+
import { Logger } from './logger';
|
|
8
|
+
import { PlaywrightGroup } from '../tools/playwright-groups';
|
|
9
|
+
import { PlaywrightBackendAdapter } from './tools/playwright-backend-adapter';
|
|
10
|
+
import { StorageService } from '@cotestdev/core-infra';
|
|
11
|
+
import { BaseLanguageModel } from '@langchain/core/language_models/base';
|
|
12
|
+
/**
|
|
13
|
+
* Agent execution mode
|
|
14
|
+
*/
|
|
15
|
+
export type AgentMode = 'heal' | 'execute';
|
|
16
|
+
/**
|
|
17
|
+
* Playwright Agent State
|
|
18
|
+
*/
|
|
19
|
+
export interface PlaywrightAgentState {
|
|
20
|
+
logger: Logger;
|
|
21
|
+
/** Playwright Page object */
|
|
22
|
+
page: Page;
|
|
23
|
+
/** Playwright BrowserContext object */
|
|
24
|
+
context: BrowserContext;
|
|
25
|
+
variables: Map<string, any>;
|
|
26
|
+
model?: BaseLanguageModel;
|
|
27
|
+
originalScript: string;
|
|
28
|
+
playwrightGroup: PlaywrightGroup;
|
|
29
|
+
adapter: PlaywrightBackendAdapter;
|
|
30
|
+
storageService: StorageService;
|
|
31
|
+
testCaseId: string;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Playwright Agent Configuration
|
|
35
|
+
*/
|
|
36
|
+
export interface PlaywrightAgentConfig {
|
|
37
|
+
/** Model configuration (for LLM Agent) */
|
|
38
|
+
model: ModelConfig;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Playwright Agent Execution Result
|
|
42
|
+
*/
|
|
43
|
+
export interface PlaywrightAgentResult {
|
|
44
|
+
/** Whether the goal was successfully completed */
|
|
45
|
+
success: boolean;
|
|
46
|
+
/** Agent's reasoning process */
|
|
47
|
+
reasoning?: string;
|
|
48
|
+
/** If failed, the error reason */
|
|
49
|
+
errorMessage?: string;
|
|
50
|
+
/** How many steps were executed */
|
|
51
|
+
steps?: number;
|
|
52
|
+
/** Detailed step records of ReAct loop */
|
|
53
|
+
reactSteps?: ReActStep[];
|
|
54
|
+
}
|
|
55
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/agents/types.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AACrD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AAC1C,OAAO,EAAE,cAAc,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AACxD,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAClC,OAAO,EAAE,eAAe,EAAE,MAAM,4BAA4B,CAAC;AAC7D,OAAO,EAAE,wBAAwB,EAAE,MAAM,oCAAoC,CAAC;AAC9E,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,EAAE,iBAAiB,EAAE,MAAM,sCAAsC,CAAC;AAMzE;;GAEG;AACH,MAAM,MAAM,SAAS,GAAG,MAAM,GAAG,SAAS,CAAC;AAM3C;;GAEG;AACH,MAAM,WAAW,oBAAoB;IACnC,MAAM,EAAE,MAAM,CAAC;IACf,6BAA6B;IAC7B,IAAI,EAAE,IAAI,CAAC;IACX,uCAAuC;IACvC,OAAO,EAAE,cAAc,CAAC;IAExB,SAAS,EAAE,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAC5B,KAAK,CAAC,EAAE,iBAAiB,CAAC;IAC1B,cAAc,EAAE,MAAM,CAAC;IACvB,eAAe,EAAE,eAAe,CAAC;IACjC,OAAO,EAAE,wBAAwB,CAAC;IAClC,cAAc,EAAE,cAAc,CAAC;IAC/B,UAAU,EAAE,MAAM,CAAC;CACpB;AAMD;;GAEG;AACH,MAAM,WAAW,qBAAqB;IACpC,0CAA0C;IAC1C,KAAK,EAAE,WAAW,CAAC;CACpB;AAMD;;GAEG;AACH,MAAM,WAAW,qBAAqB;IACpC,kDAAkD;IAClD,OAAO,EAAE,OAAO,CAAC;IAEjB,gCAAgC;IAChC,SAAS,CAAC,EAAE,MAAM,CAAC;IAEnB,kCAAkC;IAClC,YAAY,CAAC,EAAE,MAAM,CAAC;IAEtB,mCAAmC;IACnC,KAAK,CAAC,EAAE,MAAM,CAAC;IAEf,0CAA0C;IAC1C,UAAU,CAAC,EAAE,SAAS,EAAE,CAAC;CAC1B"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/agents/types.ts"],"names":[],"mappings":";AAAA;;GAEG"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.Runner = void 0;
|
|
4
|
+
// Core Classes
|
|
5
|
+
var runner_1 = require("./runner");
|
|
6
|
+
Object.defineProperty(exports, "Runner", { enumerable: true, get: function () { return runner_1.Runner; } });
|
|
7
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;AAAA,eAAe;AACf,mCAAkC;AAAzB,gGAAA,MAAM,OAAA"}
|
package/dist/runner.d.ts
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { BrowserContext, Page } from '@playwright/test';
|
|
2
|
+
export declare class Runner {
|
|
3
|
+
private abortController;
|
|
4
|
+
private variables;
|
|
5
|
+
private projectId;
|
|
6
|
+
private testCaseId;
|
|
7
|
+
private state?;
|
|
8
|
+
private constructor();
|
|
9
|
+
static NewInstance(projectId: string, testCaseId: string, canHeal?: boolean): Runner;
|
|
10
|
+
stop(): void;
|
|
11
|
+
init(page: Page, context: BrowserContext, data?: Record<string, any>): Promise<void>;
|
|
12
|
+
runStep(description: string, fn: () => Promise<void>): Promise<void>;
|
|
13
|
+
set(key: string, value: any): void;
|
|
14
|
+
get(key: string): any;
|
|
15
|
+
has(key: string): boolean;
|
|
16
|
+
delete(key: string): boolean;
|
|
17
|
+
clear(): void;
|
|
18
|
+
keys(): string[];
|
|
19
|
+
getAll(): Record<string, unknown>;
|
|
20
|
+
private loadTestScript;
|
|
21
|
+
reuseTest(useTestCaseId: string, description: string): Promise<Map<string, unknown>>;
|
|
22
|
+
}
|
|
23
|
+
//# sourceMappingURL=runner.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runner.d.ts","sourceRoot":"","sources":["../src/runner.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,cAAc,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AAUxD,qBAAa,MAAM;IACjB,OAAO,CAAC,eAAe,CAAkB;IACzC,OAAO,CAAC,SAAS,CAA4C;IAC7D,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,UAAU,CAAS;IAC3B,OAAO,CAAC,KAAK,CAAC,CAAQ;IAEtB,OAAO;IAMP,MAAM,CAAC,WAAW,CAAC,SAAS,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,OAAO,GAAE,OAAc,GAAG,MAAM;IAK1F,IAAI;IAIE,IAAI,CAAC,IAAI,EAAE,IAAI,EAAE,OAAO,EAAE,cAAc,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;IAQpF,OAAO,CAAC,WAAW,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC;IAQ1D,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,GAAG,IAAI;IAIlC,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG;IAIrB,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO;IAIzB,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO;IAI5B,KAAK,IAAI,IAAI;IAIb,IAAI,IAAI,MAAM,EAAE;IAIhB,MAAM,IAAI,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;IAIjC,OAAO,CAAC,cAAc;IAKhB,SAAS,CAAC,aAAa,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CA2B3F"}
|
package/dist/runner.js
ADDED
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.Runner = void 0;
|
|
4
|
+
const path_1 = require("path");
|
|
5
|
+
const os_1 = require("os");
|
|
6
|
+
const fs_1 = require("fs");
|
|
7
|
+
const test_1 = require("@playwright/test");
|
|
8
|
+
class Runner {
|
|
9
|
+
constructor(projectId, testCaseId) {
|
|
10
|
+
this.variables = new Map();
|
|
11
|
+
this.abortController = new AbortController();
|
|
12
|
+
this.projectId = projectId;
|
|
13
|
+
this.testCaseId = testCaseId;
|
|
14
|
+
}
|
|
15
|
+
static NewInstance(projectId, testCaseId, canHeal = true) {
|
|
16
|
+
const runner = new Runner(projectId, testCaseId);
|
|
17
|
+
return runner;
|
|
18
|
+
}
|
|
19
|
+
stop() {
|
|
20
|
+
this.abortController.abort();
|
|
21
|
+
}
|
|
22
|
+
async init(page, context, data) {
|
|
23
|
+
this.state = {
|
|
24
|
+
page: page,
|
|
25
|
+
context: context,
|
|
26
|
+
variables: this.variables,
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
async runStep(description, fn) {
|
|
30
|
+
try {
|
|
31
|
+
await fn();
|
|
32
|
+
}
|
|
33
|
+
catch (error) {
|
|
34
|
+
throw error;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
set(key, value) {
|
|
38
|
+
this.variables.set(key, value);
|
|
39
|
+
}
|
|
40
|
+
get(key) {
|
|
41
|
+
return this.variables.get(key);
|
|
42
|
+
}
|
|
43
|
+
has(key) {
|
|
44
|
+
return this.variables.has(key);
|
|
45
|
+
}
|
|
46
|
+
delete(key) {
|
|
47
|
+
return this.variables.delete(key);
|
|
48
|
+
}
|
|
49
|
+
clear() {
|
|
50
|
+
this.variables.clear();
|
|
51
|
+
}
|
|
52
|
+
keys() {
|
|
53
|
+
return Array.from(this.variables.keys());
|
|
54
|
+
}
|
|
55
|
+
getAll() {
|
|
56
|
+
return Object.fromEntries(this.variables);
|
|
57
|
+
}
|
|
58
|
+
loadTestScript(testCaseId) {
|
|
59
|
+
const scriptPath = (0, path_1.join)((0, os_1.homedir)(), '.test_agent', 'projects', this.projectId, 'script', `${testCaseId}.ts`);
|
|
60
|
+
return (0, fs_1.readFileSync)(scriptPath, 'utf-8');
|
|
61
|
+
}
|
|
62
|
+
async reuseTest(useTestCaseId, description) {
|
|
63
|
+
const scriptContent = this.loadTestScript(useTestCaseId);
|
|
64
|
+
if (!scriptContent) {
|
|
65
|
+
throw new Error(`Reusable test script not found: ${useTestCaseId}`);
|
|
66
|
+
}
|
|
67
|
+
const reuseRunner = Runner.NewInstance(this.projectId, useTestCaseId);
|
|
68
|
+
await reuseRunner.init(this.state.page, this.state.context);
|
|
69
|
+
console.log(`Starting to execute reusable test case: ${description}`);
|
|
70
|
+
try {
|
|
71
|
+
const executeScript = new Function('runner', 'page', 'context', 'expect', `
|
|
72
|
+
return (async () => {
|
|
73
|
+
${scriptContent}
|
|
74
|
+
})();
|
|
75
|
+
`);
|
|
76
|
+
await executeScript(reuseRunner, this.state.page, this.state.context, test_1.expect);
|
|
77
|
+
console.log(`Reusable test case executed successfully`);
|
|
78
|
+
return reuseRunner.state?.variables || new Map();
|
|
79
|
+
}
|
|
80
|
+
catch (error) {
|
|
81
|
+
throw new Error(`reuseTest execution failed, error: ${error instanceof Error ? error.message : String(error)}`);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
exports.Runner = Runner;
|
|
86
|
+
//# sourceMappingURL=runner.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runner.js","sourceRoot":"","sources":["../src/runner.ts"],"names":[],"mappings":";;;AAAA,+BAA4B;AAC5B,2BAA6B;AAC7B,2BAAkC;AAElC,2CAA0C;AAS1C,MAAa,MAAM;IAOjB,YAAoB,SAAiB,EAAE,UAAkB;QALjD,cAAS,GAAqB,IAAI,GAAG,EAAe,CAAC;QAM3D,IAAI,CAAC,eAAe,GAAG,IAAI,eAAe,EAAE,CAAC;QAC7C,IAAI,CAAC,SAAS,GAAG,SAAS,CAAC;QAC3B,IAAI,CAAC,UAAU,GAAG,UAAU,CAAC;IAC/B,CAAC;IAED,MAAM,CAAC,WAAW,CAAC,SAAiB,EAAE,UAAkB,EAAE,UAAmB,IAAI;QAC/E,MAAM,MAAM,GAAG,IAAI,MAAM,CAAC,SAAS,EAAE,UAAU,CAAC,CAAC;QACjD,OAAO,MAAM,CAAC;IAChB,CAAC;IAED,IAAI;QACF,IAAI,CAAC,eAAe,CAAC,KAAK,EAAE,CAAC;IAC/B,CAAC;IAED,KAAK,CAAC,IAAI,CAAC,IAAU,EAAE,OAAuB,EAAE,IAA0B;QACxE,IAAI,CAAC,KAAK,GAAG;YACX,IAAI,EAAE,IAAI;YACV,OAAO,EAAE,OAAO;YAChB,SAAS,EAAE,IAAI,CAAC,SAAS;SAC1B,CAAA;IACH,CAAC;IAED,KAAK,CAAC,OAAO,CAAC,WAAmB,EAAE,EAAuB;QACxD,IAAI,CAAC;YACH,MAAM,EAAE,EAAE,CAAC;QACb,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,KAAK,CAAC;QACd,CAAC;IACH,CAAC;IAED,GAAG,CAAC,GAAW,EAAE,KAAU;QACzB,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;IACjC,CAAC;IAED,GAAG,CAAC,GAAW;QACb,OAAO,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IACjC,CAAC;IAED,GAAG,CAAC,GAAW;QACb,OAAO,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IACjC,CAAC;IAED,MAAM,CAAC,GAAW;QAChB,OAAO,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;IACpC,CAAC;IAED,KAAK;QACH,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,CAAC;IACzB,CAAC;IAED,IAAI;QACF,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,CAAC,CAAC;IAC3C,CAAC;IAED,MAAM;QACJ,OAAO,MAAM,CAAC,WAAW,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;IAC5C,CAAC;IAEO,cAAc,CAAC,UAAkB;QACvC,MAAM,UAAU,GAAG,IAAA,WAAI,EAAC,IAAA,YAAO,GAAE,EAAE,aAAa,EAAE,UAAU,EAAE,IAAI,CAAC,SAAS,EAAE,QAAQ,EAAE,GAAG,UAAU,KAAK,CAAC,CAAC;QAC5G,OAAO,IAAA,iBAAY,EAAC,UAAU,EAAE,OAAO,CAAC,CAAC;IAC3C,CAAC;IAED,KAAK,CAAC,SAAS,CAAC,aAAqB,EAAE,WAAmB;QACxD,MAAM,aAAa,GAAG,IAAI,CAAC,cAAc,CAAC,aAAa,CAAC,CAAC;QACzD,IAAI,CAAC,aAAa,EAAE,CAAC;YACnB,MAAM,IAAI,KAAK,CAAC,mCAAmC,aAAa,EAAE,CAAC,CAAC;QACtE,CAAC;QAED,MAAM,WAAW,GAAG,MAAM,CAAC,WAAW,CAAC,IAAI,CAAC,SAAS,EAAE,aAAa,CAAC,CAAC;QACtE,MAAM,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,KAAM,CAAC,IAAI,EAAE,IAAI,CAAC,KAAM,CAAC,OAAO,CAAC,CAAC;QAE9D,OAAO,CAAC,GAAG,CAAC,2CAA2C,WAAW,EAAE,CAAC,CAAC;QAEtE,IAAI,CAAC;YACH,MAAM,aAAa,GAAG,IAAI,QAAQ,CAAC,QAAQ,EAAE,MAAM,EAAE,SAAS,EAAE,QAAQ,EAAE;;YAEpE,aAAa;;OAElB,CAAC,CAAC;YAEH,MAAM,aAAa,CAAC,WAAW,EAAE,IAAI,CAAC,KAAM,CAAC,IAAI,EAAE,IAAI,CAAC,KAAM,CAAC,OAAO,EAAE,aAAM,CAAC,CAAC;YAEhF,OAAO,CAAC,GAAG,CAAC,0CAA0C,CAAC,CAAC;YAExD,OAAO,WAAW,CAAC,KAAK,EAAE,SAAS,IAAI,IAAI,GAAG,EAAmB,CAAC;QACpE,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,IAAI,KAAK,CAAC,sCAAsC,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;QAClH,CAAC;IACH,CAAC;CACF;AAlGD,wBAkGC"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { DynamicStructuredTool } from "langchain";
|
|
2
|
+
export interface ToolGroup {
|
|
3
|
+
name: string;
|
|
4
|
+
description: string;
|
|
5
|
+
tools?: string[];
|
|
6
|
+
loadByDefault: boolean;
|
|
7
|
+
}
|
|
8
|
+
export declare abstract class AbstractGroup {
|
|
9
|
+
groups: ToolGroup[];
|
|
10
|
+
constructor(groups: ToolGroup[]);
|
|
11
|
+
abstract getAllTools(): DynamicStructuredTool[];
|
|
12
|
+
getDefaultTools(): DynamicStructuredTool[];
|
|
13
|
+
getAvailableTools(groupName: string): DynamicStructuredTool[];
|
|
14
|
+
getNonDefaultGroupInfo(): Record<string, string>;
|
|
15
|
+
}
|
|
16
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/tools/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,qBAAqB,EAAE,MAAM,WAAW,CAAC;AAElD,MAAM,WAAW,SAAS;IACtB,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;IACjB,aAAa,EAAE,OAAO,CAAC;CAC1B;AAED,8BAAsB,aAAa;IAC/B,MAAM,EAAE,SAAS,EAAE,CAAC;gBAER,MAAM,EAAE,SAAS,EAAE;IAI/B,QAAQ,CAAC,WAAW,IAAI,qBAAqB,EAAE;IAE/C,eAAe,IAAI,qBAAqB,EAAE;IAM1C,iBAAiB,CAAC,SAAS,EAAE,MAAM,GAAG,qBAAqB,EAAE;IAe7D,sBAAsB,IAAI,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC;CAQnD"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.AbstractGroup = void 0;
|
|
4
|
+
class AbstractGroup {
|
|
5
|
+
constructor(groups) {
|
|
6
|
+
this.groups = groups;
|
|
7
|
+
}
|
|
8
|
+
getDefaultTools() {
|
|
9
|
+
return this.getAllTools().filter(tool => {
|
|
10
|
+
return this.groups.some(group => group.loadByDefault && (!group.tools || group.tools.includes(tool.name)));
|
|
11
|
+
});
|
|
12
|
+
}
|
|
13
|
+
getAvailableTools(groupName) {
|
|
14
|
+
const group = this.groups.find(g => g.name === groupName);
|
|
15
|
+
if (group) {
|
|
16
|
+
const toolNames = group.tools;
|
|
17
|
+
const all = this.getAllTools();
|
|
18
|
+
if (!toolNames) {
|
|
19
|
+
return all;
|
|
20
|
+
}
|
|
21
|
+
return toolNames.filter(name => all.some(tool => tool.name === name)).map(name => all.find(tool => tool.name === name));
|
|
22
|
+
}
|
|
23
|
+
throw new Error(`Tool group ${groupName} not found`);
|
|
24
|
+
}
|
|
25
|
+
getNonDefaultGroupInfo() {
|
|
26
|
+
return this.groups
|
|
27
|
+
.filter(group => !group.loadByDefault)
|
|
28
|
+
.reduce((acc, group) => {
|
|
29
|
+
acc[group.name] = group.description;
|
|
30
|
+
return acc;
|
|
31
|
+
}, {});
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
exports.AbstractGroup = AbstractGroup;
|
|
35
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/tools/index.ts"],"names":[],"mappings":";;;AASA,MAAsB,aAAa;IAG/B,YAAY,MAAmB;QAC3B,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;IACzB,CAAC;IAID,eAAe;QACX,OAAO,IAAI,CAAC,WAAW,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE;YACpC,OAAO,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,KAAK,CAAC,aAAa,IAAI,CAAC,CAAC,KAAK,CAAC,KAAK,IAAI,KAAK,CAAC,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAC/G,CAAC,CAAC,CAAC;IACP,CAAC;IAED,iBAAiB,CAAC,SAAiB;QAC/B,MAAM,KAAK,GAAG,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC;QAC1D,IAAI,KAAK,EAAE,CAAC;YACR,MAAM,SAAS,GAAG,KAAK,CAAC,KAAK,CAAC;YAC9B,MAAM,GAAG,GAAG,IAAI,CAAC,WAAW,EAAE,CAAC;YAC/B,IAAI,CAAC,SAAS,EAAE,CAAC;gBACb,OAAO,GAAG,CAAC;YACf,CAAC;YAED,OAAO,SAAS,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,IAAI,KAAK,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,IAAI,KAAK,IAAI,CAAE,CAAC,CAAC;QAC7H,CAAC;QAED,MAAM,IAAI,KAAK,CAAC,cAAc,SAAS,YAAY,CAAC,CAAC;IACzD,CAAC;IAED,sBAAsB;QAClB,OAAO,IAAI,CAAC,MAAM;aACb,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,KAAK,CAAC,aAAa,CAAC;aACrC,MAAM,CAAC,CAAC,GAAG,EAAE,KAAK,EAAE,EAAE;YACnB,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,KAAK,CAAC,WAAW,CAAC;YACpC,OAAO,GAAG,CAAC;QACf,CAAC,EAAE,EAA4B,CAAC,CAAC;IACzC,CAAC;CACJ;AAtCD,sCAsCC"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MCP (Model Context Protocol) Client for Playwright integration
|
|
3
|
+
* Integrates with https://github.com/microsoft/playwright-mcp
|
|
4
|
+
*/
|
|
5
|
+
import { DynamicStructuredTool } from 'langchain';
|
|
6
|
+
import { AbstractGroup } from '.';
|
|
7
|
+
import { PlaywrightBackendAdapter } from 'src/agents/tools/playwright-backend-adapter';
|
|
8
|
+
export interface PlaywrightMCPOpts {
|
|
9
|
+
language: string;
|
|
10
|
+
headless?: boolean;
|
|
11
|
+
}
|
|
12
|
+
export declare class PlaywrightGroup extends AbstractGroup {
|
|
13
|
+
private allTools;
|
|
14
|
+
private adapter;
|
|
15
|
+
constructor(adapter: PlaywrightBackendAdapter);
|
|
16
|
+
callTool(toolName: string, args: any): Promise<any>;
|
|
17
|
+
getAllTools(): DynamicStructuredTool[];
|
|
18
|
+
}
|
|
19
|
+
//# sourceMappingURL=playwright-groups.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"playwright-groups.d.ts","sourceRoot":"","sources":["../../src/tools/playwright-groups.ts"],"names":[],"mappings":"AACA;;;GAGG;AACH,OAAO,EAAE,qBAAqB,EAAE,MAAM,WAAW,CAAC;AAClD,OAAO,EAAE,aAAa,EAAE,MAAM,GAAG,CAAC;AAClC,OAAO,EAAE,wBAAwB,EAAE,MAAM,6CAA6C,CAAC;AACvF,MAAM,WAAW,iBAAiB;IAChC,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAED,qBAAa,eAAgB,SAAQ,aAAa;IAChD,OAAO,CAAC,QAAQ,CAA0B;IAC1C,OAAO,CAAC,OAAO,CAA2B;gBAE9B,OAAO,EAAE,wBAAwB;IAqCvC,QAAQ,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC;IAIzD,WAAW,IAAI,qBAAqB,EAAE;CAGvC"}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.PlaywrightGroup = void 0;
|
|
4
|
+
const _1 = require(".");
|
|
5
|
+
class PlaywrightGroup extends _1.AbstractGroup {
|
|
6
|
+
constructor(adapter) {
|
|
7
|
+
super([{
|
|
8
|
+
name: 'playwright_basic',
|
|
9
|
+
description: 'Basic Playwright tools for browser interactions',
|
|
10
|
+
tools: ['browser_navigate', 'browser_click', 'browser_fill_form', 'browser_run_code', 'browser_select_option', 'browser_snapshot', 'browser_type', 'browser_wait_for'],
|
|
11
|
+
loadByDefault: true,
|
|
12
|
+
},
|
|
13
|
+
{
|
|
14
|
+
name: 'playwright_browser',
|
|
15
|
+
description: `Playwright tools for tab management, including: list, create, close, select a tab or page`,
|
|
16
|
+
tools: ['browser_tabs', 'browser_close'],
|
|
17
|
+
loadByDefault: false,
|
|
18
|
+
},
|
|
19
|
+
{
|
|
20
|
+
name: 'playwright_keyboard',
|
|
21
|
+
description: `Playwright tools for keyboard input action, including:
|
|
22
|
+
1. Press a key or keys on the keyboard
|
|
23
|
+
2. Press a key down or key up on the keyboard`,
|
|
24
|
+
tools: ['browser_press_key', 'browser_press_sequentially', 'browser_keydown', 'browser_keyup'],
|
|
25
|
+
loadByDefault: false,
|
|
26
|
+
},
|
|
27
|
+
{
|
|
28
|
+
name: 'playwright_other',
|
|
29
|
+
description: `Other Playwright tools for browser interactions, including:
|
|
30
|
+
1. Hover over element on page
|
|
31
|
+
2. Perform drag and drop between two elements
|
|
32
|
+
3. Upload one or multiple files
|
|
33
|
+
4. Handle a dialog
|
|
34
|
+
5. Check or uncheck a checkbox or radio button`,
|
|
35
|
+
tools: ['browser_hover', 'browser_drag', 'browser_file_upload', 'browser_handle_dialog', 'browser_check', 'browser_unscheck'],
|
|
36
|
+
loadByDefault: false,
|
|
37
|
+
}
|
|
38
|
+
]);
|
|
39
|
+
this.adapter = adapter;
|
|
40
|
+
this.allTools = this.adapter.getTools();
|
|
41
|
+
}
|
|
42
|
+
async callTool(toolName, args) {
|
|
43
|
+
return this.adapter.callTool(toolName, args);
|
|
44
|
+
}
|
|
45
|
+
getAllTools() {
|
|
46
|
+
return this.allTools;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
exports.PlaywrightGroup = PlaywrightGroup;
|
|
50
|
+
//# sourceMappingURL=playwright-groups.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"playwright-groups.js","sourceRoot":"","sources":["../../src/tools/playwright-groups.ts"],"names":[],"mappings":";;;AAMA,wBAAkC;AAOlC,MAAa,eAAgB,SAAQ,gBAAa;IAIhD,YAAY,OAAiC;QAC3C,KAAK,CAAC,CAAC;gBACL,IAAI,EAAE,kBAAkB;gBACxB,WAAW,EAAE,iDAAiD;gBAC9D,KAAK,EAAE,CAAC,kBAAkB,EAAE,eAAe,EAAE,mBAAmB,EAAE,kBAAkB,EAAE,uBAAuB,EAAE,kBAAkB,EAAE,cAAc,EAAE,kBAAkB,CAAC;gBACtK,aAAa,EAAE,IAAI;aACpB;YACD;gBACE,IAAI,EAAE,oBAAoB;gBAC1B,WAAW,EAAE,2FAA2F;gBACxG,KAAK,EAAE,CAAC,cAAc,EAAE,eAAe,CAAC;gBACxC,aAAa,EAAE,KAAK;aACrB;YACD;gBACE,IAAI,EAAE,qBAAqB;gBAC3B,WAAW,EAAE;;oDAEiC;gBAC9C,KAAK,EAAE,CAAC,mBAAmB,EAAE,4BAA4B,EAAE,iBAAiB,EAAE,eAAe,CAAC;gBAC9F,aAAa,EAAE,KAAK;aACrB;YACD;gBACE,IAAI,EAAE,kBAAkB;gBACxB,WAAW,EAAE;;;;;qDAKkC;gBAC/C,KAAK,EAAE,CAAC,eAAe,EAAE,cAAc,EAAE,qBAAqB,EAAE,uBAAuB,EAAE,eAAe,EAAE,kBAAkB,CAAC;gBAC7H,aAAa,EAAE,KAAK;aACrB;SACA,CAAC,CAAC;QACH,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;QACvB,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC,OAAO,CAAC,QAAQ,EAAE,CAAC;IAC1C,CAAC;IAED,KAAK,CAAC,QAAQ,CAAC,QAAgB,EAAE,IAAS;QACxC,OAAO,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;IAC/C,CAAC;IAED,WAAW;QACT,OAAO,IAAI,CAAC,QAAQ,CAAA;IACtB,CAAC;CACF;AAhDD,0CAgDC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"external.d.ts","sourceRoot":"","sources":["../../src/types/external.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,YAAY,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"external.js","sourceRoot":"","sources":["../../src/types/external.ts"],"names":[],"mappings":";AAAA;;;GAGG"}
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ai-heal Core Type Definitions (MVP)
|
|
3
|
+
* Maintain simplicity, include only necessary types
|
|
4
|
+
*/
|
|
5
|
+
export interface RunnerConfig {
|
|
6
|
+
/** Test Case ID */
|
|
7
|
+
testCaseId: string;
|
|
8
|
+
/** Project ID */
|
|
9
|
+
projectId: string;
|
|
10
|
+
}
|
|
11
|
+
export interface RunStepOptions {
|
|
12
|
+
/** Step description for AI to understand */
|
|
13
|
+
description: string;
|
|
14
|
+
}
|
|
15
|
+
export interface ReActStep {
|
|
16
|
+
/** Step number */
|
|
17
|
+
stepNumber: number;
|
|
18
|
+
/** Step type */
|
|
19
|
+
stepType: 'thought' | 'action' | 'observation' | 'reflection';
|
|
20
|
+
/** Timestamp */
|
|
21
|
+
timestamp: number;
|
|
22
|
+
/** LLM thought process (thought step) */
|
|
23
|
+
thought?: string;
|
|
24
|
+
/** Tool call information (action step) */
|
|
25
|
+
toolCall?: {
|
|
26
|
+
name: string;
|
|
27
|
+
input: any;
|
|
28
|
+
};
|
|
29
|
+
/** Tool execution result (observation step) */
|
|
30
|
+
toolResult?: {
|
|
31
|
+
output: string;
|
|
32
|
+
success: boolean;
|
|
33
|
+
duration?: number;
|
|
34
|
+
};
|
|
35
|
+
/** Reflection content (reflection step) */
|
|
36
|
+
reflection?: string;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Context information for a single self-healing process
|
|
40
|
+
*/
|
|
41
|
+
export interface HealContext {
|
|
42
|
+
/** Step description */
|
|
43
|
+
stepDescription: string;
|
|
44
|
+
/** original error */
|
|
45
|
+
error?: string;
|
|
46
|
+
/** Stack trace */
|
|
47
|
+
stackTrace?: string;
|
|
48
|
+
/** Original code */
|
|
49
|
+
originalCode: string;
|
|
50
|
+
/** Whether successful */
|
|
51
|
+
success: boolean;
|
|
52
|
+
/** Total steps executed by Agent */
|
|
53
|
+
agentSteps?: number;
|
|
54
|
+
healError?: string;
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Code execution result
|
|
58
|
+
*/
|
|
59
|
+
export interface ExecutionResult {
|
|
60
|
+
/** Whether successful */
|
|
61
|
+
success: boolean;
|
|
62
|
+
/** Return value */
|
|
63
|
+
returnValue: any;
|
|
64
|
+
/** Local variables */
|
|
65
|
+
locals: Record<string, any>;
|
|
66
|
+
/** Error message */
|
|
67
|
+
error?: Error;
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Self-healing summary information
|
|
71
|
+
*/
|
|
72
|
+
export interface HealSummary {
|
|
73
|
+
/** Total number of steps */
|
|
74
|
+
totalSteps: number;
|
|
75
|
+
/** Number of successfully healed steps */
|
|
76
|
+
healedSteps: number;
|
|
77
|
+
/** Fixed script */
|
|
78
|
+
modifiedScript?: string;
|
|
79
|
+
/** List of self-healing details */
|
|
80
|
+
healingDetails: HealingDetail[];
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Single self-healing detail
|
|
84
|
+
*/
|
|
85
|
+
export interface HealingDetail {
|
|
86
|
+
/** Step description */
|
|
87
|
+
step: string;
|
|
88
|
+
/** Error message */
|
|
89
|
+
error: string;
|
|
90
|
+
/** Recovery time */
|
|
91
|
+
recoveryTime: number;
|
|
92
|
+
/** Number of LLM interactions */
|
|
93
|
+
llmInteractions: number;
|
|
94
|
+
}
|
|
95
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/types/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAIH,MAAM,WAAW,YAAY;IAC3B,mBAAmB;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,iBAAiB;IACjB,SAAS,EAAE,MAAM,CAAC;CACnB;AAMD,MAAM,WAAW,cAAc;IAC7B,4CAA4C;IAC5C,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,SAAS;IACxB,kBAAkB;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,gBAAgB;IAChB,QAAQ,EAAE,SAAS,GAAG,QAAQ,GAAG,aAAa,GAAG,YAAY,CAAC;IAC9D,gBAAgB;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,yCAAyC;IACzC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,0CAA0C;IAC1C,QAAQ,CAAC,EAAE;QACT,IAAI,EAAE,MAAM,CAAC;QAEb,KAAK,EAAE,GAAG,CAAC;KACZ,CAAC;IACF,+CAA+C;IAC/C,UAAU,CAAC,EAAE;QACX,MAAM,EAAE,MAAM,CAAC;QACf,OAAO,EAAE,OAAO,CAAC;QACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;KACnB,CAAC;IACF,2CAA2C;IAC3C,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED;;GAEG;AACH,MAAM,WAAW,WAAW;IAC1B,uBAAuB;IACvB,eAAe,EAAE,MAAM,CAAC;IACxB,qBAAqB;IACrB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,kBAAkB;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,oBAAoB;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,yBAAyB;IACzB,OAAO,EAAE,OAAO,CAAC;IACjB,oCAAoC;IACpC,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAMD;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,yBAAyB;IACzB,OAAO,EAAE,OAAO,CAAC;IACjB,mBAAmB;IAEnB,WAAW,EAAE,GAAG,CAAC;IACjB,sBAAsB;IAEtB,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAC5B,oBAAoB;IACpB,KAAK,CAAC,EAAE,KAAK,CAAC;CACf;AAMD;;GAEG;AACH,MAAM,WAAW,WAAW;IAC1B,4BAA4B;IAC5B,UAAU,EAAE,MAAM,CAAC;IACnB,0CAA0C;IAC1C,WAAW,EAAE,MAAM,CAAC;IACpB,mBAAmB;IACnB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,mCAAmC;IACnC,cAAc,EAAE,aAAa,EAAE,CAAC;CACjC;AAED;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B,uBAAuB;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,oBAAoB;IACpB,KAAK,EAAE,MAAM,CAAC;IACd,oBAAoB;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,iCAAiC;IACjC,eAAe,EAAE,MAAM,CAAC;CACzB"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/types/index.ts"],"names":[],"mappings":";AAAA;;;GAGG"}
|
package/package.json
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@cotestdev/ai-runner-fake",
|
|
3
|
+
"version": "0.0.1",
|
|
4
|
+
"description": "AI-powered self-healing SDK for Playwright test scripts",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"types": "dist/index.d.ts",
|
|
7
|
+
"scripts": {
|
|
8
|
+
"build": "tsc",
|
|
9
|
+
"watch": "tsc --watch",
|
|
10
|
+
"test": "playwright test",
|
|
11
|
+
"test:poc": "playwright test src/poc/",
|
|
12
|
+
"test:ui": "playwright test --ui",
|
|
13
|
+
"test:debug": "playwright test --debug",
|
|
14
|
+
"example:test-backend-adapter": "ts-node src/examples/test-backend-adapter.ts",
|
|
15
|
+
"lint": "eslint src --ext .ts",
|
|
16
|
+
"prepublishOnly": "npm run build"
|
|
17
|
+
},
|
|
18
|
+
"keywords": [
|
|
19
|
+
"playwright",
|
|
20
|
+
"self-healing",
|
|
21
|
+
"ai",
|
|
22
|
+
"test-automation",
|
|
23
|
+
"auto-recovery"
|
|
24
|
+
],
|
|
25
|
+
"author": "AI Test Team",
|
|
26
|
+
"license": "MIT",
|
|
27
|
+
"devDependencies": {
|
|
28
|
+
"@playwright/test": "^1.58.0",
|
|
29
|
+
"@types/node": "^25.0.10",
|
|
30
|
+
"ts-node": "^10.9.2",
|
|
31
|
+
"typescript": "^5.0.0"
|
|
32
|
+
}
|
|
33
|
+
}
|
package/src/index.ts
ADDED
package/src/runner.ts
ADDED
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
import { join } from 'path';
|
|
2
|
+
import { homedir } from 'os';
|
|
3
|
+
import { readFileSync } from 'fs';
|
|
4
|
+
import { BrowserContext, Page } from '@playwright/test';
|
|
5
|
+
import { expect } from '@playwright/test';
|
|
6
|
+
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
7
|
+
|
|
8
|
+
interface State {
|
|
9
|
+
context: BrowserContext;
|
|
10
|
+
page: Page;
|
|
11
|
+
variables: Map<string, any>;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export class Runner {
|
|
15
|
+
private abortController: AbortController;
|
|
16
|
+
private variables: Map<string, any> = new Map<string, any>();
|
|
17
|
+
private projectId: string;
|
|
18
|
+
private testCaseId: string;
|
|
19
|
+
private state?: State;
|
|
20
|
+
|
|
21
|
+
private constructor(projectId: string, testCaseId: string) {
|
|
22
|
+
this.abortController = new AbortController();
|
|
23
|
+
this.projectId = projectId;
|
|
24
|
+
this.testCaseId = testCaseId;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
static NewInstance(projectId: string, testCaseId: string, canHeal: boolean = true): Runner {
|
|
28
|
+
const runner = new Runner(projectId, testCaseId);
|
|
29
|
+
return runner;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
stop() {
|
|
33
|
+
this.abortController.abort();
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
async init(page: Page, context: BrowserContext, data?: Record<string, any>): Promise<void> {
|
|
37
|
+
this.state = {
|
|
38
|
+
page: page,
|
|
39
|
+
context: context,
|
|
40
|
+
variables: this.variables,
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
async runStep(description: string, fn: () => Promise<void>) {
|
|
45
|
+
try {
|
|
46
|
+
await fn();
|
|
47
|
+
} catch (error) {
|
|
48
|
+
throw error;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
set(key: string, value: any): void {
|
|
53
|
+
this.variables.set(key, value);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
get(key: string): any {
|
|
57
|
+
return this.variables.get(key);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
has(key: string): boolean {
|
|
61
|
+
return this.variables.has(key);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
delete(key: string): boolean {
|
|
65
|
+
return this.variables.delete(key);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
clear(): void {
|
|
69
|
+
this.variables.clear();
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
keys(): string[] {
|
|
73
|
+
return Array.from(this.variables.keys());
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
getAll(): Record<string, unknown> {
|
|
77
|
+
return Object.fromEntries(this.variables);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
private loadTestScript(testCaseId: string): string {
|
|
81
|
+
const scriptPath = join(homedir(), '.test_agent', 'projects', this.projectId, 'script', `${testCaseId}.ts`);
|
|
82
|
+
return readFileSync(scriptPath, 'utf-8');
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
async reuseTest(useTestCaseId: string, description: string): Promise<Map<string, unknown>> {
|
|
86
|
+
const scriptContent = this.loadTestScript(useTestCaseId);
|
|
87
|
+
if (!scriptContent) {
|
|
88
|
+
throw new Error(`Reusable test script not found: ${useTestCaseId}`);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
const reuseRunner = Runner.NewInstance(this.projectId, useTestCaseId);
|
|
92
|
+
await reuseRunner.init(this.state!.page, this.state!.context);
|
|
93
|
+
|
|
94
|
+
console.log(`Starting to execute reusable test case: ${description}`);
|
|
95
|
+
|
|
96
|
+
try {
|
|
97
|
+
const executeScript = new Function('runner', 'page', 'context', 'expect', `
|
|
98
|
+
return (async () => {
|
|
99
|
+
${scriptContent}
|
|
100
|
+
})();
|
|
101
|
+
`);
|
|
102
|
+
|
|
103
|
+
await executeScript(reuseRunner, this.state!.page, this.state!.context, expect);
|
|
104
|
+
|
|
105
|
+
console.log(`Reusable test case executed successfully`);
|
|
106
|
+
|
|
107
|
+
return reuseRunner.state?.variables || new Map<string, unknown>();
|
|
108
|
+
} catch (error) {
|
|
109
|
+
throw new Error(`reuseTest execution failed, error: ${error instanceof Error ? error.message : String(error)}`);
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
}
|
package/tsconfig.json
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"target": "ES2020",
|
|
4
|
+
"module": "commonjs",
|
|
5
|
+
"lib": ["ES2020"],
|
|
6
|
+
"declaration": true,
|
|
7
|
+
"declarationMap": true,
|
|
8
|
+
"sourceMap": true,
|
|
9
|
+
"outDir": "./dist",
|
|
10
|
+
"strict": true,
|
|
11
|
+
"esModuleInterop": true,
|
|
12
|
+
"skipLibCheck": true,
|
|
13
|
+
"forceConsistentCasingInFileNames": true,
|
|
14
|
+
"resolveJsonModule": true,
|
|
15
|
+
"moduleResolution": "node",
|
|
16
|
+
"allowSyntheticDefaultImports": true,
|
|
17
|
+
"types": ["node", "@playwright/test"],
|
|
18
|
+
"baseUrl": ".",
|
|
19
|
+
"paths": {
|
|
20
|
+
}
|
|
21
|
+
},
|
|
22
|
+
"include": ["src/**/*"],
|
|
23
|
+
"exclude": ["node_modules", "dist", "tests"]
|
|
24
|
+
}
|