@midscene/test 1.15.4 → 1.15.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/es/midscene/index.mjs +2 -2
- package/dist/es/midscene/index.mjs.map +1 -1
- package/dist/es/test-cli.mjs +1 -1
- package/dist/lib/midscene/index.js +3 -0
- package/dist/lib/midscene/index.js.map +1 -1
- package/dist/lib/test-cli.js +1 -1
- package/dist/templates/test/web/cases/todo.yaml +6 -3
- package/dist/types/midscene/index.d.ts +6 -2
- package/package.json +13 -13
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { actionInputSchema, aiActInputSchema, aiActOptionsInputSchema, aiAssertInputSchema, aiAssertOptionsInputSchema, aiDragAndDropInputSchema, aiInputInputSchema, aiKeyboardPressInputSchema, aiLongPressInputSchema, aiPinchInputSchema, aiQueryInputSchema, aiScrollInputSchema, aiTapInputSchema, aiWaitForInputSchema, insightInputSchema, insightOptionsInputSchema, javascriptInputSchema, locateOptionsInputSchema, promptImageInputSchema, recordToReportInputSchema, recordToReportOptionsInputSchema, reportScreenshotInputSchema, runGherkinScenarioInputSchema, setAIContextInputSchema, structuredUserPromptInputSchema, userPromptInputSchema } from "@midscene/core/agent/test";
|
|
1
|
+
import { actionInputSchema, aiActInputSchema, aiActOptionsInputSchema, aiAssertInputSchema, aiAssertOptionsInputSchema, aiDragAndDropInputSchema, aiInputInputSchema, aiKeyboardPressInputSchema, aiLongPressInputSchema, aiPinchInputSchema, aiQueryInputSchema, aiScrollInputSchema, aiTapInputSchema, aiWaitForInputSchema, aiWaitForOptionsInputSchema, insightInputSchema, insightOptionsInputSchema, javascriptInputSchema, locateOptionsInputSchema, promptImageInputSchema, recordToReportInputSchema, recordToReportOptionsInputSchema, reportScreenshotInputSchema, runGherkinScenarioInputSchema, setAIContextInputSchema, structuredUserPromptInputSchema, userPromptInputSchema } from "@midscene/core/agent/test";
|
|
2
2
|
import { NodeDefinitionError, admitResourceOperation, collectTestRunReportMetrics, defineNode, hasPendingResourceOperation, retainResourceForScope, trackResourceOperation } from "@midscene/core/internal/test-runner";
|
|
3
3
|
import { enterYamlAction, enterYamlExecution, runInYamlExecutionContext } from "@midscene/core/internal/yaml-runtime";
|
|
4
4
|
import { getDebug } from "@midscene/shared/logger";
|
|
@@ -192,6 +192,6 @@ function createMidsceneNodes(options) {
|
|
|
192
192
|
})
|
|
193
193
|
];
|
|
194
194
|
}
|
|
195
|
-
export { actionInputSchema, aiActInputSchema, aiActOptionsInputSchema, aiAssertInputSchema, aiAssertOptionsInputSchema, aiDragAndDropInputSchema, aiInputInputSchema, aiKeyboardPressInputSchema, aiLongPressInputSchema, aiPinchInputSchema, aiQueryInputSchema, aiScrollInputSchema, aiTapInputSchema, aiWaitForInputSchema, createAgentTestRunnerNodes, createMidsceneNodes, insightInputSchema, insightOptionsInputSchema, javascriptInputSchema, locateOptionsInputSchema, promptImageInputSchema, recordToReportInputSchema, recordToReportOptionsInputSchema, reportScreenshotInputSchema, runGherkinScenarioInputSchema, setAIContextInputSchema, structuredUserPromptInputSchema, userPromptInputSchema, waitInputSchema };
|
|
195
|
+
export { actionInputSchema, aiActInputSchema, aiActOptionsInputSchema, aiAssertInputSchema, aiAssertOptionsInputSchema, aiDragAndDropInputSchema, aiInputInputSchema, aiKeyboardPressInputSchema, aiLongPressInputSchema, aiPinchInputSchema, aiQueryInputSchema, aiScrollInputSchema, aiTapInputSchema, aiWaitForInputSchema, aiWaitForOptionsInputSchema, createAgentTestRunnerNodes, createMidsceneNodes, insightInputSchema, insightOptionsInputSchema, javascriptInputSchema, locateOptionsInputSchema, promptImageInputSchema, recordToReportInputSchema, recordToReportOptionsInputSchema, reportScreenshotInputSchema, runGherkinScenarioInputSchema, setAIContextInputSchema, structuredUserPromptInputSchema, userPromptInputSchema, waitInputSchema };
|
|
196
196
|
|
|
197
197
|
//# sourceMappingURL=index.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"midscene/index.mjs","sources":["../../../src/node/define-node.ts","../../../src/midscene/index.ts"],"sourcesContent":["import { defineNode as coreDefineNode } from '@midscene/core/internal/test-runner';\nimport type {\n DefineNodeOptions,\n DefineNodeWithSchemaOptions,\n NodeDefinition,\n NodeDefinitionWithSchema,\n NodeInputSchema,\n} from './types';\n\n// A type-only facade: validation and execution still belong to the shared kernel.\ninterface DefineNativeNode {\n <TSchema extends NodeInputSchema, TData = unknown, TContext = unknown>(\n options: DefineNodeWithSchemaOptions<TSchema, TData, TContext>,\n ): NodeDefinitionWithSchema<TSchema, TData, TContext>;\n <TInput = unknown, TData = unknown, TContext = unknown>(\n options: DefineNodeOptions<TInput, TData, TContext>,\n ): NodeDefinition<TInput, TData, TContext>;\n}\nexport const defineNode: DefineNativeNode = coreDefineNode;\n","import type { IExecutionDump } from '@midscene/core';\nimport {\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';\nimport {\n type WorkflowReportSource,\n admitResourceOperation,\n collectTestRunReportMetrics,\n hasPendingResourceOperation,\n retainResourceForScope,\n trackResourceOperation,\n} from '@midscene/core/internal/test-runner';\nimport {\n enterYamlAction,\n enterYamlExecution,\n runInYamlExecutionContext,\n} from '@midscene/core/internal/yaml-runtime';\nimport { getDebug } from '@midscene/shared/logger';\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 _prepareForTestRunner?(): void;\n _createReportSource?(\n scopeId: string,\n executionIds?: readonly string[],\n ): Promise<WorkflowReportSource | undefined>;\n flushReport?(): Promise<string | undefined>;\n addDumpUpdateListener?(\n listener: (dump: string, execution?: MidsceneExecutionRef) => void,\n ): () => void;\n};\n\nexport {\n actionInputSchema,\n aiDragAndDropInputSchema,\n aiInputInputSchema,\n aiKeyboardPressInputSchema,\n aiLongPressInputSchema,\n aiPinchInputSchema,\n aiQueryInputSchema,\n aiScrollInputSchema,\n aiWaitForInputSchema,\n javascriptInputSchema,\n runGherkinScenarioInputSchema,\n setAIContextInputSchema,\n} from '@midscene/core/agent/test';\nexport type {\n ActionNodeInput,\n AiDragAndDropNodeInput,\n AiInputNodeInput,\n AiKeyboardPressNodeInput,\n AiLongPressNodeInput,\n AiPinchNodeInput,\n AiQueryNodeInput,\n AiScrollNodeInput,\n AiWaitForNodeInput,\n JavascriptNodeInput,\n RunGherkinScenarioNodeInput,\n SetAIContextNodeInput,\n} from '@midscene/core/agent/test';\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 tasks?: IExecutionDump['tasks'];\n}\n\nexport interface AgentProvider<TContext> {\n getAgent(\n runId: string,\n execution: 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 execution: 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 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 runInYamlExecutionContext(async () => {\n const scopeId =\n ctx.scope === 'case' ? ctx.case.runId : ctx.document.documentRunId;\n const isCleanupOwner = admitResourceOperation(agent, ctx.signal);\n if (captureExecutions) {\n ctx.report.onSnapshot(async (signal, traces) => {\n signal.throwIfAborted();\n const partial = hasPendingResourceOperation(agent);\n const capturedAt = new Date().toISOString();\n let source = await agent._createReportSource?.(\n scopeId,\n traces.map((trace) => trace.executionId),\n );\n // External adapters may only expose HTML. Capture it independently\n // of cleanup, while marking its mutable source as partial.\n if (!source) {\n const path = await agent.flushReport?.();\n if (path)\n source = {\n sourcePath: path,\n collection: {\n status: 'partial',\n capturedAt,\n reason:\n 'This provider exposes live HTML without immutable snapshot support.',\n },\n };\n }\n signal.throwIfAborted();\n if (!source)\n throw new Error('Agent did not return a report snapshot.');\n return {\n ...source,\n collection: {\n status:\n partial || source.collection?.status === 'partial'\n ? ('partial' as const)\n : ('complete' as const),\n capturedAt: source.collection?.capturedAt ?? capturedAt,\n ...(source.collection?.reason\n ? { reason: source.collection.reason }\n : partial\n ? {\n reason:\n 'An Agent operation was still running at the snapshot cutoff.',\n }\n : {}),\n },\n };\n });\n }\n // Native Steps own the root report. Any Agent.runYaml invoked underneath\n // contributes to that Step instead of publishing another root snapshot.\n const yamlBoundary = enterYamlExecution(agent, {\n allowIndependentOverlap: isCleanupOwner,\n });\n const leaveYamlAction = enterYamlAction(agent, ctx.signal);\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 ...(execution.tasks\n ? {\n metrics: collectTestRunReportMetrics({\n executions: [\n {\n id: execution.id,\n name: node,\n logTime: 0,\n tasks: execution.tasks,\n },\n ],\n }),\n }\n : {}),\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 trackResourceOperation(\n agent,\n Promise.resolve().then(call),\n ctx.signal,\n );\n } finally {\n leaveYamlAction();\n yamlBoundary.finish();\n ctx.signal.removeEventListener('abort', stopListeningOnAbort);\n stopListening();\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 ctx.signal.throwIfAborted();\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 agentsByScope = new Map<string, Set<MidsceneUIAgent>>();\n const getAgent = async (\n ctx: NodeExecutionContext<unknown, TContext>,\n ): Promise<MidsceneUIAgent> => {\n const runId =\n ctx.scope === 'case' ? ctx.case.runId : ctx.document.documentRunId;\n let agents = agentsByScope.get(runId);\n if (!agents) {\n agents = new Set();\n agentsByScope.set(runId, agents);\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 agentsByScope.delete(runId);\n }\n });\n }\n const scopeAgents = agents;\n // Acquisition can outlive cancellation. Teardown waits for actual settlement.\n return trackResourceOperation(\n {},\n Promise.resolve().then(async () => {\n const agent = options.agentProvider\n ? await options.agentProvider.getAgent(runId, ctx)\n : await options.getAgent!(ctx);\n retainResourceForScope(agent, ctx.signal);\n agent._prepareForTestRunner?.();\n scopeAgents.add(agent);\n return agent;\n }),\n ctx.signal,\n 'acquisition',\n );\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(execution) {\n const multiplier =\n execution.input.unit === 'min'\n ? 60_000\n : execution.input.unit === 's'\n ? 1_000\n : 1;\n const durationMs = execution.input.duration * multiplier;\n await waitFor(durationMs, execution.signal);\n return { summary: `Waited ${durationMs}ms` };\n },\n }),\n ];\n}\n"],"names":["defineNode","coreDefineNode","waitInputSchema","z","waitFor","durationMs","signal","Error","Promise","resolve","reject","timeout","setTimeout","abort","clearTimeout","createAgentTestRunnerNodes","definitions","getAgent","runAgentCall","node","ctx","agent","call","captureExecutions","runInYamlExecutionContext","scopeId","isCleanupOwner","admitResourceOperation","traces","partial","hasPendingResourceOperation","capturedAt","Date","source","trace","path","yamlBoundary","enterYamlExecution","leaveYamlAction","enterYamlAction","removeListener","sawExecutionWithoutId","stopListening","remove","undefined","stopListeningOnAbort","_dump","execution","collectTestRunReportMetrics","trackResourceOperation","warnReportTrace","definition","getDebug","createMidsceneNodes","options","NodeDefinitionError","agentsByScope","Map","runId","agents","Set","released","scopeAgents","retainResourceForScope","agentDefinitions","multiplier"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"midscene/index.mjs","sources":["../../../src/node/define-node.ts","../../../src/midscene/index.ts"],"sourcesContent":["import { defineNode as coreDefineNode } from '@midscene/core/internal/test-runner';\nimport type {\n DefineNodeOptions,\n DefineNodeWithSchemaOptions,\n NodeDefinition,\n NodeDefinitionWithSchema,\n NodeInputSchema,\n} from './types';\n\n// A type-only facade: validation and execution still belong to the shared kernel.\ninterface DefineNativeNode {\n <TSchema extends NodeInputSchema, TData = unknown, TContext = unknown>(\n options: DefineNodeWithSchemaOptions<TSchema, TData, TContext>,\n ): NodeDefinitionWithSchema<TSchema, TData, TContext>;\n <TInput = unknown, TData = unknown, TContext = unknown>(\n options: DefineNodeOptions<TInput, TData, TContext>,\n ): NodeDefinition<TInput, TData, TContext>;\n}\nexport const defineNode: DefineNativeNode = coreDefineNode;\n","import type { IExecutionDump } from '@midscene/core';\nimport {\n type AgentTestRunnerNodeDefinition,\n type AgentTestRunnerNodeProvider,\n type CommonAgentTestRunnerApi,\n aiActInputSchema,\n aiActOptionsInputSchema,\n aiAssertInputSchema,\n aiAssertOptionsInputSchema,\n aiTapInputSchema,\n aiWaitForInputSchema,\n aiWaitForOptionsInputSchema,\n insightInputSchema,\n insightOptionsInputSchema,\n locateOptionsInputSchema,\n promptImageInputSchema,\n recordToReportInputSchema,\n recordToReportOptionsInputSchema,\n reportScreenshotInputSchema,\n structuredUserPromptInputSchema,\n userPromptInputSchema,\n} from '@midscene/core/agent/test';\nimport {\n type WorkflowReportSource,\n admitResourceOperation,\n collectTestRunReportMetrics,\n hasPendingResourceOperation,\n retainResourceForScope,\n trackResourceOperation,\n} from '@midscene/core/internal/test-runner';\nimport {\n enterYamlAction,\n enterYamlExecution,\n runInYamlExecutionContext,\n} from '@midscene/core/internal/yaml-runtime';\nimport { getDebug } from '@midscene/shared/logger';\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 _prepareForTestRunner?(): void;\n _createReportSource?(\n scopeId: string,\n executionIds?: readonly string[],\n ): Promise<WorkflowReportSource | undefined>;\n flushReport?(): Promise<string | undefined>;\n addDumpUpdateListener?(\n listener: (dump: string, execution?: MidsceneExecutionRef) => void,\n ): () => void;\n};\n\nexport {\n actionInputSchema,\n aiDragAndDropInputSchema,\n aiInputInputSchema,\n aiKeyboardPressInputSchema,\n aiLongPressInputSchema,\n aiPinchInputSchema,\n aiQueryInputSchema,\n aiScrollInputSchema,\n javascriptInputSchema,\n runGherkinScenarioInputSchema,\n setAIContextInputSchema,\n} from '@midscene/core/agent/test';\nexport type {\n ActionNodeInput,\n AiDragAndDropNodeInput,\n AiInputNodeInput,\n AiKeyboardPressNodeInput,\n AiLongPressNodeInput,\n AiPinchNodeInput,\n AiQueryNodeInput,\n AiScrollNodeInput,\n JavascriptNodeInput,\n RunGherkinScenarioNodeInput,\n SetAIContextNodeInput,\n} from '@midscene/core/agent/test';\n\nexport {\n aiActInputSchema,\n aiActOptionsInputSchema,\n aiAssertInputSchema,\n aiAssertOptionsInputSchema,\n aiWaitForInputSchema,\n aiWaitForOptionsInputSchema,\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 tasks?: IExecutionDump['tasks'];\n}\n\nexport interface AgentProvider<TContext> {\n getAgent(\n runId: string,\n execution: 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 AiWaitForNodeInput = z.infer<typeof aiWaitForInputSchema>;\nexport type AiWaitForNodeOptions = z.infer<typeof aiWaitForOptionsInputSchema>;\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 execution: 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 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 runInYamlExecutionContext(async () => {\n const scopeId =\n ctx.scope === 'case' ? ctx.case.runId : ctx.document.documentRunId;\n const isCleanupOwner = admitResourceOperation(agent, ctx.signal);\n if (captureExecutions) {\n ctx.report.onSnapshot(async (signal, traces) => {\n signal.throwIfAborted();\n const partial = hasPendingResourceOperation(agent);\n const capturedAt = new Date().toISOString();\n let source = await agent._createReportSource?.(\n scopeId,\n traces.map((trace) => trace.executionId),\n );\n // External adapters may only expose HTML. Capture it independently\n // of cleanup, while marking its mutable source as partial.\n if (!source) {\n const path = await agent.flushReport?.();\n if (path)\n source = {\n sourcePath: path,\n collection: {\n status: 'partial',\n capturedAt,\n reason:\n 'This provider exposes live HTML without immutable snapshot support.',\n },\n };\n }\n signal.throwIfAborted();\n if (!source)\n throw new Error('Agent did not return a report snapshot.');\n return {\n ...source,\n collection: {\n status:\n partial || source.collection?.status === 'partial'\n ? ('partial' as const)\n : ('complete' as const),\n capturedAt: source.collection?.capturedAt ?? capturedAt,\n ...(source.collection?.reason\n ? { reason: source.collection.reason }\n : partial\n ? {\n reason:\n 'An Agent operation was still running at the snapshot cutoff.',\n }\n : {}),\n },\n };\n });\n }\n // Native Steps own the root report. Any Agent.runYaml invoked underneath\n // contributes to that Step instead of publishing another root snapshot.\n const yamlBoundary = enterYamlExecution(agent, {\n allowIndependentOverlap: isCleanupOwner,\n });\n const leaveYamlAction = enterYamlAction(agent, ctx.signal);\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 ...(execution.tasks\n ? {\n metrics: collectTestRunReportMetrics({\n executions: [\n {\n id: execution.id,\n name: node,\n logTime: 0,\n tasks: execution.tasks,\n },\n ],\n }),\n }\n : {}),\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 trackResourceOperation(\n agent,\n Promise.resolve().then(call),\n ctx.signal,\n );\n } finally {\n leaveYamlAction();\n yamlBoundary.finish();\n ctx.signal.removeEventListener('abort', stopListeningOnAbort);\n stopListening();\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 ctx.signal.throwIfAborted();\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 agentsByScope = new Map<string, Set<MidsceneUIAgent>>();\n const getAgent = async (\n ctx: NodeExecutionContext<unknown, TContext>,\n ): Promise<MidsceneUIAgent> => {\n const runId =\n ctx.scope === 'case' ? ctx.case.runId : ctx.document.documentRunId;\n let agents = agentsByScope.get(runId);\n if (!agents) {\n agents = new Set();\n agentsByScope.set(runId, agents);\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 agentsByScope.delete(runId);\n }\n });\n }\n const scopeAgents = agents;\n // Acquisition can outlive cancellation. Teardown waits for actual settlement.\n return trackResourceOperation(\n {},\n Promise.resolve().then(async () => {\n const agent = options.agentProvider\n ? await options.agentProvider.getAgent(runId, ctx)\n : await options.getAgent!(ctx);\n retainResourceForScope(agent, ctx.signal);\n agent._prepareForTestRunner?.();\n scopeAgents.add(agent);\n return agent;\n }),\n ctx.signal,\n 'acquisition',\n );\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(execution) {\n const multiplier =\n execution.input.unit === 'min'\n ? 60_000\n : execution.input.unit === 's'\n ? 1_000\n : 1;\n const durationMs = execution.input.duration * multiplier;\n await waitFor(durationMs, execution.signal);\n return { summary: `Waited ${durationMs}ms` };\n },\n }),\n ];\n}\n"],"names":["defineNode","coreDefineNode","waitInputSchema","z","waitFor","durationMs","signal","Error","Promise","resolve","reject","timeout","setTimeout","abort","clearTimeout","createAgentTestRunnerNodes","definitions","getAgent","runAgentCall","node","ctx","agent","call","captureExecutions","runInYamlExecutionContext","scopeId","isCleanupOwner","admitResourceOperation","traces","partial","hasPendingResourceOperation","capturedAt","Date","source","trace","path","yamlBoundary","enterYamlExecution","leaveYamlAction","enterYamlAction","removeListener","sawExecutionWithoutId","stopListening","remove","undefined","stopListeningOnAbort","_dump","execution","collectTestRunReportMetrics","trackResourceOperation","warnReportTrace","definition","getDebug","createMidsceneNodes","options","NodeDefinitionError","agentsByScope","Map","runId","agents","Set","released","scopeAgents","retainResourceForScope","agentDefinitions","multiplier"],"mappings":"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"}
|
package/dist/es/test-cli.mjs
CHANGED
|
@@ -37,6 +37,7 @@ __webpack_require__.d(__webpack_exports__, {
|
|
|
37
37
|
aiAssertInputSchema: ()=>test_namespaceObject.aiAssertInputSchema,
|
|
38
38
|
structuredUserPromptInputSchema: ()=>test_namespaceObject.structuredUserPromptInputSchema,
|
|
39
39
|
waitInputSchema: ()=>waitInputSchema,
|
|
40
|
+
aiWaitForOptionsInputSchema: ()=>test_namespaceObject.aiWaitForOptionsInputSchema,
|
|
40
41
|
createMidsceneNodes: ()=>createMidsceneNodes,
|
|
41
42
|
recordToReportOptionsInputSchema: ()=>test_namespaceObject.recordToReportOptionsInputSchema,
|
|
42
43
|
setAIContextInputSchema: ()=>test_namespaceObject.setAIContextInputSchema,
|
|
@@ -262,6 +263,7 @@ exports.aiQueryInputSchema = __webpack_exports__.aiQueryInputSchema;
|
|
|
262
263
|
exports.aiScrollInputSchema = __webpack_exports__.aiScrollInputSchema;
|
|
263
264
|
exports.aiTapInputSchema = __webpack_exports__.aiTapInputSchema;
|
|
264
265
|
exports.aiWaitForInputSchema = __webpack_exports__.aiWaitForInputSchema;
|
|
266
|
+
exports.aiWaitForOptionsInputSchema = __webpack_exports__.aiWaitForOptionsInputSchema;
|
|
265
267
|
exports.createAgentTestRunnerNodes = __webpack_exports__.createAgentTestRunnerNodes;
|
|
266
268
|
exports.createMidsceneNodes = __webpack_exports__.createMidsceneNodes;
|
|
267
269
|
exports.insightInputSchema = __webpack_exports__.insightInputSchema;
|
|
@@ -292,6 +294,7 @@ for(var __rspack_i in __webpack_exports__)if (-1 === [
|
|
|
292
294
|
"aiScrollInputSchema",
|
|
293
295
|
"aiTapInputSchema",
|
|
294
296
|
"aiWaitForInputSchema",
|
|
297
|
+
"aiWaitForOptionsInputSchema",
|
|
295
298
|
"createAgentTestRunnerNodes",
|
|
296
299
|
"createMidsceneNodes",
|
|
297
300
|
"insightInputSchema",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"midscene/index.js","sources":["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":["__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 { defineNode as coreDefineNode } from '@midscene/core/internal/test-runner';\nimport type {\n DefineNodeOptions,\n DefineNodeWithSchemaOptions,\n NodeDefinition,\n NodeDefinitionWithSchema,\n NodeInputSchema,\n} from './types';\n\n// A type-only facade: validation and execution still belong to the shared kernel.\ninterface DefineNativeNode {\n <TSchema extends NodeInputSchema, TData = unknown, TContext = unknown>(\n options: DefineNodeWithSchemaOptions<TSchema, TData, TContext>,\n ): NodeDefinitionWithSchema<TSchema, TData, TContext>;\n <TInput = unknown, TData = unknown, TContext = unknown>(\n options: DefineNodeOptions<TInput, TData, TContext>,\n ): NodeDefinition<TInput, TData, TContext>;\n}\nexport const defineNode: DefineNativeNode = coreDefineNode;\n","import type { IExecutionDump } from '@midscene/core';\nimport {\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';\nimport {\n type WorkflowReportSource,\n admitResourceOperation,\n collectTestRunReportMetrics,\n hasPendingResourceOperation,\n retainResourceForScope,\n trackResourceOperation,\n} from '@midscene/core/internal/test-runner';\nimport {\n enterYamlAction,\n enterYamlExecution,\n runInYamlExecutionContext,\n} from '@midscene/core/internal/yaml-runtime';\nimport { getDebug } from '@midscene/shared/logger';\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 _prepareForTestRunner?(): void;\n _createReportSource?(\n scopeId: string,\n executionIds?: readonly string[],\n ): Promise<WorkflowReportSource | undefined>;\n flushReport?(): Promise<string | undefined>;\n addDumpUpdateListener?(\n listener: (dump: string, execution?: MidsceneExecutionRef) => void,\n ): () => void;\n};\n\nexport {\n actionInputSchema,\n aiDragAndDropInputSchema,\n aiInputInputSchema,\n aiKeyboardPressInputSchema,\n aiLongPressInputSchema,\n aiPinchInputSchema,\n aiQueryInputSchema,\n aiScrollInputSchema,\n aiWaitForInputSchema,\n javascriptInputSchema,\n runGherkinScenarioInputSchema,\n setAIContextInputSchema,\n} from '@midscene/core/agent/test';\nexport type {\n ActionNodeInput,\n AiDragAndDropNodeInput,\n AiInputNodeInput,\n AiKeyboardPressNodeInput,\n AiLongPressNodeInput,\n AiPinchNodeInput,\n AiQueryNodeInput,\n AiScrollNodeInput,\n AiWaitForNodeInput,\n JavascriptNodeInput,\n RunGherkinScenarioNodeInput,\n SetAIContextNodeInput,\n} from '@midscene/core/agent/test';\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 tasks?: IExecutionDump['tasks'];\n}\n\nexport interface AgentProvider<TContext> {\n getAgent(\n runId: string,\n execution: 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 execution: 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 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 runInYamlExecutionContext(async () => {\n const scopeId =\n ctx.scope === 'case' ? ctx.case.runId : ctx.document.documentRunId;\n const isCleanupOwner = admitResourceOperation(agent, ctx.signal);\n if (captureExecutions) {\n ctx.report.onSnapshot(async (signal, traces) => {\n signal.throwIfAborted();\n const partial = hasPendingResourceOperation(agent);\n const capturedAt = new Date().toISOString();\n let source = await agent._createReportSource?.(\n scopeId,\n traces.map((trace) => trace.executionId),\n );\n // External adapters may only expose HTML. Capture it independently\n // of cleanup, while marking its mutable source as partial.\n if (!source) {\n const path = await agent.flushReport?.();\n if (path)\n source = {\n sourcePath: path,\n collection: {\n status: 'partial',\n capturedAt,\n reason:\n 'This provider exposes live HTML without immutable snapshot support.',\n },\n };\n }\n signal.throwIfAborted();\n if (!source)\n throw new Error('Agent did not return a report snapshot.');\n return {\n ...source,\n collection: {\n status:\n partial || source.collection?.status === 'partial'\n ? ('partial' as const)\n : ('complete' as const),\n capturedAt: source.collection?.capturedAt ?? capturedAt,\n ...(source.collection?.reason\n ? { reason: source.collection.reason }\n : partial\n ? {\n reason:\n 'An Agent operation was still running at the snapshot cutoff.',\n }\n : {}),\n },\n };\n });\n }\n // Native Steps own the root report. Any Agent.runYaml invoked underneath\n // contributes to that Step instead of publishing another root snapshot.\n const yamlBoundary = enterYamlExecution(agent, {\n allowIndependentOverlap: isCleanupOwner,\n });\n const leaveYamlAction = enterYamlAction(agent, ctx.signal);\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 ...(execution.tasks\n ? {\n metrics: collectTestRunReportMetrics({\n executions: [\n {\n id: execution.id,\n name: node,\n logTime: 0,\n tasks: execution.tasks,\n },\n ],\n }),\n }\n : {}),\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 trackResourceOperation(\n agent,\n Promise.resolve().then(call),\n ctx.signal,\n );\n } finally {\n leaveYamlAction();\n yamlBoundary.finish();\n ctx.signal.removeEventListener('abort', stopListeningOnAbort);\n stopListening();\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 ctx.signal.throwIfAborted();\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 agentsByScope = new Map<string, Set<MidsceneUIAgent>>();\n const getAgent = async (\n ctx: NodeExecutionContext<unknown, TContext>,\n ): Promise<MidsceneUIAgent> => {\n const runId =\n ctx.scope === 'case' ? ctx.case.runId : ctx.document.documentRunId;\n let agents = agentsByScope.get(runId);\n if (!agents) {\n agents = new Set();\n agentsByScope.set(runId, agents);\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 agentsByScope.delete(runId);\n }\n });\n }\n const scopeAgents = agents;\n // Acquisition can outlive cancellation. Teardown waits for actual settlement.\n return trackResourceOperation(\n {},\n Promise.resolve().then(async () => {\n const agent = options.agentProvider\n ? await options.agentProvider.getAgent(runId, ctx)\n : await options.getAgent!(ctx);\n retainResourceForScope(agent, ctx.signal);\n agent._prepareForTestRunner?.();\n scopeAgents.add(agent);\n return agent;\n }),\n ctx.signal,\n 'acquisition',\n );\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(execution) {\n const multiplier =\n execution.input.unit === 'min'\n ? 60_000\n : execution.input.unit === 's'\n ? 1_000\n : 1;\n const durationMs = execution.input.duration * multiplier;\n await waitFor(durationMs, execution.signal);\n return { summary: `Waited ${durationMs}ms` };\n },\n }),\n ];\n}\n"],"names":["__webpack_require__","definition","key","Object","obj","prop","Symbol","defineNode","coreDefineNode","waitInputSchema","z","waitFor","durationMs","signal","Error","Promise","resolve","reject","timeout","setTimeout","abort","clearTimeout","createAgentTestRunnerNodes","definitions","getAgent","runAgentCall","node","ctx","agent","call","captureExecutions","runInYamlExecutionContext","scopeId","isCleanupOwner","admitResourceOperation","traces","partial","hasPendingResourceOperation","capturedAt","Date","source","trace","path","yamlBoundary","enterYamlExecution","leaveYamlAction","enterYamlAction","removeListener","sawExecutionWithoutId","stopListening","remove","undefined","stopListeningOnAbort","_dump","execution","collectTestRunReportMetrics","trackResourceOperation","warnReportTrace","getDebug","createMidsceneNodes","options","NodeDefinitionError","agentsByScope","Map","runId","agents","Set","released","scopeAgents","retainResourceForScope","agentDefinitions","multiplier"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"midscene/index.js","sources":["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":["__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 { defineNode as coreDefineNode } from '@midscene/core/internal/test-runner';\nimport type {\n DefineNodeOptions,\n DefineNodeWithSchemaOptions,\n NodeDefinition,\n NodeDefinitionWithSchema,\n NodeInputSchema,\n} from './types';\n\n// A type-only facade: validation and execution still belong to the shared kernel.\ninterface DefineNativeNode {\n <TSchema extends NodeInputSchema, TData = unknown, TContext = unknown>(\n options: DefineNodeWithSchemaOptions<TSchema, TData, TContext>,\n ): NodeDefinitionWithSchema<TSchema, TData, TContext>;\n <TInput = unknown, TData = unknown, TContext = unknown>(\n options: DefineNodeOptions<TInput, TData, TContext>,\n ): NodeDefinition<TInput, TData, TContext>;\n}\nexport const defineNode: DefineNativeNode = coreDefineNode;\n","import type { IExecutionDump } from '@midscene/core';\nimport {\n type AgentTestRunnerNodeDefinition,\n type AgentTestRunnerNodeProvider,\n type CommonAgentTestRunnerApi,\n aiActInputSchema,\n aiActOptionsInputSchema,\n aiAssertInputSchema,\n aiAssertOptionsInputSchema,\n aiTapInputSchema,\n aiWaitForInputSchema,\n aiWaitForOptionsInputSchema,\n insightInputSchema,\n insightOptionsInputSchema,\n locateOptionsInputSchema,\n promptImageInputSchema,\n recordToReportInputSchema,\n recordToReportOptionsInputSchema,\n reportScreenshotInputSchema,\n structuredUserPromptInputSchema,\n userPromptInputSchema,\n} from '@midscene/core/agent/test';\nimport {\n type WorkflowReportSource,\n admitResourceOperation,\n collectTestRunReportMetrics,\n hasPendingResourceOperation,\n retainResourceForScope,\n trackResourceOperation,\n} from '@midscene/core/internal/test-runner';\nimport {\n enterYamlAction,\n enterYamlExecution,\n runInYamlExecutionContext,\n} from '@midscene/core/internal/yaml-runtime';\nimport { getDebug } from '@midscene/shared/logger';\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 _prepareForTestRunner?(): void;\n _createReportSource?(\n scopeId: string,\n executionIds?: readonly string[],\n ): Promise<WorkflowReportSource | undefined>;\n flushReport?(): Promise<string | undefined>;\n addDumpUpdateListener?(\n listener: (dump: string, execution?: MidsceneExecutionRef) => void,\n ): () => void;\n};\n\nexport {\n actionInputSchema,\n aiDragAndDropInputSchema,\n aiInputInputSchema,\n aiKeyboardPressInputSchema,\n aiLongPressInputSchema,\n aiPinchInputSchema,\n aiQueryInputSchema,\n aiScrollInputSchema,\n javascriptInputSchema,\n runGherkinScenarioInputSchema,\n setAIContextInputSchema,\n} from '@midscene/core/agent/test';\nexport type {\n ActionNodeInput,\n AiDragAndDropNodeInput,\n AiInputNodeInput,\n AiKeyboardPressNodeInput,\n AiLongPressNodeInput,\n AiPinchNodeInput,\n AiQueryNodeInput,\n AiScrollNodeInput,\n JavascriptNodeInput,\n RunGherkinScenarioNodeInput,\n SetAIContextNodeInput,\n} from '@midscene/core/agent/test';\n\nexport {\n aiActInputSchema,\n aiActOptionsInputSchema,\n aiAssertInputSchema,\n aiAssertOptionsInputSchema,\n aiWaitForInputSchema,\n aiWaitForOptionsInputSchema,\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 tasks?: IExecutionDump['tasks'];\n}\n\nexport interface AgentProvider<TContext> {\n getAgent(\n runId: string,\n execution: 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 AiWaitForNodeInput = z.infer<typeof aiWaitForInputSchema>;\nexport type AiWaitForNodeOptions = z.infer<typeof aiWaitForOptionsInputSchema>;\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 execution: 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 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 runInYamlExecutionContext(async () => {\n const scopeId =\n ctx.scope === 'case' ? ctx.case.runId : ctx.document.documentRunId;\n const isCleanupOwner = admitResourceOperation(agent, ctx.signal);\n if (captureExecutions) {\n ctx.report.onSnapshot(async (signal, traces) => {\n signal.throwIfAborted();\n const partial = hasPendingResourceOperation(agent);\n const capturedAt = new Date().toISOString();\n let source = await agent._createReportSource?.(\n scopeId,\n traces.map((trace) => trace.executionId),\n );\n // External adapters may only expose HTML. Capture it independently\n // of cleanup, while marking its mutable source as partial.\n if (!source) {\n const path = await agent.flushReport?.();\n if (path)\n source = {\n sourcePath: path,\n collection: {\n status: 'partial',\n capturedAt,\n reason:\n 'This provider exposes live HTML without immutable snapshot support.',\n },\n };\n }\n signal.throwIfAborted();\n if (!source)\n throw new Error('Agent did not return a report snapshot.');\n return {\n ...source,\n collection: {\n status:\n partial || source.collection?.status === 'partial'\n ? ('partial' as const)\n : ('complete' as const),\n capturedAt: source.collection?.capturedAt ?? capturedAt,\n ...(source.collection?.reason\n ? { reason: source.collection.reason }\n : partial\n ? {\n reason:\n 'An Agent operation was still running at the snapshot cutoff.',\n }\n : {}),\n },\n };\n });\n }\n // Native Steps own the root report. Any Agent.runYaml invoked underneath\n // contributes to that Step instead of publishing another root snapshot.\n const yamlBoundary = enterYamlExecution(agent, {\n allowIndependentOverlap: isCleanupOwner,\n });\n const leaveYamlAction = enterYamlAction(agent, ctx.signal);\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 ...(execution.tasks\n ? {\n metrics: collectTestRunReportMetrics({\n executions: [\n {\n id: execution.id,\n name: node,\n logTime: 0,\n tasks: execution.tasks,\n },\n ],\n }),\n }\n : {}),\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 trackResourceOperation(\n agent,\n Promise.resolve().then(call),\n ctx.signal,\n );\n } finally {\n leaveYamlAction();\n yamlBoundary.finish();\n ctx.signal.removeEventListener('abort', stopListeningOnAbort);\n stopListening();\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 ctx.signal.throwIfAborted();\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 agentsByScope = new Map<string, Set<MidsceneUIAgent>>();\n const getAgent = async (\n ctx: NodeExecutionContext<unknown, TContext>,\n ): Promise<MidsceneUIAgent> => {\n const runId =\n ctx.scope === 'case' ? ctx.case.runId : ctx.document.documentRunId;\n let agents = agentsByScope.get(runId);\n if (!agents) {\n agents = new Set();\n agentsByScope.set(runId, agents);\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 agentsByScope.delete(runId);\n }\n });\n }\n const scopeAgents = agents;\n // Acquisition can outlive cancellation. Teardown waits for actual settlement.\n return trackResourceOperation(\n {},\n Promise.resolve().then(async () => {\n const agent = options.agentProvider\n ? await options.agentProvider.getAgent(runId, ctx)\n : await options.getAgent!(ctx);\n retainResourceForScope(agent, ctx.signal);\n agent._prepareForTestRunner?.();\n scopeAgents.add(agent);\n return agent;\n }),\n ctx.signal,\n 'acquisition',\n );\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(execution) {\n const multiplier =\n execution.input.unit === 'min'\n ? 60_000\n : execution.input.unit === 's'\n ? 1_000\n : 1;\n const durationMs = execution.input.duration * multiplier;\n await waitFor(durationMs, execution.signal);\n return { summary: `Waited ${durationMs}ms` };\n },\n }),\n ];\n}\n"],"names":["__webpack_require__","definition","key","Object","obj","prop","Symbol","defineNode","coreDefineNode","waitInputSchema","z","waitFor","durationMs","signal","Error","Promise","resolve","reject","timeout","setTimeout","abort","clearTimeout","createAgentTestRunnerNodes","definitions","getAgent","runAgentCall","node","ctx","agent","call","captureExecutions","runInYamlExecutionContext","scopeId","isCleanupOwner","admitResourceOperation","traces","partial","hasPendingResourceOperation","capturedAt","Date","source","trace","path","yamlBoundary","enterYamlExecution","leaveYamlAction","enterYamlAction","removeListener","sawExecutionWithoutId","stopListening","remove","undefined","stopListeningOnAbort","_dump","execution","collectTestRunReportMetrics","trackResourceOperation","warnReportTrace","getDebug","createMidsceneNodes","options","NodeDefinitionError","agentsByScope","Map","runId","agents","Set","released","scopeAgents","retainResourceForScope","agentDefinitions","multiplier"],"mappings":"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"}
|
package/dist/lib/test-cli.js
CHANGED
|
@@ -37,9 +37,12 @@ cases:
|
|
|
37
37
|
timeout: 180000
|
|
38
38
|
- aiAssert:
|
|
39
39
|
prompt: >-
|
|
40
|
-
|
|
41
|
-
completed
|
|
42
|
-
"
|
|
40
|
+
The list displays exactly two Todo rows in total, counting both
|
|
41
|
+
completed and incomplete rows. "Learn AI the day after tomorrow"
|
|
42
|
+
has a checked checkbox and strikethrough text. "Learn JS today"
|
|
43
|
+
has an unchecked checkbox. There is no row named "Learn Rust
|
|
44
|
+
tomorrow". The footer indicates one incomplete item ("1 item
|
|
45
|
+
left", with or without a trailing exclamation mark).
|
|
43
46
|
message: TodoMVC does not show the expected final state.
|
|
44
47
|
$:
|
|
45
48
|
timeout: 180000
|
|
@@ -22,7 +22,7 @@ import { aiScrollInputSchema } from '@midscene/core/agent/test';
|
|
|
22
22
|
import { AiScrollNodeInput } from '@midscene/core/agent/test';
|
|
23
23
|
import { aiTapInputSchema } from '@midscene/core/agent/test';
|
|
24
24
|
import { aiWaitForInputSchema } from '@midscene/core/agent/test';
|
|
25
|
-
import {
|
|
25
|
+
import { aiWaitForOptionsInputSchema } from '@midscene/core/agent/test';
|
|
26
26
|
import { Awaitable } from '@midscene/core/internal/test-runner';
|
|
27
27
|
import { CommonAgentTestRunnerApi } from '@midscene/core/agent/test';
|
|
28
28
|
import type * as Core from '@midscene/core/internal/test-runner';
|
|
@@ -106,7 +106,11 @@ export declare type AiTapNodeInput = z.infer<typeof aiTapInputSchema>;
|
|
|
106
106
|
|
|
107
107
|
export { aiWaitForInputSchema }
|
|
108
108
|
|
|
109
|
-
export
|
|
109
|
+
export declare type AiWaitForNodeInput = z.infer<typeof aiWaitForInputSchema>;
|
|
110
|
+
|
|
111
|
+
export declare type AiWaitForNodeOptions = z.infer<typeof aiWaitForOptionsInputSchema>;
|
|
112
|
+
|
|
113
|
+
export { aiWaitForOptionsInputSchema }
|
|
110
114
|
|
|
111
115
|
/** Adapt Agent-owned descriptions to executable Midscene Test Nodes. */
|
|
112
116
|
export declare const createAgentTestRunnerNodes: <TContext>(definitions: readonly AgentTestRunnerNodeDefinition[], getAgent: (ctx: NodeExecutionContext<unknown, TContext>) => Awaitable<unknown>) => readonly NodeDefinition<any, any, TContext>[];
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@midscene/test",
|
|
3
3
|
"description": "Midscene Test: an extensible YAML testing framework and Node SDK.",
|
|
4
|
-
"version": "1.15.
|
|
4
|
+
"version": "1.15.5",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
7
7
|
"url": "https://github.com/web-infra-dev/midscene.git",
|
|
@@ -58,8 +58,8 @@
|
|
|
58
58
|
"tsx": "^4.19.2",
|
|
59
59
|
"yargs": "17.7.3",
|
|
60
60
|
"zod": "^3.25.1",
|
|
61
|
-
"@midscene/
|
|
62
|
-
"@midscene/
|
|
61
|
+
"@midscene/shared": "1.15.5",
|
|
62
|
+
"@midscene/core": "1.15.5"
|
|
63
63
|
},
|
|
64
64
|
"devDependencies": {
|
|
65
65
|
"@rslib/core": "^0.18.3",
|
|
@@ -71,20 +71,20 @@
|
|
|
71
71
|
"puppeteer": "24.6.0",
|
|
72
72
|
"typescript": "^5.8.3",
|
|
73
73
|
"vitest": "3.0.5",
|
|
74
|
-
"@midscene/
|
|
75
|
-
"@midscene/android": "1.15.
|
|
76
|
-
"@midscene/
|
|
77
|
-
"@midscene/
|
|
78
|
-
"@midscene/
|
|
74
|
+
"@midscene/computer": "1.15.5",
|
|
75
|
+
"@midscene/android": "1.15.5",
|
|
76
|
+
"@midscene/harmony": "1.15.5",
|
|
77
|
+
"@midscene/ios": "1.15.5",
|
|
78
|
+
"@midscene/web": "1.15.5"
|
|
79
79
|
},
|
|
80
80
|
"peerDependencies": {
|
|
81
81
|
"playwright": "^1.45.0",
|
|
82
82
|
"puppeteer": "24.6.0",
|
|
83
|
-
"@midscene/
|
|
84
|
-
"@midscene/
|
|
85
|
-
"@midscene/harmony": "1.15.
|
|
86
|
-
"@midscene/
|
|
87
|
-
"@midscene/
|
|
83
|
+
"@midscene/computer": "1.15.5",
|
|
84
|
+
"@midscene/android": "1.15.5",
|
|
85
|
+
"@midscene/harmony": "1.15.5",
|
|
86
|
+
"@midscene/ios": "1.15.5",
|
|
87
|
+
"@midscene/web": "1.15.5"
|
|
88
88
|
},
|
|
89
89
|
"peerDependenciesMeta": {
|
|
90
90
|
"@midscene/android": {
|