@godscene/shared 1.7.11

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 (236) hide show
  1. package/README.md +9 -0
  2. package/dist/es/baseDB.mjs +109 -0
  3. package/dist/es/cli/cli-args.mjs +95 -0
  4. package/dist/es/cli/cli-error.mjs +24 -0
  5. package/dist/es/cli/cli-runner.mjs +122 -0
  6. package/dist/es/cli/index.mjs +4 -0
  7. package/dist/es/common.mjs +37 -0
  8. package/dist/es/constants/example-code.mjs +227 -0
  9. package/dist/es/constants/index.mjs +124 -0
  10. package/dist/es/env/basic.mjs +6 -0
  11. package/dist/es/env/constants.mjs +110 -0
  12. package/dist/es/env/global-config-manager.mjs +94 -0
  13. package/dist/es/env/helper.mjs +43 -0
  14. package/dist/es/env/index.mjs +5 -0
  15. package/dist/es/env/init-debug.mjs +18 -0
  16. package/dist/es/env/model-config-manager.mjs +79 -0
  17. package/dist/es/env/parse-model-config.mjs +165 -0
  18. package/dist/es/env/types.mjs +232 -0
  19. package/dist/es/env/utils.mjs +18 -0
  20. package/dist/es/extractor/constants.mjs +2 -0
  21. package/dist/es/extractor/cs_postmessage.mjs +61 -0
  22. package/dist/es/extractor/customLocator.mjs +641 -0
  23. package/dist/es/extractor/debug.mjs +6 -0
  24. package/dist/es/extractor/dom-util.mjs +96 -0
  25. package/dist/es/extractor/index.mjs +5 -0
  26. package/dist/es/extractor/locator.mjs +250 -0
  27. package/dist/es/extractor/tree.mjs +78 -0
  28. package/dist/es/extractor/util.mjs +245 -0
  29. package/dist/es/extractor/web-extractor.mjs +393 -0
  30. package/dist/es/img/box-select.mjs +824 -0
  31. package/dist/es/img/canvas-fallback.mjs +238 -0
  32. package/dist/es/img/get-photon.mjs +45 -0
  33. package/dist/es/img/get-sharp.mjs +11 -0
  34. package/dist/es/img/index.mjs +4 -0
  35. package/dist/es/img/info.mjs +35 -0
  36. package/dist/es/img/transform.mjs +275 -0
  37. package/dist/es/index.mjs +2 -0
  38. package/dist/es/key-alias-utils.mjs +19 -0
  39. package/dist/es/logger.mjs +64 -0
  40. package/dist/es/mcp/base-server.mjs +282 -0
  41. package/dist/es/mcp/base-tools.mjs +159 -0
  42. package/dist/es/mcp/chrome-path.mjs +35 -0
  43. package/dist/es/mcp/cli-report-session.mjs +78 -0
  44. package/dist/es/mcp/error-formatter.mjs +19 -0
  45. package/dist/es/mcp/index.mjs +9 -0
  46. package/dist/es/mcp/init-arg-utils.mjs +38 -0
  47. package/dist/es/mcp/inject-report-html-plugin.mjs +53 -0
  48. package/dist/es/mcp/launcher-helper.mjs +52 -0
  49. package/dist/es/mcp/tool-generator.mjs +419 -0
  50. package/dist/es/mcp/types.mjs +3 -0
  51. package/dist/es/node/fs.mjs +44 -0
  52. package/dist/es/node/index.mjs +2 -0
  53. package/dist/es/node/port.mjs +24 -0
  54. package/dist/es/polyfills/async-hooks.mjs +2 -0
  55. package/dist/es/polyfills/index.mjs +1 -0
  56. package/dist/es/types/index.mjs +3 -0
  57. package/dist/es/us-keyboard-layout.mjs +1414 -0
  58. package/dist/es/us-keyboard-layout.mjs.LICENSE.txt +5 -0
  59. package/dist/es/utils.mjs +72 -0
  60. package/dist/es/zod-schema-utils.mjs +54 -0
  61. package/dist/lib/baseDB.js +149 -0
  62. package/dist/lib/cli/cli-args.js +138 -0
  63. package/dist/lib/cli/cli-error.js +61 -0
  64. package/dist/lib/cli/cli-runner.js +181 -0
  65. package/dist/lib/cli/index.js +53 -0
  66. package/dist/lib/common.js +93 -0
  67. package/dist/lib/constants/example-code.js +264 -0
  68. package/dist/lib/constants/index.js +221 -0
  69. package/dist/lib/env/basic.js +40 -0
  70. package/dist/lib/env/constants.js +153 -0
  71. package/dist/lib/env/global-config-manager.js +128 -0
  72. package/dist/lib/env/helper.js +80 -0
  73. package/dist/lib/env/index.js +90 -0
  74. package/dist/lib/env/init-debug.js +52 -0
  75. package/dist/lib/env/model-config-manager.js +113 -0
  76. package/dist/lib/env/parse-model-config.js +211 -0
  77. package/dist/lib/env/types.js +572 -0
  78. package/dist/lib/env/utils.js +61 -0
  79. package/dist/lib/extractor/constants.js +42 -0
  80. package/dist/lib/extractor/cs_postmessage.js +98 -0
  81. package/dist/lib/extractor/customLocator.js +693 -0
  82. package/dist/lib/extractor/debug.js +12 -0
  83. package/dist/lib/extractor/dom-util.js +157 -0
  84. package/dist/lib/extractor/index.js +87 -0
  85. package/dist/lib/extractor/locator.js +296 -0
  86. package/dist/lib/extractor/tree.js +124 -0
  87. package/dist/lib/extractor/util.js +336 -0
  88. package/dist/lib/extractor/web-extractor.js +442 -0
  89. package/dist/lib/img/box-select.js +875 -0
  90. package/dist/lib/img/canvas-fallback.js +305 -0
  91. package/dist/lib/img/get-photon.js +82 -0
  92. package/dist/lib/img/get-sharp.js +45 -0
  93. package/dist/lib/img/index.js +95 -0
  94. package/dist/lib/img/info.js +92 -0
  95. package/dist/lib/img/transform.js +364 -0
  96. package/dist/lib/index.js +36 -0
  97. package/dist/lib/key-alias-utils.js +62 -0
  98. package/dist/lib/logger.js +114 -0
  99. package/dist/lib/mcp/base-server.js +332 -0
  100. package/dist/lib/mcp/base-tools.js +193 -0
  101. package/dist/lib/mcp/chrome-path.js +72 -0
  102. package/dist/lib/mcp/cli-report-session.js +121 -0
  103. package/dist/lib/mcp/error-formatter.js +53 -0
  104. package/dist/lib/mcp/index.js +114 -0
  105. package/dist/lib/mcp/init-arg-utils.js +78 -0
  106. package/dist/lib/mcp/inject-report-html-plugin.js +98 -0
  107. package/dist/lib/mcp/launcher-helper.js +86 -0
  108. package/dist/lib/mcp/tool-generator.js +456 -0
  109. package/dist/lib/mcp/types.js +40 -0
  110. package/dist/lib/node/fs.js +97 -0
  111. package/dist/lib/node/index.js +65 -0
  112. package/dist/lib/node/port.js +61 -0
  113. package/dist/lib/polyfills/async-hooks.js +36 -0
  114. package/dist/lib/polyfills/index.js +58 -0
  115. package/dist/lib/types/index.js +37 -0
  116. package/dist/lib/us-keyboard-layout.js +1457 -0
  117. package/dist/lib/us-keyboard-layout.js.LICENSE.txt +5 -0
  118. package/dist/lib/utils.js +148 -0
  119. package/dist/lib/zod-schema-utils.js +97 -0
  120. package/dist/types/baseDB.d.ts +25 -0
  121. package/dist/types/cli/cli-args.d.ts +8 -0
  122. package/dist/types/cli/cli-error.d.ts +5 -0
  123. package/dist/types/cli/cli-runner.d.ts +19 -0
  124. package/dist/types/cli/index.d.ts +4 -0
  125. package/dist/types/common.d.ts +12 -0
  126. package/dist/types/constants/example-code.d.ts +2 -0
  127. package/dist/types/constants/index.d.ts +61 -0
  128. package/dist/types/env/basic.d.ts +6 -0
  129. package/dist/types/env/constants.d.ts +50 -0
  130. package/dist/types/env/global-config-manager.d.ts +32 -0
  131. package/dist/types/env/helper.d.ts +4 -0
  132. package/dist/types/env/index.d.ts +4 -0
  133. package/dist/types/env/init-debug.d.ts +1 -0
  134. package/dist/types/env/model-config-manager.d.ts +25 -0
  135. package/dist/types/env/parse-model-config.d.ts +31 -0
  136. package/dist/types/env/types.d.ts +339 -0
  137. package/dist/types/env/utils.d.ts +7 -0
  138. package/dist/types/extractor/constants.d.ts +1 -0
  139. package/dist/types/extractor/cs_postmessage.d.ts +2 -0
  140. package/dist/types/extractor/customLocator.d.ts +69 -0
  141. package/dist/types/extractor/debug.d.ts +1 -0
  142. package/dist/types/extractor/dom-util.d.ts +57 -0
  143. package/dist/types/extractor/index.d.ts +33 -0
  144. package/dist/types/extractor/locator.d.ts +9 -0
  145. package/dist/types/extractor/tree.d.ts +6 -0
  146. package/dist/types/extractor/util.d.ts +47 -0
  147. package/dist/types/extractor/web-extractor.d.ts +24 -0
  148. package/dist/types/img/box-select.d.ts +26 -0
  149. package/dist/types/img/canvas-fallback.d.ts +105 -0
  150. package/dist/types/img/get-photon.d.ts +19 -0
  151. package/dist/types/img/get-sharp.d.ts +3 -0
  152. package/dist/types/img/index.d.ts +3 -0
  153. package/dist/types/img/info.d.ts +34 -0
  154. package/dist/types/img/transform.d.ts +98 -0
  155. package/dist/types/index.d.ts +2 -0
  156. package/dist/types/key-alias-utils.d.ts +9 -0
  157. package/dist/types/logger.d.ts +5 -0
  158. package/dist/types/mcp/base-server.d.ts +93 -0
  159. package/dist/types/mcp/base-tools.d.ts +148 -0
  160. package/dist/types/mcp/chrome-path.d.ts +2 -0
  161. package/dist/types/mcp/cli-report-session.d.ts +12 -0
  162. package/dist/types/mcp/error-formatter.d.ts +12 -0
  163. package/dist/types/mcp/index.d.ts +9 -0
  164. package/dist/types/mcp/init-arg-utils.d.ts +13 -0
  165. package/dist/types/mcp/inject-report-html-plugin.d.ts +18 -0
  166. package/dist/types/mcp/launcher-helper.d.ts +94 -0
  167. package/dist/types/mcp/tool-generator.d.ts +10 -0
  168. package/dist/types/mcp/types.d.ts +113 -0
  169. package/dist/types/node/fs.d.ts +15 -0
  170. package/dist/types/node/index.d.ts +2 -0
  171. package/dist/types/node/port.d.ts +8 -0
  172. package/dist/types/polyfills/async-hooks.d.ts +6 -0
  173. package/dist/types/polyfills/index.d.ts +4 -0
  174. package/dist/types/types/index.d.ts +36 -0
  175. package/dist/types/us-keyboard-layout.d.ts +32 -0
  176. package/dist/types/utils.d.ts +34 -0
  177. package/dist/types/zod-schema-utils.d.ts +23 -0
  178. package/package.json +125 -0
  179. package/src/baseDB.ts +158 -0
  180. package/src/cli/cli-args.ts +173 -0
  181. package/src/cli/cli-error.ts +24 -0
  182. package/src/cli/cli-runner.ts +230 -0
  183. package/src/cli/index.ts +4 -0
  184. package/src/common.ts +67 -0
  185. package/src/constants/example-code.ts +227 -0
  186. package/src/constants/index.ts +139 -0
  187. package/src/env/basic.ts +12 -0
  188. package/src/env/constants.ts +303 -0
  189. package/src/env/global-config-manager.ts +191 -0
  190. package/src/env/helper.ts +58 -0
  191. package/src/env/index.ts +4 -0
  192. package/src/env/init-debug.ts +34 -0
  193. package/src/env/model-config-manager.ts +149 -0
  194. package/src/env/parse-model-config.ts +357 -0
  195. package/src/env/types.ts +583 -0
  196. package/src/env/utils.ts +39 -0
  197. package/src/extractor/constants.ts +5 -0
  198. package/src/extractor/cs_postmessage.ts +136 -0
  199. package/src/extractor/customLocator.ts +1245 -0
  200. package/src/extractor/debug.ts +10 -0
  201. package/src/extractor/dom-util.ts +231 -0
  202. package/src/extractor/index.ts +50 -0
  203. package/src/extractor/locator.ts +469 -0
  204. package/src/extractor/tree.ts +179 -0
  205. package/src/extractor/util.ts +482 -0
  206. package/src/extractor/web-extractor.ts +617 -0
  207. package/src/img/box-select.ts +588 -0
  208. package/src/img/canvas-fallback.ts +393 -0
  209. package/src/img/get-photon.ts +108 -0
  210. package/src/img/get-sharp.ts +18 -0
  211. package/src/img/index.ts +27 -0
  212. package/src/img/info.ts +102 -0
  213. package/src/img/transform.ts +553 -0
  214. package/src/index.ts +1 -0
  215. package/src/key-alias-utils.ts +23 -0
  216. package/src/logger.ts +96 -0
  217. package/src/mcp/base-server.ts +500 -0
  218. package/src/mcp/base-tools.ts +391 -0
  219. package/src/mcp/chrome-path.ts +48 -0
  220. package/src/mcp/cli-report-session.ts +130 -0
  221. package/src/mcp/error-formatter.ts +52 -0
  222. package/src/mcp/index.ts +9 -0
  223. package/src/mcp/init-arg-utils.ts +105 -0
  224. package/src/mcp/inject-report-html-plugin.ts +119 -0
  225. package/src/mcp/launcher-helper.ts +200 -0
  226. package/src/mcp/tool-generator.ts +658 -0
  227. package/src/mcp/types.ts +131 -0
  228. package/src/node/fs.ts +84 -0
  229. package/src/node/index.ts +2 -0
  230. package/src/node/port.ts +37 -0
  231. package/src/polyfills/async-hooks.ts +6 -0
  232. package/src/polyfills/index.ts +4 -0
  233. package/src/types/index.ts +54 -0
  234. package/src/us-keyboard-layout.ts +723 -0
  235. package/src/utils.ts +149 -0
  236. package/src/zod-schema-utils.ts +133 -0
@@ -0,0 +1,38 @@
1
+ import { getKeyAliases, isRecord } from "../key-alias-utils.mjs";
2
+ function readAliasedValue(args, key) {
3
+ for (const alias of getKeyAliases(key))if (alias in args) return args[alias];
4
+ }
5
+ function readNamespacedArg(args, namespace, key) {
6
+ const namespacedArgs = readAliasedValue(args, namespace);
7
+ if (isRecord(namespacedArgs)) {
8
+ const nestedValue = readAliasedValue(namespacedArgs, key);
9
+ if (void 0 !== nestedValue) return nestedValue;
10
+ }
11
+ const dottedValue = readAliasedValue(args, `${namespace}.${key}`);
12
+ if (void 0 !== dottedValue) return dottedValue;
13
+ const directValue = readAliasedValue(args, key);
14
+ if (void 0 !== directValue) return directValue;
15
+ }
16
+ function extractNamespacedArgs(args, namespace, keys) {
17
+ const extracted = {};
18
+ for (const key of keys){
19
+ const value = readNamespacedArg(args, namespace, key);
20
+ if (void 0 !== value) extracted[key] = value;
21
+ }
22
+ return Object.keys(extracted).length > 0 ? extracted : void 0;
23
+ }
24
+ function sanitizeNamespacedArgs(args, namespace, keys) {
25
+ const excludedKeys = new Set(getKeyAliases(namespace));
26
+ for (const key of keys){
27
+ for (const alias of getKeyAliases(key))excludedKeys.add(alias);
28
+ for (const alias of getKeyAliases(`${namespace}.${key}`))excludedKeys.add(alias);
29
+ }
30
+ return Object.fromEntries(Object.entries(args).filter(([key])=>!excludedKeys.has(key)));
31
+ }
32
+ function createNamespacedInitArgSchema(namespace, shape) {
33
+ return Object.fromEntries(Object.entries(shape).map(([key, value])=>[
34
+ `${namespace}.${key}`,
35
+ value
36
+ ]));
37
+ }
38
+ export { createNamespacedInitArgSchema, extractNamespacedArgs, sanitizeNamespacedArgs };
@@ -0,0 +1,53 @@
1
+ import node_fs from "node:fs";
2
+ import node_path from "node:path";
3
+ const MAGIC_STRING = 'REPLACE_ME_WITH_REPORT_HTML';
4
+ const REPLACED_MARK = '/*REPORT_HTML_REPLACED*/';
5
+ const REG_EXP_FOR_REPLACE = /\/\*REPORT_HTML_REPLACED\*\/.*/;
6
+ function injectReportHtmlFromCore(packageDir) {
7
+ return {
8
+ name: 'inject-report-html-from-core',
9
+ setup (api) {
10
+ api.onAfterBuild(()=>{
11
+ const coreUtilsPath = node_path.resolve(packageDir, '..', 'core', 'dist', 'lib', 'utils.js');
12
+ if (!node_fs.existsSync(coreUtilsPath)) return void console.warn('[inject-report-html] @godscene/core dist not found, skipping');
13
+ const coreContent = node_fs.readFileSync(coreUtilsPath, 'utf-8');
14
+ if (!coreContent.includes(REPLACED_MARK)) return void console.warn('[inject-report-html] HTML not found in core dist. Ensure report builds first.');
15
+ const markerIndex = coreContent.indexOf(REPLACED_MARK);
16
+ const jsonStart = markerIndex + REPLACED_MARK.length;
17
+ let jsonEnd = jsonStart;
18
+ if ('"' === coreContent[jsonStart]) {
19
+ jsonEnd = jsonStart + 1;
20
+ while(jsonEnd < coreContent.length)if ('\\' === coreContent[jsonEnd]) jsonEnd += 2;
21
+ else if ('"' === coreContent[jsonEnd]) {
22
+ jsonEnd += 1;
23
+ break;
24
+ } else jsonEnd += 1;
25
+ }
26
+ const jsonString = coreContent.slice(jsonStart, jsonEnd);
27
+ if (!jsonString || jsonString.length < 10) return void console.warn('[inject-report-html] Failed to extract HTML from core');
28
+ const finalContent = `${REPLACED_MARK}${jsonString}`;
29
+ const distDir = node_path.join(packageDir, 'dist');
30
+ if (!node_fs.existsSync(distDir)) return;
31
+ const jsFiles = node_fs.readdirSync(distDir).filter((f)=>f.endsWith('.js'));
32
+ let injectedCount = 0;
33
+ for (const file of jsFiles){
34
+ const filePath = node_path.join(distDir, file);
35
+ const content = node_fs.readFileSync(filePath, 'utf-8');
36
+ if (content.includes(REPLACED_MARK)) {
37
+ if (REG_EXP_FOR_REPLACE.test(content)) {
38
+ node_fs.writeFileSync(filePath, content.replace(REG_EXP_FOR_REPLACE, ()=>finalContent));
39
+ console.log(`[inject-report-html] Updated: ${file}`);
40
+ injectedCount++;
41
+ }
42
+ } else if (content.includes(`'${MAGIC_STRING}'`)) {
43
+ node_fs.writeFileSync(filePath, content.replace(`'${MAGIC_STRING}'`, ()=>finalContent));
44
+ console.log(`[inject-report-html] Injected: ${file}`);
45
+ injectedCount++;
46
+ }
47
+ }
48
+ if (injectedCount > 0) console.log(`[inject-report-html] Completed: ${injectedCount} file(s)`);
49
+ });
50
+ }
51
+ };
52
+ }
53
+ export { injectReportHtmlFromCore };
@@ -0,0 +1,52 @@
1
+ function createMCPServerLauncher(config) {
2
+ const { agent, platformName, ToolsManagerClass, MCPServerClass } = config;
3
+ function validateAgent() {
4
+ const device = agent.interface;
5
+ if (!device) throw new Error(`Agent must have an 'interface' property that references the underlying device.
6
+ Please ensure your agent instance is properly initialized with a device interface.
7
+ Expected: agent.interface to be defined, but got: ${typeof device}
8
+ Solution: Check that your agent constructor properly sets the interface property.`);
9
+ }
10
+ function createToolsManager() {
11
+ const toolsManager = new ToolsManagerClass();
12
+ toolsManager.agent = agent;
13
+ return toolsManager;
14
+ }
15
+ function logStartupInfo(mode, additionalInfo) {
16
+ const device = agent.interface;
17
+ console.log(`Starting Midscene ${platformName} MCP Server (${mode})...`);
18
+ console.log(`Agent: ${agent.constructor.name}`);
19
+ console.log(`Device: ${device.constructor.name}`);
20
+ if (additionalInfo?.port !== void 0) console.log(`Port: ${additionalInfo.port}`);
21
+ if (additionalInfo?.host) console.log(`Host: ${additionalInfo.host}`);
22
+ }
23
+ return {
24
+ async launch (options = {}) {
25
+ const { verbose = true } = options;
26
+ validateAgent();
27
+ if (verbose) logStartupInfo('stdio');
28
+ const toolsManager = createToolsManager();
29
+ const server = new MCPServerClass(toolsManager);
30
+ const result = await server.launch();
31
+ if (verbose) console.log(`${platformName} MCP Server started (stdio mode)`);
32
+ return result;
33
+ },
34
+ async launchHttp (options) {
35
+ const { port, host = 'localhost', verbose = true } = options;
36
+ validateAgent();
37
+ if (verbose) logStartupInfo('HTTP', {
38
+ port,
39
+ host
40
+ });
41
+ const toolsManager = createToolsManager();
42
+ const server = new MCPServerClass(toolsManager);
43
+ const result = await server.launchHttp({
44
+ port,
45
+ host
46
+ });
47
+ if (verbose) console.log(`${platformName} MCP Server started on http://${result.host}:${result.port}/mcp`);
48
+ return result;
49
+ }
50
+ };
51
+ }
52
+ export { createMCPServerLauncher };
@@ -0,0 +1,419 @@
1
+ import { parseBase64 } from "@godscene/shared/img";
2
+ import { z } from "zod";
3
+ import { getZodDescription, getZodTypeName, isMidsceneLocatorField, unwrapZodField } from "../zod-schema-utils.mjs";
4
+ import { getErrorMessage } from "./error-formatter.mjs";
5
+ function describeActionForMCP(action) {
6
+ const actionDesc = action.description || `Execute ${action.name} action`;
7
+ if (!action.paramSchema) return `${action.name} action, ${actionDesc}`;
8
+ const shape = getZodObjectShape(action.paramSchema);
9
+ if (!shape) {
10
+ const typeName = getZodTypeName(action.paramSchema);
11
+ const description = getZodDescription(action.paramSchema);
12
+ const paramDesc = description ? `${typeName} - ${description}` : typeName;
13
+ return `${action.name} action, ${actionDesc}. Parameter: ${paramDesc}`;
14
+ }
15
+ const paramDescriptions = [];
16
+ for (const [key, field] of Object.entries(shape))if (field && 'object' == typeof field) {
17
+ const isFieldOptional = 'function' == typeof field.isOptional && field.isOptional();
18
+ const typeName = getZodTypeName(field);
19
+ const description = getZodDescription(field);
20
+ let paramStr = `${key}${isFieldOptional ? '?' : ''} (${typeName})`;
21
+ if (description) paramStr += ` - ${description}`;
22
+ paramDescriptions.push(paramStr);
23
+ }
24
+ if (0 === paramDescriptions.length) return `${action.name} action, ${actionDesc}`;
25
+ return `${action.name} action, ${actionDesc}. Parameters: ${paramDescriptions.join('; ')}`;
26
+ }
27
+ function isZodOptional(value) {
28
+ return '_def' in value && value._def?.typeName === 'ZodOptional';
29
+ }
30
+ function unwrapOptional(value) {
31
+ if (isZodOptional(value)) return {
32
+ innerValue: value._def.innerType,
33
+ isOptional: true
34
+ };
35
+ return {
36
+ innerValue: value,
37
+ isOptional: false
38
+ };
39
+ }
40
+ function getZodObjectShape(value) {
41
+ if (!value) return;
42
+ const actualValue = unwrapZodField(value);
43
+ if (actualValue._def?.typeName !== 'ZodObject') return;
44
+ if ('function' == typeof actualValue._def.shape) return actualValue._def.shape();
45
+ return actualValue.shape;
46
+ }
47
+ function isRecord(value) {
48
+ return 'object' == typeof value && null !== value && !Array.isArray(value);
49
+ }
50
+ function makePromptOptional(shape, wrapInOptional) {
51
+ const newShape = {
52
+ ...shape
53
+ };
54
+ newShape.prompt = shape.prompt.optional();
55
+ let newSchema = z.object(newShape).passthrough();
56
+ if (wrapInOptional) newSchema = newSchema.optional();
57
+ return newSchema;
58
+ }
59
+ function transformSchemaField(key, value) {
60
+ const { innerValue, isOptional } = unwrapOptional(value);
61
+ const shape = getZodObjectShape(innerValue);
62
+ if (shape && isMidsceneLocatorField(innerValue)) return [
63
+ key,
64
+ makePromptOptional(shape, isOptional)
65
+ ];
66
+ return [
67
+ key,
68
+ value
69
+ ];
70
+ }
71
+ function extractActionSchema(paramSchema, actionName) {
72
+ if (!paramSchema) return {};
73
+ const shape = getZodObjectShape(paramSchema);
74
+ if (!shape) {
75
+ const typeName = paramSchema?._def?.typeName ?? 'unknown';
76
+ throw new Error(`Action "${actionName}" declared a non-object paramSchema (${typeName}). CLI and MCP tool schemas must be a ZodObject (e.g. z.object({ uri: z.string() })) or undefined. Wrap primitive fields in an object schema.`);
77
+ }
78
+ return Object.fromEntries(Object.entries(shape).map(([key, value])=>transformSchemaField(key, value)));
79
+ }
80
+ function getPromptText(prompt) {
81
+ if ('string' == typeof prompt) return prompt;
82
+ if (isRecord(prompt) && 'string' == typeof prompt.prompt) return prompt.prompt;
83
+ }
84
+ function moveLocateExtrasIntoPrompt(value, locateFieldKeys) {
85
+ const promptText = getPromptText(value.prompt);
86
+ if (!promptText) return value;
87
+ const normalizedPrompt = isRecord(value.prompt) ? {
88
+ ...value.prompt
89
+ } : {
90
+ prompt: promptText
91
+ };
92
+ const normalizedLocate = {};
93
+ let movedExtraField = false;
94
+ for (const [key, fieldValue] of Object.entries(value))if ('prompt' !== key) {
95
+ if (locateFieldKeys.has(key)) {
96
+ normalizedLocate[key] = fieldValue;
97
+ continue;
98
+ }
99
+ movedExtraField = true;
100
+ if (!(key in normalizedPrompt)) normalizedPrompt[key] = fieldValue;
101
+ }
102
+ if (!movedExtraField) return value;
103
+ return {
104
+ ...normalizedLocate,
105
+ prompt: normalizedPrompt
106
+ };
107
+ }
108
+ function normalizeLocateLikeArg(value, fieldSchema) {
109
+ if ('string' == typeof value) return {
110
+ prompt: value
111
+ };
112
+ if (!isRecord(value)) return value;
113
+ const shape = getZodObjectShape(fieldSchema);
114
+ if (!shape) return value;
115
+ return moveLocateExtrasIntoPrompt(value, new Set(Object.keys(shape)));
116
+ }
117
+ function normalizeActionArgs(args, paramSchema) {
118
+ if (!paramSchema) return args;
119
+ const shape = getZodObjectShape(paramSchema);
120
+ if (!shape) return args;
121
+ return Object.fromEntries(Object.entries(args).map(([key, value])=>{
122
+ const fieldSchema = shape[key];
123
+ if (!fieldSchema) return [
124
+ key,
125
+ value
126
+ ];
127
+ if (isMidsceneLocatorField(fieldSchema)) return [
128
+ key,
129
+ normalizeLocateLikeArg(value, fieldSchema)
130
+ ];
131
+ return [
132
+ key,
133
+ value
134
+ ];
135
+ }));
136
+ }
137
+ function serializeArgsToDescription(args) {
138
+ try {
139
+ return Object.entries(args).map(([key, value])=>{
140
+ if ('object' == typeof value && null !== value) try {
141
+ return `${key}: ${JSON.stringify(value)}`;
142
+ } catch {
143
+ return `${key}: [object]`;
144
+ }
145
+ return `${key}: "${value}"`;
146
+ }).join(', ');
147
+ } catch (error) {
148
+ const errorMessage = getErrorMessage(error);
149
+ console.error('Error serializing args:', errorMessage);
150
+ return `[args serialization failed: ${errorMessage}]`;
151
+ }
152
+ }
153
+ function buildActionInstruction(actionName, args) {
154
+ const locatePrompt = isRecord(args.locate) ? getPromptText(args.locate.prompt) : void 0;
155
+ switch(actionName){
156
+ case 'Tap':
157
+ return locatePrompt ? `Tap on "${locatePrompt}"` : 'Tap';
158
+ case 'Input':
159
+ {
160
+ const value = args.value ?? args.content ?? '';
161
+ return locatePrompt ? `Input "${value}" into "${locatePrompt}"` : `Input "${value}"`;
162
+ }
163
+ case 'Scroll':
164
+ {
165
+ const direction = args.direction ?? 'down';
166
+ return locatePrompt ? `Scroll ${direction} on "${locatePrompt}"` : `Scroll ${direction}`;
167
+ }
168
+ case 'Hover':
169
+ return locatePrompt ? `Hover over "${locatePrompt}"` : 'Hover';
170
+ case 'KeyboardPress':
171
+ {
172
+ const key = args.value ?? args.key ?? '';
173
+ return `Press key "${key}"`;
174
+ }
175
+ default:
176
+ {
177
+ const argsDescription = serializeArgsToDescription(args);
178
+ return argsDescription ? `${actionName}: ${argsDescription}` : actionName;
179
+ }
180
+ }
181
+ }
182
+ async function executeAction(agent, actionName, args) {
183
+ if (agent.callActionInActionSpace) return agent.callActionInActionSpace(actionName, args);
184
+ if (agent.aiAction) {
185
+ const instruction = buildActionInstruction(actionName, args);
186
+ return agent.aiAction(instruction);
187
+ }
188
+ throw new Error(`Action "${actionName}" is not supported by this agent`);
189
+ }
190
+ async function captureScreenshotResult(agent, actionName, actionResult) {
191
+ const content = [
192
+ {
193
+ type: 'text',
194
+ text: `Action "${actionName}" completed.`
195
+ }
196
+ ];
197
+ if (void 0 !== actionResult) content.push({
198
+ type: 'text',
199
+ text: `Result: ${serializeActionResult(actionResult)}`
200
+ });
201
+ try {
202
+ const screenshot = await agent.page?.screenshotBase64();
203
+ if (!screenshot) return {
204
+ content
205
+ };
206
+ const { mimeType, body } = parseBase64(screenshot);
207
+ content.push({
208
+ type: 'image',
209
+ data: body,
210
+ mimeType
211
+ });
212
+ return {
213
+ content
214
+ };
215
+ } catch (error) {
216
+ const errorMessage = getErrorMessage(error);
217
+ console.error('Error capturing screenshot:', errorMessage);
218
+ content[0] = {
219
+ type: 'text',
220
+ text: `Action "${actionName}" completed (screenshot unavailable: ${errorMessage})`
221
+ };
222
+ return {
223
+ content
224
+ };
225
+ }
226
+ }
227
+ function serializeActionResult(actionResult) {
228
+ if ('string' == typeof actionResult) return actionResult;
229
+ try {
230
+ return JSON.stringify(actionResult);
231
+ } catch {
232
+ return String(actionResult);
233
+ }
234
+ }
235
+ function createErrorResult(message) {
236
+ return {
237
+ content: [
238
+ {
239
+ type: 'text',
240
+ text: message
241
+ }
242
+ ],
243
+ isError: true
244
+ };
245
+ }
246
+ async function captureFailureResult(agent, actionName, errorMessage) {
247
+ const warningText = `Warning: Action "${actionName}" failed: ${errorMessage}. Check the screenshot below for the current page state and decide how to proceed.`;
248
+ try {
249
+ const screenshot = await agent.page?.screenshotBase64();
250
+ if (!screenshot) return {
251
+ content: [
252
+ {
253
+ type: 'text',
254
+ text: warningText
255
+ }
256
+ ]
257
+ };
258
+ const { mimeType, body } = parseBase64(screenshot);
259
+ return {
260
+ content: [
261
+ {
262
+ type: 'text',
263
+ text: warningText
264
+ },
265
+ {
266
+ type: 'image',
267
+ data: body,
268
+ mimeType
269
+ }
270
+ ]
271
+ };
272
+ } catch {
273
+ return {
274
+ content: [
275
+ {
276
+ type: 'text',
277
+ text: warningText
278
+ }
279
+ ]
280
+ };
281
+ }
282
+ }
283
+ function mergeToolCliMetadata(base, extra) {
284
+ const options = {
285
+ ...base?.options ?? {},
286
+ ...extra?.options ?? {}
287
+ };
288
+ return Object.keys(options).length > 0 ? {
289
+ options
290
+ } : void 0;
291
+ }
292
+ function generateToolsFromActionSpace(actionSpace, getAgent, sanitizeArgs = (args)=>args, initArgSchema = {}, initArgCliMetadata) {
293
+ return actionSpace.map((action)=>{
294
+ const schema = {
295
+ ...extractActionSchema(action.paramSchema, action.name),
296
+ ...initArgSchema
297
+ };
298
+ return {
299
+ name: action.name,
300
+ description: describeActionForMCP(action),
301
+ schema,
302
+ cli: initArgCliMetadata,
303
+ handler: async (args)=>{
304
+ try {
305
+ const agent = await getAgent(args);
306
+ const normalizedArgs = normalizeActionArgs(sanitizeArgs(args), action.paramSchema);
307
+ let actionResult;
308
+ try {
309
+ actionResult = await executeAction(agent, action.name, normalizedArgs);
310
+ } catch (error) {
311
+ const errorMessage = getErrorMessage(error);
312
+ console.error(`Error executing action "${action.name}":`, errorMessage);
313
+ return await captureFailureResult(agent, action.name, errorMessage);
314
+ }
315
+ return await captureScreenshotResult(agent, action.name, actionResult);
316
+ } catch (error) {
317
+ const errorMessage = getErrorMessage(error);
318
+ console.error(`Error in handler for "${action.name}":`, errorMessage);
319
+ return createErrorResult(`Failed to get agent or execute action "${action.name}": ${errorMessage}`);
320
+ }
321
+ }
322
+ };
323
+ });
324
+ }
325
+ function generateCommonTools(getAgent, initArgSchema = {}, initArgCliMetadata) {
326
+ return [
327
+ {
328
+ name: 'take_screenshot',
329
+ description: 'Capture screenshot of current page/screen',
330
+ schema: {
331
+ ...initArgSchema
332
+ },
333
+ cli: initArgCliMetadata,
334
+ handler: async (args = {})=>{
335
+ try {
336
+ const agent = await getAgent(args);
337
+ const screenshot = await agent.page?.screenshotBase64();
338
+ if (!screenshot) return createErrorResult('Screenshot not available');
339
+ const { mimeType, body } = parseBase64(screenshot);
340
+ return {
341
+ content: [
342
+ {
343
+ type: 'image',
344
+ data: body,
345
+ mimeType
346
+ }
347
+ ]
348
+ };
349
+ } catch (error) {
350
+ const errorMessage = getErrorMessage(error);
351
+ console.error('Error taking screenshot:', errorMessage);
352
+ return createErrorResult(`Failed to capture screenshot: ${errorMessage}`);
353
+ }
354
+ }
355
+ },
356
+ {
357
+ name: 'act',
358
+ description: 'Execute a natural language action. The AI will plan and perform multi-step operations in a single invocation, useful for transient UI interactions (e.g., Spotlight, dropdown menus) that disappear between separate commands.',
359
+ schema: {
360
+ prompt: z.string().describe('Natural language description of the action to perform, e.g. "press Command+Space, type Safari, press Enter"'),
361
+ ...initArgSchema
362
+ },
363
+ cli: mergeToolCliMetadata(void 0, initArgCliMetadata),
364
+ handler: async (args = {})=>{
365
+ const prompt = args.prompt;
366
+ try {
367
+ const agent = await getAgent(args);
368
+ if (!agent.aiAction) return createErrorResult('act is not supported by this agent');
369
+ const result = await agent.aiAction(prompt, {
370
+ deepThink: false
371
+ });
372
+ const screenshotResult = await captureScreenshotResult(agent, 'act');
373
+ if (result) {
374
+ const message = 'string' == typeof result ? result : JSON.stringify(result);
375
+ screenshotResult.content.unshift({
376
+ type: 'text',
377
+ text: `Task finished, message: ${message}`
378
+ });
379
+ }
380
+ return screenshotResult;
381
+ } catch (error) {
382
+ const errorMessage = getErrorMessage(error);
383
+ console.error('Error executing act:', errorMessage);
384
+ return createErrorResult(`Failed to execute act: ${errorMessage}`);
385
+ }
386
+ }
387
+ },
388
+ {
389
+ name: 'assert',
390
+ description: 'Assert a natural language statement against the current page/screen.',
391
+ schema: {
392
+ prompt: z.string().describe('Natural language assertion to verify, e.g. "there is a login button visible"'),
393
+ ...initArgSchema
394
+ },
395
+ cli: mergeToolCliMetadata(void 0, initArgCliMetadata),
396
+ handler: async (args = {})=>{
397
+ const prompt = args.prompt;
398
+ try {
399
+ const agent = await getAgent(args);
400
+ if (!agent.aiAssert) return createErrorResult('assert is not supported by this agent');
401
+ await agent.aiAssert(prompt);
402
+ return {
403
+ content: [
404
+ {
405
+ type: 'text',
406
+ text: 'Assertion passed.'
407
+ }
408
+ ]
409
+ };
410
+ } catch (error) {
411
+ const errorMessage = getErrorMessage(error);
412
+ console.error('Error executing assert:', errorMessage);
413
+ return createErrorResult(`Failed to execute assert: ${errorMessage}`);
414
+ }
415
+ }
416
+ }
417
+ ];
418
+ }
419
+ export { generateCommonTools, generateToolsFromActionSpace };
@@ -0,0 +1,3 @@
1
+ const defaultAppLoadingTimeoutMs = 10000;
2
+ const defaultAppLoadingCheckIntervalMs = 2000;
3
+ export { defaultAppLoadingCheckIntervalMs, defaultAppLoadingTimeoutMs };