@midscene/test 1.12.0 → 1.12.1-beta-20260824081526.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.
@@ -0,0 +1,127 @@
1
+ import { z } from "zod/v4";
2
+ function _define_property(obj, key, value) {
3
+ if (key in obj) Object.defineProperty(obj, key, {
4
+ value: value,
5
+ enumerable: true,
6
+ configurable: true,
7
+ writable: true
8
+ });
9
+ else obj[key] = value;
10
+ return obj;
11
+ }
12
+ class WorkflowError extends Error {
13
+ toJSON() {
14
+ return {
15
+ name: this.name,
16
+ message: this.message,
17
+ code: this.code,
18
+ ...void 0 === this.details ? {} : {
19
+ details: this.details
20
+ }
21
+ };
22
+ }
23
+ constructor(message, options = {}){
24
+ super(message, {
25
+ cause: options.cause
26
+ }), _define_property(this, "code", void 0), _define_property(this, "details", void 0);
27
+ this.name = new.target.name;
28
+ this.code = options.code ?? 'WORKFLOW_ERROR';
29
+ this.details = options.details;
30
+ }
31
+ }
32
+ class NodeDefinitionError extends WorkflowError {
33
+ constructor(message, details){
34
+ super(message, {
35
+ code: 'NODE_DEFINITION_ERROR',
36
+ details
37
+ });
38
+ }
39
+ }
40
+ class NodeExecutionError extends WorkflowError {
41
+ constructor(node, cause){
42
+ const causeMessage = cause instanceof Error ? cause.message : String(cause ?? 'Unknown error');
43
+ super(`Node "${node}" failed: ${causeMessage}`, {
44
+ code: 'NODE_EXECUTION_ERROR',
45
+ details: {
46
+ node
47
+ },
48
+ cause
49
+ }), _define_property(this, "node", void 0);
50
+ this.node = node;
51
+ }
52
+ }
53
+ const validateOptionalText = (value, field, node)=>{
54
+ if (void 0 !== value && ('string' != typeof value || 0 === value.trim().length)) throw new NodeDefinitionError(`Node "${node}" ${field} must be a non-empty string.`, {
55
+ node,
56
+ field
57
+ });
58
+ };
59
+ const validateInputSchema = (schema, node)=>{
60
+ if (void 0 === schema) return;
61
+ if (!(schema instanceof z.ZodObject)) throw new NodeDefinitionError(`Node "${node}" inputSchema must be a Zod object schema.`, {
62
+ node,
63
+ field: 'inputSchema'
64
+ });
65
+ if ('$' in schema.shape) throw new NodeDefinitionError(`Node "${node}" inputSchema must not declare "$" as an input property.`, {
66
+ node,
67
+ field: 'inputSchema.$'
68
+ });
69
+ };
70
+ const validateDefinition = (options)=>{
71
+ if (!options || 'object' != typeof options) throw new NodeDefinitionError('Node definition must be an object.');
72
+ if ('string' != typeof options.name || 0 === options.name.trim().length) throw new NodeDefinitionError('Node name must be a non-empty string.');
73
+ validateOptionalText(options.title, 'title', options.name);
74
+ validateOptionalText(options.description, "description", options.name);
75
+ validateInputSchema(options.inputSchema, options.name);
76
+ if ('function' != typeof options.execute) throw new NodeDefinitionError(`Node "${options.name}" must provide an execute function.`, {
77
+ node: options.name
78
+ });
79
+ };
80
+ function defineNode(options) {
81
+ validateDefinition(options);
82
+ return options;
83
+ }
84
+ const runAdbShellInputSchema = z.strictObject({
85
+ prompt: z.string().regex(/\S/).optional().describe('String shorthand for the ADB shell command.'),
86
+ command: z.string().regex(/\S/).optional().describe('The shell command, without an adb shell prefix.'),
87
+ timeoutMs: z.number().int().positive().optional().describe('ADB shell command timeout in milliseconds.')
88
+ }).superRefine((input, ctx)=>{
89
+ if (void 0 === input.prompt === (void 0 === input.command)) ctx.addIssue({
90
+ code: 'custom',
91
+ message: 'exactly one of prompt and command is required'
92
+ });
93
+ });
94
+ function createAndroidNodes(options) {
95
+ if (!options || 'object' != typeof options) throw new NodeDefinitionError('createAndroidNodes() options must be an object.');
96
+ if ('function' != typeof options.getAgent) throw new NodeDefinitionError('createAndroidNodes() requires getAgent().');
97
+ return [
98
+ defineNode({
99
+ name: 'runAdbShell',
100
+ title: 'Run an ADB shell command',
101
+ description: 'Execute a shell command through the current Android Agent. Pass only the shell command, without the adb shell prefix.',
102
+ inputSchema: runAdbShellInputSchema,
103
+ async execute (ctx) {
104
+ if (ctx.signal.aborted) throw ctx.signal.reason ?? new Error('runAdbShell aborted.');
105
+ const command = ctx.input.command ?? ctx.input.prompt;
106
+ if (/^\s*adb(?:\s|$)/i.test(command)) throw new NodeExecutionError('runAdbShell', new TypeError('command must not include an adb or adb shell prefix.'));
107
+ const agent = await options.getAgent(ctx);
108
+ if ('function' != typeof agent?.runAdbShell) throw new NodeExecutionError('runAdbShell', new TypeError('getAgent() must return an Android Agent with runAdbShell().'));
109
+ const stdout = await agent.runAdbShell(command, {
110
+ ...void 0 === ctx.input.timeoutMs ? {} : {
111
+ timeout: ctx.input.timeoutMs
112
+ }
113
+ });
114
+ if ('string' != typeof stdout) throw new NodeExecutionError('runAdbShell', new TypeError('runAdbShell() must return stdout as a string.'));
115
+ return {
116
+ summary: `Executed ADB shell command (${stdout.length} stdout characters)`,
117
+ data: {
118
+ stdout
119
+ }
120
+ };
121
+ }
122
+ })
123
+ ];
124
+ }
125
+ export { createAndroidNodes, runAdbShellInputSchema };
126
+
127
+ //# sourceMappingURL=index.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"android/index.mjs","sources":["../../../src/errors.ts","../../../src/node/define-node.ts","../../../src/android/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 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 validateInputSchema(options.inputSchema, options.name);\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 { 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\ntype NodeContext<TContext> = NodeExecutionContext<unknown, TContext>;\n\n/** Minimal Android Agent capability required by the preset Node. */\nexport interface AndroidRunnerAgent {\n /** Execute a command in the connected Android device shell. */\n runAdbShell?(\n command: string,\n options?: { timeout?: number },\n ): Promise<string>;\n}\n\n/** Dependencies used by the Android preset Nodes. */\nexport interface CreateAndroidNodesOptions<TContext> {\n /** Return the Android Agent associated with the current workflow. */\n getAgent(ctx: NodeContext<TContext>): Awaitable<AndroidRunnerAgent>;\n}\n\n/** Input schema for the Android runAdbShell Node. */\nexport const runAdbShellInputSchema = z\n .strictObject({\n prompt: z\n .string()\n .regex(/\\S/)\n .optional()\n .describe('String shorthand for the ADB shell command.'),\n command: z\n .string()\n .regex(/\\S/)\n .optional()\n .describe('The shell command, without an adb shell prefix.'),\n timeoutMs: z\n .number()\n .int()\n .positive()\n .optional()\n .describe('ADB shell command timeout in milliseconds.'),\n })\n .superRefine((input, ctx) => {\n if ((input.prompt === undefined) === (input.command === undefined)) {\n ctx.addIssue({\n code: 'custom',\n message: 'exactly one of prompt and command is required',\n });\n }\n });\n\n/** Validated input accepted by the Android runAdbShell Node. */\nexport type RunAdbShellNodeInput = z.infer<typeof runAdbShellInputSchema>;\n\n/** Create the P0 Android preset Nodes for an injected Android Agent. */\nexport function createAndroidNodes<TContext>(\n options: CreateAndroidNodesOptions<TContext>,\n): readonly NodeDefinition<any, any, TContext>[] {\n if (!options || typeof options !== 'object') {\n throw new NodeDefinitionError(\n 'createAndroidNodes() options must be an object.',\n );\n }\n if (typeof options.getAgent !== 'function') {\n throw new NodeDefinitionError('createAndroidNodes() requires getAgent().');\n }\n\n return [\n defineNode<typeof runAdbShellInputSchema, { stdout: string }, TContext>({\n name: 'runAdbShell',\n title: 'Run an ADB shell command',\n description:\n 'Execute a shell command through the current Android Agent. Pass only the shell command, without the adb shell prefix.',\n inputSchema: runAdbShellInputSchema,\n async execute(ctx) {\n if (ctx.signal.aborted) {\n throw ctx.signal.reason ?? new Error('runAdbShell aborted.');\n }\n const command = ctx.input.command ?? ctx.input.prompt!;\n if (/^\\s*adb(?:\\s|$)/i.test(command)) {\n throw new NodeExecutionError(\n 'runAdbShell',\n new TypeError(\n 'command must not include an adb or adb shell prefix.',\n ),\n );\n }\n const agent = await options.getAgent(ctx);\n if (typeof agent?.runAdbShell !== 'function') {\n throw new NodeExecutionError(\n 'runAdbShell',\n new TypeError(\n 'getAgent() must return an Android Agent with runAdbShell().',\n ),\n );\n }\n const stdout = await agent.runAdbShell(command, {\n ...(ctx.input.timeoutMs === undefined\n ? {}\n : { timeout: ctx.input.timeoutMs }),\n });\n if (typeof stdout !== 'string') {\n throw new NodeExecutionError(\n 'runAdbShell',\n new TypeError('runAdbShell() must return stdout as a string.'),\n );\n }\n return {\n summary: `Executed ADB shell command (${stdout.length} stdout characters)`,\n data: { stdout },\n };\n },\n }),\n ];\n}\n"],"names":["WorkflowError","Error","undefined","message","options","NodeDefinitionError","details","NodeExecutionError","node","cause","causeMessage","String","validateOptionalText","value","field","validateInputSchema","schema","z","validateDefinition","defineNode","runAdbShellInputSchema","input","ctx","createAndroidNodes","command","TypeError","agent","stdout"],"mappings":"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"}
@@ -519,7 +519,11 @@ const assertTypeScriptConfig = (absolutePath)=>{
519
519
  throw new TypeError(`Unsupported Midscene config extension: ${extension}. Supported extension: .ts.`);
520
520
  }
521
521
  };
522
- const canRetryWithCjsLoader = (error)=>error instanceof SyntaxError && (/^Unexpected (?:identifier|reserved word|token)/.test(error.message) || 'ERR_UNSUPPORTED_TYPESCRIPT_SYNTAX' === error.code);
522
+ const canRetryWithCjsLoader = (error)=>{
523
+ if (!(error instanceof Error)) return false;
524
+ const errorCode = error.code;
525
+ return error instanceof SyntaxError && /^Unexpected (?:identifier|reserved word|token)/.test(error.message) || 'ERR_UNSUPPORTED_TYPESCRIPT_SYNTAX' === errorCode || 'ERR_UNKNOWN_FILE_EXTENSION' === errorCode;
526
+ };
523
527
  async function loadTestProject(configPath) {
524
528
  if (!configPath) return validateTestProjectDefinition({
525
529
  nodes: []