@midscene/core 1.12.4-beta-20260904041024.0 → 1.12.4

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 (65) hide show
  1. package/dist/es/agent/agent.mjs +72 -25
  2. package/dist/es/agent/agent.mjs.map +1 -1
  3. package/dist/es/agent/index.mjs +2 -1
  4. package/dist/es/agent/insight.mjs +26 -10
  5. package/dist/es/agent/insight.mjs.map +1 -1
  6. package/dist/es/agent/prompt-context.mjs +12 -7
  7. package/dist/es/agent/prompt-context.mjs.map +1 -1
  8. package/dist/es/agent/run-gherkin-scenario.mjs +1 -1
  9. package/dist/es/agent/run-gherkin-scenario.mjs.map +1 -1
  10. package/dist/es/agent/tasks.mjs +2 -1
  11. package/dist/es/agent/tasks.mjs.map +1 -1
  12. package/dist/es/agent/test-runner-nodes.mjs +274 -0
  13. package/dist/es/agent/test-runner-nodes.mjs.map +1 -0
  14. package/dist/es/agent/utils.mjs +1 -1
  15. package/dist/es/ai-model/prompt/insight/user-prompt.mjs +1 -1
  16. package/dist/es/ai-model/prompt/insight/user-prompt.mjs.map +1 -1
  17. package/dist/es/ai-model/workflows/insight/extraction.mjs +3 -1
  18. package/dist/es/ai-model/workflows/insight/extraction.mjs.map +1 -1
  19. package/dist/es/ai-model/workflows/planning/custom-planning.mjs +3 -3
  20. package/dist/es/ai-model/workflows/planning/custom-planning.mjs.map +1 -1
  21. package/dist/es/ai-model/workflows/planning/standard-planning.mjs +1 -1
  22. package/dist/es/ai-model/workflows/planning/standard-planning.mjs.map +1 -1
  23. package/dist/es/report-html-template.mjs +1 -1
  24. package/dist/es/types.mjs.map +1 -1
  25. package/dist/es/utils.mjs +1 -1
  26. package/dist/es/yaml/player.mjs +0 -5
  27. package/dist/es/yaml/player.mjs.map +1 -1
  28. package/dist/es/yaml.mjs.map +1 -1
  29. package/dist/lib/agent/agent.js +72 -25
  30. package/dist/lib/agent/agent.js.map +1 -1
  31. package/dist/lib/agent/index.js +57 -8
  32. package/dist/lib/agent/insight.js +26 -10
  33. package/dist/lib/agent/insight.js.map +1 -1
  34. package/dist/lib/agent/prompt-context.js +16 -8
  35. package/dist/lib/agent/prompt-context.js.map +1 -1
  36. package/dist/lib/agent/run-gherkin-scenario.js +1 -1
  37. package/dist/lib/agent/run-gherkin-scenario.js.map +1 -1
  38. package/dist/lib/agent/tasks.js +2 -1
  39. package/dist/lib/agent/tasks.js.map +1 -1
  40. package/dist/lib/agent/test-runner-nodes.js +353 -0
  41. package/dist/lib/agent/test-runner-nodes.js.map +1 -0
  42. package/dist/lib/agent/utils.js +1 -1
  43. package/dist/lib/ai-model/prompt/insight/user-prompt.js +1 -1
  44. package/dist/lib/ai-model/prompt/insight/user-prompt.js.map +1 -1
  45. package/dist/lib/ai-model/workflows/insight/extraction.js +3 -1
  46. package/dist/lib/ai-model/workflows/insight/extraction.js.map +1 -1
  47. package/dist/lib/ai-model/workflows/planning/custom-planning.js +3 -3
  48. package/dist/lib/ai-model/workflows/planning/custom-planning.js.map +1 -1
  49. package/dist/lib/ai-model/workflows/planning/standard-planning.js +1 -1
  50. package/dist/lib/ai-model/workflows/planning/standard-planning.js.map +1 -1
  51. package/dist/lib/report-html-template.js +1 -1
  52. package/dist/lib/types.js.map +1 -1
  53. package/dist/lib/utils.js +1 -1
  54. package/dist/lib/yaml/player.js +0 -5
  55. package/dist/lib/yaml/player.js.map +1 -1
  56. package/dist/lib/yaml.js.map +1 -1
  57. package/dist/types/agent/agent.d.ts +26 -3
  58. package/dist/types/agent/index.d.ts +3 -1
  59. package/dist/types/agent/insight.d.ts +5 -1
  60. package/dist/types/agent/prompt-context.d.ts +2 -0
  61. package/dist/types/agent/run-gherkin-scenario.d.ts +1 -0
  62. package/dist/types/agent/test-runner-nodes.d.ts +192 -0
  63. package/dist/types/types.d.ts +28 -0
  64. package/dist/types/yaml.d.ts +12 -4
  65. package/package.json +10 -2
@@ -10,6 +10,7 @@ import { getVersion, processCacheConfig, reportHTMLContent } from "../utils.mjs"
10
10
  import { ScriptPlayer, buildDetailedLocateParam, buildDetailedLocateParamAndRestParams, parseYamlScript } from "../yaml/index.mjs";
11
11
  import { readFile } from "node:fs/promises";
12
12
  import { basename, resolve as external_node_path_resolve } from "node:path";
13
+ import { isAgentAIContextKey } from "@midscene/shared/agent-tools/agent-context";
13
14
  import { serializeError } from "@midscene/shared/agent-tools/error-formatter";
14
15
  import { observationArtifactAdapterSymbol } from "@midscene/shared/agent-tools/observation-artifact";
15
16
  import { MIDSCENE_REPLANNING_CYCLE_LIMIT, ModelConfigManager, globalConfigManager, globalModelConfigManager } from "@midscene/shared/env";
@@ -27,6 +28,7 @@ import { runGherkinScenario } from "./run-gherkin-scenario.mjs";
27
28
  import { markdownToAiActPrompt } from "./run-markdown.mjs";
28
29
  import { TaskCache } from "./task-cache.mjs";
29
30
  import { TaskExecutor, locatePlanForLocate, withFileChooser } from "./tasks.mjs";
31
+ import { commonAgentTestRunnerNodeDefinitions } from "./test-runner-nodes.mjs";
30
32
  import { UIObservationImpl, UIObserverImpl, uiContextFromObservationRecord } from "./ui-observer.mjs";
31
33
  import { locateParamStr, paramStr, taskTitleStr, typeStr } from "./ui-utils.mjs";
32
34
  import { commonContextParser, getReportFileName, normalizeFilePaths, normalizeScrollType } from "./utils.mjs";
@@ -45,6 +47,9 @@ const warn = getDebug('agent', {
45
47
  console: true
46
48
  });
47
49
  class Agent {
50
+ static getTestRunnerNodeDefinitions() {
51
+ return commonAgentTestRunnerNodeDefinitions;
52
+ }
48
53
  get onDumpUpdate() {
49
54
  return this.dumpUpdateListeners[0];
50
55
  }
@@ -52,8 +57,24 @@ class Agent {
52
57
  this.dumpUpdateListeners = [];
53
58
  if (callback) this.dumpUpdateListeners.push(callback);
54
59
  }
55
- get aiActContext() {
56
- return this.opts.aiActContext ?? this.opts.aiActionContext;
60
+ get aiContexts() {
61
+ if (!this.opts.aiContexts) this.opts.aiContexts = {};
62
+ return this.opts.aiContexts;
63
+ }
64
+ resolveUserContext(apiName, callContext) {
65
+ if (void 0 !== callContext) return callContext;
66
+ const apiContext = this.opts.aiContexts?.[apiName];
67
+ if (void 0 !== apiContext) return apiContext;
68
+ const defaultContext = this.opts.aiContexts?.default;
69
+ if (void 0 !== defaultContext) return defaultContext;
70
+ }
71
+ withContext(apiName, options) {
72
+ const resolvedContext = this.resolveUserContext(apiName, options?.context);
73
+ if (void 0 === resolvedContext) return options;
74
+ return {
75
+ ...options ?? {},
76
+ context: resolvedContext
77
+ };
57
78
  }
58
79
  get page() {
59
80
  return this.interface;
@@ -79,7 +100,7 @@ class Agent {
79
100
  };
80
101
  }
81
102
  createInsight(getUIContext) {
82
- return new Insight(this.taskExecutor, ()=>this.resolveModelRuntime('insight'), getUIContext);
103
+ return new Insight(this.taskExecutor, ()=>this.resolveModelRuntime('insight'), (apiName, callContext)=>this.resolveUserContext(apiName, callContext), getUIContext);
83
104
  }
84
105
  async getActionSpace() {
85
106
  return this.fullActionSpace;
@@ -140,12 +161,24 @@ class Agent {
140
161
  return observer;
141
162
  }
142
163
  async setAIActionContext(prompt) {
143
- await this.setAIActContext(prompt);
164
+ warn('setAIActionContext() is deprecated; use setAIContext("aiAct", context) instead.');
165
+ this.setAIContext('aiAct', prompt);
144
166
  }
145
167
  async setAIActContext(prompt) {
146
- if (this.aiActContext) console.warn('aiActContext is already set, and it is called again, will override the previous setting');
147
- this.opts.aiActContext = prompt;
148
- this.opts.aiActionContext = prompt;
168
+ warn('setAIActContext() is deprecated; use setAIContext("aiAct", context) instead.');
169
+ this.setAIContext('aiAct', prompt);
170
+ }
171
+ setAIContext(target, context) {
172
+ if (!isAgentAIContextKey(target)) throw new TypeError(`Unknown Agent context key: ${String(target)}`);
173
+ if (void 0 !== context && 'string' != typeof context) throw new TypeError('Agent context must be a string or undefined');
174
+ this.aiContexts[target] = context;
175
+ if ('aiAct' === target) if (void 0 === context) {
176
+ this.opts.aiActContext = void 0;
177
+ this.opts.aiActionContext = void 0;
178
+ } else {
179
+ this.opts.aiActContext = context;
180
+ this.opts.aiActionContext = context;
181
+ }
149
182
  }
150
183
  resetDump() {
151
184
  this.dump = new ReportActionDump({
@@ -249,7 +282,7 @@ class Agent {
249
282
  }
250
283
  async aiTap(locatePrompt, opt) {
251
284
  assert(locatePrompt, 'missing locate prompt for tap');
252
- const detailedLocateParam = buildDetailedLocateParam(locatePrompt, opt);
285
+ const detailedLocateParam = buildDetailedLocateParam(locatePrompt, this.withContext('aiTap', opt));
253
286
  const fileChooserAccept = opt?.fileChooserAccept ? this.normalizeFileInput(opt.fileChooserAccept) : void 0;
254
287
  await withFileChooser(this.interface, fileChooserAccept, async ()=>{
255
288
  await this.callActionInActionSpace('Tap', {
@@ -259,21 +292,21 @@ class Agent {
259
292
  }
260
293
  async aiRightClick(locatePrompt, opt) {
261
294
  assert(locatePrompt, 'missing locate prompt for right click');
262
- const detailedLocateParam = buildDetailedLocateParam(locatePrompt, opt);
295
+ const detailedLocateParam = buildDetailedLocateParam(locatePrompt, this.withContext('aiRightClick', opt));
263
296
  await this.callActionInActionSpace('RightClick', {
264
297
  locate: detailedLocateParam
265
298
  });
266
299
  }
267
300
  async aiDoubleClick(locatePrompt, opt) {
268
301
  assert(locatePrompt, 'missing locate prompt for double click');
269
- const detailedLocateParam = buildDetailedLocateParam(locatePrompt, opt);
302
+ const detailedLocateParam = buildDetailedLocateParam(locatePrompt, this.withContext('aiDoubleClick', opt));
270
303
  await this.callActionInActionSpace('DoubleClick', {
271
304
  locate: detailedLocateParam
272
305
  });
273
306
  }
274
307
  async aiHover(locatePrompt, opt) {
275
308
  assert(locatePrompt, 'missing locate prompt for hover');
276
- const detailedLocateParam = buildDetailedLocateParam(locatePrompt, opt);
309
+ const detailedLocateParam = buildDetailedLocateParam(locatePrompt, this.withContext('aiHover', opt));
277
310
  await this.callActionInActionSpace('Hover', {
278
311
  locate: detailedLocateParam
279
312
  });
@@ -297,7 +330,7 @@ class Agent {
297
330
  }
298
331
  assert('string' == typeof value || 'number' == typeof value, 'input value must be a string or number, use empty string if you want to clear the input');
299
332
  assert(locatePrompt, 'missing locate prompt for input');
300
- const { locateParam, restParams } = buildDetailedLocateParamAndRestParams(locatePrompt, opt);
333
+ const { locateParam, restParams } = buildDetailedLocateParamAndRestParams(locatePrompt, this.withContext('aiInput', opt));
301
334
  const stringValue = 'number' == typeof value ? String(value) : value;
302
335
  const mode = opt?.mode === 'append' ? 'typeOnly' : opt?.mode;
303
336
  await this.callActionInActionSpace('Input', {
@@ -323,7 +356,7 @@ class Agent {
323
356
  };
324
357
  }
325
358
  assert(opt?.keyName, 'missing keyName for keyboard press');
326
- const { locateParam, restParams } = buildDetailedLocateParamAndRestParams(locatePrompt || '', opt);
359
+ const { locateParam, restParams } = buildDetailedLocateParamAndRestParams(locatePrompt || '', this.withContext('aiKeyboardPress', opt));
327
360
  await this.callActionInActionSpace('KeyboardPress', {
328
361
  ...restParams,
329
362
  locate: locateParam
@@ -355,14 +388,14 @@ class Agent {
355
388
  scrollType: normalizedScrollType
356
389
  };
357
390
  }
358
- const { locateParam, restParams } = buildDetailedLocateParamAndRestParams(locatePrompt || '', opt);
391
+ const { locateParam, restParams } = buildDetailedLocateParamAndRestParams(locatePrompt || '', this.withContext('aiScroll', opt));
359
392
  await this.callActionInActionSpace('Scroll', {
360
393
  ...restParams,
361
394
  locate: locateParam
362
395
  });
363
396
  }
364
397
  async aiPinch(locatePrompt, opt) {
365
- const { locateParam, restParams } = buildDetailedLocateParamAndRestParams(locatePrompt || '', opt);
398
+ const { locateParam, restParams } = buildDetailedLocateParamAndRestParams(locatePrompt || '', this.withContext('aiPinch', opt));
366
399
  await this.callActionInActionSpace('Pinch', {
367
400
  ...restParams,
368
401
  locate: locateParam
@@ -370,7 +403,7 @@ class Agent {
370
403
  }
371
404
  async aiLongPress(locatePrompt, opt) {
372
405
  assert(locatePrompt, 'missing locate prompt for long press');
373
- const { locateParam, restParams } = buildDetailedLocateParamAndRestParams(locatePrompt, opt);
406
+ const { locateParam, restParams } = buildDetailedLocateParamAndRestParams(locatePrompt, this.withContext('aiLongPress', opt));
374
407
  await this.callActionInActionSpace('LongPress', {
375
408
  ...restParams,
376
409
  locate: locateParam
@@ -378,13 +411,14 @@ class Agent {
378
411
  }
379
412
  async aiClearInput(locatePrompt, opt) {
380
413
  assert(locatePrompt, 'missing locate prompt for clear input');
381
- const detailedLocateParam = buildDetailedLocateParam(locatePrompt, opt);
414
+ const detailedLocateParam = buildDetailedLocateParam(locatePrompt, this.withContext('aiClearInput', opt));
382
415
  await this.callActionInActionSpace('ClearInput', {
383
416
  locate: detailedLocateParam
384
417
  });
385
418
  }
386
419
  async aiAct(taskPrompt, opt) {
387
- const internalReportDisplay = opt?._internalReportDisplay;
420
+ const internalOptions = opt;
421
+ const internalReportDisplay = internalOptions?._internalReportDisplay;
388
422
  const taskPromptText = 'string' == typeof taskPrompt ? taskPrompt : taskPrompt.prompt;
389
423
  const reportPrompt = internalReportDisplay?.prompt || taskPromptText;
390
424
  const fileChooserAccept = opt?.fileChooserAccept ? this.normalizeFileInput(opt.fileChooserAccept) : void 0;
@@ -393,7 +427,7 @@ class Agent {
393
427
  const runAiAct = async ()=>{
394
428
  const planningModel = this.resolveModelRuntime('planning');
395
429
  const defaultModel = this.resolveModelRuntime('default');
396
- const aiActContext = opt?.context !== void 0 ? opt.context : this.aiActContext;
430
+ const aiActContext = this.resolveUserContext('aiAct', opt?.context);
397
431
  const cachePrompt = buildPromptWithContext(taskPrompt, aiActContext);
398
432
  const effort = (()=>{
399
433
  const resolvedEffort = opt?.effort ?? (opt?.deepThink === true ? 'deepThink' : 'balance');
@@ -511,7 +545,7 @@ class Agent {
511
545
  return this.createInsight().aiAsk(prompt, opt);
512
546
  }
513
547
  async aiLocate(prompt, opt) {
514
- const locateParam = buildDetailedLocateParam(prompt, opt);
548
+ const locateParam = buildDetailedLocateParam(prompt, this.withContext('aiLocate', opt));
515
549
  assert(locateParam, 'cannot get locate param for aiLocate');
516
550
  const locatePlan = locatePlanForLocate(locateParam);
517
551
  const plans = [
@@ -534,10 +568,11 @@ class Agent {
534
568
  }
535
569
  async aiWaitFor(assertion, opt) {
536
570
  const modelRuntime = this.resolveModelRuntime('insight');
571
+ const options = this.withContext('aiWaitFor', opt);
537
572
  await this.taskExecutor.waitFor(assertion, {
538
- ...opt,
539
- timeoutMs: opt?.timeoutMs || 15000,
540
- checkIntervalMs: opt?.checkIntervalMs || 3000
573
+ ...options,
574
+ timeoutMs: options?.timeoutMs || 15000,
575
+ checkIntervalMs: options?.checkIntervalMs || 3000
541
576
  }, modelRuntime);
542
577
  }
543
578
  async ai(...args) {
@@ -806,11 +841,23 @@ class Agent {
806
841
  groupDescription: ''
807
842
  }, opts || {});
808
843
  assertReportGenerationOptions(this.opts);
809
- const resolvedAiActContext = this.opts.aiActContext ?? this.opts.aiActionContext;
844
+ if (void 0 !== this.opts.aiContexts && ('object' != typeof this.opts.aiContexts || null === this.opts.aiContexts || Array.isArray(this.opts.aiContexts))) throw new TypeError('opts.aiContexts must be a plain object');
845
+ for (const [key, value] of Object.entries(this.opts.aiContexts ?? {})){
846
+ if (!isAgentAIContextKey(key)) throw new TypeError(`Unknown Agent context key: ${key}`);
847
+ if (void 0 !== value && 'string' != typeof value) throw new TypeError(`Agent context "${key}" must be a string`);
848
+ }
849
+ const deprecatedAiActContextOption = void 0 !== this.opts.aiActContext ? 'aiActContext' : void 0 !== this.opts.aiActionContext ? 'aiActionContext' : void 0;
850
+ if (deprecatedAiActContextOption) warn(`Agent option "${deprecatedAiActContextOption}" is deprecated; use "aiContexts.aiAct" instead. When both are provided, "aiContexts.aiAct" takes precedence.`);
851
+ const normalizedAIContexts = {
852
+ ...this.opts.aiContexts
853
+ };
854
+ const resolvedAiActContext = normalizedAIContexts.aiAct ?? this.opts.aiActContext ?? this.opts.aiActionContext;
810
855
  if (void 0 !== resolvedAiActContext) {
856
+ normalizedAIContexts.aiAct = resolvedAiActContext;
811
857
  this.opts.aiActContext = resolvedAiActContext;
812
- this.opts.aiActionContext ??= resolvedAiActContext;
858
+ this.opts.aiActionContext = resolvedAiActContext;
813
859
  }
860
+ this.opts.aiContexts = normalizedAIContexts;
814
861
  if (opts?.modelConfig && ('object' != typeof opts?.modelConfig || Array.isArray(opts.modelConfig))) throw new Error(`opts.modelConfig must be a plain object map of env keys to values, but got ${typeof opts?.modelConfig}`);
815
862
  const hasCustomConfig = opts?.modelConfig || opts?.createOpenAIClient;
816
863
  this.modelConfigManager = hasCustomConfig ? new ModelConfigManager(opts?.modelConfig, opts?.createOpenAIClient) : globalModelConfigManager;