@midscene/core 1.17.5-beta-20261102094111.0 → 1.17.5

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.
Files changed (122) hide show
  1. package/dist/es/agent/agent-report-manager.mjs +28 -5
  2. package/dist/es/agent/agent-report-manager.mjs.map +1 -1
  3. package/dist/es/agent/agent.mjs +6 -22
  4. package/dist/es/agent/agent.mjs.map +1 -1
  5. package/dist/es/agent/tasks.mjs +57 -103
  6. package/dist/es/agent/tasks.mjs.map +1 -1
  7. package/dist/es/agent/utils.mjs +1 -1
  8. package/dist/es/ai-model/workflows/planning/custom-planning.mjs +1 -1
  9. package/dist/es/ai-model/workflows/planning/custom-planning.mjs.map +1 -1
  10. package/dist/es/ai-model/workflows/planning/standard-planning.mjs +1 -1
  11. package/dist/es/ai-model/workflows/planning/standard-planning.mjs.map +1 -1
  12. package/dist/es/dump/html-utils.mjs +51 -68
  13. package/dist/es/dump/html-utils.mjs.map +1 -1
  14. package/dist/es/dump/report-artifact-publication.mjs +52 -0
  15. package/dist/es/dump/report-artifact-publication.mjs.map +1 -0
  16. package/dist/es/dump/report-artifact-store.mjs +2 -2
  17. package/dist/es/dump/report-artifact-store.mjs.map +1 -1
  18. package/dist/es/dump/report-artifact-writer.mjs +129 -0
  19. package/dist/es/dump/report-artifact-writer.mjs.map +1 -0
  20. package/dist/es/dump/report-session.mjs +229 -0
  21. package/dist/es/dump/report-session.mjs.map +1 -0
  22. package/dist/es/dump/test-report-images.mjs +68 -42
  23. package/dist/es/dump/test-report-images.mjs.map +1 -1
  24. package/dist/es/index.mjs +2 -2
  25. package/dist/es/index.mjs.map +1 -1
  26. package/dist/es/report-cli.mjs +38 -11
  27. package/dist/es/report-cli.mjs.map +1 -1
  28. package/dist/es/report-generator.mjs +2 -1
  29. package/dist/es/report-generator.mjs.map +1 -1
  30. package/dist/es/report-html-template.mjs +1 -1
  31. package/dist/es/report.mjs +152 -159
  32. package/dist/es/report.mjs.map +1 -1
  33. package/dist/es/task-runner.mjs +1 -16
  34. package/dist/es/task-runner.mjs.map +1 -1
  35. package/dist/es/test-run-report.mjs.map +1 -1
  36. package/dist/es/types.mjs.map +1 -1
  37. package/dist/es/utils.mjs +1 -1
  38. package/dist/es/yaml/player.mjs +1 -1
  39. package/dist/es/yaml/player.mjs.map +1 -1
  40. package/dist/lib/agent/agent-report-manager.js +27 -4
  41. package/dist/lib/agent/agent-report-manager.js.map +1 -1
  42. package/dist/lib/agent/agent.js +6 -22
  43. package/dist/lib/agent/agent.js.map +1 -1
  44. package/dist/lib/agent/tasks.js +56 -102
  45. package/dist/lib/agent/tasks.js.map +1 -1
  46. package/dist/lib/agent/utils.js +1 -1
  47. package/dist/lib/ai-model/workflows/planning/custom-planning.js +1 -1
  48. package/dist/lib/ai-model/workflows/planning/custom-planning.js.map +1 -1
  49. package/dist/lib/ai-model/workflows/planning/standard-planning.js +1 -1
  50. package/dist/lib/ai-model/workflows/planning/standard-planning.js.map +1 -1
  51. package/dist/lib/dump/html-utils.js +59 -70
  52. package/dist/lib/dump/html-utils.js.map +1 -1
  53. package/dist/lib/dump/report-artifact-publication.js +89 -0
  54. package/dist/lib/dump/report-artifact-publication.js.map +1 -0
  55. package/dist/lib/dump/report-artifact-store.js +2 -2
  56. package/dist/lib/dump/report-artifact-store.js.map +1 -1
  57. package/dist/lib/dump/report-artifact-writer.js +163 -0
  58. package/dist/lib/dump/report-artifact-writer.js.map +1 -0
  59. package/dist/lib/dump/report-session.js +266 -0
  60. package/dist/lib/dump/report-session.js.map +1 -0
  61. package/dist/lib/dump/test-report-images.js +67 -41
  62. package/dist/lib/dump/test-report-images.js.map +1 -1
  63. package/dist/lib/index.js +3 -0
  64. package/dist/lib/index.js.map +1 -1
  65. package/dist/lib/report-cli.js +37 -10
  66. package/dist/lib/report-cli.js.map +1 -1
  67. package/dist/lib/report-generator.js +2 -1
  68. package/dist/lib/report-generator.js.map +1 -1
  69. package/dist/lib/report-html-template.js +1 -1
  70. package/dist/lib/report.js +152 -153
  71. package/dist/lib/report.js.map +1 -1
  72. package/dist/lib/task-runner.js +0 -15
  73. package/dist/lib/task-runner.js.map +1 -1
  74. package/dist/lib/test-run-report.js.map +1 -1
  75. package/dist/lib/types.js.map +1 -1
  76. package/dist/lib/utils.js +1 -1
  77. package/dist/lib/yaml/player.js +1 -1
  78. package/dist/lib/yaml/player.js.map +1 -1
  79. package/dist/types/agent/agent-report-manager.d.ts +4 -1
  80. package/dist/types/agent/agent-report-manager.d.ts.map +1 -1
  81. package/dist/types/agent/agent.d.ts +1 -10
  82. package/dist/types/agent/agent.d.ts.map +1 -1
  83. package/dist/types/agent/tasks.d.ts +1 -3
  84. package/dist/types/agent/tasks.d.ts.map +1 -1
  85. package/dist/types/dump/html-utils.d.ts +7 -1
  86. package/dist/types/dump/html-utils.d.ts.map +1 -1
  87. package/dist/types/dump/report-artifact-publication.d.ts +5 -0
  88. package/dist/types/dump/report-artifact-publication.d.ts.map +1 -0
  89. package/dist/types/dump/report-artifact-store.d.ts +1 -1
  90. package/dist/types/dump/report-artifact-store.d.ts.map +1 -1
  91. package/dist/types/dump/report-artifact-writer.d.ts +21 -0
  92. package/dist/types/dump/report-artifact-writer.d.ts.map +1 -0
  93. package/dist/types/dump/report-session.d.ts +48 -0
  94. package/dist/types/dump/report-session.d.ts.map +1 -0
  95. package/dist/types/dump/test-report-images.d.ts +5 -2
  96. package/dist/types/dump/test-report-images.d.ts.map +1 -1
  97. package/dist/types/index.d.ts +1 -1
  98. package/dist/types/index.d.ts.map +1 -1
  99. package/dist/types/report-cli.d.ts +2 -1
  100. package/dist/types/report-cli.d.ts.map +1 -1
  101. package/dist/types/report-generator.d.ts.map +1 -1
  102. package/dist/types/report.d.ts +11 -0
  103. package/dist/types/report.d.ts.map +1 -1
  104. package/dist/types/task-runner.d.ts +0 -1
  105. package/dist/types/task-runner.d.ts.map +1 -1
  106. package/dist/types/test-run-report.d.ts +2 -2
  107. package/dist/types/test-run-report.d.ts.map +1 -1
  108. package/dist/types/types.d.ts +0 -10
  109. package/dist/types/types.d.ts.map +1 -1
  110. package/package.json +2 -2
  111. package/dist/es/agent/plan-freshness.mjs +0 -39
  112. package/dist/es/agent/plan-freshness.mjs.map +0 -1
  113. package/dist/es/agent/planned-wait.mjs +0 -62
  114. package/dist/es/agent/planned-wait.mjs.map +0 -1
  115. package/dist/lib/agent/plan-freshness.js +0 -76
  116. package/dist/lib/agent/plan-freshness.js.map +0 -1
  117. package/dist/lib/agent/planned-wait.js +0 -105
  118. package/dist/lib/agent/planned-wait.js.map +0 -1
  119. package/dist/types/agent/plan-freshness.d.ts +0 -15
  120. package/dist/types/agent/plan-freshness.d.ts.map +0 -1
  121. package/dist/types/agent/planned-wait.d.ts +0 -11
  122. package/dist/types/agent/planned-wait.d.ts.map +0 -1
@@ -2,7 +2,8 @@ import { getDebug } from "@midscene/shared/logger";
2
2
  import { assert, ifInBrowser, uuid } from "@midscene/shared/utils";
3
3
  import { IS_REPORT_BUILD } from "../constants.mjs";
4
4
  import { generateTestRunReportScriptTag } from "../dump/html-utils.mjs";
5
- import { ReportGenerator } from "../report-generator.mjs";
5
+ import { currentReportSession } from "../dump/report-session.mjs";
6
+ import { ReportGenerator, assertReportGenerationOptions, nullReportGenerator } from "../report-generator.mjs";
6
7
  import { WorkflowError } from "../test-runner/errors.mjs";
7
8
  import { buildAgentTestRunReportDump } from "../test-runner/reporting/agent-report.mjs";
8
9
  import { executionRecordsToReportInput } from "../test-runner/reporting/execution-record.mjs";
@@ -44,8 +45,20 @@ class AgentReportManager {
44
45
  set reportFileName(value) {
45
46
  this.reportState.fileName = value;
46
47
  }
47
- _prepareForTestRunner() {
48
- this.reportState.generator.enableSourceSnapshots?.();
48
+ async _prepareForTestRunner() {
49
+ const report = this.reportState;
50
+ const session = currentReportSession();
51
+ if (session && session !== report.session) {
52
+ if (report.session) throw new Error('An Agent cannot be shared by different Test report sessions. Await resetDump() between runs.');
53
+ this.assertReportIdle();
54
+ await report.generator.finalize();
55
+ const recorder = session.createRecorder(()=>this.isReportBusy(report));
56
+ this.clearDumpInMemory(report);
57
+ report.generator = recorder;
58
+ report.session = session;
59
+ report.file = void 0;
60
+ }
61
+ report.generator.enableSourceSnapshots?.();
49
62
  }
50
63
  async _createReportSource(scopeId, executionIds) {
51
64
  return this.reportState.generator.createSourceSnapshot?.(scopeId, executionIds);
@@ -110,10 +123,12 @@ class AgentReportManager {
110
123
  });
111
124
  }
112
125
  createReportState(fileName, reuseExistingReport = false) {
113
- return {
126
+ assertReportGenerationOptions(this.opts);
127
+ const session = currentReportSession();
128
+ const state = {
114
129
  dump: this.createEmptyDump(),
115
130
  fileName,
116
- generator: ReportGenerator.create(fileName, {
131
+ generator: session ? nullReportGenerator : ReportGenerator.create(fileName, {
117
132
  generateReport: this.opts.generateReport,
118
133
  persistExecutionDump: this.opts.persistExecutionDump,
119
134
  outputFormat: this.opts.outputFormat,
@@ -125,6 +140,14 @@ class AgentReportManager {
125
140
  yamlRecords: [],
126
141
  activeOperations: new Set()
127
142
  };
143
+ if (session) {
144
+ state.generator = session.createRecorder(()=>this.isReportBusy(state));
145
+ state.session = session;
146
+ }
147
+ return state;
148
+ }
149
+ isReportBusy(report) {
150
+ return report.activeOperations.size > 0 || this.context.isExternallyBusy();
128
151
  }
129
152
  clearDumpInMemory(report = this.reportState) {
130
153
  report.dump = this.createEmptyDump();
@@ -1 +1 @@
1
- {"version":3,"file":"agent/agent-report-manager.mjs","sources":["../../../src/agent/agent-report-manager.ts"],"sourcesContent":["import { getDebug } from '@midscene/shared/logger';\nimport { assert, ifInBrowser, uuid } from '@midscene/shared/utils';\nimport { IS_REPORT_BUILD } from '../constants';\nimport { generateTestRunReportScriptTag } from '../dump/html-utils';\nimport { type IReportGenerator, ReportGenerator } from '../report-generator';\nimport type { TaskRunner } from '../task-runner';\nimport { WorkflowError } from '../test-runner/errors';\nimport type { WorkflowExecutionRecord } from '../test-runner/execution-record';\nimport { buildAgentTestRunReportDump } from '../test-runner/reporting/agent-report';\nimport { executionRecordsToReportInput } from '../test-runner/reporting/execution-record';\nimport {\n type AgentOpt,\n type ExecutionDump,\n ReportActionDump,\n type ReportMeta,\n} from '../types';\nimport { getVersion, reportHTMLContent } from '../utils';\nimport { getReportFileName } from './utils';\n\nconst warn = getDebug('agent', { console: true });\n\ntype ReportOptions = Pick<\n AgentOpt,\n | 'groupName'\n | 'groupDescription'\n | 'generateReport'\n | 'persistExecutionDump'\n | 'outputFormat'\n | 'autoPrintReportMsg'\n | 'reportAttributes'\n | 'reportFileName'\n | 'testId'\n>;\n\ninterface AgentReportContext {\n getOptions(): ReportOptions;\n getDeviceType(): ReportActionDump['deviceType'];\n isDestroyed(): boolean;\n isExternallyBusy(): boolean;\n}\n\ninterface AgentReportState {\n dump: ReportActionDump;\n file?: string | null;\n fileName?: string;\n generator: IReportGenerator;\n finalization?: Promise<string | undefined>;\n lastExecution?: ExecutionDump;\n executionIndexByRunner: WeakMap<TaskRunner, number>;\n yamlScopeId: string;\n yamlRecords: WorkflowExecutionRecord[];\n activeOperations: Set<Promise<unknown>>;\n}\n\n/** Owns report state and persistence; execution and device ownership stay with Agent. */\nexport class AgentReportManager {\n private reportState: AgentReportState;\n private reportReset?: Promise<ReportActionDump>;\n private readonly reportByRunner = new WeakMap<TaskRunner, AgentReportState>();\n private dumpUpdateListeners: Array<\n (dump: string, executionDump?: ExecutionDump) => void\n > = [];\n\n constructor(private readonly context: AgentReportContext) {\n const opts = this.opts;\n const fileName =\n opts.reportFileName ??\n getReportFileName(opts.testId || context.getDeviceType() || 'web');\n this.reportState = this.createReportState(\n fileName,\n opts.reportAttributes?.['data-group-id'] === fileName,\n );\n }\n\n private get opts(): ReportOptions {\n return this.context.getOptions();\n }\n\n get dump(): ReportActionDump {\n return this.reportState.dump;\n }\n set dump(value: ReportActionDump) {\n this.reportState.dump = value;\n }\n\n get reportFile(): string | null | undefined {\n return this.reportState.file;\n }\n set reportFile(value: string | null | undefined) {\n this.reportState.file = value;\n }\n\n get reportFileName(): string | undefined {\n return this.reportState.fileName;\n }\n set reportFileName(value: string | undefined) {\n this.reportState.fileName = value;\n }\n\n /** @internal Runner snapshots retain immutable data and shared image files. */\n _prepareForTestRunner(): void {\n this.reportState.generator.enableSourceSnapshots?.();\n }\n async _createReportSource(scopeId: string, executionIds?: readonly string[]) {\n return this.reportState.generator.createSourceSnapshot?.(\n scopeId,\n executionIds,\n );\n }\n\n /** @internal The Agent owns one report stream across root YAML invocations. */\n async _writeYamlExecutionReport(\n record: WorkflowExecutionRecord,\n ): Promise<string | undefined> {\n const report = this.reportState;\n const existingIndex = report.yamlRecords.findIndex(\n (entry) => entry.runId === record.runId,\n );\n const recordIndex =\n existingIndex < 0 ? report.yamlRecords.length : existingIndex;\n report.yamlRecords[recordIndex] = record;\n try {\n const path = await report.generator.writeRunnerReport?.(\n this.buildYamlReportInput(),\n report.yamlScopeId,\n this.getReportMeta(),\n );\n report.file = path ?? report.file;\n return path;\n } catch (error) {\n report.yamlRecords[recordIndex] = Object.freeze({\n ...record,\n status: 'failed',\n reportError: error,\n });\n throw error;\n }\n }\n\n private buildYamlReportInput() {\n const scopedRecords = this.reportState.yamlRecords.map((entry) => ({\n ...entry,\n ...(entry.execution\n ? {\n execution: {\n document: {\n ...entry.execution.document,\n reportScopeId: this.reportState.yamlScopeId,\n },\n cases: entry.execution.cases.map((outcome) => ({\n ...outcome,\n ...(outcome.run\n ? {\n run: {\n ...outcome.run,\n reportScopeId: this.reportState.yamlScopeId,\n },\n }\n : {}),\n ...(outcome.attempts\n ? {\n attempts: outcome.attempts.map((attempt) => ({\n ...attempt,\n reportScopeId: this.reportState.yamlScopeId,\n })),\n }\n : {}),\n })),\n },\n }\n : {}),\n }));\n return executionRecordsToReportInput(scopedRecords, {\n runId: this.reportState.yamlScopeId,\n });\n }\n\n private createEmptyDump(): ReportActionDump {\n return new ReportActionDump({\n sdkVersion: getVersion(),\n groupName: this.opts.groupName!,\n groupDescription: this.opts.groupDescription,\n executions: [],\n modelBriefs: [],\n deviceType: this.context.getDeviceType(),\n });\n }\n\n private createReportState(\n fileName: string,\n reuseExistingReport = false,\n ): AgentReportState {\n return {\n dump: this.createEmptyDump(),\n fileName,\n generator: ReportGenerator.create(fileName, {\n generateReport: this.opts.generateReport,\n persistExecutionDump: this.opts.persistExecutionDump,\n outputFormat: this.opts.outputFormat,\n autoPrintReportMsg: this.opts.autoPrintReportMsg,\n reuseExistingReport,\n }),\n executionIndexByRunner: new WeakMap(),\n yamlScopeId: uuid(),\n yamlRecords: [],\n activeOperations: new Set(),\n };\n }\n\n private clearDumpInMemory(report = this.reportState): void {\n report.dump = this.createEmptyDump();\n report.executionIndexByRunner = new WeakMap();\n report.lastExecution = undefined;\n report.yamlRecords.length = 0;\n }\n\n private assertReportIdle(): void {\n assert(\n !this.reportState.activeOperations.size &&\n !this.context.isExternallyBusy(),\n 'Cannot reset or finalize a report while the Agent is executing. Await the active operation first.',\n );\n }\n\n assertReportWritable(): AgentReportState {\n const report = this.reportState;\n assert(\n !this.context.isDestroyed(),\n 'Cannot execute using a destroyed Agent.',\n );\n assert(\n !this.reportReset,\n 'Report reset is in progress. Await resetDump() first.',\n );\n assert(\n !report.finalization,\n 'The report has been finalized. Call and await resetDump() before executing again.',\n );\n return report;\n }\n\n async withReportOperation<T>(operation: () => Promise<T>): Promise<T> {\n const report = this.assertReportWritable();\n const pending = Promise.resolve().then(operation);\n report.activeOperations.add(pending);\n try {\n return await pending;\n } finally {\n report.activeOperations.delete(pending);\n }\n }\n\n /**\n * Finalize the preceding report and reset execution records for a new report.\n * Historical artifacts are retained; this Agent and its device stay connected.\n * Await this method before executing again. Concurrent resets share one reset.\n */\n async resetDump(): Promise<ReportActionDump> {\n assert(\n !this.context.isDestroyed(),\n 'Cannot reset a report using a destroyed Agent.',\n );\n if (this.reportReset) return this.reportReset;\n this.assertReportIdle();\n this.reportReset = (async () => {\n try {\n await this.finalizeReport();\n } catch (error) {\n // Failure belongs to the preceding report, not to the next write queue.\n warn(\n `Failed to finalize previous report; resetting dump: ${String(error)}`,\n );\n }\n assert(\n !this.context.isDestroyed(),\n 'Cannot reset a report using a destroyed Agent.',\n );\n const fileName = getReportFileName(\n this.opts.testId || this.context.getDeviceType() || 'web',\n );\n this.reportState = this.createReportState(fileName);\n return this.dump;\n })();\n try {\n return await this.reportReset;\n } finally {\n this.reportReset = undefined;\n }\n }\n\n /**\n * Seal the current report and release its in-memory records without\n * disconnecting the device. Export in-memory data before calling this method.\n * Repeated calls return the same result and never rewrite published artifacts.\n */\n async finalizeReport(): Promise<string | undefined> {\n const report = this.reportState;\n if (!report.finalization) {\n this.assertReportIdle();\n report.finalization = (async () => {\n await report.generator.flush();\n const path = await report.generator.finalize();\n report.file = path;\n this.clearDumpInMemory(report);\n return path;\n })();\n }\n return report.finalization;\n }\n\n appendExecutionDump(execution: ExecutionDump, runner?: TaskRunner) {\n assert(\n !this.reportState.finalization,\n 'Cannot append to a finalized report. Await resetDump() first.',\n );\n const currentDump = this.dump;\n if (runner) {\n const existingIndex = this.reportState.executionIndexByRunner.get(runner);\n if (existingIndex !== undefined) {\n currentDump.executions[existingIndex] = execution;\n return;\n }\n currentDump.executions.push(execution);\n this.reportState.executionIndexByRunner.set(\n runner,\n currentDump.executions.length - 1,\n );\n return;\n }\n currentDump.executions.push(execution);\n }\n\n dumpDataString(opt?: { inlineScreenshots?: boolean }) {\n // update dump info\n this.dump.groupName = this.opts.groupName!;\n this.dump.groupDescription = this.opts.groupDescription;\n // In browser environment, use inline screenshots since file system is not available\n if (ifInBrowser || opt?.inlineScreenshots) {\n return this.dump.serializeWithInlineScreenshots();\n }\n return this.dump.serialize();\n }\n\n reportHTMLString(getDumpString: () => string) {\n // Short-circuit at the call site because JavaScript evaluates function\n // arguments first. This avoids serializing the dump (including inline\n // screenshots) when the Report Viewer build does not need report HTML.\n if (IS_REPORT_BUILD) {\n return '';\n }\n\n // dumpDataString() handles browser environment with inline screenshots\n const dumpString = getDumpString();\n if (!this.reportState.yamlRecords.length)\n return reportHTMLContent(dumpString);\n\n // Browser exports have no file writer, so the execution record must own\n // the hierarchy independently of whether file report generation is enabled.\n const reportId = this.reportState.yamlScopeId;\n const runnerDump = buildAgentTestRunReportDump(\n this.buildYamlReportInput(),\n this.dump,\n {\n reportId,\n scopeId: this.reportState.yamlScopeId,\n sourcePath: this.reportFile ?? '<inline-agent-report>',\n },\n );\n return `${reportHTMLContent({\n dumpString,\n attributes: { 'data-group-id': reportId, 'data-report-id': reportId },\n })}\\n${generateTestRunReportScriptTag(runnerDump)}`;\n }\n\n writeOutActionDumps(executionDump?: ExecutionDump) {\n const report = this.reportState;\n if (report.finalization) {\n if (executionDump) {\n throw new WorkflowError(\n 'Cannot append to a finalized report. Await resetDump() first.',\n {\n code: 'REPORT_FINALIZED',\n },\n );\n }\n return;\n }\n const exec = executionDump || report.lastExecution;\n if (exec) {\n report.lastExecution = exec;\n report.generator.onExecutionUpdate(\n exec,\n this.getReportMeta(),\n this.opts.reportAttributes,\n );\n }\n report.file = report.generator.getReportPath();\n }\n\n /** Persist current report data without disposing this Agent or its device. */\n async flushReport(): Promise<string | undefined> {\n if (this.reportReset) await this.reportReset;\n const report = this.reportState;\n if (report.finalization) return report.finalization;\n this.writeOutActionDumps();\n await report.generator.flush();\n return report.lastExecution ? (report.file ?? undefined) : undefined;\n }\n\n private getReportMeta(): ReportMeta {\n return {\n groupName: this.dump.groupName,\n groupDescription: this.dump.groupDescription,\n sdkVersion: this.dump.sdkVersion,\n modelBriefs: this.dump.modelBriefs,\n deviceType: this.dump.deviceType,\n };\n }\n\n get onDumpUpdate():\n | ((dump: string, executionDump?: ExecutionDump) => void)\n | undefined {\n return this.dumpUpdateListeners[0];\n }\n\n set onDumpUpdate(callback:\n | ((dump: string, executionDump?: ExecutionDump) => void)\n | undefined) {\n // Clear existing listeners\n this.dumpUpdateListeners = [];\n // Add callback to array if provided\n if (callback) {\n this.dumpUpdateListeners.push(callback);\n }\n }\n\n addDumpUpdateListener(\n listener: (dump: string, executionDump?: ExecutionDump) => void,\n ): () => void {\n this.dumpUpdateListeners.push(listener);\n\n // Return remove function\n return () => {\n this.removeDumpUpdateListener(listener);\n };\n }\n\n /**\n * Remove a dump update listener\n * @param listener The listener function to remove\n */\n removeDumpUpdateListener(\n listener: (dump: string, executionDump?: ExecutionDump) => void,\n ): void {\n const index = this.dumpUpdateListeners.indexOf(listener);\n if (index > -1) {\n this.dumpUpdateListeners.splice(index, 1);\n }\n }\n\n /**\n * Clear all dump update listeners\n */\n clearDumpUpdateListeners(): void {\n this.dumpUpdateListeners = [];\n }\n\n notifyDumpUpdateListeners(executionDump?: ExecutionDump) {\n if (this.dumpUpdateListeners.length === 0) return;\n const dumpString = this.dumpDataString();\n for (const listener of this.dumpUpdateListeners) {\n try {\n listener(dumpString, executionDump);\n } catch (error) {\n console.error('Error in onDumpUpdate listener', error);\n }\n }\n }\n\n bindRunner(runner: TaskRunner): void {\n this.reportByRunner.set(runner, this.reportState);\n }\n\n assertRunnerCurrent(runner: TaskRunner): void {\n const report = this.reportByRunner.get(runner);\n assert(\n report === this.reportState && !report.finalization,\n 'Cannot write a late execution update into a different or finalized report.',\n );\n }\n\n async flushPendingWrites(): Promise<void> {\n await this.reportState.generator.flush();\n }\n\n async waitForOperations(): Promise<void> {\n while (this.reportState.activeOperations.size) {\n await Promise.allSettled([...this.reportState.activeOperations]);\n }\n }\n\n async waitForReset(): Promise<void> {\n if (this.reportReset) await this.reportReset.catch(() => {});\n }\n}\n"],"names":["warn","getDebug","AgentReportManager","value","scopeId","executionIds","record","report","existingIndex","entry","recordIndex","path","error","Object","scopedRecords","outcome","attempt","executionRecordsToReportInput","ReportActionDump","getVersion","fileName","reuseExistingReport","ReportGenerator","WeakMap","uuid","Set","undefined","assert","operation","pending","Promise","String","getReportFileName","execution","runner","currentDump","opt","ifInBrowser","getDumpString","IS_REPORT_BUILD","dumpString","reportHTMLContent","reportId","runnerDump","buildAgentTestRunReportDump","generateTestRunReportScriptTag","executionDump","WorkflowError","exec","callback","listener","index","console","context","opts"],"mappings":";;;;;;;;;;;;;;;;;;;;;AAmBA,MAAMA,OAAOC,SAAS,SAAS;IAAE,SAAS;AAAK;AAoCxC,MAAMC;IAmBX,IAAY,OAAsB;QAChC,OAAO,IAAI,CAAC,OAAO,CAAC,UAAU;IAChC;IAEA,IAAI,OAAyB;QAC3B,OAAO,IAAI,CAAC,WAAW,CAAC,IAAI;IAC9B;IACA,IAAI,KAAKC,KAAuB,EAAE;QAChC,IAAI,CAAC,WAAW,CAAC,IAAI,GAAGA;IAC1B;IAEA,IAAI,aAAwC;QAC1C,OAAO,IAAI,CAAC,WAAW,CAAC,IAAI;IAC9B;IACA,IAAI,WAAWA,KAAgC,EAAE;QAC/C,IAAI,CAAC,WAAW,CAAC,IAAI,GAAGA;IAC1B;IAEA,IAAI,iBAAqC;QACvC,OAAO,IAAI,CAAC,WAAW,CAAC,QAAQ;IAClC;IACA,IAAI,eAAeA,KAAyB,EAAE;QAC5C,IAAI,CAAC,WAAW,CAAC,QAAQ,GAAGA;IAC9B;IAGA,wBAA8B;QAC5B,IAAI,CAAC,WAAW,CAAC,SAAS,CAAC,qBAAqB;IAClD;IACA,MAAM,oBAAoBC,OAAe,EAAEC,YAAgC,EAAE;QAC3E,OAAO,IAAI,CAAC,WAAW,CAAC,SAAS,CAAC,oBAAoB,GACpDD,SACAC;IAEJ;IAGA,MAAM,0BACJC,MAA+B,EACF;QAC7B,MAAMC,SAAS,IAAI,CAAC,WAAW;QAC/B,MAAMC,gBAAgBD,OAAO,WAAW,CAAC,SAAS,CAChD,CAACE,QAAUA,MAAM,KAAK,KAAKH,OAAO,KAAK;QAEzC,MAAMI,cACJF,gBAAgB,IAAID,OAAO,WAAW,CAAC,MAAM,GAAGC;QAClDD,OAAO,WAAW,CAACG,YAAY,GAAGJ;QAClC,IAAI;YACF,MAAMK,OAAO,MAAMJ,OAAO,SAAS,CAAC,iBAAiB,GACnD,IAAI,CAAC,oBAAoB,IACzBA,OAAO,WAAW,EAClB,IAAI,CAAC,aAAa;YAEpBA,OAAO,IAAI,GAAGI,QAAQJ,OAAO,IAAI;YACjC,OAAOI;QACT,EAAE,OAAOC,OAAO;YACdL,OAAO,WAAW,CAACG,YAAY,GAAGG,OAAO,MAAM,CAAC;gBAC9C,GAAGP,MAAM;gBACT,QAAQ;gBACR,aAAaM;YACf;YACA,MAAMA;QACR;IACF;IAEQ,uBAAuB;QAC7B,MAAME,gBAAgB,IAAI,CAAC,WAAW,CAAC,WAAW,CAAC,GAAG,CAAC,CAACL,QAAW;gBACjE,GAAGA,KAAK;gBACR,GAAIA,MAAM,SAAS,GACf;oBACE,WAAW;wBACT,UAAU;4BACR,GAAGA,MAAM,SAAS,CAAC,QAAQ;4BAC3B,eAAe,IAAI,CAAC,WAAW,CAAC,WAAW;wBAC7C;wBACA,OAAOA,MAAM,SAAS,CAAC,KAAK,CAAC,GAAG,CAAC,CAACM,UAAa;gCAC7C,GAAGA,OAAO;gCACV,GAAIA,QAAQ,GAAG,GACX;oCACE,KAAK;wCACH,GAAGA,QAAQ,GAAG;wCACd,eAAe,IAAI,CAAC,WAAW,CAAC,WAAW;oCAC7C;gCACF,IACA,CAAC,CAAC;gCACN,GAAIA,QAAQ,QAAQ,GAChB;oCACE,UAAUA,QAAQ,QAAQ,CAAC,GAAG,CAAC,CAACC,UAAa;4CAC3C,GAAGA,OAAO;4CACV,eAAe,IAAI,CAAC,WAAW,CAAC,WAAW;wCAC7C;gCACF,IACA,CAAC,CAAC;4BACR;oBACF;gBACF,IACA,CAAC,CAAC;YACR;QACA,OAAOC,8BAA8BH,eAAe;YAClD,OAAO,IAAI,CAAC,WAAW,CAAC,WAAW;QACrC;IACF;IAEQ,kBAAoC;QAC1C,OAAO,IAAII,iBAAiB;YAC1B,YAAYC;YACZ,WAAW,IAAI,CAAC,IAAI,CAAC,SAAS;YAC9B,kBAAkB,IAAI,CAAC,IAAI,CAAC,gBAAgB;YAC5C,YAAY,EAAE;YACd,aAAa,EAAE;YACf,YAAY,IAAI,CAAC,OAAO,CAAC,aAAa;QACxC;IACF;IAEQ,kBACNC,QAAgB,EAChBC,sBAAsB,KAAK,EACT;QAClB,OAAO;YACL,MAAM,IAAI,CAAC,eAAe;YAC1BD;YACA,WAAWE,gBAAgB,MAAM,CAACF,UAAU;gBAC1C,gBAAgB,IAAI,CAAC,IAAI,CAAC,cAAc;gBACxC,sBAAsB,IAAI,CAAC,IAAI,CAAC,oBAAoB;gBACpD,cAAc,IAAI,CAAC,IAAI,CAAC,YAAY;gBACpC,oBAAoB,IAAI,CAAC,IAAI,CAAC,kBAAkB;gBAChDC;YACF;YACA,wBAAwB,IAAIE;YAC5B,aAAaC;YACb,aAAa,EAAE;YACf,kBAAkB,IAAIC;QACxB;IACF;IAEQ,kBAAkBlB,SAAS,IAAI,CAAC,WAAW,EAAQ;QACzDA,OAAO,IAAI,GAAG,IAAI,CAAC,eAAe;QAClCA,OAAO,sBAAsB,GAAG,IAAIgB;QACpChB,OAAO,aAAa,GAAGmB;QACvBnB,OAAO,WAAW,CAAC,MAAM,GAAG;IAC9B;IAEQ,mBAAyB;QAC/BoB,OACE,CAAC,IAAI,CAAC,WAAW,CAAC,gBAAgB,CAAC,IAAI,IACrC,CAAC,IAAI,CAAC,OAAO,CAAC,gBAAgB,IAChC;IAEJ;IAEA,uBAAyC;QACvC,MAAMpB,SAAS,IAAI,CAAC,WAAW;QAC/BoB,OACE,CAAC,IAAI,CAAC,OAAO,CAAC,WAAW,IACzB;QAEFA,OACE,CAAC,IAAI,CAAC,WAAW,EACjB;QAEFA,OACE,CAACpB,OAAO,YAAY,EACpB;QAEF,OAAOA;IACT;IAEA,MAAM,oBAAuBqB,SAA2B,EAAc;QACpE,MAAMrB,SAAS,IAAI,CAAC,oBAAoB;QACxC,MAAMsB,UAAUC,QAAQ,OAAO,GAAG,IAAI,CAACF;QACvCrB,OAAO,gBAAgB,CAAC,GAAG,CAACsB;QAC5B,IAAI;YACF,OAAO,MAAMA;QACf,SAAU;YACRtB,OAAO,gBAAgB,CAAC,MAAM,CAACsB;QACjC;IACF;IAOA,MAAM,YAAuC;QAC3CF,OACE,CAAC,IAAI,CAAC,OAAO,CAAC,WAAW,IACzB;QAEF,IAAI,IAAI,CAAC,WAAW,EAAE,OAAO,IAAI,CAAC,WAAW;QAC7C,IAAI,CAAC,gBAAgB;QACrB,IAAI,CAAC,WAAW,GAAI;YAClB,IAAI;gBACF,MAAM,IAAI,CAAC,cAAc;YAC3B,EAAE,OAAOf,OAAO;gBAEdZ,KACE,CAAC,oDAAoD,EAAE+B,OAAOnB,QAAQ;YAE1E;YACAe,OACE,CAAC,IAAI,CAAC,OAAO,CAAC,WAAW,IACzB;YAEF,MAAMP,WAAWY,kBACf,IAAI,CAAC,IAAI,CAAC,MAAM,IAAI,IAAI,CAAC,OAAO,CAAC,aAAa,MAAM;YAEtD,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC,iBAAiB,CAACZ;YAC1C,OAAO,IAAI,CAAC,IAAI;QAClB;QACA,IAAI;YACF,OAAO,MAAM,IAAI,CAAC,WAAW;QAC/B,SAAU;YACR,IAAI,CAAC,WAAW,GAAGM;QACrB;IACF;IAOA,MAAM,iBAA8C;QAClD,MAAMnB,SAAS,IAAI,CAAC,WAAW;QAC/B,IAAI,CAACA,OAAO,YAAY,EAAE;YACxB,IAAI,CAAC,gBAAgB;YACrBA,OAAO,YAAY,GAAI;gBACrB,MAAMA,OAAO,SAAS,CAAC,KAAK;gBAC5B,MAAMI,OAAO,MAAMJ,OAAO,SAAS,CAAC,QAAQ;gBAC5CA,OAAO,IAAI,GAAGI;gBACd,IAAI,CAAC,iBAAiB,CAACJ;gBACvB,OAAOI;YACT;QACF;QACA,OAAOJ,OAAO,YAAY;IAC5B;IAEA,oBAAoB0B,SAAwB,EAAEC,MAAmB,EAAE;QACjEP,OACE,CAAC,IAAI,CAAC,WAAW,CAAC,YAAY,EAC9B;QAEF,MAAMQ,cAAc,IAAI,CAAC,IAAI;QAC7B,IAAID,QAAQ;YACV,MAAM1B,gBAAgB,IAAI,CAAC,WAAW,CAAC,sBAAsB,CAAC,GAAG,CAAC0B;YAClE,IAAI1B,AAAkBkB,WAAlBlB,eAA6B;gBAC/B2B,YAAY,UAAU,CAAC3B,cAAc,GAAGyB;gBACxC;YACF;YACAE,YAAY,UAAU,CAAC,IAAI,CAACF;YAC5B,IAAI,CAAC,WAAW,CAAC,sBAAsB,CAAC,GAAG,CACzCC,QACAC,YAAY,UAAU,CAAC,MAAM,GAAG;YAElC;QACF;QACAA,YAAY,UAAU,CAAC,IAAI,CAACF;IAC9B;IAEA,eAAeG,GAAqC,EAAE;QAEpD,IAAI,CAAC,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS;QACzC,IAAI,CAAC,IAAI,CAAC,gBAAgB,GAAG,IAAI,CAAC,IAAI,CAAC,gBAAgB;QAEvD,IAAIC,eAAeD,KAAK,mBACtB,OAAO,IAAI,CAAC,IAAI,CAAC,8BAA8B;QAEjD,OAAO,IAAI,CAAC,IAAI,CAAC,SAAS;IAC5B;IAEA,iBAAiBE,aAA2B,EAAE;QAI5C,IAAIC,iBACF,OAAO;QAIT,MAAMC,aAAaF;QACnB,IAAI,CAAC,IAAI,CAAC,WAAW,CAAC,WAAW,CAAC,MAAM,EACtC,OAAOG,kBAAkBD;QAI3B,MAAME,WAAW,IAAI,CAAC,WAAW,CAAC,WAAW;QAC7C,MAAMC,aAAaC,4BACjB,IAAI,CAAC,oBAAoB,IACzB,IAAI,CAAC,IAAI,EACT;YACEF;YACA,SAAS,IAAI,CAAC,WAAW,CAAC,WAAW;YACrC,YAAY,IAAI,CAAC,UAAU,IAAI;QACjC;QAEF,OAAO,GAAGD,kBAAkB;YAC1BD;YACA,YAAY;gBAAE,iBAAiBE;gBAAU,kBAAkBA;YAAS;QACtE,GAAG,EAAE,EAAEG,+BAA+BF,aAAa;IACrD;IAEA,oBAAoBG,aAA6B,EAAE;QACjD,MAAMvC,SAAS,IAAI,CAAC,WAAW;QAC/B,IAAIA,OAAO,YAAY,EAAE;YACvB,IAAIuC,eACF,MAAM,IAAIC,cACR,iEACA;gBACE,MAAM;YACR;YAGJ;QACF;QACA,MAAMC,OAAOF,iBAAiBvC,OAAO,aAAa;QAClD,IAAIyC,MAAM;YACRzC,OAAO,aAAa,GAAGyC;YACvBzC,OAAO,SAAS,CAAC,iBAAiB,CAChCyC,MACA,IAAI,CAAC,aAAa,IAClB,IAAI,CAAC,IAAI,CAAC,gBAAgB;QAE9B;QACAzC,OAAO,IAAI,GAAGA,OAAO,SAAS,CAAC,aAAa;IAC9C;IAGA,MAAM,cAA2C;QAC/C,IAAI,IAAI,CAAC,WAAW,EAAE,MAAM,IAAI,CAAC,WAAW;QAC5C,MAAMA,SAAS,IAAI,CAAC,WAAW;QAC/B,IAAIA,OAAO,YAAY,EAAE,OAAOA,OAAO,YAAY;QACnD,IAAI,CAAC,mBAAmB;QACxB,MAAMA,OAAO,SAAS,CAAC,KAAK;QAC5B,OAAOA,OAAO,aAAa,GAAIA,OAAO,IAAI,IAAImB,SAAaA;IAC7D;IAEQ,gBAA4B;QAClC,OAAO;YACL,WAAW,IAAI,CAAC,IAAI,CAAC,SAAS;YAC9B,kBAAkB,IAAI,CAAC,IAAI,CAAC,gBAAgB;YAC5C,YAAY,IAAI,CAAC,IAAI,CAAC,UAAU;YAChC,aAAa,IAAI,CAAC,IAAI,CAAC,WAAW;YAClC,YAAY,IAAI,CAAC,IAAI,CAAC,UAAU;QAClC;IACF;IAEA,IAAI,eAEU;QACZ,OAAO,IAAI,CAAC,mBAAmB,CAAC,EAAE;IACpC;IAEA,IAAI,aAAauB,QAEJ,EAAE;QAEb,IAAI,CAAC,mBAAmB,GAAG,EAAE;QAE7B,IAAIA,UACF,IAAI,CAAC,mBAAmB,CAAC,IAAI,CAACA;IAElC;IAEA,sBACEC,QAA+D,EACnD;QACZ,IAAI,CAAC,mBAAmB,CAAC,IAAI,CAACA;QAG9B,OAAO;YACL,IAAI,CAAC,wBAAwB,CAACA;QAChC;IACF;IAMA,yBACEA,QAA+D,EACzD;QACN,MAAMC,QAAQ,IAAI,CAAC,mBAAmB,CAAC,OAAO,CAACD;QAC/C,IAAIC,QAAQ,IACV,IAAI,CAAC,mBAAmB,CAAC,MAAM,CAACA,OAAO;IAE3C;IAKA,2BAAiC;QAC/B,IAAI,CAAC,mBAAmB,GAAG,EAAE;IAC/B;IAEA,0BAA0BL,aAA6B,EAAE;QACvD,IAAI,AAAoC,MAApC,IAAI,CAAC,mBAAmB,CAAC,MAAM,EAAQ;QAC3C,MAAMN,aAAa,IAAI,CAAC,cAAc;QACtC,KAAK,MAAMU,YAAY,IAAI,CAAC,mBAAmB,CAC7C,IAAI;YACFA,SAASV,YAAYM;QACvB,EAAE,OAAOlC,OAAO;YACdwC,QAAQ,KAAK,CAAC,kCAAkCxC;QAClD;IAEJ;IAEA,WAAWsB,MAAkB,EAAQ;QACnC,IAAI,CAAC,cAAc,CAAC,GAAG,CAACA,QAAQ,IAAI,CAAC,WAAW;IAClD;IAEA,oBAAoBA,MAAkB,EAAQ;QAC5C,MAAM3B,SAAS,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC2B;QACvCP,OACEpB,WAAW,IAAI,CAAC,WAAW,IAAI,CAACA,OAAO,YAAY,EACnD;IAEJ;IAEA,MAAM,qBAAoC;QACxC,MAAM,IAAI,CAAC,WAAW,CAAC,SAAS,CAAC,KAAK;IACxC;IAEA,MAAM,oBAAmC;QACvC,MAAO,IAAI,CAAC,WAAW,CAAC,gBAAgB,CAAC,IAAI,CAC3C,MAAMuB,QAAQ,UAAU,CAAC;eAAI,IAAI,CAAC,WAAW,CAAC,gBAAgB;SAAC;IAEnE;IAEA,MAAM,eAA8B;QAClC,IAAI,IAAI,CAAC,WAAW,EAAE,MAAM,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC,KAAO;IAC5D;IAxbA,YAA6BuB,OAA2B,CAAE;;QAP1D,uBAAQ,eAAR;QACA,uBAAQ,eAAR;QACA,uBAAiB,kBAAjB;QACA,uBAAQ,uBAAR;aAI6BA,OAAO,GAAPA;aALZ,cAAc,GAAG,IAAI9B;aAC9B,mBAAmB,GAEvB,EAAE;QAGJ,MAAM+B,OAAO,IAAI,CAAC,IAAI;QACtB,MAAMlC,WACJkC,KAAK,cAAc,IACnBtB,kBAAkBsB,KAAK,MAAM,IAAID,QAAQ,aAAa,MAAM;QAC9D,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC,iBAAiB,CACvCjC,UACAkC,KAAK,gBAAgB,EAAE,CAAC,gBAAgB,KAAKlC;IAEjD;AAgbF"}
1
+ {"version":3,"file":"agent/agent-report-manager.mjs","sources":["../../../src/agent/agent-report-manager.ts"],"sourcesContent":["import { getDebug } from '@midscene/shared/logger';\nimport { assert, ifInBrowser, uuid } from '@midscene/shared/utils';\nimport { IS_REPORT_BUILD } from '../constants';\nimport { generateTestRunReportScriptTag } from '../dump/html-utils';\nimport {\n type ReportSession,\n currentReportSession,\n} from '../dump/report-session';\nimport {\n type IReportGenerator,\n ReportGenerator,\n assertReportGenerationOptions,\n nullReportGenerator,\n} from '../report-generator';\nimport type { TaskRunner } from '../task-runner';\nimport { WorkflowError } from '../test-runner/errors';\nimport type { WorkflowExecutionRecord } from '../test-runner/execution-record';\nimport { buildAgentTestRunReportDump } from '../test-runner/reporting/agent-report';\nimport { executionRecordsToReportInput } from '../test-runner/reporting/execution-record';\nimport {\n type AgentOpt,\n type ExecutionDump,\n ReportActionDump,\n type ReportMeta,\n} from '../types';\nimport { getVersion, reportHTMLContent } from '../utils';\nimport { getReportFileName } from './utils';\n\nconst warn = getDebug('agent', { console: true });\n\ntype ReportOptions = Pick<\n AgentOpt,\n | 'groupName'\n | 'groupDescription'\n | 'generateReport'\n | 'persistExecutionDump'\n | 'outputFormat'\n | 'autoPrintReportMsg'\n | 'reportAttributes'\n | 'reportFileName'\n | 'testId'\n>;\n\ninterface AgentReportContext {\n getOptions(): ReportOptions;\n getDeviceType(): ReportActionDump['deviceType'];\n isDestroyed(): boolean;\n isExternallyBusy(): boolean;\n}\n\ninterface AgentReportState {\n dump: ReportActionDump;\n file?: string | null;\n fileName?: string;\n generator: IReportGenerator;\n session?: ReportSession;\n finalization?: Promise<string | undefined>;\n lastExecution?: ExecutionDump;\n executionIndexByRunner: WeakMap<TaskRunner, number>;\n yamlScopeId: string;\n yamlRecords: WorkflowExecutionRecord[];\n activeOperations: Set<Promise<unknown>>;\n}\n\n/** Owns report state and persistence; execution and device ownership stay with Agent. */\nexport class AgentReportManager {\n private reportState: AgentReportState;\n private reportReset?: Promise<ReportActionDump>;\n private readonly reportByRunner = new WeakMap<TaskRunner, AgentReportState>();\n private dumpUpdateListeners: Array<\n (dump: string, executionDump?: ExecutionDump) => void\n > = [];\n\n constructor(private readonly context: AgentReportContext) {\n const opts = this.opts;\n const fileName =\n opts.reportFileName ??\n getReportFileName(opts.testId || context.getDeviceType() || 'web');\n this.reportState = this.createReportState(\n fileName,\n opts.reportAttributes?.['data-group-id'] === fileName,\n );\n }\n\n private get opts(): ReportOptions {\n return this.context.getOptions();\n }\n\n get dump(): ReportActionDump {\n return this.reportState.dump;\n }\n set dump(value: ReportActionDump) {\n this.reportState.dump = value;\n }\n\n get reportFile(): string | null | undefined {\n return this.reportState.file;\n }\n set reportFile(value: string | null | undefined) {\n this.reportState.file = value;\n }\n\n get reportFileName(): string | undefined {\n return this.reportState.fileName;\n }\n set reportFileName(value: string | undefined) {\n this.reportState.fileName = value;\n }\n\n /** @internal Runner snapshots retain immutable data and shared image files. */\n async _prepareForTestRunner(): Promise<void> {\n const report = this.reportState;\n const session = currentReportSession();\n if (session && session !== report.session) {\n if (report.session)\n throw new Error(\n 'An Agent cannot be shared by different Test report sessions. Await resetDump() between runs.',\n );\n this.assertReportIdle();\n await report.generator.finalize();\n const recorder = session.createRecorder(() => this.isReportBusy(report));\n // The previous standalone report owns its history. The Test stream starts\n // at acquisition, so previous script operations do not enter this run.\n this.clearDumpInMemory(report);\n report.generator = recorder;\n report.session = session;\n report.file = undefined;\n }\n report.generator.enableSourceSnapshots?.();\n }\n async _createReportSource(scopeId: string, executionIds?: readonly string[]) {\n return this.reportState.generator.createSourceSnapshot?.(\n scopeId,\n executionIds,\n );\n }\n\n /** @internal The Agent owns one report stream across root YAML invocations. */\n async _writeYamlExecutionReport(\n record: WorkflowExecutionRecord,\n ): Promise<string | undefined> {\n const report = this.reportState;\n const existingIndex = report.yamlRecords.findIndex(\n (entry) => entry.runId === record.runId,\n );\n const recordIndex =\n existingIndex < 0 ? report.yamlRecords.length : existingIndex;\n report.yamlRecords[recordIndex] = record;\n try {\n const path = await report.generator.writeRunnerReport?.(\n this.buildYamlReportInput(),\n report.yamlScopeId,\n this.getReportMeta(),\n );\n report.file = path ?? report.file;\n return path;\n } catch (error) {\n report.yamlRecords[recordIndex] = Object.freeze({\n ...record,\n status: 'failed',\n reportError: error,\n });\n throw error;\n }\n }\n\n private buildYamlReportInput() {\n const scopedRecords = this.reportState.yamlRecords.map((entry) => ({\n ...entry,\n ...(entry.execution\n ? {\n execution: {\n document: {\n ...entry.execution.document,\n reportScopeId: this.reportState.yamlScopeId,\n },\n cases: entry.execution.cases.map((outcome) => ({\n ...outcome,\n ...(outcome.run\n ? {\n run: {\n ...outcome.run,\n reportScopeId: this.reportState.yamlScopeId,\n },\n }\n : {}),\n ...(outcome.attempts\n ? {\n attempts: outcome.attempts.map((attempt) => ({\n ...attempt,\n reportScopeId: this.reportState.yamlScopeId,\n })),\n }\n : {}),\n })),\n },\n }\n : {}),\n }));\n return executionRecordsToReportInput(scopedRecords, {\n runId: this.reportState.yamlScopeId,\n });\n }\n\n private createEmptyDump(): ReportActionDump {\n return new ReportActionDump({\n sdkVersion: getVersion(),\n groupName: this.opts.groupName!,\n groupDescription: this.opts.groupDescription,\n executions: [],\n modelBriefs: [],\n deviceType: this.context.getDeviceType(),\n });\n }\n\n private createReportState(\n fileName: string,\n reuseExistingReport = false,\n ): AgentReportState {\n assertReportGenerationOptions(this.opts);\n const session = currentReportSession();\n const state: AgentReportState = {\n dump: this.createEmptyDump(),\n fileName,\n generator: session\n ? nullReportGenerator\n : ReportGenerator.create(fileName, {\n generateReport: this.opts.generateReport,\n persistExecutionDump: this.opts.persistExecutionDump,\n outputFormat: this.opts.outputFormat,\n autoPrintReportMsg: this.opts.autoPrintReportMsg,\n reuseExistingReport,\n }),\n executionIndexByRunner: new WeakMap(),\n yamlScopeId: uuid(),\n yamlRecords: [],\n activeOperations: new Set(),\n };\n if (session) {\n state.generator = session.createRecorder(() => this.isReportBusy(state));\n state.session = session;\n }\n return state;\n }\n\n private isReportBusy(report: AgentReportState): boolean {\n return report.activeOperations.size > 0 || this.context.isExternallyBusy();\n }\n\n private clearDumpInMemory(report = this.reportState): void {\n report.dump = this.createEmptyDump();\n report.executionIndexByRunner = new WeakMap();\n report.lastExecution = undefined;\n report.yamlRecords.length = 0;\n }\n\n private assertReportIdle(): void {\n assert(\n !this.reportState.activeOperations.size &&\n !this.context.isExternallyBusy(),\n 'Cannot reset or finalize a report while the Agent is executing. Await the active operation first.',\n );\n }\n\n assertReportWritable(): AgentReportState {\n const report = this.reportState;\n assert(\n !this.context.isDestroyed(),\n 'Cannot execute using a destroyed Agent.',\n );\n assert(\n !this.reportReset,\n 'Report reset is in progress. Await resetDump() first.',\n );\n assert(\n !report.finalization,\n 'The report has been finalized. Call and await resetDump() before executing again.',\n );\n return report;\n }\n\n async withReportOperation<T>(operation: () => Promise<T>): Promise<T> {\n const report = this.assertReportWritable();\n const pending = Promise.resolve().then(operation);\n report.activeOperations.add(pending);\n try {\n return await pending;\n } finally {\n report.activeOperations.delete(pending);\n }\n }\n\n /**\n * Finalize the preceding report and reset execution records for a new report.\n * Historical artifacts are retained; this Agent and its device stay connected.\n * Await this method before executing again. Concurrent resets share one reset.\n */\n async resetDump(): Promise<ReportActionDump> {\n assert(\n !this.context.isDestroyed(),\n 'Cannot reset a report using a destroyed Agent.',\n );\n if (this.reportReset) return this.reportReset;\n this.assertReportIdle();\n this.reportReset = (async () => {\n try {\n await this.finalizeReport();\n } catch (error) {\n // Failure belongs to the preceding report, not to the next write queue.\n warn(\n `Failed to finalize previous report; resetting dump: ${String(error)}`,\n );\n }\n assert(\n !this.context.isDestroyed(),\n 'Cannot reset a report using a destroyed Agent.',\n );\n const fileName = getReportFileName(\n this.opts.testId || this.context.getDeviceType() || 'web',\n );\n this.reportState = this.createReportState(fileName);\n return this.dump;\n })();\n try {\n return await this.reportReset;\n } finally {\n this.reportReset = undefined;\n }\n }\n\n /**\n * Seal the current report and release its in-memory records without\n * disconnecting the device. Export in-memory data before calling this method.\n * Repeated calls return the same result and never rewrite published artifacts.\n */\n async finalizeReport(): Promise<string | undefined> {\n const report = this.reportState;\n if (!report.finalization) {\n this.assertReportIdle();\n report.finalization = (async () => {\n await report.generator.flush();\n const path = await report.generator.finalize();\n report.file = path;\n this.clearDumpInMemory(report);\n return path;\n })();\n }\n return report.finalization;\n }\n\n appendExecutionDump(execution: ExecutionDump, runner?: TaskRunner) {\n assert(\n !this.reportState.finalization,\n 'Cannot append to a finalized report. Await resetDump() first.',\n );\n const currentDump = this.dump;\n if (runner) {\n const existingIndex = this.reportState.executionIndexByRunner.get(runner);\n if (existingIndex !== undefined) {\n currentDump.executions[existingIndex] = execution;\n return;\n }\n currentDump.executions.push(execution);\n this.reportState.executionIndexByRunner.set(\n runner,\n currentDump.executions.length - 1,\n );\n return;\n }\n currentDump.executions.push(execution);\n }\n\n dumpDataString(opt?: { inlineScreenshots?: boolean }) {\n // update dump info\n this.dump.groupName = this.opts.groupName!;\n this.dump.groupDescription = this.opts.groupDescription;\n // In browser environment, use inline screenshots since file system is not available\n if (ifInBrowser || opt?.inlineScreenshots) {\n return this.dump.serializeWithInlineScreenshots();\n }\n return this.dump.serialize();\n }\n\n reportHTMLString(getDumpString: () => string) {\n // Short-circuit at the call site because JavaScript evaluates function\n // arguments first. This avoids serializing the dump (including inline\n // screenshots) when the Report Viewer build does not need report HTML.\n if (IS_REPORT_BUILD) {\n return '';\n }\n\n // dumpDataString() handles browser environment with inline screenshots\n const dumpString = getDumpString();\n if (!this.reportState.yamlRecords.length)\n return reportHTMLContent(dumpString);\n\n // Browser exports have no file writer, so the execution record must own\n // the hierarchy independently of whether file report generation is enabled.\n const reportId = this.reportState.yamlScopeId;\n const runnerDump = buildAgentTestRunReportDump(\n this.buildYamlReportInput(),\n this.dump,\n {\n reportId,\n scopeId: this.reportState.yamlScopeId,\n sourcePath: this.reportFile ?? '<inline-agent-report>',\n },\n );\n return `${reportHTMLContent({\n dumpString,\n attributes: { 'data-group-id': reportId, 'data-report-id': reportId },\n })}\\n${generateTestRunReportScriptTag(runnerDump)}`;\n }\n\n writeOutActionDumps(executionDump?: ExecutionDump) {\n const report = this.reportState;\n if (report.finalization) {\n if (executionDump) {\n throw new WorkflowError(\n 'Cannot append to a finalized report. Await resetDump() first.',\n {\n code: 'REPORT_FINALIZED',\n },\n );\n }\n return;\n }\n const exec = executionDump || report.lastExecution;\n if (exec) {\n report.lastExecution = exec;\n report.generator.onExecutionUpdate(\n exec,\n this.getReportMeta(),\n this.opts.reportAttributes,\n );\n }\n report.file = report.generator.getReportPath();\n }\n\n /** Persist current report data without disposing this Agent or its device. */\n async flushReport(): Promise<string | undefined> {\n if (this.reportReset) await this.reportReset;\n const report = this.reportState;\n if (report.finalization) return report.finalization;\n this.writeOutActionDumps();\n await report.generator.flush();\n return report.lastExecution ? (report.file ?? undefined) : undefined;\n }\n\n private getReportMeta(): ReportMeta {\n return {\n groupName: this.dump.groupName,\n groupDescription: this.dump.groupDescription,\n sdkVersion: this.dump.sdkVersion,\n modelBriefs: this.dump.modelBriefs,\n deviceType: this.dump.deviceType,\n };\n }\n\n get onDumpUpdate():\n | ((dump: string, executionDump?: ExecutionDump) => void)\n | undefined {\n return this.dumpUpdateListeners[0];\n }\n\n set onDumpUpdate(callback:\n | ((dump: string, executionDump?: ExecutionDump) => void)\n | undefined) {\n // Clear existing listeners\n this.dumpUpdateListeners = [];\n // Add callback to array if provided\n if (callback) {\n this.dumpUpdateListeners.push(callback);\n }\n }\n\n addDumpUpdateListener(\n listener: (dump: string, executionDump?: ExecutionDump) => void,\n ): () => void {\n this.dumpUpdateListeners.push(listener);\n\n // Return remove function\n return () => {\n this.removeDumpUpdateListener(listener);\n };\n }\n\n /**\n * Remove a dump update listener\n * @param listener The listener function to remove\n */\n removeDumpUpdateListener(\n listener: (dump: string, executionDump?: ExecutionDump) => void,\n ): void {\n const index = this.dumpUpdateListeners.indexOf(listener);\n if (index > -1) {\n this.dumpUpdateListeners.splice(index, 1);\n }\n }\n\n /**\n * Clear all dump update listeners\n */\n clearDumpUpdateListeners(): void {\n this.dumpUpdateListeners = [];\n }\n\n notifyDumpUpdateListeners(executionDump?: ExecutionDump) {\n if (this.dumpUpdateListeners.length === 0) return;\n const dumpString = this.dumpDataString();\n for (const listener of this.dumpUpdateListeners) {\n try {\n listener(dumpString, executionDump);\n } catch (error) {\n console.error('Error in onDumpUpdate listener', error);\n }\n }\n }\n\n bindRunner(runner: TaskRunner): void {\n this.reportByRunner.set(runner, this.reportState);\n }\n\n assertRunnerCurrent(runner: TaskRunner): void {\n const report = this.reportByRunner.get(runner);\n assert(\n report === this.reportState && !report.finalization,\n 'Cannot write a late execution update into a different or finalized report.',\n );\n }\n\n async flushPendingWrites(): Promise<void> {\n await this.reportState.generator.flush();\n }\n\n async waitForOperations(): Promise<void> {\n while (this.reportState.activeOperations.size) {\n await Promise.allSettled([...this.reportState.activeOperations]);\n }\n }\n\n async waitForReset(): Promise<void> {\n if (this.reportReset) await this.reportReset.catch(() => {});\n }\n}\n"],"names":["warn","getDebug","AgentReportManager","value","report","session","currentReportSession","Error","recorder","undefined","scopeId","executionIds","record","existingIndex","entry","recordIndex","path","error","Object","scopedRecords","outcome","attempt","executionRecordsToReportInput","ReportActionDump","getVersion","fileName","reuseExistingReport","assertReportGenerationOptions","state","nullReportGenerator","ReportGenerator","WeakMap","uuid","Set","assert","operation","pending","Promise","String","getReportFileName","execution","runner","currentDump","opt","ifInBrowser","getDumpString","IS_REPORT_BUILD","dumpString","reportHTMLContent","reportId","runnerDump","buildAgentTestRunReportDump","generateTestRunReportScriptTag","executionDump","WorkflowError","exec","callback","listener","index","console","context","opts"],"mappings":"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"}
@@ -6,7 +6,6 @@ import service from "../service/index.mjs";
6
6
  import { hasPendingResourceOperation, waitForResourceIdle } from "../test-runner/engine/resource-operations.mjs";
7
7
  import { ExecutionDump } from "../types.mjs";
8
8
  import { YamlExecutionOwnershipError, currentYamlSignal, enterYamlAction, enterYamlExecution, hasActiveYamlExecution, runInYamlExecutionContext } from "../yaml/execution-session.mjs";
9
- import { definePlannedWait, isPlannedWaitError, plannedWaitContext } from "./planned-wait.mjs";
10
9
  import { ScriptPlayer, buildDetailedLocateParam, buildDetailedLocateParamAndRestParams, parseYamlScript } from "../yaml/index.mjs";
11
10
  import { readFile } from "node:fs/promises";
12
11
  import { basename, resolve as external_node_path_resolve } from "node:path";
@@ -82,8 +81,8 @@ class Agent {
82
81
  set reportFileName(value) {
83
82
  this.reportManager.reportFileName = value;
84
83
  }
85
- _prepareForTestRunner() {
86
- this.reportManager._prepareForTestRunner();
84
+ async _prepareForTestRunner() {
85
+ await this.reportManager._prepareForTestRunner();
87
86
  }
88
87
  async _createReportSource(scopeId, executionIds) {
89
88
  return this.reportManager._createReportSource(scopeId, executionIds);
@@ -464,11 +463,7 @@ class Agent {
464
463
  const runAiAct = async ()=>{
465
464
  const planningModel = this.resolveModelRuntime('planning', 'planning');
466
465
  const locateModel = this.resolveModelRuntime('locate', 'locate');
467
- const userContext = this.resolveUserContext('aiAct', opt?.context);
468
- const aiActContext = this.opts.planningWaitFor ? [
469
- plannedWaitContext,
470
- userContext
471
- ].filter(Boolean).join('\n\n') : userContext;
466
+ const aiActContext = this.resolveUserContext('aiAct', opt?.context);
472
467
  const cachePrompt = buildPromptWithContext(taskPrompt, aiActContext);
473
468
  const effort = (()=>{
474
469
  const resolvedEffort = opt?.effort ?? (opt?.deepThink === true ? 'deepThink' : 'balance');
@@ -485,7 +480,7 @@ class Agent {
485
480
  warn(`The "deepLocate" option is not supported for aiAct with the current planning adapter (modelFamily: ${planningModel.config.modelFamily ?? 'unknown'}). It will be ignored.`);
486
481
  deepLocate = false;
487
482
  }
488
- const cacheable = opt?.checkScreenChanges ? false : opt?.cacheable;
483
+ const cacheable = opt?.cacheable;
489
484
  const replanningCycleLimit = this.resolveReplanningCycleLimit(planningModel);
490
485
  const planCacheEnabled = planningModel.adapter.planning.cacheEnabled;
491
486
  const matchedCache = planCacheEnabled && false !== cacheable ? this.taskCache?.matchPlanCache(cachePrompt) : void 0;
@@ -507,13 +502,13 @@ class Agent {
507
502
  });
508
503
  return;
509
504
  } catch (error) {
510
- if (error instanceof YamlExecutionOwnershipError || isActionReadinessError(error) || isPlannedWaitError(error)) throw error;
505
+ if (error instanceof YamlExecutionOwnershipError || isActionReadinessError(error)) throw error;
511
506
  abortSignal?.throwIfAborted();
512
507
  cachedYamlFailed = true;
513
508
  warn(`cached aiAct plan failed, will replan and disable the stale cache: ${error instanceof Error ? error.message : String(error)}`);
514
509
  }
515
510
  }
516
- const { output: actionOutput } = await this.taskExecutor.action(taskPrompt, planningModel, locateModel, aiActContext, cacheable, replanningCycleLimit, effort, void 0, deepLocate, abortSignal, internalReportDisplay, opt?.checkScreenChanges);
511
+ const { output: actionOutput } = await this.taskExecutor.action(taskPrompt, planningModel, locateModel, aiActContext, cacheable, replanningCycleLimit, effort, void 0, deepLocate, abortSignal, internalReportDisplay);
517
512
  if (this.taskCache && false !== cacheable) {
518
513
  const yamlFlow = cachedYamlFailed ? [] : actionOutput?.yamlFlow;
519
514
  if (!cachedYamlFailed && !yamlFlow?.length) return actionOutput?.output;
@@ -892,7 +887,6 @@ class Agent {
892
887
  cacheDir: cacheConfigObj.cacheDir
893
888
  });
894
889
  const baseActionSpace = this.interface.actionSpace();
895
- if (this.opts.planningWaitFor && baseActionSpace.some((action)=>'WaitFor' === action.name)) throw new Error('planningWaitFor reserves the WaitFor action name; remove the custom WaitFor action or disable planningWaitFor');
896
890
  const fileChooserActions = this.interface.registerFileChooserListener ? [
897
891
  defineActionRegisterFileChooserAccept(async (files)=>{
898
892
  if (!this.activeFileChooserAccepter) throw new Error('RegisterFileChooserAccept can only be used while aiAct is running');
@@ -903,15 +897,6 @@ class Agent {
903
897
  this.fullActionSpace = [
904
898
  ...baseActionSpace,
905
899
  ...fileChooserActions,
906
- ...this.opts.planningWaitFor ? [
907
- definePlannedWait(async (condition, abortSignal)=>{
908
- await this.aiWaitFor(condition, {
909
- timeoutMs: 30000,
910
- checkIntervalMs: 2000,
911
- abortSignal
912
- });
913
- })
914
- ] : [],
915
900
  defineActionSleep()
916
901
  ];
917
902
  this.taskExecutor = new TaskExecutor(this.interface, this.service, {
@@ -919,7 +904,6 @@ class Agent {
919
904
  taskCache: this.taskCache,
920
905
  onTaskStart: this.callbackOnTaskStartTip.bind(this),
921
906
  replanningCycleLimit: this.opts.replanningCycleLimit,
922
- planningWaitFor: this.opts.planningWaitFor,
923
907
  waitAfterAction: this.opts.waitAfterAction,
924
908
  actionReadiness: this.actionReadiness,
925
909
  useDeviceTime: this.opts.useDeviceTime,