@midscene/test 1.12.5 → 1.12.6-beta-20260909034232.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (40) hide show
  1. package/dist/es/1~891.mjs +1 -3
  2. package/dist/es/1~891.mjs.map +1 -1
  3. package/dist/es/android/index.mjs +71 -4
  4. package/dist/es/android/index.mjs.map +1 -1
  5. package/dist/es/cli/index.mjs +499 -25
  6. package/dist/es/cli/index.mjs.map +1 -1
  7. package/dist/es/harmony/index.mjs +71 -4
  8. package/dist/es/harmony/index.mjs.map +1 -1
  9. package/dist/es/index.mjs +478 -25
  10. package/dist/es/index.mjs.map +1 -1
  11. package/dist/es/ios/index.mjs +71 -4
  12. package/dist/es/ios/index.mjs.map +1 -1
  13. package/dist/es/midscene/index.mjs +71 -4
  14. package/dist/es/midscene/index.mjs.map +1 -1
  15. package/dist/es/test-cli.mjs +500 -25
  16. package/dist/es/test-cli.mjs.map +1 -1
  17. package/dist/lib/0~458.js +1 -3
  18. package/dist/lib/0~458.js.map +1 -1
  19. package/dist/lib/android/index.js +72 -4
  20. package/dist/lib/android/index.js.map +1 -1
  21. package/dist/lib/cli/index.js +499 -25
  22. package/dist/lib/cli/index.js.map +1 -1
  23. package/dist/lib/harmony/index.js +72 -4
  24. package/dist/lib/harmony/index.js.map +1 -1
  25. package/dist/lib/index.js +494 -26
  26. package/dist/lib/index.js.map +1 -1
  27. package/dist/lib/ios/index.js +72 -4
  28. package/dist/lib/ios/index.js.map +1 -1
  29. package/dist/lib/midscene/index.js +72 -4
  30. package/dist/lib/midscene/index.js.map +1 -1
  31. package/dist/lib/test-cli.js +500 -25
  32. package/dist/lib/test-cli.js.map +1 -1
  33. package/dist/types/android/index.d.ts +13 -0
  34. package/dist/types/cli/index.d.ts +25 -1
  35. package/dist/types/harmony/index.d.ts +13 -0
  36. package/dist/types/index.d.ts +91 -0
  37. package/dist/types/ios/index.d.ts +13 -0
  38. package/dist/types/midscene/index.d.ts +20 -1
  39. package/dist/types/playwright/index.d.ts +13 -0
  40. package/package.json +11 -10
@@ -2,6 +2,7 @@
2
2
  var __webpack_modules__ = {
3
3
  "./src/errors.ts" (__unused_rspack_module, __webpack_exports__, __webpack_require__) {
4
4
  __webpack_require__.d(__webpack_exports__, {
5
+ h2: ()=>NodeExecutionError,
5
6
  ww: ()=>NodeDefinitionError
6
7
  });
7
8
  function _define_property(obj, key, value) {
@@ -42,12 +43,26 @@ var __webpack_modules__ = {
42
43
  });
43
44
  }
44
45
  }
46
+ class NodeExecutionError extends WorkflowError {
47
+ constructor(node, cause){
48
+ const causeMessage = cause instanceof Error ? cause.message : String(cause ?? 'Unknown error');
49
+ super(`Node "${node}" failed: ${causeMessage}`, {
50
+ code: 'NODE_EXECUTION_ERROR',
51
+ details: {
52
+ node
53
+ },
54
+ cause
55
+ }), _define_property(this, "node", void 0);
56
+ this.node = node;
57
+ }
58
+ }
45
59
  },
46
60
  "./src/midscene/index.ts" (__unused_rspack_module, __webpack_exports__, __webpack_require__) {
47
61
  __webpack_require__.d(__webpack_exports__, {
48
62
  createAgentTestRunnerNodes: ()=>createAgentTestRunnerNodes
49
63
  });
50
64
  require("@midscene/core/agent/test-runner");
65
+ const logger_namespaceObject = require("@midscene/shared/logger");
51
66
  const v4_namespaceObject = require("zod/v4");
52
67
  var errors = __webpack_require__("./src/errors.ts");
53
68
  const validateOptionalText = (value, field, node)=>{
@@ -97,7 +112,54 @@ var __webpack_modules__ = {
97
112
  'min'
98
113
  ]).default('ms').describe('Duration unit: milliseconds, seconds, or minutes.')
99
114
  });
100
- const createAgentTestRunnerNodes = (definitions, getAgent)=>definitions.map((definition)=>define_node_defineNode({
115
+ const createAgentTestRunnerNodes = (definitions, getAgent)=>{
116
+ const activeAgentCalls = new WeakMap();
117
+ const runAgentCall = async (node, ctx, agent, call, captureExecutions = true)=>{
118
+ const scopeId = 'case' === ctx.scope ? ctx.case.runId : ctx.document.documentRunId;
119
+ const activeCall = activeAgentCalls.get(agent);
120
+ if (activeCall) throw new errors.h2(node, new Error(`The same Agent instance cannot execute overlapping Midscene Test Steps. Active scope: ${activeCall.scopeId} (${activeCall.node}); requested scope: ${scopeId} (${node}).`));
121
+ activeAgentCalls.set(agent, {
122
+ scopeId,
123
+ node
124
+ });
125
+ let removeListener;
126
+ let sawExecutionWithoutId = false;
127
+ const stopListening = ()=>{
128
+ const remove = removeListener;
129
+ removeListener = void 0;
130
+ remove?.();
131
+ };
132
+ const stopListeningOnAbort = ()=>stopListening();
133
+ try {
134
+ if (captureExecutions && agent.addDumpUpdateListener) {
135
+ removeListener = agent.addDumpUpdateListener((_dump, execution)=>{
136
+ if (!execution) return;
137
+ if (!execution.id) {
138
+ sawExecutionWithoutId = true;
139
+ return;
140
+ }
141
+ ctx.report.addTrace({
142
+ type: 'midscene-execution',
143
+ executionId: execution.id
144
+ });
145
+ });
146
+ if (ctx.signal.aborted) stopListening();
147
+ else ctx.signal.addEventListener('abort', stopListeningOnAbort, {
148
+ once: true
149
+ });
150
+ }
151
+ return await call();
152
+ } finally{
153
+ ctx.signal.removeEventListener('abort', stopListeningOnAbort);
154
+ try {
155
+ stopListening();
156
+ } finally{
157
+ activeAgentCalls.delete(agent);
158
+ }
159
+ if (sawExecutionWithoutId) warnReportTrace(`Skipped a report trace without a stable execution id for ${node} in scope ${scopeId}.`);
160
+ }
161
+ };
162
+ return definitions.map((definition)=>define_node_defineNode({
101
163
  name: definition.name,
102
164
  ...void 0 === definition.title ? {} : {
103
165
  title: definition.title
@@ -111,11 +173,17 @@ var __webpack_modules__ = {
111
173
  inputSchema: definition.inputSchema,
112
174
  async execute (ctx) {
113
175
  const agent = await getAgent(ctx);
114
- return definition.execute(agent, ctx.input, {
115
- signal: ctx.signal
116
- });
176
+ const call = async ()=>definition.execute(agent, ctx.input, {
177
+ signal: ctx.signal
178
+ });
179
+ if ('object' != typeof agent || null === agent) return call();
180
+ return runAgentCall(definition.name, ctx, agent, call);
117
181
  }
118
182
  }));
183
+ };
184
+ const warnReportTrace = (0, logger_namespaceObject.getDebug)('test-runner:report-trace', {
185
+ console: true
186
+ });
119
187
  }
120
188
  };
121
189
  var __webpack_module_cache__ = {};
@@ -1 +1 @@
1
- {"version":3,"file":"ios/index.js","sources":["../../../src/errors.ts","../../../src/node/define-node.ts","../../../src/midscene/index.ts","webpack/runtime/define_property_getters","webpack/runtime/has_own_property","webpack/runtime/make_namespace_object","../../../src/ios/index.ts"],"sourcesContent":["import type { z } from 'zod/v4';\n\nexport interface WorkflowErrorOptions {\n code?: string;\n details?: unknown;\n cause?: unknown;\n}\n\nexport class WorkflowError extends Error {\n readonly code: string;\n readonly details?: unknown;\n\n constructor(message: string, options: WorkflowErrorOptions = {}) {\n super(message, { cause: options.cause });\n this.name = new.target.name;\n this.code = options.code ?? 'WORKFLOW_ERROR';\n this.details = options.details;\n }\n\n toJSON(): Record<string, unknown> {\n return {\n name: this.name,\n message: this.message,\n code: this.code,\n ...(this.details === undefined ? {} : { details: this.details }),\n };\n }\n}\n\nexport class WorkflowParseError extends WorkflowError {\n constructor(message: string, details?: unknown, cause?: unknown) {\n super(message, { code: 'WORKFLOW_PARSE_ERROR', details, cause });\n }\n}\n\nexport class NodeDefinitionError extends WorkflowError {\n constructor(message: string, details?: unknown) {\n super(message, { code: 'NODE_DEFINITION_ERROR', details });\n }\n}\n\nexport class DuplicateNodeError extends WorkflowError {\n readonly node: string;\n\n constructor(node: string) {\n super(`Node \"${node}\" is already registered.`, {\n code: 'DUPLICATE_NODE',\n details: { node },\n });\n this.node = node;\n }\n}\n\nexport class NodeNotFoundError extends WorkflowError {\n readonly node: string;\n\n constructor(node: string) {\n super(`Node \"${node}\" is not registered.`, {\n code: 'NODE_NOT_FOUND',\n details: { node },\n });\n this.node = node;\n }\n}\n\nexport class NodeInputValidationError extends WorkflowError {\n constructor(message: string, details?: unknown) {\n super(message, { code: 'NODE_INPUT_VALIDATION_ERROR', details });\n }\n\n static fromZod(node: string, error: z.ZodError): NodeInputValidationError {\n const issues = error.issues.map((issue) => ({\n code: issue.code,\n path: issue.path.map(String).join('.'),\n message: issue.message,\n }));\n const firstIssue = issues[0];\n const path = firstIssue?.path || '<root>';\n const message = firstIssue?.message ?? 'invalid input';\n return new NodeInputValidationError(\n `Node \"${node}\" input validation failed at \"${path}\": ${message}`,\n { node, issues },\n );\n }\n}\n\nexport class StepTimeoutError extends WorkflowError {\n readonly timeoutMs: number;\n readonly node?: string;\n\n constructor(timeoutMs: number, node?: string) {\n super(\n node\n ? `Node \"${node}\" timed out after ${timeoutMs}ms.`\n : `Step timed out after ${timeoutMs}ms.`,\n {\n code: 'STEP_TIMEOUT',\n details: { timeoutMs, ...(node === undefined ? {} : { node }) },\n },\n );\n this.timeoutMs = timeoutMs;\n this.node = node;\n }\n}\n\nexport class NodeExecutionError extends WorkflowError {\n readonly node: string;\n\n constructor(node: string, cause: unknown) {\n const causeMessage =\n cause instanceof Error ? cause.message : String(cause ?? 'Unknown error');\n super(`Node \"${node}\" failed: ${causeMessage}`, {\n code: 'NODE_EXECUTION_ERROR',\n details: { node },\n cause,\n });\n this.node = node;\n }\n}\n\nexport class WorkflowLifecycleError extends WorkflowError {\n constructor(message: string, details?: unknown) {\n super(message, { code: 'WORKFLOW_LIFECYCLE_ERROR', details });\n }\n}\n\nexport class ProjectSetupError extends WorkflowError {\n constructor(cause: unknown, details: { projectName: string }) {\n const causeMessage =\n cause instanceof Error ? cause.message : String(cause ?? 'Unknown error');\n super(`Project \"${details.projectName}\" setup failed: ${causeMessage}`, {\n code: 'PROJECT_SETUP_ERROR',\n details,\n cause,\n });\n }\n}\n\nexport class ProjectTeardownError extends WorkflowError {\n constructor(\n cause: unknown,\n details: { projectName: string; registrationIndex: number },\n ) {\n const causeMessage =\n cause instanceof Error ? cause.message : String(cause ?? 'Unknown error');\n super(`Project \"${details.projectName}\" teardown failed: ${causeMessage}`, {\n code: 'PROJECT_TEARDOWN_ERROR',\n details,\n cause,\n });\n }\n}\n\nexport class NodeScopeTeardownError extends WorkflowError {\n constructor(\n cause: unknown,\n details: {\n scope: 'case' | 'document';\n scopeId: string;\n node: string;\n registrationIndex: number;\n },\n ) {\n const causeMessage =\n cause instanceof Error ? cause.message : String(cause ?? 'Unknown error');\n super(\n `${details.scope === 'case' ? 'Case attempt' : 'Workflow document'} node teardown failed for \"${details.node}\": ${causeMessage}`,\n { code: 'NODE_SCOPE_TEARDOWN_ERROR', details, cause },\n );\n }\n}\n\nexport class FatalDeviceError extends WorkflowError {\n constructor(message: string, cause?: unknown) {\n super(message, { code: 'FATAL_DEVICE_ERROR', cause });\n }\n}\n\nexport const isFatalDeviceError = (error: unknown): boolean => {\n if (error instanceof FatalDeviceError) return true;\n if (error instanceof WorkflowError && error.code === 'FATAL_DEVICE_ERROR') {\n return true;\n }\n if (\n error instanceof Error &&\n /device offline|device not found|(?:adb|bdc|device) connection (?:was )?closed/i.test(\n error.message,\n )\n ) {\n return true;\n }\n return error instanceof Error && error.cause !== undefined\n ? isFatalDeviceError(error.cause)\n : false;\n};\n\nexport class CaseExecutionError extends WorkflowError {\n readonly result: import('./engine/types').CaseRunResult;\n\n constructor(result: import('./engine/types').CaseRunResult) {\n super(`Case \"${result.name}\" failed.`, {\n code: 'CASE_EXECUTION_FAILED',\n details: { caseId: result.caseId, runId: result.runId },\n });\n this.result = result;\n }\n}\n\nexport class WorkflowDocumentExecutionError extends WorkflowError {\n readonly result: import('./engine/types').WorkflowDocumentRunResult;\n\n constructor(result: import('./engine/types').WorkflowDocumentRunResult) {\n super(`Workflow document \"${result.sourcePath}\" failed.`, {\n code: 'WORKFLOW_DOCUMENT_EXECUTION_FAILED',\n details: {\n documentId: result.documentId,\n documentRunId: result.documentRunId,\n },\n });\n this.result = result;\n }\n}\n\nexport function normalizeNodeExecutionError(\n error: unknown,\n node: string,\n): WorkflowError {\n return error instanceof WorkflowError\n ? error\n : new NodeExecutionError(node, error);\n}\n","import { z } from 'zod/v4';\nimport { NodeDefinitionError } from '../errors';\nimport type {\n DefineNodeOptions,\n DefineNodeWithSchemaOptions,\n NodeDefinition,\n NodeDefinitionWithSchema,\n NodeInputSchema,\n} from './types';\n\nconst validateOptionalText = (\n value: unknown,\n field: 'title' | 'description',\n node: string,\n): void => {\n if (\n value !== undefined &&\n (typeof value !== 'string' || value.trim().length === 0)\n ) {\n throw new NodeDefinitionError(\n `Node \"${node}\" ${field} must be a non-empty string.`,\n { node, field },\n );\n }\n};\n\nconst validateInputSchema = (schema: unknown, node: string): void => {\n if (schema === undefined) return;\n if (!(schema instanceof z.ZodObject)) {\n throw new NodeDefinitionError(\n `Node \"${node}\" inputSchema must be a Zod object schema.`,\n { node, field: 'inputSchema' },\n );\n }\n if ('$' in schema.shape) {\n throw new NodeDefinitionError(\n `Node \"${node}\" inputSchema must not declare \"$\" as an input property.`,\n { node, field: 'inputSchema.$' },\n );\n }\n};\n\nconst validateDefinition = (options: {\n name: string;\n title?: unknown;\n description?: unknown;\n stringInputKey?: unknown;\n inputSchema?: unknown;\n execute: unknown;\n}): void => {\n if (!options || typeof options !== 'object') {\n throw new NodeDefinitionError('Node definition must be an object.');\n }\n\n if (typeof options.name !== 'string' || options.name.trim().length === 0) {\n throw new NodeDefinitionError('Node name must be a non-empty string.');\n }\n\n validateOptionalText(options.title, 'title', options.name);\n validateOptionalText(options.description, 'description', options.name);\n if (\n options.stringInputKey !== undefined &&\n options.stringInputKey !== false &&\n (typeof options.stringInputKey !== 'string' ||\n options.stringInputKey.trim().length === 0)\n ) {\n throw new NodeDefinitionError(\n `Node \"${options.name}\" stringInputKey must be a non-empty string or false.`,\n { node: options.name, field: 'stringInputKey' },\n );\n }\n validateInputSchema(options.inputSchema, options.name);\n\n if (\n typeof options.stringInputKey === 'string' &&\n options.inputSchema instanceof z.ZodObject &&\n !(options.stringInputKey in options.inputSchema.shape)\n ) {\n throw new NodeDefinitionError(\n `Node \"${options.name}\" stringInputKey must reference a field in inputSchema.`,\n { node: options.name, field: 'stringInputKey' },\n );\n }\n\n if (typeof options.execute !== 'function') {\n throw new NodeDefinitionError(\n `Node \"${options.name}\" must provide an execute function.`,\n { node: options.name },\n );\n }\n};\n\nexport function defineNode<\n TSchema extends NodeInputSchema,\n TData = unknown,\n TContext = unknown,\n>(\n options: DefineNodeWithSchemaOptions<TSchema, TData, TContext>,\n): NodeDefinitionWithSchema<TSchema, TData, TContext>;\n\nexport function defineNode<\n TInput = unknown,\n TData = unknown,\n TContext = unknown,\n>(\n options: DefineNodeOptions<TInput, TData, TContext>,\n): NodeDefinition<TInput, TData, TContext>;\n\nexport function defineNode(\n options: DefineNodeOptions<any, any, any>,\n): NodeDefinition<any, any, any> {\n validateDefinition(options);\n return options;\n}\n","import {\n type AgentTestRunnerNodeDefinition,\n type AgentTestRunnerNodeProvider,\n type CommonAgentTestRunnerApi,\n aiActInputSchema,\n aiActOptionsInputSchema,\n aiAssertInputSchema,\n aiAssertOptionsInputSchema,\n aiTapInputSchema,\n insightInputSchema,\n insightOptionsInputSchema,\n locateOptionsInputSchema,\n promptImageInputSchema,\n recordToReportInputSchema,\n recordToReportOptionsInputSchema,\n reportScreenshotInputSchema,\n structuredUserPromptInputSchema,\n userPromptInputSchema,\n} from '@midscene/core/agent/test-runner';\nimport { z } from 'zod/v4';\nimport type { Awaitable } from '../engine/types';\nimport { NodeDefinitionError } from '../errors';\nimport { defineNode } from '../node/define-node';\nimport type { NodeDefinition, NodeExecutionContext } from '../node/types';\n\nexport type MidsceneUIAgent = CommonAgentTestRunnerApi;\n\nexport {\n aiActInputSchema,\n aiActOptionsInputSchema,\n aiAssertInputSchema,\n aiAssertOptionsInputSchema,\n aiTapInputSchema,\n insightInputSchema,\n insightOptionsInputSchema,\n locateOptionsInputSchema,\n promptImageInputSchema,\n recordToReportInputSchema,\n recordToReportOptionsInputSchema,\n reportScreenshotInputSchema,\n structuredUserPromptInputSchema,\n userPromptInputSchema,\n};\n\nexport interface AgentProvider<TContext> {\n getAgent(\n runId: string,\n ctx: NodeExecutionContext<unknown, TContext>,\n ): Awaitable<MidsceneUIAgent>;\n // biome-ignore lint/suspicious/noConfusingVoidType: providers without a report intentionally return void.\n releaseAgent?(runId: string): Awaitable<AgentReleaseResult | void>;\n dispose?(): Awaitable<void>;\n}\n\nexport interface AgentReleaseResult {\n /** Absolute path to the finalized report for this Agent scope. */\n reportPath?: string;\n}\n\nexport const waitInputSchema = z.strictObject({\n duration: z.number().positive().describe('How long to wait.'),\n unit: z\n .enum(['ms', 's', 'min'])\n .default('ms')\n .describe('Duration unit: milliseconds, seconds, or minutes.'),\n});\n\nexport type AiActNodeInput = z.infer<typeof aiActInputSchema>;\nexport type AiAssertNodeInput = z.infer<typeof aiAssertInputSchema>;\nexport type AiTapNodeInput = z.infer<typeof aiTapInputSchema>;\nexport type InsightNodeInput = z.infer<typeof insightInputSchema>;\nexport type RecordToReportNodeInput = z.infer<typeof recordToReportInputSchema>;\nexport type WaitNodeInput = z.infer<typeof waitInputSchema>;\n\nexport interface CreateMidsceneNodesOptions<TContext> {\n getAgent?(\n ctx: NodeExecutionContext<unknown, TContext>,\n ): Awaitable<MidsceneUIAgent>;\n agentProvider?: AgentProvider<TContext>;\n /** Agent class that declares the Agent-backed Nodes to register. */\n agentClass: AgentTestRunnerNodeProvider;\n}\n\nconst waitFor = async (durationMs: number, signal: AbortSignal) => {\n if (signal.aborted) {\n throw signal.reason ?? new Error('Wait aborted.');\n }\n await new Promise<void>((resolve, reject) => {\n const timeout = setTimeout(() => {\n signal.removeEventListener('abort', abort);\n resolve();\n }, durationMs);\n const abort = () => {\n clearTimeout(timeout);\n reject(signal.reason ?? new Error('Wait aborted.'));\n };\n signal.addEventListener('abort', abort, { once: true });\n });\n};\n\n/** Adapt Agent-owned descriptions to executable Midscene Test Nodes. */\nexport const createAgentTestRunnerNodes = <TContext>(\n definitions: readonly AgentTestRunnerNodeDefinition[],\n getAgent: (\n ctx: NodeExecutionContext<unknown, TContext>,\n ) => Awaitable<unknown>,\n): readonly NodeDefinition<any, any, TContext>[] =>\n definitions.map((definition) =>\n defineNode({\n name: definition.name,\n ...(definition.title === undefined ? {} : { title: definition.title }),\n ...(definition.description === undefined\n ? {}\n : { description: definition.description }),\n ...(definition.stringInputKey === undefined\n ? {}\n : { stringInputKey: definition.stringInputKey }),\n inputSchema: definition.inputSchema,\n async execute(ctx) {\n const agent = await getAgent(ctx);\n return definition.execute(agent, ctx.input, {\n signal: ctx.signal,\n });\n },\n }),\n );\n\nexport function createMidsceneNodes<TContext>(\n options: CreateMidsceneNodesOptions<TContext>,\n): readonly NodeDefinition<any, any, TContext>[] {\n if (!options || typeof options !== 'object') {\n throw new NodeDefinitionError(\n 'createMidsceneNodes() options must be an object.',\n );\n }\n if (\n typeof options.agentProvider?.getAgent !== 'function' &&\n typeof options.getAgent !== 'function'\n ) {\n throw new NodeDefinitionError(\n 'createMidsceneNodes() requires getAgent or agentProvider.getAgent.',\n );\n }\n if (\n !options.agentClass ||\n typeof options.agentClass.getTestRunnerNodeDefinitions !== 'function'\n ) {\n throw new NodeDefinitionError(\n 'createMidsceneNodes() requires agentClass.getTestRunnerNodeDefinitions().',\n );\n }\n\n const registeredAgentScopes = new Set<string>();\n const getExecutionId = (ctx: NodeExecutionContext<unknown, TContext>) =>\n ctx.scope === 'case' ? ctx.case.runId : ctx.document.documentRunId;\n const getAgent = async (\n ctx: NodeExecutionContext<unknown, TContext>,\n ): Promise<MidsceneUIAgent> => {\n if (!options.agentProvider) return options.getAgent!(ctx);\n const runId = getExecutionId(ctx);\n if (\n options.agentProvider.releaseAgent &&\n !registeredAgentScopes.has(runId)\n ) {\n registeredAgentScopes.add(runId);\n ctx.onTeardown(async () => {\n try {\n const released = await options.agentProvider!.releaseAgent!(runId);\n return released?.reportPath\n ? { reportPaths: [released.reportPath] }\n : undefined;\n } finally {\n registeredAgentScopes.delete(runId);\n }\n });\n }\n return options.agentProvider.getAgent(runId, ctx);\n };\n\n const agentDefinitions = options.agentClass.getTestRunnerNodeDefinitions();\n\n return [\n ...createAgentTestRunnerNodes(agentDefinitions, getAgent),\n defineNode<typeof waitInputSchema, unknown, TContext>({\n name: 'wait',\n description: 'Wait for a fixed duration while honoring cancellation.',\n stringInputKey: false,\n inputSchema: waitInputSchema,\n async execute(ctx) {\n const multiplier =\n ctx.input.unit === 'min'\n ? 60_000\n : ctx.input.unit === 's'\n ? 1_000\n : 1;\n const durationMs = ctx.input.duration * multiplier;\n await waitFor(durationMs, ctx.signal);\n return { summary: `Waited ${durationMs}ms` };\n },\n }),\n ];\n}\n","__webpack_require__.d = (exports, definition) => {\n\tfor(var key in definition) {\n if(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {\n Object.defineProperty(exports, key, { enumerable: true, get: definition[key] });\n }\n }\n};","__webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))","// define __esModule on exports\n__webpack_require__.r = (exports) => {\n\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n\t}\n\tObject.defineProperty(exports, '__esModule', { value: true });\n};","import type { IOSAgent } from '@midscene/ios';\nimport {\n iosAgentTestRunnerNodeDefinitions,\n launchInputSchema,\n runWdaRequestInputSchema,\n terminateInputSchema,\n wdaRequestInputSchema,\n} from '@midscene/ios/test-runner';\nexport type {\n LaunchNodeInput,\n RunWdaRequestNodeInput,\n TerminateNodeInput,\n WDAHttpMethod,\n} from '@midscene/ios/test-runner';\nimport type { Awaitable } from '../engine/types';\nimport { NodeDefinitionError } from '../errors';\nimport { createAgentTestRunnerNodes } from '../midscene';\nimport type { NodeDefinition, NodeExecutionContext } from '../node/types';\n\nexport {\n launchInputSchema,\n runWdaRequestInputSchema,\n terminateInputSchema,\n wdaRequestInputSchema,\n};\n\nexport type IOSRunnerAgent = Pick<\n IOSAgent,\n 'launch' | 'terminate' | 'runWdaRequest' | 'home' | 'appSwitcher'\n>;\n\nexport interface CreateIOSNodesOptions<TContext> {\n getAgent(\n ctx: NodeExecutionContext<unknown, TContext>,\n ): Awaitable<IOSRunnerAgent>;\n}\n\nexport function createIOSNodes<TContext>(\n options: CreateIOSNodesOptions<TContext>,\n): readonly NodeDefinition<any, any, TContext>[] {\n if (!options || typeof options !== 'object') {\n throw new NodeDefinitionError(\n 'createIOSNodes() options must be an object.',\n );\n }\n if (typeof options.getAgent !== 'function') {\n throw new NodeDefinitionError('createIOSNodes() requires getAgent().');\n }\n\n return createAgentTestRunnerNodes(\n iosAgentTestRunnerNodeDefinitions,\n options.getAgent,\n );\n}\n"],"names":["WorkflowError","Error","undefined","message","options","NodeDefinitionError","details","validateOptionalText","value","field","node","validateInputSchema","schema","z","validateDefinition","defineNode","createAgentTestRunnerNodes","definitions","getAgent","definition","ctx","agent","__webpack_require__","key","Object","obj","prop","Symbol","createIOSNodes","iosAgentTestRunnerNodeDefinitions"],"mappings":";;;;;;;;;;;;;;;;QAQO,MAAMA,sBAAsBC;YAWjC,SAAkC;gBAChC,OAAO;oBACL,MAAM,IAAI,CAAC,IAAI;oBACf,SAAS,IAAI,CAAC,OAAO;oBACrB,MAAM,IAAI,CAAC,IAAI;oBACf,GAAI,AAAiBC,WAAjB,IAAI,CAAC,OAAO,GAAiB,CAAC,IAAI;wBAAE,SAAS,IAAI,CAAC,OAAO;oBAAC,CAAC;gBACjE;YACF;YAdA,YAAYC,OAAe,EAAEC,UAAgC,CAAC,CAAC,CAAE;gBAC/D,KAAK,CAACD,SAAS;oBAAE,OAAOC,QAAQ,KAAK;gBAAC,IAJxC,uBAAS,QAAT,SACA,uBAAS,WAAT;gBAIE,IAAI,CAAC,IAAI,GAAG,WAAW,IAAI;gBAC3B,IAAI,CAAC,IAAI,GAAGA,QAAQ,IAAI,IAAI;gBAC5B,IAAI,CAAC,OAAO,GAAGA,QAAQ,OAAO;YAChC;QAUF;QAQO,MAAMC,4BAA4BL;YACvC,YAAYG,OAAe,EAAEG,OAAiB,CAAE;gBAC9C,KAAK,CAACH,SAAS;oBAAE,MAAM;oBAAyBG;gBAAQ;YAC1D;QACF;;;;;;;;;QC7BA,MAAMC,uBAAuB,CAC3BC,OACAC,OACAC;YAEA,IACEF,AAAUN,WAAVM,SACC,CAAiB,YAAjB,OAAOA,SAAsBA,AAAwB,MAAxBA,MAAM,IAAI,GAAG,MAAM,AAAK,GAEtD,MAAM,IAAIH,OAAAA,EAAmBA,CAC3B,CAAC,MAAM,EAAEK,KAAK,EAAE,EAAED,MAAM,4BAA4B,CAAC,EACrD;gBAAEC;gBAAMD;YAAM;QAGpB;QAEA,MAAME,sBAAsB,CAACC,QAAiBF;YAC5C,IAAIE,AAAWV,WAAXU,QAAsB;YAC1B,IAAI,CAAEA,CAAAA,kBAAkBC,mBAAAA,CAAAA,CAAAA,SAAU,AAAVA,GACtB,MAAM,IAAIR,OAAAA,EAAmBA,CAC3B,CAAC,MAAM,EAAEK,KAAK,0CAA0C,CAAC,EACzD;gBAAEA;gBAAM,OAAO;YAAc;YAGjC,IAAI,OAAOE,OAAO,KAAK,EACrB,MAAM,IAAIP,OAAAA,EAAmBA,CAC3B,CAAC,MAAM,EAAEK,KAAK,wDAAwD,CAAC,EACvE;gBAAEA;gBAAM,OAAO;YAAgB;QAGrC;QAEA,MAAMI,qBAAqB,CAACV;YAQ1B,IAAI,CAACA,WAAW,AAAmB,YAAnB,OAAOA,SACrB,MAAM,IAAIC,OAAAA,EAAmBA,CAAC;YAGhC,IAAI,AAAwB,YAAxB,OAAOD,QAAQ,IAAI,IAAiBA,AAA+B,MAA/BA,QAAQ,IAAI,CAAC,IAAI,GAAG,MAAM,EAChE,MAAM,IAAIC,OAAAA,EAAmBA,CAAC;YAGhCE,qBAAqBH,QAAQ,KAAK,EAAE,SAASA,QAAQ,IAAI;YACzDG,qBAAqBH,QAAQ,WAAW,EAAE,eAAeA,QAAQ,IAAI;YACrE,IACEA,AAA2BF,WAA3BE,QAAQ,cAAc,IACtBA,AAA2B,UAA3BA,QAAQ,cAAc,IACrB,CAAkC,YAAlC,OAAOA,QAAQ,cAAc,IAC5BA,AAAyC,MAAzCA,QAAQ,cAAc,CAAC,IAAI,GAAG,MAAM,AAAK,GAE3C,MAAM,IAAIC,OAAAA,EAAmBA,CAC3B,CAAC,MAAM,EAAED,QAAQ,IAAI,CAAC,qDAAqD,CAAC,EAC5E;gBAAE,MAAMA,QAAQ,IAAI;gBAAE,OAAO;YAAiB;YAGlDO,oBAAoBP,QAAQ,WAAW,EAAEA,QAAQ,IAAI;YAErD,IACE,AAAkC,YAAlC,OAAOA,QAAQ,cAAc,IAC7BA,QAAQ,WAAW,YAAYS,mBAAAA,CAAAA,CAAAA,SAAW,IAC1C,CAAET,CAAAA,QAAQ,cAAc,IAAIA,QAAQ,WAAW,CAAC,KAAI,GAEpD,MAAM,IAAIC,OAAAA,EAAmBA,CAC3B,CAAC,MAAM,EAAED,QAAQ,IAAI,CAAC,uDAAuD,CAAC,EAC9E;gBAAE,MAAMA,QAAQ,IAAI;gBAAE,OAAO;YAAiB;YAIlD,IAAI,AAA2B,cAA3B,OAAOA,QAAQ,OAAO,EACxB,MAAM,IAAIC,OAAAA,EAAmBA,CAC3B,CAAC,MAAM,EAAED,QAAQ,IAAI,CAAC,mCAAmC,CAAC,EAC1D;gBAAE,MAAMA,QAAQ,IAAI;YAAC;QAG3B;QAkBO,SAASW,uBACdX,OAAyC;YAEzCU,mBAAmBV;YACnB,OAAOA;QACT;QCtD+BS,mBAAAA,CAAAA,CAAAA,YAAc,CAAC;YAC5C,UAAUA,mBAAAA,CAAAA,CAAAA,MAAQ,GAAG,QAAQ,GAAG,QAAQ,CAAC;YACzC,MAAMA,mBAAAA,CAAAA,CAAAA,OACC,CAAC;gBAAC;gBAAM;gBAAK;aAAM,EACvB,OAAO,CAAC,MACR,QAAQ,CAAC;QACd;QAoCO,MAAMG,6BAA6B,CACxCC,aACAC,WAIAD,YAAY,GAAG,CAAC,CAACE,aACfJ,uBAAW;oBACT,MAAMI,WAAW,IAAI;oBACrB,GAAIA,AAAqBjB,WAArBiB,WAAW,KAAK,GAAiB,CAAC,IAAI;wBAAE,OAAOA,WAAW,KAAK;oBAAC,CAAC;oBACrE,GAAIA,AAA2BjB,WAA3BiB,WAAW,WAAW,GACtB,CAAC,IACD;wBAAE,aAAaA,WAAW,WAAW;oBAAC,CAAC;oBAC3C,GAAIA,AAA8BjB,WAA9BiB,WAAW,cAAc,GACzB,CAAC,IACD;wBAAE,gBAAgBA,WAAW,cAAc;oBAAC,CAAC;oBACjD,aAAaA,WAAW,WAAW;oBACnC,MAAM,SAAQC,GAAG;wBACf,MAAMC,QAAQ,MAAMH,SAASE;wBAC7B,OAAOD,WAAW,OAAO,CAACE,OAAOD,IAAI,KAAK,EAAE;4BAC1C,QAAQA,IAAI,MAAM;wBACpB;oBACF;gBACF;;;;;;;;;;;;;;IC5HJE,oBAAoB,CAAC,GAAG,CAAC,UAASH;QACjC,IAAI,IAAII,OAAOJ,WACR,IAAGG,oBAAoB,CAAC,CAACH,YAAYI,QAAQ,CAACD,oBAAoB,CAAC,CAAC,UAASC,MACzEC,OAAO,cAAc,CAAC,UAASD,KAAK;YAAE,YAAY;YAAM,KAAKJ,UAAU,CAACI,IAAI;QAAC;IAGzF;;;ICNAD,oBAAoB,CAAC,GAAG,CAACG,KAAKC,OAAUF,OAAO,SAAS,CAAC,cAAc,CAAC,IAAI,CAACC,KAAKC;;;ICClFJ,oBAAoB,CAAC,GAAG,CAAC;QACxB,IAAG,AAAkB,eAAlB,OAAOK,UAA0BA,OAAO,WAAW,EACrDH,OAAO,cAAc,CAAC,UAASG,OAAO,WAAW,EAAE;YAAE,OAAO;QAAS;QAEtEH,OAAO,cAAc,CAAC,UAAS,cAAc;YAAE,OAAO;QAAK;IAC5D;;;;;;;;;;;;;;;IC+BO,SAASI,eACdxB,OAAwC;QAExC,IAAI,CAACA,WAAW,AAAmB,YAAnB,OAAOA,SACrB,MAAM,IAAIC,OAAAA,EAAmBA,CAC3B;QAGJ,IAAI,AAA4B,cAA5B,OAAOD,QAAQ,QAAQ,EACzB,MAAM,IAAIC,OAAAA,EAAmBA,CAAC;QAGhC,OAAOW,AAAAA,IAAAA,SAAAA,0BAAAA,AAAAA,EACLa,4BAAAA,iCAAiCA,EACjCzB,QAAQ,QAAQ;IAEpB"}
1
+ {"version":3,"file":"ios/index.js","sources":["../../../src/errors.ts","../../../src/node/define-node.ts","../../../src/midscene/index.ts","webpack/runtime/define_property_getters","webpack/runtime/has_own_property","webpack/runtime/make_namespace_object","../../../src/ios/index.ts"],"sourcesContent":["import type { z } from 'zod/v4';\n\nexport interface WorkflowErrorOptions {\n code?: string;\n details?: unknown;\n cause?: unknown;\n}\n\nexport class WorkflowError extends Error {\n readonly code: string;\n readonly details?: unknown;\n\n constructor(message: string, options: WorkflowErrorOptions = {}) {\n super(message, { cause: options.cause });\n this.name = new.target.name;\n this.code = options.code ?? 'WORKFLOW_ERROR';\n this.details = options.details;\n }\n\n toJSON(): Record<string, unknown> {\n return {\n name: this.name,\n message: this.message,\n code: this.code,\n ...(this.details === undefined ? {} : { details: this.details }),\n };\n }\n}\n\nexport class WorkflowParseError extends WorkflowError {\n constructor(message: string, details?: unknown, cause?: unknown) {\n super(message, { code: 'WORKFLOW_PARSE_ERROR', details, cause });\n }\n}\n\nexport class NodeDefinitionError extends WorkflowError {\n constructor(message: string, details?: unknown) {\n super(message, { code: 'NODE_DEFINITION_ERROR', details });\n }\n}\n\nexport class DuplicateNodeError extends WorkflowError {\n readonly node: string;\n\n constructor(node: string) {\n super(`Node \"${node}\" is already registered.`, {\n code: 'DUPLICATE_NODE',\n details: { node },\n });\n this.node = node;\n }\n}\n\nexport class NodeNotFoundError extends WorkflowError {\n readonly node: string;\n\n constructor(node: string) {\n super(`Node \"${node}\" is not registered.`, {\n code: 'NODE_NOT_FOUND',\n details: { node },\n });\n this.node = node;\n }\n}\n\nexport class NodeInputValidationError extends WorkflowError {\n constructor(message: string, details?: unknown) {\n super(message, { code: 'NODE_INPUT_VALIDATION_ERROR', details });\n }\n\n static fromZod(node: string, error: z.ZodError): NodeInputValidationError {\n const issues = error.issues.map((issue) => ({\n code: issue.code,\n path: issue.path.map(String).join('.'),\n message: issue.message,\n }));\n const firstIssue = issues[0];\n const path = firstIssue?.path || '<root>';\n const message = firstIssue?.message ?? 'invalid input';\n return new NodeInputValidationError(\n `Node \"${node}\" input validation failed at \"${path}\": ${message}`,\n { node, issues },\n );\n }\n}\n\nexport class StepTimeoutError extends WorkflowError {\n readonly timeoutMs: number;\n readonly node?: string;\n\n constructor(timeoutMs: number, node?: string) {\n super(\n node\n ? `Node \"${node}\" timed out after ${timeoutMs}ms.`\n : `Step timed out after ${timeoutMs}ms.`,\n {\n code: 'STEP_TIMEOUT',\n details: { timeoutMs, ...(node === undefined ? {} : { node }) },\n },\n );\n this.timeoutMs = timeoutMs;\n this.node = node;\n }\n}\n\nexport class NodeExecutionError extends WorkflowError {\n readonly node: string;\n\n constructor(node: string, cause: unknown) {\n const causeMessage =\n cause instanceof Error ? cause.message : String(cause ?? 'Unknown error');\n super(`Node \"${node}\" failed: ${causeMessage}`, {\n code: 'NODE_EXECUTION_ERROR',\n details: { node },\n cause,\n });\n this.node = node;\n }\n}\n\nexport class WorkflowLifecycleError extends WorkflowError {\n constructor(message: string, details?: unknown) {\n super(message, { code: 'WORKFLOW_LIFECYCLE_ERROR', details });\n }\n}\n\nexport class ProjectSetupError extends WorkflowError {\n constructor(cause: unknown, details: { projectName: string }) {\n const causeMessage =\n cause instanceof Error ? cause.message : String(cause ?? 'Unknown error');\n super(`Project \"${details.projectName}\" setup failed: ${causeMessage}`, {\n code: 'PROJECT_SETUP_ERROR',\n details,\n cause,\n });\n }\n}\n\nexport class ProjectTeardownError extends WorkflowError {\n constructor(\n cause: unknown,\n details: { projectName: string; registrationIndex: number },\n ) {\n const causeMessage =\n cause instanceof Error ? cause.message : String(cause ?? 'Unknown error');\n super(`Project \"${details.projectName}\" teardown failed: ${causeMessage}`, {\n code: 'PROJECT_TEARDOWN_ERROR',\n details,\n cause,\n });\n }\n}\n\nexport class NodeScopeTeardownError extends WorkflowError {\n constructor(\n cause: unknown,\n details: {\n scope: 'case' | 'document';\n scopeId: string;\n node: string;\n registrationIndex: number;\n },\n ) {\n const causeMessage =\n cause instanceof Error ? cause.message : String(cause ?? 'Unknown error');\n super(\n `${details.scope === 'case' ? 'Case attempt' : 'Workflow document'} node teardown failed for \"${details.node}\": ${causeMessage}`,\n { code: 'NODE_SCOPE_TEARDOWN_ERROR', details, cause },\n );\n }\n}\n\nexport class FatalDeviceError extends WorkflowError {\n constructor(message: string, cause?: unknown) {\n super(message, { code: 'FATAL_DEVICE_ERROR', cause });\n }\n}\n\nexport const isFatalDeviceError = (error: unknown): boolean => {\n if (error instanceof FatalDeviceError) return true;\n if (error instanceof WorkflowError && error.code === 'FATAL_DEVICE_ERROR') {\n return true;\n }\n if (\n error instanceof Error &&\n /device offline|device not found|(?:adb|bdc|device) connection (?:was )?closed/i.test(\n error.message,\n )\n ) {\n return true;\n }\n return error instanceof Error && error.cause !== undefined\n ? isFatalDeviceError(error.cause)\n : false;\n};\n\nexport class CaseExecutionError extends WorkflowError {\n readonly result: import('./engine/types').CaseRunResult;\n\n constructor(result: import('./engine/types').CaseRunResult) {\n super(`Case \"${result.name}\" failed.`, {\n code: 'CASE_EXECUTION_FAILED',\n details: { caseId: result.caseId, runId: result.runId },\n });\n this.result = result;\n }\n}\n\nexport class WorkflowDocumentExecutionError extends WorkflowError {\n readonly result: import('./engine/types').WorkflowDocumentRunResult;\n\n constructor(result: import('./engine/types').WorkflowDocumentRunResult) {\n super(`Workflow document \"${result.sourcePath}\" failed.`, {\n code: 'WORKFLOW_DOCUMENT_EXECUTION_FAILED',\n details: {\n documentId: result.documentId,\n documentRunId: result.documentRunId,\n },\n });\n this.result = result;\n }\n}\n\nexport function normalizeNodeExecutionError(\n error: unknown,\n node: string,\n): WorkflowError {\n return error instanceof WorkflowError\n ? error\n : new NodeExecutionError(node, error);\n}\n","import { z } from 'zod/v4';\nimport { NodeDefinitionError } from '../errors';\nimport type {\n DefineNodeOptions,\n DefineNodeWithSchemaOptions,\n NodeDefinition,\n NodeDefinitionWithSchema,\n NodeInputSchema,\n} from './types';\n\nconst validateOptionalText = (\n value: unknown,\n field: 'title' | 'description',\n node: string,\n): void => {\n if (\n value !== undefined &&\n (typeof value !== 'string' || value.trim().length === 0)\n ) {\n throw new NodeDefinitionError(\n `Node \"${node}\" ${field} must be a non-empty string.`,\n { node, field },\n );\n }\n};\n\nconst validateInputSchema = (schema: unknown, node: string): void => {\n if (schema === undefined) return;\n if (!(schema instanceof z.ZodObject)) {\n throw new NodeDefinitionError(\n `Node \"${node}\" inputSchema must be a Zod object schema.`,\n { node, field: 'inputSchema' },\n );\n }\n if ('$' in schema.shape) {\n throw new NodeDefinitionError(\n `Node \"${node}\" inputSchema must not declare \"$\" as an input property.`,\n { node, field: 'inputSchema.$' },\n );\n }\n};\n\nconst validateDefinition = (options: {\n name: string;\n title?: unknown;\n description?: unknown;\n stringInputKey?: unknown;\n inputSchema?: unknown;\n execute: unknown;\n}): void => {\n if (!options || typeof options !== 'object') {\n throw new NodeDefinitionError('Node definition must be an object.');\n }\n\n if (typeof options.name !== 'string' || options.name.trim().length === 0) {\n throw new NodeDefinitionError('Node name must be a non-empty string.');\n }\n\n validateOptionalText(options.title, 'title', options.name);\n validateOptionalText(options.description, 'description', options.name);\n if (\n options.stringInputKey !== undefined &&\n options.stringInputKey !== false &&\n (typeof options.stringInputKey !== 'string' ||\n options.stringInputKey.trim().length === 0)\n ) {\n throw new NodeDefinitionError(\n `Node \"${options.name}\" stringInputKey must be a non-empty string or false.`,\n { node: options.name, field: 'stringInputKey' },\n );\n }\n validateInputSchema(options.inputSchema, options.name);\n\n if (\n typeof options.stringInputKey === 'string' &&\n options.inputSchema instanceof z.ZodObject &&\n !(options.stringInputKey in options.inputSchema.shape)\n ) {\n throw new NodeDefinitionError(\n `Node \"${options.name}\" stringInputKey must reference a field in inputSchema.`,\n { node: options.name, field: 'stringInputKey' },\n );\n }\n\n if (typeof options.execute !== 'function') {\n throw new NodeDefinitionError(\n `Node \"${options.name}\" must provide an execute function.`,\n { node: options.name },\n );\n }\n};\n\nexport function defineNode<\n TSchema extends NodeInputSchema,\n TData = unknown,\n TContext = unknown,\n>(\n options: DefineNodeWithSchemaOptions<TSchema, TData, TContext>,\n): NodeDefinitionWithSchema<TSchema, TData, TContext>;\n\nexport function defineNode<\n TInput = unknown,\n TData = unknown,\n TContext = unknown,\n>(\n options: DefineNodeOptions<TInput, TData, TContext>,\n): NodeDefinition<TInput, TData, TContext>;\n\nexport function defineNode(\n options: DefineNodeOptions<any, any, any>,\n): NodeDefinition<any, any, any> {\n validateDefinition(options);\n return options;\n}\n","import {\n type AgentTestRunnerNodeDefinition,\n type AgentTestRunnerNodeProvider,\n type CommonAgentTestRunnerApi,\n aiActInputSchema,\n aiActOptionsInputSchema,\n aiAssertInputSchema,\n aiAssertOptionsInputSchema,\n aiTapInputSchema,\n insightInputSchema,\n insightOptionsInputSchema,\n locateOptionsInputSchema,\n promptImageInputSchema,\n recordToReportInputSchema,\n recordToReportOptionsInputSchema,\n reportScreenshotInputSchema,\n structuredUserPromptInputSchema,\n userPromptInputSchema,\n} from '@midscene/core/agent/test-runner';\nimport { getDebug } from '@midscene/shared/logger';\nimport { z } from 'zod/v4';\nimport type { Awaitable } from '../engine/types';\nimport { NodeDefinitionError, NodeExecutionError } from '../errors';\nimport { defineNode } from '../node/define-node';\nimport type { NodeDefinition, NodeExecutionContext } from '../node/types';\n\nexport type MidsceneUIAgent = CommonAgentTestRunnerApi & {\n addDumpUpdateListener?(\n listener: (dump: string, execution?: MidsceneExecutionRef) => void,\n ): () => void;\n};\n\nexport {\n aiActInputSchema,\n aiActOptionsInputSchema,\n aiAssertInputSchema,\n aiAssertOptionsInputSchema,\n aiTapInputSchema,\n insightInputSchema,\n insightOptionsInputSchema,\n locateOptionsInputSchema,\n promptImageInputSchema,\n recordToReportInputSchema,\n recordToReportOptionsInputSchema,\n reportScreenshotInputSchema,\n structuredUserPromptInputSchema,\n userPromptInputSchema,\n};\n\nexport interface MidsceneExecutionRef {\n id?: string;\n}\n\nexport interface AgentProvider<TContext> {\n getAgent(\n runId: string,\n ctx: NodeExecutionContext<unknown, TContext>,\n ): Awaitable<MidsceneUIAgent>;\n // biome-ignore lint/suspicious/noConfusingVoidType: providers without a report intentionally return void.\n releaseAgent?(runId: string): Awaitable<AgentReleaseResult | void>;\n dispose?(): Awaitable<void>;\n}\n\nexport interface AgentReleaseResult {\n /** Absolute path to the finalized report for this Agent scope. */\n reportPath?: string;\n}\n\nexport const waitInputSchema = z.strictObject({\n duration: z.number().positive().describe('How long to wait.'),\n unit: z\n .enum(['ms', 's', 'min'])\n .default('ms')\n .describe('Duration unit: milliseconds, seconds, or minutes.'),\n});\n\nexport type AiActNodeInput = z.infer<typeof aiActInputSchema>;\nexport type AiAssertNodeInput = z.infer<typeof aiAssertInputSchema>;\nexport type AiTapNodeInput = z.infer<typeof aiTapInputSchema>;\nexport type InsightNodeInput = z.infer<typeof insightInputSchema>;\nexport type RecordToReportNodeInput = z.infer<typeof recordToReportInputSchema>;\nexport type WaitNodeInput = z.infer<typeof waitInputSchema>;\n\nexport interface CreateMidsceneNodesOptions<TContext> {\n getAgent?(\n ctx: NodeExecutionContext<unknown, TContext>,\n ): Awaitable<MidsceneUIAgent>;\n agentProvider?: AgentProvider<TContext>;\n /** Agent class that declares the Agent-backed Nodes to register. */\n agentClass: AgentTestRunnerNodeProvider;\n}\n\nconst waitFor = async (durationMs: number, signal: AbortSignal) => {\n if (signal.aborted) {\n throw signal.reason ?? new Error('Wait aborted.');\n }\n await new Promise<void>((resolve, reject) => {\n const timeout = setTimeout(() => {\n signal.removeEventListener('abort', abort);\n resolve();\n }, durationMs);\n const abort = () => {\n clearTimeout(timeout);\n reject(signal.reason ?? new Error('Wait aborted.'));\n };\n signal.addEventListener('abort', abort, { once: true });\n });\n};\n\n/** Adapt Agent-owned descriptions to executable Midscene Test Nodes. */\nexport const createAgentTestRunnerNodes = <TContext>(\n definitions: readonly AgentTestRunnerNodeDefinition[],\n getAgent: (\n ctx: NodeExecutionContext<unknown, TContext>,\n ) => Awaitable<unknown>,\n): readonly NodeDefinition<any, any, TContext>[] => {\n const activeAgentCalls = new WeakMap<\n MidsceneUIAgent,\n { scopeId: string; node: string }\n >();\n const runAgentCall = async <T>(\n node: string,\n ctx: NodeExecutionContext<unknown, TContext>,\n agent: MidsceneUIAgent,\n call: () => Promise<T>,\n captureExecutions = true,\n ): Promise<T> => {\n const scopeId =\n ctx.scope === 'case' ? ctx.case.runId : ctx.document.documentRunId;\n const activeCall = activeAgentCalls.get(agent);\n if (activeCall) {\n throw new NodeExecutionError(\n node,\n new Error(\n `The same Agent instance cannot execute overlapping Midscene Test Steps. Active scope: ${activeCall.scopeId} (${activeCall.node}); requested scope: ${scopeId} (${node}).`,\n ),\n );\n }\n\n activeAgentCalls.set(agent, { scopeId, node });\n let removeListener: (() => void) | undefined;\n let sawExecutionWithoutId = false;\n const stopListening = () => {\n const remove = removeListener;\n removeListener = undefined;\n remove?.();\n };\n const stopListeningOnAbort = () => stopListening();\n try {\n if (captureExecutions && agent.addDumpUpdateListener) {\n removeListener = agent.addDumpUpdateListener((_dump, execution) => {\n if (!execution) return;\n if (!execution.id) {\n sawExecutionWithoutId = true;\n return;\n }\n ctx.report.addTrace({\n type: 'midscene-execution',\n executionId: execution.id,\n });\n });\n if (ctx.signal.aborted) stopListening();\n else {\n ctx.signal.addEventListener('abort', stopListeningOnAbort, {\n once: true,\n });\n }\n }\n return await call();\n } finally {\n ctx.signal.removeEventListener('abort', stopListeningOnAbort);\n try {\n stopListening();\n } finally {\n activeAgentCalls.delete(agent);\n }\n if (sawExecutionWithoutId) {\n warnReportTrace(\n `Skipped a report trace without a stable execution id for ${node} in scope ${scopeId}.`,\n );\n }\n }\n };\n\n return definitions.map((definition) =>\n defineNode({\n name: definition.name,\n ...(definition.title === undefined ? {} : { title: definition.title }),\n ...(definition.description === undefined\n ? {}\n : { description: definition.description }),\n ...(definition.stringInputKey === undefined\n ? {}\n : { stringInputKey: definition.stringInputKey }),\n inputSchema: definition.inputSchema,\n async execute(ctx) {\n const agent = await getAgent(ctx);\n const call = async () =>\n definition.execute(agent, ctx.input, { signal: ctx.signal });\n if (typeof agent !== 'object' || agent === null) return call();\n return runAgentCall(\n definition.name,\n ctx,\n agent as MidsceneUIAgent,\n call,\n );\n },\n }),\n );\n};\n\nconst warnReportTrace = getDebug('test-runner:report-trace', {\n console: true,\n});\n\nexport function createMidsceneNodes<TContext>(\n options: CreateMidsceneNodesOptions<TContext>,\n): readonly NodeDefinition<any, any, TContext>[] {\n if (!options || typeof options !== 'object') {\n throw new NodeDefinitionError(\n 'createMidsceneNodes() options must be an object.',\n );\n }\n if (\n typeof options.agentProvider?.getAgent !== 'function' &&\n typeof options.getAgent !== 'function'\n ) {\n throw new NodeDefinitionError(\n 'createMidsceneNodes() requires getAgent or agentProvider.getAgent.',\n );\n }\n if (\n !options.agentClass ||\n typeof options.agentClass.getTestRunnerNodeDefinitions !== 'function'\n ) {\n throw new NodeDefinitionError(\n 'createMidsceneNodes() requires agentClass.getTestRunnerNodeDefinitions().',\n );\n }\n\n const registeredAgentScopes = new Set<string>();\n const getExecutionId = (ctx: NodeExecutionContext<unknown, TContext>) =>\n ctx.scope === 'case' ? ctx.case.runId : ctx.document.documentRunId;\n const getAgent = async (\n ctx: NodeExecutionContext<unknown, TContext>,\n ): Promise<MidsceneUIAgent> => {\n if (!options.agentProvider) return options.getAgent!(ctx);\n const runId = getExecutionId(ctx);\n if (\n options.agentProvider.releaseAgent &&\n !registeredAgentScopes.has(runId)\n ) {\n registeredAgentScopes.add(runId);\n ctx.onTeardown(async () => {\n try {\n const released = await options.agentProvider!.releaseAgent!(runId);\n return released?.reportPath\n ? { reportPaths: [released.reportPath] }\n : undefined;\n } finally {\n registeredAgentScopes.delete(runId);\n }\n });\n }\n return options.agentProvider.getAgent(runId, ctx);\n };\n\n const agentDefinitions = options.agentClass.getTestRunnerNodeDefinitions();\n\n return [\n ...createAgentTestRunnerNodes(agentDefinitions, getAgent),\n defineNode<typeof waitInputSchema, unknown, TContext>({\n name: 'wait',\n description: 'Wait for a fixed duration while honoring cancellation.',\n stringInputKey: false,\n inputSchema: waitInputSchema,\n async execute(ctx) {\n const multiplier =\n ctx.input.unit === 'min'\n ? 60_000\n : ctx.input.unit === 's'\n ? 1_000\n : 1;\n const durationMs = ctx.input.duration * multiplier;\n await waitFor(durationMs, ctx.signal);\n return { summary: `Waited ${durationMs}ms` };\n },\n }),\n ];\n}\n","__webpack_require__.d = (exports, definition) => {\n\tfor(var key in definition) {\n if(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {\n Object.defineProperty(exports, key, { enumerable: true, get: definition[key] });\n }\n }\n};","__webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))","// define __esModule on exports\n__webpack_require__.r = (exports) => {\n\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n\t}\n\tObject.defineProperty(exports, '__esModule', { value: true });\n};","import type { IOSAgent } from '@midscene/ios';\nimport {\n iosAgentTestRunnerNodeDefinitions,\n launchInputSchema,\n runWdaRequestInputSchema,\n terminateInputSchema,\n wdaRequestInputSchema,\n} from '@midscene/ios/test-runner';\nexport type {\n LaunchNodeInput,\n RunWdaRequestNodeInput,\n TerminateNodeInput,\n WDAHttpMethod,\n} from '@midscene/ios/test-runner';\nimport type { Awaitable } from '../engine/types';\nimport { NodeDefinitionError } from '../errors';\nimport { createAgentTestRunnerNodes } from '../midscene';\nimport type { NodeDefinition, NodeExecutionContext } from '../node/types';\n\nexport {\n launchInputSchema,\n runWdaRequestInputSchema,\n terminateInputSchema,\n wdaRequestInputSchema,\n};\n\nexport type IOSRunnerAgent = Pick<\n IOSAgent,\n 'launch' | 'terminate' | 'runWdaRequest' | 'home' | 'appSwitcher'\n>;\n\nexport interface CreateIOSNodesOptions<TContext> {\n getAgent(\n ctx: NodeExecutionContext<unknown, TContext>,\n ): Awaitable<IOSRunnerAgent>;\n}\n\nexport function createIOSNodes<TContext>(\n options: CreateIOSNodesOptions<TContext>,\n): readonly NodeDefinition<any, any, TContext>[] {\n if (!options || typeof options !== 'object') {\n throw new NodeDefinitionError(\n 'createIOSNodes() options must be an object.',\n );\n }\n if (typeof options.getAgent !== 'function') {\n throw new NodeDefinitionError('createIOSNodes() requires getAgent().');\n }\n\n return createAgentTestRunnerNodes(\n iosAgentTestRunnerNodeDefinitions,\n options.getAgent,\n );\n}\n"],"names":["WorkflowError","Error","undefined","message","options","NodeDefinitionError","details","NodeExecutionError","node","cause","causeMessage","String","validateOptionalText","value","field","validateInputSchema","schema","z","validateDefinition","defineNode","createAgentTestRunnerNodes","definitions","getAgent","activeAgentCalls","WeakMap","runAgentCall","ctx","agent","call","captureExecutions","scopeId","activeCall","removeListener","sawExecutionWithoutId","stopListening","remove","stopListeningOnAbort","_dump","execution","warnReportTrace","definition","getDebug","__webpack_require__","key","Object","obj","prop","Symbol","createIOSNodes","iosAgentTestRunnerNodeDefinitions"],"mappings":"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"}
@@ -2,6 +2,7 @@
2
2
  var __webpack_modules__ = {
3
3
  "./src/errors.ts" (__unused_rspack_module, __webpack_exports__, __webpack_require__) {
4
4
  __webpack_require__.d(__webpack_exports__, {
5
+ h2: ()=>NodeExecutionError,
5
6
  ww: ()=>NodeDefinitionError
6
7
  });
7
8
  function _define_property(obj, key, value) {
@@ -42,6 +43,19 @@ var __webpack_modules__ = {
42
43
  });
43
44
  }
44
45
  }
46
+ class NodeExecutionError extends WorkflowError {
47
+ constructor(node, cause){
48
+ const causeMessage = cause instanceof Error ? cause.message : String(cause ?? 'Unknown error');
49
+ super(`Node "${node}" failed: ${causeMessage}`, {
50
+ code: 'NODE_EXECUTION_ERROR',
51
+ details: {
52
+ node
53
+ },
54
+ cause
55
+ }), _define_property(this, "node", void 0);
56
+ this.node = node;
57
+ }
58
+ }
45
59
  }
46
60
  };
47
61
  var __webpack_module_cache__ = {};
@@ -98,6 +112,7 @@ var __webpack_exports__ = {};
98
112
  insightOptionsInputSchema: ()=>test_runner_namespaceObject.insightOptionsInputSchema
99
113
  });
100
114
  const test_runner_namespaceObject = require("@midscene/core/agent/test-runner");
115
+ const logger_namespaceObject = require("@midscene/shared/logger");
101
116
  const v4_namespaceObject = require("zod/v4");
102
117
  var errors = __webpack_require__("./src/errors.ts");
103
118
  const validateOptionalText = (value, field, node)=>{
@@ -163,7 +178,54 @@ var __webpack_exports__ = {};
163
178
  });
164
179
  });
165
180
  };
166
- const createAgentTestRunnerNodes = (definitions, getAgent)=>definitions.map((definition)=>defineNode({
181
+ const createAgentTestRunnerNodes = (definitions, getAgent)=>{
182
+ const activeAgentCalls = new WeakMap();
183
+ const runAgentCall = async (node, ctx, agent, call, captureExecutions = true)=>{
184
+ const scopeId = 'case' === ctx.scope ? ctx.case.runId : ctx.document.documentRunId;
185
+ const activeCall = activeAgentCalls.get(agent);
186
+ if (activeCall) throw new errors.h2(node, new Error(`The same Agent instance cannot execute overlapping Midscene Test Steps. Active scope: ${activeCall.scopeId} (${activeCall.node}); requested scope: ${scopeId} (${node}).`));
187
+ activeAgentCalls.set(agent, {
188
+ scopeId,
189
+ node
190
+ });
191
+ let removeListener;
192
+ let sawExecutionWithoutId = false;
193
+ const stopListening = ()=>{
194
+ const remove = removeListener;
195
+ removeListener = void 0;
196
+ remove?.();
197
+ };
198
+ const stopListeningOnAbort = ()=>stopListening();
199
+ try {
200
+ if (captureExecutions && agent.addDumpUpdateListener) {
201
+ removeListener = agent.addDumpUpdateListener((_dump, execution)=>{
202
+ if (!execution) return;
203
+ if (!execution.id) {
204
+ sawExecutionWithoutId = true;
205
+ return;
206
+ }
207
+ ctx.report.addTrace({
208
+ type: 'midscene-execution',
209
+ executionId: execution.id
210
+ });
211
+ });
212
+ if (ctx.signal.aborted) stopListening();
213
+ else ctx.signal.addEventListener('abort', stopListeningOnAbort, {
214
+ once: true
215
+ });
216
+ }
217
+ return await call();
218
+ } finally{
219
+ ctx.signal.removeEventListener('abort', stopListeningOnAbort);
220
+ try {
221
+ stopListening();
222
+ } finally{
223
+ activeAgentCalls.delete(agent);
224
+ }
225
+ if (sawExecutionWithoutId) warnReportTrace(`Skipped a report trace without a stable execution id for ${node} in scope ${scopeId}.`);
226
+ }
227
+ };
228
+ return definitions.map((definition)=>defineNode({
167
229
  name: definition.name,
168
230
  ...void 0 === definition.title ? {} : {
169
231
  title: definition.title
@@ -177,11 +239,17 @@ var __webpack_exports__ = {};
177
239
  inputSchema: definition.inputSchema,
178
240
  async execute (ctx) {
179
241
  const agent = await getAgent(ctx);
180
- return definition.execute(agent, ctx.input, {
181
- signal: ctx.signal
182
- });
242
+ const call = async ()=>definition.execute(agent, ctx.input, {
243
+ signal: ctx.signal
244
+ });
245
+ if ('object' != typeof agent || null === agent) return call();
246
+ return runAgentCall(definition.name, ctx, agent, call);
183
247
  }
184
248
  }));
249
+ };
250
+ const warnReportTrace = (0, logger_namespaceObject.getDebug)('test-runner:report-trace', {
251
+ console: true
252
+ });
185
253
  function createMidsceneNodes(options) {
186
254
  if (!options || 'object' != typeof options) throw new errors.ww('createMidsceneNodes() options must be an object.');
187
255
  if ('function' != typeof options.agentProvider?.getAgent && 'function' != typeof options.getAgent) throw new errors.ww('createMidsceneNodes() requires getAgent or agentProvider.getAgent.');
@@ -1 +1 @@
1
- {"version":3,"file":"midscene/index.js","sources":["../../../src/errors.ts","webpack/runtime/define_property_getters","webpack/runtime/has_own_property","webpack/runtime/make_namespace_object","../../../src/node/define-node.ts","../../../src/midscene/index.ts"],"sourcesContent":["import type { z } from 'zod/v4';\n\nexport interface WorkflowErrorOptions {\n code?: string;\n details?: unknown;\n cause?: unknown;\n}\n\nexport class WorkflowError extends Error {\n readonly code: string;\n readonly details?: unknown;\n\n constructor(message: string, options: WorkflowErrorOptions = {}) {\n super(message, { cause: options.cause });\n this.name = new.target.name;\n this.code = options.code ?? 'WORKFLOW_ERROR';\n this.details = options.details;\n }\n\n toJSON(): Record<string, unknown> {\n return {\n name: this.name,\n message: this.message,\n code: this.code,\n ...(this.details === undefined ? {} : { details: this.details }),\n };\n }\n}\n\nexport class WorkflowParseError extends WorkflowError {\n constructor(message: string, details?: unknown, cause?: unknown) {\n super(message, { code: 'WORKFLOW_PARSE_ERROR', details, cause });\n }\n}\n\nexport class NodeDefinitionError extends WorkflowError {\n constructor(message: string, details?: unknown) {\n super(message, { code: 'NODE_DEFINITION_ERROR', details });\n }\n}\n\nexport class DuplicateNodeError extends WorkflowError {\n readonly node: string;\n\n constructor(node: string) {\n super(`Node \"${node}\" is already registered.`, {\n code: 'DUPLICATE_NODE',\n details: { node },\n });\n this.node = node;\n }\n}\n\nexport class NodeNotFoundError extends WorkflowError {\n readonly node: string;\n\n constructor(node: string) {\n super(`Node \"${node}\" is not registered.`, {\n code: 'NODE_NOT_FOUND',\n details: { node },\n });\n this.node = node;\n }\n}\n\nexport class NodeInputValidationError extends WorkflowError {\n constructor(message: string, details?: unknown) {\n super(message, { code: 'NODE_INPUT_VALIDATION_ERROR', details });\n }\n\n static fromZod(node: string, error: z.ZodError): NodeInputValidationError {\n const issues = error.issues.map((issue) => ({\n code: issue.code,\n path: issue.path.map(String).join('.'),\n message: issue.message,\n }));\n const firstIssue = issues[0];\n const path = firstIssue?.path || '<root>';\n const message = firstIssue?.message ?? 'invalid input';\n return new NodeInputValidationError(\n `Node \"${node}\" input validation failed at \"${path}\": ${message}`,\n { node, issues },\n );\n }\n}\n\nexport class StepTimeoutError extends WorkflowError {\n readonly timeoutMs: number;\n readonly node?: string;\n\n constructor(timeoutMs: number, node?: string) {\n super(\n node\n ? `Node \"${node}\" timed out after ${timeoutMs}ms.`\n : `Step timed out after ${timeoutMs}ms.`,\n {\n code: 'STEP_TIMEOUT',\n details: { timeoutMs, ...(node === undefined ? {} : { node }) },\n },\n );\n this.timeoutMs = timeoutMs;\n this.node = node;\n }\n}\n\nexport class NodeExecutionError extends WorkflowError {\n readonly node: string;\n\n constructor(node: string, cause: unknown) {\n const causeMessage =\n cause instanceof Error ? cause.message : String(cause ?? 'Unknown error');\n super(`Node \"${node}\" failed: ${causeMessage}`, {\n code: 'NODE_EXECUTION_ERROR',\n details: { node },\n cause,\n });\n this.node = node;\n }\n}\n\nexport class WorkflowLifecycleError extends WorkflowError {\n constructor(message: string, details?: unknown) {\n super(message, { code: 'WORKFLOW_LIFECYCLE_ERROR', details });\n }\n}\n\nexport class ProjectSetupError extends WorkflowError {\n constructor(cause: unknown, details: { projectName: string }) {\n const causeMessage =\n cause instanceof Error ? cause.message : String(cause ?? 'Unknown error');\n super(`Project \"${details.projectName}\" setup failed: ${causeMessage}`, {\n code: 'PROJECT_SETUP_ERROR',\n details,\n cause,\n });\n }\n}\n\nexport class ProjectTeardownError extends WorkflowError {\n constructor(\n cause: unknown,\n details: { projectName: string; registrationIndex: number },\n ) {\n const causeMessage =\n cause instanceof Error ? cause.message : String(cause ?? 'Unknown error');\n super(`Project \"${details.projectName}\" teardown failed: ${causeMessage}`, {\n code: 'PROJECT_TEARDOWN_ERROR',\n details,\n cause,\n });\n }\n}\n\nexport class NodeScopeTeardownError extends WorkflowError {\n constructor(\n cause: unknown,\n details: {\n scope: 'case' | 'document';\n scopeId: string;\n node: string;\n registrationIndex: number;\n },\n ) {\n const causeMessage =\n cause instanceof Error ? cause.message : String(cause ?? 'Unknown error');\n super(\n `${details.scope === 'case' ? 'Case attempt' : 'Workflow document'} node teardown failed for \"${details.node}\": ${causeMessage}`,\n { code: 'NODE_SCOPE_TEARDOWN_ERROR', details, cause },\n );\n }\n}\n\nexport class FatalDeviceError extends WorkflowError {\n constructor(message: string, cause?: unknown) {\n super(message, { code: 'FATAL_DEVICE_ERROR', cause });\n }\n}\n\nexport const isFatalDeviceError = (error: unknown): boolean => {\n if (error instanceof FatalDeviceError) return true;\n if (error instanceof WorkflowError && error.code === 'FATAL_DEVICE_ERROR') {\n return true;\n }\n if (\n error instanceof Error &&\n /device offline|device not found|(?:adb|bdc|device) connection (?:was )?closed/i.test(\n error.message,\n )\n ) {\n return true;\n }\n return error instanceof Error && error.cause !== undefined\n ? isFatalDeviceError(error.cause)\n : false;\n};\n\nexport class CaseExecutionError extends WorkflowError {\n readonly result: import('./engine/types').CaseRunResult;\n\n constructor(result: import('./engine/types').CaseRunResult) {\n super(`Case \"${result.name}\" failed.`, {\n code: 'CASE_EXECUTION_FAILED',\n details: { caseId: result.caseId, runId: result.runId },\n });\n this.result = result;\n }\n}\n\nexport class WorkflowDocumentExecutionError extends WorkflowError {\n readonly result: import('./engine/types').WorkflowDocumentRunResult;\n\n constructor(result: import('./engine/types').WorkflowDocumentRunResult) {\n super(`Workflow document \"${result.sourcePath}\" failed.`, {\n code: 'WORKFLOW_DOCUMENT_EXECUTION_FAILED',\n details: {\n documentId: result.documentId,\n documentRunId: result.documentRunId,\n },\n });\n this.result = result;\n }\n}\n\nexport function normalizeNodeExecutionError(\n error: unknown,\n node: string,\n): WorkflowError {\n return error instanceof WorkflowError\n ? error\n : new NodeExecutionError(node, error);\n}\n","__webpack_require__.d = (exports, definition) => {\n\tfor(var key in definition) {\n if(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {\n Object.defineProperty(exports, key, { enumerable: true, get: definition[key] });\n }\n }\n};","__webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))","// define __esModule on exports\n__webpack_require__.r = (exports) => {\n\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n\t}\n\tObject.defineProperty(exports, '__esModule', { value: true });\n};","import { z } from 'zod/v4';\nimport { NodeDefinitionError } from '../errors';\nimport type {\n DefineNodeOptions,\n DefineNodeWithSchemaOptions,\n NodeDefinition,\n NodeDefinitionWithSchema,\n NodeInputSchema,\n} from './types';\n\nconst validateOptionalText = (\n value: unknown,\n field: 'title' | 'description',\n node: string,\n): void => {\n if (\n value !== undefined &&\n (typeof value !== 'string' || value.trim().length === 0)\n ) {\n throw new NodeDefinitionError(\n `Node \"${node}\" ${field} must be a non-empty string.`,\n { node, field },\n );\n }\n};\n\nconst validateInputSchema = (schema: unknown, node: string): void => {\n if (schema === undefined) return;\n if (!(schema instanceof z.ZodObject)) {\n throw new NodeDefinitionError(\n `Node \"${node}\" inputSchema must be a Zod object schema.`,\n { node, field: 'inputSchema' },\n );\n }\n if ('$' in schema.shape) {\n throw new NodeDefinitionError(\n `Node \"${node}\" inputSchema must not declare \"$\" as an input property.`,\n { node, field: 'inputSchema.$' },\n );\n }\n};\n\nconst validateDefinition = (options: {\n name: string;\n title?: unknown;\n description?: unknown;\n stringInputKey?: unknown;\n inputSchema?: unknown;\n execute: unknown;\n}): void => {\n if (!options || typeof options !== 'object') {\n throw new NodeDefinitionError('Node definition must be an object.');\n }\n\n if (typeof options.name !== 'string' || options.name.trim().length === 0) {\n throw new NodeDefinitionError('Node name must be a non-empty string.');\n }\n\n validateOptionalText(options.title, 'title', options.name);\n validateOptionalText(options.description, 'description', options.name);\n if (\n options.stringInputKey !== undefined &&\n options.stringInputKey !== false &&\n (typeof options.stringInputKey !== 'string' ||\n options.stringInputKey.trim().length === 0)\n ) {\n throw new NodeDefinitionError(\n `Node \"${options.name}\" stringInputKey must be a non-empty string or false.`,\n { node: options.name, field: 'stringInputKey' },\n );\n }\n validateInputSchema(options.inputSchema, options.name);\n\n if (\n typeof options.stringInputKey === 'string' &&\n options.inputSchema instanceof z.ZodObject &&\n !(options.stringInputKey in options.inputSchema.shape)\n ) {\n throw new NodeDefinitionError(\n `Node \"${options.name}\" stringInputKey must reference a field in inputSchema.`,\n { node: options.name, field: 'stringInputKey' },\n );\n }\n\n if (typeof options.execute !== 'function') {\n throw new NodeDefinitionError(\n `Node \"${options.name}\" must provide an execute function.`,\n { node: options.name },\n );\n }\n};\n\nexport function defineNode<\n TSchema extends NodeInputSchema,\n TData = unknown,\n TContext = unknown,\n>(\n options: DefineNodeWithSchemaOptions<TSchema, TData, TContext>,\n): NodeDefinitionWithSchema<TSchema, TData, TContext>;\n\nexport function defineNode<\n TInput = unknown,\n TData = unknown,\n TContext = unknown,\n>(\n options: DefineNodeOptions<TInput, TData, TContext>,\n): NodeDefinition<TInput, TData, TContext>;\n\nexport function defineNode(\n options: DefineNodeOptions<any, any, any>,\n): NodeDefinition<any, any, any> {\n validateDefinition(options);\n return options;\n}\n","import {\n type AgentTestRunnerNodeDefinition,\n type AgentTestRunnerNodeProvider,\n type CommonAgentTestRunnerApi,\n aiActInputSchema,\n aiActOptionsInputSchema,\n aiAssertInputSchema,\n aiAssertOptionsInputSchema,\n aiTapInputSchema,\n insightInputSchema,\n insightOptionsInputSchema,\n locateOptionsInputSchema,\n promptImageInputSchema,\n recordToReportInputSchema,\n recordToReportOptionsInputSchema,\n reportScreenshotInputSchema,\n structuredUserPromptInputSchema,\n userPromptInputSchema,\n} from '@midscene/core/agent/test-runner';\nimport { z } from 'zod/v4';\nimport type { Awaitable } from '../engine/types';\nimport { NodeDefinitionError } from '../errors';\nimport { defineNode } from '../node/define-node';\nimport type { NodeDefinition, NodeExecutionContext } from '../node/types';\n\nexport type MidsceneUIAgent = CommonAgentTestRunnerApi;\n\nexport {\n aiActInputSchema,\n aiActOptionsInputSchema,\n aiAssertInputSchema,\n aiAssertOptionsInputSchema,\n aiTapInputSchema,\n insightInputSchema,\n insightOptionsInputSchema,\n locateOptionsInputSchema,\n promptImageInputSchema,\n recordToReportInputSchema,\n recordToReportOptionsInputSchema,\n reportScreenshotInputSchema,\n structuredUserPromptInputSchema,\n userPromptInputSchema,\n};\n\nexport interface AgentProvider<TContext> {\n getAgent(\n runId: string,\n ctx: NodeExecutionContext<unknown, TContext>,\n ): Awaitable<MidsceneUIAgent>;\n // biome-ignore lint/suspicious/noConfusingVoidType: providers without a report intentionally return void.\n releaseAgent?(runId: string): Awaitable<AgentReleaseResult | void>;\n dispose?(): Awaitable<void>;\n}\n\nexport interface AgentReleaseResult {\n /** Absolute path to the finalized report for this Agent scope. */\n reportPath?: string;\n}\n\nexport const waitInputSchema = z.strictObject({\n duration: z.number().positive().describe('How long to wait.'),\n unit: z\n .enum(['ms', 's', 'min'])\n .default('ms')\n .describe('Duration unit: milliseconds, seconds, or minutes.'),\n});\n\nexport type AiActNodeInput = z.infer<typeof aiActInputSchema>;\nexport type AiAssertNodeInput = z.infer<typeof aiAssertInputSchema>;\nexport type AiTapNodeInput = z.infer<typeof aiTapInputSchema>;\nexport type InsightNodeInput = z.infer<typeof insightInputSchema>;\nexport type RecordToReportNodeInput = z.infer<typeof recordToReportInputSchema>;\nexport type WaitNodeInput = z.infer<typeof waitInputSchema>;\n\nexport interface CreateMidsceneNodesOptions<TContext> {\n getAgent?(\n ctx: NodeExecutionContext<unknown, TContext>,\n ): Awaitable<MidsceneUIAgent>;\n agentProvider?: AgentProvider<TContext>;\n /** Agent class that declares the Agent-backed Nodes to register. */\n agentClass: AgentTestRunnerNodeProvider;\n}\n\nconst waitFor = async (durationMs: number, signal: AbortSignal) => {\n if (signal.aborted) {\n throw signal.reason ?? new Error('Wait aborted.');\n }\n await new Promise<void>((resolve, reject) => {\n const timeout = setTimeout(() => {\n signal.removeEventListener('abort', abort);\n resolve();\n }, durationMs);\n const abort = () => {\n clearTimeout(timeout);\n reject(signal.reason ?? new Error('Wait aborted.'));\n };\n signal.addEventListener('abort', abort, { once: true });\n });\n};\n\n/** Adapt Agent-owned descriptions to executable Midscene Test Nodes. */\nexport const createAgentTestRunnerNodes = <TContext>(\n definitions: readonly AgentTestRunnerNodeDefinition[],\n getAgent: (\n ctx: NodeExecutionContext<unknown, TContext>,\n ) => Awaitable<unknown>,\n): readonly NodeDefinition<any, any, TContext>[] =>\n definitions.map((definition) =>\n defineNode({\n name: definition.name,\n ...(definition.title === undefined ? {} : { title: definition.title }),\n ...(definition.description === undefined\n ? {}\n : { description: definition.description }),\n ...(definition.stringInputKey === undefined\n ? {}\n : { stringInputKey: definition.stringInputKey }),\n inputSchema: definition.inputSchema,\n async execute(ctx) {\n const agent = await getAgent(ctx);\n return definition.execute(agent, ctx.input, {\n signal: ctx.signal,\n });\n },\n }),\n );\n\nexport function createMidsceneNodes<TContext>(\n options: CreateMidsceneNodesOptions<TContext>,\n): readonly NodeDefinition<any, any, TContext>[] {\n if (!options || typeof options !== 'object') {\n throw new NodeDefinitionError(\n 'createMidsceneNodes() options must be an object.',\n );\n }\n if (\n typeof options.agentProvider?.getAgent !== 'function' &&\n typeof options.getAgent !== 'function'\n ) {\n throw new NodeDefinitionError(\n 'createMidsceneNodes() requires getAgent or agentProvider.getAgent.',\n );\n }\n if (\n !options.agentClass ||\n typeof options.agentClass.getTestRunnerNodeDefinitions !== 'function'\n ) {\n throw new NodeDefinitionError(\n 'createMidsceneNodes() requires agentClass.getTestRunnerNodeDefinitions().',\n );\n }\n\n const registeredAgentScopes = new Set<string>();\n const getExecutionId = (ctx: NodeExecutionContext<unknown, TContext>) =>\n ctx.scope === 'case' ? ctx.case.runId : ctx.document.documentRunId;\n const getAgent = async (\n ctx: NodeExecutionContext<unknown, TContext>,\n ): Promise<MidsceneUIAgent> => {\n if (!options.agentProvider) return options.getAgent!(ctx);\n const runId = getExecutionId(ctx);\n if (\n options.agentProvider.releaseAgent &&\n !registeredAgentScopes.has(runId)\n ) {\n registeredAgentScopes.add(runId);\n ctx.onTeardown(async () => {\n try {\n const released = await options.agentProvider!.releaseAgent!(runId);\n return released?.reportPath\n ? { reportPaths: [released.reportPath] }\n : undefined;\n } finally {\n registeredAgentScopes.delete(runId);\n }\n });\n }\n return options.agentProvider.getAgent(runId, ctx);\n };\n\n const agentDefinitions = options.agentClass.getTestRunnerNodeDefinitions();\n\n return [\n ...createAgentTestRunnerNodes(agentDefinitions, getAgent),\n defineNode<typeof waitInputSchema, unknown, TContext>({\n name: 'wait',\n description: 'Wait for a fixed duration while honoring cancellation.',\n stringInputKey: false,\n inputSchema: waitInputSchema,\n async execute(ctx) {\n const multiplier =\n ctx.input.unit === 'min'\n ? 60_000\n : ctx.input.unit === 's'\n ? 1_000\n : 1;\n const durationMs = ctx.input.duration * multiplier;\n await waitFor(durationMs, ctx.signal);\n return { summary: `Waited ${durationMs}ms` };\n },\n }),\n ];\n}\n"],"names":["WorkflowError","Error","undefined","message","options","NodeDefinitionError","details","__webpack_require__","definition","key","Object","obj","prop","Symbol","validateOptionalText","value","field","node","validateInputSchema","schema","z","validateDefinition","defineNode","waitInputSchema","waitFor","durationMs","signal","Promise","resolve","reject","timeout","setTimeout","abort","clearTimeout","createAgentTestRunnerNodes","definitions","getAgent","ctx","agent","createMidsceneNodes","registeredAgentScopes","Set","getExecutionId","runId","released","agentDefinitions","multiplier"],"mappings":"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"}
1
+ {"version":3,"file":"midscene/index.js","sources":["../../../src/errors.ts","webpack/runtime/define_property_getters","webpack/runtime/has_own_property","webpack/runtime/make_namespace_object","../../../src/node/define-node.ts","../../../src/midscene/index.ts"],"sourcesContent":["import type { z } from 'zod/v4';\n\nexport interface WorkflowErrorOptions {\n code?: string;\n details?: unknown;\n cause?: unknown;\n}\n\nexport class WorkflowError extends Error {\n readonly code: string;\n readonly details?: unknown;\n\n constructor(message: string, options: WorkflowErrorOptions = {}) {\n super(message, { cause: options.cause });\n this.name = new.target.name;\n this.code = options.code ?? 'WORKFLOW_ERROR';\n this.details = options.details;\n }\n\n toJSON(): Record<string, unknown> {\n return {\n name: this.name,\n message: this.message,\n code: this.code,\n ...(this.details === undefined ? {} : { details: this.details }),\n };\n }\n}\n\nexport class WorkflowParseError extends WorkflowError {\n constructor(message: string, details?: unknown, cause?: unknown) {\n super(message, { code: 'WORKFLOW_PARSE_ERROR', details, cause });\n }\n}\n\nexport class NodeDefinitionError extends WorkflowError {\n constructor(message: string, details?: unknown) {\n super(message, { code: 'NODE_DEFINITION_ERROR', details });\n }\n}\n\nexport class DuplicateNodeError extends WorkflowError {\n readonly node: string;\n\n constructor(node: string) {\n super(`Node \"${node}\" is already registered.`, {\n code: 'DUPLICATE_NODE',\n details: { node },\n });\n this.node = node;\n }\n}\n\nexport class NodeNotFoundError extends WorkflowError {\n readonly node: string;\n\n constructor(node: string) {\n super(`Node \"${node}\" is not registered.`, {\n code: 'NODE_NOT_FOUND',\n details: { node },\n });\n this.node = node;\n }\n}\n\nexport class NodeInputValidationError extends WorkflowError {\n constructor(message: string, details?: unknown) {\n super(message, { code: 'NODE_INPUT_VALIDATION_ERROR', details });\n }\n\n static fromZod(node: string, error: z.ZodError): NodeInputValidationError {\n const issues = error.issues.map((issue) => ({\n code: issue.code,\n path: issue.path.map(String).join('.'),\n message: issue.message,\n }));\n const firstIssue = issues[0];\n const path = firstIssue?.path || '<root>';\n const message = firstIssue?.message ?? 'invalid input';\n return new NodeInputValidationError(\n `Node \"${node}\" input validation failed at \"${path}\": ${message}`,\n { node, issues },\n );\n }\n}\n\nexport class StepTimeoutError extends WorkflowError {\n readonly timeoutMs: number;\n readonly node?: string;\n\n constructor(timeoutMs: number, node?: string) {\n super(\n node\n ? `Node \"${node}\" timed out after ${timeoutMs}ms.`\n : `Step timed out after ${timeoutMs}ms.`,\n {\n code: 'STEP_TIMEOUT',\n details: { timeoutMs, ...(node === undefined ? {} : { node }) },\n },\n );\n this.timeoutMs = timeoutMs;\n this.node = node;\n }\n}\n\nexport class NodeExecutionError extends WorkflowError {\n readonly node: string;\n\n constructor(node: string, cause: unknown) {\n const causeMessage =\n cause instanceof Error ? cause.message : String(cause ?? 'Unknown error');\n super(`Node \"${node}\" failed: ${causeMessage}`, {\n code: 'NODE_EXECUTION_ERROR',\n details: { node },\n cause,\n });\n this.node = node;\n }\n}\n\nexport class WorkflowLifecycleError extends WorkflowError {\n constructor(message: string, details?: unknown) {\n super(message, { code: 'WORKFLOW_LIFECYCLE_ERROR', details });\n }\n}\n\nexport class ProjectSetupError extends WorkflowError {\n constructor(cause: unknown, details: { projectName: string }) {\n const causeMessage =\n cause instanceof Error ? cause.message : String(cause ?? 'Unknown error');\n super(`Project \"${details.projectName}\" setup failed: ${causeMessage}`, {\n code: 'PROJECT_SETUP_ERROR',\n details,\n cause,\n });\n }\n}\n\nexport class ProjectTeardownError extends WorkflowError {\n constructor(\n cause: unknown,\n details: { projectName: string; registrationIndex: number },\n ) {\n const causeMessage =\n cause instanceof Error ? cause.message : String(cause ?? 'Unknown error');\n super(`Project \"${details.projectName}\" teardown failed: ${causeMessage}`, {\n code: 'PROJECT_TEARDOWN_ERROR',\n details,\n cause,\n });\n }\n}\n\nexport class NodeScopeTeardownError extends WorkflowError {\n constructor(\n cause: unknown,\n details: {\n scope: 'case' | 'document';\n scopeId: string;\n node: string;\n registrationIndex: number;\n },\n ) {\n const causeMessage =\n cause instanceof Error ? cause.message : String(cause ?? 'Unknown error');\n super(\n `${details.scope === 'case' ? 'Case attempt' : 'Workflow document'} node teardown failed for \"${details.node}\": ${causeMessage}`,\n { code: 'NODE_SCOPE_TEARDOWN_ERROR', details, cause },\n );\n }\n}\n\nexport class FatalDeviceError extends WorkflowError {\n constructor(message: string, cause?: unknown) {\n super(message, { code: 'FATAL_DEVICE_ERROR', cause });\n }\n}\n\nexport const isFatalDeviceError = (error: unknown): boolean => {\n if (error instanceof FatalDeviceError) return true;\n if (error instanceof WorkflowError && error.code === 'FATAL_DEVICE_ERROR') {\n return true;\n }\n if (\n error instanceof Error &&\n /device offline|device not found|(?:adb|bdc|device) connection (?:was )?closed/i.test(\n error.message,\n )\n ) {\n return true;\n }\n return error instanceof Error && error.cause !== undefined\n ? isFatalDeviceError(error.cause)\n : false;\n};\n\nexport class CaseExecutionError extends WorkflowError {\n readonly result: import('./engine/types').CaseRunResult;\n\n constructor(result: import('./engine/types').CaseRunResult) {\n super(`Case \"${result.name}\" failed.`, {\n code: 'CASE_EXECUTION_FAILED',\n details: { caseId: result.caseId, runId: result.runId },\n });\n this.result = result;\n }\n}\n\nexport class WorkflowDocumentExecutionError extends WorkflowError {\n readonly result: import('./engine/types').WorkflowDocumentRunResult;\n\n constructor(result: import('./engine/types').WorkflowDocumentRunResult) {\n super(`Workflow document \"${result.sourcePath}\" failed.`, {\n code: 'WORKFLOW_DOCUMENT_EXECUTION_FAILED',\n details: {\n documentId: result.documentId,\n documentRunId: result.documentRunId,\n },\n });\n this.result = result;\n }\n}\n\nexport function normalizeNodeExecutionError(\n error: unknown,\n node: string,\n): WorkflowError {\n return error instanceof WorkflowError\n ? error\n : new NodeExecutionError(node, error);\n}\n","__webpack_require__.d = (exports, definition) => {\n\tfor(var key in definition) {\n if(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {\n Object.defineProperty(exports, key, { enumerable: true, get: definition[key] });\n }\n }\n};","__webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))","// define __esModule on exports\n__webpack_require__.r = (exports) => {\n\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n\t}\n\tObject.defineProperty(exports, '__esModule', { value: true });\n};","import { z } from 'zod/v4';\nimport { NodeDefinitionError } from '../errors';\nimport type {\n DefineNodeOptions,\n DefineNodeWithSchemaOptions,\n NodeDefinition,\n NodeDefinitionWithSchema,\n NodeInputSchema,\n} from './types';\n\nconst validateOptionalText = (\n value: unknown,\n field: 'title' | 'description',\n node: string,\n): void => {\n if (\n value !== undefined &&\n (typeof value !== 'string' || value.trim().length === 0)\n ) {\n throw new NodeDefinitionError(\n `Node \"${node}\" ${field} must be a non-empty string.`,\n { node, field },\n );\n }\n};\n\nconst validateInputSchema = (schema: unknown, node: string): void => {\n if (schema === undefined) return;\n if (!(schema instanceof z.ZodObject)) {\n throw new NodeDefinitionError(\n `Node \"${node}\" inputSchema must be a Zod object schema.`,\n { node, field: 'inputSchema' },\n );\n }\n if ('$' in schema.shape) {\n throw new NodeDefinitionError(\n `Node \"${node}\" inputSchema must not declare \"$\" as an input property.`,\n { node, field: 'inputSchema.$' },\n );\n }\n};\n\nconst validateDefinition = (options: {\n name: string;\n title?: unknown;\n description?: unknown;\n stringInputKey?: unknown;\n inputSchema?: unknown;\n execute: unknown;\n}): void => {\n if (!options || typeof options !== 'object') {\n throw new NodeDefinitionError('Node definition must be an object.');\n }\n\n if (typeof options.name !== 'string' || options.name.trim().length === 0) {\n throw new NodeDefinitionError('Node name must be a non-empty string.');\n }\n\n validateOptionalText(options.title, 'title', options.name);\n validateOptionalText(options.description, 'description', options.name);\n if (\n options.stringInputKey !== undefined &&\n options.stringInputKey !== false &&\n (typeof options.stringInputKey !== 'string' ||\n options.stringInputKey.trim().length === 0)\n ) {\n throw new NodeDefinitionError(\n `Node \"${options.name}\" stringInputKey must be a non-empty string or false.`,\n { node: options.name, field: 'stringInputKey' },\n );\n }\n validateInputSchema(options.inputSchema, options.name);\n\n if (\n typeof options.stringInputKey === 'string' &&\n options.inputSchema instanceof z.ZodObject &&\n !(options.stringInputKey in options.inputSchema.shape)\n ) {\n throw new NodeDefinitionError(\n `Node \"${options.name}\" stringInputKey must reference a field in inputSchema.`,\n { node: options.name, field: 'stringInputKey' },\n );\n }\n\n if (typeof options.execute !== 'function') {\n throw new NodeDefinitionError(\n `Node \"${options.name}\" must provide an execute function.`,\n { node: options.name },\n );\n }\n};\n\nexport function defineNode<\n TSchema extends NodeInputSchema,\n TData = unknown,\n TContext = unknown,\n>(\n options: DefineNodeWithSchemaOptions<TSchema, TData, TContext>,\n): NodeDefinitionWithSchema<TSchema, TData, TContext>;\n\nexport function defineNode<\n TInput = unknown,\n TData = unknown,\n TContext = unknown,\n>(\n options: DefineNodeOptions<TInput, TData, TContext>,\n): NodeDefinition<TInput, TData, TContext>;\n\nexport function defineNode(\n options: DefineNodeOptions<any, any, any>,\n): NodeDefinition<any, any, any> {\n validateDefinition(options);\n return options;\n}\n","import {\n type AgentTestRunnerNodeDefinition,\n type AgentTestRunnerNodeProvider,\n type CommonAgentTestRunnerApi,\n aiActInputSchema,\n aiActOptionsInputSchema,\n aiAssertInputSchema,\n aiAssertOptionsInputSchema,\n aiTapInputSchema,\n insightInputSchema,\n insightOptionsInputSchema,\n locateOptionsInputSchema,\n promptImageInputSchema,\n recordToReportInputSchema,\n recordToReportOptionsInputSchema,\n reportScreenshotInputSchema,\n structuredUserPromptInputSchema,\n userPromptInputSchema,\n} from '@midscene/core/agent/test-runner';\nimport { getDebug } from '@midscene/shared/logger';\nimport { z } from 'zod/v4';\nimport type { Awaitable } from '../engine/types';\nimport { NodeDefinitionError, NodeExecutionError } from '../errors';\nimport { defineNode } from '../node/define-node';\nimport type { NodeDefinition, NodeExecutionContext } from '../node/types';\n\nexport type MidsceneUIAgent = CommonAgentTestRunnerApi & {\n addDumpUpdateListener?(\n listener: (dump: string, execution?: MidsceneExecutionRef) => void,\n ): () => void;\n};\n\nexport {\n aiActInputSchema,\n aiActOptionsInputSchema,\n aiAssertInputSchema,\n aiAssertOptionsInputSchema,\n aiTapInputSchema,\n insightInputSchema,\n insightOptionsInputSchema,\n locateOptionsInputSchema,\n promptImageInputSchema,\n recordToReportInputSchema,\n recordToReportOptionsInputSchema,\n reportScreenshotInputSchema,\n structuredUserPromptInputSchema,\n userPromptInputSchema,\n};\n\nexport interface MidsceneExecutionRef {\n id?: string;\n}\n\nexport interface AgentProvider<TContext> {\n getAgent(\n runId: string,\n ctx: NodeExecutionContext<unknown, TContext>,\n ): Awaitable<MidsceneUIAgent>;\n // biome-ignore lint/suspicious/noConfusingVoidType: providers without a report intentionally return void.\n releaseAgent?(runId: string): Awaitable<AgentReleaseResult | void>;\n dispose?(): Awaitable<void>;\n}\n\nexport interface AgentReleaseResult {\n /** Absolute path to the finalized report for this Agent scope. */\n reportPath?: string;\n}\n\nexport const waitInputSchema = z.strictObject({\n duration: z.number().positive().describe('How long to wait.'),\n unit: z\n .enum(['ms', 's', 'min'])\n .default('ms')\n .describe('Duration unit: milliseconds, seconds, or minutes.'),\n});\n\nexport type AiActNodeInput = z.infer<typeof aiActInputSchema>;\nexport type AiAssertNodeInput = z.infer<typeof aiAssertInputSchema>;\nexport type AiTapNodeInput = z.infer<typeof aiTapInputSchema>;\nexport type InsightNodeInput = z.infer<typeof insightInputSchema>;\nexport type RecordToReportNodeInput = z.infer<typeof recordToReportInputSchema>;\nexport type WaitNodeInput = z.infer<typeof waitInputSchema>;\n\nexport interface CreateMidsceneNodesOptions<TContext> {\n getAgent?(\n ctx: NodeExecutionContext<unknown, TContext>,\n ): Awaitable<MidsceneUIAgent>;\n agentProvider?: AgentProvider<TContext>;\n /** Agent class that declares the Agent-backed Nodes to register. */\n agentClass: AgentTestRunnerNodeProvider;\n}\n\nconst waitFor = async (durationMs: number, signal: AbortSignal) => {\n if (signal.aborted) {\n throw signal.reason ?? new Error('Wait aborted.');\n }\n await new Promise<void>((resolve, reject) => {\n const timeout = setTimeout(() => {\n signal.removeEventListener('abort', abort);\n resolve();\n }, durationMs);\n const abort = () => {\n clearTimeout(timeout);\n reject(signal.reason ?? new Error('Wait aborted.'));\n };\n signal.addEventListener('abort', abort, { once: true });\n });\n};\n\n/** Adapt Agent-owned descriptions to executable Midscene Test Nodes. */\nexport const createAgentTestRunnerNodes = <TContext>(\n definitions: readonly AgentTestRunnerNodeDefinition[],\n getAgent: (\n ctx: NodeExecutionContext<unknown, TContext>,\n ) => Awaitable<unknown>,\n): readonly NodeDefinition<any, any, TContext>[] => {\n const activeAgentCalls = new WeakMap<\n MidsceneUIAgent,\n { scopeId: string; node: string }\n >();\n const runAgentCall = async <T>(\n node: string,\n ctx: NodeExecutionContext<unknown, TContext>,\n agent: MidsceneUIAgent,\n call: () => Promise<T>,\n captureExecutions = true,\n ): Promise<T> => {\n const scopeId =\n ctx.scope === 'case' ? ctx.case.runId : ctx.document.documentRunId;\n const activeCall = activeAgentCalls.get(agent);\n if (activeCall) {\n throw new NodeExecutionError(\n node,\n new Error(\n `The same Agent instance cannot execute overlapping Midscene Test Steps. Active scope: ${activeCall.scopeId} (${activeCall.node}); requested scope: ${scopeId} (${node}).`,\n ),\n );\n }\n\n activeAgentCalls.set(agent, { scopeId, node });\n let removeListener: (() => void) | undefined;\n let sawExecutionWithoutId = false;\n const stopListening = () => {\n const remove = removeListener;\n removeListener = undefined;\n remove?.();\n };\n const stopListeningOnAbort = () => stopListening();\n try {\n if (captureExecutions && agent.addDumpUpdateListener) {\n removeListener = agent.addDumpUpdateListener((_dump, execution) => {\n if (!execution) return;\n if (!execution.id) {\n sawExecutionWithoutId = true;\n return;\n }\n ctx.report.addTrace({\n type: 'midscene-execution',\n executionId: execution.id,\n });\n });\n if (ctx.signal.aborted) stopListening();\n else {\n ctx.signal.addEventListener('abort', stopListeningOnAbort, {\n once: true,\n });\n }\n }\n return await call();\n } finally {\n ctx.signal.removeEventListener('abort', stopListeningOnAbort);\n try {\n stopListening();\n } finally {\n activeAgentCalls.delete(agent);\n }\n if (sawExecutionWithoutId) {\n warnReportTrace(\n `Skipped a report trace without a stable execution id for ${node} in scope ${scopeId}.`,\n );\n }\n }\n };\n\n return definitions.map((definition) =>\n defineNode({\n name: definition.name,\n ...(definition.title === undefined ? {} : { title: definition.title }),\n ...(definition.description === undefined\n ? {}\n : { description: definition.description }),\n ...(definition.stringInputKey === undefined\n ? {}\n : { stringInputKey: definition.stringInputKey }),\n inputSchema: definition.inputSchema,\n async execute(ctx) {\n const agent = await getAgent(ctx);\n const call = async () =>\n definition.execute(agent, ctx.input, { signal: ctx.signal });\n if (typeof agent !== 'object' || agent === null) return call();\n return runAgentCall(\n definition.name,\n ctx,\n agent as MidsceneUIAgent,\n call,\n );\n },\n }),\n );\n};\n\nconst warnReportTrace = getDebug('test-runner:report-trace', {\n console: true,\n});\n\nexport function createMidsceneNodes<TContext>(\n options: CreateMidsceneNodesOptions<TContext>,\n): readonly NodeDefinition<any, any, TContext>[] {\n if (!options || typeof options !== 'object') {\n throw new NodeDefinitionError(\n 'createMidsceneNodes() options must be an object.',\n );\n }\n if (\n typeof options.agentProvider?.getAgent !== 'function' &&\n typeof options.getAgent !== 'function'\n ) {\n throw new NodeDefinitionError(\n 'createMidsceneNodes() requires getAgent or agentProvider.getAgent.',\n );\n }\n if (\n !options.agentClass ||\n typeof options.agentClass.getTestRunnerNodeDefinitions !== 'function'\n ) {\n throw new NodeDefinitionError(\n 'createMidsceneNodes() requires agentClass.getTestRunnerNodeDefinitions().',\n );\n }\n\n const registeredAgentScopes = new Set<string>();\n const getExecutionId = (ctx: NodeExecutionContext<unknown, TContext>) =>\n ctx.scope === 'case' ? ctx.case.runId : ctx.document.documentRunId;\n const getAgent = async (\n ctx: NodeExecutionContext<unknown, TContext>,\n ): Promise<MidsceneUIAgent> => {\n if (!options.agentProvider) return options.getAgent!(ctx);\n const runId = getExecutionId(ctx);\n if (\n options.agentProvider.releaseAgent &&\n !registeredAgentScopes.has(runId)\n ) {\n registeredAgentScopes.add(runId);\n ctx.onTeardown(async () => {\n try {\n const released = await options.agentProvider!.releaseAgent!(runId);\n return released?.reportPath\n ? { reportPaths: [released.reportPath] }\n : undefined;\n } finally {\n registeredAgentScopes.delete(runId);\n }\n });\n }\n return options.agentProvider.getAgent(runId, ctx);\n };\n\n const agentDefinitions = options.agentClass.getTestRunnerNodeDefinitions();\n\n return [\n ...createAgentTestRunnerNodes(agentDefinitions, getAgent),\n defineNode<typeof waitInputSchema, unknown, TContext>({\n name: 'wait',\n description: 'Wait for a fixed duration while honoring cancellation.',\n stringInputKey: false,\n inputSchema: waitInputSchema,\n async execute(ctx) {\n const multiplier =\n ctx.input.unit === 'min'\n ? 60_000\n : ctx.input.unit === 's'\n ? 1_000\n : 1;\n const durationMs = ctx.input.duration * multiplier;\n await waitFor(durationMs, ctx.signal);\n return { summary: `Waited ${durationMs}ms` };\n },\n }),\n ];\n}\n"],"names":["WorkflowError","Error","undefined","message","options","NodeDefinitionError","details","NodeExecutionError","node","cause","causeMessage","String","__webpack_require__","definition","key","Object","obj","prop","Symbol","validateOptionalText","value","field","validateInputSchema","schema","z","validateDefinition","defineNode","waitInputSchema","waitFor","durationMs","signal","Promise","resolve","reject","timeout","setTimeout","abort","clearTimeout","createAgentTestRunnerNodes","definitions","getAgent","activeAgentCalls","WeakMap","runAgentCall","ctx","agent","call","captureExecutions","scopeId","activeCall","removeListener","sawExecutionWithoutId","stopListening","remove","stopListeningOnAbort","_dump","execution","warnReportTrace","getDebug","createMidsceneNodes","registeredAgentScopes","Set","getExecutionId","runId","released","agentDefinitions","multiplier"],"mappings":"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"}