@godscene/core 1.7.11
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/LICENSE +21 -0
- package/README.md +9 -0
- package/dist/es/agent/agent.mjs +767 -0
- package/dist/es/agent/common.mjs +0 -0
- package/dist/es/agent/execution-session.mjs +39 -0
- package/dist/es/agent/index.mjs +6 -0
- package/dist/es/agent/task-builder.mjs +343 -0
- package/dist/es/agent/task-cache.mjs +212 -0
- package/dist/es/agent/tasks.mjs +428 -0
- package/dist/es/agent/ui-utils.mjs +101 -0
- package/dist/es/agent/utils.mjs +167 -0
- package/dist/es/ai-model/auto-glm/actions.mjs +237 -0
- package/dist/es/ai-model/auto-glm/index.mjs +6 -0
- package/dist/es/ai-model/auto-glm/parser.mjs +237 -0
- package/dist/es/ai-model/auto-glm/planning.mjs +69 -0
- package/dist/es/ai-model/auto-glm/prompt.mjs +220 -0
- package/dist/es/ai-model/auto-glm/util.mjs +7 -0
- package/dist/es/ai-model/connectivity.mjs +136 -0
- package/dist/es/ai-model/conversation-history.mjs +193 -0
- package/dist/es/ai-model/index.mjs +12 -0
- package/dist/es/ai-model/inspect.mjs +395 -0
- package/dist/es/ai-model/llm-planning.mjs +231 -0
- package/dist/es/ai-model/prompt/common.mjs +5 -0
- package/dist/es/ai-model/prompt/describe.mjs +64 -0
- package/dist/es/ai-model/prompt/extraction.mjs +129 -0
- package/dist/es/ai-model/prompt/llm-locator.mjs +49 -0
- package/dist/es/ai-model/prompt/llm-planning.mjs +584 -0
- package/dist/es/ai-model/prompt/llm-section-locator.mjs +42 -0
- package/dist/es/ai-model/prompt/order-sensitive-judge.mjs +33 -0
- package/dist/es/ai-model/prompt/playwright-generator.mjs +115 -0
- package/dist/es/ai-model/prompt/ui-tars-planning.mjs +34 -0
- package/dist/es/ai-model/prompt/util.mjs +57 -0
- package/dist/es/ai-model/prompt/yaml-generator.mjs +201 -0
- package/dist/es/ai-model/service-caller/codex-app-server.mjs +573 -0
- package/dist/es/ai-model/service-caller/image-detail.mjs +4 -0
- package/dist/es/ai-model/service-caller/index.mjs +648 -0
- package/dist/es/ai-model/service-caller/request-timeout.mjs +47 -0
- package/dist/es/ai-model/ui-tars-planning.mjs +247 -0
- package/dist/es/common.mjs +382 -0
- package/dist/es/device/device-options.mjs +0 -0
- package/dist/es/device/index.mjs +340 -0
- package/dist/es/dump/html-utils.mjs +290 -0
- package/dist/es/dump/index.mjs +3 -0
- package/dist/es/dump/screenshot-restoration.mjs +30 -0
- package/dist/es/dump/screenshot-store.mjs +125 -0
- package/dist/es/index.mjs +17 -0
- package/dist/es/report-cli.mjs +149 -0
- package/dist/es/report-generator.mjs +203 -0
- package/dist/es/report-markdown.mjs +216 -0
- package/dist/es/report.mjs +287 -0
- package/dist/es/screenshot-item.mjs +120 -0
- package/dist/es/service/index.mjs +272 -0
- package/dist/es/service/utils.mjs +13 -0
- package/dist/es/skill/index.mjs +35 -0
- package/dist/es/task-runner.mjs +261 -0
- package/dist/es/task-timing.mjs +10 -0
- package/dist/es/tree.mjs +11 -0
- package/dist/es/types.mjs +202 -0
- package/dist/es/utils.mjs +232 -0
- package/dist/es/yaml/builder.mjs +11 -0
- package/dist/es/yaml/index.mjs +4 -0
- package/dist/es/yaml/player.mjs +425 -0
- package/dist/es/yaml/utils.mjs +100 -0
- package/dist/es/yaml.mjs +0 -0
- package/dist/lib/agent/agent.js +815 -0
- package/dist/lib/agent/common.js +5 -0
- package/dist/lib/agent/execution-session.js +73 -0
- package/dist/lib/agent/index.js +76 -0
- package/dist/lib/agent/task-builder.js +380 -0
- package/dist/lib/agent/task-cache.js +264 -0
- package/dist/lib/agent/tasks.js +471 -0
- package/dist/lib/agent/ui-utils.js +153 -0
- package/dist/lib/agent/utils.js +238 -0
- package/dist/lib/ai-model/auto-glm/actions.js +271 -0
- package/dist/lib/ai-model/auto-glm/index.js +64 -0
- package/dist/lib/ai-model/auto-glm/parser.js +280 -0
- package/dist/lib/ai-model/auto-glm/planning.js +103 -0
- package/dist/lib/ai-model/auto-glm/prompt.js +257 -0
- package/dist/lib/ai-model/auto-glm/util.js +44 -0
- package/dist/lib/ai-model/connectivity.js +180 -0
- package/dist/lib/ai-model/conversation-history.js +227 -0
- package/dist/lib/ai-model/index.js +127 -0
- package/dist/lib/ai-model/inspect.js +441 -0
- package/dist/lib/ai-model/llm-planning.js +268 -0
- package/dist/lib/ai-model/prompt/common.js +39 -0
- package/dist/lib/ai-model/prompt/describe.js +98 -0
- package/dist/lib/ai-model/prompt/extraction.js +169 -0
- package/dist/lib/ai-model/prompt/llm-locator.js +86 -0
- package/dist/lib/ai-model/prompt/llm-planning.js +621 -0
- package/dist/lib/ai-model/prompt/llm-section-locator.js +79 -0
- package/dist/lib/ai-model/prompt/order-sensitive-judge.js +70 -0
- package/dist/lib/ai-model/prompt/playwright-generator.js +176 -0
- package/dist/lib/ai-model/prompt/ui-tars-planning.js +71 -0
- package/dist/lib/ai-model/prompt/util.js +103 -0
- package/dist/lib/ai-model/prompt/yaml-generator.js +262 -0
- package/dist/lib/ai-model/service-caller/codex-app-server.js +622 -0
- package/dist/lib/ai-model/service-caller/image-detail.js +38 -0
- package/dist/lib/ai-model/service-caller/index.js +716 -0
- package/dist/lib/ai-model/service-caller/request-timeout.js +93 -0
- package/dist/lib/ai-model/ui-tars-planning.js +281 -0
- package/dist/lib/common.js +491 -0
- package/dist/lib/device/device-options.js +18 -0
- package/dist/lib/device/index.js +467 -0
- package/dist/lib/dump/html-utils.js +366 -0
- package/dist/lib/dump/index.js +58 -0
- package/dist/lib/dump/screenshot-restoration.js +64 -0
- package/dist/lib/dump/screenshot-store.js +165 -0
- package/dist/lib/index.js +184 -0
- package/dist/lib/report-cli.js +189 -0
- package/dist/lib/report-generator.js +244 -0
- package/dist/lib/report-markdown.js +253 -0
- package/dist/lib/report.js +333 -0
- package/dist/lib/screenshot-item.js +154 -0
- package/dist/lib/service/index.js +306 -0
- package/dist/lib/service/utils.js +47 -0
- package/dist/lib/skill/index.js +69 -0
- package/dist/lib/task-runner.js +298 -0
- package/dist/lib/task-timing.js +44 -0
- package/dist/lib/tree.js +51 -0
- package/dist/lib/types.js +298 -0
- package/dist/lib/utils.js +314 -0
- package/dist/lib/yaml/builder.js +55 -0
- package/dist/lib/yaml/index.js +79 -0
- package/dist/lib/yaml/player.js +459 -0
- package/dist/lib/yaml/utils.js +153 -0
- package/dist/lib/yaml.js +18 -0
- package/dist/types/agent/agent.d.ts +220 -0
- package/dist/types/agent/common.d.ts +0 -0
- package/dist/types/agent/execution-session.d.ts +36 -0
- package/dist/types/agent/index.d.ts +9 -0
- package/dist/types/agent/task-builder.d.ts +34 -0
- package/dist/types/agent/task-cache.d.ts +49 -0
- package/dist/types/agent/tasks.d.ts +70 -0
- package/dist/types/agent/ui-utils.d.ts +14 -0
- package/dist/types/agent/utils.d.ts +25 -0
- package/dist/types/ai-model/auto-glm/actions.d.ts +78 -0
- package/dist/types/ai-model/auto-glm/index.d.ts +6 -0
- package/dist/types/ai-model/auto-glm/parser.d.ts +18 -0
- package/dist/types/ai-model/auto-glm/planning.d.ts +12 -0
- package/dist/types/ai-model/auto-glm/prompt.d.ts +27 -0
- package/dist/types/ai-model/auto-glm/util.d.ts +13 -0
- package/dist/types/ai-model/connectivity.d.ts +20 -0
- package/dist/types/ai-model/conversation-history.d.ts +105 -0
- package/dist/types/ai-model/index.d.ts +16 -0
- package/dist/types/ai-model/inspect.d.ts +67 -0
- package/dist/types/ai-model/llm-planning.d.ts +19 -0
- package/dist/types/ai-model/prompt/common.d.ts +2 -0
- package/dist/types/ai-model/prompt/describe.d.ts +1 -0
- package/dist/types/ai-model/prompt/extraction.d.ts +7 -0
- package/dist/types/ai-model/prompt/llm-locator.d.ts +3 -0
- package/dist/types/ai-model/prompt/llm-planning.d.ts +10 -0
- package/dist/types/ai-model/prompt/llm-section-locator.d.ts +3 -0
- package/dist/types/ai-model/prompt/order-sensitive-judge.d.ts +2 -0
- package/dist/types/ai-model/prompt/playwright-generator.d.ts +26 -0
- package/dist/types/ai-model/prompt/ui-tars-planning.d.ts +2 -0
- package/dist/types/ai-model/prompt/util.d.ts +33 -0
- package/dist/types/ai-model/prompt/yaml-generator.d.ts +102 -0
- package/dist/types/ai-model/service-caller/codex-app-server.d.ts +42 -0
- package/dist/types/ai-model/service-caller/image-detail.d.ts +2 -0
- package/dist/types/ai-model/service-caller/index.d.ts +60 -0
- package/dist/types/ai-model/service-caller/request-timeout.d.ts +32 -0
- package/dist/types/ai-model/ui-tars-planning.d.ts +72 -0
- package/dist/types/common.d.ts +288 -0
- package/dist/types/device/device-options.d.ts +155 -0
- package/dist/types/device/index.d.ts +2565 -0
- package/dist/types/dump/html-utils.d.ts +75 -0
- package/dist/types/dump/index.d.ts +5 -0
- package/dist/types/dump/screenshot-restoration.d.ts +8 -0
- package/dist/types/dump/screenshot-store.d.ts +49 -0
- package/dist/types/index.d.ts +21 -0
- package/dist/types/report-cli.d.ts +36 -0
- package/dist/types/report-generator.d.ts +88 -0
- package/dist/types/report-markdown.d.ts +24 -0
- package/dist/types/report.d.ts +52 -0
- package/dist/types/screenshot-item.d.ts +67 -0
- package/dist/types/service/index.d.ts +24 -0
- package/dist/types/service/utils.d.ts +2 -0
- package/dist/types/skill/index.d.ts +25 -0
- package/dist/types/task-runner.d.ts +50 -0
- package/dist/types/task-timing.d.ts +8 -0
- package/dist/types/tree.d.ts +4 -0
- package/dist/types/types.d.ts +684 -0
- package/dist/types/utils.d.ts +45 -0
- package/dist/types/yaml/builder.d.ts +2 -0
- package/dist/types/yaml/index.d.ts +4 -0
- package/dist/types/yaml/player.d.ts +34 -0
- package/dist/types/yaml/utils.d.ts +9 -0
- package/dist/types/yaml.d.ts +215 -0
- package/package.json +130 -0
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
import { existsSync, mkdirSync, readFileSync, rmSync, writeFileSync } from "node:fs";
|
|
2
|
+
import { join } from "node:path";
|
|
3
|
+
import { restoreImageReferences } from "./dump/screenshot-restoration.mjs";
|
|
4
|
+
import { ScreenshotStore } from "./dump/screenshot-store.mjs";
|
|
5
|
+
import { ScreenshotItem } from "./screenshot-item.mjs";
|
|
6
|
+
export * from "./yaml.mjs";
|
|
7
|
+
function _define_property(obj, key, value) {
|
|
8
|
+
if (key in obj) Object.defineProperty(obj, key, {
|
|
9
|
+
value: value,
|
|
10
|
+
enumerable: true,
|
|
11
|
+
configurable: true,
|
|
12
|
+
writable: true
|
|
13
|
+
});
|
|
14
|
+
else obj[key] = value;
|
|
15
|
+
return obj;
|
|
16
|
+
}
|
|
17
|
+
class UIContext {
|
|
18
|
+
}
|
|
19
|
+
class ServiceError extends Error {
|
|
20
|
+
constructor(message, dump){
|
|
21
|
+
super(message), _define_property(this, "dump", void 0);
|
|
22
|
+
this.name = 'ServiceError';
|
|
23
|
+
this.dump = dump;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
function replacerForDumpSerialization(_key, value) {
|
|
27
|
+
if (value && value.constructor?.name === 'Page') return '[Page object]';
|
|
28
|
+
if (value && value.constructor?.name === 'Browser') return '[Browser object]';
|
|
29
|
+
if (value && 'function' == typeof value.toSerializable) return value.toSerializable();
|
|
30
|
+
return value;
|
|
31
|
+
}
|
|
32
|
+
function reviverForDumpDeserialization(key, value) {
|
|
33
|
+
if ('screenshot' !== key || 'object' != typeof value || null === value) return value;
|
|
34
|
+
ScreenshotItem.isSerialized(value);
|
|
35
|
+
return value;
|
|
36
|
+
}
|
|
37
|
+
class ExecutionDump {
|
|
38
|
+
serialize(indents) {
|
|
39
|
+
return JSON.stringify(this.toJSON(), replacerForDumpSerialization, indents);
|
|
40
|
+
}
|
|
41
|
+
toJSON() {
|
|
42
|
+
return {
|
|
43
|
+
id: this.id,
|
|
44
|
+
logTime: this.logTime,
|
|
45
|
+
name: this.name,
|
|
46
|
+
description: this.description,
|
|
47
|
+
tasks: this.tasks.map((task)=>({
|
|
48
|
+
...task,
|
|
49
|
+
recorder: task.recorder || []
|
|
50
|
+
})),
|
|
51
|
+
aiActContext: this.aiActContext
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
static fromSerializedString(serialized) {
|
|
55
|
+
const parsed = JSON.parse(serialized, reviverForDumpDeserialization);
|
|
56
|
+
return new ExecutionDump(parsed);
|
|
57
|
+
}
|
|
58
|
+
static fromJSON(data) {
|
|
59
|
+
return new ExecutionDump(data);
|
|
60
|
+
}
|
|
61
|
+
collectScreenshots() {
|
|
62
|
+
const screenshots = [];
|
|
63
|
+
for (const task of this.tasks){
|
|
64
|
+
if (task.uiContext?.screenshot instanceof ScreenshotItem) screenshots.push(task.uiContext.screenshot);
|
|
65
|
+
if (task.recorder) {
|
|
66
|
+
for (const record of task.recorder)if (record.screenshot instanceof ScreenshotItem) screenshots.push(record.screenshot);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
return screenshots;
|
|
70
|
+
}
|
|
71
|
+
constructor(data){
|
|
72
|
+
_define_property(this, "id", void 0);
|
|
73
|
+
_define_property(this, "logTime", void 0);
|
|
74
|
+
_define_property(this, "name", void 0);
|
|
75
|
+
_define_property(this, "description", void 0);
|
|
76
|
+
_define_property(this, "tasks", void 0);
|
|
77
|
+
_define_property(this, "aiActContext", void 0);
|
|
78
|
+
this.id = data.id;
|
|
79
|
+
this.logTime = data.logTime;
|
|
80
|
+
this.name = data.name;
|
|
81
|
+
this.description = data.description;
|
|
82
|
+
this.tasks = data.tasks;
|
|
83
|
+
this.aiActContext = data.aiActContext;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
class ReportActionDump {
|
|
87
|
+
serialize(indents) {
|
|
88
|
+
return JSON.stringify(this.toJSON(), replacerForDumpSerialization, indents);
|
|
89
|
+
}
|
|
90
|
+
serializeWithInlineScreenshots(indents) {
|
|
91
|
+
const processValue = (obj)=>{
|
|
92
|
+
if (obj instanceof ScreenshotItem) return {
|
|
93
|
+
base64: obj.base64,
|
|
94
|
+
capturedAt: obj.capturedAt
|
|
95
|
+
};
|
|
96
|
+
if (Array.isArray(obj)) return obj.map(processValue);
|
|
97
|
+
if (obj && 'object' == typeof obj) {
|
|
98
|
+
const entries = Object.entries(obj).map(([key, value])=>[
|
|
99
|
+
key,
|
|
100
|
+
processValue(value)
|
|
101
|
+
]);
|
|
102
|
+
return Object.fromEntries(entries);
|
|
103
|
+
}
|
|
104
|
+
return obj;
|
|
105
|
+
};
|
|
106
|
+
const data = processValue(this.toJSON());
|
|
107
|
+
return JSON.stringify(data, null, indents);
|
|
108
|
+
}
|
|
109
|
+
toJSON() {
|
|
110
|
+
return {
|
|
111
|
+
sdkVersion: this.sdkVersion,
|
|
112
|
+
groupName: this.groupName,
|
|
113
|
+
groupDescription: this.groupDescription,
|
|
114
|
+
modelBriefs: this.modelBriefs,
|
|
115
|
+
executions: this.executions.map((exec)=>exec.toJSON()),
|
|
116
|
+
deviceType: this.deviceType
|
|
117
|
+
};
|
|
118
|
+
}
|
|
119
|
+
static fromSerializedString(serialized) {
|
|
120
|
+
const parsed = JSON.parse(serialized, reviverForDumpDeserialization);
|
|
121
|
+
return new ReportActionDump(parsed);
|
|
122
|
+
}
|
|
123
|
+
static fromJSON(data) {
|
|
124
|
+
return new ReportActionDump(data);
|
|
125
|
+
}
|
|
126
|
+
collectAllScreenshots() {
|
|
127
|
+
const screenshots = [];
|
|
128
|
+
for (const execution of this.executions)screenshots.push(...execution.collectScreenshots());
|
|
129
|
+
return screenshots;
|
|
130
|
+
}
|
|
131
|
+
serializeToFiles(basePath) {
|
|
132
|
+
const screenshotsDir = `${basePath}.screenshots`;
|
|
133
|
+
if (!existsSync(screenshotsDir)) mkdirSync(screenshotsDir, {
|
|
134
|
+
recursive: true
|
|
135
|
+
});
|
|
136
|
+
const screenshots = this.collectAllScreenshots();
|
|
137
|
+
for (const screenshot of screenshots){
|
|
138
|
+
const imagePath = join(screenshotsDir, `${screenshot.id}.${screenshot.extension}`);
|
|
139
|
+
if (existsSync(imagePath)) continue;
|
|
140
|
+
const rawBase64 = screenshot.rawBase64;
|
|
141
|
+
writeFileSync(imagePath, Buffer.from(rawBase64, 'base64'));
|
|
142
|
+
}
|
|
143
|
+
writeFileSync(basePath, this.serialize(), 'utf-8');
|
|
144
|
+
}
|
|
145
|
+
static fromFilesAsInlineJson(basePath) {
|
|
146
|
+
const dumpString = readFileSync(basePath, 'utf-8');
|
|
147
|
+
const screenshotsDir = `${basePath}.screenshots`;
|
|
148
|
+
const loadFromExecutionScreenshotDir = (id, mimeType)=>{
|
|
149
|
+
const ext = 'image/jpeg' === mimeType ? 'jpeg' : 'png';
|
|
150
|
+
const filePath = join(screenshotsDir, `${id}.${ext}`);
|
|
151
|
+
if (!existsSync(filePath)) return '';
|
|
152
|
+
const data = readFileSync(filePath);
|
|
153
|
+
return `data:image/${ext};base64,${data.toString('base64')}`;
|
|
154
|
+
};
|
|
155
|
+
const dumpData = JSON.parse(dumpString);
|
|
156
|
+
const store = new ScreenshotStore({
|
|
157
|
+
mode: 'directory',
|
|
158
|
+
reportPath: basePath
|
|
159
|
+
});
|
|
160
|
+
const processedData = restoreImageReferences(dumpData, (ref)=>{
|
|
161
|
+
const executionFileImage = loadFromExecutionScreenshotDir(ref.id, ref.mimeType);
|
|
162
|
+
if (executionFileImage) return executionFileImage;
|
|
163
|
+
if ('inline' === ref.storage) return '';
|
|
164
|
+
return store.loadBase64(ref);
|
|
165
|
+
});
|
|
166
|
+
return JSON.stringify(processedData);
|
|
167
|
+
}
|
|
168
|
+
static cleanupFiles(basePath) {
|
|
169
|
+
const filesToClean = [
|
|
170
|
+
basePath,
|
|
171
|
+
`${basePath}.screenshots`
|
|
172
|
+
];
|
|
173
|
+
for (const filePath of filesToClean)try {
|
|
174
|
+
rmSync(filePath, {
|
|
175
|
+
force: true,
|
|
176
|
+
recursive: true
|
|
177
|
+
});
|
|
178
|
+
} catch {}
|
|
179
|
+
}
|
|
180
|
+
static getFilePaths(basePath) {
|
|
181
|
+
return [
|
|
182
|
+
basePath,
|
|
183
|
+
`${basePath}.screenshots`
|
|
184
|
+
];
|
|
185
|
+
}
|
|
186
|
+
constructor(data){
|
|
187
|
+
_define_property(this, "sdkVersion", void 0);
|
|
188
|
+
_define_property(this, "groupName", void 0);
|
|
189
|
+
_define_property(this, "groupDescription", void 0);
|
|
190
|
+
_define_property(this, "modelBriefs", void 0);
|
|
191
|
+
_define_property(this, "executions", void 0);
|
|
192
|
+
_define_property(this, "deviceType", void 0);
|
|
193
|
+
this.sdkVersion = data.sdkVersion;
|
|
194
|
+
this.groupName = data.groupName;
|
|
195
|
+
this.groupDescription = data.groupDescription;
|
|
196
|
+
this.modelBriefs = data.modelBriefs;
|
|
197
|
+
this.executions = data.executions.map((exec)=>exec instanceof ExecutionDump ? exec : ExecutionDump.fromJSON(exec));
|
|
198
|
+
this.deviceType = data.deviceType;
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
const GroupedActionDump = ReportActionDump;
|
|
202
|
+
export { ExecutionDump, GroupedActionDump, ReportActionDump, ServiceError, UIContext };
|
|
@@ -0,0 +1,232 @@
|
|
|
1
|
+
import { execFile } from "node:child_process";
|
|
2
|
+
import { appendFileSync, closeSync, existsSync, mkdirSync, openSync, readFileSync, readSync, statSync, truncateSync, writeFileSync } from "node:fs";
|
|
3
|
+
import { tmpdir } from "node:os";
|
|
4
|
+
import { join } from "node:path";
|
|
5
|
+
import { promisify } from "node:util";
|
|
6
|
+
import { defaultRunDirName, getMidsceneRunSubDir } from "@godscene/shared/common";
|
|
7
|
+
import { MIDSCENE_CACHE, MIDSCENE_DEBUG_MODE, globalConfigManager } from "@godscene/shared/env";
|
|
8
|
+
import { getRunningPkgInfo } from "@godscene/shared/node";
|
|
9
|
+
import { assert, escapeScriptTag, ifInBrowser, ifInWorker, logMsg, uuid } from "@godscene/shared/utils";
|
|
10
|
+
let logEnvReady = false;
|
|
11
|
+
const groupedActionDumpFileExt = 'web-dump.json';
|
|
12
|
+
function processCacheConfig(cache, cacheId) {
|
|
13
|
+
if (void 0 !== cache) {
|
|
14
|
+
if (false === cache) return;
|
|
15
|
+
if (true === cache) return {
|
|
16
|
+
id: cacheId
|
|
17
|
+
};
|
|
18
|
+
if ('object' == typeof cache && null !== cache) {
|
|
19
|
+
if (!cache.id) return {
|
|
20
|
+
...cache,
|
|
21
|
+
id: cacheId
|
|
22
|
+
};
|
|
23
|
+
return cache;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
const envEnabled = globalConfigManager.getEnvConfigInBoolean(MIDSCENE_CACHE);
|
|
27
|
+
if (envEnabled && cacheId) return {
|
|
28
|
+
id: cacheId
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
const reportInitializedMap = new Map();
|
|
32
|
+
const reportGroupIdMap = new Map();
|
|
33
|
+
function getReportTpl() {
|
|
34
|
+
const reportTpl = /*REPORT_HTML_REPLACED*/"<!doctype html>\n<html>\n\n<head>\n <title>Report - RPA智能助手</title>\n <link rel=\"icon\" type=\"image/png\" sizes=\"32x32\" href=\"./favicon-32x32.png\" />\n</head>\n\n<body>\n <!-- it should be replaced by the actual content -->\n <div id=\"<%= mountId %>\" style=\"height: 100vh; width: 100vw\"></div>\n</body>\n\n</html>";
|
|
35
|
+
return reportTpl;
|
|
36
|
+
}
|
|
37
|
+
function insertContentBeforeClosingHtml(html, content) {
|
|
38
|
+
const htmlEndIdx = html.lastIndexOf('</html>');
|
|
39
|
+
if (-1 === htmlEndIdx) return html + content;
|
|
40
|
+
return `${html.slice(0, htmlEndIdx)}${content}\n${html.slice(htmlEndIdx)}`;
|
|
41
|
+
}
|
|
42
|
+
function insertScriptBeforeClosingHtml(filePath, scriptContent) {
|
|
43
|
+
const htmlEndTag = '</html>';
|
|
44
|
+
const stat = statSync(filePath);
|
|
45
|
+
const readSize = Math.min(stat.size, 4096);
|
|
46
|
+
const start = Math.max(0, stat.size - readSize);
|
|
47
|
+
const buffer = Buffer.alloc(stat.size - start);
|
|
48
|
+
const fd = openSync(filePath, 'r');
|
|
49
|
+
readSync(fd, buffer, 0, buffer.length, start);
|
|
50
|
+
closeSync(fd);
|
|
51
|
+
const tailStr = buffer.toString('utf8');
|
|
52
|
+
const htmlEndIdx = tailStr.lastIndexOf(htmlEndTag);
|
|
53
|
+
if (-1 === htmlEndIdx) throw new Error(`No </html> found in file:${filePath}`);
|
|
54
|
+
const beforeHtmlInTail = tailStr.slice(0, htmlEndIdx);
|
|
55
|
+
const htmlEndPos = start + Buffer.byteLength(beforeHtmlInTail, 'utf8');
|
|
56
|
+
truncateSync(filePath, htmlEndPos);
|
|
57
|
+
appendFileSync(filePath, `${scriptContent}\n${htmlEndTag}\n`);
|
|
58
|
+
}
|
|
59
|
+
function reportHTMLContent(dumpData, reportPath, appendReport, withTpl = true) {
|
|
60
|
+
let tpl = '';
|
|
61
|
+
if (withTpl) {
|
|
62
|
+
tpl = getReportTpl();
|
|
63
|
+
if (!tpl) {
|
|
64
|
+
console.warn('reportTpl is not set, will not write report');
|
|
65
|
+
return '';
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
const writeToFile = reportPath && !ifInBrowser;
|
|
69
|
+
let dumpContent = '';
|
|
70
|
+
const resolveAutoGroupId = ()=>{
|
|
71
|
+
if (!reportPath || !appendReport) return uuid();
|
|
72
|
+
const existingGroupId = reportGroupIdMap.get(reportPath);
|
|
73
|
+
if (existingGroupId) return existingGroupId;
|
|
74
|
+
const newGroupId = uuid();
|
|
75
|
+
reportGroupIdMap.set(reportPath, newGroupId);
|
|
76
|
+
return newGroupId;
|
|
77
|
+
};
|
|
78
|
+
if ('string' == typeof dumpData) {
|
|
79
|
+
const groupId = resolveAutoGroupId();
|
|
80
|
+
dumpContent = '<script type="midscene_web_dump" type="application/json" data-group-id="' + encodeURIComponent(groupId) + '">\n' + escapeScriptTag(dumpData) + "\n<\/script>";
|
|
81
|
+
} else {
|
|
82
|
+
const { dumpString, attributes } = dumpData;
|
|
83
|
+
const attributesArr = Object.entries(attributes || {}).filter((entry)=>void 0 !== entry[1] && null !== entry[1]).map(([key, value])=>`${key}="${encodeURIComponent(value)}"`);
|
|
84
|
+
dumpContent = '<script type="midscene_web_dump" type="application/json" ' + attributesArr.join(' ') + '>\n' + escapeScriptTag(dumpString) + "\n<\/script>";
|
|
85
|
+
}
|
|
86
|
+
if (writeToFile) {
|
|
87
|
+
if (!appendReport) {
|
|
88
|
+
writeFileSync(reportPath, insertContentBeforeClosingHtml(tpl, dumpContent), {
|
|
89
|
+
flag: 'w'
|
|
90
|
+
});
|
|
91
|
+
return reportPath;
|
|
92
|
+
}
|
|
93
|
+
if (!reportInitializedMap.get(reportPath)) {
|
|
94
|
+
writeFileSync(reportPath, tpl, {
|
|
95
|
+
flag: 'w'
|
|
96
|
+
});
|
|
97
|
+
reportInitializedMap.set(reportPath, true);
|
|
98
|
+
}
|
|
99
|
+
insertScriptBeforeClosingHtml(reportPath, dumpContent);
|
|
100
|
+
return reportPath;
|
|
101
|
+
}
|
|
102
|
+
return insertContentBeforeClosingHtml(tpl, dumpContent);
|
|
103
|
+
}
|
|
104
|
+
function writeDumpReport(fileName, dumpData, appendReport) {
|
|
105
|
+
if (ifInBrowser || ifInWorker) {
|
|
106
|
+
console.log('will not write report in browser');
|
|
107
|
+
return null;
|
|
108
|
+
}
|
|
109
|
+
const reportPath = join(getMidsceneRunSubDir('report'), `${fileName}.html`);
|
|
110
|
+
reportHTMLContent(dumpData, reportPath, appendReport);
|
|
111
|
+
if (process.env.MIDSCENE_DEBUG_LOG_JSON) {
|
|
112
|
+
const jsonPath = `${reportPath}.json`;
|
|
113
|
+
let data;
|
|
114
|
+
data = 'string' == typeof dumpData ? JSON.parse(dumpData) : dumpData;
|
|
115
|
+
writeFileSync(jsonPath, JSON.stringify(data, null, 2), {
|
|
116
|
+
flag: appendReport ? 'a' : 'w'
|
|
117
|
+
});
|
|
118
|
+
logMsg(`Midscene - dump file written: ${jsonPath}`);
|
|
119
|
+
}
|
|
120
|
+
return reportPath;
|
|
121
|
+
}
|
|
122
|
+
function writeLogFile(opts) {
|
|
123
|
+
if (ifInBrowser || ifInWorker) return '/mock/report.html';
|
|
124
|
+
const { fileName, fileExt, fileContent, type = 'dump' } = opts;
|
|
125
|
+
const targetDir = getMidsceneRunSubDir(type);
|
|
126
|
+
if (!logEnvReady) {
|
|
127
|
+
assert(targetDir, 'logDir should be set before writing dump file');
|
|
128
|
+
const gitIgnorePath = join(targetDir, '../../.gitignore');
|
|
129
|
+
const gitPath = join(targetDir, '../../.git');
|
|
130
|
+
let gitIgnoreContent = '';
|
|
131
|
+
if (existsSync(gitPath)) {
|
|
132
|
+
if (existsSync(gitIgnorePath)) gitIgnoreContent = readFileSync(gitIgnorePath, 'utf-8');
|
|
133
|
+
if (!gitIgnoreContent.includes(`${defaultRunDirName}/`)) writeFileSync(gitIgnorePath, `${gitIgnoreContent}\n# RPA智能助手 dump files\n${defaultRunDirName}/dump\n${defaultRunDirName}/report\n${defaultRunDirName}/tmp\n${defaultRunDirName}/log\n`, 'utf-8');
|
|
134
|
+
}
|
|
135
|
+
logEnvReady = true;
|
|
136
|
+
}
|
|
137
|
+
const filePath = join(targetDir, `${fileName}.${fileExt}`);
|
|
138
|
+
if ('dump' !== type) writeFileSync(filePath, JSON.stringify(fileContent));
|
|
139
|
+
if (opts?.generateReport) return writeDumpReport(fileName, fileContent, opts.appendReport);
|
|
140
|
+
return filePath;
|
|
141
|
+
}
|
|
142
|
+
function getTmpDir() {
|
|
143
|
+
try {
|
|
144
|
+
const runningPkgInfo = getRunningPkgInfo();
|
|
145
|
+
if (!runningPkgInfo) return null;
|
|
146
|
+
const { name } = runningPkgInfo;
|
|
147
|
+
const tmpPath = join(tmpdir(), name);
|
|
148
|
+
mkdirSync(tmpPath, {
|
|
149
|
+
recursive: true
|
|
150
|
+
});
|
|
151
|
+
return tmpPath;
|
|
152
|
+
} catch (e) {
|
|
153
|
+
return null;
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
function getTmpFile(fileExtWithoutDot) {
|
|
157
|
+
if (ifInBrowser || ifInWorker) return null;
|
|
158
|
+
const tmpDir = getTmpDir();
|
|
159
|
+
const filename = `${uuid()}.${fileExtWithoutDot}`;
|
|
160
|
+
return join(tmpDir, filename);
|
|
161
|
+
}
|
|
162
|
+
function overlapped(container, target) {
|
|
163
|
+
return container.left < target.left + target.width && container.left + container.width > target.left && container.top < target.top + target.height && container.top + container.height > target.top;
|
|
164
|
+
}
|
|
165
|
+
async function sleep(ms) {
|
|
166
|
+
return new Promise((resolve)=>setTimeout(resolve, ms));
|
|
167
|
+
}
|
|
168
|
+
function replacerForPageObject(_key, value) {
|
|
169
|
+
if (value && value.constructor?.name === 'Page') return '[Page object]';
|
|
170
|
+
if (value && value.constructor?.name === 'Browser') return '[Browser object]';
|
|
171
|
+
if (value && 'function' == typeof value.toSerializable) return value.toSerializable();
|
|
172
|
+
return value;
|
|
173
|
+
}
|
|
174
|
+
function stringifyDumpData(data, indents) {
|
|
175
|
+
return JSON.stringify(data, replacerForPageObject, indents);
|
|
176
|
+
}
|
|
177
|
+
function getVersion() {
|
|
178
|
+
return "1.7.10";
|
|
179
|
+
}
|
|
180
|
+
function debugLog(...message) {
|
|
181
|
+
const debugMode = process.env[MIDSCENE_DEBUG_MODE];
|
|
182
|
+
if (debugMode) console.log('[Midscene]', ...message);
|
|
183
|
+
}
|
|
184
|
+
let gitInfoPromise = null;
|
|
185
|
+
function getGitInfoAsync() {
|
|
186
|
+
if (gitInfoPromise) return gitInfoPromise;
|
|
187
|
+
const execFileAsync = promisify(execFile);
|
|
188
|
+
gitInfoPromise = Promise.all([
|
|
189
|
+
execFileAsync('git', [
|
|
190
|
+
'config',
|
|
191
|
+
'--get',
|
|
192
|
+
'remote.origin.url'
|
|
193
|
+
]).then(({ stdout })=>stdout.trim(), ()=>''),
|
|
194
|
+
execFileAsync('git', [
|
|
195
|
+
'config',
|
|
196
|
+
'--get',
|
|
197
|
+
'user.email'
|
|
198
|
+
]).then(({ stdout })=>stdout.trim(), ()=>'')
|
|
199
|
+
]).then(([repoUrl, userEmail])=>({
|
|
200
|
+
repoUrl,
|
|
201
|
+
userEmail
|
|
202
|
+
}));
|
|
203
|
+
return gitInfoPromise;
|
|
204
|
+
}
|
|
205
|
+
let lastReportedRepoUrl = '';
|
|
206
|
+
async function uploadTestInfoToServer({ testUrl, serverUrl }) {
|
|
207
|
+
if (!serverUrl) return;
|
|
208
|
+
const { repoUrl, userEmail } = await getGitInfoAsync();
|
|
209
|
+
if (repoUrl ? repoUrl !== lastReportedRepoUrl : !!testUrl) {
|
|
210
|
+
debugLog('Uploading test info to server', {
|
|
211
|
+
serverUrl,
|
|
212
|
+
repoUrl,
|
|
213
|
+
testUrl,
|
|
214
|
+
userEmail
|
|
215
|
+
});
|
|
216
|
+
fetch(serverUrl, {
|
|
217
|
+
method: 'POST',
|
|
218
|
+
headers: {
|
|
219
|
+
'Content-Type': 'application/json'
|
|
220
|
+
},
|
|
221
|
+
body: JSON.stringify({
|
|
222
|
+
repo_url: repoUrl,
|
|
223
|
+
test_url: testUrl,
|
|
224
|
+
user_email: userEmail
|
|
225
|
+
})
|
|
226
|
+
}).then((response)=>response.json()).then((data)=>{
|
|
227
|
+
debugLog('Successfully uploaded test info to server:', data);
|
|
228
|
+
}).catch((error)=>debugLog('Failed to upload test info to server:', error));
|
|
229
|
+
lastReportedRepoUrl = repoUrl;
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
export { appendFileSync, getReportTpl, getTmpDir, getTmpFile, getVersion, groupedActionDumpFileExt, insertContentBeforeClosingHtml, insertScriptBeforeClosingHtml, overlapped, processCacheConfig, replacerForPageObject, reportHTMLContent, sleep, stringifyDumpData, uploadTestInfoToServer, writeDumpReport, writeLogFile };
|