@midscene/core 1.15.6 → 1.16.1

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 (94) hide show
  1. package/dist/es/agent/agent-options.mjs +36 -0
  2. package/dist/es/agent/agent-options.mjs.map +1 -0
  3. package/dist/es/agent/agent-report-manager.mjs +323 -0
  4. package/dist/es/agent/agent-report-manager.mjs.map +1 -0
  5. package/dist/es/agent/agent.mjs +112 -228
  6. package/dist/es/agent/agent.mjs.map +1 -1
  7. package/dist/es/agent/cache-config.mjs +21 -1
  8. package/dist/es/agent/cache-config.mjs.map +1 -1
  9. package/dist/es/agent/tasks.mjs +3 -1
  10. package/dist/es/agent/tasks.mjs.map +1 -1
  11. package/dist/es/agent/utils.mjs +1 -1
  12. package/dist/es/report-generator.mjs +73 -33
  13. package/dist/es/report-generator.mjs.map +1 -1
  14. package/dist/es/report-html-template.mjs +1 -1
  15. package/dist/es/test-runner/engine/document-runtime.mjs +30 -24
  16. package/dist/es/test-runner/engine/document-runtime.mjs.map +1 -1
  17. package/dist/es/test-runner/engine/project-runtime.mjs +17 -11
  18. package/dist/es/test-runner/engine/project-runtime.mjs.map +1 -1
  19. package/dist/es/test-runner/engine/resource-operations.mjs +33 -8
  20. package/dist/es/test-runner/engine/resource-operations.mjs.map +1 -1
  21. package/dist/es/test-runner/engine/run-collected-case.mjs +1 -0
  22. package/dist/es/test-runner/engine/run-collected-case.mjs.map +1 -1
  23. package/dist/es/test-runner/engine/run-workflow-document.mjs +3 -0
  24. package/dist/es/test-runner/engine/run-workflow-document.mjs.map +1 -1
  25. package/dist/es/test-runner/engine/setup-timeout.mjs +37 -0
  26. package/dist/es/test-runner/engine/setup-timeout.mjs.map +1 -0
  27. package/dist/es/utils.mjs +1 -1
  28. package/dist/es/yaml/execution-session.mjs +2 -1
  29. package/dist/es/yaml/execution-session.mjs.map +1 -1
  30. package/dist/es/yaml/legacy-yaml-report.mjs +1 -1
  31. package/dist/es/yaml/legacy-yaml-report.mjs.map +1 -1
  32. package/dist/es/yaml/player.mjs +17 -3
  33. package/dist/es/yaml/player.mjs.map +1 -1
  34. package/dist/lib/agent/agent-options.js +73 -0
  35. package/dist/lib/agent/agent-options.js.map +1 -0
  36. package/dist/lib/agent/agent-report-manager.js +357 -0
  37. package/dist/lib/agent/agent-report-manager.js.map +1 -0
  38. package/dist/lib/agent/agent.js +110 -226
  39. package/dist/lib/agent/agent.js.map +1 -1
  40. package/dist/lib/agent/cache-config.js +23 -0
  41. package/dist/lib/agent/cache-config.js.map +1 -1
  42. package/dist/lib/agent/tasks.js +3 -1
  43. package/dist/lib/agent/tasks.js.map +1 -1
  44. package/dist/lib/agent/utils.js +1 -1
  45. package/dist/lib/report-generator.js +73 -33
  46. package/dist/lib/report-generator.js.map +1 -1
  47. package/dist/lib/report-html-template.js +1 -1
  48. package/dist/lib/test-runner/engine/document-runtime.js +30 -24
  49. package/dist/lib/test-runner/engine/document-runtime.js.map +1 -1
  50. package/dist/lib/test-runner/engine/project-runtime.js +17 -11
  51. package/dist/lib/test-runner/engine/project-runtime.js.map +1 -1
  52. package/dist/lib/test-runner/engine/resource-operations.js +36 -8
  53. package/dist/lib/test-runner/engine/resource-operations.js.map +1 -1
  54. package/dist/lib/test-runner/engine/run-collected-case.js +1 -0
  55. package/dist/lib/test-runner/engine/run-collected-case.js.map +1 -1
  56. package/dist/lib/test-runner/engine/run-workflow-document.js +3 -0
  57. package/dist/lib/test-runner/engine/run-workflow-document.js.map +1 -1
  58. package/dist/lib/test-runner/engine/setup-timeout.js +71 -0
  59. package/dist/lib/test-runner/engine/setup-timeout.js.map +1 -0
  60. package/dist/lib/utils.js +1 -1
  61. package/dist/lib/yaml/execution-session.js +4 -0
  62. package/dist/lib/yaml/execution-session.js.map +1 -1
  63. package/dist/lib/yaml/legacy-yaml-report.js +1 -1
  64. package/dist/lib/yaml/legacy-yaml-report.js.map +1 -1
  65. package/dist/lib/yaml/player.js +16 -2
  66. package/dist/lib/yaml/player.js.map +1 -1
  67. package/dist/types/agent/agent-options.d.ts +4 -0
  68. package/dist/types/agent/agent-options.d.ts.map +1 -0
  69. package/dist/types/agent/agent-report-manager.d.ts +92 -0
  70. package/dist/types/agent/agent-report-manager.d.ts.map +1 -0
  71. package/dist/types/agent/agent.d.ts +31 -24
  72. package/dist/types/agent/agent.d.ts.map +1 -1
  73. package/dist/types/agent/cache-config.d.ts +10 -0
  74. package/dist/types/agent/cache-config.d.ts.map +1 -1
  75. package/dist/types/agent/tasks.d.ts +1 -0
  76. package/dist/types/agent/tasks.d.ts.map +1 -1
  77. package/dist/types/report-generator.d.ts +5 -1
  78. package/dist/types/report-generator.d.ts.map +1 -1
  79. package/dist/types/test-runner/engine/document-runtime.d.ts.map +1 -1
  80. package/dist/types/test-runner/engine/project-runtime.d.ts.map +1 -1
  81. package/dist/types/test-runner/engine/resource-operations.d.ts +5 -0
  82. package/dist/types/test-runner/engine/resource-operations.d.ts.map +1 -1
  83. package/dist/types/test-runner/engine/run-collected-case.d.ts.map +1 -1
  84. package/dist/types/test-runner/engine/run-workflow-document.d.ts.map +1 -1
  85. package/dist/types/test-runner/engine/setup-timeout.d.ts +3 -0
  86. package/dist/types/test-runner/engine/setup-timeout.d.ts.map +1 -0
  87. package/dist/types/test-runner/engine/types.d.ts +7 -0
  88. package/dist/types/test-runner/engine/types.d.ts.map +1 -1
  89. package/dist/types/test-runner/project.d.ts +22 -0
  90. package/dist/types/test-runner/project.d.ts.map +1 -1
  91. package/dist/types/yaml/execution-session.d.ts +2 -0
  92. package/dist/types/yaml/execution-session.d.ts.map +1 -1
  93. package/dist/types/yaml/player.d.ts.map +1 -1
  94. package/package.json +2 -2
@@ -1 +1 @@
1
- {"version":3,"file":"test-runner/engine/run-collected-case.mjs","sources":["../../../../src/test-runner/engine/run-collected-case.ts"],"sourcesContent":["import { getDebug } from '@midscene/shared/logger';\nimport { uuid as randomUUID } from '@midscene/shared/utils';\nimport { NodeScopeTeardownError, WorkflowLifecycleError } from '../errors';\nimport type { CollectedCase, NormalizedStep } from '../parser/types';\nimport { executeStep } from './execute-step';\nimport {\n WorkflowExecutionFailure,\n asExecutionError,\n} from './execution-failure';\nimport {\n ResourceCleanupDeferredError,\n cleanupScopeResources,\n createResourceScope,\n getPendingScopeOperations,\n getResourceCleanupSnapshot,\n recoverCancelledScopeResources,\n setResourceOperationIdentity,\n} from './resource-operations';\nimport { phaseResult } from './result-metadata';\nimport { reportPathsFromTeardown } from './scope-teardown';\nimport type {\n CaseNodePhase,\n CaseRunResult,\n NodeCaseContext,\n NodeScopeTeardown,\n RunCollectedCaseOptions,\n StepRunResult,\n} from './types';\n\nexport async function runCollectedCase<TContext = undefined>(\n collectedCase: CollectedCase,\n options: RunCollectedCaseOptions<TContext>,\n): Promise<CaseRunResult> {\n const phases: Record<CaseNodePhase, readonly NormalizedStep[]> = {\n beforeEach: options.beforeEach ?? [],\n steps: collectedCase.definition.steps,\n afterEach: options.afterEach ?? [],\n };\n const nodes = {\n beforeEach: phases.beforeEach.map((step) => options.resolveNode(step.node)),\n steps: phases.steps.map((step) => options.resolveNode(step.node)),\n afterEach: phases.afterEach.map((step) => options.resolveNode(step.node)),\n };\n const resourceScope = createResourceScope(options.signal);\n const scopeSignal = resourceScope.signal;\n const runId = options.createRunId?.() ?? randomUUID();\n const startedAt = new Date();\n setResourceOperationIdentity(scopeSignal, { scopeId: runId });\n const beforeEach: StepRunResult[] = [];\n const steps: StepRunResult[] = [];\n const afterEach: StepRunResult[] = [];\n const capturedSources = new Map<\n string,\n import('./types').WorkflowReportSource\n >();\n const teardownStack: Array<{\n registrationIndex: number;\n node: string;\n teardown: NodeScopeTeardown;\n }> = [];\n let acceptingTeardowns = true;\n\n const onTeardown = (node: string, teardown: NodeScopeTeardown): void => {\n if (!acceptingTeardowns) {\n throw new WorkflowLifecycleError(\n 'Node teardown can only be registered while a case attempt is running.',\n { runId, node },\n );\n }\n if (typeof teardown !== 'function') {\n throw new WorkflowLifecycleError(\n 'Node onTeardown() requires a teardown function.',\n { runId, node },\n );\n }\n teardownStack.push({\n registrationIndex: teardownStack.length,\n node,\n teardown,\n });\n };\n\n const runPhase = async (\n phase: CaseNodePhase,\n results: StepRunResult[],\n signal = scopeSignal,\n ): Promise<void> => {\n for (const [stepIndex, step] of phases[phase].entries()) {\n // A Step timeout ends the Runner's wait, not the underlying operation.\n // Recovery belongs between Steps, outside the next Step's timeout budget.\n const waitForPreviousOperationMs =\n stepIndex > 0 ? await recoverCancelledScopeResources(signal) : 0;\n const caseContext: NodeCaseContext = {\n caseId: collectedCase.caseId,\n runId,\n projectName: options.projectName ?? collectedCase.projectId,\n attemptIndex: options.attemptIndex ?? 0,\n name: collectedCase.definition.name,\n sourcePath: collectedCase.sourcePath,\n caseIndex: collectedCase.caseIndex,\n phase,\n stepIndex,\n };\n const stepInfo = {\n scope: 'case' as const,\n node: step.node,\n stepCount: phases[phase].length,\n case: caseContext,\n };\n await options.onStepStart?.(stepInfo);\n const result = await executeStep(\n step,\n nodes[phase][stepIndex],\n { scope: 'case', case: caseContext },\n options.context as TContext,\n {\n signal,\n defaultTimeoutMs: options.defaultTimeoutMs,\n onTeardown,\n },\n );\n if (waitForPreviousOperationMs > 0)\n result.waitForPreviousOperationMs = waitForPreviousOperationMs;\n results.push(result);\n for (const source of result.report?.sources ?? [])\n capturedSources.set(\n `${source.sourcePath}\\u0000${source.dumpPath ?? ''}`,\n source,\n );\n await options.onStepResult?.(stepInfo, result);\n if (result.status !== 'success' && !result.continuedAfterError) break;\n }\n };\n\n const executionErrors: unknown[] = [];\n try {\n await runPhase('beforeEach', beforeEach);\n if (!beforeEach.some((step) => step.status !== 'success')) {\n await runPhase('steps', steps);\n }\n } catch (error) {\n executionErrors.push(error);\n }\n const teardownErrors: NodeScopeTeardownError[] = [];\n const reportPaths = new Set<string>();\n const reportSources: import('./types').WorkflowReportSource[] = [];\n const cleanupExecutionErrors: unknown[] = [];\n let deferredCleanup = false;\n const cleanup = async () => {\n const priorTeardownErrors = teardownErrors.length;\n acceptingTeardowns = false;\n for (const {\n registrationIndex,\n node,\n teardown,\n } of teardownStack.reverse()) {\n try {\n const released = await teardown();\n reportSources.push(...(released?.reportSources ?? []));\n for (const path of reportPathsFromTeardown(released)) {\n reportPaths.add(path);\n }\n } catch (error) {\n teardownErrors.push(\n new NodeScopeTeardownError(error, {\n scope: 'case',\n scopeId: runId,\n node,\n registrationIndex,\n }),\n );\n }\n }\n {\n const errors = [\n ...cleanupExecutionErrors,\n ...teardownErrors.slice(priorTeardownErrors),\n ];\n if (errors.length)\n throw new AggregateError(errors, 'Case cleanup failed');\n }\n };\n try {\n if (phases.afterEach.length || teardownStack.length)\n await cleanupScopeResources(scopeSignal, cleanup, {\n beforeCleanup: async (cleanupSignal) => {\n try {\n await runPhase('afterEach', afterEach, cleanupSignal);\n } catch (error) {\n executionErrors.push(error);\n cleanupExecutionErrors.push(error);\n }\n },\n onDeferredError: (error) =>\n getDebug('runner:cleanup', { console: true })(\n `Deferred Case cleanup failed: ${String(error)}`,\n ),\n });\n else acceptingTeardowns = false;\n } catch (error) {\n deferredCleanup = error instanceof ResourceCleanupDeferredError;\n if (!deferredCleanup) acceptingTeardowns = false;\n if (\n !deferredCleanup &&\n !teardownErrors.length &&\n !cleanupExecutionErrors.length\n )\n teardownErrors.push(\n new NodeScopeTeardownError(error, {\n scope: 'case',\n scopeId: runId,\n node: 'resource-drain',\n registrationIndex: -1,\n }),\n );\n }\n const endedAt = new Date();\n const cleanupSnapshot = getResourceCleanupSnapshot(scopeSignal);\n const pendingOperations = getPendingScopeOperations(scopeSignal);\n const phaseResults = {\n beforeEach: phaseResult(phases.beforeEach.length, beforeEach),\n steps: phaseResult(phases.steps.length, steps),\n afterEach: phaseResult(phases.afterEach.length, afterEach),\n };\n const result: CaseRunResult = {\n caseId: collectedCase.caseId,\n runId,\n projectName: options.projectName ?? collectedCase.projectId,\n attemptIndex: options.attemptIndex ?? 0,\n name: collectedCase.definition.name,\n sourcePath: collectedCase.sourcePath,\n caseIndex: collectedCase.caseIndex,\n status:\n executionErrors.length > 0 ||\n beforeEach.some((step) => step.status !== 'success') ||\n steps.some((step) => step.status !== 'success') ||\n afterEach.some((step) => step.status !== 'success') ||\n cleanupSnapshot.status === 'pending' ||\n cleanupSnapshot.status === 'failed' ||\n pendingOperations.length > 0 ||\n teardownErrors.length > 0\n ? 'failed'\n : 'success',\n beforeEach: [...beforeEach],\n steps: [...steps],\n afterEach: [...afterEach],\n executionStatus: Object.values(phaseResults).some(\n (phase) => phase.status === 'failed',\n )\n ? 'failed'\n : Object.values(phaseResults).some((phase) => phase.status === 'not-run')\n ? 'not-run'\n : 'success',\n phases: phaseResults,\n cleanup: cleanupSnapshot,\n ...(pendingOperations.length ? { pendingOperations } : {}),\n ...(executionErrors.length\n ? { executionErrors: executionErrors.map(asExecutionError) }\n : {}),\n ...(teardownErrors.length > 0\n ? { teardownErrors: [...teardownErrors] }\n : {}),\n ...(reportPaths.size > 0 ? { reportPaths: [...reportPaths] } : {}),\n ...(capturedSources.size || reportSources.length\n ? { reportSources: [...capturedSources.values(), ...reportSources] }\n : {}),\n ...(options.reportScopeId ? { reportScopeId: options.reportScopeId } : {}),\n startedAt: startedAt.toISOString(),\n endedAt: endedAt.toISOString(),\n durationMs: Math.max(0, endedAt.getTime() - startedAt.getTime()),\n };\n\n try {\n await options.onResult?.(result);\n } catch (error) {\n executionErrors.push(error);\n result.status = 'failed';\n result.executionErrors = executionErrors.map(asExecutionError);\n }\n resourceScope.dispose();\n if (executionErrors.length)\n throw new WorkflowExecutionFailure(result, executionErrors);\n return result;\n}\n"],"names":["runCollectedCase","collectedCase","options","phases","nodes","step","resourceScope","createResourceScope","scopeSignal","runId","randomUUID","startedAt","Date","setResourceOperationIdentity","beforeEach","steps","afterEach","capturedSources","Map","teardownStack","acceptingTeardowns","onTeardown","node","teardown","WorkflowLifecycleError","runPhase","phase","results","signal","stepIndex","waitForPreviousOperationMs","recoverCancelledScopeResources","caseContext","stepInfo","result","executeStep","source","executionErrors","error","teardownErrors","reportPaths","Set","reportSources","cleanupExecutionErrors","deferredCleanup","cleanup","priorTeardownErrors","registrationIndex","released","path","reportPathsFromTeardown","NodeScopeTeardownError","errors","AggregateError","cleanupScopeResources","cleanupSignal","getDebug","String","ResourceCleanupDeferredError","endedAt","cleanupSnapshot","getResourceCleanupSnapshot","pendingOperations","getPendingScopeOperations","phaseResults","phaseResult","Object","asExecutionError","Math","WorkflowExecutionFailure"],"mappings":"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"}
1
+ {"version":3,"file":"test-runner/engine/run-collected-case.mjs","sources":["../../../../src/test-runner/engine/run-collected-case.ts"],"sourcesContent":["import { getDebug } from '@midscene/shared/logger';\nimport { uuid as randomUUID } from '@midscene/shared/utils';\nimport { NodeScopeTeardownError, WorkflowLifecycleError } from '../errors';\nimport type { CollectedCase, NormalizedStep } from '../parser/types';\nimport { executeStep } from './execute-step';\nimport {\n WorkflowExecutionFailure,\n asExecutionError,\n} from './execution-failure';\nimport {\n ResourceCleanupDeferredError,\n cleanupScopeResources,\n createResourceScope,\n getPendingScopeOperations,\n getResourceCleanupSnapshot,\n recoverCancelledScopeResources,\n setResourceOperationIdentity,\n} from './resource-operations';\nimport { phaseResult } from './result-metadata';\nimport { reportPathsFromTeardown } from './scope-teardown';\nimport type {\n CaseNodePhase,\n CaseRunResult,\n NodeCaseContext,\n NodeScopeTeardown,\n RunCollectedCaseOptions,\n StepRunResult,\n} from './types';\n\nexport async function runCollectedCase<TContext = undefined>(\n collectedCase: CollectedCase,\n options: RunCollectedCaseOptions<TContext>,\n): Promise<CaseRunResult> {\n const phases: Record<CaseNodePhase, readonly NormalizedStep[]> = {\n beforeEach: options.beforeEach ?? [],\n steps: collectedCase.definition.steps,\n afterEach: options.afterEach ?? [],\n };\n const nodes = {\n beforeEach: phases.beforeEach.map((step) => options.resolveNode(step.node)),\n steps: phases.steps.map((step) => options.resolveNode(step.node)),\n afterEach: phases.afterEach.map((step) => options.resolveNode(step.node)),\n };\n const resourceScope = createResourceScope(options.signal);\n const scopeSignal = resourceScope.signal;\n const runId = options.createRunId?.() ?? randomUUID();\n const startedAt = new Date();\n setResourceOperationIdentity(scopeSignal, { scopeId: runId });\n const beforeEach: StepRunResult[] = [];\n const steps: StepRunResult[] = [];\n const afterEach: StepRunResult[] = [];\n const capturedSources = new Map<\n string,\n import('./types').WorkflowReportSource\n >();\n const teardownStack: Array<{\n registrationIndex: number;\n node: string;\n teardown: NodeScopeTeardown;\n }> = [];\n let acceptingTeardowns = true;\n\n const onTeardown = (node: string, teardown: NodeScopeTeardown): void => {\n if (!acceptingTeardowns) {\n throw new WorkflowLifecycleError(\n 'Node teardown can only be registered while a case attempt is running.',\n { runId, node },\n );\n }\n if (typeof teardown !== 'function') {\n throw new WorkflowLifecycleError(\n 'Node onTeardown() requires a teardown function.',\n { runId, node },\n );\n }\n teardownStack.push({\n registrationIndex: teardownStack.length,\n node,\n teardown,\n });\n };\n\n const runPhase = async (\n phase: CaseNodePhase,\n results: StepRunResult[],\n signal = scopeSignal,\n ): Promise<void> => {\n for (const [stepIndex, step] of phases[phase].entries()) {\n // A Step timeout ends the Runner's wait, not the underlying operation.\n // Recovery belongs between Steps, outside the next Step's timeout budget.\n const waitForPreviousOperationMs =\n stepIndex > 0 ? await recoverCancelledScopeResources(signal) : 0;\n const caseContext: NodeCaseContext = {\n caseId: collectedCase.caseId,\n runId,\n projectName: options.projectName ?? collectedCase.projectId,\n attemptIndex: options.attemptIndex ?? 0,\n name: collectedCase.definition.name,\n sourcePath: collectedCase.sourcePath,\n caseIndex: collectedCase.caseIndex,\n phase,\n stepIndex,\n };\n const stepInfo = {\n scope: 'case' as const,\n node: step.node,\n stepCount: phases[phase].length,\n case: caseContext,\n };\n await options.onStepStart?.(stepInfo);\n const result = await executeStep(\n step,\n nodes[phase][stepIndex],\n { scope: 'case', case: caseContext },\n options.context as TContext,\n {\n signal,\n defaultTimeoutMs: options.defaultTimeoutMs,\n onTeardown,\n },\n );\n if (waitForPreviousOperationMs > 0)\n result.waitForPreviousOperationMs = waitForPreviousOperationMs;\n results.push(result);\n for (const source of result.report?.sources ?? [])\n capturedSources.set(\n `${source.sourcePath}\\u0000${source.dumpPath ?? ''}`,\n source,\n );\n await options.onStepResult?.(stepInfo, result);\n if (result.status !== 'success' && !result.continuedAfterError) break;\n }\n };\n\n const executionErrors: unknown[] = [];\n try {\n await runPhase('beforeEach', beforeEach);\n if (!beforeEach.some((step) => step.status !== 'success')) {\n await runPhase('steps', steps);\n }\n } catch (error) {\n executionErrors.push(error);\n }\n const teardownErrors: NodeScopeTeardownError[] = [];\n const reportPaths = new Set<string>();\n const reportSources: import('./types').WorkflowReportSource[] = [];\n const cleanupExecutionErrors: unknown[] = [];\n let deferredCleanup = false;\n const cleanup = async () => {\n const priorTeardownErrors = teardownErrors.length;\n acceptingTeardowns = false;\n for (const {\n registrationIndex,\n node,\n teardown,\n } of teardownStack.reverse()) {\n try {\n const released = await teardown();\n reportSources.push(...(released?.reportSources ?? []));\n for (const path of reportPathsFromTeardown(released)) {\n reportPaths.add(path);\n }\n } catch (error) {\n teardownErrors.push(\n new NodeScopeTeardownError(error, {\n scope: 'case',\n scopeId: runId,\n node,\n registrationIndex,\n }),\n );\n }\n }\n {\n const errors = [\n ...cleanupExecutionErrors,\n ...teardownErrors.slice(priorTeardownErrors),\n ];\n if (errors.length)\n throw new AggregateError(errors, 'Case cleanup failed');\n }\n };\n try {\n if (phases.afterEach.length || teardownStack.length)\n await cleanupScopeResources(scopeSignal, cleanup, {\n totalTimeoutMs: options.teardownTimeoutMs?.(),\n beforeCleanup: async (cleanupSignal) => {\n try {\n await runPhase('afterEach', afterEach, cleanupSignal);\n } catch (error) {\n executionErrors.push(error);\n cleanupExecutionErrors.push(error);\n }\n },\n onDeferredError: (error) =>\n getDebug('runner:cleanup', { console: true })(\n `Deferred Case cleanup failed: ${String(error)}`,\n ),\n });\n else acceptingTeardowns = false;\n } catch (error) {\n deferredCleanup = error instanceof ResourceCleanupDeferredError;\n if (!deferredCleanup) acceptingTeardowns = false;\n if (\n !deferredCleanup &&\n !teardownErrors.length &&\n !cleanupExecutionErrors.length\n )\n teardownErrors.push(\n new NodeScopeTeardownError(error, {\n scope: 'case',\n scopeId: runId,\n node: 'resource-drain',\n registrationIndex: -1,\n }),\n );\n }\n const endedAt = new Date();\n const cleanupSnapshot = getResourceCleanupSnapshot(scopeSignal);\n const pendingOperations = getPendingScopeOperations(scopeSignal);\n const phaseResults = {\n beforeEach: phaseResult(phases.beforeEach.length, beforeEach),\n steps: phaseResult(phases.steps.length, steps),\n afterEach: phaseResult(phases.afterEach.length, afterEach),\n };\n const result: CaseRunResult = {\n caseId: collectedCase.caseId,\n runId,\n projectName: options.projectName ?? collectedCase.projectId,\n attemptIndex: options.attemptIndex ?? 0,\n name: collectedCase.definition.name,\n sourcePath: collectedCase.sourcePath,\n caseIndex: collectedCase.caseIndex,\n status:\n executionErrors.length > 0 ||\n beforeEach.some((step) => step.status !== 'success') ||\n steps.some((step) => step.status !== 'success') ||\n afterEach.some((step) => step.status !== 'success') ||\n cleanupSnapshot.status === 'pending' ||\n cleanupSnapshot.status === 'failed' ||\n pendingOperations.length > 0 ||\n teardownErrors.length > 0\n ? 'failed'\n : 'success',\n beforeEach: [...beforeEach],\n steps: [...steps],\n afterEach: [...afterEach],\n executionStatus: Object.values(phaseResults).some(\n (phase) => phase.status === 'failed',\n )\n ? 'failed'\n : Object.values(phaseResults).some((phase) => phase.status === 'not-run')\n ? 'not-run'\n : 'success',\n phases: phaseResults,\n cleanup: cleanupSnapshot,\n ...(pendingOperations.length ? { pendingOperations } : {}),\n ...(executionErrors.length\n ? { executionErrors: executionErrors.map(asExecutionError) }\n : {}),\n ...(teardownErrors.length > 0\n ? { teardownErrors: [...teardownErrors] }\n : {}),\n ...(reportPaths.size > 0 ? { reportPaths: [...reportPaths] } : {}),\n ...(capturedSources.size || reportSources.length\n ? { reportSources: [...capturedSources.values(), ...reportSources] }\n : {}),\n ...(options.reportScopeId ? { reportScopeId: options.reportScopeId } : {}),\n startedAt: startedAt.toISOString(),\n endedAt: endedAt.toISOString(),\n durationMs: Math.max(0, endedAt.getTime() - startedAt.getTime()),\n };\n\n try {\n await options.onResult?.(result);\n } catch (error) {\n executionErrors.push(error);\n result.status = 'failed';\n result.executionErrors = executionErrors.map(asExecutionError);\n }\n resourceScope.dispose();\n if (executionErrors.length)\n throw new WorkflowExecutionFailure(result, executionErrors);\n return result;\n}\n"],"names":["runCollectedCase","collectedCase","options","phases","nodes","step","resourceScope","createResourceScope","scopeSignal","runId","randomUUID","startedAt","Date","setResourceOperationIdentity","beforeEach","steps","afterEach","capturedSources","Map","teardownStack","acceptingTeardowns","onTeardown","node","teardown","WorkflowLifecycleError","runPhase","phase","results","signal","stepIndex","waitForPreviousOperationMs","recoverCancelledScopeResources","caseContext","stepInfo","result","executeStep","source","executionErrors","error","teardownErrors","reportPaths","Set","reportSources","cleanupExecutionErrors","deferredCleanup","cleanup","priorTeardownErrors","registrationIndex","released","path","reportPathsFromTeardown","NodeScopeTeardownError","errors","AggregateError","cleanupScopeResources","cleanupSignal","getDebug","String","ResourceCleanupDeferredError","endedAt","cleanupSnapshot","getResourceCleanupSnapshot","pendingOperations","getPendingScopeOperations","phaseResults","phaseResult","Object","asExecutionError","Math","WorkflowExecutionFailure"],"mappings":"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"}
@@ -32,6 +32,8 @@ async function runWorkflowDocument(document, options) {
32
32
  }
33
33
  }),
34
34
  documentSetup: options.documentSetup,
35
+ setupTimeoutMs: options.setupTimeoutMs,
36
+ teardownTimeoutMs: options.teardownTimeoutMs,
35
37
  documentAttemptIndex: options.documentAttemptIndex,
36
38
  resolveNode: options.resolveNode,
37
39
  project: options.project,
@@ -76,6 +78,7 @@ async function runWorkflowDocument(document, options) {
76
78
  attemptIndex,
77
79
  signal: runtime.signal,
78
80
  defaultTimeoutMs: options.defaultTimeoutMs,
81
+ teardownTimeoutMs: options.teardownTimeoutMs,
79
82
  onStepStart: options.onStepStart,
80
83
  onStepResult: options.onStepResult,
81
84
  onResult: async (result)=>{
@@ -1 +1 @@
1
- {"version":3,"file":"test-runner/engine/run-workflow-document.mjs","sources":["../../../../src/test-runner/engine/run-workflow-document.ts"],"sourcesContent":["import { isResourceRecoveryError } from '../errors';\nimport type { CollectedCase, CollectedWorkflowDocument } from '../parser/types';\nimport { buildTestRunReportPlan } from '../reporting/test-plan';\nimport { createDocumentRuntime } from './document-runtime';\nimport {\n WorkflowExecutionFailure,\n asExecutionError,\n} from './execution-failure';\nimport { decideRetry } from './result-metadata';\nimport { runCollectedCase } from './run-collected-case';\nimport type {\n CaseRunOutcome,\n CaseRunResult,\n RunWorkflowDocumentOptions,\n WorkflowDocumentExecutionResult,\n WorkflowDocumentRunResult,\n} from './types';\n\nconst asNotRun = (\n collectedCase: CollectedCase,\n projectName: string,\n reason: NonNullable<CaseRunOutcome['notRunReason']>,\n): CaseRunOutcome => ({\n caseId: collectedCase.caseId,\n projectName,\n name: collectedCase.definition.name,\n sourcePath: collectedCase.sourcePath,\n caseIndex: collectedCase.caseIndex,\n ...(collectedCase.definition.onFailure\n ? { onFailure: collectedCase.definition.onFailure }\n : {}),\n status: 'not-run',\n notRunReason: reason,\n});\n\nexport async function runWorkflowDocument<TContext = undefined>(\n document: CollectedWorkflowDocument,\n options: RunWorkflowDocumentOptions<TContext>,\n): Promise<WorkflowDocumentExecutionResult> {\n const signal = options.signal ?? new AbortController().signal;\n const createDocumentRunId = options.createDocumentRunId;\n const createCaseRunId = options.createCaseRunId;\n const projectName = options.project?.name ?? document.projectId;\n const retry = options.retry ?? options.project?.retry ?? 0;\n if (!Number.isInteger(retry) || retry < 0) {\n throw new TypeError(\n 'Workflow document retry must be a non-negative integer.',\n );\n }\n const runtime = createDocumentRuntime(document, {\n plan:\n options.plan ??\n buildTestRunReportPlan(document, {\n defaultTimeoutMs: options.defaultTimeoutMs,\n retry: { scope: 'case', count: retry },\n }),\n documentSetup: options.documentSetup,\n documentAttemptIndex: options.documentAttemptIndex,\n resolveNode: options.resolveNode,\n project: options.project,\n projectContext: options.projectContext,\n signal,\n defaultTimeoutMs: options.defaultTimeoutMs,\n onStepStart: options.onStepStart,\n onStepResult: options.onStepResult,\n onResult: async (result) => {\n await options.documentSetup?.onDocumentResult?.(result, runtime.context);\n await options.onDocumentResult?.(result);\n },\n createDocumentRunId: createDocumentRunId\n ? () => createDocumentRunId(document)\n : undefined,\n });\n const cases: CaseRunOutcome[] = [];\n let runtimeStarted = false;\n let documentResult: WorkflowDocumentRunResult | undefined;\n const executionErrors: unknown[] = [];\n let fatalError = false;\n let documentStopReason: CaseRunOutcome['notRunReason'];\n\n try {\n runtimeStarted = true;\n const startedDocument = await runtime.start();\n\n if (!runtime.canRunCases) {\n const reason = signal.aborted\n ? (options.stopReason?.() ?? 'interrupted')\n : 'document-start-failed';\n cases.push(\n ...document.cases.map((collectedCase) =>\n asNotRun(collectedCase, projectName, reason),\n ),\n );\n } else {\n for (const collectedCase of document.cases) {\n if (\n documentStopReason ||\n fatalError ||\n signal.aborted ||\n options.shouldStop?.()\n ) {\n const outcome = asNotRun(\n collectedCase,\n projectName,\n signal.aborted\n ? (options.stopReason?.() ?? 'interrupted')\n : fatalError\n ? 'fatal-error'\n : (documentStopReason ??\n options.stopReason?.() ??\n 'interrupted'),\n );\n cases.push(outcome);\n await options.onCaseOutcome?.(outcome);\n continue;\n }\n\n await options.onCaseStart?.(collectedCase);\n const attempts = [];\n for (let attemptIndex = 0; attemptIndex <= retry; attemptIndex += 1) {\n let attemptFatalError = false;\n let attemptFailure:\n | WorkflowExecutionFailure<CaseRunResult>\n | undefined;\n const run = await runCollectedCase(collectedCase, {\n resolveNode: options.resolveNode,\n beforeEach: document.lifecycle.beforeEach,\n afterEach: document.lifecycle.afterEach,\n context: runtime.context,\n projectName,\n attemptIndex,\n signal: runtime.signal,\n defaultTimeoutMs: options.defaultTimeoutMs,\n onStepStart: options.onStepStart,\n onStepResult: options.onStepResult,\n onResult: async (result) => {\n attemptFatalError = options.isFatalError?.(result) ?? false;\n result.retryDecision = decideRetry({\n scope: 'case',\n retryCount: retry,\n attemptIndex,\n status: result.status,\n cleanupPending: result.cleanup?.status === 'pending',\n operationPending: !!result.pendingOperations?.length,\n cleanupFailed:\n result.cleanup?.status === 'failed' ||\n !!result.teardownErrors?.length,\n infrastructureError: result.executionErrors?.some(\n (error) => !isResourceRecoveryError(error),\n ),\n fatalError: attemptFatalError,\n interrupted: signal.aborted,\n shouldStop: options.shouldStop?.(),\n });\n await options.onCaseResult?.(result);\n },\n reportScopeId: options.resolveCaseReportScopeId?.(\n collectedCase,\n attemptIndex,\n startedDocument.documentRunId,\n ),\n createRunId: createCaseRunId\n ? () => createCaseRunId(collectedCase, attemptIndex)\n : undefined,\n }).catch((error: unknown) => {\n if (!(error instanceof WorkflowExecutionFailure)) throw error;\n attemptFailure = error as WorkflowExecutionFailure<CaseRunResult>;\n return attemptFailure.result;\n });\n attempts.push(run);\n if (\n attemptFailure &&\n !attemptFailure.errors.every(isResourceRecoveryError)\n ) {\n run.retryDecision = decideRetry({\n scope: 'case',\n retryCount: retry,\n attemptIndex,\n status: run.status,\n infrastructureError: true,\n });\n cases.push({\n caseId: collectedCase.caseId,\n projectName,\n name: collectedCase.definition.name,\n sourcePath: collectedCase.sourcePath,\n caseIndex: collectedCase.caseIndex,\n ...(collectedCase.definition.onFailure\n ? { onFailure: collectedCase.definition.onFailure }\n : {}),\n status: 'failed',\n run,\n attempts,\n });\n throw attemptFailure;\n }\n fatalError = attemptFatalError;\n // Result callbacks can interrupt execution or trigger bail. Observe\n // that boundary again before admitting another attempt.\n run.retryDecision = decideRetry({\n scope: 'case',\n retryCount: retry,\n attemptIndex,\n status: run.status,\n cleanupPending: run.cleanup?.status === 'pending',\n cleanupFailed:\n run.cleanup?.status === 'failed' || !!run.teardownErrors?.length,\n operationPending: !!run.pendingOperations?.length,\n fatalError:\n fatalError ||\n !!run.executionErrors?.some(isResourceRecoveryError),\n interrupted: signal.aborted,\n shouldStop: options.shouldStop?.(),\n });\n if (run.retryDecision?.decision !== 'retry') break;\n }\n const run = attempts.at(-1)!;\n const outcome: CaseRunOutcome = {\n caseId: collectedCase.caseId,\n projectName,\n name: collectedCase.definition.name,\n sourcePath: collectedCase.sourcePath,\n caseIndex: collectedCase.caseIndex,\n ...(collectedCase.definition.onFailure\n ? { onFailure: collectedCase.definition.onFailure }\n : {}),\n status: run.status,\n run,\n attempts,\n };\n cases.push(outcome);\n const retryStopReason = run.retryDecision?.reason;\n documentStopReason =\n retryStopReason === 'cleanup-pending' ||\n retryStopReason === 'cleanup-failed' ||\n retryStopReason === 'operation-pending' ||\n retryStopReason === 'fatal-error'\n ? retryStopReason\n : outcome.status === 'failed' &&\n collectedCase.definition.onFailure === 'stop-document'\n ? 'bail'\n : undefined;\n await options.onCaseOutcome?.(outcome);\n }\n }\n } catch (error) {\n executionErrors.push(\n ...(error instanceof WorkflowExecutionFailure ? error.errors : [error]),\n );\n } finally {\n if (runtimeStarted) {\n try {\n documentResult = await runtime.finish();\n } catch (error) {\n if (error instanceof WorkflowExecutionFailure) {\n documentResult = error.result as WorkflowDocumentRunResult;\n for (const failure of error.errors)\n if (!executionErrors.includes(failure))\n executionErrors.push(failure);\n } else executionErrors.push(error);\n }\n }\n }\n\n if (!documentResult) {\n if (executionErrors.length)\n throw new AggregateError(\n executionErrors,\n 'Workflow execution did not produce a document result.',\n );\n throw new Error(\n `Workflow document \"${document.sourcePath}\" did not produce a result.`,\n );\n }\n if (executionErrors.length) {\n const completed = new Set(cases.map((outcome) => outcome.caseId));\n cases.push(\n ...document.cases\n .filter((item) => !completed.has(item.caseId))\n .map((item) =>\n asNotRun(\n item,\n projectName,\n executionErrors.every(isResourceRecoveryError)\n ? 'operation-pending'\n : 'interrupted',\n ),\n ),\n );\n documentResult.status = 'failed';\n documentResult.executionErrors = executionErrors\n .filter(\n (error) =>\n !documentResult.hostErrors?.some((host) => host.error === error),\n )\n .map(asExecutionError);\n throw new WorkflowExecutionFailure(\n { document: documentResult, cases },\n executionErrors,\n );\n }\n return { document: documentResult, cases };\n}\n"],"names":["asNotRun","collectedCase","projectName","reason","runWorkflowDocument","document","options","signal","AbortController","createDocumentRunId","createCaseRunId","retry","Number","TypeError","runtime","createDocumentRuntime","buildTestRunReportPlan","result","undefined","cases","runtimeStarted","documentResult","executionErrors","fatalError","documentStopReason","startedDocument","outcome","attempts","attemptIndex","attemptFatalError","attemptFailure","run","runCollectedCase","decideRetry","error","isResourceRecoveryError","WorkflowExecutionFailure","retryStopReason","failure","AggregateError","Error","completed","Set","item","host","asExecutionError"],"mappings":";;;;;;AAkBA,MAAMA,WAAW,CACfC,eACAC,aACAC,SACoB;QACpB,QAAQF,cAAc,MAAM;QAC5BC;QACA,MAAMD,cAAc,UAAU,CAAC,IAAI;QACnC,YAAYA,cAAc,UAAU;QACpC,WAAWA,cAAc,SAAS;QAClC,GAAIA,cAAc,UAAU,CAAC,SAAS,GAClC;YAAE,WAAWA,cAAc,UAAU,CAAC,SAAS;QAAC,IAChD,CAAC,CAAC;QACN,QAAQ;QACR,cAAcE;IAChB;AAEO,eAAeC,oBACpBC,QAAmC,EACnCC,OAA6C;IAE7C,MAAMC,SAASD,QAAQ,MAAM,IAAI,IAAIE,kBAAkB,MAAM;IAC7D,MAAMC,sBAAsBH,QAAQ,mBAAmB;IACvD,MAAMI,kBAAkBJ,QAAQ,eAAe;IAC/C,MAAMJ,cAAcI,QAAQ,OAAO,EAAE,QAAQD,SAAS,SAAS;IAC/D,MAAMM,QAAQL,QAAQ,KAAK,IAAIA,QAAQ,OAAO,EAAE,SAAS;IACzD,IAAI,CAACM,OAAO,SAAS,CAACD,UAAUA,QAAQ,GACtC,MAAM,IAAIE,UACR;IAGJ,MAAMC,UAAUC,sBAAsBV,UAAU;QAC9C,MACEC,QAAQ,IAAI,IACZU,uBAAuBX,UAAU;YAC/B,kBAAkBC,QAAQ,gBAAgB;YAC1C,OAAO;gBAAE,OAAO;gBAAQ,OAAOK;YAAM;QACvC;QACF,eAAeL,QAAQ,aAAa;QACpC,sBAAsBA,QAAQ,oBAAoB;QAClD,aAAaA,QAAQ,WAAW;QAChC,SAASA,QAAQ,OAAO;QACxB,gBAAgBA,QAAQ,cAAc;QACtCC;QACA,kBAAkBD,QAAQ,gBAAgB;QAC1C,aAAaA,QAAQ,WAAW;QAChC,cAAcA,QAAQ,YAAY;QAClC,UAAU,OAAOW;YACf,MAAMX,QAAQ,aAAa,EAAE,mBAAmBW,QAAQH,QAAQ,OAAO;YACvE,MAAMR,QAAQ,gBAAgB,GAAGW;QACnC;QACA,qBAAqBR,sBACjB,IAAMA,oBAAoBJ,YAC1Ba;IACN;IACA,MAAMC,QAA0B,EAAE;IAClC,IAAIC,iBAAiB;IACrB,IAAIC;IACJ,MAAMC,kBAA6B,EAAE;IACrC,IAAIC,aAAa;IACjB,IAAIC;IAEJ,IAAI;QACFJ,iBAAiB;QACjB,MAAMK,kBAAkB,MAAMX,QAAQ,KAAK;QAE3C,IAAKA,QAAQ,WAAW,EAUtB,KAAK,MAAMb,iBAAiBI,SAAS,KAAK,CAAE;YAC1C,IACEmB,sBACAD,cACAhB,OAAO,OAAO,IACdD,QAAQ,UAAU,MAClB;gBACA,MAAMoB,UAAU1B,SACdC,eACAC,aACAK,OAAO,OAAO,GACTD,QAAQ,UAAU,QAAQ,gBAC3BiB,aACE,gBACCC,sBACDlB,QAAQ,UAAU,QAClB;gBAERa,MAAM,IAAI,CAACO;gBACX,MAAMpB,QAAQ,aAAa,GAAGoB;gBAC9B;YACF;YAEA,MAAMpB,QAAQ,WAAW,GAAGL;YAC5B,MAAM0B,WAAW,EAAE;YACnB,IAAK,IAAIC,eAAe,GAAGA,gBAAgBjB,OAAOiB,gBAAgB,EAAG;gBACnE,IAAIC,oBAAoB;gBACxB,IAAIC;gBAGJ,MAAMC,MAAM,MAAMC,iBAAiB/B,eAAe;oBAChD,aAAaK,QAAQ,WAAW;oBAChC,YAAYD,SAAS,SAAS,CAAC,UAAU;oBACzC,WAAWA,SAAS,SAAS,CAAC,SAAS;oBACvC,SAASS,QAAQ,OAAO;oBACxBZ;oBACA0B;oBACA,QAAQd,QAAQ,MAAM;oBACtB,kBAAkBR,QAAQ,gBAAgB;oBAC1C,aAAaA,QAAQ,WAAW;oBAChC,cAAcA,QAAQ,YAAY;oBAClC,UAAU,OAAOW;wBACfY,oBAAoBvB,QAAQ,YAAY,GAAGW,WAAW;wBACtDA,OAAO,aAAa,GAAGgB,YAAY;4BACjC,OAAO;4BACP,YAAYtB;4BACZiB;4BACA,QAAQX,OAAO,MAAM;4BACrB,gBAAgBA,OAAO,OAAO,EAAE,WAAW;4BAC3C,kBAAkB,CAAC,CAACA,OAAO,iBAAiB,EAAE;4BAC9C,eACEA,OAAO,OAAO,EAAE,WAAW,YAC3B,CAAC,CAACA,OAAO,cAAc,EAAE;4BAC3B,qBAAqBA,OAAO,eAAe,EAAE,KAC3C,CAACiB,QAAU,CAACC,wBAAwBD;4BAEtC,YAAYL;4BACZ,aAAatB,OAAO,OAAO;4BAC3B,YAAYD,QAAQ,UAAU;wBAChC;wBACA,MAAMA,QAAQ,YAAY,GAAGW;oBAC/B;oBACA,eAAeX,QAAQ,wBAAwB,GAC7CL,eACA2B,cACAH,gBAAgB,aAAa;oBAE/B,aAAaf,kBACT,IAAMA,gBAAgBT,eAAe2B,gBACrCV;gBACN,GAAG,KAAK,CAAC,CAACgB;oBACR,IAAI,CAAEA,CAAAA,iBAAiBE,wBAAuB,GAAI,MAAMF;oBACxDJ,iBAAiBI;oBACjB,OAAOJ,eAAe,MAAM;gBAC9B;gBACAH,SAAS,IAAI,CAACI;gBACd,IACED,kBACA,CAACA,eAAe,MAAM,CAAC,KAAK,CAACK,0BAC7B;oBACAJ,IAAI,aAAa,GAAGE,YAAY;wBAC9B,OAAO;wBACP,YAAYtB;wBACZiB;wBACA,QAAQG,IAAI,MAAM;wBAClB,qBAAqB;oBACvB;oBACAZ,MAAM,IAAI,CAAC;wBACT,QAAQlB,cAAc,MAAM;wBAC5BC;wBACA,MAAMD,cAAc,UAAU,CAAC,IAAI;wBACnC,YAAYA,cAAc,UAAU;wBACpC,WAAWA,cAAc,SAAS;wBAClC,GAAIA,cAAc,UAAU,CAAC,SAAS,GAClC;4BAAE,WAAWA,cAAc,UAAU,CAAC,SAAS;wBAAC,IAChD,CAAC,CAAC;wBACN,QAAQ;wBACR8B;wBACAJ;oBACF;oBACA,MAAMG;gBACR;gBACAP,aAAaM;gBAGbE,IAAI,aAAa,GAAGE,YAAY;oBAC9B,OAAO;oBACP,YAAYtB;oBACZiB;oBACA,QAAQG,IAAI,MAAM;oBAClB,gBAAgBA,IAAI,OAAO,EAAE,WAAW;oBACxC,eACEA,IAAI,OAAO,EAAE,WAAW,YAAY,CAAC,CAACA,IAAI,cAAc,EAAE;oBAC5D,kBAAkB,CAAC,CAACA,IAAI,iBAAiB,EAAE;oBAC3C,YACER,cACA,CAAC,CAACQ,IAAI,eAAe,EAAE,KAAKI;oBAC9B,aAAa5B,OAAO,OAAO;oBAC3B,YAAYD,QAAQ,UAAU;gBAChC;gBACA,IAAIyB,IAAI,aAAa,EAAE,aAAa,SAAS;YAC/C;YACA,MAAMA,MAAMJ,SAAS,EAAE,CAAC;YACxB,MAAMD,UAA0B;gBAC9B,QAAQzB,cAAc,MAAM;gBAC5BC;gBACA,MAAMD,cAAc,UAAU,CAAC,IAAI;gBACnC,YAAYA,cAAc,UAAU;gBACpC,WAAWA,cAAc,SAAS;gBAClC,GAAIA,cAAc,UAAU,CAAC,SAAS,GAClC;oBAAE,WAAWA,cAAc,UAAU,CAAC,SAAS;gBAAC,IAChD,CAAC,CAAC;gBACN,QAAQ8B,IAAI,MAAM;gBAClBA;gBACAJ;YACF;YACAR,MAAM,IAAI,CAACO;YACX,MAAMW,kBAAkBN,IAAI,aAAa,EAAE;YAC3CP,qBACEa,AAAoB,sBAApBA,mBACAA,AAAoB,qBAApBA,mBACAA,AAAoB,wBAApBA,mBACAA,AAAoB,kBAApBA,kBACIA,kBACAX,AAAmB,aAAnBA,QAAQ,MAAM,IACZzB,AAAuC,oBAAvCA,cAAc,UAAU,CAAC,SAAS,GAClC,SACAiB;YACR,MAAMZ,QAAQ,aAAa,GAAGoB;QAChC;aA/JwB;YACxB,MAAMvB,SAASI,OAAO,OAAO,GACxBD,QAAQ,UAAU,QAAQ,gBAC3B;YACJa,MAAM,IAAI,IACLd,SAAS,KAAK,CAAC,GAAG,CAAC,CAACJ,gBACrBD,SAASC,eAAeC,aAAaC;QAG3C;IAwJF,EAAE,OAAO+B,OAAO;QACdZ,gBAAgB,IAAI,IACdY,iBAAiBE,2BAA2BF,MAAM,MAAM,GAAG;YAACA;SAAM;IAE1E,SAAU;QACR,IAAId,gBACF,IAAI;YACFC,iBAAiB,MAAMP,QAAQ,MAAM;QACvC,EAAE,OAAOoB,OAAO;YACd,IAAIA,iBAAiBE,0BAA0B;gBAC7Cf,iBAAiBa,MAAM,MAAM;gBAC7B,KAAK,MAAMI,WAAWJ,MAAM,MAAM,CAChC,IAAI,CAACZ,gBAAgB,QAAQ,CAACgB,UAC5BhB,gBAAgB,IAAI,CAACgB;YAC3B,OAAOhB,gBAAgB,IAAI,CAACY;QAC9B;IAEJ;IAEA,IAAI,CAACb,gBAAgB;QACnB,IAAIC,gBAAgB,MAAM,EACxB,MAAM,IAAIiB,eACRjB,iBACA;QAEJ,MAAM,IAAIkB,MACR,CAAC,mBAAmB,EAAEnC,SAAS,UAAU,CAAC,2BAA2B,CAAC;IAE1E;IACA,IAAIiB,gBAAgB,MAAM,EAAE;QAC1B,MAAMmB,YAAY,IAAIC,IAAIvB,MAAM,GAAG,CAAC,CAACO,UAAYA,QAAQ,MAAM;QAC/DP,MAAM,IAAI,IACLd,SAAS,KAAK,CACd,MAAM,CAAC,CAACsC,OAAS,CAACF,UAAU,GAAG,CAACE,KAAK,MAAM,GAC3C,GAAG,CAAC,CAACA,OACJ3C,SACE2C,MACAzC,aACAoB,gBAAgB,KAAK,CAACa,2BAClB,sBACA;QAIZd,eAAe,MAAM,GAAG;QACxBA,eAAe,eAAe,GAAGC,gBAC9B,MAAM,CACL,CAACY,QACC,CAACb,eAAe,UAAU,EAAE,KAAK,CAACuB,OAASA,KAAK,KAAK,KAAKV,QAE7D,GAAG,CAACW;QACP,MAAM,IAAIT,yBACR;YAAE,UAAUf;YAAgBF;QAAM,GAClCG;IAEJ;IACA,OAAO;QAAE,UAAUD;QAAgBF;IAAM;AAC3C"}
1
+ {"version":3,"file":"test-runner/engine/run-workflow-document.mjs","sources":["../../../../src/test-runner/engine/run-workflow-document.ts"],"sourcesContent":["import { isResourceRecoveryError } from '../errors';\nimport type { CollectedCase, CollectedWorkflowDocument } from '../parser/types';\nimport { buildTestRunReportPlan } from '../reporting/test-plan';\nimport { createDocumentRuntime } from './document-runtime';\nimport {\n WorkflowExecutionFailure,\n asExecutionError,\n} from './execution-failure';\nimport { decideRetry } from './result-metadata';\nimport { runCollectedCase } from './run-collected-case';\nimport type {\n CaseRunOutcome,\n CaseRunResult,\n RunWorkflowDocumentOptions,\n WorkflowDocumentExecutionResult,\n WorkflowDocumentRunResult,\n} from './types';\n\nconst asNotRun = (\n collectedCase: CollectedCase,\n projectName: string,\n reason: NonNullable<CaseRunOutcome['notRunReason']>,\n): CaseRunOutcome => ({\n caseId: collectedCase.caseId,\n projectName,\n name: collectedCase.definition.name,\n sourcePath: collectedCase.sourcePath,\n caseIndex: collectedCase.caseIndex,\n ...(collectedCase.definition.onFailure\n ? { onFailure: collectedCase.definition.onFailure }\n : {}),\n status: 'not-run',\n notRunReason: reason,\n});\n\nexport async function runWorkflowDocument<TContext = undefined>(\n document: CollectedWorkflowDocument,\n options: RunWorkflowDocumentOptions<TContext>,\n): Promise<WorkflowDocumentExecutionResult> {\n const signal = options.signal ?? new AbortController().signal;\n const createDocumentRunId = options.createDocumentRunId;\n const createCaseRunId = options.createCaseRunId;\n const projectName = options.project?.name ?? document.projectId;\n const retry = options.retry ?? options.project?.retry ?? 0;\n if (!Number.isInteger(retry) || retry < 0) {\n throw new TypeError(\n 'Workflow document retry must be a non-negative integer.',\n );\n }\n const runtime = createDocumentRuntime(document, {\n plan:\n options.plan ??\n buildTestRunReportPlan(document, {\n defaultTimeoutMs: options.defaultTimeoutMs,\n retry: { scope: 'case', count: retry },\n }),\n documentSetup: options.documentSetup,\n setupTimeoutMs: options.setupTimeoutMs,\n teardownTimeoutMs: options.teardownTimeoutMs,\n documentAttemptIndex: options.documentAttemptIndex,\n resolveNode: options.resolveNode,\n project: options.project,\n projectContext: options.projectContext,\n signal,\n defaultTimeoutMs: options.defaultTimeoutMs,\n onStepStart: options.onStepStart,\n onStepResult: options.onStepResult,\n onResult: async (result) => {\n await options.documentSetup?.onDocumentResult?.(result, runtime.context);\n await options.onDocumentResult?.(result);\n },\n createDocumentRunId: createDocumentRunId\n ? () => createDocumentRunId(document)\n : undefined,\n });\n const cases: CaseRunOutcome[] = [];\n let runtimeStarted = false;\n let documentResult: WorkflowDocumentRunResult | undefined;\n const executionErrors: unknown[] = [];\n let fatalError = false;\n let documentStopReason: CaseRunOutcome['notRunReason'];\n\n try {\n runtimeStarted = true;\n const startedDocument = await runtime.start();\n\n if (!runtime.canRunCases) {\n const reason = signal.aborted\n ? (options.stopReason?.() ?? 'interrupted')\n : 'document-start-failed';\n cases.push(\n ...document.cases.map((collectedCase) =>\n asNotRun(collectedCase, projectName, reason),\n ),\n );\n } else {\n for (const collectedCase of document.cases) {\n if (\n documentStopReason ||\n fatalError ||\n signal.aborted ||\n options.shouldStop?.()\n ) {\n const outcome = asNotRun(\n collectedCase,\n projectName,\n signal.aborted\n ? (options.stopReason?.() ?? 'interrupted')\n : fatalError\n ? 'fatal-error'\n : (documentStopReason ??\n options.stopReason?.() ??\n 'interrupted'),\n );\n cases.push(outcome);\n await options.onCaseOutcome?.(outcome);\n continue;\n }\n\n await options.onCaseStart?.(collectedCase);\n const attempts = [];\n for (let attemptIndex = 0; attemptIndex <= retry; attemptIndex += 1) {\n let attemptFatalError = false;\n let attemptFailure:\n | WorkflowExecutionFailure<CaseRunResult>\n | undefined;\n const run = await runCollectedCase(collectedCase, {\n resolveNode: options.resolveNode,\n beforeEach: document.lifecycle.beforeEach,\n afterEach: document.lifecycle.afterEach,\n context: runtime.context,\n projectName,\n attemptIndex,\n signal: runtime.signal,\n defaultTimeoutMs: options.defaultTimeoutMs,\n teardownTimeoutMs: options.teardownTimeoutMs,\n onStepStart: options.onStepStart,\n onStepResult: options.onStepResult,\n onResult: async (result) => {\n attemptFatalError = options.isFatalError?.(result) ?? false;\n result.retryDecision = decideRetry({\n scope: 'case',\n retryCount: retry,\n attemptIndex,\n status: result.status,\n cleanupPending: result.cleanup?.status === 'pending',\n operationPending: !!result.pendingOperations?.length,\n cleanupFailed:\n result.cleanup?.status === 'failed' ||\n !!result.teardownErrors?.length,\n infrastructureError: result.executionErrors?.some(\n (error) => !isResourceRecoveryError(error),\n ),\n fatalError: attemptFatalError,\n interrupted: signal.aborted,\n shouldStop: options.shouldStop?.(),\n });\n await options.onCaseResult?.(result);\n },\n reportScopeId: options.resolveCaseReportScopeId?.(\n collectedCase,\n attemptIndex,\n startedDocument.documentRunId,\n ),\n createRunId: createCaseRunId\n ? () => createCaseRunId(collectedCase, attemptIndex)\n : undefined,\n }).catch((error: unknown) => {\n if (!(error instanceof WorkflowExecutionFailure)) throw error;\n attemptFailure = error as WorkflowExecutionFailure<CaseRunResult>;\n return attemptFailure.result;\n });\n attempts.push(run);\n if (\n attemptFailure &&\n !attemptFailure.errors.every(isResourceRecoveryError)\n ) {\n run.retryDecision = decideRetry({\n scope: 'case',\n retryCount: retry,\n attemptIndex,\n status: run.status,\n infrastructureError: true,\n });\n cases.push({\n caseId: collectedCase.caseId,\n projectName,\n name: collectedCase.definition.name,\n sourcePath: collectedCase.sourcePath,\n caseIndex: collectedCase.caseIndex,\n ...(collectedCase.definition.onFailure\n ? { onFailure: collectedCase.definition.onFailure }\n : {}),\n status: 'failed',\n run,\n attempts,\n });\n throw attemptFailure;\n }\n fatalError = attemptFatalError;\n // Result callbacks can interrupt execution or trigger bail. Observe\n // that boundary again before admitting another attempt.\n run.retryDecision = decideRetry({\n scope: 'case',\n retryCount: retry,\n attemptIndex,\n status: run.status,\n cleanupPending: run.cleanup?.status === 'pending',\n cleanupFailed:\n run.cleanup?.status === 'failed' || !!run.teardownErrors?.length,\n operationPending: !!run.pendingOperations?.length,\n fatalError:\n fatalError ||\n !!run.executionErrors?.some(isResourceRecoveryError),\n interrupted: signal.aborted,\n shouldStop: options.shouldStop?.(),\n });\n if (run.retryDecision?.decision !== 'retry') break;\n }\n const run = attempts.at(-1)!;\n const outcome: CaseRunOutcome = {\n caseId: collectedCase.caseId,\n projectName,\n name: collectedCase.definition.name,\n sourcePath: collectedCase.sourcePath,\n caseIndex: collectedCase.caseIndex,\n ...(collectedCase.definition.onFailure\n ? { onFailure: collectedCase.definition.onFailure }\n : {}),\n status: run.status,\n run,\n attempts,\n };\n cases.push(outcome);\n const retryStopReason = run.retryDecision?.reason;\n documentStopReason =\n retryStopReason === 'cleanup-pending' ||\n retryStopReason === 'cleanup-failed' ||\n retryStopReason === 'operation-pending' ||\n retryStopReason === 'fatal-error'\n ? retryStopReason\n : outcome.status === 'failed' &&\n collectedCase.definition.onFailure === 'stop-document'\n ? 'bail'\n : undefined;\n await options.onCaseOutcome?.(outcome);\n }\n }\n } catch (error) {\n executionErrors.push(\n ...(error instanceof WorkflowExecutionFailure ? error.errors : [error]),\n );\n } finally {\n if (runtimeStarted) {\n try {\n documentResult = await runtime.finish();\n } catch (error) {\n if (error instanceof WorkflowExecutionFailure) {\n documentResult = error.result as WorkflowDocumentRunResult;\n for (const failure of error.errors)\n if (!executionErrors.includes(failure))\n executionErrors.push(failure);\n } else executionErrors.push(error);\n }\n }\n }\n\n if (!documentResult) {\n if (executionErrors.length)\n throw new AggregateError(\n executionErrors,\n 'Workflow execution did not produce a document result.',\n );\n throw new Error(\n `Workflow document \"${document.sourcePath}\" did not produce a result.`,\n );\n }\n if (executionErrors.length) {\n const completed = new Set(cases.map((outcome) => outcome.caseId));\n cases.push(\n ...document.cases\n .filter((item) => !completed.has(item.caseId))\n .map((item) =>\n asNotRun(\n item,\n projectName,\n executionErrors.every(isResourceRecoveryError)\n ? 'operation-pending'\n : 'interrupted',\n ),\n ),\n );\n documentResult.status = 'failed';\n documentResult.executionErrors = executionErrors\n .filter(\n (error) =>\n !documentResult.hostErrors?.some((host) => host.error === error),\n )\n .map(asExecutionError);\n throw new WorkflowExecutionFailure(\n { document: documentResult, cases },\n executionErrors,\n );\n }\n return { document: documentResult, cases };\n}\n"],"names":["asNotRun","collectedCase","projectName","reason","runWorkflowDocument","document","options","signal","AbortController","createDocumentRunId","createCaseRunId","retry","Number","TypeError","runtime","createDocumentRuntime","buildTestRunReportPlan","result","undefined","cases","runtimeStarted","documentResult","executionErrors","fatalError","documentStopReason","startedDocument","outcome","attempts","attemptIndex","attemptFatalError","attemptFailure","run","runCollectedCase","decideRetry","error","isResourceRecoveryError","WorkflowExecutionFailure","retryStopReason","failure","AggregateError","Error","completed","Set","item","host","asExecutionError"],"mappings":"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"}
@@ -0,0 +1,37 @@
1
+ import { WorkflowError } from "../errors.mjs";
2
+ import { trackResourceOperation } from "./resource-operations.mjs";
3
+ async function runSetupWithTimeout(setup, signal, abort, timeoutMs) {
4
+ if (void 0 === timeoutMs) return setup();
5
+ signal.throwIfAborted();
6
+ const operation = Promise.resolve().then(setup);
7
+ trackResourceOperation({}, operation, signal);
8
+ let timer;
9
+ let onAbort;
10
+ const stopped = new Promise((_resolve, reject)=>{
11
+ onAbort = ()=>reject(signal.reason);
12
+ signal.addEventListener('abort', onAbort, {
13
+ once: true
14
+ });
15
+ timer = setTimeout(()=>{
16
+ const error = new WorkflowError(`Environment setup timed out after ${timeoutMs}ms.`, {
17
+ code: 'SETUP_TIMEOUT',
18
+ details: {
19
+ timeoutMs
20
+ }
21
+ });
22
+ abort(error);
23
+ }, timeoutMs);
24
+ });
25
+ try {
26
+ return await Promise.race([
27
+ operation,
28
+ stopped
29
+ ]);
30
+ } finally{
31
+ clearTimeout(timer);
32
+ signal.removeEventListener('abort', onAbort);
33
+ }
34
+ }
35
+ export { runSetupWithTimeout };
36
+
37
+ //# sourceMappingURL=setup-timeout.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"test-runner/engine/setup-timeout.mjs","sources":["../../../../src/test-runner/engine/setup-timeout.ts"],"sourcesContent":["import { WorkflowError } from '../errors';\nimport { trackResourceOperation } from './resource-operations';\n\n/** Keep tracking a timed-out acquisition until it actually settles. */\nexport async function runSetupWithTimeout<T>(\n setup: () => Promise<T>,\n signal: AbortSignal,\n abort: (reason: unknown) => void,\n timeoutMs?: number,\n): Promise<T> {\n if (timeoutMs === undefined) return setup();\n signal.throwIfAborted();\n const operation = Promise.resolve().then(setup);\n trackResourceOperation({}, operation, signal);\n let timer: ReturnType<typeof setTimeout> | undefined;\n let onAbort!: () => void;\n const stopped = new Promise<never>((_resolve, reject) => {\n onAbort = () => reject(signal.reason);\n signal.addEventListener('abort', onAbort, { once: true });\n timer = setTimeout(() => {\n const error = new WorkflowError(\n `Environment setup timed out after ${timeoutMs}ms.`,\n {\n code: 'SETUP_TIMEOUT',\n details: { timeoutMs },\n },\n );\n abort(error);\n }, timeoutMs);\n });\n try {\n return await Promise.race([operation, stopped]);\n } finally {\n clearTimeout(timer);\n signal.removeEventListener('abort', onAbort);\n }\n}\n"],"names":["runSetupWithTimeout","setup","signal","abort","timeoutMs","undefined","operation","Promise","trackResourceOperation","timer","onAbort","stopped","_resolve","reject","setTimeout","error","WorkflowError","clearTimeout"],"mappings":";;AAIO,eAAeA,oBACpBC,KAAuB,EACvBC,MAAmB,EACnBC,KAAgC,EAChCC,SAAkB;IAElB,IAAIA,AAAcC,WAAdD,WAAyB,OAAOH;IACpCC,OAAO,cAAc;IACrB,MAAMI,YAAYC,QAAQ,OAAO,GAAG,IAAI,CAACN;IACzCO,uBAAuB,CAAC,GAAGF,WAAWJ;IACtC,IAAIO;IACJ,IAAIC;IACJ,MAAMC,UAAU,IAAIJ,QAAe,CAACK,UAAUC;QAC5CH,UAAU,IAAMG,OAAOX,OAAO,MAAM;QACpCA,OAAO,gBAAgB,CAAC,SAASQ,SAAS;YAAE,MAAM;QAAK;QACvDD,QAAQK,WAAW;YACjB,MAAMC,QAAQ,IAAIC,cAChB,CAAC,kCAAkC,EAAEZ,UAAU,GAAG,CAAC,EACnD;gBACE,MAAM;gBACN,SAAS;oBAAEA;gBAAU;YACvB;YAEFD,MAAMY;QACR,GAAGX;IACL;IACA,IAAI;QACF,OAAO,MAAMG,QAAQ,IAAI,CAAC;YAACD;YAAWK;SAAQ;IAChD,SAAU;QACRM,aAAaR;QACbP,OAAO,mBAAmB,CAAC,SAASQ;IACtC;AACF"}
package/dist/es/utils.mjs CHANGED
@@ -184,7 +184,7 @@ function stringifyDumpData(data, indents) {
184
184
  return JSON.stringify(data, replacerForPageObject, indents);
185
185
  }
186
186
  function getVersion() {
187
- return "1.15.6";
187
+ return "1.16.1";
188
188
  }
189
189
  function debugLog(...message) {
190
190
  const debugMode = process.env[MIDSCENE_DEBUG_MODE];
@@ -8,6 +8,7 @@ host[stateKey] ??= {
8
8
  context: createExecutionContext()
9
9
  };
10
10
  const { sessions, signals, context } = host[stateKey];
11
+ const hasActiveYamlExecution = (agent)=>Boolean(sessions.get(agent)?.length);
11
12
  function runInYamlExecutionContext(callback) {
12
13
  const frame = {
13
14
  parent: context.getStore(),
@@ -85,6 +86,6 @@ function enterYamlExecution(agent, options = {}) {
85
86
  finish: session.finish
86
87
  };
87
88
  }
88
- export { YamlExecutionOwnershipError, currentYamlSignal, enterYamlAction, enterYamlExecution, runInYamlExecutionContext };
89
+ export { YamlExecutionOwnershipError, currentYamlSignal, enterYamlAction, enterYamlExecution, hasActiveYamlExecution, runInYamlExecutionContext };
89
90
 
90
91
  //# sourceMappingURL=execution-session.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"yaml/execution-session.mjs","sources":["../../../src/yaml/execution-session.ts"],"sourcesContent":["import {\n createExecutionContext,\n supportsAsyncContext,\n} from '#yaml-execution-context';\nimport { WorkflowError } from '../test-runner/errors';\nimport type { WorkflowExecutionRecord } from '../test-runner/execution-record';\n\ninterface YamlExecutionSession {\n agent: object;\n children: WorkflowExecutionRecord[];\n finished: boolean;\n finish(record?: WorkflowExecutionRecord): void;\n}\n\ninterface ExecutionFrame {\n parent?: ExecutionFrame;\n session?: YamlExecutionSession;\n signals: WeakMap<object, { signal: AbortSignal }[]>;\n}\n\nconst stateKey = Symbol.for('@midscene/core/yaml-execution-session/v2');\nconst host = globalThis as typeof globalThis & {\n [stateKey]?: {\n sessions: WeakMap<object, YamlExecutionSession[]>;\n signals: WeakMap<object, { signal: AbortSignal }[]>;\n context: ReturnType<typeof createExecutionContext<ExecutionFrame>>;\n };\n};\nhost[stateKey] ??= {\n sessions: new WeakMap(),\n signals: new WeakMap(),\n context: createExecutionContext<ExecutionFrame>(),\n};\nconst { sessions, signals, context } = host[stateKey];\n\n/** Every entry gets its own async frame, shared across CJS and ESM copies. */\nexport function runInYamlExecutionContext<T>(\n callback: () => Promise<T>,\n): Promise<T> {\n const frame: ExecutionFrame = {\n parent: context.getStore(),\n signals: new WeakMap(),\n };\n return context.run(frame, async () => {\n try {\n return await callback();\n } finally {\n frame.session?.finish();\n }\n });\n}\n\nexport const currentYamlSignal = (agent: object): AbortSignal | undefined => {\n if (!supportsAsyncContext) return signals.get(agent)?.at(-1)?.signal;\n for (let frame = context.getStore(); frame; frame = frame.parent) {\n const signal = frame.signals.get(agent)?.at(-1)?.signal;\n if (signal) return signal;\n }\n return undefined;\n};\n\nexport function enterYamlAction(\n agent: object,\n signal: AbortSignal,\n): () => void {\n const scopeSignals = supportsAsyncContext\n ? context.getStore()?.signals\n : signals;\n if (!scopeSignals)\n throw new Error('YAML action requires an execution context.');\n const stack = scopeSignals.get(agent) ?? [];\n scopeSignals.set(agent, stack);\n const entry = { signal };\n stack.push(entry);\n return () => {\n const index = stack.indexOf(entry);\n if (index >= 0) stack.splice(index, 1);\n if (!stack.length) scopeSignals.delete(agent);\n };\n}\n\nexport class YamlExecutionOwnershipError extends WorkflowError {}\n\n/** Nested runs borrow ownership. They never finalize or drain their parent. */\nexport function enterYamlExecution(\n agent: object,\n options: { allowIndependentOverlap?: boolean } = {},\n) {\n const stack = sessions.get(agent) ?? [];\n const frame = context.getStore();\n let parent = supportsAsyncContext ? undefined : stack.at(-1);\n if (supportsAsyncContext) {\n if (!frame || frame.session)\n throw new Error('YAML execution requires a fresh execution context.');\n for (let owner = frame.parent; owner; owner = owner.parent) {\n if (owner.session?.agent === agent) {\n parent = owner.session;\n break;\n }\n }\n if (parent?.finished)\n throw new YamlExecutionOwnershipError(\n 'Cannot start nested YAML after its owning execution has finished.',\n { code: 'YAML_EXECUTION_SCOPE_CLOSED' },\n );\n if (stack.at(-1) !== parent && !options.allowIndependentOverlap)\n throw new YamlExecutionOwnershipError(\n 'The same Agent cannot run independent overlapping YAML executions. Await the active run before starting another.',\n { code: 'YAML_EXECUTION_OVERLAP' },\n );\n }\n const session: YamlExecutionSession = {\n agent,\n children: [],\n finished: false,\n finish(record?: WorkflowExecutionRecord) {\n if (session.finished) return;\n session.finished = true;\n const index = stack.indexOf(session);\n if (index >= 0) stack.splice(index, 1);\n if (!stack.length) sessions.delete(agent);\n if (record) parent?.children.push(record);\n else parent?.children.push(...session.children);\n },\n };\n stack.push(session);\n sessions.set(agent, stack);\n if (frame) frame.session = session;\n return {\n isRoot: !parent,\n children: session.children,\n finish: session.finish,\n };\n}\n"],"names":["stateKey","Symbol","host","globalThis","WeakMap","createExecutionContext","sessions","signals","context","runInYamlExecutionContext","callback","frame","currentYamlSignal","agent","supportsAsyncContext","signal","enterYamlAction","scopeSignals","Error","stack","entry","index","YamlExecutionOwnershipError","WorkflowError","enterYamlExecution","options","parent","undefined","owner","session","record"],"mappings":"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"}
1
+ {"version":3,"file":"yaml/execution-session.mjs","sources":["../../../src/yaml/execution-session.ts"],"sourcesContent":["import {\n createExecutionContext,\n supportsAsyncContext,\n} from '#yaml-execution-context';\nimport { WorkflowError } from '../test-runner/errors';\nimport type { WorkflowExecutionRecord } from '../test-runner/execution-record';\n\ninterface YamlExecutionSession {\n agent: object;\n children: WorkflowExecutionRecord[];\n finished: boolean;\n finish(record?: WorkflowExecutionRecord): void;\n}\n\ninterface ExecutionFrame {\n parent?: ExecutionFrame;\n session?: YamlExecutionSession;\n signals: WeakMap<object, { signal: AbortSignal }[]>;\n}\n\nconst stateKey = Symbol.for('@midscene/core/yaml-execution-session/v2');\nconst host = globalThis as typeof globalThis & {\n [stateKey]?: {\n sessions: WeakMap<object, YamlExecutionSession[]>;\n signals: WeakMap<object, { signal: AbortSignal }[]>;\n context: ReturnType<typeof createExecutionContext<ExecutionFrame>>;\n };\n};\nhost[stateKey] ??= {\n sessions: new WeakMap(),\n signals: new WeakMap(),\n context: createExecutionContext<ExecutionFrame>(),\n};\nconst { sessions, signals, context } = host[stateKey];\n\n/** Report boundaries cannot change while a YAML owner still uses the Agent. */\nexport const hasActiveYamlExecution = (agent: object): boolean =>\n Boolean(sessions.get(agent)?.length);\n\n/** Every entry gets its own async frame, shared across CJS and ESM copies. */\nexport function runInYamlExecutionContext<T>(\n callback: () => Promise<T>,\n): Promise<T> {\n const frame: ExecutionFrame = {\n parent: context.getStore(),\n signals: new WeakMap(),\n };\n return context.run(frame, async () => {\n try {\n return await callback();\n } finally {\n frame.session?.finish();\n }\n });\n}\n\nexport const currentYamlSignal = (agent: object): AbortSignal | undefined => {\n if (!supportsAsyncContext) return signals.get(agent)?.at(-1)?.signal;\n for (let frame = context.getStore(); frame; frame = frame.parent) {\n const signal = frame.signals.get(agent)?.at(-1)?.signal;\n if (signal) return signal;\n }\n return undefined;\n};\n\nexport function enterYamlAction(\n agent: object,\n signal: AbortSignal,\n): () => void {\n const scopeSignals = supportsAsyncContext\n ? context.getStore()?.signals\n : signals;\n if (!scopeSignals)\n throw new Error('YAML action requires an execution context.');\n const stack = scopeSignals.get(agent) ?? [];\n scopeSignals.set(agent, stack);\n const entry = { signal };\n stack.push(entry);\n return () => {\n const index = stack.indexOf(entry);\n if (index >= 0) stack.splice(index, 1);\n if (!stack.length) scopeSignals.delete(agent);\n };\n}\n\nexport class YamlExecutionOwnershipError extends WorkflowError {}\n\n/** Nested runs borrow ownership. They never finalize or drain their parent. */\nexport function enterYamlExecution(\n agent: object,\n options: { allowIndependentOverlap?: boolean } = {},\n) {\n const stack = sessions.get(agent) ?? [];\n const frame = context.getStore();\n let parent = supportsAsyncContext ? undefined : stack.at(-1);\n if (supportsAsyncContext) {\n if (!frame || frame.session)\n throw new Error('YAML execution requires a fresh execution context.');\n for (let owner = frame.parent; owner; owner = owner.parent) {\n if (owner.session?.agent === agent) {\n parent = owner.session;\n break;\n }\n }\n if (parent?.finished)\n throw new YamlExecutionOwnershipError(\n 'Cannot start nested YAML after its owning execution has finished.',\n { code: 'YAML_EXECUTION_SCOPE_CLOSED' },\n );\n if (stack.at(-1) !== parent && !options.allowIndependentOverlap)\n throw new YamlExecutionOwnershipError(\n 'The same Agent cannot run independent overlapping YAML executions. Await the active run before starting another.',\n { code: 'YAML_EXECUTION_OVERLAP' },\n );\n }\n const session: YamlExecutionSession = {\n agent,\n children: [],\n finished: false,\n finish(record?: WorkflowExecutionRecord) {\n if (session.finished) return;\n session.finished = true;\n const index = stack.indexOf(session);\n if (index >= 0) stack.splice(index, 1);\n if (!stack.length) sessions.delete(agent);\n if (record) parent?.children.push(record);\n else parent?.children.push(...session.children);\n },\n };\n stack.push(session);\n sessions.set(agent, stack);\n if (frame) frame.session = session;\n return {\n isRoot: !parent,\n children: session.children,\n finish: session.finish,\n };\n}\n"],"names":["stateKey","Symbol","host","globalThis","WeakMap","createExecutionContext","sessions","signals","context","hasActiveYamlExecution","agent","Boolean","runInYamlExecutionContext","callback","frame","currentYamlSignal","supportsAsyncContext","signal","enterYamlAction","scopeSignals","Error","stack","entry","index","YamlExecutionOwnershipError","WorkflowError","enterYamlExecution","options","parent","undefined","owner","session","record"],"mappings":"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"}
@@ -34,8 +34,8 @@ async function publishLegacyYamlReport(options) {
34
34
  sdkVersion: getVersion(),
35
35
  modelBriefs: []
36
36
  });
37
- await generator.finalize();
38
37
  const source = await generator.createSourceSnapshot?.(runId);
38
+ await generator.finalize();
39
39
  if (source) record = Object.freeze({
40
40
  ...record,
41
41
  reportSources: [
@@ -1 +1 @@
1
- {"version":3,"file":"yaml/legacy-yaml-report.mjs","sources":["../../../src/yaml/legacy-yaml-report.ts"],"sourcesContent":["import { basename } from 'node:path';\nimport type { Agent } from '@/agent/agent';\nimport type { MidsceneYamlScript } from '@/types';\nimport { ifInBrowser, ifInWorker } from '@midscene/shared/utils';\nimport { ReportGenerator } from '../report-generator';\nimport type { WorkflowExecutionRecord } from '../test-runner';\nimport { executionRecordsToReportInput } from '../test-runner/reporting/execution-record';\nimport { getVersion } from '../utils';\nimport { isYamlReportEnabled } from './report-policy';\n\ninterface PublishLegacyYamlReportOptions {\n agent: Agent | null;\n record: WorkflowExecutionRecord;\n runId: string;\n script: MidsceneYamlScript;\n scriptPath?: string;\n fallbackReportFileName?: string;\n}\n\nexport interface PublishedLegacyYamlReport {\n record: WorkflowExecutionRecord;\n reportFile?: string | null;\n}\n\n/** Report publication is a host projection, not a ScriptPlayer state concern. */\nexport async function publishLegacyYamlReport(\n options: PublishLegacyYamlReportOptions,\n): Promise<PublishedLegacyYamlReport> {\n const { agent, runId } = options;\n let record = options.record;\n if (agent) {\n const reportFile =\n (await agent._writeYamlExecutionReport?.(record)) ?? agent.reportFile;\n const source = await agent._createReportSource?.(runId);\n if (source) record = Object.freeze({ ...record, reportSources: [source] });\n return { record, reportFile };\n }\n if (ifInBrowser || ifInWorker || !isYamlReportEnabled(options.script))\n return { record };\n\n const generator = ReportGenerator.create(\n options.fallbackReportFileName ??\n options.script.agent?.reportFileName ??\n options.script.agent?.testId ??\n (options.scriptPath\n ? basename(options.scriptPath).replace(/\\.ya?ml$/i, '')\n : `script-${runId}`),\n options.script.agent ?? {},\n );\n const reportFile = await generator.writeRunnerReport?.(\n executionRecordsToReportInput([record], { runId }),\n runId,\n {\n groupName: 'YAML execution',\n sdkVersion: getVersion(),\n modelBriefs: [],\n },\n );\n await generator.finalize();\n const source = await generator.createSourceSnapshot?.(runId);\n if (source) record = Object.freeze({ ...record, reportSources: [source] });\n return { record, reportFile };\n}\n"],"names":["publishLegacyYamlReport","options","agent","runId","record","reportFile","source","Object","ifInBrowser","ifInWorker","isYamlReportEnabled","generator","ReportGenerator","basename","executionRecordsToReportInput","getVersion"],"mappings":";;;;;;AAyBO,eAAeA,wBACpBC,OAAuC;IAEvC,MAAM,EAAEC,KAAK,EAAEC,KAAK,EAAE,GAAGF;IACzB,IAAIG,SAASH,QAAQ,MAAM;IAC3B,IAAIC,OAAO;QACT,MAAMG,aACH,MAAMH,MAAM,yBAAyB,GAAGE,WAAYF,MAAM,UAAU;QACvE,MAAMI,SAAS,MAAMJ,MAAM,mBAAmB,GAAGC;QACjD,IAAIG,QAAQF,SAASG,OAAO,MAAM,CAAC;YAAE,GAAGH,MAAM;YAAE,eAAe;gBAACE;aAAO;QAAC;QACxE,OAAO;YAAEF;YAAQC;QAAW;IAC9B;IACA,IAAIG,eAAeC,cAAc,CAACC,oBAAoBT,QAAQ,MAAM,GAClE,OAAO;QAAEG;IAAO;IAElB,MAAMO,YAAYC,gBAAgB,MAAM,CACtCX,QAAQ,sBAAsB,IAC5BA,QAAQ,MAAM,CAAC,KAAK,EAAE,kBACtBA,QAAQ,MAAM,CAAC,KAAK,EAAE,UACrBA,CAAAA,QAAQ,UAAU,GACfY,SAASZ,QAAQ,UAAU,EAAE,OAAO,CAAC,aAAa,MAClD,CAAC,OAAO,EAAEE,OAAM,GACtBF,QAAQ,MAAM,CAAC,KAAK,IAAI,CAAC;IAE3B,MAAMI,aAAa,MAAMM,UAAU,iBAAiB,GAClDG,8BAA8B;QAACV;KAAO,EAAE;QAAED;IAAM,IAChDA,OACA;QACE,WAAW;QACX,YAAYY;QACZ,aAAa,EAAE;IACjB;IAEF,MAAMJ,UAAU,QAAQ;IACxB,MAAML,SAAS,MAAMK,UAAU,oBAAoB,GAAGR;IACtD,IAAIG,QAAQF,SAASG,OAAO,MAAM,CAAC;QAAE,GAAGH,MAAM;QAAE,eAAe;YAACE;SAAO;IAAC;IACxE,OAAO;QAAEF;QAAQC;IAAW;AAC9B"}
1
+ {"version":3,"file":"yaml/legacy-yaml-report.mjs","sources":["../../../src/yaml/legacy-yaml-report.ts"],"sourcesContent":["import { basename } from 'node:path';\nimport type { Agent } from '@/agent/agent';\nimport type { MidsceneYamlScript } from '@/types';\nimport { ifInBrowser, ifInWorker } from '@midscene/shared/utils';\nimport { ReportGenerator } from '../report-generator';\nimport type { WorkflowExecutionRecord } from '../test-runner';\nimport { executionRecordsToReportInput } from '../test-runner/reporting/execution-record';\nimport { getVersion } from '../utils';\nimport { isYamlReportEnabled } from './report-policy';\n\ninterface PublishLegacyYamlReportOptions {\n agent: Agent | null;\n record: WorkflowExecutionRecord;\n runId: string;\n script: MidsceneYamlScript;\n scriptPath?: string;\n fallbackReportFileName?: string;\n}\n\nexport interface PublishedLegacyYamlReport {\n record: WorkflowExecutionRecord;\n reportFile?: string | null;\n}\n\n/** Report publication is a host projection, not a ScriptPlayer state concern. */\nexport async function publishLegacyYamlReport(\n options: PublishLegacyYamlReportOptions,\n): Promise<PublishedLegacyYamlReport> {\n const { agent, runId } = options;\n let record = options.record;\n if (agent) {\n const reportFile =\n (await agent._writeYamlExecutionReport?.(record)) ?? agent.reportFile;\n const source = await agent._createReportSource?.(runId);\n if (source) record = Object.freeze({ ...record, reportSources: [source] });\n return { record, reportFile };\n }\n if (ifInBrowser || ifInWorker || !isYamlReportEnabled(options.script))\n return { record };\n\n const generator = ReportGenerator.create(\n options.fallbackReportFileName ??\n options.script.agent?.reportFileName ??\n options.script.agent?.testId ??\n (options.scriptPath\n ? basename(options.scriptPath).replace(/\\.ya?ml$/i, '')\n : `script-${runId}`),\n options.script.agent ?? {},\n );\n const reportFile = await generator.writeRunnerReport?.(\n executionRecordsToReportInput([record], { runId }),\n runId,\n {\n groupName: 'YAML execution',\n sdkVersion: getVersion(),\n modelBriefs: [],\n },\n );\n const source = await generator.createSourceSnapshot?.(runId);\n await generator.finalize();\n if (source) record = Object.freeze({ ...record, reportSources: [source] });\n return { record, reportFile };\n}\n"],"names":["publishLegacyYamlReport","options","agent","runId","record","reportFile","source","Object","ifInBrowser","ifInWorker","isYamlReportEnabled","generator","ReportGenerator","basename","executionRecordsToReportInput","getVersion"],"mappings":";;;;;;AAyBO,eAAeA,wBACpBC,OAAuC;IAEvC,MAAM,EAAEC,KAAK,EAAEC,KAAK,EAAE,GAAGF;IACzB,IAAIG,SAASH,QAAQ,MAAM;IAC3B,IAAIC,OAAO;QACT,MAAMG,aACH,MAAMH,MAAM,yBAAyB,GAAGE,WAAYF,MAAM,UAAU;QACvE,MAAMI,SAAS,MAAMJ,MAAM,mBAAmB,GAAGC;QACjD,IAAIG,QAAQF,SAASG,OAAO,MAAM,CAAC;YAAE,GAAGH,MAAM;YAAE,eAAe;gBAACE;aAAO;QAAC;QACxE,OAAO;YAAEF;YAAQC;QAAW;IAC9B;IACA,IAAIG,eAAeC,cAAc,CAACC,oBAAoBT,QAAQ,MAAM,GAClE,OAAO;QAAEG;IAAO;IAElB,MAAMO,YAAYC,gBAAgB,MAAM,CACtCX,QAAQ,sBAAsB,IAC5BA,QAAQ,MAAM,CAAC,KAAK,EAAE,kBACtBA,QAAQ,MAAM,CAAC,KAAK,EAAE,UACrBA,CAAAA,QAAQ,UAAU,GACfY,SAASZ,QAAQ,UAAU,EAAE,OAAO,CAAC,aAAa,MAClD,CAAC,OAAO,EAAEE,OAAM,GACtBF,QAAQ,MAAM,CAAC,KAAK,IAAI,CAAC;IAE3B,MAAMI,aAAa,MAAMM,UAAU,iBAAiB,GAClDG,8BAA8B;QAACV;KAAO,EAAE;QAAED;IAAM,IAChDA,OACA;QACE,WAAW;QACX,YAAYY;QACZ,aAAa,EAAE;IACjB;IAEF,MAAMT,SAAS,MAAMK,UAAU,oBAAoB,GAAGR;IACtD,MAAMQ,UAAU,QAAQ;IACxB,IAAIL,QAAQF,SAASG,OAAO,MAAM,CAAC;QAAE,GAAGH,MAAM;QAAE,eAAe;YAACE;SAAO;IAAC;IACxE,OAAO;QAAEF;QAAQC;IAAW;AAC9B"}
@@ -7,7 +7,7 @@ import { assert, ifInBrowser, ifInWorker, uuid } from "@midscene/shared/utils";
7
7
  import { WorkflowExecutionFailure, WorkflowPublicationError } from "../test-runner/engine/execution-failure.mjs";
8
8
  import { cleanupResources } from "../test-runner/engine/resource-operations.mjs";
9
9
  import { runFreeFnCleanup } from "./cleanup.mjs";
10
- import { YamlExecutionOwnershipError, currentYamlSignal, enterYamlExecution, runInYamlExecutionContext } from "./execution-session.mjs";
10
+ import { YamlExecutionOwnershipError, currentYamlSignal, enterYamlExecution, hasActiveYamlExecution, runInYamlExecutionContext } from "./execution-session.mjs";
11
11
  import { createLegacyYamlExecutionRecord } from "./legacy-yaml-execution-record.mjs";
12
12
  import { publishLegacyYamlReport } from "./legacy-yaml-report.mjs";
13
13
  import { createLegacyYamlRuntime, legacyYamlOutcomeError } from "./legacy-yaml-runtime.mjs";
@@ -141,11 +141,11 @@ class ScriptPlayer {
141
141
  try {
142
142
  const { agent: newAgent, freeFn: newFreeFn } = await this.setupAgent(platform);
143
143
  agent = newAgent;
144
- agent._prepareForTestRunner?.();
144
+ session = enterYamlExecution(agent);
145
145
  freeFn = [
146
146
  ...newFreeFn || []
147
147
  ];
148
- session = enterYamlExecution(agent);
148
+ agent._prepareForTestRunner?.();
149
149
  signal = this.abortSignal ?? currentYamlSignal(agent);
150
150
  signal?.throwIfAborted();
151
151
  this.actionSpace = await agent.getActionSpace();
@@ -267,6 +267,20 @@ class ScriptPlayer {
267
267
  });
268
268
  }
269
269
  session?.finish(state.executionRecord);
270
+ if (agent?.destroyed && !hasActiveYamlExecution(agent)) try {
271
+ await agent.finalizeReport();
272
+ } catch (error) {
273
+ reportError = reportError ? new AggregateError([
274
+ reportError,
275
+ error
276
+ ], 'YAML report publication failed') : error;
277
+ this.setPlayerStatus('error', reportError);
278
+ state.executionRecord = Object.freeze({
279
+ ...state.executionRecord,
280
+ status: 'failed',
281
+ reportError
282
+ });
283
+ }
270
284
  if (reportError) {
271
285
  const errors = [
272
286
  setupError,
@@ -1 +1 @@
1
- {"version":3,"file":"yaml/player.mjs","sources":["../../../src/yaml/player.ts"],"sourcesContent":["import { mkdir, writeFile } from 'node:fs/promises';\nimport { basename, dirname, join, resolve } from 'node:path';\nimport { isActionReadinessError } from '@/agent/action-readiness';\nimport type { Agent } from '@/agent/agent';\nimport type {\n DeviceAction,\n FreeFn,\n MidsceneYamlScript,\n MidsceneYamlScriptEnv,\n ScriptPlayerStatusValue,\n ScriptPlayerTaskStatus,\n} from '@/types';\nimport { getMidsceneRunSubDir } from '@midscene/shared/common';\nimport { getDebug } from '@midscene/shared/logger';\nimport { assert, ifInBrowser, ifInWorker, uuid } from '@midscene/shared/utils';\nimport type { WorkflowDocumentExecutionResult } from '../test-runner';\nimport {\n WorkflowExecutionFailure,\n WorkflowPublicationError,\n} from '../test-runner/engine/execution-failure';\nimport { cleanupResources } from '../test-runner/engine/resource-operations';\nimport { runFreeFnCleanup } from './cleanup';\nimport {\n YamlExecutionOwnershipError,\n currentYamlSignal,\n enterYamlExecution,\n runInYamlExecutionContext,\n} from './execution-session';\nimport { createLegacyYamlExecutionRecord } from './legacy-yaml-execution-record';\nimport { publishLegacyYamlReport } from './legacy-yaml-report';\nimport {\n createLegacyYamlRuntime,\n legacyYamlOutcomeError,\n} from './legacy-yaml-runtime';\nimport {\n getLegacyYamlPlayerState,\n initializeLegacyYamlPlayerState,\n} from './player-state';\nimport { collectLegacyYamlDocument } from './test-runner-compat';\nimport { resolveWebTarget, resolveYamlOutputConfig } from './utils';\n\nconst debug = getDebug('yaml-player');\n\n/**\n * Compatibility facade for the legacy YAML API.\n *\n * Execution is delegated to the shared Runner kernel through\n * createLegacyYamlRuntime(). This class keeps the mutable status, result,\n * progress, output, and setup/cleanup behavior exposed by the old API.\n */\nexport class ScriptPlayer<T extends MidsceneYamlScriptEnv> {\n public currentTaskIndex?: number;\n public taskStatusList: ScriptPlayerTaskStatus[] = [];\n public status: ScriptPlayerStatusValue = 'init';\n public reportFile?: string | null;\n public result: Record<string, any>;\n private unnamedResultIndex = 0;\n private publicationErrors: WorkflowPublicationError[] = [];\n public output?: string | null;\n public unstableLogContent?: string | null;\n public errorInSetup?: Error;\n private interfaceAgent: Agent | null = null;\n public agentStatusTip?: string;\n public target?: MidsceneYamlScriptEnv;\n private actionSpace: DeviceAction[] = [];\n private scriptPath?: string;\n\n constructor(\n private script: MidsceneYamlScript,\n private setupAgent: (platform: T) => Promise<{\n agent: Agent;\n freeFn: FreeFn[];\n }>,\n public onTaskStatusChange?: (taskStatus: ScriptPlayerTaskStatus) => void,\n scriptPath?: string,\n private readonly abortSignal?: AbortSignal,\n ) {\n this.scriptPath = scriptPath;\n // Collection validates syntax but defers old task/Step errors until execution.\n collectLegacyYamlDocument(script, scriptPath);\n initializeLegacyYamlPlayerState(this);\n this.result = {};\n\n this.target =\n resolveWebTarget(script)?.target ||\n script.android ||\n script.ios ||\n script.harmony ||\n script.computer ||\n script.config;\n const outputConfig = resolveYamlOutputConfig(script);\n\n if (ifInBrowser || ifInWorker) {\n this.output = undefined;\n debug('output is undefined in browser or worker');\n } else if (outputConfig.output) {\n this.output = resolve(process.cwd(), outputConfig.output);\n debug('setting output by config.output', this.output);\n } else {\n const scriptName = this.scriptPath\n ? basename(this.scriptPath, '.yaml').replace(/\\.(ya?ml)$/i, '')\n : 'script';\n this.output = join(\n getMidsceneRunSubDir('output'),\n `${scriptName}-${uuid()}.json`,\n );\n debug('setting output by script path', this.output);\n }\n\n if (ifInBrowser || ifInWorker) {\n this.unstableLogContent = undefined;\n } else if (typeof outputConfig.unstableLogContent === 'string') {\n this.unstableLogContent = resolve(\n process.cwd(),\n outputConfig.unstableLogContent,\n );\n } else if (outputConfig.unstableLogContent === true) {\n this.unstableLogContent = join(\n getMidsceneRunSubDir('output'),\n 'unstableLogContent.json',\n );\n }\n\n this.taskStatusList = (script.tasks || []).map((task, taskIndex) => ({\n ...task,\n index: taskIndex,\n status: 'init',\n totalSteps: task.flow?.length || 0,\n }));\n }\n\n private setResult(key: string | undefined, value: any) {\n const keyToUse = key || this.unnamedResultIndex++;\n if (this.result[keyToUse]) {\n getDebug('yaml-player', { console: true })(\n `result key ${keyToUse} already exists, will overwrite`,\n );\n }\n this.result[keyToUse] = value;\n\n return this.flushResult();\n }\n\n private setPlayerStatus(status: ScriptPlayerStatusValue, error?: Error) {\n this.status = status;\n this.errorInSetup = error;\n }\n\n private notifyCurrentTaskStatusChange(taskIndex?: number) {\n const taskIndexToNotify =\n typeof taskIndex === 'number' ? taskIndex : this.currentTaskIndex;\n\n if (typeof taskIndexToNotify !== 'number') return;\n\n const taskStatus = this.taskStatusList[taskIndexToNotify];\n this.onTaskStatusChange?.(taskStatus);\n }\n\n private async setTaskStatus(\n index: number,\n statusValue: ScriptPlayerStatusValue,\n error?: Error,\n ) {\n this.taskStatusList[index].status = statusValue;\n if (error) this.taskStatusList[index].error = error;\n this.notifyCurrentTaskStatusChange(index);\n }\n\n private setTaskIndex(taskIndex: number) {\n this.currentTaskIndex = taskIndex;\n }\n\n private async flushResult() {\n if (this.output) {\n const output = resolve(process.cwd(), this.output);\n await this.publish(output, async () => {\n const outputDir = dirname(output);\n await mkdir(outputDir, { recursive: true });\n await writeFile(\n output,\n JSON.stringify(this.result || {}, undefined, 2),\n );\n });\n }\n }\n\n private async flushUnstableLogContent() {\n if (this.unstableLogContent) {\n const content = this.interfaceAgent?._unstableLogContent();\n const filePath = resolve(process.cwd(), this.unstableLogContent);\n await this.publish(filePath, async () => {\n const outputDir = dirname(filePath);\n await mkdir(outputDir, { recursive: true });\n await writeFile(filePath, JSON.stringify(content, null, 2));\n });\n }\n }\n\n private async publish(path: string, write: () => Promise<void>) {\n try {\n await write();\n } catch (cause) {\n const error = new WorkflowPublicationError('write-result', path, cause);\n this.publicationErrors.push(error);\n throw error;\n }\n }\n\n private createRuntime(agent: Agent) {\n return createLegacyYamlRuntime({\n agent,\n actionSpace: this.actionSpace,\n sourcePath: this.scriptPath,\n setResult: (key, value) => this.setResult(key, value),\n });\n }\n\n async playTask(taskStatus: ScriptPlayerTaskStatus, agent: Agent) {\n const { flow } = taskStatus;\n assert(flow, 'missing flow in task');\n const statusIndex = this.taskStatusList.indexOf(taskStatus);\n const declaredIndex = (\n taskStatus as ScriptPlayerTaskStatus & {\n index?: unknown;\n }\n ).index;\n const taskIndex =\n statusIndex >= 0\n ? statusIndex\n : typeof declaredIndex === 'number' && Number.isInteger(declaredIndex)\n ? declaredIndex\n : 0;\n\n const state = getLegacyYamlPlayerState(this);\n state.executionResult = await this.createRuntime(agent).runTask(\n taskStatus,\n taskIndex,\n {\n signal: this.abortSignal ?? currentYamlSignal(agent),\n onStepStart: (info) => {\n if (info.scope === 'case' && info.case.phase === 'steps') {\n taskStatus.currentStep = info.case.stepIndex;\n }\n },\n },\n );\n\n const outcome = state.executionResult.cases[0];\n if (!outcome || outcome.status === 'not-run') {\n throw new Error(`Task \"${taskStatus.name}\" did not run.`);\n }\n if (outcome.status === 'failed') throw legacyYamlOutcomeError(outcome);\n\n this.reportFile = agent.reportFile;\n await this.flushUnstableLogContent();\n }\n\n async run() {\n return runInYamlExecutionContext(() => this.runInContext());\n }\n\n private async runInContext() {\n const startedAt = new Date();\n const runId = uuid();\n const state = getLegacyYamlPlayerState(this);\n state.executionResult = undefined;\n state.executionRecord = undefined;\n this.publicationErrors = [];\n const { android, ios, harmony, computer } = this.script;\n const webEnv = resolveWebTarget(this.script)?.target;\n const androidEnv = android;\n const iosEnv = ios;\n const harmonyEnv = harmony;\n const computerEnv = computer;\n const platform =\n webEnv || androidEnv || iosEnv || harmonyEnv || computerEnv;\n\n this.setPlayerStatus('running');\n\n let agent: Agent | null = null;\n let freeFn: FreeFn[] = [];\n let setupError: unknown;\n let executionError: unknown;\n let cleanupError: unknown;\n let signal: AbortSignal | undefined;\n let session: ReturnType<typeof enterYamlExecution> | undefined;\n try {\n const { agent: newAgent, freeFn: newFreeFn } = await this.setupAgent(\n platform as T,\n );\n // Register ownership immediately: discovering actions can fail too.\n agent = newAgent;\n agent._prepareForTestRunner?.();\n freeFn = [...(newFreeFn || [])];\n session = enterYamlExecution(agent);\n signal = this.abortSignal ?? currentYamlSignal(agent);\n signal?.throwIfAborted();\n this.actionSpace = await agent.getActionSpace();\n const originalOnTaskStartTip = agent.onTaskStartTip;\n agent.onTaskStartTip = (tip) => {\n if (this.status === 'running') this.agentStatusTip = tip;\n originalOnTaskStartTip?.(tip);\n };\n freeFn.push({\n name: 'restore-agent-onTaskStartTip',\n fn: () => {\n if (agent) agent.onTaskStartTip = originalOnTaskStartTip;\n },\n });\n } catch (error) {\n // A rejected borrower must not close or publish into another run's Agent.\n if (error instanceof YamlExecutionOwnershipError) throw error;\n setupError = error;\n this.setPlayerStatus('error', error as Error);\n }\n this.interfaceAgent = agent;\n\n const document = collectLegacyYamlDocument(\n this.script,\n this.scriptPath ?? '<inline-yaml>',\n this.actionSpace,\n );\n const runtime =\n agent && !setupError ? this.createRuntime(agent) : undefined;\n try {\n if (runtime && agent) {\n state.executionResult = await runtime.runScript(this.script, {\n document,\n signal,\n createDocumentRunId: () => runId,\n onCaseStart: (collectedCase) => {\n const taskIndex = collectedCase.caseIndex;\n this.setTaskIndex(taskIndex);\n return this.setTaskStatus(taskIndex, 'running');\n },\n onStepStart: (info) => {\n if (info.scope !== 'case' || info.case.phase !== 'steps') return;\n const taskStatus = this.taskStatusList[info.case.caseIndex];\n if (taskStatus) taskStatus.currentStep = info.case.stepIndex;\n },\n onCaseOutcome: async (outcome) => {\n if (outcome.status === 'not-run') return;\n const taskIndex = outcome.caseIndex;\n const taskStatus = this.taskStatusList[taskIndex];\n assert(taskStatus, `missing YAML task at index ${taskIndex}`);\n\n this.reportFile = agent?.reportFile;\n if (outcome.status === 'success') {\n await this.setTaskStatus(taskIndex, 'done');\n await this.flushUnstableLogContent();\n return;\n }\n\n const error = legacyYamlOutcomeError(outcome);\n await this.setTaskStatus(taskIndex, 'error', error);\n },\n });\n const stoppedOnFailure = state.executionResult.cases.some(\n (outcome) =>\n outcome.status === 'failed' &&\n (!this.taskStatusList[outcome.caseIndex]?.continueOnError ||\n isActionReadinessError(legacyYamlOutcomeError(outcome))),\n );\n this.setPlayerStatus(\n stoppedOnFailure || signal?.aborted ? 'error' : 'done',\n );\n }\n } catch (error) {\n executionError = error;\n if (error instanceof WorkflowExecutionFailure)\n state.executionResult = error.result as WorkflowDocumentExecutionResult;\n this.setPlayerStatus('error', error as Error);\n }\n\n this.reportFile = agent?.reportFile;\n this.agentStatusTip = '';\n\n try {\n // A timeout settles the Runner before an uncooperative device action.\n // Never dispose its Agent while that action is still using it.\n if (session?.isRoot && agent) {\n await cleanupResources([agent], () => runFreeFnCleanup(freeFn), {\n owner: this,\n signal,\n onDeferredError: (error) =>\n getDebug('yaml-player', { console: true })(\n `Deferred YAML cleanup failed: ${String(error)}`,\n ),\n });\n } else await runFreeFnCleanup(freeFn);\n } catch (error) {\n cleanupError = error;\n this.setPlayerStatus(\n 'error',\n (setupError ?? executionError ?? error) as Error,\n );\n }\n\n const endedAt = new Date();\n const cleanupErrors =\n cleanupError instanceof AggregateError\n ? cleanupError.errors\n : cleanupError === undefined\n ? []\n : [cleanupError];\n state.executionRecord = createLegacyYamlExecutionRecord({\n runId,\n attemptIndex: 0,\n script: this.script,\n document,\n startedAt,\n endedAt,\n execution: state.executionResult,\n setupError,\n executionError,\n cleanupErrors,\n aborted: signal?.aborted ?? false,\n publicationErrors: this.publicationErrors,\n outputs: this.result,\n reportFile: agent?.reportFile,\n children: session?.children,\n });\n let reportError: unknown;\n if (!session || session.isRoot) {\n try {\n const published = await publishLegacyYamlReport({\n agent,\n record: state.executionRecord,\n runId,\n script: this.script,\n scriptPath: this.scriptPath,\n fallbackReportFileName: state.fallbackReportFileName,\n });\n this.reportFile = published.reportFile;\n state.executionRecord = published.record;\n } catch (error) {\n reportError = error;\n this.setPlayerStatus(\n 'error',\n (setupError ?? executionError ?? cleanupError ?? error) as Error,\n );\n state.executionRecord = Object.freeze({\n ...state.executionRecord,\n status: 'failed',\n reportError: error,\n });\n }\n }\n session?.finish(state.executionRecord);\n if (reportError) {\n const errors = [\n setupError,\n executionError,\n ...cleanupErrors,\n reportError,\n ].filter((error) => error !== undefined);\n throw errors.length === 1\n ? reportError\n : new AggregateError(\n errors,\n 'YAML execution/report finalization failed',\n );\n }\n if (executionError && cleanupError) {\n throw new AggregateError(\n [executionError, ...cleanupErrors],\n 'YAML execution and cleanup failed',\n );\n }\n if (executionError) throw executionError;\n if (cleanupError) throw cleanupError;\n }\n}\n"],"names":["debug","getDebug","ScriptPlayer","key","value","keyToUse","status","error","taskIndex","taskIndexToNotify","taskStatus","index","statusValue","output","resolve","process","outputDir","dirname","mkdir","writeFile","JSON","undefined","content","filePath","path","write","cause","WorkflowPublicationError","agent","createLegacyYamlRuntime","flow","assert","statusIndex","declaredIndex","Number","state","getLegacyYamlPlayerState","currentYamlSignal","info","outcome","Error","legacyYamlOutcomeError","runInYamlExecutionContext","startedAt","Date","runId","uuid","android","ios","harmony","computer","webEnv","resolveWebTarget","androidEnv","iosEnv","harmonyEnv","computerEnv","platform","freeFn","setupError","executionError","cleanupError","signal","session","newAgent","newFreeFn","enterYamlExecution","originalOnTaskStartTip","tip","YamlExecutionOwnershipError","document","collectLegacyYamlDocument","runtime","collectedCase","stoppedOnFailure","isActionReadinessError","WorkflowExecutionFailure","cleanupResources","runFreeFnCleanup","String","endedAt","cleanupErrors","AggregateError","createLegacyYamlExecutionRecord","reportError","published","publishLegacyYamlReport","Object","errors","script","setupAgent","onTaskStatusChange","scriptPath","abortSignal","initializeLegacyYamlPlayerState","outputConfig","resolveYamlOutputConfig","ifInBrowser","ifInWorker","scriptName","basename","join","getMidsceneRunSubDir","task"],"mappings":"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"}
1
+ {"version":3,"file":"yaml/player.mjs","sources":["../../../src/yaml/player.ts"],"sourcesContent":["import { mkdir, writeFile } from 'node:fs/promises';\nimport { basename, dirname, join, resolve } from 'node:path';\nimport { isActionReadinessError } from '@/agent/action-readiness';\nimport type { Agent } from '@/agent/agent';\nimport type {\n DeviceAction,\n FreeFn,\n MidsceneYamlScript,\n MidsceneYamlScriptEnv,\n ScriptPlayerStatusValue,\n ScriptPlayerTaskStatus,\n} from '@/types';\nimport { getMidsceneRunSubDir } from '@midscene/shared/common';\nimport { getDebug } from '@midscene/shared/logger';\nimport { assert, ifInBrowser, ifInWorker, uuid } from '@midscene/shared/utils';\nimport type { WorkflowDocumentExecutionResult } from '../test-runner';\nimport {\n WorkflowExecutionFailure,\n WorkflowPublicationError,\n} from '../test-runner/engine/execution-failure';\nimport { cleanupResources } from '../test-runner/engine/resource-operations';\nimport { runFreeFnCleanup } from './cleanup';\nimport {\n YamlExecutionOwnershipError,\n currentYamlSignal,\n enterYamlExecution,\n hasActiveYamlExecution,\n runInYamlExecutionContext,\n} from './execution-session';\nimport { createLegacyYamlExecutionRecord } from './legacy-yaml-execution-record';\nimport { publishLegacyYamlReport } from './legacy-yaml-report';\nimport {\n createLegacyYamlRuntime,\n legacyYamlOutcomeError,\n} from './legacy-yaml-runtime';\nimport {\n getLegacyYamlPlayerState,\n initializeLegacyYamlPlayerState,\n} from './player-state';\nimport { collectLegacyYamlDocument } from './test-runner-compat';\nimport { resolveWebTarget, resolveYamlOutputConfig } from './utils';\n\nconst debug = getDebug('yaml-player');\n\n/**\n * Compatibility facade for the legacy YAML API.\n *\n * Execution is delegated to the shared Runner kernel through\n * createLegacyYamlRuntime(). This class keeps the mutable status, result,\n * progress, output, and setup/cleanup behavior exposed by the old API.\n */\nexport class ScriptPlayer<T extends MidsceneYamlScriptEnv> {\n public currentTaskIndex?: number;\n public taskStatusList: ScriptPlayerTaskStatus[] = [];\n public status: ScriptPlayerStatusValue = 'init';\n public reportFile?: string | null;\n public result: Record<string, any>;\n private unnamedResultIndex = 0;\n private publicationErrors: WorkflowPublicationError[] = [];\n public output?: string | null;\n public unstableLogContent?: string | null;\n public errorInSetup?: Error;\n private interfaceAgent: Agent | null = null;\n public agentStatusTip?: string;\n public target?: MidsceneYamlScriptEnv;\n private actionSpace: DeviceAction[] = [];\n private scriptPath?: string;\n\n constructor(\n private script: MidsceneYamlScript,\n private setupAgent: (platform: T) => Promise<{\n agent: Agent;\n freeFn: FreeFn[];\n }>,\n public onTaskStatusChange?: (taskStatus: ScriptPlayerTaskStatus) => void,\n scriptPath?: string,\n private readonly abortSignal?: AbortSignal,\n ) {\n this.scriptPath = scriptPath;\n // Collection validates syntax but defers old task/Step errors until execution.\n collectLegacyYamlDocument(script, scriptPath);\n initializeLegacyYamlPlayerState(this);\n this.result = {};\n\n this.target =\n resolveWebTarget(script)?.target ||\n script.android ||\n script.ios ||\n script.harmony ||\n script.computer ||\n script.config;\n const outputConfig = resolveYamlOutputConfig(script);\n\n if (ifInBrowser || ifInWorker) {\n this.output = undefined;\n debug('output is undefined in browser or worker');\n } else if (outputConfig.output) {\n this.output = resolve(process.cwd(), outputConfig.output);\n debug('setting output by config.output', this.output);\n } else {\n const scriptName = this.scriptPath\n ? basename(this.scriptPath, '.yaml').replace(/\\.(ya?ml)$/i, '')\n : 'script';\n this.output = join(\n getMidsceneRunSubDir('output'),\n `${scriptName}-${uuid()}.json`,\n );\n debug('setting output by script path', this.output);\n }\n\n if (ifInBrowser || ifInWorker) {\n this.unstableLogContent = undefined;\n } else if (typeof outputConfig.unstableLogContent === 'string') {\n this.unstableLogContent = resolve(\n process.cwd(),\n outputConfig.unstableLogContent,\n );\n } else if (outputConfig.unstableLogContent === true) {\n this.unstableLogContent = join(\n getMidsceneRunSubDir('output'),\n 'unstableLogContent.json',\n );\n }\n\n this.taskStatusList = (script.tasks || []).map((task, taskIndex) => ({\n ...task,\n index: taskIndex,\n status: 'init',\n totalSteps: task.flow?.length || 0,\n }));\n }\n\n private setResult(key: string | undefined, value: any) {\n const keyToUse = key || this.unnamedResultIndex++;\n if (this.result[keyToUse]) {\n getDebug('yaml-player', { console: true })(\n `result key ${keyToUse} already exists, will overwrite`,\n );\n }\n this.result[keyToUse] = value;\n\n return this.flushResult();\n }\n\n private setPlayerStatus(status: ScriptPlayerStatusValue, error?: Error) {\n this.status = status;\n this.errorInSetup = error;\n }\n\n private notifyCurrentTaskStatusChange(taskIndex?: number) {\n const taskIndexToNotify =\n typeof taskIndex === 'number' ? taskIndex : this.currentTaskIndex;\n\n if (typeof taskIndexToNotify !== 'number') return;\n\n const taskStatus = this.taskStatusList[taskIndexToNotify];\n this.onTaskStatusChange?.(taskStatus);\n }\n\n private async setTaskStatus(\n index: number,\n statusValue: ScriptPlayerStatusValue,\n error?: Error,\n ) {\n this.taskStatusList[index].status = statusValue;\n if (error) this.taskStatusList[index].error = error;\n this.notifyCurrentTaskStatusChange(index);\n }\n\n private setTaskIndex(taskIndex: number) {\n this.currentTaskIndex = taskIndex;\n }\n\n private async flushResult() {\n if (this.output) {\n const output = resolve(process.cwd(), this.output);\n await this.publish(output, async () => {\n const outputDir = dirname(output);\n await mkdir(outputDir, { recursive: true });\n await writeFile(\n output,\n JSON.stringify(this.result || {}, undefined, 2),\n );\n });\n }\n }\n\n private async flushUnstableLogContent() {\n if (this.unstableLogContent) {\n const content = this.interfaceAgent?._unstableLogContent();\n const filePath = resolve(process.cwd(), this.unstableLogContent);\n await this.publish(filePath, async () => {\n const outputDir = dirname(filePath);\n await mkdir(outputDir, { recursive: true });\n await writeFile(filePath, JSON.stringify(content, null, 2));\n });\n }\n }\n\n private async publish(path: string, write: () => Promise<void>) {\n try {\n await write();\n } catch (cause) {\n const error = new WorkflowPublicationError('write-result', path, cause);\n this.publicationErrors.push(error);\n throw error;\n }\n }\n\n private createRuntime(agent: Agent) {\n return createLegacyYamlRuntime({\n agent,\n actionSpace: this.actionSpace,\n sourcePath: this.scriptPath,\n setResult: (key, value) => this.setResult(key, value),\n });\n }\n\n async playTask(taskStatus: ScriptPlayerTaskStatus, agent: Agent) {\n const { flow } = taskStatus;\n assert(flow, 'missing flow in task');\n const statusIndex = this.taskStatusList.indexOf(taskStatus);\n const declaredIndex = (\n taskStatus as ScriptPlayerTaskStatus & {\n index?: unknown;\n }\n ).index;\n const taskIndex =\n statusIndex >= 0\n ? statusIndex\n : typeof declaredIndex === 'number' && Number.isInteger(declaredIndex)\n ? declaredIndex\n : 0;\n\n const state = getLegacyYamlPlayerState(this);\n state.executionResult = await this.createRuntime(agent).runTask(\n taskStatus,\n taskIndex,\n {\n signal: this.abortSignal ?? currentYamlSignal(agent),\n onStepStart: (info) => {\n if (info.scope === 'case' && info.case.phase === 'steps') {\n taskStatus.currentStep = info.case.stepIndex;\n }\n },\n },\n );\n\n const outcome = state.executionResult.cases[0];\n if (!outcome || outcome.status === 'not-run') {\n throw new Error(`Task \"${taskStatus.name}\" did not run.`);\n }\n if (outcome.status === 'failed') throw legacyYamlOutcomeError(outcome);\n\n this.reportFile = agent.reportFile;\n await this.flushUnstableLogContent();\n }\n\n async run() {\n return runInYamlExecutionContext(() => this.runInContext());\n }\n\n private async runInContext() {\n const startedAt = new Date();\n const runId = uuid();\n const state = getLegacyYamlPlayerState(this);\n state.executionResult = undefined;\n state.executionRecord = undefined;\n this.publicationErrors = [];\n const { android, ios, harmony, computer } = this.script;\n const webEnv = resolveWebTarget(this.script)?.target;\n const androidEnv = android;\n const iosEnv = ios;\n const harmonyEnv = harmony;\n const computerEnv = computer;\n const platform =\n webEnv || androidEnv || iosEnv || harmonyEnv || computerEnv;\n\n this.setPlayerStatus('running');\n\n let agent: Agent | null = null;\n let freeFn: FreeFn[] = [];\n let setupError: unknown;\n let executionError: unknown;\n let cleanupError: unknown;\n let signal: AbortSignal | undefined;\n let session: ReturnType<typeof enterYamlExecution> | undefined;\n try {\n const { agent: newAgent, freeFn: newFreeFn } = await this.setupAgent(\n platform as T,\n );\n // Register ownership immediately: discovering actions can fail too.\n agent = newAgent;\n session = enterYamlExecution(agent);\n freeFn = [...(newFreeFn || [])];\n agent._prepareForTestRunner?.();\n signal = this.abortSignal ?? currentYamlSignal(agent);\n signal?.throwIfAborted();\n this.actionSpace = await agent.getActionSpace();\n const originalOnTaskStartTip = agent.onTaskStartTip;\n agent.onTaskStartTip = (tip) => {\n if (this.status === 'running') this.agentStatusTip = tip;\n originalOnTaskStartTip?.(tip);\n };\n freeFn.push({\n name: 'restore-agent-onTaskStartTip',\n fn: () => {\n if (agent) agent.onTaskStartTip = originalOnTaskStartTip;\n },\n });\n } catch (error) {\n // A rejected borrower must not close or publish into another run's Agent.\n if (error instanceof YamlExecutionOwnershipError) throw error;\n setupError = error;\n this.setPlayerStatus('error', error as Error);\n }\n this.interfaceAgent = agent;\n\n const document = collectLegacyYamlDocument(\n this.script,\n this.scriptPath ?? '<inline-yaml>',\n this.actionSpace,\n );\n const runtime =\n agent && !setupError ? this.createRuntime(agent) : undefined;\n try {\n if (runtime && agent) {\n state.executionResult = await runtime.runScript(this.script, {\n document,\n signal,\n createDocumentRunId: () => runId,\n onCaseStart: (collectedCase) => {\n const taskIndex = collectedCase.caseIndex;\n this.setTaskIndex(taskIndex);\n return this.setTaskStatus(taskIndex, 'running');\n },\n onStepStart: (info) => {\n if (info.scope !== 'case' || info.case.phase !== 'steps') return;\n const taskStatus = this.taskStatusList[info.case.caseIndex];\n if (taskStatus) taskStatus.currentStep = info.case.stepIndex;\n },\n onCaseOutcome: async (outcome) => {\n if (outcome.status === 'not-run') return;\n const taskIndex = outcome.caseIndex;\n const taskStatus = this.taskStatusList[taskIndex];\n assert(taskStatus, `missing YAML task at index ${taskIndex}`);\n\n this.reportFile = agent?.reportFile;\n if (outcome.status === 'success') {\n await this.setTaskStatus(taskIndex, 'done');\n await this.flushUnstableLogContent();\n return;\n }\n\n const error = legacyYamlOutcomeError(outcome);\n await this.setTaskStatus(taskIndex, 'error', error);\n },\n });\n const stoppedOnFailure = state.executionResult.cases.some(\n (outcome) =>\n outcome.status === 'failed' &&\n (!this.taskStatusList[outcome.caseIndex]?.continueOnError ||\n isActionReadinessError(legacyYamlOutcomeError(outcome))),\n );\n this.setPlayerStatus(\n stoppedOnFailure || signal?.aborted ? 'error' : 'done',\n );\n }\n } catch (error) {\n executionError = error;\n if (error instanceof WorkflowExecutionFailure)\n state.executionResult = error.result as WorkflowDocumentExecutionResult;\n this.setPlayerStatus('error', error as Error);\n }\n\n this.reportFile = agent?.reportFile;\n this.agentStatusTip = '';\n\n try {\n // A timeout settles the Runner before an uncooperative device action.\n // Never dispose its Agent while that action is still using it.\n if (session?.isRoot && agent) {\n await cleanupResources([agent], () => runFreeFnCleanup(freeFn), {\n owner: this,\n signal,\n onDeferredError: (error) =>\n getDebug('yaml-player', { console: true })(\n `Deferred YAML cleanup failed: ${String(error)}`,\n ),\n });\n } else await runFreeFnCleanup(freeFn);\n } catch (error) {\n cleanupError = error;\n this.setPlayerStatus(\n 'error',\n (setupError ?? executionError ?? error) as Error,\n );\n }\n\n const endedAt = new Date();\n const cleanupErrors =\n cleanupError instanceof AggregateError\n ? cleanupError.errors\n : cleanupError === undefined\n ? []\n : [cleanupError];\n state.executionRecord = createLegacyYamlExecutionRecord({\n runId,\n attemptIndex: 0,\n script: this.script,\n document,\n startedAt,\n endedAt,\n execution: state.executionResult,\n setupError,\n executionError,\n cleanupErrors,\n aborted: signal?.aborted ?? false,\n publicationErrors: this.publicationErrors,\n outputs: this.result,\n reportFile: agent?.reportFile,\n children: session?.children,\n });\n let reportError: unknown;\n if (!session || session.isRoot) {\n try {\n const published = await publishLegacyYamlReport({\n agent,\n record: state.executionRecord,\n runId,\n script: this.script,\n scriptPath: this.scriptPath,\n fallbackReportFileName: state.fallbackReportFileName,\n });\n this.reportFile = published.reportFile;\n state.executionRecord = published.record;\n } catch (error) {\n reportError = error;\n this.setPlayerStatus(\n 'error',\n (setupError ?? executionError ?? cleanupError ?? error) as Error,\n );\n state.executionRecord = Object.freeze({\n ...state.executionRecord,\n status: 'failed',\n reportError: error,\n });\n }\n }\n session?.finish(state.executionRecord);\n // destroy() defers report finalization while YAML owns the Agent. Publish\n // cleanup outcomes and source snapshots before releasing its executions.\n if (agent?.destroyed && !hasActiveYamlExecution(agent)) {\n try {\n await agent.finalizeReport();\n } catch (error) {\n reportError = reportError\n ? new AggregateError(\n [reportError, error],\n 'YAML report publication failed',\n )\n : error;\n this.setPlayerStatus('error', reportError as Error);\n state.executionRecord = Object.freeze({\n ...state.executionRecord,\n status: 'failed',\n reportError,\n });\n }\n }\n if (reportError) {\n const errors = [\n setupError,\n executionError,\n ...cleanupErrors,\n reportError,\n ].filter((error) => error !== undefined);\n throw errors.length === 1\n ? reportError\n : new AggregateError(\n errors,\n 'YAML execution/report finalization failed',\n );\n }\n if (executionError && cleanupError) {\n throw new AggregateError(\n [executionError, ...cleanupErrors],\n 'YAML execution and cleanup failed',\n );\n }\n if (executionError) throw executionError;\n if (cleanupError) throw cleanupError;\n }\n}\n"],"names":["debug","getDebug","ScriptPlayer","key","value","keyToUse","status","error","taskIndex","taskIndexToNotify","taskStatus","index","statusValue","output","resolve","process","outputDir","dirname","mkdir","writeFile","JSON","undefined","content","filePath","path","write","cause","WorkflowPublicationError","agent","createLegacyYamlRuntime","flow","assert","statusIndex","declaredIndex","Number","state","getLegacyYamlPlayerState","currentYamlSignal","info","outcome","Error","legacyYamlOutcomeError","runInYamlExecutionContext","startedAt","Date","runId","uuid","android","ios","harmony","computer","webEnv","resolveWebTarget","androidEnv","iosEnv","harmonyEnv","computerEnv","platform","freeFn","setupError","executionError","cleanupError","signal","session","newAgent","newFreeFn","enterYamlExecution","originalOnTaskStartTip","tip","YamlExecutionOwnershipError","document","collectLegacyYamlDocument","runtime","collectedCase","stoppedOnFailure","isActionReadinessError","WorkflowExecutionFailure","cleanupResources","runFreeFnCleanup","String","endedAt","cleanupErrors","AggregateError","createLegacyYamlExecutionRecord","reportError","published","publishLegacyYamlReport","Object","hasActiveYamlExecution","errors","script","setupAgent","onTaskStatusChange","scriptPath","abortSignal","initializeLegacyYamlPlayerState","outputConfig","resolveYamlOutputConfig","ifInBrowser","ifInWorker","scriptName","basename","join","getMidsceneRunSubDir","task"],"mappings":"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"}
@@ -0,0 +1,73 @@
1
+ "use strict";
2
+ var __webpack_require__ = {};
3
+ (()=>{
4
+ __webpack_require__.d = (exports1, definition)=>{
5
+ for(var key in definition)if (__webpack_require__.o(definition, key) && !__webpack_require__.o(exports1, key)) Object.defineProperty(exports1, key, {
6
+ enumerable: true,
7
+ get: definition[key]
8
+ });
9
+ };
10
+ })();
11
+ (()=>{
12
+ __webpack_require__.o = (obj, prop)=>Object.prototype.hasOwnProperty.call(obj, prop);
13
+ })();
14
+ (()=>{
15
+ __webpack_require__.r = (exports1)=>{
16
+ if ('undefined' != typeof Symbol && Symbol.toStringTag) Object.defineProperty(exports1, Symbol.toStringTag, {
17
+ value: 'Module'
18
+ });
19
+ Object.defineProperty(exports1, '__esModule', {
20
+ value: true
21
+ });
22
+ };
23
+ })();
24
+ var __webpack_exports__ = {};
25
+ __webpack_require__.r(__webpack_exports__);
26
+ __webpack_require__.d(__webpack_exports__, {
27
+ withAgentDefaults: ()=>withAgentDefaults,
28
+ normalizeAgentOptions: ()=>normalizeAgentOptions
29
+ });
30
+ const agent_context_namespaceObject = require("@midscene/shared/agent-tools/agent-context");
31
+ const external_report_generator_js_namespaceObject = require("../report-generator.js");
32
+ function withAgentDefaults(opts) {
33
+ const options = Object.assign({
34
+ generateReport: true,
35
+ persistExecutionDump: false,
36
+ autoPrintReportMsg: true,
37
+ groupName: 'Midscene Report',
38
+ groupDescription: ''
39
+ }, opts || {});
40
+ (0, external_report_generator_js_namespaceObject.assertReportGenerationOptions)(options);
41
+ return options;
42
+ }
43
+ function normalizeAgentOptions(options, warn) {
44
+ if (void 0 !== options.aiContexts && ('object' != typeof options.aiContexts || null === options.aiContexts || Array.isArray(options.aiContexts))) throw new TypeError('opts.aiContexts must be a plain object');
45
+ for (const [key, value] of Object.entries(options.aiContexts ?? {})){
46
+ if (!(0, agent_context_namespaceObject.isAgentAIContextKey)(key)) throw new TypeError(`Unknown Agent context key: ${key}`);
47
+ if (void 0 !== value && 'string' != typeof value) throw new TypeError(`Agent context "${key}" must be a string`);
48
+ }
49
+ const deprecatedAiActContextOption = void 0 !== options.aiActContext ? 'aiActContext' : void 0 !== options.aiActionContext ? 'aiActionContext' : void 0;
50
+ if (deprecatedAiActContextOption) warn(`Agent option "${deprecatedAiActContextOption}" is deprecated; use "aiContexts.aiAct" instead. When both are provided, "aiContexts.aiAct" takes precedence.`);
51
+ const normalizedAIContexts = {
52
+ ...options.aiContexts
53
+ };
54
+ const resolvedAiActContext = normalizedAIContexts.aiAct ?? options.aiActContext ?? options.aiActionContext;
55
+ if (void 0 !== resolvedAiActContext) {
56
+ normalizedAIContexts.aiAct = resolvedAiActContext;
57
+ options.aiActContext = resolvedAiActContext;
58
+ options.aiActionContext = resolvedAiActContext;
59
+ }
60
+ options.aiContexts = normalizedAIContexts;
61
+ if (options.modelConfig && ('object' != typeof options.modelConfig || Array.isArray(options.modelConfig))) throw new Error(`opts.modelConfig must be a plain object map of env keys to values, but got ${typeof options.modelConfig}`);
62
+ }
63
+ exports.normalizeAgentOptions = __webpack_exports__.normalizeAgentOptions;
64
+ exports.withAgentDefaults = __webpack_exports__.withAgentDefaults;
65
+ for(var __rspack_i in __webpack_exports__)if (-1 === [
66
+ "normalizeAgentOptions",
67
+ "withAgentDefaults"
68
+ ].indexOf(__rspack_i)) exports[__rspack_i] = __webpack_exports__[__rspack_i];
69
+ Object.defineProperty(exports, '__esModule', {
70
+ value: true
71
+ });
72
+
73
+ //# sourceMappingURL=agent-options.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"agent/agent-options.js","sources":["webpack/runtime/define_property_getters","webpack/runtime/has_own_property","webpack/runtime/make_namespace_object","../../../src/agent/agent-options.ts"],"sourcesContent":["__webpack_require__.d = (exports, definition) => {\n\tfor(var key in definition) {\n if(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {\n Object.defineProperty(exports, key, { enumerable: true, get: definition[key] });\n }\n }\n};","__webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))","// define __esModule on exports\n__webpack_require__.r = (exports) => {\n\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n\t}\n\tObject.defineProperty(exports, '__esModule', { value: true });\n};","import { isAgentAIContextKey } from '@midscene/shared/agent-tools/agent-context';\nimport { assertReportGenerationOptions } from '../report-generator';\nimport type { AgentAIContexts, AgentOpt } from '../types';\n\nexport function withAgentDefaults(opts?: AgentOpt): AgentOpt {\n const options = Object.assign(\n {\n generateReport: true,\n persistExecutionDump: false,\n autoPrintReportMsg: true,\n groupName: 'Midscene Report',\n groupDescription: '',\n },\n opts || {},\n );\n assertReportGenerationOptions(options);\n return options;\n}\n\nexport function normalizeAgentOptions(\n options: AgentOpt,\n warn: (message: string) => void,\n): void {\n if (\n options.aiContexts !== undefined &&\n (typeof options.aiContexts !== 'object' ||\n options.aiContexts === null ||\n Array.isArray(options.aiContexts))\n ) {\n throw new TypeError('opts.aiContexts must be a plain object');\n }\n\n for (const [key, value] of Object.entries(options.aiContexts ?? {})) {\n if (!isAgentAIContextKey(key)) {\n throw new TypeError(`Unknown Agent context key: ${key}`);\n }\n if (value !== undefined && typeof value !== 'string') {\n throw new TypeError(`Agent context \"${key}\" must be a string`);\n }\n }\n\n const deprecatedAiActContextOption =\n options.aiActContext !== undefined\n ? 'aiActContext'\n : options.aiActionContext !== undefined\n ? 'aiActionContext'\n : undefined;\n if (deprecatedAiActContextOption) {\n warn(\n `Agent option \"${deprecatedAiActContextOption}\" is deprecated; use \"aiContexts.aiAct\" instead. When both are provided, \"aiContexts.aiAct\" takes precedence.`,\n );\n }\n\n const normalizedAIContexts: AgentAIContexts = { ...options.aiContexts };\n const resolvedAiActContext =\n normalizedAIContexts.aiAct ??\n options.aiActContext ??\n options.aiActionContext;\n if (resolvedAiActContext !== undefined) {\n normalizedAIContexts.aiAct = resolvedAiActContext;\n options.aiActContext = resolvedAiActContext;\n options.aiActionContext = resolvedAiActContext;\n }\n options.aiContexts = normalizedAIContexts;\n\n if (\n options.modelConfig &&\n (typeof options.modelConfig !== 'object' ||\n Array.isArray(options.modelConfig))\n ) {\n throw new Error(\n `opts.modelConfig must be a plain object map of env keys to values, but got ${typeof options.modelConfig}`,\n );\n }\n}\n"],"names":["__webpack_require__","definition","key","Object","obj","prop","Symbol","withAgentDefaults","opts","options","assertReportGenerationOptions","normalizeAgentOptions","warn","undefined","Array","TypeError","value","isAgentAIContextKey","deprecatedAiActContextOption","normalizedAIContexts","resolvedAiActContext","Error"],"mappings":";;;IAAAA,oBAAoB,CAAC,GAAG,CAAC,UAASC;QACjC,IAAI,IAAIC,OAAOD,WACR,IAAGD,oBAAoB,CAAC,CAACC,YAAYC,QAAQ,CAACF,oBAAoB,CAAC,CAAC,UAASE,MACzEC,OAAO,cAAc,CAAC,UAASD,KAAK;YAAE,YAAY;YAAM,KAAKD,UAAU,CAACC,IAAI;QAAC;IAGzF;;;ICNAF,oBAAoB,CAAC,GAAG,CAACI,KAAKC,OAAUF,OAAO,SAAS,CAAC,cAAc,CAAC,IAAI,CAACC,KAAKC;;;ICClFL,oBAAoB,CAAC,GAAG,CAAC;QACxB,IAAG,AAAkB,eAAlB,OAAOM,UAA0BA,OAAO,WAAW,EACrDH,OAAO,cAAc,CAAC,UAASG,OAAO,WAAW,EAAE;YAAE,OAAO;QAAS;QAEtEH,OAAO,cAAc,CAAC,UAAS,cAAc;YAAE,OAAO;QAAK;IAC5D;;;;;;;;;;ACFO,SAASI,kBAAkBC,IAAe;IAC/C,MAAMC,UAAUN,OAAO,MAAM,CAC3B;QACE,gBAAgB;QAChB,sBAAsB;QACtB,oBAAoB;QACpB,WAAW;QACX,kBAAkB;IACpB,GACAK,QAAQ,CAAC;IAEXE,IAAAA,6CAAAA,6BAAAA,AAAAA,EAA8BD;IAC9B,OAAOA;AACT;AAEO,SAASE,sBACdF,OAAiB,EACjBG,IAA+B;IAE/B,IACEH,AAAuBI,WAAvBJ,QAAQ,UAAU,IACjB,CAA8B,YAA9B,OAAOA,QAAQ,UAAU,IACxBA,AAAuB,SAAvBA,QAAQ,UAAU,IAClBK,MAAM,OAAO,CAACL,QAAQ,UAAU,IAElC,MAAM,IAAIM,UAAU;IAGtB,KAAK,MAAM,CAACb,KAAKc,MAAM,IAAIb,OAAO,OAAO,CAACM,QAAQ,UAAU,IAAI,CAAC,GAAI;QACnE,IAAI,CAACQ,AAAAA,IAAAA,8BAAAA,mBAAAA,AAAAA,EAAoBf,MACvB,MAAM,IAAIa,UAAU,CAAC,2BAA2B,EAAEb,KAAK;QAEzD,IAAIc,AAAUH,WAAVG,SAAuB,AAAiB,YAAjB,OAAOA,OAChC,MAAM,IAAID,UAAU,CAAC,eAAe,EAAEb,IAAI,kBAAkB,CAAC;IAEjE;IAEA,MAAMgB,+BACJT,AAAyBI,WAAzBJ,QAAQ,YAAY,GAChB,iBACAA,AAA4BI,WAA5BJ,QAAQ,eAAe,GACrB,oBACAI;IACR,IAAIK,8BACFN,KACE,CAAC,cAAc,EAAEM,6BAA6B,6GAA6G,CAAC;IAIhK,MAAMC,uBAAwC;QAAE,GAAGV,QAAQ,UAAU;IAAC;IACtE,MAAMW,uBACJD,qBAAqB,KAAK,IAC1BV,QAAQ,YAAY,IACpBA,QAAQ,eAAe;IACzB,IAAIW,AAAyBP,WAAzBO,sBAAoC;QACtCD,qBAAqB,KAAK,GAAGC;QAC7BX,QAAQ,YAAY,GAAGW;QACvBX,QAAQ,eAAe,GAAGW;IAC5B;IACAX,QAAQ,UAAU,GAAGU;IAErB,IACEV,QAAQ,WAAW,IAClB,CAA+B,YAA/B,OAAOA,QAAQ,WAAW,IACzBK,MAAM,OAAO,CAACL,QAAQ,WAAW,IAEnC,MAAM,IAAIY,MACR,CAAC,2EAA2E,EAAE,OAAOZ,QAAQ,WAAW,EAAE;AAGhH"}