@midscene/core 1.9.8 → 1.10.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/dist/es/agent/agent.mjs +26 -94
- package/dist/es/agent/agent.mjs.map +1 -1
- package/dist/es/agent/prompt-context.mjs +14 -0
- package/dist/es/agent/prompt-context.mjs.map +1 -0
- package/dist/es/agent/run-gherkin-scenario.mjs +114 -0
- package/dist/es/agent/run-gherkin-scenario.mjs.map +1 -0
- package/dist/es/agent/task-builder.mjs +4 -4
- package/dist/es/agent/task-builder.mjs.map +1 -1
- package/dist/es/agent/tasks.mjs +4 -8
- package/dist/es/agent/tasks.mjs.map +1 -1
- package/dist/es/agent/utils.mjs +15 -3
- package/dist/es/agent/utils.mjs.map +1 -1
- package/dist/es/ai-model/index.mjs +1 -2
- package/dist/es/ai-model/inspect.mjs +77 -50
- package/dist/es/ai-model/inspect.mjs.map +1 -1
- package/dist/es/ai-model/llm-planning.mjs +10 -26
- package/dist/es/ai-model/llm-planning.mjs.map +1 -1
- package/dist/es/ai-model/model-adapter/chat-completion.mjs +46 -0
- package/dist/es/ai-model/model-adapter/chat-completion.mjs.map +1 -0
- package/dist/es/ai-model/model-adapter/index.mjs +2 -0
- package/dist/es/ai-model/model-adapter/locate.mjs +33 -0
- package/dist/es/ai-model/model-adapter/locate.mjs.map +1 -0
- package/dist/es/ai-model/model-adapter/planning.mjs +44 -0
- package/dist/es/ai-model/model-adapter/planning.mjs.map +1 -0
- package/dist/es/ai-model/model-adapter/resolve.mjs +43 -0
- package/dist/es/ai-model/model-adapter/resolve.mjs.map +1 -0
- package/dist/es/ai-model/model-adapter/types.mjs +0 -0
- package/dist/es/ai-model/models/auto-glm/actions.mjs +19 -31
- package/dist/es/ai-model/models/auto-glm/actions.mjs.map +1 -1
- package/dist/es/ai-model/models/auto-glm/adapter.mjs +8 -16
- package/dist/es/ai-model/models/auto-glm/adapter.mjs.map +1 -1
- package/dist/es/ai-model/models/auto-glm/locate.mjs +6 -108
- package/dist/es/ai-model/models/auto-glm/locate.mjs.map +1 -1
- package/dist/es/ai-model/models/auto-glm/parser.mjs +19 -41
- package/dist/es/ai-model/models/auto-glm/parser.mjs.map +1 -1
- package/dist/es/ai-model/models/auto-glm/planning.mjs +27 -70
- package/dist/es/ai-model/models/auto-glm/planning.mjs.map +1 -1
- package/dist/es/ai-model/models/default.mjs.map +1 -1
- package/dist/es/ai-model/models/doubao.mjs.map +1 -1
- package/dist/es/ai-model/models/gemini.mjs +1 -1
- package/dist/es/ai-model/models/gemini.mjs.map +1 -1
- package/dist/es/ai-model/models/glm.mjs.map +1 -1
- package/dist/es/ai-model/models/gpt.mjs.map +1 -1
- package/dist/es/ai-model/models/kimi.mjs.map +1 -1
- package/dist/es/ai-model/models/mimo.mjs.map +1 -1
- package/dist/es/ai-model/models/qwen.mjs.map +1 -1
- package/dist/es/ai-model/models/registry.mjs +1 -1
- package/dist/es/ai-model/models/registry.mjs.map +1 -1
- package/dist/es/ai-model/models/ui-tars/actions.mjs +147 -0
- package/dist/es/ai-model/models/ui-tars/actions.mjs.map +1 -0
- package/dist/es/ai-model/models/ui-tars/adapter.mjs +2 -2
- package/dist/es/ai-model/models/ui-tars/adapter.mjs.map +1 -1
- package/dist/es/ai-model/models/ui-tars/parser.mjs +40 -0
- package/dist/es/ai-model/models/ui-tars/parser.mjs.map +1 -0
- package/dist/es/ai-model/models/ui-tars/planning.mjs +19 -230
- package/dist/es/ai-model/models/ui-tars/planning.mjs.map +1 -1
- package/dist/es/ai-model/{prompt/ui-tars-planning.mjs → models/ui-tars/prompt.mjs} +1 -1
- package/dist/es/ai-model/models/ui-tars/prompt.mjs.map +1 -0
- package/dist/es/ai-model/service-caller/index.mjs +1 -3
- package/dist/es/ai-model/service-caller/index.mjs.map +1 -1
- package/dist/es/ai-model/shared/model-locate-result/coordinate-distance.mjs +10 -0
- package/dist/es/ai-model/shared/model-locate-result/coordinate-distance.mjs.map +1 -0
- package/dist/es/ai-model/shared/model-locate-result/factory.mjs +1 -3
- package/dist/es/ai-model/shared/model-locate-result/factory.mjs.map +1 -1
- package/dist/es/ai-model/shared/model-locate-result/index.mjs +3 -2
- package/dist/es/ai-model/shared/planning-action.mjs +6 -0
- package/dist/es/ai-model/shared/planning-action.mjs.map +1 -0
- package/dist/es/ai-model/workflows/inspect/planning-action-locate.mjs +95 -0
- package/dist/es/ai-model/workflows/inspect/planning-action-locate.mjs.map +1 -0
- package/dist/es/ai-model/workflows/planning/custom-planning.mjs +126 -0
- package/dist/es/ai-model/workflows/planning/custom-planning.mjs.map +1 -0
- package/dist/es/ai-model/workflows/planning/locate-normalization.mjs +31 -0
- package/dist/es/ai-model/workflows/planning/locate-normalization.mjs.map +1 -0
- package/dist/es/common.mjs +10 -6
- package/dist/es/common.mjs.map +1 -1
- package/dist/es/element-describer.mjs +180 -0
- package/dist/es/element-describer.mjs.map +1 -0
- package/dist/es/index.mjs +2 -1
- package/dist/es/index.mjs.map +1 -1
- package/dist/es/report-generator.mjs +3 -5
- package/dist/es/report-generator.mjs.map +1 -1
- package/dist/es/service/index.mjs +3 -2
- package/dist/es/service/index.mjs.map +1 -1
- package/dist/es/skill/index.mjs +1 -1
- package/dist/es/skill/index.mjs.map +1 -1
- package/dist/es/types.mjs.map +1 -1
- package/dist/es/utils.mjs +2 -2
- package/dist/es/yaml/player.mjs +7 -0
- package/dist/es/yaml/player.mjs.map +1 -1
- package/dist/lib/agent/agent.js +25 -93
- package/dist/lib/agent/agent.js.map +1 -1
- package/dist/lib/{ai-model/models/chat-content.js → agent/prompt-context.js} +13 -13
- package/dist/lib/agent/prompt-context.js.map +1 -0
- package/dist/lib/agent/run-gherkin-scenario.js +151 -0
- package/dist/lib/agent/run-gherkin-scenario.js.map +1 -0
- package/dist/lib/agent/task-builder.js +4 -4
- package/dist/lib/agent/task-builder.js.map +1 -1
- package/dist/lib/agent/tasks.js +4 -8
- package/dist/lib/agent/tasks.js.map +1 -1
- package/dist/lib/agent/utils.js +14 -2
- package/dist/lib/agent/utils.js.map +1 -1
- package/dist/lib/ai-model/index.js +0 -10
- package/dist/lib/ai-model/inspect.js +77 -50
- package/dist/lib/ai-model/inspect.js.map +1 -1
- package/dist/lib/ai-model/llm-planning.js +9 -25
- package/dist/lib/ai-model/llm-planning.js.map +1 -1
- package/dist/lib/ai-model/model-adapter/chat-completion.js +83 -0
- package/dist/lib/ai-model/model-adapter/chat-completion.js.map +1 -0
- package/dist/lib/ai-model/model-adapter/custom-planning-types.js +20 -0
- package/dist/lib/ai-model/model-adapter/custom-planning-types.js.map +1 -0
- package/dist/lib/ai-model/model-adapter/index.js +38 -0
- package/dist/lib/ai-model/model-adapter/index.js.map +1 -0
- package/dist/lib/ai-model/model-adapter/locate.js +67 -0
- package/dist/lib/ai-model/model-adapter/locate.js.map +1 -0
- package/dist/lib/ai-model/model-adapter/planning.js +81 -0
- package/dist/lib/ai-model/model-adapter/planning.js.map +1 -0
- package/dist/lib/ai-model/model-adapter/resolve.js +77 -0
- package/dist/lib/ai-model/model-adapter/resolve.js.map +1 -0
- package/dist/lib/ai-model/model-adapter/types.js.map +1 -0
- package/dist/lib/ai-model/models/auto-glm/actions.js +19 -31
- package/dist/lib/ai-model/models/auto-glm/actions.js.map +1 -1
- package/dist/lib/ai-model/models/auto-glm/adapter.js +6 -14
- package/dist/lib/ai-model/models/auto-glm/adapter.js.map +1 -1
- package/dist/lib/ai-model/models/auto-glm/locate.js +8 -110
- package/dist/lib/ai-model/models/auto-glm/locate.js.map +1 -1
- package/dist/lib/ai-model/models/auto-glm/parser.js +24 -46
- package/dist/lib/ai-model/models/auto-glm/parser.js.map +1 -1
- package/dist/lib/ai-model/models/auto-glm/planning.js +28 -71
- package/dist/lib/ai-model/models/auto-glm/planning.js.map +1 -1
- package/dist/lib/ai-model/models/default.js.map +1 -1
- package/dist/lib/ai-model/models/doubao.js.map +1 -1
- package/dist/lib/ai-model/models/gemini.js +2 -2
- package/dist/lib/ai-model/models/gemini.js.map +1 -1
- package/dist/lib/ai-model/models/glm.js.map +1 -1
- package/dist/lib/ai-model/models/gpt.js.map +1 -1
- package/dist/lib/ai-model/models/kimi.js.map +1 -1
- package/dist/lib/ai-model/models/mimo.js.map +1 -1
- package/dist/lib/ai-model/models/qwen.js.map +1 -1
- package/dist/lib/ai-model/models/registry.js +2 -2
- package/dist/lib/ai-model/models/registry.js.map +1 -1
- package/dist/lib/ai-model/models/ui-tars/actions.js +181 -0
- package/dist/lib/ai-model/models/ui-tars/actions.js.map +1 -0
- package/dist/lib/ai-model/models/ui-tars/adapter.js +1 -1
- package/dist/lib/ai-model/models/ui-tars/adapter.js.map +1 -1
- package/dist/lib/ai-model/models/ui-tars/parser.js +74 -0
- package/dist/lib/ai-model/models/ui-tars/parser.js.map +1 -0
- package/dist/lib/ai-model/models/ui-tars/planning.js +21 -232
- package/dist/lib/ai-model/models/ui-tars/planning.js.map +1 -1
- package/dist/lib/ai-model/{prompt/ui-tars-planning.js → models/ui-tars/prompt.js} +1 -1
- package/dist/lib/ai-model/models/ui-tars/prompt.js.map +1 -0
- package/dist/lib/ai-model/service-caller/index.js +1 -3
- package/dist/lib/ai-model/service-caller/index.js.map +1 -1
- package/dist/lib/ai-model/shared/model-locate-result/coordinate-distance.js +44 -0
- package/dist/lib/ai-model/shared/model-locate-result/coordinate-distance.js.map +1 -0
- package/dist/lib/ai-model/shared/model-locate-result/factory.js +5 -4
- package/dist/lib/ai-model/shared/model-locate-result/factory.js.map +1 -1
- package/dist/lib/ai-model/shared/model-locate-result/index.js +7 -0
- package/dist/lib/ai-model/shared/planning-action.js +40 -0
- package/dist/lib/ai-model/shared/planning-action.js.map +1 -0
- package/dist/lib/ai-model/workflows/inspect/planning-action-locate.js +129 -0
- package/dist/lib/ai-model/workflows/inspect/planning-action-locate.js.map +1 -0
- package/dist/lib/ai-model/workflows/planning/custom-planning.js +163 -0
- package/dist/lib/ai-model/workflows/planning/custom-planning.js.map +1 -0
- package/dist/lib/ai-model/workflows/planning/locate-normalization.js +65 -0
- package/dist/lib/ai-model/workflows/planning/locate-normalization.js.map +1 -0
- package/dist/lib/common.js +13 -6
- package/dist/lib/common.js.map +1 -1
- package/dist/lib/element-describer.js +223 -0
- package/dist/lib/element-describer.js.map +1 -0
- package/dist/lib/index.js +14 -1
- package/dist/lib/index.js.map +1 -1
- package/dist/lib/report-generator.js +4 -6
- package/dist/lib/report-generator.js.map +1 -1
- package/dist/lib/service/index.js +3 -2
- package/dist/lib/service/index.js.map +1 -1
- package/dist/lib/skill/index.js +1 -1
- package/dist/lib/skill/index.js.map +1 -1
- package/dist/lib/types.js.map +1 -1
- package/dist/lib/utils.js +2 -2
- package/dist/lib/yaml/player.js +7 -0
- package/dist/lib/yaml/player.js.map +1 -1
- package/dist/types/agent/agent.d.ts +4 -18
- package/dist/types/agent/index.d.ts +3 -2
- package/dist/types/agent/prompt-context.d.ts +2 -0
- package/dist/types/agent/run-gherkin-scenario.d.ts +26 -0
- package/dist/types/agent/tasks.d.ts +3 -1
- package/dist/types/ai-model/index.d.ts +0 -2
- package/dist/types/ai-model/inspect.d.ts +3 -2
- package/dist/types/ai-model/model-adapter/chat-completion.d.ts +3 -0
- package/dist/types/ai-model/model-adapter/custom-planning-types.d.ts +32 -0
- package/dist/types/ai-model/model-adapter/index.d.ts +2 -0
- package/dist/types/ai-model/model-adapter/locate.d.ts +3 -0
- package/dist/types/ai-model/model-adapter/planning.d.ts +4 -0
- package/dist/types/ai-model/{models → model-adapter}/types.d.ts +39 -4
- package/dist/types/ai-model/models/auto-glm/actions.d.ts +8 -5
- package/dist/types/ai-model/models/auto-glm/adapter.d.ts +1 -1
- package/dist/types/ai-model/models/auto-glm/locate.d.ts +2 -3
- package/dist/types/ai-model/models/auto-glm/parser.d.ts +6 -10
- package/dist/types/ai-model/models/auto-glm/planning.d.ts +5 -4
- package/dist/types/ai-model/models/default.d.ts +1 -1
- package/dist/types/ai-model/models/doubao.d.ts +1 -1
- package/dist/types/ai-model/models/gemini.d.ts +1 -1
- package/dist/types/ai-model/models/glm.d.ts +1 -1
- package/dist/types/ai-model/models/gpt.d.ts +1 -1
- package/dist/types/ai-model/models/index.d.ts +1 -1
- package/dist/types/ai-model/models/kimi.d.ts +1 -1
- package/dist/types/ai-model/models/mimo.d.ts +1 -1
- package/dist/types/ai-model/models/qwen.d.ts +1 -1
- package/dist/types/ai-model/models/registry.d.ts +10 -10
- package/dist/types/ai-model/models/ui-tars/actions.d.ts +3 -0
- package/dist/types/ai-model/models/ui-tars/adapter.d.ts +1 -1
- package/dist/types/ai-model/models/ui-tars/parser.d.ts +72 -0
- package/dist/types/ai-model/models/ui-tars/planning.d.ts +3 -68
- package/dist/types/ai-model/service-caller/index.d.ts +4 -5
- package/dist/types/ai-model/shared/model-locate-result/coordinate-distance.d.ts +4 -0
- package/dist/types/ai-model/shared/model-locate-result/factory.d.ts +2 -1
- package/dist/types/ai-model/shared/model-locate-result/index.d.ts +4 -2
- package/dist/types/ai-model/shared/model-locate-result/types.d.ts +0 -1
- package/dist/types/ai-model/shared/planning-action.d.ts +20 -0
- package/dist/types/ai-model/workflows/inspect/planning-action-locate.d.ts +4 -0
- package/dist/types/ai-model/workflows/inspect/types.d.ts +21 -2
- package/dist/types/ai-model/workflows/planning/custom-planning.d.ts +7 -0
- package/dist/types/ai-model/workflows/planning/locate-normalization.d.ts +9 -0
- package/dist/types/common.d.ts +1 -0
- package/dist/types/device/index.d.ts +17 -17
- package/dist/types/element-describer.d.ts +46 -0
- package/dist/types/index.d.ts +2 -1
- package/dist/types/service/index.d.ts +3 -1
- package/dist/types/types.d.ts +5 -0
- package/dist/types/yaml.d.ts +4 -1
- package/package.json +3 -3
- package/dist/es/ai-model/models/chat-content.mjs +0 -14
- package/dist/es/ai-model/models/chat-content.mjs.map +0 -1
- package/dist/es/ai-model/models/resolved.mjs +0 -107
- package/dist/es/ai-model/models/resolved.mjs.map +0 -1
- package/dist/es/ai-model/prompt/recorder-ui-describer.mjs +0 -56
- package/dist/es/ai-model/prompt/recorder-ui-describer.mjs.map +0 -1
- package/dist/es/ai-model/prompt/ui-tars-planning.mjs.map +0 -1
- package/dist/es/recorder-ui-describer.mjs +0 -379
- package/dist/es/recorder-ui-describer.mjs.map +0 -1
- package/dist/lib/ai-model/models/chat-content.js.map +0 -1
- package/dist/lib/ai-model/models/resolved.js +0 -141
- package/dist/lib/ai-model/models/resolved.js.map +0 -1
- package/dist/lib/ai-model/models/types.js.map +0 -1
- package/dist/lib/ai-model/prompt/recorder-ui-describer.js +0 -90
- package/dist/lib/ai-model/prompt/recorder-ui-describer.js.map +0 -1
- package/dist/lib/ai-model/prompt/ui-tars-planning.js.map +0 -1
- package/dist/lib/recorder-ui-describer.js +0 -419
- package/dist/lib/recorder-ui-describer.js.map +0 -1
- package/dist/types/ai-model/models/chat-content.d.ts +0 -2
- package/dist/types/ai-model/prompt/recorder-ui-describer.d.ts +0 -1
- package/dist/types/recorder-ui-describer.d.ts +0 -20
- /package/dist/es/ai-model/{models/types.mjs → model-adapter/custom-planning-types.mjs} +0 -0
- /package/dist/lib/ai-model/{models → model-adapter}/types.js +0 -0
- /package/dist/types/ai-model/{models/resolved.d.ts → model-adapter/resolve.d.ts} +0 -0
- /package/dist/types/ai-model/{prompt/ui-tars-planning.d.ts → models/ui-tars/prompt.d.ts} +0 -0
|
@@ -0,0 +1,223 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __webpack_require__ = {};
|
|
3
|
+
(()=>{
|
|
4
|
+
__webpack_require__.d = (exports1, definition)=>{
|
|
5
|
+
for(var key in definition)if (__webpack_require__.o(definition, key) && !__webpack_require__.o(exports1, key)) Object.defineProperty(exports1, key, {
|
|
6
|
+
enumerable: true,
|
|
7
|
+
get: definition[key]
|
|
8
|
+
});
|
|
9
|
+
};
|
|
10
|
+
})();
|
|
11
|
+
(()=>{
|
|
12
|
+
__webpack_require__.o = (obj, prop)=>Object.prototype.hasOwnProperty.call(obj, prop);
|
|
13
|
+
})();
|
|
14
|
+
(()=>{
|
|
15
|
+
__webpack_require__.r = (exports1)=>{
|
|
16
|
+
if ('undefined' != typeof Symbol && Symbol.toStringTag) Object.defineProperty(exports1, Symbol.toStringTag, {
|
|
17
|
+
value: 'Module'
|
|
18
|
+
});
|
|
19
|
+
Object.defineProperty(exports1, '__esModule', {
|
|
20
|
+
value: true
|
|
21
|
+
});
|
|
22
|
+
};
|
|
23
|
+
})();
|
|
24
|
+
var __webpack_exports__ = {};
|
|
25
|
+
__webpack_require__.r(__webpack_exports__);
|
|
26
|
+
__webpack_require__.d(__webpack_exports__, {
|
|
27
|
+
verifyElementByServiceLocate: ()=>verifyElementByServiceLocate,
|
|
28
|
+
verifyLocator: ()=>verifyLocator,
|
|
29
|
+
describeElementAtPoint: ()=>describeElementAtPoint,
|
|
30
|
+
verifyElementDescriptionAtPoint: ()=>verifyElementDescriptionAtPoint
|
|
31
|
+
});
|
|
32
|
+
const utils_namespaceObject = require("@midscene/shared/utils");
|
|
33
|
+
const utils_js_namespaceObject = require("./agent/utils.js");
|
|
34
|
+
const external_yaml_utils_js_namespaceObject = require("./yaml/utils.js");
|
|
35
|
+
const distanceOfTwoPoints = (p1, p2)=>{
|
|
36
|
+
const [x1, y1] = p1;
|
|
37
|
+
const [x2, y2] = p2;
|
|
38
|
+
return Math.round(Math.sqrt((x1 - x2) ** 2 + (y1 - y2) ** 2));
|
|
39
|
+
};
|
|
40
|
+
const includedInRect = (point, rect)=>{
|
|
41
|
+
const [x, y] = point;
|
|
42
|
+
const { left, top, width, height } = rect;
|
|
43
|
+
return x >= left && x <= left + width && y >= top && y <= top + height;
|
|
44
|
+
};
|
|
45
|
+
const buildLocateValidatorResult = (expectCenter, located, verifyLocateOption)=>{
|
|
46
|
+
const distance = distanceOfTwoPoints(expectCenter, located.center);
|
|
47
|
+
const included = includedInRect(expectCenter, located.rect);
|
|
48
|
+
const pass = distance <= (verifyLocateOption?.centerDistanceThreshold || 20) || included;
|
|
49
|
+
return {
|
|
50
|
+
pass,
|
|
51
|
+
rect: located.rect,
|
|
52
|
+
center: located.center,
|
|
53
|
+
centerDistance: distance,
|
|
54
|
+
includedInRect: included
|
|
55
|
+
};
|
|
56
|
+
};
|
|
57
|
+
function assertPositiveSize(size, label) {
|
|
58
|
+
(0, utils_namespaceObject.assert)(size && Number.isFinite(size.width) && Number.isFinite(size.height) && size.width > 0 && size.height > 0, `${label} must include positive width and height`);
|
|
59
|
+
}
|
|
60
|
+
const mapPointToScreenshotSpace = (center, screenshotSize, opt)=>{
|
|
61
|
+
const coordinateSpace = opt.coordinateSpace || 'screenshot';
|
|
62
|
+
if ('screenshot' === coordinateSpace) return center;
|
|
63
|
+
assertPositiveSize(opt.logicalSize, 'logicalSize is required when coordinateSpace is logical');
|
|
64
|
+
return [
|
|
65
|
+
center[0] * screenshotSize.width / opt.logicalSize.width,
|
|
66
|
+
center[1] * screenshotSize.height / opt.logicalSize.height
|
|
67
|
+
];
|
|
68
|
+
};
|
|
69
|
+
const createScreenshotBoundLocatorContext = async (center, opt)=>{
|
|
70
|
+
const screenshotContext = opt?.screenshotBase64 ? await (0, utils_js_namespaceObject.createScreenshotBoundUIContext)(opt.screenshotBase64, opt) : void 0;
|
|
71
|
+
const targetCenter = screenshotContext ? mapPointToScreenshotSpace(center, screenshotContext.shotSize, opt || {}) : center;
|
|
72
|
+
return {
|
|
73
|
+
screenshotContext,
|
|
74
|
+
locateOpt: screenshotContext ? {
|
|
75
|
+
uiContext: screenshotContext
|
|
76
|
+
} : void 0,
|
|
77
|
+
targetCenter
|
|
78
|
+
};
|
|
79
|
+
};
|
|
80
|
+
async function verifyLocator(runtime, prompt, locateOpt, expectCenter, verifyLocateOption) {
|
|
81
|
+
return locateAndVerify(runtime, prompt, expectCenter, {
|
|
82
|
+
centerDistanceThreshold: verifyLocateOption?.centerDistanceThreshold,
|
|
83
|
+
uiContext: locateOpt?.uiContext
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
function applyLocatorVerifyFn(locatorVerifyFn, input) {
|
|
87
|
+
if (!locatorVerifyFn) return input.verifyResult;
|
|
88
|
+
const customResult = locatorVerifyFn(input);
|
|
89
|
+
if ('boolean' == typeof customResult) return {
|
|
90
|
+
...input.verifyResult,
|
|
91
|
+
pass: customResult
|
|
92
|
+
};
|
|
93
|
+
return customResult;
|
|
94
|
+
}
|
|
95
|
+
function errorMessage(error) {
|
|
96
|
+
return error instanceof Error ? error.message : String(error);
|
|
97
|
+
}
|
|
98
|
+
async function describeElementAtPoint(runtime, center, opt) {
|
|
99
|
+
const { verifyPrompt = true, retryLimit = 3 } = opt || {};
|
|
100
|
+
const { screenshotContext, locateOpt, targetCenter } = await createScreenshotBoundLocatorContext(center, opt);
|
|
101
|
+
let success = false;
|
|
102
|
+
let retryCount = 0;
|
|
103
|
+
let resultPrompt = '';
|
|
104
|
+
let deepLocate = opt?.deepLocate || false;
|
|
105
|
+
let verifyResult;
|
|
106
|
+
let lastError;
|
|
107
|
+
let failureStage;
|
|
108
|
+
while(!success && retryCount < retryLimit){
|
|
109
|
+
if (retryCount >= 2) deepLocate = true;
|
|
110
|
+
const describeOpt = screenshotContext ? {
|
|
111
|
+
deepLocate,
|
|
112
|
+
context: screenshotContext
|
|
113
|
+
} : {
|
|
114
|
+
deepLocate
|
|
115
|
+
};
|
|
116
|
+
let text;
|
|
117
|
+
try {
|
|
118
|
+
text = await runtime.service.describe(targetCenter, runtime.describeModelRuntime, describeOpt);
|
|
119
|
+
} catch (error) {
|
|
120
|
+
return {
|
|
121
|
+
prompt: resultPrompt,
|
|
122
|
+
deepLocate,
|
|
123
|
+
verifyResult,
|
|
124
|
+
success: false,
|
|
125
|
+
error: errorMessage(error),
|
|
126
|
+
failureStage: 'describe'
|
|
127
|
+
};
|
|
128
|
+
}
|
|
129
|
+
if (!text.description) return {
|
|
130
|
+
prompt: resultPrompt,
|
|
131
|
+
deepLocate,
|
|
132
|
+
verifyResult,
|
|
133
|
+
success: false,
|
|
134
|
+
error: `failed to describe element at [${targetCenter}]`,
|
|
135
|
+
failureStage: 'describe'
|
|
136
|
+
};
|
|
137
|
+
resultPrompt = text.description;
|
|
138
|
+
if (!verifyPrompt) {
|
|
139
|
+
opt?.onProgress?.({
|
|
140
|
+
prompt: resultPrompt,
|
|
141
|
+
deepLocate
|
|
142
|
+
});
|
|
143
|
+
success = true;
|
|
144
|
+
break;
|
|
145
|
+
}
|
|
146
|
+
try {
|
|
147
|
+
verifyResult = await verifyLocator(runtime, resultPrompt, locateOpt, targetCenter, opt);
|
|
148
|
+
verifyResult = applyLocatorVerifyFn(opt?.locatorVerifyFn, {
|
|
149
|
+
prompt: resultPrompt,
|
|
150
|
+
expectCenter: targetCenter,
|
|
151
|
+
deepLocate,
|
|
152
|
+
retryCount,
|
|
153
|
+
verifyResult
|
|
154
|
+
});
|
|
155
|
+
opt?.onProgress?.({
|
|
156
|
+
prompt: resultPrompt,
|
|
157
|
+
deepLocate,
|
|
158
|
+
verifyResult
|
|
159
|
+
});
|
|
160
|
+
if (verifyResult.pass) success = true;
|
|
161
|
+
else {
|
|
162
|
+
lastError = void 0;
|
|
163
|
+
failureStage = 'verify';
|
|
164
|
+
retryCount++;
|
|
165
|
+
}
|
|
166
|
+
} catch (error) {
|
|
167
|
+
lastError = errorMessage(error);
|
|
168
|
+
failureStage = 'verify';
|
|
169
|
+
opt?.onProgress?.({
|
|
170
|
+
prompt: resultPrompt,
|
|
171
|
+
deepLocate
|
|
172
|
+
});
|
|
173
|
+
retryCount++;
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
return {
|
|
177
|
+
prompt: resultPrompt,
|
|
178
|
+
deepLocate,
|
|
179
|
+
verifyResult,
|
|
180
|
+
success,
|
|
181
|
+
error: success || !verifyPrompt ? void 0 : lastError || 'describeElementAtPoint verify failed',
|
|
182
|
+
failureStage: success ? void 0 : failureStage
|
|
183
|
+
};
|
|
184
|
+
}
|
|
185
|
+
async function verifyElementDescriptionAtPoint(runtime, description, center, opt) {
|
|
186
|
+
(0, utils_namespaceObject.assert)(description?.trim(), "description must not be empty");
|
|
187
|
+
const { locateOpt, targetCenter } = await createScreenshotBoundLocatorContext(center, opt);
|
|
188
|
+
return verifyLocator(runtime, description, locateOpt, targetCenter, opt);
|
|
189
|
+
}
|
|
190
|
+
async function verifyElementByServiceLocate(runtime, description, center, opt) {
|
|
191
|
+
return locateAndVerify(runtime, description, center, opt);
|
|
192
|
+
}
|
|
193
|
+
async function locateAndVerify(runtime, description, center, opt) {
|
|
194
|
+
(0, utils_namespaceObject.assert)(description?.trim(), "description must not be empty");
|
|
195
|
+
const { screenshotContext, targetCenter } = await createScreenshotBoundLocatorContext(center, opt);
|
|
196
|
+
const context = opt?.uiContext || screenshotContext;
|
|
197
|
+
const locateParam = (0, external_yaml_utils_js_namespaceObject.buildDetailedLocateParam)(description, {
|
|
198
|
+
cacheable: opt?.cacheable,
|
|
199
|
+
deepLocate: opt?.deepLocate,
|
|
200
|
+
xpath: opt?.xpath
|
|
201
|
+
});
|
|
202
|
+
(0, utils_namespaceObject.assert)(locateParam, 'cannot get locate param for service locate');
|
|
203
|
+
const locateResult = await runtime.service.locate(locateParam, context ? {
|
|
204
|
+
context
|
|
205
|
+
} : {}, runtime.locateModelRuntime, opt?.abortSignal);
|
|
206
|
+
(0, utils_namespaceObject.assert)(locateResult.element, `Element not found: ${description}`);
|
|
207
|
+
return buildLocateValidatorResult(targetCenter, locateResult.element, opt);
|
|
208
|
+
}
|
|
209
|
+
exports.describeElementAtPoint = __webpack_exports__.describeElementAtPoint;
|
|
210
|
+
exports.verifyElementByServiceLocate = __webpack_exports__.verifyElementByServiceLocate;
|
|
211
|
+
exports.verifyElementDescriptionAtPoint = __webpack_exports__.verifyElementDescriptionAtPoint;
|
|
212
|
+
exports.verifyLocator = __webpack_exports__.verifyLocator;
|
|
213
|
+
for(var __rspack_i in __webpack_exports__)if (-1 === [
|
|
214
|
+
"describeElementAtPoint",
|
|
215
|
+
"verifyElementByServiceLocate",
|
|
216
|
+
"verifyElementDescriptionAtPoint",
|
|
217
|
+
"verifyLocator"
|
|
218
|
+
].indexOf(__rspack_i)) exports[__rspack_i] = __webpack_exports__[__rspack_i];
|
|
219
|
+
Object.defineProperty(exports, '__esModule', {
|
|
220
|
+
value: true
|
|
221
|
+
});
|
|
222
|
+
|
|
223
|
+
//# sourceMappingURL=element-describer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"element-describer.js","sources":["webpack/runtime/define_property_getters","webpack/runtime/has_own_property","webpack/runtime/make_namespace_object","../../src/element-describer.ts"],"sourcesContent":["__webpack_require__.d = (exports, definition) => {\n\tfor(var key in definition) {\n if(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {\n Object.defineProperty(exports, key, { enumerable: true, get: definition[key] });\n }\n }\n};","__webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))","// define __esModule on exports\n__webpack_require__.r = (exports) => {\n\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n\t}\n\tObject.defineProperty(exports, '__esModule', { value: true });\n};","import type { ModelRuntime } from '@/ai-model/models';\nimport { assert } from '@midscene/shared/utils';\nimport { createScreenshotBoundUIContext } from './agent/utils';\nimport type Service from './service';\nimport type {\n AgentDescribeElementAtPointResult,\n LocateOption,\n LocateResultElement,\n LocateValidatorResult,\n LocatorValidatorOption,\n Rect,\n Size,\n UIContext,\n} from './types';\nimport { buildDetailedLocateParam } from './yaml/utils';\n\nexport type DescribeElementCoordinateSpace = 'screenshot' | 'logical';\n\nexport type LocatorVerifyFn = (input: {\n prompt: string;\n expectCenter: [number, number];\n deepLocate: boolean;\n retryCount: number;\n verifyResult: LocateValidatorResult;\n}) => LocateValidatorResult | boolean;\n\nexport type DescribeElementAtPointOptions = {\n verifyPrompt?: boolean;\n retryLimit?: number;\n deepLocate?: boolean;\n locatorVerifyFn?: LocatorVerifyFn;\n screenshotBase64?: string;\n screenshotSize?: Size;\n coordinateSpace?: DescribeElementCoordinateSpace;\n logicalSize?: Size;\n onProgress?: (progress: {\n prompt?: string;\n deepLocate?: boolean;\n verifyResult?: LocateValidatorResult;\n }) => void;\n} & LocatorValidatorOption;\n\ntype ScreenshotBoundContextOptions = {\n screenshotBase64?: string;\n screenshotSize?: Size;\n coordinateSpace?: DescribeElementCoordinateSpace;\n logicalSize?: Size;\n};\n\nexport type VerifyElementDescriptionAtPointOptions =\n ScreenshotBoundContextOptions & LocatorValidatorOption;\n\nexport type VerifyElementByServiceLocateOptions =\n VerifyElementDescriptionAtPointOptions &\n Pick<LocateOption, 'cacheable' | 'deepLocate' | 'xpath'> & {\n abortSignal?: AbortSignal;\n };\n\nexport type ElementDescriberRuntime = {\n service: Pick<Service, 'describe' | 'locate'>;\n describeModelRuntime: ModelRuntime;\n locateModelRuntime: ModelRuntime;\n};\n\nconst distanceOfTwoPoints = (p1: [number, number], p2: [number, number]) => {\n const [x1, y1] = p1;\n const [x2, y2] = p2;\n return Math.round(Math.sqrt((x1 - x2) ** 2 + (y1 - y2) ** 2));\n};\n\nconst includedInRect = (point: [number, number], rect: Rect) => {\n const [x, y] = point;\n const { left, top, width, height } = rect;\n return x >= left && x <= left + width && y >= top && y <= top + height;\n};\n\nconst buildLocateValidatorResult = (\n expectCenter: [number, number],\n located: Pick<LocateResultElement, 'center' | 'rect'>,\n verifyLocateOption?: LocatorValidatorOption,\n): LocateValidatorResult => {\n const distance = distanceOfTwoPoints(expectCenter, located.center);\n const included = includedInRect(expectCenter, located.rect);\n const pass =\n distance <= (verifyLocateOption?.centerDistanceThreshold || 20) || included;\n return {\n pass,\n rect: located.rect,\n center: located.center,\n centerDistance: distance,\n includedInRect: included,\n };\n};\n\nfunction assertPositiveSize(\n size: Size | undefined,\n label: string,\n): asserts size is Size {\n assert(\n size &&\n Number.isFinite(size.width) &&\n Number.isFinite(size.height) &&\n size.width > 0 &&\n size.height > 0,\n `${label} must include positive width and height`,\n );\n}\n\nconst mapPointToScreenshotSpace = (\n center: [number, number],\n screenshotSize: Size,\n opt: ScreenshotBoundContextOptions,\n): [number, number] => {\n const coordinateSpace = opt.coordinateSpace || 'screenshot';\n if (coordinateSpace === 'screenshot') {\n return center;\n }\n\n assertPositiveSize(\n opt.logicalSize,\n 'logicalSize is required when coordinateSpace is logical',\n );\n return [\n (center[0] * screenshotSize.width) / opt.logicalSize.width,\n (center[1] * screenshotSize.height) / opt.logicalSize.height,\n ];\n};\n\nconst createScreenshotBoundLocatorContext = async (\n center: [number, number],\n opt?: ScreenshotBoundContextOptions,\n): Promise<{\n screenshotContext?: UIContext;\n locateOpt?: LocateOption;\n targetCenter: [number, number];\n}> => {\n const screenshotContext = opt?.screenshotBase64\n ? await createScreenshotBoundUIContext(opt.screenshotBase64, opt)\n : undefined;\n const targetCenter = screenshotContext\n ? mapPointToScreenshotSpace(center, screenshotContext.shotSize, opt || {})\n : center;\n return {\n screenshotContext,\n locateOpt: screenshotContext ? { uiContext: screenshotContext } : undefined,\n targetCenter,\n };\n};\n\nexport async function verifyLocator(\n runtime: Pick<ElementDescriberRuntime, 'service' | 'locateModelRuntime'>,\n prompt: string,\n locateOpt: LocateOption | undefined,\n expectCenter: [number, number],\n verifyLocateOption?: LocatorValidatorOption,\n): Promise<LocateValidatorResult> {\n return locateAndVerify(runtime, prompt, expectCenter, {\n centerDistanceThreshold: verifyLocateOption?.centerDistanceThreshold,\n uiContext: locateOpt?.uiContext,\n });\n}\n\nfunction applyLocatorVerifyFn(\n locatorVerifyFn: LocatorVerifyFn | undefined,\n input: Parameters<LocatorVerifyFn>[0],\n): LocateValidatorResult {\n if (!locatorVerifyFn) {\n return input.verifyResult;\n }\n const customResult = locatorVerifyFn(input);\n if (typeof customResult === 'boolean') {\n return {\n ...input.verifyResult,\n pass: customResult,\n };\n }\n return customResult;\n}\n\nfunction errorMessage(error: unknown): string {\n return error instanceof Error ? error.message : String(error);\n}\n\nexport async function describeElementAtPoint(\n runtime: ElementDescriberRuntime,\n center: [number, number],\n opt?: DescribeElementAtPointOptions,\n): Promise<AgentDescribeElementAtPointResult> {\n const { verifyPrompt = true, retryLimit = 3 } = opt || {};\n const { screenshotContext, locateOpt, targetCenter } =\n await createScreenshotBoundLocatorContext(center, opt);\n\n let success = false;\n let retryCount = 0;\n let resultPrompt = '';\n let deepLocate = opt?.deepLocate || false;\n let verifyResult: LocateValidatorResult | undefined;\n let lastError: string | undefined;\n let failureStage: AgentDescribeElementAtPointResult['failureStage'];\n\n while (!success && retryCount < retryLimit) {\n if (retryCount >= 2) {\n deepLocate = true;\n }\n const describeOpt = screenshotContext\n ? { deepLocate, context: screenshotContext }\n : { deepLocate };\n\n let text: Awaited<\n ReturnType<ElementDescriberRuntime['service']['describe']>\n >;\n try {\n text = await runtime.service.describe(\n targetCenter,\n runtime.describeModelRuntime,\n describeOpt,\n );\n } catch (error) {\n return {\n prompt: resultPrompt,\n deepLocate,\n verifyResult,\n success: false,\n error: errorMessage(error),\n failureStage: 'describe',\n };\n }\n if (!text.description) {\n return {\n prompt: resultPrompt,\n deepLocate,\n verifyResult,\n success: false,\n error: `failed to describe element at [${targetCenter}]`,\n failureStage: 'describe',\n };\n }\n resultPrompt = text.description;\n\n if (!verifyPrompt) {\n opt?.onProgress?.({ prompt: resultPrompt, deepLocate });\n success = true;\n break;\n }\n\n try {\n verifyResult = await verifyLocator(\n runtime,\n resultPrompt,\n locateOpt,\n targetCenter,\n opt,\n );\n verifyResult = applyLocatorVerifyFn(opt?.locatorVerifyFn, {\n prompt: resultPrompt,\n expectCenter: targetCenter,\n deepLocate,\n retryCount,\n verifyResult,\n });\n opt?.onProgress?.({ prompt: resultPrompt, deepLocate, verifyResult });\n if (verifyResult.pass) {\n success = true;\n } else {\n lastError = undefined;\n failureStage = 'verify';\n retryCount++;\n }\n } catch (error) {\n lastError = errorMessage(error);\n failureStage = 'verify';\n opt?.onProgress?.({ prompt: resultPrompt, deepLocate });\n retryCount++;\n }\n }\n\n return {\n prompt: resultPrompt,\n deepLocate,\n verifyResult,\n success,\n error:\n success || !verifyPrompt\n ? undefined\n : lastError || 'describeElementAtPoint verify failed',\n failureStage: success ? undefined : failureStage,\n };\n}\n\nexport async function verifyElementDescriptionAtPoint(\n runtime: ElementDescriberRuntime,\n description: string,\n center: [number, number],\n opt?: VerifyElementDescriptionAtPointOptions,\n): Promise<LocateValidatorResult> {\n assert(description?.trim(), 'description must not be empty');\n const { locateOpt, targetCenter } = await createScreenshotBoundLocatorContext(\n center,\n opt,\n );\n\n return verifyLocator(runtime, description, locateOpt, targetCenter, opt);\n}\n\nexport async function verifyElementByServiceLocate(\n runtime: Pick<ElementDescriberRuntime, 'service' | 'locateModelRuntime'>,\n description: string,\n center: [number, number],\n opt?: VerifyElementByServiceLocateOptions,\n): Promise<LocateValidatorResult> {\n return locateAndVerify(runtime, description, center, opt);\n}\n\nasync function locateAndVerify(\n runtime: Pick<ElementDescriberRuntime, 'service' | 'locateModelRuntime'>,\n description: string,\n center: [number, number],\n opt?: VerifyElementByServiceLocateOptions & { uiContext?: UIContext },\n): Promise<LocateValidatorResult> {\n assert(description?.trim(), 'description must not be empty');\n const { screenshotContext, targetCenter } =\n await createScreenshotBoundLocatorContext(center, opt);\n const context = opt?.uiContext || screenshotContext;\n const locateParam = buildDetailedLocateParam(description, {\n cacheable: opt?.cacheable,\n deepLocate: opt?.deepLocate,\n xpath: opt?.xpath,\n });\n assert(locateParam, 'cannot get locate param for service locate');\n\n const locateResult = await runtime.service.locate(\n locateParam,\n context ? { context } : {},\n runtime.locateModelRuntime,\n opt?.abortSignal,\n );\n assert(locateResult.element, `Element not found: ${description}`);\n return buildLocateValidatorResult(targetCenter, locateResult.element, opt);\n}\n"],"names":["__webpack_require__","definition","key","Object","obj","prop","Symbol","distanceOfTwoPoints","p1","p2","x1","y1","x2","y2","Math","includedInRect","point","rect","x","y","left","top","width","height","buildLocateValidatorResult","expectCenter","located","verifyLocateOption","distance","included","pass","assertPositiveSize","size","label","assert","Number","mapPointToScreenshotSpace","center","screenshotSize","opt","coordinateSpace","createScreenshotBoundLocatorContext","screenshotContext","createScreenshotBoundUIContext","undefined","targetCenter","verifyLocator","runtime","prompt","locateOpt","locateAndVerify","applyLocatorVerifyFn","locatorVerifyFn","input","customResult","errorMessage","error","Error","String","describeElementAtPoint","verifyPrompt","retryLimit","success","retryCount","resultPrompt","deepLocate","verifyResult","lastError","failureStage","describeOpt","text","verifyElementDescriptionAtPoint","description","verifyElementByServiceLocate","context","locateParam","buildDetailedLocateParam","locateResult"],"mappings":"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"}
|
package/dist/lib/index.js
CHANGED
|
@@ -45,6 +45,7 @@ __webpack_require__.d(__webpack_exports__, {
|
|
|
45
45
|
splitReportHtmlByExecution: ()=>external_report_js_namespaceObject.splitReportHtmlByExecution,
|
|
46
46
|
getTaskSearchArea: ()=>task_service_dump_js_namespaceObject.getTaskSearchArea,
|
|
47
47
|
parseDumpScriptAttributes: ()=>external_dump_index_js_namespaceObject.parseDumpScriptAttributes,
|
|
48
|
+
verifyElementByServiceLocate: ()=>external_element_describer_js_namespaceObject.verifyElementByServiceLocate,
|
|
48
49
|
z: ()=>external_zod_namespaceObject.z,
|
|
49
50
|
generateDumpScriptTag: ()=>external_dump_index_js_namespaceObject.generateDumpScriptTag,
|
|
50
51
|
SizeSchema: ()=>external_ai_model_index_js_namespaceObject.SizeSchema,
|
|
@@ -57,7 +58,9 @@ __webpack_require__.d(__webpack_exports__, {
|
|
|
57
58
|
PointSchema: ()=>external_ai_model_index_js_namespaceObject.PointSchema,
|
|
58
59
|
RectSchema: ()=>external_ai_model_index_js_namespaceObject.RectSchema,
|
|
59
60
|
Agent: ()=>external_agent_index_js_namespaceObject.Agent,
|
|
61
|
+
verifyElementDescriptionAtPoint: ()=>external_element_describer_js_namespaceObject.verifyElementDescriptionAtPoint,
|
|
60
62
|
nullReportGenerator: ()=>external_report_generator_js_namespaceObject.nullReportGenerator,
|
|
63
|
+
verifyLocator: ()=>external_element_describer_js_namespaceObject.verifyLocator,
|
|
61
64
|
ScreenshotStore: ()=>screenshot_store_js_namespaceObject.ScreenshotStore,
|
|
62
65
|
ReportMergingTool: ()=>external_report_js_namespaceObject.ReportMergingTool,
|
|
63
66
|
Service: ()=>index_js_default(),
|
|
@@ -69,8 +72,9 @@ __webpack_require__.d(__webpack_exports__, {
|
|
|
69
72
|
ExecutionDump: ()=>external_types_js_namespaceObject.ExecutionDump,
|
|
70
73
|
dedupeExecutionsKeepLatest: ()=>external_report_js_namespaceObject.dedupeExecutionsKeepLatest,
|
|
71
74
|
ReportGenerator: ()=>external_report_generator_js_namespaceObject.ReportGenerator,
|
|
72
|
-
|
|
75
|
+
describeElementAtPoint: ()=>external_element_describer_js_namespaceObject.describeElementAtPoint,
|
|
73
76
|
TaskRunner: ()=>external_task_runner_js_namespaceObject.TaskRunner,
|
|
77
|
+
escapeContent: ()=>external_dump_index_js_namespaceObject.escapeContent,
|
|
74
78
|
ReportActionDump: ()=>external_types_js_namespaceObject.ReportActionDump,
|
|
75
79
|
GroupedActionDump: ()=>external_types_js_namespaceObject.GroupedActionDump,
|
|
76
80
|
TMultimodalPromptSchema: ()=>external_ai_model_index_js_namespaceObject.TMultimodalPromptSchema,
|
|
@@ -88,6 +92,7 @@ const external_ai_model_index_js_namespaceObject = require("./ai-model/index.js"
|
|
|
88
92
|
const env_namespaceObject = require("@midscene/shared/env");
|
|
89
93
|
const external_types_js_namespaceObject = require("./types.js");
|
|
90
94
|
const external_agent_index_js_namespaceObject = require("./agent/index.js");
|
|
95
|
+
const external_element_describer_js_namespaceObject = require("./element-describer.js");
|
|
91
96
|
const external_dump_index_js_namespaceObject = require("./dump/index.js");
|
|
92
97
|
const task_service_dump_js_namespaceObject = require("./dump/task-service-dump.js");
|
|
93
98
|
const external_report_generator_js_namespaceObject = require("./report-generator.js");
|
|
@@ -120,6 +125,7 @@ exports.createAgent = __webpack_exports__.createAgent;
|
|
|
120
125
|
exports.createReportCliCommands = __webpack_exports__.createReportCliCommands;
|
|
121
126
|
exports.dedupeExecutionsKeepLatest = __webpack_exports__.dedupeExecutionsKeepLatest;
|
|
122
127
|
exports["default"] = __webpack_exports__["default"];
|
|
128
|
+
exports.describeElementAtPoint = __webpack_exports__.describeElementAtPoint;
|
|
123
129
|
exports.escapeContent = __webpack_exports__.escapeContent;
|
|
124
130
|
exports.executionToMarkdown = __webpack_exports__.executionToMarkdown;
|
|
125
131
|
exports.generateDumpScriptTag = __webpack_exports__.generateDumpScriptTag;
|
|
@@ -141,6 +147,9 @@ exports.runConnectivityTest = __webpack_exports__.runConnectivityTest;
|
|
|
141
147
|
exports.splitReportFile = __webpack_exports__.splitReportFile;
|
|
142
148
|
exports.splitReportHtmlByExecution = __webpack_exports__.splitReportHtmlByExecution;
|
|
143
149
|
exports.unescapeContent = __webpack_exports__.unescapeContent;
|
|
150
|
+
exports.verifyElementByServiceLocate = __webpack_exports__.verifyElementByServiceLocate;
|
|
151
|
+
exports.verifyElementDescriptionAtPoint = __webpack_exports__.verifyElementDescriptionAtPoint;
|
|
152
|
+
exports.verifyLocator = __webpack_exports__.verifyLocator;
|
|
144
153
|
exports.z = __webpack_exports__.z;
|
|
145
154
|
for(var __rspack_i in __webpack_exports__)if (-1 === [
|
|
146
155
|
"Agent",
|
|
@@ -166,6 +175,7 @@ for(var __rspack_i in __webpack_exports__)if (-1 === [
|
|
|
166
175
|
"createReportCliCommands",
|
|
167
176
|
"dedupeExecutionsKeepLatest",
|
|
168
177
|
"default",
|
|
178
|
+
"describeElementAtPoint",
|
|
169
179
|
"escapeContent",
|
|
170
180
|
"executionToMarkdown",
|
|
171
181
|
"generateDumpScriptTag",
|
|
@@ -187,6 +197,9 @@ for(var __rspack_i in __webpack_exports__)if (-1 === [
|
|
|
187
197
|
"splitReportFile",
|
|
188
198
|
"splitReportHtmlByExecution",
|
|
189
199
|
"unescapeContent",
|
|
200
|
+
"verifyElementByServiceLocate",
|
|
201
|
+
"verifyElementDescriptionAtPoint",
|
|
202
|
+
"verifyLocator",
|
|
190
203
|
"z"
|
|
191
204
|
].indexOf(__rspack_i)) exports[__rspack_i] = __webpack_exports__[__rspack_i];
|
|
192
205
|
Object.defineProperty(exports, '__esModule', {
|
package/dist/lib/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":["webpack/runtime/compat_get_default_export","webpack/runtime/define_property_getters","webpack/runtime/has_own_property","webpack/runtime/make_namespace_object","../../src/index.ts"],"sourcesContent":["// getDefaultExport function for compatibility with non-ESM modules\n__webpack_require__.n = (module) => {\n\tvar getter = module && module.__esModule ?\n\t\t() => (module['default']) :\n\t\t() => (module);\n\t__webpack_require__.d(getter, { a: getter });\n\treturn getter;\n};\n","__webpack_require__.d = (exports, definition) => {\n\tfor(var key in definition) {\n if(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {\n Object.defineProperty(exports, key, { enumerable: true, get: definition[key] });\n }\n }\n};","__webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))","// define __esModule on exports\n__webpack_require__.r = (exports) => {\n\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n\t}\n\tObject.defineProperty(exports, '__esModule', { value: true });\n};","import { z } from 'zod';\nimport Service from './service/index';\nimport { TaskRunner } from './task-runner';\nimport { getVersion } from './utils';\n\nexport {\n plan,\n AiLocateElement,\n runConnectivityTest,\n getMidsceneLocationSchema,\n PointSchema,\n SizeSchema,\n RectSchema,\n TMultimodalPromptSchema,\n TUserPromptSchema,\n type TMultimodalPrompt,\n type TUserPrompt,\n type ConnectivityCheckResultItem,\n type ConnectivityTestConfig,\n type ConnectivityTestResult,\n} from './ai-model/index';\n\nexport {\n MIDSCENE_MODEL_NAME,\n type CreateOpenAIClientFn,\n} from '@midscene/shared/env';\n\nexport type * from './types';\nexport {\n ServiceError,\n ExecutionDump,\n ReportActionDump,\n GroupedActionDump,\n type IExecutionDump,\n type IReportActionDump,\n type IGroupedActionDump,\n type ReportMeta,\n type GroupMeta,\n} from './types';\n\nexport { z };\n\nexport default Service;\nexport { TaskRunner, Service, getVersion };\n\nexport type {\n MidsceneYamlScript,\n MidsceneYamlTask,\n MidsceneYamlFlowItem,\n MidsceneYamlConfigResult,\n MidsceneYamlConfig,\n MidsceneYamlScriptWebEnv,\n MidsceneYamlScriptAndroidEnv,\n MidsceneYamlScriptIOSEnv,\n MidsceneYamlScriptEnv,\n LocateOption,\n DetailedLocateParam,\n} from './yaml';\n\nexport {\n Agent,\n type AgentOpt,\n type AiActOptions,\n createAgent,\n} from './agent';\n\n// Dump utilities\nexport {\n restoreImageReferences,\n escapeContent,\n unescapeContent,\n parseImageScripts,\n parseDumpScript,\n parseDumpScriptAttributes,\n generateImageScriptTag,\n generateDumpScriptTag,\n} from './dump';\nexport {\n getTaskSearchArea,\n getTaskServiceDump,\n} from './dump/task-service-dump';\n\n// Report generator\nexport type { IReportGenerator } from './report-generator';\nexport { ReportGenerator, nullReportGenerator } from './report-generator';\nexport {\n collectDedupedExecutions,\n ReportMergingTool,\n dedupeExecutionsKeepLatest,\n splitReportHtmlByExecution,\n} from './report';\nexport {\n createReportCliCommands,\n reportFileToMarkdown,\n splitReportFile,\n mergeReportFiles,\n type ConsumeReportFileAction,\n type ReportFileToMarkdownOptions,\n type ReportCliCommandDefinition,\n type ReportCliCommandEntry,\n type SplitReportFileOptions,\n type MergeReportFilesOptions,\n type MergeReportFilesResult,\n} from './report-cli';\n\n// ScreenshotItem\nexport { ScreenshotItem } from './screenshot-item';\nexport { ScreenshotStore, type ScreenshotRef } from './dump/screenshot-store';\n\nexport {\n executionToMarkdown,\n reportToMarkdown,\n type ExecutionMarkdownOptions,\n type ExecutionMarkdownResult,\n type ReportMarkdownResult,\n type MarkdownAttachment,\n} from './report-markdown';\n"],"names":["__webpack_require__","module","getter","definition","key","Object","obj","prop","Symbol","Service"],"mappings":";;;IACAA,oBAAoB,CAAC,GAAG,CAACC;QACxB,IAAIC,SAASD,UAAUA,OAAO,UAAU,GACvC,IAAOA,MAAM,CAAC,UAAU,GACxB,IAAOA;QACRD,oBAAoB,CAAC,CAACE,QAAQ;YAAE,GAAGA;QAAO;QAC1C,OAAOA;IACR;;;ICPAF,oBAAoB,CAAC,GAAG,CAAC,UAASG;QACjC,IAAI,IAAIC,OAAOD,WACR,IAAGH,oBAAoB,CAAC,CAACG,YAAYC,QAAQ,CAACJ,oBAAoB,CAAC,CAAC,UAASI,MACzEC,OAAO,cAAc,CAAC,UAASD,KAAK;YAAE,YAAY;YAAM,KAAKD,UAAU,CAACC,IAAI;QAAC;IAGzF;;;ICNAJ,oBAAoB,CAAC,GAAG,CAACM,KAAKC,OAAUF,OAAO,SAAS,CAAC,cAAc,CAAC,IAAI,CAACC,KAAKC;;;ICClFP,oBAAoB,CAAC,GAAG,CAAC;QACxB,IAAG,AAAkB,eAAlB,OAAOQ,UAA0BA,OAAO,WAAW,EACrDH,OAAO,cAAc,CAAC,UAASG,OAAO,WAAW,EAAE;YAAE,OAAO;QAAS;QAEtEH,OAAO,cAAc,CAAC,UAAS,cAAc;YAAE,OAAO;QAAK;IAC5D
|
|
1
|
+
{"version":3,"file":"index.js","sources":["webpack/runtime/compat_get_default_export","webpack/runtime/define_property_getters","webpack/runtime/has_own_property","webpack/runtime/make_namespace_object","../../src/index.ts"],"sourcesContent":["// getDefaultExport function for compatibility with non-ESM modules\n__webpack_require__.n = (module) => {\n\tvar getter = module && module.__esModule ?\n\t\t() => (module['default']) :\n\t\t() => (module);\n\t__webpack_require__.d(getter, { a: getter });\n\treturn getter;\n};\n","__webpack_require__.d = (exports, definition) => {\n\tfor(var key in definition) {\n if(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {\n Object.defineProperty(exports, key, { enumerable: true, get: definition[key] });\n }\n }\n};","__webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))","// define __esModule on exports\n__webpack_require__.r = (exports) => {\n\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n\t}\n\tObject.defineProperty(exports, '__esModule', { value: true });\n};","import { z } from 'zod';\nimport Service from './service/index';\nimport { TaskRunner } from './task-runner';\nimport { getVersion } from './utils';\n\nexport {\n plan,\n AiLocateElement,\n runConnectivityTest,\n getMidsceneLocationSchema,\n PointSchema,\n SizeSchema,\n RectSchema,\n TMultimodalPromptSchema,\n TUserPromptSchema,\n type TMultimodalPrompt,\n type TUserPrompt,\n type ConnectivityCheckResultItem,\n type ConnectivityTestConfig,\n type ConnectivityTestResult,\n} from './ai-model/index';\n\nexport {\n MIDSCENE_MODEL_NAME,\n type CreateOpenAIClientFn,\n} from '@midscene/shared/env';\n\nexport type * from './types';\nexport {\n ServiceError,\n ExecutionDump,\n ReportActionDump,\n GroupedActionDump,\n type IExecutionDump,\n type IReportActionDump,\n type IGroupedActionDump,\n type ReportMeta,\n type GroupMeta,\n} from './types';\n\nexport { z };\n\nexport default Service;\nexport { TaskRunner, Service, getVersion };\n\nexport type {\n MidsceneYamlScript,\n MidsceneYamlTask,\n MidsceneYamlFlowItem,\n MidsceneYamlConfigResult,\n MidsceneYamlConfig,\n MidsceneYamlScriptWebEnv,\n MidsceneYamlScriptAndroidEnv,\n MidsceneYamlScriptIOSEnv,\n MidsceneYamlScriptEnv,\n LocateOption,\n DetailedLocateParam,\n} from './yaml';\n\nexport {\n Agent,\n type AgentOpt,\n type AiActOptions,\n type GherkinStepKeyword,\n type RunGherkinScenarioOptions,\n createAgent,\n} from './agent';\nexport {\n describeElementAtPoint,\n verifyElementDescriptionAtPoint,\n verifyElementByServiceLocate,\n verifyLocator,\n type DescribeElementAtPointOptions,\n type DescribeElementCoordinateSpace,\n type ElementDescriberRuntime,\n type VerifyElementDescriptionAtPointOptions,\n type VerifyElementByServiceLocateOptions,\n} from './element-describer';\n\n// Dump utilities\nexport {\n restoreImageReferences,\n escapeContent,\n unescapeContent,\n parseImageScripts,\n parseDumpScript,\n parseDumpScriptAttributes,\n generateImageScriptTag,\n generateDumpScriptTag,\n} from './dump';\nexport {\n getTaskSearchArea,\n getTaskServiceDump,\n} from './dump/task-service-dump';\n\n// Report generator\nexport type { IReportGenerator } from './report-generator';\nexport { ReportGenerator, nullReportGenerator } from './report-generator';\nexport {\n collectDedupedExecutions,\n ReportMergingTool,\n dedupeExecutionsKeepLatest,\n splitReportHtmlByExecution,\n} from './report';\nexport {\n createReportCliCommands,\n reportFileToMarkdown,\n splitReportFile,\n mergeReportFiles,\n type ConsumeReportFileAction,\n type ReportFileToMarkdownOptions,\n type ReportCliCommandDefinition,\n type ReportCliCommandEntry,\n type SplitReportFileOptions,\n type MergeReportFilesOptions,\n type MergeReportFilesResult,\n} from './report-cli';\n\n// ScreenshotItem\nexport { ScreenshotItem } from './screenshot-item';\nexport { ScreenshotStore, type ScreenshotRef } from './dump/screenshot-store';\n\nexport {\n executionToMarkdown,\n reportToMarkdown,\n type ExecutionMarkdownOptions,\n type ExecutionMarkdownResult,\n type ReportMarkdownResult,\n type MarkdownAttachment,\n} from './report-markdown';\n"],"names":["__webpack_require__","module","getter","definition","key","Object","obj","prop","Symbol","Service"],"mappings":";;;IACAA,oBAAoB,CAAC,GAAG,CAACC;QACxB,IAAIC,SAASD,UAAUA,OAAO,UAAU,GACvC,IAAOA,MAAM,CAAC,UAAU,GACxB,IAAOA;QACRD,oBAAoB,CAAC,CAACE,QAAQ;YAAE,GAAGA;QAAO;QAC1C,OAAOA;IACR;;;ICPAF,oBAAoB,CAAC,GAAG,CAAC,UAASG;QACjC,IAAI,IAAIC,OAAOD,WACR,IAAGH,oBAAoB,CAAC,CAACG,YAAYC,QAAQ,CAACJ,oBAAoB,CAAC,CAAC,UAASI,MACzEC,OAAO,cAAc,CAAC,UAASD,KAAK;YAAE,YAAY;YAAM,KAAKD,UAAU,CAACC,IAAI;QAAC;IAGzF;;;ICNAJ,oBAAoB,CAAC,GAAG,CAACM,KAAKC,OAAUF,OAAO,SAAS,CAAC,cAAc,CAAC,IAAI,CAACC,KAAKC;;;ICClFP,oBAAoB,CAAC,GAAG,CAAC;QACxB,IAAG,AAAkB,eAAlB,OAAOQ,UAA0BA,OAAO,WAAW,EACrDH,OAAO,cAAc,CAAC,UAASG,OAAO,WAAW,EAAE;YAAE,OAAO;QAAS;QAEtEH,OAAO,cAAc,CAAC,UAAS,cAAc;YAAE,OAAO;QAAK;IAC5D;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACoCA,YAAeI"}
|
|
@@ -91,17 +91,16 @@ class ReportGenerator {
|
|
|
91
91
|
await this.flush();
|
|
92
92
|
this.destroyed = true;
|
|
93
93
|
if (!this.initialized) return;
|
|
94
|
-
this.printReportPath('finalized');
|
|
95
94
|
return this.reportPath;
|
|
96
95
|
}
|
|
97
96
|
getReportPath() {
|
|
98
97
|
return this.reportPath;
|
|
99
98
|
}
|
|
100
|
-
printReportPath(
|
|
99
|
+
printReportPath() {
|
|
101
100
|
if (!this.autoPrint || !this.reportPath) return;
|
|
102
101
|
if (env_namespaceObject.globalConfigManager.getEnvConfigInBoolean(env_namespaceObject.MIDSCENE_REPORT_QUIET)) return;
|
|
103
|
-
if ('directory' === this.screenshotMode) (0, utils_namespaceObject.logMsg)(`Midscene - report
|
|
104
|
-
else (0, utils_namespaceObject.logMsg)(`Midscene - report
|
|
102
|
+
if ('directory' === this.screenshotMode) (0, utils_namespaceObject.logMsg)(`Midscene - report file updated: npx serve ${(0, external_node_path_namespaceObject.dirname)(this.reportPath)}`);
|
|
103
|
+
else (0, utils_namespaceObject.logMsg)(`Midscene - report file updated: ${this.reportPath}`);
|
|
105
104
|
}
|
|
106
105
|
async doWriteExecution(execution, reportMeta) {
|
|
107
106
|
const singleDump = this.wrapAsReportDump(execution, reportMeta);
|
|
@@ -110,7 +109,7 @@ class ReportGenerator {
|
|
|
110
109
|
if (this.shouldPersistExecutionDump) await this.persistExecutionDumpToFile(execution, singleDump);
|
|
111
110
|
if (!this.firstWriteDone) {
|
|
112
111
|
this.firstWriteDone = true;
|
|
113
|
-
this.printReportPath(
|
|
112
|
+
this.printReportPath();
|
|
114
113
|
}
|
|
115
114
|
}
|
|
116
115
|
mergeReportAttributes(attributes) {
|
|
@@ -220,7 +219,6 @@ class ReportGenerator {
|
|
|
220
219
|
alsoWriteFileCopy: this.shouldPersistExecutionDump
|
|
221
220
|
});
|
|
222
221
|
if (options.reuseExistingReport) this.hydrateStateFromExistingReport();
|
|
223
|
-
this.printReportPath('will be generated at');
|
|
224
222
|
}
|
|
225
223
|
}
|
|
226
224
|
function ensureHtmlFileName(reportFileName) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"report-generator.js","sources":["webpack/runtime/define_property_getters","webpack/runtime/has_own_property","webpack/runtime/make_namespace_object","../../src/report-generator.ts"],"sourcesContent":["__webpack_require__.d = (exports, definition) => {\n\tfor(var key in definition) {\n if(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {\n Object.defineProperty(exports, key, { enumerable: true, get: definition[key] });\n }\n }\n};","__webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))","// define __esModule on exports\n__webpack_require__.r = (exports) => {\n\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n\t}\n\tObject.defineProperty(exports, '__esModule', { value: true });\n};","/*\n * PERF INVARIANT — DO NOT reintroduce sync fs APIs (writeFileSync /\n * appendFileSync) in this file's write paths. `ReportGenerator` runs on\n * the Electron main event loop during agent execution, and a single\n * progress tick appends a multi-MB ExecutionDump payload. Sync I/O here\n * blocked the loop for 20+ seconds per run, freezing IPC, scrcpy and\n * every renderer round-trip. Always use `fs/promises`. See commit\n * 6a25e05c and `report-generator-async-contract.test.ts`.\n */\nimport { existsSync, mkdirSync, readdirSync } from 'node:fs';\nimport {\n appendFile as appendFileAsync,\n writeFile as writeFileAsync,\n} from 'node:fs/promises';\nimport { dirname, join } from 'node:path';\nimport { getMidsceneRunSubDir } from '@midscene/shared/common';\nimport {\n MIDSCENE_REPORT_QUIET,\n globalConfigManager,\n} from '@midscene/shared/env';\nimport { ifInBrowser, logMsg, uuid } from '@midscene/shared/utils';\nimport {\n generateDumpScriptTag,\n generateImageScriptTag,\n getBaseUrlFixScript,\n} from './dump/html-utils';\nimport { ScreenshotStore } from './dump/screenshot-store';\nimport {\n type ExecutionDump,\n ReportActionDump,\n type ReportAttributes,\n type ReportMeta,\n} from './types';\nimport { getReportTpl } from './utils';\n\nexport interface IReportGenerator {\n /**\n * Write or update a single execution.\n * Each call appends a new dump script tag. The frontend deduplicates\n * executions with the same id/name, keeping only the last one.\n *\n * @param execution Current execution's full data\n * @param reportMeta Report-level metadata (groupName, sdkVersion, etc.)\n */\n onExecutionUpdate(\n execution: ExecutionDump,\n reportMeta: ReportMeta,\n attributes?: ReportAttributes,\n ): void;\n\n /**\n * @deprecated Use onExecutionUpdate instead. Kept for backward compatibility.\n */\n onDumpUpdate?(dump: ReportActionDump): void;\n\n /**\n * Wait for all queued write operations to complete.\n */\n flush(): Promise<void>;\n\n /**\n * Finalize the report. Calls flush() internally.\n */\n finalize(): Promise<string | undefined>;\n\n getReportPath(): string | undefined;\n}\n\nexport const nullReportGenerator: IReportGenerator = {\n onExecutionUpdate: () => {},\n flush: async () => {},\n finalize: async () => undefined,\n getReportPath: () => undefined,\n};\n\nexport function assertReportGenerationOptions(opts: {\n generateReport?: boolean;\n persistExecutionDump?: boolean;\n}): void {\n if (opts.generateReport === false && opts.persistExecutionDump === true) {\n throw new Error(\n 'persistExecutionDump cannot be true when generateReport is false',\n );\n }\n}\n\nexport class ReportGenerator implements IReportGenerator {\n private reportPath: string;\n private screenshotMode: 'inline' | 'directory';\n private shouldPersistExecutionDump: boolean;\n private autoPrint: boolean;\n private firstWriteDone = false;\n private executionLogIndex = 0;\n private executionLogFileIndexByExecutionKey = new Map<string, number>();\n\n // Unique identifier for this report stream — used as data-group-id\n private readonly reportStreamId: string;\n\n // Tracks screenshots already written to disk (by id) to avoid duplicates\n private screenshotStore: ScreenshotStore;\n private initialized = false;\n\n // Tracks the last execution + groupMeta for re-writing on finalize\n private lastExecution?: ExecutionDump;\n private lastReportMeta?: ReportMeta;\n private reportAttributes: Record<string, string> = {};\n\n // write queue for serial execution\n private writeQueue: Promise<void> = Promise.resolve();\n private destroyed = false;\n\n constructor(options: {\n reportPath: string;\n screenshotMode: 'inline' | 'directory';\n persistExecutionDump?: boolean;\n autoPrint?: boolean;\n reuseExistingReport?: boolean;\n }) {\n this.reportPath = options.reportPath;\n this.screenshotMode = options.screenshotMode;\n this.shouldPersistExecutionDump = options.persistExecutionDump ?? false;\n this.autoPrint = options.autoPrint ?? true;\n this.reportStreamId = uuid();\n this.screenshotStore = new ScreenshotStore({\n mode: this.screenshotMode === 'inline' ? 'inline' : 'directory',\n reportPath: this.reportPath,\n screenshotsDir: join(dirname(this.reportPath), 'screenshots'),\n writeInlineImage: async (id, base64) => {\n await appendFileAsync(\n this.reportPath,\n `\\n${generateImageScriptTag(id, base64)}`,\n );\n },\n alsoWriteFileCopy: this.shouldPersistExecutionDump,\n });\n if (options.reuseExistingReport) {\n this.hydrateStateFromExistingReport();\n }\n this.printReportPath('will be generated at');\n }\n\n static create(\n reportFileName: string,\n opts: {\n generateReport?: boolean;\n persistExecutionDump?: boolean;\n outputFormat?: 'single-html' | 'html-and-external-assets';\n autoPrintReportMsg?: boolean;\n reuseExistingReport?: boolean;\n },\n ): IReportGenerator {\n assertReportGenerationOptions(opts);\n validateReportFileName(reportFileName);\n if (opts.generateReport === false) return nullReportGenerator;\n\n // In browser environment, file system is not available\n if (ifInBrowser) return nullReportGenerator;\n\n const reportRootDir = getMidsceneRunSubDir('report');\n const outputDir = join(reportRootDir, reportFileName);\n const reportPath =\n opts.outputFormat === 'html-and-external-assets'\n ? join(outputDir, 'index.html')\n : join(reportRootDir, ensureHtmlFileName(reportFileName));\n return new ReportGenerator({\n reportPath,\n screenshotMode:\n opts.outputFormat === 'html-and-external-assets'\n ? 'directory'\n : 'inline',\n persistExecutionDump: opts.persistExecutionDump,\n autoPrint: opts.autoPrintReportMsg,\n reuseExistingReport: opts.reuseExistingReport,\n });\n }\n\n onExecutionUpdate(\n execution: ExecutionDump,\n reportMeta: ReportMeta,\n attributes?: ReportAttributes,\n ): void {\n this.lastExecution = execution;\n this.lastReportMeta = reportMeta;\n this.mergeReportAttributes(attributes);\n this.writeQueue = this.writeQueue.then(async () => {\n if (this.destroyed) return;\n await this.doWriteExecution(execution, reportMeta);\n });\n }\n\n async flush(): Promise<void> {\n await this.writeQueue;\n }\n\n async finalize(): Promise<string | undefined> {\n // Re-write the last execution to capture any final state changes\n if (this.lastExecution && this.lastReportMeta) {\n this.onExecutionUpdate(this.lastExecution, this.lastReportMeta);\n }\n await this.flush();\n this.destroyed = true;\n\n if (!this.initialized) {\n // No executions were ever written — no file exists\n return undefined;\n }\n\n this.printReportPath('finalized');\n return this.reportPath;\n }\n\n getReportPath(): string | undefined {\n return this.reportPath;\n }\n\n private printReportPath(verb: string): void {\n if (!this.autoPrint || !this.reportPath) return;\n if (globalConfigManager.getEnvConfigInBoolean(MIDSCENE_REPORT_QUIET))\n return;\n\n if (this.screenshotMode === 'directory') {\n logMsg(\n `Midscene - report ${verb}: npx serve ${dirname(this.reportPath)}`,\n );\n } else {\n logMsg(`Midscene - report ${verb}: ${this.reportPath}`);\n }\n }\n\n private async doWriteExecution(\n execution: ExecutionDump,\n reportMeta: ReportMeta,\n ): Promise<void> {\n const singleDump = this.wrapAsReportDump(execution, reportMeta);\n\n if (this.screenshotMode === 'inline') {\n await this.writeInlineExecution(execution, singleDump);\n } else {\n await this.writeDirectoryExecution(execution, singleDump);\n }\n\n if (this.shouldPersistExecutionDump) {\n await this.persistExecutionDumpToFile(execution, singleDump);\n }\n\n if (!this.firstWriteDone) {\n this.firstWriteDone = true;\n this.printReportPath('generated');\n }\n }\n\n private mergeReportAttributes(attributes?: ReportAttributes): void {\n if (!attributes) {\n return;\n }\n\n for (const [key, value] of Object.entries(attributes)) {\n if (value === undefined || value === null) {\n continue;\n }\n this.reportAttributes[key] = String(value);\n }\n }\n\n private hydrateStateFromExistingReport(): void {\n if (!existsSync(this.reportPath)) {\n return;\n }\n\n // Reuse existing report file and append new updates instead of rewriting.\n this.initialized = true;\n\n if (!this.shouldPersistExecutionDump) {\n return;\n }\n\n const reportDir = dirname(this.reportPath);\n const existingExecutionIndices = readdirSync(reportDir)\n .map((name) => /^(\\d+)\\.execution\\.json$/.exec(name)?.[1])\n .filter((index): index is string => Boolean(index))\n .map((index) => Number.parseInt(index, 10))\n .filter((index) => Number.isFinite(index));\n\n if (existingExecutionIndices.length > 0) {\n this.executionLogIndex = Math.max(...existingExecutionIndices);\n }\n }\n\n private getDumpScriptAttributes(): Record<string, string> {\n return {\n 'data-group-id': this.reportStreamId,\n ...this.reportAttributes,\n };\n }\n\n /**\n * Wrap an ExecutionDump + ReportMeta into a single-execution ReportActionDump.\n */\n private wrapAsReportDump(\n execution: ExecutionDump,\n reportMeta: ReportMeta,\n ): ReportActionDump {\n return new ReportActionDump({\n sdkVersion: reportMeta.sdkVersion,\n groupName: reportMeta.groupName,\n groupDescription: reportMeta.groupDescription,\n modelBriefs: reportMeta.modelBriefs,\n deviceType: reportMeta.deviceType,\n executions: [execution],\n });\n }\n\n /**\n * Append-only inline mode: write new screenshots and a dump tag on every call.\n * The frontend deduplicates executions with the same id/name (keeps last).\n * Duplicate dump JSON is acceptable; only screenshots are deduplicated.\n *\n * All writes go through `fs/promises` so they run on libuv's thread pool\n * rather than blocking the Node event loop. A long agent run previously\n * appended multi-MB dumps (screenshots + serialized tasks) per progress\n * tick on the main thread, starving IPC and UI for >10s per stall.\n */\n private async writeInlineExecution(\n execution: ExecutionDump,\n singleDump: ReportActionDump,\n ): Promise<void> {\n const dir = dirname(this.reportPath);\n if (!existsSync(dir)) {\n mkdirSync(dir, { recursive: true });\n }\n\n // Initialize: write HTML template once\n if (!this.initialized) {\n await writeFileAsync(this.reportPath, getReportTpl());\n this.initialized = true;\n }\n\n // Append new screenshots (skip already-written ones)\n for (const screenshot of execution.collectScreenshots()) {\n await this.screenshotStore.persist(screenshot);\n }\n\n // Append dump tag (always — frontend keeps only last per execution id)\n const serialized = singleDump.serialize();\n await appendFileAsync(\n this.reportPath,\n `\\n${generateDumpScriptTag(serialized, this.getDumpScriptAttributes())}`,\n );\n }\n\n private async writeDirectoryExecution(\n execution: ExecutionDump,\n singleDump: ReportActionDump,\n ): Promise<void> {\n const dir = dirname(this.reportPath);\n if (!existsSync(dir)) {\n mkdirSync(dir, { recursive: true });\n }\n\n for (const screenshot of execution.collectScreenshots()) {\n await this.screenshotStore.persist(screenshot);\n }\n\n // 2. Append dump tag (always — frontend keeps only last per execution id)\n const serialized = singleDump.serialize();\n\n if (!this.initialized) {\n await writeFileAsync(\n this.reportPath,\n `${getReportTpl()}${getBaseUrlFixScript()}`,\n );\n this.initialized = true;\n }\n\n await appendFileAsync(\n this.reportPath,\n `\\n${generateDumpScriptTag(serialized, this.getDumpScriptAttributes())}`,\n );\n }\n\n private getExecutionLogKey(execution: ExecutionDump): string {\n if (!execution.id) {\n throw new Error(\n 'ReportGenerator: execution.id is required for persisting execution dumps',\n );\n }\n return `id:${execution.id}`;\n }\n\n private async persistExecutionDumpToFile(\n execution: ExecutionDump,\n singleDump: ReportActionDump,\n ): Promise<void> {\n const dir = dirname(this.reportPath);\n if (!existsSync(dir)) {\n mkdirSync(dir, { recursive: true });\n }\n\n const executionLogKey = this.getExecutionLogKey(execution);\n let fileIndex =\n this.executionLogFileIndexByExecutionKey.get(executionLogKey);\n if (!fileIndex) {\n this.executionLogIndex += 1;\n fileIndex = this.executionLogIndex;\n this.executionLogFileIndexByExecutionKey.set(executionLogKey, fileIndex);\n }\n\n const fileName = `${fileIndex}.execution.json`;\n const filePath = join(dirname(this.reportPath), fileName);\n await writeFileAsync(filePath, singleDump.serialize(2), 'utf-8');\n }\n}\n\nfunction ensureHtmlFileName(reportFileName: string): string {\n return reportFileName.endsWith('.html')\n ? reportFileName\n : `${reportFileName}.html`;\n}\n\nfunction validateReportFileName(reportFileName: string): void {\n if (!reportFileName?.trim()) {\n throw new Error('reportFileName must be a non-empty string');\n }\n\n if (/[\\\\/]/.test(reportFileName)) {\n throw new Error(\n 'reportFileName must not contain path separators (`/` or `\\\\\\\\`)',\n );\n }\n\n if (/[:*?\"<>|]/.test(reportFileName)) {\n throw new Error(\n 'reportFileName contains illegal filename characters: : * ? \" < > |',\n );\n }\n}\n"],"names":["__webpack_require__","definition","key","Object","obj","prop","Symbol","nullReportGenerator","undefined","assertReportGenerationOptions","opts","Error","ReportGenerator","reportFileName","validateReportFileName","ifInBrowser","reportRootDir","getMidsceneRunSubDir","outputDir","join","reportPath","ensureHtmlFileName","execution","reportMeta","attributes","verb","globalConfigManager","MIDSCENE_REPORT_QUIET","logMsg","dirname","singleDump","value","String","existsSync","reportDir","existingExecutionIndices","readdirSync","name","index","Boolean","Number","Math","ReportActionDump","dir","mkdirSync","writeFileAsync","getReportTpl","screenshot","serialized","appendFileAsync","generateDumpScriptTag","getBaseUrlFixScript","executionLogKey","fileIndex","fileName","filePath","options","Map","Promise","uuid","ScreenshotStore","id","base64","generateImageScriptTag"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"report-generator.js","sources":["webpack/runtime/define_property_getters","webpack/runtime/has_own_property","webpack/runtime/make_namespace_object","../../src/report-generator.ts"],"sourcesContent":["__webpack_require__.d = (exports, definition) => {\n\tfor(var key in definition) {\n if(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {\n Object.defineProperty(exports, key, { enumerable: true, get: definition[key] });\n }\n }\n};","__webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))","// define __esModule on exports\n__webpack_require__.r = (exports) => {\n\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n\t}\n\tObject.defineProperty(exports, '__esModule', { value: true });\n};","/*\n * PERF INVARIANT — DO NOT reintroduce sync fs APIs (writeFileSync /\n * appendFileSync) in this file's write paths. `ReportGenerator` runs on\n * the Electron main event loop during agent execution, and a single\n * progress tick appends a multi-MB ExecutionDump payload. Sync I/O here\n * blocked the loop for 20+ seconds per run, freezing IPC, scrcpy and\n * every renderer round-trip. Always use `fs/promises`. See commit\n * 6a25e05c and `report-generator-async-contract.test.ts`.\n */\nimport { existsSync, mkdirSync, readdirSync } from 'node:fs';\nimport {\n appendFile as appendFileAsync,\n writeFile as writeFileAsync,\n} from 'node:fs/promises';\nimport { dirname, join } from 'node:path';\nimport { getMidsceneRunSubDir } from '@midscene/shared/common';\nimport {\n MIDSCENE_REPORT_QUIET,\n globalConfigManager,\n} from '@midscene/shared/env';\nimport { ifInBrowser, logMsg, uuid } from '@midscene/shared/utils';\nimport {\n generateDumpScriptTag,\n generateImageScriptTag,\n getBaseUrlFixScript,\n} from './dump/html-utils';\nimport { ScreenshotStore } from './dump/screenshot-store';\nimport {\n type ExecutionDump,\n ReportActionDump,\n type ReportAttributes,\n type ReportMeta,\n} from './types';\nimport { getReportTpl } from './utils';\n\nexport interface IReportGenerator {\n /**\n * Write or update a single execution.\n * Each call appends a new dump script tag. The frontend deduplicates\n * executions with the same id/name, keeping only the last one.\n *\n * @param execution Current execution's full data\n * @param reportMeta Report-level metadata (groupName, sdkVersion, etc.)\n */\n onExecutionUpdate(\n execution: ExecutionDump,\n reportMeta: ReportMeta,\n attributes?: ReportAttributes,\n ): void;\n\n /**\n * @deprecated Use onExecutionUpdate instead. Kept for backward compatibility.\n */\n onDumpUpdate?(dump: ReportActionDump): void;\n\n /**\n * Wait for all queued write operations to complete.\n */\n flush(): Promise<void>;\n\n /**\n * Finalize the report. Calls flush() internally.\n */\n finalize(): Promise<string | undefined>;\n\n getReportPath(): string | undefined;\n}\n\nexport const nullReportGenerator: IReportGenerator = {\n onExecutionUpdate: () => {},\n flush: async () => {},\n finalize: async () => undefined,\n getReportPath: () => undefined,\n};\n\nexport function assertReportGenerationOptions(opts: {\n generateReport?: boolean;\n persistExecutionDump?: boolean;\n}): void {\n if (opts.generateReport === false && opts.persistExecutionDump === true) {\n throw new Error(\n 'persistExecutionDump cannot be true when generateReport is false',\n );\n }\n}\n\nexport class ReportGenerator implements IReportGenerator {\n private reportPath: string;\n private screenshotMode: 'inline' | 'directory';\n private shouldPersistExecutionDump: boolean;\n private autoPrint: boolean;\n private firstWriteDone = false;\n private executionLogIndex = 0;\n private executionLogFileIndexByExecutionKey = new Map<string, number>();\n\n // Unique identifier for this report stream — used as data-group-id\n private readonly reportStreamId: string;\n\n // Tracks screenshots already written to disk (by id) to avoid duplicates\n private screenshotStore: ScreenshotStore;\n private initialized = false;\n\n // Tracks the last execution + groupMeta for re-writing on finalize\n private lastExecution?: ExecutionDump;\n private lastReportMeta?: ReportMeta;\n private reportAttributes: Record<string, string> = {};\n\n // write queue for serial execution\n private writeQueue: Promise<void> = Promise.resolve();\n private destroyed = false;\n\n constructor(options: {\n reportPath: string;\n screenshotMode: 'inline' | 'directory';\n persistExecutionDump?: boolean;\n autoPrint?: boolean;\n reuseExistingReport?: boolean;\n }) {\n this.reportPath = options.reportPath;\n this.screenshotMode = options.screenshotMode;\n this.shouldPersistExecutionDump = options.persistExecutionDump ?? false;\n this.autoPrint = options.autoPrint ?? true;\n this.reportStreamId = uuid();\n this.screenshotStore = new ScreenshotStore({\n mode: this.screenshotMode === 'inline' ? 'inline' : 'directory',\n reportPath: this.reportPath,\n screenshotsDir: join(dirname(this.reportPath), 'screenshots'),\n writeInlineImage: async (id, base64) => {\n await appendFileAsync(\n this.reportPath,\n `\\n${generateImageScriptTag(id, base64)}`,\n );\n },\n alsoWriteFileCopy: this.shouldPersistExecutionDump,\n });\n if (options.reuseExistingReport) {\n this.hydrateStateFromExistingReport();\n }\n }\n\n static create(\n reportFileName: string,\n opts: {\n generateReport?: boolean;\n persistExecutionDump?: boolean;\n outputFormat?: 'single-html' | 'html-and-external-assets';\n autoPrintReportMsg?: boolean;\n reuseExistingReport?: boolean;\n },\n ): IReportGenerator {\n assertReportGenerationOptions(opts);\n validateReportFileName(reportFileName);\n if (opts.generateReport === false) return nullReportGenerator;\n\n // In browser environment, file system is not available\n if (ifInBrowser) return nullReportGenerator;\n\n const reportRootDir = getMidsceneRunSubDir('report');\n const outputDir = join(reportRootDir, reportFileName);\n const reportPath =\n opts.outputFormat === 'html-and-external-assets'\n ? join(outputDir, 'index.html')\n : join(reportRootDir, ensureHtmlFileName(reportFileName));\n return new ReportGenerator({\n reportPath,\n screenshotMode:\n opts.outputFormat === 'html-and-external-assets'\n ? 'directory'\n : 'inline',\n persistExecutionDump: opts.persistExecutionDump,\n autoPrint: opts.autoPrintReportMsg,\n reuseExistingReport: opts.reuseExistingReport,\n });\n }\n\n onExecutionUpdate(\n execution: ExecutionDump,\n reportMeta: ReportMeta,\n attributes?: ReportAttributes,\n ): void {\n this.lastExecution = execution;\n this.lastReportMeta = reportMeta;\n this.mergeReportAttributes(attributes);\n this.writeQueue = this.writeQueue.then(async () => {\n if (this.destroyed) return;\n await this.doWriteExecution(execution, reportMeta);\n });\n }\n\n async flush(): Promise<void> {\n await this.writeQueue;\n }\n\n async finalize(): Promise<string | undefined> {\n // Re-write the last execution to capture any final state changes\n if (this.lastExecution && this.lastReportMeta) {\n this.onExecutionUpdate(this.lastExecution, this.lastReportMeta);\n }\n await this.flush();\n this.destroyed = true;\n\n if (!this.initialized) {\n // No executions were ever written — no file exists\n return undefined;\n }\n\n return this.reportPath;\n }\n\n getReportPath(): string | undefined {\n return this.reportPath;\n }\n\n private printReportPath(): void {\n if (!this.autoPrint || !this.reportPath) return;\n if (globalConfigManager.getEnvConfigInBoolean(MIDSCENE_REPORT_QUIET))\n return;\n\n if (this.screenshotMode === 'directory') {\n logMsg(\n `Midscene - report file updated: npx serve ${dirname(this.reportPath)}`,\n );\n } else {\n logMsg(`Midscene - report file updated: ${this.reportPath}`);\n }\n }\n\n private async doWriteExecution(\n execution: ExecutionDump,\n reportMeta: ReportMeta,\n ): Promise<void> {\n const singleDump = this.wrapAsReportDump(execution, reportMeta);\n\n if (this.screenshotMode === 'inline') {\n await this.writeInlineExecution(execution, singleDump);\n } else {\n await this.writeDirectoryExecution(execution, singleDump);\n }\n\n if (this.shouldPersistExecutionDump) {\n await this.persistExecutionDumpToFile(execution, singleDump);\n }\n\n if (!this.firstWriteDone) {\n this.firstWriteDone = true;\n this.printReportPath();\n }\n }\n\n private mergeReportAttributes(attributes?: ReportAttributes): void {\n if (!attributes) {\n return;\n }\n\n for (const [key, value] of Object.entries(attributes)) {\n if (value === undefined || value === null) {\n continue;\n }\n this.reportAttributes[key] = String(value);\n }\n }\n\n private hydrateStateFromExistingReport(): void {\n if (!existsSync(this.reportPath)) {\n return;\n }\n\n // Reuse existing report file and append new updates instead of rewriting.\n this.initialized = true;\n\n if (!this.shouldPersistExecutionDump) {\n return;\n }\n\n const reportDir = dirname(this.reportPath);\n const existingExecutionIndices = readdirSync(reportDir)\n .map((name) => /^(\\d+)\\.execution\\.json$/.exec(name)?.[1])\n .filter((index): index is string => Boolean(index))\n .map((index) => Number.parseInt(index, 10))\n .filter((index) => Number.isFinite(index));\n\n if (existingExecutionIndices.length > 0) {\n this.executionLogIndex = Math.max(...existingExecutionIndices);\n }\n }\n\n private getDumpScriptAttributes(): Record<string, string> {\n return {\n 'data-group-id': this.reportStreamId,\n ...this.reportAttributes,\n };\n }\n\n /**\n * Wrap an ExecutionDump + ReportMeta into a single-execution ReportActionDump.\n */\n private wrapAsReportDump(\n execution: ExecutionDump,\n reportMeta: ReportMeta,\n ): ReportActionDump {\n return new ReportActionDump({\n sdkVersion: reportMeta.sdkVersion,\n groupName: reportMeta.groupName,\n groupDescription: reportMeta.groupDescription,\n modelBriefs: reportMeta.modelBriefs,\n deviceType: reportMeta.deviceType,\n executions: [execution],\n });\n }\n\n /**\n * Append-only inline mode: write new screenshots and a dump tag on every call.\n * The frontend deduplicates executions with the same id/name (keeps last).\n * Duplicate dump JSON is acceptable; only screenshots are deduplicated.\n *\n * All writes go through `fs/promises` so they run on libuv's thread pool\n * rather than blocking the Node event loop. A long agent run previously\n * appended multi-MB dumps (screenshots + serialized tasks) per progress\n * tick on the main thread, starving IPC and UI for >10s per stall.\n */\n private async writeInlineExecution(\n execution: ExecutionDump,\n singleDump: ReportActionDump,\n ): Promise<void> {\n const dir = dirname(this.reportPath);\n if (!existsSync(dir)) {\n mkdirSync(dir, { recursive: true });\n }\n\n // Initialize: write HTML template once\n if (!this.initialized) {\n await writeFileAsync(this.reportPath, getReportTpl());\n this.initialized = true;\n }\n\n // Append new screenshots (skip already-written ones)\n for (const screenshot of execution.collectScreenshots()) {\n await this.screenshotStore.persist(screenshot);\n }\n\n // Append dump tag (always — frontend keeps only last per execution id)\n const serialized = singleDump.serialize();\n await appendFileAsync(\n this.reportPath,\n `\\n${generateDumpScriptTag(serialized, this.getDumpScriptAttributes())}`,\n );\n }\n\n private async writeDirectoryExecution(\n execution: ExecutionDump,\n singleDump: ReportActionDump,\n ): Promise<void> {\n const dir = dirname(this.reportPath);\n if (!existsSync(dir)) {\n mkdirSync(dir, { recursive: true });\n }\n\n for (const screenshot of execution.collectScreenshots()) {\n await this.screenshotStore.persist(screenshot);\n }\n\n // 2. Append dump tag (always — frontend keeps only last per execution id)\n const serialized = singleDump.serialize();\n\n if (!this.initialized) {\n await writeFileAsync(\n this.reportPath,\n `${getReportTpl()}${getBaseUrlFixScript()}`,\n );\n this.initialized = true;\n }\n\n await appendFileAsync(\n this.reportPath,\n `\\n${generateDumpScriptTag(serialized, this.getDumpScriptAttributes())}`,\n );\n }\n\n private getExecutionLogKey(execution: ExecutionDump): string {\n if (!execution.id) {\n throw new Error(\n 'ReportGenerator: execution.id is required for persisting execution dumps',\n );\n }\n return `id:${execution.id}`;\n }\n\n private async persistExecutionDumpToFile(\n execution: ExecutionDump,\n singleDump: ReportActionDump,\n ): Promise<void> {\n const dir = dirname(this.reportPath);\n if (!existsSync(dir)) {\n mkdirSync(dir, { recursive: true });\n }\n\n const executionLogKey = this.getExecutionLogKey(execution);\n let fileIndex =\n this.executionLogFileIndexByExecutionKey.get(executionLogKey);\n if (!fileIndex) {\n this.executionLogIndex += 1;\n fileIndex = this.executionLogIndex;\n this.executionLogFileIndexByExecutionKey.set(executionLogKey, fileIndex);\n }\n\n const fileName = `${fileIndex}.execution.json`;\n const filePath = join(dirname(this.reportPath), fileName);\n await writeFileAsync(filePath, singleDump.serialize(2), 'utf-8');\n }\n}\n\nfunction ensureHtmlFileName(reportFileName: string): string {\n return reportFileName.endsWith('.html')\n ? reportFileName\n : `${reportFileName}.html`;\n}\n\nfunction validateReportFileName(reportFileName: string): void {\n if (!reportFileName?.trim()) {\n throw new Error('reportFileName must be a non-empty string');\n }\n\n if (/[\\\\/]/.test(reportFileName)) {\n throw new Error(\n 'reportFileName must not contain path separators (`/` or `\\\\\\\\`)',\n );\n }\n\n if (/[:*?\"<>|]/.test(reportFileName)) {\n throw new Error(\n 'reportFileName contains illegal filename characters: : * ? \" < > |',\n );\n }\n}\n"],"names":["__webpack_require__","definition","key","Object","obj","prop","Symbol","nullReportGenerator","undefined","assertReportGenerationOptions","opts","Error","ReportGenerator","reportFileName","validateReportFileName","ifInBrowser","reportRootDir","getMidsceneRunSubDir","outputDir","join","reportPath","ensureHtmlFileName","execution","reportMeta","attributes","globalConfigManager","MIDSCENE_REPORT_QUIET","logMsg","dirname","singleDump","value","String","existsSync","reportDir","existingExecutionIndices","readdirSync","name","index","Boolean","Number","Math","ReportActionDump","dir","mkdirSync","writeFileAsync","getReportTpl","screenshot","serialized","appendFileAsync","generateDumpScriptTag","getBaseUrlFixScript","executionLogKey","fileIndex","fileName","filePath","options","Map","Promise","uuid","ScreenshotStore","id","base64","generateImageScriptTag"],"mappings":"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"}
|
|
@@ -188,7 +188,7 @@ class Service {
|
|
|
188
188
|
}
|
|
189
189
|
};
|
|
190
190
|
}
|
|
191
|
-
async extract(dataDemand, modelRuntime, opt, pageDescription, multimodalPrompt, context) {
|
|
191
|
+
async extract(dataDemand, modelRuntime, opt, pageDescription, multimodalPrompt, context, executionOptions) {
|
|
192
192
|
(0, utils_namespaceObject.assert)(context, 'context is required for extract');
|
|
193
193
|
(0, utils_namespaceObject.assert)('object' == typeof dataDemand || 'string' == typeof dataDemand, `dataDemand should be object or string, but get ${typeof dataDemand}`);
|
|
194
194
|
const startTime = Date.now();
|
|
@@ -204,7 +204,8 @@ class Service {
|
|
|
204
204
|
multimodalPrompt,
|
|
205
205
|
extractOption: opt,
|
|
206
206
|
modelRuntime,
|
|
207
|
-
pageDescription
|
|
207
|
+
pageDescription,
|
|
208
|
+
abortSignal: executionOptions?.abortSignal
|
|
208
209
|
});
|
|
209
210
|
parseResult = result.parseResult;
|
|
210
211
|
rawResponse = result.rawResponse;
|