misoai-web 1.6.0 → 1.6.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/es/agent.js +108 -50
- package/dist/es/agent.js.map +1 -1
- package/dist/es/bridge-mode-browser.js +3 -3
- package/dist/es/bridge-mode-browser.js.map +1 -1
- package/dist/es/bridge-mode.js +110 -52
- package/dist/es/bridge-mode.js.map +1 -1
- package/dist/es/chrome-extension.js +109 -51
- package/dist/es/chrome-extension.js.map +1 -1
- package/dist/es/index.js +425 -68
- package/dist/es/index.js.map +1 -1
- package/dist/es/midscene-playground.js +111 -53
- package/dist/es/midscene-playground.js.map +1 -1
- package/dist/es/midscene-server.js +4 -4
- package/dist/es/midscene-server.js.map +1 -1
- package/dist/es/playground.js +108 -50
- package/dist/es/playground.js.map +1 -1
- package/dist/es/playwright-report.js +1 -1
- package/dist/es/playwright-report.js.map +1 -1
- package/dist/es/playwright.js +425 -68
- package/dist/es/playwright.js.map +1 -1
- package/dist/es/puppeteer-agent-launcher.js +424 -67
- package/dist/es/puppeteer-agent-launcher.js.map +1 -1
- package/dist/es/puppeteer.js +424 -67
- package/dist/es/puppeteer.js.map +1 -1
- package/dist/es/utils.js +1 -1
- package/dist/es/utils.js.map +1 -1
- package/dist/es/yaml.js +1 -1
- package/dist/es/yaml.js.map +1 -1
- package/dist/lib/agent.js +108 -50
- package/dist/lib/agent.js.map +1 -1
- package/dist/lib/bridge-mode-browser.js +3 -3
- package/dist/lib/bridge-mode-browser.js.map +1 -1
- package/dist/lib/bridge-mode.js +110 -52
- package/dist/lib/bridge-mode.js.map +1 -1
- package/dist/lib/chrome-extension.js +109 -51
- package/dist/lib/chrome-extension.js.map +1 -1
- package/dist/lib/index.js +425 -68
- package/dist/lib/index.js.map +1 -1
- package/dist/lib/midscene-playground.js +111 -53
- package/dist/lib/midscene-playground.js.map +1 -1
- package/dist/lib/midscene-server.js +4 -4
- package/dist/lib/midscene-server.js.map +1 -1
- package/dist/lib/playground.js +108 -50
- package/dist/lib/playground.js.map +1 -1
- package/dist/lib/playwright-report.js +1 -1
- package/dist/lib/playwright-report.js.map +1 -1
- package/dist/lib/playwright.js +425 -68
- package/dist/lib/playwright.js.map +1 -1
- package/dist/lib/puppeteer-agent-launcher.js +424 -67
- package/dist/lib/puppeteer-agent-launcher.js.map +1 -1
- package/dist/lib/puppeteer.js +424 -67
- package/dist/lib/puppeteer.js.map +1 -1
- package/dist/lib/utils.js +1 -1
- package/dist/lib/utils.js.map +1 -1
- package/dist/lib/yaml.js +1 -1
- package/dist/lib/yaml.js.map +1 -1
- package/dist/types/agent.d.ts +1 -1
- package/dist/types/bridge-mode-browser.d.ts +2 -2
- package/dist/types/bridge-mode.d.ts +2 -2
- package/dist/types/{browser-9b472ffb.d.ts → browser-f205f69d.d.ts} +1 -1
- package/dist/types/chrome-extension.d.ts +2 -2
- package/dist/types/index.d.ts +2 -2
- package/dist/types/midscene-server.d.ts +1 -1
- package/dist/types/{page-ed0ecb44.d.ts → page-c5452809.d.ts} +45 -0
- package/dist/types/playground.d.ts +2 -2
- package/dist/types/playwright.d.ts +2 -2
- package/dist/types/puppeteer-agent-launcher.d.ts +1 -1
- package/dist/types/puppeteer.d.ts +2 -2
- package/dist/types/utils.d.ts +1 -1
- package/dist/types/yaml.d.ts +1 -1
- package/package.json +18 -54
package/dist/lib/bridge-mode.js
CHANGED
@@ -345,8 +345,8 @@ var ScriptPlayer = class {
|
|
345
345
|
var import_js_yaml = __toESM(require("js-yaml"));
|
346
346
|
|
347
347
|
// src/yaml/utils.ts
|
348
|
-
var import_utils2 = require("misoai-shared/utils");
|
349
348
|
var import_js_yaml2 = __toESM(require("js-yaml"));
|
349
|
+
var import_utils2 = require("misoai-shared/utils");
|
350
350
|
function interpolateEnvVars(content) {
|
351
351
|
return content.replace(/\$\{([^}]+)\}/g, (_, envVar) => {
|
352
352
|
const value = process.env[envVar.trim()];
|
@@ -492,13 +492,13 @@ function paramStr(task) {
|
|
492
492
|
}
|
493
493
|
|
494
494
|
// src/common/utils.ts
|
495
|
+
var import_dayjs = __toESM(require("dayjs"));
|
495
496
|
var import_ai_model = require("misoai-core/ai-model");
|
496
497
|
var import_utils3 = require("misoai-core/utils");
|
497
498
|
var import_env = require("misoai-shared/env");
|
498
499
|
var import_extractor = require("misoai-shared/extractor");
|
499
500
|
var import_img = require("misoai-shared/img");
|
500
501
|
var import_utils4 = require("misoai-shared/utils");
|
501
|
-
var import_dayjs = __toESM(require("dayjs"));
|
502
502
|
|
503
503
|
// src/web-element.ts
|
504
504
|
var WebElementInfo = class {
|
@@ -639,8 +639,12 @@ var WorkflowMemory = class {
|
|
639
639
|
const workflow = this.workflows.get(workflowId) || this.createEmptyWorkflowData(workflowId);
|
640
640
|
workflow.memory = [...memory];
|
641
641
|
workflow.metadata.totalSteps = workflow.steps.length;
|
642
|
-
workflow.metadata.completedSteps = workflow.steps.filter(
|
643
|
-
|
642
|
+
workflow.metadata.completedSteps = workflow.steps.filter(
|
643
|
+
(s) => s.status === "completed"
|
644
|
+
).length;
|
645
|
+
workflow.metadata.failedSteps = workflow.steps.filter(
|
646
|
+
(s) => s.status === "failed"
|
647
|
+
).length;
|
644
648
|
this.workflows.set(workflowId, workflow);
|
645
649
|
this.enforceRetentionPolicy();
|
646
650
|
}
|
@@ -651,7 +655,9 @@ var WorkflowMemory = class {
|
|
651
655
|
const workflow = this.workflows.get(workflowId) || this.createEmptyWorkflowData(workflowId);
|
652
656
|
workflow.context = { ...workflow.context, ...context };
|
653
657
|
if (context.currentStep) {
|
654
|
-
const existingStep = workflow.steps.find(
|
658
|
+
const existingStep = workflow.steps.find(
|
659
|
+
(s) => s.stepName === context.currentStep
|
660
|
+
);
|
655
661
|
if (!existingStep) {
|
656
662
|
workflow.steps.push({
|
657
663
|
stepId: `step_${workflow.steps.length + 1}`,
|
@@ -696,7 +702,9 @@ var WorkflowMemory = class {
|
|
696
702
|
enforceRetentionPolicy() {
|
697
703
|
const maxWorkflows = 10;
|
698
704
|
if (this.workflows.size > maxWorkflows) {
|
699
|
-
const sortedWorkflows = Array.from(this.workflows.entries()).sort(
|
705
|
+
const sortedWorkflows = Array.from(this.workflows.entries()).sort(
|
706
|
+
([, a], [, b]) => (b.metadata.endTime || b.metadata.startTime) - (a.metadata.endTime || a.metadata.startTime)
|
707
|
+
);
|
700
708
|
const toDelete = sortedWorkflows.slice(maxWorkflows);
|
701
709
|
toDelete.forEach(([workflowId]) => this.workflows.delete(workflowId));
|
702
710
|
}
|
@@ -1263,6 +1271,7 @@ var PageTaskExecutor = class {
|
|
1263
1271
|
actions: [],
|
1264
1272
|
more_actions_needed_by_instruction: false,
|
1265
1273
|
log: "",
|
1274
|
+
summary: "Loaded YAML workflow configuration",
|
1266
1275
|
yamlString
|
1267
1276
|
},
|
1268
1277
|
cache: {
|
@@ -1364,6 +1373,7 @@ var PageTaskExecutor = class {
|
|
1364
1373
|
actions: finalActions,
|
1365
1374
|
more_actions_needed_by_instruction,
|
1366
1375
|
log: log2,
|
1376
|
+
summary: planResult.summary || "Generated action plan from user instruction",
|
1367
1377
|
yamlFlow: planResult.yamlFlow
|
1368
1378
|
},
|
1369
1379
|
cache: {
|
@@ -1419,6 +1429,7 @@ var PageTaskExecutor = class {
|
|
1419
1429
|
actionType: actions[0].type,
|
1420
1430
|
more_actions_needed_by_instruction: true,
|
1421
1431
|
log: "",
|
1432
|
+
summary: action_summary || "Generated VLM action plan",
|
1422
1433
|
yamlFlow: planResult.yamlFlow
|
1423
1434
|
},
|
1424
1435
|
cache: {
|
@@ -1435,7 +1446,9 @@ var PageTaskExecutor = class {
|
|
1435
1446
|
*/
|
1436
1447
|
getPersistentExecutor() {
|
1437
1448
|
if (!this.persistentExecutor || this.persistentExecutor.status === "error") {
|
1438
|
-
const previousMemory = this.workflowMemory.getWorkflowMemory(
|
1449
|
+
const previousMemory = this.workflowMemory.getWorkflowMemory(
|
1450
|
+
this.sessionContext.workflowId
|
1451
|
+
);
|
1439
1452
|
this.persistentExecutor = new import_misoai_core.Executor("Persistent Task Executor", {
|
1440
1453
|
onTaskStart: this.onTaskStartCallback,
|
1441
1454
|
initialMemory: previousMemory
|
@@ -1464,7 +1477,9 @@ var PageTaskExecutor = class {
|
|
1464
1477
|
if (this.persistentExecutor) {
|
1465
1478
|
this.persistentExecutor.clearMemory();
|
1466
1479
|
}
|
1467
|
-
this.workflowMemory.clearWorkflow(
|
1480
|
+
this.workflowMemory.clearWorkflow(
|
1481
|
+
this.sessionContext.workflowId || "default"
|
1482
|
+
);
|
1468
1483
|
}
|
1469
1484
|
/**
|
1470
1485
|
* Mevcut hafızayı döndürür
|
@@ -1476,7 +1491,9 @@ var PageTaskExecutor = class {
|
|
1476
1491
|
* İş akışı hafızasını döndürür
|
1477
1492
|
*/
|
1478
1493
|
getWorkflowMemory() {
|
1479
|
-
return this.workflowMemory.getWorkflowData(
|
1494
|
+
return this.workflowMemory.getWorkflowData(
|
1495
|
+
this.sessionContext.workflowId || "default"
|
1496
|
+
);
|
1480
1497
|
}
|
1481
1498
|
/**
|
1482
1499
|
* Hafıza istatistiklerini döndürür
|
@@ -1484,7 +1501,13 @@ var PageTaskExecutor = class {
|
|
1484
1501
|
getMemoryStats() {
|
1485
1502
|
return this.persistentExecutor?.getMemoryStats() || {
|
1486
1503
|
totalItems: 0,
|
1487
|
-
analytics: {
|
1504
|
+
analytics: {
|
1505
|
+
totalTasks: 0,
|
1506
|
+
memoryHits: 0,
|
1507
|
+
memoryMisses: 0,
|
1508
|
+
averageMemorySize: 0,
|
1509
|
+
memoryEffectiveness: 0
|
1510
|
+
},
|
1488
1511
|
config: this.memoryConfig
|
1489
1512
|
};
|
1490
1513
|
}
|
@@ -1520,11 +1543,14 @@ var PageTaskExecutor = class {
|
|
1520
1543
|
let taskExecutor;
|
1521
1544
|
if (useMemory) {
|
1522
1545
|
taskExecutor = this.getPersistentExecutor();
|
1523
|
-
this.workflowMemory.updateWorkflowContext(
|
1524
|
-
|
1525
|
-
|
1526
|
-
|
1527
|
-
|
1546
|
+
this.workflowMemory.updateWorkflowContext(
|
1547
|
+
{
|
1548
|
+
currentStep: title,
|
1549
|
+
pageInfo: this.sessionContext.pageInfo,
|
1550
|
+
timestamp: Date.now()
|
1551
|
+
},
|
1552
|
+
this.sessionContext.workflowId || "default"
|
1553
|
+
);
|
1528
1554
|
} else {
|
1529
1555
|
taskExecutor = new import_misoai_core.Executor(title, {
|
1530
1556
|
onTaskStart: this.onTaskStartCallback
|
@@ -1890,14 +1916,19 @@ var PageTaskExecutor = class {
|
|
1890
1916
|
*/
|
1891
1917
|
addToMemory(memoryItem) {
|
1892
1918
|
if (!this.persistentExecutor || this.persistentExecutor.status === "error") {
|
1893
|
-
const previousMemory = this.workflowMemory.getWorkflowMemory(
|
1919
|
+
const previousMemory = this.workflowMemory.getWorkflowMemory(
|
1920
|
+
this.sessionContext.workflowId
|
1921
|
+
);
|
1894
1922
|
this.persistentExecutor = new import_misoai_core.Executor("Persistent Task Executor", {
|
1895
1923
|
onTaskStart: this.onTaskStartCallback,
|
1896
1924
|
initialMemory: previousMemory
|
1897
1925
|
});
|
1898
1926
|
}
|
1899
1927
|
this.persistentExecutor.memoryStore?.add(memoryItem);
|
1900
|
-
this.persistentExecutor.memoryAnalytics?.recordMemoryOperation(
|
1928
|
+
this.persistentExecutor.memoryAnalytics?.recordMemoryOperation(
|
1929
|
+
"add",
|
1930
|
+
memoryItem
|
1931
|
+
);
|
1901
1932
|
}
|
1902
1933
|
};
|
1903
1934
|
|
@@ -1986,14 +2017,14 @@ function buildPlans(type, locateParam, param) {
|
|
1986
2017
|
var import_node_assert = __toESM(require("assert"));
|
1987
2018
|
var import_node_fs2 = require("fs");
|
1988
2019
|
var import_node_path2 = require("path");
|
2020
|
+
var import_js_yaml3 = __toESM(require("js-yaml"));
|
1989
2021
|
var import_common2 = require("misoai-shared/common");
|
1990
2022
|
var import_logger3 = require("misoai-shared/logger");
|
1991
2023
|
var import_utils9 = require("misoai-shared/utils");
|
1992
|
-
var import_js_yaml3 = __toESM(require("js-yaml"));
|
1993
2024
|
var import_semver = __toESM(require("semver"));
|
1994
2025
|
|
1995
2026
|
// package.json
|
1996
|
-
var version = "1.6.
|
2027
|
+
var version = "1.6.2";
|
1997
2028
|
|
1998
2029
|
// src/common/task-cache.ts
|
1999
2030
|
var debug3 = (0, import_logger3.getDebug)("cache");
|
@@ -2288,22 +2319,28 @@ var PageAgent = class {
|
|
2288
2319
|
const allThoughts = executor.tasks.filter((task) => task.thought).map((task) => task.thought);
|
2289
2320
|
const allLocates = executor.tasks.filter((task) => task.locate).map((task) => task.locate);
|
2290
2321
|
const allPlans = executor.tasks.filter((task) => task.param?.plans).map((task) => task.param?.plans);
|
2291
|
-
const planningTasks = executor.tasks.filter(
|
2292
|
-
|
2322
|
+
const planningTasks = executor.tasks.filter(
|
2323
|
+
(task) => task.type === "Planning"
|
2324
|
+
);
|
2325
|
+
const insightTasks = executor.tasks.filter(
|
2326
|
+
(task) => task.type === "Insight"
|
2327
|
+
);
|
2293
2328
|
const actionTasks = executor.tasks.filter((task) => task.type === "Action");
|
2294
2329
|
const planning = planningTasks.length > 0 ? {
|
2295
2330
|
type: "Planning",
|
2296
|
-
description:
|
2331
|
+
description: "Planning for task execution",
|
2297
2332
|
steps: planningTasks.map((task) => task.thought || "Planning step")
|
2298
2333
|
} : void 0;
|
2299
2334
|
const insight = insightTasks.length > 0 ? {
|
2300
2335
|
type: "Insight",
|
2301
|
-
description:
|
2302
|
-
elements: insightTasks.map(
|
2336
|
+
description: "Insight for task execution",
|
2337
|
+
elements: insightTasks.map(
|
2338
|
+
(task) => task.thought || "Insight element"
|
2339
|
+
)
|
2303
2340
|
} : void 0;
|
2304
2341
|
const action = actionTasks.length > 0 ? {
|
2305
2342
|
type: "Action",
|
2306
|
-
description:
|
2343
|
+
description: "Action for task execution",
|
2307
2344
|
result: lastTask?.output
|
2308
2345
|
} : void 0;
|
2309
2346
|
const actionDetails = executor.tasks.map((task) => ({
|
@@ -2637,7 +2674,10 @@ ${memoryContext}` : void 0;
|
|
2637
2674
|
}
|
2638
2675
|
const memoryContext = this.getMemoryAsContext();
|
2639
2676
|
const assertionWithContext = currentUrl ? `For the page at URL "${currentUrl}", ${assertion}` : assertion;
|
2640
|
-
const { output, executor } = await this.taskExecutor.assert(
|
2677
|
+
const { output, executor } = await this.taskExecutor.assert(
|
2678
|
+
assertionWithContext,
|
2679
|
+
memoryContext
|
2680
|
+
);
|
2641
2681
|
const metadata = this.afterTaskRunning(executor, true);
|
2642
2682
|
if (output && opt?.keepRawResponse) {
|
2643
2683
|
return {
|
@@ -2676,7 +2716,10 @@ A complex CAPTCHA typically has one or more of these characteristics:
|
|
2676
2716
|
Return only "complex" or "simple" based on your analysis.
|
2677
2717
|
`;
|
2678
2718
|
const complexityMsgs = [
|
2679
|
-
{
|
2719
|
+
{
|
2720
|
+
role: "system",
|
2721
|
+
content: "You are an AI assistant that analyzes screenshots to determine CAPTCHA complexity."
|
2722
|
+
},
|
2680
2723
|
{
|
2681
2724
|
role: "user",
|
2682
2725
|
content: [
|
@@ -2700,7 +2743,12 @@ Return only "complex" or "simple" based on your analysis.
|
|
2700
2743
|
);
|
2701
2744
|
const responseText = typeof complexityResult.content === "string" ? complexityResult.content.toLowerCase() : JSON.stringify(complexityResult.content).toLowerCase();
|
2702
2745
|
shouldUseDeepThink = responseText.includes("complex");
|
2703
|
-
debug4(
|
2746
|
+
debug4(
|
2747
|
+
"CAPTCHA complexity analysis:",
|
2748
|
+
responseText,
|
2749
|
+
"Using deep think:",
|
2750
|
+
shouldUseDeepThink
|
2751
|
+
);
|
2704
2752
|
} catch (error) {
|
2705
2753
|
debug4("Failed to analyze CAPTCHA complexity:", error);
|
2706
2754
|
}
|
@@ -2717,7 +2765,9 @@ Return only "complex" or "simple" based on your analysis.
|
|
2717
2765
|
await this.aiTap(action.target, { deepThink: shouldUseDeepThink });
|
2718
2766
|
} else if (action.type === "input" && action.value) {
|
2719
2767
|
if (action.target) {
|
2720
|
-
await this.aiInput(action.value, action.target, {
|
2768
|
+
await this.aiInput(action.value, action.target, {
|
2769
|
+
deepThink: shouldUseDeepThink
|
2770
|
+
});
|
2721
2771
|
}
|
2722
2772
|
} else if (action.type === "verify" && action.target) {
|
2723
2773
|
await this.aiTap(action.target, { deepThink: shouldUseDeepThink });
|
@@ -2729,7 +2779,9 @@ Return only "complex" or "simple" based on your analysis.
|
|
2729
2779
|
if (action.coordinates) {
|
2730
2780
|
const x = action.coordinates[0];
|
2731
2781
|
const y = action.coordinates[1];
|
2732
|
-
await this.aiTap(`element at coordinates (${x}, ${y})`, {
|
2782
|
+
await this.aiTap(`element at coordinates (${x}, ${y})`, {
|
2783
|
+
deepThink: shouldUseDeepThink
|
2784
|
+
});
|
2733
2785
|
} else if (action.target) {
|
2734
2786
|
await this.aiTap(action.target, { deepThink: shouldUseDeepThink });
|
2735
2787
|
}
|
@@ -2881,25 +2933,27 @@ ${errors}`);
|
|
2881
2933
|
const executionDump = {
|
2882
2934
|
name: screenshotTitle,
|
2883
2935
|
description: content,
|
2884
|
-
tasks: [
|
2885
|
-
|
2886
|
-
|
2887
|
-
|
2888
|
-
|
2889
|
-
|
2890
|
-
|
2891
|
-
|
2892
|
-
|
2893
|
-
|
2894
|
-
|
2895
|
-
|
2896
|
-
|
2897
|
-
|
2898
|
-
|
2899
|
-
|
2900
|
-
|
2936
|
+
tasks: [
|
2937
|
+
{
|
2938
|
+
type: "Screenshot",
|
2939
|
+
subType: "log",
|
2940
|
+
status: "finished",
|
2941
|
+
executor: null,
|
2942
|
+
param: {
|
2943
|
+
title: screenshotTitle,
|
2944
|
+
content
|
2945
|
+
},
|
2946
|
+
output: {
|
2947
|
+
screenshot
|
2948
|
+
},
|
2949
|
+
thought: `Logged screenshot: ${screenshotTitle}`,
|
2950
|
+
timing: {
|
2951
|
+
start: Date.now(),
|
2952
|
+
end: Date.now(),
|
2953
|
+
cost: 0
|
2954
|
+
}
|
2901
2955
|
}
|
2902
|
-
|
2956
|
+
],
|
2903
2957
|
sdkVersion: "1.0.0",
|
2904
2958
|
logTime: Date.now(),
|
2905
2959
|
model_name: "screenshot"
|
@@ -2951,7 +3005,9 @@ ${errors}`);
|
|
2951
3005
|
totalTasks: stats.analytics.totalTasks,
|
2952
3006
|
memoryHits: stats.analytics.memoryHits,
|
2953
3007
|
memoryMisses: stats.analytics.memoryMisses,
|
2954
|
-
memoryEffectiveness: Math.round(
|
3008
|
+
memoryEffectiveness: Math.round(
|
3009
|
+
stats.analytics.memoryEffectiveness * 100
|
3010
|
+
),
|
2955
3011
|
averageMemorySize: Math.round(stats.analytics.averageMemorySize * 100) / 100
|
2956
3012
|
},
|
2957
3013
|
config: stats.config,
|
@@ -3015,7 +3071,9 @@ ${errors}`);
|
|
3015
3071
|
calculateSuccessRate(memory) {
|
3016
3072
|
if (memory.length === 0)
|
3017
3073
|
return 0;
|
3018
|
-
const successCount = memory.filter(
|
3074
|
+
const successCount = memory.filter(
|
3075
|
+
(item) => item.metadata?.success !== false
|
3076
|
+
).length;
|
3019
3077
|
return Math.round(successCount / memory.length * 100);
|
3020
3078
|
}
|
3021
3079
|
calculateAverageExecutionTime(memory) {
|
@@ -3154,7 +3212,7 @@ var BridgeServer = class {
|
|
3154
3212
|
this.socket = socket;
|
3155
3213
|
const clientVersion = socket.handshake.query.version;
|
3156
3214
|
(0, import_utils16.logMsg)(
|
3157
|
-
`Bridge connected, cli-side version v${"1.6.
|
3215
|
+
`Bridge connected, cli-side version v${"1.6.2"}, browser-side version v${clientVersion}`
|
3158
3216
|
);
|
3159
3217
|
socket.on("bridge-call-response" /* CallResponse */, (params) => {
|
3160
3218
|
const id = params.id;
|
@@ -3185,7 +3243,7 @@ var BridgeServer = class {
|
|
3185
3243
|
setTimeout(() => {
|
3186
3244
|
this.onConnect?.();
|
3187
3245
|
const payload = {
|
3188
|
-
version: "1.6.
|
3246
|
+
version: "1.6.2"
|
3189
3247
|
};
|
3190
3248
|
socket.emit("bridge-connected" /* Connected */, payload);
|
3191
3249
|
Promise.resolve().then(() => {
|