@loadmill/droid-cua 2.10.1-rc.9 → 2.12.0
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 +51 -2
- package/build/index.js +133 -16
- package/build/src/browser/playwright/connection.js +11 -4
- package/build/src/browser/playwright/installed-browser.js +36 -26
- package/build/src/cli/headless-instructions.js +38 -2
- package/build/src/cli/headless-target.js +124 -1
- package/build/src/cli/lambdatest-app-upload.js +66 -0
- package/build/src/commands/help.js +7 -0
- package/build/src/core/context-optimization.js +1 -1
- package/build/src/core/session.js +1 -0
- package/build/src/core/tool-handlers/assert.js +114 -27
- package/build/src/core/tool-handlers/loadmill.js +8 -1
- package/build/src/device/android/actions.js +11 -28
- package/build/src/device/assertions.js +1 -5
- package/build/src/device/cloud/actions.js +33 -49
- package/build/src/device/cloud/connection.js +7 -5
- package/build/src/device/cloud/lambdatest/adapter.js +51 -4
- package/build/src/device/ios/actions.js +22 -33
- package/build/src/device/loadmill.js +47 -6
- package/build/src/device/mobile-keypress.js +117 -0
- package/build/src/device/openai.js +6 -2
- package/build/src/integrations/loadmill/client.js +11 -0
- package/build/src/integrations/loadmill/executor.js +121 -2
- package/build/src/integrations/loadmill/index.js +1 -1
- package/build/src/integrations/loadmill/parameters.js +127 -0
- package/build/src/modes/execution-mode.js +7 -1
- package/build/src/prompts/execution.js +25 -8
- package/build/src/utils/cua-debug-tracer.js +24 -2
- package/package.json +1 -1
|
@@ -40,7 +40,9 @@ CRITICAL RULES:
|
|
|
40
40
|
Your process:
|
|
41
41
|
1. Read the instruction
|
|
42
42
|
2. Choose the right tool when the instruction is really a higher-level capability:
|
|
43
|
-
- Use \`assert\` for assertions and verification intent, including legacy \`assert:\` lines and natural language like verify, validate, ensure, or confirm
|
|
43
|
+
- Use \`assert\` for assertions and verification intent, including legacy \`assert:\` lines and natural language like verify, validate, ensure, or confirm. When calling \`assert\`, include a \`context\` value with the prior details needed to interpret the condition. If no prior context is needed, say that explicitly.
|
|
44
|
+
- Before calling \`assert\`, make sure the current screen contains the evidence needed to validate the condition. If needed, perform only minimal preparation first, such as taking a screenshot, waiting briefly, closing the keyboard, scrolling within the relevant view, or opening the relevant menu.
|
|
45
|
+
- Once you call \`assert\`, validation is read-only. The assertion tool will not click, type, wait, scroll, request screenshots, or change the device state.
|
|
44
46
|
- Use \`navigate\` for direct browser navigation instead of trying to manipulate the address bar
|
|
45
47
|
- Use \`loadmill\` only when the instruction explicitly references the word "loadmill"
|
|
46
48
|
3. Execute the required actions
|
|
@@ -88,24 +90,39 @@ ${transitionLine}${transcriptSection}
|
|
|
88
90
|
|
|
89
91
|
[IMPORTANT: Continue the current test from this new page. Use the prior context above, but rely on the latest screenshot for the current UI.]`;
|
|
90
92
|
}
|
|
91
|
-
export function buildAssertionSystemPrompt(baseSystemPrompt, assertionPrompt) {
|
|
93
|
+
export function buildAssertionSystemPrompt(baseSystemPrompt, assertionPrompt, { assertionContext = "", transcript = "", } = {}) {
|
|
94
|
+
const normalizedAssertionContext = typeof assertionContext === "string" && assertionContext.trim()
|
|
95
|
+
? assertionContext.trim()
|
|
96
|
+
: "No additional assertion context was provided.";
|
|
97
|
+
const normalizedTranscript = typeof transcript === "string" && transcript.trim()
|
|
98
|
+
? transcript.trim()
|
|
99
|
+
: "No prior session transcript was provided.";
|
|
92
100
|
return `${baseSystemPrompt}
|
|
93
101
|
|
|
94
102
|
ASSERTION MODE:
|
|
95
|
-
You are
|
|
103
|
+
You are validating one assertion as part of an automated test run.
|
|
104
|
+
This is a read-only check.
|
|
96
105
|
|
|
97
106
|
Your task:
|
|
98
|
-
1.
|
|
99
|
-
2.
|
|
100
|
-
3.
|
|
107
|
+
1. Use only the provided screenshot, assertion context, app context already included above, and session transcript.
|
|
108
|
+
2. Do not ask for more screenshots, do not click, do not type, do not wait, and do not propose actions.
|
|
109
|
+
3. Determine if the assertion is TRUE or FALSE based on the current state and provided context.
|
|
110
|
+
4. If the evidence is insufficient, treat the assertion as false.
|
|
111
|
+
5. You MUST respond with a clear verdict in this exact format:
|
|
101
112
|
- If the assertion is true, include the text: "ASSERTION RESULT: PASS"
|
|
102
113
|
- If the assertion is false or cannot be confidently validated, include: "ASSERTION RESULT: FAIL"
|
|
103
|
-
|
|
114
|
+
6. After the verdict, provide a brief explanation (1-2 sentences) of why it passed or failed.
|
|
104
115
|
|
|
105
116
|
The assertion to validate is: "${assertionPrompt}"
|
|
106
117
|
|
|
118
|
+
ASSERTION CONTEXT:
|
|
119
|
+
${normalizedAssertionContext}
|
|
120
|
+
|
|
121
|
+
SESSION TRANSCRIPT SO FAR:
|
|
122
|
+
${normalizedTranscript}
|
|
123
|
+
|
|
107
124
|
Remember:
|
|
108
125
|
- If you cannot confidently validate the assertion, treat it as FAIL.
|
|
109
126
|
- You must include either "ASSERTION RESULT: PASS" or "ASSERTION RESULT: FAIL" in your response.
|
|
110
|
-
-
|
|
127
|
+
- This is read-only evaluation. Return the verdict and reason only.`;
|
|
111
128
|
}
|
|
@@ -176,6 +176,17 @@ function extractResponseTexts(response) {
|
|
|
176
176
|
})
|
|
177
177
|
.filter(Boolean);
|
|
178
178
|
}
|
|
179
|
+
function summarizeContextManagement(contextManagement) {
|
|
180
|
+
const entries = Array.isArray(contextManagement) ? contextManagement : [];
|
|
181
|
+
const compaction = entries.find((entry) => entry?.type === "compaction") || null;
|
|
182
|
+
return {
|
|
183
|
+
enabled: Boolean(compaction),
|
|
184
|
+
compactThreshold: typeof compaction?.compact_threshold === "number"
|
|
185
|
+
? compaction.compact_threshold
|
|
186
|
+
: null,
|
|
187
|
+
entries: entries.length > 0 ? entries : [],
|
|
188
|
+
};
|
|
189
|
+
}
|
|
179
190
|
export class CuaDebugTracer {
|
|
180
191
|
constructor(logger) {
|
|
181
192
|
this.logger = logger;
|
|
@@ -221,12 +232,14 @@ export class CuaDebugTracer {
|
|
|
221
232
|
const missingCallIds = inputCallIds.filter((callId) => !lastResponseCallIds.includes(callId));
|
|
222
233
|
const previousResponseIdMatchesLastResponseId = !previousResponseId || !lastResponseMeta?.id ? null : previousResponseId === lastResponseMeta.id;
|
|
223
234
|
const allInputCallIdsFoundInLastResponse = inputCallIds.length === 0 ? true : missingCallIds.length === 0;
|
|
235
|
+
const contextManagement = summarizeContextManagement(requestParams.context_management);
|
|
224
236
|
const requestConfig = {
|
|
225
237
|
model: requestParams.model,
|
|
226
238
|
tools: requestParams.tools,
|
|
227
239
|
truncation: requestParams.truncation,
|
|
228
240
|
reasoning: requestParams.reasoning,
|
|
229
|
-
store: requestParams.store
|
|
241
|
+
store: requestParams.store,
|
|
242
|
+
context_management: requestParams.context_management || null
|
|
230
243
|
};
|
|
231
244
|
const requestConfigHash = crypto.createHash("sha256").update(JSON.stringify(requestConfig)).digest("hex");
|
|
232
245
|
emitDesktopDebug("cua.request", scope, ids, {
|
|
@@ -249,6 +262,7 @@ export class CuaDebugTracer {
|
|
|
249
262
|
acknowledgedSent: acknowledgedSafetyChecksSent,
|
|
250
263
|
acknowledgedSentCount: acknowledgedSafetyChecksSent.length
|
|
251
264
|
},
|
|
265
|
+
contextManagement,
|
|
252
266
|
chain: {
|
|
253
267
|
lastResponseId: lastResponseMeta?.id ?? null,
|
|
254
268
|
lastResponseOutputTypes: lastResponseMeta?.outputTypes ?? [],
|
|
@@ -269,6 +283,7 @@ export class CuaDebugTracer {
|
|
|
269
283
|
lastResponseComputerCallIds: lastResponseCallIds,
|
|
270
284
|
allInputCallIdsFoundInLastResponse,
|
|
271
285
|
missingCallIds,
|
|
286
|
+
contextManagement,
|
|
272
287
|
requestConfigHash
|
|
273
288
|
});
|
|
274
289
|
return {
|
|
@@ -278,6 +293,7 @@ export class CuaDebugTracer {
|
|
|
278
293
|
localRequestId,
|
|
279
294
|
requestLog,
|
|
280
295
|
requestConfigHash,
|
|
296
|
+
contextManagement,
|
|
281
297
|
previousPendingSafetyChecks,
|
|
282
298
|
acknowledgedSafetyChecksSent,
|
|
283
299
|
previousResponseIdMatchesLastResponseId,
|
|
@@ -322,7 +338,8 @@ export class CuaDebugTracer {
|
|
|
322
338
|
output_length: totalItems,
|
|
323
339
|
output_types: outputTypes,
|
|
324
340
|
tool_calls: toolCalls.length > 0 ? toolCalls : "none",
|
|
325
|
-
pending_safety_checks: safetyChecks.length > 0 ? safetyChecks : "none"
|
|
341
|
+
pending_safety_checks: safetyChecks.length > 0 ? safetyChecks : "none",
|
|
342
|
+
usage: response.usage || null
|
|
326
343
|
});
|
|
327
344
|
if (accountedItems < totalItems) {
|
|
328
345
|
this.logger.debug("UNACCOUNTED OUTPUT ITEMS - Full output array:", response.output);
|
|
@@ -334,6 +351,9 @@ export class CuaDebugTracer {
|
|
|
334
351
|
outputTypes,
|
|
335
352
|
output: summarizeResponseOutput(response),
|
|
336
353
|
texts: extractResponseTexts(response),
|
|
354
|
+
usage: response.usage || null,
|
|
355
|
+
contextManagement: trace.contextManagement,
|
|
356
|
+
requestConfigHash: trace.requestConfigHash,
|
|
337
357
|
safetyChecks: {
|
|
338
358
|
pending: safetyChecks,
|
|
339
359
|
pendingCount: safetyChecks.length
|
|
@@ -351,6 +371,7 @@ export class CuaDebugTracer {
|
|
|
351
371
|
localRequestId: trace.localRequestId,
|
|
352
372
|
request: trace.requestLog,
|
|
353
373
|
requestConfigHash: trace.requestConfigHash,
|
|
374
|
+
contextManagement: trace.contextManagement,
|
|
354
375
|
chain: {
|
|
355
376
|
lastResponseId: trace.lastResponseMeta?.id ?? null,
|
|
356
377
|
lastResponseOutputTypes: trace.lastResponseMeta?.outputTypes ?? [],
|
|
@@ -394,6 +415,7 @@ export class CuaDebugTracer {
|
|
|
394
415
|
missingCallIds: trace.missingCallIds
|
|
395
416
|
},
|
|
396
417
|
requestConfigHash: trace.requestConfigHash,
|
|
418
|
+
contextManagement: trace.contextManagement,
|
|
397
419
|
details: responseError,
|
|
398
420
|
safetyChecks: {
|
|
399
421
|
previousPending: trace.previousPendingSafetyChecks,
|