@midscene/core 1.14.0 → 1.15.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (96) hide show
  1. package/dist/es/agent/action-readiness.mjs +72 -0
  2. package/dist/es/agent/action-readiness.mjs.map +1 -0
  3. package/dist/es/agent/agent.mjs +14 -6
  4. package/dist/es/agent/agent.mjs.map +1 -1
  5. package/dist/es/agent/task-builder.mjs +45 -33
  6. package/dist/es/agent/task-builder.mjs.map +1 -1
  7. package/dist/es/agent/tasks.mjs +9 -2
  8. package/dist/es/agent/tasks.mjs.map +1 -1
  9. package/dist/es/agent/utils.mjs +1 -1
  10. package/dist/es/ai-model/connectivity/run-connectivity-test.mjs +24 -6
  11. package/dist/es/ai-model/connectivity/run-connectivity-test.mjs.map +1 -1
  12. package/dist/es/ai-model/service-caller/call-ai.mjs +10 -3
  13. package/dist/es/ai-model/service-caller/call-ai.mjs.map +1 -1
  14. package/dist/es/ai-model/service-caller/openai/call-openai.mjs +3 -2
  15. package/dist/es/ai-model/service-caller/openai/call-openai.mjs.map +1 -1
  16. package/dist/es/ai-model/service-caller/openai/chat-completion/stream.mjs +10 -6
  17. package/dist/es/ai-model/service-caller/openai/chat-completion/stream.mjs.map +1 -1
  18. package/dist/es/ai-model/service-caller/openai/responses/stream.mjs +8 -1
  19. package/dist/es/ai-model/service-caller/openai/responses/stream.mjs.map +1 -1
  20. package/dist/es/ai-model/service-caller/utils.mjs +3 -2
  21. package/dist/es/ai-model/service-caller/utils.mjs.map +1 -1
  22. package/dist/es/device/index.mjs +11 -4
  23. package/dist/es/device/index.mjs.map +1 -1
  24. package/dist/es/index.mjs.map +1 -1
  25. package/dist/es/report-html-template.mjs +1 -1
  26. package/dist/es/types.mjs.map +1 -1
  27. package/dist/es/utils.mjs +1 -1
  28. package/dist/es/yaml/legacy-yaml-runtime.mjs +6 -0
  29. package/dist/es/yaml/legacy-yaml-runtime.mjs.map +1 -1
  30. package/dist/es/yaml/player.mjs +7 -3
  31. package/dist/es/yaml/player.mjs.map +1 -1
  32. package/dist/lib/agent/action-readiness.js +112 -0
  33. package/dist/lib/agent/action-readiness.js.map +1 -0
  34. package/dist/lib/agent/agent.js +13 -5
  35. package/dist/lib/agent/agent.js.map +1 -1
  36. package/dist/lib/agent/task-builder.js +45 -33
  37. package/dist/lib/agent/task-builder.js.map +1 -1
  38. package/dist/lib/agent/tasks.js +9 -2
  39. package/dist/lib/agent/tasks.js.map +1 -1
  40. package/dist/lib/agent/utils.js +1 -1
  41. package/dist/lib/ai-model/connectivity/run-connectivity-test.js +24 -6
  42. package/dist/lib/ai-model/connectivity/run-connectivity-test.js.map +1 -1
  43. package/dist/lib/ai-model/service-caller/call-ai.js +10 -3
  44. package/dist/lib/ai-model/service-caller/call-ai.js.map +1 -1
  45. package/dist/lib/ai-model/service-caller/openai/call-openai.js +3 -2
  46. package/dist/lib/ai-model/service-caller/openai/call-openai.js.map +1 -1
  47. package/dist/lib/ai-model/service-caller/openai/chat-completion/stream.js +10 -6
  48. package/dist/lib/ai-model/service-caller/openai/chat-completion/stream.js.map +1 -1
  49. package/dist/lib/ai-model/service-caller/openai/responses/stream.js +8 -1
  50. package/dist/lib/ai-model/service-caller/openai/responses/stream.js.map +1 -1
  51. package/dist/lib/ai-model/service-caller/utils.js +3 -2
  52. package/dist/lib/ai-model/service-caller/utils.js.map +1 -1
  53. package/dist/lib/device/index.js +11 -4
  54. package/dist/lib/device/index.js.map +1 -1
  55. package/dist/lib/index.js.map +1 -1
  56. package/dist/lib/report-html-template.js +1 -1
  57. package/dist/lib/types.js.map +1 -1
  58. package/dist/lib/utils.js +1 -1
  59. package/dist/lib/yaml/legacy-yaml-runtime.js +6 -0
  60. package/dist/lib/yaml/legacy-yaml-runtime.js.map +1 -1
  61. package/dist/lib/yaml/player.js +7 -3
  62. package/dist/lib/yaml/player.js.map +1 -1
  63. package/dist/types/agent/action-readiness.d.ts +14 -0
  64. package/dist/types/agent/action-readiness.d.ts.map +1 -0
  65. package/dist/types/agent/agent.d.ts +6 -2
  66. package/dist/types/agent/agent.d.ts.map +1 -1
  67. package/dist/types/agent/index.d.ts +1 -1
  68. package/dist/types/agent/index.d.ts.map +1 -1
  69. package/dist/types/agent/task-builder.d.ts +4 -1
  70. package/dist/types/agent/task-builder.d.ts.map +1 -1
  71. package/dist/types/agent/tasks.d.ts +3 -0
  72. package/dist/types/agent/tasks.d.ts.map +1 -1
  73. package/dist/types/ai-model/connectivity/index.d.ts +1 -1
  74. package/dist/types/ai-model/connectivity/index.d.ts.map +1 -1
  75. package/dist/types/ai-model/connectivity/run-connectivity-test.d.ts +14 -1
  76. package/dist/types/ai-model/connectivity/run-connectivity-test.d.ts.map +1 -1
  77. package/dist/types/ai-model/index.d.ts +1 -1
  78. package/dist/types/ai-model/index.d.ts.map +1 -1
  79. package/dist/types/ai-model/model-adapter/types.d.ts +2 -0
  80. package/dist/types/ai-model/model-adapter/types.d.ts.map +1 -1
  81. package/dist/types/ai-model/service-caller/call-ai.d.ts.map +1 -1
  82. package/dist/types/ai-model/service-caller/openai/call-openai.d.ts.map +1 -1
  83. package/dist/types/ai-model/service-caller/openai/chat-completion/stream.d.ts.map +1 -1
  84. package/dist/types/ai-model/service-caller/openai/responses/stream.d.ts.map +1 -1
  85. package/dist/types/ai-model/service-caller/utils.d.ts +3 -2
  86. package/dist/types/ai-model/service-caller/utils.d.ts.map +1 -1
  87. package/dist/types/device/index.d.ts +7 -1
  88. package/dist/types/device/index.d.ts.map +1 -1
  89. package/dist/types/index.d.ts +1 -1
  90. package/dist/types/index.d.ts.map +1 -1
  91. package/dist/types/types.d.ts +28 -1
  92. package/dist/types/types.d.ts.map +1 -1
  93. package/dist/types/yaml/legacy-yaml-runtime.d.ts.map +1 -1
  94. package/dist/types/yaml/player.d.ts +2 -1
  95. package/dist/types/yaml/player.d.ts.map +1 -1
  96. package/package.json +2 -2
@@ -0,0 +1,72 @@
1
+ import { getErrorMessage } from "@midscene/shared/agent-tools/error-formatter";
2
+ import { getDebug } from "@midscene/shared/logger";
3
+ function _define_property(obj, key, value) {
4
+ if (key in obj) Object.defineProperty(obj, key, {
5
+ value: value,
6
+ enumerable: true,
7
+ configurable: true,
8
+ writable: true
9
+ });
10
+ else obj[key] = value;
11
+ return obj;
12
+ }
13
+ const warn = getDebug('agent:action-readiness', {
14
+ console: true
15
+ });
16
+ const errorCode = 'ACTION_READINESS_FAILED';
17
+ class ActionReadinessError extends Error {
18
+ constructor(phase, actionName, cause){
19
+ super(`waitForActionReady ${phase} failed for ${actionName}: ${getErrorMessage(cause)}`, {
20
+ cause
21
+ }), _define_property(this, "code", errorCode);
22
+ this.name = 'ActionReadinessError';
23
+ }
24
+ }
25
+ function isActionReadinessError(error) {
26
+ const seen = new Set();
27
+ while(error && 'object' == typeof error && !seen.has(error)){
28
+ seen.add(error);
29
+ const value = error;
30
+ if (value.code === errorCode) return true;
31
+ error = value.cause;
32
+ }
33
+ return false;
34
+ }
35
+ class ActionReadiness {
36
+ async wait(action, signal) {
37
+ signal?.throwIfAborted();
38
+ let onAbort;
39
+ const timer = setTimeout(()=>{
40
+ warn(`waitForActionReady for ${action.name} (${action.id}) is still pending after 5000ms; continuing to wait.`);
41
+ }, 5000);
42
+ try {
43
+ await new Promise((resolve, reject)=>{
44
+ if (signal) {
45
+ onAbort = ()=>reject(signal.reason);
46
+ signal.addEventListener('abort', onAbort, {
47
+ once: true
48
+ });
49
+ }
50
+ Promise.resolve(this.callback({
51
+ action,
52
+ signal
53
+ })).then(resolve, reject);
54
+ });
55
+ signal?.throwIfAborted();
56
+ } catch (cause) {
57
+ signal?.throwIfAborted();
58
+ throw new ActionReadinessError('wait', action.name, cause);
59
+ } finally{
60
+ clearTimeout(timer);
61
+ if (signal && onAbort) signal.removeEventListener('abort', onAbort);
62
+ }
63
+ }
64
+ constructor(callback){
65
+ _define_property(this, "callback", void 0);
66
+ this.callback = callback;
67
+ if ('function' != typeof callback) throw new Error('waitForActionReady must be a function');
68
+ }
69
+ }
70
+ export { ActionReadiness, ActionReadinessError, isActionReadinessError };
71
+
72
+ //# sourceMappingURL=action-readiness.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"agent/action-readiness.mjs","sources":["../../../src/agent/action-readiness.ts"],"sourcesContent":["import type { ActionReadyContext, WaitForActionReady } from '@/types';\nimport { getErrorMessage } from '@midscene/shared/agent-tools/error-formatter';\nimport { getDebug } from '@midscene/shared/logger';\n\nconst warn = getDebug('agent:action-readiness', { console: true });\nconst errorCode = 'ACTION_READINESS_FAILED';\n\nexport class ActionReadinessError extends Error {\n readonly code = errorCode;\n\n constructor(phase: string, actionName: string, cause: unknown) {\n super(\n `waitForActionReady ${phase} failed for ${actionName}: ${getErrorMessage(cause)}`,\n { cause },\n );\n this.name = 'ActionReadinessError';\n }\n}\n\n/** Also recognizes the bounded cause retained by TaskExecutionError. */\nexport function isActionReadinessError(error: unknown): boolean {\n const seen = new Set<unknown>();\n while (error && typeof error === 'object' && !seen.has(error)) {\n seen.add(error);\n const value = error as { code?: unknown; cause?: unknown };\n if (value.code === errorCode) return true;\n error = value.cause;\n }\n return false;\n}\n\n/** Await application readiness after a successful action; slow waits only warn. */\nexport class ActionReadiness {\n constructor(private readonly callback: WaitForActionReady) {\n if (typeof callback !== 'function') {\n throw new Error('waitForActionReady must be a function');\n }\n }\n\n async wait(\n action: ActionReadyContext['action'],\n signal?: AbortSignal,\n ): Promise<void> {\n signal?.throwIfAborted();\n let onAbort: (() => void) | undefined;\n const timer = setTimeout(() => {\n warn(\n `waitForActionReady for ${action.name} (${action.id}) is still pending after 5000ms; continuing to wait.`,\n );\n }, 5000);\n try {\n await new Promise<void>((resolve, reject) => {\n // Listen before invoking user code, including callbacks that abort\n // synchronously or never settle. Both late outcomes stay handled.\n if (signal) {\n onAbort = () => reject(signal.reason);\n signal.addEventListener('abort', onAbort, { once: true });\n }\n Promise.resolve(this.callback({ action, signal })).then(\n resolve,\n reject,\n );\n });\n signal?.throwIfAborted();\n } catch (cause) {\n // Preserve the cancellation reason instead of reporting a readiness failure.\n signal?.throwIfAborted();\n throw new ActionReadinessError('wait', action.name, cause);\n } finally {\n clearTimeout(timer);\n if (signal && onAbort) signal.removeEventListener('abort', onAbort);\n }\n }\n}\n"],"names":["warn","getDebug","errorCode","ActionReadinessError","Error","phase","actionName","cause","getErrorMessage","isActionReadinessError","error","seen","Set","value","ActionReadiness","action","signal","onAbort","timer","setTimeout","Promise","resolve","reject","clearTimeout","callback"],"mappings":";;;;;;;;;;;;AAIA,MAAMA,OAAOC,SAAS,0BAA0B;IAAE,SAAS;AAAK;AAChE,MAAMC,YAAY;AAEX,MAAMC,6BAA6BC;IAGxC,YAAYC,KAAa,EAAEC,UAAkB,EAAEC,KAAc,CAAE;QAC7D,KAAK,CACH,CAAC,mBAAmB,EAAEF,MAAM,YAAY,EAAEC,WAAW,EAAE,EAAEE,gBAAgBD,QAAQ,EACjF;YAAEA;QAAM,IALZ,uBAAS,QAAOL;QAOd,IAAI,CAAC,IAAI,GAAG;IACd;AACF;AAGO,SAASO,uBAAuBC,KAAc;IACnD,MAAMC,OAAO,IAAIC;IACjB,MAAOF,SAAS,AAAiB,YAAjB,OAAOA,SAAsB,CAACC,KAAK,GAAG,CAACD,OAAQ;QAC7DC,KAAK,GAAG,CAACD;QACT,MAAMG,QAAQH;QACd,IAAIG,MAAM,IAAI,KAAKX,WAAW,OAAO;QACrCQ,QAAQG,MAAM,KAAK;IACrB;IACA,OAAO;AACT;AAGO,MAAMC;IAOX,MAAM,KACJC,MAAoC,EACpCC,MAAoB,EACL;QACfA,QAAQ;QACR,IAAIC;QACJ,MAAMC,QAAQC,WAAW;YACvBnB,KACE,CAAC,uBAAuB,EAAEe,OAAO,IAAI,CAAC,EAAE,EAAEA,OAAO,EAAE,CAAC,oDAAoD,CAAC;QAE7G,GAAG;QACH,IAAI;YACF,MAAM,IAAIK,QAAc,CAACC,SAASC;gBAGhC,IAAIN,QAAQ;oBACVC,UAAU,IAAMK,OAAON,OAAO,MAAM;oBACpCA,OAAO,gBAAgB,CAAC,SAASC,SAAS;wBAAE,MAAM;oBAAK;gBACzD;gBACAG,QAAQ,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC;oBAAEL;oBAAQC;gBAAO,IAAI,IAAI,CACrDK,SACAC;YAEJ;YACAN,QAAQ;QACV,EAAE,OAAOT,OAAO;YAEdS,QAAQ;YACR,MAAM,IAAIb,qBAAqB,QAAQY,OAAO,IAAI,EAAER;QACtD,SAAU;YACRgB,aAAaL;YACb,IAAIF,UAAUC,SAASD,OAAO,mBAAmB,CAAC,SAASC;QAC7D;IACF;IAvCA,YAA6BO,QAA4B,CAAE;;aAA9BA,QAAQ,GAARA;QAC3B,IAAI,AAAoB,cAApB,OAAOA,UACT,MAAM,IAAIpB,MAAM;IAEpB;AAoCF"}
@@ -9,7 +9,7 @@ import { waitForResourceIdle } from "../test-runner/engine/resource-operations.m
9
9
  import { buildAgentTestRunReportDump } from "../test-runner/reporting/agent-report.mjs";
10
10
  import { executionRecordsToReportInput } from "../test-runner/reporting/execution-record.mjs";
11
11
  import { ExecutionDump, ReportActionDump } from "../types.mjs";
12
- import { YamlExecutionOwnershipError, enterYamlAction, enterYamlExecution, runInYamlExecutionContext } from "../yaml/execution-session.mjs";
12
+ import { YamlExecutionOwnershipError, currentYamlSignal, enterYamlAction, enterYamlExecution, runInYamlExecutionContext } from "../yaml/execution-session.mjs";
13
13
  import { ReportGenerator, assertReportGenerationOptions } from "../report-generator.mjs";
14
14
  import { getVersion, processCacheConfig, reportHTMLContent } from "../utils.mjs";
15
15
  import { ScriptPlayer, buildDetailedLocateParam, buildDetailedLocateParamAndRestParams, parseYamlScript } from "../yaml/index.mjs";
@@ -22,6 +22,7 @@ import { MIDSCENE_REPLANNING_CYCLE_LIMIT, ModelConfigManager, globalConfigManage
22
22
  import { getDebug } from "@midscene/shared/logger";
23
23
  import { assert, ifInBrowser, uuid } from "@midscene/shared/utils";
24
24
  import { defineActionRegisterFileChooserAccept, defineActionSleep } from "../device/index.mjs";
25
+ import { ActionReadiness, isActionReadinessError } from "./action-readiness.mjs";
25
26
  import { validateAgentCacheInput } from "./cache-config.mjs";
26
27
  import { FileChooserAccepter } from "./file-chooser.mjs";
27
28
  import { Insight } from "./insight.mjs";
@@ -352,7 +353,7 @@ class Agent {
352
353
  wrapActionInActionSpace(name) {
353
354
  return async (param)=>await this.callActionInActionSpace(name, param);
354
355
  }
355
- async callActionInActionSpace(type, opt) {
356
+ async callActionInActionSpace(type, opt, abortSignal) {
356
357
  debug('callActionInActionSpace', type, ',', opt);
357
358
  const clonedActionParam = opt && 'object' == typeof opt && !Array.isArray(opt) ? {
358
359
  ...opt
@@ -369,7 +370,9 @@ class Agent {
369
370
  const title = taskTitleStr(type, locateParamStr(opt?.locate || {}));
370
371
  const defaultModel = this.resolveModelRuntime('default');
371
372
  const planningModel = this.resolveModelRuntime('planning');
372
- const { output } = await this.taskExecutor.runPlans(title, plans, planningModel, defaultModel);
373
+ const { output } = await this.taskExecutor.runPlans(title, plans, planningModel, defaultModel, {
374
+ abortSignal: abortSignal ?? currentYamlSignal(this)
375
+ });
373
376
  return output;
374
377
  }
375
378
  async aiTap(locatePrompt, opt) {
@@ -558,7 +561,7 @@ class Agent {
558
561
  });
559
562
  return;
560
563
  } catch (error) {
561
- if (error instanceof YamlExecutionOwnershipError) throw error;
564
+ if (error instanceof YamlExecutionOwnershipError || isActionReadinessError(error)) throw error;
562
565
  abortSignal?.throwIfAborted();
563
566
  cachedYamlFailed = true;
564
567
  warn(`cached aiAct plan failed, will replan and disable the stale cache: ${error instanceof Error ? error.message : String(error)}`);
@@ -686,15 +689,17 @@ class Agent {
686
689
  async ai(...args) {
687
690
  return this.aiAct(...args);
688
691
  }
689
- async runYaml(yamlScriptContent) {
692
+ async runYaml(yamlScriptContent, options) {
690
693
  if (this.destroyed) throw new Error('Cannot run YAML using a destroyed Agent.');
691
694
  const script = parseYamlScript(yamlScriptContent, 'yaml');
692
695
  const player = new ScriptPlayer(script, async ()=>({
693
696
  agent: this,
694
697
  freeFn: []
695
- }));
698
+ }), void 0, void 0, options?.abortSignal);
696
699
  await player.run();
697
700
  if ('error' === player.status) {
701
+ const readinessFailure = player.taskStatusList.find((task)=>isActionReadinessError(task.error));
702
+ if (readinessFailure) throw readinessFailure.error;
698
703
  const errors = player.taskStatusList.filter((task)=>'error' === task.status).map((task)=>`task - ${task.name}: ${task.error?.message}`).join('\n');
699
704
  throw new Error(`Error(s) occurred in running yaml script:\n${errors}`);
700
705
  }
@@ -938,6 +943,7 @@ class Agent {
938
943
  _define_property(this, "dumpUpdateListeners", []);
939
944
  _define_property(this, "progressBus", new AgentProgressBus());
940
945
  _define_property(this, "destroyed", false);
946
+ _define_property(this, "actionReadiness", void 0);
941
947
  _define_property(this, "modelConfigManager", void 0);
942
948
  _define_property(this, "frozenUIContext", void 0);
943
949
  _define_property(this, "activeObserver", null);
@@ -957,6 +963,7 @@ class Agent {
957
963
  groupDescription: ''
958
964
  }, opts || {});
959
965
  assertReportGenerationOptions(this.opts);
966
+ if (void 0 !== this.opts.waitForActionReady) this.actionReadiness = new ActionReadiness(this.opts.waitForActionReady);
960
967
  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');
961
968
  for (const [key, value] of Object.entries(this.opts.aiContexts ?? {})){
962
969
  if (!isAgentAIContextKey(key)) throw new TypeError(`Unknown Agent context key: ${key}`);
@@ -1002,6 +1009,7 @@ class Agent {
1002
1009
  onTaskStart: this.callbackOnTaskStartTip.bind(this),
1003
1010
  replanningCycleLimit: this.opts.replanningCycleLimit,
1004
1011
  waitAfterAction: this.opts.waitAfterAction,
1012
+ actionReadiness: this.actionReadiness,
1005
1013
  useDeviceTime: this.opts.useDeviceTime,
1006
1014
  actionSpace: this.fullActionSpace,
1007
1015
  hooks: {