@midscene/core 1.10.2-beta-20260706032158.0 → 1.10.3

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 (161) hide show
  1. package/dist/es/agent/agent.mjs +40 -1
  2. package/dist/es/agent/agent.mjs.map +1 -1
  3. package/dist/es/agent/metrics.mjs +81 -0
  4. package/dist/es/agent/metrics.mjs.map +1 -0
  5. package/dist/es/agent/task-builder.mjs +1 -1
  6. package/dist/es/agent/task-builder.mjs.map +1 -1
  7. package/dist/es/agent/utils.mjs +1 -1
  8. package/dist/es/ai-model/connectivity/run-connectivity-test.mjs +9 -3
  9. package/dist/es/ai-model/connectivity/run-connectivity-test.mjs.map +1 -1
  10. package/dist/es/ai-model/inspect.mjs +3 -3
  11. package/dist/es/ai-model/inspect.mjs.map +1 -1
  12. package/dist/es/ai-model/llm-planning.mjs +1 -1
  13. package/dist/es/ai-model/llm-planning.mjs.map +1 -1
  14. package/dist/es/ai-model/model-adapter/resolve.mjs +2 -2
  15. package/dist/es/ai-model/model-adapter/resolve.mjs.map +1 -1
  16. package/dist/es/ai-model/models/default.mjs +2 -1
  17. package/dist/es/ai-model/models/default.mjs.map +1 -1
  18. package/dist/es/ai-model/models/doubao.mjs +38 -60
  19. package/dist/es/ai-model/models/doubao.mjs.map +1 -1
  20. package/dist/es/ai-model/models/gemini.mjs +4 -15
  21. package/dist/es/ai-model/models/gemini.mjs.map +1 -1
  22. package/dist/es/ai-model/models/glm.mjs +4 -0
  23. package/dist/es/ai-model/models/glm.mjs.map +1 -1
  24. package/dist/es/ai-model/models/gpt.mjs +5 -1
  25. package/dist/es/ai-model/models/gpt.mjs.map +1 -1
  26. package/dist/es/ai-model/models/kimi.mjs +4 -0
  27. package/dist/es/ai-model/models/kimi.mjs.map +1 -1
  28. package/dist/es/ai-model/models/mimo.mjs +3 -2
  29. package/dist/es/ai-model/models/mimo.mjs.map +1 -1
  30. package/dist/es/ai-model/models/qwen.mjs.map +1 -1
  31. package/dist/es/ai-model/models/ui-tars/adapter.mjs +2 -41
  32. package/dist/es/ai-model/models/ui-tars/adapter.mjs.map +1 -1
  33. package/dist/es/ai-model/models/utils/intent.mjs +6 -0
  34. package/dist/es/ai-model/models/utils/intent.mjs.map +1 -0
  35. package/dist/es/ai-model/prompt/describe.mjs +31 -34
  36. package/dist/es/ai-model/prompt/describe.mjs.map +1 -1
  37. package/dist/es/ai-model/prompt/extraction.mjs +15 -9
  38. package/dist/es/ai-model/prompt/extraction.mjs.map +1 -1
  39. package/dist/es/ai-model/prompt/llm-planning.mjs +19 -19
  40. package/dist/es/ai-model/prompt/llm-planning.mjs.map +1 -1
  41. package/dist/es/ai-model/prompt/locate-grounding-rules.mjs +7 -3
  42. package/dist/es/ai-model/prompt/locate-grounding-rules.mjs.map +1 -1
  43. package/dist/es/ai-model/prompt/recorder-metadata-generator.mjs +2 -1
  44. package/dist/es/ai-model/prompt/recorder-metadata-generator.mjs.map +1 -1
  45. package/dist/es/ai-model/service-caller/index.mjs +40 -19
  46. package/dist/es/ai-model/service-caller/index.mjs.map +1 -1
  47. package/dist/es/ai-model/service-caller/json.mjs +31 -28
  48. package/dist/es/ai-model/service-caller/json.mjs.map +1 -1
  49. package/dist/es/device/index.mjs +2 -4
  50. package/dist/es/device/index.mjs.map +1 -1
  51. package/dist/es/dump/html-utils.mjs +63 -1
  52. package/dist/es/dump/html-utils.mjs.map +1 -1
  53. package/dist/es/dump/screenshot-restoration.mjs +6 -0
  54. package/dist/es/dump/screenshot-restoration.mjs.map +1 -1
  55. package/dist/es/element-describer.mjs +36 -18
  56. package/dist/es/element-describer.mjs.map +1 -1
  57. package/dist/es/index.mjs +2 -2
  58. package/dist/es/index.mjs.map +1 -1
  59. package/dist/es/report-generator.mjs +28 -1
  60. package/dist/es/report-generator.mjs.map +1 -1
  61. package/dist/es/report-markdown.mjs +300 -35
  62. package/dist/es/report-markdown.mjs.map +1 -1
  63. package/dist/es/report.mjs +29 -1
  64. package/dist/es/report.mjs.map +1 -1
  65. package/dist/es/service/index.mjs +101 -25
  66. package/dist/es/service/index.mjs.map +1 -1
  67. package/dist/es/service/utils.mjs +65 -1
  68. package/dist/es/service/utils.mjs.map +1 -1
  69. package/dist/es/types.mjs.map +1 -1
  70. package/dist/es/utils.mjs +2 -2
  71. package/dist/lib/agent/agent.js +40 -1
  72. package/dist/lib/agent/agent.js.map +1 -1
  73. package/dist/lib/agent/metrics.js +115 -0
  74. package/dist/lib/agent/metrics.js.map +1 -0
  75. package/dist/lib/agent/task-builder.js +1 -1
  76. package/dist/lib/agent/task-builder.js.map +1 -1
  77. package/dist/lib/agent/utils.js +1 -1
  78. package/dist/lib/ai-model/connectivity/run-connectivity-test.js +9 -3
  79. package/dist/lib/ai-model/connectivity/run-connectivity-test.js.map +1 -1
  80. package/dist/lib/ai-model/inspect.js +3 -3
  81. package/dist/lib/ai-model/inspect.js.map +1 -1
  82. package/dist/lib/ai-model/llm-planning.js +1 -1
  83. package/dist/lib/ai-model/llm-planning.js.map +1 -1
  84. package/dist/lib/ai-model/model-adapter/resolve.js +1 -1
  85. package/dist/lib/ai-model/model-adapter/resolve.js.map +1 -1
  86. package/dist/lib/ai-model/models/default.js +2 -1
  87. package/dist/lib/ai-model/models/default.js.map +1 -1
  88. package/dist/lib/ai-model/models/doubao.js +38 -69
  89. package/dist/lib/ai-model/models/doubao.js.map +1 -1
  90. package/dist/lib/ai-model/models/gemini.js +4 -15
  91. package/dist/lib/ai-model/models/gemini.js.map +1 -1
  92. package/dist/lib/ai-model/models/glm.js +4 -0
  93. package/dist/lib/ai-model/models/glm.js.map +1 -1
  94. package/dist/lib/ai-model/models/gpt.js +5 -1
  95. package/dist/lib/ai-model/models/gpt.js.map +1 -1
  96. package/dist/lib/ai-model/models/kimi.js +4 -0
  97. package/dist/lib/ai-model/models/kimi.js.map +1 -1
  98. package/dist/lib/ai-model/models/mimo.js +3 -2
  99. package/dist/lib/ai-model/models/mimo.js.map +1 -1
  100. package/dist/lib/ai-model/models/qwen.js.map +1 -1
  101. package/dist/lib/ai-model/models/ui-tars/adapter.js +1 -40
  102. package/dist/lib/ai-model/models/ui-tars/adapter.js.map +1 -1
  103. package/dist/lib/ai-model/models/utils/intent.js +40 -0
  104. package/dist/lib/ai-model/models/utils/intent.js.map +1 -0
  105. package/dist/lib/ai-model/prompt/describe.js +31 -34
  106. package/dist/lib/ai-model/prompt/describe.js.map +1 -1
  107. package/dist/lib/ai-model/prompt/extraction.js +14 -8
  108. package/dist/lib/ai-model/prompt/extraction.js.map +1 -1
  109. package/dist/lib/ai-model/prompt/llm-planning.js +19 -19
  110. package/dist/lib/ai-model/prompt/llm-planning.js.map +1 -1
  111. package/dist/lib/ai-model/prompt/locate-grounding-rules.js +7 -3
  112. package/dist/lib/ai-model/prompt/locate-grounding-rules.js.map +1 -1
  113. package/dist/lib/ai-model/prompt/recorder-metadata-generator.js +4 -3
  114. package/dist/lib/ai-model/prompt/recorder-metadata-generator.js.map +1 -1
  115. package/dist/lib/ai-model/service-caller/index.js +44 -23
  116. package/dist/lib/ai-model/service-caller/index.js.map +1 -1
  117. package/dist/lib/ai-model/service-caller/json.js +33 -33
  118. package/dist/lib/ai-model/service-caller/json.js.map +1 -1
  119. package/dist/lib/device/index.js +2 -4
  120. package/dist/lib/device/index.js.map +1 -1
  121. package/dist/lib/dump/html-utils.js +65 -0
  122. package/dist/lib/dump/html-utils.js.map +1 -1
  123. package/dist/lib/dump/screenshot-restoration.js +6 -0
  124. package/dist/lib/dump/screenshot-restoration.js.map +1 -1
  125. package/dist/lib/element-describer.js +37 -22
  126. package/dist/lib/element-describer.js.map +1 -1
  127. package/dist/lib/index.js +1 -4
  128. package/dist/lib/index.js.map +1 -1
  129. package/dist/lib/report-generator.js +27 -0
  130. package/dist/lib/report-generator.js.map +1 -1
  131. package/dist/lib/report-markdown.js +300 -35
  132. package/dist/lib/report-markdown.js.map +1 -1
  133. package/dist/lib/report.js +28 -0
  134. package/dist/lib/report.js.map +1 -1
  135. package/dist/lib/service/index.js +99 -23
  136. package/dist/lib/service/index.js.map +1 -1
  137. package/dist/lib/service/utils.js +98 -1
  138. package/dist/lib/service/utils.js.map +1 -1
  139. package/dist/lib/types.js.map +1 -1
  140. package/dist/lib/utils.js +2 -2
  141. package/dist/types/agent/agent.d.ts +15 -2
  142. package/dist/types/agent/index.d.ts +1 -0
  143. package/dist/types/agent/metrics.d.ts +48 -0
  144. package/dist/types/ai-model/model-adapter/types.d.ts +8 -0
  145. package/dist/types/ai-model/models/doubao.d.ts +1 -4
  146. package/dist/types/ai-model/models/gemini.d.ts +1 -1
  147. package/dist/types/ai-model/models/registry.d.ts +1 -1
  148. package/dist/types/ai-model/models/utils/intent.d.ts +2 -0
  149. package/dist/types/ai-model/service-caller/index.d.ts +8 -3
  150. package/dist/types/ai-model/service-caller/json.d.ts +19 -2
  151. package/dist/types/device/device-options.d.ts +0 -28
  152. package/dist/types/device/index.d.ts +0 -5
  153. package/dist/types/dump/html-utils.d.ts +2 -0
  154. package/dist/types/dump/screenshot-restoration.d.ts +1 -1
  155. package/dist/types/element-describer.d.ts +3 -6
  156. package/dist/types/index.d.ts +2 -2
  157. package/dist/types/report-generator.d.ts +6 -0
  158. package/dist/types/service/index.d.ts +1 -1
  159. package/dist/types/service/utils.d.ts +21 -2
  160. package/dist/types/types.d.ts +12 -2
  161. package/package.json +3 -3
@@ -4,6 +4,7 @@ import { type ActionParam, type ActionReturn, type AgentAssertOpt, type AgentOpt
4
4
  import type { AbstractInterface } from '../device';
5
5
  import type { TaskRunner } from '../task-runner';
6
6
  import { ModelConfigManager } from '@midscene/shared/env';
7
+ import { type MidsceneUsageMetrics } from './metrics';
7
8
  import { type RunGherkinScenarioOptions } from './run-gherkin-scenario';
8
9
  import { TaskCache } from './task-cache';
9
10
  import { TaskExecutor } from './tasks';
@@ -29,6 +30,9 @@ export declare class Agent<InterfaceType extends AbstractInterface = AbstractInt
29
30
  dryMode: boolean;
30
31
  onTaskStartTip?: OnTaskStartTip;
31
32
  taskCache?: TaskCache;
33
+ private readonly metricsCollector;
34
+ private usageCallCounter;
35
+ private readonly countedUsageKeys;
32
36
  private dumpUpdateListeners;
33
37
  private readonly progressBus;
34
38
  get onDumpUpdate(): ((dump: string, executionDump?: ExecutionDump) => void) | undefined;
@@ -80,6 +84,17 @@ export declare class Agent<InterfaceType extends AbstractInterface = AbstractInt
80
84
  setAIActContext(prompt: string): Promise<void>;
81
85
  resetDump(): ReportActionDump;
82
86
  appendExecutionDump(execution: ExecutionDump, runner?: TaskRunner): void;
87
+ /**
88
+ * Fold any not-yet-counted task usage from an execution dump into the
89
+ * instance metrics. Snapshots are re-emitted as tasks progress, so each
90
+ * usage value is keyed by `${taskId}:${field}` and counted at most once.
91
+ */
92
+ private collectUsageMetrics;
93
+ private consumeUsage;
94
+ /**
95
+ * Aggregated LLM usage accumulated by this agent since it was created.
96
+ */
97
+ get metrics(): MidsceneUsageMetrics;
83
98
  dumpDataString(opt?: {
84
99
  inlineScreenshots?: boolean;
85
100
  }): string;
@@ -102,7 +117,6 @@ export declare class Agent<InterfaceType extends AbstractInterface = AbstractInt
102
117
  value: string | number;
103
118
  } & {
104
119
  autoDismissKeyboard?: boolean;
105
- keyboardTypeDelay?: number;
106
120
  } & {
107
121
  mode?: 'replace' | 'clear' | 'typeOnly' | 'append';
108
122
  }): Promise<void>;
@@ -111,7 +125,6 @@ export declare class Agent<InterfaceType extends AbstractInterface = AbstractInt
111
125
  */
112
126
  aiInput(value: string | number, locatePrompt: TUserPrompt, opt?: LocateOption & {
113
127
  autoDismissKeyboard?: boolean;
114
- keyboardTypeDelay?: number;
115
128
  } & {
116
129
  mode?: 'replace' | 'clear' | 'typeOnly' | 'append';
117
130
  }): Promise<void>;
@@ -5,6 +5,7 @@ export { extractInsightParam, locateParamStr, paramStr, taskTitleStr, typeStr, }
5
5
  export { type LocateCache, type PlanningCache, TaskCache } from './task-cache';
6
6
  export { cacheFileExt } from './task-cache';
7
7
  export { TaskExecutor } from './tasks';
8
+ export type { MidsceneUsageMetrics, UsageBucket } from './metrics';
8
9
  export type { GherkinStepKeyword, RunGherkinScenarioOptions, } from './run-gherkin-scenario';
9
10
  export type { AgentOpt } from '../types';
10
11
  export type { RecordToReportOptions, RecordToReportScreenshot } from '../types';
@@ -0,0 +1,48 @@
1
+ import type { AIUsageInfo } from '../types';
2
+ /**
3
+ * Aggregated usage for a single grouping key (intent or model).
4
+ */
5
+ export interface UsageBucket {
6
+ promptTokens: number;
7
+ completionTokens: number;
8
+ totalTokens: number;
9
+ calls: number;
10
+ }
11
+ /**
12
+ * Instance-level snapshot of LLM usage accumulated by an Agent.
13
+ *
14
+ * Designed for cost observability: read it back after a logical unit of work
15
+ * and push to tools like Langfuse. `byIntent` / `byModel` provide free
16
+ * breakdowns derived from the usage data Midscene already records per call.
17
+ */
18
+ export interface MidsceneUsageMetrics {
19
+ totalPromptTokens: number;
20
+ totalCompletionTokens: number;
21
+ totalTokens: number;
22
+ totalCachedInput: number;
23
+ totalTimeCostMs: number;
24
+ calls: number;
25
+ byIntent: Record<string, UsageBucket>;
26
+ byModel: Record<string, UsageBucket>;
27
+ }
28
+ /**
29
+ * Pure accumulator for {@link AIUsageInfo}. Deduplication of calls is the
30
+ * caller's responsibility; every `add` counts as one call.
31
+ */
32
+ export declare class MetricsCollector {
33
+ private totalPromptTokens;
34
+ private totalCompletionTokens;
35
+ private totalTokens;
36
+ private totalCachedInput;
37
+ private totalTimeCostMs;
38
+ private calls;
39
+ private byIntent;
40
+ private byModel;
41
+ add(usage: AIUsageInfo): void;
42
+ snapshot(): MidsceneUsageMetrics;
43
+ /**
44
+ * Clear all accumulated state. Not wired to a public Agent API yet; kept for
45
+ * a future per-unit reset (e.g. resetting metrics at the start of a spec).
46
+ */
47
+ reset(): void;
48
+ }
@@ -1,4 +1,5 @@
1
1
  import type { PixelBbox, PlanningAction } from '../../types';
2
+ import type { AIUsageInfo } from '../../types';
2
3
  import type { IModelConfig, TIntent, TModelReasoningEnabled } from '@midscene/shared/env';
3
4
  import type OpenAI from 'openai';
4
5
  import type { JsonParser, JsonParserContext, JsonParserSource } from '../service-caller/json';
@@ -152,6 +153,13 @@ export interface ModelAdapter {
152
153
  export interface ModelRuntime {
153
154
  config: IModelConfig;
154
155
  adapter: ModelAdapter;
156
+ /**
157
+ * Optional callback fired after every underlying model call with the shaped
158
+ * usage info. Provides a single collection point for callers that want to
159
+ * aggregate usage across all model invocations (including auxiliary calls
160
+ * such as order-sensitive judging and deep-locate search-area calls).
161
+ */
162
+ onUsage?: (usage: AIUsageInfo) => void;
155
163
  }
156
164
  export interface ModelAdapterDefinition {
157
165
  jsonParser?: JsonParserPreset | JsonParser;
@@ -1,8 +1,5 @@
1
- import type { JsonParserContext, JsonParserSource, ModelAdapterDefinition } from '../model-adapter/types';
1
+ import type { ModelAdapterDefinition } from '../model-adapter/types';
2
2
  import { type LocateResultValue } from '../shared/model-locate-result';
3
- export declare function normalizeDoubaoJsonObject(obj: any, context?: Pick<JsonParserContext, 'preserveStringValueKeys'>): any;
4
- export declare function shouldRepairDoubaoLocateJson(source: JsonParserSource): source is "planning-action-param" | "locate" | "section-locator";
5
- export declare function preprocessDoubaoLocateJson(input: string): string;
6
3
  export declare function parseDoubaoRawLocateValue(input: unknown): LocateResultValue;
7
4
  export declare const doubaoAdapters: {
8
5
  'doubao-vision': ModelAdapterDefinition;
@@ -14,7 +14,7 @@ export declare const extractGeminiContentAndReasoning: (message: GeminiContentSo
14
14
  export declare const geminiAdapters: {
15
15
  gemini: {
16
16
  chatCompletion: {
17
- unsupportedUserConfig: ("reasoningEnabled" | "reasoningBudget")[];
17
+ unsupportedUserConfig: "reasoningBudget"[];
18
18
  buildChatCompletionParams: (input: ChatCompletionCallContext) => ChatCompletionParamsResult;
19
19
  messageExtraction: {
20
20
  kind: "custom";
@@ -63,7 +63,7 @@ export declare const MODEL_ADAPTER_CONFIGS: {
63
63
  'vlm-ui-tars-doubao-1.5': ModelAdapterDefinition;
64
64
  gemini: {
65
65
  chatCompletion: {
66
- unsupportedUserConfig: ("reasoningEnabled" | "reasoningBudget")[];
66
+ unsupportedUserConfig: "reasoningBudget"[];
67
67
  buildChatCompletionParams: (input: import("../model-adapter/types").ChatCompletionCallContext) => import("../model-adapter/types").ChatCompletionParamsResult;
68
68
  messageExtraction: {
69
69
  kind: "custom";
@@ -0,0 +1,2 @@
1
+ import type { TIntent } from '@midscene/shared/env';
2
+ export declare function isLocateIntent(intent?: TIntent): boolean;
@@ -13,12 +13,17 @@ export declare class AIResponseParseError extends Error {
13
13
  import { type IModelConfig, type TModelFamily } from '@midscene/shared/env';
14
14
  import OpenAI from 'openai';
15
15
  import type { ChatCompletionMessageParam } from 'openai/resources/index';
16
- import { type ModelRuntime } from '../models';
16
+ import type { ModelRuntime } from '../models';
17
17
  import type { AIArgs } from '../types';
18
18
  import type { JsonParserSource } from './json';
19
19
  import { type OpenAIErrorResponseContext } from './openai-error';
20
- export { extractJSONFromCodeBlock, normalJsonParser, safeParseJson, } from './json';
20
+ export { extractJSONFromCodeBlock, parseModelResponseJson, } from './json';
21
21
  export type { JsonParser } from './json';
22
+ /**
23
+ * Internal field name stamped onto every AIUsageInfo shaped by callAI().
24
+ * Used for cross-path dedup when the provider does not return a request_id.
25
+ */
26
+ export declare const INTERNAL_CALL_ID_FIELD = "_midscene_call_id";
22
27
  export declare function createChatClient({ modelConfig, }: {
23
28
  modelConfig: IModelConfig;
24
29
  }): Promise<{
@@ -41,7 +46,7 @@ export declare function callAI(messages: ChatCompletionMessageParam[], modelRunt
41
46
  usage?: AIUsageInfo;
42
47
  isStreamed: boolean;
43
48
  }>;
44
- export declare function callAIWithObjectResponse<T>(messages: ChatCompletionMessageParam[], model: IModelConfig | ModelRuntime, options?: {
49
+ export declare function callAIWithObjectResponse<T>(messages: ChatCompletionMessageParam[], modelRuntime: ModelRuntime, options?: {
45
50
  abortSignal?: AbortSignal;
46
51
  jsonParserSource?: JsonParserSource;
47
52
  }): Promise<{
@@ -1,9 +1,26 @@
1
+ /**
2
+ * Extract the JSON portion from a model response.
3
+ *
4
+ * This mainly handles fenced JSON like ```json { ... } ``` by removing the
5
+ * fence. If that does not produce a JSON object, it falls back to a greedy regex
6
+ * that extracts from the first "{" to the last "}". If that still fails, the
7
+ * original response is returned.
8
+ *
9
+ * Expected model responses are JSON objects, possibly wrapped in markdown
10
+ * fences. Natural language mixed with JSON, or arrays like
11
+ * [{"type":"Tap"}, {"type":"Hover"}], are outside the supported contract and
12
+ * are not reliably recoverable.
13
+ *
14
+ * This legacy extractor is also used by extraction responses that can be any
15
+ * JSON value. In those cases, arrays/strings/numbers have no object braces and
16
+ * pass through unchanged.
17
+ */
1
18
  export declare function extractJSONFromCodeBlock(response: string): string;
2
19
  export type JsonParserSource = 'generic-object' | 'planning-action-param' | 'locate' | 'section-locator';
3
20
  export interface JsonParserContext {
4
21
  source: JsonParserSource;
5
22
  preserveStringValueKeys?: string[];
23
+ requireObject?: boolean;
6
24
  }
7
25
  export type JsonParser = (raw: string, context?: JsonParserContext) => unknown;
8
- export declare function safeParseJson(raw: string, context?: JsonParserContext): any;
9
- export declare const normalJsonParser: JsonParser;
26
+ export declare function parseModelResponseJson(raw: string, context?: JsonParserContext): any;
@@ -7,18 +7,6 @@ export type AndroidDeviceInputOpt = {
7
7
  autoDismissKeyboard?: boolean;
8
8
  /** Strategy for dismissing the keyboard: 'esc-first' tries ESC before BACK, 'back-first' tries BACK before ESC */
9
9
  keyboardDismissStrategy?: 'esc-first' | 'back-first';
10
- /**
11
- * Delay in milliseconds between keystrokes when typing text.
12
- *
13
- * When set, text is typed one character at a time with this delay between
14
- * each character, instead of sending the whole string at once. This helps
15
- * on devices or input fields that drop characters when input arrives too
16
- * fast (e.g. WiFi password fields on automotive displays).
17
- *
18
- * Only applies to the `input text` path (non-yadb). When yadb is used, the
19
- * entire string is committed atomically and this option is ignored.
20
- */
21
- keyboardTypeDelay?: number;
22
10
  };
23
11
  /**
24
12
  * Android device options
@@ -121,14 +109,6 @@ export type AndroidDeviceOpt = {
121
109
  export type IOSDeviceInputOpt = {
122
110
  /** Automatically dismiss the keyboard after input is completed */
123
111
  autoDismissKeyboard?: boolean;
124
- /**
125
- * Delay in milliseconds between keystrokes when typing text.
126
- *
127
- * When set, text is typed one character at a time with this delay between
128
- * each character, instead of sending the whole string at once. This helps
129
- * on devices or input fields that drop characters when input arrives too fast.
130
- */
131
- keyboardTypeDelay?: number;
132
112
  };
133
113
  /**
134
114
  * iOS device options
@@ -166,14 +146,6 @@ export type HarmonyDeviceInputOpt = {
166
146
  autoDismissKeyboard?: boolean;
167
147
  /** Strategy for dismissing the keyboard. Defaults to 'esc-first'. */
168
148
  keyboardDismissStrategy?: 'esc-first' | 'back-first';
169
- /**
170
- * Delay in milliseconds between keystrokes when typing text.
171
- *
172
- * When set, text is typed one character at a time with this delay between
173
- * each character, instead of sending the whole string at once. This helps
174
- * on devices or input fields that drop characters when input arrives too fast.
175
- */
176
- keyboardTypeDelay?: number;
177
149
  };
178
150
  /**
179
151
  * HarmonyOS device options
@@ -59,7 +59,6 @@ export interface KeyboardInputPrimitives {
59
59
  typeText(value: string, opts?: {
60
60
  autoDismissKeyboard?: boolean;
61
61
  keyboardDismissStrategy?: 'esc-first' | 'back-first';
62
- keyboardTypeDelay?: number;
63
62
  target?: unknown;
64
63
  replace?: boolean;
65
64
  focusOnly?: boolean;
@@ -899,7 +898,6 @@ export declare const actionInputParamSchema: z.ZodObject<{
899
898
  }, z.ZodTypeAny, "passthrough">>>;
900
899
  mode: z.ZodDefault<z.ZodEnum<["replace", "clear", "typeOnly"]>>;
901
900
  autoDismissKeyboard: z.ZodOptional<z.ZodBoolean>;
902
- keyboardTypeDelay: z.ZodOptional<z.ZodNumber>;
903
901
  }, "strip", z.ZodTypeAny, {
904
902
  value: string;
905
903
  mode: "replace" | "clear" | "typeOnly";
@@ -941,7 +939,6 @@ export declare const actionInputParamSchema: z.ZodObject<{
941
939
  xpath: z.ZodOptional<z.ZodUnion<[z.ZodString, z.ZodBoolean]>>;
942
940
  }, z.ZodTypeAny, "passthrough"> | undefined;
943
941
  autoDismissKeyboard?: boolean | undefined;
944
- keyboardTypeDelay?: number | undefined;
945
942
  }, {
946
943
  value: string | number;
947
944
  locate?: z.objectInputType<{
@@ -983,14 +980,12 @@ export declare const actionInputParamSchema: z.ZodObject<{
983
980
  }, z.ZodTypeAny, "passthrough"> | undefined;
984
981
  mode?: "replace" | "clear" | "typeOnly" | undefined;
985
982
  autoDismissKeyboard?: boolean | undefined;
986
- keyboardTypeDelay?: number | undefined;
987
983
  }>;
988
984
  export type ActionInputParam = {
989
985
  value: string;
990
986
  locate?: LocateResultElement;
991
987
  mode?: 'replace' | 'clear' | 'typeOnly' | 'append';
992
988
  autoDismissKeyboard?: boolean;
993
- keyboardTypeDelay?: number;
994
989
  };
995
990
  export declare const defineActionInput: (keyboard: KeyboardInputPrimitives) => DeviceAction<ActionInputParam>;
996
991
  export declare const actionKeyboardPressParamSchema: z.ZodObject<{
@@ -1,5 +1,7 @@
1
+ import type { IReportActionDump } from '../types';
1
2
  export declare const escapeContent: (html: string) => string;
2
3
  export declare const unescapeContent: (html: string) => string;
4
+ export declare function generateAgentReportComment(report: IReportActionDump): string;
3
5
  /** Chunk size for streaming file operations (64KB) */
4
6
  export declare const STREAMING_CHUNK_SIZE: number;
5
7
  /**
@@ -2,7 +2,7 @@ import { type ScreenshotRef } from './screenshot-store';
2
2
  /**
3
3
  * Recursively restore image references in parsed data.
4
4
  * Replaces ScreenshotRef with lazy
5
- * { get base64() {...}, capturedAt } objects.
5
+ * { get base64() {...}, capturedAt, sourceRef } objects.
6
6
  * The resolver is only called when .base64 is first accessed.
7
7
  */
8
8
  export declare function restoreImageReferences<T>(data: T, resolveImage: (ref: ScreenshotRef) => string): T;
@@ -5,13 +5,13 @@ export type DescribeElementCoordinateSpace = 'screenshot' | 'logical';
5
5
  export type LocatorVerifyFn = (input: {
6
6
  prompt: string;
7
7
  expectCenter: [number, number];
8
- deepLocate: boolean;
9
8
  retryCount: number;
10
9
  verifyResult: LocateValidatorResult;
11
10
  }) => LocateValidatorResult | boolean;
12
11
  export type DescribeElementAtPointOptions = {
13
12
  verifyPrompt?: boolean;
14
13
  retryLimit?: number;
14
+ deepDescribe?: boolean;
15
15
  deepLocate?: boolean;
16
16
  locatorVerifyFn?: LocatorVerifyFn;
17
17
  screenshotBase64?: string;
@@ -20,6 +20,7 @@ export type DescribeElementAtPointOptions = {
20
20
  logicalSize?: Size;
21
21
  onProgress?: (progress: {
22
22
  prompt?: string;
23
+ deepDescribe?: boolean;
23
24
  deepLocate?: boolean;
24
25
  verifyResult?: LocateValidatorResult;
25
26
  }) => void;
@@ -31,16 +32,12 @@ type ScreenshotBoundContextOptions = {
31
32
  logicalSize?: Size;
32
33
  };
33
34
  export type VerifyElementDescriptionAtPointOptions = ScreenshotBoundContextOptions & LocatorValidatorOption;
34
- export type VerifyElementByServiceLocateOptions = VerifyElementDescriptionAtPointOptions & Pick<LocateOption, 'cacheable' | 'deepLocate' | 'xpath'> & {
35
- abortSignal?: AbortSignal;
36
- };
37
35
  export type ElementDescriberRuntime = {
38
36
  service: Pick<Service, 'describe' | 'locate'>;
39
37
  describeModelRuntime: ModelRuntime;
40
38
  locateModelRuntime: ModelRuntime;
41
39
  };
42
- export declare function verifyLocator(runtime: Pick<ElementDescriberRuntime, 'service' | 'locateModelRuntime'>, prompt: string, locateOpt: LocateOption | undefined, expectCenter: [number, number], verifyLocateOption?: LocatorValidatorOption): Promise<LocateValidatorResult>;
40
+ export declare function verifyLocator(runtime: Pick<ElementDescriberRuntime, 'service' | 'locateModelRuntime'>, prompt: string, locateOpt: LocateOption | undefined, expectCenter: [number, number], verifyLocateOption?: LocatorValidatorOption & Pick<LocateOption, 'deepLocate'>): Promise<LocateValidatorResult>;
43
41
  export declare function describeElementAtPoint(runtime: ElementDescriberRuntime, center: [number, number], opt?: DescribeElementAtPointOptions): Promise<AgentDescribeElementAtPointResult>;
44
42
  export declare function verifyElementDescriptionAtPoint(runtime: ElementDescriberRuntime, description: string, center: [number, number], opt?: VerifyElementDescriptionAtPointOptions): Promise<LocateValidatorResult>;
45
- export declare function verifyElementByServiceLocate(runtime: Pick<ElementDescriberRuntime, 'service' | 'locateModelRuntime'>, description: string, center: [number, number], opt?: VerifyElementByServiceLocateOptions): Promise<LocateValidatorResult>;
46
43
  export {};
@@ -10,8 +10,8 @@ export { z };
10
10
  export default Service;
11
11
  export { TaskRunner, Service, getVersion };
12
12
  export type { MidsceneYamlScript, MidsceneYamlTask, MidsceneYamlFlowItem, MidsceneYamlConfigResult, MidsceneYamlConfig, MidsceneYamlScriptWebEnv, MidsceneYamlScriptAndroidEnv, MidsceneYamlScriptIOSEnv, MidsceneYamlScriptEnv, LocateOption, DetailedLocateParam, } from './yaml';
13
- export { Agent, type AgentOpt, type AiActOptions, type GherkinStepKeyword, type RunGherkinScenarioOptions, createAgent, } from './agent';
14
- export { describeElementAtPoint, verifyElementDescriptionAtPoint, verifyElementByServiceLocate, verifyLocator, type DescribeElementAtPointOptions, type DescribeElementCoordinateSpace, type ElementDescriberRuntime, type VerifyElementDescriptionAtPointOptions, type VerifyElementByServiceLocateOptions, } from './element-describer';
13
+ export { Agent, type AgentOpt, type AiActOptions, type GherkinStepKeyword, type MidsceneUsageMetrics, type RunGherkinScenarioOptions, type UsageBucket, createAgent, } from './agent';
14
+ export { describeElementAtPoint, verifyElementDescriptionAtPoint, verifyLocator, type DescribeElementAtPointOptions, type DescribeElementCoordinateSpace, type ElementDescriberRuntime, type VerifyElementDescriptionAtPointOptions, } from './element-describer';
15
15
  export { restoreImageReferences, escapeContent, unescapeContent, parseImageScripts, parseDumpScript, parseDumpScriptAttributes, generateImageScriptTag, generateDumpScriptTag, deriveTaskStatus, deriveCaseStatus, } from './dump';
16
16
  export type { TaskStatusFields, DerivedTaskStatus } from './dump';
17
17
  export { getTaskSearchArea, getTaskServiceDump, } from './dump/task-service-dump';
@@ -41,7 +41,11 @@ export declare class ReportGenerator implements IReportGenerator {
41
41
  private initialized;
42
42
  private lastExecution?;
43
43
  private lastReportMeta?;
44
+ private executionsByKey;
45
+ private executionCommentKeyByObject;
46
+ private executionCommentKeyIndex;
44
47
  private reportAttributes;
48
+ private agentCommentWritten;
45
49
  private writeQueue;
46
50
  private destroyed;
47
51
  constructor(options: {
@@ -83,6 +87,8 @@ export declare class ReportGenerator implements IReportGenerator {
83
87
  */
84
88
  private writeInlineExecution;
85
89
  private writeDirectoryExecution;
90
+ private appendAgentReportComment;
86
91
  private getExecutionLogKey;
92
+ private getExecutionCommentKey;
87
93
  private persistExecutionDumpToFile;
88
94
  }
@@ -21,7 +21,7 @@ export default class Service {
21
21
  abortSignal?: AbortSignal;
22
22
  }): Promise<ServiceExtractResult<T>>;
23
23
  describe(target: Rect | [number, number], modelRuntime: ModelRuntime, opt?: {
24
- deepLocate?: boolean;
24
+ deepDescribe?: boolean;
25
25
  context?: UIContext;
26
26
  }): Promise<Pick<AIDescribeElementResponse, 'description'>>;
27
27
  }
@@ -1,4 +1,23 @@
1
- import type { AIDescribeElementResponse } from '../types';
2
- import type { PartialServiceDumpFromSDK, ServiceDump } from '../types';
1
+ import type { AIDescribeElementResponse, PartialServiceDumpFromSDK, Rect, ServiceDump, Size } from '../types';
2
+ export declare const DESCRIBE_POINT_MARKER_MAX_SIZE = 40;
3
+ export declare const DESCRIBE_RECT_MARKER_BORDER_THICKNESS = 1;
4
+ export declare const DESCRIBE_LARGE_RECT_MARKER_BORDER_THICKNESS = 2;
5
+ export declare const DESCRIBE_WIDE_MARKER_INSET_MIN_WIDTH = 100;
6
+ export declare const DESCRIBE_DEEP_CONTEXT_CONFIG: {
7
+ readonly resize: {
8
+ readonly cropMaxLongEdge: 1000;
9
+ readonly cropUpscaleMaxRatio: 2;
10
+ };
11
+ };
12
+ export type DescribeDeepContextArea = {
13
+ kind: 'focused';
14
+ rect: Rect;
15
+ };
16
+ export declare function clampRect(rect: Rect, size: Size): Rect;
17
+ export declare function getDescribeDeepContextAreas(rect: Rect, screenSize: Size): DescribeDeepContextArea[];
18
+ export declare function getRectInCrop(rect: Rect, cropRect: Rect, cropSize: Size): Rect;
19
+ export declare function getDescribeMarkerRect(rect: Rect): Rect;
20
+ export declare function getDescribeMarkerBorderThickness(rect: Rect): number;
21
+ export declare function getDescribeDeepLocateResizeSize(size: Size): Size | undefined;
3
22
  export declare function createServiceDump(data: PartialServiceDumpFromSDK): ServiceDump;
4
23
  export declare function recoverDescribeResponseFromParseError(error: unknown): Pick<AIDescribeElementResponse, 'description'> | undefined;
@@ -84,6 +84,7 @@ export interface LocateValidatorResult {
84
84
  export interface AgentDescribeElementAtPointResult {
85
85
  prompt: string;
86
86
  deepLocate: boolean;
87
+ deepDescribe: boolean;
87
88
  verifyResult?: LocateValidatorResult;
88
89
  success: boolean;
89
90
  error?: string;
@@ -130,12 +131,12 @@ export type ThinkingLevel = 'off' | 'medium' | 'high';
130
131
  export type DeepThinkOption = 'unset' | true | false;
131
132
  export interface ServiceTaskInfo {
132
133
  durationMs: number;
133
- formatResponse?: string;
134
+ formatResponse?: unknown;
134
135
  /**
135
136
  * Adapter-extracted content used by Midscene for parsing. This is not the
136
137
  * full provider response or choices[0].message.
137
138
  */
138
- rawResponse?: string;
139
+ rawResponse?: unknown;
139
140
  rawChoiceMessage?: unknown;
140
141
  usage?: AIUsageInfo;
141
142
  searchArea?: Rect;
@@ -703,6 +704,15 @@ export interface AgentOpt {
703
704
  * ```
704
705
  */
705
706
  createOpenAIClient?: CreateOpenAIClientFn;
707
+ /**
708
+ * Called once per LLM call as soon as its usage is available, with the raw
709
+ * {@link AIUsageInfo} (token counts, model name, intent, request id, etc.).
710
+ *
711
+ * Use this for real-time, per-spec cost observability — e.g. push each call
712
+ * to Langfuse without waiting for the run to finish. For aggregated totals,
713
+ * read `agent.metrics` instead.
714
+ */
715
+ onLLMUsage?: (usage: AIUsageInfo) => void;
706
716
  }
707
717
  export type TestStatus = 'passed' | 'failed' | 'timedOut' | 'skipped' | 'interrupted';
708
718
  export interface ReportFileAttributes {
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@midscene/core",
3
3
  "description": "Automate browser actions, extract data, and perform assertions using AI. It offers JavaScript SDK, Chrome extension, and support for scripting in YAML. See https://midscenejs.com/ for details.",
4
- "version": "1.10.2-beta-20260706032158.0",
4
+ "version": "1.10.3",
5
5
  "repository": "https://github.com/web-infra-dev/midscene",
6
6
  "homepage": "https://midscenejs.com/",
7
7
  "main": "./dist/lib/index.js",
@@ -100,14 +100,14 @@
100
100
  "dotenv": "^16.4.5",
101
101
  "fetch-socks": "^1.3.0",
102
102
  "js-yaml": "4.1.0",
103
- "jsonrepair": "3.12.0",
103
+ "jsonrepair": "3.14.0",
104
104
  "mdast-util-from-markdown": "^2.0.2",
105
105
  "mdast-util-to-markdown": "^2.1.2",
106
106
  "openai": "6.3.0",
107
107
  "semver": "7.5.2",
108
108
  "undici": "^6.0.0",
109
109
  "zod": "^3.25.1",
110
- "@midscene/shared": "1.10.2-beta-20260706032158.0"
110
+ "@midscene/shared": "1.10.3"
111
111
  },
112
112
  "devDependencies": {
113
113
  "@rslib/core": "^0.18.3",